X-Git-Url: https://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/486240dc4c5d57b0afaddba60d87fe375112bed5..d52e64e92557f0b6d7704077ec175c88fa7ca243:/src/lexer.l diff --git a/src/lexer.l b/src/lexer.l index a33eed0..0dc3cda 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -1,5 +1,7 @@ /* GOB C Preprocessor - * Copyright (C) 1999 the Free Software Foundation. + * Copyright (C) 1999-2000 the Free Software Foundation. + * Copyright (C) 2000 Eazel, Inc. + * Copyright (C) 2001-2011 George (Jiri) Lebl * * Author: George Lebl * @@ -21,8 +23,10 @@ %{ #include "config.h" -#include +#include #include +#include +#include #include "treefuncs.h" #include "parse.h" @@ -30,9 +34,17 @@ #include "util.h" static int parenth_depth = 0; -static int before_comment = INITIAL; +static int before_comment +/* New flex is on drugs */ +#if defined(FLEX_SCANNER) && ! defined(INITIAL) + = 0; +#else + = INITIAL; +#endif static gboolean class_after_c = FALSE; static int code_type = CCODE; +static int before_string; +static int property_paren_depth = 0; /* GTK+ doc stuff */ static char *gtk_doc_func = NULL; /* current gtk-doc func */ @@ -46,6 +58,8 @@ GList *include_files = NULL; static int look_for_includes = 0; int line_no = 1; +/* last filename parsed from a #line directive */ +char *hline_filename = NULL; static void clear_cbuf(void) @@ -81,18 +95,22 @@ add_gtk_doc_func(void) gtk_doc_func = NULL; } -/* Ugly warning avoiding */ +/* Ugly warning / error avoidings */ #ifdef FLEX_SCANNER int yylex(void); +int yywrap(void) { return 1; } #endif %} %x COMMENT %x C_CODE -%x C_CODE_STRING +%x CODE_STRING %x CLASS_CODE +%x CLASS_STRING %x CLASS_CODE_I +%x PROPERTY_CODE +%x PROPERTY_CODE_I %x GTK_DOC_BEFORE_NAME %x GTK_DOC %x GTK_DOC_LINE @@ -101,6 +119,14 @@ int yylex(void); %% +%{ +/* Avoid warning from flex, cuz flex sucks */ +#ifdef FLEX_SCANNER +yy_current_state = 0; +#endif +%} + + <*>\n { line_no++; REJECT; } ^(I(S.RI).E\(([1-9][0-9]+|[2-9]))/(\)) { @@ -126,7 +152,45 @@ REJECT; } \/\/.*$ { ; /*comment, ignore*/ } -^#[ \t]*include[ \t][<"][^\n">]*[>"] { + +<*>^#[ \t]*line[ \t]+[0-9]+([ \t]\"[^\n\r\f\"]*\")? { + char *p; + char *number; + char *filename; + char *str=g_strdup(yytext); + + /* find first digit of line number */ + p=str; + while(*p&&!isdigit(*p)) p++; + number=p; + + /* find end of line number */ + while(*p&&isdigit(*p)) p++; + if(*p) *p++=0; + + /* find beginning of filename */ + p=strchr(p,'"'); + if(p) p++; + filename=p; + + /* find end of filename */ + if(p) p=strchr(p,'"'); + if(p) *p=0; + + /* stash number (minus one because we don't count this line) */ + if(number) line_no=atoi(number)-1; + + /* stash filename */ + if(filename) { + if(hline_filename) g_free(hline_filename); + hline_filename=g_strdup(filename); + } + + /* clean up */ + g_free(str); +} + +^#[ \t]*include[ \t][<"][^\n\r">]*[>"] { if(look_for_includes==1) { char *p; char *file; @@ -136,9 +200,11 @@ REJECT; file++; p = strchr(file,'"'); if(!p) p = strchr(file,'>'); - *p = '\0'; - include_files = g_list_prepend(include_files,g_strdup(file)); - g_free(str); + if (p != NULL) { + *p = '\0'; + include_files = g_list_prepend(include_files,g_strdup(file)); + g_free(str); + } } REJECT; } @@ -177,7 +243,7 @@ REJECT; BEGIN(CLASS_CODE_I); add_gtk_doc_func(); } -^[ \t]*\*\ { +^[ \t]*\*[ \t] { fflush(stdout); add_to_cbuf(" * "); BEGIN(GTK_DOC_LINE); @@ -207,6 +273,7 @@ REJECT; \/\/.*$ { add_to_cbuf(yytext); /*comment, ignore*/ } \/\/.*$ { ; /*comment, ignore*/ } \/\/.*$ { ; /*comment, ignore*/ } +\/\/.*$ { ; /*comment, ignore*/ } \/\* {BEGIN(COMMENT); before_comment = INITIAL; } \/\* { add_to_cbuf(yytext); @@ -215,6 +282,7 @@ REJECT; } \/\* {BEGIN(COMMENT); before_comment = CLASS_CODE; } \/\* {BEGIN(COMMENT); before_comment = CLASS_CODE_I; } +\/\* {BEGIN(COMMENT); before_comment = PROPERTY_CODE_I; } \*\/ { if(before_comment == C_CODE) add_to_cbuf(yytext); BEGIN(before_comment); @@ -279,6 +347,24 @@ REJECT; if(look_for_includes==0) look_for_includes=1; } +^\%(ct|ctop)\{ { + BEGIN(C_CODE); + parenth_depth = 1; + class_after_c = FALSE; + code_type = CTCODE; + clear_cbuf(); + ccode_line = line_no; + if(look_for_includes==0) + look_for_includes=1; + } +^\%(ad|afterdecls)\{ { + BEGIN(C_CODE); + parenth_depth = 1; + class_after_c = FALSE; + code_type = ADCODE; + clear_cbuf(); + ccode_line = line_no; + } ^\%\} { BEGIN(INITIAL); yylval.cbuf = cbuf; @@ -296,17 +382,31 @@ REJECT; \'\\\"\' { add_to_cbuf(yytext); } \\. { add_to_cbuf(yytext); } + + \" { - BEGIN(C_CODE_STRING); + BEGIN(CODE_STRING); + before_string = C_CODE; + add_to_cbuf(yytext); + } +\" { + BEGIN(CODE_STRING); + before_string = PROPERTY_CODE_I; add_to_cbuf(yytext); } -\\. { add_to_cbuf(yytext); } -\" { - BEGIN(C_CODE); - add_to_cbuf(yytext); +\\. { add_to_cbuf(yytext); } +\" { + BEGIN(before_string); + add_to_cbuf(yytext); + if (before_string == PROPERTY_CODE_I) { + yylval.id = cbuf->str; + g_string_free (cbuf, FALSE); + cbuf = NULL; + return STRING; } -. { add_to_cbuf(yytext); } -\n { add_to_cbuf(yytext); } + } +. { add_to_cbuf(yytext); } +\n { add_to_cbuf(yytext); } \{ { parenth_depth++; @@ -334,65 +434,99 @@ class { BEGIN(CLASS_CODE); if(++found_classes > 1) { - print_error(FALSE, - "Only one class per file allowed", - line_no); + error_print(GOB_ERROR, line_no, + "Only one class per file allowed"); } return CLASS; } +error { return ERROR; } +enum { return ENUM; } +flags { return FLAGS; } + ^[ \t]*requires[ \t]+[0-9]+\.[0-9]+\.[0-9]+[\t ]*$ { - int maj = 0,min = 0,pl = 0; - int rmaj = 0,rmin = 0,rpl = 0; + int maj = 0, min = 0, pl = 0; + int rmaj = 0, rmin = 0, rpl = 0; + int effective_maj = 0; + int effective_rmaj = 0; char *p; - sscanf(VERSION,"%d.%d.%d",&rmaj,&rmin,&rpl); - p = strchr(yytext,'r'); - g_assert(p); /* we MUST have found it */ - sscanf(p,"requires %d.%d.%d",&maj,&min,&pl); + sscanf (VERSION, "%d.%d.%d", &rmaj, &rmin, &rpl); + effective_rmaj = rmaj; + if (rmin >= 90) + effective_rmaj = rmaj + 1; + + p = strchr (yytext,'r'); + g_assert (p); /* we MUST have found it */ + sscanf (p, "requires %d.%d.%d", &maj, &min, &pl); + effective_maj = maj; + if (min >= 90) + effective_maj = maj + 1; + if(rmaj < maj || (rmaj == maj && rmin < min) || (rmaj == maj && rmin == min && rpl < pl)) { - char *s; - s = g_strdup_printf( - "GOB version %d.%d.%d required " - "(this is %s)\n" - "To upgrade your gob, see: " - "http://www.5z.com/jirka/gob.html", - maj,min,pl,VERSION); - print_error(FALSE, s, line_no); - g_free(s); + error_printf (GOB_ERROR, line_no, + "GOB version at least %d.%d.%d required " + "(this is %s)\n" + "To upgrade your gob, see: " + "http://www.5z.com/jirka/gob.html", + maj, min, pl, VERSION); + } + + if(effective_rmaj != effective_maj) { + error_printf(GOB_ERROR, line_no, + "GOB major version %d required " + "(this is %s)\n" + "To upgrade your gob, see: " + "http://www.5z.com/jirka/gob.html", + effective_maj, VERSION); } + } class|this { if(for_cpp) { - char *s; - s = g_strdup_printf("'%s' keyword should not " - "be used when generating " - "C++ code", yytext); - print_error(TRUE, s, line_no); - g_free(s); + error_printf(GOB_WARN, line_no, + "'%s' keyword should not " + "be used when generating " + "C++ code", yytext); } REJECT; } from {return FROM;} - -void {return VOID;} -struct {return STRUCT;} -union {return UNION;} -enum {return ENUM;} -signed {return SIGNED;} -unsigned {return UNSIGNED;} -long {return LONG;} -short {return SHORT;} -int {return INT;} -float {return FLOAT;} -double {return DOUBLE;} -char {return CHAR;} -const {return CONST;} +\" { + BEGIN(CLASS_STRING); + before_string = CLASS_CODE; + add_to_cbuf(yytext); + } +\\. { add_to_cbuf(yytext); } +\" { + BEGIN(before_string); + add_to_cbuf(yytext); + yylval.id = cbuf->str; + g_string_free (cbuf, FALSE); + cbuf = NULL; + return STRING; + } +. { add_to_cbuf(yytext); } +\n { add_to_cbuf(yytext); } + +void {return VOID;} +struct {return STRUCT;} +union {return UNION;} +enum {return ENUM;} +signed {return SIGNED;} +unsigned {return UNSIGNED;} +long {return LONG;} +short {return SHORT;} +int {return INT;} +float {return FLOAT;} +double {return DOUBLE;} +char {return CHAR;} +const {return CONST;} \.\.\. {return THREEDOTS;} @@ -404,35 +538,89 @@ class { virtual {yylval.line = line_no; return VIRTUAL;} signal {yylval.line = line_no; return SIGNAL;} override {yylval.line = line_no; return OVERRIDE;} -0|[1-9][0-9]*|0x[0-9a-fA-F]+|0[0-7]+|[0-9]*\.[0-9]+|\.[0-9][0-9]* { +property { + yylval.line = line_no; + BEGIN(PROPERTY_CODE); + return PROPERTY; + } +nick { yylval.line = line_no; return NICK; } +blurb { yylval.line = line_no; return BLURB; } +maximum { yylval.line = line_no; return MAXIMUM; } +minimum { yylval.line = line_no; return MINIMUM; } +default_value { yylval.line = line_no; return DEFAULT_VALUE; } +flags { yylval.line = line_no; return FLAGS; } +type { yylval.line = line_no; return TYPE; } +flags_type { yylval.line = line_no; return FLAGS_TYPE; } +enum_type { yylval.line = line_no; return ENUM_TYPE; } +param_type { yylval.line = line_no; return PARAM_TYPE; } +boxed_type { yylval.line = line_no; return BOXED_TYPE; } +object_type { yylval.line = line_no; return OBJECT_TYPE; } +[(] { + yylval.line = line_no; + property_paren_depth = 1; + BEGIN(PROPERTY_CODE_I); + return '('; + } +[(] { + yylval.line = line_no; + property_paren_depth++; + return '('; + } +[)] { + yylval.line = line_no; + property_paren_depth--; + if (property_paren_depth == 0) { + BEGIN(CLASS_CODE_I); + } + return ')'; + } + +0|[1-9][0-9]*|0x[0-9a-fA-F]+|0[0-7]+|[0-9]*\.[0-9]+|\.[0-9][0-9]* { yylval.id = g_strdup(yytext); return NUMBER; } -[A-Za-z_][A-Za-z0-9_]*(:[A-Za-z0-9_]*)+ { +[A-Za-z_][A-Za-z0-9_]*(::[A-Za-z0-9_]*)+ { + /* This is cpp kind of token thingie */ + if (for_cpp) { + yylval.id = g_strdup(yytext); + return TOKEN; + } else { + REJECT; + } + } +[A-Za-z_][A-Za-z0-9_]*(:[A-Za-z_][A-Za-z0-9_]*)+ { /* this one is for a classname with a namespace */ yylval.id = g_strdup(yytext); return TYPETOKEN; } -:[A-Za-z_][A-Za-z0-9_]*(:[A-Za-z0-9_]*)* { +:[A-Za-z_][A-Za-z0-9_]*(:[A-Za-z_][A-Za-z0-9_]*)* { /* this is for a classname with an empty namespace */ yylval.id = g_strdup(yytext); return TYPETOKEN; } -[A-Za-z_][A-Za-z0-9_]* { +[A-Za-z_][A-Za-z0-9_]* { yylval.id = g_strdup(yytext); return TOKEN; } +\'\\.\'|\'.\' { + yylval.id = g_strdup(yytext); + return SINGLE_CHAR; + } (\[[0-9]*\]|\[[A-Za-z_][A-Za-z0-9_]*\])+ { yylval.id = g_strdup(yytext); return ARRAY_DIM; } - +:[0-9]+ { + /* cheat for bitfield */ + yylval.id = g_strdup(yytext); + return ARRAY_DIM; + } \{ { BEGIN(CLASS_CODE_I); return '{'; } -\{ { +\{ { BEGIN(C_CODE); parenth_depth=1; class_after_c = TRUE; @@ -446,24 +634,23 @@ class { return '}'; } -[\t ] ; /*ignore*/ +[\f\t ] ; /*ignore*/ + +<*>[\n\r] ; /*ignore*/ + <*>. { yylval.line = line_no; return yytext[0]; } -<*>[\n\r] ; /*ignore*/ +^[ \t]*prealloc[ \t]+[0-9]+[ \t]*$ { + char *p; + int t; + p = strchr (yytext,'p'); + g_assert (p); /* we MUST have found it */ + sscanf (p, "prealloc %d", &t); + prealloc=t; + } %% - -/* Ugly warning avoiding */ -#ifdef FLEX_SCANNER -static void warning_avoider(void) G_GNUC_UNUSED; -static void warning_avoider(void) { - yy_flex_realloc(NULL, 0); - yyunput(0, NULL); - warning_avoider(); -} -#endif -