/*xxxlex.c */ /* This is a small table-driven, recursive-descent lexer for XML that can be readily adapted to also parse entities with different notations. Each invocation of the lexer matches using the following abstract-syntax rule: tag :== startDelimiter, { whiteSpace? }, ( subtag1 | subtag2 | subtag3 | subtag4 | subtag5 | subtag6 | subtag7 | subtag8 | (token whiteSpace?) | CDATA )* ( altEndDelimiter | endDelimter ) where the concrete non-terminals, scanning parameters and handler routines for each are set in a structure. The initial { whiteSpace? } has not been implemented yet. The lexer is powerful enough that signature detection in the XML PI is does not require special routines. */ /* INFELICITIES 1) When testing for delimiters length > 1, EOF is not tested. TODO: 1) Speedup near line 700 & 755 needs to be smarter and less XML dependent: new field in lexrules? 2) WF Error-handling is not Draconian Probably best to use exceptions? 3) Entities not handled yet 4) XML header setting and UCS2 support 5) Figure out API 6) Figure out buffer handling 7) Think about short-refs and WML 8) Check for lexer against tail-recursive criteria */ /* #define TXCOPY($a, $b) printf($a, $b); #define TXTRACE($a, $b, $c) printf($a, $b, $c); #define TXTRACETRIES($a, $b) */ #define TXCOPY($a, $b) #define TXTRACE($a, $b, $c) #define TXTRACETRIES($a, $b) printf($a, $b); #include #include #include #include #ifndef NULL #define NULL 0 #endif #define TXCHAR unsigned char /* =============================== Entity Manager Class ======== */ #define TXBUFSIZE 100000 struct entity { unsigned char *cursor; unsigned char *datastart; unsigned char *tokenstart; unsigned char *spacestart; ssize_t buffersize; /* int (*getlinenumber)(struct entity*);*/ unsigned char buffer[TXBUFSIZE]; }; /* =============================== Entity Manager Instance ======== */ int entityGetLineNumber ( struct entity *entity) { unsigned char *i; unsigned int j=1; for (entity->buffer; i < entity->cursor;i++) if (*i=='\n') j++; return j; } struct entity stdinEntity ; /* =============================== Lexeme Class ======== */ struct lexrules { unsigned char *name; TXCHAR *startDelimiter; /* 0 means no delimiter (succeed) -1 is for future use to implement RCDATA and modal parsing */ TXCHAR *endDelimiter; /* 0 means no delimiter (skip), -1 means the start delimiter is a sole delimiters */ TXCHAR *altEndDelimiter; /* 0 means no delimiter (skip), -1 means ommissible end-delimiter ?? */ struct lexrules *sublexer1; /* longest match first */ struct lexrules *sublexer2; struct lexrules *sublexer3; struct lexrules *sublexer4; struct lexrules *sublexer5; struct lexrules *sublexer6; struct lexrules *sublexer7; struct lexrules *sublexer8; enum { noStrip = 0, strip} striptStartWhiteSpace; enum { CDATA = 0, oneTokenNoSpace, oneTokenThenOptSpace, multipleTokens } tokenize; enum { noEOF =0, allowEOF } allowEOF; int (*tokenchartest)(struct entity *, struct lexrules *); /* test function for tokenizing */ int (*whitespacechartest)(struct entity *, struct lexrules *); /* test function for whitespace handling */ int (*taghandler)(struct entity *, struct lexrules *, int); /* handler for that tag */ int (*datahandler)(struct entity *, struct lexrules *); /* handler for raw data */ int (*whitespacehandler)(struct entity *, struct lexrules *); /* handler for whitespace*/ int (*tokenhandler)(struct entity *, struct lexrules *); /* handler for tokens*/ }; /* =============================== Character Classes and Handlers for XML ======== */ /* 0 = definitely no, 1 = probably yes */ /* This is good enough for non-validating */ int nonnmtokenchar( struct entity *input, struct lexrules *rules ) { TXCHAR xc; if ((xc=*input->cursor) > 127) return 1; if ((!((xc >='a') && (xc <= 'z'))) && (!((xc >='A') && (xc <= 'Z'))) && (!((xc >='1') && (xc <= '9'))) && (xc != '0') && ( xc !='.' ) && (xc != ':') && ( xc !='-' ) && (xc !='_')) return(1); return 0; } /* 0 = no, 1 = yes */ /* This relies on ACII/UCS code positions, without checking */ int nonwhitespacechar ( struct entity *input, struct lexrules *rules ) { if (*input->cursor > ' ') return 1; else return 0; } int xmltag( struct entity *input, struct lexrules *rules, int position ) { if (position < 1) TXTRACE("[%s %d d]", rules->name, (int)input->cursor - (int)input->buffer ); return 0; } int resetcursor( struct entity *input, struct lexrules *rules, int position ) { if (position < 1) TXTRACE("[%s %d d]", rules->name, (int)input->cursor - (int)input->buffer ); if (position < 2) input->cursor=input->buffer; return 0; } /* nothing special yet: transcode buffer if not UCS-2 */ int doxmlheader( struct entity *input, struct lexrules *rules, int position ) { if (position < 1) TXTRACE("[%s %d d]", rules->name, (int)input->cursor - (int)input->buffer ); if (position > 1) input->cursor=input->buffer; return 0; } int xmldata( /* not implemented yet */ struct entity *input, struct lexrules *rules ) { TXTRACE("[data %d %d]", (int)input->datastart, (int)input->cursor); return 0; } int xmltoken( struct entity *input, struct lexrules *rules ) { TXTRACE("}token %d %d}", (int)input->tokenstart, (int)input->cursor); return 0; } int xmlwhitespace( struct entity *input, struct lexrules *rules ) { TXTRACE("}s %d %d}", (int)input->spacestart, (int)input->cursor); return 0; } /* returns 1 if OK, 0 if allowed EOF, and -1 if bad EOF */ int checkOverrun( struct entity *input, struct lexrules *rules ) { /* Check we have not overrun the input buffer */ /* To do: we can overrun on lookahead */ if (( (ssize_t)input->cursor - (ssize_t)input->buffer ) >= input->buffersize) { if (rules->allowEOF == noEOF) { perror("\nDocument error: unexpected end of input: "); printf("\nDocument error: unexpected end of input: %d, %d, %d. ", (ssize_t)input->cursor, (ssize_t)input->buffer , input->buffersize); return -1; } else return 0; } else return 1; } /* =============================== Lexeme Instances ======== */ /* reference tags */ static struct lexrules ncrLexical = { "ncr", "&#\0\0", ";\0\0\0", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, oneTokenNoSpace, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules hncrLexical = { "hncr", "&#x\0", ";\0\0\0", 0 , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, oneTokenNoSpace, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules erefLexical = { "eref", "&\0\0\0", ";\0\0\0", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, oneTokenNoSpace, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules prefLexical = { "pref", "%\0\0\0", ";\0\0\0", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, noStrip,oneTokenNoSpace, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules piLexical = { "pi", "\0\0", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, multipleTokens, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules commentLexical = { "comment", "\0", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, CDATA, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules cdatamsLexical = { "cdatams", "\0", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, strip, CDATA, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules viLexical = { "vi", "=\0\0\0", (TXCHAR *) -1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, CDATA, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules litLexical = { "lit", "\"\0\0\0", "\"\0\0\0", 0, &hncrLexical, &ncrLexical, &erefLexical, NULL, NULL, NULL, NULL, NULL, strip, multipleTokens, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules litaLexical = { "lita", "'\0\0\0", "\'\0\0\0", 0, &hncrLexical, &ncrLexical, &erefLexical, NULL, NULL, NULL, NULL, NULL, strip, multipleTokens, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules etagLexical = { "etag", "\0\0\0", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, oneTokenThenOptSpace, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules stagLexical = { "stag", "<\0\0\0", ">\0\0\0", "/>\0\0", /* &litLexical, &litaLexical, NULL, */ &litLexical, &litaLexical, &viLexical, NULL, NULL, NULL, NULL, NULL, noStrip, multipleTokens, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules contentLexical = { "content", 0, 0, 0, &piLexical, &commentLexical, &cdatamsLexical, &etagLexical, &stagLexical, &hncrLexical, &ncrLexical, &erefLexical, noStrip, CDATA, allowEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; /* Tags only used for markup declarations */ static struct lexrules plitLexical = { "plit", "\"\0\0\0", "\"\0\0\0", 0, &hncrLexical, &ncrLexical, &prefLexical, NULL, NULL, NULL, NULL, NULL, strip, multipleTokens, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules plitaLexical = { "plita", "'\0\0\0", "\'\0\0\0", 0, &hncrLexical, &ncrLexical, &prefLexical, NULL, NULL, NULL, NULL, NULL, strip, multipleTokens, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules seqLexical = { "seq", ",\0\0\0", (TXCHAR *) -1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, strip, CDATA, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules orLexical = { "or", "|\0\0\0", (TXCHAR *) -1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, strip, CDATA, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules andLexical = { "and", "&\0\0\0", (TXCHAR *) -1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, strip, CDATA, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules starLexical = { "star", "*\0\0\0", (TXCHAR *) -1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, strip, CDATA, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules plusLexical = { "plus", "+\0\0\0", (TXCHAR *) -1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, strip, CDATA, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules optLexical = { "opt", "?\0\0\0", (TXCHAR *) -1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, strip, CDATA, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; /* bug? should )+ be allowed as a 2nd alternative end? */ static struct lexrules groupLexical = { "group", "(\0\0\0", ")\0\0\0", ")*\0\0", &prefLexical, &groupLexical, &orLexical, &andLexical, &starLexical, &plusLexical, &seqLexical, &optLexical, strip , multipleTokens, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules declarationLexical = { "declaration", "\0\0\0", 0, &hncrLexical, &ncrLexical, &prefLexical, &plitLexical, &plitaLexical, &groupLexical, NULL, NULL, strip , multipleTokens, noEOF , &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules declarationsLexical = { "declarations", 0, 0, 0, &piLexical, &commentLexical, &cdatamsLexical, &hncrLexical, &ncrLexical, &prefLexical, NULL, NULL, strip, multipleTokens, allowEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; /* =============================== Handle Encodings ======== */ static struct lexrules bigendianLexical= { "bigendian", "\0xff\0xfe\0\0", 0, 0, &contentLexical, NULL, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, CDATA, allowEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules littleendianLexical= { "littleendian", "\0xff\0xfe\0\0", 0, 0, &contentLexical, NULL, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, CDATA, allowEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules abnormalpiLexical= { "abnormalpi", 0, "?>\0\0", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, multipleTokens, noEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules isntxmlheaderLexical = { "isntxmlheader", 0, 0, 0, &contentLexical, NULL, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, CDATA, allowEOF, &nonnmtokenchar, &nonwhitespacechar, &resetcursor, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules xmlheaderLexical = { "xmlheader", 0, "?>\0\0", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, multipleTokens, noEOF, &nonnmtokenchar, &nonwhitespacechar, &doxmlheader, /* reads the header then resets the cursor */ &xmldata, &xmlwhitespace, &xmltoken }; /* I cannot remember why this works now...*/ static struct lexrules xmlheaderholderLexical = { "xmlheaderholder", "\0\0\0\0" , (TXCHAR *) -1, 0, /* start delim is not 0, because that means "no delimiters" */ &xmlheaderLexical, &contentLexical, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, CDATA, allowEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; /* One lexrules to handle each kind of whitespace */ static struct lexrules isxmlheaderLexical1= { "isxmlheader1", "xml ", 0, 0, &xmlheaderholderLexical, &contentLexical, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, CDATA, allowEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules isxmlheaderLexical2= { "isxmlheader2", "xml\t", 0, 0, &xmlheaderholderLexical, &contentLexical, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, CDATA, allowEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules isxmlheaderLexical3= { "isxmlheader3", "xml\n", 0, 0, &xmlheaderholderLexical, &contentLexical, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, CDATA, allowEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; static struct lexrules isxmlheaderLexical4= { "isxmlheader4", "xml\r", 0, 0, &xmlheaderholderLexical, &contentLexical, NULL, NULL, NULL, NULL, NULL, NULL, noStrip, CDATA, allowEOF, &nonnmtokenchar, &nonwhitespacechar, &xmltag, &xmldata, &xmlwhitespace, &xmltoken }; /* If the entity starts with a PI, it could be an XML header */ static struct lexrules couldbeheaderLexical = { "couldbeheader", "0 (delimiter length) for yes */ int tinystrcmp( TXCHAR *a, /* the text */ TXCHAR *b) /* the delimiter: four characters long */ { int n=0; if ((a != 0 ) && (b!= 0) && ( a[0]!=0)) { n= tinycharcmp( 0, a, b); if (n <= 0 ) return 0; /* no match */ n= tinycharcmp( 1, a, b); if (n < 0 ) return 0; /* no match */ if (n == 0 ) return 1; n= tinycharcmp( 2, a, b); if (n < 0 ) return 0; /* no match */ if (n == 0 ) return 2; n= tinycharcmp( 3, a, b); if (n < 0 ) return 0; /* no match */ if (n == 0 ) return 3; return 4; } return 0; /* no match */ } /* =============================== Lexer ======== */ /* Recursive-descent scanner: all parameters for determining and grouping rules supplied as function arguments. */ /* returns -1 if error, 0 if not found, 1 if found */ int lexer( struct entity *input, struct lexrules *rules ) { int overrun=1; if (input->cursor == 0 ) return(-1); /* empty is puzzle*/ TXTRACETRIES("\n---->%s", rules->name); /* is the start delimiter found? */ /* if there is no start delimiter, proceed directly to loop */ if (rules->startDelimiter != 0 ) { switch ( tinystrcmp(input->cursor, rules->startDelimiter)){ case 0: return 0; /* not found */ case 4: TXCOPY("%c", *input->cursor ); input->cursor++; case 3: TXCOPY("%c", *input->cursor ); input->cursor++; case 2: TXCOPY("%c", *input->cursor ); input->cursor++; case 1: TXCOPY("%c", *input->cursor ); input->cursor++; break; default: perror("\nProgramming error (__LINE__): tinystrcmp returns unexpected value"); } rules->taghandler( input, rules, 0 ); } else rules->taghandler( input, rules, 1 ); TXTRACETRIES("\n-->%s\n", rules->name); if ((rules->endDelimiter)==(TXCHAR *)-1) { input->cursor--; rules->taghandler( input, rules, 2 ); return 1; } for (;;input->cursor++) { /* check the entity hasn't ended unexpectedly */ if (( overrun = checkOverrun(input, rules))!=1) return(overrun); /* wrap this in a test to cull candidates : endtags must start '@' */ if ((char)*input->cursor <= (char)'?') { /* is the end delimiter found? */ if (rules->endDelimiter!= 0 ) { switch ( tinystrcmp(input->cursor, rules->endDelimiter)){ case 0: break; case 4: TXCOPY("%c", *input->cursor ); input->cursor++; case 3: TXCOPY("%c", *input->cursor ); input->cursor++; case 2: TXCOPY("%c", *input->cursor ); input->cursor++; case 1: TXCOPY("%c", *input->cursor ); rules->taghandler( input, rules, 3 ); return(1); default: perror("\nProgramming error (__LINE__): tinystrcmp returns unexpected value"); } } /* is the alternative end delimiter found? */ if (rules->altEndDelimiter!= 0 ) { if (((rules->altEndDelimiter)==(TXCHAR *)-1) && ((*(rules->tokenchartest))(input, rules)==1)) { return 1; } else switch ( tinystrcmp(input->cursor, rules->altEndDelimiter)){ case 0: break; case 4: TXCOPY("%c", *input->cursor ); input->cursor++; case 3: TXCOPY("%c", *input->cursor ); input->cursor++; case 2: TXCOPY("%c", *input->cursor ); input->cursor++; case 1: TXCOPY("%c", *input->cursor ); rules->taghandler( input, rules, 4 ); return(1); default: perror("\nProgramming error (__LINE__): tinystrcmp returns unexpected value"); } } } /* critical loop for speed: but '|' because content models on helps non-ASCII chars */ if ((char)*input->cursor <= (char)'|') { /* test for delimiters that don't cause exits */ if ( rules->sublexer1 != NULL) { if ((lexer( input, rules->sublexer1)) == 1 ) continue; else { if ( rules->sublexer2 != NULL) { if ( (lexer( input, rules->sublexer2)) == 1 ) continue ; else { if ( rules->sublexer3 != NULL) { if ( (lexer( input, rules->sublexer3)) == 1 ) continue; else { if ( rules->sublexer4 != NULL) { if ( (lexer( input, rules->sublexer4)) == 1 ) continue ; else { if ( rules->sublexer5 != NULL) { if ( (lexer( input, rules->sublexer5)) == 1 ) continue ; else { if ( rules->sublexer6 != NULL) { if ( (lexer( input, rules->sublexer6)) == 1 ) continue ; else { if ( rules->sublexer7 != NULL) { if ( (lexer( input, rules->sublexer7)) == 1 ) continue ; else if (( rules->sublexer8 != NULL) && ( (lexer( input, rules->sublexer8)) == 1)) continue ; } } } } } } } } } } } } } } /* handle tokenizing */ if ( rules->tokenize == multipleTokens ){ if ( (*(rules->tokenchartest))( input, rules) == 0) { input->tokenstart=input->cursor; rules->tokenhandler(input, rules); while ( (*(rules->tokenchartest))( input, rules) == 0) { TXCOPY("%c", *input->cursor ); input->cursor++; /* check the entity hasn't ended unexpectedly */ if (( overrun = checkOverrun(input, rules))!=1) return(overrun); } rules->tokenhandler( input, rules ); input->cursor--; } else if ( (*(rules->whitespacechartest))( input, rules) == 0) { input->spacestart=input->cursor; rules->whitespacehandler(input, rules); while ( (*(rules->whitespacechartest))( input, rules) == 0) { TXCOPY("%c", *input->cursor ); input->cursor++; /* check the entity hasn't ended unexpectedly */ if (( overrun = checkOverrun(input, rules))!=1) return(overrun); } rules->whitespacehandler( input, rules ); input->cursor--; } else TXCOPY("%c", *input->cursor ); } /* handle char */ else TXCOPY("%c", *input->cursor ); } perror("\nProgramming error: Should be never reached"); return 0; } /* =============================== Main ======== */ int main( argc, argv) { /* read file into buffer */ printf("Starting..."); stdinEntity.buffersize = read( 0 , (char *)stdinEntity.buffer, TXBUFSIZE); stdinEntity.cursor = stdinEntity.buffer; printf("Starting...(%d),(%d)", *stdinEntity.buffer, stdinEntity.buffersize); if ( lexer( &stdinEntity , &wfdocentityLexical) == -1) perror("\nProgramming error (__LINE__): unexpected error from lexer "); printf("Finished"); return 0; }