Pristine Ack-5.5
[Ack-5.5.git] / lang / m2 / m2mm / 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  * Author: Ceriel J.H. Jacobs
6  */
7
8 /* M A I N   P R O G R A M */
9
10 /* stripped down version from the one in the Modula-2 compiler */
11
12 /* $Id: main.c,v 1.16 1995/12/04 15:20:46 ceriel Exp $ */
13
14 #include        <alloc.h>
15
16 #include        "input.h"
17 #include        "f_info.h"
18 #include        "idf.h"
19 #include        "LLlex.h"
20 #include        "Lpars.h"
21 #include        "tokenname.h"
22
23 int             state;                  /* either IMPLEMENTATION or PROGRAM */
24 char            *ProgName;
25 char            **DEFPATH;
26 int             nDEF, mDEF;
27 struct file_list *CurrentArg;
28 extern int      err_occurred;
29 extern int      Roption;
30 extern char     *strrindex();
31 extern char     *strcpy(), *strcat();
32
33 char *
34 basename(s)
35         char *s;
36 {
37         static char buf[256];
38         char *p = strrindex(s, '.');
39
40         if (p != 0) *p = 0;
41         strcpy(buf, s);
42         if (p != 0) *p = '.';
43         return buf;
44 }
45
46 char *
47 getwdir(fn)
48         register char *fn;
49 {
50         register char *p;
51
52         p = strrindex(fn, '/');
53         while (p && *(p + 1) == '\0') { /* remove trailing /'s */
54                 *p = '\0';
55                 p = strrindex(fn, '/');
56         }
57
58         if (p) {
59                 register char **d = DEFPATH;
60
61                 *p = '\0';
62                 while (*d && strcmp(*d, fn) != 0) d++;
63                 if (*d) {
64                         *p = '/';
65                         return *d;
66                 }
67                 fn = Salloc(fn, (unsigned) (p - &fn[0] + 1));
68                 *p = '/';
69                 return fn;
70         }
71         return ".";
72 }
73
74 static struct file_list *arglist;
75
76 #ifndef M2COMPILER
77 #define M2COMPILER      "m2"
78 #endif
79
80 char *mflags = "";
81 char *compiler = M2COMPILER;
82 char *suff = "o";
83 char *llibs = 0;
84
85 main(argc, argv)
86         register char **argv;
87 {
88         extern struct tokenname tkidf[];
89         extern char *getwdir();
90         int i;
91
92         ProgName = *argv++;
93         DEFPATH = (char **) Malloc(10 * sizeof(char *));
94         DEFPATH[1] = 0;
95         mDEF = 10;
96         nDEF = 2;
97
98         while (--argc > 0) {
99                 if (**argv == '-')
100                         DoOption((*argv++) + 1);
101                 else {
102                         Add(&arglist, *argv, getwdir(*argv), 1);
103                         argv++;
104                 }
105         }
106
107         init_idf();
108         reserve(tkidf);
109         print("IFLAGS =");
110         for (i = 1; i < nDEF; i++) {
111                 if (DEFPATH[i]) print(" -I%s", DEFPATH[i]);
112         }
113         print("\nM2FLAGS = %s\nMOD = %s\nSUFFIX = %s\nLIBS = %s\n", mflags, compiler, suff, llibs ? llibs : "");
114         init_lib();
115         ProcessArgs();
116         find_dependencies();
117         print_dep();
118         programs();
119         exit(err_occurred);
120 }
121
122 struct file_list *
123 new_file_list()
124 {
125         static struct file_list *p;
126         register struct file_list *f;
127         static int cnt;
128
129         if (--cnt < 0) {
130                 p = (struct file_list *)Malloc(50*sizeof(struct file_list));
131                 cnt = 49;
132         }
133         f = p++;
134         f->a_filename = 0;
135         f->a_dir = 0;
136         f->a_next = 0;
137         f->a_idf = 0;
138         f->a_notfound = 0;
139         return f;
140 }
141
142 Add(parglist, f, d, copy)
143         char *f, *d;
144         struct file_list **parglist;
145 {
146         register struct file_list *a, *b = 0;
147
148         if (f == 0) return;
149
150         f_walk(*parglist, a) {
151                 if (strcmp(f_filename(a), f) == 0) break;
152                 b = a;
153         }
154         if (a) return 0;
155         a = new_file_list();
156         if (copy) {
157                 a->a_filename = Salloc(f, (unsigned) (strlen(f)+1));
158         }
159         else {
160                 a->a_filename = f;
161         }
162         a->a_dir = d;
163         if (! b) *parglist = a;
164         else b->a_next = a;
165         return 1;
166 }
167
168 int
169 openfile(a)
170         register struct file_list *a;
171 {
172         char *fn;
173
174         if (!f_notfound(a) && ! InsertFile(f_filename(a), DEFPATH, &fn)) {
175                 a->a_notfound = 1;
176                 Gerror("Could not find %s", f_filename(a));
177                 return 0;
178         }
179         FileName = fn;
180         LineNumber = 1;
181         a->a_dir = WorkingDir = getwdir(FileName);
182         return 1;
183 }
184
185 ProcessArgs()
186 {
187         register struct file_list *a;
188
189         f_walk(arglist, a) {
190                 register char *p = strrindex(f_filename(a), '.');
191
192                 CurrentArg = a;
193                 DEFPATH[0] = f_dir(a);
194                 if ( p && strcmp(p, ".def") == 0) {
195                         ForeignFlag = 0;
196                         if (! openfile(a)) {
197                                 continue;
198                         }
199                         DefModule();
200                 }
201                 else if (p && strcmp(p, ".mod") == 0) {
202                         if (! openfile(a)) {
203                                 *p = 0;         /* ??? */
204                                 continue;
205                         }
206                         CompUnit();
207                 }
208                 else fatal("No Modula-2 file: %s", f_filename(a));
209         }
210 }
211
212 void
213 No_Mem()
214 {
215         fatal("out of memory");
216 }
217
218 AddToList(name, ext)
219         char *name, *ext;
220 {
221         /*      Try to find a file with basename "name" and extension ".def",
222                 in the directories mentioned in "DEFPATH".
223         */
224         char buf[15];
225         char *strncpy();
226
227         if (strcmp(name, "SYSTEM") != 0 && ! is_library_dir(WorkingDir)) {
228                 strncpy(buf, name, 10);
229                 buf[10] = '\0';                 /* maximum length */
230                 strcat(buf, ext);
231                 Add(&arglist, buf, WorkingDir, 1);
232                 return 1;
233         }
234         return 0;
235 }
236
237 find_dependencies()
238 {
239         register struct file_list *arg;
240
241         print("\nall:\t");
242         f_walk(arglist, arg) {
243                 char *fn = f_filename(arg);
244                 char *dotspot = strrindex(fn, '.');
245
246                 if (dotspot && strcmp(dotspot, ".mod") == 0) {
247                         register struct idf *id = f_idf(arg);
248
249                         if (! f_notfound(arg) && id) {
250                                 if (id->id_type == PROGRAM) {
251                                         *dotspot = 0;
252                                         print("%s ", fn);
253                                         *dotspot = '.';
254                                 }
255                                 file_dep(id);
256                         }
257                 }
258         }
259         print("\n\n");
260         print("objects:\t");
261         f_walk(arglist, arg) {
262                 char *fn = f_filename(arg);
263                 char *dotspot = strrindex(fn, '.');
264
265                 if (dotspot && strcmp(dotspot, ".mod") == 0) {
266                         register struct idf *id = f_idf(arg);
267
268                         if (! f_notfound(arg) && id) {
269                                 if (id->id_type == PROGRAM) {
270                                         *dotspot = 0;
271                                         print("%s_o_files ", fn);
272                                         *dotspot = '.';
273                                 }
274                         }
275                 }
276         }
277         print("\n\n\n");
278 }
279
280 file_dep(id)
281         register struct idf *id;
282 {
283         register struct lnk *m;
284
285         if (id->id_ddependson || id->id_mdependson) return;
286         if (id->id_def) Add(&(id->id_mdependson), id->id_def, id->id_dir, 0);
287         for (m = id->id_defimports; m; m = m->lnk_next) {
288                 register struct idf *iid = m->lnk_imp;
289
290                 Add(&(id->id_mdependson), iid->id_def, iid->id_dir, 0);
291                 if (Add(&(id->id_ddependson), iid->id_def, iid->id_dir, 0)) {
292                         register struct file_list *p;
293
294                         file_dep(iid);
295                         f_walk(iid->id_ddependson, p) {
296                                 Add(&(id->id_ddependson), f_filename(p),
297                                     f_dir(p), 0);
298                                 Add(&(id->id_mdependson), f_filename(p),
299                                     f_dir(p), 0);
300                         }
301                 }
302         }
303         for (m = id->id_modimports; m; m = m->lnk_next) {
304                 register struct idf *iid = m->lnk_imp;
305
306                 if (Add(&(id->id_mdependson), iid->id_def, iid->id_dir, 0)) {
307                         register struct file_list *p;
308
309                         file_dep(iid);
310                         f_walk(iid->id_ddependson, p) {
311                                 Add(&(id->id_mdependson), f_filename(p),
312                                     f_dir(p), 0);
313                         }
314                 }
315         }
316 }
317
318 char *
319 object(arg)
320         register struct file_list *arg;
321 {
322         static char buf[512];
323         char *dotp = strrindex(f_filename(arg), '.');
324
325         buf[0] = 0;
326 /*
327         if (strcmp(f_dir(arg), ".") != 0) {
328                 strcpy(buf, f_dir(arg));
329                 strcat(buf, "/");
330         }
331 */
332         if (dotp) *dotp = 0;
333         strcat(buf, f_filename(arg));
334         if (dotp) *dotp = '.';
335         strcat(buf, ".$(SUFFIX)");
336         return buf;
337 }
338
339 pr_arg(a)
340         register struct file_list *a;
341 {
342         char *f = f_filename(a);
343         char *d = f_dir(a);
344
345         if (strcmp(d, ".") == 0 || *f == '/' || *f == '.') {
346                 print(f);
347         }
348         else    print("%s/%s", d, f);
349 }
350
351 print_dep()
352 {
353         register struct file_list *arg;
354
355         f_walk(arglist, arg) {
356                 char *dotspot = strrindex(f_filename(arg), '.');
357
358                 if (dotspot && strcmp(dotspot, ".mod") == 0) {
359                         register struct idf *id = f_idf(arg);
360
361                         if (! f_notfound(arg) && id) {
362                                 char *obj = object(arg);
363                                 register struct file_list *a;
364
365                                 print("%s: \\\n\t", obj);
366                                 pr_arg(arg);
367                                 f_walk(id->id_mdependson, a) {
368                                         if (*(f_filename(a))) /* ??? */ {
369                                                 print(" \\\n\t");
370                                                 pr_arg(a);
371                                         }
372                                 }
373                                 print("\n\t$(MOD) -c $(M2FLAGS) $(IFLAGS) ");
374                                 pr_arg(arg);
375                                 print("\n");
376                         }
377                 }
378         }
379 }
380
381 prog_dep(id, a)
382         register struct idf *id;
383         struct file_list *a;
384 {
385         register struct lnk *m;
386         register struct file_list *p;
387
388         id->id_mdependson = 0;
389         id->id_def = 0;
390         if (id->id_type == PROGRAM) {
391                 Add(&(id->id_mdependson), f_filename(a), f_dir(a), 0);
392         }
393         else {
394                 if (strlen(id->id_text) >= 10) id->id_text[10] = 0;
395                 Add(&(id->id_mdependson), id->id_text, id->id_dir, 0);
396         }
397         for (m = id->id_modimports; m; m = m->lnk_next) {
398                 register struct idf *iid = m->lnk_imp;
399
400                 if (Add(&(id->id_mdependson), iid->id_text, iid->id_dir, 0)) {
401                         if (iid->id_def) prog_dep(iid);
402                         f_walk(iid->id_mdependson, p) {
403                                 Add(&(id->id_mdependson), f_filename(p),
404                                     f_dir(p), 0);
405                         }
406                 }
407         }
408 }
409
410 module_in_arglist(n)
411         char *n;
412 {
413         register struct file_list *a;
414
415         f_walk(arglist, a) {
416                 char *dotp = strrindex(f_filename(a), '.');
417
418                 if (dotp && strcmp(dotp, ".mod") == 0 && ! f_notfound(a)) {
419                         *dotp = 0;
420                         if (strcmp(f_filename(a), n) == 0) {
421                                 *dotp = '.';
422                                 return 1;
423                         }
424                         *dotp = '.';
425                 }
426         }
427         return 0;
428 }
429
430 pr_prog_dep(id, a)
431         register struct idf *id;
432         struct file_list *a;
433 {
434         register struct file_list *p;
435
436         print("\nOBS_%s =", id->id_text);
437         f_walk(id->id_mdependson, p) {
438                 if (module_in_arglist(f_filename(p)) || ! f_dir(p)) {
439                         print(" \\\n\t%s", object(p));
440                 }
441         }
442         print("\n\nOBS2_%s =", id->id_text);
443         f_walk(id->id_mdependson, p) {
444                 if (module_in_arglist(f_filename(p)) || ! f_dir(p)) {
445                         /* nothing */
446                 }
447                 else if (! is_library_dir(f_dir(p))) {
448                         print(" \\\n\t%s/%s", f_dir(p), object(p));
449                 }
450         }
451         print("\n\n");
452         print("%s_o_files:\t$(OBS_%s)\n\n", basename(f_filename(a)), id->id_text);
453         print("%s:\t$(OBS_%s) $(OBS2_%s)\n", basename(f_filename(a)), id->id_text, id->id_text);
454         print("\t$(MOD) -o %s $(M2FLAGS) $(OBS_%s) $(OBS2_%s) $(LIBS)\n", basename(f_filename(a)), id->id_text, id->id_text);
455 }
456
457 programs()
458 {
459         register struct file_list *a;
460
461         f_walk(arglist, a) {
462                 char *dotspot = strrindex(f_filename(a), '.');
463
464                 if (dotspot && strcmp(dotspot, ".mod") == 0) {
465                         register struct idf *id = f_idf(a);
466
467                         if (! f_notfound(a) && id && id->id_type == PROGRAM) {
468                                 prog_dep(id, a);
469                                 /* *dotspot = 0; */
470                                 pr_prog_dep(id, a);
471                                 /* *dotspot = '.'; */
472                         }
473                 }
474         }
475 }