Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
718 jacekm 1
/*
2
** Small-C Compiler -- Part 2 -- Front End and Miscellaneous.
3
** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix
4
** Copyright 1998 H T Walheim
5
** All rights reserved.
6
*/
7
 
8
#include 
9
#include "cc.h"
10
 
11
extern char
12
 *symtab, *macn, *macq, *pline, *mline,  optimize,
13
  alarm, *glbptr, *line, *lptr, *cptr, *cptr2,  *cptr3,
14
 *locptr, msname[NAMESIZE],  pause,  quote[2];
15
 
16
extern int
17
  *wq,  ccode,  ch,  csp,  eof,  errflag,  iflevel,
18
  input,  input2,  listfp,  macptr,  nch,
19
  nxtlab,  op[16],  opindex,  opsize,  output,  pptr,
20
  skiplevel,  *wqptr;
21
 
22
/********************** input functions **********************/
23
 
24
preprocess() {
25
  int k;
26
  char c;
27
  if(ccode) {
28
    line = mline;
29
    ifline();
30
    if(eof) return;
31
    }
32
  else {
33
    inline();
34
    return;
35
    }
36
  pptr = -1;
37
  while(ch != NEWLINE && ch) {
38
    if(white()) {
39
      keepch(' ');
40
      while(white()) gch();
41
      }
42
    else if(ch == '"') {
43
      keepch(ch);
44
      gch();
45
      while(ch != '"' || (*(lptr-1) == 92 && *(lptr-2) != 92)) {
46
        if(ch == NULL) {
47
          error("no quote");
48
          break;
49
          }
50
        keepch(gch());
51
        }
52
      gch();
53
      keepch('"');
54
      }
55
    else if(ch == 39) {
56
      keepch(39);
57
      gch();
58
      while(ch != 39 || (*(lptr-1) == 92 && *(lptr-2) != 92)) {
59
        if(ch == NULL) {
60
          error("no apostrophe");
61
          break;
62
          }
63
        keepch(gch());
64
        }
65
      gch();
66
      keepch(39);
67
      }
68
    else if(ch == '/' && nch == '*')
69
      {
70
	bump(2);
71
	while((ch == '*' && nch == '/') == 0)
72
	  {
73
	    if(ch)
74
	      bump(1);
75
	    else
76
	      {
77
		ifline();
78
		if(eof)
79
		  break;
80
	      }
81
	  }
82
	bump(2);
83
      }
84
    else  if(ch == '/' && nch == '/')
85
      {
86
	bump(2);
87
	while(ch != NEWLINE)
88
	  {
89
	    if(ch)
90
	      bump(1);
91
	    else
92
	      {
93
		if(eof)
94
		  break;
95
	      }
96
	  }
97
	bump(1);
98
      }
99
    else if(an(ch)) {
100
      k = 0;
101
      while(an(ch) && k < NAMEMAX) {
102
        msname[k++] = ch;
103
        gch();
104
        }
105
      msname[k] = NULL;
106
      if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)) {
107
        k = getint(cptr+NAMESIZE, 2/*INTSIZE*/);
108
        while(c = macq[k++]) keepch(c);
109
        while(an(ch)) gch();
110
        }
111
      else {
112
        k = 0;
113
        while(c = msname[k++]) keepch(c);
114
        }
115
      }
116
    else keepch(gch());
117
    }
118
  if(pptr >= LINEMAX) error("line too long");
119
  keepch(NULL);
120
  line = pline;
121
  bump(0);
122
  }
123
 
124
keepch(c)  char c; {
125
  if(pptr < LINEMAX) pline[++pptr] = c;
126
  }
127
 
128
ifline() {
129
  while(1) {
130
    inline();
131
    if(eof) return;
132
    if(match("#ifdef")) {
133
      ++iflevel;
134
      if(skiplevel) continue;
135
      symname(msname);
136
      if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0) == 0)
137
        skiplevel = iflevel;
138
      continue;
139
      }
140
    if(match("#ifndef")) {
141
      ++iflevel;
142
      if(skiplevel) continue;
143
      symname(msname);
144
      if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0))
145
        skiplevel = iflevel;
146
      continue;
147
      }
148
    if(match("#else")) {
149
      if(iflevel) {
150
        if(skiplevel == iflevel) skiplevel = 0;
151
        else if(skiplevel == 0)  skiplevel = iflevel;
152
        }
153
      else noiferr();
154
      continue;
155
      }
156
    if(match("#endif")) {
157
      if(iflevel) {
158
        if(skiplevel == iflevel) skiplevel = 0;
159
        --iflevel;
160
        }
161
      else noiferr();
162
      continue;
163
      }
164
    if(skiplevel) continue;
165
    if(ch == 0) continue;
166
    break;
167
    }
168
  }
169
 
170
inline() {           /* numerous revisions */
171
  int k, unit;
172
 
173
  if(input == EOF) openfile();
174
  if(eof) return;
175
  if((unit = input2) == EOF) unit = input;
176
  if(fgets(line, LINEMAX, unit) == NULL) {
177
    fclose(unit);
178
    if(input2 != EOF)
179
         input2 = EOF;
180
    else input  = EOF;
181
    *line = NULL;
182
    }
183
  else if(listfp)
184
    {
185
    if(listfp == output) fputc(';', output);
186
    fputs(line, listfp);
187
    }
188
#ifdef _MSC_VER
189
  else
190
    {
191
      fputc(';', output);
192
      fputs(line, output);
193
    }
194
#endif
195
  bump(0);
196
  }
197
 
198
inbyte()  {
199
  while(ch == 0) {
200
    if(eof) return 0;
201
    preprocess();
202
    }
203
  return gch();
204
  }
205
 
206
/********************* scanning functions ********************/
207
 
208
/*
209
** test if next input string is legal symbol name
210
*/
211
symname(sname) char *sname; {
212
  int k;char c;
213
  blanks();
214
  if(alpha(ch) == 0) return (*sname = 0);
215
  k = 0;
216
  while(an(ch)) {
217
    sname[k] = gch();
218
    if(k < NAMEMAX) ++k;
219
    }
220
  sname[k] = 0;
221
  return 1;
222
  }
223
 
224
need(str)  char *str; {
225
  if(match(str) == 0) error("missing token");
226
  }
227
 
228
ns()  {
229
  if(match(";") == 0) error("no semicolon");
230
  else errflag = 0;
231
  }
232
 
233
match(lit)  char *lit; {
234
  int k;
235
  blanks();
236
  if(k = streq(lptr, lit)) {
237
    bump(k);
238
    return 1;
239
    }
240
  return 0;
241
  }
242
 
243
streq(str1, str2)  char str1[], str2[]; {
244
  int k;
245
  k = 0;
246
  while (str2[k]) {
247
    if(str1[k] != str2[k]) return 0;
248
    ++k;
249
    }
250
  return k;
251
 }
252
 
253
amatch(lit, len)  char *lit; int len; {
254
  int k;
255
  blanks();
256
  if(k = astreq(lptr, lit, len)) {
257
    bump(k);
258
    return 1;
259
    }
260
  return 0;
261
 }
262
 
263
astreq(str1, str2, len)  char str1[], str2[]; int len; {
264
  int k;
265
  k = 0;
266
  while (k < len) {
267
    if(str1[k] != str2[k]) break;
268
    /*
269
    ** must detect end of symbol table names terminated by
270
    ** symbol length in binary
271
    */
272
    if(str2[k] < ' ') break;
273
    if(str1[k] < ' ') break;
274
    ++k;
275
    }
276
  if(an(str1[k]) || an(str2[k])) return 0;
277
  return k;
278
  }
279
 
280
nextop(list) char *list; {
281
  char op[4];
282
  opindex = 0;
283
  blanks();
284
  while(1) {
285
    opsize = 0;
286
    while(*list > ' ') op[opsize++] = *list++;
287
    op[opsize] = 0;
288
    if(opsize = streq(lptr, op))
289
      if(*(lptr+opsize) != '=' &&
290
         *(lptr+opsize) != *(lptr+opsize-1))
291
         return 1;
292
    if(*list) {
293
      ++list;
294
      ++opindex;
295
      }
296
    else return 0;
297
    }
298
  }
299
 
300
blanks() {
301
  while(1) {
302
    while(ch) {
303
      if(white()) gch();
304
      else return;
305
      }
306
    if(line == mline) return;
307
    preprocess();
308
    if(eof) break;
309
    }
310
  }
311
 
312
white() {
313
  return (*lptr <= ' ' && *lptr);
314
  }
315
 
316
gch() {
317
  int c;
318
  if(c = ch) bump(1);
319
  return c;
320
  }
321
 
322
bump(n) int n; {
323
  if(n) lptr += n;
324
  else  lptr  = line;
325
  if(ch = nch = *lptr) nch = *(lptr+1);
326
  }
327
 
328
kill() {
329
  *line = 0;
330
  bump(0);
331
  }
332
 
333
skip() {
334
  if(an(inbyte()))
335
       while(an(ch)) gch();
336
  else while(an(ch) == 0) {
337
    if(ch == 0) break;
338
    gch();
339
    }
340
  blanks();
341
  }
342
 
343
endst() {
344
  blanks();
345
  return (streq(lptr, ";") || ch == 0);
346
  }
347
 
348
/*********** symbol table management functions ***********/
349
 
350
addsym(sname, id, type, size, value, lgpp, class)
351
char *sname, id, type;
352
int size, value, *lgpp, class;
353
  {
354
    if(lgpp == &glbptr)
355
      {
356
	if(cptr2 = findglb(sname))
357
	  return cptr2;
358
	if(cptr == 0)
359
	  {
360
	    error("global symbol table overflow");
361
	    return 0;
362
	  }
363
      }
364
    else
365
      {
366
	if(locptr > (ENDLOC-SYMMAX))
367
	  {
368
	    error("local symbol table overflow");
369
	    exit(ERRCODE);
370
	  }
371
	cptr = *lgpp;
372
      }
373
    cptr[IDENT] = id;
374
    cptr[TYPE]  = type;
375
    cptr[CLASS] = class;
376
    putint(size, cptr + SIZE, INTSIZE);
377
    putint(value, cptr + OFFSET, INTSIZE);
378
    cptr3 = cptr2 = cptr + NAME;
379
    while(an(*sname))
380
      *cptr2++ = *sname++;
381
 
382
    if(lgpp == &locptr)
383
      {
384
	*cptr2 = cptr2 - cptr3;         /* set length */
385
	*lgpp = ++cptr2;
386
      }
387
    return cptr;
388
  }
389
 
390
/*
391
** search for symbol match
392
** on return cptr points to slot found or empty slot
393
*/
394
search(sname, buf, len, end, max, off)
395
  char *sname, *buf, *end;  int len, max, off; {
396
  cptr  =
397
  cptr2 = buf+((hash(sname)%(max-1))*len);
398
  while(*cptr != NULL) {
399
    if(astreq(sname, cptr+off, NAMEMAX)) return 1;
400
    if((cptr = cptr+len) >= end) cptr = buf;
401
    if(cptr == cptr2) return (cptr = 0);
402
    }
403
  return 0;
404
  }
405
 
406
hash(sname) char *sname; {
407
  int i, c;
408
  i = 0;
409
  while(c = *sname++) i = (i << 1) + c;
410
  return i;
411
  }
412
 
413
findglb(sname)  char *sname; {
414
  if(search(sname, STARTGLB, SYMMAX, ENDGLB, NUMGLBS, NAME))
415
    return cptr;
416
  return 0;
417
  }
418
 
419
findloc(sname)  char *sname;  {
420
  cptr = locptr - 1;  /* search backward for block locals */
421
  while(cptr > STARTLOC) {
422
    cptr = cptr - *cptr;
423
    if(astreq(sname, cptr, NAMEMAX)) return (cptr - NAME);
424
    cptr = cptr - NAME - 1;
425
    }
426
  return 0;
427
  }
428
 
429
nextsym(entry) char *entry; {
430
  entry = entry + NAME;
431
  while(*entry++ >= ' ');    /* find length byte */
432
  return entry;
433
  }
434
 
435
/******** while queue management functions *********/
436
 
437
addwhile(ptr)  int ptr[]; {
438
  int k;
439
  ptr[WQSP]   = csp;         /* and stk ptr */
440
  ptr[WQLOOP] = getlabel();  /* and looping label */
441
  ptr[WQEXIT] = getlabel();  /* and exit label */
442
  if(wqptr == WQMAX) {
443
    error("control statement nesting limit");
444
    exit(ERRCODE);
445
    }
446
  k = 0;
447
  while (k < WQSIZ) *wqptr++ = ptr[k++];
448
  }
449
 
450
readwhile(ptr) int *ptr; {
451
  if(ptr <= wq) {
452
    error("out of context");
453
    return 0;
454
    }
455
  else return (ptr - WQSIZ);
456
 }
457
 
458
delwhile() {
459
  if(wqptr > wq) wqptr -= WQSIZ;
460
  }
461
 
462
/****************** utility functions ********************/
463
 
464
/*
465
** test if c is alphabetic
466
*/
467
alpha(c)  char c; {
468
  return (isalpha(c) || c == '_');
469
  }
470
 
471
/*
472
** test if given character is alphanumeric
473
*/
474
an(c)  char c; {
475
  return (alpha(c) || isdigit(c));
476
  }
477
 
478
/*
479
** return next avail internal label number
480
*/
481
getlabel() {
482
  return(++nxtlab);
483
  }
484
 
485
/*
486
** get integer of length len from address addr
487
** (byte sequence set by "putint")
488
*/
489
getint(addr, len) char *addr; int len; {
490
  int i;
491
  i = *(addr + --len);  /* high order byte sign extended */
492
  while(len--) i = (i << 8) | *(addr + len) & 255;
493
  return i;
494
  }
495
 
496
/*
497
** put integer i of length len into address addr
498
** (low byte first)
499
*/
500
putint(i, addr, len) char *addr; int i, len; {
501
  while(len--) {
502
    *addr++ = i;
503
    i = i >> 8;
504
    }
505
  }
506
 
507
lout(line, fd) char *line; int fd; {
508
  fputs(line, fd);
509
  fputc(NEWLINE, fd);
510
  }
511
 
512
/******************* error functions *********************/
513
 
514
illname() {
515
  error("illegal symbol");
516
  skip();
517
  }
518
 
519
multidef(sname)  char *sname; {
520
  error("already defined");
521
  }
522
 
523
needlval() {
524
  error("must be lvalue");
525
  }
526
 
527
noiferr() {
528
  error("no matching #if...");
529
  errflag = 0;
530
  }
531
 
532
error(msg)
533
char msg[];
534
  {
535
    if(errflag)
536
      return;
537
    else
538
      errflag = 1;
539
 
540
    lout(line, stderr);
541
    errout(msg, stderr);
542
    if(alarm)
543
      fputc(7, stderr);
544
    if(pause)
545
      while(fgetc(stderr) != NEWLINE);
546
    if(listfp > 0)
547
      errout(msg, listfp);
548
  }
549
 
550
errout(msg, fp) char msg[]; int fp; {
551
  int k;
552
  k = line+2;
553
  while(k++ <= lptr) fputc(' ', fp);
554
  lout("/\\", fp);
555
  fputs("**** ", fp); lout(msg, fp);
556
  }
557