#ifndef lint
static char Rcs_Id[] =
"$Id: fields.c,v 1.7 1994/01/06 05:26:37 geoff Exp $";
#endif
#include <stdio.h>
#include "config.h"
#include "fields.h"
field_t * fieldread P ((FILE * file, char * delims,
int flags, int maxf));
field_t * fieldmake P ((char * line, int allocated, char * delims,
int flags, int maxf));
static field_t * fieldparse P ((field_t * fieldp, char * line, char * delims,
int flags, int maxf));
static int fieldbackch P ((char * str, char ** out, int strip));
int fieldwrite P ((FILE * file, field_t * fieldp, int delim));
void fieldfree P ((field_t * fieldp));
unsigned int field_field_inc = 20;
unsigned int field_line_inc = 512;
#ifndef USG
#define strchr index
#endif
extern void free ();
extern char * malloc ();
extern char * realloc ();
extern char * strchr ();
extern int strlen ();
field_t * fieldread (file, delims, flags, maxf)
FILE * file;
char * delims;
int flags;
int maxf;
{
register char * linebuf;
int linemax;
int linesize;
linebuf = (char *) malloc (field_line_inc);
if (linebuf == NULL)
return NULL;
linemax = field_line_inc;
linesize = 0;
while (fgets (&linebuf[linesize], linemax - linesize, file)
!= NULL)
{
linesize += strlen (&linebuf[linesize]);
if (linebuf[linesize - 1] == '\n')
break;
else
{
linemax += field_line_inc;
linebuf = (char *) realloc (linebuf, linemax);
if (linebuf == NULL)
return NULL;
}
}
if (linesize == 0)
{
free (linebuf);
return NULL;
}
return fieldmake (linebuf, 1, delims, flags, maxf);
}
field_t * fieldmake (line, allocated, delims, flags, maxf)
char * line;
int allocated;
char * delims;
int flags;
int maxf;
{
register field_t * fieldp;
int linesize;
fieldp = (field_t *) malloc (sizeof (field_t));
if (fieldp == NULL)
return NULL;
fieldp->nfields = 0;
fieldp->linebuf = allocated ? line : NULL;
fieldp->fields = NULL;
fieldp->hadnl = 0;
linesize = strlen (line);
if (line[linesize - 1] == '\n')
{
line[--linesize] = '\0';
fieldp->hadnl = 1;
}
if (allocated && (flags & FLD_NOSHRINK) == 0)
{
line = fieldp->linebuf =
(char *) realloc (fieldp->linebuf, linesize + 1);
if (fieldp->linebuf == NULL)
{
fieldfree (fieldp);
return NULL;
}
}
return fieldparse (fieldp, line, delims, flags, maxf);
}
static field_t * fieldparse (fieldp, line, delims, flags, maxf)
register field_t * fieldp;
register char * line;
char * delims;
int flags;
int maxf;
{
int fieldmax;
char * lineout;
char quote;
fieldp->nfields = 0;
fieldmax =
(maxf != 0 && maxf < field_field_inc) ? maxf + 2 : field_field_inc;
fieldp->fields = (char **) malloc (fieldmax * sizeof (char *));
if (fieldp->fields == NULL)
{
fieldfree (fieldp);
return NULL;
}
if ((flags
& (FLD_SHQUOTES | FLD_SNGLQUOTES | FLD_BACKQUOTES | FLD_DBLQUOTES))
== FLD_SHQUOTES)
flags |= FLD_SNGLQUOTES | FLD_BACKQUOTES | FLD_DBLQUOTES;
while (1)
{
if (flags & FLD_RUNS)
{
while (*line != '\0' && strchr (delims, *line) != NULL)
line++;
if (*line == '\0')
break;
}
fieldp->fields[fieldp->nfields] = lineout = line;
if (flags
& (FLD_SHQUOTES | FLD_SNGLQUOTES | FLD_BACKQUOTES
| FLD_DBLQUOTES | FLD_BACKSLASH))
{
while (*line != '\0')
{
if (strchr (delims, *line) != NULL)
break;
else if (((flags & FLD_SNGLQUOTES) && *line == '\'')
|| ((flags & FLD_BACKQUOTES) && *line == '`')
|| ((flags & FLD_DBLQUOTES) && *line == '"'))
{
if ((flags & FLD_SHQUOTES) == 0
&& line != fieldp->fields[fieldp->nfields])
quote = '\0';
else
quote = *line;
}
else
quote = '\0';
if (quote == '\0')
{
if (*line == '\\' && (flags & FLD_BACKSLASH))
{
line++;
if (*line == '\0')
break;
line += fieldbackch (line, &lineout,
flags & FLD_STRIPQUOTES);
}
else
*lineout++ = *line++;
}
else
{
if ((flags & FLD_STRIPQUOTES) == 0)
*lineout++ = quote;
++line;
while (*line != '\0')
{
if (*line == quote)
{
if ((flags & FLD_STRIPQUOTES) == 0)
*lineout++ = quote;
line++;
if ((flags & FLD_SHQUOTES) == 0)
{
while (*line != '\0'
&& strchr (delims, *line) == NULL)
line++;
}
break;
}
else if (*line == '\\')
{
if (flags & FLD_BACKSLASH)
{
line++;
if (*line == '\0')
break;
else
line += fieldbackch (line, &lineout,
flags & FLD_STRIPQUOTES);
}
else
{
*lineout++ = '\\';
if (*++line == '\0')
break;
*lineout++ = *line;
}
}
else
*lineout++ = *line++;
}
}
}
}
else
{
while (*line != '\0' && strchr (delims, *line) == NULL)
line++;
lineout = line;
}
fieldp->nfields++;
if (*line++ == '\0')
break;
if (maxf != 0 && fieldp->nfields > maxf)
break;
*lineout = '\0';
if (fieldp->nfields >= fieldmax)
{
fieldmax += field_field_inc;
fieldp->fields =
(char **) realloc (fieldp->fields, fieldmax * sizeof (char *));
if (fieldp->fields == NULL)
{
fieldfree (fieldp);
return NULL;
}
}
}
if ((flags & FLD_NOSHRINK) == 0 && fieldp->nfields >= fieldmax)
{
fieldp->fields = (char **) realloc (fieldp->fields,
(fieldp->nfields + 1) * sizeof (char *));
if (fieldp->fields == NULL)
{
fieldfree (fieldp);
return NULL;
}
}
fieldp->fields[fieldp->nfields] = NULL;
return fieldp;
}
static int fieldbackch (str, out, strip)
register char * str;
register char ** out;
int strip;
{
register int ch;
char * origstr;
if (!strip)
{
*(*out)++ = '\\';
if (*str != 'x' && *str != 'X' && (*str < '0' || *str > '7'))
{
*(*out)++ = *str;
return *str != '\0';
}
}
switch (*str)
{
case '\0':
*(*out)++ = '\0';
return 0;
case 'a':
*(*out)++ = '\007';
return 1;
case 'b':
*(*out)++ = '\b';
return 1;
case 'f':
*(*out)++ = '\f';
return 1;
case 'n':
*(*out)++ = '\n';
return 1;
case 'r':
*(*out)++ = '\r';
return 1;
case 'v':
*(*out)++ = '\v';
return 1;
case 'X':
case 'x':
origstr = str++;
ch = 0;
if (*str >= '0' && *str <= '9')
ch = *str++ - '0';
else if (*str >= 'a' && *str <= 'f')
ch = *str++ - 'a' + 0xa;
else if (*str >= 'A' && *str <= 'F')
ch = *str++ - 'A' + 0xa;
if (*str >= '0' && *str <= '9')
ch = (ch << 4) | (*str++ - '0');
else if (*str >= 'a' && *str <= 'f')
ch = (ch << 4) | (*str++ - 'a' + 0xa);
else if (*str >= 'A' && *str <= 'F')
ch = (ch << 4) | (*str++ - 'A' + 0xa);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
origstr = str;
ch = *str++ - '0';
if (*str >= '0' && *str <= '7')
ch = (ch << 3) | (*str++ - '0');
if (*str >= '0' && *str <= '7')
ch = (ch << 3) | (*str++ - '0');
break;
default:
*(*out)++ = *str;
return 1;
}
if (strip)
{
*(*out)++ = ch;
return str - origstr;
}
else
{
for (ch = 0; origstr < str; ch++)
*(*out)++ = *origstr++;
return ch;
}
}
int fieldwrite (file, fieldp, delim)
FILE * file;
register field_t * fieldp;
int delim;
{
int error;
register int fieldno;
error = 0;
for (fieldno = 0; fieldno < fieldp->nfields; fieldno++)
{
if (fieldno != 0)
error |= putc (delim, file) == EOF;
error |= fputs (fieldp->fields[fieldno], file) == EOF;
}
if (fieldp->hadnl)
error |= putc ('\n', file) == EOF;
return error;
}
void fieldfree (fieldp)
register field_t * fieldp;
{
if (fieldp == NULL)
return;
if (fieldp->linebuf != NULL)
free ((char *) fieldp->linebuf);
if (fieldp->fields != NULL)
free ((char *) fieldp->fields);
free ((char *) fieldp);
}