xref: /freebsd/usr.sbin/crunch/crunchgen/crunchgen.c (revision db7f7446b5bcb26c7aaf13c8151b4ae8051c5732)
1de566360SJordan K. Hubbard /*
2de566360SJordan K. Hubbard  * Copyright (c) 1994 University of Maryland
3de566360SJordan K. Hubbard  * All Rights Reserved.
4de566360SJordan K. Hubbard  *
5de566360SJordan K. Hubbard  * Permission to use, copy, modify, distribute, and sell this software and its
6de566360SJordan K. Hubbard  * documentation for any purpose is hereby granted without fee, provided that
7de566360SJordan K. Hubbard  * the above copyright notice appear in all copies and that both that
8de566360SJordan K. Hubbard  * copyright notice and this permission notice appear in supporting
9de566360SJordan K. Hubbard  * documentation, and that the name of U.M. not be used in advertising or
10de566360SJordan K. Hubbard  * publicity pertaining to distribution of the software without specific,
11de566360SJordan K. Hubbard  * written prior permission.  U.M. makes no representations about the
12de566360SJordan K. Hubbard  * suitability of this software for any purpose.  It is provided "as is"
13de566360SJordan K. Hubbard  * without express or implied warranty.
14de566360SJordan K. Hubbard  *
15de566360SJordan K. Hubbard  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
16de566360SJordan K. Hubbard  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
17de566360SJordan K. Hubbard  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18de566360SJordan K. Hubbard  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
19de566360SJordan K. Hubbard  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20de566360SJordan K. Hubbard  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21de566360SJordan K. Hubbard  *
22de566360SJordan K. Hubbard  * Author: James da Silva, Systems Design and Analysis Group
23de566360SJordan K. Hubbard  *			   Computer Science Department
24de566360SJordan K. Hubbard  *			   University of Maryland at College Park
25de566360SJordan K. Hubbard  */
26de566360SJordan K. Hubbard /*
27de566360SJordan K. Hubbard  * ========================================================================
28de566360SJordan K. Hubbard  * crunchgen.c
29de566360SJordan K. Hubbard  *
30de566360SJordan K. Hubbard  * Generates a Makefile and main C file for a crunched executable,
31de566360SJordan K. Hubbard  * from specs given in a .conf file.
32de566360SJordan K. Hubbard  */
3302c75192SDavid E. O'Brien 
3402c75192SDavid E. O'Brien #include <sys/cdefs.h>
3502c75192SDavid E. O'Brien __FBSDID("$FreeBSD$");
3602c75192SDavid E. O'Brien 
3787eb4a42SJosef Karthauser #include <sys/param.h>
3802c75192SDavid E. O'Brien #include <sys/stat.h>
3987eb4a42SJosef Karthauser 
40de566360SJordan K. Hubbard #include <ctype.h>
41b17e90a9SPhilippe Charnier #include <err.h>
42188d6f4bSAlex Richardson #include <fcntl.h>
4361ffadb1SJosef Karthauser #include <paths.h>
44188d6f4bSAlex Richardson #include <stdbool.h>
45b17e90a9SPhilippe Charnier #include <stdio.h>
46b17e90a9SPhilippe Charnier #include <stdlib.h>
47de566360SJordan K. Hubbard #include <string.h>
48188d6f4bSAlex Richardson #include <sysexits.h>
49b17e90a9SPhilippe Charnier #include <unistd.h>
50de566360SJordan K. Hubbard 
51de566360SJordan K. Hubbard #define CRUNCH_VERSION	"0.2"
52de566360SJordan K. Hubbard 
53de566360SJordan K. Hubbard #define MAXLINELEN	16384
54de566360SJordan K. Hubbard #define MAXFIELDS 	 2048
55de566360SJordan K. Hubbard 
56de566360SJordan K. Hubbard 
57de566360SJordan K. Hubbard /* internal representation of conf file: */
58de566360SJordan K. Hubbard 
59de566360SJordan K. Hubbard /* simple lists of strings suffice for most parms */
60de566360SJordan K. Hubbard 
61de566360SJordan K. Hubbard typedef struct strlst {
62de566360SJordan K. Hubbard 	struct strlst *next;
63de566360SJordan K. Hubbard 	char *str;
64de566360SJordan K. Hubbard } strlst_t;
65de566360SJordan K. Hubbard 
66de566360SJordan K. Hubbard /* progs have structure, each field can be set with "special" or calculated */
67de566360SJordan K. Hubbard 
68de566360SJordan K. Hubbard typedef struct prog {
6908826cadSLuigi Rizzo 	struct prog *next;	/* link field */
7008826cadSLuigi Rizzo 	char *name;		/* program name */
7108826cadSLuigi Rizzo 	char *ident;		/* C identifier for the program name */
7208826cadSLuigi Rizzo 	char *srcdir;
73843d8d51SJosef Karthauser 	char *realsrcdir;
7408826cadSLuigi Rizzo 	char *objdir;
7508826cadSLuigi Rizzo 	char *objvar;		/* Makefile variable to replace OBJS */
76de566360SJordan K. Hubbard 	strlst_t *objs, *objpaths;
7734944d48SJosef Karthauser 	strlst_t *buildopts;
7842ac3bf1SJoerg Wunsch 	strlst_t *keeplist;
79de566360SJordan K. Hubbard 	strlst_t *links;
80252f13abSLuigi Rizzo 	strlst_t *libs;
8155f92f64SCeri Davies 	strlst_t *libs_so;
82de566360SJordan K. Hubbard 	int goterror;
83de566360SJordan K. Hubbard } prog_t;
84de566360SJordan K. Hubbard 
85de566360SJordan K. Hubbard 
86de566360SJordan K. Hubbard /* global state */
87de566360SJordan K. Hubbard 
8808a15190SJosef Karthauser strlst_t *buildopts = NULL;
89de566360SJordan K. Hubbard strlst_t *srcdirs   = NULL;
90de566360SJordan K. Hubbard strlst_t *libs      = NULL;
9155f92f64SCeri Davies strlst_t *libs_so   = NULL;
92de566360SJordan K. Hubbard prog_t   *progs     = NULL;
93de566360SJordan K. Hubbard 
94de566360SJordan K. Hubbard char confname[MAXPATHLEN], infilename[MAXPATHLEN];
95de566360SJordan K. Hubbard char outmkname[MAXPATHLEN], outcfname[MAXPATHLEN], execfname[MAXPATHLEN];
96de566360SJordan K. Hubbard char tempfname[MAXPATHLEN], cachename[MAXPATHLEN], curfilename[MAXPATHLEN];
97188d6f4bSAlex Richardson bool tempfname_initialized = false;
9808826cadSLuigi Rizzo char outhdrname[MAXPATHLEN] ;	/* user-supplied header for *.mk */
99*db7f7446SKyle Evans const char *objprefix;		/* where are the objects ? */
100*db7f7446SKyle Evans const char *path_make;
101de566360SJordan K. Hubbard int linenum = -1;
102de566360SJordan K. Hubbard int goterror = 0;
103de566360SJordan K. Hubbard 
104de566360SJordan K. Hubbard int verbose, readcache;		/* options */
105de566360SJordan K. Hubbard int reading_cache;
106ba2250ddSJosef Karthauser int makeobj = 0;		/* add 'make obj' rules to the makefile */
107de566360SJordan K. Hubbard 
108fb7f926eSPoul-Henning Kamp int list_mode;
109fb7f926eSPoul-Henning Kamp 
110de566360SJordan K. Hubbard /* general library routines */
111de566360SJordan K. Hubbard 
11296acb2c4SPedro F. Giffuni void status(const char *str);
113de566360SJordan K. Hubbard void out_of_memory(void);
114de566360SJordan K. Hubbard void add_string(strlst_t **listp, char *str);
11596acb2c4SPedro F. Giffuni int is_dir(const char *pathname);
11696acb2c4SPedro F. Giffuni int is_nonempty_file(const char *pathname);
11755f92f64SCeri Davies int subtract_strlst(strlst_t **lista, strlst_t **listb);
11855f92f64SCeri Davies int in_list(strlst_t **listp, char *str);
119de566360SJordan K. Hubbard 
120997d42d7SPedro F. Giffuni /* helper routines for main() */
121de566360SJordan K. Hubbard 
122de566360SJordan K. Hubbard void usage(void);
123de566360SJordan K. Hubbard void parse_conf_file(void);
124de566360SJordan K. Hubbard void gen_outputs(void);
125de566360SJordan K. Hubbard 
126*db7f7446SKyle Evans extern const char *crunched_skel[];
127997d42d7SPedro F. Giffuni 
128de566360SJordan K. Hubbard 
12902c75192SDavid E. O'Brien int
13002c75192SDavid E. O'Brien main(int argc, char **argv)
131de566360SJordan K. Hubbard {
132de566360SJordan K. Hubbard 	char *p;
133de566360SJordan K. Hubbard 	int optc;
134de566360SJordan K. Hubbard 
135de566360SJordan K. Hubbard 	verbose = 1;
136de566360SJordan K. Hubbard 	readcache = 1;
137de566360SJordan K. Hubbard 	*outmkname = *outcfname = *execfname = '\0';
138de566360SJordan K. Hubbard 
13970840a51SDavid E. O'Brien 	path_make = getenv("MAKE");
14070840a51SDavid E. O'Brien 	if (path_make == NULL || *path_make == '\0')
14170840a51SDavid E. O'Brien 		path_make = "make";
14270840a51SDavid E. O'Brien 
143019d04d1SLuigi Rizzo 	p = getenv("MAKEOBJDIRPREFIX");
144019d04d1SLuigi Rizzo 	if (p == NULL || *p == '\0')
145019d04d1SLuigi Rizzo 		objprefix = "/usr/obj"; /* default */
146019d04d1SLuigi Rizzo 	else
147f3c47f54SJosef Karthauser 		if ((objprefix = strdup(p)) == NULL)
148f3c47f54SJosef Karthauser 			out_of_memory();
149019d04d1SLuigi Rizzo 
150019d04d1SLuigi Rizzo 	while((optc = getopt(argc, argv, "lh:m:c:e:p:foq")) != -1) {
151de566360SJordan K. Hubbard 		switch(optc) {
15287eb4a42SJosef Karthauser 		case 'f':
15387eb4a42SJosef Karthauser 			readcache = 0;
15487eb4a42SJosef Karthauser 			break;
15587eb4a42SJosef Karthauser 		case 'o':
15687eb4a42SJosef Karthauser 			makeobj = 1;
15787eb4a42SJosef Karthauser 			break;
15887eb4a42SJosef Karthauser 		case 'q':
15987eb4a42SJosef Karthauser 			verbose = 0;
16087eb4a42SJosef Karthauser 			break;
161de566360SJordan K. Hubbard 
16287eb4a42SJosef Karthauser 		case 'm':
16387eb4a42SJosef Karthauser 			strlcpy(outmkname, optarg, sizeof(outmkname));
16487eb4a42SJosef Karthauser 			break;
16587eb4a42SJosef Karthauser 		case 'p':
16687eb4a42SJosef Karthauser 			if ((objprefix = strdup(optarg)) == NULL)
167f3c47f54SJosef Karthauser 				out_of_memory();
168f3c47f54SJosef Karthauser 			break;
16987eb4a42SJosef Karthauser 
17087eb4a42SJosef Karthauser 		case 'h':
17187eb4a42SJosef Karthauser 			strlcpy(outhdrname, optarg, sizeof(outhdrname));
17287eb4a42SJosef Karthauser 			break;
17387eb4a42SJosef Karthauser 		case 'c':
17487eb4a42SJosef Karthauser 			strlcpy(outcfname, optarg, sizeof(outcfname));
17587eb4a42SJosef Karthauser 			break;
17687eb4a42SJosef Karthauser 		case 'e':
17787eb4a42SJosef Karthauser 			strlcpy(execfname, optarg, sizeof(execfname));
17887eb4a42SJosef Karthauser 			break;
17987eb4a42SJosef Karthauser 
18087eb4a42SJosef Karthauser 		case 'l':
18187eb4a42SJosef Karthauser 			list_mode++;
18287eb4a42SJosef Karthauser 			verbose = 0;
18387eb4a42SJosef Karthauser 			break;
184de566360SJordan K. Hubbard 
185de566360SJordan K. Hubbard 		case '?':
18687eb4a42SJosef Karthauser 		default:
18787eb4a42SJosef Karthauser 			usage();
188de566360SJordan K. Hubbard 		}
189de566360SJordan K. Hubbard 	}
190de566360SJordan K. Hubbard 
191de566360SJordan K. Hubbard 	argc -= optind;
192de566360SJordan K. Hubbard 	argv += optind;
193de566360SJordan K. Hubbard 
19487eb4a42SJosef Karthauser 	if (argc != 1)
19587eb4a42SJosef Karthauser 		usage();
196de566360SJordan K. Hubbard 
197de566360SJordan K. Hubbard 	/*
198de566360SJordan K. Hubbard 	 * generate filenames
199de566360SJordan K. Hubbard 	 */
200de566360SJordan K. Hubbard 
201f3c47f54SJosef Karthauser 	strlcpy(infilename, argv[0], sizeof(infilename));
202de566360SJordan K. Hubbard 
203de566360SJordan K. Hubbard 	/* confname = `basename infilename .conf` */
204de566360SJordan K. Hubbard 
205f3c47f54SJosef Karthauser 	if ((p=strrchr(infilename, '/')) != NULL)
206f3c47f54SJosef Karthauser 		strlcpy(confname, p + 1, sizeof(confname));
207f3c47f54SJosef Karthauser 	else
208f3c47f54SJosef Karthauser 		strlcpy(confname, infilename, sizeof(confname));
209de566360SJordan K. Hubbard 
21087eb4a42SJosef Karthauser 	if ((p=strrchr(confname, '.')) != NULL && !strcmp(p, ".conf"))
21187eb4a42SJosef Karthauser 		*p = '\0';
21287eb4a42SJosef Karthauser 
21387eb4a42SJosef Karthauser 	if (!*outmkname)
21487eb4a42SJosef Karthauser 		snprintf(outmkname, sizeof(outmkname), "%s.mk", confname);
21587eb4a42SJosef Karthauser 	if (!*outcfname)
21687eb4a42SJosef Karthauser 		snprintf(outcfname, sizeof(outcfname), "%s.c", confname);
21787eb4a42SJosef Karthauser 	if (!*execfname)
21887eb4a42SJosef Karthauser 		snprintf(execfname, sizeof(execfname), "%s", confname);
219de566360SJordan K. Hubbard 
220019d04d1SLuigi Rizzo 	snprintf(cachename, sizeof(cachename), "%s.cache", confname);
22161ffadb1SJosef Karthauser 	snprintf(tempfname, sizeof(tempfname), "%s/crunchgen_%sXXXXXX",
22261ffadb1SJosef Karthauser 	getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP, confname);
223188d6f4bSAlex Richardson 	tempfname_initialized = false;
224de566360SJordan K. Hubbard 
225de566360SJordan K. Hubbard 	parse_conf_file();
226fb7f926eSPoul-Henning Kamp 	if (list_mode)
227fb7f926eSPoul-Henning Kamp 		exit(goterror);
228fb7f926eSPoul-Henning Kamp 
229de566360SJordan K. Hubbard 	gen_outputs();
230de566360SJordan K. Hubbard 
231de566360SJordan K. Hubbard 	exit(goterror);
232de566360SJordan K. Hubbard }
233de566360SJordan K. Hubbard 
234de566360SJordan K. Hubbard 
23502c75192SDavid E. O'Brien void
23602c75192SDavid E. O'Brien usage(void)
237de566360SJordan K. Hubbard {
23887eb4a42SJosef Karthauser 	fprintf(stderr, "%s%s\n\t%s%s\n", "usage: crunchgen [-foq] ",
23987eb4a42SJosef Karthauser 	    "[-h <makefile-header-name>] [-m <makefile>]",
24087eb4a42SJosef Karthauser 	    "[-p <obj-prefix>] [-c <c-file-name>] [-e <exec-file>] ",
24187eb4a42SJosef Karthauser 	    "<conffile>");
242de566360SJordan K. Hubbard 	exit(1);
243de566360SJordan K. Hubbard }
244de566360SJordan K. Hubbard 
245de566360SJordan K. Hubbard 
246de566360SJordan K. Hubbard /*
247de566360SJordan K. Hubbard  * ========================================================================
248de566360SJordan K. Hubbard  * parse_conf_file subsystem
249de566360SJordan K. Hubbard  *
250de566360SJordan K. Hubbard  */
251de566360SJordan K. Hubbard 
252de566360SJordan K. Hubbard /* helper routines for parse_conf_file */
253de566360SJordan K. Hubbard 
254de566360SJordan K. Hubbard void parse_one_file(char *filename);
25596acb2c4SPedro F. Giffuni void parse_line(char *pline, int *fc, char **fv, int nf);
256de566360SJordan K. Hubbard void add_srcdirs(int argc, char **argv);
257de566360SJordan K. Hubbard void add_progs(int argc, char **argv);
258de566360SJordan K. Hubbard void add_link(int argc, char **argv);
259de566360SJordan K. Hubbard void add_libs(int argc, char **argv);
26055f92f64SCeri Davies void add_libs_so(int argc, char **argv);
26108a15190SJosef Karthauser void add_buildopts(int argc, char **argv);
262de566360SJordan K. Hubbard void add_special(int argc, char **argv);
263de566360SJordan K. Hubbard 
264de566360SJordan K. Hubbard prog_t *find_prog(char *str);
265de566360SJordan K. Hubbard void add_prog(char *progname);
266de566360SJordan K. Hubbard 
267de566360SJordan K. Hubbard 
26802c75192SDavid E. O'Brien void
26902c75192SDavid E. O'Brien parse_conf_file(void)
270de566360SJordan K. Hubbard {
271b17e90a9SPhilippe Charnier 	if (!is_nonempty_file(infilename))
272b17e90a9SPhilippe Charnier 		errx(1, "fatal: input file \"%s\" not found", infilename);
27387eb4a42SJosef Karthauser 
274de566360SJordan K. Hubbard 	parse_one_file(infilename);
275de566360SJordan K. Hubbard 	if (readcache && is_nonempty_file(cachename)) {
276de566360SJordan K. Hubbard 		reading_cache = 1;
277de566360SJordan K. Hubbard 		parse_one_file(cachename);
278de566360SJordan K. Hubbard 	}
279de566360SJordan K. Hubbard }
280de566360SJordan K. Hubbard 
281de566360SJordan K. Hubbard 
28202c75192SDavid E. O'Brien void
28302c75192SDavid E. O'Brien parse_one_file(char *filename)
284de566360SJordan K. Hubbard {
285de566360SJordan K. Hubbard 	char *fieldv[MAXFIELDS];
286de566360SJordan K. Hubbard 	int fieldc;
287de566360SJordan K. Hubbard 	void (*f)(int c, char **v);
288de566360SJordan K. Hubbard 	FILE *cf;
289019d04d1SLuigi Rizzo 	char line[MAXLINELEN];
290de566360SJordan K. Hubbard 
291f3c47f54SJosef Karthauser 	snprintf(line, sizeof(line), "reading %s", filename);
292de566360SJordan K. Hubbard 	status(line);
293f3c47f54SJosef Karthauser 	strlcpy(curfilename, filename, sizeof(curfilename));
294de566360SJordan K. Hubbard 
295de566360SJordan K. Hubbard 	if ((cf = fopen(curfilename, "r")) == NULL) {
296b17e90a9SPhilippe Charnier 		warn("%s", curfilename);
297de566360SJordan K. Hubbard 		goterror = 1;
298de566360SJordan K. Hubbard 		return;
299de566360SJordan K. Hubbard 	}
300de566360SJordan K. Hubbard 
301de566360SJordan K. Hubbard 	linenum = 0;
302de566360SJordan K. Hubbard 	while (fgets(line, MAXLINELEN, cf) != NULL) {
303de566360SJordan K. Hubbard 		linenum++;
304de566360SJordan K. Hubbard 		parse_line(line, &fieldc, fieldv, MAXFIELDS);
30587eb4a42SJosef Karthauser 
30687eb4a42SJosef Karthauser 		if (fieldc < 1)
30787eb4a42SJosef Karthauser 			continue;
30887eb4a42SJosef Karthauser 
30987eb4a42SJosef Karthauser 		if (!strcmp(fieldv[0], "srcdirs"))
31087eb4a42SJosef Karthauser 			f = add_srcdirs;
31187eb4a42SJosef Karthauser 		else if(!strcmp(fieldv[0], "progs"))
31287eb4a42SJosef Karthauser 			f = add_progs;
31387eb4a42SJosef Karthauser 		else if(!strcmp(fieldv[0], "ln"))
31487eb4a42SJosef Karthauser 			f = add_link;
31587eb4a42SJosef Karthauser 		else if(!strcmp(fieldv[0], "libs"))
31687eb4a42SJosef Karthauser 			f = add_libs;
31755f92f64SCeri Davies 		else if(!strcmp(fieldv[0], "libs_so"))
31855f92f64SCeri Davies 			f = add_libs_so;
31987eb4a42SJosef Karthauser 		else if(!strcmp(fieldv[0], "buildopts"))
32087eb4a42SJosef Karthauser 			f = add_buildopts;
32187eb4a42SJosef Karthauser 		else if(!strcmp(fieldv[0], "special"))
32287eb4a42SJosef Karthauser 			f = add_special;
323de566360SJordan K. Hubbard 		else {
324b17e90a9SPhilippe Charnier 			warnx("%s:%d: skipping unknown command `%s'",
325de566360SJordan K. Hubbard 			    curfilename, linenum, fieldv[0]);
326de566360SJordan K. Hubbard 			goterror = 1;
327de566360SJordan K. Hubbard 			continue;
328de566360SJordan K. Hubbard 		}
32987eb4a42SJosef Karthauser 
330de566360SJordan K. Hubbard 		if (fieldc < 2) {
33187eb4a42SJosef Karthauser 			warnx("%s:%d: %s %s",
33287eb4a42SJosef Karthauser 			    curfilename, linenum, fieldv[0],
33387eb4a42SJosef Karthauser 			    "command needs at least 1 argument, skipping");
334de566360SJordan K. Hubbard 			goterror = 1;
335de566360SJordan K. Hubbard 			continue;
336de566360SJordan K. Hubbard 		}
33787eb4a42SJosef Karthauser 
338de566360SJordan K. Hubbard 		f(fieldc, fieldv);
339de566360SJordan K. Hubbard 	}
340de566360SJordan K. Hubbard 
341de566360SJordan K. Hubbard 	if (ferror(cf)) {
342b17e90a9SPhilippe Charnier 		warn("%s", curfilename);
343de566360SJordan K. Hubbard 		goterror = 1;
344de566360SJordan K. Hubbard 	}
345de566360SJordan K. Hubbard 	fclose(cf);
346de566360SJordan K. Hubbard }
347de566360SJordan K. Hubbard 
348de566360SJordan K. Hubbard 
34902c75192SDavid E. O'Brien void
35096acb2c4SPedro F. Giffuni parse_line(char *pline, int *fc, char **fv, int nf)
351de566360SJordan K. Hubbard {
352de566360SJordan K. Hubbard 	char *p;
353de566360SJordan K. Hubbard 
35496acb2c4SPedro F. Giffuni 	p = pline;
355de566360SJordan K. Hubbard 	*fc = 0;
356de566360SJordan K. Hubbard 
35787eb4a42SJosef Karthauser 	while (1) {
35896acb2c4SPedro F. Giffuni 		while (isspace((unsigned char)*p))
35987eb4a42SJosef Karthauser 			p++;
36087eb4a42SJosef Karthauser 
36187eb4a42SJosef Karthauser 		if (*p == '\0' || *p == '#')
36287eb4a42SJosef Karthauser 			break;
36387eb4a42SJosef Karthauser 
36487eb4a42SJosef Karthauser 		if (*fc < nf)
36587eb4a42SJosef Karthauser 			fv[(*fc)++] = p;
36687eb4a42SJosef Karthauser 
36796acb2c4SPedro F. Giffuni 		while (*p && !isspace((unsigned char)*p) && *p != '#')
36887eb4a42SJosef Karthauser 			p++;
36987eb4a42SJosef Karthauser 
37087eb4a42SJosef Karthauser 		if (*p == '\0' || *p == '#')
37187eb4a42SJosef Karthauser 			break;
37287eb4a42SJosef Karthauser 
373de566360SJordan K. Hubbard 		*p++ = '\0';
374de566360SJordan K. Hubbard 	}
37587eb4a42SJosef Karthauser 
37687eb4a42SJosef Karthauser 	if (*p)
37787eb4a42SJosef Karthauser 		*p = '\0';		/* needed for '#' case */
378de566360SJordan K. Hubbard }
379de566360SJordan K. Hubbard 
380de566360SJordan K. Hubbard 
38102c75192SDavid E. O'Brien void
38202c75192SDavid E. O'Brien add_srcdirs(int argc, char **argv)
383de566360SJordan K. Hubbard {
384de566360SJordan K. Hubbard 	int i;
385de566360SJordan K. Hubbard 
386de566360SJordan K. Hubbard 	for (i = 1; i < argc; i++) {
387de566360SJordan K. Hubbard 		if (is_dir(argv[i]))
388de566360SJordan K. Hubbard 			add_string(&srcdirs, argv[i]);
389de566360SJordan K. Hubbard 		else {
390b17e90a9SPhilippe Charnier 			warnx("%s:%d: `%s' is not a directory, skipping it",
391de566360SJordan K. Hubbard 			    curfilename, linenum, argv[i]);
392de566360SJordan K. Hubbard 			goterror = 1;
393de566360SJordan K. Hubbard 		}
394de566360SJordan K. Hubbard 	}
395de566360SJordan K. Hubbard }
396de566360SJordan K. Hubbard 
397de566360SJordan K. Hubbard 
39802c75192SDavid E. O'Brien void
39902c75192SDavid E. O'Brien add_progs(int argc, char **argv)
400de566360SJordan K. Hubbard {
401de566360SJordan K. Hubbard 	int i;
402de566360SJordan K. Hubbard 
403de566360SJordan K. Hubbard 	for (i = 1; i < argc; i++)
404de566360SJordan K. Hubbard 		add_prog(argv[i]);
405de566360SJordan K. Hubbard }
406de566360SJordan K. Hubbard 
407de566360SJordan K. Hubbard 
40802c75192SDavid E. O'Brien void
40902c75192SDavid E. O'Brien add_prog(char *progname)
410de566360SJordan K. Hubbard {
411de566360SJordan K. Hubbard 	prog_t *p1, *p2;
412de566360SJordan K. Hubbard 
413de566360SJordan K. Hubbard 	/* add to end, but be smart about dups */
414de566360SJordan K. Hubbard 
415de566360SJordan K. Hubbard 	for (p1 = NULL, p2 = progs; p2 != NULL; p1 = p2, p2 = p2->next)
41687eb4a42SJosef Karthauser 		if (!strcmp(p2->name, progname))
41787eb4a42SJosef Karthauser 			return;
418de566360SJordan K. Hubbard 
419de566360SJordan K. Hubbard 	p2 = malloc(sizeof(prog_t));
420eb148815SJoerg Wunsch 	if(p2) {
421eb148815SJoerg Wunsch 		memset(p2, 0, sizeof(prog_t));
422eb148815SJoerg Wunsch 		p2->name = strdup(progname);
423eb148815SJoerg Wunsch 	}
424de566360SJordan K. Hubbard 	if (!p2 || !p2->name)
425de566360SJordan K. Hubbard 		out_of_memory();
426de566360SJordan K. Hubbard 
427de566360SJordan K. Hubbard 	p2->next = NULL;
42887eb4a42SJosef Karthauser 	if (p1 == NULL)
42987eb4a42SJosef Karthauser 		progs = p2;
43087eb4a42SJosef Karthauser 	else
43187eb4a42SJosef Karthauser 		p1->next = p2;
432de566360SJordan K. Hubbard 
43387eb4a42SJosef Karthauser 	p2->ident = NULL;
43487eb4a42SJosef Karthauser 	p2->srcdir = NULL;
43587eb4a42SJosef Karthauser 	p2->realsrcdir = NULL;
43687eb4a42SJosef Karthauser 	p2->objdir = NULL;
43787eb4a42SJosef Karthauser 	p2->links = NULL;
438252f13abSLuigi Rizzo 	p2->libs = NULL;
43955f92f64SCeri Davies 	p2->libs_so = NULL;
44087eb4a42SJosef Karthauser 	p2->objs = NULL;
44187eb4a42SJosef Karthauser 	p2->keeplist = NULL;
44234944d48SJosef Karthauser 	p2->buildopts = NULL;
443de566360SJordan K. Hubbard 	p2->goterror = 0;
44487eb4a42SJosef Karthauser 
445fb7f926eSPoul-Henning Kamp 	if (list_mode)
446fb7f926eSPoul-Henning Kamp 		printf("%s\n",progname);
447de566360SJordan K. Hubbard }
448de566360SJordan K. Hubbard 
449de566360SJordan K. Hubbard 
45002c75192SDavid E. O'Brien void
45102c75192SDavid E. O'Brien add_link(int argc, char **argv)
452de566360SJordan K. Hubbard {
453de566360SJordan K. Hubbard 	int i;
454de566360SJordan K. Hubbard 	prog_t *p = find_prog(argv[1]);
455de566360SJordan K. Hubbard 
456de566360SJordan K. Hubbard 	if (p == NULL) {
457b17e90a9SPhilippe Charnier 		warnx("%s:%d: no prog %s previously declared, skipping link",
458de566360SJordan K. Hubbard 		    curfilename, linenum, argv[1]);
459de566360SJordan K. Hubbard 		goterror = 1;
460de566360SJordan K. Hubbard 		return;
461de566360SJordan K. Hubbard 	}
46287eb4a42SJosef Karthauser 
463fb7f926eSPoul-Henning Kamp 	for (i = 2; i < argc; i++) {
464fb7f926eSPoul-Henning Kamp 		if (list_mode)
465fb7f926eSPoul-Henning Kamp 			printf("%s\n",argv[i]);
46687eb4a42SJosef Karthauser 
467de566360SJordan K. Hubbard 		add_string(&p->links, argv[i]);
468de566360SJordan K. Hubbard 	}
469fb7f926eSPoul-Henning Kamp }
470de566360SJordan K. Hubbard 
471de566360SJordan K. Hubbard 
47202c75192SDavid E. O'Brien void
47302c75192SDavid E. O'Brien add_libs(int argc, char **argv)
474de566360SJordan K. Hubbard {
475de566360SJordan K. Hubbard 	int i;
476de566360SJordan K. Hubbard 
47755f92f64SCeri Davies 	for(i = 1; i < argc; i++) {
478de566360SJordan K. Hubbard 		add_string(&libs, argv[i]);
47955f92f64SCeri Davies 		if ( in_list(&libs_so, argv[i]) )
48055f92f64SCeri Davies 			warnx("%s:%d: "
48155f92f64SCeri Davies 				"library `%s' specified as dynamic earlier",
48255f92f64SCeri Davies 				curfilename, linenum, argv[i]);
48355f92f64SCeri Davies 	}
48455f92f64SCeri Davies }
48555f92f64SCeri Davies 
48655f92f64SCeri Davies 
48702c75192SDavid E. O'Brien void
48802c75192SDavid E. O'Brien add_libs_so(int argc, char **argv)
48955f92f64SCeri Davies {
49055f92f64SCeri Davies 	int i;
49155f92f64SCeri Davies 
49255f92f64SCeri Davies 	for(i = 1; i < argc; i++) {
49355f92f64SCeri Davies 		add_string(&libs_so, argv[i]);
49455f92f64SCeri Davies 		if ( in_list(&libs, argv[i]) )
49555f92f64SCeri Davies 			warnx("%s:%d: "
49655f92f64SCeri Davies 				"library `%s' specified as static earlier",
49755f92f64SCeri Davies 				curfilename, linenum, argv[i]);
49855f92f64SCeri Davies 	}
499de566360SJordan K. Hubbard }
500de566360SJordan K. Hubbard 
501de566360SJordan K. Hubbard 
50202c75192SDavid E. O'Brien void
50302c75192SDavid E. O'Brien add_buildopts(int argc, char **argv)
50408a15190SJosef Karthauser {
50508a15190SJosef Karthauser 	int i;
50608a15190SJosef Karthauser 
50708a15190SJosef Karthauser 	for (i = 1; i < argc; i++)
50808a15190SJosef Karthauser 		add_string(&buildopts, argv[i]);
50908a15190SJosef Karthauser }
51008a15190SJosef Karthauser 
51108a15190SJosef Karthauser 
51202c75192SDavid E. O'Brien void
51302c75192SDavid E. O'Brien add_special(int argc, char **argv)
514de566360SJordan K. Hubbard {
515de566360SJordan K. Hubbard 	int i;
516de566360SJordan K. Hubbard 	prog_t *p = find_prog(argv[1]);
517de566360SJordan K. Hubbard 
518de566360SJordan K. Hubbard 	if (p == NULL) {
51987eb4a42SJosef Karthauser 		if (reading_cache)
52087eb4a42SJosef Karthauser 			return;
52187eb4a42SJosef Karthauser 
522b17e90a9SPhilippe Charnier 		warnx("%s:%d: no prog %s previously declared, skipping special",
523de566360SJordan K. Hubbard 		    curfilename, linenum, argv[1]);
524de566360SJordan K. Hubbard 		goterror = 1;
525de566360SJordan K. Hubbard 		return;
526de566360SJordan K. Hubbard 	}
527de566360SJordan K. Hubbard 
528de566360SJordan K. Hubbard 	if (!strcmp(argv[2], "ident")) {
52987eb4a42SJosef Karthauser 		if (argc != 4)
53087eb4a42SJosef Karthauser 			goto argcount;
531de566360SJordan K. Hubbard 		if ((p->ident = strdup(argv[3])) == NULL)
532de566360SJordan K. Hubbard 			out_of_memory();
53387eb4a42SJosef Karthauser 	} else if (!strcmp(argv[2], "srcdir")) {
53487eb4a42SJosef Karthauser 		if (argc != 4)
53587eb4a42SJosef Karthauser 			goto argcount;
536de566360SJordan K. Hubbard 		if ((p->srcdir = strdup(argv[3])) == NULL)
537de566360SJordan K. Hubbard 			out_of_memory();
53887eb4a42SJosef Karthauser 	} else if (!strcmp(argv[2], "objdir")) {
53987eb4a42SJosef Karthauser 		if(argc != 4)
54087eb4a42SJosef Karthauser 			goto argcount;
541de566360SJordan K. Hubbard 		if((p->objdir = strdup(argv[3])) == NULL)
542de566360SJordan K. Hubbard 			out_of_memory();
54387eb4a42SJosef Karthauser 	} else if (!strcmp(argv[2], "objs")) {
544de566360SJordan K. Hubbard 		p->objs = NULL;
545de566360SJordan K. Hubbard 		for (i = 3; i < argc; i++)
546de566360SJordan K. Hubbard 			add_string(&p->objs, argv[i]);
54787eb4a42SJosef Karthauser 	} else if (!strcmp(argv[2], "objpaths")) {
548de566360SJordan K. Hubbard 		p->objpaths = NULL;
549de566360SJordan K. Hubbard 		for (i = 3; i < argc; i++)
550de566360SJordan K. Hubbard 			add_string(&p->objpaths, argv[i]);
55187eb4a42SJosef Karthauser 	} else if (!strcmp(argv[2], "keep")) {
55242ac3bf1SJoerg Wunsch 		p->keeplist = NULL;
55342ac3bf1SJoerg Wunsch 		for(i = 3; i < argc; i++)
55442ac3bf1SJoerg Wunsch 			add_string(&p->keeplist, argv[i]);
55587eb4a42SJosef Karthauser 	} else if (!strcmp(argv[2], "objvar")) {
55608826cadSLuigi Rizzo 		if(argc != 4)
55708826cadSLuigi Rizzo 			goto argcount;
55808826cadSLuigi Rizzo 		if ((p->objvar = strdup(argv[3])) == NULL)
55908826cadSLuigi Rizzo 			out_of_memory();
56087eb4a42SJosef Karthauser 	} else if (!strcmp(argv[2], "buildopts")) {
56134944d48SJosef Karthauser 		p->buildopts = NULL;
56234944d48SJosef Karthauser 		for (i = 3; i < argc; i++)
56334944d48SJosef Karthauser 			add_string(&p->buildopts, argv[i]);
564252f13abSLuigi Rizzo 	} else if (!strcmp(argv[2], "lib")) {
565252f13abSLuigi Rizzo 		for (i = 3; i < argc; i++)
566252f13abSLuigi Rizzo 			add_string(&p->libs, argv[i]);
56787eb4a42SJosef Karthauser 	} else {
568b17e90a9SPhilippe Charnier 		warnx("%s:%d: bad parameter name `%s', skipping line",
569de566360SJordan K. Hubbard 		    curfilename, linenum, argv[2]);
570de566360SJordan K. Hubbard 		goterror = 1;
571de566360SJordan K. Hubbard 	}
572de566360SJordan K. Hubbard 	return;
573de566360SJordan K. Hubbard 
574de566360SJordan K. Hubbard  argcount:
575b17e90a9SPhilippe Charnier 	warnx("%s:%d: too %s arguments, expected \"special %s %s <string>\"",
576de566360SJordan K. Hubbard 	    curfilename, linenum, argc < 4? "few" : "many", argv[1], argv[2]);
577de566360SJordan K. Hubbard 	goterror = 1;
578de566360SJordan K. Hubbard }
579de566360SJordan K. Hubbard 
580de566360SJordan K. Hubbard 
581de566360SJordan K. Hubbard prog_t *find_prog(char *str)
582de566360SJordan K. Hubbard {
583de566360SJordan K. Hubbard 	prog_t *p;
584de566360SJordan K. Hubbard 
585de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next)
58687eb4a42SJosef Karthauser 		if (!strcmp(p->name, str))
58787eb4a42SJosef Karthauser 			return p;
588de566360SJordan K. Hubbard 
589de566360SJordan K. Hubbard 	return NULL;
590de566360SJordan K. Hubbard }
591de566360SJordan K. Hubbard 
592de566360SJordan K. Hubbard 
593de566360SJordan K. Hubbard /*
594de566360SJordan K. Hubbard  * ========================================================================
595de566360SJordan K. Hubbard  * gen_outputs subsystem
596de566360SJordan K. Hubbard  *
597de566360SJordan K. Hubbard  */
598de566360SJordan K. Hubbard 
599de566360SJordan K. Hubbard /* helper subroutines */
600de566360SJordan K. Hubbard 
601de566360SJordan K. Hubbard void remove_error_progs(void);
602de566360SJordan K. Hubbard void fillin_program(prog_t *p);
603de566360SJordan K. Hubbard void gen_specials_cache(void);
604de566360SJordan K. Hubbard void gen_output_makefile(void);
605de566360SJordan K. Hubbard void gen_output_cfile(void);
606de566360SJordan K. Hubbard 
607de566360SJordan K. Hubbard void fillin_program_objs(prog_t *p, char *path);
608de566360SJordan K. Hubbard void top_makefile_rules(FILE *outmk);
609de566360SJordan K. Hubbard void prog_makefile_rules(FILE *outmk, prog_t *p);
610de566360SJordan K. Hubbard void output_strlst(FILE *outf, strlst_t *lst);
611de566360SJordan K. Hubbard char *genident(char *str);
612de566360SJordan K. Hubbard char *dir_search(char *progname);
613de566360SJordan K. Hubbard 
614de566360SJordan K. Hubbard 
61502c75192SDavid E. O'Brien void
61602c75192SDavid E. O'Brien gen_outputs(void)
617de566360SJordan K. Hubbard {
618de566360SJordan K. Hubbard 	prog_t *p;
619de566360SJordan K. Hubbard 
620de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next)
621de566360SJordan K. Hubbard 		fillin_program(p);
622de566360SJordan K. Hubbard 
623de566360SJordan K. Hubbard 	remove_error_progs();
624de566360SJordan K. Hubbard 	gen_specials_cache();
625de566360SJordan K. Hubbard 	gen_output_cfile();
626de566360SJordan K. Hubbard 	gen_output_makefile();
627de566360SJordan K. Hubbard 	status("");
628de566360SJordan K. Hubbard 	fprintf(stderr,
62970840a51SDavid E. O'Brien 	    "Run \"%s -f %s\" to build crunched binary.\n",
63070840a51SDavid E. O'Brien 	    path_make, outmkname);
631de566360SJordan K. Hubbard }
632de566360SJordan K. Hubbard 
63308826cadSLuigi Rizzo /*
63408826cadSLuigi Rizzo  * run the makefile for the program to find which objects are necessary
63508826cadSLuigi Rizzo  */
63602c75192SDavid E. O'Brien void
63702c75192SDavid E. O'Brien fillin_program(prog_t *p)
638de566360SJordan K. Hubbard {
639de566360SJordan K. Hubbard 	char path[MAXPATHLEN];
640019d04d1SLuigi Rizzo 	char line[MAXLINELEN];
641843d8d51SJosef Karthauser 	FILE *f;
642de566360SJordan K. Hubbard 
643019d04d1SLuigi Rizzo 	snprintf(line, MAXLINELEN, "filling in parms for %s", p->name);
644de566360SJordan K. Hubbard 	status(line);
645de566360SJordan K. Hubbard 
646de566360SJordan K. Hubbard 	if (!p->ident)
647de566360SJordan K. Hubbard 		p->ident = genident(p->name);
648e3b7d178SJosef Karthauser 
649e3b7d178SJosef Karthauser 	/* look for the source directory if one wasn't specified by a special */
650de566360SJordan K. Hubbard 	if (!p->srcdir) {
651e3b7d178SJosef Karthauser 		p->srcdir = dir_search(p->name);
652de566360SJordan K. Hubbard 	}
653843d8d51SJosef Karthauser 
654843d8d51SJosef Karthauser 	/* Determine the actual srcdir (maybe symlinked). */
655e3b7d178SJosef Karthauser 	if (p->srcdir) {
6560d5e6518SAlex Richardson 		snprintf(line, MAXLINELEN, "cd %s && pwd -P", p->srcdir);
657019d04d1SLuigi Rizzo 		f = popen(line,"r");
658e3b7d178SJosef Karthauser 		if (!f)
659e3b7d178SJosef Karthauser 			errx(1, "Can't execute: %s\n", line);
660e3b7d178SJosef Karthauser 
661019d04d1SLuigi Rizzo 		path[0] = '\0';
662154fd6a9SPoul-Henning Kamp 		fgets(path, sizeof path, f);
663e3b7d178SJosef Karthauser 		if (pclose(f))
664e3b7d178SJosef Karthauser 			errx(1, "Can't execute: %s\n", line);
665e3b7d178SJosef Karthauser 
666e3b7d178SJosef Karthauser 		if (!*path)
667e3b7d178SJosef Karthauser 			errx(1, "Can't perform pwd on: %s\n", p->srcdir);
668e3b7d178SJosef Karthauser 
6699c7bd4f1SKyle Evans 		/* Chop off trailing newline. */
6709c7bd4f1SKyle Evans 		path[strlen(path) - 1] = '\0';
671843d8d51SJosef Karthauser 		p->realsrcdir = strdup(path);
672154fd6a9SPoul-Henning Kamp 	}
673843d8d51SJosef Karthauser 
674843d8d51SJosef Karthauser 	/* Unless the option to make object files was specified the
675843d8d51SJosef Karthauser 	* the objects will be built in the source directory unless
676843d8d51SJosef Karthauser 	* an object directory already exists.
677843d8d51SJosef Karthauser 	*/
678843d8d51SJosef Karthauser 	if (!makeobj && !p->objdir && p->srcdir) {
679eb9b07bbSBryan Drewery 		char *auto_obj;
680eb9b07bbSBryan Drewery 
681eb9b07bbSBryan Drewery 		auto_obj = NULL;
682843d8d51SJosef Karthauser 		snprintf(line, sizeof line, "%s/%s", objprefix, p->realsrcdir);
683eb9b07bbSBryan Drewery 		if (is_dir(line) ||
684eb9b07bbSBryan Drewery 		    ((auto_obj = getenv("MK_AUTO_OBJ")) != NULL &&
685eb9b07bbSBryan Drewery 		    strcmp(auto_obj, "yes") == 0)) {
686f3c47f54SJosef Karthauser 			if ((p->objdir = strdup(line)) == NULL)
687f3c47f54SJosef Karthauser 			out_of_memory();
6885e5f3826SJosef Karthauser 		} else
689843d8d51SJosef Karthauser 			p->objdir = p->realsrcdir;
690de566360SJordan K. Hubbard 	}
69187eb4a42SJosef Karthauser 
69208826cadSLuigi Rizzo 	/*
69308826cadSLuigi Rizzo 	* XXX look for a Makefile.{name} in local directory first.
69408826cadSLuigi Rizzo 	* This lets us override the original Makefile.
69508826cadSLuigi Rizzo 	*/
696019d04d1SLuigi Rizzo 	snprintf(path, sizeof(path), "Makefile.%s", p->name);
69708826cadSLuigi Rizzo 	if (is_nonempty_file(path)) {
698019d04d1SLuigi Rizzo 		snprintf(line, MAXLINELEN, "Using %s for %s", path, p->name);
69908826cadSLuigi Rizzo 		status(line);
70008826cadSLuigi Rizzo 	} else
70187eb4a42SJosef Karthauser 		if (p->srcdir)
70287eb4a42SJosef Karthauser 			snprintf(path, sizeof(path), "%s/Makefile", p->srcdir);
703de566360SJordan K. Hubbard 	if (!p->objs && p->srcdir && is_nonempty_file(path))
704de566360SJordan K. Hubbard 		fillin_program_objs(p, path);
705de566360SJordan K. Hubbard 
70611384533SJosef Karthauser 	if (!p->srcdir && !p->objdir && verbose)
70787eb4a42SJosef Karthauser 		warnx("%s: %s: %s",
70887eb4a42SJosef Karthauser 		    "warning: could not find source directory",
709de566360SJordan K. Hubbard 		    infilename, p->name);
710de566360SJordan K. Hubbard 	if (!p->objs && verbose)
711b17e90a9SPhilippe Charnier 		warnx("%s: %s: warning: could not find any .o files",
712de566360SJordan K. Hubbard 		    infilename, p->name);
713617b8180SJosef Karthauser 
7141554755eSJosef Karthauser 	if ((!p->srcdir || !p->objdir) && !p->objs)
715617b8180SJosef Karthauser 		p->goterror = 1;
716de566360SJordan K. Hubbard }
717de566360SJordan K. Hubbard 
71802c75192SDavid E. O'Brien void
71902c75192SDavid E. O'Brien fillin_program_objs(prog_t *p, char *path)
720de566360SJordan K. Hubbard {
721de566360SJordan K. Hubbard 	char *obj, *cp;
722f3c47f54SJosef Karthauser 	int fd, rc;
723de566360SJordan K. Hubbard 	FILE *f;
724*db7f7446SKyle Evans 	const char *objvar="OBJS";
72534944d48SJosef Karthauser 	strlst_t *s;
726019d04d1SLuigi Rizzo 	char line[MAXLINELEN];
727de566360SJordan K. Hubbard 
728de566360SJordan K. Hubbard 	/* discover the objs from the srcdir Makefile */
729de566360SJordan K. Hubbard 
730188d6f4bSAlex Richardson 	/*
731188d6f4bSAlex Richardson 	 * We reuse the same temporary file name for multiple objects. However,
732188d6f4bSAlex Richardson 	 * some libc implementations (such as glibc) return EINVAL if there
733188d6f4bSAlex Richardson 	 * are no XXXXX characters in the template. This happens after the
734188d6f4bSAlex Richardson 	 * first call to mkstemp since the argument is modified in-place.
735188d6f4bSAlex Richardson 	 * To avoid this error we use open() instead of mkstemp() after the
736188d6f4bSAlex Richardson 	 * call to mkstemp().
737188d6f4bSAlex Richardson 	 */
738188d6f4bSAlex Richardson 	if (tempfname_initialized) {
739188d6f4bSAlex Richardson 		if ((fd = open(tempfname, O_CREAT | O_EXCL | O_RDWR, 0600)) == -1) {
740188d6f4bSAlex Richardson 			err(EX_OSERR, "open(%s)", tempfname);
741f3c47f54SJosef Karthauser 		}
742188d6f4bSAlex Richardson 	} else if ((fd = mkstemp(tempfname)) == -1) {
743188d6f4bSAlex Richardson 		err(EX_OSERR, "mkstemp(%s)", tempfname);
744188d6f4bSAlex Richardson 	}
745188d6f4bSAlex Richardson 	tempfname_initialized = true;
746f3c47f54SJosef Karthauser 	if ((f = fdopen(fd, "w")) == NULL) {
747188d6f4bSAlex Richardson 		warn("fdopen(%s)", tempfname);
748de566360SJordan K. Hubbard 		goterror = 1;
749188d6f4bSAlex Richardson 		goto out;
750de566360SJordan K. Hubbard 	}
75108826cadSLuigi Rizzo 	if (p->objvar)
75208826cadSLuigi Rizzo 		objvar = p->objvar;
753de566360SJordan K. Hubbard 
75408826cadSLuigi Rizzo 	/*
75508826cadSLuigi Rizzo 	* XXX include outhdrname (e.g. to contain Make variables)
75608826cadSLuigi Rizzo 	*/
75708826cadSLuigi Rizzo 	if (outhdrname[0] != '\0')
75808826cadSLuigi Rizzo 		fprintf(f, ".include \"%s\"\n", outhdrname);
759de566360SJordan K. Hubbard 	fprintf(f, ".include \"%s\"\n", path);
760b0889725SDavid E. O'Brien 	fprintf(f, ".POSIX:\n");
76108a15190SJosef Karthauser 	if (buildopts) {
76208a15190SJosef Karthauser 		fprintf(f, "BUILDOPTS+=");
76308a15190SJosef Karthauser 		output_strlst(f, buildopts);
76408a15190SJosef Karthauser 	}
7657328f913SDavid E. O'Brien 	fprintf(f, ".if defined(PROG)\n");
7667328f913SDavid E. O'Brien 	fprintf(f, "%s?=${PROG}.o\n", objvar);
767de566360SJordan K. Hubbard 	fprintf(f, ".endif\n");
76865cb078fSJosef Karthauser 	fprintf(f, "loop:\n\t@echo 'OBJS= '${%s}\n", objvar);
76934944d48SJosef Karthauser 
7702343a534SRuslan Ermilov 	fprintf(f, "crunchgen_objs:\n"
77170840a51SDavid E. O'Brien 	    "\t@cd %s && %s -f %s $(BUILDOPTS) $(%s_OPTS)",
77270840a51SDavid E. O'Brien 	    p->srcdir, path_make, tempfname, p->ident);
77334944d48SJosef Karthauser 	for (s = p->buildopts; s != NULL; s = s->next)
77434944d48SJosef Karthauser 		fprintf(f, " %s", s->str);
77534944d48SJosef Karthauser 	fprintf(f, " loop\n");
77634944d48SJosef Karthauser 
777de566360SJordan K. Hubbard 	fclose(f);
778de566360SJordan K. Hubbard 
77970840a51SDavid E. O'Brien 	snprintf(line, MAXLINELEN, "cd %s && %s -f %s -B crunchgen_objs",
78070840a51SDavid E. O'Brien 	     p->srcdir, path_make, tempfname);
781de566360SJordan K. Hubbard 	if ((f = popen(line, "r")) == NULL) {
782b17e90a9SPhilippe Charnier 		warn("submake pipe");
783de566360SJordan K. Hubbard 		goterror = 1;
784188d6f4bSAlex Richardson 		goto out;
785de566360SJordan K. Hubbard 	}
786de566360SJordan K. Hubbard 
787de566360SJordan K. Hubbard 	while(fgets(line, MAXLINELEN, f)) {
788de566360SJordan K. Hubbard 		if (strncmp(line, "OBJS= ", 6)) {
789b17e90a9SPhilippe Charnier 			warnx("make error: %s", line);
790de566360SJordan K. Hubbard 			goterror = 1;
791188d6f4bSAlex Richardson 			goto out;
792de566360SJordan K. Hubbard 		}
79387eb4a42SJosef Karthauser 
794de566360SJordan K. Hubbard 		cp = line + 6;
79596acb2c4SPedro F. Giffuni 		while (isspace((unsigned char)*cp))
79687eb4a42SJosef Karthauser 			cp++;
79787eb4a42SJosef Karthauser 
798de566360SJordan K. Hubbard 		while(*cp) {
799de566360SJordan K. Hubbard 			obj = cp;
80096acb2c4SPedro F. Giffuni 			while (*cp && !isspace((unsigned char)*cp))
80187eb4a42SJosef Karthauser 				cp++;
80287eb4a42SJosef Karthauser 			if (*cp)
80387eb4a42SJosef Karthauser 				*cp++ = '\0';
804de566360SJordan K. Hubbard 			add_string(&p->objs, obj);
80596acb2c4SPedro F. Giffuni 			while (isspace((unsigned char)*cp))
80687eb4a42SJosef Karthauser 				cp++;
807de566360SJordan K. Hubbard 		}
808de566360SJordan K. Hubbard 	}
80987eb4a42SJosef Karthauser 
810de566360SJordan K. Hubbard 	if ((rc=pclose(f)) != 0) {
811b17e90a9SPhilippe Charnier 		warnx("make error: make returned %d", rc);
812de566360SJordan K. Hubbard 		goterror = 1;
813de566360SJordan K. Hubbard 	}
814188d6f4bSAlex Richardson out:
815de566360SJordan K. Hubbard 	unlink(tempfname);
816de566360SJordan K. Hubbard }
817de566360SJordan K. Hubbard 
81802c75192SDavid E. O'Brien void
81902c75192SDavid E. O'Brien remove_error_progs(void)
820de566360SJordan K. Hubbard {
821de566360SJordan K. Hubbard 	prog_t *p1, *p2;
822de566360SJordan K. Hubbard 
823de566360SJordan K. Hubbard 	p1 = NULL; p2 = progs;
824de566360SJordan K. Hubbard 	while (p2 != NULL) {
825de566360SJordan K. Hubbard 		if (!p2->goterror)
826de566360SJordan K. Hubbard 			p1 = p2, p2 = p2->next;
827de566360SJordan K. Hubbard 		else {
828de566360SJordan K. Hubbard 			/* delete it from linked list */
829b17e90a9SPhilippe Charnier 			warnx("%s: %s: ignoring program because of errors",
830de566360SJordan K. Hubbard 			    infilename, p2->name);
83187eb4a42SJosef Karthauser 			if (p1)
83287eb4a42SJosef Karthauser 				p1->next = p2->next;
83387eb4a42SJosef Karthauser 			else
83487eb4a42SJosef Karthauser 				progs = p2->next;
835de566360SJordan K. Hubbard 			p2 = p2->next;
836de566360SJordan K. Hubbard 		}
837de566360SJordan K. Hubbard 	}
838de566360SJordan K. Hubbard }
839de566360SJordan K. Hubbard 
84002c75192SDavid E. O'Brien void
84102c75192SDavid E. O'Brien gen_specials_cache(void)
842de566360SJordan K. Hubbard {
843de566360SJordan K. Hubbard 	FILE *cachef;
844de566360SJordan K. Hubbard 	prog_t *p;
845019d04d1SLuigi Rizzo 	char line[MAXLINELEN];
846de566360SJordan K. Hubbard 
847019d04d1SLuigi Rizzo 	snprintf(line, MAXLINELEN, "generating %s", cachename);
848de566360SJordan K. Hubbard 	status(line);
849de566360SJordan K. Hubbard 
850de566360SJordan K. Hubbard 	if ((cachef = fopen(cachename, "w")) == NULL) {
851b17e90a9SPhilippe Charnier 		warn("%s", cachename);
852de566360SJordan K. Hubbard 		goterror = 1;
853de566360SJordan K. Hubbard 		return;
854de566360SJordan K. Hubbard 	}
855de566360SJordan K. Hubbard 
85687eb4a42SJosef Karthauser 	fprintf(cachef, "# %s - parm cache generated from %s by crunchgen "
85787eb4a42SJosef Karthauser 	    " %s\n\n",
858de566360SJordan K. Hubbard 	    cachename, infilename, CRUNCH_VERSION);
859de566360SJordan K. Hubbard 
860de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next) {
861de566360SJordan K. Hubbard 		fprintf(cachef, "\n");
862de566360SJordan K. Hubbard 		if (p->srcdir)
86387eb4a42SJosef Karthauser 			fprintf(cachef, "special %s srcdir %s\n",
86487eb4a42SJosef Karthauser 			    p->name, p->srcdir);
865de566360SJordan K. Hubbard 		if (p->objdir)
86687eb4a42SJosef Karthauser 			fprintf(cachef, "special %s objdir %s\n",
86787eb4a42SJosef Karthauser 			    p->name, p->objdir);
868de566360SJordan K. Hubbard 		if (p->objs) {
869de566360SJordan K. Hubbard 			fprintf(cachef, "special %s objs", p->name);
870de566360SJordan K. Hubbard 			output_strlst(cachef, p->objs);
871de566360SJordan K. Hubbard 		}
872843d8d51SJosef Karthauser 		if (p->objpaths) {
873de566360SJordan K. Hubbard 			fprintf(cachef, "special %s objpaths", p->name);
874de566360SJordan K. Hubbard 			output_strlst(cachef, p->objpaths);
875de566360SJordan K. Hubbard 		}
876843d8d51SJosef Karthauser 	}
877de566360SJordan K. Hubbard 	fclose(cachef);
878de566360SJordan K. Hubbard }
879de566360SJordan K. Hubbard 
880de566360SJordan K. Hubbard 
88102c75192SDavid E. O'Brien void
88202c75192SDavid E. O'Brien gen_output_makefile(void)
883de566360SJordan K. Hubbard {
884de566360SJordan K. Hubbard 	prog_t *p;
885de566360SJordan K. Hubbard 	FILE *outmk;
886019d04d1SLuigi Rizzo 	char line[MAXLINELEN];
887de566360SJordan K. Hubbard 
888019d04d1SLuigi Rizzo 	snprintf(line, MAXLINELEN, "generating %s", outmkname);
889de566360SJordan K. Hubbard 	status(line);
890de566360SJordan K. Hubbard 
891de566360SJordan K. Hubbard 	if ((outmk = fopen(outmkname, "w")) == NULL) {
892b17e90a9SPhilippe Charnier 		warn("%s", outmkname);
893de566360SJordan K. Hubbard 		goterror = 1;
894de566360SJordan K. Hubbard 		return;
895de566360SJordan K. Hubbard 	}
896de566360SJordan K. Hubbard 
897de566360SJordan K. Hubbard 	fprintf(outmk, "# %s - generated from %s by crunchgen %s\n\n",
898de566360SJordan K. Hubbard 	    outmkname, infilename, CRUNCH_VERSION);
89987eb4a42SJosef Karthauser 
90008826cadSLuigi Rizzo 	if (outhdrname[0] != '\0')
90108826cadSLuigi Rizzo 		fprintf(outmk, ".include \"%s\"\n", outhdrname);
902de566360SJordan K. Hubbard 
903de566360SJordan K. Hubbard 	top_makefile_rules(outmk);
904de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next)
905de566360SJordan K. Hubbard 		prog_makefile_rules(outmk, p);
906de566360SJordan K. Hubbard 
907de566360SJordan K. Hubbard 	fprintf(outmk, "\n# ========\n");
908de566360SJordan K. Hubbard 	fclose(outmk);
909de566360SJordan K. Hubbard }
910de566360SJordan K. Hubbard 
911de566360SJordan K. Hubbard 
91202c75192SDavid E. O'Brien void
91302c75192SDavid E. O'Brien gen_output_cfile(void)
914de566360SJordan K. Hubbard {
915*db7f7446SKyle Evans 	const char **cp;
916de566360SJordan K. Hubbard 	FILE *outcf;
917de566360SJordan K. Hubbard 	prog_t *p;
918de566360SJordan K. Hubbard 	strlst_t *s;
919019d04d1SLuigi Rizzo 	char line[MAXLINELEN];
920de566360SJordan K. Hubbard 
921019d04d1SLuigi Rizzo 	snprintf(line, MAXLINELEN, "generating %s", outcfname);
922de566360SJordan K. Hubbard 	status(line);
923de566360SJordan K. Hubbard 
924de566360SJordan K. Hubbard 	if((outcf = fopen(outcfname, "w")) == NULL) {
925b17e90a9SPhilippe Charnier 		warn("%s", outcfname);
926de566360SJordan K. Hubbard 		goterror = 1;
927de566360SJordan K. Hubbard 		return;
928de566360SJordan K. Hubbard 	}
929de566360SJordan K. Hubbard 
930de566360SJordan K. Hubbard 	fprintf(outcf,
931de566360SJordan K. Hubbard 	    "/* %s - generated from %s by crunchgen %s */\n",
932de566360SJordan K. Hubbard 	    outcfname, infilename, CRUNCH_VERSION);
933de566360SJordan K. Hubbard 
934de566360SJordan K. Hubbard 	fprintf(outcf, "#define EXECNAME \"%s\"\n", execfname);
935de566360SJordan K. Hubbard 	for (cp = crunched_skel; *cp != NULL; cp++)
936de566360SJordan K. Hubbard 		fprintf(outcf, "%s\n", *cp);
937de566360SJordan K. Hubbard 
938de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next)
939fc905210SKyle Evans 		fprintf(outcf,
940fc905210SKyle Evans 		    "extern crunched_stub_t _crunched_%s_stub;\n",
941fc905210SKyle Evans 		    p->ident);
942de566360SJordan K. Hubbard 
943de566360SJordan K. Hubbard 	fprintf(outcf, "\nstruct stub entry_points[] = {\n");
944de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next) {
945de566360SJordan K. Hubbard 		fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n",
946de566360SJordan K. Hubbard 		    p->name, p->ident);
947de566360SJordan K. Hubbard 		for (s = p->links; s != NULL; s = s->next)
948de566360SJordan K. Hubbard 			fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n",
949de566360SJordan K. Hubbard 			    s->str, p->ident);
950de566360SJordan K. Hubbard 	}
951de566360SJordan K. Hubbard 
952de566360SJordan K. Hubbard 	fprintf(outcf, "\t{ EXECNAME, crunched_main },\n");
953de566360SJordan K. Hubbard 	fprintf(outcf, "\t{ NULL, NULL }\n};\n");
954de566360SJordan K. Hubbard 	fclose(outcf);
955de566360SJordan K. Hubbard }
956de566360SJordan K. Hubbard 
957de566360SJordan K. Hubbard 
958de566360SJordan K. Hubbard char *genident(char *str)
959de566360SJordan K. Hubbard {
960de566360SJordan K. Hubbard 	char *n, *s, *d;
961de566360SJordan K. Hubbard 
962de566360SJordan K. Hubbard 	/*
96387eb4a42SJosef Karthauser 	 * generates a Makefile/C identifier from a program name,
96487eb4a42SJosef Karthauser 	 * mapping '-' to '_' and ignoring all other non-identifier
96587eb4a42SJosef Karthauser 	 * characters.  This leads to programs named "foo.bar" and
96687eb4a42SJosef Karthauser 	 * "foobar" to map to the same identifier.
967de566360SJordan K. Hubbard 	 */
968de566360SJordan K. Hubbard 
969de566360SJordan K. Hubbard 	if ((n = strdup(str)) == NULL)
970de566360SJordan K. Hubbard 		return NULL;
971de566360SJordan K. Hubbard 	for (d = s = n; *s != '\0'; s++) {
97287eb4a42SJosef Karthauser 		if (*s == '-')
97387eb4a42SJosef Karthauser 			*d++ = '_';
97496acb2c4SPedro F. Giffuni 		else if (*s == '_' || isalnum((unsigned char)*s))
97587eb4a42SJosef Karthauser 			*d++ = *s;
976de566360SJordan K. Hubbard 	}
977de566360SJordan K. Hubbard 	*d = '\0';
978de566360SJordan K. Hubbard 	return n;
979de566360SJordan K. Hubbard }
980de566360SJordan K. Hubbard 
981de566360SJordan K. Hubbard 
982de566360SJordan K. Hubbard char *dir_search(char *progname)
983de566360SJordan K. Hubbard {
984de566360SJordan K. Hubbard 	char path[MAXPATHLEN];
985de566360SJordan K. Hubbard 	strlst_t *dir;
986e3b7d178SJosef Karthauser 	char *srcdir;
987de566360SJordan K. Hubbard 
988de566360SJordan K. Hubbard 	for (dir = srcdirs; dir != NULL; dir = dir->next) {
989019d04d1SLuigi Rizzo 		snprintf(path, MAXPATHLEN, "%s/%s", dir->str, progname);
99087eb4a42SJosef Karthauser 		if (!is_dir(path))
991e3b7d178SJosef Karthauser 			continue;
992e3b7d178SJosef Karthauser 
993e3b7d178SJosef Karthauser 		if ((srcdir = strdup(path)) == NULL)
994e3b7d178SJosef Karthauser 			out_of_memory();
99587eb4a42SJosef Karthauser 
996e3b7d178SJosef Karthauser 		return srcdir;
997de566360SJordan K. Hubbard 	}
998de566360SJordan K. Hubbard 	return NULL;
999de566360SJordan K. Hubbard }
1000de566360SJordan K. Hubbard 
1001de566360SJordan K. Hubbard 
100202c75192SDavid E. O'Brien void
100302c75192SDavid E. O'Brien top_makefile_rules(FILE *outmk)
1004de566360SJordan K. Hubbard {
1005de566360SJordan K. Hubbard 	prog_t *p;
1006de566360SJordan K. Hubbard 
10072ebed5dbSPedro F. Giffuni 	fprintf(outmk, "LD?= ld\n");
100855f92f64SCeri Davies 	if ( subtract_strlst(&libs, &libs_so) )
100955f92f64SCeri Davies 		fprintf(outmk, "# NOTE: Some LIBS declarations below overridden by LIBS_SO\n");
101055f92f64SCeri Davies 
1011d1a97625SJosef Karthauser 	fprintf(outmk, "LIBS+=");
1012de566360SJordan K. Hubbard 	output_strlst(outmk, libs);
1013de566360SJordan K. Hubbard 
101455f92f64SCeri Davies 	fprintf(outmk, "LIBS_SO+=");
101555f92f64SCeri Davies 	output_strlst(outmk, libs_so);
101655f92f64SCeri Davies 
1017843d8d51SJosef Karthauser 	if (makeobj) {
1018843d8d51SJosef Karthauser 		fprintf(outmk, "MAKEOBJDIRPREFIX?=%s\n", objprefix);
1019a8595b66SHartmut Brandt 		fprintf(outmk, "MAKEENV=env MAKEOBJDIRPREFIX=$(MAKEOBJDIRPREFIX)\n");
1020a8595b66SHartmut Brandt 		fprintf(outmk, "CRUNCHMAKE=$(MAKEENV) $(MAKE)\n");
1021843d8d51SJosef Karthauser 	} else {
1022a8595b66SHartmut Brandt 		fprintf(outmk, "CRUNCHMAKE=$(MAKE)\n");
1023843d8d51SJosef Karthauser 	}
1024843d8d51SJosef Karthauser 
102508a15190SJosef Karthauser 	if (buildopts) {
102608a15190SJosef Karthauser 		fprintf(outmk, "BUILDOPTS+=");
102708a15190SJosef Karthauser 		output_strlst(outmk, buildopts);
102808a15190SJosef Karthauser 	}
102908a15190SJosef Karthauser 
1030de566360SJordan K. Hubbard 	fprintf(outmk, "CRUNCHED_OBJS=");
1031de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next)
1032de566360SJordan K. Hubbard 		fprintf(outmk, " %s.lo", p->name);
1033de566360SJordan K. Hubbard 	fprintf(outmk, "\n");
1034de566360SJordan K. Hubbard 
1035de566360SJordan K. Hubbard 	fprintf(outmk, "SUBMAKE_TARGETS=");
1036de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next)
1037de566360SJordan K. Hubbard 		fprintf(outmk, " %s_make", p->ident);
1038ced716c3SBrian Somers 	fprintf(outmk, "\nSUBCLEAN_TARGETS=");
1039ced716c3SBrian Somers 	for (p = progs; p != NULL; p = p->next)
1040ced716c3SBrian Somers 		fprintf(outmk, " %s_clean", p->ident);
1041de566360SJordan K. Hubbard 	fprintf(outmk, "\n\n");
1042de566360SJordan K. Hubbard 
1043843d8d51SJosef Karthauser 	fprintf(outmk, "all: objs exe\nobjs: $(SUBMAKE_TARGETS)\n");
1044843d8d51SJosef Karthauser 	fprintf(outmk, "exe: %s\n", execfname);
1045e8a1d46eSJohn Birrell 	fprintf(outmk, "%s: %s.o $(CRUNCHED_OBJS) $(SUBMAKE_TARGETS)\n", execfname, execfname);
104655f92f64SCeri Davies 	fprintf(outmk, ".if defined(LIBS_SO) && !empty(LIBS_SO)\n");
104755f92f64SCeri Davies 	fprintf(outmk, "\t$(CC) -o %s %s.o $(CRUNCHED_OBJS) \\\n",
104855f92f64SCeri Davies 	    execfname, execfname);
104955f92f64SCeri Davies 	fprintf(outmk, "\t\t-Xlinker -Bstatic $(LIBS) \\\n");
105055f92f64SCeri Davies 	fprintf(outmk, "\t\t-Xlinker -Bdynamic $(LIBS_SO)\n");
105155f92f64SCeri Davies 	fprintf(outmk, ".else\n");
1052de566360SJordan K. Hubbard 	fprintf(outmk, "\t$(CC) -static -o %s %s.o $(CRUNCHED_OBJS) $(LIBS)\n",
1053de566360SJordan K. Hubbard 	    execfname, execfname);
105455f92f64SCeri Davies 	fprintf(outmk, ".endif\n");
1055ced716c3SBrian Somers 	fprintf(outmk, "realclean: clean subclean\n");
105687eb4a42SJosef Karthauser 	fprintf(outmk, "clean:\n\trm -f %s *.lo *.o *_stub.c\n", execfname);
1057ced716c3SBrian Somers 	fprintf(outmk, "subclean: $(SUBCLEAN_TARGETS)\n");
1058de566360SJordan K. Hubbard }
1059de566360SJordan K. Hubbard 
1060de566360SJordan K. Hubbard 
106102c75192SDavid E. O'Brien void
106202c75192SDavid E. O'Brien prog_makefile_rules(FILE *outmk, prog_t *p)
1063de566360SJordan K. Hubbard {
106442ac3bf1SJoerg Wunsch 	strlst_t *lst;
106542ac3bf1SJoerg Wunsch 
1066de566360SJordan K. Hubbard 	fprintf(outmk, "\n# -------- %s\n\n", p->name);
1067de566360SJordan K. Hubbard 
1068843d8d51SJosef Karthauser 	fprintf(outmk, "%s_OBJDIR=", p->ident);
1069843d8d51SJosef Karthauser 	if (p->objdir)
1070843d8d51SJosef Karthauser 		fprintf(outmk, "%s", p->objdir);
1071843d8d51SJosef Karthauser 	else
1072843d8d51SJosef Karthauser 		fprintf(outmk, "$(MAKEOBJDIRPREFIX)/$(%s_REALSRCDIR)\n",
1073843d8d51SJosef Karthauser 		    p->ident);
1074843d8d51SJosef Karthauser 	fprintf(outmk, "\n");
1075843d8d51SJosef Karthauser 
107680f498e5SJohn Birrell 	fprintf(outmk, "%s_OBJPATHS=", p->ident);
107780f498e5SJohn Birrell 	if (p->objpaths)
107880f498e5SJohn Birrell 		output_strlst(outmk, p->objpaths);
107980f498e5SJohn Birrell 	else {
108080f498e5SJohn Birrell 		for (lst = p->objs; lst != NULL; lst = lst->next) {
108180f498e5SJohn Birrell 			fprintf(outmk, " $(%s_OBJDIR)/%s", p->ident, lst->str);
108280f498e5SJohn Birrell 		}
108380f498e5SJohn Birrell 		fprintf(outmk, "\n");
108480f498e5SJohn Birrell 	}
10855017231aSBryan Drewery 	fprintf(outmk, "$(%s_OBJPATHS): .NOMETA\n", p->ident);
108680f498e5SJohn Birrell 
108711384533SJosef Karthauser 	if (p->srcdir && p->objs) {
108811384533SJosef Karthauser 		fprintf(outmk, "%s_SRCDIR=%s\n", p->ident, p->srcdir);
108911384533SJosef Karthauser 		fprintf(outmk, "%s_REALSRCDIR=%s\n", p->ident, p->realsrcdir);
109011384533SJosef Karthauser 
1091de566360SJordan K. Hubbard 		fprintf(outmk, "%s_OBJS=", p->ident);
1092de566360SJordan K. Hubbard 		output_strlst(outmk, p->objs);
109334944d48SJosef Karthauser 		if (p->buildopts != NULL) {
109434944d48SJosef Karthauser 			fprintf(outmk, "%s_OPTS+=", p->ident);
109534944d48SJosef Karthauser 			output_strlst(outmk, p->buildopts);
109634944d48SJosef Karthauser 		}
109751d9ddc6SJohn Birrell #if 0
109880f498e5SJohn Birrell 		fprintf(outmk, "$(%s_OBJPATHS): %s_make\n\n", p->ident, p->ident);
109951d9ddc6SJohn Birrell #endif
1100de566360SJordan K. Hubbard 		fprintf(outmk, "%s_make:\n", p->ident);
1101ba2250ddSJosef Karthauser 		fprintf(outmk, "\t(cd $(%s_SRCDIR) && ", p->ident);
1102ba2250ddSJosef Karthauser 		if (makeobj)
1103a8595b66SHartmut Brandt 			fprintf(outmk, "$(CRUNCHMAKE) obj && ");
1104ba2250ddSJosef Karthauser 		fprintf(outmk, "\\\n");
1105a8595b66SHartmut Brandt 		fprintf(outmk, "\t\t$(CRUNCHMAKE) $(BUILDOPTS) $(%s_OPTS) depend &&",
110687eb4a42SJosef Karthauser 		    p->ident);
110787eb4a42SJosef Karthauser 		fprintf(outmk, "\\\n");
1108a8595b66SHartmut Brandt 		fprintf(outmk, "\t\t$(CRUNCHMAKE) $(BUILDOPTS) $(%s_OPTS) "
110987eb4a42SJosef Karthauser 		    "$(%s_OBJS))",
111087eb4a42SJosef Karthauser 		    p->ident, p->ident);
111187eb4a42SJosef Karthauser 		fprintf(outmk, "\n");
1112ced716c3SBrian Somers 		fprintf(outmk, "%s_clean:\n", p->ident);
1113a8595b66SHartmut Brandt 		fprintf(outmk, "\t(cd $(%s_SRCDIR) && $(CRUNCHMAKE) $(BUILDOPTS) clean cleandepend)\n\n",
111487eb4a42SJosef Karthauser 		    p->ident);
111587eb4a42SJosef Karthauser 	} else {
111687eb4a42SJosef Karthauser 		fprintf(outmk, "%s_make:\n", p->ident);
111787eb4a42SJosef Karthauser 		fprintf(outmk, "\t@echo \"** cannot make objs for %s\"\n\n",
1118a0bac7e0SRuslan Ermilov 		    p->name);
111987eb4a42SJosef Karthauser 	}
1120de566360SJordan K. Hubbard 
1121252f13abSLuigi Rizzo 	if (p->libs) {
1122252f13abSLuigi Rizzo 		fprintf(outmk, "%s_LIBS=", p->ident);
1123252f13abSLuigi Rizzo 		output_strlst(outmk, p->libs);
1124252f13abSLuigi Rizzo 	}
1125de566360SJordan K. Hubbard 
1126de566360SJordan K. Hubbard 	fprintf(outmk, "%s_stub.c:\n", p->name);
1127de566360SJordan K. Hubbard 	fprintf(outmk, "\techo \""
1128e881ec16SRyan Libby 	    "extern int main(int argc, char **argv, char **envp); "
1129fc905210SKyle Evans 	    "int _crunched_%s_stub(int argc, char **argv, char **envp);"
1130de566360SJordan K. Hubbard 	    "int _crunched_%s_stub(int argc, char **argv, char **envp)"
1131de566360SJordan K. Hubbard 	    "{return main(argc,argv,envp);}\" >%s_stub.c\n",
1132fc905210SKyle Evans 	    p->ident, p->ident, p->name);
1133252f13abSLuigi Rizzo 	fprintf(outmk, "%s.lo: %s_stub.o $(%s_OBJPATHS)",
1134de566360SJordan K. Hubbard 	    p->name, p->name, p->ident);
1135252f13abSLuigi Rizzo 	if (p->libs)
1136252f13abSLuigi Rizzo 		fprintf(outmk, " $(%s_LIBS)", p->ident);
113755f92f64SCeri Davies 
1138252f13abSLuigi Rizzo 	fprintf(outmk, "\n");
113919e58304STijl Coosemans 	fprintf(outmk, "\t$(CC) -nostdlib -Wl,-dc -r -o %s.lo %s_stub.o $(%s_OBJPATHS)",
1140de566360SJordan K. Hubbard 	    p->name, p->name, p->ident);
1141252f13abSLuigi Rizzo 	if (p->libs)
1142252f13abSLuigi Rizzo 		fprintf(outmk, " $(%s_LIBS)", p->ident);
1143252f13abSLuigi Rizzo 	fprintf(outmk, "\n");
11446cd35234SJordan K. Hubbard 	fprintf(outmk, "\tcrunchide -k _crunched_%s_stub ", p->ident);
114542ac3bf1SJoerg Wunsch 	for (lst = p->keeplist; lst != NULL; lst = lst->next)
114642ac3bf1SJoerg Wunsch 		fprintf(outmk, "-k _%s ", lst->str);
114742ac3bf1SJoerg Wunsch 	fprintf(outmk, "%s.lo\n", p->name);
1148de566360SJordan K. Hubbard }
1149de566360SJordan K. Hubbard 
115002c75192SDavid E. O'Brien void
115102c75192SDavid E. O'Brien output_strlst(FILE *outf, strlst_t *lst)
1152de566360SJordan K. Hubbard {
1153de566360SJordan K. Hubbard 	for (; lst != NULL; lst = lst->next)
115455f92f64SCeri Davies 		if ( strlen(lst->str) )
1155de566360SJordan K. Hubbard 			fprintf(outf, " %s", lst->str);
1156de566360SJordan K. Hubbard 	fprintf(outf, "\n");
1157de566360SJordan K. Hubbard }
1158de566360SJordan K. Hubbard 
1159de566360SJordan K. Hubbard 
1160de566360SJordan K. Hubbard /*
1161de566360SJordan K. Hubbard  * ========================================================================
1162de566360SJordan K. Hubbard  * general library routines
1163de566360SJordan K. Hubbard  *
1164de566360SJordan K. Hubbard  */
1165de566360SJordan K. Hubbard 
116602c75192SDavid E. O'Brien void
116796acb2c4SPedro F. Giffuni status(const char *str)
1168de566360SJordan K. Hubbard {
1169de566360SJordan K. Hubbard 	static int lastlen = 0;
1170de566360SJordan K. Hubbard 	int len, spaces;
1171de566360SJordan K. Hubbard 
117287eb4a42SJosef Karthauser 	if (!verbose)
117387eb4a42SJosef Karthauser 		return;
1174de566360SJordan K. Hubbard 
1175de566360SJordan K. Hubbard 	len = strlen(str);
1176de566360SJordan K. Hubbard 	spaces = lastlen - len;
117787eb4a42SJosef Karthauser 	if (spaces < 1)
117887eb4a42SJosef Karthauser 		spaces = 1;
1179de566360SJordan K. Hubbard 
1180de566360SJordan K. Hubbard 	fprintf(stderr, " [%s]%*.*s\r", str, spaces, spaces, " ");
1181de566360SJordan K. Hubbard 	fflush(stderr);
1182de566360SJordan K. Hubbard 	lastlen = len;
1183de566360SJordan K. Hubbard }
1184de566360SJordan K. Hubbard 
1185de566360SJordan K. Hubbard 
118602c75192SDavid E. O'Brien void
118702c75192SDavid E. O'Brien out_of_memory(void)
1188de566360SJordan K. Hubbard {
1189f3c47f54SJosef Karthauser 	err(1, "%s: %d: out of memory, stopping", infilename, linenum);
1190de566360SJordan K. Hubbard }
1191de566360SJordan K. Hubbard 
1192de566360SJordan K. Hubbard 
119302c75192SDavid E. O'Brien void
119402c75192SDavid E. O'Brien add_string(strlst_t **listp, char *str)
1195de566360SJordan K. Hubbard {
1196de566360SJordan K. Hubbard 	strlst_t *p1, *p2;
1197de566360SJordan K. Hubbard 
1198de566360SJordan K. Hubbard 	/* add to end, but be smart about dups */
1199de566360SJordan K. Hubbard 
1200de566360SJordan K. Hubbard 	for (p1 = NULL, p2 = *listp; p2 != NULL; p1 = p2, p2 = p2->next)
120187eb4a42SJosef Karthauser 		if (!strcmp(p2->str, str))
120287eb4a42SJosef Karthauser 			return;
1203de566360SJordan K. Hubbard 
1204de566360SJordan K. Hubbard 	p2 = malloc(sizeof(strlst_t));
1205eb148815SJoerg Wunsch 	if (p2) {
1206019d04d1SLuigi Rizzo 		p2->next = NULL;
1207eb148815SJoerg Wunsch 		p2->str = strdup(str);
1208eb148815SJoerg Wunsch     	}
1209de566360SJordan K. Hubbard 	if (!p2 || !p2->str)
1210de566360SJordan K. Hubbard 		out_of_memory();
1211de566360SJordan K. Hubbard 
121287eb4a42SJosef Karthauser 	if (p1 == NULL)
121387eb4a42SJosef Karthauser 		*listp = p2;
121487eb4a42SJosef Karthauser 	else
121587eb4a42SJosef Karthauser 		p1->next = p2;
1216de566360SJordan K. Hubbard }
1217de566360SJordan K. Hubbard 
121802c75192SDavid E. O'Brien int
121902c75192SDavid E. O'Brien subtract_strlst(strlst_t **lista, strlst_t **listb)
122055f92f64SCeri Davies {
122155f92f64SCeri Davies 	int subtract_count = 0;
122255f92f64SCeri Davies 	strlst_t *p1;
122355f92f64SCeri Davies 	for (p1 = *listb; p1 != NULL; p1 = p1->next)
122455f92f64SCeri Davies 		if ( in_list(lista, p1->str) ) {
122555f92f64SCeri Davies 			warnx("Will compile library `%s' dynamically", p1->str);
122655f92f64SCeri Davies 			strcat(p1->str, "");
122755f92f64SCeri Davies 			subtract_count++;
122855f92f64SCeri Davies 		}
122955f92f64SCeri Davies 	return subtract_count;
123055f92f64SCeri Davies }
123155f92f64SCeri Davies 
123202c75192SDavid E. O'Brien int
123302c75192SDavid E. O'Brien in_list(strlst_t **listp, char *str)
123455f92f64SCeri Davies {
123555f92f64SCeri Davies 	strlst_t *p1;
123655f92f64SCeri Davies 	for (p1 = *listp; p1 != NULL; p1 = p1->next)
123755f92f64SCeri Davies 		if (!strcmp(p1->str, str))
123855f92f64SCeri Davies 			return 1;
123955f92f64SCeri Davies 	return 0;
124055f92f64SCeri Davies }
1241de566360SJordan K. Hubbard 
124202c75192SDavid E. O'Brien int
124396acb2c4SPedro F. Giffuni is_dir(const char *pathname)
1244de566360SJordan K. Hubbard {
1245de566360SJordan K. Hubbard 	struct stat buf;
1246de566360SJordan K. Hubbard 
1247de566360SJordan K. Hubbard 	if (stat(pathname, &buf) == -1)
1248de566360SJordan K. Hubbard 		return 0;
124987eb4a42SJosef Karthauser 
1250de566360SJordan K. Hubbard 	return S_ISDIR(buf.st_mode);
1251de566360SJordan K. Hubbard }
1252de566360SJordan K. Hubbard 
125302c75192SDavid E. O'Brien int
125496acb2c4SPedro F. Giffuni is_nonempty_file(const char *pathname)
1255de566360SJordan K. Hubbard {
1256de566360SJordan K. Hubbard 	struct stat buf;
1257de566360SJordan K. Hubbard 
1258de566360SJordan K. Hubbard 	if (stat(pathname, &buf) == -1)
1259de566360SJordan K. Hubbard 		return 0;
1260de566360SJordan K. Hubbard 
1261de566360SJordan K. Hubbard 	return S_ISREG(buf.st_mode) && buf.st_size > 0;
1262de566360SJordan K. Hubbard }
1263