xref: /freebsd/usr.sbin/crunch/crunchgen/crunchgen.c (revision 70840a510a1e4b505ed1125dc8bb7ca538b7a03c)
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
2508826cadSLuigi Rizzo  *
2608826cadSLuigi Rizzo  * $FreeBSD$
27de566360SJordan K. Hubbard  */
28de566360SJordan K. Hubbard /*
29de566360SJordan K. Hubbard  * ========================================================================
30de566360SJordan K. Hubbard  * crunchgen.c
31de566360SJordan K. Hubbard  *
32de566360SJordan K. Hubbard  * Generates a Makefile and main C file for a crunched executable,
33de566360SJordan K. Hubbard  * from specs given in a .conf file.
34de566360SJordan K. Hubbard  */
3587eb4a42SJosef Karthauser #include <sys/types.h>
3687eb4a42SJosef Karthauser #include <sys/stat.h>
3787eb4a42SJosef Karthauser #include <sys/param.h>
3887eb4a42SJosef Karthauser 
39de566360SJordan K. Hubbard #include <ctype.h>
40b17e90a9SPhilippe Charnier #include <err.h>
4161ffadb1SJosef Karthauser #include <paths.h>
42b17e90a9SPhilippe Charnier #include <stdio.h>
43b17e90a9SPhilippe Charnier #include <stdlib.h>
44de566360SJordan K. Hubbard #include <string.h>
45b17e90a9SPhilippe Charnier #include <unistd.h>
46de566360SJordan K. Hubbard 
47de566360SJordan K. Hubbard #define CRUNCH_VERSION	"0.2"
48de566360SJordan K. Hubbard 
49de566360SJordan K. Hubbard #define MAXLINELEN	16384
50de566360SJordan K. Hubbard #define MAXFIELDS 	 2048
51de566360SJordan K. Hubbard 
52de566360SJordan K. Hubbard 
53de566360SJordan K. Hubbard /* internal representation of conf file: */
54de566360SJordan K. Hubbard 
55de566360SJordan K. Hubbard /* simple lists of strings suffice for most parms */
56de566360SJordan K. Hubbard 
57de566360SJordan K. Hubbard typedef struct strlst {
58de566360SJordan K. Hubbard 	struct strlst *next;
59de566360SJordan K. Hubbard 	char *str;
60de566360SJordan K. Hubbard } strlst_t;
61de566360SJordan K. Hubbard 
62de566360SJordan K. Hubbard /* progs have structure, each field can be set with "special" or calculated */
63de566360SJordan K. Hubbard 
64de566360SJordan K. Hubbard typedef struct prog {
6508826cadSLuigi Rizzo 	struct prog *next;	/* link field */
6608826cadSLuigi Rizzo 	char *name;		/* program name */
6708826cadSLuigi Rizzo 	char *ident;		/* C identifier for the program name */
6808826cadSLuigi Rizzo 	char *srcdir;
69843d8d51SJosef Karthauser 	char *realsrcdir;
7008826cadSLuigi Rizzo 	char *objdir;
7108826cadSLuigi Rizzo 	char *objvar;		/* Makefile variable to replace OBJS */
72de566360SJordan K. Hubbard 	strlst_t *objs, *objpaths;
7334944d48SJosef Karthauser 	strlst_t *buildopts;
7442ac3bf1SJoerg Wunsch 	strlst_t *keeplist;
75de566360SJordan K. Hubbard 	strlst_t *links;
76252f13abSLuigi Rizzo 	strlst_t *libs;
7755f92f64SCeri Davies 	strlst_t *libs_so;
78de566360SJordan K. Hubbard 	int goterror;
79de566360SJordan K. Hubbard } prog_t;
80de566360SJordan K. Hubbard 
81de566360SJordan K. Hubbard 
82de566360SJordan K. Hubbard /* global state */
83de566360SJordan K. Hubbard 
8408a15190SJosef Karthauser strlst_t *buildopts = NULL;
85de566360SJordan K. Hubbard strlst_t *srcdirs   = NULL;
86de566360SJordan K. Hubbard strlst_t *libs      = NULL;
8755f92f64SCeri Davies strlst_t *libs_so   = NULL;
88de566360SJordan K. Hubbard prog_t   *progs     = NULL;
89de566360SJordan K. Hubbard 
90de566360SJordan K. Hubbard char confname[MAXPATHLEN], infilename[MAXPATHLEN];
91de566360SJordan K. Hubbard char outmkname[MAXPATHLEN], outcfname[MAXPATHLEN], execfname[MAXPATHLEN];
92de566360SJordan K. Hubbard char tempfname[MAXPATHLEN], cachename[MAXPATHLEN], curfilename[MAXPATHLEN];
9308826cadSLuigi Rizzo char outhdrname[MAXPATHLEN] ;	/* user-supplied header for *.mk */
94019d04d1SLuigi Rizzo char *objprefix;		/* where are the objects ? */
95*70840a51SDavid E. O'Brien char *path_make;
96de566360SJordan K. Hubbard int linenum = -1;
97de566360SJordan K. Hubbard int goterror = 0;
98de566360SJordan K. Hubbard 
99de566360SJordan K. Hubbard int verbose, readcache;		/* options */
100de566360SJordan K. Hubbard int reading_cache;
101ba2250ddSJosef Karthauser int makeobj = 0;		/* add 'make obj' rules to the makefile */
102de566360SJordan K. Hubbard 
103fb7f926eSPoul-Henning Kamp int list_mode;
104fb7f926eSPoul-Henning Kamp 
105de566360SJordan K. Hubbard /* general library routines */
106de566360SJordan K. Hubbard 
107de566360SJordan K. Hubbard void status(char *str);
108de566360SJordan K. Hubbard void out_of_memory(void);
109de566360SJordan K. Hubbard void add_string(strlst_t **listp, char *str);
110de566360SJordan K. Hubbard int is_dir(char *pathname);
111de566360SJordan K. Hubbard int is_nonempty_file(char *pathname);
11255f92f64SCeri Davies int subtract_strlst(strlst_t **lista, strlst_t **listb);
11355f92f64SCeri Davies int in_list(strlst_t **listp, char *str);
114de566360SJordan K. Hubbard 
115de566360SJordan K. Hubbard /* helper routines for main() */
116de566360SJordan K. Hubbard 
117de566360SJordan K. Hubbard void usage(void);
118de566360SJordan K. Hubbard void parse_conf_file(void);
119de566360SJordan K. Hubbard void gen_outputs(void);
120de566360SJordan K. Hubbard 
121de566360SJordan K. Hubbard 
122de566360SJordan K. Hubbard int main(int argc, char **argv)
123de566360SJordan K. Hubbard {
124de566360SJordan K. Hubbard 	char *p;
125de566360SJordan K. Hubbard 	int optc;
126de566360SJordan K. Hubbard 
127de566360SJordan K. Hubbard 	verbose = 1;
128de566360SJordan K. Hubbard 	readcache = 1;
129de566360SJordan K. Hubbard 	*outmkname = *outcfname = *execfname = '\0';
130de566360SJordan K. Hubbard 
131*70840a51SDavid E. O'Brien 	path_make = getenv("MAKE");
132*70840a51SDavid E. O'Brien 	if (path_make == NULL || *path_make == '\0')
133*70840a51SDavid E. O'Brien 		path_make = "make";
134*70840a51SDavid E. O'Brien 
135019d04d1SLuigi Rizzo 	p = getenv("MAKEOBJDIRPREFIX");
136019d04d1SLuigi Rizzo 	if (p == NULL || *p == '\0')
137019d04d1SLuigi Rizzo 		objprefix = "/usr/obj"; /* default */
138019d04d1SLuigi Rizzo 	else
139f3c47f54SJosef Karthauser 		if ((objprefix = strdup(p)) == NULL)
140f3c47f54SJosef Karthauser 			out_of_memory();
141019d04d1SLuigi Rizzo 
142019d04d1SLuigi Rizzo 	while((optc = getopt(argc, argv, "lh:m:c:e:p:foq")) != -1) {
143de566360SJordan K. Hubbard 		switch(optc) {
14487eb4a42SJosef Karthauser 		case 'f':
14587eb4a42SJosef Karthauser 			readcache = 0;
14687eb4a42SJosef Karthauser 			break;
14787eb4a42SJosef Karthauser 		case 'o':
14887eb4a42SJosef Karthauser 			makeobj = 1;
14987eb4a42SJosef Karthauser 			break;
15087eb4a42SJosef Karthauser 		case 'q':
15187eb4a42SJosef Karthauser 			verbose = 0;
15287eb4a42SJosef Karthauser 			break;
153de566360SJordan K. Hubbard 
15487eb4a42SJosef Karthauser 		case 'm':
15587eb4a42SJosef Karthauser 			strlcpy(outmkname, optarg, sizeof(outmkname));
15687eb4a42SJosef Karthauser 			break;
15787eb4a42SJosef Karthauser 		case 'p':
15887eb4a42SJosef Karthauser 			if ((objprefix = strdup(optarg)) == NULL)
159f3c47f54SJosef Karthauser 				out_of_memory();
160f3c47f54SJosef Karthauser 			break;
16187eb4a42SJosef Karthauser 
16287eb4a42SJosef Karthauser 		case 'h':
16387eb4a42SJosef Karthauser 			strlcpy(outhdrname, optarg, sizeof(outhdrname));
16487eb4a42SJosef Karthauser 			break;
16587eb4a42SJosef Karthauser 		case 'c':
16687eb4a42SJosef Karthauser 			strlcpy(outcfname, optarg, sizeof(outcfname));
16787eb4a42SJosef Karthauser 			break;
16887eb4a42SJosef Karthauser 		case 'e':
16987eb4a42SJosef Karthauser 			strlcpy(execfname, optarg, sizeof(execfname));
17087eb4a42SJosef Karthauser 			break;
17187eb4a42SJosef Karthauser 
17287eb4a42SJosef Karthauser 		case 'l':
17387eb4a42SJosef Karthauser 			list_mode++;
17487eb4a42SJosef Karthauser 			verbose = 0;
17587eb4a42SJosef Karthauser 			break;
176de566360SJordan K. Hubbard 
177de566360SJordan K. Hubbard 		case '?':
17887eb4a42SJosef Karthauser 		default:
17987eb4a42SJosef Karthauser 			usage();
180de566360SJordan K. Hubbard 		}
181de566360SJordan K. Hubbard 	}
182de566360SJordan K. Hubbard 
183de566360SJordan K. Hubbard 	argc -= optind;
184de566360SJordan K. Hubbard 	argv += optind;
185de566360SJordan K. Hubbard 
18687eb4a42SJosef Karthauser 	if (argc != 1)
18787eb4a42SJosef Karthauser 		usage();
188de566360SJordan K. Hubbard 
189de566360SJordan K. Hubbard 	/*
190de566360SJordan K. Hubbard 	 * generate filenames
191de566360SJordan K. Hubbard 	 */
192de566360SJordan K. Hubbard 
193f3c47f54SJosef Karthauser 	strlcpy(infilename, argv[0], sizeof(infilename));
194de566360SJordan K. Hubbard 
195de566360SJordan K. Hubbard 	/* confname = `basename infilename .conf` */
196de566360SJordan K. Hubbard 
197f3c47f54SJosef Karthauser 	if ((p=strrchr(infilename, '/')) != NULL)
198f3c47f54SJosef Karthauser 		strlcpy(confname, p + 1, sizeof(confname));
199f3c47f54SJosef Karthauser 	else
200f3c47f54SJosef Karthauser 		strlcpy(confname, infilename, sizeof(confname));
201de566360SJordan K. Hubbard 
20287eb4a42SJosef Karthauser 	if ((p=strrchr(confname, '.')) != NULL && !strcmp(p, ".conf"))
20387eb4a42SJosef Karthauser 		*p = '\0';
20487eb4a42SJosef Karthauser 
20587eb4a42SJosef Karthauser 	if (!*outmkname)
20687eb4a42SJosef Karthauser 		snprintf(outmkname, sizeof(outmkname), "%s.mk", confname);
20787eb4a42SJosef Karthauser 	if (!*outcfname)
20887eb4a42SJosef Karthauser 		snprintf(outcfname, sizeof(outcfname), "%s.c", confname);
20987eb4a42SJosef Karthauser 	if (!*execfname)
21087eb4a42SJosef Karthauser 		snprintf(execfname, sizeof(execfname), "%s", confname);
211de566360SJordan K. Hubbard 
212019d04d1SLuigi Rizzo 	snprintf(cachename, sizeof(cachename), "%s.cache", confname);
21361ffadb1SJosef Karthauser 	snprintf(tempfname, sizeof(tempfname), "%s/crunchgen_%sXXXXXX",
21461ffadb1SJosef Karthauser 	getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP, confname);
215de566360SJordan K. Hubbard 
216de566360SJordan K. Hubbard 	parse_conf_file();
217fb7f926eSPoul-Henning Kamp 	if (list_mode)
218fb7f926eSPoul-Henning Kamp 		exit(goterror);
219fb7f926eSPoul-Henning Kamp 
220de566360SJordan K. Hubbard 	gen_outputs();
221de566360SJordan K. Hubbard 
222de566360SJordan K. Hubbard 	exit(goterror);
223de566360SJordan K. Hubbard }
224de566360SJordan K. Hubbard 
225de566360SJordan K. Hubbard 
226de566360SJordan K. Hubbard void usage(void)
227de566360SJordan K. Hubbard {
22887eb4a42SJosef Karthauser 	fprintf(stderr, "%s%s\n\t%s%s\n", "usage: crunchgen [-foq] ",
22987eb4a42SJosef Karthauser 	    "[-h <makefile-header-name>] [-m <makefile>]",
23087eb4a42SJosef Karthauser 	    "[-p <obj-prefix>] [-c <c-file-name>] [-e <exec-file>] ",
23187eb4a42SJosef Karthauser 	    "<conffile>");
232de566360SJordan K. Hubbard 	exit(1);
233de566360SJordan K. Hubbard }
234de566360SJordan K. Hubbard 
235de566360SJordan K. Hubbard 
236de566360SJordan K. Hubbard /*
237de566360SJordan K. Hubbard  * ========================================================================
238de566360SJordan K. Hubbard  * parse_conf_file subsystem
239de566360SJordan K. Hubbard  *
240de566360SJordan K. Hubbard  */
241de566360SJordan K. Hubbard 
242de566360SJordan K. Hubbard /* helper routines for parse_conf_file */
243de566360SJordan K. Hubbard 
244de566360SJordan K. Hubbard void parse_one_file(char *filename);
245de566360SJordan K. Hubbard void parse_line(char *line, int *fc, char **fv, int nf);
246de566360SJordan K. Hubbard void add_srcdirs(int argc, char **argv);
247de566360SJordan K. Hubbard void add_progs(int argc, char **argv);
248de566360SJordan K. Hubbard void add_link(int argc, char **argv);
249de566360SJordan K. Hubbard void add_libs(int argc, char **argv);
25055f92f64SCeri Davies void add_libs_so(int argc, char **argv);
25108a15190SJosef Karthauser void add_buildopts(int argc, char **argv);
252de566360SJordan K. Hubbard void add_special(int argc, char **argv);
253de566360SJordan K. Hubbard 
254de566360SJordan K. Hubbard prog_t *find_prog(char *str);
255de566360SJordan K. Hubbard void add_prog(char *progname);
256de566360SJordan K. Hubbard 
257de566360SJordan K. Hubbard 
258de566360SJordan K. Hubbard void parse_conf_file(void)
259de566360SJordan K. Hubbard {
260b17e90a9SPhilippe Charnier 	if (!is_nonempty_file(infilename))
261b17e90a9SPhilippe Charnier 		errx(1, "fatal: input file \"%s\" not found", infilename);
26287eb4a42SJosef Karthauser 
263de566360SJordan K. Hubbard 	parse_one_file(infilename);
264de566360SJordan K. Hubbard 	if (readcache && is_nonempty_file(cachename)) {
265de566360SJordan K. Hubbard 		reading_cache = 1;
266de566360SJordan K. Hubbard 		parse_one_file(cachename);
267de566360SJordan K. Hubbard 	}
268de566360SJordan K. Hubbard }
269de566360SJordan K. Hubbard 
270de566360SJordan K. Hubbard 
271de566360SJordan K. Hubbard void parse_one_file(char *filename)
272de566360SJordan K. Hubbard {
273de566360SJordan K. Hubbard 	char *fieldv[MAXFIELDS];
274de566360SJordan K. Hubbard 	int fieldc;
275de566360SJordan K. Hubbard 	void (*f)(int c, char **v);
276de566360SJordan K. Hubbard 	FILE *cf;
277019d04d1SLuigi Rizzo 	char line[MAXLINELEN];
278de566360SJordan K. Hubbard 
279f3c47f54SJosef Karthauser 	snprintf(line, sizeof(line), "reading %s", filename);
280de566360SJordan K. Hubbard 	status(line);
281f3c47f54SJosef Karthauser 	strlcpy(curfilename, filename, sizeof(curfilename));
282de566360SJordan K. Hubbard 
283de566360SJordan K. Hubbard 	if ((cf = fopen(curfilename, "r")) == NULL) {
284b17e90a9SPhilippe Charnier 		warn("%s", curfilename);
285de566360SJordan K. Hubbard 		goterror = 1;
286de566360SJordan K. Hubbard 		return;
287de566360SJordan K. Hubbard 	}
288de566360SJordan K. Hubbard 
289de566360SJordan K. Hubbard 	linenum = 0;
290de566360SJordan K. Hubbard 	while (fgets(line, MAXLINELEN, cf) != NULL) {
291de566360SJordan K. Hubbard 		linenum++;
292de566360SJordan K. Hubbard 		parse_line(line, &fieldc, fieldv, MAXFIELDS);
29387eb4a42SJosef Karthauser 
29487eb4a42SJosef Karthauser 		if (fieldc < 1)
29587eb4a42SJosef Karthauser 			continue;
29687eb4a42SJosef Karthauser 
29787eb4a42SJosef Karthauser 		if (!strcmp(fieldv[0], "srcdirs"))
29887eb4a42SJosef Karthauser 			f = add_srcdirs;
29987eb4a42SJosef Karthauser 		else if(!strcmp(fieldv[0], "progs"))
30087eb4a42SJosef Karthauser 			f = add_progs;
30187eb4a42SJosef Karthauser 		else if(!strcmp(fieldv[0], "ln"))
30287eb4a42SJosef Karthauser 			f = add_link;
30387eb4a42SJosef Karthauser 		else if(!strcmp(fieldv[0], "libs"))
30487eb4a42SJosef Karthauser 			f = add_libs;
30555f92f64SCeri Davies 		else if(!strcmp(fieldv[0], "libs_so"))
30655f92f64SCeri Davies 			f = add_libs_so;
30787eb4a42SJosef Karthauser 		else if(!strcmp(fieldv[0], "buildopts"))
30887eb4a42SJosef Karthauser 			f = add_buildopts;
30987eb4a42SJosef Karthauser 		else if(!strcmp(fieldv[0], "special"))
31087eb4a42SJosef Karthauser 			f = add_special;
311de566360SJordan K. Hubbard 		else {
312b17e90a9SPhilippe Charnier 			warnx("%s:%d: skipping unknown command `%s'",
313de566360SJordan K. Hubbard 			    curfilename, linenum, fieldv[0]);
314de566360SJordan K. Hubbard 			goterror = 1;
315de566360SJordan K. Hubbard 			continue;
316de566360SJordan K. Hubbard 		}
31787eb4a42SJosef Karthauser 
318de566360SJordan K. Hubbard 		if (fieldc < 2) {
31987eb4a42SJosef Karthauser 			warnx("%s:%d: %s %s",
32087eb4a42SJosef Karthauser 			    curfilename, linenum, fieldv[0],
32187eb4a42SJosef Karthauser 			    "command needs at least 1 argument, skipping");
322de566360SJordan K. Hubbard 			goterror = 1;
323de566360SJordan K. Hubbard 			continue;
324de566360SJordan K. Hubbard 		}
32587eb4a42SJosef Karthauser 
326de566360SJordan K. Hubbard 		f(fieldc, fieldv);
327de566360SJordan K. Hubbard 	}
328de566360SJordan K. Hubbard 
329de566360SJordan K. Hubbard 	if (ferror(cf)) {
330b17e90a9SPhilippe Charnier 		warn("%s", curfilename);
331de566360SJordan K. Hubbard 		goterror = 1;
332de566360SJordan K. Hubbard 	}
333de566360SJordan K. Hubbard 	fclose(cf);
334de566360SJordan K. Hubbard }
335de566360SJordan K. Hubbard 
336de566360SJordan K. Hubbard 
337de566360SJordan K. Hubbard void parse_line(char *line, int *fc, char **fv, int nf)
338de566360SJordan K. Hubbard {
339de566360SJordan K. Hubbard 	char *p;
340de566360SJordan K. Hubbard 
341de566360SJordan K. Hubbard 	p = line;
342de566360SJordan K. Hubbard 	*fc = 0;
343de566360SJordan K. Hubbard 
34487eb4a42SJosef Karthauser 	while (1) {
34587eb4a42SJosef Karthauser 		while (isspace(*p))
34687eb4a42SJosef Karthauser 			p++;
34787eb4a42SJosef Karthauser 
34887eb4a42SJosef Karthauser 		if (*p == '\0' || *p == '#')
34987eb4a42SJosef Karthauser 			break;
35087eb4a42SJosef Karthauser 
35187eb4a42SJosef Karthauser 		if (*fc < nf)
35287eb4a42SJosef Karthauser 			fv[(*fc)++] = p;
35387eb4a42SJosef Karthauser 
35487eb4a42SJosef Karthauser 		while (*p && !isspace(*p) && *p != '#')
35587eb4a42SJosef Karthauser 			p++;
35687eb4a42SJosef Karthauser 
35787eb4a42SJosef Karthauser 		if (*p == '\0' || *p == '#')
35887eb4a42SJosef Karthauser 			break;
35987eb4a42SJosef Karthauser 
360de566360SJordan K. Hubbard 		*p++ = '\0';
361de566360SJordan K. Hubbard 	}
36287eb4a42SJosef Karthauser 
36387eb4a42SJosef Karthauser 	if (*p)
36487eb4a42SJosef Karthauser 		*p = '\0';		/* needed for '#' case */
365de566360SJordan K. Hubbard }
366de566360SJordan K. Hubbard 
367de566360SJordan K. Hubbard 
368de566360SJordan K. Hubbard void add_srcdirs(int argc, char **argv)
369de566360SJordan K. Hubbard {
370de566360SJordan K. Hubbard 	int i;
371de566360SJordan K. Hubbard 
372de566360SJordan K. Hubbard 	for (i = 1; i < argc; i++) {
373de566360SJordan K. Hubbard 		if (is_dir(argv[i]))
374de566360SJordan K. Hubbard 			add_string(&srcdirs, argv[i]);
375de566360SJordan K. Hubbard 		else {
376b17e90a9SPhilippe Charnier 			warnx("%s:%d: `%s' is not a directory, skipping it",
377de566360SJordan K. Hubbard 			    curfilename, linenum, argv[i]);
378de566360SJordan K. Hubbard 			goterror = 1;
379de566360SJordan K. Hubbard 		}
380de566360SJordan K. Hubbard 	}
381de566360SJordan K. Hubbard }
382de566360SJordan K. Hubbard 
383de566360SJordan K. Hubbard 
384de566360SJordan K. Hubbard void add_progs(int argc, char **argv)
385de566360SJordan K. Hubbard {
386de566360SJordan K. Hubbard 	int i;
387de566360SJordan K. Hubbard 
388de566360SJordan K. Hubbard 	for (i = 1; i < argc; i++)
389de566360SJordan K. Hubbard 		add_prog(argv[i]);
390de566360SJordan K. Hubbard }
391de566360SJordan K. Hubbard 
392de566360SJordan K. Hubbard 
393de566360SJordan K. Hubbard void add_prog(char *progname)
394de566360SJordan K. Hubbard {
395de566360SJordan K. Hubbard 	prog_t *p1, *p2;
396de566360SJordan K. Hubbard 
397de566360SJordan K. Hubbard 	/* add to end, but be smart about dups */
398de566360SJordan K. Hubbard 
399de566360SJordan K. Hubbard 	for (p1 = NULL, p2 = progs; p2 != NULL; p1 = p2, p2 = p2->next)
40087eb4a42SJosef Karthauser 		if (!strcmp(p2->name, progname))
40187eb4a42SJosef Karthauser 			return;
402de566360SJordan K. Hubbard 
403de566360SJordan K. Hubbard 	p2 = malloc(sizeof(prog_t));
404eb148815SJoerg Wunsch 	if(p2) {
405eb148815SJoerg Wunsch 		memset(p2, 0, sizeof(prog_t));
406eb148815SJoerg Wunsch 		p2->name = strdup(progname);
407eb148815SJoerg Wunsch 	}
408de566360SJordan K. Hubbard 	if (!p2 || !p2->name)
409de566360SJordan K. Hubbard 		out_of_memory();
410de566360SJordan K. Hubbard 
411de566360SJordan K. Hubbard 	p2->next = NULL;
41287eb4a42SJosef Karthauser 	if (p1 == NULL)
41387eb4a42SJosef Karthauser 		progs = p2;
41487eb4a42SJosef Karthauser 	else
41587eb4a42SJosef Karthauser 		p1->next = p2;
416de566360SJordan K. Hubbard 
41787eb4a42SJosef Karthauser 	p2->ident = NULL;
41887eb4a42SJosef Karthauser 	p2->srcdir = NULL;
41987eb4a42SJosef Karthauser 	p2->realsrcdir = NULL;
42087eb4a42SJosef Karthauser 	p2->objdir = NULL;
42187eb4a42SJosef Karthauser 	p2->links = NULL;
422252f13abSLuigi Rizzo 	p2->libs = NULL;
42355f92f64SCeri Davies 	p2->libs_so = NULL;
42487eb4a42SJosef Karthauser 	p2->objs = NULL;
42587eb4a42SJosef Karthauser 	p2->keeplist = NULL;
42634944d48SJosef Karthauser 	p2->buildopts = NULL;
427de566360SJordan K. Hubbard 	p2->goterror = 0;
42887eb4a42SJosef Karthauser 
429fb7f926eSPoul-Henning Kamp 	if (list_mode)
430fb7f926eSPoul-Henning Kamp 		printf("%s\n",progname);
431de566360SJordan K. Hubbard }
432de566360SJordan K. Hubbard 
433de566360SJordan K. Hubbard 
434de566360SJordan K. Hubbard void add_link(int argc, char **argv)
435de566360SJordan K. Hubbard {
436de566360SJordan K. Hubbard 	int i;
437de566360SJordan K. Hubbard 	prog_t *p = find_prog(argv[1]);
438de566360SJordan K. Hubbard 
439de566360SJordan K. Hubbard 	if (p == NULL) {
440b17e90a9SPhilippe Charnier 		warnx("%s:%d: no prog %s previously declared, skipping link",
441de566360SJordan K. Hubbard 		    curfilename, linenum, argv[1]);
442de566360SJordan K. Hubbard 		goterror = 1;
443de566360SJordan K. Hubbard 		return;
444de566360SJordan K. Hubbard 	}
44587eb4a42SJosef Karthauser 
446fb7f926eSPoul-Henning Kamp 	for (i = 2; i < argc; i++) {
447fb7f926eSPoul-Henning Kamp 		if (list_mode)
448fb7f926eSPoul-Henning Kamp 			printf("%s\n",argv[i]);
44987eb4a42SJosef Karthauser 
450de566360SJordan K. Hubbard 		add_string(&p->links, argv[i]);
451de566360SJordan K. Hubbard 	}
452fb7f926eSPoul-Henning Kamp }
453de566360SJordan K. Hubbard 
454de566360SJordan K. Hubbard 
455de566360SJordan K. Hubbard void add_libs(int argc, char **argv)
456de566360SJordan K. Hubbard {
457de566360SJordan K. Hubbard 	int i;
458de566360SJordan K. Hubbard 
45955f92f64SCeri Davies 	for(i = 1; i < argc; i++) {
460de566360SJordan K. Hubbard 		add_string(&libs, argv[i]);
46155f92f64SCeri Davies 		if ( in_list(&libs_so, argv[i]) )
46255f92f64SCeri Davies 			warnx("%s:%d: "
46355f92f64SCeri Davies 				"library `%s' specified as dynamic earlier",
46455f92f64SCeri Davies 				curfilename, linenum, argv[i]);
46555f92f64SCeri Davies 	}
46655f92f64SCeri Davies }
46755f92f64SCeri Davies 
46855f92f64SCeri Davies 
46955f92f64SCeri Davies void add_libs_so(int argc, char **argv)
47055f92f64SCeri Davies {
47155f92f64SCeri Davies 	int i;
47255f92f64SCeri Davies 
47355f92f64SCeri Davies 	for(i = 1; i < argc; i++) {
47455f92f64SCeri Davies 		add_string(&libs_so, argv[i]);
47555f92f64SCeri Davies 		if ( in_list(&libs, argv[i]) )
47655f92f64SCeri Davies 			warnx("%s:%d: "
47755f92f64SCeri Davies 				"library `%s' specified as static earlier",
47855f92f64SCeri Davies 				curfilename, linenum, argv[i]);
47955f92f64SCeri Davies 	}
480de566360SJordan K. Hubbard }
481de566360SJordan K. Hubbard 
482de566360SJordan K. Hubbard 
48308a15190SJosef Karthauser void add_buildopts(int argc, char **argv)
48408a15190SJosef Karthauser {
48508a15190SJosef Karthauser 	int i;
48608a15190SJosef Karthauser 
48708a15190SJosef Karthauser 	for (i = 1; i < argc; i++)
48808a15190SJosef Karthauser 		add_string(&buildopts, argv[i]);
48908a15190SJosef Karthauser }
49008a15190SJosef Karthauser 
49108a15190SJosef Karthauser 
492de566360SJordan K. Hubbard void add_special(int argc, char **argv)
493de566360SJordan K. Hubbard {
494de566360SJordan K. Hubbard 	int i;
495de566360SJordan K. Hubbard 	prog_t *p = find_prog(argv[1]);
496de566360SJordan K. Hubbard 
497de566360SJordan K. Hubbard 	if (p == NULL) {
49887eb4a42SJosef Karthauser 		if (reading_cache)
49987eb4a42SJosef Karthauser 			return;
50087eb4a42SJosef Karthauser 
501b17e90a9SPhilippe Charnier 		warnx("%s:%d: no prog %s previously declared, skipping special",
502de566360SJordan K. Hubbard 		    curfilename, linenum, argv[1]);
503de566360SJordan K. Hubbard 		goterror = 1;
504de566360SJordan K. Hubbard 		return;
505de566360SJordan K. Hubbard 	}
506de566360SJordan K. Hubbard 
507de566360SJordan K. Hubbard 	if (!strcmp(argv[2], "ident")) {
50887eb4a42SJosef Karthauser 		if (argc != 4)
50987eb4a42SJosef Karthauser 			goto argcount;
510de566360SJordan K. Hubbard 		if ((p->ident = strdup(argv[3])) == NULL)
511de566360SJordan K. Hubbard 			out_of_memory();
51287eb4a42SJosef Karthauser 	} else if (!strcmp(argv[2], "srcdir")) {
51387eb4a42SJosef Karthauser 		if (argc != 4)
51487eb4a42SJosef Karthauser 			goto argcount;
515de566360SJordan K. Hubbard 		if ((p->srcdir = strdup(argv[3])) == NULL)
516de566360SJordan K. Hubbard 			out_of_memory();
51787eb4a42SJosef Karthauser 	} else if (!strcmp(argv[2], "objdir")) {
51887eb4a42SJosef Karthauser 		if(argc != 4)
51987eb4a42SJosef Karthauser 			goto argcount;
520de566360SJordan K. Hubbard 		if((p->objdir = strdup(argv[3])) == NULL)
521de566360SJordan K. Hubbard 			out_of_memory();
52287eb4a42SJosef Karthauser 	} else if (!strcmp(argv[2], "objs")) {
523de566360SJordan K. Hubbard 		p->objs = NULL;
524de566360SJordan K. Hubbard 		for (i = 3; i < argc; i++)
525de566360SJordan K. Hubbard 			add_string(&p->objs, argv[i]);
52687eb4a42SJosef Karthauser 	} else if (!strcmp(argv[2], "objpaths")) {
527de566360SJordan K. Hubbard 		p->objpaths = NULL;
528de566360SJordan K. Hubbard 		for (i = 3; i < argc; i++)
529de566360SJordan K. Hubbard 			add_string(&p->objpaths, argv[i]);
53087eb4a42SJosef Karthauser 	} else if (!strcmp(argv[2], "keep")) {
53142ac3bf1SJoerg Wunsch 		p->keeplist = NULL;
53242ac3bf1SJoerg Wunsch 		for(i = 3; i < argc; i++)
53342ac3bf1SJoerg Wunsch 			add_string(&p->keeplist, argv[i]);
53487eb4a42SJosef Karthauser 	} else if (!strcmp(argv[2], "objvar")) {
53508826cadSLuigi Rizzo 		if(argc != 4)
53608826cadSLuigi Rizzo 			goto argcount;
53708826cadSLuigi Rizzo 		if ((p->objvar = strdup(argv[3])) == NULL)
53808826cadSLuigi Rizzo 			out_of_memory();
53987eb4a42SJosef Karthauser 	} else if (!strcmp(argv[2], "buildopts")) {
54034944d48SJosef Karthauser 		p->buildopts = NULL;
54134944d48SJosef Karthauser 		for (i = 3; i < argc; i++)
54234944d48SJosef Karthauser 			add_string(&p->buildopts, argv[i]);
543252f13abSLuigi Rizzo 	} else if (!strcmp(argv[2], "lib")) {
544252f13abSLuigi Rizzo 		for (i = 3; i < argc; i++)
545252f13abSLuigi Rizzo 			add_string(&p->libs, argv[i]);
54687eb4a42SJosef Karthauser 	} else {
547b17e90a9SPhilippe Charnier 		warnx("%s:%d: bad parameter name `%s', skipping line",
548de566360SJordan K. Hubbard 		    curfilename, linenum, argv[2]);
549de566360SJordan K. Hubbard 		goterror = 1;
550de566360SJordan K. Hubbard 	}
551de566360SJordan K. Hubbard 	return;
552de566360SJordan K. Hubbard 
553de566360SJordan K. Hubbard  argcount:
554b17e90a9SPhilippe Charnier 	warnx("%s:%d: too %s arguments, expected \"special %s %s <string>\"",
555de566360SJordan K. Hubbard 	    curfilename, linenum, argc < 4? "few" : "many", argv[1], argv[2]);
556de566360SJordan K. Hubbard 	goterror = 1;
557de566360SJordan K. Hubbard }
558de566360SJordan K. Hubbard 
559de566360SJordan K. Hubbard 
560de566360SJordan K. Hubbard prog_t *find_prog(char *str)
561de566360SJordan K. Hubbard {
562de566360SJordan K. Hubbard 	prog_t *p;
563de566360SJordan K. Hubbard 
564de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next)
56587eb4a42SJosef Karthauser 		if (!strcmp(p->name, str))
56687eb4a42SJosef Karthauser 			return p;
567de566360SJordan K. Hubbard 
568de566360SJordan K. Hubbard 	return NULL;
569de566360SJordan K. Hubbard }
570de566360SJordan K. Hubbard 
571de566360SJordan K. Hubbard 
572de566360SJordan K. Hubbard /*
573de566360SJordan K. Hubbard  * ========================================================================
574de566360SJordan K. Hubbard  * gen_outputs subsystem
575de566360SJordan K. Hubbard  *
576de566360SJordan K. Hubbard  */
577de566360SJordan K. Hubbard 
578de566360SJordan K. Hubbard /* helper subroutines */
579de566360SJordan K. Hubbard 
580de566360SJordan K. Hubbard void remove_error_progs(void);
581de566360SJordan K. Hubbard void fillin_program(prog_t *p);
582de566360SJordan K. Hubbard void gen_specials_cache(void);
583de566360SJordan K. Hubbard void gen_output_makefile(void);
584de566360SJordan K. Hubbard void gen_output_cfile(void);
585de566360SJordan K. Hubbard 
586de566360SJordan K. Hubbard void fillin_program_objs(prog_t *p, char *path);
587de566360SJordan K. Hubbard void top_makefile_rules(FILE *outmk);
588de566360SJordan K. Hubbard void prog_makefile_rules(FILE *outmk, prog_t *p);
589de566360SJordan K. Hubbard void output_strlst(FILE *outf, strlst_t *lst);
590de566360SJordan K. Hubbard char *genident(char *str);
591de566360SJordan K. Hubbard char *dir_search(char *progname);
592de566360SJordan K. Hubbard 
593de566360SJordan K. Hubbard 
594de566360SJordan K. Hubbard void gen_outputs(void)
595de566360SJordan K. Hubbard {
596de566360SJordan K. Hubbard 	prog_t *p;
597de566360SJordan K. Hubbard 
598de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next)
599de566360SJordan K. Hubbard 		fillin_program(p);
600de566360SJordan K. Hubbard 
601de566360SJordan K. Hubbard 	remove_error_progs();
602de566360SJordan K. Hubbard 	gen_specials_cache();
603de566360SJordan K. Hubbard 	gen_output_cfile();
604de566360SJordan K. Hubbard 	gen_output_makefile();
605de566360SJordan K. Hubbard 	status("");
606de566360SJordan K. Hubbard 	fprintf(stderr,
607*70840a51SDavid E. O'Brien 	    "Run \"%s -f %s\" to build crunched binary.\n",
608*70840a51SDavid E. O'Brien 	    path_make, outmkname);
609de566360SJordan K. Hubbard }
610de566360SJordan K. Hubbard 
61108826cadSLuigi Rizzo /*
61208826cadSLuigi Rizzo  * run the makefile for the program to find which objects are necessary
61308826cadSLuigi Rizzo  */
614de566360SJordan K. Hubbard void fillin_program(prog_t *p)
615de566360SJordan K. Hubbard {
616de566360SJordan K. Hubbard 	char path[MAXPATHLEN];
617019d04d1SLuigi Rizzo 	char line[MAXLINELEN];
618843d8d51SJosef Karthauser 	FILE *f;
619de566360SJordan K. Hubbard 
620019d04d1SLuigi Rizzo 	snprintf(line, MAXLINELEN, "filling in parms for %s", p->name);
621de566360SJordan K. Hubbard 	status(line);
622de566360SJordan K. Hubbard 
623de566360SJordan K. Hubbard 	if (!p->ident)
624de566360SJordan K. Hubbard 		p->ident = genident(p->name);
625e3b7d178SJosef Karthauser 
626e3b7d178SJosef Karthauser 	/* look for the source directory if one wasn't specified by a special */
627de566360SJordan K. Hubbard 	if (!p->srcdir) {
628e3b7d178SJosef Karthauser 		p->srcdir = dir_search(p->name);
629de566360SJordan K. Hubbard 	}
630843d8d51SJosef Karthauser 
631843d8d51SJosef Karthauser 	/* Determine the actual srcdir (maybe symlinked). */
632e3b7d178SJosef Karthauser 	if (p->srcdir) {
63387eb4a42SJosef Karthauser 		snprintf(line, MAXLINELEN, "cd %s && echo -n `/bin/pwd`",
63487eb4a42SJosef Karthauser 		    p->srcdir);
635019d04d1SLuigi Rizzo 		f = popen(line,"r");
636e3b7d178SJosef Karthauser 		if (!f)
637e3b7d178SJosef Karthauser 			errx(1, "Can't execute: %s\n", line);
638e3b7d178SJosef Karthauser 
639019d04d1SLuigi Rizzo 		path[0] = '\0';
640154fd6a9SPoul-Henning Kamp 		fgets(path, sizeof path, f);
641e3b7d178SJosef Karthauser 		if (pclose(f))
642e3b7d178SJosef Karthauser 			errx(1, "Can't execute: %s\n", line);
643e3b7d178SJosef Karthauser 
644e3b7d178SJosef Karthauser 		if (!*path)
645e3b7d178SJosef Karthauser 			errx(1, "Can't perform pwd on: %s\n", p->srcdir);
646e3b7d178SJosef Karthauser 
647843d8d51SJosef Karthauser 		p->realsrcdir = strdup(path);
648154fd6a9SPoul-Henning Kamp 	}
649843d8d51SJosef Karthauser 
650843d8d51SJosef Karthauser 	/* Unless the option to make object files was specified the
651843d8d51SJosef Karthauser 	* the objects will be built in the source directory unless
652843d8d51SJosef Karthauser 	* an object directory already exists.
653843d8d51SJosef Karthauser 	*/
654843d8d51SJosef Karthauser 	if (!makeobj && !p->objdir && p->srcdir) {
655843d8d51SJosef Karthauser 		snprintf(line, sizeof line, "%s/%s", objprefix, p->realsrcdir);
6565e5f3826SJosef Karthauser 		if (is_dir(line)) {
657f3c47f54SJosef Karthauser 			if ((p->objdir = strdup(line)) == NULL)
658f3c47f54SJosef Karthauser 			out_of_memory();
6595e5f3826SJosef Karthauser 		} else
660843d8d51SJosef Karthauser 			p->objdir = p->realsrcdir;
661de566360SJordan K. Hubbard 	}
66287eb4a42SJosef Karthauser 
66308826cadSLuigi Rizzo 	/*
66408826cadSLuigi Rizzo 	* XXX look for a Makefile.{name} in local directory first.
66508826cadSLuigi Rizzo 	* This lets us override the original Makefile.
66608826cadSLuigi Rizzo 	*/
667019d04d1SLuigi Rizzo 	snprintf(path, sizeof(path), "Makefile.%s", p->name);
66808826cadSLuigi Rizzo 	if (is_nonempty_file(path)) {
669019d04d1SLuigi Rizzo 		snprintf(line, MAXLINELEN, "Using %s for %s", path, p->name);
67008826cadSLuigi Rizzo 		status(line);
67108826cadSLuigi Rizzo 	} else
67287eb4a42SJosef Karthauser 		if (p->srcdir)
67387eb4a42SJosef Karthauser 			snprintf(path, sizeof(path), "%s/Makefile", p->srcdir);
674de566360SJordan K. Hubbard 	if (!p->objs && p->srcdir && is_nonempty_file(path))
675de566360SJordan K. Hubbard 		fillin_program_objs(p, path);
676de566360SJordan K. Hubbard 
67711384533SJosef Karthauser 	if (!p->srcdir && !p->objdir && verbose)
67887eb4a42SJosef Karthauser 		warnx("%s: %s: %s",
67987eb4a42SJosef Karthauser 		    "warning: could not find source directory",
680de566360SJordan K. Hubbard 		    infilename, p->name);
681de566360SJordan K. Hubbard 	if (!p->objs && verbose)
682b17e90a9SPhilippe Charnier 		warnx("%s: %s: warning: could not find any .o files",
683de566360SJordan K. Hubbard 		    infilename, p->name);
684617b8180SJosef Karthauser 
6851554755eSJosef Karthauser 	if ((!p->srcdir || !p->objdir) && !p->objs)
686617b8180SJosef Karthauser 		p->goterror = 1;
687de566360SJordan K. Hubbard }
688de566360SJordan K. Hubbard 
689de566360SJordan K. Hubbard void fillin_program_objs(prog_t *p, char *path)
690de566360SJordan K. Hubbard {
691de566360SJordan K. Hubbard 	char *obj, *cp;
692f3c47f54SJosef Karthauser 	int fd, rc;
693de566360SJordan K. Hubbard 	FILE *f;
69408826cadSLuigi Rizzo 	char *objvar="OBJS";
69534944d48SJosef Karthauser 	strlst_t *s;
696019d04d1SLuigi Rizzo 	char line[MAXLINELEN];
697de566360SJordan K. Hubbard 
698de566360SJordan K. Hubbard 	/* discover the objs from the srcdir Makefile */
699de566360SJordan K. Hubbard 
700f3c47f54SJosef Karthauser 	if ((fd = mkstemp(tempfname)) == -1) {
701f3c47f54SJosef Karthauser 		perror(tempfname);
702f3c47f54SJosef Karthauser 		exit(1);
703f3c47f54SJosef Karthauser 	}
704f3c47f54SJosef Karthauser 	if ((f = fdopen(fd, "w")) == NULL) {
705b17e90a9SPhilippe Charnier 		warn("%s", tempfname);
706de566360SJordan K. Hubbard 		goterror = 1;
707de566360SJordan K. Hubbard 		return;
708de566360SJordan K. Hubbard 	}
70908826cadSLuigi Rizzo 	if (p->objvar)
71008826cadSLuigi Rizzo 		objvar = p->objvar;
711de566360SJordan K. Hubbard 
71208826cadSLuigi Rizzo 	/*
71308826cadSLuigi Rizzo 	* XXX include outhdrname (e.g. to contain Make variables)
71408826cadSLuigi Rizzo 	*/
71508826cadSLuigi Rizzo 	if (outhdrname[0] != '\0')
71608826cadSLuigi Rizzo 		fprintf(f, ".include \"%s\"\n", outhdrname);
717de566360SJordan K. Hubbard 	fprintf(f, ".include \"%s\"\n", path);
718b0889725SDavid E. O'Brien 	fprintf(f, ".POSIX:\n");
71908a15190SJosef Karthauser 	if (buildopts) {
72008a15190SJosef Karthauser 		fprintf(f, "BUILDOPTS+=");
72108a15190SJosef Karthauser 		output_strlst(f, buildopts);
72208a15190SJosef Karthauser 	}
7237328f913SDavid E. O'Brien 	fprintf(f, ".if defined(PROG)\n");
7247328f913SDavid E. O'Brien 	fprintf(f, "%s?=${PROG}.o\n", objvar);
725de566360SJordan K. Hubbard 	fprintf(f, ".endif\n");
72665cb078fSJosef Karthauser 	fprintf(f, "loop:\n\t@echo 'OBJS= '${%s}\n", objvar);
72734944d48SJosef Karthauser 
7282343a534SRuslan Ermilov 	fprintf(f, "crunchgen_objs:\n"
729*70840a51SDavid E. O'Brien 	    "\t@cd %s && %s -f %s $(BUILDOPTS) $(%s_OPTS)",
730*70840a51SDavid E. O'Brien 	    p->srcdir, path_make, tempfname, p->ident);
73134944d48SJosef Karthauser 	for (s = p->buildopts; s != NULL; s = s->next)
73234944d48SJosef Karthauser 		fprintf(f, " %s", s->str);
73334944d48SJosef Karthauser 	fprintf(f, " loop\n");
73434944d48SJosef Karthauser 
735de566360SJordan K. Hubbard 	fclose(f);
736de566360SJordan K. Hubbard 
737*70840a51SDavid E. O'Brien 	snprintf(line, MAXLINELEN, "cd %s && %s -f %s -B crunchgen_objs",
738*70840a51SDavid E. O'Brien 	     p->srcdir, path_make, tempfname);
739de566360SJordan K. Hubbard 	if ((f = popen(line, "r")) == NULL) {
740b17e90a9SPhilippe Charnier 		warn("submake pipe");
741de566360SJordan K. Hubbard 		goterror = 1;
742de566360SJordan K. Hubbard 		return;
743de566360SJordan K. Hubbard 	}
744de566360SJordan K. Hubbard 
745de566360SJordan K. Hubbard 	while(fgets(line, MAXLINELEN, f)) {
746de566360SJordan K. Hubbard 		if (strncmp(line, "OBJS= ", 6)) {
747b17e90a9SPhilippe Charnier 			warnx("make error: %s", line);
748de566360SJordan K. Hubbard 			goterror = 1;
749de566360SJordan K. Hubbard 			continue;
750de566360SJordan K. Hubbard 		}
75187eb4a42SJosef Karthauser 
752de566360SJordan K. Hubbard 		cp = line + 6;
75387eb4a42SJosef Karthauser 		while (isspace(*cp))
75487eb4a42SJosef Karthauser 			cp++;
75587eb4a42SJosef Karthauser 
756de566360SJordan K. Hubbard 		while(*cp) {
757de566360SJordan K. Hubbard 			obj = cp;
75887eb4a42SJosef Karthauser 			while (*cp && !isspace(*cp))
75987eb4a42SJosef Karthauser 				cp++;
76087eb4a42SJosef Karthauser 			if (*cp)
76187eb4a42SJosef Karthauser 				*cp++ = '\0';
762de566360SJordan K. Hubbard 			add_string(&p->objs, obj);
76387eb4a42SJosef Karthauser 			while (isspace(*cp))
76487eb4a42SJosef Karthauser 				cp++;
765de566360SJordan K. Hubbard 		}
766de566360SJordan K. Hubbard 	}
76787eb4a42SJosef Karthauser 
768de566360SJordan K. Hubbard 	if ((rc=pclose(f)) != 0) {
769b17e90a9SPhilippe Charnier 		warnx("make error: make returned %d", rc);
770de566360SJordan K. Hubbard 		goterror = 1;
771de566360SJordan K. Hubbard 	}
77287eb4a42SJosef Karthauser 
773de566360SJordan K. Hubbard 	unlink(tempfname);
774de566360SJordan K. Hubbard }
775de566360SJordan K. Hubbard 
776de566360SJordan K. Hubbard void remove_error_progs(void)
777de566360SJordan K. Hubbard {
778de566360SJordan K. Hubbard 	prog_t *p1, *p2;
779de566360SJordan K. Hubbard 
780de566360SJordan K. Hubbard 	p1 = NULL; p2 = progs;
781de566360SJordan K. Hubbard 	while (p2 != NULL) {
782de566360SJordan K. Hubbard 		if (!p2->goterror)
783de566360SJordan K. Hubbard 			p1 = p2, p2 = p2->next;
784de566360SJordan K. Hubbard 		else {
785de566360SJordan K. Hubbard 			/* delete it from linked list */
786b17e90a9SPhilippe Charnier 			warnx("%s: %s: ignoring program because of errors",
787de566360SJordan K. Hubbard 			    infilename, p2->name);
78887eb4a42SJosef Karthauser 			if (p1)
78987eb4a42SJosef Karthauser 				p1->next = p2->next;
79087eb4a42SJosef Karthauser 			else
79187eb4a42SJosef Karthauser 				progs = p2->next;
792de566360SJordan K. Hubbard 			p2 = p2->next;
793de566360SJordan K. Hubbard 		}
794de566360SJordan K. Hubbard 	}
795de566360SJordan K. Hubbard }
796de566360SJordan K. Hubbard 
797de566360SJordan K. Hubbard void gen_specials_cache(void)
798de566360SJordan K. Hubbard {
799de566360SJordan K. Hubbard 	FILE *cachef;
800de566360SJordan K. Hubbard 	prog_t *p;
801019d04d1SLuigi Rizzo 	char line[MAXLINELEN];
802de566360SJordan K. Hubbard 
803019d04d1SLuigi Rizzo 	snprintf(line, MAXLINELEN, "generating %s", cachename);
804de566360SJordan K. Hubbard 	status(line);
805de566360SJordan K. Hubbard 
806de566360SJordan K. Hubbard 	if ((cachef = fopen(cachename, "w")) == NULL) {
807b17e90a9SPhilippe Charnier 		warn("%s", cachename);
808de566360SJordan K. Hubbard 		goterror = 1;
809de566360SJordan K. Hubbard 		return;
810de566360SJordan K. Hubbard 	}
811de566360SJordan K. Hubbard 
81287eb4a42SJosef Karthauser 	fprintf(cachef, "# %s - parm cache generated from %s by crunchgen "
81387eb4a42SJosef Karthauser 	    " %s\n\n",
814de566360SJordan K. Hubbard 	    cachename, infilename, CRUNCH_VERSION);
815de566360SJordan K. Hubbard 
816de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next) {
817de566360SJordan K. Hubbard 		fprintf(cachef, "\n");
818de566360SJordan K. Hubbard 		if (p->srcdir)
81987eb4a42SJosef Karthauser 			fprintf(cachef, "special %s srcdir %s\n",
82087eb4a42SJosef Karthauser 			    p->name, p->srcdir);
821de566360SJordan K. Hubbard 		if (p->objdir)
82287eb4a42SJosef Karthauser 			fprintf(cachef, "special %s objdir %s\n",
82387eb4a42SJosef Karthauser 			    p->name, p->objdir);
824de566360SJordan K. Hubbard 		if (p->objs) {
825de566360SJordan K. Hubbard 			fprintf(cachef, "special %s objs", p->name);
826de566360SJordan K. Hubbard 			output_strlst(cachef, p->objs);
827de566360SJordan K. Hubbard 		}
828843d8d51SJosef Karthauser 		if (p->objpaths) {
829de566360SJordan K. Hubbard 			fprintf(cachef, "special %s objpaths", p->name);
830de566360SJordan K. Hubbard 			output_strlst(cachef, p->objpaths);
831de566360SJordan K. Hubbard 		}
832843d8d51SJosef Karthauser 	}
833de566360SJordan K. Hubbard 	fclose(cachef);
834de566360SJordan K. Hubbard }
835de566360SJordan K. Hubbard 
836de566360SJordan K. Hubbard 
837de566360SJordan K. Hubbard void gen_output_makefile(void)
838de566360SJordan K. Hubbard {
839de566360SJordan K. Hubbard 	prog_t *p;
840de566360SJordan K. Hubbard 	FILE *outmk;
841019d04d1SLuigi Rizzo 	char line[MAXLINELEN];
842de566360SJordan K. Hubbard 
843019d04d1SLuigi Rizzo 	snprintf(line, MAXLINELEN, "generating %s", outmkname);
844de566360SJordan K. Hubbard 	status(line);
845de566360SJordan K. Hubbard 
846de566360SJordan K. Hubbard 	if ((outmk = fopen(outmkname, "w")) == NULL) {
847b17e90a9SPhilippe Charnier 		warn("%s", outmkname);
848de566360SJordan K. Hubbard 		goterror = 1;
849de566360SJordan K. Hubbard 		return;
850de566360SJordan K. Hubbard 	}
851de566360SJordan K. Hubbard 
852de566360SJordan K. Hubbard 	fprintf(outmk, "# %s - generated from %s by crunchgen %s\n\n",
853de566360SJordan K. Hubbard 	    outmkname, infilename, CRUNCH_VERSION);
85487eb4a42SJosef Karthauser 
85508826cadSLuigi Rizzo 	if (outhdrname[0] != '\0')
85608826cadSLuigi Rizzo 		fprintf(outmk, ".include \"%s\"\n", outhdrname);
857de566360SJordan K. Hubbard 
858de566360SJordan K. Hubbard 	top_makefile_rules(outmk);
859de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next)
860de566360SJordan K. Hubbard 		prog_makefile_rules(outmk, p);
861de566360SJordan K. Hubbard 
862de566360SJordan K. Hubbard 	fprintf(outmk, "\n# ========\n");
863de566360SJordan K. Hubbard 	fclose(outmk);
864de566360SJordan K. Hubbard }
865de566360SJordan K. Hubbard 
866de566360SJordan K. Hubbard 
867de566360SJordan K. Hubbard void gen_output_cfile(void)
868de566360SJordan K. Hubbard {
869de566360SJordan K. Hubbard 	extern char *crunched_skel[];
870de566360SJordan K. Hubbard 	char **cp;
871de566360SJordan K. Hubbard 	FILE *outcf;
872de566360SJordan K. Hubbard 	prog_t *p;
873de566360SJordan K. Hubbard 	strlst_t *s;
874019d04d1SLuigi Rizzo 	char line[MAXLINELEN];
875de566360SJordan K. Hubbard 
876019d04d1SLuigi Rizzo 	snprintf(line, MAXLINELEN, "generating %s", outcfname);
877de566360SJordan K. Hubbard 	status(line);
878de566360SJordan K. Hubbard 
879de566360SJordan K. Hubbard 	if((outcf = fopen(outcfname, "w")) == NULL) {
880b17e90a9SPhilippe Charnier 		warn("%s", outcfname);
881de566360SJordan K. Hubbard 		goterror = 1;
882de566360SJordan K. Hubbard 		return;
883de566360SJordan K. Hubbard 	}
884de566360SJordan K. Hubbard 
885de566360SJordan K. Hubbard 	fprintf(outcf,
886de566360SJordan K. Hubbard 	    "/* %s - generated from %s by crunchgen %s */\n",
887de566360SJordan K. Hubbard 	    outcfname, infilename, CRUNCH_VERSION);
888de566360SJordan K. Hubbard 
889de566360SJordan K. Hubbard 	fprintf(outcf, "#define EXECNAME \"%s\"\n", execfname);
890de566360SJordan K. Hubbard 	for (cp = crunched_skel; *cp != NULL; cp++)
891de566360SJordan K. Hubbard 		fprintf(outcf, "%s\n", *cp);
892de566360SJordan K. Hubbard 
893de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next)
894de566360SJordan K. Hubbard 		fprintf(outcf, "extern int _crunched_%s_stub();\n", p->ident);
895de566360SJordan K. Hubbard 
896de566360SJordan K. Hubbard 	fprintf(outcf, "\nstruct stub entry_points[] = {\n");
897de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next) {
898de566360SJordan K. Hubbard 		fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n",
899de566360SJordan K. Hubbard 		    p->name, p->ident);
900de566360SJordan K. Hubbard 		for (s = p->links; s != NULL; s = s->next)
901de566360SJordan K. Hubbard 			fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n",
902de566360SJordan K. Hubbard 			    s->str, p->ident);
903de566360SJordan K. Hubbard 	}
904de566360SJordan K. Hubbard 
905de566360SJordan K. Hubbard 	fprintf(outcf, "\t{ EXECNAME, crunched_main },\n");
906de566360SJordan K. Hubbard 	fprintf(outcf, "\t{ NULL, NULL }\n};\n");
907de566360SJordan K. Hubbard 	fclose(outcf);
908de566360SJordan K. Hubbard }
909de566360SJordan K. Hubbard 
910de566360SJordan K. Hubbard 
911de566360SJordan K. Hubbard char *genident(char *str)
912de566360SJordan K. Hubbard {
913de566360SJordan K. Hubbard 	char *n, *s, *d;
914de566360SJordan K. Hubbard 
915de566360SJordan K. Hubbard 	/*
91687eb4a42SJosef Karthauser 	 * generates a Makefile/C identifier from a program name,
91787eb4a42SJosef Karthauser 	 * mapping '-' to '_' and ignoring all other non-identifier
91887eb4a42SJosef Karthauser 	 * characters.  This leads to programs named "foo.bar" and
91987eb4a42SJosef Karthauser 	 * "foobar" to map to the same identifier.
920de566360SJordan K. Hubbard 	 */
921de566360SJordan K. Hubbard 
922de566360SJordan K. Hubbard 	if ((n = strdup(str)) == NULL)
923de566360SJordan K. Hubbard 		return NULL;
924de566360SJordan K. Hubbard 	for (d = s = n; *s != '\0'; s++) {
92587eb4a42SJosef Karthauser 		if (*s == '-')
92687eb4a42SJosef Karthauser 			*d++ = '_';
92787eb4a42SJosef Karthauser 		else if (*s == '_' || isalnum(*s))
92887eb4a42SJosef Karthauser 			*d++ = *s;
929de566360SJordan K. Hubbard 	}
930de566360SJordan K. Hubbard 	*d = '\0';
931de566360SJordan K. Hubbard 	return n;
932de566360SJordan K. Hubbard }
933de566360SJordan K. Hubbard 
934de566360SJordan K. Hubbard 
935de566360SJordan K. Hubbard char *dir_search(char *progname)
936de566360SJordan K. Hubbard {
937de566360SJordan K. Hubbard 	char path[MAXPATHLEN];
938de566360SJordan K. Hubbard 	strlst_t *dir;
939e3b7d178SJosef Karthauser 	char *srcdir;
940de566360SJordan K. Hubbard 
941de566360SJordan K. Hubbard 	for (dir = srcdirs; dir != NULL; dir = dir->next) {
942019d04d1SLuigi Rizzo 		snprintf(path, MAXPATHLEN, "%s/%s", dir->str, progname);
94387eb4a42SJosef Karthauser 		if (!is_dir(path))
944e3b7d178SJosef Karthauser 			continue;
945e3b7d178SJosef Karthauser 
946e3b7d178SJosef Karthauser 		if ((srcdir = strdup(path)) == NULL)
947e3b7d178SJosef Karthauser 			out_of_memory();
94887eb4a42SJosef Karthauser 
949e3b7d178SJosef Karthauser 		return srcdir;
950de566360SJordan K. Hubbard 	}
951de566360SJordan K. Hubbard 	return NULL;
952de566360SJordan K. Hubbard }
953de566360SJordan K. Hubbard 
954de566360SJordan K. Hubbard 
955de566360SJordan K. Hubbard void top_makefile_rules(FILE *outmk)
956de566360SJordan K. Hubbard {
957de566360SJordan K. Hubbard 	prog_t *p;
958de566360SJordan K. Hubbard 
95955f92f64SCeri Davies 	if ( subtract_strlst(&libs, &libs_so) )
96055f92f64SCeri Davies 		fprintf(outmk, "# NOTE: Some LIBS declarations below overridden by LIBS_SO\n");
96155f92f64SCeri Davies 
962d1a97625SJosef Karthauser 	fprintf(outmk, "LIBS+=");
963de566360SJordan K. Hubbard 	output_strlst(outmk, libs);
964de566360SJordan K. Hubbard 
96555f92f64SCeri Davies 	fprintf(outmk, "LIBS_SO+=");
96655f92f64SCeri Davies 	output_strlst(outmk, libs_so);
96755f92f64SCeri Davies 
968843d8d51SJosef Karthauser 	if (makeobj) {
969843d8d51SJosef Karthauser 		fprintf(outmk, "MAKEOBJDIRPREFIX?=%s\n", objprefix);
970a8595b66SHartmut Brandt 		fprintf(outmk, "MAKEENV=env MAKEOBJDIRPREFIX=$(MAKEOBJDIRPREFIX)\n");
971a8595b66SHartmut Brandt 		fprintf(outmk, "CRUNCHMAKE=$(MAKEENV) $(MAKE)\n");
972843d8d51SJosef Karthauser 	} else {
973a8595b66SHartmut Brandt 		fprintf(outmk, "CRUNCHMAKE=$(MAKE)\n");
974843d8d51SJosef Karthauser 	}
975843d8d51SJosef Karthauser 
97608a15190SJosef Karthauser 	if (buildopts) {
97708a15190SJosef Karthauser 		fprintf(outmk, "BUILDOPTS+=");
97808a15190SJosef Karthauser 		output_strlst(outmk, buildopts);
97908a15190SJosef Karthauser 	}
98008a15190SJosef Karthauser 
981de566360SJordan K. Hubbard 	fprintf(outmk, "CRUNCHED_OBJS=");
982de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next)
983de566360SJordan K. Hubbard 		fprintf(outmk, " %s.lo", p->name);
984de566360SJordan K. Hubbard 	fprintf(outmk, "\n");
985de566360SJordan K. Hubbard 
986de566360SJordan K. Hubbard 	fprintf(outmk, "SUBMAKE_TARGETS=");
987de566360SJordan K. Hubbard 	for (p = progs; p != NULL; p = p->next)
988de566360SJordan K. Hubbard 		fprintf(outmk, " %s_make", p->ident);
989ced716c3SBrian Somers 	fprintf(outmk, "\nSUBCLEAN_TARGETS=");
990ced716c3SBrian Somers 	for (p = progs; p != NULL; p = p->next)
991ced716c3SBrian Somers 		fprintf(outmk, " %s_clean", p->ident);
992de566360SJordan K. Hubbard 	fprintf(outmk, "\n\n");
993de566360SJordan K. Hubbard 
994843d8d51SJosef Karthauser 	fprintf(outmk, "all: objs exe\nobjs: $(SUBMAKE_TARGETS)\n");
995843d8d51SJosef Karthauser 	fprintf(outmk, "exe: %s\n", execfname);
996e8a1d46eSJohn Birrell 	fprintf(outmk, "%s: %s.o $(CRUNCHED_OBJS) $(SUBMAKE_TARGETS)\n", execfname, execfname);
99755f92f64SCeri Davies 	fprintf(outmk, ".if defined(LIBS_SO) && !empty(LIBS_SO)\n");
99855f92f64SCeri Davies 	fprintf(outmk, "\t$(CC) -o %s %s.o $(CRUNCHED_OBJS) \\\n",
99955f92f64SCeri Davies 	    execfname, execfname);
100055f92f64SCeri Davies 	fprintf(outmk, "\t\t-Xlinker -Bstatic $(LIBS) \\\n");
100155f92f64SCeri Davies 	fprintf(outmk, "\t\t-Xlinker -Bdynamic $(LIBS_SO)\n");
100255f92f64SCeri Davies 	fprintf(outmk, ".else\n");
1003de566360SJordan K. Hubbard 	fprintf(outmk, "\t$(CC) -static -o %s %s.o $(CRUNCHED_OBJS) $(LIBS)\n",
1004de566360SJordan K. Hubbard 	    execfname, execfname);
100555f92f64SCeri Davies 	fprintf(outmk, ".endif\n");
1006de566360SJordan K. Hubbard 	fprintf(outmk, "\tstrip %s\n", execfname);
1007ced716c3SBrian Somers 	fprintf(outmk, "realclean: clean subclean\n");
100887eb4a42SJosef Karthauser 	fprintf(outmk, "clean:\n\trm -f %s *.lo *.o *_stub.c\n", execfname);
1009ced716c3SBrian Somers 	fprintf(outmk, "subclean: $(SUBCLEAN_TARGETS)\n");
1010de566360SJordan K. Hubbard }
1011de566360SJordan K. Hubbard 
1012de566360SJordan K. Hubbard 
1013de566360SJordan K. Hubbard void prog_makefile_rules(FILE *outmk, prog_t *p)
1014de566360SJordan K. Hubbard {
101542ac3bf1SJoerg Wunsch 	strlst_t *lst;
101642ac3bf1SJoerg Wunsch 
1017de566360SJordan K. Hubbard 	fprintf(outmk, "\n# -------- %s\n\n", p->name);
1018de566360SJordan K. Hubbard 
1019843d8d51SJosef Karthauser 	fprintf(outmk, "%s_OBJDIR=", p->ident);
1020843d8d51SJosef Karthauser 	if (p->objdir)
1021843d8d51SJosef Karthauser 		fprintf(outmk, "%s", p->objdir);
1022843d8d51SJosef Karthauser 	else
1023843d8d51SJosef Karthauser 		fprintf(outmk, "$(MAKEOBJDIRPREFIX)/$(%s_REALSRCDIR)\n",
1024843d8d51SJosef Karthauser 		    p->ident);
1025843d8d51SJosef Karthauser 	fprintf(outmk, "\n");
1026843d8d51SJosef Karthauser 
102780f498e5SJohn Birrell 	fprintf(outmk, "%s_OBJPATHS=", p->ident);
102880f498e5SJohn Birrell 	if (p->objpaths)
102980f498e5SJohn Birrell 		output_strlst(outmk, p->objpaths);
103080f498e5SJohn Birrell 	else {
103180f498e5SJohn Birrell 		for (lst = p->objs; lst != NULL; lst = lst->next) {
103280f498e5SJohn Birrell 			fprintf(outmk, " $(%s_OBJDIR)/%s", p->ident, lst->str);
103380f498e5SJohn Birrell 		}
103480f498e5SJohn Birrell 		fprintf(outmk, "\n");
103580f498e5SJohn Birrell 	}
103680f498e5SJohn Birrell 
103711384533SJosef Karthauser 	if (p->srcdir && p->objs) {
103811384533SJosef Karthauser 		fprintf(outmk, "%s_SRCDIR=%s\n", p->ident, p->srcdir);
103911384533SJosef Karthauser 		fprintf(outmk, "%s_REALSRCDIR=%s\n", p->ident, p->realsrcdir);
104011384533SJosef Karthauser 
1041de566360SJordan K. Hubbard 		fprintf(outmk, "%s_OBJS=", p->ident);
1042de566360SJordan K. Hubbard 		output_strlst(outmk, p->objs);
104334944d48SJosef Karthauser 		if (p->buildopts != NULL) {
104434944d48SJosef Karthauser 			fprintf(outmk, "%s_OPTS+=", p->ident);
104534944d48SJosef Karthauser 			output_strlst(outmk, p->buildopts);
104634944d48SJosef Karthauser 		}
104751d9ddc6SJohn Birrell #if 0
104880f498e5SJohn Birrell 		fprintf(outmk, "$(%s_OBJPATHS): %s_make\n\n", p->ident, p->ident);
104951d9ddc6SJohn Birrell #endif
1050de566360SJordan K. Hubbard 		fprintf(outmk, "%s_make:\n", p->ident);
1051ba2250ddSJosef Karthauser 		fprintf(outmk, "\t(cd $(%s_SRCDIR) && ", p->ident);
1052ba2250ddSJosef Karthauser 		if (makeobj)
1053a8595b66SHartmut Brandt 			fprintf(outmk, "$(CRUNCHMAKE) obj && ");
1054ba2250ddSJosef Karthauser 		fprintf(outmk, "\\\n");
1055a8595b66SHartmut Brandt 		fprintf(outmk, "\t\t$(CRUNCHMAKE) $(BUILDOPTS) $(%s_OPTS) depend &&",
105687eb4a42SJosef Karthauser 		    p->ident);
105787eb4a42SJosef Karthauser 		fprintf(outmk, "\\\n");
1058a8595b66SHartmut Brandt 		fprintf(outmk, "\t\t$(CRUNCHMAKE) $(BUILDOPTS) $(%s_OPTS) "
105987eb4a42SJosef Karthauser 		    "$(%s_OBJS))",
106087eb4a42SJosef Karthauser 		    p->ident, p->ident);
106187eb4a42SJosef Karthauser 		fprintf(outmk, "\n");
1062ced716c3SBrian Somers 		fprintf(outmk, "%s_clean:\n", p->ident);
1063a8595b66SHartmut Brandt 		fprintf(outmk, "\t(cd $(%s_SRCDIR) && $(CRUNCHMAKE) $(BUILDOPTS) clean cleandepend)\n\n",
106487eb4a42SJosef Karthauser 		    p->ident);
106587eb4a42SJosef Karthauser 	} else {
106687eb4a42SJosef Karthauser 		fprintf(outmk, "%s_make:\n", p->ident);
106787eb4a42SJosef Karthauser 		fprintf(outmk, "\t@echo \"** cannot make objs for %s\"\n\n",
1068a0bac7e0SRuslan Ermilov 		    p->name);
106987eb4a42SJosef Karthauser 	}
1070de566360SJordan K. Hubbard 
1071252f13abSLuigi Rizzo 	if (p->libs) {
1072252f13abSLuigi Rizzo 		fprintf(outmk, "%s_LIBS=", p->ident);
1073252f13abSLuigi Rizzo 		output_strlst(outmk, p->libs);
1074252f13abSLuigi Rizzo 	}
1075de566360SJordan K. Hubbard 
1076de566360SJordan K. Hubbard 	fprintf(outmk, "%s_stub.c:\n", p->name);
1077de566360SJordan K. Hubbard 	fprintf(outmk, "\techo \""
1078de566360SJordan K. Hubbard 	    "int _crunched_%s_stub(int argc, char **argv, char **envp)"
1079de566360SJordan K. Hubbard 	    "{return main(argc,argv,envp);}\" >%s_stub.c\n",
1080de566360SJordan K. Hubbard 	    p->ident, p->name);
1081252f13abSLuigi Rizzo 	fprintf(outmk, "%s.lo: %s_stub.o $(%s_OBJPATHS)",
1082de566360SJordan K. Hubbard 	    p->name, p->name, p->ident);
1083252f13abSLuigi Rizzo 	if (p->libs)
1084252f13abSLuigi Rizzo 		fprintf(outmk, " $(%s_LIBS)", p->ident);
108555f92f64SCeri Davies 
1086252f13abSLuigi Rizzo 	fprintf(outmk, "\n");
1087252f13abSLuigi Rizzo 	fprintf(outmk, "\tld -dc -r -o %s.lo %s_stub.o $(%s_OBJPATHS)",
1088de566360SJordan K. Hubbard 	    p->name, p->name, p->ident);
1089252f13abSLuigi Rizzo 	if (p->libs)
1090252f13abSLuigi Rizzo 		fprintf(outmk, " $(%s_LIBS)", p->ident);
1091252f13abSLuigi Rizzo 	fprintf(outmk, "\n");
10926cd35234SJordan K. Hubbard 	fprintf(outmk, "\tcrunchide -k _crunched_%s_stub ", p->ident);
109342ac3bf1SJoerg Wunsch 	for (lst = p->keeplist; lst != NULL; lst = lst->next)
109442ac3bf1SJoerg Wunsch 		fprintf(outmk, "-k _%s ", lst->str);
109542ac3bf1SJoerg Wunsch 	fprintf(outmk, "%s.lo\n", p->name);
1096de566360SJordan K. Hubbard }
1097de566360SJordan K. Hubbard 
1098de566360SJordan K. Hubbard void output_strlst(FILE *outf, strlst_t *lst)
1099de566360SJordan K. Hubbard {
1100de566360SJordan K. Hubbard 	for (; lst != NULL; lst = lst->next)
110155f92f64SCeri Davies 		if ( strlen(lst->str) )
1102de566360SJordan K. Hubbard 			fprintf(outf, " %s", lst->str);
1103de566360SJordan K. Hubbard 	fprintf(outf, "\n");
1104de566360SJordan K. Hubbard }
1105de566360SJordan K. Hubbard 
1106de566360SJordan K. Hubbard 
1107de566360SJordan K. Hubbard /*
1108de566360SJordan K. Hubbard  * ========================================================================
1109de566360SJordan K. Hubbard  * general library routines
1110de566360SJordan K. Hubbard  *
1111de566360SJordan K. Hubbard  */
1112de566360SJordan K. Hubbard 
1113de566360SJordan K. Hubbard void status(char *str)
1114de566360SJordan K. Hubbard {
1115de566360SJordan K. Hubbard 	static int lastlen = 0;
1116de566360SJordan K. Hubbard 	int len, spaces;
1117de566360SJordan K. Hubbard 
111887eb4a42SJosef Karthauser 	if (!verbose)
111987eb4a42SJosef Karthauser 		return;
1120de566360SJordan K. Hubbard 
1121de566360SJordan K. Hubbard 	len = strlen(str);
1122de566360SJordan K. Hubbard 	spaces = lastlen - len;
112387eb4a42SJosef Karthauser 	if (spaces < 1)
112487eb4a42SJosef Karthauser 		spaces = 1;
1125de566360SJordan K. Hubbard 
1126de566360SJordan K. Hubbard 	fprintf(stderr, " [%s]%*.*s\r", str, spaces, spaces, " ");
1127de566360SJordan K. Hubbard 	fflush(stderr);
1128de566360SJordan K. Hubbard 	lastlen = len;
1129de566360SJordan K. Hubbard }
1130de566360SJordan K. Hubbard 
1131de566360SJordan K. Hubbard 
1132de566360SJordan K. Hubbard void out_of_memory(void)
1133de566360SJordan K. Hubbard {
1134f3c47f54SJosef Karthauser 	err(1, "%s: %d: out of memory, stopping", infilename, linenum);
1135de566360SJordan K. Hubbard }
1136de566360SJordan K. Hubbard 
1137de566360SJordan K. Hubbard 
1138de566360SJordan K. Hubbard void add_string(strlst_t **listp, char *str)
1139de566360SJordan K. Hubbard {
1140de566360SJordan K. Hubbard 	strlst_t *p1, *p2;
1141de566360SJordan K. Hubbard 
1142de566360SJordan K. Hubbard 	/* add to end, but be smart about dups */
1143de566360SJordan K. Hubbard 
1144de566360SJordan K. Hubbard 	for (p1 = NULL, p2 = *listp; p2 != NULL; p1 = p2, p2 = p2->next)
114587eb4a42SJosef Karthauser 		if (!strcmp(p2->str, str))
114687eb4a42SJosef Karthauser 			return;
1147de566360SJordan K. Hubbard 
1148de566360SJordan K. Hubbard 	p2 = malloc(sizeof(strlst_t));
1149eb148815SJoerg Wunsch 	if (p2) {
1150019d04d1SLuigi Rizzo 		p2->next = NULL;
1151eb148815SJoerg Wunsch 		p2->str = strdup(str);
1152eb148815SJoerg Wunsch     	}
1153de566360SJordan K. Hubbard 	if (!p2 || !p2->str)
1154de566360SJordan K. Hubbard 		out_of_memory();
1155de566360SJordan K. Hubbard 
115687eb4a42SJosef Karthauser 	if (p1 == NULL)
115787eb4a42SJosef Karthauser 		*listp = p2;
115887eb4a42SJosef Karthauser 	else
115987eb4a42SJosef Karthauser 		p1->next = p2;
1160de566360SJordan K. Hubbard }
1161de566360SJordan K. Hubbard 
116255f92f64SCeri Davies int subtract_strlst(strlst_t **lista, strlst_t **listb)
116355f92f64SCeri Davies {
116455f92f64SCeri Davies 	int subtract_count = 0;
116555f92f64SCeri Davies 	strlst_t *p1;
116655f92f64SCeri Davies 	for (p1 = *listb; p1 != NULL; p1 = p1->next)
116755f92f64SCeri Davies 		if ( in_list(lista, p1->str) ) {
116855f92f64SCeri Davies 			warnx("Will compile library `%s' dynamically", p1->str);
116955f92f64SCeri Davies 			strcat(p1->str, "");
117055f92f64SCeri Davies 			subtract_count++;
117155f92f64SCeri Davies 		}
117255f92f64SCeri Davies 	return subtract_count;
117355f92f64SCeri Davies }
117455f92f64SCeri Davies 
117555f92f64SCeri Davies int in_list(strlst_t **listp, char *str)
117655f92f64SCeri Davies {
117755f92f64SCeri Davies 	strlst_t *p1;
117855f92f64SCeri Davies 	for (p1 = *listp; p1 != NULL; p1 = p1->next)
117955f92f64SCeri Davies 		if (!strcmp(p1->str, str))
118055f92f64SCeri Davies 			return 1;
118155f92f64SCeri Davies 	return 0;
118255f92f64SCeri Davies }
1183de566360SJordan K. Hubbard 
1184de566360SJordan K. Hubbard int is_dir(char *pathname)
1185de566360SJordan K. Hubbard {
1186de566360SJordan K. Hubbard 	struct stat buf;
1187de566360SJordan K. Hubbard 
1188de566360SJordan K. Hubbard 	if (stat(pathname, &buf) == -1)
1189de566360SJordan K. Hubbard 		return 0;
119087eb4a42SJosef Karthauser 
1191de566360SJordan K. Hubbard 	return S_ISDIR(buf.st_mode);
1192de566360SJordan K. Hubbard }
1193de566360SJordan K. Hubbard 
1194de566360SJordan K. Hubbard int is_nonempty_file(char *pathname)
1195de566360SJordan K. Hubbard {
1196de566360SJordan K. Hubbard 	struct stat buf;
1197de566360SJordan K. Hubbard 
1198de566360SJordan K. Hubbard 	if (stat(pathname, &buf) == -1)
1199de566360SJordan K. Hubbard 		return 0;
1200de566360SJordan K. Hubbard 
1201de566360SJordan K. Hubbard 	return S_ISREG(buf.st_mode) && buf.st_size > 0;
1202de566360SJordan K. Hubbard }
1203