Pristine Ack-5.5
[Ack-5.5.git] / util / cpp / preprocess.c
1 /* $Id: preprocess.c,v 1.21 1994/06/24 10:18:50 ceriel Exp $ */
2 /*
3  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4  * See the copyright notice in the ACK home directory, in the file "Copyright".
5  */
6 /* PREPROCESSOR DRIVER */
7
8 #include <system.h>
9 #include "input.h"
10 #include "obufsize.h"
11 #include "LLlex.h"
12 #include "class.h"
13 #include "idf.h"
14 #include "idfsize.h"
15 #include "bits.h"
16 #include "line_prefix.h"
17
18 #ifdef DOBITS
19 char bits[128];
20 #endif
21
22 char _obuf[OBUFSIZE];
23 extern int do_preprocess;
24
25 Xflush()
26 {
27         if (do_preprocess) sys_write(STDOUT, _obuf, OBUFSIZE);
28 }
29
30 preprocess(fn)
31         char *fn;
32 {
33         register int c;
34         register char *op = _obuf;
35         register char *ob = &_obuf[OBUFSIZE];
36         char Xbuf[256];
37         int lineno = 0;
38         extern char options[];
39
40 #define flush(X)        (! do_preprocess || sys_write(STDOUT,_obuf,X))
41 #define echo(ch)        if (op == ob) { Xflush(); op = _obuf; } *op++ = (ch);
42 #define newline()       echo('\n')
43
44         if (! options['P']) {
45                 /* Generate a line directive communicating the
46                    source filename
47                 */
48                 register char *p = Xbuf;
49
50                 sprint(p, "%s 1 \"%s\"\n",
51                         LINE_PREFIX,
52                         FileName);
53                 while (*p) {
54                         echo(*p++);
55                 }
56         }
57         for (;;) {
58                 LineNumber++;
59                 lineno++;
60                 LoadChar(c);
61                 while (c == '#') {
62                         domacro();
63                         lineno++;
64                         newline();
65                         LoadChar(c);
66                 }
67                 if (lineno != LineNumber || fn != FileName) {
68                         fn = FileName;
69                         lineno = LineNumber;
70                         if (! options['P']) {
71                                 register char *p = Xbuf;
72
73                                 sprint(p, "%s %d \"%s\"\n",
74                                         LINE_PREFIX,
75                                         LineNumber,
76                                         FileName);
77                                 while (*p) {
78                                         echo(*p++);
79                                 }
80                         }
81                 }
82                 for (;;) {
83                         if (c & 0200)  {
84                                 if (c == EOI) {
85                                         newline();
86                                         flush(op-_obuf);
87                                         return;
88                                 }
89                                 fatal("non-ascii character read");
90                         }
91                         if (c == '/') {
92                                 LoadChar(c);
93                                 if (c == '*') {
94                                         NoUnstack++;
95                                         if (options['C']) {
96                                                 echo('/');
97                                                 echo('*');
98                                         }
99                                         for (;;) {
100                                                 LoadChar(c);
101                                                 if (c == '\n') {
102                                                         ++LineNumber;
103                                                         ++lineno;
104                                                         echo(c);
105                                                 }
106                                                 else if (c == EOI) {
107                                                         newline();
108                                                         flush(op - _obuf);
109                                                         return;
110                                                 }
111                                                 else if (c == '*') {
112                                                         if (options['C']) {
113                                                                 echo(c);
114                                                         }
115                                                         LoadChar(c);
116                                                         if (c == '/') {
117                                                            if (options['C']) {
118                                                                 echo(c);
119                                                            }
120                                                            break;
121                                                         }
122                                                         else {
123                                                                 PushBack();
124                                                         }
125                                                 }
126                                                 else if (options['C']) {
127                                                         echo(c);
128                                                 }
129                                         }
130                                         NoUnstack--;
131                                         LoadChar(c);
132                                         continue;
133                                 }
134                                 echo('/');
135                                 continue;
136                         }
137                         switch(class(c)) {
138                         case STNL:
139                                 echo(c);
140                                 break;
141                         case STSTR:
142                         case STCHAR: {
143                                 register int stopc = c;
144                                 int escaped;
145         
146                                 do {
147
148                                         escaped = 0;
149                                         echo(c);
150                                         LoadChar(c);
151                                         if (c == '\n') {
152                                                 break;
153                                         }
154                                         else if (c == EOI) {
155                                                 newline();
156                                                 flush(op-_obuf);
157                                                 return;
158                                         }
159                                         if (c == '\\') {
160                                                 echo(c);
161                                                 LoadChar(c);
162                                                 if (c == '\n') {
163                                                         ++LineNumber;
164                                                         lineno++;
165                                                 }
166                                                 else escaped = 1;
167                                         }
168                                 } while (escaped || c != stopc);
169                                 echo(c);
170                                 if (c == '\n')
171                                         break;  /* Don't eat # */
172                                 LoadChar(c);
173                                 continue;
174                                 }
175                         case STNUM:
176 #define getdec(c)       do { echo(c); LoadChar(c);} while (is_dig(c))
177 #define gethex(c)       do { echo(c); LoadChar(c);} while (is_hex(c))
178
179                                 if (c != '0') {
180                                         getdec(c);
181                                         if (c == '.') getdec(c);
182                                         if (c == 'e') {
183                                                 echo(c);
184                                                 LoadChar(c);
185                                                 if (c == '+' || c == '-') {
186                                                         echo(c);
187                                                         LoadChar(c);
188                                                 }
189                                                 if (is_dig(c)) getdec(c);
190                                         }
191                                 }
192                                 else {
193                                         echo(c);
194                                         LoadChar(c);
195                                         if (c == 'x' || c == 'X') gethex(c);
196                                         else if (is_dig(c)) getdec(c);
197                                 }
198                                 continue;
199                             case STIDF: {
200                                 extern int idfsize;             /* ??? */
201                                 char buf[IDFSIZE + 1];
202                                 register char *tg = &buf[0];
203                                 register char *maxpos = &buf[idfsize];
204                                 register struct idf *idef;
205
206 #define tstmac(bx)      if (!(bits[c] & bx)) goto nomac
207 #define cpy             if (Unstacked) EnableMacros(); *tg++ = c
208 #define load            LoadChar(c); if (!in_idf(c)) goto endidf
209
210 #ifdef DOBITS
211                                 cpy; tstmac(bit0); load;
212                                 cpy; tstmac(bit1); load;
213                                 cpy; tstmac(bit2); load;
214                                 cpy; tstmac(bit3); load;
215                                 cpy; tstmac(bit4); load;
216                                 cpy; tstmac(bit5); load;
217                                 cpy; tstmac(bit6); load;
218                                 cpy; tstmac(bit7); load;
219 #endif
220
221                                 for(;;) {
222                                         if (tg < maxpos) {
223                                                 cpy;
224                                         }
225                                         else break;
226                                         load;
227                                 }
228                         endidf:
229                                 PushBack();
230                                 *tg = '\0';     /* mark the end of the identifier */
231                                 idef = findidf(buf);
232                                 if (idef && idef->id_macro) {
233                                         do {
234                                                 LoadChar(c);
235                                         } while  (in_idf(c));
236                                         PushBack();
237                                         if (replace(idef)) {
238                                                 LoadChar(c);
239                                                 continue;
240                                         }
241                                 }
242                         nomac:
243                                 *tg = 0;
244                                 tg = buf;
245                                 while (*tg) {
246                                         echo(*tg++);
247                                 }
248                                 LoadChar(c);
249                                 while (in_idf(c)) {
250                                         echo(c);
251                                         LoadChar(c);
252                                 }
253                                 continue;
254                                 }
255                             default:
256                                 echo(c);
257                                 LoadChar(c);
258                                 continue;
259                         }
260                         break;
261                 }
262         }
263         /*NOTREACHED*/
264 }