1 |
|
|
/* $OpenBSD: crunchgen.c,v 1.19 2017/07/27 15:33:42 espie Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 1994 University of Maryland |
5 |
|
|
* All Rights Reserved. |
6 |
|
|
* |
7 |
|
|
* Permission to use, copy, modify, distribute, and sell this software and its |
8 |
|
|
* documentation for any purpose is hereby granted without fee, provided that |
9 |
|
|
* the above copyright notice appear in all copies and that both that |
10 |
|
|
* copyright notice and this permission notice appear in supporting |
11 |
|
|
* documentation, and that the name of U.M. not be used in advertising or |
12 |
|
|
* publicity pertaining to distribution of the software without specific, |
13 |
|
|
* written prior permission. U.M. makes no representations about the |
14 |
|
|
* suitability of this software for any purpose. It is provided "as is" |
15 |
|
|
* without express or implied warranty. |
16 |
|
|
* |
17 |
|
|
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL |
18 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. |
19 |
|
|
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
20 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
21 |
|
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
22 |
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
23 |
|
|
* |
24 |
|
|
* Author: James da Silva, Systems Design and Analysis Group |
25 |
|
|
* Computer Science Department |
26 |
|
|
* University of Maryland at College Park |
27 |
|
|
*/ |
28 |
|
|
/* |
29 |
|
|
* ======================================================================== |
30 |
|
|
* crunchgen.c |
31 |
|
|
* |
32 |
|
|
* Generates a Makefile and main C file for a crunched executable, |
33 |
|
|
* from specs given in a .conf file. |
34 |
|
|
*/ |
35 |
|
|
#include <sys/param.h> /* MACHINE */ |
36 |
|
|
#include <sys/types.h> |
37 |
|
|
#include <sys/stat.h> |
38 |
|
|
|
39 |
|
|
#include <stdio.h> |
40 |
|
|
#include <stdlib.h> |
41 |
|
|
#include <unistd.h> |
42 |
|
|
#include <ctype.h> |
43 |
|
|
#include <string.h> |
44 |
|
|
#include <limits.h> |
45 |
|
|
|
46 |
|
|
#define CRUNCH_VERSION "1.3" |
47 |
|
|
|
48 |
|
|
#define MAXLINELEN 16384 |
49 |
|
|
#define MAXFIELDS 2048 |
50 |
|
|
|
51 |
|
|
/* XXX - This should be runtime configurable */ |
52 |
|
|
/* |
53 |
|
|
* We might have more than one makefile |
54 |
|
|
* name on any given platform. Make sure |
55 |
|
|
* default name is last though. |
56 |
|
|
*/ |
57 |
|
|
char *mf_name[] = { |
58 |
|
|
"Makefile.bsd-wrapper", |
59 |
|
|
"Makefile", |
60 |
|
|
NULL |
61 |
|
|
}; |
62 |
|
|
|
63 |
|
|
/* internal representation of conf file: */ |
64 |
|
|
|
65 |
|
|
/* simple lists of strings suffice for most parms */ |
66 |
|
|
|
67 |
|
|
typedef struct strlst { |
68 |
|
|
struct strlst *next; |
69 |
|
|
char *str; |
70 |
|
|
} strlst_t; |
71 |
|
|
|
72 |
|
|
/* progs have structure, each field can be set with "special" or calculated */ |
73 |
|
|
|
74 |
|
|
typedef struct prog { |
75 |
|
|
struct prog *next; |
76 |
|
|
char *name, *ident, *mf_name; |
77 |
|
|
char *srcdir, *objdir; |
78 |
|
|
strlst_t *objs, *objpaths; |
79 |
|
|
strlst_t *links; |
80 |
|
|
int goterror; |
81 |
|
|
} prog_t; |
82 |
|
|
|
83 |
|
|
strlst_t *srcdirs = NULL; |
84 |
|
|
strlst_t *libs = NULL; |
85 |
|
|
strlst_t *libdirs = NULL; |
86 |
|
|
char objdir[PATH_MAX] = "obj"; |
87 |
|
|
prog_t *progs = NULL; |
88 |
|
|
|
89 |
|
|
char line[MAXLINELEN]; |
90 |
|
|
|
91 |
|
|
char confname[PATH_MAX], infilename[PATH_MAX]; |
92 |
|
|
char outmkname[PATH_MAX], outcfname[PATH_MAX]; |
93 |
|
|
char cachename[PATH_MAX], curfilename[PATH_MAX]; |
94 |
|
|
char topdir[PATH_MAX], execfname[PATH_MAX]; |
95 |
|
|
int linenum = -1; |
96 |
|
|
int goterror = 0; |
97 |
|
|
|
98 |
|
|
extern char *__progname; |
99 |
|
|
|
100 |
|
|
int verbose = 1, readcache = 1, elf_names, elf_mangle; /* options */ |
101 |
|
|
int reading_cache; |
102 |
|
|
|
103 |
|
|
void out_of_memory(void); |
104 |
|
|
void add_string(strlst_t ** listp, char *str); |
105 |
|
|
int is_dir(char *pathname); |
106 |
|
|
int is_nonempty_file(char *pathname); |
107 |
|
|
void usage(void); |
108 |
|
|
void parse_conf_file(void); |
109 |
|
|
void gen_outputs(void); |
110 |
|
|
|
111 |
|
|
extern int crunchide_main(int, char *[]); |
112 |
|
|
|
113 |
|
|
int |
114 |
|
|
main(int argc, char *argv[]) |
115 |
|
|
{ |
116 |
|
|
char *p; |
117 |
|
|
int optc; |
118 |
|
|
extern int optind; |
119 |
|
|
extern char *optarg; |
120 |
|
|
|
121 |
|
|
if (pledge("stdio rpath wpath cpath proc exec flock", NULL) == -1) { |
122 |
|
|
perror("pledge"); |
123 |
|
|
exit(1); |
124 |
|
|
} |
125 |
|
|
|
126 |
|
|
while ((optc = getopt(argc, argv, "hm:c:e:fqD:EL:O:M")) != -1) { |
127 |
|
|
switch (optc) { |
128 |
|
|
case 'h': |
129 |
|
|
optreset = 1; |
130 |
|
|
return (crunchide_main(argc, argv)); |
131 |
|
|
break; |
132 |
|
|
case 'f': |
133 |
|
|
readcache = 0; |
134 |
|
|
break; |
135 |
|
|
case 'q': |
136 |
|
|
verbose = 0; |
137 |
|
|
break; |
138 |
|
|
|
139 |
|
|
case 'm': |
140 |
|
|
if (strlcpy(outmkname, optarg, sizeof(outmkname)) >= |
141 |
|
|
sizeof(outmkname)) |
142 |
|
|
usage(); |
143 |
|
|
break; |
144 |
|
|
case 'c': |
145 |
|
|
if (strlcpy(outcfname, optarg, sizeof(outcfname)) >= |
146 |
|
|
sizeof(outcfname)) |
147 |
|
|
usage(); |
148 |
|
|
break; |
149 |
|
|
case 'e': |
150 |
|
|
if (strlcpy(execfname, optarg, sizeof(execfname)) >= |
151 |
|
|
sizeof(execfname)) |
152 |
|
|
usage(); |
153 |
|
|
break; |
154 |
|
|
|
155 |
|
|
case 'D': |
156 |
|
|
if (strlcpy(topdir, optarg, sizeof(topdir)) >= sizeof(topdir)) |
157 |
|
|
usage(); |
158 |
|
|
break; |
159 |
|
|
case 'E': |
160 |
|
|
elf_names = 1; |
161 |
|
|
break; |
162 |
|
|
case 'L': |
163 |
|
|
if (strlen(optarg) >= PATH_MAX) |
164 |
|
|
usage(); |
165 |
|
|
add_string(&libdirs, optarg); |
166 |
|
|
break; |
167 |
|
|
case 'O': |
168 |
|
|
if (strlcpy(objdir, optarg, sizeof(objdir)) >= |
169 |
|
|
sizeof(objdir)) |
170 |
|
|
usage(); |
171 |
|
|
break; |
172 |
|
|
case 'M': |
173 |
|
|
elf_mangle = 1; |
174 |
|
|
break; |
175 |
|
|
default: |
176 |
|
|
usage(); |
177 |
|
|
} |
178 |
|
|
} |
179 |
|
|
|
180 |
|
|
argc -= optind; |
181 |
|
|
argv += optind; |
182 |
|
|
|
183 |
|
|
if (argc != 1) |
184 |
|
|
usage(); |
185 |
|
|
|
186 |
|
|
if (libdirs == NULL) |
187 |
|
|
add_string(&libdirs, "/usr/lib"); |
188 |
|
|
/* |
189 |
|
|
* generate filenames |
190 |
|
|
*/ |
191 |
|
|
|
192 |
|
|
if (strlcpy(infilename, argv[0], sizeof(infilename)) >= |
193 |
|
|
sizeof(infilename)) |
194 |
|
|
usage(); |
195 |
|
|
|
196 |
|
|
/* confname = `basename infilename .conf` */ |
197 |
|
|
|
198 |
|
|
if ((p = strrchr(infilename, '/')) != NULL) |
199 |
|
|
strlcpy(confname, p + 1, sizeof confname); |
200 |
|
|
else |
201 |
|
|
strlcpy(confname, infilename, sizeof confname); |
202 |
|
|
if ((p = strrchr(confname, '.')) != NULL && !strcmp(p, ".conf")) |
203 |
|
|
*p = '\0'; |
204 |
|
|
|
205 |
|
|
if (!*outmkname) |
206 |
|
|
snprintf(outmkname, sizeof(outmkname), "%s.mk", confname); |
207 |
|
|
if (!*outcfname) |
208 |
|
|
snprintf(outcfname, sizeof(outcfname), "%s.c", confname); |
209 |
|
|
if (!*execfname) |
210 |
|
|
snprintf(execfname, sizeof(execfname), "%s", confname); |
211 |
|
|
snprintf(cachename, sizeof(cachename), "%s.cache", confname); |
212 |
|
|
|
213 |
|
|
parse_conf_file(); |
214 |
|
|
gen_outputs(); |
215 |
|
|
|
216 |
|
|
exit(goterror); |
217 |
|
|
} |
218 |
|
|
|
219 |
|
|
void |
220 |
|
|
usage(void) |
221 |
|
|
{ |
222 |
|
|
fprintf(stderr, |
223 |
|
|
"usage: crunchgen [-EfMq] [-c c-file-name] [-D src-root] [-e exec-file-name]\n" |
224 |
|
|
"\t[-L lib-dir] [-m makefile-name] [-O objdir-name] conf-file\n"); |
225 |
|
|
fprintf(stderr, |
226 |
|
|
" crunchgen -h [-M] [-f keep-list-file] [-k keep-symbol] object-file ...\n"); |
227 |
|
|
exit(1); |
228 |
|
|
} |
229 |
|
|
|
230 |
|
|
void parse_one_file(char *filename); |
231 |
|
|
void parse_line(char *line, int *fc, char **fv, int nf); |
232 |
|
|
void add_srcdirs(int argc, char **argv); |
233 |
|
|
void add_progs(int argc, char **argv); |
234 |
|
|
void add_link(int argc, char **argv); |
235 |
|
|
void add_libs(int argc, char **argv); |
236 |
|
|
void add_libdirs(int argc, char **argv); |
237 |
|
|
void add_special(int argc, char **argv); |
238 |
|
|
|
239 |
|
|
prog_t *find_prog(char *str); |
240 |
|
|
void add_prog(char *progname); |
241 |
|
|
|
242 |
|
|
void |
243 |
|
|
parse_conf_file(void) |
244 |
|
|
{ |
245 |
|
|
if (!is_nonempty_file(infilename)) { |
246 |
|
|
fprintf(stderr, "%s: fatal: input file \"%s\" not found.\n", |
247 |
|
|
__progname, infilename); |
248 |
|
|
exit(1); |
249 |
|
|
} |
250 |
|
|
parse_one_file(infilename); |
251 |
|
|
if (readcache && is_nonempty_file(cachename)) { |
252 |
|
|
reading_cache = 1; |
253 |
|
|
parse_one_file(cachename); |
254 |
|
|
} |
255 |
|
|
} |
256 |
|
|
|
257 |
|
|
void |
258 |
|
|
parse_one_file(char *filename) |
259 |
|
|
{ |
260 |
|
|
char *fieldv[MAXFIELDS]; |
261 |
|
|
int fieldc; |
262 |
|
|
void (*f) (int c, char **v); |
263 |
|
|
FILE *cf; |
264 |
|
|
|
265 |
|
|
strlcpy(curfilename, filename, sizeof curfilename); |
266 |
|
|
|
267 |
|
|
if ((cf = fopen(curfilename, "r")) == NULL) { |
268 |
|
|
perror(curfilename); |
269 |
|
|
goterror = 1; |
270 |
|
|
return; |
271 |
|
|
} |
272 |
|
|
linenum = 0; |
273 |
|
|
while (fgets(line, MAXLINELEN, cf) != NULL) { |
274 |
|
|
linenum++; |
275 |
|
|
parse_line(line, &fieldc, fieldv, MAXFIELDS); |
276 |
|
|
if (fieldc < 1) |
277 |
|
|
continue; |
278 |
|
|
if (!strcmp(fieldv[0], "srcdirs")) |
279 |
|
|
f = add_srcdirs; |
280 |
|
|
else if (!strcmp(fieldv[0], "progs")) |
281 |
|
|
f = add_progs; |
282 |
|
|
else if (!strcmp(fieldv[0], "ln")) |
283 |
|
|
f = add_link; |
284 |
|
|
else if (!strcmp(fieldv[0], "libs")) |
285 |
|
|
f = add_libs; |
286 |
|
|
else if (!strcmp(fieldv[0], "special")) |
287 |
|
|
f = add_special; |
288 |
|
|
else if (!strcmp(fieldv[0], "libdirs")) |
289 |
|
|
f = add_libdirs; |
290 |
|
|
else { |
291 |
|
|
fprintf(stderr, "%s:%d: skipping unknown command `%s'.\n", |
292 |
|
|
curfilename, linenum, fieldv[0]); |
293 |
|
|
goterror = 1; |
294 |
|
|
continue; |
295 |
|
|
} |
296 |
|
|
if (fieldc < 2) { |
297 |
|
|
fprintf(stderr, |
298 |
|
|
"%s:%d: %s command needs at least 1 " |
299 |
|
|
"argument, skipping.\n", |
300 |
|
|
curfilename, linenum, fieldv[0]); |
301 |
|
|
goterror = 1; |
302 |
|
|
continue; |
303 |
|
|
} |
304 |
|
|
f(fieldc, fieldv); |
305 |
|
|
} |
306 |
|
|
|
307 |
|
|
if (ferror(cf)) { |
308 |
|
|
perror(curfilename); |
309 |
|
|
goterror = 1; |
310 |
|
|
} |
311 |
|
|
fclose(cf); |
312 |
|
|
} |
313 |
|
|
|
314 |
|
|
void |
315 |
|
|
parse_line(char *line, int *fc, char **fv, int nf) |
316 |
|
|
{ |
317 |
|
|
char *p; |
318 |
|
|
|
319 |
|
|
p = line; |
320 |
|
|
*fc = 0; |
321 |
|
|
while (1) { |
322 |
|
|
while (isspace((unsigned char)*p)) |
323 |
|
|
p++; |
324 |
|
|
if (*p == '\0' || *p == '#') |
325 |
|
|
break; |
326 |
|
|
|
327 |
|
|
if (*fc < nf) |
328 |
|
|
fv[(*fc)++] = p; |
329 |
|
|
while (*p && !isspace((unsigned char)*p) && *p != '#') |
330 |
|
|
p++; |
331 |
|
|
if (*p == '\0' || *p == '#') |
332 |
|
|
break; |
333 |
|
|
*p++ = '\0'; |
334 |
|
|
} |
335 |
|
|
if (*p) |
336 |
|
|
*p = '\0'; /* needed for '#' case */ |
337 |
|
|
} |
338 |
|
|
|
339 |
|
|
void |
340 |
|
|
add_srcdirs(int argc, char **argv) |
341 |
|
|
{ |
342 |
|
|
int i; |
343 |
|
|
char tmppath[PATH_MAX]; |
344 |
|
|
int overflow; |
345 |
|
|
|
346 |
|
|
for (i = 1; i < argc; i++) { |
347 |
|
|
overflow = 0; |
348 |
|
|
if (argv[i][0] == '/' || topdir[0] == '\0') { |
349 |
|
|
if (strlcpy(tmppath, argv[i], sizeof(tmppath)) >= |
350 |
|
|
sizeof(tmppath)) |
351 |
|
|
overflow = 1; |
352 |
|
|
} else { |
353 |
|
|
if (strlcpy(tmppath, topdir, sizeof(tmppath)) >= |
354 |
|
|
sizeof(tmppath) || |
355 |
|
|
strlcat(tmppath, "/", sizeof(tmppath)) >= |
356 |
|
|
sizeof(tmppath) || |
357 |
|
|
strlcat(tmppath, argv[i], sizeof(tmppath)) >= |
358 |
|
|
sizeof(tmppath)) |
359 |
|
|
overflow = 1; |
360 |
|
|
} |
361 |
|
|
if (overflow) { |
362 |
|
|
goterror = 1; |
363 |
|
|
fprintf(stderr, "%s:%d: `%.40s...' is too long, skipping it.\n", |
364 |
|
|
curfilename, linenum, argv[i]); |
365 |
|
|
continue; |
366 |
|
|
} |
367 |
|
|
if (is_dir(tmppath)) |
368 |
|
|
add_string(&srcdirs, tmppath); |
369 |
|
|
else { |
370 |
|
|
fprintf(stderr, "%s:%d: `%s' is not a directory, skipping it.\n", |
371 |
|
|
curfilename, linenum, tmppath); |
372 |
|
|
goterror = 1; |
373 |
|
|
} |
374 |
|
|
} |
375 |
|
|
} |
376 |
|
|
|
377 |
|
|
void |
378 |
|
|
add_libdirs(int argc, char **argv) |
379 |
|
|
{ |
380 |
|
|
int i; |
381 |
|
|
char tmppath[PATH_MAX]; |
382 |
|
|
char tmppath2[PATH_MAX]; |
383 |
|
|
int overflow; |
384 |
|
|
|
385 |
|
|
for (i = 1; i < argc; i++) { |
386 |
|
|
overflow = 0; |
387 |
|
|
if (argv[i][0] == '/' || topdir[0] == '\0') { |
388 |
|
|
if (strlcpy(tmppath, argv[i], sizeof(tmppath)) >= |
389 |
|
|
sizeof(tmppath)) |
390 |
|
|
overflow = 1; |
391 |
|
|
} else { |
392 |
|
|
if (strlcpy(tmppath, topdir, sizeof(tmppath)) >= |
393 |
|
|
sizeof(tmppath) || |
394 |
|
|
strlcat(tmppath, "/", sizeof(tmppath)) >= |
395 |
|
|
sizeof(tmppath) || |
396 |
|
|
strlcat(tmppath, argv[i], sizeof(tmppath)) >= |
397 |
|
|
sizeof(tmppath)) |
398 |
|
|
overflow = 1; |
399 |
|
|
} |
400 |
|
|
if (overflow) { |
401 |
|
|
goterror = 1; |
402 |
|
|
fprintf(stderr, "%s:%d: `%.40s...' is too long, skipping it.\n", |
403 |
|
|
curfilename, linenum, argv[i]); |
404 |
|
|
continue; |
405 |
|
|
} |
406 |
|
|
if (is_dir(tmppath)) { |
407 |
|
|
snprintf(tmppath2, sizeof(tmppath2), "%s/%s", tmppath, |
408 |
|
|
objdir); |
409 |
|
|
if (is_dir(tmppath2)) |
410 |
|
|
add_string(&libdirs, tmppath2); |
411 |
|
|
else { |
412 |
|
|
snprintf(tmppath2, sizeof(tmppath2), |
413 |
|
|
"%s/obj.%s", tmppath, MACHINE); |
414 |
|
|
if (is_dir(tmppath2)) |
415 |
|
|
add_string(&libdirs, tmppath2); |
416 |
|
|
else |
417 |
|
|
add_string(&libdirs, tmppath); |
418 |
|
|
} |
419 |
|
|
} |
420 |
|
|
else { |
421 |
|
|
fprintf(stderr, "%s:%d: `%s' is not a directory, skipping it.\n", |
422 |
|
|
curfilename, linenum, tmppath); |
423 |
|
|
goterror = 1; |
424 |
|
|
} |
425 |
|
|
} |
426 |
|
|
} |
427 |
|
|
|
428 |
|
|
|
429 |
|
|
void |
430 |
|
|
add_progs(int argc, char **argv) |
431 |
|
|
{ |
432 |
|
|
int i; |
433 |
|
|
|
434 |
|
|
for (i = 1; i < argc; i++) |
435 |
|
|
add_prog(argv[i]); |
436 |
|
|
} |
437 |
|
|
|
438 |
|
|
void |
439 |
|
|
add_prog(char *progname) |
440 |
|
|
{ |
441 |
|
|
prog_t *p1, *p2; |
442 |
|
|
|
443 |
|
|
/* add to end, but be smart about dups */ |
444 |
|
|
|
445 |
|
|
for (p1 = NULL, p2 = progs; p2 != NULL; p1 = p2, p2 = p2->next) |
446 |
|
|
if (!strcmp(p2->name, progname)) |
447 |
|
|
return; |
448 |
|
|
|
449 |
|
|
p2 = calloc(1, sizeof(prog_t)); |
450 |
|
|
if (p2) |
451 |
|
|
p2->name = strdup(progname); |
452 |
|
|
if (!p2 || !p2->name) |
453 |
|
|
out_of_memory(); |
454 |
|
|
|
455 |
|
|
p2->next = NULL; |
456 |
|
|
if (p1 == NULL) |
457 |
|
|
progs = p2; |
458 |
|
|
else |
459 |
|
|
p1->next = p2; |
460 |
|
|
|
461 |
|
|
p2->ident = p2->srcdir = p2->objdir = NULL; |
462 |
|
|
p2->links = p2->objs = NULL; |
463 |
|
|
p2->goterror = 0; |
464 |
|
|
} |
465 |
|
|
|
466 |
|
|
void |
467 |
|
|
add_link(int argc, char **argv) |
468 |
|
|
{ |
469 |
|
|
int i; |
470 |
|
|
prog_t *p = find_prog(argv[1]); |
471 |
|
|
|
472 |
|
|
if (p == NULL) { |
473 |
|
|
fprintf(stderr, |
474 |
|
|
"%s:%d: no prog %s previously declared, skipping link.\n", |
475 |
|
|
curfilename, linenum, argv[1]); |
476 |
|
|
goterror = 1; |
477 |
|
|
return; |
478 |
|
|
} |
479 |
|
|
for (i = 2; i < argc; i++) |
480 |
|
|
add_string(&p->links, argv[i]); |
481 |
|
|
} |
482 |
|
|
|
483 |
|
|
void |
484 |
|
|
add_libs(int argc, char **argv) |
485 |
|
|
{ |
486 |
|
|
int i; |
487 |
|
|
|
488 |
|
|
for (i = 1; i < argc; i++) |
489 |
|
|
add_string(&libs, argv[i]); |
490 |
|
|
} |
491 |
|
|
|
492 |
|
|
void |
493 |
|
|
add_special(int argc, char **argv) |
494 |
|
|
{ |
495 |
|
|
int i; |
496 |
|
|
prog_t *p = find_prog(argv[1]); |
497 |
|
|
|
498 |
|
|
if (p == NULL) { |
499 |
|
|
if (reading_cache) |
500 |
|
|
return; |
501 |
|
|
fprintf(stderr, |
502 |
|
|
"%s:%d: no prog %s previously declared, skipping special.\n", |
503 |
|
|
curfilename, linenum, argv[1]); |
504 |
|
|
goterror = 1; |
505 |
|
|
return; |
506 |
|
|
} |
507 |
|
|
if (!strcmp(argv[2], "ident")) { |
508 |
|
|
if (argc != 4) |
509 |
|
|
goto argcount; |
510 |
|
|
if ((p->ident = strdup(argv[3])) == NULL) |
511 |
|
|
out_of_memory(); |
512 |
|
|
} else if (!strcmp(argv[2], "srcdir")) { |
513 |
|
|
if (argc != 4) |
514 |
|
|
goto argcount; |
515 |
|
|
if ((p->srcdir = strdup(argv[3])) == NULL) |
516 |
|
|
out_of_memory(); |
517 |
|
|
} else if (!strcmp(argv[2], "mf_name")) { |
518 |
|
|
if (argc != 4) |
519 |
|
|
goto argcount; |
520 |
|
|
if ((p->mf_name = strdup(argv[3])) == NULL) |
521 |
|
|
out_of_memory(); |
522 |
|
|
} else if (!strcmp(argv[2], "objdir")) { |
523 |
|
|
if (argc != 4) |
524 |
|
|
goto argcount; |
525 |
|
|
if ((p->objdir = strdup(argv[3])) == NULL) |
526 |
|
|
out_of_memory(); |
527 |
|
|
} else if (!strcmp(argv[2], "objs")) { |
528 |
|
|
p->objs = NULL; |
529 |
|
|
for (i = 3; i < argc; i++) |
530 |
|
|
add_string(&p->objs, argv[i]); |
531 |
|
|
} else if (!strcmp(argv[2], "objpaths")) { |
532 |
|
|
p->objpaths = NULL; |
533 |
|
|
for (i = 3; i < argc; i++) |
534 |
|
|
add_string(&p->objpaths, argv[i]); |
535 |
|
|
} else { |
536 |
|
|
fprintf(stderr, "%s:%d: bad parameter name `%s', skipping line.\n", |
537 |
|
|
curfilename, linenum, argv[2]); |
538 |
|
|
goterror = 1; |
539 |
|
|
} |
540 |
|
|
return; |
541 |
|
|
|
542 |
|
|
argcount: |
543 |
|
|
fprintf(stderr, |
544 |
|
|
"%s:%d: too %s arguments, expected \"special %s %s <string>\".\n", |
545 |
|
|
curfilename, linenum, argc < 4 ? "few" : "many", argv[1], argv[2]); |
546 |
|
|
goterror = 1; |
547 |
|
|
} |
548 |
|
|
|
549 |
|
|
prog_t * |
550 |
|
|
find_prog(char *str) |
551 |
|
|
{ |
552 |
|
|
prog_t *p; |
553 |
|
|
|
554 |
|
|
for (p = progs; p != NULL; p = p->next) |
555 |
|
|
if (!strcmp(p->name, str)) |
556 |
|
|
return p; |
557 |
|
|
return NULL; |
558 |
|
|
} |
559 |
|
|
|
560 |
|
|
void remove_error_progs(void); |
561 |
|
|
void fillin_program(prog_t * p); |
562 |
|
|
void gen_specials_cache(void); |
563 |
|
|
void gen_output_makefile(void); |
564 |
|
|
void gen_output_cfile(void); |
565 |
|
|
|
566 |
|
|
void fillin_program_objs(prog_t * p, char *path); |
567 |
|
|
void top_makefile_rules(FILE * outmk); |
568 |
|
|
void prog_makefile_rules(FILE * outmk, prog_t * p); |
569 |
|
|
void output_strlst(FILE * outf, strlst_t * lst); |
570 |
|
|
char *genident(char *str); |
571 |
|
|
char *dir_search(char *progname); |
572 |
|
|
|
573 |
|
|
void |
574 |
|
|
gen_outputs(void) |
575 |
|
|
{ |
576 |
|
|
prog_t *p; |
577 |
|
|
|
578 |
|
|
for (p = progs; p != NULL; p = p->next) |
579 |
|
|
fillin_program(p); |
580 |
|
|
|
581 |
|
|
remove_error_progs(); |
582 |
|
|
gen_specials_cache(); |
583 |
|
|
gen_output_cfile(); |
584 |
|
|
gen_output_makefile(); |
585 |
|
|
} |
586 |
|
|
|
587 |
|
|
void |
588 |
|
|
fillin_program(prog_t * p) |
589 |
|
|
{ |
590 |
|
|
char path[PATH_MAX]; |
591 |
|
|
char *srcparent; |
592 |
|
|
strlst_t *s; |
593 |
|
|
int i; |
594 |
|
|
|
595 |
|
|
if (!p->ident) |
596 |
|
|
p->ident = genident(p->name); |
597 |
|
|
if (!p->srcdir) { |
598 |
|
|
srcparent = dir_search(p->name); |
599 |
|
|
if (srcparent) |
600 |
|
|
snprintf(path, sizeof(path), "%s/%s", srcparent, p->name); |
601 |
|
|
if (is_dir(path)) |
602 |
|
|
p->srcdir = strdup(path); |
603 |
|
|
} |
604 |
|
|
if (!p->objdir && p->srcdir) { |
605 |
|
|
snprintf(path, sizeof(path), "%s/%s", p->srcdir, objdir); |
606 |
|
|
if (is_dir(path)) |
607 |
|
|
p->objdir = strdup(path); |
608 |
|
|
else { |
609 |
|
|
snprintf(path, sizeof(path), "%s/obj.%s", p->srcdir, MACHINE); |
610 |
|
|
if (is_dir(path)) |
611 |
|
|
p->objdir = strdup(path); |
612 |
|
|
else |
613 |
|
|
p->objdir = p->srcdir; |
614 |
|
|
} |
615 |
|
|
/* Fill p->mf_name so it is not a null pointer */ |
616 |
|
|
for (i = 0; mf_name[i] != NULL; i++) { |
617 |
|
|
snprintf(path, sizeof(path), "%s/%s", p->srcdir, mf_name[i]); |
618 |
|
|
if (is_nonempty_file(path)) { |
619 |
|
|
p->mf_name = mf_name[i]; |
620 |
|
|
break; |
621 |
|
|
} |
622 |
|
|
} |
623 |
|
|
} |
624 |
|
|
/* We have a sourcedir and no explicit objs, try */ |
625 |
|
|
/* to find makefile and get objs from it. */ |
626 |
|
|
if (p->srcdir && !p->objs) { |
627 |
|
|
for (i = 0; mf_name[i] != NULL; i++) { |
628 |
|
|
snprintf(path, sizeof(path), "%s/%s", p->srcdir, mf_name[i]); |
629 |
|
|
if (is_nonempty_file(path)) { |
630 |
|
|
p->mf_name = mf_name[i]; |
631 |
|
|
fillin_program_objs(p, path); |
632 |
|
|
break; |
633 |
|
|
} |
634 |
|
|
} |
635 |
|
|
} |
636 |
|
|
if (!p->objpaths && p->objdir && p->objs) |
637 |
|
|
for (s = p->objs; s != NULL; s = s->next) { |
638 |
|
|
snprintf(line, sizeof(line), "%s/%s", p->objdir, s->str); |
639 |
|
|
add_string(&p->objpaths, line); |
640 |
|
|
} |
641 |
|
|
|
642 |
|
|
if (!p->srcdir && verbose) |
643 |
|
|
fprintf(stderr, "%s: %s: warning: could not find source directory.\n", |
644 |
|
|
infilename, p->name); |
645 |
|
|
if (!p->objs && verbose) |
646 |
|
|
fprintf(stderr, "%s: %s: warning: could not find any .o files.\n", |
647 |
|
|
infilename, p->name); |
648 |
|
|
|
649 |
|
|
if (!p->objpaths) { |
650 |
|
|
fprintf(stderr, |
651 |
|
|
"%s: %s: error: no objpaths specified or calculated.\n", |
652 |
|
|
infilename, p->name); |
653 |
|
|
p->goterror = goterror = 1; |
654 |
|
|
} |
655 |
|
|
} |
656 |
|
|
|
657 |
|
|
void |
658 |
|
|
fillin_program_objs(prog_t * p, char *path) |
659 |
|
|
{ |
660 |
|
|
char *cp, *obj, tempfname[PATH_MAX]; |
661 |
|
|
int fd, rc; |
662 |
|
|
FILE *f; |
663 |
|
|
|
664 |
|
|
/* discover the objs from the srcdir Makefile */ |
665 |
|
|
|
666 |
|
|
snprintf(tempfname, sizeof(tempfname), ".tmp_%sXXXXXXXXXX", confname); |
667 |
|
|
if ((fd = mkstemp(tempfname)) == -1 || (f = fdopen(fd, "w")) == NULL) { |
668 |
|
|
if (fd != -1) |
669 |
|
|
close(fd); |
670 |
|
|
perror(tempfname); |
671 |
|
|
goterror = 1; |
672 |
|
|
return; |
673 |
|
|
} |
674 |
|
|
fprintf(f, ".include \"%s\"\n", path); |
675 |
|
|
fprintf(f, ".if defined(PROG) && !defined(OBJS)\n"); |
676 |
|
|
fprintf(f, "OBJS=${PROG}.o\n"); |
677 |
|
|
fprintf(f, ".endif\n"); |
678 |
|
|
fprintf(f, "crunchgen_objs:\n\t@echo 'OBJS= '${OBJS}\n"); |
679 |
|
|
fclose(f); |
680 |
|
|
|
681 |
|
|
snprintf(line, sizeof(line), "make -f %s crunchgen_objs 2>&1", tempfname); |
682 |
|
|
if ((f = popen(line, "r")) == NULL) { |
683 |
|
|
perror("submake pipe"); |
684 |
|
|
goterror = 1; |
685 |
|
|
return; |
686 |
|
|
} |
687 |
|
|
while (fgets(line, MAXLINELEN, f)) { |
688 |
|
|
if (strncmp(line, "OBJS= ", 6)) { |
689 |
|
|
if (strcmp(line, |
690 |
|
|
"sh: warning: running as root with dot in PATH\n") == 0) |
691 |
|
|
continue; |
692 |
|
|
fprintf(stderr, "make error: %s", line); |
693 |
|
|
goterror = 1; |
694 |
|
|
continue; |
695 |
|
|
} |
696 |
|
|
cp = line + 6; |
697 |
|
|
while (isspace((unsigned char)*cp)) |
698 |
|
|
cp++; |
699 |
|
|
while (*cp) { |
700 |
|
|
obj = cp; |
701 |
|
|
while (*cp && !isspace((unsigned char)*cp)) |
702 |
|
|
cp++; |
703 |
|
|
if (*cp) |
704 |
|
|
*cp++ = '\0'; |
705 |
|
|
add_string(&p->objs, obj); |
706 |
|
|
while (isspace((unsigned char)*cp)) |
707 |
|
|
cp++; |
708 |
|
|
} |
709 |
|
|
} |
710 |
|
|
if ((rc = pclose(f)) != 0) { |
711 |
|
|
fprintf(stderr, "make error: make returned %d\n", rc); |
712 |
|
|
goterror = 1; |
713 |
|
|
} |
714 |
|
|
unlink(tempfname); |
715 |
|
|
} |
716 |
|
|
|
717 |
|
|
void |
718 |
|
|
remove_error_progs(void) |
719 |
|
|
{ |
720 |
|
|
prog_t *p1, *p2; |
721 |
|
|
|
722 |
|
|
p1 = NULL; |
723 |
|
|
p2 = progs; |
724 |
|
|
while (p2 != NULL) { |
725 |
|
|
if (!p2->goterror) |
726 |
|
|
p1 = p2, p2 = p2->next; |
727 |
|
|
else { |
728 |
|
|
/* delete it from linked list */ |
729 |
|
|
fprintf(stderr, "%s: %s: ignoring program because of errors.\n", |
730 |
|
|
infilename, p2->name); |
731 |
|
|
if (p1) |
732 |
|
|
p1->next = p2->next; |
733 |
|
|
else |
734 |
|
|
progs = p2->next; |
735 |
|
|
p2 = p2->next; |
736 |
|
|
} |
737 |
|
|
} |
738 |
|
|
} |
739 |
|
|
|
740 |
|
|
void |
741 |
|
|
gen_specials_cache(void) |
742 |
|
|
{ |
743 |
|
|
FILE *cachef; |
744 |
|
|
prog_t *p; |
745 |
|
|
|
746 |
|
|
if ((cachef = fopen(cachename, "w")) == NULL) { |
747 |
|
|
perror(cachename); |
748 |
|
|
goterror = 1; |
749 |
|
|
return; |
750 |
|
|
} |
751 |
|
|
fprintf(cachef, "# %s - parm cache generated from %s by crunchgen %s\n\n", |
752 |
|
|
cachename, infilename, CRUNCH_VERSION); |
753 |
|
|
|
754 |
|
|
for (p = progs; p != NULL; p = p->next) { |
755 |
|
|
fprintf(cachef, "\n"); |
756 |
|
|
if (p->srcdir) |
757 |
|
|
fprintf(cachef, "special %s srcdir %s\n", p->name, p->srcdir); |
758 |
|
|
if (p->mf_name) |
759 |
|
|
fprintf(cachef, "special %s mf_name %s\n", p->name, p->mf_name); |
760 |
|
|
if (p->objdir) |
761 |
|
|
fprintf(cachef, "special %s objdir %s\n", p->name, p->objdir); |
762 |
|
|
if (p->objs) { |
763 |
|
|
fprintf(cachef, "special %s objs", p->name); |
764 |
|
|
output_strlst(cachef, p->objs); |
765 |
|
|
} |
766 |
|
|
fprintf(cachef, "special %s objpaths", p->name); |
767 |
|
|
output_strlst(cachef, p->objpaths); |
768 |
|
|
} |
769 |
|
|
fclose(cachef); |
770 |
|
|
} |
771 |
|
|
|
772 |
|
|
void |
773 |
|
|
gen_output_makefile(void) |
774 |
|
|
{ |
775 |
|
|
prog_t *p; |
776 |
|
|
FILE *outmk; |
777 |
|
|
|
778 |
|
|
if ((outmk = fopen(outmkname, "w")) == NULL) { |
779 |
|
|
perror(outmkname); |
780 |
|
|
goterror = 1; |
781 |
|
|
return; |
782 |
|
|
} |
783 |
|
|
fprintf(outmk, "# %s - generated from %s by crunchgen %s\n\n", |
784 |
|
|
outmkname, infilename, CRUNCH_VERSION); |
785 |
|
|
|
786 |
|
|
top_makefile_rules(outmk); |
787 |
|
|
|
788 |
|
|
for (p = progs; p != NULL; p = p->next) |
789 |
|
|
prog_makefile_rules(outmk, p); |
790 |
|
|
|
791 |
|
|
fprintf(outmk, "\n# ========\n"); |
792 |
|
|
fclose(outmk); |
793 |
|
|
} |
794 |
|
|
|
795 |
|
|
void |
796 |
|
|
gen_output_cfile(void) |
797 |
|
|
{ |
798 |
|
|
extern char *crunched_skel[]; |
799 |
|
|
char **cp; |
800 |
|
|
FILE *outcf; |
801 |
|
|
prog_t *p; |
802 |
|
|
strlst_t *s; |
803 |
|
|
|
804 |
|
|
if ((outcf = fopen(outcfname, "w")) == NULL) { |
805 |
|
|
perror(outcfname); |
806 |
|
|
goterror = 1; |
807 |
|
|
return; |
808 |
|
|
} |
809 |
|
|
fprintf(outcf, "/* %s - generated from %s by crunchgen %s */\n", |
810 |
|
|
outcfname, infilename, CRUNCH_VERSION); |
811 |
|
|
|
812 |
|
|
fprintf(outcf, "#define EXECNAME \"%s\"\n", execfname); |
813 |
|
|
for (cp = crunched_skel; *cp != NULL; cp++) |
814 |
|
|
fprintf(outcf, "%s\n", *cp); |
815 |
|
|
|
816 |
|
|
for (p = progs; p != NULL; p = p->next) |
817 |
|
|
fprintf(outcf, "extern int _crunched_%s_stub();\n", p->ident); |
818 |
|
|
|
819 |
|
|
fprintf(outcf, "\nstruct stub entry_points[] = {\n"); |
820 |
|
|
for (p = progs; p != NULL; p = p->next) { |
821 |
|
|
fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n", |
822 |
|
|
p->name, p->ident); |
823 |
|
|
for (s = p->links; s != NULL; s = s->next) |
824 |
|
|
fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n", |
825 |
|
|
s->str, p->ident); |
826 |
|
|
} |
827 |
|
|
|
828 |
|
|
fprintf(outcf, "\t{ EXECNAME, crunched_main },\n"); |
829 |
|
|
fprintf(outcf, "\t{ NULL, NULL }\n};\n"); |
830 |
|
|
fclose(outcf); |
831 |
|
|
} |
832 |
|
|
|
833 |
|
|
char * |
834 |
|
|
genident(char *str) |
835 |
|
|
{ |
836 |
|
|
char *n, *s, *d; |
837 |
|
|
|
838 |
|
|
/* |
839 |
|
|
* generates a Makefile/C identifier from a program name, mapping '-' to |
840 |
|
|
* '_' and ignoring all other non-identifier characters. This leads to |
841 |
|
|
* programs named "foo.bar" and "foobar" to map to the same identifier. |
842 |
|
|
*/ |
843 |
|
|
|
844 |
|
|
if ((n = strdup(str)) == NULL) |
845 |
|
|
return NULL; |
846 |
|
|
for (d = s = n; *s != '\0'; s++) { |
847 |
|
|
if (*s == '-') |
848 |
|
|
*d++ = '_'; |
849 |
|
|
else if (*s == '_' || isalnum((unsigned char)*s)) |
850 |
|
|
*d++ = *s; |
851 |
|
|
} |
852 |
|
|
*d = '\0'; |
853 |
|
|
return n; |
854 |
|
|
} |
855 |
|
|
|
856 |
|
|
char * |
857 |
|
|
dir_search(char *progname) |
858 |
|
|
{ |
859 |
|
|
char path[PATH_MAX]; |
860 |
|
|
strlst_t *dir; |
861 |
|
|
|
862 |
|
|
for (dir = srcdirs; dir != NULL; dir = dir->next) { |
863 |
|
|
snprintf(path, sizeof(path), "%s/%s", dir->str, progname); |
864 |
|
|
if (is_dir(path)) |
865 |
|
|
return dir->str; |
866 |
|
|
} |
867 |
|
|
return NULL; |
868 |
|
|
} |
869 |
|
|
|
870 |
|
|
void |
871 |
|
|
top_makefile_rules(FILE * outmk) |
872 |
|
|
{ |
873 |
|
|
prog_t *p; |
874 |
|
|
strlst_t *l; |
875 |
|
|
|
876 |
|
|
|
877 |
|
|
fprintf(outmk, ".include <bsd.own.mk>\n"); |
878 |
|
|
fprintf(outmk, "CFLAGS+=$(NOPIE_FLAGS)\n"); |
879 |
|
|
fprintf(outmk, "CFLAGS+=-Oz\n"); |
880 |
|
|
fprintf(outmk, "LDFLAGS+=$(NOPIE_LDFLAGS)\n"); |
881 |
|
|
fprintf(outmk, "STRIP?=strip\n"); |
882 |
|
|
fprintf(outmk, "LINK=$(LD) -dc -r ${LDFLAGS}\n"); |
883 |
|
|
fprintf(outmk, "LIBS="); |
884 |
|
|
for (l = libdirs; l != NULL; l = l->next) |
885 |
|
|
fprintf(outmk, " -L%s", l->str); |
886 |
|
|
output_strlst(outmk, libs); |
887 |
|
|
|
888 |
|
|
fprintf(outmk, "CRUNCHED_OBJS="); |
889 |
|
|
for (p = progs; p != NULL; p = p->next) |
890 |
|
|
fprintf(outmk, " %s.lo", p->name); |
891 |
|
|
fprintf(outmk, "\n"); |
892 |
|
|
|
893 |
|
|
fprintf(outmk, "SUBMAKE_TARGETS="); |
894 |
|
|
for (p = progs; p != NULL; p = p->next) |
895 |
|
|
fprintf(outmk, " %s_make", p->ident); |
896 |
|
|
fprintf(outmk, "\n\n"); |
897 |
|
|
|
898 |
|
|
fprintf(outmk, "CLIB=\n"); |
899 |
|
|
fprintf(outmk, ".if defined(SRCLIBDIR)\n"); |
900 |
|
|
fprintf(outmk, ". for lib in ${LIBS:M-l*:S/-l//}\n"); |
901 |
|
|
fprintf(outmk, ". if exists(${SRCLIBDIR}/lib${lib})\n"); |
902 |
|
|
fprintf(outmk, "CLIB+=lib${lib}.a\n"); |
903 |
|
|
fprintf(outmk, ". endif\n"); |
904 |
|
|
fprintf(outmk, ". endfor\n"); |
905 |
|
|
fprintf(outmk, ".endif\n\n"); |
906 |
|
|
|
907 |
|
|
fprintf(outmk, "%s: %s.o $(CRUNCHED_OBJS) ${CLIB}\n", |
908 |
|
|
execfname, execfname); |
909 |
|
|
fprintf(outmk, "\t$(CC) -static -L. ${LDFLAGS} -o $@ %s.o $(CRUNCHED_OBJS) $(LIBS)\n", |
910 |
|
|
execfname); |
911 |
|
|
fprintf(outmk, "\t$(STRIP) %s\n", execfname); |
912 |
|
|
|
913 |
|
|
fprintf(outmk, "\n"); |
914 |
|
|
fprintf(outmk, ".if !empty(CLIB)\n"); |
915 |
|
|
fprintf(outmk, ".SUFFIXES: .a .olist\n"); |
916 |
|
|
fprintf(outmk, ".olist.a:\n"); |
917 |
|
|
fprintf(outmk, "\t@rm -f ${.TARGET}\n"); |
918 |
|
|
fprintf(outmk, "\t@cd ${SRCLIBDIR}/${.PREFIX} &&\t\t\t\t\\\n"); |
919 |
|
|
fprintf(outmk, "\t${MAKE} DIST_OBJS=\"`cat ${.OBJDIR}/${.IMPSRC}`\"\t\t\\\n"); |
920 |
|
|
fprintf(outmk, "\t DIST_LIB=${.OBJDIR}/${.TARGET} ${.OBJDIR}/${.TARGET}\n\n"); |
921 |
|
|
|
922 |
|
|
fprintf(outmk, "%s.map: %s.o $(CRUNCHED_OBJS)\n", execfname, execfname); |
923 |
|
|
fprintf(outmk, "\t$(CC) -static ${LDFLAGS} -o %s.o.o %s.o $(CRUNCHED_OBJS) \\\n", execfname, execfname); |
924 |
|
|
fprintf(outmk, "\t $(LIBS) -Wl,--trace | sed -e 's/^(\\(..*\\))\\(..*\\)/\\1(\\2)/' >${.TARGET}\n\n"); |
925 |
|
|
|
926 |
|
|
fprintf(outmk, "${CLIB:.a=.olist}: %s.map\n", execfname); |
927 |
|
|
fprintf(outmk, "\tsed -n -e 's!^${DESTDIR}/usr/lib/${.TARGET:R}\\.a(\\([^)]*\\.o\\)).*!\\1!p' \\\n"); |
928 |
|
|
fprintf(outmk, "\t < %s.map | tr '\\012' ' ' >$@\n", execfname); |
929 |
|
|
fprintf(outmk, ".endif\n\n"); |
930 |
|
|
|
931 |
|
|
fprintf(outmk, "all: objs exe\nobjs: $(SUBMAKE_TARGETS)\n"); |
932 |
|
|
fprintf(outmk, "exe: %s\n", execfname); |
933 |
|
|
fprintf(outmk, "clean:\n\trm -f %s *.lo *.o *_stub.c\n", |
934 |
|
|
execfname); |
935 |
|
|
fprintf(outmk, ".PHONY: all objs exe clean $(SUBMAKE_TARGETS)\n\n"); |
936 |
|
|
} |
937 |
|
|
|
938 |
|
|
void |
939 |
|
|
prog_makefile_rules(FILE * outmk, prog_t * p) |
940 |
|
|
{ |
941 |
|
|
fprintf(outmk, "\n# -------- %s\n\n", p->name); |
942 |
|
|
|
943 |
|
|
if (p->srcdir && p->objs) { |
944 |
|
|
fprintf(outmk, "%s_SRCDIR=%s\n", p->ident, p->srcdir); |
945 |
|
|
fprintf(outmk, "%s_OBJS=", p->ident); |
946 |
|
|
output_strlst(outmk, p->objs); |
947 |
|
|
fprintf(outmk, "%s_make:\n", p->ident); |
948 |
|
|
fprintf(outmk, "\tcd $(%s_SRCDIR) && exec $(MAKE) -f %s $(%s_OBJS)\n\n", |
949 |
|
|
p->ident, p->mf_name, p->ident); |
950 |
|
|
} else |
951 |
|
|
fprintf(outmk, "%s_make:\n\t@echo \"** cannot make objs for %s\"\n\n", |
952 |
|
|
p->ident, p->name); |
953 |
|
|
|
954 |
|
|
fprintf(outmk, "%s_OBJPATHS=", p->ident); |
955 |
|
|
output_strlst(outmk, p->objpaths); |
956 |
|
|
|
957 |
|
|
fprintf(outmk, "%s_stub.c:\n", p->name); |
958 |
|
|
fprintf(outmk, "\t@echo \"" |
959 |
|
|
"extern int main(int argc, char **argv, char **envp);\\\n" |
960 |
|
|
"int _crunched_%s_stub(int argc, char **argv, char **envp)" |
961 |
|
|
" { return main(argc, argv, envp); }\" >$@\n", |
962 |
|
|
p->ident); |
963 |
|
|
fprintf(outmk, "%s.lo: %s_stub.o $(%s_OBJPATHS)\n", |
964 |
|
|
p->name, p->name, p->ident); |
965 |
|
|
fprintf(outmk, "\t$(LINK) -o $@ %s_stub.o $(%s_OBJPATHS)\n", |
966 |
|
|
p->name, p->ident); |
967 |
|
|
fprintf(outmk, "\tcrunchgen -h %s -k %s_crunched_%s_stub $@\n", |
968 |
|
|
elf_mangle ? "-M" : "", |
969 |
|
|
elf_names ? "" : "_", p->ident); |
970 |
|
|
} |
971 |
|
|
|
972 |
|
|
void |
973 |
|
|
output_strlst(FILE * outf, strlst_t * lst) |
974 |
|
|
{ |
975 |
|
|
for (; lst != NULL; lst = lst->next) |
976 |
|
|
fprintf(outf, " %s", lst->str); |
977 |
|
|
fprintf(outf, "\n"); |
978 |
|
|
} |
979 |
|
|
|
980 |
|
|
void |
981 |
|
|
out_of_memory(void) |
982 |
|
|
{ |
983 |
|
|
fprintf(stderr, "%s: %d: out of memory, stopping.\n", infilename, linenum); |
984 |
|
|
exit(1); |
985 |
|
|
} |
986 |
|
|
|
987 |
|
|
void |
988 |
|
|
add_string(strlst_t ** listp, char *str) |
989 |
|
|
{ |
990 |
|
|
strlst_t *p1, *p2; |
991 |
|
|
|
992 |
|
|
/* add to end, but be smart about dups */ |
993 |
|
|
|
994 |
|
|
for (p1 = NULL, p2 = *listp; p2 != NULL; p1 = p2, p2 = p2->next) |
995 |
|
|
if (!strcmp(p2->str, str)) |
996 |
|
|
return; |
997 |
|
|
|
998 |
|
|
p2 = calloc(1, sizeof(strlst_t)); |
999 |
|
|
if (p2) |
1000 |
|
|
p2->str = strdup(str); |
1001 |
|
|
if (!p2 || !p2->str) |
1002 |
|
|
out_of_memory(); |
1003 |
|
|
|
1004 |
|
|
p2->next = NULL; |
1005 |
|
|
if (p1 == NULL) |
1006 |
|
|
*listp = p2; |
1007 |
|
|
else |
1008 |
|
|
p1->next = p2; |
1009 |
|
|
} |
1010 |
|
|
|
1011 |
|
|
int |
1012 |
|
|
is_dir(char *pathname) |
1013 |
|
|
{ |
1014 |
|
|
struct stat buf; |
1015 |
|
|
|
1016 |
|
|
if (stat(pathname, &buf) == -1) |
1017 |
|
|
return 0; |
1018 |
|
|
return S_ISDIR(buf.st_mode); |
1019 |
|
|
} |
1020 |
|
|
|
1021 |
|
|
int |
1022 |
|
|
is_nonempty_file(char *pathname) |
1023 |
|
|
{ |
1024 |
|
|
struct stat buf; |
1025 |
|
|
|
1026 |
|
|
if (stat(pathname, &buf) == -1) |
1027 |
|
|
return 0; |
1028 |
|
|
|
1029 |
|
|
return S_ISREG(buf.st_mode) && buf.st_size > 0; |
1030 |
|
|
} |