OD [0-7] NZD [1-9] D [0-9] H [a-fA-F0-9] L [a-zA-Z_] E ([Ee][+\-]?{D}+) FS (f|F|l|L) IS ([uU][lL]?|[lL][uU]?) %x Str incl %pointer %{ #include "m.h" #define MAXSTR BUFSIZ static char string_buf[MAXSTR]; static char *p; static int quote; static int copychar( int c); void count( void); void comment( void); int check_type( void); void yyerror( const char *msg); static int floating_constant( void); static int integer_constant( int base); static int char_constant( void); static int string_literal( void); /* * code to handle #include was adapted from the example in flexdoc.1 */ #define MAX_INCLUDE_DEPTH 10 static int include_stack_ptr = 0; static struct { FILE *fp; YY_BUFFER_STATE state; } include_stack[MAX_INCLUDE_DEPTH]; int isatty(int fd); /* to avoid gcc warning */ %} %% "/*" { comment(); } "NULL" { /* added this. RP */ count(); yylval.sym = NULL; return(CONSTANT); } ^[ \t]*"#"[ \t]*"include" { count(); BEGIN(incl); } "auto" { count(); return(AUTO); } "break" { count(); return(BREAK); } "case" { count(); return(CASE); } "char" { count(); return(CHAR); } "const" { count(); return(CONST); } "continue" { count(); return(CONTINUE); } "default" { count(); return(DEFAULT); } "do" { count(); return(DO); } "double" { count(); return(DOUBLE); } "else" { count(); return(ELSE); } "enum" { count(); return(ENUM); } "extern" { count(); return(EXTERN); } "float" { count(); return(FLOAT); } "for" { count(); return(FOR); } "goto" { count(); return(GOTO); } "if" { count(); return(IF); } "int" { count(); return(INT); } "long" { count(); return(LONG); } "register" { count(); return(REGISTER); } "return" { count(); return(RETURN); } "short" { count(); return(SHORT); } "signed" { count(); return(SIGNED); } "sizeof" { count(); return(SIZEOF); } "static" { count(); return(STATIC); } "struct" { count(); return(STRUCT); } "switch" { count(); return(SWITCH); } "typedef" { count(); return(TYPEDEF); } "union" { count(); return(UNION); } "unsigned" { count(); return(UNSIGNED); } "void" { count(); return(VOID); } "volatile" { count(); return(VOLATILE); } "while" { count(); return(WHILE); } {L}({L}|{D})* { count(); return(check_type()); /* identifier */ } 0[xX]{H}+{IS}? { count(); return(integer_constant(16)); } 0{OD}*{IS}? { count(); return(integer_constant(8)); } {NZD}{D}*{IS}? { count(); return(floating_constant()); } {D}+{E}{FS}? { count(); return(floating_constant()); } {D}*"."{D}+{E}?{FS}? { count(); return(floating_constant()); } {D}+"."{E}?{FS}? { count(); return(floating_constant()); } L?(\"|') { count(); p = string_buf; quote = (yytext[0] == 'L') ? yytext[1] : yytext[0]; BEGIN(Str); } \"|' { count(); if( yytext[0] == quote) { /* saw closing quote - all done */ BEGIN(INITIAL); if( !copychar( '\0') ) *--p = '\0'; if( quote == '\'' && p == string_buf) yyerror("scan: empty char constant"); return (quote == '"') ? string_literal() : char_constant(); } else copychar( yytext[0]); } \\{OD}{1,3}|\\x{H}+ { /* octal or hex escape sequence */ unsigned result; count(); if( sscanf( yytext + 1 + (yytext[1] == 'x'), (yytext[1] == 'x') ? "%x" : "%o", &result ) != 1) yyerror( "scan: sscanf() failed on octal or hex escape sequence"); /* check for out-of-bounds result */ if( result != (unsigned char) result) yyerror( "scan: octal/hex escape sequence overflow"); copychar( result); } \\' { count(); copychar( '\''); } \\\" { count(); copychar( '\"'); } \\\? { count(); copychar( '\?'); } \\\\ { count(); copychar( '\\'); } \\a { count(); copychar( '\a'); } \\b { count(); copychar( '\b'); } \\f { count(); copychar( '\f'); } \\n { count(); copychar( '\n'); } \\r { count(); copychar( '\r'); } \\t { count(); copychar( '\t'); } \\v { count(); copychar( '\v'); } \\. { count(); copychar( yytext[1]); yyerror("scan: bad escape character"); } \n { count(); yyerror("scan: newline in string"); } [^\\\n'\"]+ { char *yyp = yytext; count(); while ( *yyp ) copychar( *yyp++); } . { count(); yyerror("scan: bad character"); } "..." { count(); return(ELIPSIS); } ">>=" { count(); return(RIGHT_ASSIGN); } "<<=" { count(); return(LEFT_ASSIGN); } "+=" { count(); return(ADD_ASSIGN); } "-=" { count(); return(SUB_ASSIGN); } "*=" { count(); return(MUL_ASSIGN); } "/=" { count(); return(DIV_ASSIGN); } "%=" { count(); return(MOD_ASSIGN); } "&=" { count(); return(AND_ASSIGN); } "^=" { count(); return(XOR_ASSIGN); } "|=" { count(); return(OR_ASSIGN); } ">>" { count(); return(RIGHT_OP); } "<<" { count(); return(LEFT_OP); } "++" { count(); return(INC_OP); } "--" { count(); return(DEC_OP); } "->" { count(); return(PTR_OP); } "&&" { count(); return(AND_OP); } "||" { count(); return(OR_OP); } "<=" { count(); return(LE_OP); } ">=" { count(); return(GE_OP); } "==" { count(); return(EQ_OP); } "!=" { count(); return(NE_OP); } ";" { count(); return(';'); } "{" { count(); return('{'); } "}" { count(); return('}'); } "," { count(); return(','); } ":" { count(); return(':'); } "=" { count(); return('='); } "(" { count(); return('('); } ")" { count(); return(')'); } "[" { count(); return('['); } "]" { count(); return(']'); } "." { count(); return('.'); } "&" { count(); return('&'); } "!" { count(); return('!'); } "~" { count(); return('~'); } "-" { count(); return('-'); } "+" { count(); return('+'); } "*" { count(); return('*'); } "/" { count(); return('/'); } "%" { count(); return('%'); } "<" { count(); return('<'); } ">" { count(); return('>'); } "^" { count(); return('^'); } "|" { count(); return('|'); } "?" { count(); return('?'); } [ \t]* { count(); /* eat the whitespace */ } [ \t]*\n { count(); BEGIN(INITIAL); yyerror("scan: missing filename after #include"); } [^ \t\n]+ { /* got the include file name */ FILE *fp; count(); if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) { yyerror( "Includes nested too deeply" ); BEGIN(INITIAL); YY_BREAK } fp = open_include( yytext); if ( ! fp ) { yyerror( "can't open #include file in yylex()"); BEGIN(INITIAL); YY_BREAK } include_stack[include_stack_ptr].state = YY_CURRENT_BUFFER; include_stack[include_stack_ptr++].fp = fp; yy_switch_to_buffer( yy_create_buffer( fp, YY_BUF_SIZE ) ); BEGIN(INITIAL); } <> { if ( --include_stack_ptr < 0 ) { yyterminate(); } else { if( fclose( include_stack[include_stack_ptr].fp) != 0) perror( "fclose() in yylex()"); yy_delete_buffer( YY_CURRENT_BUFFER ); yy_switch_to_buffer( include_stack[include_stack_ptr].state ); } } [ \t\v\n\f] { count(); } . { count(); return yytext[0]; /* bad token */ } %% #undef yywrap int yywrap( void) { return(1); } void comment( void) { char c = 0, d; while( (d = input()) != 0) if( c == '*' && d == '/') return; else c = d; yyerror( "scan: unterminated comment"); } int column = 0; void count( void) { int i; for (i = 0; yytext[i] != '\0'; i++) if (yytext[i] == '\n') column = 0; else if (yytext[i] == '\t') column += 8 - (column % 8); else column++; } int check_type( void) { /* * pseudo code --- this is what it should check * * if (yytext == type_name) * return(TYPE_NAME); * * return(IDENTIFIER); */ if( (yylval.sym = lookup( yytext)) == NULL) yylval.sym = install( yytext, UNDEF, NEW, 0, 0); /* built-in TYPE_NAME symbols are defined in init.h */ if( yylval.sym->type == TYPE_NAME) return TYPE_NAME; return IDENTIFIER; } /* * attempt to append a character to string_buf array */ static int copychar( int c) { if( p < string_buf + MAXSTR) { /* have room */ *p++ = c; return 1; } else { yyerror( "scan: string overflow"); return 0; } } /* to avoid gcc warnings */ static void yy_flex_strcpy( char *s1, const char *s2 ) {} void *junk[] = { (void *) yyunput, (void *) yy_push_state, (void *) yy_pop_state, (void *) yy_top_state, (void *) yy_flex_strcpy }; #include static int floating_constant( void) { double x; errno = 0; x = strtod( yytext, NULL); /* no need to check *endp here */ if( errno) { perror("strtod"); yyerror( "bad number in floating_constant()"); } if( (yylval.sym = install( NULL, NUMBER, indef ? DEFN : (inloop ? LOOP : CONST), 1, 1)) ) VAL(yylval.sym) = x; return CONSTANT; } static int integer_constant( int base) { double x; errno = 0; x = strtol( yytext, NULL, base); /* no need to check *endp here */ if( errno) { perror("strtol"); yyerror( "bad number in integer_constant()"); } if( (yylval.sym = install( NULL, NUMBER, indef ? DEFN : (inloop ? LOOP : CONST), 1, 1)) ) VAL(yylval.sym) = x; return CONSTANT; } static int string_literal( void) { yylval.sym = install( NULL, STRING, indef ? DEFN : (inloop ? LOOP : CONST), 1, strlen(string_buf)); if( (STR(yylval.sym) = strdup(string_buf)) == NULL) error("strdup() failed in yylex()",""); return STRING_LITERAL; } static int char_constant( void) { if( (yylval.sym = install( NULL, NUMBER, indef ? DEFN : (inloop ? LOOP : CONST), 1, 1)) ) VAL(yylval.sym) = string_buf[0]; return CONSTANT; }