| %{ |
| /* m2.flex implements lexical analysis for Modula-2. |
| |
| Copyright (C) 2004-2023 Free Software Foundation, Inc. |
| Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>. |
| |
| This file is part of GNU Modula-2. |
| |
| GNU Modula-2 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 3, or (at your option) |
| any later version. |
| |
| GNU Modula-2 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 GNU Modula-2; see the file COPYING3. If not see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include "gm2-gcc/gcc-consolidation.h" |
| |
| #include "GM2Reserved.h" |
| #include "GM2LexBuf.h" |
| #include "input.h" |
| #include "m2options.h" |
| |
| static int cpreprocessor = 0; /* Replace this with correct getter. */ |
| |
| #if defined(GM2USEGGC) |
| # include "ggc.h" |
| #endif |
| |
| #include "timevar.h" |
| |
| #define START_FILE(F,L) m2linemap_StartFile(F,L) |
| #define END_FILE() m2linemap_EndFile() |
| #define START_LINE(N,S) m2linemap_StartLine(N,S) |
| #define GET_LOCATION(COLUMN_START,COLUMN_END) \ |
| m2linemap_GetLocationRange(COLUMN_START,COLUMN_END) |
| #define TIMEVAR_PUSH_LEX timevar_push (TV_LEX) |
| #define TIMEVAR_POP_LEX timevar_pop (TV_LEX) |
| |
| #ifdef __cplusplus |
| #define EXTERN extern "C" |
| #endif |
| |
| /* m2.flex provides a lexical analyser for GNU Modula-2. */ |
| |
| struct lineInfo { |
| char *linebuf; /* line contents */ |
| int linelen; /* length */ |
| int tokenpos; /* start position of token within line */ |
| int toklen; /* a copy of yylen (length of token) */ |
| int nextpos; /* position after token */ |
| int lineno; /* line number of this line */ |
| int column; /* first column number of token on this line */ |
| int inuse; /* do we need to keep this line info? */ |
| location_t location; /* the corresponding gcc location_t */ |
| struct lineInfo *next; |
| }; |
| |
| struct functionInfo { |
| char *name; /* function name */ |
| int module; /* is it really a module? */ |
| struct functionInfo *next; /* list of nested functions */ |
| }; |
| |
| static int lineno =1; /* a running count of the file line number */ |
| static char *filename =NULL; |
| static int commentLevel=0; |
| static int commentCLevel=0; |
| static struct lineInfo *currentLine=NULL; |
| static struct functionInfo *currentFunction=NULL; |
| static int seenFunctionStart=FALSE; |
| static int seenEnd=FALSE; |
| static int seenModuleStart=FALSE; |
| static int isDefinitionModule=FALSE; |
| static int totalLines=0; |
| |
| static void pushLine (void); |
| static void popLine (void); |
| static void finishedLine (void); |
| static void resetpos (void); |
| static void consumeLine (void); |
| static void updatepos (void); |
| static void skippos (void); |
| static void poperrorskip (const char *); |
| static void endOfComment (void); |
| static void endOfCComment (void); |
| static void splitSlashStar (void); |
| static void handleDate (void); |
| static void handleLine (void); |
| static void handleFile (void); |
| static void handleFunction (void); |
| static void handleColumn (void); |
| static void pushFunction (char *function, int module); |
| static void popFunction (void); |
| static void checkFunction (void); |
| EXTERN void m2flex_M2Error (const char *); |
| EXTERN location_t m2flex_GetLocation (void); |
| EXTERN int m2flex_GetColumnNo (void); |
| EXTERN int m2flex_OpenSource (char *s); |
| EXTERN int m2flex_GetLineNo (void); |
| EXTERN void m2flex_CloseSource (void); |
| EXTERN char *m2flex_GetToken (void); |
| EXTERN void _M2_m2flex_init (void); |
| EXTERN int m2flex_GetTotalLines (void); |
| extern void yylex (void); |
| |
| #if !defined(TRUE) |
| # define TRUE (1==1) |
| #endif |
| #if !defined(FALSE) |
| # define FALSE (1==0) |
| #endif |
| |
| #define YY_DECL void yylex (void) |
| %} |
| |
| %option nounput |
| %x COMMENT COMMENT1 COMMENTC LINE0 LINE1 LINE2 |
| |
| %% |
| |
| "(*" { updatepos(); |
| commentLevel=1; pushLine(); skippos(); |
| BEGIN COMMENT; } |
| <COMMENT>"*)" { endOfComment(); } |
| <COMMENT>"(*" { commentLevel++; pushLine(); updatepos(); skippos(); } |
| <COMMENT>"<*" { if (commentLevel == 1) { |
| updatepos(); |
| pushLine(); |
| skippos(); |
| BEGIN COMMENT1; |
| } else { |
| updatepos(); skippos(); |
| } |
| } |
| <COMMENT>\n.* { consumeLine(); } |
| <COMMENT>. { updatepos(); skippos(); } |
| <COMMENT1>. { updatepos(); skippos(); } |
| <COMMENT1>"*>" { updatepos(); skippos(); finishedLine(); BEGIN COMMENT; } |
| <COMMENT1>\n.* { consumeLine(); } |
| <COMMENT1>"*)" { poperrorskip("unterminated source code directive, missing *>"); |
| endOfComment(); } |
| <COMMENT1><<EOF>> { poperrorskip("unterminated source code directive, missing *>"); BEGIN COMMENT; } |
| <COMMENT><<EOF>> { poperrorskip("unterminated comment found at the end of the file, missing *)"); BEGIN INITIAL; } |
| |
| "/*" { /* Possibly handle C preprocessor comment. */ |
| if (cpreprocessor) |
| { |
| updatepos (); |
| commentCLevel++; |
| if (commentCLevel == 1) |
| { |
| pushLine (); |
| skippos (); |
| } |
| BEGIN COMMENTC; |
| } |
| else |
| splitSlashStar (); |
| } |
| <COMMENTC>. { updatepos(); skippos(); } |
| <COMMENTC>\n.* { consumeLine(); } |
| <COMMENTC>"*/" { endOfCComment(); } |
| ^\#.* { consumeLine(); /* printf("found: %s\n", currentLine->linebuf); */ BEGIN LINE0; } |
| \n\#.* { consumeLine(); /* printf("found: %s\n", currentLine->linebuf); */ BEGIN LINE0; } |
| <LINE0>\#[ \t]* { updatepos(); } |
| <LINE0>[0-9]+[ \t]*\" { updatepos(); lineno=atoi(yytext)-1; BEGIN LINE1; } |
| <LINE0>\n { m2flex_M2Error("missing initial quote after #line directive"); resetpos(); BEGIN INITIAL; } |
| <LINE0>[^\n] |
| <LINE1>[^\"\n]+ { m2flex_M2Error("missing final quote after #line directive"); resetpos(); BEGIN INITIAL; } |
| <LINE1>.*\" { updatepos(); |
| filename = (char *)xrealloc(filename, yyleng+1); |
| strcpy(filename, yytext); |
| filename[yyleng-1] = (char)0; /* remove trailing quote */ |
| START_FILE (filename, lineno); |
| BEGIN LINE2; |
| } |
| <LINE2>[ \t]* { updatepos(); } |
| <LINE2>\n { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; } |
| <LINE2>2[ \t]*\n { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; } |
| <LINE2>1[ \t]*\n { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; } |
| <LINE2>1[ \t]*.*\n { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; } |
| <LINE2>2[ \t]*.*\n { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; } |
| <LINE2>3[ \t]*.*\n { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; } |
| |
| \n[^\#].* { consumeLine(); /* printf("found: %s\n", currentLine->linebuf); */ } |
| \n { consumeLine(); /* printf("found: %s\n", currentLine->linebuf); */ } |
| |
| \"[^\"\n]*\" { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_stringtok, yytext); return; } |
| \"[^\"\n]*$ { updatepos(); |
| m2flex_M2Error("missing terminating quote, \""); |
| resetpos(); return; |
| } |
| |
| '[^'\n]*' { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_stringtok, yytext); return; } |
| '[^'\n]*$ { updatepos(); |
| m2flex_M2Error("missing terminating quote, '"); |
| resetpos(); return; |
| } |
| |
| <<EOF>> { updatepos(); M2LexBuf_AddTok(M2Reserved_eoftok); return; } |
| \+ { updatepos(); M2LexBuf_AddTok(M2Reserved_plustok); return; } |
| - { updatepos(); M2LexBuf_AddTok(M2Reserved_minustok); return; } |
| "*" { updatepos(); M2LexBuf_AddTok(M2Reserved_timestok); return; } |
| \/ { updatepos(); M2LexBuf_AddTok(M2Reserved_dividetok); return; } |
| := { updatepos(); M2LexBuf_AddTok(M2Reserved_becomestok); return; } |
| \& { updatepos(); M2LexBuf_AddTok(M2Reserved_ambersandtok); return; } |
| \. { updatepos(); M2LexBuf_AddTok(M2Reserved_periodtok); return; } |
| \, { updatepos(); M2LexBuf_AddTok(M2Reserved_commatok); return; } |
| \; { updatepos(); M2LexBuf_AddTok(M2Reserved_semicolontok); return; } |
| \( { updatepos(); M2LexBuf_AddTok(M2Reserved_lparatok); return; } |
| \) { updatepos(); M2LexBuf_AddTok(M2Reserved_rparatok); return; } |
| \[ { updatepos(); M2LexBuf_AddTok(M2Reserved_lsbratok); return; } |
| \] { updatepos(); M2LexBuf_AddTok(M2Reserved_rsbratok); return; } |
| \(\! { updatepos(); M2LexBuf_AddTok(M2Reserved_lsbratok); return; } |
| \!\) { updatepos(); M2LexBuf_AddTok(M2Reserved_rsbratok); return; } |
| \^ { updatepos(); M2LexBuf_AddTok(M2Reserved_uparrowtok); return; } |
| \@ { updatepos(); M2LexBuf_AddTok(M2Reserved_uparrowtok); return; } |
| \{ { updatepos(); M2LexBuf_AddTok(M2Reserved_lcbratok); return; } |
| \} { updatepos(); M2LexBuf_AddTok(M2Reserved_rcbratok); return; } |
| \(\: { updatepos(); M2LexBuf_AddTok(M2Reserved_lcbratok); return; } |
| \:\) { updatepos(); M2LexBuf_AddTok(M2Reserved_rcbratok); return; } |
| \' { updatepos(); M2LexBuf_AddTok(M2Reserved_singlequotetok); return; } |
| \= { updatepos(); M2LexBuf_AddTok(M2Reserved_equaltok); return; } |
| \# { updatepos(); M2LexBuf_AddTok(M2Reserved_hashtok); return; } |
| \< { updatepos(); M2LexBuf_AddTok(M2Reserved_lesstok); return; } |
| \> { updatepos(); M2LexBuf_AddTok(M2Reserved_greatertok); return; } |
| \<\> { updatepos(); M2LexBuf_AddTok(M2Reserved_lessgreatertok); return; } |
| \<\= { updatepos(); M2LexBuf_AddTok(M2Reserved_lessequaltok); return; } |
| \>\= { updatepos(); M2LexBuf_AddTok(M2Reserved_greaterequaltok); return; } |
| "<*" { updatepos(); M2LexBuf_AddTok(M2Reserved_ldirectivetok); return; } |
| "*>" { updatepos(); M2LexBuf_AddTok(M2Reserved_rdirectivetok); return; } |
| \.\. { updatepos(); M2LexBuf_AddTok(M2Reserved_periodperiodtok); return; } |
| \.\.\. { updatepos(); M2LexBuf_AddTok(M2Reserved_periodperiodperiodtok); return; } |
| \: { updatepos(); M2LexBuf_AddTok(M2Reserved_colontok); return; } |
| \" { updatepos(); M2LexBuf_AddTok(M2Reserved_doublequotestok); return; } |
| \| { updatepos(); M2LexBuf_AddTok(M2Reserved_bartok); return; } |
| \! { updatepos(); M2LexBuf_AddTok(M2Reserved_bartok); return; } |
| \~ { updatepos(); M2LexBuf_AddTok(M2Reserved_nottok); return; } |
| AND { updatepos(); M2LexBuf_AddTok(M2Reserved_andtok); return; } |
| ARRAY { updatepos(); M2LexBuf_AddTok(M2Reserved_arraytok); return; } |
| BEGIN { updatepos(); M2LexBuf_AddTok(M2Reserved_begintok); return; } |
| BY { updatepos(); M2LexBuf_AddTok(M2Reserved_bytok); return; } |
| CASE { updatepos(); M2LexBuf_AddTok(M2Reserved_casetok); return; } |
| CONST { updatepos(); M2LexBuf_AddTok(M2Reserved_consttok); return; } |
| DEFINITION { updatepos(); isDefinitionModule = TRUE; |
| M2LexBuf_AddTok(M2Reserved_definitiontok); return; } |
| DIV { updatepos(); M2LexBuf_AddTok(M2Reserved_divtok); return; } |
| DO { updatepos(); M2LexBuf_AddTok(M2Reserved_dotok); return; } |
| ELSE { updatepos(); M2LexBuf_AddTok(M2Reserved_elsetok); return; } |
| ELSIF { updatepos(); M2LexBuf_AddTok(M2Reserved_elsiftok); return; } |
| END { updatepos(); seenEnd=TRUE; |
| M2LexBuf_AddTok(M2Reserved_endtok); return; } |
| EXCEPT { updatepos(); M2LexBuf_AddTok(M2Reserved_excepttok); return; } |
| EXIT { updatepos(); M2LexBuf_AddTok(M2Reserved_exittok); return; } |
| EXPORT { updatepos(); M2LexBuf_AddTok(M2Reserved_exporttok); return; } |
| FINALLY { updatepos(); M2LexBuf_AddTok(M2Reserved_finallytok); return; } |
| FOR { updatepos(); M2LexBuf_AddTok(M2Reserved_fortok); return; } |
| FROM { updatepos(); M2LexBuf_AddTok(M2Reserved_fromtok); return; } |
| IF { updatepos(); M2LexBuf_AddTok(M2Reserved_iftok); return; } |
| IMPLEMENTATION { updatepos(); M2LexBuf_AddTok(M2Reserved_implementationtok); return; } |
| IMPORT { updatepos(); M2LexBuf_AddTok(M2Reserved_importtok); return; } |
| IN { updatepos(); M2LexBuf_AddTok(M2Reserved_intok); return; } |
| LOOP { updatepos(); M2LexBuf_AddTok(M2Reserved_looptok); return; } |
| MOD { updatepos(); M2LexBuf_AddTok(M2Reserved_modtok); return; } |
| MODULE { updatepos(); seenModuleStart=TRUE; |
| M2LexBuf_AddTok(M2Reserved_moduletok); return; } |
| NOT { updatepos(); M2LexBuf_AddTok(M2Reserved_nottok); return; } |
| OF { updatepos(); M2LexBuf_AddTok(M2Reserved_oftok); return; } |
| OR { updatepos(); M2LexBuf_AddTok(M2Reserved_ortok); return; } |
| PACKEDSET { updatepos(); M2LexBuf_AddTok(M2Reserved_packedsettok); return; } |
| POINTER { updatepos(); M2LexBuf_AddTok(M2Reserved_pointertok); return; } |
| PROCEDURE { updatepos(); seenFunctionStart=TRUE; |
| M2LexBuf_AddTok(M2Reserved_proceduretok); return; } |
| QUALIFIED { updatepos(); M2LexBuf_AddTok(M2Reserved_qualifiedtok); return; } |
| UNQUALIFIED { updatepos(); M2LexBuf_AddTok(M2Reserved_unqualifiedtok); return; } |
| RECORD { updatepos(); M2LexBuf_AddTok(M2Reserved_recordtok); return; } |
| REM { updatepos(); M2LexBuf_AddTok(M2Reserved_remtok); return; } |
| REPEAT { updatepos(); M2LexBuf_AddTok(M2Reserved_repeattok); return; } |
| RETRY { updatepos(); M2LexBuf_AddTok(M2Reserved_retrytok); return; } |
| RETURN { updatepos(); M2LexBuf_AddTok(M2Reserved_returntok); return; } |
| SET { updatepos(); M2LexBuf_AddTok(M2Reserved_settok); return; } |
| THEN { updatepos(); M2LexBuf_AddTok(M2Reserved_thentok); return; } |
| TO { updatepos(); M2LexBuf_AddTok(M2Reserved_totok); return; } |
| TYPE { updatepos(); M2LexBuf_AddTok(M2Reserved_typetok); return; } |
| UNTIL { updatepos(); M2LexBuf_AddTok(M2Reserved_untiltok); return; } |
| VAR { updatepos(); M2LexBuf_AddTok(M2Reserved_vartok); return; } |
| WHILE { updatepos(); M2LexBuf_AddTok(M2Reserved_whiletok); return; } |
| WITH { updatepos(); M2LexBuf_AddTok(M2Reserved_withtok); return; } |
| ASM { updatepos(); M2LexBuf_AddTok(M2Reserved_asmtok); return; } |
| VOLATILE { updatepos(); M2LexBuf_AddTok(M2Reserved_volatiletok); return; } |
| \_\_DATE\_\_ { updatepos(); handleDate(); return; } |
| \_\_LINE\_\_ { updatepos(); handleLine(); return; } |
| \_\_FILE\_\_ { updatepos(); handleFile(); return; } |
| \_\_FUNCTION\_\_ { updatepos(); handleFunction(); return; } |
| \_\_COLUMN\_\_ { updatepos(); handleColumn(); return; } |
| \_\_ATTRIBUTE\_\_ { updatepos(); M2LexBuf_AddTok(M2Reserved_attributetok); return; } |
| \_\_BUILTIN\_\_ { updatepos(); M2LexBuf_AddTok(M2Reserved_builtintok); return; } |
| \_\_INLINE\_\_ { updatepos(); M2LexBuf_AddTok(M2Reserved_inlinetok); return; } |
| |
| |
| (([0-9]*\.[0-9]+)(E[+-]?[0-9]+)?) { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_realtok, yytext); return; } |
| [0-9]*\.E[+-]?[0-9]+ { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_realtok, yytext); return; } |
| [a-zA-Z_][a-zA-Z0-9_]* { checkFunction(); updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_identtok, yytext); return; } |
| [0-9]+ { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; } |
| [0-9]+B { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; } |
| [0-9]+C { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; } |
| [0-9A-F]+H { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; } |
| [\t\r ]+ { currentLine->tokenpos += yyleng; /* Ignore space. */; } |
| . { updatepos(); m2flex_M2Error("unrecognised symbol"); skippos(); } |
| |
| %% |
| |
| /* have removed the -? from the beginning of the real/integer constant literal rules */ |
| |
| /* |
| * hand built routines |
| */ |
| |
| /* |
| * handleFile - handles the __FILE__ construct by wraping it in double quotes and putting |
| * it into the token buffer as a string. |
| */ |
| |
| static void handleFile (void) |
| { |
| char *s = (char *)alloca(strlen(filename)+2+1); |
| |
| strcpy(s, "\""); |
| strcat(s, filename); |
| strcat(s, "\""); |
| M2LexBuf_AddTokCharStar(M2Reserved_stringtok, s); |
| } |
| |
| /* |
| * handleLine - handles the __LINE__ construct by passing an integer to |
| * the token buffer. |
| */ |
| |
| static void handleLine (void) |
| { |
| M2LexBuf_AddTokInteger(M2Reserved_integertok, lineno); |
| } |
| |
| /* |
| * handleColumn - handles the __COLUMN__ construct by passing an integer to |
| * the token buffer. |
| */ |
| |
| static void handleColumn (void) |
| { |
| M2LexBuf_AddTokInteger(M2Reserved_integertok, m2flex_GetColumnNo()); |
| } |
| |
| /* |
| * handleDate - handles the __DATE__ construct by passing the date |
| * as a string to the token buffer. |
| */ |
| |
| static void handleDate (void) |
| { |
| time_t clock = time ((time_t *)0); |
| char *sdate = ctime (&clock); |
| char *s = (char *) alloca (strlen (sdate) + 2 + 1); |
| char *p = index (sdate, '\n'); |
| |
| if (p != NULL) { |
| *p = (char) 0; |
| } |
| strcpy(s, "\""); |
| strcat(s, sdate); |
| strcat(s, "\""); |
| M2LexBuf_AddTokCharStar (M2Reserved_stringtok, s); |
| } |
| |
| /* |
| * handleFunction - handles the __FUNCTION__ construct by wrapping |
| * it in double quotes and putting it into the token |
| * buffer as a string. |
| */ |
| |
| static void handleFunction (void) |
| { |
| if (currentFunction == NULL) |
| M2LexBuf_AddTokCharStar(M2Reserved_stringtok, const_cast<char *>("\"\"")); |
| else if (currentFunction->module) { |
| char *s = (char *) alloca(strlen(yytext) + |
| strlen("\"module initialization\"") + 1); |
| strcpy(s, "\"module "); |
| strcat(s, currentFunction->name); |
| strcat(s, " initialization\""); |
| M2LexBuf_AddTokCharStar(M2Reserved_stringtok, s); |
| } else { |
| char *function = currentFunction->name; |
| char *s = (char *)alloca(strlen(function)+2+1); |
| strcpy(s, "\""); |
| strcat(s, function); |
| strcat(s, "\""); |
| M2LexBuf_AddTokCharStar(M2Reserved_stringtok, s); |
| } |
| } |
| |
| /* |
| * pushFunction - pushes the function name onto the stack. |
| */ |
| |
| static void pushFunction (char *function, int module) |
| { |
| if (currentFunction == NULL) { |
| currentFunction = (struct functionInfo *)xmalloc (sizeof (struct functionInfo)); |
| currentFunction->name = xstrdup(function); |
| currentFunction->next = NULL; |
| currentFunction->module = module; |
| } else { |
| struct functionInfo *f = (struct functionInfo *)xmalloc (sizeof (struct functionInfo)); |
| f->name = xstrdup(function); |
| f->next = currentFunction; |
| f->module = module; |
| currentFunction = f; |
| } |
| } |
| |
| /* |
| * popFunction - pops the current function. |
| */ |
| |
| static void popFunction (void) |
| { |
| if (currentFunction != NULL && currentFunction->next != NULL) { |
| struct functionInfo *f = currentFunction; |
| |
| currentFunction = currentFunction->next; |
| if (f->name != NULL) |
| free(f->name); |
| free(f); |
| } |
| } |
| |
| /* |
| * endOfComment - handles the end of comment |
| */ |
| |
| static void endOfComment (void) |
| { |
| commentLevel--; |
| updatepos(); |
| skippos(); |
| if (commentLevel==0) { |
| BEGIN INITIAL; |
| finishedLine(); |
| } else |
| popLine(); |
| } |
| |
| /* |
| * endOfCComment - handles the end of C comment. |
| */ |
| |
| static void endOfCComment (void) |
| { |
| commentCLevel = 0; |
| updatepos(); |
| skippos(); |
| BEGIN INITIAL; |
| finishedLine(); |
| } |
| |
| /* |
| * m2flex_M2Error - displays the error message, s, after the code line and pointer |
| * to the erroneous token. |
| */ |
| |
| EXTERN void m2flex_M2Error (const char *s) |
| { |
| if (currentLine->linebuf != NULL) { |
| int i=1; |
| |
| printf("%s:%d:%s\n", filename, currentLine->lineno, currentLine->linebuf); |
| printf("%s:%d:%*s", filename, currentLine->lineno, 1+currentLine->tokenpos, "^"); |
| while (i<currentLine->toklen) { |
| putchar('^'); |
| i++; |
| } |
| putchar('\n'); |
| } |
| printf("%s:%d:%s\n", filename, currentLine->lineno, s); |
| } |
| |
| static void poperrorskip (const char *s) |
| { |
| int nextpos =currentLine->nextpos; |
| int tokenpos=currentLine->tokenpos; |
| |
| popLine(); |
| m2flex_M2Error(s); |
| if (currentLine != NULL) { |
| currentLine->nextpos = nextpos; |
| currentLine->tokenpos = tokenpos; |
| } |
| } |
| |
| /* |
| * consumeLine - reads a line into a buffer, it then pushes back the whole |
| * line except the initial \n. |
| */ |
| |
| static void consumeLine (void) |
| { |
| if (currentLine->linelen<yyleng) { |
| currentLine->linebuf = (char *)xrealloc (currentLine->linebuf, yyleng); |
| currentLine->linelen = yyleng; |
| } |
| strcpy(currentLine->linebuf, yytext+1); /* copy all except the initial \n */ |
| lineno++; |
| totalLines++; |
| currentLine->lineno = lineno; |
| currentLine->tokenpos=0; |
| currentLine->nextpos=0; |
| currentLine->column=0; |
| START_LINE (lineno, yyleng); |
| yyless(1); /* push back all but the \n */ |
| } |
| |
| static void assert_location (location_t location ATTRIBUTE_UNUSED) |
| { |
| #if 0 |
| if ((location != BUILTINS_LOCATION) && (location != UNKNOWN_LOCATION) && (! M2Options_GetCpp ())) { |
| expanded_location xl = expand_location (location); |
| if (xl.line != currentLine->lineno) { |
| m2flex_M2Error ("mismatched gcc location and front end token number"); |
| } |
| } |
| #endif |
| } |
| |
| /* |
| * splitSlashStar - called if we are not tokenizing source code after it |
| * has been preprocessed by cpp. It is only called |
| * if the current token was a / immediately followed by * and |
| * therefore it will be split into two m2 tokens: / and *. |
| */ |
| |
| static void splitSlashStar (void) |
| { |
| seenFunctionStart = FALSE; |
| seenEnd = FALSE; |
| seenModuleStart = FALSE; |
| currentLine->nextpos = currentLine->tokenpos+1; /* "/". */ |
| currentLine->toklen = 1; |
| currentLine->column = currentLine->tokenpos+1; |
| currentLine->location = |
| M2Options_OverrideLocation (GET_LOCATION (currentLine->column, |
| currentLine->column+currentLine->toklen-1)); |
| assert_location (GET_LOCATION (currentLine->column, |
| currentLine->column+currentLine->toklen-1)); |
| M2LexBuf_AddTok (M2Reserved_dividetok); |
| currentLine->nextpos = currentLine->tokenpos+1; /* "*". */ |
| currentLine->toklen = 1; |
| currentLine->column = currentLine->tokenpos+1; |
| currentLine->location = |
| M2Options_OverrideLocation (GET_LOCATION (currentLine->column, |
| currentLine->column+currentLine->toklen-1)); |
| assert_location (GET_LOCATION (currentLine->column, |
| currentLine->column+currentLine->toklen-1)); |
| M2LexBuf_AddTok (M2Reserved_timestok); |
| } |
| |
| |
| /* |
| * updatepos - updates the current token position. |
| * Should be used when a rule matches a token. |
| */ |
| |
| static void updatepos (void) |
| { |
| seenFunctionStart = FALSE; |
| seenEnd = FALSE; |
| seenModuleStart = FALSE; |
| currentLine->nextpos = currentLine->tokenpos+yyleng; |
| currentLine->toklen = yyleng; |
| /* if (currentLine->column == 0) */ |
| currentLine->column = currentLine->tokenpos+1; |
| currentLine->location = |
| M2Options_OverrideLocation (GET_LOCATION (currentLine->column, |
| currentLine->column+currentLine->toklen-1)); |
| assert_location (GET_LOCATION (currentLine->column, |
| currentLine->column+currentLine->toklen-1)); |
| } |
| |
| /* |
| * checkFunction - checks to see whether we have seen the start |
| * or end of a function. |
| */ |
| |
| static void checkFunction (void) |
| { |
| if (! isDefinitionModule) { |
| if (seenModuleStart) |
| pushFunction(yytext, 1); |
| if (seenFunctionStart) |
| pushFunction(yytext, 0); |
| if (seenEnd && currentFunction != NULL && |
| (strcmp(currentFunction->name, yytext) == 0)) |
| popFunction(); |
| } |
| seenFunctionStart = FALSE; |
| seenEnd = FALSE; |
| seenModuleStart = FALSE; |
| } |
| |
| /* |
| * skippos - skips over this token. This function should be called |
| * if we are not returning and thus not calling getToken. |
| */ |
| |
| static void skippos (void) |
| { |
| currentLine->tokenpos = currentLine->nextpos; |
| } |
| |
| /* |
| * initLine - initializes a currentLine |
| */ |
| |
| static void initLine (void) |
| { |
| currentLine = (struct lineInfo *)xmalloc (sizeof(struct lineInfo)); |
| |
| if (currentLine == NULL) |
| perror("xmalloc"); |
| currentLine->linebuf = NULL; |
| currentLine->linelen = 0; |
| currentLine->tokenpos = 0; |
| currentLine->toklen = 0; |
| currentLine->nextpos = 0; |
| currentLine->lineno = lineno; |
| currentLine->column = 0; |
| currentLine->inuse = TRUE; |
| currentLine->next = NULL; |
| } |
| |
| /* |
| * pushLine - pushes a new line structure. |
| */ |
| |
| static void pushLine (void) |
| { |
| if (currentLine == NULL) |
| initLine(); |
| else if (currentLine->inuse) { |
| struct lineInfo *l = (struct lineInfo *)xmalloc (sizeof(struct lineInfo)); |
| |
| if (currentLine->linebuf == NULL) { |
| l->linebuf = NULL; |
| l->linelen = 0; |
| } else { |
| l->linebuf = (char *)xstrdup (currentLine->linebuf); |
| l->linelen = strlen (l->linebuf)+1; |
| } |
| l->tokenpos = currentLine->tokenpos; |
| l->toklen = currentLine->toklen; |
| l->nextpos = currentLine->nextpos; |
| l->lineno = currentLine->lineno; |
| l->column = currentLine->column; |
| l->next = currentLine; |
| currentLine = l; |
| } |
| currentLine->inuse = TRUE; |
| } |
| |
| /* |
| * popLine - pops a line structure. |
| */ |
| |
| static void popLine (void) |
| { |
| if (currentLine != NULL) { |
| struct lineInfo *l = currentLine; |
| |
| if (currentLine->linebuf != NULL) |
| free(currentLine->linebuf); |
| currentLine = l->next; |
| free(l); |
| } |
| } |
| |
| /* |
| * resetpos - resets the position of the next token to the start of the line. |
| */ |
| |
| static void resetpos (void) |
| { |
| if (currentLine != NULL) |
| currentLine->nextpos = 0; |
| } |
| |
| /* |
| * finishedLine - indicates that the current line does not need to be preserved when a pushLine |
| * occurs. |
| */ |
| |
| static void finishedLine (void) |
| { |
| currentLine->inuse = FALSE; |
| } |
| |
| /* |
| * m2flex_GetToken - returns a new token. |
| */ |
| |
| EXTERN char *m2flex_GetToken (void) |
| { |
| TIMEVAR_PUSH_LEX; |
| if (currentLine == NULL) |
| initLine(); |
| currentLine->tokenpos = currentLine->nextpos; |
| yylex(); |
| TIMEVAR_POP_LEX; |
| return yytext; |
| } |
| |
| /* |
| * CloseSource - provided for semantic sugar |
| */ |
| |
| EXTERN void m2flex_CloseSource (void) |
| { |
| END_FILE (); |
| } |
| |
| /* |
| * OpenSource - returns TRUE if file s can be opened and |
| * all tokens are taken from this file. |
| */ |
| |
| EXTERN int m2flex_OpenSource (char *s) |
| { |
| FILE *f = fopen(s, "r"); |
| |
| if (f == NULL) |
| return( FALSE ); |
| else { |
| isDefinitionModule = FALSE; |
| while (currentFunction != NULL) |
| { |
| struct functionInfo *f = currentFunction; |
| currentFunction = f->next; |
| if (f->name != NULL) |
| free(f->name); |
| free(f); |
| } |
| yy_delete_buffer (YY_CURRENT_BUFFER); |
| yy_switch_to_buffer (yy_create_buffer(f, YY_BUF_SIZE)); |
| filename = xstrdup (s); |
| lineno = 1; |
| if (currentLine == NULL) |
| pushLine (); |
| else |
| currentLine->lineno = lineno; |
| START_FILE (filename, lineno); |
| BEGIN INITIAL; resetpos (); |
| return TRUE; |
| } |
| } |
| |
| /* |
| * m2flex_GetLineNo - returns the current line number. |
| */ |
| |
| EXTERN int m2flex_GetLineNo (void) |
| { |
| if (currentLine != NULL) |
| return currentLine->lineno; |
| else |
| return 0; |
| } |
| |
| /* |
| * m2flex_GetColumnNo - returns the column where the current |
| * token starts. |
| */ |
| |
| EXTERN int m2flex_GetColumnNo (void) |
| { |
| if (currentLine != NULL) |
| return currentLine->column; |
| else |
| return 0; |
| } |
| |
| /* |
| * m2flex_GetLocation - returns the gcc location_t of the current token. |
| */ |
| |
| EXTERN location_t m2flex_GetLocation (void) |
| { |
| if (currentLine != NULL) |
| return currentLine->location; |
| else |
| return 0; |
| } |
| |
| /* |
| * GetTotalLines - returns the total number of lines parsed. |
| */ |
| |
| EXTERN int m2flex_GetTotalLines (void) |
| { |
| return totalLines; |
| } |
| |
| /* |
| * yywrap is called when end of file is seen. We push an eof token |
| * and tell the lexical analysis to stop. |
| */ |
| |
| int yywrap (void) |
| { |
| updatepos(); M2LexBuf_AddTok(M2Reserved_eoftok); return 1; |
| } |
| |
| EXTERN void _M2_m2flex_init (void) {} |
| EXTERN void _M2_m2flex_fini (void) {} |