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