crunchgen.c revision 113886
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 113886 2003-04-23 04:28:35Z ru $ 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; 7770884Sjoe int goterror; 781722Sjkh} prog_t; 791722Sjkh 801722Sjkh 811722Sjkh/* global state */ 821722Sjkh 8368750Sjoestrlst_t *buildopts = NULL; 8470884Sjoestrlst_t *srcdirs = NULL; 8570884Sjoestrlst_t *libs = NULL; 8670884Sjoeprog_t *progs = NULL; 871722Sjkh 881722Sjkhchar confname[MAXPATHLEN], infilename[MAXPATHLEN]; 891722Sjkhchar outmkname[MAXPATHLEN], outcfname[MAXPATHLEN], execfname[MAXPATHLEN]; 901722Sjkhchar tempfname[MAXPATHLEN], cachename[MAXPATHLEN], curfilename[MAXPATHLEN]; 9170884Sjoechar outhdrname[MAXPATHLEN] ; /* user-supplied header for *.mk */ 9270884Sjoechar *objprefix; /* where are the objects ? */ 931722Sjkhint linenum = -1; 941722Sjkhint goterror = 0; 951722Sjkh 9670884Sjoeint verbose, readcache; /* options */ 971722Sjkhint reading_cache; 9870884Sjoeint makeobj = 0; /* add 'make obj' rules to the makefile */ 991722Sjkh 1006696Sphkint list_mode; 1016696Sphk 1021722Sjkh/* general library routines */ 1031722Sjkh 1041722Sjkhvoid status(char *str); 1051722Sjkhvoid out_of_memory(void); 1061722Sjkhvoid add_string(strlst_t **listp, char *str); 1071722Sjkhint is_dir(char *pathname); 1081722Sjkhint is_nonempty_file(char *pathname); 1091722Sjkh 1101722Sjkh/* helper routines for main() */ 1111722Sjkh 1128857Srgrimesvoid usage(void); 1131722Sjkhvoid parse_conf_file(void); 1141722Sjkhvoid gen_outputs(void); 1151722Sjkh 1161722Sjkh 1171722Sjkhint main(int argc, char **argv) 1181722Sjkh{ 11970884Sjoe char *p; 12070884Sjoe int optc; 1211722Sjkh 12270884Sjoe verbose = 1; 12370884Sjoe readcache = 1; 12470884Sjoe *outmkname = *outcfname = *execfname = '\0'; 1258857Srgrimes 12670884Sjoe p = getenv("MAKEOBJDIRPREFIX"); 12770884Sjoe if (p == NULL || *p == '\0') 12870884Sjoe objprefix = "/usr/obj"; /* default */ 12970884Sjoe else 13070884Sjoe if ((objprefix = strdup(p)) == NULL) 13170884Sjoe out_of_memory(); 13269413Sluigi 13370884Sjoe while((optc = getopt(argc, argv, "lh:m:c:e:p:foq")) != -1) { 13470884Sjoe switch(optc) { 13570884Sjoe case 'f': 13670884Sjoe readcache = 0; 13770884Sjoe break; 13870884Sjoe case 'o': 13970884Sjoe makeobj = 1; 14070884Sjoe break; 14170884Sjoe case 'q': 14270884Sjoe verbose = 0; 14370884Sjoe break; 1441722Sjkh 14570884Sjoe case 'm': 14670884Sjoe strlcpy(outmkname, optarg, sizeof(outmkname)); 14770884Sjoe break; 14870884Sjoe case 'p': 14970884Sjoe if ((objprefix = strdup(optarg)) == NULL) 15070113Sjoe out_of_memory(); 15170113Sjoe break; 1521722Sjkh 15370884Sjoe case 'h': 15470884Sjoe strlcpy(outhdrname, optarg, sizeof(outhdrname)); 15570884Sjoe break; 15670884Sjoe case 'c': 15770884Sjoe strlcpy(outcfname, optarg, sizeof(outcfname)); 15870884Sjoe break; 15970884Sjoe case 'e': 16070884Sjoe strlcpy(execfname, optarg, sizeof(execfname)); 16170884Sjoe break; 16270884Sjoe 16370884Sjoe case 'l': 16470884Sjoe list_mode++; 16570884Sjoe verbose = 0; 16670884Sjoe break; 16770884Sjoe 16870884Sjoe case '?': 16970884Sjoe default: 17070884Sjoe usage(); 17170884Sjoe } 1721722Sjkh } 1731722Sjkh 17470884Sjoe argc -= optind; 17570884Sjoe argv += optind; 1761722Sjkh 17770884Sjoe if (argc != 1) 17870884Sjoe usage(); 1791722Sjkh 18070884Sjoe /* 18170884Sjoe * generate filenames 18270884Sjoe */ 1831722Sjkh 18470884Sjoe strlcpy(infilename, argv[0], sizeof(infilename)); 1851722Sjkh 18670884Sjoe /* confname = `basename infilename .conf` */ 1871722Sjkh 18870884Sjoe if ((p=strrchr(infilename, '/')) != NULL) 18970884Sjoe strlcpy(confname, p + 1, sizeof(confname)); 19070884Sjoe else 19170884Sjoe strlcpy(confname, infilename, sizeof(confname)); 1921722Sjkh 19370884Sjoe if ((p=strrchr(confname, '.')) != NULL && !strcmp(p, ".conf")) 19470884Sjoe *p = '\0'; 1951722Sjkh 19670884Sjoe if (!*outmkname) 19770884Sjoe snprintf(outmkname, sizeof(outmkname), "%s.mk", confname); 19870884Sjoe if (!*outcfname) 19970884Sjoe snprintf(outcfname, sizeof(outcfname), "%s.c", confname); 20070884Sjoe if (!*execfname) 20170884Sjoe snprintf(execfname, sizeof(execfname), "%s", confname); 20270884Sjoe 20370884Sjoe snprintf(cachename, sizeof(cachename), "%s.cache", confname); 20470884Sjoe snprintf(tempfname, sizeof(tempfname), "%s/crunchgen_%sXXXXXX", 20570124Sjoe getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP, confname); 2061722Sjkh 20770884Sjoe parse_conf_file(); 20870884Sjoe if (list_mode) 20970884Sjoe exit(goterror); 2106696Sphk 21170884Sjoe gen_outputs(); 2121722Sjkh 21370884Sjoe exit(goterror); 2141722Sjkh} 2151722Sjkh 2161722Sjkh 2171722Sjkhvoid usage(void) 2181722Sjkh{ 21970884Sjoe fprintf(stderr, "%s%s\n\t%s%s\n", "usage: crunchgen [-foq] ", 22070884Sjoe "[-h <makefile-header-name>] [-m <makefile>]", 22170884Sjoe "[-p <obj-prefix>] [-c <c-file-name>] [-e <exec-file>] ", 22270884Sjoe "<conffile>"); 22370884Sjoe exit(1); 2241722Sjkh} 2251722Sjkh 2261722Sjkh 2271722Sjkh/* 2281722Sjkh * ======================================================================== 2291722Sjkh * parse_conf_file subsystem 2301722Sjkh * 2311722Sjkh */ 2321722Sjkh 2331722Sjkh/* helper routines for parse_conf_file */ 2341722Sjkh 2351722Sjkhvoid parse_one_file(char *filename); 2368857Srgrimesvoid parse_line(char *line, int *fc, char **fv, int nf); 2371722Sjkhvoid add_srcdirs(int argc, char **argv); 2381722Sjkhvoid add_progs(int argc, char **argv); 2391722Sjkhvoid add_link(int argc, char **argv); 2401722Sjkhvoid add_libs(int argc, char **argv); 24168750Sjoevoid add_buildopts(int argc, char **argv); 2421722Sjkhvoid add_special(int argc, char **argv); 2431722Sjkh 2441722Sjkhprog_t *find_prog(char *str); 2451722Sjkhvoid add_prog(char *progname); 2461722Sjkh 2471722Sjkh 2481722Sjkhvoid parse_conf_file(void) 2491722Sjkh{ 25070884Sjoe if (!is_nonempty_file(infilename)) 25129453Scharnier errx(1, "fatal: input file \"%s\" not found", infilename); 25270884Sjoe 25370884Sjoe parse_one_file(infilename); 25470884Sjoe if (readcache && is_nonempty_file(cachename)) { 25570884Sjoe reading_cache = 1; 25670884Sjoe parse_one_file(cachename); 25770884Sjoe } 2581722Sjkh} 2591722Sjkh 2601722Sjkh 2611722Sjkhvoid parse_one_file(char *filename) 2621722Sjkh{ 26370884Sjoe char *fieldv[MAXFIELDS]; 26470884Sjoe int fieldc; 26570884Sjoe void (*f)(int c, char **v); 26670884Sjoe FILE *cf; 26770884Sjoe char line[MAXLINELEN]; 2681722Sjkh 26970884Sjoe snprintf(line, sizeof(line), "reading %s", filename); 27070884Sjoe status(line); 27170884Sjoe strlcpy(curfilename, filename, sizeof(curfilename)); 2721722Sjkh 27370884Sjoe if ((cf = fopen(curfilename, "r")) == NULL) { 27470884Sjoe warn("%s", curfilename); 27570884Sjoe goterror = 1; 27670884Sjoe return; 27770884Sjoe } 2781722Sjkh 27970884Sjoe linenum = 0; 28070884Sjoe while (fgets(line, MAXLINELEN, cf) != NULL) { 28170884Sjoe linenum++; 28270884Sjoe parse_line(line, &fieldc, fieldv, MAXFIELDS); 28370884Sjoe 28470884Sjoe if (fieldc < 1) 28570884Sjoe continue; 28670884Sjoe 28770884Sjoe if (!strcmp(fieldv[0], "srcdirs")) 28870884Sjoe f = add_srcdirs; 28970884Sjoe else if(!strcmp(fieldv[0], "progs")) 29070884Sjoe f = add_progs; 29170884Sjoe else if(!strcmp(fieldv[0], "ln")) 29270884Sjoe f = add_link; 29370884Sjoe else if(!strcmp(fieldv[0], "libs")) 29470884Sjoe f = add_libs; 29570884Sjoe else if(!strcmp(fieldv[0], "buildopts")) 29670884Sjoe f = add_buildopts; 29770884Sjoe else if(!strcmp(fieldv[0], "special")) 29870884Sjoe f = add_special; 29970884Sjoe else { 30070884Sjoe warnx("%s:%d: skipping unknown command `%s'", 30170884Sjoe curfilename, linenum, fieldv[0]); 30270884Sjoe goterror = 1; 30370884Sjoe continue; 30470884Sjoe } 30570884Sjoe 30670884Sjoe if (fieldc < 2) { 30770884Sjoe warnx("%s:%d: %s %s", 30870884Sjoe curfilename, linenum, fieldv[0], 30970884Sjoe "command needs at least 1 argument, skipping"); 31070884Sjoe goterror = 1; 31170884Sjoe continue; 31270884Sjoe } 31370884Sjoe 31470884Sjoe f(fieldc, fieldv); 3151722Sjkh } 31670884Sjoe 31770884Sjoe if (ferror(cf)) { 31870884Sjoe warn("%s", curfilename); 31970884Sjoe goterror = 1; 3201722Sjkh } 32170884Sjoe fclose(cf); 3221722Sjkh} 3231722Sjkh 3241722Sjkh 3251722Sjkhvoid parse_line(char *line, int *fc, char **fv, int nf) 3261722Sjkh{ 32770884Sjoe char *p; 3281722Sjkh 32970884Sjoe p = line; 33070884Sjoe *fc = 0; 3311722Sjkh 33270884Sjoe while (1) { 33370884Sjoe while (isspace(*p)) 33470884Sjoe p++; 33570884Sjoe 33670884Sjoe if (*p == '\0' || *p == '#') 33770884Sjoe break; 33870884Sjoe 33970884Sjoe if (*fc < nf) 34070884Sjoe fv[(*fc)++] = p; 34170884Sjoe 34270884Sjoe while (*p && !isspace(*p) && *p != '#') 34370884Sjoe p++; 34470884Sjoe 34570884Sjoe if (*p == '\0' || *p == '#') 34670884Sjoe break; 34770884Sjoe 34870884Sjoe *p++ = '\0'; 34970884Sjoe } 35070884Sjoe 35170884Sjoe if (*p) 35270884Sjoe *p = '\0'; /* needed for '#' case */ 3531722Sjkh} 3541722Sjkh 3551722Sjkh 3561722Sjkhvoid add_srcdirs(int argc, char **argv) 3571722Sjkh{ 35870884Sjoe int i; 3591722Sjkh 36070884Sjoe for (i = 1; i < argc; i++) { 36170884Sjoe if (is_dir(argv[i])) 36270884Sjoe add_string(&srcdirs, argv[i]); 36370884Sjoe else { 36470884Sjoe warnx("%s:%d: `%s' is not a directory, skipping it", 36570884Sjoe curfilename, linenum, argv[i]); 36670884Sjoe goterror = 1; 36770884Sjoe } 3681722Sjkh } 3691722Sjkh} 3701722Sjkh 3711722Sjkh 3721722Sjkhvoid add_progs(int argc, char **argv) 3731722Sjkh{ 37470884Sjoe int i; 3751722Sjkh 37670884Sjoe for (i = 1; i < argc; i++) 37770884Sjoe add_prog(argv[i]); 3781722Sjkh} 3791722Sjkh 3801722Sjkh 3811722Sjkhvoid add_prog(char *progname) 3821722Sjkh{ 38370884Sjoe prog_t *p1, *p2; 3841722Sjkh 38570884Sjoe /* add to end, but be smart about dups */ 3861722Sjkh 38770884Sjoe for (p1 = NULL, p2 = progs; p2 != NULL; p1 = p2, p2 = p2->next) 38870884Sjoe if (!strcmp(p2->name, progname)) 38970884Sjoe return; 3901722Sjkh 39170884Sjoe p2 = malloc(sizeof(prog_t)); 39270884Sjoe if(p2) { 39370884Sjoe memset(p2, 0, sizeof(prog_t)); 39470884Sjoe p2->name = strdup(progname); 39570884Sjoe } 39670884Sjoe if (!p2 || !p2->name) 39770884Sjoe out_of_memory(); 3981722Sjkh 39970884Sjoe p2->next = NULL; 40070884Sjoe if (p1 == NULL) 40170884Sjoe progs = p2; 40270884Sjoe else 40370884Sjoe p1->next = p2; 4041722Sjkh 40570884Sjoe p2->ident = NULL; 40670884Sjoe p2->srcdir = NULL; 40770884Sjoe p2->realsrcdir = NULL; 40870884Sjoe p2->objdir = NULL; 40970884Sjoe p2->links = NULL; 41093435Sluigi p2->libs = NULL; 41170884Sjoe p2->objs = NULL; 41270884Sjoe p2->keeplist = NULL; 41370884Sjoe p2->buildopts = NULL; 41470884Sjoe p2->goterror = 0; 41570884Sjoe 41670884Sjoe if (list_mode) 41770884Sjoe printf("%s\n",progname); 4181722Sjkh} 4191722Sjkh 4201722Sjkh 4211722Sjkhvoid add_link(int argc, char **argv) 4221722Sjkh{ 42370884Sjoe int i; 42470884Sjoe prog_t *p = find_prog(argv[1]); 4251722Sjkh 42670884Sjoe if (p == NULL) { 42770884Sjoe warnx("%s:%d: no prog %s previously declared, skipping link", 42870884Sjoe curfilename, linenum, argv[1]); 42970884Sjoe goterror = 1; 43070884Sjoe return; 43170884Sjoe } 43270884Sjoe 43370884Sjoe for (i = 2; i < argc; i++) { 43470884Sjoe if (list_mode) 43570884Sjoe printf("%s\n",argv[i]); 43670884Sjoe 43770884Sjoe add_string(&p->links, argv[i]); 43870884Sjoe } 4391722Sjkh} 4401722Sjkh 4411722Sjkh 4421722Sjkhvoid add_libs(int argc, char **argv) 4431722Sjkh{ 44470884Sjoe int i; 4451722Sjkh 44670884Sjoe for(i = 1; i < argc; i++) 44770884Sjoe add_string(&libs, argv[i]); 4481722Sjkh} 4491722Sjkh 4501722Sjkh 45168750Sjoevoid add_buildopts(int argc, char **argv) 45268750Sjoe{ 45370884Sjoe int i; 45468750Sjoe 45570884Sjoe for (i = 1; i < argc; i++) 45670884Sjoe add_string(&buildopts, argv[i]); 45768750Sjoe} 45868750Sjoe 45968750Sjoe 4601722Sjkhvoid add_special(int argc, char **argv) 4611722Sjkh{ 46270884Sjoe int i; 46370884Sjoe prog_t *p = find_prog(argv[1]); 4641722Sjkh 46570884Sjoe if (p == NULL) { 46670884Sjoe if (reading_cache) 46770884Sjoe return; 4681722Sjkh 46970884Sjoe warnx("%s:%d: no prog %s previously declared, skipping special", 47070884Sjoe curfilename, linenum, argv[1]); 47170884Sjoe goterror = 1; 47270884Sjoe return; 47370884Sjoe } 4741722Sjkh 47570884Sjoe if (!strcmp(argv[2], "ident")) { 47670884Sjoe if (argc != 4) 47770884Sjoe goto argcount; 47870884Sjoe if ((p->ident = strdup(argv[3])) == NULL) 47970884Sjoe out_of_memory(); 48070884Sjoe } else if (!strcmp(argv[2], "srcdir")) { 48170884Sjoe if (argc != 4) 48270884Sjoe goto argcount; 48370884Sjoe if ((p->srcdir = strdup(argv[3])) == NULL) 48470884Sjoe out_of_memory(); 48570884Sjoe } else if (!strcmp(argv[2], "objdir")) { 48670884Sjoe if(argc != 4) 48770884Sjoe goto argcount; 48870884Sjoe if((p->objdir = strdup(argv[3])) == NULL) 48970884Sjoe out_of_memory(); 49070884Sjoe } else if (!strcmp(argv[2], "objs")) { 49170884Sjoe p->objs = NULL; 49270884Sjoe for (i = 3; i < argc; i++) 49370884Sjoe add_string(&p->objs, argv[i]); 49470884Sjoe } else if (!strcmp(argv[2], "objpaths")) { 49570884Sjoe p->objpaths = NULL; 49670884Sjoe for (i = 3; i < argc; i++) 49770884Sjoe add_string(&p->objpaths, argv[i]); 49870884Sjoe } else if (!strcmp(argv[2], "keep")) { 49970884Sjoe p->keeplist = NULL; 50070884Sjoe for(i = 3; i < argc; i++) 50170884Sjoe add_string(&p->keeplist, argv[i]); 50270884Sjoe } else if (!strcmp(argv[2], "objvar")) { 50370884Sjoe if(argc != 4) 50470884Sjoe goto argcount; 50570884Sjoe if ((p->objvar = strdup(argv[3])) == NULL) 50670884Sjoe out_of_memory(); 50770884Sjoe } else if (!strcmp(argv[2], "buildopts")) { 50870884Sjoe p->buildopts = NULL; 50970884Sjoe for (i = 3; i < argc; i++) 51070884Sjoe add_string(&p->buildopts, argv[i]); 51193435Sluigi } else if (!strcmp(argv[2], "lib")) { 51293435Sluigi for (i = 3; i < argc; i++) 51393435Sluigi add_string(&p->libs, argv[i]); 51470884Sjoe } else { 51570884Sjoe warnx("%s:%d: bad parameter name `%s', skipping line", 51670884Sjoe curfilename, linenum, argv[2]); 51770884Sjoe goterror = 1; 51870884Sjoe } 51970884Sjoe return; 5201722Sjkh 5211722Sjkh argcount: 52270884Sjoe warnx("%s:%d: too %s arguments, expected \"special %s %s <string>\"", 5231722Sjkh curfilename, linenum, argc < 4? "few" : "many", argv[1], argv[2]); 52470884Sjoe goterror = 1; 5251722Sjkh} 5261722Sjkh 5271722Sjkh 5281722Sjkhprog_t *find_prog(char *str) 5291722Sjkh{ 53070884Sjoe prog_t *p; 5311722Sjkh 53270884Sjoe for (p = progs; p != NULL; p = p->next) 53370884Sjoe if (!strcmp(p->name, str)) 53470884Sjoe return p; 5351722Sjkh 53670884Sjoe return NULL; 5371722Sjkh} 5381722Sjkh 5391722Sjkh 5401722Sjkh/* 5411722Sjkh * ======================================================================== 5421722Sjkh * gen_outputs subsystem 5431722Sjkh * 5441722Sjkh */ 5451722Sjkh 5461722Sjkh/* helper subroutines */ 5471722Sjkh 5481722Sjkhvoid remove_error_progs(void); 5491722Sjkhvoid fillin_program(prog_t *p); 5501722Sjkhvoid gen_specials_cache(void); 5511722Sjkhvoid gen_output_makefile(void); 5521722Sjkhvoid gen_output_cfile(void); 5531722Sjkh 5541722Sjkhvoid fillin_program_objs(prog_t *p, char *path); 5551722Sjkhvoid top_makefile_rules(FILE *outmk); 5561722Sjkhvoid prog_makefile_rules(FILE *outmk, prog_t *p); 5571722Sjkhvoid output_strlst(FILE *outf, strlst_t *lst); 5581722Sjkhchar *genident(char *str); 5591722Sjkhchar *dir_search(char *progname); 5601722Sjkh 5611722Sjkh 5621722Sjkhvoid gen_outputs(void) 5631722Sjkh{ 56470884Sjoe prog_t *p; 5651722Sjkh 56670884Sjoe for (p = progs; p != NULL; p = p->next) 56770884Sjoe fillin_program(p); 5681722Sjkh 56970884Sjoe remove_error_progs(); 57070884Sjoe gen_specials_cache(); 57170884Sjoe gen_output_cfile(); 57270884Sjoe gen_output_makefile(); 57370884Sjoe status(""); 57470884Sjoe fprintf(stderr, 57570112Sjoe "Run \"make -f %s\" to build crunched binary.\n", outmkname); 5761722Sjkh} 5771722Sjkh 57856995Sluigi/* 57956995Sluigi * run the makefile for the program to find which objects are necessary 58056995Sluigi */ 5811722Sjkhvoid fillin_program(prog_t *p) 5821722Sjkh{ 58370884Sjoe char path[MAXPATHLEN]; 58470884Sjoe char line[MAXLINELEN]; 58570884Sjoe FILE *f; 5861722Sjkh 58770884Sjoe snprintf(line, MAXLINELEN, "filling in parms for %s", p->name); 58870884Sjoe status(line); 5891722Sjkh 59070884Sjoe if (!p->ident) 59170884Sjoe p->ident = genident(p->name); 59270331Sjoe 59370884Sjoe /* look for the source directory if one wasn't specified by a special */ 59470884Sjoe if (!p->srcdir) { 59570884Sjoe p->srcdir = dir_search(p->name); 59670884Sjoe } 59770112Sjoe 59870884Sjoe /* Determine the actual srcdir (maybe symlinked). */ 59970884Sjoe if (p->srcdir) { 60070884Sjoe snprintf(line, MAXLINELEN, "cd %s && echo -n `/bin/pwd`", 60170884Sjoe p->srcdir); 60270884Sjoe f = popen(line,"r"); 60370884Sjoe if (!f) 60470884Sjoe errx(1, "Can't execute: %s\n", line); 60570331Sjoe 60670884Sjoe path[0] = '\0'; 60770884Sjoe fgets(path, sizeof path, f); 60870884Sjoe if (pclose(f)) 60970884Sjoe errx(1, "Can't execute: %s\n", line); 61070331Sjoe 61170884Sjoe if (!*path) 61270884Sjoe errx(1, "Can't perform pwd on: %s\n", p->srcdir); 61370331Sjoe 61470884Sjoe p->realsrcdir = strdup(path); 61570884Sjoe } 61670112Sjoe 61770884Sjoe /* Unless the option to make object files was specified the 61870884Sjoe * the objects will be built in the source directory unless 61970884Sjoe * an object directory already exists. 62070884Sjoe */ 62170884Sjoe if (!makeobj && !p->objdir && p->srcdir) { 62270884Sjoe snprintf(line, sizeof line, "%s/%s", objprefix, p->realsrcdir); 62370884Sjoe if (is_dir(line)) { 62470884Sjoe if ((p->objdir = strdup(line)) == NULL) 62570884Sjoe out_of_memory(); 62670884Sjoe } else 62770884Sjoe p->objdir = p->realsrcdir; 62870884Sjoe } 62970884Sjoe 63070884Sjoe /* 63170884Sjoe * XXX look for a Makefile.{name} in local directory first. 63270884Sjoe * This lets us override the original Makefile. 63370884Sjoe */ 63470884Sjoe snprintf(path, sizeof(path), "Makefile.%s", p->name); 63570884Sjoe if (is_nonempty_file(path)) { 63670884Sjoe snprintf(line, MAXLINELEN, "Using %s for %s", path, p->name); 63770884Sjoe status(line); 63870114Sjoe } else 63970884Sjoe if (p->srcdir) 64070884Sjoe snprintf(path, sizeof(path), "%s/Makefile", p->srcdir); 64170884Sjoe if (!p->objs && p->srcdir && is_nonempty_file(path)) 64270884Sjoe fillin_program_objs(p, path); 6431722Sjkh 64481700Sjoe if (!p->srcdir && !p->objdir && verbose) 64570884Sjoe warnx("%s: %s: %s", 64670884Sjoe "warning: could not find source directory", 64770884Sjoe infilename, p->name); 64870884Sjoe if (!p->objs && verbose) 64970884Sjoe warnx("%s: %s: warning: could not find any .o files", 65070884Sjoe infilename, p->name); 65170880Sjoe 65281823Sjoe if ((!p->srcdir || !p->objdir) && !p->objs) 65370884Sjoe p->goterror = 1; 6541722Sjkh} 6551722Sjkh 6561722Sjkhvoid fillin_program_objs(prog_t *p, char *path) 6571722Sjkh{ 65870884Sjoe char *obj, *cp; 65970884Sjoe int fd, rc; 66070884Sjoe FILE *f; 66170884Sjoe char *objvar="OBJS"; 66270884Sjoe strlst_t *s; 66370884Sjoe char line[MAXLINELEN]; 6641722Sjkh 66570884Sjoe /* discover the objs from the srcdir Makefile */ 6661722Sjkh 66770884Sjoe if ((fd = mkstemp(tempfname)) == -1) { 66870884Sjoe perror(tempfname); 66970884Sjoe exit(1); 67070884Sjoe } 67170884Sjoe if ((f = fdopen(fd, "w")) == NULL) { 67270884Sjoe warn("%s", tempfname); 67370884Sjoe goterror = 1; 67470884Sjoe return; 67570884Sjoe } 67670884Sjoe if (p->objvar) 67770884Sjoe objvar = p->objvar; 6788857Srgrimes 67970884Sjoe /* 68070884Sjoe * XXX include outhdrname (e.g. to contain Make variables) 68170884Sjoe */ 68270884Sjoe if (outhdrname[0] != '\0') 68370884Sjoe fprintf(f, ".include \"%s\"\n", outhdrname); 68470884Sjoe fprintf(f, ".include \"%s\"\n", path); 68570884Sjoe if (buildopts) { 68670884Sjoe fprintf(f, "BUILDOPTS+="); 68770884Sjoe output_strlst(f, buildopts); 68870884Sjoe } 68970884Sjoe fprintf(f, ".if defined(PROG) && !defined(%s)\n", objvar); 69070884Sjoe fprintf(f, "%s=${PROG}.o\n", objvar); 69170884Sjoe fprintf(f, ".endif\n"); 69270884Sjoe fprintf(f, "loop:\n\t@echo 'OBJS= '${%s}\n", objvar); 69368569Sjoe 694113886Sru fprintf(f, "crunchgen_objs:\n" 695113886Sru "\t@cd %s && make -f %s $(BUILDOPTS) $(%s_OPTS)", 696113886Sru p->srcdir, tempfname, p->ident); 69770884Sjoe for (s = p->buildopts; s != NULL; s = s->next) 69870884Sjoe fprintf(f, " %s", s->str); 69970884Sjoe fprintf(f, " loop\n"); 70068569Sjoe 70170884Sjoe fclose(f); 7021722Sjkh 703113855Sru snprintf(line, MAXLINELEN, "cd %s && make -f %s crunchgen_objs 2>&1", 704113855Sru p->srcdir, tempfname); 70570884Sjoe if ((f = popen(line, "r")) == NULL) { 70670884Sjoe warn("submake pipe"); 70770884Sjoe goterror = 1; 70870884Sjoe return; 70970884Sjoe } 7101722Sjkh 71170884Sjoe while(fgets(line, MAXLINELEN, f)) { 71270884Sjoe if (strncmp(line, "OBJS= ", 6)) { 71370884Sjoe warnx("make error: %s", line); 71470884Sjoe goterror = 1; 71570884Sjoe continue; 71670884Sjoe } 71770884Sjoe 71870884Sjoe cp = line + 6; 71970884Sjoe while (isspace(*cp)) 72070884Sjoe cp++; 72170884Sjoe 72270884Sjoe while(*cp) { 72370884Sjoe obj = cp; 72470884Sjoe while (*cp && !isspace(*cp)) 72570884Sjoe cp++; 72670884Sjoe if (*cp) 72770884Sjoe *cp++ = '\0'; 72870884Sjoe add_string(&p->objs, obj); 72970884Sjoe while (isspace(*cp)) 73070884Sjoe cp++; 73170884Sjoe } 7321722Sjkh } 73370884Sjoe 73470884Sjoe if ((rc=pclose(f)) != 0) { 73570884Sjoe warnx("make error: make returned %d", rc); 73670884Sjoe goterror = 1; 7371722Sjkh } 73870884Sjoe 73970884Sjoe unlink(tempfname); 7401722Sjkh} 7411722Sjkh 7421722Sjkhvoid remove_error_progs(void) 7431722Sjkh{ 74470884Sjoe prog_t *p1, *p2; 7451722Sjkh 74670884Sjoe p1 = NULL; p2 = progs; 74770884Sjoe while (p2 != NULL) { 74870884Sjoe if (!p2->goterror) 74970884Sjoe p1 = p2, p2 = p2->next; 75070884Sjoe else { 75170884Sjoe /* delete it from linked list */ 75270884Sjoe warnx("%s: %s: ignoring program because of errors", 75370884Sjoe infilename, p2->name); 75470884Sjoe if (p1) 75570884Sjoe p1->next = p2->next; 75670884Sjoe else 75770884Sjoe progs = p2->next; 75870884Sjoe p2 = p2->next; 75970884Sjoe } 7601722Sjkh } 7611722Sjkh} 7621722Sjkh 7631722Sjkhvoid gen_specials_cache(void) 7641722Sjkh{ 76570884Sjoe FILE *cachef; 76670884Sjoe prog_t *p; 76770884Sjoe char line[MAXLINELEN]; 7681722Sjkh 76970884Sjoe snprintf(line, MAXLINELEN, "generating %s", cachename); 77070884Sjoe status(line); 7711722Sjkh 77270884Sjoe if ((cachef = fopen(cachename, "w")) == NULL) { 77370884Sjoe warn("%s", cachename); 77470884Sjoe goterror = 1; 77570884Sjoe return; 77670884Sjoe } 7771722Sjkh 77870884Sjoe fprintf(cachef, "# %s - parm cache generated from %s by crunchgen " 77970884Sjoe " %s\n\n", 7801722Sjkh cachename, infilename, CRUNCH_VERSION); 7811722Sjkh 78270884Sjoe for (p = progs; p != NULL; p = p->next) { 78370884Sjoe fprintf(cachef, "\n"); 78470884Sjoe if (p->srcdir) 78570884Sjoe fprintf(cachef, "special %s srcdir %s\n", 78670884Sjoe p->name, p->srcdir); 78770884Sjoe if (p->objdir) 78870884Sjoe fprintf(cachef, "special %s objdir %s\n", 78970884Sjoe p->name, p->objdir); 79070884Sjoe if (p->objs) { 79170884Sjoe fprintf(cachef, "special %s objs", p->name); 79270884Sjoe output_strlst(cachef, p->objs); 79370884Sjoe } 79470884Sjoe if (p->objpaths) { 79570884Sjoe fprintf(cachef, "special %s objpaths", p->name); 79670884Sjoe output_strlst(cachef, p->objpaths); 79770884Sjoe } 7981722Sjkh } 79970884Sjoe fclose(cachef); 8001722Sjkh} 8011722Sjkh 8021722Sjkh 8031722Sjkhvoid gen_output_makefile(void) 8041722Sjkh{ 80570884Sjoe prog_t *p; 80670884Sjoe FILE *outmk; 80770884Sjoe char line[MAXLINELEN]; 8081722Sjkh 80970884Sjoe snprintf(line, MAXLINELEN, "generating %s", outmkname); 81070884Sjoe status(line); 8111722Sjkh 81270884Sjoe if ((outmk = fopen(outmkname, "w")) == NULL) { 81370884Sjoe warn("%s", outmkname); 81470884Sjoe goterror = 1; 81570884Sjoe return; 81670884Sjoe } 8171722Sjkh 81870884Sjoe fprintf(outmk, "# %s - generated from %s by crunchgen %s\n\n", 8191722Sjkh outmkname, infilename, CRUNCH_VERSION); 8201722Sjkh 82170884Sjoe if (outhdrname[0] != '\0') 82270884Sjoe fprintf(outmk, ".include \"%s\"\n", outhdrname); 8231722Sjkh 82470884Sjoe top_makefile_rules(outmk); 82570884Sjoe for (p = progs; p != NULL; p = p->next) 82670884Sjoe prog_makefile_rules(outmk, p); 82770884Sjoe 82870884Sjoe fprintf(outmk, "\n# ========\n"); 82970884Sjoe fclose(outmk); 8301722Sjkh} 8311722Sjkh 8321722Sjkh 8331722Sjkhvoid gen_output_cfile(void) 8341722Sjkh{ 83570884Sjoe extern char *crunched_skel[]; 83670884Sjoe char **cp; 83770884Sjoe FILE *outcf; 83870884Sjoe prog_t *p; 83970884Sjoe strlst_t *s; 84070884Sjoe char line[MAXLINELEN]; 8411722Sjkh 84270884Sjoe snprintf(line, MAXLINELEN, "generating %s", outcfname); 84370884Sjoe status(line); 8441722Sjkh 84570884Sjoe if((outcf = fopen(outcfname, "w")) == NULL) { 84670884Sjoe warn("%s", outcfname); 84770884Sjoe goterror = 1; 84870884Sjoe return; 84970884Sjoe } 8501722Sjkh 85170884Sjoe fprintf(outcf, 85270884Sjoe "/* %s - generated from %s by crunchgen %s */\n", 8531722Sjkh outcfname, infilename, CRUNCH_VERSION); 8541722Sjkh 85570884Sjoe fprintf(outcf, "#define EXECNAME \"%s\"\n", execfname); 85670884Sjoe for (cp = crunched_skel; *cp != NULL; cp++) 85770884Sjoe fprintf(outcf, "%s\n", *cp); 8581722Sjkh 85970884Sjoe for (p = progs; p != NULL; p = p->next) 86070884Sjoe fprintf(outcf, "extern int _crunched_%s_stub();\n", p->ident); 8611722Sjkh 86270884Sjoe fprintf(outcf, "\nstruct stub entry_points[] = {\n"); 86370884Sjoe for (p = progs; p != NULL; p = p->next) { 86470884Sjoe fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n", 86570884Sjoe p->name, p->ident); 86670884Sjoe for (s = p->links; s != NULL; s = s->next) 86770884Sjoe fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n", 86870884Sjoe s->str, p->ident); 86970884Sjoe } 8708857Srgrimes 87170884Sjoe fprintf(outcf, "\t{ EXECNAME, crunched_main },\n"); 87270884Sjoe fprintf(outcf, "\t{ NULL, NULL }\n};\n"); 87370884Sjoe fclose(outcf); 8741722Sjkh} 8751722Sjkh 8761722Sjkh 8771722Sjkhchar *genident(char *str) 8781722Sjkh{ 87970884Sjoe char *n, *s, *d; 8801722Sjkh 88170884Sjoe /* 88270884Sjoe * generates a Makefile/C identifier from a program name, 88370884Sjoe * mapping '-' to '_' and ignoring all other non-identifier 88470884Sjoe * characters. This leads to programs named "foo.bar" and 88570884Sjoe * "foobar" to map to the same identifier. 88670884Sjoe */ 8871722Sjkh 88870884Sjoe if ((n = strdup(str)) == NULL) 88970884Sjoe return NULL; 89070884Sjoe for (d = s = n; *s != '\0'; s++) { 89170884Sjoe if (*s == '-') 89270884Sjoe *d++ = '_'; 89370884Sjoe else if (*s == '_' || isalnum(*s)) 89470884Sjoe *d++ = *s; 89570884Sjoe } 89670884Sjoe *d = '\0'; 89770884Sjoe return n; 8981722Sjkh} 8991722Sjkh 9001722Sjkh 9011722Sjkhchar *dir_search(char *progname) 9021722Sjkh{ 90370884Sjoe char path[MAXPATHLEN]; 90470884Sjoe strlst_t *dir; 90570884Sjoe char *srcdir; 9061722Sjkh 90770884Sjoe for (dir = srcdirs; dir != NULL; dir = dir->next) { 90870884Sjoe snprintf(path, MAXPATHLEN, "%s/%s", dir->str, progname); 90970884Sjoe if (!is_dir(path)) 91070884Sjoe continue; 91170884Sjoe 91270884Sjoe if ((srcdir = strdup(path)) == NULL) 91370884Sjoe out_of_memory(); 91470884Sjoe 91570884Sjoe return srcdir; 91670331Sjoe } 91770884Sjoe return NULL; 9181722Sjkh} 9191722Sjkh 9201722Sjkh 9211722Sjkhvoid top_makefile_rules(FILE *outmk) 9221722Sjkh{ 92370884Sjoe prog_t *p; 9241722Sjkh 92578520Sjoe fprintf(outmk, "LIBS+="); 92670884Sjoe output_strlst(outmk, libs); 9271722Sjkh 92870884Sjoe if (makeobj) { 92970884Sjoe fprintf(outmk, "MAKEOBJDIRPREFIX?=%s\n", objprefix); 93070884Sjoe fprintf(outmk, "MAKE=env MAKEOBJDIRPREFIX=$(MAKEOBJDIRPREFIX) " 93170884Sjoe "make\n"); 93270884Sjoe } else { 93370884Sjoe fprintf(outmk, "MAKE=make\n"); 93470884Sjoe } 93570112Sjoe 93670884Sjoe if (buildopts) { 93770884Sjoe fprintf(outmk, "BUILDOPTS+="); 93870884Sjoe output_strlst(outmk, buildopts); 93970884Sjoe } 94068750Sjoe 94170884Sjoe fprintf(outmk, "CRUNCHED_OBJS="); 94270884Sjoe for (p = progs; p != NULL; p = p->next) 94370884Sjoe fprintf(outmk, " %s.lo", p->name); 94470884Sjoe fprintf(outmk, "\n"); 9451722Sjkh 94670884Sjoe fprintf(outmk, "SUBMAKE_TARGETS="); 94770884Sjoe for (p = progs; p != NULL; p = p->next) 94870884Sjoe fprintf(outmk, " %s_make", p->ident); 94970884Sjoe fprintf(outmk, "\nSUBCLEAN_TARGETS="); 95070884Sjoe for (p = progs; p != NULL; p = p->next) 95170884Sjoe fprintf(outmk, " %s_clean", p->ident); 95270884Sjoe fprintf(outmk, "\n\n"); 9531722Sjkh 95470884Sjoe fprintf(outmk, "all: objs exe\nobjs: $(SUBMAKE_TARGETS)\n"); 95570884Sjoe fprintf(outmk, "exe: %s\n", execfname); 95670884Sjoe fprintf(outmk, "%s: %s.o $(CRUNCHED_OBJS)\n", execfname, execfname); 95770884Sjoe fprintf(outmk, "\t$(CC) -static -o %s %s.o $(CRUNCHED_OBJS) $(LIBS)\n", 9581722Sjkh execfname, execfname); 95970884Sjoe fprintf(outmk, "\tstrip %s\n", execfname); 96070884Sjoe fprintf(outmk, "realclean: clean subclean\n"); 96170884Sjoe fprintf(outmk, "clean:\n\trm -f %s *.lo *.o *_stub.c\n", execfname); 96270884Sjoe fprintf(outmk, "subclean: $(SUBCLEAN_TARGETS)\n"); 9631722Sjkh} 9641722Sjkh 9651722Sjkh 9661722Sjkhvoid prog_makefile_rules(FILE *outmk, prog_t *p) 9671722Sjkh{ 96870884Sjoe strlst_t *lst; 96930120Sjoerg 97070884Sjoe fprintf(outmk, "\n# -------- %s\n\n", p->name); 9711722Sjkh 97281700Sjoe fprintf(outmk, "%s_OBJDIR=", p->ident); 97381700Sjoe if (p->objdir) 97481700Sjoe fprintf(outmk, "%s", p->objdir); 97581700Sjoe else 97681700Sjoe fprintf(outmk, "$(MAKEOBJDIRPREFIX)/$(%s_REALSRCDIR)\n", 97781700Sjoe p->ident); 97881700Sjoe fprintf(outmk, "\n"); 97981700Sjoe 98070884Sjoe if (p->srcdir && p->objs) { 98170884Sjoe fprintf(outmk, "%s_SRCDIR=%s\n", p->ident, p->srcdir); 98270884Sjoe fprintf(outmk, "%s_REALSRCDIR=%s\n", p->ident, p->realsrcdir); 98370112Sjoe 98470884Sjoe fprintf(outmk, "%s_OBJS=", p->ident); 98570884Sjoe output_strlst(outmk, p->objs); 98670884Sjoe if (p->buildopts != NULL) { 98770884Sjoe fprintf(outmk, "%s_OPTS+=", p->ident); 98870884Sjoe output_strlst(outmk, p->buildopts); 98970884Sjoe } 99070884Sjoe fprintf(outmk, "%s_make:\n", p->ident); 99170884Sjoe fprintf(outmk, "\t(cd $(%s_SRCDIR) && ", p->ident); 99270884Sjoe if (makeobj) 99370884Sjoe fprintf(outmk, "$(MAKE) obj && "); 99470884Sjoe fprintf(outmk, "\\\n"); 99570884Sjoe fprintf(outmk, "\t\t$(MAKE) $(BUILDOPTS) $(%s_OPTS) depend &&", 99670112Sjoe p->ident); 99770884Sjoe fprintf(outmk, "\\\n"); 99870884Sjoe fprintf(outmk, "\t\t$(MAKE) $(BUILDOPTS) $(%s_OPTS) " 99970884Sjoe "$(%s_OBJS))", 100070884Sjoe p->ident, p->ident); 100170884Sjoe fprintf(outmk, "\n"); 100270884Sjoe fprintf(outmk, "%s_clean:\n", p->ident); 100375152Sru fprintf(outmk, "\t(cd $(%s_SRCDIR) && $(MAKE) $(BUILDOPTS) clean cleandepend)\n\n", 100470884Sjoe p->ident); 100570884Sjoe } else { 100670884Sjoe fprintf(outmk, "%s_make:\n", p->ident); 100770884Sjoe fprintf(outmk, "\t@echo \"** cannot make objs for %s\"\n\n", 100875152Sru p->name); 100968569Sjoe } 10101722Sjkh 101170884Sjoe fprintf(outmk, "%s_OBJPATHS=", p->ident); 101270884Sjoe if (p->objpaths) 101370884Sjoe output_strlst(outmk, p->objpaths); 101470884Sjoe else { 101570884Sjoe for (lst = p->objs; lst != NULL; lst = lst->next) { 101670884Sjoe fprintf(outmk, " $(%s_OBJDIR)/%s", p->ident, lst->str); 101770884Sjoe } 101870884Sjoe fprintf(outmk, "\n"); 101970112Sjoe } 102093435Sluigi if (p->libs) { 102193435Sluigi fprintf(outmk, "%s_LIBS=", p->ident); 102293435Sluigi output_strlst(outmk, p->libs); 102393435Sluigi } 10241722Sjkh 102570884Sjoe fprintf(outmk, "%s_stub.c:\n", p->name); 102670884Sjoe fprintf(outmk, "\techo \"" 102770884Sjoe "int _crunched_%s_stub(int argc, char **argv, char **envp)" 102870884Sjoe "{return main(argc,argv,envp);}\" >%s_stub.c\n", 10291722Sjkh p->ident, p->name); 103093435Sluigi fprintf(outmk, "%s.lo: %s_stub.o $(%s_OBJPATHS)", 10311722Sjkh p->name, p->name, p->ident); 103293435Sluigi if (p->libs) 103393435Sluigi fprintf(outmk, " $(%s_LIBS)", p->ident); 103493435Sluigi fprintf(outmk, "\n"); 103593435Sluigi fprintf(outmk, "\tld -dc -r -o %s.lo %s_stub.o $(%s_OBJPATHS)", 10361722Sjkh p->name, p->name, p->ident); 103793435Sluigi if (p->libs) 103893435Sluigi fprintf(outmk, " $(%s_LIBS)", p->ident); 103993435Sluigi fprintf(outmk, "\n"); 104070884Sjoe fprintf(outmk, "\tcrunchide -k _crunched_%s_stub ", p->ident); 104170884Sjoe for (lst = p->keeplist; lst != NULL; lst = lst->next) 104270884Sjoe fprintf(outmk, "-k _%s ", lst->str); 104370884Sjoe fprintf(outmk, "%s.lo\n", p->name); 10441722Sjkh} 10451722Sjkh 10461722Sjkhvoid output_strlst(FILE *outf, strlst_t *lst) 10471722Sjkh{ 104870884Sjoe for (; lst != NULL; lst = lst->next) 104970884Sjoe fprintf(outf, " %s", lst->str); 105070884Sjoe fprintf(outf, "\n"); 10511722Sjkh} 10521722Sjkh 10531722Sjkh 10541722Sjkh/* 10551722Sjkh * ======================================================================== 10561722Sjkh * general library routines 10571722Sjkh * 10581722Sjkh */ 10591722Sjkh 10601722Sjkhvoid status(char *str) 10611722Sjkh{ 106270884Sjoe static int lastlen = 0; 106370884Sjoe int len, spaces; 10641722Sjkh 106570884Sjoe if (!verbose) 106670884Sjoe return; 10671722Sjkh 106870884Sjoe len = strlen(str); 106970884Sjoe spaces = lastlen - len; 107070884Sjoe if (spaces < 1) 107170884Sjoe spaces = 1; 10721722Sjkh 107370884Sjoe fprintf(stderr, " [%s]%*.*s\r", str, spaces, spaces, " "); 107470884Sjoe fflush(stderr); 107570884Sjoe lastlen = len; 10761722Sjkh} 10771722Sjkh 10781722Sjkh 10791722Sjkhvoid out_of_memory(void) 10801722Sjkh{ 108170884Sjoe err(1, "%s: %d: out of memory, stopping", infilename, linenum); 10821722Sjkh} 10831722Sjkh 10841722Sjkh 10851722Sjkhvoid add_string(strlst_t **listp, char *str) 10861722Sjkh{ 108770884Sjoe strlst_t *p1, *p2; 10881722Sjkh 108970884Sjoe /* add to end, but be smart about dups */ 10901722Sjkh 109170884Sjoe for (p1 = NULL, p2 = *listp; p2 != NULL; p1 = p2, p2 = p2->next) 109270884Sjoe if (!strcmp(p2->str, str)) 109370884Sjoe return; 10941722Sjkh 109570884Sjoe p2 = malloc(sizeof(strlst_t)); 109670884Sjoe if (p2) { 109770884Sjoe p2->next = NULL; 109870884Sjoe p2->str = strdup(str); 109970884Sjoe } 110070884Sjoe if (!p2 || !p2->str) 110170884Sjoe out_of_memory(); 11021722Sjkh 110370884Sjoe if (p1 == NULL) 110470884Sjoe *listp = p2; 110570884Sjoe else 110670884Sjoe p1->next = p2; 11071722Sjkh} 11081722Sjkh 11091722Sjkh 11101722Sjkhint is_dir(char *pathname) 11111722Sjkh{ 111270884Sjoe struct stat buf; 11131722Sjkh 111470884Sjoe if (stat(pathname, &buf) == -1) 111570884Sjoe return 0; 111670884Sjoe 111770884Sjoe return S_ISDIR(buf.st_mode); 11181722Sjkh} 11191722Sjkh 11201722Sjkhint is_nonempty_file(char *pathname) 11211722Sjkh{ 112270884Sjoe struct stat buf; 11231722Sjkh 112470884Sjoe if (stat(pathname, &buf) == -1) 112570884Sjoe return 0; 11261722Sjkh 112770884Sjoe return S_ISREG(buf.st_mode) && buf.st_size > 0; 11281722Sjkh} 1129