|
|
1.1 root 1: /*
2: * Memory initialization and allocation; also parses arguments.
3: */
4:
5: #include "ilink.h"
6: #ifndef VMS
7: #ifndef ATT3B
8: #ifndef LATTICE
9: #include <sys/types.h>
10: #include <sys/stat.h>
11: #endif LATTICE
12: #endif ATT3B
13: #endif VMS
14:
15: /*
16: * Memory initialization
17: */
18:
19: struct gentry **ghash; /* hash area for global table */
20: struct ientry **ihash; /* hash area for identifier table */
21: struct fentry **fhash; /* hash area for field table */
22:
23: struct lentry *ltable; /* local table */
24: struct gentry *gtable; /* global table */
25: struct centry *ctable; /* constant table */
26: struct ientry *itable; /* identifier table */
27: struct fentry *ftable; /* field table headers */
28: struct rentry *rtable; /* field table record lists */
29:
30: char *strings; /* string space */
31: word *labels; /* label table */
32: char *code; /* generated code space */
33:
34: struct gentry *gfree; /* free pointer for global table */
35: struct ientry *ifree; /* free pointer for identifier table */
36: struct fentry *ffree; /* free pointer for field table headers */
37: struct rentry *rfree; /* free pointer for field table record lists */
38: char *strfree; /* free pointer for string space */
39: char *codep; /* free pointer for code space */
40:
41: word lsize = Lsize; /* size of local table */
42: word gsize = GSize; /* size of global table */
43: word csize = CSize; /* size of constant table */
44: word isize = ISize; /* size of identifier table */
45: word fsize = FSize; /* size of field table headers */
46: word rsize = RSize; /* size of field table record lists */
47: word ssize = StrSize; /* size of string space */
48: word ghsize = GhSize; /* size of global hash table */
49: word ihsize = IhSize; /* size of identifier hash table */
50: word fhsize = FhSize; /* size of field hash table */
51: word maxlabels = MaxLabels; /* maximum number of labels per procedure */
52: word maxcode = MaxCode; /* maximum amount of code per procedure */
53: int gmask; /* mask for global table hash */
54: int imask; /* mask for identifier table hash */
55: int fmask; /* mask for field table hash */
56:
57: char *ipath;
58:
59: #ifdef VMS
60: #define MaxNAME 256
61: char lclname[MaxNAME]; /* local name string for access() */
62: #endif VMS
63: #ifdef MSDOS
64: #define MaxNAME 256
65: char lclname[MaxNAME]; /* local name string for access() */
66: #endif MSDOS
67:
68: char *maknam();
69: char *maknam2();
70:
71: /*
72: * meminit - scan the command line arguments and initialize data structures.
73: */
74: meminit(argc,argv)
75: int argc;
76: char **argv;
77: {
78: int aval;
79: register int i;
80: register union {
81: struct gentry **gp;
82: struct ientry **ip;
83: struct fentry **fp;
84: } p;
85: extern char *allocate();
86: extern char *instalid();
87: extern char *getenv();
88: extern struct gentry *putglob();
89:
90: lfiles = NULL; /* Zero queue of files to link. */
91: if ((ipath = getenv("IPATH")) == NULL)
92: #ifndef VMS
93: #ifndef MSDOS
94: ipath = "."; /* Just look in current directory if no IPATH. */
95: #else MSDOS
96: ipath = ";"; /* Just look in current directory if no IPATH. */
97: #endif MSDOS
98: #else VMS
99: ipath = "[]"; /* Just look in current directory if no IPATH. */
100: #endif VMS
101: /*
102: * Process the command line arguments.
103: */
104: while (--argc) {
105: if (**++argv == '-') {
106: switch ((*argv)[1]) {
107: case 'm': /* -m and -u are for the translator. */
108: case 'u':
109: continue;
110: case 't': /* Set &trace to -1 when Icon starts up. */
111: trace = -1;
112: continue;
113: case 'D': /* Produce a .ux file, which is a readable
114: version of the icode file produced. */
115: Dflag++;
116: continue;
117: case 'o': /* Output file is next argument. */
118: strcpy(outname,*++argv);
119: argc--;
120: continue;
121: #ifdef VMS
122: case 'r':
123: #endif VMS
124: case 'S': /* Change some table size. */
125: if ((*argv)[3] == 'h') { /* Change hash table size. */
126: aval = atoi(&(*argv)[4]);
127: if (aval <= 0)
128: goto badarg;
129: switch ((*argv)[2]) {
130: case 'i': ihsize = aval; continue;
131: case 'g': ghsize = aval; continue;
132: case 'c': continue;
133: case 'f': fhsize = aval; continue;
134: case 'l': continue;
135: }
136: }
137: else { /* Change symbol table size. */
138: aval = atoi(&(*argv)[3]);
139: if (aval <= 0)
140: goto badarg;
141: switch ((*argv)[2]) {
142: case 'c': csize = aval; continue;
143: case 'i': isize = aval; continue;
144: case 'g': gsize = aval; continue;
145: case 'l': lsize = aval; continue;
146: case 's': ssize = aval; continue;
147: case 't': continue;
148: case 'f': fsize = aval; continue;
149: case 'r': rsize = aval; continue;
150: case 'L': maxlabels = aval; continue;
151: case 'C': maxcode = aval; continue;
152: }
153: }
154: case 'i': {
155: iconx = *++argv;
156: argc--;
157: continue;
158: }
159: default:
160: badarg:
161: printf("bad argument: %s\n", *argv);
162: continue;
163: }
164: }
165: else { /* If not an argument, assume it's an input file. */
166: #ifndef VMS
167: #ifndef MSDOS
168: if (access(*argv,4) != 0) {
169: #else MSDOS
170: /* *********** I don't know why this is here, addlfile
171: searches the paths for the file and determines if the file
172: can be read */
173: #endif MSDOS
174: #else VMS
175: if ( access( maknam2(lclname,*argv,".u1"),4 ) != 0 ) {
176: #endif VMS
177: #ifndef MSDOS
178: fprintf(stderr, "ilink: cannot open %s\n", *argv);
179: exit(ErrorExit);
180: }
181: #endif MSDOS
182: addlfile(*argv);
183: }
184: }
185:
186: /*
187: * Round sizes of hash tables for locals, globals, constants, and
188: * identifiers to next larger power of two. The corresponding
189: * mask values are set to one less than the hash table size so that
190: * an integer value can be &'d with the mask to produce a hash value.
191: * (See [lgc]hasher in sym.h.)
192: */
193: for (i = 1; i < ghsize; i <<= 1) ;
194: ghsize = i;
195: gmask = i - 1;
196: for (i = 1; i < ihsize; i <<= 1) ;
197: ihsize = i;
198: imask = i - 1;
199: for (i = 1; i < fhsize; i <<= 1) ;
200: fhsize = i;
201: fmask = i - 1;
202: /*
203: * Allocate the various data structures that are made on a per-file
204: * basis.
205: */
206: ghash = (struct gentry **) allocate((int)ghsize, sizeof(struct gentry *));
207: ihash = (struct ientry **) allocate((int)ihsize, sizeof(struct ientry *));
208: fhash = (struct fentry **) allocate((int)fhsize, sizeof(struct fentry *));
209: ltable = (struct lentry *) allocate((int)lsize, sizeof(struct lentry));
210: gtable = (struct gentry *) allocate((int)gsize, sizeof(struct gentry));
211: ctable = (struct centry *) allocate((int)csize, sizeof(struct centry));
212: itable = (struct ientry *) allocate((int)isize, sizeof(struct ientry ));
213: ftable = (struct fentry *) allocate((int)fsize, sizeof(struct fentry));
214: rtable = (struct rentry *) allocate((int)rsize, sizeof(struct rentry));
215: strings = (char *) allocate((int)ssize, sizeof(char *));
216: labels = (word *) allocate((int)maxlabels, sizeof(word *));
217: code = (char *) allocate((int)maxcode, sizeof(char *));
218: /*
219: * Check to see if there was enough memory. This assumes that the
220: * allocation for strings fails if any of the other allocations
221: * failed. Apparent bug - that assumption is not necessarily valid.
222: */
223:
224: if (code == NULL)
225: syserr("can't get enough memory");
226: /*
227: * Reset the free pointer for each region.
228: */
229: gfree = gtable;
230: ifree = itable;
231: ffree = ftable;
232: rfree = rtable;
233: strfree = strings;
234: codep = code;
235: /*
236: * Zero out the hash tables.
237: */
238: for (p.gp = ghash; p.gp < &ghash[ghsize]; p.gp++)
239: *p.gp = NULL;
240: for (p.ip = ihash; p.ip < &ihash[ihsize]; p.ip++)
241: *p.ip = NULL;
242: for (p.fp = fhash; p.fp < &fhash[fhsize]; p.fp++)
243: *p.fp = NULL;
244: /*
245: * Install "main" as a global variable in order to insure that it
246: * is the first global variable. iconx/start.s depends on main
247: * being global number 0.
248: */
249: putglob(instalid("main"), F_Global, 0);
250: }
251:
252: /*
253: * allocate - get more memory from system.
254: */
255: char *allocate(n, size)
256: int n, size;
257: {
258: #ifndef MSDOS
259: return (char *)malloc(n * size);
260: #else MSDOS
261: return (char *)calloc(n,size);
262: #endif MSDOS
263: }
264:
265: /*
266: * alclfile - allocate an lfile structure for the named file, fill
267: * in the name and return a pointer to it.
268: */
269: struct lfile *alclfile(name)
270: char *name;
271: {
272: struct lfile *p;
273: char *np;
274: int l;
275:
276: p = (struct lfile *)allocate(1,sizeof(struct lfile));
277: if (!p)
278: syserr("not enough memory for file list");
279: p->lf_link = NULL;
280: l = strlen(name);
281: np = allocate(1,(l+1+sizeof(int *)) & ~(sizeof(int *)-1));
282: if (!np)
283: syserr("not enough memory for file list");
284: strncpy(np,name,l);
285: p->lf_name = np;
286: return p;
287: }
288:
289: /*
290: * dumplfiles - print the list of files to link. Used for debugging only.
291: */
292:
293: dumplfiles()
294: {
295: struct lfile *p,*lfls;
296:
297: printf("lfiles:\n");
298: lfls = lfiles;
299: while (p = getlfile(&lfls))
300: printf("'%s'\n",p->lf_name);
301: }
302: /*
303: * addlfile - create an lfile structure for the named file and add it to the
304: * end of the list of files (lfiles) to generate link instructions for.
305: */
306: char *pptr;
307: addlfile(name)
308: char *name;
309: {
310: struct lfile *nlf, *p;
311: char file[256], ok;
312:
313: #ifndef VMS
314: #ifndef MSDOS
315: if (index(name,'/') == 0) {
316: #else MSDOS
317: if (index(name,'/') == 0 &&
318: index(name,'\\') == 0 &&
319: index(name,':') == 0) {
320: #endif MSDOS
321: #else VMS
322: if (strchr(name,']') == 0 && strchr(name,':') == 0) {
323: #endif VMS
324: pptr = ipath;
325: ok = 0;
326: #ifdef MSDOS
327: strcpy(file,name);
328: if (canread(file)) ok++; /* See if we can read the file here */
329: else
330: #endif MSDOS
331: while (trypath(name,file)) {
332: if (canread(file)) {
333: ok++;
334: break;
335: }
336: }
337: if (!ok) {
338: fprintf(stderr, "Can't resolve reference to file '%s'\n",name);
339: exit(ErrorExit);
340: }
341: }
342: else
343: strcpy(file,name);
344: nlf = alclfile(file);
345: if (lfiles == NULL) {
346: lfiles = nlf;
347: }
348: else {
349: p = lfiles;
350: while (p->lf_link != NULL) {
351: if (strcmp(p->lf_name,file) == 0)
352: return;
353: p = p->lf_link;
354: }
355: if (strcmp(p->lf_name,file) == 0)
356: return;
357: p->lf_link = nlf;
358: }
359: }
360:
361: /*
362: * getlfile - return a pointer (p) to the lfile structure pointed at by lptr
363: * and move lptr to the lfile structure that p points at. That is, getlfile
364: * returns a pointer to the current (wrt. lptr) lfile and advances lptr.
365: */
366: struct lfile *
367: getlfile(lptr)
368: struct lfile **lptr;
369: {
370: struct lfile *p;
371:
372: if (*lptr == NULL)
373: return NULL;
374: else {
375: p = *lptr;
376: *lptr = p->lf_link;
377: return p;
378: }
379: }
380:
381: /*
382: * canread - see if file can be read and be sure that it's just an
383: * ordinary file.
384: */
385: canread(file)
386: char *file;
387: {
388: #ifndef VMS
389: #ifndef LATTICE
390: struct stat statb;
391: #endif LATTICE
392: #endif VMS
393:
394: #ifndef VMS
395: #ifndef LATTICE
396: if (access(file,4) == 0) {
397: stat(file,&statb);
398: if (statb.st_mode & S_IFREG)
399: return 1;
400: }
401: #else LATTICE
402: if (access( maknam2(lclname,file,".u1"), 4 ) == 0 )
403: return 1;
404: #endif LATTICE
405: #else VMS
406: if (access( maknam2(lclname,file,".u1"), 4 ) == 0 )
407: return 1;
408: #endif VMS
409:
410: return 0;
411: }
412:
413: /*
414: * trypath - form a file name in file by concatenating name onto the
415: * next path element.
416: */
417: trypath(name,file)
418: char *name, *file;
419: {
420: char *n, c;
421:
422: #ifndef VMS
423: #ifndef MSDOS
424: while (*pptr == ':')
425: #else MSDOS
426: while (*pptr ==';')
427: #endif MSDOS
428: #else VMS
429: while (*pptr == ' ')
430: #endif VMS
431: pptr++;
432: if (!*pptr)
433: return 0;
434: do {
435: c = (*file++ = *pptr++);
436: #ifndef VMS
437: #ifndef MSDOS
438: } while (c != ':' && c);
439: #else MSDOS
440: } while (c != ';' && c);
441: #endif MSDOS
442: #else VMS
443: } while (c != ' ' && c);
444: #endif VMS
445: pptr--;
446: file--;
447:
448: #ifndef VMS
449: *file++ = '/';
450: #endif VMS
451: while (*file++ = *name++);
452: *file = 0;
453: return(1);
454: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.