CMake Nightly Date Stamp
[kiteware-cmake.git] / Source / LexerParser / cmListFileLexer.in.l
blob94cf8a59430546df77979bf8a2cf735c48a6de1f
1 %{
2 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
3    file Copyright.txt or https://cmake.org/licensing for details.  */
4 /*
6 This file must be translated to C and modified to build everywhere.
8 Run flex >= 2.6 like this:
10   flex --nounistd -DFLEXINT_H --noline -ocmListFileLexer.c cmListFileLexer.in.l
12 Modify cmListFileLexer.c:
13   - remove trailing whitespace:              sed -i 's/\s*$//' cmListFileLexer.c
14   - remove blank lines at end of file:       sed -i '${/^$/d;}' cmListFileLexer.c
15   - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmListFileLexer.c
19 /* IWYU pragma: no_forward_declare yyguts_t */
21 #ifdef _WIN32
22 #include "cmsys/Encoding.h"
23 #endif
25 /* Setup the proper cmListFileLexer_yylex declaration.  */
26 #define YY_EXTRA_TYPE cmListFileLexer*
27 #define YY_DECL int cmListFileLexer_yylex (yyscan_t yyscanner, cmListFileLexer* lexer)
29 #include "cmListFileLexer.h"
31 /*--------------------------------------------------------------------------*/
32 struct cmListFileLexer_s
34   cmListFileLexer_Token token;
35   int bracket;
36   int comment;
37   int line;
38   int column;
39   int size;
40   FILE* file;
41   size_t cr;
42   char* string_buffer;
43   char* string_position;
44   int string_left;
45   yyscan_t scanner;
48 static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
49                                     int length);
50 static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
51                                   int length);
52 static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
53                                 size_t bufferSize);
54 static void cmListFileLexerInit(cmListFileLexer* lexer);
55 static void cmListFileLexerDestroy(cmListFileLexer* lexer);
57 /* Replace the lexer input function.  */
58 #undef YY_INPUT
59 #define YY_INPUT(buf, result, max_size) \
60   do { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); } while (0)
62 /*--------------------------------------------------------------------------*/
65 %option prefix="cmListFileLexer_yy"
67 %option reentrant
68 %option yylineno
69 %option noyywrap
70 %pointer
71 %x STRING
72 %x BRACKET
73 %x BRACKETEND
74 %x COMMENT
76 MAKEVAR \$\([A-Za-z0-9_]*\)
77 UNQUOTED ([^ \0\t\r\n\(\)#\\\"[=]|\\[^\0\n])
78 LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t[=])*\"
82 <INITIAL,COMMENT>\n {
83   lexer->token.type = cmListFileLexer_Token_Newline;
84   cmListFileLexerSetToken(lexer, yytext, yyleng);
85   ++lexer->line;
86   lexer->column = 1;
87   BEGIN(INITIAL);
88   return 1;
91 #?\[=*\[\n? {
92   const char* bracket = yytext;
93   lexer->comment = yytext[0] == '#';
94   if (lexer->comment) {
95     lexer->token.type = cmListFileLexer_Token_CommentBracket;
96     bracket += 1;
97   } else {
98     lexer->token.type = cmListFileLexer_Token_ArgumentBracket;
99   }
100   cmListFileLexerSetToken(lexer, "", 0);
101   lexer->bracket = strchr(bracket+1, '[') - bracket;
102   if (yytext[yyleng-1] == '\n') {
103     ++lexer->line;
104     lexer->column = 1;
105   } else {
106     lexer->column += yyleng;
107   }
108   BEGIN(BRACKET);
111 # {
112   lexer->column += yyleng;
113   BEGIN(COMMENT);
116 <COMMENT>[^\0\n]* {
117   lexer->column += yyleng;
120 \( {
121   lexer->token.type = cmListFileLexer_Token_ParenLeft;
122   cmListFileLexerSetToken(lexer, yytext, yyleng);
123   lexer->column += yyleng;
124   return 1;
127 \) {
128   lexer->token.type = cmListFileLexer_Token_ParenRight;
129   cmListFileLexerSetToken(lexer, yytext, yyleng);
130   lexer->column += yyleng;
131   return 1;
134 [A-Za-z_][A-Za-z0-9_]* {
135   lexer->token.type = cmListFileLexer_Token_Identifier;
136   cmListFileLexerSetToken(lexer, yytext, yyleng);
137   lexer->column += yyleng;
138   return 1;
141 <BRACKET>\]=* {
142   /* Handle ]]====]=======]*/
143   cmListFileLexerAppend(lexer, yytext, yyleng);
144   lexer->column += yyleng;
145   if (yyleng == lexer->bracket) {
146     BEGIN(BRACKETEND);
147   }
150 <BRACKETEND>\] {
151   lexer->column += yyleng;
152   /* Erase the partial bracket from the token.  */
153   lexer->token.length -= lexer->bracket;
154   lexer->token.text[lexer->token.length] = 0;
155   BEGIN(INITIAL);
156   return 1;
159 <BRACKET>([^]\0\n])+ {
160   cmListFileLexerAppend(lexer, yytext, yyleng);
161   lexer->column += yyleng;
164 <BRACKET,BRACKETEND>\n {
165   cmListFileLexerAppend(lexer, yytext, yyleng);
166   ++lexer->line;
167   lexer->column = 1;
168   BEGIN(BRACKET);
171 <BRACKET,BRACKETEND>[^\0\n] {
172   cmListFileLexerAppend(lexer, yytext, yyleng);
173   lexer->column += yyleng;
174   BEGIN(BRACKET);
177 <BRACKET,BRACKETEND><<EOF>> {
178   lexer->token.type = cmListFileLexer_Token_BadBracket;
179   BEGIN(INITIAL);
180   return 1;
183 ({UNQUOTED}|=|\[=*{UNQUOTED})({UNQUOTED}|[[=])* {
184   lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
185   cmListFileLexerSetToken(lexer, yytext, yyleng);
186   lexer->column += yyleng;
187   return 1;
190 ({MAKEVAR}|{UNQUOTED}|=|\[=*{LEGACY})({LEGACY}|[[=])* {
191   lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
192   cmListFileLexerSetToken(lexer, yytext, yyleng);
193   lexer->column += yyleng;
194   return 1;
197 \[ {
198   lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
199   cmListFileLexerSetToken(lexer, yytext, yyleng);
200   lexer->column += yyleng;
201   return 1;
204 \" {
205   lexer->token.type = cmListFileLexer_Token_ArgumentQuoted;
206   cmListFileLexerSetToken(lexer, "", 0);
207   lexer->column += yyleng;
208   BEGIN(STRING);
211 <STRING>([^\\\0\n\"]|\\[^\0\n])+ {
212   cmListFileLexerAppend(lexer, yytext, yyleng);
213   lexer->column += yyleng;
216 <STRING>\\\n {
217   /* Continuation: text is not part of string */
218   ++lexer->line;
219   lexer->column = 1;
222 <STRING>\n {
223   cmListFileLexerAppend(lexer, yytext, yyleng);
224   ++lexer->line;
225   lexer->column = 1;
228 <STRING>\" {
229   lexer->column += yyleng;
230   BEGIN(INITIAL);
231   return 1;
234 <STRING>[^\0\n] {
235   cmListFileLexerAppend(lexer, yytext, yyleng);
236   lexer->column += yyleng;
239 <STRING><<EOF>> {
240   lexer->token.type = cmListFileLexer_Token_BadString;
241   BEGIN(INITIAL);
242   return 1;
245 [ \t\r]+ {
246   lexer->token.type = cmListFileLexer_Token_Space;
247   cmListFileLexerSetToken(lexer, yytext, yyleng);
248   lexer->column += yyleng;
249   return 1;
252 . {
253   lexer->token.type = cmListFileLexer_Token_BadCharacter;
254   cmListFileLexerSetToken(lexer, yytext, yyleng);
255   lexer->column += yyleng;
256   return 1;
259 <<EOF>> {
260   lexer->token.type = cmListFileLexer_Token_None;
261   cmListFileLexerSetToken(lexer, 0, 0);
262   return 0;
267 /*--------------------------------------------------------------------------*/
268 static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
269                                     int length)
271   /* Set the token line and column number.  */
272   lexer->token.line = lexer->line;
273   lexer->token.column = lexer->column;
275   /* Use the same buffer if possible.  */
276   if (lexer->token.text) {
277     if (text && length < lexer->size) {
278       strcpy(lexer->token.text, text);
279       lexer->token.length = length;
280       return;
281     }
282     free(lexer->token.text);
283     lexer->token.text = 0;
284     lexer->size = 0;
285   }
287   /* Need to extend the buffer.  */
288   if (text) {
289     lexer->token.text = strdup(text);
290     lexer->token.length = length;
291     lexer->size = length + 1;
292   } else {
293     lexer->token.length = 0;
294   }
297 /*--------------------------------------------------------------------------*/
298 static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
299                                   int length)
301   char* temp;
302   int newSize;
304   /* If the appended text will fit in the buffer, do not reallocate.  */
305   newSize = lexer->token.length + length + 1;
306   if (lexer->token.text && newSize <= lexer->size) {
307     strcpy(lexer->token.text + lexer->token.length, text);
308     lexer->token.length += length;
309     return;
310   }
312   /* We need to extend the buffer.  */
313   temp = malloc(newSize);
314   if (lexer->token.text) {
315     memcpy(temp, lexer->token.text, lexer->token.length);
316     free(lexer->token.text);
317   }
318   memcpy(temp + lexer->token.length, text, length);
319   temp[lexer->token.length + length] = 0;
320   lexer->token.text = temp;
321   lexer->token.length += length;
322   lexer->size = newSize;
325 /*--------------------------------------------------------------------------*/
326 static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
327                                 size_t bufferSize)
329   if (lexer) {
330     if (lexer->file) {
331       /* Convert CRLF -> LF explicitly.  The C FILE "t"ext mode
332          does not convert newlines on all platforms.  Move any
333          trailing CR to the start of the buffer for the next read. */
334       size_t cr = lexer->cr;
335       size_t n;
336       buffer[0] = '\r';
337       n = fread(buffer + cr, 1, bufferSize - cr, lexer->file);
338       if (n) {
339         char* o = buffer;
340         const char* i = buffer;
341         const char* e;
342         n += cr;
343         cr = (buffer[n - 1] == '\r') ? 1 : 0;
344         e = buffer + n - cr;
345         while (i != e) {
346           if (i[0] == '\r' && i[1] == '\n') {
347             ++i;
348           }
349           *o++ = *i++;
350         }
351         n = o - buffer;
352       } else {
353         n = cr;
354         cr = 0;
355       }
356       lexer->cr = cr;
357       return n;
358     } else if (lexer->string_left) {
359       int length = lexer->string_left;
360       if ((int)bufferSize < length) {
361         length = (int)bufferSize;
362       }
363       memcpy(buffer, lexer->string_position, length);
364       lexer->string_position += length;
365       lexer->string_left -= length;
366       return length;
367     }
368   }
369   return 0;
372 /*--------------------------------------------------------------------------*/
373 static void cmListFileLexerInit(cmListFileLexer* lexer)
375   if (lexer->file || lexer->string_buffer) {
376     cmListFileLexer_yylex_init(&lexer->scanner);
377     cmListFileLexer_yyset_extra(lexer, lexer->scanner);
378   }
381 /*--------------------------------------------------------------------------*/
382 static void cmListFileLexerDestroy(cmListFileLexer* lexer)
384   cmListFileLexerSetToken(lexer, 0, 0);
385   if (lexer->file || lexer->string_buffer) {
386     cmListFileLexer_yylex_destroy(lexer->scanner);
387     if (lexer->file) {
388       fclose(lexer->file);
389       lexer->file = 0;
390     }
391     if (lexer->string_buffer) {
392       free(lexer->string_buffer);
393       lexer->string_buffer = 0;
394       lexer->string_left = 0;
395       lexer->string_position = 0;
396     }
397   }
400 /*--------------------------------------------------------------------------*/
401 cmListFileLexer* cmListFileLexer_New(void)
403   cmListFileLexer* lexer = (cmListFileLexer*)malloc(sizeof(cmListFileLexer));
404   if (!lexer) {
405     return 0;
406   }
407   memset(lexer, 0, sizeof(*lexer));
408   lexer->line = 1;
409   lexer->column = 1;
410   return lexer;
413 /*--------------------------------------------------------------------------*/
414 void cmListFileLexer_Delete(cmListFileLexer* lexer)
416   cmListFileLexer_SetFileName(lexer, 0, 0);
417   free(lexer);
420 /*--------------------------------------------------------------------------*/
421 static cmListFileLexer_BOM cmListFileLexer_ReadBOM(FILE* f)
423   unsigned char b[2];
424   if (fread(b, 1, 2, f) == 2) {
425     if (b[0] == 0xEF && b[1] == 0xBB) {
426       if (fread(b, 1, 1, f) == 1 && b[0] == 0xBF) {
427         return cmListFileLexer_BOM_UTF8;
428       }
429     } else if (b[0] == 0xFE && b[1] == 0xFF) {
430       /* UTF-16 BE */
431       return cmListFileLexer_BOM_UTF16BE;
432     } else if (b[0] == 0 && b[1] == 0) {
433       if (fread(b, 1, 2, f) == 2 && b[0] == 0xFE && b[1] == 0xFF) {
434         return cmListFileLexer_BOM_UTF32BE;
435       }
436     } else if (b[0] == 0xFF && b[1] == 0xFE) {
437       fpos_t p;
438       fgetpos(f, &p);
439       if (fread(b, 1, 2, f) == 2 && b[0] == 0 && b[1] == 0) {
440         return cmListFileLexer_BOM_UTF32LE;
441       }
442       if (fsetpos(f, &p) != 0) {
443         return cmListFileLexer_BOM_Broken;
444       }
445       return cmListFileLexer_BOM_UTF16LE;
446     }
447   }
448   if (fseek(f, 0, SEEK_SET) != 0) {
449     return cmListFileLexer_BOM_Broken;
450   }
451   return cmListFileLexer_BOM_None;
454 /*--------------------------------------------------------------------------*/
455 int cmListFileLexer_SetFileName(cmListFileLexer* lexer, const char* name,
456                                 cmListFileLexer_BOM* bom)
458   int result = 1;
459   cmListFileLexerDestroy(lexer);
460   if (name) {
461 #ifdef _WIN32
462     wchar_t* wname = cmsysEncoding_DupToWide(name);
463     lexer->file = _wfopen(wname, L"rb");
464     free(wname);
465 #else
466     lexer->file = fopen(name, "rb");
467 #endif
468     if (lexer->file) {
469       if (bom) {
470         *bom = cmListFileLexer_ReadBOM(lexer->file);
471       }
472     } else {
473       result = 0;
474     }
475   }
476   cmListFileLexerInit(lexer);
477   return result;
480 /*--------------------------------------------------------------------------*/
481 int cmListFileLexer_SetString(cmListFileLexer* lexer, const char* text)
483   int result = 1;
484   cmListFileLexerDestroy(lexer);
485   if (text) {
486     int length = (int)strlen(text);
487     lexer->string_buffer = (char*)malloc(length + 1);
488     if (lexer->string_buffer) {
489       strcpy(lexer->string_buffer, text);
490       lexer->string_position = lexer->string_buffer;
491       lexer->string_left = length;
492     } else {
493       result = 0;
494     }
495   }
496   cmListFileLexerInit(lexer);
497   return result;
500 /*--------------------------------------------------------------------------*/
501 cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer* lexer)
503   if (!lexer->file && !lexer->string_buffer) {
504     return 0;
505   }
506   if (cmListFileLexer_yylex(lexer->scanner, lexer)) {
507     return &lexer->token;
508   } else {
509     cmListFileLexer_SetFileName(lexer, 0, 0);
510     return 0;
511   }
514 /*--------------------------------------------------------------------------*/
515 long cmListFileLexer_GetCurrentLine(cmListFileLexer* lexer)
517   return lexer->line;
520 /*--------------------------------------------------------------------------*/
521 long cmListFileLexer_GetCurrentColumn(cmListFileLexer* lexer)
523   return lexer->column;
526 /*--------------------------------------------------------------------------*/
527 const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer,
528                                             cmListFileLexer_Type type)
530   (void)lexer;
531   switch (type) {
532     case cmListFileLexer_Token_None:
533       return "nothing";
534     case cmListFileLexer_Token_Space:
535       return "space";
536     case cmListFileLexer_Token_Newline:
537       return "newline";
538     case cmListFileLexer_Token_Identifier:
539       return "identifier";
540     case cmListFileLexer_Token_ParenLeft:
541       return "left paren";
542     case cmListFileLexer_Token_ParenRight:
543       return "right paren";
544     case cmListFileLexer_Token_ArgumentUnquoted:
545       return "unquoted argument";
546     case cmListFileLexer_Token_ArgumentQuoted:
547       return "quoted argument";
548     case cmListFileLexer_Token_ArgumentBracket:
549       return "bracket argument";
550     case cmListFileLexer_Token_CommentBracket:
551       return "bracket comment";
552     case cmListFileLexer_Token_BadCharacter:
553       return "bad character";
554     case cmListFileLexer_Token_BadBracket:
555       return "unterminated bracket";
556     case cmListFileLexer_Token_BadString:
557       return "unterminated string";
558   }
559   return "unknown token";