/* * 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 */ #include #include #include #include #include #include #include "basics.h" #include "allocate.h" #include "lexer.h" #include "fatal.h" lexer_t lex; /* additional return value info */ #define MAX_STR_LEN (1024+1) static struct { char base[MAX_STR_LEN]; char * ptr; } sbuffer; #if TESTRIG /* { */ #include #include void fatal(char *s,...); #endif /* } */ #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); \ *sbuffer.ptr++ = (_c); \ } while(0) %} DECNUM ("0"|([1-9][0-9]*)) %x comment %x string %% <> return T_EOF; "{" return T_L_Brace; "}" return T_R_Brace; ")" return T_R_Bracket; "," return T_Comma; ";" return T_S_Colon; "+" return T_Plus; "*" return T_Multiply; "-" return T_Minus; "&" return T_And; "|" return T_Or; "^" return T_Xor; "~" return T_Not; "<<" return T_LShift; "=" return T_Equals; "]" return T_R_Bracket; "[" return T_L_Bracket; ^"#"[ \t].*$ { char lbuf[1024]; int num; if (sscanf(mdlextext,"# %d \"%[^\"]\"", &num, lbuf)!=2) lex_fatal("Illegal # directive"); lex.linenum = num-1; if (lex.fnamep != (char*)0) Xfree(lex.fnamep); lex.fnamep = Xstrdup(lbuf); } "node" return T_KW_node; "proto" return T_KW_proto; "include" return T_KW_include; "(" return T_KW_expr; "expr(" return T_KW_expr; "lookup(" return T_KW_lookup; "setprop(" return T_KW_setprop; "->" return T_KW_arc; \" { sbuffer.ptr = sbuffer.base; BEGIN(string); } \" { /* closing quote - wrap up string and return it */ BEGIN(INITIAL); sbuffer.ptr[0]='\0'; lex.strp = sbuffer.base; return T_String; } \n { lex_fatal("unterminated string"); } \\[0-7]{1,3} { /* octal escape sequence */ int result; result=-1; (void) sscanf( mdlextext + 1, "%o", &result ); if ( result<0 || result>0xff ) lex_fatal("error, constant is out-of-bounds"); SBUFFER_INS( result ); } \\[0-9]+ { lex_fatal("illegal escape sequence"); } \\n SBUFFER_INS( '\n' ); \\t SBUFFER_INS( '\t' ); \\r SBUFFER_INS( '\r' ); \\b SBUFFER_INS( '\b' ); \\f SBUFFER_INS( '\f' ); \\(.|\n) SBUFFER_INS( mdlextext[1] ); [^\\\n\"]+ { char *iptr = mdlextext; while ( *iptr ) SBUFFER_INS( *iptr++ ); } "0x"[0-9A-F][0-9A-F]* { lex.val = strtoull(mdlextext, (char **)NULL, 16); return T_Number; } "0x"[0-9a-f][0-9a-f]* { lex.val = strtoull(mdlextext, (char **)NULL, 16); return T_Number; } {DECNUM}[KkMmGg] { char * ep; lex.val = strtoll(mdlextext, &ep, 10); switch(*ep) { case 'G': case 'g': lex.val <<= 30; break; case 'M': case 'm': lex.val <<= 20; break; case 'K': case 'k': lex.val <<= 10; break; default: lex_fatal("parsing number"); } return T_Number; } {DECNUM} { lex.val = atoll(mdlextext); return T_Number; } \-{DECNUM} { lex.val = atoll(mdlextext); return T_Number; } [A-Za-z_#?$][A-Za-z_#\-?$0-9]* { lex.strp = mdlextext; return T_Token; } /* Note: . = any character EXCEPT newline */ \/\/.* { /* nada - swallow single line comments */ } [\t ]* { /* nada - swallow white space */ } "\n" { lex.linenum ++; } . { 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.linenum = 1; lex.fnamep = Xstrdup(fnamep); lex.ungot_available = false; lex.last_token = T_Error; mdlexin = fp; } lexer_tok_t lex_get_token() { if (lex.ungot_available) { lex.ungot_available = false; return lex.last_token; } lex.last_token = mdlexlex(); return lex.last_token; } void lex_unget() { if (lex.ungot_available) fatal("Internal error, lex_unget with token already ungot"); lex.ungot_available = true; } void lex_get(lexer_tok_t expected) { lexer_tok_t tok; char *s; char buffer[1024]; tok = lex_get_token(); if (tok == expected) return; switch(tok) { 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; case T_Token: sprintf(buffer,"token %s", lex.strp); s=buffer; break; 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; default: s="unknown token - internal error"; break; } lex_fatal("unexpected %s", s); } /* * Special version of fatal for the lexer * to enable cleanup of stuff before death */ void lex_fatal(char * fmt, ...) { va_list args; if (errno != 0) perror("FATAL: "); else fprintf(stderr,"FATAL: "); if (fmt) { va_start(args, fmt); (void) vfprintf(stderr, fmt, args); va_end(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); Xfree(lex.fnamep); SANITY( lex.fnamep = NULL; ); SANITY( lex.cleanup_filep = NULL; ); exit(1); } int mdlexwrap(void) { return (1); } #if TESTRIG /* { */ main() { lexer_tok_t tok; lex.linenum = 1; lex.fnamep = "test"; do { tok = lexlex(); 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, ...) { va_list args; int status; if (errno!=0) perror("FATAL: "); else fprintf(stderr,"FATAL: "); if (fmt) { va_start(args, fmt); (void)vfprintf(stderr, fmt, args); va_end(args); } fprintf(stderr,"\n"); fflush(stderr); fflush(stdout); thr_exit(&status); } #endif /* } */