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: }