annotate keiko/oblink.c @ 1:b5139af1a420 tip basis

Fixed permissions on compile scripts
author Mike Spivey <mike@cs.ox.ac.uk>
date Fri, 13 Oct 2017 17:27:58 +0100
parents bfdcc3820b32
children
rev   line source
0
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
1 /*
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
2 * oblink.c
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
3 *
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
4 * This file is part of the Oxford Oberon-2 compiler
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
5 * Copyright (c) 2006--2016 J. M. Spivey
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
6 * All rights reserved
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
7 *
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
8 * Redistribution and use in source and binary forms, with or without
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
9 * modification, are permitted provided that the following conditions are met:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
10 *
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
11 * 1. Redistributions of source code must retain the above copyright notice,
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
12 * this list of conditions and the following disclaimer.
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
14 * this list of conditions and the following disclaimer in the documentation
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
15 * and/or other materials provided with the distribution.
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
16 * 3. The name of the author may not be used to endorse or promote products
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
17 * derived from this software without specific prior written permission.
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
18 *
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
29 */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
30
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
31 #define EXTERN
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
32 #include "oblink.h"
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
33 #include "keiko.h"
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
34
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
35 const char *version =
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
36 "Oxford Oberon-2 linker version " PACKAGE_VERSION " [build " REVID "]";
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
37 const char *copyright = "Copyright (C) 1999--2012 J. M. Spivey";
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
38
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
39 /* The module table has one entry for each module that appears in the
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
40 input files. There's another table kept by the linker itself that
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
41 has one entry for each module actually selected for linking. */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
42
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
43 struct _module {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
44 char *m_file; /* Name of the file */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
45 char *m_name; /* Name of the module */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
46 mybool m_lib, m_needed; /* Whether a library module, whether needed */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
47 int m_dep; /* Index of first prerequisite */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
48 int m_check; /* Checksum */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
49 };
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
50
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
51 static growdecl(module);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
52 #define module growbuf(module, struct _module)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
53 #define nmodules growsize(module)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
54
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
55 /* The imports of module m are dep[module[m].m_dep .. module[m+1].m_dep) */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
56
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
57 static growdecl(dep);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
58 #define dep growbuf(dep, int)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
59 #define ndeps growsize(dep)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
60
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
61 #ifdef HAVE_GETOPT_LONG_ONLY
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
62 static int nfiles;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
63 static char **file;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
64 #else
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
65 static growdecl(file);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
66 #define file growbuf(file, char *)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
67 #define nfiles growsize(file)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
68 #endif
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
69
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
70 #define MAXLINE 1024
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
71
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
72 static char line[MAXLINE];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
73 static int nwords;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
74 static char *words[MAXWORDS];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
75
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
76 static mybool stdlib = TRUE;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
77 static char *lscript = (char *) "lscript";
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
78 static char *interp = NULL;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
79 static char *outname = (char *) "a.out";
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
80 static char *libdir = NULL;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
81 static char *rtlibdir = NULL;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
82
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
83 static int find_module(char *name) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
84 for (int i = 0; i < nmodules; i++)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
85 if (strcmp(name, module[i].m_name) == 0)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
86 return i;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
87
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
88 return -1;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
89 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
90
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
91 /* scan -- scan a file for MODULE and IMPORT directives */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
92 static void scan(char *name, mybool islib) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
93 FILE *fp;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
94 int m = -1, m2, chksum;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
95
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
96 err_file = must_strdup(name);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
97 fp = fopen(name, "r");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
98 if (fp == NULL) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
99 perror(name);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
100 exit(2);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
101 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
102
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
103 while (fgets(line, MAXLINE, fp) != NULL) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
104 nwords = split_line(line, words);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
105 if (nwords == 0) continue;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
106
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
107 if (strcmp(words[0], "MODULE") == 0) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
108 char *mname = words[1];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
109 m = find_module(mname);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
110 if (m >= 0) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
111 if (module[m].m_lib)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
112 error("%s has the same name as a library module",
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
113 words[1]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
114 else
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
115 error("%s is loaded more than once", words[1]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
116 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
117
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
118 buf_grow(module);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
119 m = nmodules;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
120 module[m].m_file = name;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
121 module[m].m_name = must_strdup(mname);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
122 module[m].m_lib = islib;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
123 module[m].m_needed = FALSE;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
124 module[m].m_dep = ndeps;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
125 module[m].m_check = strtoul(words[2], NULL, 0);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
126 nmodules++;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
127 } else if (strcmp(words[0], "IMPORT") == 0) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
128 if (m < 0)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
129 error("IMPORT appears before MODULE in %s", name);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
130
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
131 m2 = find_module(words[1]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
132 chksum = strtoul(words[2], NULL, 0);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
133 buf_grow(dep);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
134 if (m2 < 0)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
135 error("%s imports %s -- please load it first",
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
136 module[m].m_name, words[1]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
137 else {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
138 dep[ndeps++] = m2;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
139 if (module[m2].m_check != chksum)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
140 error("checksum of module %s does not match value"
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
141 " expected by module %s",
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
142 words[1], module[m].m_name);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
143 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
144 } else if (strcmp(words[0], "ENDHDR") == 0) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
145 break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
146 } else {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
147 panic("*bad directive %s in file header", words[0]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
148 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
149 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
150
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
151 fclose(fp);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
152 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
153
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
154 static void scan_files(void) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
155 if (stdlib) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
156 char buf[128];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
157 sprintf(buf, "%s%s%s", libdir, DIRSEP, lscript);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
158 FILE *fp = fopen(buf, "r");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
159 if (fp == NULL) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
160 perror(buf);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
161 exit(2);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
162 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
163
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
164 while (fgets(line, MAXLINE, fp) != NULL) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
165 line[strlen(line)-1] = '\0';
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
166 sprintf(buf, "%s%s%s", libdir, DIRSEP, line);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
167 scan(must_strdup(buf), TRUE);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
168 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
169
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
170 fclose(fp);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
171 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
172
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
173 for (int i = 0; i < nfiles; i++)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
174 scan(file[i], FALSE);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
175 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
176
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
177 /* load_needed -- load files containing needed modules */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
178 static void load_needed() {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
179 for (int i = 0; i < nmodules; i++) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
180 if (!module[i].m_needed) continue;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
181
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
182 char *name = module[i].m_file;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
183 err_file = name;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
184 FILE *fp = fopen(name, "r");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
185 if (fp == NULL) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
186 perror(name);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
187 exit(2);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
188 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
189
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
190 while (fgets(line, MAXLINE, fp) != NULL) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
191 nwords = split_line(line, words);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
192 if (nwords == 0) continue;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
193 put_inst(words[0], &words[1], nwords-1);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
194 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
195
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
196 fclose(fp);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
197 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
198 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
199
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
200 /* trace_imports -- compute needed modules */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
201 static void trace_imports(void) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
202 for (int i = nmodules-1; i >= 0; i--) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
203 if (!module[i].m_lib || strcmp(module[i].m_name, "_Builtin") == 0)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
204 module[i].m_needed = TRUE;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
205
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
206 if (module[i].m_needed)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
207 for (int j = module[i].m_dep; j < module[i+1].m_dep; j++)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
208 module[dep[j]].m_needed = TRUE;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
209 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
210
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
211 #ifdef DEBUG
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
212 if (dflag) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
213 fprintf(stderr, "Needed:");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
214 for (int i = 0; i < nmodules; i++)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
215 if (module[i].m_needed)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
216 fprintf(stderr, " %s", module[i].m_name);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
217 fprintf(stderr, "\n");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
218 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
219 #endif
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
220 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
221
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
222 /* gen_main -- generate the main program */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
223 static void gen_main(void) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
224 char buf[128];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
225
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
226 if (known("MAIN")) return;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
227
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
228 err_file = (char *) "main program";
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
229
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
230 /* For completeness, generate a header listing all loaded modules. */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
231 gen_inst("MODULE %%Main 0 0");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
232 for (int i = 0; i < nmodules; i++) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
233 if (strcmp(module[i].m_name, "_Builtin") == 0
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
234 || !module[i].m_needed) continue;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
235 gen_inst("IMPORT %s %#x", module[i].m_name, module[i].m_check);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
236 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
237 gen_inst("ENDHDR");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
238
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
239 gen_inst("PROC MAIN 0 4 0");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
240 /* Code to call each module body */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
241 for (int i = 0; i < nmodules; i++) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
242 if (!module[i].m_needed) continue;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
243 sprintf(buf, "%s.%%main", module[i].m_name);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
244 if (known(buf)) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
245 gen_inst("GLOBAL %s", buf);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
246 gen_inst("CALL 0");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
247 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
248 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
249 gen_inst("RETURN");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
250 gen_inst("END");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
251
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
252 /* Make global pointer map */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
253 gen_inst("DEFINE GCMAP");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
254 for (int i = 0; i < nmodules; i++) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
255 if (!module[i].m_needed) continue;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
256 sprintf(buf, "%s.%%gcmap", module[i].m_name);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
257 if (known(buf)) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
258 gen_inst("WORD GC_MAP");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
259 gen_inst("WORD %s", buf);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
260 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
261 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
262 gen_inst("WORD GC_END");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
263 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
264
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
265 #include <getopt.h>
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
266
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
267 #define SCRIPT 1
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
268
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
269 static struct option longopts[] = {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
270 { "script", required_argument, NULL, SCRIPT },
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
271 { "nostdlib", no_argument, &stdlib, FALSE },
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
272 { "pl", no_argument, &linecount, TRUE },
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
273 { NULL, 0, NULL, 0 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
274 };
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
275
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
276 /* get_options -- analyse arguments */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
277 static void get_options(int argc, char **argv) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
278 for (;;) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
279 int c = getopt_long_only(argc, argv, "dvsgCi:L:R:o:k:",
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
280 longopts, NULL);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
281
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
282 if (c == -1) break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
283
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
284 switch (c) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
285 case 'd':
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
286 dflag++; break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
287 case 'v':
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
288 printf("%s\n", version);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
289 exit(0);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
290 break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
291 case 's':
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
292 sflag = TRUE; break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
293 case 'g':
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
294 gflag = TRUE; break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
295 case 'C':
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
296 custom = TRUE; break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
297 case 'i':
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
298 interp = optarg; break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
299 case 'L':
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
300 libdir = optarg; break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
301 case 'R':
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
302 rtlibdir = optarg; break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
303 case 'o':
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
304 outname = optarg; break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
305 case 'k':
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
306 stack_size = atoi(optarg);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
307 if (stack_size < MIN_STACK) stack_size = MIN_STACK;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
308 break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
309 case 0:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
310 /* Long option with flag */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
311 break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
312 case SCRIPT:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
313 /* -script */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
314 lscript = optarg; break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
315 case '?':
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
316 /* Error has been reported by getopt */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
317 exit(2);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
318 break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
319 default:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
320 panic("*bad option");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
321 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
322 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
323
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
324 nfiles = argc - optind;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
325 file = &argv[optind];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
326 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
327
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
328 int main(int argc, char **argv) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
329 progname = argv[0];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
330
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
331 buf_init(module, INIT_MODS, 1, struct _module, "modules");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
332 buf_init(dep, INIT_MODS, 1, int, "dependencies");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
333
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
334 stack_size = STACK_SIZE;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
335
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
336 get_options(argc, argv);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
337 if (nfiles == 0) panic("no input files");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
338 if (stdlib && libdir == NULL) panic("no libdir specified");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
339 if (rtlibdir == NULL) rtlibdir = libdir;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
340
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
341 #define bind(x) def_global(find_symbol(#x), ABS, x, X_SYM)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
342
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
343 bind(GC_BASE); bind(GC_REPEAT); bind(GC_BLOCK);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
344 bind(GC_MAP); bind(GC_FLEX); bind(GC_END); bind(GC_POINTER);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
345 bind(E_CAST); bind(E_ASSIGN); bind(E_CASE);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
346 bind(E_WITH); bind(E_ASSERT); bind(E_RETURN);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
347 bind(E_BOUND); bind(E_NULL); bind(E_DIV);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
348 bind(E_FDIV); bind(E_STACK); bind(E_GLOB);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
349
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
350 /* First pass -- check for dependencies */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
351 scan_files();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
352
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
353 /* Compute needed modules */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
354 buf_grow(module);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
355 module[nmodules].m_dep = ndeps;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
356 trace_imports();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
357
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
358 if (status != 0) return status;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
359
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
360 /* Second pass -- link the modules that are needed */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
361 init_linker(outname, interp);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
362 load_needed();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
363 gen_main();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
364 if (rtlibdir != NULL)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
365 save_string("LIBDIR", rtlibdir);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
366 end_linking();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
367
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
368 if (custom)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
369 dump_prims();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
370
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
371 return status;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
372 }