crunchgen.c revision 153687
11722Sjkh/* 21722Sjkh * Copyright (c) 1994 University of Maryland 31722Sjkh * All Rights Reserved. 41722Sjkh * 51722Sjkh * Permission to use, copy, modify, distribute, and sell this software and its 61722Sjkh * documentation for any purpose is hereby granted without fee, provided that 71722Sjkh * the above copyright notice appear in all copies and that both that 81722Sjkh * copyright notice and this permission notice appear in supporting 91722Sjkh * documentation, and that the name of U.M. not be used in advertising or 101722Sjkh * publicity pertaining to distribution of the software without specific, 111722Sjkh * written prior permission. U.M. makes no representations about the 121722Sjkh * suitability of this software for any purpose. It is provided "as is" 131722Sjkh * without express or implied warranty. 141722Sjkh * 151722Sjkh * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 161722Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. 171722Sjkh * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 181722Sjkh * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 191722Sjkh * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 201722Sjkh * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 211722Sjkh * 221722Sjkh * Author: James da Silva, Systems Design and Analysis Group 231722Sjkh * Computer Science Department 241722Sjkh * University of Maryland at College Park 2556995Sluigi * 2656995Sluigi * $FreeBSD: head/usr.sbin/crunch/crunchgen/crunchgen.c 153687 2005-12-23 15:31:37Z ceri $ 271722Sjkh */ 281722Sjkh/* 291722Sjkh * ======================================================================== 301722Sjkh * crunchgen.c 311722Sjkh * 321722Sjkh * Generates a Makefile and main C file for a crunched executable, 338857Srgrimes * from specs given in a .conf file. 341722Sjkh */ 3570884Sjoe#include <sys/types.h> 3670884Sjoe#include <sys/stat.h> 3770884Sjoe#include <sys/param.h> 3870884Sjoe 3929453Scharnier#include <ctype.h> 4029453Scharnier#include <err.h> 4170124Sjoe#include <paths.h> 4229453Scharnier#include <stdio.h> 431722Sjkh#include <stdlib.h> 4429453Scharnier#include <string.h> 451722Sjkh#include <unistd.h> 461722Sjkh 471722Sjkh#define CRUNCH_VERSION "0.2" 481722Sjkh 491722Sjkh#define MAXLINELEN 16384 501722Sjkh#define MAXFIELDS 2048 511722Sjkh 521722Sjkh 531722Sjkh/* internal representation of conf file: */ 541722Sjkh 551722Sjkh/* simple lists of strings suffice for most parms */ 561722Sjkh 571722Sjkhtypedef struct strlst { 5870884Sjoe struct strlst *next; 5970884Sjoe char *str; 601722Sjkh} strlst_t; 611722Sjkh 621722Sjkh/* progs have structure, each field can be set with "special" or calculated */ 631722Sjkh 641722Sjkhtypedef struct prog { 6570884Sjoe struct prog *next; /* link field */ 6670884Sjoe char *name; /* program name */ 6770884Sjoe char *ident; /* C identifier for the program name */ 6870884Sjoe char *srcdir; 6970884Sjoe char *realsrcdir; 7070884Sjoe char *objdir; 7170884Sjoe char *objvar; /* Makefile variable to replace OBJS */ 7270884Sjoe strlst_t *objs, *objpaths; 7370884Sjoe strlst_t *buildopts; 7470884Sjoe strlst_t *keeplist; 7570884Sjoe strlst_t *links; 7693435Sluigi strlst_t *libs; 77153687Sceri strlst_t *libs_so; 7870884Sjoe int goterror; 791722Sjkh} prog_t; 801722Sjkh 811722Sjkh 821722Sjkh/* global state */ 831722Sjkh 8468750Sjoestrlst_t *buildopts = NULL; 8570884Sjoestrlst_t *srcdirs = NULL; 8670884Sjoestrlst_t *libs = NULL; 87153687Sceristrlst_t *libs_so = NULL; 8870884Sjoeprog_t *progs = NULL; 891722Sjkh 901722Sjkhchar confname[MAXPATHLEN], infilename[MAXPATHLEN]; 911722Sjkhchar outmkname[MAXPATHLEN], outcfname[MAXPATHLEN], execfname[MAXPATHLEN]; 921722Sjkhchar tempfname[MAXPATHLEN], cachename[MAXPATHLEN], curfilename[MAXPATHLEN]; 9370884Sjoechar outhdrname[MAXPATHLEN] ; /* user-supplied header for *.mk */ 9470884Sjoechar *objprefix; /* where are the objects ? */ 951722Sjkhint linenum = -1; 961722Sjkhint goterror = 0; 971722Sjkh 9870884Sjoeint verbose, readcache; /* options */ 991722Sjkhint reading_cache; 10070884Sjoeint makeobj = 0; /* add 'make obj' rules to the makefile */ 1011722Sjkh 1026696Sphkint list_mode; 1036696Sphk 1041722Sjkh/* general library routines */ 1051722Sjkh 1061722Sjkhvoid status(char *str); 1071722Sjkhvoid out_of_memory(void); 1081722Sjkhvoid add_string(strlst_t **listp, char *str); 1091722Sjkhint is_dir(char *pathname); 1101722Sjkhint is_nonempty_file(char *pathname); 111153687Sceriint subtract_strlst(strlst_t **lista, strlst_t **listb); 112153687Sceriint in_list(strlst_t **listp, char *str); 1131722Sjkh 1141722Sjkh/* helper routines for main() */ 1151722Sjkh 1168857Srgrimesvoid usage(void); 1171722Sjkhvoid parse_conf_file(void); 1181722Sjkhvoid gen_outputs(void); 1191722Sjkh 1201722Sjkh 1211722Sjkhint main(int argc, char **argv) 1221722Sjkh{ 12370884Sjoe char *p; 12470884Sjoe int optc; 1251722Sjkh 12670884Sjoe verbose = 1; 12770884Sjoe readcache = 1; 12870884Sjoe *outmkname = *outcfname = *execfname = '\0'; 1298857Srgrimes 13070884Sjoe p = getenv("MAKEOBJDIRPREFIX"); 13170884Sjoe if (p == NULL || *p == '\0') 13270884Sjoe objprefix = "/usr/obj"; /* default */ 13370884Sjoe else 13470884Sjoe if ((objprefix = strdup(p)) == NULL) 13570884Sjoe out_of_memory(); 13669413Sluigi 13770884Sjoe while((optc = getopt(argc, argv, "lh:m:c:e:p:foq")) != -1) { 13870884Sjoe switch(optc) { 13970884Sjoe case 'f': 14070884Sjoe readcache = 0; 14170884Sjoe break; 14270884Sjoe case 'o': 14370884Sjoe makeobj = 1; 14470884Sjoe break; 14570884Sjoe case 'q': 14670884Sjoe verbose = 0; 14770884Sjoe break; 1481722Sjkh 14970884Sjoe case 'm': 15070884Sjoe strlcpy(outmkname, optarg, sizeof(outmkname)); 15170884Sjoe break; 15270884Sjoe case 'p': 15370884Sjoe if ((objprefix = strdup(optarg)) == NULL) 15470113Sjoe out_of_memory(); 15570113Sjoe break; 1561722Sjkh 15770884Sjoe case 'h': 15870884Sjoe strlcpy(outhdrname, optarg, sizeof(outhdrname)); 15970884Sjoe break; 16070884Sjoe case 'c': 16170884Sjoe strlcpy(outcfname, optarg, sizeof(outcfname)); 16270884Sjoe break; 16370884Sjoe case 'e': 16470884Sjoe strlcpy(execfname, optarg, sizeof(execfname)); 16570884Sjoe break; 16670884Sjoe 16770884Sjoe case 'l': 16870884Sjoe list_mode++; 16970884Sjoe verbose = 0; 17070884Sjoe break; 17170884Sjoe 17270884Sjoe case '?': 17370884Sjoe default: 17470884Sjoe usage(); 17570884Sjoe } 1761722Sjkh } 1771722Sjkh 17870884Sjoe argc -= optind; 17970884Sjoe argv += optind; 1801722Sjkh 18170884Sjoe if (argc != 1) 18270884Sjoe usage(); 1831722Sjkh 18470884Sjoe /* 18570884Sjoe * generate filenames 18670884Sjoe */ 1871722Sjkh 18870884Sjoe strlcpy(infilename, argv[0], sizeof(infilename)); 1891722Sjkh 19070884Sjoe /* confname = `basename infilename .conf` */ 1911722Sjkh 19270884Sjoe if ((p=strrchr(infilename, '/')) != NULL) 19370884Sjoe strlcpy(confname, p + 1, sizeof(confname)); 19470884Sjoe else 19570884Sjoe strlcpy(confname, infilename, sizeof(confname)); 1961722Sjkh 19770884Sjoe if ((p=strrchr(confname, '.')) != NULL && !strcmp(p, ".conf")) 19870884Sjoe *p = '\0'; 1991722Sjkh 20070884Sjoe if (!*outmkname) 20170884Sjoe snprintf(outmkname, sizeof(outmkname), "%s.mk", confname); 20270884Sjoe if (!*outcfname) 20370884Sjoe snprintf(outcfname, sizeof(outcfname), "%s.c", confname); 20470884Sjoe if (!*execfname) 20570884Sjoe snprintf(execfname, sizeof(execfname), "%s", confname); 20670884Sjoe 20770884Sjoe snprintf(cachename, sizeof(cachename), "%s.cache", confname); 20870884Sjoe snprintf(tempfname, sizeof(tempfname), "%s/crunchgen_%sXXXXXX", 20970124Sjoe getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP, confname); 2101722Sjkh 21170884Sjoe parse_conf_file(); 21270884Sjoe if (list_mode) 21370884Sjoe exit(goterror); 2146696Sphk 21570884Sjoe gen_outputs(); 2161722Sjkh 21770884Sjoe exit(goterror); 2181722Sjkh} 2191722Sjkh 2201722Sjkh 2211722Sjkhvoid usage(void) 2221722Sjkh{ 22370884Sjoe fprintf(stderr, "%s%s\n\t%s%s\n", "usage: crunchgen [-foq] ", 22470884Sjoe "[-h <makefile-header-name>] [-m <makefile>]", 22570884Sjoe "[-p <obj-prefix>] [-c <c-file-name>] [-e <exec-file>] ", 22670884Sjoe "<conffile>"); 22770884Sjoe exit(1); 2281722Sjkh} 2291722Sjkh 2301722Sjkh 2311722Sjkh/* 2321722Sjkh * ======================================================================== 2331722Sjkh * parse_conf_file subsystem 2341722Sjkh * 2351722Sjkh */ 2361722Sjkh 2371722Sjkh/* helper routines for parse_conf_file */ 2381722Sjkh 2391722Sjkhvoid parse_one_file(char *filename); 2408857Srgrimesvoid parse_line(char *line, int *fc, char **fv, int nf); 2411722Sjkhvoid add_srcdirs(int argc, char **argv); 2421722Sjkhvoid add_progs(int argc, char **argv); 2431722Sjkhvoid add_link(int argc, char **argv); 2441722Sjkhvoid add_libs(int argc, char **argv); 245153687Scerivoid add_libs_so(int argc, char **argv); 24668750Sjoevoid add_buildopts(int argc, char **argv); 2471722Sjkhvoid add_special(int argc, char **argv); 2481722Sjkh 2491722Sjkhprog_t *find_prog(char *str); 2501722Sjkhvoid add_prog(char *progname); 2511722Sjkh 2521722Sjkh 2531722Sjkhvoid parse_conf_file(void) 2541722Sjkh{ 25570884Sjoe if (!is_nonempty_file(infilename)) 25629453Scharnier errx(1, "fatal: input file \"%s\" not found", infilename); 25770884Sjoe 25870884Sjoe parse_one_file(infilename); 25970884Sjoe if (readcache && is_nonempty_file(cachename)) { 26070884Sjoe reading_cache = 1; 26170884Sjoe parse_one_file(cachename); 26270884Sjoe } 2631722Sjkh} 2641722Sjkh 2651722Sjkh 2661722Sjkhvoid parse_one_file(char *filename) 2671722Sjkh{ 26870884Sjoe char *fieldv[MAXFIELDS]; 26970884Sjoe int fieldc; 27070884Sjoe void (*f)(int c, char **v); 27170884Sjoe FILE *cf; 27270884Sjoe char line[MAXLINELEN]; 2731722Sjkh 27470884Sjoe snprintf(line, sizeof(line), "reading %s", filename); 27570884Sjoe status(line); 27670884Sjoe strlcpy(curfilename, filename, sizeof(curfilename)); 2771722Sjkh 27870884Sjoe if ((cf = fopen(curfilename, "r")) == NULL) { 27970884Sjoe warn("%s", curfilename); 28070884Sjoe goterror = 1; 28170884Sjoe return; 28270884Sjoe } 2831722Sjkh 28470884Sjoe linenum = 0; 28570884Sjoe while (fgets(line, MAXLINELEN, cf) != NULL) { 28670884Sjoe linenum++; 28770884Sjoe parse_line(line, &fieldc, fieldv, MAXFIELDS); 28870884Sjoe 28970884Sjoe if (fieldc < 1) 29070884Sjoe continue; 29170884Sjoe 29270884Sjoe if (!strcmp(fieldv[0], "srcdirs")) 29370884Sjoe f = add_srcdirs; 29470884Sjoe else if(!strcmp(fieldv[0], "progs")) 29570884Sjoe f = add_progs; 29670884Sjoe else if(!strcmp(fieldv[0], "ln")) 29770884Sjoe f = add_link; 29870884Sjoe else if(!strcmp(fieldv[0], "libs")) 29970884Sjoe f = add_libs; 300153687Sceri else if(!strcmp(fieldv[0], "libs_so")) 301153687Sceri f = add_libs_so; 30270884Sjoe else if(!strcmp(fieldv[0], "buildopts")) 30370884Sjoe f = add_buildopts; 30470884Sjoe else if(!strcmp(fieldv[0], "special")) 30570884Sjoe f = add_special; 30670884Sjoe else { 30770884Sjoe warnx("%s:%d: skipping unknown command `%s'", 30870884Sjoe curfilename, linenum, fieldv[0]); 30970884Sjoe goterror = 1; 31070884Sjoe continue; 31170884Sjoe } 31270884Sjoe 31370884Sjoe if (fieldc < 2) { 31470884Sjoe warnx("%s:%d: %s %s", 31570884Sjoe curfilename, linenum, fieldv[0], 31670884Sjoe "command needs at least 1 argument, skipping"); 31770884Sjoe goterror = 1; 31870884Sjoe continue; 31970884Sjoe } 32070884Sjoe 32170884Sjoe f(fieldc, fieldv); 3221722Sjkh } 32370884Sjoe 32470884Sjoe if (ferror(cf)) { 32570884Sjoe warn("%s", curfilename); 32670884Sjoe goterror = 1; 3271722Sjkh } 32870884Sjoe fclose(cf); 3291722Sjkh} 3301722Sjkh 3311722Sjkh 3321722Sjkhvoid parse_line(char *line, int *fc, char **fv, int nf) 3331722Sjkh{ 33470884Sjoe char *p; 3351722Sjkh 33670884Sjoe p = line; 33770884Sjoe *fc = 0; 3381722Sjkh 33970884Sjoe while (1) { 34070884Sjoe while (isspace(*p)) 34170884Sjoe p++; 34270884Sjoe 34370884Sjoe if (*p == '\0' || *p == '#') 34470884Sjoe break; 34570884Sjoe 34670884Sjoe if (*fc < nf) 34770884Sjoe fv[(*fc)++] = p; 34870884Sjoe 34970884Sjoe while (*p && !isspace(*p) && *p != '#') 35070884Sjoe p++; 35170884Sjoe 35270884Sjoe if (*p == '\0' || *p == '#') 35370884Sjoe break; 35470884Sjoe 35570884Sjoe *p++ = '\0'; 35670884Sjoe } 35770884Sjoe 35870884Sjoe if (*p) 35970884Sjoe *p = '\0'; /* needed for '#' case */ 3601722Sjkh} 3611722Sjkh 3621722Sjkh 3631722Sjkhvoid add_srcdirs(int argc, char **argv) 3641722Sjkh{ 36570884Sjoe int i; 3661722Sjkh 36770884Sjoe for (i = 1; i < argc; i++) { 36870884Sjoe if (is_dir(argv[i])) 36970884Sjoe add_string(&srcdirs, argv[i]); 37070884Sjoe else { 37170884Sjoe warnx("%s:%d: `%s' is not a directory, skipping it", 37270884Sjoe curfilename, linenum, argv[i]); 37370884Sjoe goterror = 1; 37470884Sjoe } 3751722Sjkh } 3761722Sjkh} 3771722Sjkh 3781722Sjkh 3791722Sjkhvoid add_progs(int argc, char **argv) 3801722Sjkh{ 38170884Sjoe int i; 3821722Sjkh 38370884Sjoe for (i = 1; i < argc; i++) 38470884Sjoe add_prog(argv[i]); 3851722Sjkh} 3861722Sjkh 3871722Sjkh 3881722Sjkhvoid add_prog(char *progname) 3891722Sjkh{ 39070884Sjoe prog_t *p1, *p2; 3911722Sjkh 39270884Sjoe /* add to end, but be smart about dups */ 3931722Sjkh 39470884Sjoe for (p1 = NULL, p2 = progs; p2 != NULL; p1 = p2, p2 = p2->next) 39570884Sjoe if (!strcmp(p2->name, progname)) 39670884Sjoe return; 3971722Sjkh 39870884Sjoe p2 = malloc(sizeof(prog_t)); 39970884Sjoe if(p2) { 40070884Sjoe memset(p2, 0, sizeof(prog_t)); 40170884Sjoe p2->name = strdup(progname); 40270884Sjoe } 40370884Sjoe if (!p2 || !p2->name) 40470884Sjoe out_of_memory(); 4051722Sjkh 40670884Sjoe p2->next = NULL; 40770884Sjoe if (p1 == NULL) 40870884Sjoe progs = p2; 40970884Sjoe else 41070884Sjoe p1->next = p2; 4111722Sjkh 41270884Sjoe p2->ident = NULL; 41370884Sjoe p2->srcdir = NULL; 41470884Sjoe p2->realsrcdir = NULL; 41570884Sjoe p2->objdir = NULL; 41670884Sjoe p2->links = NULL; 41793435Sluigi p2->libs = NULL; 418153687Sceri p2->libs_so = NULL; 41970884Sjoe p2->objs = NULL; 42070884Sjoe p2->keeplist = NULL; 42170884Sjoe p2->buildopts = NULL; 42270884Sjoe p2->goterror = 0; 42370884Sjoe 42470884Sjoe if (list_mode) 42570884Sjoe printf("%s\n",progname); 4261722Sjkh} 4271722Sjkh 4281722Sjkh 4291722Sjkhvoid add_link(int argc, char **argv) 4301722Sjkh{ 43170884Sjoe int i; 43270884Sjoe prog_t *p = find_prog(argv[1]); 4331722Sjkh 43470884Sjoe if (p == NULL) { 43570884Sjoe warnx("%s:%d: no prog %s previously declared, skipping link", 43670884Sjoe curfilename, linenum, argv[1]); 43770884Sjoe goterror = 1; 43870884Sjoe return; 43970884Sjoe } 44070884Sjoe 44170884Sjoe for (i = 2; i < argc; i++) { 44270884Sjoe if (list_mode) 44370884Sjoe printf("%s\n",argv[i]); 44470884Sjoe 44570884Sjoe add_string(&p->links, argv[i]); 44670884Sjoe } 4471722Sjkh} 4481722Sjkh 4491722Sjkh 4501722Sjkhvoid add_libs(int argc, char **argv) 4511722Sjkh{ 45270884Sjoe int i; 4531722Sjkh 454153687Sceri for(i = 1; i < argc; i++) { 45570884Sjoe add_string(&libs, argv[i]); 456153687Sceri if ( in_list(&libs_so, argv[i]) ) 457153687Sceri warnx("%s:%d: " 458153687Sceri "library `%s' specified as dynamic earlier", 459153687Sceri curfilename, linenum, argv[i]); 460153687Sceri } 4611722Sjkh} 4621722Sjkh 4631722Sjkh 464153687Scerivoid add_libs_so(int argc, char **argv) 465153687Sceri{ 466153687Sceri int i; 467153687Sceri 468153687Sceri for(i = 1; i < argc; i++) { 469153687Sceri add_string(&libs_so, argv[i]); 470153687Sceri if ( in_list(&libs, argv[i]) ) 471153687Sceri warnx("%s:%d: " 472153687Sceri "library `%s' specified as static earlier", 473153687Sceri curfilename, linenum, argv[i]); 474153687Sceri } 475153687Sceri} 476153687Sceri 477153687Sceri 47868750Sjoevoid add_buildopts(int argc, char **argv) 47968750Sjoe{ 48070884Sjoe int i; 48168750Sjoe 48270884Sjoe for (i = 1; i < argc; i++) 48370884Sjoe add_string(&buildopts, argv[i]); 48468750Sjoe} 48568750Sjoe 48668750Sjoe 4871722Sjkhvoid add_special(int argc, char **argv) 4881722Sjkh{ 48970884Sjoe int i; 49070884Sjoe prog_t *p = find_prog(argv[1]); 4911722Sjkh 49270884Sjoe if (p == NULL) { 49370884Sjoe if (reading_cache) 49470884Sjoe return; 4951722Sjkh 49670884Sjoe warnx("%s:%d: no prog %s previously declared, skipping special", 49770884Sjoe curfilename, linenum, argv[1]); 49870884Sjoe goterror = 1; 49970884Sjoe return; 50070884Sjoe } 5011722Sjkh 50270884Sjoe if (!strcmp(argv[2], "ident")) { 50370884Sjoe if (argc != 4) 50470884Sjoe goto argcount; 50570884Sjoe if ((p->ident = strdup(argv[3])) == NULL) 50670884Sjoe out_of_memory(); 50770884Sjoe } else if (!strcmp(argv[2], "srcdir")) { 50870884Sjoe if (argc != 4) 50970884Sjoe goto argcount; 51070884Sjoe if ((p->srcdir = strdup(argv[3])) == NULL) 51170884Sjoe out_of_memory(); 51270884Sjoe } else if (!strcmp(argv[2], "objdir")) { 51370884Sjoe if(argc != 4) 51470884Sjoe goto argcount; 51570884Sjoe if((p->objdir = strdup(argv[3])) == NULL) 51670884Sjoe out_of_memory(); 51770884Sjoe } else if (!strcmp(argv[2], "objs")) { 51870884Sjoe p->objs = NULL; 51970884Sjoe for (i = 3; i < argc; i++) 52070884Sjoe add_string(&p->objs, argv[i]); 52170884Sjoe } else if (!strcmp(argv[2], "objpaths")) { 52270884Sjoe p->objpaths = NULL; 52370884Sjoe for (i = 3; i < argc; i++) 52470884Sjoe add_string(&p->objpaths, argv[i]); 52570884Sjoe } else if (!strcmp(argv[2], "keep")) { 52670884Sjoe p->keeplist = NULL; 52770884Sjoe for(i = 3; i < argc; i++) 52870884Sjoe add_string(&p->keeplist, argv[i]); 52970884Sjoe } else if (!strcmp(argv[2], "objvar")) { 53070884Sjoe if(argc != 4) 53170884Sjoe goto argcount; 53270884Sjoe if ((p->objvar = strdup(argv[3])) == NULL) 53370884Sjoe out_of_memory(); 53470884Sjoe } else if (!strcmp(argv[2], "buildopts")) { 53570884Sjoe p->buildopts = NULL; 53670884Sjoe for (i = 3; i < argc; i++) 53770884Sjoe add_string(&p->buildopts, argv[i]); 53893435Sluigi } else if (!strcmp(argv[2], "lib")) { 53993435Sluigi for (i = 3; i < argc; i++) 54093435Sluigi add_string(&p->libs, argv[i]); 54170884Sjoe } else { 54270884Sjoe warnx("%s:%d: bad parameter name `%s', skipping line", 54370884Sjoe curfilename, linenum, argv[2]); 54470884Sjoe goterror = 1; 54570884Sjoe } 54670884Sjoe return; 5471722Sjkh 5481722Sjkh argcount: 54970884Sjoe warnx("%s:%d: too %s arguments, expected \"special %s %s <string>\"", 5501722Sjkh curfilename, linenum, argc < 4? "few" : "many", argv[1], argv[2]); 55170884Sjoe goterror = 1; 5521722Sjkh} 5531722Sjkh 5541722Sjkh 5551722Sjkhprog_t *find_prog(char *str) 5561722Sjkh{ 55770884Sjoe prog_t *p; 5581722Sjkh 55970884Sjoe for (p = progs; p != NULL; p = p->next) 56070884Sjoe if (!strcmp(p->name, str)) 56170884Sjoe return p; 5621722Sjkh 56370884Sjoe return NULL; 5641722Sjkh} 5651722Sjkh 5661722Sjkh 5671722Sjkh/* 5681722Sjkh * ======================================================================== 5691722Sjkh * gen_outputs subsystem 5701722Sjkh * 5711722Sjkh */ 5721722Sjkh 5731722Sjkh/* helper subroutines */ 5741722Sjkh 5751722Sjkhvoid remove_error_progs(void); 5761722Sjkhvoid fillin_program(prog_t *p); 5771722Sjkhvoid gen_specials_cache(void); 5781722Sjkhvoid gen_output_makefile(void); 5791722Sjkhvoid gen_output_cfile(void); 5801722Sjkh 5811722Sjkhvoid fillin_program_objs(prog_t *p, char *path); 5821722Sjkhvoid top_makefile_rules(FILE *outmk); 5831722Sjkhvoid prog_makefile_rules(FILE *outmk, prog_t *p); 5841722Sjkhvoid output_strlst(FILE *outf, strlst_t *lst); 5851722Sjkhchar *genident(char *str); 5861722Sjkhchar *dir_search(char *progname); 5871722Sjkh 5881722Sjkh 5891722Sjkhvoid gen_outputs(void) 5901722Sjkh{ 59170884Sjoe prog_t *p; 5921722Sjkh 59370884Sjoe for (p = progs; p != NULL; p = p->next) 59470884Sjoe fillin_program(p); 5951722Sjkh 59670884Sjoe remove_error_progs(); 59770884Sjoe gen_specials_cache(); 59870884Sjoe gen_output_cfile(); 59970884Sjoe gen_output_makefile(); 60070884Sjoe status(""); 60170884Sjoe fprintf(stderr, 60270112Sjoe "Run \"make -f %s\" to build crunched binary.\n", outmkname); 6031722Sjkh} 6041722Sjkh 60556995Sluigi/* 60656995Sluigi * run the makefile for the program to find which objects are necessary 60756995Sluigi */ 6081722Sjkhvoid fillin_program(prog_t *p) 6091722Sjkh{ 61070884Sjoe char path[MAXPATHLEN]; 61170884Sjoe char line[MAXLINELEN]; 61270884Sjoe FILE *f; 6131722Sjkh 61470884Sjoe snprintf(line, MAXLINELEN, "filling in parms for %s", p->name); 61570884Sjoe status(line); 6161722Sjkh 61770884Sjoe if (!p->ident) 61870884Sjoe p->ident = genident(p->name); 61970331Sjoe 62070884Sjoe /* look for the source directory if one wasn't specified by a special */ 62170884Sjoe if (!p->srcdir) { 62270884Sjoe p->srcdir = dir_search(p->name); 62370884Sjoe } 62470112Sjoe 62570884Sjoe /* Determine the actual srcdir (maybe symlinked). */ 62670884Sjoe if (p->srcdir) { 62770884Sjoe snprintf(line, MAXLINELEN, "cd %s && echo -n `/bin/pwd`", 62870884Sjoe p->srcdir); 62970884Sjoe f = popen(line,"r"); 63070884Sjoe if (!f) 63170884Sjoe errx(1, "Can't execute: %s\n", line); 63270331Sjoe 63370884Sjoe path[0] = '\0'; 63470884Sjoe fgets(path, sizeof path, f); 63570884Sjoe if (pclose(f)) 63670884Sjoe errx(1, "Can't execute: %s\n", line); 63770331Sjoe 63870884Sjoe if (!*path) 63970884Sjoe errx(1, "Can't perform pwd on: %s\n", p->srcdir); 64070331Sjoe 64170884Sjoe p->realsrcdir = strdup(path); 64270884Sjoe } 64370112Sjoe 64470884Sjoe /* Unless the option to make object files was specified the 64570884Sjoe * the objects will be built in the source directory unless 64670884Sjoe * an object directory already exists. 64770884Sjoe */ 64870884Sjoe if (!makeobj && !p->objdir && p->srcdir) { 64970884Sjoe snprintf(line, sizeof line, "%s/%s", objprefix, p->realsrcdir); 65070884Sjoe if (is_dir(line)) { 65170884Sjoe if ((p->objdir = strdup(line)) == NULL) 65270884Sjoe out_of_memory(); 65370884Sjoe } else 65470884Sjoe p->objdir = p->realsrcdir; 65570884Sjoe } 65670884Sjoe 65770884Sjoe /* 65870884Sjoe * XXX look for a Makefile.{name} in local directory first. 65970884Sjoe * This lets us override the original Makefile. 66070884Sjoe */ 66170884Sjoe snprintf(path, sizeof(path), "Makefile.%s", p->name); 66270884Sjoe if (is_nonempty_file(path)) { 66370884Sjoe snprintf(line, MAXLINELEN, "Using %s for %s", path, p->name); 66470884Sjoe status(line); 66570114Sjoe } else 66670884Sjoe if (p->srcdir) 66770884Sjoe snprintf(path, sizeof(path), "%s/Makefile", p->srcdir); 66870884Sjoe if (!p->objs && p->srcdir && is_nonempty_file(path)) 66970884Sjoe fillin_program_objs(p, path); 6701722Sjkh 67181700Sjoe if (!p->srcdir && !p->objdir && verbose) 67270884Sjoe warnx("%s: %s: %s", 67370884Sjoe "warning: could not find source directory", 67470884Sjoe infilename, p->name); 67570884Sjoe if (!p->objs && verbose) 67670884Sjoe warnx("%s: %s: warning: could not find any .o files", 67770884Sjoe infilename, p->name); 67870880Sjoe 67981823Sjoe if ((!p->srcdir || !p->objdir) && !p->objs) 68070884Sjoe p->goterror = 1; 6811722Sjkh} 6821722Sjkh 6831722Sjkhvoid fillin_program_objs(prog_t *p, char *path) 6841722Sjkh{ 68570884Sjoe char *obj, *cp; 68670884Sjoe int fd, rc; 68770884Sjoe FILE *f; 68870884Sjoe char *objvar="OBJS"; 68970884Sjoe strlst_t *s; 69070884Sjoe char line[MAXLINELEN]; 6911722Sjkh 69270884Sjoe /* discover the objs from the srcdir Makefile */ 6931722Sjkh 69470884Sjoe if ((fd = mkstemp(tempfname)) == -1) { 69570884Sjoe perror(tempfname); 69670884Sjoe exit(1); 69770884Sjoe } 69870884Sjoe if ((f = fdopen(fd, "w")) == NULL) { 69970884Sjoe warn("%s", tempfname); 70070884Sjoe goterror = 1; 70170884Sjoe return; 70270884Sjoe } 70370884Sjoe if (p->objvar) 70470884Sjoe objvar = p->objvar; 7058857Srgrimes 70670884Sjoe /* 70770884Sjoe * XXX include outhdrname (e.g. to contain Make variables) 70870884Sjoe */ 70970884Sjoe if (outhdrname[0] != '\0') 71070884Sjoe fprintf(f, ".include \"%s\"\n", outhdrname); 71170884Sjoe fprintf(f, ".include \"%s\"\n", path); 71270884Sjoe if (buildopts) { 71370884Sjoe fprintf(f, "BUILDOPTS+="); 71470884Sjoe output_strlst(f, buildopts); 71570884Sjoe } 71670884Sjoe fprintf(f, ".if defined(PROG) && !defined(%s)\n", objvar); 71770884Sjoe fprintf(f, "%s=${PROG}.o\n", objvar); 71870884Sjoe fprintf(f, ".endif\n"); 71970884Sjoe fprintf(f, "loop:\n\t@echo 'OBJS= '${%s}\n", objvar); 72068569Sjoe 721113886Sru fprintf(f, "crunchgen_objs:\n" 722113886Sru "\t@cd %s && make -f %s $(BUILDOPTS) $(%s_OPTS)", 723113886Sru p->srcdir, tempfname, p->ident); 72470884Sjoe for (s = p->buildopts; s != NULL; s = s->next) 72570884Sjoe fprintf(f, " %s", s->str); 72670884Sjoe fprintf(f, " loop\n"); 72768569Sjoe 72870884Sjoe fclose(f); 7291722Sjkh 730140509Sru snprintf(line, MAXLINELEN, "cd %s && make -f %s crunchgen_objs", 731113855Sru p->srcdir, tempfname); 73270884Sjoe if ((f = popen(line, "r")) == NULL) { 73370884Sjoe warn("submake pipe"); 73470884Sjoe goterror = 1; 73570884Sjoe return; 73670884Sjoe } 7371722Sjkh 73870884Sjoe while(fgets(line, MAXLINELEN, f)) { 73970884Sjoe if (strncmp(line, "OBJS= ", 6)) { 74070884Sjoe warnx("make error: %s", line); 74170884Sjoe goterror = 1; 74270884Sjoe continue; 74370884Sjoe } 74470884Sjoe 74570884Sjoe cp = line + 6; 74670884Sjoe while (isspace(*cp)) 74770884Sjoe cp++; 74870884Sjoe 74970884Sjoe while(*cp) { 75070884Sjoe obj = cp; 75170884Sjoe while (*cp && !isspace(*cp)) 75270884Sjoe cp++; 75370884Sjoe if (*cp) 75470884Sjoe *cp++ = '\0'; 75570884Sjoe add_string(&p->objs, obj); 75670884Sjoe while (isspace(*cp)) 75770884Sjoe cp++; 75870884Sjoe } 7591722Sjkh } 76070884Sjoe 76170884Sjoe if ((rc=pclose(f)) != 0) { 76270884Sjoe warnx("make error: make returned %d", rc); 76370884Sjoe goterror = 1; 7641722Sjkh } 76570884Sjoe 76670884Sjoe unlink(tempfname); 7671722Sjkh} 7681722Sjkh 7691722Sjkhvoid remove_error_progs(void) 7701722Sjkh{ 77170884Sjoe prog_t *p1, *p2; 7721722Sjkh 77370884Sjoe p1 = NULL; p2 = progs; 77470884Sjoe while (p2 != NULL) { 77570884Sjoe if (!p2->goterror) 77670884Sjoe p1 = p2, p2 = p2->next; 77770884Sjoe else { 77870884Sjoe /* delete it from linked list */ 77970884Sjoe warnx("%s: %s: ignoring program because of errors", 78070884Sjoe infilename, p2->name); 78170884Sjoe if (p1) 78270884Sjoe p1->next = p2->next; 78370884Sjoe else 78470884Sjoe progs = p2->next; 78570884Sjoe p2 = p2->next; 78670884Sjoe } 7871722Sjkh } 7881722Sjkh} 7891722Sjkh 7901722Sjkhvoid gen_specials_cache(void) 7911722Sjkh{ 79270884Sjoe FILE *cachef; 79370884Sjoe prog_t *p; 79470884Sjoe char line[MAXLINELEN]; 7951722Sjkh 79670884Sjoe snprintf(line, MAXLINELEN, "generating %s", cachename); 79770884Sjoe status(line); 7981722Sjkh 79970884Sjoe if ((cachef = fopen(cachename, "w")) == NULL) { 80070884Sjoe warn("%s", cachename); 80170884Sjoe goterror = 1; 80270884Sjoe return; 80370884Sjoe } 8041722Sjkh 80570884Sjoe fprintf(cachef, "# %s - parm cache generated from %s by crunchgen " 80670884Sjoe " %s\n\n", 8071722Sjkh cachename, infilename, CRUNCH_VERSION); 8081722Sjkh 80970884Sjoe for (p = progs; p != NULL; p = p->next) { 81070884Sjoe fprintf(cachef, "\n"); 81170884Sjoe if (p->srcdir) 81270884Sjoe fprintf(cachef, "special %s srcdir %s\n", 81370884Sjoe p->name, p->srcdir); 81470884Sjoe if (p->objdir) 81570884Sjoe fprintf(cachef, "special %s objdir %s\n", 81670884Sjoe p->name, p->objdir); 81770884Sjoe if (p->objs) { 81870884Sjoe fprintf(cachef, "special %s objs", p->name); 81970884Sjoe output_strlst(cachef, p->objs); 82070884Sjoe } 82170884Sjoe if (p->objpaths) { 82270884Sjoe fprintf(cachef, "special %s objpaths", p->name); 82370884Sjoe output_strlst(cachef, p->objpaths); 82470884Sjoe } 8251722Sjkh } 82670884Sjoe fclose(cachef); 8271722Sjkh} 8281722Sjkh 8291722Sjkh 8301722Sjkhvoid gen_output_makefile(void) 8311722Sjkh{ 83270884Sjoe prog_t *p; 83370884Sjoe FILE *outmk; 83470884Sjoe char line[MAXLINELEN]; 8351722Sjkh 83670884Sjoe snprintf(line, MAXLINELEN, "generating %s", outmkname); 83770884Sjoe status(line); 8381722Sjkh 83970884Sjoe if ((outmk = fopen(outmkname, "w")) == NULL) { 84070884Sjoe warn("%s", outmkname); 84170884Sjoe goterror = 1; 84270884Sjoe return; 84370884Sjoe } 8441722Sjkh 84570884Sjoe fprintf(outmk, "# %s - generated from %s by crunchgen %s\n\n", 8461722Sjkh outmkname, infilename, CRUNCH_VERSION); 8471722Sjkh 84870884Sjoe if (outhdrname[0] != '\0') 84970884Sjoe fprintf(outmk, ".include \"%s\"\n", outhdrname); 8501722Sjkh 85170884Sjoe top_makefile_rules(outmk); 85270884Sjoe for (p = progs; p != NULL; p = p->next) 85370884Sjoe prog_makefile_rules(outmk, p); 85470884Sjoe 85570884Sjoe fprintf(outmk, "\n# ========\n"); 85670884Sjoe fclose(outmk); 8571722Sjkh} 8581722Sjkh 8591722Sjkh 8601722Sjkhvoid gen_output_cfile(void) 8611722Sjkh{ 86270884Sjoe extern char *crunched_skel[]; 86370884Sjoe char **cp; 86470884Sjoe FILE *outcf; 86570884Sjoe prog_t *p; 86670884Sjoe strlst_t *s; 86770884Sjoe char line[MAXLINELEN]; 8681722Sjkh 86970884Sjoe snprintf(line, MAXLINELEN, "generating %s", outcfname); 87070884Sjoe status(line); 8711722Sjkh 87270884Sjoe if((outcf = fopen(outcfname, "w")) == NULL) { 87370884Sjoe warn("%s", outcfname); 87470884Sjoe goterror = 1; 87570884Sjoe return; 87670884Sjoe } 8771722Sjkh 87870884Sjoe fprintf(outcf, 87970884Sjoe "/* %s - generated from %s by crunchgen %s */\n", 8801722Sjkh outcfname, infilename, CRUNCH_VERSION); 8811722Sjkh 88270884Sjoe fprintf(outcf, "#define EXECNAME \"%s\"\n", execfname); 88370884Sjoe for (cp = crunched_skel; *cp != NULL; cp++) 88470884Sjoe fprintf(outcf, "%s\n", *cp); 8851722Sjkh 88670884Sjoe for (p = progs; p != NULL; p = p->next) 88770884Sjoe fprintf(outcf, "extern int _crunched_%s_stub();\n", p->ident); 8881722Sjkh 88970884Sjoe fprintf(outcf, "\nstruct stub entry_points[] = {\n"); 89070884Sjoe for (p = progs; p != NULL; p = p->next) { 89170884Sjoe fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n", 89270884Sjoe p->name, p->ident); 89370884Sjoe for (s = p->links; s != NULL; s = s->next) 89470884Sjoe fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n", 89570884Sjoe s->str, p->ident); 89670884Sjoe } 8978857Srgrimes 89870884Sjoe fprintf(outcf, "\t{ EXECNAME, crunched_main },\n"); 89970884Sjoe fprintf(outcf, "\t{ NULL, NULL }\n};\n"); 90070884Sjoe fclose(outcf); 9011722Sjkh} 9021722Sjkh 9031722Sjkh 9041722Sjkhchar *genident(char *str) 9051722Sjkh{ 90670884Sjoe char *n, *s, *d; 9071722Sjkh 90870884Sjoe /* 90970884Sjoe * generates a Makefile/C identifier from a program name, 91070884Sjoe * mapping '-' to '_' and ignoring all other non-identifier 91170884Sjoe * characters. This leads to programs named "foo.bar" and 91270884Sjoe * "foobar" to map to the same identifier. 91370884Sjoe */ 9141722Sjkh 91570884Sjoe if ((n = strdup(str)) == NULL) 91670884Sjoe return NULL; 91770884Sjoe for (d = s = n; *s != '\0'; s++) { 91870884Sjoe if (*s == '-') 91970884Sjoe *d++ = '_'; 92070884Sjoe else if (*s == '_' || isalnum(*s)) 92170884Sjoe *d++ = *s; 92270884Sjoe } 92370884Sjoe *d = '\0'; 92470884Sjoe return n; 9251722Sjkh} 9261722Sjkh 9271722Sjkh 9281722Sjkhchar *dir_search(char *progname) 9291722Sjkh{ 93070884Sjoe char path[MAXPATHLEN]; 93170884Sjoe strlst_t *dir; 93270884Sjoe char *srcdir; 9331722Sjkh 93470884Sjoe for (dir = srcdirs; dir != NULL; dir = dir->next) { 93570884Sjoe snprintf(path, MAXPATHLEN, "%s/%s", dir->str, progname); 93670884Sjoe if (!is_dir(path)) 93770884Sjoe continue; 93870884Sjoe 93970884Sjoe if ((srcdir = strdup(path)) == NULL) 94070884Sjoe out_of_memory(); 94170884Sjoe 94270884Sjoe return srcdir; 94370331Sjoe } 94470884Sjoe return NULL; 9451722Sjkh} 9461722Sjkh 9471722Sjkh 9481722Sjkhvoid top_makefile_rules(FILE *outmk) 9491722Sjkh{ 95070884Sjoe prog_t *p; 9511722Sjkh 952153687Sceri if ( subtract_strlst(&libs, &libs_so) ) 953153687Sceri fprintf(outmk, "# NOTE: Some LIBS declarations below overridden by LIBS_SO\n"); 954153687Sceri 95578520Sjoe fprintf(outmk, "LIBS+="); 95670884Sjoe output_strlst(outmk, libs); 9571722Sjkh 958153687Sceri fprintf(outmk, "LIBS_SO+="); 959153687Sceri output_strlst(outmk, libs_so); 960153687Sceri 96170884Sjoe if (makeobj) { 96270884Sjoe fprintf(outmk, "MAKEOBJDIRPREFIX?=%s\n", objprefix); 963133399Sharti fprintf(outmk, "MAKEENV=env MAKEOBJDIRPREFIX=$(MAKEOBJDIRPREFIX)\n"); 964133399Sharti fprintf(outmk, "CRUNCHMAKE=$(MAKEENV) $(MAKE)\n"); 96570884Sjoe } else { 966133399Sharti fprintf(outmk, "CRUNCHMAKE=$(MAKE)\n"); 96770884Sjoe } 96870112Sjoe 96970884Sjoe if (buildopts) { 97070884Sjoe fprintf(outmk, "BUILDOPTS+="); 97170884Sjoe output_strlst(outmk, buildopts); 97270884Sjoe } 97368750Sjoe 97470884Sjoe fprintf(outmk, "CRUNCHED_OBJS="); 97570884Sjoe for (p = progs; p != NULL; p = p->next) 97670884Sjoe fprintf(outmk, " %s.lo", p->name); 97770884Sjoe fprintf(outmk, "\n"); 9781722Sjkh 97970884Sjoe fprintf(outmk, "SUBMAKE_TARGETS="); 98070884Sjoe for (p = progs; p != NULL; p = p->next) 98170884Sjoe fprintf(outmk, " %s_make", p->ident); 98270884Sjoe fprintf(outmk, "\nSUBCLEAN_TARGETS="); 98370884Sjoe for (p = progs; p != NULL; p = p->next) 98470884Sjoe fprintf(outmk, " %s_clean", p->ident); 98570884Sjoe fprintf(outmk, "\n\n"); 9861722Sjkh 98770884Sjoe fprintf(outmk, "all: objs exe\nobjs: $(SUBMAKE_TARGETS)\n"); 98870884Sjoe fprintf(outmk, "exe: %s\n", execfname); 98970884Sjoe fprintf(outmk, "%s: %s.o $(CRUNCHED_OBJS)\n", execfname, execfname); 990153687Sceri fprintf(outmk, ".if defined(LIBS_SO) && !empty(LIBS_SO)\n"); 991153687Sceri fprintf(outmk, "\t$(CC) -o %s %s.o $(CRUNCHED_OBJS) \\\n", 992153687Sceri execfname, execfname); 993153687Sceri fprintf(outmk, "\t\t-Xlinker -Bstatic $(LIBS) \\\n"); 994153687Sceri fprintf(outmk, "\t\t-Xlinker -Bdynamic $(LIBS_SO)\n"); 995153687Sceri fprintf(outmk, ".else\n"); 99670884Sjoe fprintf(outmk, "\t$(CC) -static -o %s %s.o $(CRUNCHED_OBJS) $(LIBS)\n", 9971722Sjkh execfname, execfname); 998153687Sceri fprintf(outmk, ".endif\n"); 99970884Sjoe fprintf(outmk, "\tstrip %s\n", execfname); 100070884Sjoe fprintf(outmk, "realclean: clean subclean\n"); 100170884Sjoe fprintf(outmk, "clean:\n\trm -f %s *.lo *.o *_stub.c\n", execfname); 100270884Sjoe fprintf(outmk, "subclean: $(SUBCLEAN_TARGETS)\n"); 10031722Sjkh} 10041722Sjkh 10051722Sjkh 10061722Sjkhvoid prog_makefile_rules(FILE *outmk, prog_t *p) 10071722Sjkh{ 100870884Sjoe strlst_t *lst; 100930120Sjoerg 101070884Sjoe fprintf(outmk, "\n# -------- %s\n\n", p->name); 10111722Sjkh 101281700Sjoe fprintf(outmk, "%s_OBJDIR=", p->ident); 101381700Sjoe if (p->objdir) 101481700Sjoe fprintf(outmk, "%s", p->objdir); 101581700Sjoe else 101681700Sjoe fprintf(outmk, "$(MAKEOBJDIRPREFIX)/$(%s_REALSRCDIR)\n", 101781700Sjoe p->ident); 101881700Sjoe fprintf(outmk, "\n"); 101981700Sjoe 102070884Sjoe if (p->srcdir && p->objs) { 102170884Sjoe fprintf(outmk, "%s_SRCDIR=%s\n", p->ident, p->srcdir); 102270884Sjoe fprintf(outmk, "%s_REALSRCDIR=%s\n", p->ident, p->realsrcdir); 102370112Sjoe 102470884Sjoe fprintf(outmk, "%s_OBJS=", p->ident); 102570884Sjoe output_strlst(outmk, p->objs); 102670884Sjoe if (p->buildopts != NULL) { 102770884Sjoe fprintf(outmk, "%s_OPTS+=", p->ident); 102870884Sjoe output_strlst(outmk, p->buildopts); 102970884Sjoe } 103070884Sjoe fprintf(outmk, "%s_make:\n", p->ident); 103170884Sjoe fprintf(outmk, "\t(cd $(%s_SRCDIR) && ", p->ident); 103270884Sjoe if (makeobj) 1033133399Sharti fprintf(outmk, "$(CRUNCHMAKE) obj && "); 103470884Sjoe fprintf(outmk, "\\\n"); 1035133399Sharti fprintf(outmk, "\t\t$(CRUNCHMAKE) $(BUILDOPTS) $(%s_OPTS) depend &&", 103670112Sjoe p->ident); 103770884Sjoe fprintf(outmk, "\\\n"); 1038133399Sharti fprintf(outmk, "\t\t$(CRUNCHMAKE) $(BUILDOPTS) $(%s_OPTS) " 103970884Sjoe "$(%s_OBJS))", 104070884Sjoe p->ident, p->ident); 104170884Sjoe fprintf(outmk, "\n"); 104270884Sjoe fprintf(outmk, "%s_clean:\n", p->ident); 1043133399Sharti fprintf(outmk, "\t(cd $(%s_SRCDIR) && $(CRUNCHMAKE) $(BUILDOPTS) clean cleandepend)\n\n", 104470884Sjoe p->ident); 104570884Sjoe } else { 104670884Sjoe fprintf(outmk, "%s_make:\n", p->ident); 104770884Sjoe fprintf(outmk, "\t@echo \"** cannot make objs for %s\"\n\n", 104875152Sru p->name); 104968569Sjoe } 10501722Sjkh 105170884Sjoe fprintf(outmk, "%s_OBJPATHS=", p->ident); 105270884Sjoe if (p->objpaths) 105370884Sjoe output_strlst(outmk, p->objpaths); 105470884Sjoe else { 105570884Sjoe for (lst = p->objs; lst != NULL; lst = lst->next) { 105670884Sjoe fprintf(outmk, " $(%s_OBJDIR)/%s", p->ident, lst->str); 105770884Sjoe } 105870884Sjoe fprintf(outmk, "\n"); 105970112Sjoe } 106093435Sluigi if (p->libs) { 106193435Sluigi fprintf(outmk, "%s_LIBS=", p->ident); 106293435Sluigi output_strlst(outmk, p->libs); 106393435Sluigi } 10641722Sjkh 106570884Sjoe fprintf(outmk, "%s_stub.c:\n", p->name); 106670884Sjoe fprintf(outmk, "\techo \"" 106770884Sjoe "int _crunched_%s_stub(int argc, char **argv, char **envp)" 106870884Sjoe "{return main(argc,argv,envp);}\" >%s_stub.c\n", 10691722Sjkh p->ident, p->name); 107093435Sluigi fprintf(outmk, "%s.lo: %s_stub.o $(%s_OBJPATHS)", 10711722Sjkh p->name, p->name, p->ident); 107293435Sluigi if (p->libs) 107393435Sluigi fprintf(outmk, " $(%s_LIBS)", p->ident); 1074153687Sceri 107593435Sluigi fprintf(outmk, "\n"); 107693435Sluigi fprintf(outmk, "\tld -dc -r -o %s.lo %s_stub.o $(%s_OBJPATHS)", 10771722Sjkh p->name, p->name, p->ident); 107893435Sluigi if (p->libs) 107993435Sluigi fprintf(outmk, " $(%s_LIBS)", p->ident); 108093435Sluigi fprintf(outmk, "\n"); 108170884Sjoe fprintf(outmk, "\tcrunchide -k _crunched_%s_stub ", p->ident); 108270884Sjoe for (lst = p->keeplist; lst != NULL; lst = lst->next) 108370884Sjoe fprintf(outmk, "-k _%s ", lst->str); 108470884Sjoe fprintf(outmk, "%s.lo\n", p->name); 10851722Sjkh} 10861722Sjkh 10871722Sjkhvoid output_strlst(FILE *outf, strlst_t *lst) 10881722Sjkh{ 108970884Sjoe for (; lst != NULL; lst = lst->next) 1090153687Sceri if ( strlen(lst->str) ) 1091153687Sceri fprintf(outf, " %s", lst->str); 109270884Sjoe fprintf(outf, "\n"); 10931722Sjkh} 10941722Sjkh 10951722Sjkh 10961722Sjkh/* 10971722Sjkh * ======================================================================== 10981722Sjkh * general library routines 10991722Sjkh * 11001722Sjkh */ 11011722Sjkh 11021722Sjkhvoid status(char *str) 11031722Sjkh{ 110470884Sjoe static int lastlen = 0; 110570884Sjoe int len, spaces; 11061722Sjkh 110770884Sjoe if (!verbose) 110870884Sjoe return; 11091722Sjkh 111070884Sjoe len = strlen(str); 111170884Sjoe spaces = lastlen - len; 111270884Sjoe if (spaces < 1) 111370884Sjoe spaces = 1; 11141722Sjkh 111570884Sjoe fprintf(stderr, " [%s]%*.*s\r", str, spaces, spaces, " "); 111670884Sjoe fflush(stderr); 111770884Sjoe lastlen = len; 11181722Sjkh} 11191722Sjkh 11201722Sjkh 11211722Sjkhvoid out_of_memory(void) 11221722Sjkh{ 112370884Sjoe err(1, "%s: %d: out of memory, stopping", infilename, linenum); 11241722Sjkh} 11251722Sjkh 11261722Sjkh 11271722Sjkhvoid add_string(strlst_t **listp, char *str) 11281722Sjkh{ 112970884Sjoe strlst_t *p1, *p2; 11301722Sjkh 113170884Sjoe /* add to end, but be smart about dups */ 11321722Sjkh 113370884Sjoe for (p1 = NULL, p2 = *listp; p2 != NULL; p1 = p2, p2 = p2->next) 113470884Sjoe if (!strcmp(p2->str, str)) 113570884Sjoe return; 11361722Sjkh 113770884Sjoe p2 = malloc(sizeof(strlst_t)); 113870884Sjoe if (p2) { 113970884Sjoe p2->next = NULL; 114070884Sjoe p2->str = strdup(str); 114170884Sjoe } 114270884Sjoe if (!p2 || !p2->str) 114370884Sjoe out_of_memory(); 11441722Sjkh 114570884Sjoe if (p1 == NULL) 114670884Sjoe *listp = p2; 114770884Sjoe else 114870884Sjoe p1->next = p2; 11491722Sjkh} 11501722Sjkh 1151153687Sceriint subtract_strlst(strlst_t **lista, strlst_t **listb) 1152153687Sceri{ 1153153687Sceri int subtract_count = 0; 1154153687Sceri strlst_t *p1; 1155153687Sceri for (p1 = *listb; p1 != NULL; p1 = p1->next) 1156153687Sceri if ( in_list(lista, p1->str) ) { 1157153687Sceri warnx("Will compile library `%s' dynamically", p1->str); 1158153687Sceri strcat(p1->str, ""); 1159153687Sceri subtract_count++; 1160153687Sceri } 1161153687Sceri return subtract_count; 1162153687Sceri} 11631722Sjkh 1164153687Sceriint in_list(strlst_t **listp, char *str) 1165153687Sceri{ 1166153687Sceri strlst_t *p1; 1167153687Sceri for (p1 = *listp; p1 != NULL; p1 = p1->next) 1168153687Sceri if (!strcmp(p1->str, str)) 1169153687Sceri return 1; 1170153687Sceri return 0; 1171153687Sceri} 1172153687Sceri 11731722Sjkhint is_dir(char *pathname) 11741722Sjkh{ 117570884Sjoe struct stat buf; 11761722Sjkh 117770884Sjoe if (stat(pathname, &buf) == -1) 117870884Sjoe return 0; 117970884Sjoe 118070884Sjoe return S_ISDIR(buf.st_mode); 11811722Sjkh} 11821722Sjkh 11831722Sjkhint is_nonempty_file(char *pathname) 11841722Sjkh{ 118570884Sjoe struct stat buf; 11861722Sjkh 118770884Sjoe if (stat(pathname, &buf) == -1) 118870884Sjoe return 0; 11891722Sjkh 119070884Sjoe return S_ISREG(buf.st_mode) && buf.st_size > 0; 11911722Sjkh} 1192