Pristine Ack-5.5
[Ack-5.5.git] / mach / proto / as / comm5.c
1 /* $Id: comm5.c,v 2.13 1994/06/24 13:22:08 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 /* @(#)comm5.c  1.1 */
7
8 #include        "comm0.h"
9 #include        "comm1.h"
10 #include        "y.tab.h"
11
12 extern YYSTYPE  yylval;
13
14 yylex()
15 {
16         register c;
17
18         if (pass == PASS_1) {
19                 /* scan the input file */
20                 do
21                         c = nextchar();
22                 while (isspace(c) && c != '\n');
23                 if (ISALPHA(c))
24                         c = inident(c);
25                 else if (isdigit(c))
26                         c = innumber(c);
27                 else switch (c) {
28                 case '=':
29                 case '<':
30                 case '>':
31                 case '|':
32                 case '&':
33                         c = induo(c); break;
34                 case ASC_SQUO:
35                 case ASC_DQUO:
36                         c = instring(c); break;
37                 case ASC_COMM:
38                         do
39                                 c = nextchar();
40                         while (c != '\n' && c != '\0');
41                         break;
42                 case CTRL('A'):
43                         c = CODE1; readcode(1); break;
44                 case CTRL('B'):
45                         c = CODE2; readcode(2); break;
46                 case CTRL('C'):
47                         c = CODE4; readcode(4); break;
48                 }
49
50                 /* produce the intermediate token file */
51                 if (c <= 0)
52                         return(0);
53                 if (c <= 127)
54                         putc(c, tempfile);
55                 else
56                         putval(c);
57         } else {
58                 /* read from intermediate token file */
59                 c = getc(tempfile);
60                 if (c == EOF)
61                         return(0);
62                 if (c > 127) {
63                         c += 128;
64                         c = getval(c);
65                 }
66         }
67         curr_token = c;
68         return(c);
69 }
70
71 putval(c)
72 {
73         register valu_t v;
74         register n = 0;
75         register char *p = 0;
76
77         assert(c >= 256 && c < 256+128);
78         switch (c) {
79         case CODE1:
80                 n = 1; goto putnum;
81         case CODE2:
82                 n = 2; goto putnum;
83         case CODE4:
84                 n = 4; goto putnum;
85         case NUMBER:
86                 v = yylval.y_valu;
87                 for (n = 0; n < sizeof(v); n++) {
88                         if (v == 0)
89                                 break;
90                         v >>= 8;
91                 }
92                 c = NUMBER0 + n;
93         putnum:
94                 putc(c-128, tempfile);
95                 v = yylval.y_valu;
96                 while (--n >= 0)
97                         putc((int) (v >> (n*8)), tempfile);
98                 return;
99         case IDENT:
100         case FBSYM:
101                 n = sizeof(item_t *);
102                 p = (char *) &yylval.y_item; break;
103 #ifdef ASLD
104         case MODULE:
105                 n = sizeof(char *);
106                 p = (char *) &yylval.y_strp; break;
107 #endif
108         case STRING:
109                 v = stringlen;
110                 putc(c-128, tempfile);
111                 for (n = 0; n < sizeof(v); n++) {
112                         if (v == 0)
113                                 break;
114                         v >>= 8;
115                 }
116                 c = NUMBER0 + n;
117                 putc(c-128, tempfile);
118                 v = stringlen;
119                 while (--n >= 0)
120                         putc((int) (v >> (n*8)), tempfile);
121                 p = stringbuf;
122                 n = stringlen;
123                 while (--n >= 0)
124                         putc(*p++, tempfile);
125                 return;
126         case OP_EQ:
127         case OP_NE:
128         case OP_LE:
129         case OP_GE:
130         case OP_LL:
131         case OP_RR:
132         case OP_OO:
133         case OP_AA:
134                 break;
135         default:
136                 n = sizeof(word_t);
137                 p = (char *) &yylval.y_word; break;
138         }
139         putc(c-128, tempfile);
140         while (--n >= 0)
141                 putc(*p++, tempfile);
142 }
143
144 getval(c)
145 {
146         register n = 0;
147         register valu_t v;
148         register char *p = 0;
149
150         switch (c) {
151         case CODE1:
152                 n = 1; goto getnum;
153         case CODE2:
154                 n = 2; goto getnum;
155         case CODE4:
156                 n = 4; goto getnum;
157         case NUMBER0:
158                 c = NUMBER; goto getnum;
159         case NUMBER1:
160                 n = 1; c = NUMBER; goto getnum;
161         case NUMBER2:
162                 n = 2; c = NUMBER; goto getnum;
163         case NUMBER3:
164                 n = 3; c = NUMBER; goto getnum;
165         case NUMBER:
166                 n = 4;
167         getnum:
168                 v = 0;
169                 while (--n >= 0) {
170                         v <<= 8;
171                         v |= getc(tempfile);
172                 }
173                 yylval.y_valu = v;
174                 return(c);
175         case IDENT:
176         case FBSYM:
177                 n = sizeof(item_t *);
178                 p = (char *) &yylval.y_item; break;
179 #ifdef ASLD
180         case MODULE:
181                 n = sizeof(char *);
182                 p = (char *) &yylval.y_strp; break;
183 #endif
184         case STRING:
185                 getval(getc(tempfile)+128);
186                 stringlen = n = yylval.y_valu;
187                 p = stringbuf;
188                 p[n] = '\0'; break;
189         case OP_EQ:
190         case OP_NE:
191         case OP_LE:
192         case OP_GE:
193         case OP_LL:
194         case OP_RR:
195         case OP_OO:
196         case OP_AA:
197                 break;
198         default:
199                 n = sizeof(word_t);
200                 p = (char *) &yylval.y_word; break;
201         }
202         while (--n >= 0)
203                 *p++ = getc(tempfile);
204         return(c);
205 }
206
207 /* ---------- lexical scan in pass 1 ---------- */
208
209 nextchar()
210 {
211         register c;
212
213         if (peekc != -1) {
214                 c = peekc;
215                 peekc = -1;
216                 return(c);
217         }
218 #ifdef ASLD
219         if (archmode && --archsize < 0)
220                 return(0);
221 #endif
222         if ((c = getc(input)) == EOF)
223                 return(0);
224         if (isascii(c) == 0)
225                 fatal("non-ascii character");
226 #ifdef LISTING
227         if (listflag & 0440)
228                 putc(c, listfile);
229 #endif
230         return(c);
231 }
232
233 readcode(n)
234 {
235         register c;
236
237         yylval.y_valu = 0;
238         do {
239                 if (
240 #ifdef ASLD
241                         (archmode && --archsize < 0)
242                         ||
243 #endif
244                         (c = getc(input)) == EOF
245                 )
246                         fatal("unexpected EOF in compact input");
247                 yylval.y_valu <<= 8;
248                 yylval.y_valu |= c;
249         } while (--n);
250 }
251
252 induo(c)
253 register c;
254 {
255         static short duo[] = {
256                 ('='<<8) | '=', OP_EQ,
257                 ('<'<<8) | '>', OP_NE,
258                 ('<'<<8) | '=', OP_LE,
259                 ('>'<<8) | '=', OP_GE,
260                 ('<'<<8) | '<', OP_LL,
261                 ('>'<<8) | '>', OP_RR,
262                 ('|'<<8) | '|', OP_OO,
263                 ('&'<<8) | '&', OP_AA,
264         };
265         register short *p;
266
267         c = (c<<8) | nextchar();
268         for (p = duo; *p; p++)
269                 if (*p++ == c)
270                         return(*p++);
271         peekc = c & 0377;
272         return(c>>8);
273 }
274
275 static char name[NAMEMAX+1];
276
277 inident(c)
278 register  c;
279 {
280         register char *p = name;
281         register item_t *ip;
282         register n = NAMEMAX;
283
284         do {
285                 if (--n >= 0)
286                         *p++ = c;
287                 c = nextchar();
288         } while (ISALNUM(c));
289         *p = '\0';
290         peekc = c;
291         ip = item_search(name);
292         if (ip == 0) {
293                 ip = item_alloc(S_UND);
294                 ip->i_name = remember(name);
295                 /* printf("ident %s %o\n", ip->i_name, ip); */
296                 unresolved++;
297                 item_insert(ip, H_LOCAL + (hashindex%H_SIZE));
298         } else if (hashindex < H_SIZE) {
299                 assert(H_KEY == 0);
300                 yylval.y_word = (word_t) ip->i_valu;
301                 return(ip->i_type);
302         }
303         yylval.y_item = ip;
304         return(IDENT);
305 }
306
307 #ifdef ASLD
308 char *
309 readident(c)
310 register c;
311 {
312         register n = NAMEMAX;
313         register char *p = name;
314
315         do {
316                 if (--n >= 0)
317                         *p++ = c;
318                 c = nextchar();
319         } while (ISALNUM(c));
320         *p++ = '\0';
321         peekc = c;
322         return(name);
323 }
324 #endif
325
326 innumber(c)
327 register c;
328 {
329         register char *p;
330         register radix;
331         static char num[20+1];
332
333         p = num;
334         radix = 20;
335         do {
336                 if (--radix < 0)
337                         fatal("number too long");
338                 if (isupper(c))
339                         c += ('a' - 'A');
340                 *p++ = c;
341                 c = nextchar();
342         } while (isalnum(c));
343         peekc = c;
344         *p = '\0';
345         c = *--p;
346         p = num;
347         radix = 10;
348         if (*p == '0') {
349                 radix = 8;
350                 p++;
351                 if (*p == 'x') {
352                         radix = 16;
353                         p++;
354                 } else if (*p == 'b') {
355                         radix = 2;
356                         p++;
357                 }
358         }
359         if (radix != 16 && (c == 'f' || c == 'b'))
360                 return(infbsym(num));
361         yylval.y_valu = 0;
362         while (c = *p++) {
363                 if (c > '9')
364                         c -= ('a' - '9' - 1);
365                 c -= '0';
366                 if ((unsigned)c >= radix)
367                         serror("digit exceeds radix");
368                 yylval.y_valu = yylval.y_valu * radix + c;
369         }
370         return(NUMBER);
371 }
372
373 instring(termc)
374 {
375         register char *p;
376         register c;
377         static int maxstring = 0;
378
379         if (! maxstring) {
380                 maxstring = STRINGMAX;
381                 if ((stringbuf = malloc(maxstring)) == 0) {
382                         fatal("out of memory");
383                 }
384         }
385         p = stringbuf;
386         for (;;) {
387                 c = nextchar();
388                 if (c == '\n' || c == '\0') {
389                         peekc = c;
390                         serror("non-terminated string");
391                         break;
392                 }
393                 if (c == termc)
394                         break;
395                 if (c == '\\')
396                         c = inescape();
397                 if (p >= &stringbuf[maxstring - 1]) {
398                         int cnt = p - stringbuf;
399
400                         if ((stringbuf = realloc(stringbuf, maxstring += 256)) == 0) {
401                                 fatal("out of memory");
402                         }
403                         p = stringbuf + cnt;
404                 }
405                 *p++ = c;
406         }
407         stringlen = p - stringbuf;
408         *p = '\0';
409         return(STRING);
410 }
411
412 inescape()
413 {
414         register c, j, r;
415
416         c = nextchar();
417         if (c >= '0' && c <= '7') {
418                 r = c - '0';
419                 for (j = 0; j < 2; j++) {
420                         c = nextchar();
421                         if (c < '0' || c > '7') {
422                                 peekc = c;
423                                 return(r);
424                         }
425                         r <<= 3;
426                         r += (c - '0');
427                 }
428                 return(r);
429         }
430         switch (c) {
431         case 'b':       return('\b');
432         case 'f':       return('\f');
433         case 'n':       return('\n');
434         case 'r':       return('\r');
435         case 't':       return('\t');
436         case '\'':      return('\'');
437         case '"':       return('"');
438         }
439         return(c);
440 }
441
442 infbsym(p)
443 register char *p;
444 {
445         register lab;
446         register item_t *ip;
447
448         lab = *p++ - '0';
449         if ((unsigned)lab < 10) {
450                 if (*p++ == 'f') {
451                         ip = fb_ptr[FB_FORW+lab];
452                         if (ip == 0) {
453                                 ip = fb_alloc(lab);
454                                 fb_ptr[FB_FORW+lab] = ip;
455                         }
456                         goto ok;
457                 }
458                 ip = fb_ptr[FB_BACK+lab];
459                 if (ip != 0 && *p == 0)
460                         goto ok;
461         }
462         serror("bad numeric label");
463         ip = fb_alloc(0);
464 ok:
465         yylval.y_item = ip;
466         return(FBSYM);
467 }
468
469 hash(p)
470 register char *p;
471 {
472         register unsigned short h;
473         register c;
474
475         h = 0;
476         while (c = *p++) {
477                 h <<= 2;
478                 h += c;
479         }
480         return(h % H_SIZE);
481 }
482
483 item_t *
484 item_search(p)
485 char *p;
486 {
487         register h;
488         register item_t *ip;
489
490         for (h = hash(p); h < H_TOTAL; h += H_SIZE) {
491                 ip = hashtab[h];
492                 while (ip != 0) {
493                         if (strcmp(p, ip->i_name) == 0)
494                                 goto done;
495                         ip = ip->i_next;
496                 }
497         }
498 done:
499         hashindex = h;
500         return(ip);
501 }
502
503 item_insert(ip, h)
504 item_t *ip;
505 {
506         ip->i_next = hashtab[h];
507         hashtab[h] = ip;
508 }
509
510 item_t *
511 item_alloc(typ)
512 {
513         register item_t *ip;
514         static nleft = 0;
515         static item_t *next;
516
517         if (--nleft < 0) {
518                 next = (item_t *) malloc(MEMINCR);
519                 if (next == 0)
520                         fatal("out of memory");
521                 nleft += (MEMINCR / sizeof(item_t));
522         }
523         ip = next++;
524         ip->i_next = 0;
525         ip->i_type = typ;
526         ip->i_name = 0;
527         ip->i_valu = 0;
528         return(ip);
529 }
530
531 item_t *
532 fb_alloc(lab)
533 register lab;
534 {
535         register item_t *ip, *p;
536
537         ip = item_alloc(S_UND);
538         p = fb_ptr[FB_TAIL+lab];
539         if (p == 0)
540                 fb_ptr[FB_HEAD+lab] = ip;
541         else
542                 p->i_next = ip;
543         fb_ptr[FB_TAIL+lab] = ip;
544         return(ip);
545 }
546
547 item_t *
548 fb_shift(lab)
549 register lab;
550 {
551         register item_t *ip;
552
553         ip = fb_ptr[FB_FORW+lab];
554         if (ip == 0)
555                 if (pass == PASS_1)
556                         ip = fb_alloc(lab);
557                 else
558                         ip = fb_ptr[FB_HEAD+lab];
559         fb_ptr[FB_BACK+lab] = ip;
560         fb_ptr[FB_FORW+lab] = ip->i_next;
561         return(ip);
562 }