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 */ 35de566360SJordan K. Hubbard #include <ctype.h> 36b17e90a9SPhilippe Charnier #include <err.h> 37b17e90a9SPhilippe Charnier #include <stdio.h> 38b17e90a9SPhilippe Charnier #include <stdlib.h> 39de566360SJordan K. Hubbard #include <string.h> 40b17e90a9SPhilippe Charnier #include <unistd.h> 41de566360SJordan K. Hubbard 42de566360SJordan K. Hubbard #include <sys/types.h> 43de566360SJordan K. Hubbard #include <sys/stat.h> 44de566360SJordan K. Hubbard #include <sys/param.h> 45de566360SJordan K. Hubbard 46de566360SJordan K. Hubbard #define CRUNCH_VERSION "0.2" 47de566360SJordan K. Hubbard 48de566360SJordan K. Hubbard #define MAXLINELEN 16384 49de566360SJordan K. Hubbard #define MAXFIELDS 2048 50de566360SJordan K. Hubbard 51de566360SJordan K. Hubbard 52de566360SJordan K. Hubbard /* internal representation of conf file: */ 53de566360SJordan K. Hubbard 54de566360SJordan K. Hubbard /* simple lists of strings suffice for most parms */ 55de566360SJordan K. Hubbard 56de566360SJordan K. Hubbard typedef struct strlst { 57de566360SJordan K. Hubbard struct strlst *next; 58de566360SJordan K. Hubbard char *str; 59de566360SJordan K. Hubbard } strlst_t; 60de566360SJordan K. Hubbard 61de566360SJordan K. Hubbard /* progs have structure, each field can be set with "special" or calculated */ 62de566360SJordan K. Hubbard 63de566360SJordan K. Hubbard typedef struct prog { 6408826cadSLuigi Rizzo struct prog *next; /* link field */ 6508826cadSLuigi Rizzo char *name; /* program name */ 6608826cadSLuigi Rizzo char *ident; /* C identifier for the program name */ 6708826cadSLuigi Rizzo char *srcdir; 6808826cadSLuigi Rizzo char *objdir; 6908826cadSLuigi Rizzo char *objvar; /* Makefile variable to replace OBJS */ 70de566360SJordan K. Hubbard strlst_t *objs, *objpaths; 7142ac3bf1SJoerg Wunsch strlst_t *keeplist; 72de566360SJordan K. Hubbard strlst_t *links; 73de566360SJordan K. Hubbard int goterror; 74de566360SJordan K. Hubbard } prog_t; 75de566360SJordan K. Hubbard 76de566360SJordan K. Hubbard 77de566360SJordan K. Hubbard /* global state */ 78de566360SJordan K. Hubbard 79de566360SJordan K. Hubbard strlst_t *srcdirs = NULL; 80de566360SJordan K. Hubbard strlst_t *libs = NULL; 81de566360SJordan K. Hubbard prog_t *progs = NULL; 82de566360SJordan K. Hubbard 83de566360SJordan K. Hubbard char line[MAXLINELEN]; 84de566360SJordan K. Hubbard 85de566360SJordan K. Hubbard char confname[MAXPATHLEN], infilename[MAXPATHLEN]; 86de566360SJordan K. Hubbard char outmkname[MAXPATHLEN], outcfname[MAXPATHLEN], execfname[MAXPATHLEN]; 87de566360SJordan K. Hubbard char tempfname[MAXPATHLEN], cachename[MAXPATHLEN], curfilename[MAXPATHLEN]; 8808826cadSLuigi Rizzo char outhdrname[MAXPATHLEN] ; /* user-supplied header for *.mk */ 89de566360SJordan K. Hubbard int linenum = -1; 90de566360SJordan K. Hubbard int goterror = 0; 91de566360SJordan K. Hubbard 92de566360SJordan K. Hubbard int verbose, readcache; /* options */ 93de566360SJordan K. Hubbard int reading_cache; 94de566360SJordan K. Hubbard 95fb7f926eSPoul-Henning Kamp int list_mode; 96fb7f926eSPoul-Henning Kamp 97de566360SJordan K. Hubbard /* general library routines */ 98de566360SJordan K. Hubbard 99de566360SJordan K. Hubbard void status(char *str); 100de566360SJordan K. Hubbard void out_of_memory(void); 101de566360SJordan K. Hubbard void add_string(strlst_t **listp, char *str); 102de566360SJordan K. Hubbard int is_dir(char *pathname); 103de566360SJordan K. Hubbard int is_nonempty_file(char *pathname); 104de566360SJordan K. Hubbard 105de566360SJordan K. Hubbard /* helper routines for main() */ 106de566360SJordan K. Hubbard 107de566360SJordan K. Hubbard void usage(void); 108de566360SJordan K. Hubbard void parse_conf_file(void); 109de566360SJordan K. Hubbard void gen_outputs(void); 110de566360SJordan K. Hubbard 111de566360SJordan K. Hubbard 112de566360SJordan K. Hubbard int main(int argc, char **argv) 113de566360SJordan K. Hubbard { 114de566360SJordan K. Hubbard char *p; 115de566360SJordan K. Hubbard int optc; 116de566360SJordan K. Hubbard 117de566360SJordan K. Hubbard verbose = 1; 118de566360SJordan K. Hubbard readcache = 1; 119de566360SJordan K. Hubbard *outmkname = *outcfname = *execfname = '\0'; 120de566360SJordan K. Hubbard 12108826cadSLuigi Rizzo while((optc = getopt(argc, argv, "lh:m:c:e:fq")) != -1) { 122de566360SJordan K. Hubbard switch(optc) { 123de566360SJordan K. Hubbard case 'f': readcache = 0; break; 124de566360SJordan K. Hubbard case 'q': verbose = 0; break; 125de566360SJordan K. Hubbard 126de566360SJordan K. Hubbard case 'm': strcpy(outmkname, optarg); break; 12708826cadSLuigi Rizzo case 'h': strcpy(outhdrname, optarg); break; 128de566360SJordan K. Hubbard case 'c': strcpy(outcfname, optarg); break; 129de566360SJordan K. Hubbard case 'e': strcpy(execfname, optarg); break; 130fb7f926eSPoul-Henning Kamp case 'l': list_mode++; verbose = 0; break; 131de566360SJordan K. Hubbard 132de566360SJordan K. Hubbard case '?': 133de566360SJordan K. Hubbard default: usage(); 134de566360SJordan K. Hubbard } 135de566360SJordan K. Hubbard } 136de566360SJordan K. Hubbard 137de566360SJordan K. Hubbard argc -= optind; 138de566360SJordan K. Hubbard argv += optind; 139de566360SJordan K. Hubbard 140de566360SJordan K. Hubbard if(argc != 1) usage(); 141de566360SJordan K. Hubbard 142de566360SJordan K. Hubbard /* 143de566360SJordan K. Hubbard * generate filenames 144de566360SJordan K. Hubbard */ 145de566360SJordan K. Hubbard 146de566360SJordan K. Hubbard strcpy(infilename, argv[0]); 147de566360SJordan K. Hubbard 148de566360SJordan K. Hubbard /* confname = `basename infilename .conf` */ 149de566360SJordan K. Hubbard 150de566360SJordan K. Hubbard if((p=strrchr(infilename, '/')) != NULL) strcpy(confname, p+1); 151de566360SJordan K. Hubbard else strcpy(confname, infilename); 152de566360SJordan K. Hubbard if((p=strrchr(confname, '.')) != NULL && !strcmp(p, ".conf")) *p = '\0'; 153de566360SJordan K. Hubbard 154de566360SJordan K. Hubbard if(!*outmkname) sprintf(outmkname, "%s.mk", confname); 155de566360SJordan K. Hubbard if(!*outcfname) sprintf(outcfname, "%s.c", confname); 156de566360SJordan K. Hubbard if(!*execfname) sprintf(execfname, "%s", confname); 157de566360SJordan K. Hubbard 158de566360SJordan K. Hubbard sprintf(cachename, "%s.cache", confname); 159de566360SJordan K. Hubbard sprintf(tempfname, ".tmp_%sXXXXXX", confname); 160de566360SJordan K. Hubbard if(mktemp(tempfname) == NULL) { 161de566360SJordan K. Hubbard perror(tempfname); 162de566360SJordan K. Hubbard exit(1); 163de566360SJordan K. Hubbard } 164de566360SJordan K. Hubbard 165de566360SJordan K. Hubbard parse_conf_file(); 166fb7f926eSPoul-Henning Kamp if (list_mode) 167fb7f926eSPoul-Henning Kamp exit(goterror); 168fb7f926eSPoul-Henning Kamp 169de566360SJordan K. Hubbard gen_outputs(); 170de566360SJordan K. Hubbard 171de566360SJordan K. Hubbard exit(goterror); 172de566360SJordan K. Hubbard } 173de566360SJordan K. Hubbard 174de566360SJordan K. Hubbard 175de566360SJordan K. Hubbard void usage(void) 176de566360SJordan K. Hubbard { 177b17e90a9SPhilippe Charnier fprintf(stderr, "%s\n%s\n", 178b17e90a9SPhilippe Charnier "usage: crunchgen [-fq] [-m <makefile>] [-c <c file>]", 179b17e90a9SPhilippe Charnier " [-e <exec file>] <conffile>"); 180de566360SJordan K. Hubbard exit(1); 181de566360SJordan K. Hubbard } 182de566360SJordan K. Hubbard 183de566360SJordan K. Hubbard 184de566360SJordan K. Hubbard /* 185de566360SJordan K. Hubbard * ======================================================================== 186de566360SJordan K. Hubbard * parse_conf_file subsystem 187de566360SJordan K. Hubbard * 188de566360SJordan K. Hubbard */ 189de566360SJordan K. Hubbard 190de566360SJordan K. Hubbard /* helper routines for parse_conf_file */ 191de566360SJordan K. Hubbard 192de566360SJordan K. Hubbard void parse_one_file(char *filename); 193de566360SJordan K. Hubbard void parse_line(char *line, int *fc, char **fv, int nf); 194de566360SJordan K. Hubbard void add_srcdirs(int argc, char **argv); 195de566360SJordan K. Hubbard void add_progs(int argc, char **argv); 196de566360SJordan K. Hubbard void add_link(int argc, char **argv); 197de566360SJordan K. Hubbard void add_libs(int argc, char **argv); 198de566360SJordan K. Hubbard void add_special(int argc, char **argv); 199de566360SJordan K. Hubbard 200de566360SJordan K. Hubbard prog_t *find_prog(char *str); 201de566360SJordan K. Hubbard void add_prog(char *progname); 202de566360SJordan K. Hubbard 203de566360SJordan K. Hubbard 204de566360SJordan K. Hubbard void parse_conf_file(void) 205de566360SJordan K. Hubbard { 206b17e90a9SPhilippe Charnier if(!is_nonempty_file(infilename)) 207b17e90a9SPhilippe Charnier errx(1, "fatal: input file \"%s\" not found", infilename); 208de566360SJordan K. Hubbard parse_one_file(infilename); 209de566360SJordan K. Hubbard if(readcache && is_nonempty_file(cachename)) { 210de566360SJordan K. Hubbard reading_cache = 1; 211de566360SJordan K. Hubbard parse_one_file(cachename); 212de566360SJordan K. Hubbard } 213de566360SJordan K. Hubbard } 214de566360SJordan K. Hubbard 215de566360SJordan K. Hubbard 216de566360SJordan K. Hubbard void parse_one_file(char *filename) 217de566360SJordan K. Hubbard { 218de566360SJordan K. Hubbard char *fieldv[MAXFIELDS]; 219de566360SJordan K. Hubbard int fieldc; 220de566360SJordan K. Hubbard void (*f)(int c, char **v); 221de566360SJordan K. Hubbard FILE *cf; 222de566360SJordan K. Hubbard 223de566360SJordan K. Hubbard sprintf(line, "reading %s", filename); 224de566360SJordan K. Hubbard status(line); 225de566360SJordan K. Hubbard strcpy(curfilename, filename); 226de566360SJordan K. Hubbard 227de566360SJordan K. Hubbard if((cf = fopen(curfilename, "r")) == NULL) { 228b17e90a9SPhilippe Charnier warn("%s", curfilename); 229de566360SJordan K. Hubbard goterror = 1; 230de566360SJordan K. Hubbard return; 231de566360SJordan K. Hubbard } 232de566360SJordan K. Hubbard 233de566360SJordan K. Hubbard linenum = 0; 234de566360SJordan K. Hubbard while(fgets(line, MAXLINELEN, cf) != NULL) { 235de566360SJordan K. Hubbard linenum++; 236de566360SJordan K. Hubbard parse_line(line, &fieldc, fieldv, MAXFIELDS); 237de566360SJordan K. Hubbard if(fieldc < 1) continue; 238de566360SJordan K. Hubbard if(!strcmp(fieldv[0], "srcdirs")) f = add_srcdirs; 239de566360SJordan K. Hubbard else if(!strcmp(fieldv[0], "progs")) f = add_progs; 240de566360SJordan K. Hubbard else if(!strcmp(fieldv[0], "ln")) f = add_link; 241de566360SJordan K. Hubbard else if(!strcmp(fieldv[0], "libs")) f = add_libs; 242de566360SJordan K. Hubbard else if(!strcmp(fieldv[0], "special")) f = add_special; 243de566360SJordan K. Hubbard else { 244b17e90a9SPhilippe Charnier warnx("%s:%d: skipping unknown command `%s'", 245de566360SJordan K. Hubbard curfilename, linenum, fieldv[0]); 246de566360SJordan K. Hubbard goterror = 1; 247de566360SJordan K. Hubbard continue; 248de566360SJordan K. Hubbard } 249de566360SJordan K. Hubbard if(fieldc < 2) { 250b17e90a9SPhilippe Charnier warnx("%s:%d: %s command needs at least 1 argument, skipping", 251de566360SJordan K. Hubbard curfilename, linenum, fieldv[0]); 252de566360SJordan K. Hubbard goterror = 1; 253de566360SJordan K. Hubbard continue; 254de566360SJordan K. Hubbard } 255de566360SJordan K. Hubbard f(fieldc, fieldv); 256de566360SJordan K. Hubbard } 257de566360SJordan K. Hubbard 258de566360SJordan K. Hubbard if(ferror(cf)) { 259b17e90a9SPhilippe Charnier warn("%s", curfilename); 260de566360SJordan K. Hubbard goterror = 1; 261de566360SJordan K. Hubbard } 262de566360SJordan K. Hubbard fclose(cf); 263de566360SJordan K. Hubbard } 264de566360SJordan K. Hubbard 265de566360SJordan K. Hubbard 266de566360SJordan K. Hubbard void parse_line(char *line, int *fc, char **fv, int nf) 267de566360SJordan K. Hubbard { 268de566360SJordan K. Hubbard char *p; 269de566360SJordan K. Hubbard 270de566360SJordan K. Hubbard p = line; 271de566360SJordan K. Hubbard *fc = 0; 272de566360SJordan K. Hubbard while(1) { 273de566360SJordan K. Hubbard while(isspace(*p)) p++; 274de566360SJordan K. Hubbard if(*p == '\0' || *p == '#') break; 275de566360SJordan K. Hubbard 276de566360SJordan K. Hubbard if(*fc < nf) fv[(*fc)++] = p; 277de566360SJordan K. Hubbard while(*p && !isspace(*p) && *p != '#') p++; 278de566360SJordan K. Hubbard if(*p == '\0' || *p == '#') break; 279de566360SJordan K. Hubbard *p++ = '\0'; 280de566360SJordan K. Hubbard } 281de566360SJordan K. Hubbard if(*p) *p = '\0'; /* needed for '#' case */ 282de566360SJordan K. Hubbard } 283de566360SJordan K. Hubbard 284de566360SJordan K. Hubbard 285de566360SJordan K. Hubbard void add_srcdirs(int argc, char **argv) 286de566360SJordan K. Hubbard { 287de566360SJordan K. Hubbard int i; 288de566360SJordan K. Hubbard 289de566360SJordan K. Hubbard for(i=1;i<argc;i++) { 290de566360SJordan K. Hubbard if(is_dir(argv[i])) 291de566360SJordan K. Hubbard add_string(&srcdirs, argv[i]); 292de566360SJordan K. Hubbard else { 293b17e90a9SPhilippe Charnier warnx("%s:%d: `%s' is not a directory, skipping it", 294de566360SJordan K. Hubbard curfilename, linenum, argv[i]); 295de566360SJordan K. Hubbard goterror = 1; 296de566360SJordan K. Hubbard } 297de566360SJordan K. Hubbard } 298de566360SJordan K. Hubbard } 299de566360SJordan K. Hubbard 300de566360SJordan K. Hubbard 301de566360SJordan K. Hubbard void add_progs(int argc, char **argv) 302de566360SJordan K. Hubbard { 303de566360SJordan K. Hubbard int i; 304de566360SJordan K. Hubbard 305de566360SJordan K. Hubbard for(i=1;i<argc;i++) 306de566360SJordan K. Hubbard add_prog(argv[i]); 307de566360SJordan K. Hubbard } 308de566360SJordan K. Hubbard 309de566360SJordan K. Hubbard 310de566360SJordan K. Hubbard void add_prog(char *progname) 311de566360SJordan K. Hubbard { 312de566360SJordan K. Hubbard prog_t *p1, *p2; 313de566360SJordan K. Hubbard 314de566360SJordan K. Hubbard /* add to end, but be smart about dups */ 315de566360SJordan K. Hubbard 316de566360SJordan K. Hubbard for(p1 = NULL, p2 = progs; p2 != NULL; p1 = p2, p2 = p2->next) 317de566360SJordan K. Hubbard if(!strcmp(p2->name, progname)) return; 318de566360SJordan K. Hubbard 319de566360SJordan K. Hubbard p2 = malloc(sizeof(prog_t)); 320eb148815SJoerg Wunsch if(p2) { 321eb148815SJoerg Wunsch memset(p2, 0, sizeof(prog_t)); 322eb148815SJoerg Wunsch p2->name = strdup(progname); 323eb148815SJoerg Wunsch } 324de566360SJordan K. Hubbard if(!p2 || !p2->name) 325de566360SJordan K. Hubbard out_of_memory(); 326de566360SJordan K. Hubbard 327de566360SJordan K. Hubbard p2->next = NULL; 328de566360SJordan K. Hubbard if(p1 == NULL) progs = p2; 329de566360SJordan K. Hubbard else p1->next = p2; 330de566360SJordan K. Hubbard 331de566360SJordan K. Hubbard p2->ident = p2->srcdir = p2->objdir = NULL; 33242ac3bf1SJoerg Wunsch p2->links = p2->objs = p2->keeplist = NULL; 333de566360SJordan K. Hubbard p2->goterror = 0; 334fb7f926eSPoul-Henning Kamp if (list_mode) 335fb7f926eSPoul-Henning Kamp printf("%s\n",progname); 336de566360SJordan K. Hubbard } 337de566360SJordan K. Hubbard 338de566360SJordan K. Hubbard 339de566360SJordan K. Hubbard void add_link(int argc, char **argv) 340de566360SJordan K. Hubbard { 341de566360SJordan K. Hubbard int i; 342de566360SJordan K. Hubbard prog_t *p = find_prog(argv[1]); 343de566360SJordan K. Hubbard 344de566360SJordan K. Hubbard if(p == NULL) { 345b17e90a9SPhilippe Charnier warnx("%s:%d: no prog %s previously declared, skipping link", 346de566360SJordan K. Hubbard curfilename, linenum, argv[1]); 347de566360SJordan K. Hubbard goterror = 1; 348de566360SJordan K. Hubbard return; 349de566360SJordan K. Hubbard } 350fb7f926eSPoul-Henning Kamp for(i=2;i<argc;i++) { 351fb7f926eSPoul-Henning Kamp if (list_mode) 352fb7f926eSPoul-Henning Kamp printf("%s\n",argv[i]); 353de566360SJordan K. Hubbard add_string(&p->links, argv[i]); 354de566360SJordan K. Hubbard } 355fb7f926eSPoul-Henning Kamp } 356de566360SJordan K. Hubbard 357de566360SJordan K. Hubbard 358de566360SJordan K. Hubbard void add_libs(int argc, char **argv) 359de566360SJordan K. Hubbard { 360de566360SJordan K. Hubbard int i; 361de566360SJordan K. Hubbard 362de566360SJordan K. Hubbard for(i=1;i<argc;i++) 363de566360SJordan K. Hubbard add_string(&libs, argv[i]); 364de566360SJordan K. Hubbard } 365de566360SJordan K. Hubbard 366de566360SJordan K. Hubbard 367de566360SJordan K. Hubbard void add_special(int argc, char **argv) 368de566360SJordan K. Hubbard { 369de566360SJordan K. Hubbard int i; 370de566360SJordan K. Hubbard prog_t *p = find_prog(argv[1]); 371de566360SJordan K. Hubbard 372de566360SJordan K. Hubbard if(p == NULL) { 373de566360SJordan K. Hubbard if(reading_cache) return; 374b17e90a9SPhilippe Charnier warnx("%s:%d: no prog %s previously declared, skipping special", 375de566360SJordan K. Hubbard curfilename, linenum, argv[1]); 376de566360SJordan K. Hubbard goterror = 1; 377de566360SJordan K. Hubbard return; 378de566360SJordan K. Hubbard } 379de566360SJordan K. Hubbard 380de566360SJordan K. Hubbard if(!strcmp(argv[2], "ident")) { 381de566360SJordan K. Hubbard if(argc != 4) goto argcount; 382de566360SJordan K. Hubbard if((p->ident = strdup(argv[3])) == NULL) 383de566360SJordan K. Hubbard out_of_memory(); 384de566360SJordan K. Hubbard } 385de566360SJordan K. Hubbard else if(!strcmp(argv[2], "srcdir")) { 386de566360SJordan K. Hubbard if(argc != 4) goto argcount; 387de566360SJordan K. Hubbard if((p->srcdir = strdup(argv[3])) == NULL) 388de566360SJordan K. Hubbard out_of_memory(); 389de566360SJordan K. Hubbard } 390de566360SJordan K. Hubbard else if(!strcmp(argv[2], "objdir")) { 391de566360SJordan K. Hubbard if(argc != 4) goto argcount; 392de566360SJordan K. Hubbard if((p->objdir = strdup(argv[3])) == NULL) 393de566360SJordan K. Hubbard out_of_memory(); 394de566360SJordan K. Hubbard } 395de566360SJordan K. Hubbard else if(!strcmp(argv[2], "objs")) { 396de566360SJordan K. Hubbard p->objs = NULL; 397de566360SJordan K. Hubbard for(i=3;i<argc;i++) 398de566360SJordan K. Hubbard add_string(&p->objs, argv[i]); 399de566360SJordan K. Hubbard } 400de566360SJordan K. Hubbard else if(!strcmp(argv[2], "objpaths")) { 401de566360SJordan K. Hubbard p->objpaths = NULL; 402de566360SJordan K. Hubbard for(i=3;i<argc;i++) 403de566360SJordan K. Hubbard add_string(&p->objpaths, argv[i]); 404de566360SJordan K. Hubbard } 40542ac3bf1SJoerg Wunsch else if(!strcmp(argv[2], "keep")) { 40642ac3bf1SJoerg Wunsch p->keeplist = NULL; 40742ac3bf1SJoerg Wunsch for(i=3;i<argc;i++) 40842ac3bf1SJoerg Wunsch add_string(&p->keeplist, argv[i]); 40942ac3bf1SJoerg Wunsch } 41008826cadSLuigi Rizzo else if(!strcmp(argv[2], "objvar")) { 41108826cadSLuigi Rizzo if(argc != 4) 41208826cadSLuigi Rizzo goto argcount; 41308826cadSLuigi Rizzo if((p->objvar = strdup(argv[3])) == NULL) 41408826cadSLuigi Rizzo out_of_memory(); 41508826cadSLuigi Rizzo } 416de566360SJordan K. Hubbard else { 417b17e90a9SPhilippe Charnier warnx("%s:%d: bad parameter name `%s', skipping line", 418de566360SJordan K. Hubbard curfilename, linenum, argv[2]); 419de566360SJordan K. Hubbard goterror = 1; 420de566360SJordan K. Hubbard } 421de566360SJordan K. Hubbard return; 422de566360SJordan K. Hubbard 423de566360SJordan K. Hubbard 424de566360SJordan K. Hubbard argcount: 425b17e90a9SPhilippe Charnier warnx("%s:%d: too %s arguments, expected \"special %s %s <string>\"", 426de566360SJordan K. Hubbard curfilename, linenum, argc < 4? "few" : "many", argv[1], argv[2]); 427de566360SJordan K. Hubbard goterror = 1; 428de566360SJordan K. Hubbard } 429de566360SJordan K. Hubbard 430de566360SJordan K. Hubbard 431de566360SJordan K. Hubbard prog_t *find_prog(char *str) 432de566360SJordan K. Hubbard { 433de566360SJordan K. Hubbard prog_t *p; 434de566360SJordan K. Hubbard 435de566360SJordan K. Hubbard for(p = progs; p != NULL; p = p->next) 436de566360SJordan K. Hubbard if(!strcmp(p->name, str)) return p; 437de566360SJordan K. Hubbard 438de566360SJordan K. Hubbard return NULL; 439de566360SJordan K. Hubbard } 440de566360SJordan K. Hubbard 441de566360SJordan K. Hubbard 442de566360SJordan K. Hubbard /* 443de566360SJordan K. Hubbard * ======================================================================== 444de566360SJordan K. Hubbard * gen_outputs subsystem 445de566360SJordan K. Hubbard * 446de566360SJordan K. Hubbard */ 447de566360SJordan K. Hubbard 448de566360SJordan K. Hubbard /* helper subroutines */ 449de566360SJordan K. Hubbard 450de566360SJordan K. Hubbard void remove_error_progs(void); 451de566360SJordan K. Hubbard void fillin_program(prog_t *p); 452de566360SJordan K. Hubbard void gen_specials_cache(void); 453de566360SJordan K. Hubbard void gen_output_makefile(void); 454de566360SJordan K. Hubbard void gen_output_cfile(void); 455de566360SJordan K. Hubbard 456de566360SJordan K. Hubbard void fillin_program_objs(prog_t *p, char *path); 457de566360SJordan K. Hubbard void top_makefile_rules(FILE *outmk); 458de566360SJordan K. Hubbard void prog_makefile_rules(FILE *outmk, prog_t *p); 459de566360SJordan K. Hubbard void output_strlst(FILE *outf, strlst_t *lst); 460de566360SJordan K. Hubbard char *genident(char *str); 461de566360SJordan K. Hubbard char *dir_search(char *progname); 462de566360SJordan K. Hubbard 463de566360SJordan K. Hubbard 464de566360SJordan K. Hubbard void gen_outputs(void) 465de566360SJordan K. Hubbard { 466de566360SJordan K. Hubbard prog_t *p; 467de566360SJordan K. Hubbard 468de566360SJordan K. Hubbard for(p = progs; p != NULL; p = p->next) 469de566360SJordan K. Hubbard fillin_program(p); 470de566360SJordan K. Hubbard 471de566360SJordan K. Hubbard remove_error_progs(); 472de566360SJordan K. Hubbard gen_specials_cache(); 473de566360SJordan K. Hubbard gen_output_cfile(); 474de566360SJordan K. Hubbard gen_output_makefile(); 475de566360SJordan K. Hubbard status(""); 476de566360SJordan K. Hubbard fprintf(stderr, 477de566360SJordan K. Hubbard "Run \"make -f %s objs exe\" to build crunched binary.\n", 478de566360SJordan K. Hubbard outmkname); 479de566360SJordan K. Hubbard } 480de566360SJordan K. Hubbard 48108826cadSLuigi Rizzo /* 48208826cadSLuigi Rizzo * run the makefile for the program to find which objects are necessary 48308826cadSLuigi Rizzo */ 484de566360SJordan K. Hubbard void fillin_program(prog_t *p) 485de566360SJordan K. Hubbard { 486de566360SJordan K. Hubbard char path[MAXPATHLEN]; 487de566360SJordan K. Hubbard char *srcparent; 488de566360SJordan K. Hubbard strlst_t *s; 489de566360SJordan K. Hubbard 490de566360SJordan K. Hubbard sprintf(line, "filling in parms for %s", p->name); 491de566360SJordan K. Hubbard status(line); 492de566360SJordan K. Hubbard 493de566360SJordan K. Hubbard if(!p->ident) 494de566360SJordan K. Hubbard p->ident = genident(p->name); 495de566360SJordan K. Hubbard if(!p->srcdir) { 496de566360SJordan K. Hubbard srcparent = dir_search(p->name); 497de566360SJordan K. Hubbard if(srcparent) 498de566360SJordan K. Hubbard sprintf(path, "%s/%s", srcparent, p->name); 499de566360SJordan K. Hubbard if(is_dir(path)) 500de566360SJordan K. Hubbard p->srcdir = strdup(path); 501de566360SJordan K. Hubbard } 502de566360SJordan K. Hubbard if(!p->objdir && p->srcdir) { 503154fd6a9SPoul-Henning Kamp FILE *f; 504154fd6a9SPoul-Henning Kamp 505f5dee082SSøren Schmidt sprintf(path, "cd %s && echo -n /usr/obj`/bin/pwd`", p->srcdir); 506154fd6a9SPoul-Henning Kamp p->objdir = p->srcdir; 507154fd6a9SPoul-Henning Kamp f = popen(path,"r"); 508154fd6a9SPoul-Henning Kamp if (f) { 509154fd6a9SPoul-Henning Kamp fgets(path,sizeof path, f); 510154fd6a9SPoul-Henning Kamp if (!pclose(f)) { 511de566360SJordan K. Hubbard if(is_dir(path)) 512de566360SJordan K. Hubbard p->objdir = strdup(path); 513154fd6a9SPoul-Henning Kamp } 514154fd6a9SPoul-Henning Kamp } 515de566360SJordan K. Hubbard } 51608826cadSLuigi Rizzo /* 51708826cadSLuigi Rizzo * XXX look for a Makefile.{name} in local directory first. 51808826cadSLuigi Rizzo * This lets us override the original Makefile. 51908826cadSLuigi Rizzo */ 52008826cadSLuigi Rizzo sprintf(path, "Makefile.%s", p->name); 52108826cadSLuigi Rizzo if (is_nonempty_file(path)) { 52208826cadSLuigi Rizzo sprintf(line, "Using %s for %s", path, p->name); 52308826cadSLuigi Rizzo status(line); 52408826cadSLuigi Rizzo } else 525de566360SJordan K. Hubbard if(p->srcdir) sprintf(path, "%s/Makefile", p->srcdir); 526de566360SJordan K. Hubbard if(!p->objs && p->srcdir && is_nonempty_file(path)) 527de566360SJordan K. Hubbard fillin_program_objs(p, path); 528de566360SJordan K. Hubbard 529de566360SJordan K. Hubbard if(!p->objpaths && p->objdir && p->objs) 530de566360SJordan K. Hubbard for(s = p->objs; s != NULL; s = s->next) { 531de566360SJordan K. Hubbard sprintf(line, "%s/%s", p->objdir, s->str); 532de566360SJordan K. Hubbard add_string(&p->objpaths, line); 533de566360SJordan K. Hubbard } 534de566360SJordan K. Hubbard 535de566360SJordan K. Hubbard if(!p->srcdir && verbose) 536b17e90a9SPhilippe Charnier warnx("%s: %s: warning: could not find source directory", 537de566360SJordan K. Hubbard infilename, p->name); 538de566360SJordan K. Hubbard if(!p->objs && verbose) 539b17e90a9SPhilippe Charnier warnx("%s: %s: warning: could not find any .o files", 540de566360SJordan K. Hubbard infilename, p->name); 541de566360SJordan K. Hubbard 542de566360SJordan K. Hubbard if(!p->objpaths) { 543b17e90a9SPhilippe Charnier warnx("%s: %s: error: no objpaths specified or calculated", 544de566360SJordan K. Hubbard infilename, p->name); 545de566360SJordan K. Hubbard p->goterror = goterror = 1; 546de566360SJordan K. Hubbard } 547de566360SJordan K. Hubbard } 548de566360SJordan K. Hubbard 549de566360SJordan K. Hubbard void fillin_program_objs(prog_t *p, char *path) 550de566360SJordan K. Hubbard { 551de566360SJordan K. Hubbard char *obj, *cp; 552de566360SJordan K. Hubbard int rc; 553de566360SJordan K. Hubbard FILE *f; 55408826cadSLuigi Rizzo char *objvar="OBJS"; 555de566360SJordan K. Hubbard 556de566360SJordan K. Hubbard /* discover the objs from the srcdir Makefile */ 557de566360SJordan K. Hubbard 558de566360SJordan K. Hubbard if((f = fopen(tempfname, "w")) == NULL) { 559b17e90a9SPhilippe Charnier warn("%s", tempfname); 560de566360SJordan K. Hubbard goterror = 1; 561de566360SJordan K. Hubbard return; 562de566360SJordan K. Hubbard } 56308826cadSLuigi Rizzo if (p->objvar) 56408826cadSLuigi Rizzo objvar = p->objvar ; 565de566360SJordan K. Hubbard 56608826cadSLuigi Rizzo /* 56708826cadSLuigi Rizzo * XXX include outhdrname (e.g. to contain Make variables) 56808826cadSLuigi Rizzo */ 56908826cadSLuigi Rizzo if (outhdrname[0] != '\0') 57008826cadSLuigi Rizzo fprintf(f, ".include \"%s\"\n", outhdrname); 571de566360SJordan K. Hubbard fprintf(f, ".include \"%s\"\n", path); 57208826cadSLuigi Rizzo fprintf(f, ".if defined(PROG) && !defined(%s)\n", objvar); 57308826cadSLuigi Rizzo fprintf(f, "%s=${PROG}.o\n", objvar); 574de566360SJordan K. Hubbard fprintf(f, ".endif\n"); 57565cb078fSJosef Karthauser fprintf(f, "loop:\n\t@echo 'OBJS= '${%s}\n", objvar); 57665cb078fSJosef Karthauser fprintf(f, "crunchgen_objs:\n\t@make -f %s $(OPTS) $(%s_OPTS) loop\n", 57765cb078fSJosef Karthauser tempfname, p->ident); 578de566360SJordan K. Hubbard fclose(f); 579de566360SJordan K. Hubbard 580de566360SJordan K. Hubbard sprintf(line, "make -f %s crunchgen_objs 2>&1", tempfname); 581de566360SJordan K. Hubbard if((f = popen(line, "r")) == NULL) { 582b17e90a9SPhilippe Charnier warn("submake pipe"); 583de566360SJordan K. Hubbard goterror = 1; 584de566360SJordan K. Hubbard return; 585de566360SJordan K. Hubbard } 586de566360SJordan K. Hubbard 587de566360SJordan K. Hubbard while(fgets(line, MAXLINELEN, f)) { 588de566360SJordan K. Hubbard if(strncmp(line, "OBJS= ", 6)) { 589b17e90a9SPhilippe Charnier warnx("make error: %s", line); 590de566360SJordan K. Hubbard goterror = 1; 591de566360SJordan K. Hubbard continue; 592de566360SJordan K. Hubbard } 593de566360SJordan K. Hubbard cp = line + 6; 594de566360SJordan K. Hubbard while(isspace(*cp)) cp++; 595de566360SJordan K. Hubbard while(*cp) { 596de566360SJordan K. Hubbard obj = cp; 597de566360SJordan K. Hubbard while(*cp && !isspace(*cp)) cp++; 598de566360SJordan K. Hubbard if(*cp) *cp++ = '\0'; 599de566360SJordan K. Hubbard add_string(&p->objs, obj); 600de566360SJordan K. Hubbard while(isspace(*cp)) cp++; 601de566360SJordan K. Hubbard } 602de566360SJordan K. Hubbard } 603de566360SJordan K. Hubbard if((rc=pclose(f)) != 0) { 604b17e90a9SPhilippe Charnier warnx("make error: make returned %d", rc); 605de566360SJordan K. Hubbard goterror = 1; 606de566360SJordan K. Hubbard } 607de566360SJordan K. Hubbard unlink(tempfname); 608de566360SJordan K. Hubbard } 609de566360SJordan K. Hubbard 610de566360SJordan K. Hubbard void remove_error_progs(void) 611de566360SJordan K. Hubbard { 612de566360SJordan K. Hubbard prog_t *p1, *p2; 613de566360SJordan K. Hubbard 614de566360SJordan K. Hubbard p1 = NULL; p2 = progs; 615de566360SJordan K. Hubbard while(p2 != NULL) { 616de566360SJordan K. Hubbard if(!p2->goterror) 617de566360SJordan K. Hubbard p1 = p2, p2 = p2->next; 618de566360SJordan K. Hubbard else { 619de566360SJordan K. Hubbard /* delete it from linked list */ 620b17e90a9SPhilippe Charnier warnx("%s: %s: ignoring program because of errors", 621de566360SJordan K. Hubbard infilename, p2->name); 622de566360SJordan K. Hubbard if(p1) p1->next = p2->next; 623de566360SJordan K. Hubbard else progs = p2->next; 624de566360SJordan K. Hubbard p2 = p2->next; 625de566360SJordan K. Hubbard } 626de566360SJordan K. Hubbard } 627de566360SJordan K. Hubbard } 628de566360SJordan K. Hubbard 629de566360SJordan K. Hubbard void gen_specials_cache(void) 630de566360SJordan K. Hubbard { 631de566360SJordan K. Hubbard FILE *cachef; 632de566360SJordan K. Hubbard prog_t *p; 633de566360SJordan K. Hubbard 634de566360SJordan K. Hubbard sprintf(line, "generating %s", cachename); 635de566360SJordan K. Hubbard status(line); 636de566360SJordan K. Hubbard 637de566360SJordan K. Hubbard if((cachef = fopen(cachename, "w")) == NULL) { 638b17e90a9SPhilippe Charnier warn("%s", cachename); 639de566360SJordan K. Hubbard goterror = 1; 640de566360SJordan K. Hubbard return; 641de566360SJordan K. Hubbard } 642de566360SJordan K. Hubbard 643de566360SJordan K. Hubbard fprintf(cachef, "# %s - parm cache generated from %s by crunchgen %s\n\n", 644de566360SJordan K. Hubbard cachename, infilename, CRUNCH_VERSION); 645de566360SJordan K. Hubbard 646de566360SJordan K. Hubbard for(p = progs; p != NULL; p = p->next) { 647de566360SJordan K. Hubbard fprintf(cachef, "\n"); 648de566360SJordan K. Hubbard if(p->srcdir) 649de566360SJordan K. Hubbard fprintf(cachef, "special %s srcdir %s\n", p->name, p->srcdir); 650de566360SJordan K. Hubbard if(p->objdir) 651de566360SJordan K. Hubbard fprintf(cachef, "special %s objdir %s\n", p->name, p->objdir); 652de566360SJordan K. Hubbard if(p->objs) { 653de566360SJordan K. Hubbard fprintf(cachef, "special %s objs", p->name); 654de566360SJordan K. Hubbard output_strlst(cachef, p->objs); 655de566360SJordan K. Hubbard } 656de566360SJordan K. Hubbard fprintf(cachef, "special %s objpaths", p->name); 657de566360SJordan K. Hubbard output_strlst(cachef, p->objpaths); 658de566360SJordan K. Hubbard } 659de566360SJordan K. Hubbard fclose(cachef); 660de566360SJordan K. Hubbard } 661de566360SJordan K. Hubbard 662de566360SJordan K. Hubbard 663de566360SJordan K. Hubbard void gen_output_makefile(void) 664de566360SJordan K. Hubbard { 665de566360SJordan K. Hubbard prog_t *p; 666de566360SJordan K. Hubbard FILE *outmk; 667de566360SJordan K. Hubbard 668de566360SJordan K. Hubbard sprintf(line, "generating %s", outmkname); 669de566360SJordan K. Hubbard status(line); 670de566360SJordan K. Hubbard 671de566360SJordan K. Hubbard if((outmk = fopen(outmkname, "w")) == NULL) { 672b17e90a9SPhilippe Charnier warn("%s", outmkname); 673de566360SJordan K. Hubbard goterror = 1; 674de566360SJordan K. Hubbard return; 675de566360SJordan K. Hubbard } 676de566360SJordan K. Hubbard 677de566360SJordan K. Hubbard fprintf(outmk, "# %s - generated from %s by crunchgen %s\n\n", 678de566360SJordan K. Hubbard outmkname, infilename, CRUNCH_VERSION); 67908826cadSLuigi Rizzo if (outhdrname[0] != '\0') 68008826cadSLuigi Rizzo fprintf(outmk, ".include \"%s\"\n", outhdrname); 681de566360SJordan K. Hubbard 682de566360SJordan K. Hubbard top_makefile_rules(outmk); 683de566360SJordan K. Hubbard 684de566360SJordan K. Hubbard for(p = progs; p != NULL; p = p->next) 685de566360SJordan K. Hubbard prog_makefile_rules(outmk, p); 686de566360SJordan K. Hubbard 687de566360SJordan K. Hubbard fprintf(outmk, "\n# ========\n"); 688de566360SJordan K. Hubbard fclose(outmk); 689de566360SJordan K. Hubbard } 690de566360SJordan K. Hubbard 691de566360SJordan K. Hubbard 692de566360SJordan K. Hubbard void gen_output_cfile(void) 693de566360SJordan K. Hubbard { 694de566360SJordan K. Hubbard extern char *crunched_skel[]; 695de566360SJordan K. Hubbard char **cp; 696de566360SJordan K. Hubbard FILE *outcf; 697de566360SJordan K. Hubbard prog_t *p; 698de566360SJordan K. Hubbard strlst_t *s; 699de566360SJordan K. Hubbard 700de566360SJordan K. Hubbard sprintf(line, "generating %s", outcfname); 701de566360SJordan K. Hubbard status(line); 702de566360SJordan K. Hubbard 703de566360SJordan K. Hubbard if((outcf = fopen(outcfname, "w")) == NULL) { 704b17e90a9SPhilippe Charnier warn("%s", outcfname); 705de566360SJordan K. Hubbard goterror = 1; 706de566360SJordan K. Hubbard return; 707de566360SJordan K. Hubbard } 708de566360SJordan K. Hubbard 709de566360SJordan K. Hubbard fprintf(outcf, 710de566360SJordan K. Hubbard "/* %s - generated from %s by crunchgen %s */\n", 711de566360SJordan K. Hubbard outcfname, infilename, CRUNCH_VERSION); 712de566360SJordan K. Hubbard 713de566360SJordan K. Hubbard fprintf(outcf, "#define EXECNAME \"%s\"\n", execfname); 714de566360SJordan K. Hubbard for(cp = crunched_skel; *cp != NULL; cp++) 715de566360SJordan K. Hubbard fprintf(outcf, "%s\n", *cp); 716de566360SJordan K. Hubbard 717de566360SJordan K. Hubbard for(p = progs; p != NULL; p = p->next) 718de566360SJordan K. Hubbard fprintf(outcf, "extern int _crunched_%s_stub();\n", p->ident); 719de566360SJordan K. Hubbard 720de566360SJordan K. Hubbard fprintf(outcf, "\nstruct stub entry_points[] = {\n"); 721de566360SJordan K. Hubbard for(p = progs; p != NULL; p = p->next) { 722de566360SJordan K. Hubbard fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n", 723de566360SJordan K. Hubbard p->name, p->ident); 724de566360SJordan K. Hubbard for(s = p->links; s != NULL; s = s->next) 725de566360SJordan K. Hubbard fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n", 726de566360SJordan K. Hubbard s->str, p->ident); 727de566360SJordan K. Hubbard } 728de566360SJordan K. Hubbard 729de566360SJordan K. Hubbard fprintf(outcf, "\t{ EXECNAME, crunched_main },\n"); 730de566360SJordan K. Hubbard fprintf(outcf, "\t{ NULL, NULL }\n};\n"); 731de566360SJordan K. Hubbard fclose(outcf); 732de566360SJordan K. Hubbard } 733de566360SJordan K. Hubbard 734de566360SJordan K. Hubbard 735de566360SJordan K. Hubbard char *genident(char *str) 736de566360SJordan K. Hubbard { 737de566360SJordan K. Hubbard char *n,*s,*d; 738de566360SJordan K. Hubbard 739de566360SJordan K. Hubbard /* 740de566360SJordan K. Hubbard * generates a Makefile/C identifier from a program name, mapping '-' to 741de566360SJordan K. Hubbard * '_' and ignoring all other non-identifier characters. This leads to 742de566360SJordan K. Hubbard * programs named "foo.bar" and "foobar" to map to the same identifier. 743de566360SJordan K. Hubbard */ 744de566360SJordan K. Hubbard 745de566360SJordan K. Hubbard if((n = strdup(str)) == NULL) 746de566360SJordan K. Hubbard return NULL; 747de566360SJordan K. Hubbard for(d = s = n; *s != '\0'; s++) { 748de566360SJordan K. Hubbard if(*s == '-') *d++ = '_'; 749de566360SJordan K. Hubbard else if(*s == '_' || isalnum(*s)) *d++ = *s; 750de566360SJordan K. Hubbard } 751de566360SJordan K. Hubbard *d = '\0'; 752de566360SJordan K. Hubbard return n; 753de566360SJordan K. Hubbard } 754de566360SJordan K. Hubbard 755de566360SJordan K. Hubbard 756de566360SJordan K. Hubbard char *dir_search(char *progname) 757de566360SJordan K. Hubbard { 758de566360SJordan K. Hubbard char path[MAXPATHLEN]; 759de566360SJordan K. Hubbard strlst_t *dir; 760de566360SJordan K. Hubbard 761de566360SJordan K. Hubbard for(dir=srcdirs; dir != NULL; dir=dir->next) { 762de566360SJordan K. Hubbard sprintf(path, "%s/%s", dir->str, progname); 763de566360SJordan K. Hubbard if(is_dir(path)) return dir->str; 764de566360SJordan K. Hubbard } 765de566360SJordan K. Hubbard return NULL; 766de566360SJordan K. Hubbard } 767de566360SJordan K. Hubbard 768de566360SJordan K. Hubbard 769de566360SJordan K. Hubbard void top_makefile_rules(FILE *outmk) 770de566360SJordan K. Hubbard { 771de566360SJordan K. Hubbard prog_t *p; 772de566360SJordan K. Hubbard 773de566360SJordan K. Hubbard fprintf(outmk, "LIBS="); 774de566360SJordan K. Hubbard output_strlst(outmk, libs); 775de566360SJordan K. Hubbard 776de566360SJordan K. Hubbard fprintf(outmk, "CRUNCHED_OBJS="); 777de566360SJordan K. Hubbard for(p = progs; p != NULL; p = p->next) 778de566360SJordan K. Hubbard fprintf(outmk, " %s.lo", p->name); 779de566360SJordan K. Hubbard fprintf(outmk, "\n"); 780de566360SJordan K. Hubbard 781de566360SJordan K. Hubbard fprintf(outmk, "SUBMAKE_TARGETS="); 782de566360SJordan K. Hubbard for(p = progs; p != NULL; p = p->next) 783de566360SJordan K. Hubbard fprintf(outmk, " %s_make", p->ident); 784ced716c3SBrian Somers fprintf(outmk, "\nSUBCLEAN_TARGETS="); 785ced716c3SBrian Somers for(p = progs; p != NULL; p = p->next) 786ced716c3SBrian Somers fprintf(outmk, " %s_clean", p->ident); 787de566360SJordan K. Hubbard fprintf(outmk, "\n\n"); 788de566360SJordan K. Hubbard 789de566360SJordan K. Hubbard fprintf(outmk, "%s: %s.o $(CRUNCHED_OBJS)\n", 790de566360SJordan K. Hubbard execfname, execfname); 791de566360SJordan K. Hubbard fprintf(outmk, "\t$(CC) -static -o %s %s.o $(CRUNCHED_OBJS) $(LIBS)\n", 792de566360SJordan K. Hubbard execfname, execfname); 793de566360SJordan K. Hubbard fprintf(outmk, "\tstrip %s\n", execfname); 794de566360SJordan K. Hubbard fprintf(outmk, "all: objs exe\nobjs: $(SUBMAKE_TARGETS)\n"); 795de566360SJordan K. Hubbard fprintf(outmk, "exe: %s\n", execfname); 796ced716c3SBrian Somers fprintf(outmk, "realclean: clean subclean\n"); 797de566360SJordan K. Hubbard fprintf(outmk, "clean:\n\trm -f %s *.lo *.o *_stub.c\n", 798de566360SJordan K. Hubbard execfname); 799ced716c3SBrian Somers fprintf(outmk, "subclean: $(SUBCLEAN_TARGETS)\n"); 800de566360SJordan K. Hubbard } 801de566360SJordan K. Hubbard 802de566360SJordan K. Hubbard 803de566360SJordan K. Hubbard void prog_makefile_rules(FILE *outmk, prog_t *p) 804de566360SJordan K. Hubbard { 80542ac3bf1SJoerg Wunsch strlst_t *lst; 80642ac3bf1SJoerg Wunsch 807de566360SJordan K. Hubbard fprintf(outmk, "\n# -------- %s\n\n", p->name); 808de566360SJordan K. Hubbard 809de566360SJordan K. Hubbard if(p->srcdir && p->objs) { 810de566360SJordan K. Hubbard fprintf(outmk, "%s_SRCDIR=%s\n", p->ident, p->srcdir); 811de566360SJordan K. Hubbard fprintf(outmk, "%s_OBJS=", p->ident); 812de566360SJordan K. Hubbard output_strlst(outmk, p->objs); 813de566360SJordan K. Hubbard fprintf(outmk, "%s_make:\n", p->ident); 81465cb078fSJosef Karthauser fprintf(outmk, "\t(cd $(%s_SRCDIR) && make obj && \\\n" 81565cb078fSJosef Karthauser "\t\tmake $(OPTS) $(%s_OPTS) depend && \\\n" 81665cb078fSJosef Karthauser "\t\tmake $(OPTS) $(%s_OPTS) $(%s_OBJS))\n", 81765cb078fSJosef Karthauser p->ident, p->ident, p->ident, p->ident); 818ced716c3SBrian Somers fprintf(outmk, "%s_clean:\n", p->ident); 819ced716c3SBrian Somers fprintf(outmk, "\t(cd $(%s_SRCDIR) && make clean)\n\n", p->ident); 820de566360SJordan K. Hubbard } 821de566360SJordan K. Hubbard else 822de566360SJordan K. Hubbard fprintf(outmk, "%s_make:\n\t@echo \"** cannot make objs for %s\"\n\n", 823de566360SJordan K. Hubbard p->ident, p->name); 824de566360SJordan K. Hubbard 825de566360SJordan K. Hubbard fprintf(outmk, "%s_OBJPATHS=", p->ident); 826de566360SJordan K. Hubbard output_strlst(outmk, p->objpaths); 827de566360SJordan K. Hubbard 828de566360SJordan K. Hubbard fprintf(outmk, "%s_stub.c:\n", p->name); 829de566360SJordan K. Hubbard fprintf(outmk, "\techo \"" 830de566360SJordan K. Hubbard "int _crunched_%s_stub(int argc, char **argv, char **envp)" 831de566360SJordan K. Hubbard "{return main(argc,argv,envp);}\" >%s_stub.c\n", 832de566360SJordan K. Hubbard p->ident, p->name); 833de566360SJordan K. Hubbard fprintf(outmk, "%s.lo: %s_stub.o $(%s_OBJPATHS)\n", 834de566360SJordan K. Hubbard p->name, p->name, p->ident); 835de566360SJordan K. Hubbard fprintf(outmk, "\tld -dc -r -o %s.lo %s_stub.o $(%s_OBJPATHS)\n", 836de566360SJordan K. Hubbard p->name, p->name, p->ident); 8376cd35234SJordan K. Hubbard fprintf(outmk, "\tcrunchide -k _crunched_%s_stub ", p->ident); 83842ac3bf1SJoerg Wunsch for(lst = p->keeplist; lst != NULL; lst = lst->next) 83942ac3bf1SJoerg Wunsch fprintf(outmk, "-k _%s ", lst->str); 84042ac3bf1SJoerg Wunsch fprintf(outmk, "%s.lo\n", p->name); 841de566360SJordan K. Hubbard } 842de566360SJordan K. Hubbard 843de566360SJordan K. Hubbard void output_strlst(FILE *outf, strlst_t *lst) 844de566360SJordan K. Hubbard { 845de566360SJordan K. Hubbard for(; lst != NULL; lst = lst->next) 846de566360SJordan K. Hubbard fprintf(outf, " %s", lst->str); 847de566360SJordan K. Hubbard fprintf(outf, "\n"); 848de566360SJordan K. Hubbard } 849de566360SJordan K. Hubbard 850de566360SJordan K. Hubbard 851de566360SJordan K. Hubbard /* 852de566360SJordan K. Hubbard * ======================================================================== 853de566360SJordan K. Hubbard * general library routines 854de566360SJordan K. Hubbard * 855de566360SJordan K. Hubbard */ 856de566360SJordan K. Hubbard 857de566360SJordan K. Hubbard void status(char *str) 858de566360SJordan K. Hubbard { 859de566360SJordan K. Hubbard static int lastlen = 0; 860de566360SJordan K. Hubbard int len, spaces; 861de566360SJordan K. Hubbard 862de566360SJordan K. Hubbard if(!verbose) return; 863de566360SJordan K. Hubbard 864de566360SJordan K. Hubbard len = strlen(str); 865de566360SJordan K. Hubbard spaces = lastlen - len; 866de566360SJordan K. Hubbard if(spaces < 1) spaces = 1; 867de566360SJordan K. Hubbard 868de566360SJordan K. Hubbard fprintf(stderr, " [%s]%*.*s\r", str, spaces, spaces, " "); 869de566360SJordan K. Hubbard fflush(stderr); 870de566360SJordan K. Hubbard lastlen = len; 871de566360SJordan K. Hubbard } 872de566360SJordan K. Hubbard 873de566360SJordan K. Hubbard 874de566360SJordan K. Hubbard void out_of_memory(void) 875de566360SJordan K. Hubbard { 876b17e90a9SPhilippe Charnier errx(1, "%s: %d: out of memory, stopping", infilename, linenum); 877de566360SJordan K. Hubbard } 878de566360SJordan K. Hubbard 879de566360SJordan K. Hubbard 880de566360SJordan K. Hubbard void add_string(strlst_t **listp, char *str) 881de566360SJordan K. Hubbard { 882de566360SJordan K. Hubbard strlst_t *p1, *p2; 883de566360SJordan K. Hubbard 884de566360SJordan K. Hubbard /* add to end, but be smart about dups */ 885de566360SJordan K. Hubbard 886de566360SJordan K. Hubbard for(p1 = NULL, p2 = *listp; p2 != NULL; p1 = p2, p2 = p2->next) 887de566360SJordan K. Hubbard if(!strcmp(p2->str, str)) return; 888de566360SJordan K. Hubbard 889de566360SJordan K. Hubbard p2 = malloc(sizeof(strlst_t)); 890eb148815SJoerg Wunsch if(p2) { 891eb148815SJoerg Wunsch memset(p2, 0, sizeof(strlst_t)); 892eb148815SJoerg Wunsch p2->str = strdup(str); 893eb148815SJoerg Wunsch } 894de566360SJordan K. Hubbard if(!p2 || !p2->str) 895de566360SJordan K. Hubbard out_of_memory(); 896de566360SJordan K. Hubbard 897de566360SJordan K. Hubbard p2->next = NULL; 898de566360SJordan K. Hubbard if(p1 == NULL) *listp = p2; 899de566360SJordan K. Hubbard else p1->next = p2; 900de566360SJordan K. Hubbard } 901de566360SJordan K. Hubbard 902de566360SJordan K. Hubbard 903de566360SJordan K. Hubbard int is_dir(char *pathname) 904de566360SJordan K. Hubbard { 905de566360SJordan K. Hubbard struct stat buf; 906de566360SJordan K. Hubbard 907de566360SJordan K. Hubbard if(stat(pathname, &buf) == -1) 908de566360SJordan K. Hubbard return 0; 909de566360SJordan K. Hubbard return S_ISDIR(buf.st_mode); 910de566360SJordan K. Hubbard } 911de566360SJordan K. Hubbard 912de566360SJordan K. Hubbard int is_nonempty_file(char *pathname) 913de566360SJordan K. Hubbard { 914de566360SJordan K. Hubbard struct stat buf; 915de566360SJordan K. Hubbard 916de566360SJordan K. Hubbard if(stat(pathname, &buf) == -1) 917de566360SJordan K. Hubbard return 0; 918de566360SJordan K. Hubbard 919de566360SJordan K. Hubbard return S_ISREG(buf.st_mode) && buf.st_size > 0; 920de566360SJordan K. Hubbard } 921