Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cpp.ansi / preprocess.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 /* $Id: preprocess.c,v 1.18 1994/06/24 11:37:53 ceriel Exp $ */
6 /* PREPROCESSOR DRIVER */
7
8 #include        <system.h>
9 #include        <alloc.h>
10 #include        "input.h"
11 #include        "obufsize.h"
12 #include        "arith.h"
13 #include        "LLlex.h"
14 #include        "class.h"
15 #include        "macro.h"
16 #include        "idf.h"
17 #include        "idfsize.h"
18 #include        "bits.h"
19 #include        "ln_prefix.h"
20 #include        "textsize.h"
21
22 char    _obuf[OBUFSIZE];
23 #ifdef DOBITS
24 char    bits[128];
25 #endif
26 extern int InputLevel;
27
28 extern char *sprint();
29
30 Xflush()
31 {
32         sys_write(STDOUT, _obuf, OBUFSIZE);
33 }
34
35 static char *SkipComment();
36 extern char options[];
37
38 /* #pragma directives are saved here and passed to the compiler later on.
39  */
40 struct prag_info {
41         int     pr_linnr;
42         char    *pr_fil;
43         char    *pr_text;
44 };
45 static struct prag_info *pragma_tab;
46 static int pragma_nr;
47
48 do_pragma()
49 {
50         register int size = ITEXTSIZE;
51         char *cur_line = Malloc((unsigned)size);
52         register char *c_ptr = cur_line;
53         register int c = GetChar();
54         register int delim = 0;
55
56         while(c != '\n') {
57                 if (c_ptr + 1 - cur_line == size) {
58                         cur_line = Realloc(cur_line, (unsigned)(size + ITEXTSIZE));
59                         c_ptr = cur_line + size - 1;
60                         size += ITEXTSIZE;
61                 }
62                 if (delim) {
63                         if (c == delim) {
64                                 delim = 0;
65                         }
66                         else if (c == '\\') {
67                                 *c_ptr++ = c;
68                                 c = GetChar();
69                                 if (c == '\n') break;
70                         }
71                 }
72                 else if (c == '\'' || c == '"') {
73                         delim = c;
74                 }
75                 else if (c == '/') {
76                         if ((c = GetChar()) != '*' || InputLevel) {
77                                 *c_ptr++ = '/';
78                         }
79                         else {
80                                 skipcomment();
81                                 continue;
82                         }
83                 }
84                 *c_ptr++ = c;
85                 c = GetChar();
86         }
87         *c_ptr = '\0';
88         if (!pragma_nr) {
89                 pragma_tab = (struct prag_info *)Malloc(sizeof(struct prag_info));
90         } else {
91                 pragma_tab = (struct prag_info *)Realloc((char *)pragma_tab
92                                     , (unsigned)(sizeof(struct prag_info) * (pragma_nr+1)));
93         }
94         if (delim) {
95                 error("unclosed opening %c", delim);
96         }
97         pragma_tab[pragma_nr].pr_linnr = LineNumber;
98         pragma_tab[pragma_nr].pr_fil = FileName;
99         pragma_tab[pragma_nr].pr_text = cur_line;
100         pragma_nr++;
101         LineNumber++;
102 }
103
104 char Xbuf[256];
105
106 preprocess(fn)
107         char *fn;
108 {
109         register int c;
110         register char *op = _obuf;
111         register char *ob = &_obuf[OBUFSIZE];
112         int lineno = 0;
113         int startline;
114
115 #define flush(X)        (sys_write(STDOUT,_obuf,X))
116 #define echo(ch)        if (op == ob) { Xflush(); op = _obuf; } *op++ = (ch);
117 #define newline()       op--; while (op >= _obuf && (*op == ' ' || *op == '\t')) op--; op++; echo('\n')
118
119         if (!options['P']) {
120                 /* Generate a line directive communicating the
121                    source filename
122                 */
123                 register char *p = Xbuf;
124
125                 sprint(p, "%s 1 \"%s\"\n",
126                         LINE_PREFIX,
127                         FileName);
128                 while (*p) {
129                         echo(*p++);
130                 }
131         }
132
133 #define do_line_dir(lineno, fn)                                         \
134                 if (lineno != LineNumber || fn != FileName) {           \
135                         fn = FileName;                                  \
136                         lineno = LineNumber;                            \
137                         if (! options['P']) {                           \
138                                 register char *p = Xbuf;                \
139                                 sprint(Xbuf, "%s %d \"%s\"\n",          \
140                                         LINE_PREFIX,                    \
141                                         (int)LineNumber,                \
142                                         FileName);                      \
143                                 op--;                                   \
144                                 while (op >= _obuf                      \
145                                        && (class(*op) == STSKIP         \
146                                            || *op == '\n')) op--;       \
147                                 op++;                                   \
148                                 newline();                              \
149                                 while (*p) {                            \
150                                         echo(*p++);                     \
151                                 }                                       \
152                         }                                               \
153                 }
154
155         for (;;) {
156                 LineNumber++;
157                 lineno++;
158                 startline = 1;
159                 c = GetChar();
160                 while (startline) {
161                     /* first flush the saved pragma's */
162                     if (pragma_nr) {
163                         register int i = 0;
164                         int LiNo = LineNumber;
165                         char *FiNam = FileName;
166
167                         while (i < pragma_nr) {
168                             register char *c_ptr = "#pragma";
169
170                             LineNumber = pragma_tab[i].pr_linnr;
171                             FileName = pragma_tab[i].pr_fil;
172                             do_line_dir(lineno, fn);
173                             while (*c_ptr) { echo(*c_ptr++); }
174                             c_ptr = pragma_tab[i].pr_text;
175                             while (*c_ptr) { echo(*c_ptr++); }
176                             newline(); lineno++;
177                             free(pragma_tab[i].pr_text);
178                             i++;
179                         }
180                         free((char *) pragma_tab);
181                         pragma_tab = (struct prag_info *)0;
182                         pragma_nr = 0;
183                         LineNumber = LiNo;
184                         FileName = FiNam;
185                         do_line_dir(lineno, fn);
186                     }
187
188
189                     while (class(c) == STSKIP || c == '/') {
190                         if (c == '/') {
191                             if (!InputLevel) {
192                                 c = GetChar();
193                                 if (c == '*') {
194                                     op = SkipComment(op, &lineno);
195                                     if (!op) return;
196                                     if (!options['C']) { echo(' '); }
197                                     c = GetChar();
198                                     continue;
199                                 }
200                                 UnGetChar();
201                                 c = '/';
202                             }
203                             break;
204                         }
205                         echo(c);
206                         c = GetChar();
207                     }
208
209                     if (c == '#') {
210                         domacro();
211                         lineno++;
212                         newline();
213                         c = GetChar();
214                     } else startline = 0;
215                 }
216                 do_line_dir(lineno, fn);
217                 for (;;) {
218
219                         /* illegal character */
220                         if (c & 0200)  {
221                                 if (c == EOI) {
222                                         newline();
223                                         flush((int)(op-_obuf));
224                                         return;
225                                 }
226                                 fatal("non-ascii character read");
227                         }
228
229                         /* comments */
230                         if (c == '/' && !InputLevel) {
231                                 c = GetChar();
232                                 if (c == '*') {
233                                         op = SkipComment(op, &lineno);
234                                         if (!op) return;
235                                         if (!options['C']) { echo(' '); }
236                                         c = GetChar();
237                                         continue;
238                                 }
239                                 echo('/');
240                                 continue;
241                         }
242
243                         /* switch on character */
244                         switch(class(c)) {
245                         case STNL:
246                                 newline();
247                                 break;
248                         case STSTR:
249                         case STCHAR:
250                                 {
251                                 register int stopc = c;
252                                 int escaped;
253
254                                 do {
255                                         escaped = 0;
256                                         echo(c);
257                                         c = GetChar();
258                                         if (c == '\n') {
259                                         /* the compiler will complain */
260                                                 break;
261                                         }
262                                         else if (c == EOI) {
263                                                 newline();
264                                                 flush((int)(op-_obuf));
265                                                 return;
266                                         }
267                                         if (c == '\\') {
268                                                 echo(c);
269                                                 c = GetChar();
270                                                 if (c == '\n') {
271                                                         ++LineNumber;
272                                                         lineno++;
273                                                 } else escaped = 1;
274                                         }
275                                 } while (escaped || c != stopc);
276                                 echo(c);
277                                 if (c == '\n')
278                                         break;  /* Don't eat # */
279                                 c = GetChar();
280                                 continue;
281                                 }
282                         case STNUM:
283                         /* The following code is quit ugly. This because
284                          * ..3 == . .3 , whereas ...3 == ... 3
285                          */
286                                 echo(c);
287                                 if (c == '.') {
288                                         c = GetChar();
289                                         if (c == '.') {
290                                                 if ((c = GetChar()) == '.') {
291                                                         echo('.'); echo('.');
292                                                         c = GetChar();
293                                                         continue;
294                                                 }
295                                                 UnGetChar();
296                                                 c = '.';
297                                                 continue;
298                                         } else if (!is_dig(c)) {
299                                                 continue;
300                                         } else { echo(c); }
301                                 }
302                                 c = GetChar();
303                                 while (in_idf(c) || c == '.') {
304                                         echo(c);
305                                         if (c == 'e' || c == 'E') {
306                                                 c = GetChar();
307                                                 if (c == '+' || c == '-') {
308                                                         echo(c);
309                                                         c = GetChar();
310                                                 }
311                                         } else  c = GetChar();
312                                 }
313                                 continue;
314                         case STELL:
315                                 c = GetChar();
316                                 UnGetChar();
317                                 if (c == '"' || c == '\'') {
318                                         echo('L');
319                                         continue;
320                                 }
321                                 c = 'L';
322                         case STIDF: {
323                                 extern int idfsize;             /* ??? */
324                                 char buf[IDFSIZE + 1];
325                                 register char *tg = &buf[0];
326                                 register char *maxpos = &buf[idfsize];
327                                 register struct idf *idef;
328                                 int NoExpandNext = 0;
329
330 #define tstmac(bx)      if (!(bits[c] & bx)) goto nomac
331 #define cpy             *tg++ = c
332 #define load            c = GetChar(); if (!in_idf(c)) goto endidf
333
334                                 /* unstack macro's when allowed. */
335                                 if (Unstacked)
336                                         EnableMacros();
337                                 if (c == NOEXPM) {
338                                         NoExpandNext = 1;
339                                         c = GetChar();
340                                 }
341
342 #ifdef DOBITS
343                                 cpy; tstmac(bit0); load;
344                                 cpy; tstmac(bit1); load;
345                                 cpy; tstmac(bit2); load;
346                                 cpy; tstmac(bit3); load;
347                                 cpy; tstmac(bit4); load;
348                                 cpy; tstmac(bit5); load;
349                                 cpy; tstmac(bit6); load;
350                                 cpy; tstmac(bit7); load;
351 #endif
352
353                                 for(;;) {
354                                         if (tg < maxpos) {
355                                                 cpy;
356                                         }
357                                         load;
358                                 }
359                         endidf:
360                                 if (c != EOF) UnGetChar();
361                                 *tg = '\0';     /* mark the end of the identifier */
362                                 if ((idef = findidf(buf))
363                                     && idef->id_macro
364                                     && ReplaceMacros && !NoExpandNext) {
365                                         if (replace(idef)) {
366                                                 echo(' ');
367                                                 c = GetChar();
368                                                 continue;
369                                         }
370                                         tg = buf;
371                                         while (*tg) {
372                                                 echo(*tg++);
373                                         }
374                                         c = GetChar();
375                                         if (in_idf(c)) { echo(' '); }
376                                         continue;
377                                 }
378                         nomac:
379                                 *tg = '\0';
380                                 tg = buf;
381                                 while (*tg) {
382                                         echo(*tg++);
383                                 }
384                                 c = GetChar();
385                                 while (in_idf(c)) {
386                                         echo(c);
387                                         c = GetChar();
388                                 }
389                                 continue;
390                                 }
391                         case STMSPEC:
392                                 if (InputLevel) {
393                                         echo(' ');      /* seperate tokens */
394                                         c = GetChar();
395                                         continue;
396                                 }
397                                 /* else fallthrough */
398                         default:
399                                 echo(c);
400                                 c = GetChar();
401                                 continue;
402                         }
403                         break;
404                 }
405         }
406         /*NOTREACHED*/
407 }
408
409 static char *
410 SkipComment(op, lineno)
411 char *op;
412 int *lineno;
413 {
414         char *ob = &_obuf[OBUFSIZE];
415         register int c, oldc = '\0';
416
417         NoUnstack++;
418         if (options['C']) {
419                 echo('/');
420                 echo('*');
421         }
422         c = GetChar();
423         for(;;) {
424                 if (c == EOI) {
425                         newline();
426                         flush((int)(op - _obuf));
427                         op = 0;
428                         break;
429                 }
430                 if (options['C']) {
431                         echo(c);
432                 }
433                 if (c == '\n') {
434                         ++LineNumber;
435                         ++*lineno;
436                         if (!options['C']) {
437                                 echo(c);
438                         }
439                 }
440                 if (c == '*') {
441                         c = GetChar();
442                         if (c == '/') {
443                                 if (options['C']) {
444                                         echo(c);
445                                 }
446                                 break;                  /* for(;;) */
447                         } else if (oldc == '/') {
448                                 warning("comment inside comment ?");
449                         }
450                         oldc = '*';
451                 } else {
452                         oldc = c;
453                         c = GetChar();
454                 }
455         }
456         NoUnstack--;
457         return op;
458 }