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