|
|
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.