Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20150303160423

Diff

Diff from 1.124 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/cc/cpp/token.c

Annotated File View

ragge
1.124
1 /*      $Id: token.c,v 1.124 2015/03/03 16:04:23 ragge Exp $    */
ragge
1.1
2
3 /*
ragge
1.13
4  * Copyright (c) 2004,2009 Anders Magnusson. All rights reserved.
ragge
1.1
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
ragge
1.19
27 /*
28  * Tokenizer for the C preprocessor.
29  * There are three main routines:
30  *      - fastscan() loops over the input stream searching for magic
31  *              characters that may require actions.
32  *      - sloscan() tokenize the input stream and returns tokens.
plunky
1.113
33  *      - yylex() returns something from the input stream that
ragge
1.19
34  *              is suitable for yacc.
35  *
36  *      Other functions of common use:
37  *      - inpch() returns a raw character from the current input stream.
38  *      - inch() is like inpch but \\n and trigraphs are expanded.
39  *      - unch() pushes back a character to the input stream.
40  */
41
ragge
1.13
42 #include "config.h"
43
ragge
1.1
44 #include <stdlib.h>
45 #include <string.h>
ragge
1.13
46 #ifdef HAVE_UNISTD_H
ragge
1.2
47 #include <unistd.h>
ragge
1.13
48 #endif
ragge
1.2
49 #include <fcntl.h>
ragge
1.1
50
ragge
1.13
51 #include "compat.h"
ragge
1.1
52 #include "cpp.h"
ragge
1.13
53
plunky
1.112
54 static void cvtdig(int);
plunky
1.114
55 static int dig2num(int);
ragge
1.13
56 static int charcon(usch *);
57 static void elsestmt(void);
58 static void ifdefstmt(void);
59 static void ifndefstmt(void);
60 static void endifstmt(void);
61 static void ifstmt(void);
62 static void cpperror(void);
plunky
1.102
63 static void cppwarning(void);
64 static void undefstmt(void);
ragge
1.13
65 static void pragmastmt(void);
66 static void elifstmt(void);
67
ragge
1.122
68 static int inpch(void);
69 static int chktg(void);
70 static int chkucn(void);
71 static void unch(int c);
72
plunky
1.121
73 #define PUTCH(ch) if (!flslvl) putch(ch)
ragge
1.13
74 /* protection against recursion in #include */
75 #define MAX_INCLEVEL    100
76 static int inclevel;
77
ragge
1.44
78 usch yytext[CPPBUF];
gmcgarry
1.16
79
plunky
1.81
80 struct includ *ifiles;
81
plunky
1.97
82 /* some common special combos for init */
83 #define C_NL    (C_SPEC|C_WSNL)
84 #define C_DX    (C_SPEC|C_ID|C_DIGIT|C_HEX)
85 #define C_I     (C_SPEC|C_ID|C_ID0)
86 #define C_IP    (C_SPEC|C_ID|C_ID0|C_EP)
87 #define C_IX    (C_SPEC|C_ID|C_ID0|C_HEX)
88 #define C_IXE   (C_SPEC|C_ID|C_ID0|C_HEX|C_EP)
89
90 usch spechr[256] = {
ragge
1.43
91         0,      0,      0,      0,      C_SPECC_SPEC0,      0,
plunky
1.97
92         0,      C_WSNLC_NL,   0,      0,      C_WSNL0,      0,
ragge
1.19
93         0,      0,      0,      0,      0,      0,      0,      0,
94         0,      0,      0,      0,      0,      0,      0,      0,
95
ragge
1.43
96         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
ragge
1.33
97         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
plunky
1.97
98         C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,
plunky
1.102
99         C_DX,   C_DX,   0,      0,      C_2,    C_2,    C_2,    0,
ragge
1.19
100
plunky
1.97
101         0,      C_IX,   C_IX,   C_IX,   C_IX,   C_IXE,  C_IX,   C_I,
ragge
1.19
102         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
plunky
1.97
103         C_IP,   C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
plunky
1.114
104         C_I,    C_I,    C_I,    0,      C_SPEC0,      0,      C_I,
ragge
1.19
105
plunky
1.97
106         0,      C_IX,   C_IX,   C_IX,   C_IX,   C_IXE,  C_IX,   C_I,
ragge
1.19
107         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
plunky
1.97
108         C_IP,   C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.19
109         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
ragge
1.111
110
111 /* utf-8 */
112         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
113         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
114         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
115         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
116
117         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
118         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
119         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
120         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
121
122         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
123         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
124         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
125         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
126
127         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
128         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
129         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
plunky
1.112
130         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.19
131 };
ragge
1.1
132
ragge
1.122
133 #if 0
134 int
135 getc_cooked(void)
136 {
137         int ch = inpch();
138
139         switch (ch) {
140         case -1:
141                 return -1;
142         case '?':
143                 if (ch == chktg())
144                         return ch;
145                 break;
146         case '\\':
147                 if (chkucn())
148                         return getc_cooked();
149                 if ((ch = inpch()) == '\r')
150                         ch = inpch();
151                 if (ch == '\n') {
152                         ifiles->escln++;
153                         return getc_cooked();
154                 } else {
155                         unch(ch);
156                         ch = '\\';
157                 }
158                 break;
159         case '%'/* Deal with only this digraph here */
160                   /* XXX strings??? */
161                 if ((ch = inpch()) == ':') {
162                         ch = '#';
163                 } else {
164                         unch(ch);
165                         ch = '%';
166                 }
167                 break;
168         }
169         return ch;
170 }
171 #endif
172
plunky
1.102
173 /*
174  * fill up the input buffer
175  */
176 static int
177 inpbuf(void)
178 {
179         int len;
180
181         if (ifiles->infil == -1)
182                 return 0;
183         len = read(ifiles->infilifiles->bufferCPPBUF);
184         if (len == -1)
185                 error("read error on file %s"ifiles->orgfn);
186         if (len > 0) {
187                 ifiles->buffer[len] = 0;
188                 ifiles->curptr = ifiles->buffer;
189                 ifiles->maxread = ifiles->buffer + len;
190         }
191         return len;
192 }
193
194 /*
195  * return a raw character from the input stream
196  */
197 static inline int
198 inpch(void)
199 {
200
201         do {
202                 if (ifiles->curptr < ifiles->maxread)
203                         return *ifiles->curptr++;
204         } while (inpbuf() > 0);
205
206         return -1;
207 }
208
209 /*
210  * push a character back to the input stream
211  */
ragge
1.13
212 static void
213 unch(int c)
214 {
plunky
1.93
215         if (c == -1)
216                 return;
plunky
1.113
217
plunky
1.102
218         ifiles->curptr--;
ragge
1.15
219         if (ifiles->curptr < ifiles->bbuf)
220                 error("pushback buffer full");
gmcgarry
1.26
221         *ifiles->curptr = (usch)c;
ragge
1.13
222 }
ragge
1.1
223
plunky
1.102
224 /*
225  * Check for (and convert) trigraphs.
226  */
227 static int
228 chktg(void)
229 {
230         int ch;
231
232         if ((ch = inpch()) != '?') {
233                 unch(ch);
234                 return 0;
235         }
236
237         switch (ch = inpch()) {
238         case '=':  return '#';
239         case '(':  return '[';
240         case ')':  return ']';
241         case '<':  return '{';
242         case '>':  return '}';
243         case '/':  return '\\';
244         case '\''return '^';
245         case '!':  return '|';
246         case '-':  return '~';
247         }
248
249         unch(ch);
250         unch('?');
251         return 0;
252 }
253
254 /*
255  * check for (and eat) end-of-line
256  */
257 static int
258 chkeol(void)
259 {
260         int ch;
261
262         ch = inpch();
263         if (ch == '\r') {
264                 ch = inpch();
265                 if (ch == '\n')
266                         return '\n';
267
268                 unch(ch);
269                 unch('\r');
270                 return 0;
271         }
272         if (ch == '\n')
273                 return '\n';
274
275         unch(ch);
276         return 0;
277 }
278
279 /*
280  * return next char, after converting trigraphs and
281  * skipping escaped line endings
282  */
283 static inline int
284 inch(void)
285 {
286         int ch;
287
288         for (;;) {
289                 ch = inpch();
290                 if (ch == '?' && (ch = chktg()) == 0)
291                         return '?';
292                 if (ch != '\\' || chkeol() == 0)
293                         return ch;
294                 ifiles->escln++;
295         }
296 }
297
plunky
1.114
298 /*
299  * check for universal-character-name on input, and
300  * unput to the pushback buffer encoded as UTF-8.
301  */
302 static int
303 chkucn(void)
304 {
305         unsigned long cpm;
306         int chn;
307
308         if ((ch = inch()) == -1)
309                 return 0;
310         if (ch == 'u')
311                 n = 4;
312         else if (ch == 'U')
313                 n = 8;
314         else {
315                 unch(ch);
316                 return 0;
317         }
318
319         cp = 0;
320         while (n-- > 0) {
321                 if ((ch = inch()) == -1 || (spechr[ch] & C_HEX) == 0) {
322                         warning("invalid universal character name");
323                         // XXX should actually unput the chars and return 0
324                         unch(ch); // XXX eof
325                         break;
326                 }
327                 cp = cp * 16 + dig2num(ch);
328         }
329
plunky
1.115
330         if ((cp < 0xa0 && cp != 0x24 && cp != 0x40 && cp != 0x60)
331             || (cp >= 0xd800 && cp <= 0xdfff))  /* 6.4.3.2 */
332                 error("universal character name cannot be used");
333
plunky
1.114
334         if (cp > 0x7fffffff)
335                 error("universal character name out of range");
336
337         n = 0;
338         m = 0x7f;
339         while (cp > m) {
340                 unch(0x80 | (cp & 0x3f));
341                 cp >>= 6;
342                 m >>= (n++ ? 1 : 2);
343         }
344         unch(((m << 1) ^ 0xfe) | cp);
345         return 1;
346 }
347
ragge
1.122
348 /*
349  * deal with comments in the fast scanner.
350  */
351 static int
352 fastcmnt(int ps)
353 {
354         int ch;
355
356         if ((ch = inch()) == '/') { /* C++ comment */
357                 while ((ch = inch()) != '\n')
358                         ;
359                 unch(ch);
360         } else if (ch == '*') {
361                 for (;;) {
362                         ch = inch();
363                         if (ch == '*') {
364                                 if ((ch = inch()) == '/') {
365                                         break;
366                                 } else
367                                         unch(ch);
368                         } else if (ch == '\n') {
369                                 ifiles->lineno++;
370                                 putch('\n');
371                         }
372                 }
373         } else {
374                 if (psPUTCH('/'); /* XXX ? */
375                 unch(ch);
376                 return 0;
377         }
378         return 1;
379 }
380
381 /*
382  * deal with comments when -C is active.
383  */
384 static int
385 Ccmnt(int ps)
386 {
387         int ch;
388
389         if ((ch = inch()) == '/') { /* C++ comment */
390                 PUTCH(ch);
391                 do {
392                         PUTCH(ch);
393                 } while ((ch = inch()) != '\n');
394                 unch(ch);
395                 return 1;
396         } else if (ch == '*') {
397                 printf("/*");
398                 for (;;) {
399                         ch = inch();
400                         PUTCH(ch);
401                         if (ch == '*') {
402                                 if ((ch = inch()) == '/') {
403                                         PUTCH(ch);
404                                         return 1;
405                                 } else
406                                         unch(ch);
407                         } else if (ch == '\n') {
408                                 ifiles->lineno++;
409                                 PUTCH('\n');
410                         }
411                 }
412         }
413         PUTCH('/');
414         unch(ch);
415         return 0;
416 }
417
418
plunky
1.108
419 static int
ragge
1.45
420 eatcmnt(void)
421 {
422         int ch;
423
plunky
1.108
424         if (Cflag) {
425                 PUTCH('/'); PUTCH('*');
426         }
ragge
1.45
427         for (;;) {
428                 ch = inch();
429                 if (ch == '\n') {
430                         ifiles->lineno++;
plunky
1.121
431                         putch('\n');
plunky
1.102
432                         continue;
ragge
1.45
433                 }
434                 if (ch == -1)
plunky
1.108
435                         return -1;
ragge
1.45
436                 if (ch == '*') {
437                         ch = inch();
plunky
1.108
438                         if (ch == '/')
ragge
1.45
439                                 break;
440                         unch(ch);
441                         ch = '*';
442                 }
443                 if (CflagPUTCH(ch);
444         }
plunky
1.108
445         if (Cflag) {
446                 PUTCH('*'); PUTCH('/');
447         } else
448                 PUTCH(' ');
449
450         return 0;
ragge
1.45
451 }
452
ragge
1.19
453 /*
ragge
1.122
454  * Traverse over spaces and comments from the input stream,
455  * printing out them if -C. Returns first non-space character.
456  * This function is only called after a '#' is found.
457  */
458 static int
459 fastspc(int pre)
460 {
461         int ch;
462
463         while ((ch = inch()) == ' ' || ch == '\t' || ch == '/') {
464                 if (ch == '/')
465                         if (pre && Cflag ? Ccmnt(0) : fastcmnt(0) == 0)
466                                 break;
467         }
468         return ch;
469 }
470
471
472 /*
473  * readin chars and store in yytext. Warn about too long names.
474  */
475 static void
476 fastid(int ch)
477 {
478         int i = 0;
479
480         do {
481                 yytext[i++] = ch;
482         } while (spechr[ch = inch()] & C_ID);
483         yytext[i] = 0;
484         unch(ch);
485 }
486
487
488 /*
ragge
1.19
489  * Scan quickly the input file searching for:
490  *      - '#' directives
491  *      - keywords (if not flslvl)
492  *      - comments
493  *
494  *      Handle strings, numbers and trigraphs with care.
495  *      Only data from pp files are scanned here, never any rescans.
496  *      TODO: Only print out strings before calling other functions.
497  */
498 static void
499 fastscan(void)
500 {
501         struct symtab *nl;
plunky
1.102
502         int chi;
ragge
1.49
503         usch *cp;
ragge
1.19
504
505         goto run;
506         for (;;) {
plunky
1.102
507                 ch = inch();
ragge
1.19
508 xloop:          if (ch == -1)
509                         return;
plunky
1.60
510 #ifdef PCC_DEBUG
ragge
1.43
511                 if (dflag>1)
512                         printf("fastscan ch %d (%c)\n"chch > 31 ? ch : '@');
plunky
1.60
513 #endif
ragge
1.19
514                 if ((spechr[ch] & C_SPEC) == 0) {
515                         PUTCH(ch);
516                         continue;
517                 }
518                 switch (ch) {
ragge
1.44
519                 case EBLOCK:
ragge
1.43
520                 case WARN:
521                 case CONC:
522                         error("bad char passed");
523                         break;
524
ragge
1.19
525                 case '/'/* Comments */
526                         if ((ch = inch()) == '/') {
ragge
1.120
527                                 if (!flslvl) {
plunky
1.121
528 cppcmt:                                 putch(Cflag ? ch : ' ');
ragge
1.120
529                                 }
ragge
1.19
530                                 do {
plunky
1.121
531                                         if (Cflag && !flslvlputch(ch);
ragge
1.19
532                                         ch = inch();
plunky
1.108
533                                         if (ch == -1)
534                                                 goto eof;
535                                 } while (ch != '\n');
ragge
1.19
536                                 goto xloop;
537                         } else if (ch == '*') {
plunky
1.108
538                                 if (eatcmnt() == -1)
539                                         goto eof;
ragge
1.19
540                         } else {
plunky
1.121
541                                 PUTCH('/');
ragge
1.19
542                                 goto xloop;
543                         }
544                         break;
545
546                 case '\n'/* newlines, for pp directives */
plunky
1.102
547                         i = ifiles->escln + 1;
548                         ifiles->lineno += i;
549                         ifiles->escln = 0;
550                         while (i-- > 0)
plunky
1.121
551                                 putch('\n');
plunky
1.102
552 run:                    for(;;) {
553                                 ch = inch();
ragge
1.45
554                                 if (ch == '/') {
plunky
1.102
555                                         ch = inch();
ragge
1.45
556                                         if (ch == '/')
557                                                 goto cppcmt;
558                                         if (ch == '*') {
plunky
1.108
559                                                 if (eatcmnt() == -1)
560                                                         goto eof;
plunky
1.102
561                                                 continue;
plunky
1.92
562                                         }
ragge
1.45
563                                         unch(ch);
564                                         ch = '/';
565                                 }
plunky
1.102
566                                 if (ch != ' ' && ch != '\t')
567                                         break;
plunky
1.121
568                                 PUTCH(ch);
ragge
1.50
569                         }
ragge
1.19
570                         if (ch == '#') {
571                                 ppdir();
572                                 continue;
ragge
1.40
573                         } else if (ch == '%') {
plunky
1.102
574                                 ch = inch();
ragge
1.40
575                                 if (ch == ':') {
576                                         ppdir();
577                                         continue;
578                                 }
plunky
1.92
579                                 unch(ch);
580                                 ch = '%';
ragge
1.19
581                         }
582                         goto xloop;
583
584                 case '\"'/* strings */
ragge
1.21
585 str:                    PUTCH(ch);
plunky
1.102
586                         while ((ch = inch()) != '\"') {
587                                 if (ch == '\\') {
plunky
1.114
588                                         if (chkucn())
589                                                 continue;
plunky
1.102
590                                         PUTCH('\\');
591                                         ch = inch();
592                                 }
plunky
1.104
593                                 if (ch == '\n') {
594                                         warning("unterminated string literal");
ragge
1.53
595                                         goto xloop;
plunky
1.104
596                                 }
plunky
1.90
597                                 if (ch == -1)
plunky
1.108
598                                         goto eof;
ragge
1.53
599                                 PUTCH(ch);
ragge
1.21
600                         }
ragge
1.19
601                         PUTCH(ch);
602                         break;
603
604                 case '.':  /* for pp-number */
605                         PUTCH(ch);
plunky
1.102
606                         ch = inch();
ragge
1.19
607                         if (ch < '0' || ch > '9')
608                                 goto xloop;
plunky
1.102
609
ragge
1.19
610                         /* FALLTHROUGH */
611                 case '0'case '1'case '2'case '3'case '4':
612                 case '5'case '6'case '7'case '8'case '9':
613                         do {
plunky
1.99
614 nxp:                            PUTCH(ch);
plunky
1.102
615                                 ch = inch();
plunky
1.94
616                                 if (ch == -1)
plunky
1.108
617                                         goto eof;
plunky
1.112
618                                 if ((spechr[ch] & C_EP)) {
ragge
1.19
619                                         PUTCH(ch);
plunky
1.102
620                                         ch = inch();
ragge
1.19
621                                         if (ch == '-' || ch == '+')
plunky
1.99
622                                                 goto nxp;
plunky
1.94
623                                         if (ch == -1)
plunky
1.108
624                                                 goto eof;
ragge
1.19
625                                 }
626                         } while ((spechr[ch] & C_ID) || (ch == '.'));
627                         goto xloop;
628
plunky
1.104
629                 case '\''/* character constant */
ragge
1.21
630 con:                    PUTCH(ch);
ragge
1.23
631                         if (tflag)
plunky
1.102
632                                 break/* character constants ignored */
633                         while ((ch = inch()) != '\'') {
634                                 if (ch == '\\') {
plunky
1.114
635                                         if (chkucn())
636                                                 continue;
plunky
1.102
637                                         PUTCH('\\');
638                                         ch = inch();
639                                 }
plunky
1.104
640                                 if (ch == '\n') {
641                                         warning("unterminated character constant");
ragge
1.52
642                                         goto xloop;
plunky
1.104
643                                 }
plunky
1.90
644                                 if (ch == -1)
plunky
1.108
645                                         goto eof;
ragge
1.52
646                                 PUTCH(ch);
ragge
1.21
647                         }
ragge
1.19
648                         PUTCH(ch);
649                         break;
ragge
1.21
650
ragge
1.19
651                 case 'L':
plunky
1.102
652                         ch = inch();
ragge
1.19
653                         if (ch == '\"') {
654                                 PUTCH('L');
655                                 goto str;
656                         }
657                         if (ch == '\'') {
658                                 PUTCH('L');
659                                 goto con;
660                         }
661                         unch(ch);
662                         ch = 'L';
plunky
1.102
663
ragge
1.19
664                         /* FALLTHROUGH */
665                 default:
plunky
1.102
666 #ifdef PCC_DEBUG
ragge
1.19
667                         if ((spechr[ch] & C_ID) == 0)
668                                 error("fastscan");
plunky
1.102
669 #endif
plunky
1.114
670                 ident:
ragge
1.122
671                         fastid(ch);
plunky
1.108
672                         if (flslvl == 0) {
673                                 cp = stringbuf;
674                                 if ((nl = lookup(yytextFIND)) && kfind(nl))
plunky
1.121
675                                         putstr(stringbuf);
plunky
1.108
676                                 else
plunky
1.121
677                                         putstr((usch *)yytext);
plunky
1.108
678                                 stringbuf = cp;
679                         }
680                         if (ch == -1)
681                                 goto eof;
ragge
1.43
682
ragge
1.19
683                         break;
plunky
1.114
684
685                 case '\\':
686                         if (chkucn()) {
687                                 ch = inch();
688                                 goto ident;
689                         }
690
691                         PUTCH('\\');
692                         break;
ragge
1.19
693                 }
694         }
plunky
1.108
695
696 eof:    warning("unexpected EOF");
plunky
1.121
697         putch('\n');
ragge
1.19
698 }
ragge
1.1
699
ragge
1.13
700 int
plunky
1.64
701 sloscan(void)
ragge
1.3
702 {
ragge
1.13
703         int ch;
704         int yyp;
705
706 zagain:
707         yyp = 0;
plunky
1.113
708         ch = inch();
gmcgarry
1.26
709         yytext[yyp++] = (usch)ch;
ragge
1.13
710         switch (ch) {
plunky
1.108
711         case -1/* EOF */
ragge
1.14
712                 return 0;
plunky
1.108
713
714         case '\n'/* do not pass NL */
ragge
1.19
715                 unch(ch);
plunky
1.94
716                 yytext[yyp] = 0;
717                 return ch;
ragge
1.13
718
plunky
1.108
719         case '\r'/* Ignore CR */
720                 goto zagain;
ragge
1.13
721
plunky
1.113
722         case '0'case '1'case '2'case '3'case '4'case '5':
ragge
1.13
723         case '6'case '7'case '8'case '9':
plunky
1.108
724                 /* reading a "pp-number" */
ragge
1.13
725 ppnum:          for (;;) {
ragge
1.19
726                         ch = inch();
plunky
1.94
727                         if (ch == -1)
728                                 break;
plunky
1.112
729                         if ((spechr[ch] & C_EP)) {
gmcgarry
1.26
730                                 yytext[yyp++] = (usch)ch;
ragge
1.19
731                                 ch = inch();
ragge
1.13
732                                 if (ch == '-' || ch == '+') {
gmcgarry
1.26
733                                         yytext[yyp++] = (usch)ch;
ragge
1.13
734                                 } else
ragge
1.19
735                                         unch(ch);
ragge
1.118
736                                 if ((spechr[ch = inch()] & C_DIGIT) == 0)
737                                         break/* only digits allowed */
738                                 unch(ch);
ragge
1.13
739                                 continue;
740                         }
ragge
1.19
741                         if ((spechr[ch] & C_ID) || ch == '.') {
gmcgarry
1.26
742                                 yytext[yyp++] = (usch)ch;
ragge
1.13
743                                 continue;
plunky
1.113
744                         }
ragge
1.13
745                         break;
746                 }
ragge
1.19
747                 unch(ch);
ragge
1.13
748                 yytext[yyp] = 0;
ragge
1.19
749                 return NUMBER;
ragge
1.13
750
751         case '\'':
plunky
1.113
752 chlit:
ragge
1.13
753                 for (;;) {
ragge
1.19
754                         if ((ch = inch()) == '\\') {
plunky
1.114
755                                 if (chkucn())
756                                         continue;
gmcgarry
1.26
757                                 yytext[yyp++] = (usch)ch;
plunky
1.108
758                                 ch = inch();
759                         } else if (ch == '\'')
760                                 break;
761                         if (ch == -1 || ch == '\n') {
ragge
1.13
762                                 /* not a constant */
763                                 while (yyp > 1)
ragge
1.19
764                                         unch(yytext[--yyp]);
ragge
1.13
765                                 goto any;
plunky
1.108
766                         }
767                         yytext[yyp++] = (usch)ch;
ragge
1.13
768                 }
plunky
1.108
769                 yytext[yyp++] = (usch)'\'';
ragge
1.13
770                 yytext[yyp] = 0;
plunky
1.74
771                 return NUMBER;
ragge
1.13
772
773         case ' ':
774         case '\t':
ragge
1.19
775                 while ((ch = inch()) == ' ' || ch == '\t')
gmcgarry
1.26
776                         yytext[yyp++] = (usch)ch;
ragge
1.19
777                 unch(ch);
778                 yytext[yyp] = 0;
plunky
1.74
779                 return WSPACE;
ragge
1.13
780
781         case '/':
plunky
1.108
782                 if ((ch = inch()) == '/') {     /* C++ comment */
ragge
1.13
783                         do {
gmcgarry
1.26
784                                 yytext[yyp++] = (usch)ch;
ragge
1.19
785                                 ch = inch();
plunky
1.94
786                         } while (ch != -1 && ch != '\n');
ragge
1.13
787                         yytext[yyp] = 0;
788                         unch(ch);
789                         goto zagain;
plunky
1.108
790                 } else if (ch == '*') {         /* C comment */
ragge
1.13
791                         int cwrn;
792                         extern int readmac;
793
ragge
1.33
794                         if (Cflag && !flslvl && readmac) {
795                                 unch(ch);
ragge
1.34
796                                 yytext[yyp] = 0;
ragge
1.13
797                                 return CMNT;
ragge
1.33
798                         }
ragge
1.13
799
800                         wrn = 0;
plunky
1.94
801                 more:   while ((c = inch()) != '*') {
802                                 if (c == -1)
plunky
1.113
803                                         return 0;
ragge
1.13
804                                 if (c == '\n')
plunky
1.121
805                                         putch(c), ifiles->lineno++;
ragge
1.48
806                                 else if (c == EBLOCK) {
ragge
1.46
807                                         (void)inch();
ragge
1.48
808                                         (void)inch();
plunky
1.96
809                                 } else if (c == WARN)
ragge
1.13
810                                         wrn = 1;
811                         }
plunky
1.94
812                         if ((c = inch()) == -1)
ragge
1.13
813                                 return 0;
plunky
1.94
814                         if (c != '/') {
ragge
1.19
815                                 unch(c);
ragge
1.13
816                                 goto more;
817                         }
818                         if (!tflag && !Cflag && !flslvl)
ragge
1.19
819                                 unch(' ');
ragge
1.13
820                         if (wrn)
plunky
1.96
821                                 unch(WARN);
ragge
1.13
822                         goto zagain;
823                 }
824                 unch(ch);
825                 goto any;
826
ragge
1.19
827         case '.':
plunky
1.94
828                 if ((ch = inch()) == -1)
plunky
1.108
829                         goto any;
plunky
1.97
830                 if ((spechr[ch] & C_DIGIT)) {
gmcgarry
1.26
831                         yytext[yyp++] = (usch)ch;
ragge
1.19
832                         goto ppnum;
ragge
1.13
833                 }
plunky
1.108
834                 unch(ch);
ragge
1.19
835                 goto any;
ragge
1.13
836
837         case '\"':
ragge
1.62
838                 if (tflag && defining)
ragge
1.42
839                         goto any;
ragge
1.13
840         strng:
841                 for (;;) {
ragge
1.19
842                         if ((ch = inch()) == '\\') {
plunky
1.114
843                                 if (chkucn())
844                                         continue;
gmcgarry
1.26
845                                 yytext[yyp++] = (usch)ch;
plunky
1.108
846                                 ch = inch();
847                         } else if (ch == '\"') {
gmcgarry
1.26
848                                 yytext[yyp++] = (usch)ch;
ragge
1.13
849                                 break;
plunky
1.108
850                         }
851                         if (ch == -1 || ch == '\n') {
852                                 warning("unterminated string");
853                                 unch(ch);
854                                 break;  // XXX the STRING does not have a closing quote
855                         }
856                         yytext[yyp++] = (usch)ch;
ragge
1.13
857                 }
858                 yytext[yyp] = 0;
plunky
1.74
859                 return STRING;
ragge
1.13
860
plunky
1.114
861         case '\\':
862                 if (chkucn()) {
863                         --yyp;
864                         goto ident;
865                 }
866                 goto any;
867
ragge
1.13
868         case 'L':
ragge
1.42
869                 if ((ch = inch()) == '\"' && !tflag) {
gmcgarry
1.26
870                         yytext[yyp++] = (usch)ch;
ragge
1.13
871                         goto strng;
ragge
1.42
872                 } else if (ch == '\'' && !tflag) {
gmcgarry
1.26
873                         yytext[yyp++] = (usch)ch;
ragge
1.13
874                         goto chlit;
875                 }
ragge
1.19
876                 unch(ch);
ragge
1.13
877                 /* FALLTHROUGH */
878
879         /* Yetch, all identifiers */
plunky
1.113
880         case 'a'case 'b'case 'c'case 'd'case 'e'case 'f':
881         case 'g'case 'h'case 'i'case 'j'case 'k'case 'l':
882         case 'm'case 'n'case 'o'case 'p'case 'q'case 'r':
883         case 's'case 't'case 'u'case 'v'case 'w'case 'x':
ragge
1.13
884         case 'y'case 'z':
plunky
1.113
885         case 'A'case 'B'case 'C'case 'D'case 'E'case 'F':
ragge
1.13
886         case 'G'case 'H'case 'I'case 'J'case 'K':
plunky
1.113
887         case 'M'case 'N'case 'O'case 'P'case 'Q'case 'R':
888         case 'S'case 'T'case 'U'case 'V'case 'W'case 'X':
ragge
1.13
889         case 'Y'case 'Z':
ragge
1.19
890         case '_'/* {L}({L}|{D})* */
ragge
1.13
891
plunky
1.114
892         ident:
ragge
1.13
893                 for (;;) { /* get chars */
plunky
1.94
894                         if ((ch = inch()) == -1)
895                                 break;
plunky
1.114
896                         if (ch == '\\') {
897                                 if (chkucn())
898                                         continue;
899                                 unch('\\');
900                                 break;
901                         }
902                         if ((spechr[ch] & C_ID) == 0) {
plunky
1.94
903                                 unch(ch);
ragge
1.13
904                                 break;
ragge
1.14
905                         }
plunky
1.114
906                         yytext[yyp++] = (usch)ch;
ragge
1.13
907                 }
908                 yytext[yyp] = 0/* need already string */
plunky
1.108
909                 return IDENT;
ragge
1.13
910
911         default:
plunky
1.114
912                 if ((ch & 0x80))
913                         goto ident;
914
ragge
1.13
915         any:
916                 yytext[yyp] = 0;
ragge
1.19
917                 return yytext[0];
plunky
1.108
918         } /* endcase */
ragge
1.3
919
plunky
1.108
920         /* NOTREACHED */
ragge
1.3
921 }
922
ragge
1.19
923 int
plunky
1.64
924 yylex(void)
ragge
1.19
925 {
926         static int ifdefnoex;
927         struct symtab *nl;
928         int chc2;
929
930         while ((ch = sloscan()) == WSPACE)
931                 ;
plunky
1.97
932         if (ch < 128 && (spechr[ch