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