Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom / main.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: main.c,v 3.44 1994/06/24 12:05:17 ceriel Exp $ */
6 /* MAIN PROGRAM */
7
8 #include        "lint.h"
9 #include        "nofloat.h"
10 #include        <system.h>
11 #include        "nopp.h"
12 #include        "target_sizes.h"
13 #include        "debug.h"
14 #include        "use_tmp.h"
15 #include        "inputtype.h"
16 #include        "input.h"
17 #include        "level.h"
18 #include        "idf.h"
19 #include        "arith.h"
20 #include        "type.h"
21 #include        "declar.h"
22 #include        "tokenname.h"
23 #include        "Lpars.h"
24 #include        "LLlex.h"
25 #include        <alloc.h>
26 #include        "specials.h"
27 #include        "noRoption.h"
28 #include        "nocross.h"
29 #include        "sizes.h"
30 #include        "align.h"
31 #include        "assert.h"
32 #include        "macro.h"
33
34 extern struct tokenname tkidf[], tkother[];
35 extern char *symbol2str();
36 extern char options[128];
37
38
39 #ifndef NOPP
40 int inc_pos = 1;                        /* place where next -I goes */
41 int inc_total = 0;
42 int inc_max;
43 char **inctable;
44
45 extern int do_dependencies;
46 extern char *dep_file;
47 static File *dep_fd = STDOUT;
48
49 extern char *getwdir();
50 #endif /* NOPP */
51
52 struct sp_id special_ids[] =    {
53         {"setjmp", SP_SETJMP},  /* non-local goto's are registered      */
54         {0, 0}
55 };
56
57 #ifndef NOCROSS
58 arith
59         short_size = SZ_SHORT,
60         word_size = SZ_WORD,
61         dword_size = (2 * SZ_WORD),
62         int_size = SZ_INT,
63         long_size = SZ_LONG,
64 #ifndef NOFLOAT
65         float_size = SZ_FLOAT,
66         double_size = SZ_DOUBLE,
67 #endif /* NOFLOAT */
68         pointer_size = SZ_POINTER;
69
70 int
71         short_align = AL_SHORT,
72         word_align = AL_WORD,
73         int_align = AL_INT,
74         long_align = AL_LONG,
75 #ifndef NOFLOAT
76         float_align = AL_FLOAT,
77         double_align = AL_DOUBLE,
78 #endif /* NOFLOAT */
79         pointer_align = AL_POINTER,
80         struct_align = AL_STRUCT,
81         union_align = AL_UNION;
82 #endif /* NOCROSS */
83
84 #ifndef NOPP
85 arith ifval;    /* ifval will contain the result of the #if expression  */
86 #endif /* NOPP */
87
88 char *prog_name;
89
90 main(argc, argv)
91         char *argv[];
92 {
93         /* parse and interpret the command line options */
94         prog_name = argv[0];
95
96         init_hmask();
97 #ifndef NOPP
98         inctable = (char **) Malloc(10 * sizeof(char *));
99         inctable[0] = "";
100         inctable[1] = "/usr/include";
101         inctable[2] = 0;
102         inc_total = 3;
103         inc_max = 10;
104
105         init_pp();      /* initialise the preprocessor macros   */
106 #endif /* NOPP */
107
108         /*      Note: source file "-" indicates that the source is supplied
109                 as standard input.  This is only allowed if INP_READ_IN_ONE is
110                 not defined!
111         */
112 #ifdef INP_READ_IN_ONE
113         while (argc > 1 && *argv[1] == '-')
114 #else /* INP_READ_IN_ONE */
115         while (argc > 1 && *argv[1] == '-' && argv[1][1] != '\0')
116 #endif /* INP_READ_IN_ONE */
117         {
118                 char *par = &argv[1][1];
119
120                 do_option(par);
121                 argc--, argv++;
122         }
123 #ifdef  LINT
124         lint_init();
125 #endif  /* LINT */
126         compile(argc - 1, &argv[1]);
127
128 #ifdef  DEBUG
129         hash_stat();
130 #endif  /* DEBUG */
131
132 #ifndef NOPP
133         if (do_dependencies) {
134             extern char *source;
135
136             list_dependencies(source);
137         }
138 #endif
139         sys_stop(err_occurred ? S_EXIT : S_END);
140         /*NOTREACHED*/
141 }
142
143 #ifndef NOPP
144
145 struct idf    *file_head;
146 extern char *strrindex();
147
148 list_dependencies(source)
149 char *source;
150 {
151     register struct idf *p = file_head;
152
153     if (source) {
154         register char *s = strrindex(source, '.');
155
156         if (s && *(s+1)) {
157             s++;
158             *s++ = 'o';
159             *s = '\0';
160             /* the source may be in another directory than the
161              * object generated, so don't include the pathname
162              * leading to it.
163              */
164             if (s = strrindex(source, '/')) {
165                 source = s + 1;
166             }
167         }
168         else source = 0;
169     }
170     if (dep_file && !sys_open(dep_file, OP_WRITE, &dep_fd)) {
171         fatal("could not open %s", dep_file);
172     }
173     while (p) {
174         ASSERT(p->id_resmac == K_FILE);
175         dependency(p->id_text, source);
176         p = (struct idf *) (p->id_file);
177     }
178 }
179
180 add_dependency(s)
181 char *s;
182 {
183     register struct idf *p = str2idf(s);
184     
185     if (! p->id_resmac) {
186         p->id_resmac = K_FILE;
187         p->id_file = (char *) file_head;
188         file_head = p;
189     }
190 }
191
192 dependency(s, source)
193 char *s, *source;
194 {
195     if (options['i'] && !strncmp(s, "/usr/include/", 13)) {
196         return;
197     }
198     if (options['m'] && source) {
199         fprint(dep_fd, "%s: %s\n", source, s);
200     }
201     else    fprint(dep_fd, "%s\n", s);
202 }
203
204 #endif /* NOPP */
205
206 char *source = 0;
207
208 char *nmlist = 0;
209
210 compile(argc, argv)
211         char *argv[];
212 {
213         char *result;
214 #ifndef LINT
215         register char *destination = 0;
216 #endif  /* LINT */
217
218 #ifdef DEBUG
219 #ifndef NOPP
220         int pp_only = options['E'] || options['P'] || options['C'];
221 #endif /* NOPP */
222 #endif
223
224         switch (argc) {
225         case 1:
226 #ifndef LINT
227 #ifdef DEBUG
228 #ifndef NOPP
229                 if (!pp_only)
230 #endif /* NOPP */
231 #endif
232                         fatal("%s: destination file not specified", prog_name);
233 #endif  /* LINT */
234                 break;
235
236 #ifndef LINT
237         case 2:
238                 destination = argv[1];
239                 break;
240         case 3:
241                 nmlist = argv[2];
242                 destination = argv[1];
243                 break;
244 #endif  /* LINT */
245
246         default:
247 #ifndef LINT
248                 fatal("use: %s source destination [namelist]", prog_name);
249 #else   /* LINT */
250                 fatal("use: %s source", prog_name);
251 #endif  /* LINT */
252                 break;
253         }
254
255         if (strcmp(argv[0], "-"))
256                 FileName = source = argv[0];
257         else {
258                 source = 0;
259                 FileName = "standard input";
260         }
261
262         if (!InsertFile(source, (char **) 0, &result)) /* read the source file  */
263                 fatal("%s: no source file %s\n", prog_name, FileName);
264         File_Inserted = 1;
265         init();
266         LineNumber = 0;
267         nestlow = -1;
268 #ifndef LINT
269         init_code(destination && strcmp(destination, "-") != 0 ?
270                                 destination : 0);
271 #endif
272 #ifndef NOPP
273         WorkingDir = getwdir(source);
274 #endif /* NOPP */
275         PushLex();                      /* initialize lex machine */
276
277 #ifdef DEBUG
278 #ifndef NOPP
279         if (pp_only) /* run the preprocessor as if it is stand-alone    */
280                 preprocess();
281         else
282 #endif /* NOPP */
283 #endif /* DEBUG */
284         {
285 #ifndef LINT
286                 /* compile the source text                      */
287                 C_program();
288 #ifdef PREPEND_SCOPES
289                 prepend_scopes();
290 #endif /* PREPEND_SCOPES */
291                 end_code();
292 #else   /* LINT */
293                 /* lint the source text                         */
294                 C_program();
295 #endif  /* LINT */
296
297 #ifdef  DEBUG
298                 if (options['u'])       {
299                         unstack_level();        /* unstack L_GLOBAL */
300                 }
301                 if (options['f'] || options['t'])
302                         dumpidftab("end of main", options['f'] ? 0 : 0);
303 #endif  /* DEBUG */
304         }
305         PopLex();
306 }
307
308 init()
309 {
310         init_cst();     /* initialize variables of "cstoper.c"          */
311         reserve(tkidf);         /* mark the C reserved words as such    */
312         init_specials(special_ids);     /* mark special ids as such     */
313
314 #ifndef NOROPTION
315         if (options['R'])
316                 reserve(tkother);
317 #endif
318
319         char_type = standard_type(CHAR, 0, 1, (arith)1);
320         uchar_type = standard_type(CHAR, UNSIGNED, 1, (arith)1);
321
322         short_type = standard_type(SHORT, 0, short_align, short_size);
323         ushort_type = standard_type(SHORT, UNSIGNED, short_align, short_size);
324
325         /*      Treat type `word' as `int', having its own size and
326                 alignment requirements.
327                 This type is transparent to the user.
328         */
329         word_type = standard_type(INT, 0, word_align, word_size);
330         uword_type = standard_type(INT, UNSIGNED, word_align, word_size);
331
332         int_type = standard_type(INT, 0, int_align, int_size);
333         uint_type = standard_type(INT, UNSIGNED, int_align, int_size);
334
335         long_type = standard_type(LONG, 0, long_align, long_size);
336         ulong_type = standard_type(LONG, UNSIGNED, long_align, long_size);
337
338 #ifndef NOFLOAT
339         float_type = standard_type(FLOAT, 0, float_align, float_size);
340         double_type = standard_type(DOUBLE, 0, double_align, double_size);
341 #endif /* NOFLOAT */
342         void_type = standard_type(VOID, 0, 1, (arith)0);
343         label_type = standard_type(LABEL, 0, 0, (arith)0);
344         error_type = standard_type(ERRONEOUS, 0, 1, (arith)1);
345
346         /*      Pointer Arithmetic type: all arithmetics concerning
347                 pointers is supposed to be performed in the
348                 pointer arithmetic type which is equal to either
349                 int_type or long_type, depending on the pointer_size
350         */
351         if ((int)pointer_size == (int)word_size)
352                 pa_type = word_type;
353         else
354         if ((int)pointer_size == (int)short_size)
355                 pa_type = short_type;
356         else
357         if ((int)pointer_size == (int)int_size)
358                 pa_type = int_type;
359         else
360         if ((int)pointer_size == (int)long_size)
361                 pa_type = long_type;
362         else
363                 fatal("pointer size incompatible with any integral size");
364
365         if ((int)int_size != (int)word_size)
366                 fatal("int_size and word_size are not equal");
367         if ((int)short_size > (int)int_size || (int)int_size > (int)long_size)
368                 fatal("sizes of short/int/long decreasing");
369
370         /* Build a type for function returning int, RM 13 */
371         funint_type = construct_type(FUNCTION, int_type, (arith)0);
372         string_type = construct_type(POINTER, char_type, (arith)0);
373
374         /* Define the standard type identifiers. */
375         add_def(str2idf("char"), TYPEDEF, char_type, L_UNIVERSAL);
376         add_def(str2idf("int"), TYPEDEF, int_type, L_UNIVERSAL);
377 #ifndef NOFLOAT
378         add_def(str2idf("float"), TYPEDEF, float_type, L_UNIVERSAL);
379         add_def(str2idf("double"), TYPEDEF, double_type, L_UNIVERSAL);
380 #endif /* NOFLOAT */
381         add_def(str2idf("void"), TYPEDEF, void_type, L_UNIVERSAL);
382         stack_level();
383 }
384
385 init_specials(si)
386         register struct sp_id *si;
387 {
388         while (si->si_identifier)       {
389                 struct idf *idf = str2idf(si->si_identifier);
390                 
391                 if (idf->id_special)
392                         fatal("maximum identifier length insufficient");
393                 idf->id_special = si->si_flag;
394                 si++;
395         }
396 }
397
398 #ifdef DEBUG
399 #ifndef NOPP
400 preprocess()
401 {
402         /*      preprocess() is the "stand-alone" preprocessor which
403                 consecutively calls the lexical analyzer LLlex() to get
404                 the tokens and prints them in a suitable way.
405         */
406         static unsigned int lastlineno = 0;
407         static char *lastfilenm = "";
408
409         while (LLlex() !=  EOI) {
410                 if (lastlineno != dot.tk_line)  {
411                         if (strcmp(lastfilenm, dot.tk_file) == 0)       {
412                                 if (dot.tk_line - lastlineno <= 1)      {
413                                         lastlineno++;
414                                         print("\n");
415                                 }
416                                 else    {
417                                         lastlineno = dot.tk_line;
418                                         if (!options['P'])
419                                                 print("\n#line %ld \"%s\"\n",
420                                                         lastlineno,
421                                                         lastfilenm
422                                                 );
423                                 }
424                         }
425                         else    {
426                                 lastfilenm = dot.tk_file;
427                                 lastlineno = dot.tk_line;
428                                 if (!options['P'])
429                                         print("\n#line %ld \"%s\"\n",
430                                                 lastlineno, lastfilenm);
431                         }
432                 }
433                 else
434                 if (strcmp(lastfilenm, dot.tk_file) != 0)       {
435                         lastfilenm = dot.tk_file;
436                         if (!options['P'])
437                                 print("\n#line %ld \"%s\"\n",
438                                         lastlineno, lastfilenm);
439                 }
440                 switch (DOT)    {
441                 case IDENTIFIER:
442                 case TYPE_IDENTIFIER:
443                         print("%s ", dot.tk_idf->id_text);
444                         break;
445                 case STRING:
446                 {
447                         char sbuf[1024];        /* a transient buffer */
448                         char *bts2str();
449
450                         print("\"%s\" ", bts2str(dot.tk_bts, dot.tk_len, sbuf));
451                         break;
452                 }
453                 case INTEGER:
454                         print("%ld ", dot.tk_ival);
455                         break;
456 #ifndef NOFLOAT
457                 case FLOATING:
458                         print("%s ", dot.tk_fval);
459                         break;
460 #endif /* NOFLOAT */
461                 case EOI:
462                 case EOF:
463                         return;
464                 default:        /* very expensive...    */
465                         print("%s ", symbol2str(DOT));
466                 }
467         }
468 }
469 #endif /* NOPP */
470 #endif /* DEBUG */
471
472 void
473 No_Mem()                                /* called by alloc package */
474 {
475         fatal("out of memory");
476 }
477
478 void
479 C_failed()                              /* called by EM_code module */
480 {
481         fatal("write failed");
482 }
483