* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
#pragma ident "@(#)mdlex.l 1.3 05/11/03 SMI"
/* any C includes here */
lexer_t lex; /* additional return value info */
#define MAX_STR_LEN (1024+1)
#define SBUFFER_INS(_c) do { \
if ((sbuffer.ptr - sbuffer.base)>=MAX_STR_LEN) \
lex_fatal("Parse string too long - maximum is %d characters", MAX_STR_LEN); \
DECNUM ("0"|([1-9][0-9]*))
if (sscanf(mdlextext,"# %d \"%[^\"]\"", &num, lbuf)!=2)
lex_fatal("Illegal # directive");
if (lex.fnamep != (char*)0) Xfree(lex.fnamep);
lex.fnamep = Xstrdup(lbuf);
"proto" return T_KW_proto;
"include" return T_KW_include;
"expr(" return T_KW_expr;
"lookup(" return T_KW_lookup;
"setprop(" return T_KW_setprop;
sbuffer.ptr = sbuffer.base;
<string>\" { /* closing quote - wrap up string and return it */
lex_fatal("unterminated string");
/* octal escape sequence */
(void) sscanf( mdlextext + 1, "%o", &result );
if ( result<0 || result>0xff )
lex_fatal("error, constant is out-of-bounds");
lex_fatal("illegal escape sequence");
<string>\\n SBUFFER_INS( '\n' );
<string>\\t SBUFFER_INS( '\t' );
<string>\\r SBUFFER_INS( '\r' );
<string>\\b SBUFFER_INS( '\b' );
<string>\\f SBUFFER_INS( '\f' );
<string>\\(.|\n) SBUFFER_INS( mdlextext[1] );
while ( *iptr ) SBUFFER_INS( *iptr++ );
lex.val = strtoull(mdlextext, (char **)NULL, 16);
lex.val = strtoull(mdlextext, (char **)NULL, 16);
lex.val = strtoll(mdlextext, &ep, 10);
lex_fatal("parsing number");
lex.val = atoll(mdlextext);
lex.val = atoll(mdlextext);
[A-Za-z_#?$][A-Za-z_#\-?$0-9]* {
/* Note: . = any character EXCEPT newline */
\/\/.* { /* nada - swallow single line comments */ }
[\t ]* { /* nada - swallow white space */ }
lex_fatal("Illegal character %s", mdlextext);
void init_lexer(char * fnamep, FILE *fp, char * cleanup_filep)
lex.cleanup_filep = cleanup_filep ? Xstrdup(cleanup_filep) : (char*)0;
lex.fnamep = Xstrdup(fnamep);
lex.ungot_available = false;
lex.last_token = T_Error;
lexer_tok_t lex_get_token()
if (lex.ungot_available) {
lex.ungot_available = false;
lex.last_token = mdlexlex();
if (lex.ungot_available) fatal("Internal error, lex_unget with token already ungot");
lex.ungot_available = true;
void lex_get(lexer_tok_t expected)
if (tok == expected) return;
case T_EOF: s="end of file"; break;
case T_L_Brace: s="{"; break;
case T_R_Brace: s="}"; break;
case T_S_Colon: s=";"; break;
case T_Plus: s="+"; break;
case T_Minus: s="-"; break;
case T_Equals: s="="; break;
case T_Number: s="number"; break;
case T_String: s="string"; break;
sprintf(buffer,"token %s", lex.strp);
case T_KW_node: s="node"; break;
case T_KW_proto: s="proto"; break;
case T_KW_include: s="include("; break;
case T_KW_expr: s="expr("; break;
case T_KW_lookup: s="lookup("; break;
case T_KW_setprop: s="setprop("; break;
case T_Error: s="error"; break;
s="unknown token - internal error";
lex_fatal("unexpected %s", s);
* Special version of fatal for the lexer
* to enable cleanup of stuff before death
lex_fatal(char * fmt, ...)
fprintf(stderr,"FATAL: ");
(void) vfprintf(stderr, fmt, args);
if (lex.cleanup_filep != (char *)0) {
unlink(lex.cleanup_filep);
Xfree(lex.cleanup_filep);
fprintf(stderr," at line %d of %s\n", lex.linenum, lex.fnamep);
SANITY( lex.fnamep = NULL; );
SANITY( lex.cleanup_filep = NULL; );
fprintf(stderr,"token = %d at line %d in %s\n",tok, lex.linenum, lex.fnamep);
} while (tok!=T_Error && tok!=T_EOF);
void fatal(char* fmt, ...)
if (errno!=0) perror("FATAL: "); else fprintf(stderr,"FATAL: ");
(void)vfprintf(stderr, fmt, args);