2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
27 ** MODULE DESCRIPTION:
29 ** This module scans one line of Larch C Interface Language (LCL) input at
32 ** The input is source text, line at a time. The output is a sequence
33 ** of tokens, reported by call-out LSLScanFreshToken.
35 ** This organization allows implementation of line-at-a-time incremental
36 ** scanning. The incremental mechanism is in the driving module scan.c.
38 ** The main loop of the scanner keys on the leading character.
39 ** Within the loop are actions which collect the rest of the
40 ** token starting with the character. Various careful hacks
41 ** show up to disambiguate tokens that break the general pattern
42 ** (Examples, \/ and /\). White space is passed and the loop
43 ** goes once again without calling LSLScanFreshToken ().
44 ** The line ends with a null.
48 ** JPW, GAF, Yang Meng Tan
52 # include "splintMacros.nf"
54 # include "lslscanline.h"
56 # include "lclscanline.h"
57 # include "lcltokentable.h"
58 # include "lclsyntable.h"
59 # include "llgrammar.h"
61 /*@constant int CHARSIZE;@*/
62 # define CHARSIZE 256 /* on an 8-bit machine */
65 # define LCLMOVECHAR() \
66 do { *bufPtr++ = currentChar; currentChar = *currentLine++; \
67 colNumber++; } while (FALSE)
70 # define LOOKAHEADCHAR() (*currentLine)
73 # define LOOKAHEADTWICECHAR() (*(currentLine + 1))
75 /*@constant static int MAXCHAR;@*/
76 # define MAXCHAR 512 /* storage for a lexeme */
79 ** Printname for the TokenCode NOTTOKEN (also 1st one reserved)
80 ** Printname for the TokenCode BADTOKEN (also last one reserved)
83 /*@constant static observer char *FIRSTRESERVEDNAME;@*/
84 # define FIRSTRESERVEDNAME "?"
87 ** The scanner establishes lexical boundaries by first switching
88 ** on the leading character of the pending lexeme.
93 STARTCNUM
, /* First character of a C number. */
94 STARTCNUMDOT
, /* "." only starts a C number if digit follows*/
95 STARTCSTR
, /* First character of a C string. */
96 STARTCCHAR
, /* First character of a C character. */
97 STARTWIDE
, /* slash L starts both string and character. */
98 STARTSLASH
, /* "/" starts caret, comment comment, operator */
99 STARTOTHER
/* Everything else. */
102 static void ScanCComment (void);
103 static void ScanEscape (void);
104 static void ScanCString (void);
105 static void ScanCChar (void);
106 static void ScanCNumber (void);
107 static void LocalUserError (/*@temp@*/ char *);
110 ** Array to store character class defintions and record end-of-comment
114 static charClassData LCLcharClass
[LASTCHAR
+ 1];
117 ** Data shared between routines LCLScanLine, ScanCString, ScanCChar,
118 ** ScanCNumber. LCLScanLine was getting too big for one routine and
119 ** passing this data was rather cumbersome. Making this data global seemed
120 ** to be the simpliest solution.
123 /* evs - sounds bogus to me! */
125 static int colNumber
;
127 static char *currentLine
;
128 static char currentChar
;
129 static ltokenCode tokenCode
;
130 static lsymbol tokenSym
;
133 static bool inComment
;
134 static /*@only@*/ ltoken commentTok
;
135 static ltokenCode prevTokenCode
; /* to disambiguate ' */
137 static StartCharType startClass
[CHARSIZE
] =
139 STARTOTHER
, /* ^@ 00x */
140 STARTOTHER
, /* ^a 01x */
141 STARTOTHER
, /* ^b 02x */
142 STARTOTHER
, /* ^c 03x */
143 STARTOTHER
, /* ^d 04x */
144 STARTOTHER
, /* ^e 05x */
145 STARTOTHER
, /* ^f 06x */
146 STARTOTHER
, /* ^g BELL 07x */
148 STARTOTHER
, /* ^h BACKSPACE 08x */
149 STARTOTHER
, /* ^i TAB 09x */
150 STARTOTHER
, /* ^j NEWLINE 0Ax */
151 STARTOTHER
, /* ^k 0Bx */
152 STARTOTHER
, /* ^l FORMFEED 0Cx */
153 STARTOTHER
, /* ^m RETURN 0Dx */
154 STARTOTHER
, /* ^n 0Ex */
155 STARTOTHER
, /* ^o 0Fx */
157 STARTOTHER
, /* ^p 10x */
158 STARTOTHER
, /* ^q 11x */
159 STARTOTHER
, /* ^r 12x */
160 STARTOTHER
, /* ^s 13x */
161 STARTOTHER
, /* ^t 14x */
162 STARTOTHER
, /* ^u 15x */
163 STARTOTHER
, /* ^v 16x */
164 STARTOTHER
, /* ^w 17x */
166 STARTOTHER
, /* ^x 18x */
167 STARTOTHER
, /* ^y 19x */
168 STARTOTHER
, /* ^z 1Ax */
169 STARTOTHER
, /* ^[ ESC 1Bx */
170 STARTOTHER
, /* ^slash 1Cx */
171 STARTOTHER
, /* ^] 1Dx */
172 STARTOTHER
, /* ^^ 1Ex */
173 STARTOTHER
, /* ^_ 1Fx */
175 STARTOTHER
, /* BLANK 20x */
176 STARTOTHER
, /* ! 21x */
177 STARTCSTR
, /* " 22x */
178 STARTOTHER
, /* # 23x */
179 STARTOTHER
, /* $ (may be changed in reset) 24x */
180 STARTOTHER
, /* % 25x */
181 STARTOTHER
, /* & 26x */
182 STARTCCHAR
, /* ' 27x */
184 STARTOTHER
, /* ( 28x */
185 STARTOTHER
, /* ) 29x */
186 STARTOTHER
, /* * 2Ax */
187 STARTOTHER
, /* + 2Bx */
188 STARTOTHER
, /* , 2Cx */
189 STARTOTHER
, /* - 2Dx */
190 STARTCNUMDOT
, /* . 2Ex */
191 STARTSLASH
, /* / 2Fx */
193 STARTCNUM
, /* 0 30x */
194 STARTCNUM
, /* 1 31x */
195 STARTCNUM
, /* 2 32x */
196 STARTCNUM
, /* 3 33x */
197 STARTCNUM
, /* 4 34x */
198 STARTCNUM
, /* 5 35x */
199 STARTCNUM
, /* 6 36x */
200 STARTCNUM
, /* 7 37x */
202 STARTCNUM
, /* 8 38x */
203 STARTCNUM
, /* 9 39x */
204 STARTOTHER
, /* : 3Ax */
205 STARTOTHER
, /* ; 3Bx */
206 STARTOTHER
, /* < 3Cx */
207 STARTOTHER
, /* = 3Dx */
208 STARTOTHER
, /* > 3Ex */
209 STARTOTHER
, /* ? 3Fx */
211 STARTOTHER
, /* @ 40x */
212 STARTOTHER
, /* A 41x */
213 STARTOTHER
, /* B 42x */
214 STARTOTHER
, /* C 43x */
215 STARTOTHER
, /* D 44x */
216 STARTOTHER
, /* E 45x */
217 STARTOTHER
, /* F 46x */
218 STARTOTHER
, /* G 47x */
220 STARTOTHER
, /* H 48x */
221 STARTOTHER
, /* I 49x */
222 STARTOTHER
, /* J 4Ax */
223 STARTOTHER
, /* K 4Bx */
224 STARTOTHER
, /* L 4Cx */
225 STARTOTHER
, /* M 4Dx */
226 STARTOTHER
, /* N 4Ex */
227 STARTOTHER
, /* O 4Fx */
229 STARTOTHER
, /* P 50x */
230 STARTOTHER
, /* Q 51x */
231 STARTOTHER
, /* R 52x */
232 STARTOTHER
, /* S 53x */
233 STARTOTHER
, /* T 54x */
234 STARTOTHER
, /* U 55x */
235 STARTOTHER
, /* V 56x */
236 STARTOTHER
, /* W 57x */
238 STARTOTHER
, /* X 58x */
239 STARTOTHER
, /* Y 59x */
240 STARTOTHER
, /* Z 5Ax */
241 STARTOTHER
, /* [ 5Bx */
242 STARTWIDE
, /* slash 5Cx */
243 STARTOTHER
, /* ] 5Dx */
244 STARTOTHER
, /* ^ 5Ex */
245 STARTOTHER
, /* _ 5Fx */
247 STARTOTHER
, /* ` 60x */
248 STARTOTHER
, /* a 61x */
249 STARTOTHER
, /* b 62x */
250 STARTOTHER
, /* c 63x */
251 STARTOTHER
, /* d 64x */
252 STARTOTHER
, /* e 65x */
253 STARTOTHER
, /* f 66x */
254 STARTOTHER
, /* g 67x */
256 STARTOTHER
, /* h 68x */
257 STARTOTHER
, /* i 69x */
258 STARTOTHER
, /* j 6Ax */
259 STARTOTHER
, /* k 6Bx */
260 STARTOTHER
, /* l 6Cx */
261 STARTOTHER
, /* m 6Dx */
262 STARTOTHER
, /* n 6Ex */
263 STARTOTHER
, /* o 6Fx */
265 STARTOTHER
, /* p 70x */
266 STARTOTHER
, /* q 71x */
267 STARTOTHER
, /* r 72x */
268 STARTOTHER
, /* s 73x */
269 STARTOTHER
, /* t 74x */
270 STARTOTHER
, /* u 75x */
271 STARTOTHER
, /* v 76x */
272 STARTOTHER
, /* w 77x */
274 STARTOTHER
, /* x 78x */
275 STARTOTHER
, /* y 79x */
276 STARTOTHER
, /* z 7Ax */
277 STARTOTHER
, /* { 7Dx */
278 STARTOTHER
, /* | 7Cx */
279 STARTOTHER
, /* } 7Dx */
280 STARTOTHER
, /* ~ 7Ex */
282 STARTOTHER
/* RUBOUT 7Fx */
286 ** Given a character code, its status as part of an decimal escape sequence
287 ** can be derived from this table. Digits 0-9 allowed.
290 static bool isDigit
[CHARSIZE
] =
292 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
293 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
294 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
295 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
,
296 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
297 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
298 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
299 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
300 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
304 * Given a character code, its status as part of an octal escape sequence
305 * can be derived from this table. Digits 0-7 allowed.
308 static bool isOigit
[CHARSIZE
] =
310 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
311 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
312 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
313 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
314 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
315 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
316 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
317 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
321 * Given a character code, its status as part of a hex escape sequence
322 * can be derived from this table. Digits, a-f, A-F allowed.
325 static bool isXigit
[CHARSIZE
] =
327 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
328 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
329 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
331 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
332 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
,
333 TRUE
, TRUE
, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
335 FALSE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
336 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
337 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
339 FALSE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
340 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
341 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
346 * Given a character code, its status as part of a C string
347 * can be derived from this table. Everything but quotes and newline
351 static bool isStrChar
[CHARSIZE
] =
353 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, FALSE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
,
354 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
,
355 TRUE
, TRUE
, FALSE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
,
356 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
,
357 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
,
358 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, FALSE
, TRUE
, TRUE
, TRUE
,
359 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
,
360 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
364 * Given a character code, its status as part of a C Character
365 * can be derived from this table. Everything but quotes and newline
369 static bool isCharChar
[CHARSIZE
] =
371 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, FALSE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
,
372 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
,
373 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, FALSE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
,
374 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
,
375 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
,
376 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, FALSE
, TRUE
, TRUE
, TRUE
,
377 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
,
378 TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
, TRUE
382 ** Given a character code, its status as part of a string or character
383 ** simple escape sequence ('slash'', 'slash"', 'slash?', 'slashslash',
384 ** 'slasha', 'slashb', 'slashf', 'slashn', 'slasht', and 'slashv')
385 ** can be derived from this table. ''', '"', '?', 'slash', 'a',
386 ** 'b', 'f', 'n', 't', and 'v' are allowed.
389 static bool isSimpleEscape
[CHARSIZE
] =
391 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
392 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
393 FALSE
, FALSE
, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
394 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, TRUE
,
395 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
396 FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, TRUE
, FALSE
, FALSE
, FALSE
,
397 FALSE
, TRUE
, TRUE
, FALSE
, FALSE
, FALSE
, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, TRUE
, FALSE
,
398 FALSE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
401 static bool reportEOL
;
402 static bool reportComments
;
404 static char tokenBuffer
[MAXCHAR
];
406 static const charClassData charClassDef
[] =
408 /* Control characters */
410 { SINGLECHAR
, FALSE
}, /* 0 NULL */
411 { SINGLECHAR
, FALSE
}, /* 1 CTRL-A */
412 { SINGLECHAR
, FALSE
}, /* 2 CTRL-B */
413 { SINGLECHAR
, FALSE
}, /* 3 CTRL-C */
414 { SINGLECHAR
, FALSE
}, /* 4 CTRL-D */
415 { SINGLECHAR
, FALSE
}, /* 5 CTRL-E */
416 { SINGLECHAR
, FALSE
}, /* 6 CTRL-F */
417 { SINGLECHAR
, FALSE
}, /* 7 CTRL-G */
418 { SINGLECHAR
, FALSE
}, /* 8 CTRL-H */
420 /* defined formatting characters */
421 { WHITECHAR
, FALSE
}, /* 9 CTRL-I TAB */
422 { CHC_NULL
, TRUE
}, /* 10 CTRL-J EOL */
424 /* more control characters */
425 { SINGLECHAR
, FALSE
}, /* 11 CTRL-K */
426 { WHITECHAR
, FALSE
}, /* 12 CTRL-L */
427 { SINGLECHAR
, FALSE
}, /* 13 CTRL-M */
428 { SINGLECHAR
, FALSE
}, /* 14 CTRL-N */
429 { SINGLECHAR
, FALSE
}, /* 15 CTRL-O */
430 { SINGLECHAR
, FALSE
}, /* 16 CTRL-P */
431 { SINGLECHAR
, FALSE
}, /* 17 CTRL-Q */
432 { SINGLECHAR
, FALSE
}, /* 18 CTRL-R */
433 { SINGLECHAR
, FALSE
}, /* 19 CTRL-S */
434 { SINGLECHAR
, FALSE
}, /* 20 CTRL-T */
435 { SINGLECHAR
, FALSE
}, /* 21 CTRL-U */
436 { SINGLECHAR
, FALSE
}, /* 22 CTRL-V */
437 { SINGLECHAR
, FALSE
}, /* 23 CTRL-W */
438 { SINGLECHAR
, FALSE
}, /* 24 CTRL-X */
439 { SINGLECHAR
, FALSE
}, /* 25 CTRL-Y */
440 { SINGLECHAR
, FALSE
}, /* 26 CTRL-Z */
441 { SINGLECHAR
, FALSE
}, /* 27 CTRL-[ ESC */
442 { SINGLECHAR
, FALSE
}, /* 28 CTRL-slash FS */
443 { SINGLECHAR
, FALSE
}, /* 29 CTRL-] GS */
444 { SINGLECHAR
, FALSE
}, /* 30 CTRL-^ RS */
445 { SINGLECHAR
, FALSE
}, /* 31 CTRL-_ US */
447 /* Special printing characters */
448 { WHITECHAR
, FALSE
}, /* 32 space */
449 { SINGLECHAR
, FALSE
}, /* 33 ! */
450 { SINGLECHAR
, FALSE
}, /* 34 " */
451 { SINGLECHAR
, FALSE
}, /* 35 # */
452 { SINGLECHAR
, FALSE
}, /* 36 $ */
453 { SINGLECHAR
, FALSE
}, /* 37 % */
454 { SINGLECHAR
, FALSE
}, /* 38 & */
455 { SINGLECHAR
, FALSE
}, /* 39 ' */
457 /* Reserved characters */
458 { PERMCHAR
, FALSE
}, /* 40 ( */
459 { PERMCHAR
, FALSE
}, /* 41 ) */
460 { PERMCHAR
, FALSE
}, /* 42 * */
461 { OPCHAR
, FALSE
}, /* 43 + */
462 { PERMCHAR
, FALSE
}, /* 44 , */
463 { OPCHAR
, FALSE
}, /* 45 - */
464 { OPCHAR
, FALSE
}, /* 46 . */
465 { OPCHAR
, FALSE
}, /* 47 / */
468 { IDCHAR
, FALSE
}, /* 48 0 */
469 { IDCHAR
, FALSE
}, /* 49 1 */
470 { IDCHAR
, FALSE
}, /* 50 2 */
471 { IDCHAR
, FALSE
}, /* 51 3 */
472 { IDCHAR
, FALSE
}, /* 52 4 */
473 { IDCHAR
, FALSE
}, /* 53 5 */
474 { IDCHAR
, FALSE
}, /* 54 6 */
475 { IDCHAR
, FALSE
}, /* 55 7 */
476 { IDCHAR
, FALSE
}, /* 56 8 */
477 { IDCHAR
, FALSE
}, /* 57 9 */
479 /* More reserved and special printing characters */
480 { PERMCHAR
, FALSE
}, /* 58 : */
481 { PERMCHAR
, FALSE
}, /* 59; */
482 { OPCHAR
, FALSE
}, /* 60 < */
483 { OPCHAR
, FALSE
}, /* 61 = */
484 { OPCHAR
, FALSE
}, /* 62 > */
485 { SINGLECHAR
, FALSE
}, /* 63 ? */
486 { SINGLECHAR
, FALSE
}, /* 64 @ */
488 /* Uppercase Alphabetics */
489 { IDCHAR
, FALSE
}, /* 65 A */
490 { IDCHAR
, FALSE
}, /* 66 B */
491 { IDCHAR
, FALSE
}, /* 67 C */
492 { IDCHAR
, FALSE
}, /* 68 D */
493 { IDCHAR
, FALSE
}, /* 69 E */
494 { IDCHAR
, FALSE
}, /* 70 F */
495 { IDCHAR
, FALSE
}, /* 71 G */
496 { IDCHAR
, FALSE
}, /* 72 H */
497 { IDCHAR
, FALSE
}, /* 73 I */
498 { IDCHAR
, FALSE
}, /* 74 J */
499 { IDCHAR
, FALSE
}, /* 75 K */
500 { IDCHAR
, FALSE
}, /* 76 L */
501 { IDCHAR
, FALSE
}, /* 77 M */
502 { IDCHAR
, FALSE
}, /* 78 N */
503 { IDCHAR
, FALSE
}, /* 79 O */
504 { IDCHAR
, FALSE
}, /* 80 P */
505 { IDCHAR
, FALSE
}, /* 81 Q */
506 { IDCHAR
, FALSE
}, /* 82 R */
507 { IDCHAR
, FALSE
}, /* 83 S */
508 { IDCHAR
, FALSE
}, /* 84 T */
509 { IDCHAR
, FALSE
}, /* 85 U */
510 { IDCHAR
, FALSE
}, /* 86 V */
511 { IDCHAR
, FALSE
}, /* 87 W */
512 { IDCHAR
, FALSE
}, /* 88 X */
513 { IDCHAR
, FALSE
}, /* 89 Y */
514 { IDCHAR
, FALSE
}, /* 90 Z */
516 /* Still more reserved and special printing characters */
517 { PERMCHAR
, FALSE
}, /* 91 [ */
518 { CHC_EXTENSION
, FALSE
}, /* 92 slash */
519 { PERMCHAR
, FALSE
}, /* 93 ] */
520 { SINGLECHAR
, FALSE
}, /* 94 ^ */
521 { IDCHAR
, FALSE
}, /* 95 _ */
522 { SINGLECHAR
, FALSE
}, /* 96 ` */
524 /* Lowercase alphabetics */
525 { IDCHAR
, FALSE
}, /* 97 a */
526 { IDCHAR
, FALSE
}, /* 98 b */
527 { IDCHAR
, FALSE
}, /* 99 c */
528 { IDCHAR
, FALSE
}, /* 100 d */
529 { IDCHAR
, FALSE
}, /* 101 e */
530 { IDCHAR
, FALSE
}, /* 102 f */
531 { IDCHAR
, FALSE
}, /* 103 g */
532 { IDCHAR
, FALSE
}, /* 104 h */
533 { IDCHAR
, FALSE
}, /* 105 i */
534 { IDCHAR
, FALSE
}, /* 106 j */
535 { IDCHAR
, FALSE
}, /* 107 k */
536 { IDCHAR
, FALSE
}, /* 108 l */
537 { IDCHAR
, FALSE
}, /* 109 m */
538 { IDCHAR
, FALSE
}, /* 110 n */
539 { IDCHAR
, FALSE
}, /* 111 o */
540 { IDCHAR
, FALSE
}, /* 112 p */
541 { IDCHAR
, FALSE
}, /* 113 q */
542 { IDCHAR
, FALSE
}, /* 114 r */
543 { IDCHAR
, FALSE
}, /* 115 s */
544 { IDCHAR
, FALSE
}, /* 116 t */
545 { IDCHAR
, FALSE
}, /* 117 u */
546 { IDCHAR
, FALSE
}, /* 118 v */
547 { IDCHAR
, FALSE
}, /* 119 w */
548 { IDCHAR
, FALSE
}, /* 120 x */
549 { IDCHAR
, FALSE
}, /* 121 y */
550 { IDCHAR
, FALSE
}, /* 122 z */
552 { SINGLECHAR
, FALSE
}, /* 123 { */
553 { SINGLECHAR
, FALSE
}, /* 124 | */
554 { SINGLECHAR
, FALSE
}, /* 125 } */
555 { SINGLECHAR
, FALSE
}, /* 126 ~ */
556 { SINGLECHAR
, FALSE
}, /* 127 DEL */
558 /* MCS - unused in English */
559 { SINGLECHAR
, FALSE
}, /* 128 */
560 { SINGLECHAR
, FALSE
}, /* 129 */
561 { SINGLECHAR
, FALSE
}, /* 130 */
562 { SINGLECHAR
, FALSE
}, /* 131 */
563 { SINGLECHAR
, FALSE
}, /* 132 */
564 { SINGLECHAR
, FALSE
}, /* 133 */
565 { SINGLECHAR
, FALSE
}, /* 134 */
566 { SINGLECHAR
, FALSE
}, /* 135 */
567 { SINGLECHAR
, FALSE
}, /* 136 */
568 { SINGLECHAR
, FALSE
}, /* 137 */
569 { SINGLECHAR
, FALSE
}, /* 138 */
570 { SINGLECHAR
, FALSE
}, /* 139 */
571 { SINGLECHAR
, FALSE
}, /* 140 */
572 { SINGLECHAR
, FALSE
}, /* 141 */
573 { SINGLECHAR
, FALSE
}, /* 142 */
574 { SINGLECHAR
, FALSE
}, /* 143 */
575 { SINGLECHAR
, FALSE
}, /* 144 */
576 { SINGLECHAR
, FALSE
}, /* 145 */
577 { SINGLECHAR
, FALSE
}, /* 146 */
578 { SINGLECHAR
, FALSE
}, /* 147 */
579 { SINGLECHAR
, FALSE
}, /* 148 */
580 { SINGLECHAR
, FALSE
}, /* 149 */
581 { SINGLECHAR
, FALSE
}, /* 150 */
582 { SINGLECHAR
, FALSE
}, /* 151 */
583 { SINGLECHAR
, FALSE
}, /* 152 */
584 { SINGLECHAR
, FALSE
}, /* 153 */
585 { SINGLECHAR
, FALSE
}, /* 154 */
586 { SINGLECHAR
, FALSE
}, /* 155 */
587 { SINGLECHAR
, FALSE
}, /* 156 */
588 { SINGLECHAR
, FALSE
}, /* 157 */
589 { SINGLECHAR
, FALSE
}, /* 158 */
590 { SINGLECHAR
, FALSE
}, /* 159 */
591 { SINGLECHAR
, FALSE
}, /* 160 */
592 { SINGLECHAR
, FALSE
}, /* 161 */
593 { SINGLECHAR
, FALSE
}, /* 162 */
594 { SINGLECHAR
, FALSE
}, /* 163 */
595 { SINGLECHAR
, FALSE
}, /* 164 */
596 { SINGLECHAR
, FALSE
}, /* 165 */
597 { SINGLECHAR
, FALSE
}, /* 166 */
598 { SINGLECHAR
, FALSE
}, /* 167 */
599 { SINGLECHAR
, FALSE
}, /* 168 */
600 { SINGLECHAR
, FALSE
}, /* 169 */
601 { SINGLECHAR
, FALSE
}, /* 170 */
602 { SINGLECHAR
, FALSE
}, /* 171 */
603 { SINGLECHAR
, FALSE
}, /* 172 */
604 { SINGLECHAR
, FALSE
}, /* 173 */
605 { SINGLECHAR
, FALSE
}, /* 174 */
606 { SINGLECHAR
, FALSE
}, /* 175 */
607 { SINGLECHAR
, FALSE
}, /* 176 */
608 { SINGLECHAR
, FALSE
}, /* 177 */
609 { SINGLECHAR
, FALSE
}, /* 178 */
610 { SINGLECHAR
, FALSE
}, /* 179 */
611 { SINGLECHAR
, FALSE
}, /* 180 */
612 { SINGLECHAR
, FALSE
}, /* 181 */
613 { SINGLECHAR
, FALSE
}, /* 182 */
614 { SINGLECHAR
, FALSE
}, /* 183 */
615 { SINGLECHAR
, FALSE
}, /* 184 */
616 { SINGLECHAR
, FALSE
}, /* 185 */
617 { SINGLECHAR
, FALSE
}, /* 186 */
618 { SINGLECHAR
, FALSE
}, /* 187 */
619 { SINGLECHAR
, FALSE
}, /* 188 */
620 { SINGLECHAR
, FALSE
}, /* 189 */
621 { SINGLECHAR
, FALSE
}, /* 190 */
622 { SINGLECHAR
, FALSE
}, /* 191 */
623 { SINGLECHAR
, FALSE
}, /* 192 */
624 { SINGLECHAR
, FALSE
}, /* 193 */
625 { SINGLECHAR
, FALSE
}, /* 194 */
626 { SINGLECHAR
, FALSE
}, /* 195 */
627 { SINGLECHAR
, FALSE
}, /* 196 */
628 { SINGLECHAR
, FALSE
}, /* 197 */
629 { SINGLECHAR
, FALSE
}, /* 198 */
630 { SINGLECHAR
, FALSE
}, /* 199 */
631 { SINGLECHAR
, FALSE
}, /* 200 */
632 { SINGLECHAR
, FALSE
}, /* 201 */
633 { SINGLECHAR
, FALSE
}, /* 202 */
634 { SINGLECHAR
, FALSE
}, /* 203 */
635 { SINGLECHAR
, FALSE
}, /* 204 */
636 { SINGLECHAR
, FALSE
}, /* 205 */
637 { SINGLECHAR
, FALSE
}, /* 206 */
638 { SINGLECHAR
, FALSE
}, /* 207 */
639 { SINGLECHAR
, FALSE
}, /* 208 */
640 { SINGLECHAR
, FALSE
}, /* 209 */
641 { SINGLECHAR
, FALSE
}, /* 210 */
642 { SINGLECHAR
, FALSE
}, /* 211 */
643 { SINGLECHAR
, FALSE
}, /* 212 */
644 { SINGLECHAR
, FALSE
}, /* 213 */
645 { SINGLECHAR
, FALSE
}, /* 214 */
646 { SINGLECHAR
, FALSE
}, /* 215 */
647 { SINGLECHAR
, FALSE
}, /* 216 */
648 { SINGLECHAR
, FALSE
}, /* 217 */
649 { SINGLECHAR
, FALSE
}, /* 218 */
650 { SINGLECHAR
, FALSE
}, /* 219 */
651 { SINGLECHAR
, FALSE
}, /* 220 */
652 { SINGLECHAR
, FALSE
}, /* 221 */
653 { SINGLECHAR
, FALSE
}, /* 222 */
654 { SINGLECHAR
, FALSE
}, /* 223 */
655 { SINGLECHAR
, FALSE
}, /* 224 */
656 { SINGLECHAR
, FALSE
}, /* 225 */
657 { SINGLECHAR
, FALSE
}, /* 226 */
658 { SINGLECHAR
, FALSE
}, /* 227 */
659 { SINGLECHAR
, FALSE
}, /* 228 */
660 { SINGLECHAR
, FALSE
}, /* 229 */
661 { SINGLECHAR
, FALSE
}, /* 230 */
662 { SINGLECHAR
, FALSE
}, /* 231 */
663 { SINGLECHAR
, FALSE
}, /* 232 */
664 { SINGLECHAR
, FALSE
}, /* 233 */
665 { SINGLECHAR
, FALSE
}, /* 234 */
666 { SINGLECHAR
, FALSE
}, /* 235 */
667 { SINGLECHAR
, FALSE
}, /* 236 */
668 { SINGLECHAR
, FALSE
}, /* 237 */
669 { SINGLECHAR
, FALSE
}, /* 238 */
670 { SINGLECHAR
, FALSE
}, /* 239 */
671 { SINGLECHAR
, FALSE
}, /* 240 */
672 { SINGLECHAR
, FALSE
}, /* 241 */
673 { SINGLECHAR
, FALSE
}, /* 242 */
674 { SINGLECHAR
, FALSE
}, /* 243 */
675 { SINGLECHAR
, FALSE
}, /* 244 */
676 { SINGLECHAR
, FALSE
}, /* 245 */
677 { SINGLECHAR
, FALSE
}, /* 246 */
678 { SINGLECHAR
, FALSE
}, /* 247 */
679 { SINGLECHAR
, FALSE
}, /* 248 */
680 { SINGLECHAR
, FALSE
}, /* 249 */
681 { SINGLECHAR
, FALSE
}, /* 250 */
682 { SINGLECHAR
, FALSE
}, /* 251 */
683 { SINGLECHAR
, FALSE
}, /* 252 */
684 { SINGLECHAR
, FALSE
}, /* 253 */
685 { SINGLECHAR
, FALSE
}, /* 254 */
686 { SINGLECHAR
, FALSE
} /* 255 */
699 if (currentChar
== '/')
705 /*@switchbreak@*/ break;
717 if (isSimpleEscape
[(int)currentChar
])
719 LCLMOVECHAR (); /* discard simple escape character. */
721 else if (currentChar
== 'x')
723 LCLMOVECHAR (); /* discard 'x'. */
724 if (!isXigit
[(int)currentChar
])
726 LocalUserError ("at least one hex digit must follow '\\x'");
728 while (isXigit
[(int)currentChar
])
730 LCLMOVECHAR (); /* discard hex digits. */
733 else if (isOigit
[(int)currentChar
])
735 LCLMOVECHAR (); /* discard first hex digit. */
736 if (isOigit
[(int)currentChar
])
738 LCLMOVECHAR (); /* discard second hex digit. */
740 if (isOigit
[(int)currentChar
])
742 LCLMOVECHAR (); /* discard third hex digit. */
747 LocalUserError ("invalid escape sequence in a C string or character");
754 if (currentChar
== '\\' && LOOKAHEADCHAR () == 'L')
756 LCLMOVECHAR (); /* discard slash */
757 LCLMOVECHAR (); /* discard 'L'. */
760 if (currentChar
== '\"')
762 LCLMOVECHAR (); /* discard opening quote. */
764 while (currentChar
!= '\"')
766 if (isStrChar
[(int)currentChar
])
768 LCLMOVECHAR (); /* discard string character. */
770 else if (currentChar
== '\\')
772 LCLMOVECHAR (); /* discard slash */
775 else if (currentChar
== '\n')
777 LocalUserError ("Unterminated C string");
781 LocalUserError ("Invalid character in C string");
784 LCLMOVECHAR (); /* discard closing quote */
789 LocalUserError ("C string must start with '\"'");
793 *bufPtr
= '\0'; /* null terminate in buffer */
794 tokenSym
= lsymbol_fromChars (&tokenBuffer
[0]);
795 tokenCode
= LLT_LCSTRING
;
801 if (currentChar
== '\\' && LOOKAHEADCHAR () == 'L')
803 LCLMOVECHAR (); /* discard slash */
804 LCLMOVECHAR (); /* discard 'L'. */
807 if (currentChar
== '\'')
809 LCLMOVECHAR (); /* discard opening quote */
811 while (currentChar
!= '\'')
813 if (isCharChar
[(int)currentChar
])
815 LCLMOVECHAR (); /* discard string character. */
817 else if (currentChar
== '\\')
819 LCLMOVECHAR (); /* discard slash */
822 else if (currentChar
== '\n')
824 LocalUserError ("Unterminated C character constant");
828 LocalUserError ("Invalid character in C character");
831 LCLMOVECHAR (); /* discard closing quote */
836 LocalUserError ("Invalid C character");
840 *bufPtr
= '\0'; /* null terminate in buffer */
841 tokenSym
= lsymbol_fromChars (&tokenBuffer
[0]);
842 tokenCode
= LLT_CCHAR
;
848 tokenCode
= LLT_CINTEGER
;
854 tokenCode
= LLT_CFLOAT
;
855 if (!isDigit
[(int)currentChar
])
857 LocalUserError ("at least one digit must follow '.'");
859 while (isDigit
[(int)currentChar
])
863 if (currentChar
== 'e' || currentChar
== 'E')
865 LCLMOVECHAR (); /* discard 'e' or 'E'. */
866 if (currentChar
== '+' || currentChar
== '-')
870 if (!isDigit
[(int)currentChar
])
872 LocalUserError ("digit must follow exponent");
874 while (isDigit
[(int)currentChar
])
879 if (currentChar
== 'f' || currentChar
== 'l' ||
880 currentChar
== 'F' || currentChar
== 'L')
887 LCLMOVECHAR (); /* discard '0'. */
893 if (!isXigit
[(int)currentChar
])
895 LocalUserError ("hex digit must follow 'x' or 'X'");
897 while (isXigit
[(int)currentChar
])
901 /*@switchbreak@*/ break;
905 ** Could either be an octal number or a floating point
906 ** number. Scan decimal digits so don't run into
907 ** problems if turns out problems if it is an fp
908 ** number. Let converter/parser catch bad octal
909 ** numbers. e.g. 018 not caught by scanner.
912 while (isDigit
[(int)currentChar
])
919 LCLMOVECHAR (); /* discard '.'. */
920 tokenCode
= LLT_CFLOAT
;
921 while (isDigit
[(int)currentChar
])
925 if (currentChar
== 'e' || currentChar
== 'E')
927 LCLMOVECHAR (); /* discard 'e' or 'E'. */
928 if (currentChar
== '+' || currentChar
== '-')
932 if (!isDigit
[(int)currentChar
])
934 LocalUserError ("digit must follow exponent");
936 while (isDigit
[(int)currentChar
])
941 if (currentChar
== 'f' ||
942 currentChar
== 'l' ||
943 currentChar
== 'F' ||
948 /*@switchbreak@*/ break;
953 tokenCode
= LLT_CFLOAT
;
954 if (currentChar
== '+' || currentChar
== '-')
958 if (!isDigit
[(int)currentChar
])
960 LocalUserError ("digit must follow exponent");
962 while (isDigit
[(int)currentChar
])
966 if (currentChar
== 'f' ||
967 currentChar
== 'l' ||
968 currentChar
== 'F' ||
973 /*@switchbreak@*/ break;
976 /* Scan integer suffix. */
982 if (currentChar
== 'l' || currentChar
== 'L')
986 /*@switchbreak@*/ break;
990 if (currentChar
== 'u' || currentChar
== 'U')
995 /*@switchbreak@*/ break;
997 /*@switchbreak@*/ break;
1001 /* Scan integer suffix. */
1002 switch (currentChar
)
1007 if (currentChar
== 'l' || currentChar
== 'L')
1011 /*@switchbreak@*/ break;
1015 if (currentChar
== 'u' || currentChar
== 'U')
1019 /*@switchbreak@*/ break;
1024 if (isDigit
[(int)currentChar
])
1026 while (isDigit
[(int)currentChar
])
1030 switch (currentChar
)
1033 LCLMOVECHAR (); /* discard '.'. */
1034 tokenCode
= LLT_CFLOAT
;
1035 while (isDigit
[(int)currentChar
])
1039 if (currentChar
== 'e' || currentChar
== 'E')
1042 if (currentChar
== '+' || currentChar
== '-')
1046 if (!isDigit
[(int)currentChar
])
1048 LocalUserError ("digit must follow exponent");
1050 while (isDigit
[(int)currentChar
])
1055 if (currentChar
== 'f' ||
1056 currentChar
== 'l' ||
1057 currentChar
== 'F' ||
1062 /*@switchbreak@*/ break;
1067 tokenCode
= LLT_CFLOAT
;
1068 if (currentChar
== '+' || currentChar
== '-')
1072 if (!isDigit
[(int)currentChar
])
1074 LocalUserError ("digit must follow exponent");
1076 while (isDigit
[(int)currentChar
])
1080 if (currentChar
== 'f' ||
1081 currentChar
== 'l' ||
1082 currentChar
== 'F' ||
1088 /*@switchbreak@*/ break;
1090 switch (currentChar
)
1095 if (currentChar
== 'l' || currentChar
== 'L')
1099 /*@switchbreak@*/ break;
1103 if (currentChar
== 'u' || currentChar
== 'U')
1107 /*@switchbreak@*/ break;
1109 /*@switchbreak@*/ break;
1114 LocalUserError ("invalid C number");
1122 tokenSym
= lsymbol_fromChars (&tokenBuffer
[0]);
1125 static void ScanOther (void)
1127 switch (LCLScanCharClass (currentChar
))
1130 tokenSym
= lsymbol_fromChars ("E O L");
1131 tokenCode
= LLT_EOL
;
1138 while (LCLScanCharClass (currentChar
) == IDCHAR
)
1139 { /* identifier: find end */
1143 *bufPtr
= '\0'; /* null terminate in buffer */
1144 tokenSym
= lsymbol_fromChars (&tokenBuffer
[0]);
1145 tokenCode
= simpleId
;
1148 /* one-character tokens */
1154 tokenSym
= lsymbol_fromChars (&tokenBuffer
[0]);
1155 tokenCode
= simpleOp
;
1158 /* operator symbols */
1162 if (currentChar
== '.' && LOOKAHEADCHAR () == '.' &&
1163 LOOKAHEADTWICECHAR () == '.')
1169 tokenSym
= lsymbol_fromChars ("...");
1170 tokenCode
= LLT_TELIPSIS
;
1174 if (currentChar
== '/' && LOOKAHEADCHAR () == '\\')
1181 while (LCLScanCharClass (currentChar
) == OPCHAR
)
1188 tokenSym
= lsymbol_fromChars (&tokenBuffer
[0]);
1189 tokenCode
= simpleOp
;
1195 /*@-loopswitchbreak@*/
1196 /*@-switchswitchbreak@*/
1197 switch (currentChar
)
1200 LCLMOVECHAR (); /* tabs only count as one character */
1206 colNumber
--; /* does not change column */
1213 /*@=switchswitchbreak@*/
1216 tokenSym
= lsymbol_fromChars (&tokenBuffer
[0]);
1217 tokenCode
= LLT_WHITESPACE
;
1225 /*@-switchswitchbreak@*/
1226 switch (currentChar
)
1228 /* open and close */
1231 while (LCLScanCharClass (currentChar
) == IDCHAR
)
1236 tokenSym
= lsymbol_fromChars (&tokenBuffer
[0]);
1237 tokenCode
= openSym
;
1242 while (LCLScanCharClass (currentChar
) == IDCHAR
)
1247 tokenSym
= lsymbol_fromChars (&tokenBuffer
[0]);
1248 tokenCode
= closeSym
;
1254 while (LCLScanCharClass (currentChar
) == IDCHAR
)
1259 tokenSym
= lsymbol_fromChars (&tokenBuffer
[0]);
1266 while (LCLScanCharClass (currentChar
) == IDCHAR
)
1271 tokenSym
= lsymbol_fromChars (&tokenBuffer
[0]);
1272 tokenCode
= simpleId
;
1276 if (LCLScanCharClass (currentChar
) == IDCHAR
)
1282 while (LCLScanCharClass (currentChar
) == IDCHAR
);
1284 tokenSym
= lsymbol_fromChars (&tokenBuffer
[0]);
1285 tokenCode
= simpleOp
;
1290 ** Meets none of the above. Take the extension
1291 ** character and the character following and treat
1292 ** together as a SINGLECHAR. SINGLECHARs tranlate into
1298 tokenSym
= lsymbol_fromChars (&tokenBuffer
[0]);
1299 tokenCode
= simpleOp
;
1302 /*@=switchswitchbreak@*/
1307 LocalUserError ("unexpected character in input");
1310 /*@=loopswitchbreak@*/
1314 nextCanBeCharLiteral (ltokenCode c
)
1318 /* A ' following these tokens starts a C character literal. */
1335 case LLT_CONSTRAINT
:
1342 /* A ' following these tokens means post */
1356 /* Neither a C character literal nor post should follow these tokens */
1362 case LLT_VERTICALBAR
:
1386 case LLT_TAGGEDUNION
:
1396 case LLT_TYPEDEF_NAME
:
1408 /* These tokens should have been ignored */
1411 case LLT_WHITESPACE
:
1414 llcontbuglit ("scanline: nextCanBeChar");
1423 LCLScanLine (char *line
)
1426 lsymbol CCommentSym
= lsymbol_fromChars ("/*");
1427 size_t linelength
= strlen (line
);
1428 static bool inSpecComment
= FALSE
;
1430 line
[(int)linelength
] = '\n';
1433 currentChar
= *currentLine
++;
1434 context_processedSpecLine ();
1446 newToken
= ltoken_createRaw (simpleId
, lsymbol_fromChars (&tokenBuffer
[0]));
1447 LCLScanFreshToken (newToken
);
1453 if (currentChar
== '*' &&
1454 LOOKAHEADCHAR () == '/')
1458 inSpecComment
= FALSE
;
1465 if (inSpecComment
&& currentChar
== '*' && LOOKAHEADCHAR () == '/')
1469 inSpecComment
= FALSE
;
1472 bufPtr
= &tokenBuffer
[0];
1473 startCol
= colNumber
;
1476 /*@-loopswitchbreak@*/
1477 switch (startClass
[(int)currentChar
])
1484 if (isDigit
[(int) LOOKAHEADCHAR ()])
1499 if (nextCanBeCharLiteral (prevTokenCode
))
1510 if (LOOKAHEADCHAR () == 'L' && LOOKAHEADTWICECHAR () == '\"')
1514 else if (LOOKAHEADCHAR () == 'L' && LOOKAHEADTWICECHAR () == '\'')
1525 if (LOOKAHEADCHAR () == '*')
1530 if (currentChar
== '@')
1532 char *s
= mstring_createEmpty ();
1536 while (currentChar
!= '\0' && currentChar
!= ' '
1537 && currentChar
!= '*' && currentChar
!= '\t' &&
1538 currentChar
!= '\n')
1540 s
= mstring_append (s
, currentChar
);
1544 if (mstring_equal (s
, "alt"))
1546 tokenCode
= LLT_VERTICALBAR
;
1547 tokenSym
= lsymbol_fromChars ("|");
1548 inSpecComment
= TRUE
;
1553 tokenCode
= commentSym
;
1554 tokenSym
= CCommentSym
;
1563 tokenCode
= commentSym
;
1564 tokenSym
= CCommentSym
;
1578 llcontbuglit ("LCLScanLine: bad case");
1582 /*@=loopswitchbreak@*/
1585 ** Above code only "guessed" at token type. Insert it into the
1586 ** TokenTable. If the token already exists, it is returned as
1587 ** previously defined. If it does not exist, it is inserted as the
1588 ** token code computed above.
1591 newToken
= LCLInsertToken (tokenCode
, tokenSym
, lsymbol_undefined
, FALSE
);
1594 if (LCLIsSyn (ltoken_getText (newToken
)))
1597 ** Token is a synonym. Get the actual token and set the raw
1598 ** text to the synonym name.
1601 newToken
= ltoken_copy (LCLGetTokenForSyn (ltoken_getText (newToken
)));
1603 ltoken_setRawText (newToken
, tokenSym
);
1607 newToken
= ltoken_copy (newToken
);
1610 ltoken_setCol (newToken
, startCol
);
1611 ltoken_setLine (newToken
, inputStream_thisLineNumber (LCLScanSource ()));
1612 ltoken_setFileName (newToken
, inputStream_fileName (LCLScanSource ()));
1614 if (ltoken_getCode (newToken
) == commentSym
)
1616 if (tokenSym
== CCommentSym
)
1617 { /* C-style comment */
1618 ltoken_free (commentTok
);
1619 commentTok
= ltoken_copy (newToken
);
1621 if (!inComment
&& reportComments
)
1624 ltoken_setRawText (newToken
,
1625 lsymbol_fromChars (&tokenBuffer
[0]));
1626 LCLScanFreshToken (newToken
);
1630 ltoken_free (newToken
);
1634 { /* LSL-style comment */
1635 bufPtr
= &tokenBuffer
[0];
1636 while (!LCLIsEndComment (currentChar
))
1640 if (LCLScanCharClass (currentChar
) != CHC_NULL
)
1642 /* Not EOL character. Toss it out. */
1649 ltoken_setRawText (newToken
,
1650 lsymbol_fromChars (&tokenBuffer
[0]));
1651 LCLScanFreshToken (newToken
);
1655 ltoken_free (newToken
);
1659 else if (ltoken_getCode (newToken
) == LLT_EOL
)
1663 LCLScanFreshToken (newToken
);
1667 ltoken_free (newToken
);
1670 line
[(int) linelength
] = '\0';
1673 else if (ltoken_getCode (newToken
) != LLT_WHITESPACE
)
1675 prevTokenCode
= ltoken_getCode (newToken
);
1676 LCLScanFreshToken (newToken
);
1680 ltoken_free (newToken
);
1685 /*@exposed@*/ ltoken
1686 LCLScanEofToken (void)
1688 ltoken t
= LCLInsertToken (LEOFTOKEN
, lsymbol_fromChars ("E O F"), 0, TRUE
);
1692 lclerror (commentTok
, cstring_makeLiteral ("Unterminated comment"));
1695 ltoken_setCol (t
, colNumber
);
1696 ltoken_setLine (t
, inputStream_thisLineNumber (LCLScanSource ()));
1697 ltoken_setFileName (t
, inputStream_fileName (LCLScanSource ()));
1703 LCLReportEolTokens (bool setting
)
1705 reportEOL
= setting
;
1709 LocalUserError (char *msg
)
1711 inputStream s
= LCLScanSource ();
1712 llfatalerror (message ("%s:%d,%d: %s",
1713 inputStream_fileName (s
),
1714 inputStream_thisLineNumber (s
),
1716 cstring_fromChars (msg
)));
1720 LCLScanLineInit (void)
1726 reportComments
= FALSE
;
1728 for (i
= 0; i
<= LASTCHAR
; i
++)
1730 LCLcharClass
[i
] = charClassDef
[i
];
1736 ** Make sure first postion is never used because use the 0th index to
1740 (void) lsymbol_fromChars (FIRSTRESERVEDNAME
);
1743 /* Predefined LSL Tokens */
1745 ltoken_forall
= LCLReserveToken (quantifierSym
, "\\forall");
1747 ltoken_exists
= LCLReserveToken (quantifierSym
, "\\exists");
1748 ltoken_implies
= LCLReserveToken (logicalOp
, "\\implies");
1749 ltoken_eqsep
= LCLReserveToken (eqSepSym
, "\\eqsep");
1750 ltoken_select
= LCLReserveToken (selectSym
, "\\select");
1751 ltoken_open
= LCLReserveToken (openSym
, "\\open");
1752 ltoken_sep
= LCLReserveToken (sepSym
, "\\,");
1753 ltoken_close
= LCLReserveToken (closeSym
, "\\close");
1754 ltoken_id
= LCLReserveToken (simpleId
, "\\:");
1755 ltoken_arrow
= LCLReserveToken (mapSym
, "\\arrow");
1756 ltoken_marker
= LCLReserveToken (markerSym
, "\\marker");
1757 ltoken_pre
= LCLReserveToken (preSym
, "\\pre");
1758 ltoken_post
= LCLReserveToken (postSym
, "\\post");
1759 ltoken_comment
= LCLReserveToken (commentSym
, "\\comment");
1760 ltoken_any
= LCLReserveToken (anySym
, "\\any");
1762 ltoken_result
= LCLReserveToken (LLT_RESULT
, "result");
1763 ltoken_typename
= LCLReserveToken (LLT_TYPEDEF_NAME
, "TYPEDEF_NAME");
1764 ltoken_setIdType (ltoken_typename
, SID_TYPE
);
1767 ** Not context_getBoolName () --- "bool" is built in to LCL.
1768 ** This is bogus, but necessary for a lot of old lcl files.
1771 ltoken_bool
= LCLReserveToken (LLT_TYPEDEF_NAME
, "bool");
1773 ltoken_lbracked
= LCLReserveToken (LLT_LBRACKET
, "[");
1774 ltoken_rbracket
= LCLReserveToken (LLT_RBRACKET
, "]");
1776 (void) LCLReserveToken (LLT_COLON
, ":");
1777 (void) LCLReserveToken (LLT_COMMA
, ",");
1779 (void) LCLReserveToken (LLT_EQUALS
, "=");
1780 (void) LCLReserveToken (LLT_LBRACE
, "{");
1781 (void) LCLReserveToken (LLT_LPAR
, "(");
1782 (void) LCLReserveToken (LLT_RBRACE
, "}");
1783 (void) LCLReserveToken (LLT_RPAR
, ")");
1784 (void) LCLReserveToken (LLT_SEMI
, ";");
1785 (void) LCLReserveToken (LLT_VERTICALBAR
, "|");
1787 (void) LCLReserveToken (LLT_MULOP
, "*");
1789 (void) LCLReserveToken (LLT_WHITESPACE
, " ");
1790 (void) LCLReserveToken (LLT_WHITESPACE
, "\t");
1791 (void) LCLReserveToken (LLT_WHITESPACE
, "\f");
1792 (void) LCLReserveToken (LLT_WHITESPACE
, "\n");
1794 (void) LCLReserveToken (LEOFTOKEN
, "E O F");
1795 (void) LCLReserveToken (LLT_EOL
, "E O L");
1798 ltoken_and
= LCLReserveToken (logicalOp
, "\\and");
1799 ltoken_or
= LCLReserveToken (logicalOp
, "\\or");
1801 ltoken_equals
= LCLReserveToken (equationSym
, "\\equals");
1803 ltoken_eq
= LCLReserveToken (eqOp
, "\\eq");
1804 ltoken_neq
= LCLReserveToken (eqOp
, "\\neq");
1806 ltoken_not
= LCLReserveToken (simpleOp
, "\\not");
1807 ltoken_true
= LCLReserveToken (simpleId
, "true");
1808 ltoken_false
= LCLReserveToken (simpleId
, "false");
1811 (void) LCLReserveToken (LLT_ALL
, "all");
1812 (void) LCLReserveToken (LLT_ANYTHING
, "anything");
1813 (void) LCLReserveToken (LLT_BE
, "be");
1814 (void) LCLReserveToken (LLT_CONSTANT
, "constant");
1815 (void) LCLReserveToken (LLT_CHECKS
, "checks");
1816 (void) LCLReserveToken (LLT_ELSE
, "else");
1817 (void) LCLReserveToken (LLT_ENSURES
, "ensures");
1818 (void) LCLReserveToken (LLT_FOR
, "for");
1819 (void) LCLReserveToken (LLT_IF
, "if");
1820 (void) LCLReserveToken (LLT_IMMUTABLE
, "immutable");
1821 (void) LCLReserveToken (LLT_OBJ
, "obj");
1822 (void) LCLReserveToken (LLT_OUT
, "out");
1823 (void) LCLReserveToken (LLT_ITER
, "iter");
1824 (void) LCLReserveToken (LLT_YIELD
, "yield");
1825 (void) LCLReserveToken (LLT_PARTIAL
, "partial");
1826 (void) LCLReserveToken (LLT_ONLY
, "only");
1827 (void) LCLReserveToken (LLT_UNDEF
, "undef");
1828 (void) LCLReserveToken (LLT_KILLED
, "killed");
1829 (void) LCLReserveToken (LLT_OWNED
, "owned");
1830 (void) LCLReserveToken (LLT_DEPENDENT
, "dependent");
1831 (void) LCLReserveToken (LLT_PARTIAL
, "partial");
1832 (void) LCLReserveToken (LLT_RELDEF
, "reldef");
1833 (void) LCLReserveToken (LLT_KEEP
, "keep");
1834 (void) LCLReserveToken (LLT_KEPT
, "kept");
1835 (void) LCLReserveToken (LLT_TEMP
, "temp");
1836 (void) LCLReserveToken (LLT_SHARED
, "shared");
1837 (void) LCLReserveToken (LLT_RELNULL
, "relnull");
1838 (void) LCLReserveToken (LLT_RELDEF
, "reldef");
1839 (void) LCLReserveToken (LLT_CHECKED
, "checked");
1840 (void) LCLReserveToken (LLT_UNCHECKED
, "unchecked");
1841 (void) LCLReserveToken (LLT_CHECKEDSTRICT
, "checkedstrict");
1842 (void) LCLReserveToken (LLT_CHECKMOD
, "checkmod");
1843 (void) LCLReserveToken (LLT_TRUENULL
, "truenull");
1844 (void) LCLReserveToken (LLT_FALSENULL
, "falsenull");
1845 (void) LCLReserveToken (LLT_LNULL
, "null");
1846 (void) LCLReserveToken (LLT_LNOTNULL
, "notnull");
1847 (void) LCLReserveToken (LLT_RETURNED
, "returned");
1848 (void) LCLReserveToken (LLT_OBSERVER
, "observer");
1849 (void) LCLReserveToken (LLT_EXPOSED
, "exposed");
1850 (void) LCLReserveToken (LLT_REFCOUNTED
, "refcounted");
1851 (void) LCLReserveToken (LLT_REFS
, "refs");
1852 (void) LCLReserveToken (LLT_NEWREF
, "newref");
1853 (void) LCLReserveToken (LLT_TEMPREF
, "tempref");
1854 (void) LCLReserveToken (LLT_KILLREF
, "killref");
1855 (void) LCLReserveToken (LLT_NULLTERMINATED
, "nullterminated");
1856 (void) LCLReserveToken (LLT_EXITS
, "exits");
1857 (void) LCLReserveToken (LLT_MAYEXIT
, "mayexit");
1858 (void) LCLReserveToken (LLT_TRUEEXIT
, "trueexit");
1859 (void) LCLReserveToken (LLT_FALSEEXIT
, "falseexit");
1860 (void) LCLReserveToken (LLT_NEVEREXIT
, "neverexit");
1861 (void) LCLReserveToken (LLT_SEF
, "sef");
1862 (void) LCLReserveToken (LLT_UNUSED
, "unused");
1863 (void) LCLReserveToken (LLT_UNIQUE
, "unique");
1864 (void) LCLReserveToken (LLT_IMPORTS
, "imports");
1865 (void) LCLReserveToken (LLT_CONSTRAINT
, "constraint");
1866 (void) LCLReserveToken (LLT_LET
, "let");
1867 (void) LCLReserveToken (LLT_MODIFIES
, "modifies");
1868 (void) LCLReserveToken (LLT_CLAIMS
, "claims");
1869 (void) LCLReserveToken (LLT_BODY
, "body");
1870 (void) LCLReserveToken (LLT_MUTABLE
, "mutable");
1871 (void) LCLReserveToken (LLT_FRESH
, "fresh");
1872 (void) LCLReserveToken (LLT_NOTHING
, "nothing");
1873 (void) LCLReserveToken (LLT_INTERNAL
, "internalState");
1874 (void) LCLReserveToken (LLT_FILESYS
, "fileSystem");
1875 (void) LCLReserveToken (LLT_PRIVATE
, "private");
1876 (void) LCLReserveToken (LLT_SPEC
, "spec");
1877 (void) LCLReserveToken (LLT_REQUIRES
, "requires");
1878 (void) LCLReserveToken (LLT_SIZEOF
, "sizeof");
1879 (void) LCLReserveToken (LLT_TAGGEDUNION
, "taggedunion");
1880 (void) LCLReserveToken (LLT_THEN
, "then");
1881 (void) LCLReserveToken (LLT_TYPE
, "type");
1882 (void) LCLReserveToken (LLT_TYPEDEF
, "typedef");
1883 (void) LCLReserveToken (LLT_UNCHANGED
, "unchanged");
1884 (void) LCLReserveToken (LLT_USES
, "uses");
1885 (void) LCLReserveToken (LLT_PRINTFLIKE
, "printflike");
1886 (void) LCLReserveToken (LLT_SCANFLIKE
, "scanflike");
1887 (void) LCLReserveToken (LLT_MESSAGELIKE
, "messagelike");
1889 /* LCL C Keywords */
1890 (void) LCLReserveToken (LLT_CHAR
, "char");
1891 (void) LCLReserveToken (LLT_CONST
, "const");
1892 (void) LCLReserveToken (LLT_DOUBLE
, "double");
1893 (void) LCLReserveToken (LLT_ENUM
, "enum");
1895 /* comment out so we can add in lclinit.lci: synonym double float */
1896 /* LCLReserveToken (LLT_FLOAT, "float"); */
1897 /* But we need to make the scanner parse "float" not as a simpleId, but
1898 as a TYPEDEF_NAME. This is done later in abstract_init */
1900 (void) LCLReserveToken (LLT_INT
, "int");
1901 (void) LCLReserveToken (LLT_LONG
, "long");
1902 (void) LCLReserveToken (LLT_SHORT
, "short");
1903 (void) LCLReserveToken (LLT_STRUCT
, "struct");
1904 (void) LCLReserveToken (LLT_SIGNED
, "signed");
1905 (void) LCLReserveToken (LLT_UNION
, "union");
1906 (void) LCLReserveToken (LLT_UNKNOWN
, "__unknown");
1907 (void) LCLReserveToken (LLT_UNSIGNED
, "unsigned");
1908 (void) LCLReserveToken (LLT_VOID
, "void");
1909 (void) LCLReserveToken (LLT_VOLATILE
, "volatile");
1914 LCLScanLineReset (void)
1917 prevTokenCode
= LLT_LPAR
; /* Presume first ' starts literal */
1921 LCLScanLineCleanup (void)
1925 bool LCLIsEndComment (char c
)
1927 return LCLcharClass
[(int)(c
)].endCommentChar
;
1930 charCode
LCLScanCharClass (char c
)
1932 return LCLcharClass
[(int)(c
)].code
;
1935 void LCLSetCharClass (char c
, charCode cod
)
1937 LCLcharClass
[(int)(c
)].code
= (cod
);
1940 void LCLSetEndCommentChar (char c
, bool flag
)
1942 LCLcharClass
[(int)(c
)].endCommentChar
= flag
;