1: /* 2: * Linker main program that controls the linking process. 3: */ 4: 5: #include "ilink.h" 6: 7: #define MAXNAME 256 /* maximum length of file name */ 8: 9: FILE *infile; /* input file (.u1 or .u2) */ 10: FILE *outfile; /* interpreter code output file */ 11: FILE *dbgfile; /* debug file */ 12: char inbuf[BUFSIZ]; /* buffer for input file */ 13: char inname[MAXNAME]; /* input file name */ 14: char outname[MAXNAME]; /* output file name */ 15: char icnname[MAXNAME]; /* icon source file name */ 16: char dbgname[MAXNAME]; /* debug file name */ 17: char ixhdr[50]; /* header for directly executable .u files */ 18: char *iconx = "/bin/echo iconx path not in"; /* pathname of iconx */ 19: int hdrloc; /* location to place hdr at */ 20: struct lfile *lfiles; /* List of files to link */ 21: 22: int line = 0; /* current source program line number */ 23: char *file = NULL; /* current source program file */ 24: int fatalerrs = 0; /* number of errors encountered */ 25: int Dflag = 0; /* debug flag */ 26: 27: char *pname; /* name of program that is running */ 28: char **filep; /* name of current input file */ 29: 30: main(argc, argv) 31: int argc; 32: char **argv; 33: { 34: register int i; 35: extern char *maknam(), *maknam2(); 36: char *p, *getenv(); 37: struct lfile *lf,*lfls; 38: 39: pname = argv[0]; 40: meminit(argc, argv); /* Note that meminit also processes arguments. */ 41: 42: /* 43: * Phase I: load global information contained in .u2 files into 44: * data structures. 45: * 46: * The list of files to link is maintained as a queue with lfiles 47: * as the base. lf moves along the list. Each file is processed 48: * in turn by forming .u2 and .icn names from each file name, each 49: * of which ends in .u1. The .u2 file is opened and globals is called 50: * to process it. When the end of the list is reached, lf becomes 51: * NULL and the loop is terminated, completing phase I. Note that 52: * link instructions in the .u2 file cause files to be added to list 53: * of files to link. 54: */ 55: if (!(lf = lfiles)) 56: exit(0); 57: while (lf) { 58: filep = &(lf->lf_name); 59: maknam2(inname, *filep, ".u2"); 60: maknam(icnname, *filep, ".icn"); 61: infile = fopen(inname, "r"); 62: if (infile == NULL) { 63: fprintf(stderr, "%s: cannot open %s\n", pname, inname); 64: exit(1); 65: } 66: setbuf(infile, inbuf); 67: globals(i); 68: fclose(infile); 69: lf = lf->lf_link; 70: } 71: 72: /* Phase II: resolve undeclared variables and generate code. */ 73: 74: /* 75: * Open the output file. If no file was named with -o, form the 76: * name from that of the first input file named. 77: */ 78: if (!outname[0]) 79: maknam(outname, lfiles->lf_name, ""); 80: outfile = fopen(outname, "w"); 81: if (outfile == NULL) { 82: fprintf(stderr, "%s: cannot create %s\n", pname, outname); 83: exit(1); 84: } 85: setbuf(outfile, NULL); 86: 87: /* 88: * Form the #! line. 89: */ 90: #ifdef DIREX 91: sprintf(ixhdr,"#!%s\n",iconx); 92: hdrloc = strlen(ixhdr); /* point past end of #! line */ 93: if (hdrloc > 32) 94: syserr("interpreter pathname too long--see section 3.1 of installation document"); 95: #else 96: { 97: /* 98: * Direct execution of icode files is not available. Open HDRFILE, 99: * which contains the start-up program and copy it to the output 100: * file. Then, set up for an fseek by setting hdrloc to the byte 101: * past the end of the start-up program and the #! line. 102: */ 103: int hfile, hsize; 104: char hdrdat[MAXHDR]; 105: 106: sprintf(ixhdr,"#!iconx\n"); 107: hfile = open(HDRFILE,0); 108: if (hfile == -1) { 109: fprintf(stderr,"Can't open linker header file %s\n",HDRFILE); 110: exit(1); 111: } 112: hsize = read(hfile,hdrdat,MAXHDR); 113: fwrite(hdrdat,sizeof(char),hsize,outfile); 114: fseek(outfile,(long)MAXHDR,0); 115: hdrloc = MAXHDR + strlen(ixhdr); 116: } 117: #endif DIREX 118: /* 119: * Put the #! line in the file and seek past it and possibly the 120: * start-up program, and leave space for the icode file header. 121: */ 122: genheader(); 123: fseek(outfile, (long)(hdrloc + sizeof(struct header)), 0); 124: 125: /* 126: * Open the .ux file if debugging is on. 127: */ 128: if (Dflag) { 129: maknam(dbgname, lfiles->lf_name, ".ux"); 130: dbgfile = fopen(dbgname, "w"); 131: if (dbgfile == NULL) { 132: fprintf(stderr, "%s: cannot create %s\n", pname, dbgname); 133: exit(1); 134: } 135: setbuf(dbgfile, NULL); 136: } 137: 138: /* 139: * Loop through input files and generate code for each. 140: */ 141: lfls = lfiles; 142: while (lf = getlfile(&lfls)) { 143: filep = &(lf->lf_name); 144: maknam2(inname, *filep, ".u1"); 145: maknam(icnname, *filep, ".icn"); 146: infile = fopen(inname, "r"); 147: if (infile == NULL) { 148: fprintf(stderr, "%s: cannot open %s\n", pname, inname); 149: exit(1); 150: } 151: setbuf(infile, inbuf); 152: gencode(); 153: fclose(infile); 154: } 155: gentables(); /* Generate record, field, global, global names, 156: static, and identifier tables. */ 157: if (fatalerrs > 0) 158: exit(1); 159: exit(0); 160: } 161: 162: /* 163: * maknam - makes a file name from prefix and suffix. 164: * 165: * Uses only the last file specification if name is a path, 166: * replaces suffix of name with suffix argument. 167: */ 168: char *maknam(dest, name, suffix) 169: char *dest, *name, *suffix; 170: { 171: register char *d, *pre, *suf; 172: char *mark; 173: 174: d = dest; 175: pre = name; 176: suf = suffix; 177: mark = pre; 178: while (*pre) /* find last slash */ 179: if (*pre++ == '/') 180: mark = pre; 181: pre = mark; 182: mark = 0; 183: while (*d = *pre++) /* copy from last slash into dest */ 184: if (*d++ == '.') /* look for last dot, too */ 185: mark = d - 1; 186: if (mark) /* if no dot, just append suffix */ 187: d = mark; 188: while (*d++ = *suf++) ; /* copy suffix into dest */ 189: return (dest); 190: } 191: 192: /* 193: * maknam2 - makes a file name from prefix and suffix. 194: * 195: * Like maknam, but leaves initial pathname component intact. 196: */ 197: char *maknam2(dest, name, suffix) 198: char *dest, *name, *suffix; 199: { 200: register char *d, *pre, *suf; 201: char *mark; 202: 203: d = dest; 204: pre = name; 205: suf = suffix; 206: mark = 0; 207: while (*d = *pre++) { 208: if (*d == '/') 209: mark = 0; 210: if (*d++ == '.') /* look for last dot, too */ 211: mark = d - 1; 212: } 213: if (mark) /* if no dot, just append suffix */ 214: d = mark; 215: while (*d++ = *suf++) ; /* copy suffix into dest */ 216: return (dest); 217: } 218: 219: /* 220: * syserr - issue error message and die. 221: */ 222: syserr(s) 223: char *s; 224: { 225: fprintf(stderr, "%s\n", s); 226: exit(1); 227: } 228: 229: /* 230: * warn - issue a warning message. 231: */ 232: warn(s1, s2, s3) 233: char *s1, *s2, *s3; 234: { 235: fprintf(stderr, "%s: ", icnname); 236: if (line) 237: fprintf(stderr, "%d: ", line); 238: if (s1) 239: fprintf(stderr, "\"%s\": ", s1); 240: if (s2) 241: fprintf(stderr, "%s", s2); 242: if (s3) 243: fprintf(stderr, "%s", s3); 244: fprintf(stderr, "\n"); 245: } 246: 247: /* 248: * err - issue an error message. 249: */ 250: 251: err(s1, s2, s3) 252: char *s1, *s2, *s3; 253: { 254: fprintf(stderr, "%s: ", icnname); 255: if (line) 256: fprintf(stderr, "%d: ", line); 257: if (s1) 258: fprintf(stderr, "\"%s\": ", s1); 259: if (s2) 260: fprintf(stderr, "%s", s2); 261: if (s3) 262: fprintf(stderr, "%s", s3); 263: fprintf(stderr, "\n"); 264: fatalerrs++; 265: }