source: trunk/third/ispell/fields.c @ 10593

Revision 10593, 11.0 KB checked in by ghudson, 27 years ago (diff)
Don't declare strlen(); it bombs out on Irix 6.3.
Line 
1#ifndef lint
2static char Rcs_Id[] =
3    "$Id: fields.c,v 1.2 1997-10-18 16:39:29 ghudson Exp $";
4#endif
5
6/*
7 * $Log: not supported by cvs2svn $
8 * Revision 1.1.1.1  1997/09/03 21:08:08  ghudson
9 * Import of ispell 3.1.20
10 *
11 * Revision 1.7  1994/01/06  05:26:37  geoff
12 * Get rid of all references to System V string routines, for portability
13 * (sigh).
14 *
15 * Revision 1.6  1994/01/05  20:13:43  geoff
16 * Add the maxf parameter
17 *
18 * Revision 1.5  1994/01/04  02:40:21  geoff
19 * Make the increments settable (field_line_inc and field_field_inc).
20 * Add support for the FLD_NOSHRINK flag.
21 *
22 * Revision 1.4  1993/09/27  17:48:02  geoff
23 * Fix some lint complaints and some parenthesization errors.
24 *
25 * Revision 1.3  1993/09/09  01:11:11  geoff
26 * Add a return value to fieldwrite.  Add support for backquotes and for
27 * unstripped backslashes.
28 *
29 * Revision 1.2  1993/08/26  00:02:50  geoff
30 * Fix a stupid null-pointer bug
31 *
32 * Revision 1.1  1993/08/25  21:32:05  geoff
33 * Initial revision
34 *
35 */
36
37#include <stdio.h>
38#include "config.h"
39#include "fields.h"
40
41field_t *       fieldread P ((FILE * file, char * delims,
42                                  int flags, int maxf));
43                                /* Read a line with fields from a file */
44field_t *       fieldmake P ((char * line, int allocated, char * delims,
45                                  int flags, int maxf));
46                                /* Make a field structure from a line */
47static field_t * fieldparse P ((field_t * fieldp, char * line, char * delims,
48                                  int flags, int maxf));
49                                /* Parse the fields in a line */
50static int      fieldbackch P ((char * str, char ** out, int strip));
51                                /* Process backslash sequences */
52int             fieldwrite P ((FILE * file, field_t * fieldp, int delim));
53                                /* Write a line with fields to a file */
54void            fieldfree P ((field_t * fieldp));
55                                /* Free a field returned by fieldread */
56
57unsigned int    field_field_inc = 20; /* Increment to increase # fields by */
58unsigned int    field_line_inc = 512; /* Incr to increase line length by */
59
60#ifndef USG
61#define strchr  index
62#endif /* USG */
63
64extern void     free ();
65extern char *   malloc ();
66extern char *   realloc ();
67extern char *   strchr ();
68
69/*
70 * Read one line of the given file into a buffer, break it up into
71 * fields, and return them to the caller.  The field_t structure
72 * returned must eventually be freed with fieldfree.
73 */
74field_t * fieldread (file, delims, flags, maxf)
75    FILE *              file;   /* File to read lines from */
76    char *              delims; /* Characters to use for field delimiters */
77    int                 flags;  /* Option flags;  see fields.h */
78    int                 maxf;   /* Maximum number of fields to parse */
79    {
80    register char *     linebuf; /* Buffer to hold the line read in */
81    int                 linemax; /* Maximum line buffer size */
82    int                 linesize; /* Current line buffer size */
83
84    linebuf = (char *) malloc (field_line_inc);
85    if (linebuf == NULL)
86        return NULL;
87    linemax = field_line_inc;
88    linesize = 0;
89    /*
90     * Read in the line.
91     */
92    while (fgets (&linebuf[linesize], linemax - linesize, file)
93      != NULL)
94        {
95        linesize += strlen (&linebuf[linesize]);
96        if (linebuf[linesize - 1] == '\n')
97            break;
98        else
99            {
100            linemax += field_line_inc;
101            linebuf = (char *) realloc (linebuf, linemax);
102            if (linebuf == NULL)
103                return NULL;
104            }
105        }
106    if (linesize == 0)
107        {
108        free (linebuf);
109        return NULL;
110        }
111    return fieldmake (linebuf, 1, delims, flags, maxf);
112    }
113
114field_t * fieldmake (line, allocated, delims, flags, maxf)
115    char *              line;   /* Line to make into a field structure */
116    int                 allocated; /* NZ if line allocated with malloc */
117    char *              delims; /* Characters to use for field delimiters */
118    int                 flags;  /* Option flags;  see fields.h */
119    int                 maxf;   /* Maximum number of fields to parse */
120    {
121    register field_t *  fieldp; /* Structure describing the fields */
122    int                 linesize; /* Current line buffer size */
123
124    fieldp = (field_t *) malloc (sizeof (field_t));
125    if (fieldp == NULL)
126        return NULL;
127    fieldp->nfields = 0;
128    fieldp->linebuf = allocated ? line : NULL;
129    fieldp->fields = NULL;
130    fieldp->hadnl = 0;
131    linesize = strlen (line);
132    if (line[linesize - 1] == '\n')
133        {
134        line[--linesize] = '\0';
135        fieldp->hadnl = 1;
136        }
137    /*
138     * Shrink the line buffer if necessary.
139     */
140    if (allocated  &&  (flags & FLD_NOSHRINK) == 0)
141        {
142        line = fieldp->linebuf =
143          (char *) realloc (fieldp->linebuf, linesize + 1);
144        if (fieldp->linebuf == NULL)
145            {
146            fieldfree (fieldp);
147            return NULL;
148            }
149        }
150    return fieldparse (fieldp, line, delims, flags, maxf);
151    }
152
153static field_t * fieldparse (fieldp, line, delims, flags, maxf)
154    register field_t *  fieldp; /* Field structure to parse into */
155    register char *     line;   /* Line to be parsed */
156    char *              delims; /* Characters to use for field delimiters */
157    int                 flags;  /* Option flags;  see fields.h */
158    int                 maxf;   /* Maximum number of fields to parse */
159    {
160    int                 fieldmax; /* Max size of fields array */
161    char *              lineout; /* Where to store xlated char in line */
162    char                quote;  /* Quote character in use */
163
164    fieldp->nfields = 0;
165    fieldmax =
166      (maxf != 0  &&  maxf < field_field_inc) ? maxf + 2 : field_field_inc;
167    fieldp->fields = (char **) malloc (fieldmax * sizeof (char *));
168    if (fieldp->fields == NULL)
169        {
170        fieldfree (fieldp);
171        return NULL;
172        }
173    if ((flags
174        & (FLD_SHQUOTES | FLD_SNGLQUOTES | FLD_BACKQUOTES | FLD_DBLQUOTES))
175      == FLD_SHQUOTES)
176        flags |= FLD_SNGLQUOTES | FLD_BACKQUOTES | FLD_DBLQUOTES;
177    while (1)
178        {
179        if (flags & FLD_RUNS)
180            {
181            while (*line != '\0'  &&  strchr (delims, *line) != NULL)
182                line++;                 /* Skip runs of delimiters */
183            if (*line == '\0')
184                break;
185            }
186        fieldp->fields[fieldp->nfields] = lineout = line;
187        /*
188         * Skip to the next delimiter.  At the end of skipping, "line" will
189         * point to either a delimiter or a null byte.
190         */
191        if (flags
192          & (FLD_SHQUOTES | FLD_SNGLQUOTES | FLD_BACKQUOTES
193            | FLD_DBLQUOTES | FLD_BACKSLASH))
194            {
195            while (*line != '\0')
196                {
197                if (strchr (delims, *line) != NULL)
198                    break;
199                else if (((flags & FLD_SNGLQUOTES)  &&  *line == '\'')
200                  ||  ((flags & FLD_BACKQUOTES)  &&  *line == '`')
201                  ||  ((flags & FLD_DBLQUOTES)  &&  *line == '"'))
202                    {
203                    if ((flags & FLD_SHQUOTES) == 0
204                      &&  line != fieldp->fields[fieldp->nfields])
205                        quote = '\0';
206                    else
207                        quote = *line;
208                    }
209                else
210                    quote = '\0';
211                if (quote == '\0')
212                    {
213                    if (*line == '\\'  &&  (flags & FLD_BACKSLASH))
214                        {
215                        line++;
216                        if (*line == '\0')
217                            break;
218                        line += fieldbackch (line, &lineout,
219                          flags & FLD_STRIPQUOTES);
220                        }
221                    else
222                        *lineout++ = *line++;
223                    }
224                else
225                    {
226                    /* Process quoted string */
227                    if ((flags & FLD_STRIPQUOTES) == 0)
228                        *lineout++ = quote;
229                    ++line;
230                    while (*line != '\0')
231                        {
232                        if (*line == quote)
233                            {
234                            if ((flags & FLD_STRIPQUOTES) == 0)
235                                *lineout++ = quote;
236                            line++;             /* Go on past quote */
237                            if ((flags & FLD_SHQUOTES) == 0)
238                                {
239                                while (*line != '\0'
240                                  &&  strchr (delims, *line) == NULL)
241                                    line++;     /* Skip to delimiter */
242                                }
243                            break;
244                            }
245                        else if (*line == '\\')
246                            {
247                            if (flags & FLD_BACKSLASH)
248                                {
249                                line++;
250                                if (*line == '\0')
251                                    break;
252                                else
253                                    line += fieldbackch (line, &lineout,
254                                      flags & FLD_STRIPQUOTES);
255                                }
256                            else
257                                {
258                                *lineout++ = '\\';
259                                if (*++line == '\0')
260                                    break;
261                                *lineout++ = *line;
262                                }
263                            }
264                        else
265                            *lineout++ = *line++;
266                        }
267                    }
268                }
269            }
270        else
271            {
272            while (*line != '\0'  &&  strchr (delims, *line) == NULL)
273                line++;                 /* Skip to delimiter */
274            lineout = line;
275            }
276        fieldp->nfields++;
277        if (*line++ == '\0')
278            break;
279        if (maxf != 0  &&  fieldp->nfields > maxf)
280            break;
281        *lineout = '\0';
282        if (fieldp->nfields >= fieldmax)
283            {
284            fieldmax += field_field_inc;
285            fieldp->fields =
286              (char **) realloc (fieldp->fields, fieldmax * sizeof (char *));
287            if (fieldp->fields == NULL)
288                {
289                fieldfree (fieldp);
290                return NULL;
291                }
292            }
293        }
294    /*
295     * Shrink the field pointers and return the field structure.
296     */
297    if ((flags & FLD_NOSHRINK) == 0  &&  fieldp->nfields >= fieldmax)
298        {
299        fieldp->fields = (char **) realloc (fieldp->fields,
300          (fieldp->nfields + 1) * sizeof (char *));
301        if (fieldp->fields == NULL)
302            {
303            fieldfree (fieldp);
304            return NULL;
305            }
306        }
307    fieldp->fields[fieldp->nfields] = NULL;
308    return fieldp;
309    }
310
311static int fieldbackch (str, out, strip)
312    register char *     str;            /* First char of backslash sequence */
313    register char **    out;            /* Where to store result */
314    int                 strip;          /* NZ to convert the sequence */
315    {
316    register int        ch;             /* Character being developed */
317    char *              origstr;        /* Original value of str */
318
319    if (!strip)
320        {
321        *(*out)++ = '\\';
322        if (*str != 'x'  &&  *str != 'X'  &&  (*str < '0'  ||  *str > '7'))
323            {
324            *(*out)++ = *str;
325            return *str != '\0';
326            }
327        }
328    switch (*str)
329        {
330        case '\0':
331            *(*out)++ = '\0';
332            return 0;
333        case 'a':
334            *(*out)++ = '\007';
335            return 1;
336        case 'b':
337            *(*out)++ = '\b';
338            return 1;
339        case 'f':
340            *(*out)++ = '\f';
341            return 1;
342        case 'n':
343            *(*out)++ = '\n';
344            return 1;
345        case 'r':
346            *(*out)++ = '\r';
347            return 1;
348        case 'v':
349            *(*out)++ = '\v';
350            return 1;
351        case 'X':
352        case 'x':
353            /* Hexadecimal sequence */
354            origstr = str++;
355            ch = 0;
356            if (*str >= '0'  &&  *str <= '9')
357                ch = *str++ - '0';
358            else if (*str >= 'a'  &&  *str <= 'f')
359                ch = *str++ - 'a' + 0xa;
360            else if (*str >= 'A'  &&  *str <= 'F')
361                ch = *str++ - 'A' + 0xa;
362            if (*str >= '0'  &&  *str <= '9')
363                ch = (ch << 4) | (*str++ - '0');
364            else if (*str >= 'a'  &&  *str <= 'f')
365                ch = (ch << 4) | (*str++ - 'a' + 0xa);
366            else if (*str >= 'A'  &&  *str <= 'F')
367                ch = (ch << 4) | (*str++ - 'A' + 0xa);
368            break;
369        case '0':
370        case '1':
371        case '2':
372        case '3':
373        case '4':
374        case '5':
375        case '6':
376        case '7':
377            /* Octal sequence */
378            origstr = str;
379            ch = *str++ - '0';
380            if (*str >= '0'  &&  *str <= '7')
381                ch = (ch << 3) | (*str++ - '0');
382            if (*str >= '0'  &&  *str <= '7')
383                ch = (ch << 3) | (*str++ - '0');
384            break;
385        default:
386            *(*out)++ = *str;
387            return 1;
388        }
389    if (strip)
390        {
391        *(*out)++ = ch;
392        return str - origstr;
393        }
394    else
395        {
396        for (ch = 0;  origstr < str;  ch++)
397            *(*out)++ = *origstr++;
398        return ch;
399        }
400    }
401
402int fieldwrite (file, fieldp, delim)
403    FILE *              file;   /* File to write to */
404    register field_t *  fieldp; /* Field structure to write */
405    int                 delim;  /* Delimiter to place between fields */
406    {
407    int                 error;  /* NZ if an error occurs */
408    register int        fieldno; /* Number of field being written */
409
410    error = 0;
411    for (fieldno = 0;  fieldno < fieldp->nfields;  fieldno++)
412        {
413        if (fieldno != 0)
414            error |= putc (delim, file) == EOF;
415        error |= fputs (fieldp->fields[fieldno], file) == EOF;
416        }
417    if (fieldp->hadnl)
418        error |= putc ('\n', file) == EOF;
419    return error;
420    }
421
422void fieldfree (fieldp)
423    register field_t *  fieldp; /* Field structure to free */
424    {
425
426    if (fieldp == NULL)
427        return;
428    if (fieldp->linebuf != NULL)
429        free ((char *) fieldp->linebuf);
430    if (fieldp->fields != NULL)
431        free ((char *) fieldp->fields);
432    free ((char *) fieldp);
433    }
Note: See TracBrowser for help on using the repository browser.