libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / m2 / m2.flex
blob7f9b2d3d9319aa90a43c815c1bd7bedd351b451a
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"
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 FROM                       { updatepos(); M2LexBuf_AddTok(M2Reserved_fromtok); return; }
268 IF                         { updatepos(); M2LexBuf_AddTok(M2Reserved_iftok); return; }
269 IMPLEMENTATION             { updatepos(); M2LexBuf_AddTok(M2Reserved_implementationtok); return; }
270 IMPORT                     { updatepos(); M2LexBuf_AddTok(M2Reserved_importtok); return; }
271 IN                         { updatepos(); M2LexBuf_AddTok(M2Reserved_intok); return; }
272 LOOP                       { updatepos(); M2LexBuf_AddTok(M2Reserved_looptok); return; }
273 MOD                        { updatepos(); M2LexBuf_AddTok(M2Reserved_modtok); return; }
274 MODULE                     { updatepos(); seenModuleStart=true;
275                              M2LexBuf_AddTok(M2Reserved_moduletok); return; }
276 NOT                        { updatepos(); M2LexBuf_AddTok(M2Reserved_nottok); return; }
277 OF                         { updatepos(); M2LexBuf_AddTok(M2Reserved_oftok); return; }
278 OR                         { updatepos(); M2LexBuf_AddTok(M2Reserved_ortok); return; }
279 PACKEDSET                  { updatepos(); M2LexBuf_AddTok(M2Reserved_packedsettok); return; }
280 POINTER                    { updatepos(); M2LexBuf_AddTok(M2Reserved_pointertok); return; }
281 PROCEDURE                  { updatepos(); seenFunctionStart=true;
282                              M2LexBuf_AddTok(M2Reserved_proceduretok); return; }
283 QUALIFIED                  { updatepos(); M2LexBuf_AddTok(M2Reserved_qualifiedtok); return; }
284 UNQUALIFIED                { updatepos(); M2LexBuf_AddTok(M2Reserved_unqualifiedtok); return; }
285 RECORD                     { updatepos(); M2LexBuf_AddTok(M2Reserved_recordtok); return; }
286 REM                        { updatepos(); M2LexBuf_AddTok(M2Reserved_remtok); return; }
287 REPEAT                     { updatepos(); M2LexBuf_AddTok(M2Reserved_repeattok); return; }
288 RETRY                      { updatepos(); M2LexBuf_AddTok(M2Reserved_retrytok); return; }
289 RETURN                     { updatepos(); M2LexBuf_AddTok(M2Reserved_returntok); return; }
290 SET                        { updatepos(); M2LexBuf_AddTok(M2Reserved_settok); return; }
291 THEN                       { updatepos(); M2LexBuf_AddTok(M2Reserved_thentok); return; }
292 TO                         { updatepos(); M2LexBuf_AddTok(M2Reserved_totok); return; }
293 TYPE                       { updatepos(); M2LexBuf_AddTok(M2Reserved_typetok); return; }
294 UNTIL                      { updatepos(); M2LexBuf_AddTok(M2Reserved_untiltok); return; }
295 VAR                        { updatepos(); M2LexBuf_AddTok(M2Reserved_vartok); return; }
296 WHILE                      { updatepos(); M2LexBuf_AddTok(M2Reserved_whiletok); return; }
297 WITH                       { updatepos(); M2LexBuf_AddTok(M2Reserved_withtok); return; }
298 ASM                        { updatepos(); M2LexBuf_AddTok(M2Reserved_asmtok); return; }
299 VOLATILE                   { updatepos(); M2LexBuf_AddTok(M2Reserved_volatiletok); return; }
300 \_\_DATE\_\_               { updatepos(); handleDate(); return; }
301 \_\_LINE\_\_               { updatepos(); handleLine(); return; }
302 \_\_FILE\_\_               { updatepos(); handleFile(); return; }
303 \_\_FUNCTION\_\_           { updatepos(); handleFunction(); return; }
304 \_\_COLUMN\_\_             { updatepos(); handleColumn(); return; }
305 \_\_ATTRIBUTE\_\_          { updatepos(); M2LexBuf_AddTok(M2Reserved_attributetok); return; }
306 \_\_BUILTIN\_\_            { updatepos(); M2LexBuf_AddTok(M2Reserved_builtintok); return; }
307 \_\_INLINE\_\_             { updatepos(); M2LexBuf_AddTok(M2Reserved_inlinetok); return; }
310 (([0-9]*\.[0-9]+)(E[+-]?[0-9]+)?) { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_realtok, yytext); return; }
311 [0-9]*\.E[+-]?[0-9]+       { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_realtok, yytext); return; }
312 [a-zA-Z_][a-zA-Z0-9_]*     { checkFunction(); updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_identtok, yytext); return; }
313 [0-9]+                     { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
314 [0-1]+A                    { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
315 [0-9]+B                    { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
316 [0-9]+C                    { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
317 [0-9A-F]+H                 { updatepos(); M2LexBuf_AddTokCharStar(M2Reserved_integertok, yytext); return; }
318 [\t\r ]+                   { currentLine->tokenpos += yyleng;  /* Ignore space.  */; }
319 .                          { updatepos(); m2flex_M2Error("unrecognised symbol"); skippos(); }
323 /* have removed the -? from the beginning of the real/integer constant literal rules */
326  *  hand built routines
327  */
330  *  handleFile - handles the __FILE__ construct by wraping it in double quotes and putting
331  *               it into the token buffer as a string.
332  */
334 static void handleFile (void)
336   char *s = (char *)alloca(strlen(filename)+2+1);
338   strcpy(s, "\"");
339   strcat(s, filename);
340   strcat(s, "\"");
341   M2LexBuf_AddTokCharStar(M2Reserved_stringtok, s);
345  *  handleLine - handles the __LINE__ construct by passing an integer to
346  *               the token buffer.
347  */
349 static void handleLine (void)
351   M2LexBuf_AddTokInteger(M2Reserved_integertok, lineno);
355  *  handleColumn - handles the __COLUMN__ construct by passing an integer to
356  *                 the token buffer.
357  */
359 static void handleColumn (void)
361   M2LexBuf_AddTokInteger(M2Reserved_integertok, m2flex_GetColumnNo());
365  *  handleDate - handles the __DATE__ construct by passing the date
366  *               as a string to the token buffer.
367  */
369 static void handleDate (void)
371   time_t  clock = time ((time_t *)0);
372   char   *sdate = ctime (&clock);
373   char   *s     = (char *) alloca (strlen (sdate) + 2 + 1);
374   char   *p     = index (sdate, '\n');
376   if (p != NULL) {
377     *p = (char) 0;
378   }
379   strcpy(s, "\"");
380   strcat(s, sdate);
381   strcat(s, "\"");
382   M2LexBuf_AddTokCharStar (M2Reserved_stringtok, s);
386  *  handleFunction - handles the __FUNCTION__ construct by wrapping
387  *                   it in double quotes and putting it into the token
388  *                   buffer as a string.
389  */
391 static void handleFunction (void)
393   if (currentFunction == NULL)
394     M2LexBuf_AddTokCharStar(M2Reserved_stringtok, const_cast<char *>("\"\""));
395   else if (currentFunction->module) {
396     char *s = (char *) alloca(strlen(yytext) +
397                               strlen("\"module  initialization\"") + 1);
398     strcpy(s, "\"module ");
399     strcat(s, currentFunction->name);
400     strcat(s, " initialization\"");
401     M2LexBuf_AddTokCharStar(M2Reserved_stringtok, s);
402   } else {
403     char *function = currentFunction->name;
404     char *s = (char *)alloca(strlen(function)+2+1);
405     strcpy(s, "\"");
406     strcat(s, function);
407     strcat(s, "\"");
408     M2LexBuf_AddTokCharStar(M2Reserved_stringtok, s);
409   }
413  *  pushFunction - pushes the function name onto the stack.
414  */
416 static void pushFunction (char *function, bool module)
418   if (currentFunction == NULL) {
419     currentFunction = (struct functionInfo *)xmalloc (sizeof (struct functionInfo));
420     currentFunction->name = xstrdup(function);
421     currentFunction->next = NULL;
422     currentFunction->module = module;
423   } else {
424     struct functionInfo *f = (struct functionInfo *)xmalloc (sizeof (struct functionInfo));
425     f->name = xstrdup(function);
426     f->next = currentFunction;
427     f->module = module;
428     currentFunction = f;
429   }
433  *  popFunction - pops the current function.
434  */
436 static void popFunction (void)
438   if (currentFunction != NULL && currentFunction->next != NULL) {
439     struct functionInfo *f = currentFunction;
441     currentFunction = currentFunction->next;
442     if (f->name != NULL)
443       free(f->name);
444     free(f);
445   }
449  *  endOfComment - handles the end of comment
450  */
452 static void endOfComment (void)
454   commentLevel--;
455   updatepos();
456   skippos();
457   if (commentLevel==0) {
458     BEGIN INITIAL;
459     finishedLine();
460   } else
461     popLine();
465  *  endOfCComment - handles the end of C comment.
466  */
468 static void endOfCComment (void)
470   commentCLevel = 0;
471   updatepos();
472   skippos();
473   BEGIN INITIAL;
474   finishedLine();
478  *  m2flex_M2Error - displays the error message, s, after the code line and pointer
479  *                   to the erroneous token.
480  */
482 EXTERN void m2flex_M2Error (const char *s)
484   if (currentLine->linebuf != NULL) {
485     int i=1;
487     printf("%s:%d:%s\n", filename, currentLine->lineno, currentLine->linebuf);
488     printf("%s:%d:%*s", filename, currentLine->lineno, 1+currentLine->tokenpos, "^");
489     while (i<currentLine->toklen) {
490       putchar('^');
491       i++;
492     }
493     putchar('\n');
494   }
495   if (s == NULL)
496     printf("%s:%d\n", filename, currentLine->lineno);
497   else
498     printf("%s:%d:%s\n", filename, currentLine->lineno, s);
501 static void poperrorskip (const char *s)
503   int nextpos =currentLine->nextpos;
504   int tokenpos=currentLine->tokenpos;
506   popLine();
507   m2flex_M2Error(s);
508   if (currentLine != NULL) {
509     currentLine->nextpos  = nextpos;
510     currentLine->tokenpos = tokenpos;
511   }
514 /* skipnewline skips all '\n' at the start of the line and returns
515    the new position.  */
517 static
518 char *
519 skipnewline (char *line)
521   while (((*line) != (char)0) && ((*line) == '\n'))
522     line++;
523   return line;
526 /* traceLine display the source line providing -fdebug-trace-line was
527    enabled.  */
529 static
530 void
531 traceLine (void)
533   if (M2Options_GetDebugTraceLine ())
534     {
535       char *line = skipnewline (currentLine->linebuf);
536       if (filename == NULL)
537         printf("<stdin>:%d:%s\n", currentLine->lineno, line);
538       else
539         printf("%s:%d:%s\n", filename, currentLine->lineno, line);
540     }
544  *  consumeLine - reads a line into a buffer, it then pushes back the whole
545  *                line except the initial \n.
546  */
548 static void consumeLine (void)
550   if (currentLine->linelen<yyleng) {
551     currentLine->linebuf = (char *)xrealloc (currentLine->linebuf, yyleng);
552     currentLine->linelen = yyleng;
553   }
554   strcpy(currentLine->linebuf, yytext+1);  /* copy all except the initial \n */
555   lineno++;
556   totalLines++;
557   currentLine->lineno = lineno;
558   currentLine->tokenpos=0;
559   currentLine->nextpos=0;
560   currentLine->column=0;
561   START_LINE (lineno, yyleng);
562   yyless(1);                  /* push back all but the \n */
563   traceLine ();
566 static void assert_location (location_t location ATTRIBUTE_UNUSED)
568 #if 0
569   if ((location != BUILTINS_LOCATION) && (location != UNKNOWN_LOCATION) && (! M2Options_GetCpp ())) {
570      expanded_location xl = expand_location (location);
571      if (xl.line != currentLine->lineno) {
572        m2flex_M2Error ("mismatched gcc location and front end token number");
573      }
574   }
575 #endif
579  *  splitSlashStar - called if we are not tokenizing source code after it
580  *                   has been preprocessed by cpp.  It is only called
581  *                   if the current token was a / immediately followed by * and
582  *                   therefore it will be split into two m2 tokens:  / and *.
583  */
585 static void splitSlashStar (void)
587   seenFunctionStart    = false;
588   seenEnd              = false;
589   seenModuleStart      = false;
590   currentLine->nextpos = currentLine->tokenpos+1;  /* "/".  */
591   currentLine->toklen  = 1;
592   currentLine->column = currentLine->tokenpos+1;
593   currentLine->location =
594     M2Options_OverrideLocation (GET_LOCATION (currentLine->column,
595                                               currentLine->column+currentLine->toklen-1));
596   assert_location (GET_LOCATION (currentLine->column,
597                                  currentLine->column+currentLine->toklen-1));
598   M2LexBuf_AddTok (M2Reserved_dividetok);
599   currentLine->nextpos = currentLine->tokenpos+1;  /* "*".  */
600   currentLine->toklen  = 1;
601   currentLine->column = currentLine->tokenpos+1;
602   currentLine->location =
603     M2Options_OverrideLocation (GET_LOCATION (currentLine->column,
604                                               currentLine->column+currentLine->toklen-1));
605   assert_location (GET_LOCATION (currentLine->column,
606                                  currentLine->column+currentLine->toklen-1));
607   M2LexBuf_AddTok (M2Reserved_timestok);
612  *  updatepos - updates the current token position.
613  *              Should be used when a rule matches a token.
614  */
616 static void updatepos (void)
618   seenFunctionStart    = false;
619   seenEnd              = false;
620   seenModuleStart      = false;
621   currentLine->nextpos = currentLine->tokenpos+yyleng;
622   currentLine->toklen  = yyleng;
623   /* if (currentLine->column == 0) */
624   currentLine->column = currentLine->tokenpos+1;
625   currentLine->location =
626     M2Options_OverrideLocation (GET_LOCATION (currentLine->column,
627                                               currentLine->column+currentLine->toklen-1));
628   assert_location (GET_LOCATION (currentLine->column,
629                                  currentLine->column+currentLine->toklen-1));
633  *  checkFunction - checks to see whether we have seen the start
634  *                  or end of a function.
635  */
637 static void checkFunction (void)
639   if (! isDefinitionModule) {
640     if (seenModuleStart)
641       pushFunction(yytext, 1);
642     if (seenFunctionStart)
643       pushFunction(yytext, 0);
644     if (seenEnd && currentFunction != NULL &&
645         (strcmp(currentFunction->name, yytext) == 0))
646       popFunction();
647   }
648   seenFunctionStart = false;
649   seenEnd           = false;
650   seenModuleStart   = false;
654  *  skippos - skips over this token. This function should be called
655  *            if we are not returning and thus not calling getToken.
656  */
658 static void skippos (void)
660   currentLine->tokenpos = currentLine->nextpos;
664  *  initLine - initializes a currentLine
665  */
667 static void initLine (void)
669   currentLine = (struct lineInfo *)xmalloc (sizeof(struct lineInfo));
671   if (currentLine == NULL)
672     perror("xmalloc");
673   currentLine->linebuf    = NULL;
674   currentLine->linelen    = 0;
675   currentLine->tokenpos   = 0;
676   currentLine->toklen     = 0;
677   currentLine->nextpos    = 0;
678   currentLine->lineno = lineno;
679   currentLine->column     = 0;
680   currentLine->inuse      = true;
681   currentLine->next       = NULL;
685  *  pushLine - pushes a new line structure.
686  */
688 static void pushLine (void)
690   if (currentLine == NULL)
691     initLine();
692   else if (currentLine->inuse) {
693       struct lineInfo *l = (struct lineInfo *)xmalloc (sizeof(struct lineInfo));
695       if (currentLine->linebuf == NULL) {
696         l->linebuf  = NULL;
697         l->linelen  = 0;
698       } else {
699         l->linebuf    = (char *)xstrdup (currentLine->linebuf);
700         l->linelen    = strlen (l->linebuf)+1;
701       }
702       l->tokenpos   = currentLine->tokenpos;
703       l->toklen     = currentLine->toklen;
704       l->nextpos    = currentLine->nextpos;
705       l->lineno = currentLine->lineno;
706       l->column     = currentLine->column;
707       l->next       = currentLine;
708       currentLine   = l;
709   }
710   currentLine->inuse = true;
714  *  popLine - pops a line structure.
715  */
717 static void popLine (void)
719   if (currentLine != NULL) {
720     struct lineInfo *l = currentLine;
722     if (currentLine->linebuf != NULL)
723       free(currentLine->linebuf);
724     currentLine = l->next;
725     free(l);
726   }
730  *  resetpos - resets the position of the next token to the start of the line.
731  */
733 static void resetpos (void)
735   if (currentLine != NULL)
736     currentLine->nextpos = 0;
740  *  finishedLine - indicates that the current line does not need to be
741  *                 preserved when a pushLine occurs.
742  */
744 static void finishedLine (void)
746   currentLine->inuse = false;
750  *  m2flex_GetToken - returns a new token.
751  */
753 EXTERN char *m2flex_GetToken (void)
755   TIMEVAR_PUSH_LEX;
756   if (currentLine == NULL)
757     initLine();
758   currentLine->tokenpos = currentLine->nextpos;
759   yylex();
760   TIMEVAR_POP_LEX;
761   return yytext;
765  *  CloseSource - provided for semantic sugar
766  */
768 EXTERN void m2flex_CloseSource (void)
770   END_FILE ();
774  *  OpenSource - returns true if file s can be opened and
775  *               all tokens are taken from this file.
776  */
778 EXTERN bool m2flex_OpenSource (char *s)
780   FILE *f = fopen(s, "r");
782   if (f == NULL)
783     return( false );
784   else {
785     isDefinitionModule = false;
786     while (currentFunction != NULL)
787       {
788         struct functionInfo *f = currentFunction;
789         currentFunction = f->next;
790         if (f->name != NULL)
791           free(f->name);
792         free(f);
793       }
794     yy_delete_buffer (YY_CURRENT_BUFFER);
795     yy_switch_to_buffer (yy_create_buffer(f, YY_BUF_SIZE));
796     filename = xstrdup (s);
797     lineno = 1;
798     if (currentLine == NULL)
799       pushLine ();
800     else
801       currentLine->lineno = lineno;
802     START_FILE (filename, lineno);
803     BEGIN INITIAL; resetpos ();
804     return true;
805   }
809  *  m2flex_GetLineNo - returns the current line number.
810  */
812 EXTERN int m2flex_GetLineNo (void)
814   if (currentLine != NULL)
815     return currentLine->lineno;
816   else
817     return 0;
821  *  m2flex_GetColumnNo - returns the column where the current
822  *                       token starts.
823  */
825 EXTERN int m2flex_GetColumnNo (void)
827   if (currentLine != NULL)
828     return currentLine->column;
829   else
830     return 0;
834  *  m2flex_GetLocation - returns the gcc location_t of the current token.
835  */
837 EXTERN location_t m2flex_GetLocation (void)
839   if (currentLine != NULL)
840     return currentLine->location;
841   else
842     return 0;
846  *  GetTotalLines - returns the total number of lines parsed.
847  */
849 EXTERN int m2flex_GetTotalLines (void)
851   return totalLines;
855  *  yywrap is called when end of file is seen. We push an eof token
856  *         and tell the lexical analysis to stop.
857  */
859 int yywrap (void)
861   updatepos(); M2LexBuf_AddTok(M2Reserved_eoftok); return 1;
864 EXTERN void _M2_m2flex_init (void) {}
865 EXTERN void _M2_m2flex_fini (void) {}