[PR target/115123] Fix testsuite fallout from sinking heuristic change
[official-gcc.git] / gcc / m2 / m2.flex
blobd08ac3edefa9d41b4f0f8e43dd1ecaa58459efb8
1 %{
2 /* m2.flex implements lexical analysis for Modula-2.
4 Copyright (C) 2004-2025 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"
29 #include "Gm2linemap.h"
31 static int cpreprocessor = 0;  /* Replace this with correct getter.  */
33 #if defined(GM2USEGGC)
34 #  include "ggc.h"
35 #endif
37 #include "timevar.h"
39 #define START_FILE(F,L)   m2linemap_StartFile(F,L)
40 #define END_FILE()        m2linemap_EndFile()
41 #define START_LINE(N,S)   m2linemap_StartLine(N,S)
42 #define GET_LOCATION(COLUMN_START,COLUMN_END) \
43         m2linemap_GetLocationRange(COLUMN_START,COLUMN_END)
44 #define TIMEVAR_PUSH_LEX  timevar_push (TV_LEX)
45 #define TIMEVAR_POP_LEX   timevar_pop (TV_LEX)
47 #ifdef __cplusplus
48 #define EXTERN extern "C"
49 #endif
51   /* m2.flex provides a lexical analyser for GNU Modula-2.  */
53   struct lineInfo {
54     char            *linebuf;          /* line contents */
55     int              linelen;          /* length */
56     int              tokenpos;         /* start position of token within line */
57     int              toklen;           /* a copy of yylen (length of token) */
58     int              nextpos;          /* position after token */
59     int              lineno;           /* line number of this line */
60     int              column;           /* first column number of token on this line */
61     bool             inuse;            /* do we need to keep this line info? */
62     location_t       location;         /* the corresponding gcc location_t */
63     struct lineInfo *next;
64   };
66   struct functionInfo {
67     char                *name;         /* function name */
68     bool                 module;       /* is it really a module? */
69     struct functionInfo *next;         /* list of nested functions */
70   };
72   static int                  lineno      =1;   /* a running count of the file line number */
73   static char                *filename    =NULL;
74   static int                  commentLevel=0;
75   static int                  commentCLevel=0;
76   static struct lineInfo     *currentLine=NULL;
77   static struct functionInfo *currentFunction=NULL;
78   static bool                 seenFunctionStart=false;
79   static bool                 seenEnd=false;
80   static bool                 seenModuleStart=false;
81   static bool                 isDefinitionModule=false;
82   static int                  totalLines=0;
84 static  void pushLine                 (void);
85 static  void popLine                  (void);
86 static  void finishedLine             (void);
87 static  void resetpos                 (void);
88 static  void consumeLine              (void);
89 static  void updatepos                (void);
90 static  void skippos                  (void);
91 static  void poperrorskip             (const char *);
92 static  void endOfComment             (void);
93 static  void endOfCComment            (void);
94 static  void splitSlashStar           (void);
95 static  void handleDate               (void);
96 static  void handleLine               (void);
97 static  void handleFile               (void);
98 static  void handleFunction           (void);
99 static  void handleColumn             (void);
100 static  void pushFunction             (char *function, bool module);
101 static  void popFunction              (void);
102 static  void checkFunction            (void);
103 EXTERN  void m2flex_M2Error           (const char *);
104 EXTERN  location_t m2flex_GetLocation (void);
105 EXTERN  int  m2flex_GetColumnNo       (void);
106 EXTERN  bool m2flex_OpenSource        (char *s);
107 EXTERN  int  m2flex_GetLineNo         (void);
108 EXTERN  void m2flex_CloseSource       (void);
109 EXTERN  char *m2flex_GetToken         (void);
110 EXTERN  void _M2_m2flex_init          (void);
111 EXTERN  int  m2flex_GetTotalLines     (void);
112 extern  void  yylex                   (void);
114 #define YY_DECL void yylex (void)
117 %option nounput
118 %x COMMENT COMMENT1 COMMENTC LINE0 LINE1 LINE2
122 "(*"                       { updatepos();
123                              commentLevel=1; pushLine(); skippos();
124                              BEGIN COMMENT; }
125 <COMMENT>"*)"              { endOfComment(); }
126 <COMMENT>"(*"              { commentLevel++; pushLine(); updatepos(); skippos(); }
127 <COMMENT>"<*"              { if (commentLevel == 1) {
128                                updatepos();
129                                pushLine();
130                                skippos();
131                                BEGIN COMMENT1;
132                              } else {
133                                updatepos(); skippos();
134                              }
135                            }
136 <COMMENT>\n.*              { consumeLine(); }
137 <COMMENT>.                 { updatepos(); skippos(); }
138 <COMMENT1>.                { updatepos(); skippos(); }
139 <COMMENT1>"*>"             { updatepos(); skippos(); finishedLine(); BEGIN COMMENT; }
140 <COMMENT1>\n.*             { consumeLine(); }
141 <COMMENT1>"*)"             { poperrorskip("unterminated source code directive, missing *>");
142                              endOfComment(); }
143 <COMMENT1><<EOF>>          { poperrorskip("unterminated source code directive, missing *>"); BEGIN COMMENT; }
144 <COMMENT><<EOF>>           { poperrorskip("unterminated comment found at the end of the file, missing *)"); BEGIN INITIAL; }
146 "/*"                       { /* Possibly handle C preprocessor comment.  */
147                              if (cpreprocessor)
148                                {
149                                  updatepos ();
150                                  commentCLevel++;
151                                  if (commentCLevel == 1)
152                                    {
153                                      pushLine ();
154                                      skippos ();
155                                    }
156                                  BEGIN COMMENTC;
157                                }
158                              else
159                                splitSlashStar ();
160                            }
161 <COMMENTC>.                { updatepos(); skippos(); }
162 <COMMENTC>\n.*             { consumeLine(); }
163 <COMMENTC>"*/"             { endOfCComment(); }
164 ^\#.*                      { consumeLine(); /* printf("found: %s\n", currentLine->linebuf); */
165                              if (M2Options_GetLineDirectives ())
166                                 BEGIN LINE0;
167                            }
168 \n\#.*                     { consumeLine(); /* printf("found: %s\n", currentLine->linebuf); */
169                              if (M2Options_GetLineDirectives ())
170                                 BEGIN LINE0;
171                            }
172 <LINE0>\#[ \t]*            { updatepos(); }
173 <LINE0>[0-9]+[ \t]*\"      { updatepos(); lineno=atoi(yytext); BEGIN LINE1; }
174 <LINE0>\n                  { m2flex_M2Error("missing initial quote after #line directive"); resetpos(); BEGIN INITIAL; }
175 <LINE0>[^\n]
176 <LINE1>[^\"\n]+            { m2flex_M2Error("missing final quote after #line directive"); resetpos(); BEGIN INITIAL; }
177 <LINE1>.*\"                { updatepos();
178                              filename = (char *)xrealloc(filename, yyleng+1);
179                              strcpy(filename, yytext);
180                              filename[yyleng-1] = (char)0;  /* remove trailing quote */
181                              START_FILE (filename, lineno);
182                              BEGIN LINE2;
183                            }
184 <LINE2>[ \t]*              { updatepos(); }
185 <LINE2>\n                  { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; }
186 <LINE2>2[ \t]*\n           { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; }
187 <LINE2>1[ \t]*\n           { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; }
188 <LINE2>1[ \t]*.*\n         { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; }
189 <LINE2>2[ \t]*.*\n         { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; }
190 <LINE2>3[ \t]*.*\n         { M2LexBuf_SetFile(filename); updatepos(); BEGIN INITIAL; }
192 \n[^\#].*                  { consumeLine(); /* printf("found: %s\n", currentLine->linebuf); */ }
193 \n                         { consumeLine(); /* printf("found: %s\n", currentLine->linebuf); */ }
195 \"[^\"\n]*\"               { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_stringtok, yytext); return; }
196 \"[^\"\n]*$                { updatepos();
197                              m2flex_M2Error("missing terminating quote, \"");
198                              M2LexBuf_AddTokCharStar(M2Reserved_stringtok, yytext);
199                              resetpos(); return;
200                            }
202 '[^'\n]*'                  { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_stringtok, yytext); return; }
203 '[^'\n]*$                  { updatepos();
204                              m2flex_M2Error("missing terminating quote, '");
205                              M2LexBuf_AddTokCharStar(M2Reserved_stringtok, yytext);
206                              resetpos(); return;
207                            }
209 <<EOF>>                    { updatepos(); M2LexBuf_AddTok(M2Reserved_eoftok); return; }
210 \+                         { updatepos(); M2LexBuf_AddTok(M2Reserved_plustok); return; }
211 -                          { updatepos(); M2LexBuf_AddTok(M2Reserved_minustok); return; }
212 "*"                        { updatepos(); M2LexBuf_AddTok(M2Reserved_timestok); return; }
213 \/                         { updatepos(); M2LexBuf_AddTok(M2Reserved_dividetok); return; }
214 :=                         { updatepos(); M2LexBuf_AddTok(M2Reserved_becomestok); return; }
215 \&                         { updatepos(); M2LexBuf_AddTok(M2Reserved_ambersandtok); return; }
216 \.                         { updatepos(); M2LexBuf_AddTok(M2Reserved_periodtok); return; }
217 \,                         { updatepos(); M2LexBuf_AddTok(M2Reserved_commatok); return; }
218 \;                         { updatepos(); M2LexBuf_AddTok(M2Reserved_semicolontok); return; }
219 \(                         { updatepos(); M2LexBuf_AddTok(M2Reserved_lparatok); return; }
220 \)                         { updatepos(); M2LexBuf_AddTok(M2Reserved_rparatok); return; }
221 \[                         { updatepos(); M2LexBuf_AddTok(M2Reserved_lsbratok); return; }
222 \]                         { updatepos(); M2LexBuf_AddTok(M2Reserved_rsbratok); return; }
223 \(\!                       { updatepos(); M2LexBuf_AddTok(M2Reserved_lsbratok); return; }
224 \!\)                       { updatepos(); M2LexBuf_AddTok(M2Reserved_rsbratok); return; }
225 \^                         { updatepos(); M2LexBuf_AddTok(M2Reserved_uparrowtok); return; }
226 \@                         { updatepos(); M2LexBuf_AddTok(M2Reserved_uparrowtok); return; }
227 \{                         { updatepos(); M2LexBuf_AddTok(M2Reserved_lcbratok); return; }
228 \}                         { updatepos(); M2LexBuf_AddTok(M2Reserved_rcbratok); return; }
229 \(\:                       { updatepos(); M2LexBuf_AddTok(M2Reserved_lcbratok); return; }
230 \:\)                       { updatepos(); M2LexBuf_AddTok(M2Reserved_rcbratok); return; }
231 \'                         { updatepos(); M2LexBuf_AddTok(M2Reserved_singlequotetok); return; }
232 \=                         { updatepos(); M2LexBuf_AddTok(M2Reserved_equaltok); return; }
233 \#                         { updatepos(); M2LexBuf_AddTok(M2Reserved_hashtok); return; }
234 \<                         { updatepos(); M2LexBuf_AddTok(M2Reserved_lesstok); return; }
235 \>                         { updatepos(); M2LexBuf_AddTok(M2Reserved_greatertok); return; }
236 \<\>                       { updatepos(); M2LexBuf_AddTok(M2Reserved_lessgreatertok); return; }
237 \<\=                       { updatepos(); M2LexBuf_AddTok(M2Reserved_lessequaltok); return; }
238 \>\=                       { updatepos(); M2LexBuf_AddTok(M2Reserved_greaterequaltok); return; }
239 "<*"                       { updatepos(); M2LexBuf_AddTok(M2Reserved_ldirectivetok); return; }
240 "*>"                       { updatepos(); M2LexBuf_AddTok(M2Reserved_rdirectivetok); return; }
241 \.\.                       { updatepos(); M2LexBuf_AddTok(M2Reserved_periodperiodtok); return; }
242 \.\.\.                     { updatepos(); M2LexBuf_AddTok(M2Reserved_periodperiodperiodtok); return; }
243 \:                         { updatepos(); M2LexBuf_AddTok(M2Reserved_colontok); return; }
244 \"                         { updatepos(); M2LexBuf_AddTok(M2Reserved_doublequotestok); return; }
245 \|                         { updatepos(); M2LexBuf_AddTok(M2Reserved_bartok); return; }
246 \!                         { updatepos(); M2LexBuf_AddTok(M2Reserved_bartok); return; }
247 \~                         { updatepos(); M2LexBuf_AddTok(M2Reserved_nottok); return; }
248 AND                        { updatepos(); M2LexBuf_AddTok(M2Reserved_andtok); return; }
249 ARRAY                      { updatepos(); M2LexBuf_AddTok(M2Reserved_arraytok); return; }
250 BEGIN                      { updatepos(); M2LexBuf_AddTok(M2Reserved_begintok); return; }
251 BY                         { updatepos(); M2LexBuf_AddTok(M2Reserved_bytok); return; }
252 CASE                       { updatepos(); M2LexBuf_AddTok(M2Reserved_casetok); return; }
253 CONST                      { updatepos(); M2LexBuf_AddTok(M2Reserved_consttok); return; }
254 DEFINITION                 { updatepos(); isDefinitionModule = true;
255                              M2LexBuf_AddTok(M2Reserved_definitiontok); return; }
256 DIV                        { updatepos(); M2LexBuf_AddTok(M2Reserved_divtok); return; }
257 DO                         { updatepos(); M2LexBuf_AddTok(M2Reserved_dotok); return; }
258 ELSE                       { updatepos(); M2LexBuf_AddTok(M2Reserved_elsetok); return; }
259 ELSIF                      { updatepos(); M2LexBuf_AddTok(M2Reserved_elsiftok); return; }
260 END                        { updatepos(); seenEnd=true;
261                              M2LexBuf_AddTok(M2Reserved_endtok); return; }
262 EXCEPT                     { updatepos(); M2LexBuf_AddTok(M2Reserved_excepttok); return; }
263 EXIT                       { updatepos(); M2LexBuf_AddTok(M2Reserved_exittok); return; }
264 EXPORT                     { updatepos(); M2LexBuf_AddTok(M2Reserved_exporttok); return; }
265 FINALLY                    { updatepos(); M2LexBuf_AddTok(M2Reserved_finallytok); return; }
266 FOR                        { updatepos(); M2LexBuf_AddTok(M2Reserved_fortok); return; }
267 FORWARD                    { updatepos(); M2LexBuf_AddTok(M2Reserved_forwardtok); return; }
268 FROM                       { updatepos(); M2LexBuf_AddTok(M2Reserved_fromtok); return; }
269 IF                         { updatepos(); M2LexBuf_AddTok(M2Reserved_iftok); return; }
270 IMPLEMENTATION             { updatepos(); M2LexBuf_AddTok(M2Reserved_implementationtok); return; }
271 IMPORT                     { updatepos(); M2LexBuf_AddTok(M2Reserved_importtok); return; }
272 IN                         { updatepos(); M2LexBuf_AddTok(M2Reserved_intok); return; }
273 LOOP                       { updatepos(); M2LexBuf_AddTok(M2Reserved_looptok); return; }
274 MOD                        { updatepos(); M2LexBuf_AddTok(M2Reserved_modtok); return; }
275 MODULE                     { updatepos(); seenModuleStart=true;
276                              M2LexBuf_AddTok(M2Reserved_moduletok); return; }
277 NOT                        { updatepos(); M2LexBuf_AddTok(M2Reserved_nottok); return; }
278 OF                         { updatepos(); M2LexBuf_AddTok(M2Reserved_oftok); return; }
279 OR                         { updatepos(); M2LexBuf_AddTok(M2Reserved_ortok); return; }
280 PACKEDSET                  { updatepos(); M2LexBuf_AddTok(M2Reserved_packedsettok); return; }
281 POINTER                    { updatepos(); M2LexBuf_AddTok(M2Reserved_pointertok); return; }
282 PROCEDURE                  { updatepos(); seenFunctionStart=true;
283                              M2LexBuf_AddTok(M2Reserved_proceduretok); return; }
284 QUALIFIED                  { updatepos(); M2LexBuf_AddTok(M2Reserved_qualifiedtok); return; }
285 UNQUALIFIED                { updatepos(); M2LexBuf_AddTok(M2Reserved_unqualifiedtok); return; }
286 RECORD                     { updatepos(); M2LexBuf_AddTok(M2Reserved_recordtok); return; }
287 REM                        { updatepos(); M2LexBuf_AddTok(M2Reserved_remtok); return; }
288 REPEAT                     { updatepos(); M2LexBuf_AddTok(M2Reserved_repeattok); return; }
289 RETRY                      { updatepos(); M2LexBuf_AddTok(M2Reserved_retrytok); return; }
290 RETURN                     { updatepos(); M2LexBuf_AddTok(M2Reserved_returntok); return; }
291 SET                        { updatepos(); M2LexBuf_AddTok(M2Reserved_settok); return; }
292 THEN                       { updatepos(); M2LexBuf_AddTok(M2Reserved_thentok); return; }
293 TO                         { updatepos(); M2LexBuf_AddTok(M2Reserved_totok); return; }
294 TYPE                       { updatepos(); M2LexBuf_AddTok(M2Reserved_typetok); return; }
295 UNTIL                      { updatepos(); M2LexBuf_AddTok(M2Reserved_untiltok); return; }
296 VAR                        { updatepos(); M2LexBuf_AddTok(M2Reserved_vartok); return; }
297 WHILE                      { updatepos(); M2LexBuf_AddTok(M2Reserved_whiletok); return; }
298 WITH                       { updatepos(); M2LexBuf_AddTok(M2Reserved_withtok); return; }
299 ASM                        { updatepos(); M2LexBuf_AddTok(M2Reserved_asmtok); return; }
300 VOLATILE                   { updatepos(); M2LexBuf_AddTok(M2Reserved_volatiletok); return; }
301 \_\_DATE\_\_               { updatepos(); handleDate(); return; }
302 \_\_LINE\_\_               { updatepos(); handleLine(); return; }
303 \_\_FILE\_\_               { updatepos(); handleFile(); return; }
304 \_\_FUNCTION\_\_           { updatepos(); handleFunction(); return; }
305 \_\_COLUMN\_\_             { updatepos(); handleColumn(); return; }
306 \_\_ATTRIBUTE\_\_          { updatepos(); M2LexBuf_AddTok(M2Reserved_attributetok); return; }
307 \_\_BUILTIN\_\_            { updatepos(); M2LexBuf_AddTok(M2Reserved_builtintok); return; }
308 \_\_INLINE\_\_             { updatepos(); M2LexBuf_AddTok(M2Reserved_inlinetok); return; }
311 (([0-9]*\.[0-9]+)(E[+-]?[0-9]+)?) { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_realtok, yytext); return; }
312 [0-9]*\.E[+-]?[0-9]+       { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_realtok, yytext); return; }
313 [a-zA-Z_][a-zA-Z0-9_]*     { checkFunction(); updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_identtok, yytext); return; }
314 [0-9]+                     { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
315 [0-1]+A                    { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
316 [0-9]+B                    { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
317 [0-9]+C                    { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
318 [0-9A-F]+H                 { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
319 [\t\r ]+                   { currentLine->tokenpos += yyleng;  /* Ignore space.  */; }
320 .                          { updatepos(); m2flex_M2Error("unrecognised symbol"); skippos(); }
324 /* have removed the -? from the beginning of the real/integer constant literal rules */
327  *  hand built routines
328  */
331  *  handleFile - handles the __FILE__ construct by wraping it in double quotes and putting
332  *               it into the token buffer as a string.
333  */
335 static void handleFile (void)
337   char *s = (char *)alloca(strlen(filename)+2+1);
339   strcpy(s, "\"");
340   strcat(s, filename);
341   strcat(s, "\"");
342   M2LexBuf_AddTokCharStar(M2Reserved_stringtok, s);
346  *  handleLine - handles the __LINE__ construct by passing an integer to
347  *               the token buffer.
348  */
350 static void handleLine (void)
352   M2LexBuf_AddTokInteger(M2Reserved_integertok, lineno);
356  *  handleColumn - handles the __COLUMN__ construct by passing an integer to
357  *                 the token buffer.
358  */
360 static void handleColumn (void)
362   M2LexBuf_AddTokInteger(M2Reserved_integertok, m2flex_GetColumnNo());
366  *  handleDate - handles the __DATE__ construct by passing the date
367  *               as a string to the token buffer.
368  */
370 static void handleDate (void)
372   time_t  clock = time ((time_t *)0);
373   char   *sdate = ctime (&clock);
374   char   *s     = (char *) alloca (strlen (sdate) + 2 + 1);
375   char   *p     = index (sdate, '\n');
377   if (p != NULL) {
378     *p = (char) 0;
379   }
380   strcpy(s, "\"");
381   strcat(s, sdate);
382   strcat(s, "\"");
383   M2LexBuf_AddTokCharStar (M2Reserved_stringtok, s);
387  *  handleFunction - handles the __FUNCTION__ construct by wrapping
388  *                   it in double quotes and putting it into the token
389  *                   buffer as a string.
390  */
392 static void handleFunction (void)
394   if (currentFunction == NULL)
395     M2LexBuf_AddTokCharStar(M2Reserved_stringtok, const_cast<char *>("\"\""));
396   else if (currentFunction->module) {
397     char *s = (char *) alloca(strlen(yytext) +
398                               strlen("\"module  initialization\"") + 1);
399     strcpy(s, "\"module ");
400     strcat(s, currentFunction->name);
401     strcat(s, " initialization\"");
402     M2LexBuf_AddTokCharStar(M2Reserved_stringtok, s);
403   } else {
404     char *function = currentFunction->name;
405     char *s = (char *)alloca(strlen(function)+2+1);
406     strcpy(s, "\"");
407     strcat(s, function);
408     strcat(s, "\"");
409     M2LexBuf_AddTokCharStar(M2Reserved_stringtok, s);
410   }
414  *  pushFunction - pushes the function name onto the stack.
415  */
417 static void pushFunction (char *function, bool module)
419   if (currentFunction == NULL) {
420     currentFunction = (struct functionInfo *)xmalloc (sizeof (struct functionInfo));
421     currentFunction->name = xstrdup(function);
422     currentFunction->next = NULL;
423     currentFunction->module = module;
424   } else {
425     struct functionInfo *f = (struct functionInfo *)xmalloc (sizeof (struct functionInfo));
426     f->name = xstrdup(function);
427     f->next = currentFunction;
428     f->module = module;
429     currentFunction = f;
430   }
434  *  popFunction - pops the current function.
435  */
437 static void popFunction (void)
439   if (currentFunction != NULL && currentFunction->next != NULL) {
440     struct functionInfo *f = currentFunction;
442     currentFunction = currentFunction->next;
443     if (f->name != NULL)
444       free(f->name);
445     free(f);
446   }
450  *  endOfComment - handles the end of comment
451  */
453 static void endOfComment (void)
455   commentLevel--;
456   updatepos();
457   skippos();
458   if (commentLevel==0) {
459     BEGIN INITIAL;
460     finishedLine();
461   } else
462     popLine();
466  *  endOfCComment - handles the end of C comment.
467  */
469 static void endOfCComment (void)
471   commentCLevel = 0;
472   updatepos();
473   skippos();
474   BEGIN INITIAL;
475   finishedLine();
479  *  m2flex_M2Error - displays the error message, s, after the code line and pointer
480  *                   to the erroneous token.
481  */
483 EXTERN void m2flex_M2Error (const char *s)
485   if (currentLine->linebuf != NULL) {
486     int i=1;
488     printf("%s:%d:%s\n", filename, currentLine->lineno, currentLine->linebuf);
489     printf("%s:%d:%*s", filename, currentLine->lineno, 1+currentLine->tokenpos, "^");
490     while (i<currentLine->toklen) {
491       putchar('^');
492       i++;
493     }
494     putchar('\n');
495   }
496   if (s == NULL)
497     printf("%s:%d\n", filename, currentLine->lineno);
498   else
499     printf("%s:%d:%s\n", filename, currentLine->lineno, s);
502 static void poperrorskip (const char *s)
504   int nextpos =currentLine->nextpos;
505   int tokenpos=currentLine->tokenpos;
507   popLine();
508   m2flex_M2Error(s);
509   if (currentLine != NULL) {
510     currentLine->nextpos  = nextpos;
511     currentLine->tokenpos = tokenpos;
512   }
515 /* skipnewline skips all '\n' at the start of the line and returns
516    the new position.  */
518 static
519 char *
520 skipnewline (char *line)
522   while (((*line) != (char)0) && ((*line) == '\n'))
523     line++;
524   return line;
527 /* traceLine display the source line providing -fdebug-trace-line was
528    enabled.  */
530 static
531 void
532 traceLine (void)
534   if (M2Options_GetDebugTraceLine ())
535     {
536       char *line = skipnewline (currentLine->linebuf);
537       if (filename == NULL)
538         printf("<stdin>:%d:%s\n", currentLine->lineno, line);
539       else
540         printf("%s:%d:%s\n", filename, currentLine->lineno, line);
541     }
545  *  consumeLine - reads a line into a buffer, it then pushes back the whole
546  *                line except the initial \n.
547  */
549 static void consumeLine (void)
551   if (currentLine->linelen<yyleng) {
552     currentLine->linebuf = (char *)xrealloc (currentLine->linebuf, yyleng);
553     currentLine->linelen = yyleng;
554   }
555   strcpy(currentLine->linebuf, yytext+1);  /* copy all except the initial \n */
556   lineno++;
557   totalLines++;
558   currentLine->lineno = lineno;
559   currentLine->tokenpos=0;
560   currentLine->nextpos=0;
561   currentLine->column=0;
562   START_LINE (lineno, yyleng);
563   yyless(1);                  /* push back all but the \n */
564   traceLine ();
567 static void assert_location (location_t location ATTRIBUTE_UNUSED)
569 #if 0
570   if ((location != BUILTINS_LOCATION) && (location != UNKNOWN_LOCATION) && (! M2Options_GetCpp ())) {
571      expanded_location xl = expand_location (location);
572      if (xl.line != currentLine->lineno) {
573        m2flex_M2Error ("mismatched gcc location and front end token number");
574      }
575   }
576 #endif
580  *  splitSlashStar - called if we are not tokenizing source code after it
581  *                   has been preprocessed by cpp.  It is only called
582  *                   if the current token was a / immediately followed by * and
583  *                   therefore it will be split into two m2 tokens:  / and *.
584  */
586 static void splitSlashStar (void)
588   seenFunctionStart    = false;
589   seenEnd              = false;
590   seenModuleStart      = false;
591   currentLine->nextpos = currentLine->tokenpos+1;  /* "/".  */
592   currentLine->toklen  = 1;
593   currentLine->column = currentLine->tokenpos+1;
594   currentLine->location =
595     M2Options_OverrideLocation (GET_LOCATION (currentLine->column,
596                                               currentLine->column+currentLine->toklen-1));
597   assert_location (GET_LOCATION (currentLine->column,
598                                  currentLine->column+currentLine->toklen-1));
599   M2LexBuf_AddTok (M2Reserved_dividetok);
600   currentLine->nextpos = currentLine->tokenpos+1;  /* "*".  */
601   currentLine->toklen  = 1;
602   currentLine->column = currentLine->tokenpos+1;
603   currentLine->location =
604     M2Options_OverrideLocation (GET_LOCATION (currentLine->column,
605                                               currentLine->column+currentLine->toklen-1));
606   assert_location (GET_LOCATION (currentLine->column,
607                                  currentLine->column+currentLine->toklen-1));
608   M2LexBuf_AddTok (M2Reserved_timestok);
613  *  updatepos - updates the current token position.
614  *              Should be used when a rule matches a token.
615  */
617 static void updatepos (void)
619   seenFunctionStart    = false;
620   seenEnd              = false;
621   seenModuleStart      = false;
622   currentLine->nextpos = currentLine->tokenpos+yyleng;
623   currentLine->toklen  = yyleng;
624   /* if (currentLine->column == 0) */
625   currentLine->column = currentLine->tokenpos+1;
626   currentLine->location =
627     M2Options_OverrideLocation (GET_LOCATION (currentLine->column,
628                                               currentLine->column+currentLine->toklen-1));
629   assert_location (GET_LOCATION (currentLine->column,
630                                  currentLine->column+currentLine->toklen-1));
634  *  checkFunction - checks to see whether we have seen the start
635  *                  or end of a function.
636  */
638 static void checkFunction (void)
640   if (! isDefinitionModule) {
641     if (seenModuleStart)
642       pushFunction(yytext, 1);
643     if (seenFunctionStart)
644       pushFunction(yytext, 0);
645     if (seenEnd && currentFunction != NULL &&
646         (strcmp(currentFunction->name, yytext) == 0))
647       popFunction();
648   }
649   seenFunctionStart = false;
650   seenEnd           = false;
651   seenModuleStart   = false;
655  *  skippos - skips over this token. This function should be called
656  *            if we are not returning and thus not calling getToken.
657  */
659 static void skippos (void)
661   currentLine->tokenpos = currentLine->nextpos;
665  *  initLine - initializes a currentLine
666  */
668 static void initLine (void)
670   currentLine = (struct lineInfo *)xmalloc (sizeof(struct lineInfo));
672   if (currentLine == NULL)
673     perror("xmalloc");
674   currentLine->linebuf    = NULL;
675   currentLine->linelen    = 0;
676   currentLine->tokenpos   = 0;
677   currentLine->toklen     = 0;
678   currentLine->nextpos    = 0;
679   currentLine->lineno = lineno;
680   currentLine->column     = 0;
681   currentLine->inuse      = true;
682   currentLine->next       = NULL;
686  *  pushLine - pushes a new line structure.
687  */
689 static void pushLine (void)
691   if (currentLine == NULL)
692     initLine();
693   else if (currentLine->inuse) {
694       struct lineInfo *l = (struct lineInfo *)xmalloc (sizeof(struct lineInfo));
696       if (currentLine->linebuf == NULL) {
697         l->linebuf  = NULL;
698         l->linelen  = 0;
699       } else {
700         l->linebuf    = (char *)xstrdup (currentLine->linebuf);
701         l->linelen    = strlen (l->linebuf)+1;
702       }
703       l->tokenpos   = currentLine->tokenpos;
704       l->toklen     = currentLine->toklen;
705       l->nextpos    = currentLine->nextpos;
706       l->lineno = currentLine->lineno;
707       l->column     = currentLine->column;
708       l->next       = currentLine;
709       currentLine   = l;
710   }
711   currentLine->inuse = true;
715  *  popLine - pops a line structure.
716  */
718 static void popLine (void)
720   if (currentLine != NULL) {
721     struct lineInfo *l = currentLine;
723     if (currentLine->linebuf != NULL)
724       free(currentLine->linebuf);
725     currentLine = l->next;
726     free(l);
727   }
731  *  resetpos - resets the position of the next token to the start of the line.
732  */
734 static void resetpos (void)
736   if (currentLine != NULL)
737     currentLine->nextpos = 0;
741  *  finishedLine - indicates that the current line does not need to be
742  *                 preserved when a pushLine occurs.
743  */
745 static void finishedLine (void)
747   currentLine->inuse = false;
751  *  m2flex_GetToken - returns a new token.
752  */
754 EXTERN char *m2flex_GetToken (void)
756   TIMEVAR_PUSH_LEX;
757   if (currentLine == NULL)
758     initLine();
759   currentLine->tokenpos = currentLine->nextpos;
760   yylex();
761   TIMEVAR_POP_LEX;
762   return yytext;
766  *  CloseSource - provided for semantic sugar
767  */
769 EXTERN void m2flex_CloseSource (void)
771   END_FILE ();
775  *  OpenSource - returns true if file s can be opened and
776  *               all tokens are taken from this file.
777  */
779 EXTERN bool m2flex_OpenSource (char *s)
781   FILE *f = fopen(s, "r");
783   if (f == NULL)
784     return( false );
785   else {
786     isDefinitionModule = false;
787     while (currentFunction != NULL)
788       {
789         struct functionInfo *f = currentFunction;
790         currentFunction = f->next;
791         if (f->name != NULL)
792           free(f->name);
793         free(f);
794       }
795     yy_delete_buffer (YY_CURRENT_BUFFER);
796     yy_switch_to_buffer (yy_create_buffer(f, YY_BUF_SIZE));
797     filename = xstrdup (s);
798     lineno = 1;
799     if (currentLine == NULL)
800       pushLine ();
801     else
802       currentLine->lineno = lineno;
803     START_FILE (filename, lineno);
804     BEGIN INITIAL; resetpos ();
805     return true;
806   }
810  *  m2flex_GetLineNo - returns the current line number.
811  */
813 EXTERN int m2flex_GetLineNo (void)
815   if (currentLine != NULL)
816     return currentLine->lineno;
817   else
818     return 0;
822  *  m2flex_GetColumnNo - returns the column where the current
823  *                       token starts.
824  */
826 EXTERN int m2flex_GetColumnNo (void)
828   if (currentLine != NULL)
829     return currentLine->column;
830   else
831     return 0;
835  *  m2flex_GetLocation - returns the gcc location_t of the current token.
836  */
838 EXTERN location_t m2flex_GetLocation (void)
840   if (currentLine != NULL)
841     return currentLine->location;
842   else
843     return 0;
847  *  GetTotalLines - returns the total number of lines parsed.
848  */
850 EXTERN int m2flex_GetTotalLines (void)
852   return totalLines;
856  *  yywrap is called when end of file is seen. We push an eof token
857  *         and tell the lexical analysis to stop.
858  */
860 int yywrap (void)
862   updatepos(); M2LexBuf_AddTok(M2Reserved_eoftok); return 1;
865 EXTERN void _M2_m2flex_init (void) {}
866 EXTERN void _M2_m2flex_fini (void) {}