/* GOB C Preprocessor * Copyright (C) 1999 the Free Software Foundation. * * Author: George Lebl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ %{ #include "config.h" #include #include #include "parse.h" #include "main.h" #include "util.h" static int parenth_depth = 0; static int before_comment = INITIAL; static gboolean class_after_c = FALSE; static int code_type = CCODE; static GString *cbuf = NULL; int ccode_line = 1; GList *include_files = NULL; /* 0 no, 1 means yes, 2+ means don't even start looking anymore */ static int look_for_includes = 0; int line_no = 1; static void clear_cbuf(void) { if(!cbuf) { cbuf = g_string_new(""); } else { cbuf = g_string_assign(cbuf,""); } } static void add_to_cbuf(char *s) { if(!cbuf) { cbuf = g_string_new(s); } else { cbuf = g_string_append(cbuf,s); } } %} %x COMMENT %x C_CODE %x C_CODE_STRING %x CLASS_CODE %x CLASS_CODE_I %% <*>\n { line_no++; REJECT; } <*>MOTHERFUCKER { fprintf(stderr,"You are a bad bad person!\n"); REJECT; } \/\/.*$ { ; /*comment, ignore*/ } ^#[ \t]*include[ \t][<"][^\n">]*[>"] { if(look_for_includes==1) { char *p; char *file; char *str = g_strdup(yytext); file = strchr(str,'"'); if(!file) file = strchr(str,'<'); file++; p = strchr(file,'"'); if(!p) p = strchr(file,'>'); *p = '\0'; include_files = g_list_prepend(include_files,g_strdup(file)); g_free(str); } REJECT; } \/\/.*$ { add_to_cbuf(yytext); /*comment, ignore*/ } \/\/.*$ { ; /*comment, ignore*/ } \/\/.*$ { ; /*comment, ignore*/ } \/\* {BEGIN(COMMENT); before_comment = INITIAL; } \/\* { add_to_cbuf(yytext); BEGIN(COMMENT); before_comment = C_CODE; } \/\* {BEGIN(COMMENT); before_comment = CLASS_CODE; } \/\* {BEGIN(COMMENT); before_comment = CLASS_CODE_I; } \*\/ { if(before_comment == C_CODE) add_to_cbuf(yytext); BEGIN(before_comment); } . { /* comment, ignore */ if(before_comment == C_CODE) add_to_cbuf(yytext); } \n { /* comment, ignore */ if(before_comment == C_CODE) add_to_cbuf(yytext); } ^\%(ht|headertop)\{ { BEGIN(C_CODE); parenth_depth = 1; class_after_c = FALSE; code_type = HTCODE; clear_cbuf(); ccode_line = line_no; } ^\%(ph|privateheader)\{ { BEGIN(C_CODE); parenth_depth = 1; class_after_c = FALSE; code_type = PHCODE; clear_cbuf(); ccode_line = line_no; } ^\%(h|header)\{ { BEGIN(C_CODE); parenth_depth = 1; class_after_c = FALSE; code_type = HCODE; clear_cbuf(); ccode_line = line_no; } ^\%\{ { BEGIN(C_CODE); parenth_depth = 1; class_after_c = FALSE; code_type = CCODE; clear_cbuf(); ccode_line = line_no; if(look_for_includes==0) look_for_includes=1; } ^\%\} { BEGIN(INITIAL); yylval.cbuf = cbuf; cbuf = NULL; if(look_for_includes==1) look_for_includes=0; return code_type; } \'\{\' { add_to_cbuf(yytext); } \'\\\{\' { add_to_cbuf(yytext); } \'\}\' { add_to_cbuf(yytext); } \'\\\}\' { add_to_cbuf(yytext); } \'\"\' { add_to_cbuf(yytext); } \'\\\"\' { add_to_cbuf(yytext); } \\. { add_to_cbuf(yytext); } \" { BEGIN(C_CODE_STRING); add_to_cbuf(yytext); } \\. { add_to_cbuf(yytext); } \" { BEGIN(C_CODE); add_to_cbuf(yytext); } . { add_to_cbuf(yytext); } \n { add_to_cbuf(yytext); } \{ { parenth_depth++; add_to_cbuf(yytext); } \} { parenth_depth--; if(parenth_depth<0) { REJECT; } else if(parenth_depth==0 && class_after_c) { BEGIN(CLASS_CODE_I); yylval.cbuf = cbuf; cbuf = NULL; return CCODE; } add_to_cbuf(yytext); } . { add_to_cbuf(yytext); } \n { add_to_cbuf(yytext); } class { look_for_includes = 2; BEGIN(CLASS_CODE); return CLASS; } ^[ \t]*requires[ \t]+[0-9]+\.[0-9]+\.[0-9]+[\t ]*$ { int maj = 0,min = 0,pl = 0; int rmaj = 0,rmin = 0,rpl = 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); 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); } } 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); } 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;} \.\.\. {return THREEDOTS;} public {yylval.line = line_no; return PUBLIC;} private {yylval.line = line_no; return PRIVATE;} protected {yylval.line = line_no; return PROTECTED;} argument {yylval.line = line_no; return ARGUMENT;} virtual {yylval.line = line_no; return VIRTUAL;} signal {yylval.line = line_no; return SIGNAL;} override {yylval.line = line_no; return OVERRIDE;} onerror {return ONERROR;} 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_]*)+ { yylval.id = g_strdup(yytext); return TYPETOKEN; } [A-Za-z_][A-Za-z0-9_]* { yylval.id = g_strdup(yytext); return TOKEN; } (\[[0-9]*\])+ { yylval.id = g_strdup(yytext); return ARRAY_DIM; } \{ { BEGIN(CLASS_CODE_I); return '{'; } \{ { BEGIN(C_CODE); parenth_depth=1; class_after_c = TRUE; yylval.line = line_no; clear_cbuf(); ccode_line = line_no; return '{'; } \} { BEGIN(INITIAL); return '}'; } [\t ] ; /*ignore*/ <*>. { yylval.line = line_no; return yytext[0]; } <*>[\n\r] ; /*ignore*/