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 1 --  Top End.
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 "notice.h"
10
#include "cc.h"
11
 
12
/*
13
** miscellaneous storage
14
*/
15
int
16
  nogo,     /* disable goto statements? */
17
  noloc,    /* disable block locals? */
18
  opindex,  /* index to matched operator */
19
  opsize,   /* size of operator in characters */
20
  swactive, /* inside a switch? */
21
  swdefault,/* default label #, else 0 */
22
 *swnext,   /* address of next entry */
23
 *swend,    /* address of last entry */
24
 *stage,    /* staging buffer address */
25
 *wq,       /* while queue */
26
  argcs,    /* static argc */
27
 *argvs,    /* static argv */
28
 *wqptr,    /* ptr to next entry */
29
  litptr,   /* ptr to next entry */
30
  macptr,   /* macro buffer index */
31
  pptr,     /* ptr to parsing buffer */
32
  ch,       /* current character of input line */
33
  nch,      /* next character of input line */
34
  declared, /* # of local bytes to declare, -1 when declared */
35
  iflevel,  /* #if... nest level */
36
  skiplevel,/* level at which #if... skipping started */
37
  nxtlab,   /* next avail label # */
38
  litlab,   /* label # assigned to literal pool */
39
  csp,      /* compiler relative stk ptr */
40
  argstk,   /* function arg sp */
41
  argtop,   /* highest formal argument offset */
42
  ncmp,     /* # open compound statements */
43
  errflag,  /* true after 1st error in statement */
44
  eof,      /* true on final input eof */
45
  output,   /* fd for output file */
46
  files,    /* true if file list specified on cmd line */
47
  filearg = 0,   /* cur file arg index */
48
  input   = EOF, /* fd for input file */
49
  input2  = EOF, /* fd for "#include" file */
50
  usexpr  = YES, /* true if value of expression is used */
51
  ccode   = YES, /* true while parsing C code */
52
 *snext,    /* next addr in stage */
53
 *stail,    /* last addr of data in stage */
54
 *slast,    /* last addr in stage */
55
  listfp,   /* file pointer to list device */
56
  lastst,   /* last parsed statement type */
57
  oldseg;   /* current segment (0, DATASEG, CODESEG) */
58
 
59
char
60
  optimize, /* optimize output of staging buffer? */
61
  alarm,    /* audible alarm on errors? */
62
  monitor,  /* monitor function headers? */
63
  pause,    /* pause for operator on errors? */
64
 *symtab,   /* symbol table */
65
 *litq,     /* literal pool */
66
 *macn,     /* macro name buffer */
67
 *macq,     /* macro string buffer */
68
 *pline,    /* parsing buffer */
69
 *mline,    /* macro buffer */
70
 *line,     /* ptr to pline or mline */
71
 *lptr,     /* ptr to current character in "line" */
72
 *glbptr,   /* global symbol table */
73
 *locptr,   /* next local symbol table entry */
74
  quote[2] = {'"'}, /* literal string for '"' */
75
 *cptr,     /* work ptrs to any char buffer */
76
 *cptr2,
77
 *cptr3,
78
  msname[NAMESIZE],   /* macro symbol name */
79
  ssname[NAMESIZE];   /* static symbol name */
80
 
81
int op[16] = {   /* p-codes of signed binary operators */
82
  OR12,                        /* level5 */
83
  XOR12,                       /* level6 */
84
  AND12,                       /* level7 */
85
  EQ12,   NE12,                /* level8 */
86
  LE12,   GE12,  LT12,  GT12,  /* level9 */
87
  ASR12,  ASL12,               /* level10 */
88
  ADD12,  SUB12,               /* level11 */
89
  MUL12, DIV12, MOD12          /* level12 */
90
  };
91
 
92
int op2[16] = {  /* p-codes of unsigned binary operators */
93
  OR12,                        /* level5 */
94
  XOR12,                       /* level6 */
95
  AND12,                       /* level7 */
96
  EQ12,   NE12,                /* level8 */
97
  LE12u,  GE12u, LT12u, GT12u, /* level9 */
98
  ASR12,  ASL12,               /* level10 */
99
  ADD12,  SUB12,               /* level11 */
100
  MUL12u, DIV12u, MOD12u       /* level12 */
101
  };
102
 
103
/*
104
** execution begins here
105
*/
106
main(argc, argv) int argc, *argv; {
107
  fputs(VERSION, stdout);
108
  fputs(CRIGHT1, stdout);
109
  fputs(CRIGHT2, stdout);
110
  argcs   = argc;
111
  argvs   = argv;
112
  swnext  = calloc(SWTABSZ, 1);
113
  swend   = swnext+(SWTABSZ-SWSIZ);
114
  stage   = calloc(STAGESIZE, 2*INTSIZE);
115
  wqptr   =
116
  wq      = calloc(WQTABSZ, INTSIZE);
117
  litq    = calloc(LITABSZ, 1);
118
  macn    = calloc(MACNSIZE, 1);
119
  macq    = calloc(MACQSIZE, 1);
120
  pline   = calloc(LINESIZE, 1);
121
  mline   = calloc(LINESIZE, 1);
122
  slast   = stage+(STAGESIZE*2*INTSIZE);
123
  symtab  = calloc((NUMLOCS*SYMAVG + NUMGLBS*SYMMAX), 1);
124
  locptr  = STARTLOC;
125
  glbptr  = STARTGLB;
126
 
127
  ask();          /* get user options */
128
  openfile();     /* and initial input file */
129
  preprocess();   /* fetch first line */
130
  header();       /* intro code */
131
  setcodes();     /* initialize code pointer array */
132
  parse();        /* process ALL input */
133
  trailer();      /* follow-up code */
134
  fclose(output); /* explicitly close output */
135
  }
136
 
137
/******************** high level parsing *******************/
138
 
139
/*
140
** process all input text
141
**
142
** At this level, only static declarations,
143
**      defines, includes and function
144
**      definitions are legal...
145
*/
146
parse() {
147
  while (eof == 0) {
148
    if     (amatch("extern", 6)) dodeclare(EXTERNAL);
149
    else if(dodeclare(STATIC))   ;
150
    else if( match("#asm"))      doasm();
151
    else if( match("#include"))  doinclude();
152
    else if( match("#define"))   dodefine();
153
    else                         dofunction();
154
    blanks();                 /* force eof if pending */
155
    }
156
  }
157
 
158
/*
159
** test for global declarations
160
*/
161
dodeclare(class) int class; {
162
  if     (amatch("char",     4))  declglb(CHR,  class);
163
  else if(amatch("unsigned", 8)) {
164
    if   (amatch("char",     4))  declglb(UCHR, class);
165
    else {amatch("int",      3);  declglb(UINT, class);}
166
    }
167
  else if(amatch("int",      3)
168
       || class == EXTERNAL)      declglb(INT,  class);
169
  else return 0;
170
  ns();
171
  return 1;
172
  }
173
 
174
/*
175
** declare a static variable
176
*/
177
declglb(type, class)
178
int type, class;
179
  {
180
    int id, dim;
181
 
182
    while(1)
183
      {
184
	if(endst())
185
	  return;  /* do line */
186
	if(match("*"))
187
	  {
188
	    id = POINTER;  dim = 0;
189
	  }
190
	else
191
	  {
192
	    id = VARIABLE; dim = 1;
193
	  }
194
	if(symname(ssname) == 0)
195
	  illname();
196
	if(findglb(ssname))
197
	  multidef(ssname);
198
	if(id == VARIABLE)
199
	  {
200
	    if (match("("))
201
	      {
202
		id = FUNCTION; need(")");
203
	      }
204
	    else if(match("["))
205
	      {
206
		id = ARRAY; dim = needsub();
207
	      }
208
	  }
209
	if (class == EXTERNAL)
210
	  external(ssname, type >> 2, id);
211
	else if (id != FUNCTION)
212
	  initials(type >> 2, id, dim);
213
	if(id == POINTER)
214
	  addsym(ssname, id, type, PTRSIZE, 0, &glbptr, class);
215
	else
216
	  addsym(ssname, id, type, dim * (type >> 2), 0, &glbptr, class);
217
	if(match(",") == 0)
218
	  return;
219
      }
220
  }
221
 
222
/*
223
** initialize global objects
224
*/
225
initials(size, ident, dim) int size, ident, dim; {
226
  int savedim;
227
  litptr = 0;
228
  if(dim == 0) dim = -1;         /* *... or ...[] */
229
  savedim = dim;
230
/*  public(ident); */
231
  if(match("=")) {
232
    if(match("{")) {
233
      while(dim) {
234
        init(size, ident, &dim);
235
        if(match(",") == 0) break;
236
        }
237
      need("}");
238
      }
239
    else init(size, ident, &dim);
240
    }
241
  if(savedim == -1 && dim == -1) {
242
    if(ident == ARRAY) error("need array size");
243
    stowlit(0, size = PTRSIZE);
244
    }
245
 
246
/* FASM */
247
  public(ident);
248
  if(litptr>0) dumplits(size);
249
  else if(dim>0)
250
  {/*In FASM: ": TIMES  D 0" */
251
   fputc(':',output);
252
  }
253
  dumpzero(size, dim);           /* only if dim > 0 */
254
/* FASM */
255
  }
256
 
257
/*
258
** evaluate one initializer
259
*/
260
init(size, ident, dim) int size, ident, *dim; {
261
  int value;
262
  if(string(&value)) {
263
    if(ident == VARIABLE || size != 1)
264
      error("must assign to char pointer or char array");
265
    *dim -= (litptr - value);
266
    if(ident == POINTER) point();
267
    }
268
  else if(constexpr(&value)) {
269
    if(ident == POINTER) error("cannot assign to pointer");
270
    stowlit(value, size);
271
    *dim -= 1;
272
    }
273
  }
274
 
275
/*
276
** get required array size
277
*/
278
needsub()  {
279
  int val;
280
  if(match("]")) return 0; /* null size */
281
  if(constexpr(&val) == 0) val = 1;
282
  if(val < 0) {
283
    error("negative size illegal");
284
    val = -val;
285
    }
286
  need("]");               /* force single dimension */
287
  return val;              /* and return size */
288
  }
289
 
290
/*
291
** open an include file
292
*/
293
doinclude() {
294
  int i; char str[30];
295
  blanks();       /* skip over to name */
296
  if(*lptr == '"' || *lptr == '<') ++lptr;
297
  i = 0;
298
  while(lptr[i]
299
     && lptr[i] != '"'
300
     && lptr[i] != '>'
301
     && lptr[i] != '\n') {
302
    str[i] = lptr[i];
303
    ++i;
304
    }
305
  str[i] = NULL;
306
  if((input2 = fopen(str,"r")) == NULL) {
307
    input2 = EOF;
308
    error("open failure on include file");
309
    }
310
  kill();   /* make next read come from new file (if open) */
311
  }
312
 
313
/*
314
** define a macro symbol
315
*/
316
dodefine() {
317
  int k;
318
  if(symname(msname) == 0) {
319
    illname();
320
    kill();
321
    return;
322
    }
323
/*
324
  puts (msname);
325
  puts (" is #defined\n");
326
*/
327
  k = 0;
328
  if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0) == 0) {
329
    if(cptr2 = cptr)
330
      while(*cptr2++ = msname[k++]) ;
331
    else {
332
      error("macro name table full");
333
      return;
334
      }
335
    }
336
  putint(macptr, cptr+NAMESIZE, 2 /*INTSIZE*/);
337
  while(white()) gch();
338
  while(putmac(gch()));
339
  if(macptr >= MACMAX) {
340
    error("macro string queue full");
341
    exit(ERRCODE);
342
    }
343
  }
344
 
345
putmac(c)  char c; {
346
  macq[macptr] = c;
347
  if(macptr < MACMAX) ++macptr;
348
  return c;
349
  }
350
 
351
/*
352
** begin a function
353
**
354
** called from "parse" and tries to make a function
355
** out of the following text
356
*/
357
dofunction()  {
358
  char *ptr;
359
  nogo   =                      /* enable goto statements */
360
  noloc  =                      /* enable block-local declarations */
361
  lastst =                      /* no statement yet */
362
  litptr = 0;                   /* clear lit pool */
363
  litlab = getlabel();          /* label next lit pool */
364
  locptr = STARTLOC;            /* clear local variables */
365
  if(match("void")) blanks();   /* skip "void" & locate header */
366
  if(monitor) lout(line, stderr);
367
  if(symname(ssname) == 0) {
368
    error("illegal function or declaration");
369
    errflag = 0;
370
    kill();                     /* invalidate line */
371
    return;
372
    }
373
  if(ptr = findglb(ssname)) {   /* already in symbol table? */
374
    if(ptr[CLASS] == AUTOEXT)
375
         ptr[CLASS] = STATIC;
376
    else multidef(ssname);
377
    }
378
  else addsym(ssname, FUNCTION, INT, 0, 0, &glbptr, STATIC);
379
  public(FUNCTION);
380
  argstk = 0;                  /* init arg count */
381
  if(match("(") == 0) error("no open paren");
382
  while(match(")") == 0) {     /* then count args */
383
    if(symname(ssname)) {
384
      if(findloc(ssname)) multidef(ssname);
385
      else {
386
        addsym(ssname, 0, 0, 0, argstk, &locptr, AUTOMATIC);
387
        argstk += INTSIZE;
388
        }
389
      }
390
    else {
391
      error("illegal argument name");
392
      skip();
393
      }
394
    blanks();
395
    if(streq(lptr,")") == 0 && match(",") == 0)
396
      error("no comma");
397
    if(endst()) break;
398
    }
399
  csp = 0;                     /* preset stack ptr */
400
  argtop = argstk+INTSIZE;         /* account for the pushed BP */
401
  while(argstk) {
402
    if     (amatch("char",     4)) {doargs(CHR);  ns();}
403
    else if(amatch("int",      3)) {doargs(INT);  ns();}
404
    else if(amatch("unsigned", 8)) {
405
      if   (amatch("char", 4))     {doargs(UCHR); ns();}
406
      else {amatch("int", 3);       doargs(UINT); ns();}
407
      }
408
    else {error("wrong number of arguments"); break;}
409
    }
410
  gen(ENTER, 0);
411
  statement();
412
  if(lastst != STRETURN && lastst != STGOTO)
413
    gen(RETURN, 0);
414
  if(litptr) {
415
    toseg(DATASEG);
416
    gen(REFm, litlab);
417
    dumplits(1);               /* dump literals */
418
    }
419
  }
420
 
421
/*
422
** declare argument types
423
*/
424
doargs(type) int type; {
425
  int id, sz;
426
  char c, *ptr;
427
  while(1) {
428
    if(argstk == 0) return;           /* no arguments */
429
    if(decl(type, POINTER, &id, &sz)) {
430
      if(ptr = findloc(ssname)) {
431
        ptr[IDENT] = id;
432
        ptr[TYPE]  = type;
433
        putint(sz, ptr+SIZE, INTSIZE);
434
        putint(argtop-getint(ptr+OFFSET, INTSIZE), ptr+OFFSET, INTSIZE);
435
        }
436
      else error("not an argument");
437
      }
438
    argstk = argstk - INTSIZE;            /* cnt down */
439
    if(endst()) return;
440
    if(match(",") == 0) error("no comma");
441
    }
442
  }
443
 
444
/*
445
** parse next local or argument declaration
446
*/
447
decl(type, aid, id, sz)
448
int type, aid, *id, *sz;
449
{
450
  int n, p;
451
  int mod;
452
  if(match("(")) p = 1;
453
  else           p = 0;
454
  if(match("*"))        {*id = POINTER;  *sz  = PTRSIZE;}
455
  else                  {*id = VARIABLE; *sz  = type >> 2;}
456
  if((n = symname(ssname)) == 0) illname();
457
  if(p && match(")")) ;
458
  if(match("("))
459
    {
460
      if(!p || *id != POINTER)
461
	error("try (*...)()");
462
      need(")");
463
    }
464
  else if(*id == VARIABLE && match("["))
465
    {
466
      *id = aid;
467
      if((*sz *= needsub()) == 0)
468
	{
469
	  if(aid == ARRAY) error("need array size");
470
	  *sz  = PTRSIZE;      /* size of pointer argument */
471
	}
472
    }
473
  mod = *sz % ALIGN;
474
 
475
  if (mod)
476
    {
477
      *sz = *sz + (ALIGN-mod);
478
    }
479
  return n;
480
  }
481
 
482
/******************** start 2nd level parsing *******************/
483
 
484
/*
485
** statement parser
486
*/
487
statement() {
488
  if(ch == 0 && eof) return;
489
  else if(amatch("char",     4)) {declloc(CHR);    ns();}
490
  else if(amatch("int",      3)) {declloc(INT);    ns();}
491
  else if(amatch("unsigned", 8)) {
492
    if   (amatch("char",     4)) {declloc(UCHR);   ns();}
493
    else {amatch("int",      3);  declloc(UINT);   ns();}
494
    }
495
  else {
496
    if(declared >= 0) {
497
      if(ncmp > 1) nogo = declared;   /* disable goto */
498
      gen(ADDSP, csp - declared);
499
      declared = -1;
500
      }
501
    if(match("{"))                 compound();
502
    else if(amatch("if",       2)) {doif();           lastst = STIF;}
503
    else if(amatch("while",    5)) {dowhile();        lastst = STWHILE;}
504
    else if(amatch("do",       2)) {dodo();           lastst = STDO;}
505
    else if(amatch("for",      3)) {dofor();          lastst = STFOR;}
506
    else if(amatch("switch",   6)) {doswitch();       lastst = STSWITCH;}
507
    else if(amatch("case",     4)) {docase();         lastst = STCASE;}
508
    else if(amatch("default",  7)) {dodefault();      lastst = STDEF;}
509
    else if(amatch("goto",     4)) {dogoto();         lastst = STGOTO;}
510
    else if(dolabel())                                lastst = STLABEL;
511
    else if(amatch("return",   6)) {doreturn(); ns(); lastst = STRETURN;}
512
    else if(amatch("break",    5)) {dobreak();  ns(); lastst = STBREAK;}
513
    else if(amatch("continue", 8)) {docont();   ns(); lastst = STCONT;}
514
    else if(match(";"))            errflag = 0;
515
    else if(match("#asm"))         {doasm();          lastst = STASM;}
516
    else                           {doexpr(NO); ns(); lastst = STEXPR;}
517
    }
518
  return lastst;
519
  }
520
 
521
/*
522
** declare local variables
523
*/
524
declloc(type)  int type;  {
525
  int id, sz;
526
  if(swactive)     error("not allowed in switch");
527
  if(noloc)        error("not allowed with goto");
528
  if(declared < 0) error("must declare first in block");
529
  while(1) {
530
    if(endst()) return;
531
    decl(type, ARRAY, &id, &sz);
532
    declared += sz;
533
    addsym(ssname, id, type,  sz, csp - declared, &locptr, AUTOMATIC);
534
    if(match(",") == 0) return;
535
    }
536
  }
537
 
538
compound()  {
539
  int savcsp;
540
  char *savloc;
541
  savcsp = csp;
542
  savloc = locptr;
543
  declared = 0;           /* may now declare local variables */
544
  ++ncmp;                 /* new level open */
545
  while (match("}") == 0)
546
    if(eof) {
547
      error("no final }");
548
      break;
549
      }
550
    else statement();     /* do one */
551
  if(--ncmp               /* close current level */
552
  && lastst != STRETURN
553
  && lastst != STGOTO)
554
    gen(ADDSP, savcsp);   /* delete local variable space */
555
  cptr = savloc;          /* retain labels */
556
  while(cptr < locptr) {
557
    cptr2 = nextsym(cptr);
558
    if(cptr[IDENT] == LABEL) {
559
      while(cptr < cptr2) *savloc++ = *cptr++;
560
      }
561
    else cptr = cptr2;
562
    }
563
  locptr = savloc;        /* delete local symbols */
564
  declared = -1;          /* may not declare variables */
565
  }
566
 
567
doif()  {
568
  int flab1, flab2;
569
  test(flab1 = getlabel(), YES);  /* get expr, and branch false */
570
  statement();                    /* if true, do a statement */
571
  if(amatch("else", 4) == 0) {    /* if...else ? */
572
    /* simple "if"...print false label */
573
    gen(LABm, flab1);
574
    return;                       /* and exit */
575
    }
576
  flab2 = getlabel();
577
  if(lastst != STRETURN && lastst != STGOTO)
578
    gen(JMPm, flab2);
579
  gen(LABm, flab1);    /* print false label */
580
  statement();         /* and do "else" clause */
581
  gen(LABm, flab2);    /* print true label */
582
  }
583
 
584
dowhile()  {
585
  int wq[4];              /* allocate local queue */
586
  addwhile(wq);           /* add entry to queue for "break" */
587
  gen(LABm, wq[WQLOOP]);  /* loop label */
588
  test(wq[WQEXIT], YES);  /* see if true */
589
  statement();            /* if so, do a statement */
590
  gen(JMPm, wq[WQLOOP]);  /* loop to label */
591
  gen(LABm, wq[WQEXIT]);  /* exit label */
592
  delwhile();             /* delete queue entry */
593
  }
594
 
595
dodo() {
596
  int wq[4];
597
  addwhile(wq);
598
  gen(LABm, wq[WQLOOP]);
599
  statement();
600
  need("while");
601
  test(wq[WQEXIT], YES);
602
  gen(JMPm, wq[WQLOOP]);
603
  gen(LABm, wq[WQEXIT]);
604
  delwhile();
605
  ns();
606
  }
607
 
608
dofor() {
609
  int wq[4], lab1, lab2;
610
  addwhile(wq);
611
  lab1 = getlabel();
612
  lab2 = getlabel();
613
  need("(");
614
  if(match(";") == 0) {
615
    doexpr(NO);           /* expr 1 */
616
    ns();
617
    }
618
  gen(LABm, lab1);
619
  if(match(";") == 0) {
620
    test(wq[WQEXIT], NO); /* expr 2 */
621
    ns();
622
    }
623
  gen(JMPm, lab2);
624
  gen(LABm, wq[WQLOOP]);
625
  if(match(")") == 0) {
626
    doexpr(NO);           /* expr 3 */
627
    need(")");
628
    }
629
  gen(JMPm, lab1);
630
  gen(LABm, lab2);
631
  statement();
632
  gen(JMPm, wq[WQLOOP]);
633
  gen(LABm, wq[WQEXIT]);
634
  delwhile();
635
  }
636
 
637
doswitch() {
638
  int wq[4], endlab, swact, swdef, *swnex, *swptr;
639
  swact = swactive;
640
  swdef = swdefault;
641
  swnex = swptr = swnext;
642
  addwhile(wq);
643
  *(wqptr + WQLOOP - WQSIZ) = 0;
644
  need("(");
645
  doexpr(YES);                /* evaluate switch expression */
646
  need(")");
647
  swdefault = 0;
648
  swactive = 1;
649
  gen(JMPm, endlab = getlabel());
650
  statement();                /* cases, etc. */
651
  gen(JMPm, wq[WQEXIT]);
652
  gen(LABm, endlab);
653
  gen(SWITCH, 0);             /* match cases */
654
  while(swptr < swnext) {
655
    gen(NEARm, *swptr++);
656
#ifdef INT32
657
    gen(DWORDn, *swptr++);    /* case value */
658
#else
659
    gen(WORDn,  *swptr++);    /* case value */
660
#endif
661
    }
662
#ifdef INT32
663
  gen(DWORDn, 0);
664
#else
665
  gen(WORDn, 0);
666
#endif
667
  if(swdefault) gen(JMPm, swdefault);
668
  gen(LABm, wq[WQEXIT]);
669
  delwhile();
670
  swnext    = swnex;
671
  swdefault = swdef;
672
  swactive  = swact;
673
  }
674
 
675
docase() {
676
  if(swactive == 0) error("not in switch");
677
  if(swnext > swend) {
678
    error("too many cases");
679
    return;
680
    }
681
  gen(LABm, *swnext++ = getlabel());
682
  constexpr(swnext++);
683
  need(":");
684
  }
685
 
686
dodefault() {
687
  if(swactive) {
688
    if(swdefault) error("multiple defaults");
689
    }
690
  else error("not in switch");
691
  need(":");
692
  gen(LABm, swdefault = getlabel());
693
  }
694
 
695
dogoto() {
696
  if(nogo > 0) error("not allowed with block-locals");
697
  else noloc = 1;
698
  if(symname(ssname)) gen(JMPm, addlabel(NO));
699
  else error("bad label");
700
  ns();
701
  }
702
 
703
dolabel() {
704
  char *savelptr;
705
  blanks();
706
  savelptr = lptr;
707
  if(symname(ssname)) {
708
    if(gch() == ':') {
709
      gen(LABm, addlabel(YES));
710
      return 1;
711
      }
712
    else bump(savelptr-lptr);
713
    }
714
  return 0;
715
  }
716
 
717
addlabel(def) int def; {
718
  if(cptr = findloc(ssname)) {
719
    if(cptr[IDENT] != LABEL) error("not a label");
720
    else if(def) {
721
      if(cptr[TYPE]) error("duplicate label");
722
      else cptr[TYPE] = YES;
723
      }
724
    }
725
  else cptr = addsym(ssname, LABEL, def, 0, getlabel(), &locptr, LABEL);
726
  return (getint(cptr+OFFSET, INTSIZE));
727
  }
728
 
729
doreturn()  {
730
  int savcsp;
731
  if(endst() == 0) doexpr(YES);
732
  savcsp = csp;
733
  gen(RETURN, 0);
734
  csp = savcsp;
735
  }
736
 
737
dobreak()  {
738
  int *ptr;
739
  if((ptr = readwhile(wqptr)) == 0) return;
740
  gen(ADDSP, ptr[WQSP]);
741
  gen(JMPm, ptr[WQEXIT]);
742
  }
743
 
744
docont()  {
745
  int *ptr;
746
  ptr = wqptr;
747
  while (1) {
748
    if((ptr = readwhile(ptr)) == 0) return;
749
    if(ptr[WQLOOP]) break;
750
    }
751
  gen(ADDSP, ptr[WQSP]);
752
  gen(JMPm, ptr[WQLOOP]);
753
  }
754
 
755
doasm()  {
756
  ccode = 0;           /* mark mode as "asm" */
757
  while (1) {
758
    inline();
759
    if(match("#endasm")) break;
760
    if(eof)break;
761
    fputs(line, output);
762
    }
763
  kill();
764
  ccode = 1;
765
  }
766
 
767
doexpr(use) int use; {
768
  int constant, val;
769
  int *before, *start;
770
  usexpr = use;        /* tell isfree() whether expr value is used */
771
  while(1) {
772
    setstage(&before, &start);
773
    expression(&constant, &val);
774
    clearstage(before, start);
775
    if(ch != ',') break;
776
    bump(1);
777
    }
778
  usexpr = YES;        /* return to normal value */
779
  }
780
 
781
/******************** miscellaneous functions *******************/
782
 
783
/*
784
** get run options
785
*/
786
ask()
787
  {
788
    int i;
789
    int j;
790
    i = listfp = nxtlab = 0;
791
    output = stdout;
792
#ifdef LATER
793
    optimize = YES;	// Not working for 32 bit int's yer
794
#else
795
    optimize = NO;
796
#endif
797
    alarm = monitor = pause = NO;
798
    line = mline;
799
    while(getarg(++i, line, LINESIZE, argcs, argvs) != EOF)
800
      {
801
	if(line[0] != '-' && line[0] != '/')
802
	  continue;
803
	if(toupper(line[1]) == 'L'	// List
804
	   && isdigit(line[2])
805
	   && line[3] <= ' ')
806
	  {
807
	    listfp = line[2]-'0';
808
	    continue;
809
	  }
810
	if(toupper(line[1]) == 'N'	// No optimize
811
	   && toupper(line[2]) == 'O'
812
	   && line[3] <= ' ')
813
	  {
814
	    optimize = NO;
815
	    continue;
816
	  }
817
	if(toupper(line[1]) == 'D')
818
	  {
819
	    j = 0;
820
	    ch = line[j+2];
821
	    lptr = line + j+2;
822
	    /*
823
	    while (line[j+2] != ' ')
824
	      {
825
		if (j < (NAMEMAX-1))
826
		  {
827
		    msname[j] = line[j+1];
828
		    ++j;
829
		  }
830
		else
831
		  {
832
		    break;
833
		  }
834
	      }
835
	    msname[j] = '\0';
836
	    */
837
	    dodefine ();
838
	    continue;
839
	  }
840
 
841
	if(line[2] <= ' ')
842
	  {
843
	    if(toupper(line[1]) == 'A') {alarm   = YES; continue;}
844
	    if(toupper(line[1]) == 'M') {monitor = YES; continue;}
845
	    if(toupper(line[1]) == 'P') {pause   = YES; continue;}
846
	  }
847
	fputs("usage: cc [file]... [-m] [-a] [-p] [-l#] [-no] [-d]\n", stderr);
848
	fputs(" -m     monitor\n", stderr);
849
	fputs(" -a     alarm\n", stderr);
850
	fputs(" -p     pause\n", stderr);
851
	fputs(" -l#    list\n", stderr);
852
	fputs(" -no    no optimize\n", stderr);
853
	fputs(" -d pre-#define id\n", stderr);
854
	exit(ERRCODE);
855
      }
856
  }
857
 
858
/*
859
** input and output file opens
860
*/
861
openfile() {        /* entire function revised */
862
  char outfn[15];
863
  int i, j, ext;
864
  input = EOF;
865
  while(getarg(++filearg, pline, LINESIZE, argcs, argvs) != EOF) {
866
    if(pline[0] == '-' || pline[0] == '/') continue;
867
    ext = NO;
868
    i = -1;
869
    j = 0;
870
    while(pline[++i]) {
871
      if(pline[i] == '.') {
872
        ext = YES;
873
        break;
874
        }
875
      if(j < 10) outfn[j++] = pline[i];
876
      }
877
    if(!ext) strcpy(pline + i, ".C");
878
    input = mustopen(pline, "r");
879
#ifdef _MSC_VER
880
 
881
    if(!files) {
882
      strcpy(outfn + j, ".ASM");
883
      output = mustopen(outfn, "w");
884
    }
885
 
886
#else
887
    if(!files /* && iscons(stdout)*/) {
888
      strcpy(outfn + j, ".ASM");
889
      output = mustopen(outfn, "w");
890
      }
891
#endif
892
    files = YES;
893
    kill();
894
    return;
895
    }
896
  if(files++) eof = YES;
897
  else input = stdin;
898
  kill();
899
  }
900
 
901
/*
902
** open a file with error checking
903
*/
904
mustopen(fn, mode) char *fn, *mode; {
905
  int fd;
906
  if(fd = fopen(fn, mode)) return fd;
907
  fputs("open error on ", stderr);
908
  lout(fn, stderr);
909
  exit(ERRCODE);
910
  }
911