[testsuite] [i386] work around fails with --enable-frame-pointer
[official-gcc.git] / gcc / m2 / m2.flex
blob2483b282d4861c414ef554a71f8b8b5034baf749
1 %{
2 /* m2.flex implements lexical analysis for Modula-2.
4 Copyright (C) 2004-2024 Free Software Foundation, Inc.
5 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
7 This file is part of GNU Modula-2.
9 GNU Modula-2 is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
14 GNU Modula-2 is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Modula-2; see the file COPYING3.  If not see
21 <http://www.gnu.org/licenses/>.  */
23 #include "gm2-gcc/gcc-consolidation.h"
25 #include "GM2Reserved.h"
26 #include "GM2LexBuf.h"
27 #include "input.h"
28 #include "m2options.h"
30 static int cpreprocessor = 0;  /* Replace this with correct getter.  */
32 #if defined(GM2USEGGC)
33 #  include "ggc.h"
34 #endif
36 #include "timevar.h"
38 #define START_FILE(F,L)   m2linemap_StartFile(F,L)
39 #define END_FILE()        m2linemap_EndFile()
40 #define START_LINE(N,S)   m2linemap_StartLine(N,S)
41 #define GET_LOCATION(COLUMN_START,COLUMN_END) \
42         m2linemap_GetLocationRange(COLUMN_START,COLUMN_END)
43 #define TIMEVAR_PUSH_LEX  timevar_push (TV_LEX)
44 #define TIMEVAR_POP_LEX   timevar_pop (TV_LEX)
46 #ifdef __cplusplus
47 #define EXTERN extern "C"
48 #endif
50   /* m2.flex provides a lexical analyser for GNU Modula-2.  */
52   struct lineInfo {
53     char            *linebuf;          /* line contents */
54     int              linelen;          /* length */
55     int              tokenpos;         /* start position of token within line */
56     int              toklen;           /* a copy of yylen (length of token) */
57     int              nextpos;          /* position after token */
58     int              lineno;           /* line number of this line */
59     int              column;           /* first column number of token on this line */
60     bool             inuse;            /* do we need to keep this line info? */
61     location_t       location;         /* the corresponding gcc location_t */
62     struct lineInfo *next;
63   };
65   struct functionInfo {
66     char                *name;         /* function name */
67     bool                 module;       /* is it really a module? */
68     struct functionInfo *next;         /* list of nested functions */
69   };
71   static int                  lineno      =1;   /* a running count of the file line number */
72   static char                *filename    =NULL;
73   static int                  commentLevel=0;
74   static int                  commentCLevel=0;
75   static struct lineInfo     *currentLine=NULL;
76   static struct functionInfo *currentFunction=NULL;
77   static bool                 seenFunctionStart=false;
78   static bool                 seenEnd=false;
79   static bool                 seenModuleStart=false;
80   static bool                 isDefinitionModule=false;
81   static int                  totalLines=0;
83 static  void pushLine                 (void);
84 static  void popLine                  (void);
85 static  void finishedLine             (void);
86 static  void resetpos                 (void);
87 static  void consumeLine              (void);
88 static  void updatepos                (void);
89 static  void skippos                  (void);
90 static  void poperrorskip             (const char *);
91 static  void endOfComment             (void);
92 static  void endOfCComment            (void);
93 static  void splitSlashStar           (void);
94 static  void handleDate               (void);
95 static  void handleLine               (void);
96 static  void handleFile               (void);
97 static  void handleFunction           (void);
98 static  void handleColumn             (void);
99 static  void pushFunction             (char *function, bool module);
100 static  void popFunction              (void);
101 static  void checkFunction            (void);
102 EXTERN  void m2flex_M2Error           (const char *);
103 EXTERN  location_t m2flex_GetLocation (void);
104 EXTERN  int  m2flex_GetColumnNo       (void);
105 EXTERN  bool m2flex_OpenSource        (char *s);
106 EXTERN  int  m2flex_GetLineNo         (void);
107 EXTERN  void m2flex_CloseSource       (void);
108 EXTERN  char *m2flex_GetToken         (void);
109 EXTERN  void _M2_m2flex_init          (void);
110 EXTERN  int  m2flex_GetTotalLines     (void);
111 extern  void  yylex                   (void);
113 #define YY_DECL void yylex (void)
116 %option nounput
117 %x COMMENT COMMENT1 COMMENTC LINE0 LINE1 LINE2
121 "(*"                       { updatepos();
122                              commentLevel=1; pushLine(); skippos();
123                              BEGIN COMMENT; }
124 <COMMENT>"*)"              { endOfComment(); }
125 <COMMENT>"(*"              { commentLevel++; pushLine(); updatepos(); skippos(); }
126 <COMMENT>"<*"              { if (commentLevel == 1) {
127                                updatepos();
128                                pushLine();
129                                skippos();
130                                BEGIN COMMENT1;
131                              } else {
132                                updatepos(); skippos();
133                              }
134                            }
135 <COMMENT>\n.*              { consumeLine(); }
136 <COMMENT>.                 { updatepos(); skippos(); }
137 <COMMENT1>.                { updatepos(); skippos(); }
138 <COMMENT1>"*>"             { updatepos(); skippos(); finishedLine(); BEGIN COMMENT; }
139 <COMMENT1>\n.*             { consumeLine(); }
140 <COMMENT1>"*)"             { poperrorskip("unterminated source code directive, missing *>");
141                              endOfComment(); }
142 <COMMENT1><<EOF>>          { poperrorskip("unterminated source code directive, missing *>"); BEGIN COMMENT; }
143 <COMMENT><<EOF>>           { poperrorskip("unterminated comment found at the end of the file, missing *)"); BEGIN INITIAL; }
145 "/*"                       { /* Possibly handle C preprocessor comment.  */
146                              if (cpreprocessor)
147                                {
148                                  updatepos ();
149                                  commentCLevel++;
150                                  if (commentCLevel == 1)
151                                    {
152                                      pushLine ();
153                                      skippos ();
154                                    }
155                                  BEGIN COMMENTC;
156                                }
157                              else
158                                splitSlashStar ();
159                            }
160 <COMMENTC>.                { updatepos(); skippos(); }
161 <COMMENTC>\n.*             { consumeLine(); }
162 <COMMENTC>"*/"             { endOfCComment(); }
163 ^\#.*                      { consumeLine(); /* printf("found: %s\n", currentLine->linebuf); */
164                              if (M2Options_GetLineDirectives ())
165                                 BEGIN LINE0;
166                            }
167 \n\#.*                     { consumeLine(); /* printf("found: %s\n", currentLine->linebuf); */
168                              if (M2Options_GetLineDirectives ())
169                                 BEGIN LINE0;
170                            }
171 <LINE0>\#[ \t]*            { updatepos(); }
172 <LINE0>[0-9]+[ \t]*\"      { updatepos(); lineno=atoi(yytext); BEGIN LINE1; }
173 <LINE0>\n                  { m2flex_M2Error("missing initial quote after #line directive"); resetpos(); BEGIN INITIAL; }
174 <LINE0>[^\n]
175 <LINE1>[^\"\n]+            { m2flex_M2Error("missing final quote after #line directive"); resetpos(); BEGIN INITIAL; }
176 <LINE1>.*\"                { updatepos();
177                              filename = (char *)xrealloc(filename, yyleng+1);
178                              strcpy(filename, yytext);
179                              filename[yyleng-1] = (char)0;  /* remove trailing quote */
180                              START_FILE (filename, lineno);
181                              BEGIN LINE2;
182                            }
183 <LINE2>[ \t]*              { updatepos(); }
184 <LINE2>\n                  { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; }
185 <LINE2>2[ \t]*\n           { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; }
186 <LINE2>1[ \t]*\n           { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; }
187 <LINE2>1[ \t]*.*\n         { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; }
188 <LINE2>2[ \t]*.*\n         { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; }
189 <LINE2>3[ \t]*.*\n         { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; }
191 \n[^\#].*                  { consumeLine(); /* printf("found: %s\n", currentLine->linebuf); */ }
192 \n                         { consumeLine(); /* printf("found: %s\n", currentLine->linebuf); */ }
194 \"[^\"\n]*\"               { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_stringtok, yytext); return; }
195 \"[^\"\n]*$                { updatepos();
196                              m2flex_M2Error("missing terminating quote, \"");
197                              M2LexBuf_AddTokCharStar(M2Reserved_stringtok, yytext);
198                              resetpos(); return;
199                            }
201 '[^'\n]*'                  { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_stringtok, yytext); return; }
202 '[^'\n]*$                  { updatepos();
203                              m2flex_M2Error("missing terminating quote, '");
204                              M2LexBuf_AddTokCharStar(M2Reserved_stringtok, yytext);
205                              resetpos(); return;
206                            }
208 <<EOF>>                    { updatepos(); M2LexBuf_AddTok(M2Reserved_eoftok); return; }
209 \+                         { updatepos(); M2LexBuf_AddTok(M2Reserved_plustok); return; }
210 -                          { updatepos(); M2LexBuf_AddTok(M2Reserved_minustok); return; }
211 "*"                        { updatepos(); M2LexBuf_AddTok(M2Reserved_timestok); return; }
212 \/                         { updatepos(); M2LexBuf_AddTok(M2Reserved_dividetok); return; }
213 :=                         { updatepos(); M2LexBuf_AddTok(M2Reserved_becomestok); return; }
214 \&                         { updatepos(); M2LexBuf_AddTok(M2Reserved_ambersandtok); return; }
215 \.                         { updatepos(); M2LexBuf_AddTok(M2Reserved_periodtok); return; }
216 \,                         { updatepos(); M2LexBuf_AddTok(M2Reserved_commatok); return; }
217 \;                         { updatepos(); M2LexBuf_AddTok(M2Reserved_semicolontok); return; }
218 \(                         { updatepos(); M2LexBuf_AddTok(M2Reserved_lparatok); return; }
219 \)                         { updatepos(); M2LexBuf_AddTok(M2Reserved_rparatok); return; }
220 \[                         { updatepos(); M2LexBuf_AddTok(M2Reserved_lsbratok); return; }
221 \]                         { updatepos(); M2LexBuf_AddTok(M2Reserved_rsbratok); return; }
222 \(\!                       { updatepos(); M2LexBuf_AddTok(M2Reserved_lsbratok); return; }
223 \!\)                       { updatepos(); M2LexBuf_AddTok(M2Reserved_rsbratok); return; }
224 \^                         { updatepos(); M2LexBuf_AddTok(M2Reserved_uparrowtok); return; }
225 \@                         { updatepos(); M2LexBuf_AddTok(M2Reserved_uparrowtok); return; }
226 \{                         { updatepos(); M2LexBuf_AddTok(M2Reserved_lcbratok); return; }
227 \}                         { updatepos(); M2LexBuf_AddTok(M2Reserved_rcbratok); return; }
228 \(\:                       { updatepos(); M2LexBuf_AddTok(M2Reserved_lcbratok); return; }
229 \:\)                       { updatepos(); M2LexBuf_AddTok(M2Reserved_rcbratok); return; }
230 \'                         { updatepos(); M2LexBuf_AddTok(M2Reserved_singlequotetok); return; }
231 \=                         { updatepos(); M2LexBuf_AddTok(M2Reserved_equaltok); return; }
232 \#                         { updatepos(); M2LexBuf_AddTok(M2Reserved_hashtok); return; }
233 \<                         { updatepos(); M2LexBuf_AddTok(M2Reserved_lesstok); return; }
234 \>                         { updatepos(); M2LexBuf_AddTok(M2Reserved_greatertok); return; }
235 \<\>                       { updatepos(); M2LexBuf_AddTok(M2Reserved_lessgreatertok); return; }
236 \<\=                       { updatepos(); M2LexBuf_AddTok(M2Reserved_lessequaltok); return; }
237 \>\=                       { updatepos(); M2LexBuf_AddTok(M2Reserved_greaterequaltok); return; }
238 "<*"                       { updatepos(); M2LexBuf_AddTok(M2Reserved_ldirectivetok); return; }
239 "*>"                       { updatepos(); M2LexBuf_AddTok(M2Reserved_rdirectivetok); return; }
240 \.\.                       { updatepos(); M2LexBuf_AddTok(M2Reserved_periodperiodtok); return; }
241 \.\.\.                     { updatepos(); M2LexBuf_AddTok(M2Reserved_periodperiodperiodtok); return; }
242 \:                         { updatepos(); M2LexBuf_AddTok(M2Reserved_colontok); return; }
243 \"                         { updatepos(); M2LexBuf_AddTok(M2Reserved_doublequotestok); return; }
244 \|                         { updatepos(); M2LexBuf_AddTok(M2Reserved_bartok); return; }
245 \!                         { updatepos(); M2LexBuf_AddTok(M2Reserved_bartok); return; }
246 \~                         { updatepos(); M2LexBuf_AddTok(M2Reserved_nottok); return; }
247 AND                        { updatepos(); M2LexBuf_AddTok(M2Reserved_andtok); return; }
248 ARRAY                      { updatepos(); M2LexBuf_AddTok(M2Reserved_arraytok); return; }
249 BEGIN                      { updatepos(); M2LexBuf_AddTok(M2Reserved_begintok); return; }
250 BY                         { updatepos(); M2LexBuf_AddTok(M2Reserved_bytok); return; }
251 CASE                       { updatepos(); M2LexBuf_AddTok(M2Reserved_casetok); return; }
252 CONST                      { updatepos(); M2LexBuf_AddTok(M2Reserved_consttok); return; }
253 DEFINITION                 { updatepos(); isDefinitionModule = true;
254                              M2LexBuf_AddTok(M2Reserved_definitiontok); return; }
255 DIV                        { updatepos(); M2LexBuf_AddTok(M2Reserved_divtok); return; }
256 DO                         { updatepos(); M2LexBuf_AddTok(M2Reserved_dotok); return; }
257 ELSE                       { updatepos(); M2LexBuf_AddTok(M2Reserved_elsetok); return; }
258 ELSIF                      { updatepos(); M2LexBuf_AddTok(M2Reserved_elsiftok); return; }
259 END                        { updatepos(); seenEnd=true;
260                              M2LexBuf_AddTok(M2Reserved_endtok); return; }
261 EXCEPT                     { updatepos(); M2LexBuf_AddTok(M2Reserved_excepttok); return; }
262 EXIT                       { updatepos(); M2LexBuf_AddTok(M2Reserved_exittok); return; }
263 EXPORT                     { updatepos(); M2LexBuf_AddTok(M2Reserved_exporttok); return; }
264 FINALLY                    { updatepos(); M2LexBuf_AddTok(M2Reserved_finallytok); return; }
265 FOR                        { updatepos(); M2LexBuf_AddTok(M2Reserved_fortok); return; }
266 FROM                       { updatepos(); M2LexBuf_AddTok(M2Reserved_fromtok); return; }
267 IF                         { updatepos(); M2LexBuf_AddTok(M2Reserved_iftok); return; }
268 IMPLEMENTATION             { updatepos(); M2LexBuf_AddTok(M2Reserved_implementationtok); return; }
269 IMPORT                     { updatepos(); M2LexBuf_AddTok(M2Reserved_importtok); return; }
270 IN                         { updatepos(); M2LexBuf_AddTok(M2Reserved_intok); return; }
271 LOOP                       { updatepos(); M2LexBuf_AddTok(M2Reserved_looptok); return; }
272 MOD                        { updatepos(); M2LexBuf_AddTok(M2Reserved_modtok); return; }
273 MODULE                     { updatepos(); seenModuleStart=true;
274                              M2LexBuf_AddTok(M2Reserved_moduletok); return; }
275 NOT                        { updatepos(); M2LexBuf_AddTok(M2Reserved_nottok); return; }
276 OF                         { updatepos(); M2LexBuf_AddTok(M2Reserved_oftok); return; }
277 OR                         { updatepos(); M2LexBuf_AddTok(M2Reserved_ortok); return; }
278 PACKEDSET                  { updatepos(); M2LexBuf_AddTok(M2Reserved_packedsettok); return; }
279 POINTER                    { updatepos(); M2LexBuf_AddTok(M2Reserved_pointertok); return; }
280 PROCEDURE                  { updatepos(); seenFunctionStart=true;
281                              M2LexBuf_AddTok(M2Reserved_proceduretok); return; }
282 QUALIFIED                  { updatepos(); M2LexBuf_AddTok(M2Reserved_qualifiedtok); return; }
283 UNQUALIFIED                { updatepos(); M2LexBuf_AddTok(M2Reserved_unqualifiedtok); return; }
284 RECORD                     { updatepos(); M2LexBuf_AddTok(M2Reserved_recordtok); return; }
285 REM                        { updatepos(); M2LexBuf_AddTok(M2Reserved_remtok); return; }
286 REPEAT                     { updatepos(); M2LexBuf_AddTok(M2Reserved_repeattok); return; }
287 RETRY                      { updatepos(); M2LexBuf_AddTok(M2Reserved_retrytok); return; }
288 RETURN                     { updatepos(); M2LexBuf_AddTok(M2Reserved_returntok); return; }
289 SET                        { updatepos(); M2LexBuf_AddTok(M2Reserved_settok); return; }
290 THEN                       { updatepos(); M2LexBuf_AddTok(M2Reserved_thentok); return; }
291 TO                         { updatepos(); M2LexBuf_AddTok(M2Reserved_totok); return; }
292 TYPE                       { updatepos(); M2LexBuf_AddTok(M2Reserved_typetok); return; }
293 UNTIL                      { updatepos(); M2LexBuf_AddTok(M2Reserved_untiltok); return; }
294 VAR                        { updatepos(); M2LexBuf_AddTok(M2Reserved_vartok); return; }
295 WHILE                      { updatepos(); M2LexBuf_AddTok(M2Reserved_whiletok); return; }
296 WITH                       { updatepos(); M2LexBuf_AddTok(M2Reserved_withtok); return; }
297 ASM                        { updatepos(); M2LexBuf_AddTok(M2Reserved_asmtok); return; }
298 VOLATILE                   { updatepos(); M2LexBuf_AddTok(M2Reserved_volatiletok); return; }
299 \_\_DATE\_\_               { updatepos(); handleDate(); return; }
300 \_\_LINE\_\_               { updatepos(); handleLine(); return; }
301 \_\_FILE\_\_               { updatepos(); handleFile(); return; }
302 \_\_FUNCTION\_\_           { updatepos(); handleFunction(); return; }
303 \_\_COLUMN\_\_             { updatepos(); handleColumn(); return; }
304 \_\_ATTRIBUTE\_\_          { updatepos(); M2LexBuf_AddTok(M2Reserved_attributetok); return; }
305 \_\_BUILTIN\_\_            { updatepos(); M2LexBuf_AddTok(M2Reserved_builtintok); return; }
306 \_\_INLINE\_\_             { updatepos(); M2LexBuf_AddTok(M2Reserved_inlinetok); return; }
309 (([0-9]*\.[0-9]+)(E[+-]?[0-9]+)?) { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_realtok, yytext); return; }
310 [0-9]*\.E[+-]?[0-9]+       { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_realtok, yytext); return; }
311 [a-zA-Z_][a-zA-Z0-9_]*     { checkFunction(); updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_identtok, yytext); return; }
312 [0-9]+                     { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
313 [0-1]+A                    { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
314 [0-9]+B                    { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
315 [0-9]+C                    { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
316 [0-9A-F]+H                 { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
317 [\t\r ]+                   { currentLine->tokenpos += yyleng;  /* Ignore space.  */; }
318 .                          { updatepos(); m2flex_M2Error("unrecognised symbol"); skippos(); }
322 /* have removed the -? from the beginning of the real/integer constant literal rules */
325  *  hand built routines
326  */
329  *  handleFile - handles the __FILE__ construct by wraping it in double quotes and putting
330  *               it into the token buffer as a string.
331  */
333 static void handleFile (void)
335   char *s = (char *)alloca(strlen(filename)+2+1);
337   strcpy(s, "\"");
338   strcat(s, filename);
339   strcat(s, "\"");
340   M2LexBuf_AddTokCharStar(M2Reserved_stringtok, s);
344  *  handleLine - handles the __LINE__ construct by passing an integer to
345  *               the token buffer.
346  */
348 static void handleLine (void)
350   M2LexBuf_AddTokInteger(M2Reserved_integertok, lineno);
354  *  handleColumn - handles the __COLUMN__ construct by passing an integer to
355  *                 the token buffer.
356  */
358 static void handleColumn (void)
360   M2LexBuf_AddTokInteger(M2Reserved_integertok, m2flex_GetColumnNo());
364  *  handleDate - handles the __DATE__ construct by passing the date
365  *               as a string to the token buffer.
366  */
368 static void handleDate (void)
370   time_t  clock = time ((time_t *)0);
371   char   *sdate = ctime (&clock);
372   char   *s     = (char *) alloca (strlen (sdate) + 2 + 1);
373   char   *p     = index (sdate, '\n');
375   if (p != NULL) {
376     *p = (char) 0;
377   }
378   strcpy(s, "\"");
379   strcat(s, sdate);
380   strcat(s, "\"");
381   M2LexBuf_AddTokCharStar (M2Reserved_stringtok, s);
385  *  handleFunction - handles the __FUNCTION__ construct by wrapping
386  *                   it in double quotes and putting it into the token
387  *                   buffer as a string.
388  */
390 static void handleFunction (void)
392   if (currentFunction == NULL)
393     M2LexBuf_AddTokCharStar(M2Reserved_stringtok, const_cast<char *>("\"\""));
394   else if (currentFunction->module) {
395     char *s = (char *) alloca(strlen(yytext) +
396                               strlen("\"module  initialization\"") + 1);
397     strcpy(s, "\"module ");
398     strcat(s, currentFunction->name);
399     strcat(s, " initialization\"");
400     M2LexBuf_AddTokCharStar(M2Reserved_stringtok, s);
401   } else {
402     char *function = currentFunction->name;
403     char *s = (char *)alloca(strlen(function)+2+1);
404     strcpy(s, "\"");
405     strcat(s, function);
406     strcat(s, "\"");
407     M2LexBuf_AddTokCharStar(M2Reserved_stringtok, s);
408   }
412  *  pushFunction - pushes the function name onto the stack.
413  */
415 static void pushFunction (char *function, bool module)
417   if (currentFunction == NULL) {
418     currentFunction = (struct functionInfo *)xmalloc (sizeof (struct functionInfo));
419     currentFunction->name = xstrdup(function);
420     currentFunction->next = NULL;
421     currentFunction->module = module;
422   } else {
423     struct functionInfo *f = (struct functionInfo *)xmalloc (sizeof (struct functionInfo));
424     f->name = xstrdup(function);
425     f->next = currentFunction;
426     f->module = module;
427     currentFunction = f;
428   }
432  *  popFunction - pops the current function.
433  */
435 static void popFunction (void)
437   if (currentFunction != NULL && currentFunction->next != NULL) {
438     struct functionInfo *f = currentFunction;
440     currentFunction = currentFunction->next;
441     if (f->name != NULL)
442       free(f->name);
443     free(f);
444   }
448  *  endOfComment - handles the end of comment
449  */
451 static void endOfComment (void)
453   commentLevel--;
454   updatepos();
455   skippos();
456   if (commentLevel==0) {
457     BEGIN INITIAL;
458     finishedLine();
459   } else
460     popLine();
464  *  endOfCComment - handles the end of C comment.
465  */
467 static void endOfCComment (void)
469   commentCLevel = 0;
470   updatepos();
471   skippos();
472   BEGIN INITIAL;
473   finishedLine();
477  *  m2flex_M2Error - displays the error message, s, after the code line and pointer
478  *                   to the erroneous token.
479  */
481 EXTERN void m2flex_M2Error (const char *s)
483   if (currentLine->linebuf != NULL) {
484     int i=1;
486     printf("%s:%d:%s\n", filename, currentLine->lineno, currentLine->linebuf);
487     printf("%s:%d:%*s", filename, currentLine->lineno, 1+currentLine->tokenpos, "^");
488     while (i<currentLine->toklen) {
489       putchar('^');
490       i++;
491     }
492     putchar('\n');
493   }
494   if (s == NULL)
495     printf("%s:%d\n", filename, currentLine->lineno);
496   else
497     printf("%s:%d:%s\n", filename, currentLine->lineno, s);
500 static void poperrorskip (const char *s)
502   int nextpos =currentLine->nextpos;
503   int tokenpos=currentLine->tokenpos;
505   popLine();
506   m2flex_M2Error(s);
507   if (currentLine != NULL) {
508     currentLine->nextpos  = nextpos;
509     currentLine->tokenpos = tokenpos;
510   }
513 /* skipnewline skips all '\n' at the start of the line and returns
514    the new position.  */
516 static
517 char *
518 skipnewline (char *line)
520   while (((*line) != (char)0) && ((*line) == '\n'))
521     line++;
522   return line;
525 /* traceLine display the source line providing -fdebug-trace-line was
526    enabled.  */
528 static
529 void
530 traceLine (void)
532   if (M2Options_GetDebugTraceLine ())
533     {
534       char *line = skipnewline (currentLine->linebuf);
535       if (filename == NULL)
536         printf("<stdin>:%d:%s\n", currentLine->lineno, line);
537       else
538         printf("%s:%d:%s\n", filename, currentLine->lineno, line);
539     }
543  *  consumeLine - reads a line into a buffer, it then pushes back the whole
544  *                line except the initial \n.
545  */
547 static void consumeLine (void)
549   if (currentLine->linelen<yyleng) {
550     currentLine->linebuf = (char *)xrealloc (currentLine->linebuf, yyleng);
551     currentLine->linelen = yyleng;
552   }
553   strcpy(currentLine->linebuf, yytext+1);  /* copy all except the initial \n */
554   lineno++;
555   totalLines++;
556   currentLine->lineno = lineno;
557   currentLine->tokenpos=0;
558   currentLine->nextpos=0;
559   currentLine->column=0;
560   START_LINE (lineno, yyleng);
561   yyless(1);                  /* push back all but the \n */
562   traceLine ();
565 static void assert_location (location_t location ATTRIBUTE_UNUSED)
567 #if 0
568   if ((location != BUILTINS_LOCATION) && (location != UNKNOWN_LOCATION) && (! M2Options_GetCpp ())) {
569      expanded_location xl = expand_location (location);
570      if (xl.line != currentLine->lineno) {
571        m2flex_M2Error ("mismatched gcc location and front end token number");
572      }
573   }
574 #endif
578  *  splitSlashStar - called if we are not tokenizing source code after it
579  *                   has been preprocessed by cpp.  It is only called
580  *                   if the current token was a / immediately followed by * and
581  *                   therefore it will be split into two m2 tokens:  / and *.
582  */
584 static void splitSlashStar (void)
586   seenFunctionStart    = false;
587   seenEnd              = false;
588   seenModuleStart      = false;
589   currentLine->nextpos = currentLine->tokenpos+1;  /* "/".  */
590   currentLine->toklen  = 1;
591   currentLine->column = currentLine->tokenpos+1;
592   currentLine->location =
593     M2Options_OverrideLocation (GET_LOCATION (currentLine->column,
594                                               currentLine->column+currentLine->toklen-1));
595   assert_location (GET_LOCATION (currentLine->column,
596                                  currentLine->column+currentLine->toklen-1));
597   M2LexBuf_AddTok (M2Reserved_dividetok);
598   currentLine->nextpos = currentLine->tokenpos+1;  /* "*".  */
599   currentLine->toklen  = 1;
600   currentLine->column = currentLine->tokenpos+1;
601   currentLine->location =
602     M2Options_OverrideLocation (GET_LOCATION (currentLine->column,
603                                               currentLine->column+currentLine->toklen-1));
604   assert_location (GET_LOCATION (currentLine->column,
605                                  currentLine->column+currentLine->toklen-1));
606   M2LexBuf_AddTok (M2Reserved_timestok);
611  *  updatepos - updates the current token position.
612  *              Should be used when a rule matches a token.
613  */
615 static void updatepos (void)
617   seenFunctionStart    = false;
618   seenEnd              = false;
619   seenModuleStart      = false;
620   currentLine->nextpos = currentLine->tokenpos+yyleng;
621   currentLine->toklen  = yyleng;
622   /* if (currentLine->column == 0) */
623   currentLine->column = currentLine->tokenpos+1;
624   currentLine->location =
625     M2Options_OverrideLocation (GET_LOCATION (currentLine->column,
626                                               currentLine->column+currentLine->toklen-1));
627   assert_location (GET_LOCATION (currentLine->column,
628                                  currentLine->column+currentLine->toklen-1));
632  *  checkFunction - checks to see whether we have seen the start
633  *                  or end of a function.
634  */
636 static void checkFunction (void)
638   if (! isDefinitionModule) {
639     if (seenModuleStart)
640       pushFunction(yytext, 1);
641     if (seenFunctionStart)
642       pushFunction(yytext, 0);
643     if (seenEnd && currentFunction != NULL &&
644         (strcmp(currentFunction->name, yytext) == 0))
645       popFunction();
646   }
647   seenFunctionStart = false;
648   seenEnd           = false;
649   seenModuleStart   = false;
653  *  skippos - skips over this token. This function should be called
654  *            if we are not returning and thus not calling getToken.
655  */
657 static void skippos (void)
659   currentLine->tokenpos = currentLine->nextpos;
663  *  initLine - initializes a currentLine
664  */
666 static void initLine (void)
668   currentLine = (struct lineInfo *)xmalloc (sizeof(struct lineInfo));
670   if (currentLine == NULL)
671     perror("xmalloc");
672   currentLine->linebuf    = NULL;
673   currentLine->linelen    = 0;
674   currentLine->tokenpos   = 0;
675   currentLine->toklen     = 0;
676   currentLine->nextpos    = 0;
677   currentLine->lineno = lineno;
678   currentLine->column     = 0;
679   currentLine->inuse      = true;
680   currentLine->next       = NULL;
684  *  pushLine - pushes a new line structure.
685  */
687 static void pushLine (void)
689   if (currentLine == NULL)
690     initLine();
691   else if (currentLine->inuse) {
692       struct lineInfo *l = (struct lineInfo *)xmalloc (sizeof(struct lineInfo));
694       if (currentLine->linebuf == NULL) {
695         l->linebuf  = NULL;
696         l->linelen  = 0;
697       } else {
698         l->linebuf    = (char *)xstrdup (currentLine->linebuf);
699         l->linelen    = strlen (l->linebuf)+1;
700       }
701       l->tokenpos   = currentLine->tokenpos;
702       l->toklen     = currentLine->toklen;
703       l->nextpos    = currentLine->nextpos;
704       l->lineno = currentLine->lineno;
705       l->column     = currentLine->column;
706       l->next       = currentLine;
707       currentLine   = l;
708   }
709   currentLine->inuse = true;
713  *  popLine - pops a line structure.
714  */
716 static void popLine (void)
718   if (currentLine != NULL) {
719     struct lineInfo *l = currentLine;
721     if (currentLine->linebuf != NULL)
722       free(currentLine->linebuf);
723     currentLine = l->next;
724     free(l);
725   }
729  *  resetpos - resets the position of the next token to the start of the line.
730  */
732 static void resetpos (void)
734   if (currentLine != NULL)
735     currentLine->nextpos = 0;
739  *  finishedLine - indicates that the current line does not need to be
740  *                 preserved when a pushLine occurs.
741  */
743 static void finishedLine (void)
745   currentLine->inuse = false;
749  *  m2flex_GetToken - returns a new token.
750  */
752 EXTERN char *m2flex_GetToken (void)
754   TIMEVAR_PUSH_LEX;
755   if (currentLine == NULL)
756     initLine();
757   currentLine->tokenpos = currentLine->nextpos;
758   yylex();
759   TIMEVAR_POP_LEX;
760   return yytext;
764  *  CloseSource - provided for semantic sugar
765  */
767 EXTERN void m2flex_CloseSource (void)
769   END_FILE ();
773  *  OpenSource - returns true if file s can be opened and
774  *               all tokens are taken from this file.
775  */
777 EXTERN bool m2flex_OpenSource (char *s)
779   FILE *f = fopen(s, "r");
781   if (f == NULL)
782     return( false );
783   else {
784     isDefinitionModule = false;
785     while (currentFunction != NULL)
786       {
787         struct functionInfo *f = currentFunction;
788         currentFunction = f->next;
789         if (f->name != NULL)
790           free(f->name);
791         free(f);
792       }
793     yy_delete_buffer (YY_CURRENT_BUFFER);
794     yy_switch_to_buffer (yy_create_buffer(f, YY_BUF_SIZE));
795     filename = xstrdup (s);
796     lineno = 1;
797     if (currentLine == NULL)
798       pushLine ();
799     else
800       currentLine->lineno = lineno;
801     START_FILE (filename, lineno);
802     BEGIN INITIAL; resetpos ();
803     return true;
804   }
808  *  m2flex_GetLineNo - returns the current line number.
809  */
811 EXTERN int m2flex_GetLineNo (void)
813   if (currentLine != NULL)
814     return currentLine->lineno;
815   else
816     return 0;
820  *  m2flex_GetColumnNo - returns the column where the current
821  *                       token starts.
822  */
824 EXTERN int m2flex_GetColumnNo (void)
826   if (currentLine != NULL)
827     return currentLine->column;
828   else
829     return 0;
833  *  m2flex_GetLocation - returns the gcc location_t of the current token.
834  */
836 EXTERN location_t m2flex_GetLocation (void)
838   if (currentLine != NULL)
839     return currentLine->location;
840   else
841     return 0;
845  *  GetTotalLines - returns the total number of lines parsed.
846  */
848 EXTERN int m2flex_GetTotalLines (void)
850   return totalLines;
854  *  yywrap is called when end of file is seen. We push an eof token
855  *         and tell the lexical analysis to stop.
856  */
858 int yywrap (void)
860   updatepos(); M2LexBuf_AddTok(M2Reserved_eoftok); return 1;
863 EXTERN void _M2_m2flex_init (void) {}
864 EXTERN void _M2_m2flex_fini (void) {}