2021-10-11 19:38:01 -03:00

378 lines
8.0 KiB
C
Executable File

/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)parse.c 1.4 92/07/14 SMI" /* SVr4.0 1.8 */
#include <ctype.h>
#include <table.h>
#include <internal.h>
#ifdef WHITESP
/* I don't think WHITESPACE should be skipped */
#define SKIPWS(p,d) \
while( p && *p \
&& *p != e->td_eoe && *p != e->td_comment && *p != td_fs \
&& (*p == ' ' || *p == '\t') ) \
p++
#else
#define SKIPWS(p,d)
#endif
#define FSMSG "FIELD SEPARATOR="
#define ENTMSG "ENTRY FORMAT="
#define isoctal(c) (isdigit((int)c) && c != '8' && c != '9')
#define ISWSPACE(c) (c == ' ' || c == '\t')
#define FOUND 1
#define NOT_FOUND 0
#define P_ERROR -1
static unsigned char *inptr;
static int p_errno;
extern tbl_t TLtables[];
extern unsigned char TLinbuffer[];
char *strpbrk();
/*
Find either \\octal number or a char
*/
static
TLp_char()
{
register tmp = 0, i;
if( *inptr == '\\' ) {
inptr++;
if( isoctal( *inptr ) ) {
for( i = 0; i < 3; i++ )
if( *inptr && isoctal( *inptr ) ) {
tmp = tmp * 8 + (int)*inptr;
inptr++;
} else break;
} else return( *inptr++ );
} else tmp = *inptr++;
return( (char) tmp );
}
/*
Like strpbrk(3C) but also returns ptr to NULL
*/
unsigned char *
TLstrpbrk( s1, s2 )
unsigned char *s1, *s2;
{
register unsigned char *ptr;
if( ptr = (unsigned char *)strpbrk( (char *)s1, (char *)s2 ) )
return( ptr );
return( s1 + Strlen(s1) );
}
/*
get the next field, handling escapes. Return ptr to
spot after field.
*/
static
unsigned char *
getfield( ptr, size, terminators )
unsigned char *ptr, *terminators;
int *size;
{
register unsigned char *to = ptr, *t;
register sz = 0, nescapes = 0;
while( *ptr ) {
/* skip escapes except for <esc><null> */
if( *ptr == '\\' && *(++ptr) ) {
/* Found an escape - skip it */
nescapes++;
} else for( t = terminators; *t; t++ ) {
if( *t == *ptr )
/* Found a terminator */
goto gf_done;
}
/*
If some escapes have been found,
then squeeze the effective field
string together.
*/
if( nescapes > 0 ) *to = *ptr;
ptr++;
to++;
sz++;
}
gf_done:
*size = sz;
return( ptr );
}
/*
Parse:
[ <field> <sep> ]* <sep>
*/
static
TLp_fields( tptr, pstruct, count_wspace )
tbl_t *tptr;
parse_t *pstruct;
int count_wspace;
{
register unsigned char *tsave = inptr, *ptr;
register field_t *fieldp = &(pstruct->fields);
unsigned char terminators[ 10 ];
int size, saw_fs = FALSE;
fieldp->count = 0;
(void)sprintf( (char *)terminators, "%c%c%s", tptr->description.td_fs,
tptr->description.td_comment, (count_wspace? " \t": "") );
while( TRUE ) {
/*
Look for next field - field is terminated by one of the
terminator characters. Handle escapes.
*/
ptr = (unsigned char *)getfield( inptr, &size, terminators );
if( size || saw_fs || *ptr == tptr->description.td_fs ) {
/* Found a field */
if( fieldp->count == TL_MAXFIELDS ) {
/* Too many fields */
p_errno = TLBADFORMAT;
return( P_ERROR );
}
/* Found a field - get a buffer for it */
if( !(fieldp->values[ fieldp->count ] =
(unsigned char *)Malloc( size + 1 ) ) ) {
inptr = tsave;
p_errno = TLNOMEMORY;
return( P_ERROR );
}
Strncpy( fieldp->values[ fieldp->count ], inptr, size );
fieldp->values[ fieldp->count ][size] = '\0';
fieldp->count++;
}
if( !*ptr
|| *ptr == tptr->description.td_comment
|| isspace((int)*ptr) && !count_wspace ) {
/* Field was not terminated by a field separator; ergo we're done */
if( !fieldp->count ) {
inptr = tsave;
return( NOT_FOUND );
}
inptr = ptr;
return( FOUND );
}
/* Skip the separator */
if( *ptr == tptr->description.td_fs ) {
saw_fs = TRUE;
ptr++;
}
inptr = ptr;
}
}
/*
parse "FIELD SEPARATOR=x"
where:
x is some character, or \\octal number
*/
/*ARGSUSED*/
static
TLp_fs( tptr, pstruct )
tbl_t *tptr;
parse_t *pstruct;
{
register unsigned char *tsave = inptr;
if( !Strncmp( inptr, FSMSG, Strlen( FSMSG ) ) ) {
inptr += Strlen( FSMSG );
if( pstruct->descr.td_fs = TLp_char() ) {
pstruct->type |= (PT_COMMENT|PT_SPECIAL);
return( FOUND );
}
}
inptr = tsave;
return( NOT_FOUND );
}
/*
Parse "ENTRY FORMAT=[[^<sep>]+<sep>]+
*/
static
TLp_format( tptr, pstruct )
tbl_t *tptr;
parse_t *pstruct;
{
register unsigned char *tsave = inptr;
register rc = NOT_FOUND, countwspace;
if( !Strncmp( inptr, ENTMSG, Strlen( ENTMSG ) ) ) {
inptr += Strlen( ENTMSG );
countwspace = ISWSPACE(tptr->description.td_fs)
|| ISWSPACE(tptr->description.td_comment);
switch( rc = TLp_fields( tptr, pstruct, countwspace ) ) {
case FOUND:
if( pstruct->fields.count == 0 ) {
/* Disallow empty ENTRY FORMATs */
inptr = tsave;
p_errno = TLBADFORMAT;
rc = P_ERROR;
} else {
pstruct->type |= (PT_COMMENT|PT_SPECIAL);
rc = FOUND;
}
break;
default:
inptr = tsave;
}
}
return( rc );
}
/*
Parse a Special Self-describing comment.
*/
static
TLp_special( tptr, pstruct )
tbl_t *tptr;
parse_t *pstruct;
{
register unsigned char *tsave = inptr;
if( *inptr != tptr->description.td_comment )
return( NOT_FOUND );
inptr++;
/* Two types of special comments:
> Field separator setting,
> Entry format
*/
while( TLp_fs( tptr, pstruct ) || TLp_format( tptr, pstruct ) )
SKIPWS( inptr, tptr );
if( !(pstruct->type & PT_SPECIAL) ) {
/* This was not a SPECIAL comment */
inptr = tsave;
return( NOT_FOUND );
} else return( FOUND );
}
/*
Parse a Comment
*/
static
TLp_comment( tptr, pstruct )
tbl_t *tptr;
parse_t *pstruct;
{
register unsigned char *tsave = inptr;
register size;
if( *inptr != tptr->description.td_comment )
return( NOT_FOUND );
if( TLp_special( tptr, pstruct ) == NOT_FOUND )
pstruct->type |= PT_COMMENT;
/* Regardless of whether or not it is a SPECIAL comment, it is a comment,
so record it. */
inptr = tsave + 1;
while( *inptr && *inptr != tptr->description.td_eoe ) inptr++;
if( inptr != tsave + 1 ) {
size = inptr - tsave + 1;
if( !(pstruct->comment
= (unsigned char *)Malloc( size + 5 ))) {
/* Extra character malloc'd for strncpy's null */
inptr = tsave;
p_errno = TLNOMEMORY;
return( P_ERROR );
}
Strncpy( pstruct->comment, tsave + 1, size );
pstruct->comment[ size + 1 ] = '\0';
} else pstruct->comment = 0;
return( FOUND );
}
/*
Parse an entry - this is some (possibly zero) number of fields followed
by an optional comment;
*/
static
TLp_entry( tptr, pstruct )
tbl_t *tptr;
parse_t *pstruct;
{
if( TLp_fields( tptr, pstruct, FALSE ) == P_ERROR ) return( P_ERROR );
if( TLp_comment( tptr, pstruct ) == P_ERROR ) return( P_ERROR );
return( FOUND );
}
/*
TLbparse() - parse an entry that is currently in a buffer.
*/
int
TLbparse( tid, pstruct, buffer )
int tid;
parse_t *pstruct;
unsigned char *buffer;
{
register tbl_t *tptr = TLtables + tid;
Strncpy( pstruct, "", sizeof( parse_t ) );
/* Assume buffer is null-terminated */
inptr = buffer;
SKIPWS( inptr, &(tptr->description) );
if( TLp_entry( tptr, pstruct ) == P_ERROR )
return( p_errno );
return( TLOK );
}
/*
TLparse() starts at where ever the file id currently points, gets an
entry, and parses it. The parse results are placed in pstruct;
*/
int
TLparse( tid, pstruct, size )
int tid, *size;
parse_t *pstruct;
{
register rc;
/* Read next entry into max-sized buffer */
if( (rc = TLfl_getentry( tid, TLinbuffer, 2 * TL_MAXLINESZ )) > 0 ) {
*size = rc;
return( TLbparse( tid, pstruct, TLinbuffer ) );
}
if( rc < 0 ) return( rc );
return( TLOK );
}
int
TLp_iscomment( tid, ptr )
int tid;
unsigned char *ptr;
{
register tbl_t *tptr = TLtables + tid;
SKIPWS(ptr, &(tptr->description) );
return( *ptr == tptr->description.td_comment );
}
/*
Parse and fill in field names
*/
int
TLp_fieldnames( tid, buffer )
int tid;
unsigned char *buffer;
{
register tbl_t *tptr = TLtables + tid;
parse_t pstruct;
inptr = buffer;
if( TLp_fields( tptr, &pstruct, FALSE ) != FOUND )
return( FALSE );
tptr->fieldnames = pstruct.fields;
return( TRUE );
}