10eb10989Smrg/* 20eb10989Smrg 30eb10989SmrgCopyright (c) 1993, 1994, 1998 The Open Group 40eb10989Smrg 50eb10989SmrgPermission to use, copy, modify, distribute, and sell this software and its 60eb10989Smrgdocumentation for any purpose is hereby granted without fee, provided that 70eb10989Smrgthe above copyright notice appear in all copies and that both that 80eb10989Smrgcopyright notice and this permission notice appear in supporting 90eb10989Smrgdocumentation. 100eb10989Smrg 110eb10989SmrgThe above copyright notice and this permission notice shall be included in 120eb10989Smrgall copies or substantial portions of the Software. 130eb10989Smrg 140eb10989SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 150eb10989SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 160eb10989SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 170eb10989SmrgTHE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 180eb10989SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 190eb10989SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 200eb10989Smrg 210eb10989SmrgExcept as contained in this notice, the name of The Open Group shall not be 220eb10989Smrgused in advertising or otherwise to promote the sale, use or other dealings 230eb10989Smrgin this Software without prior written authorization from The Open Group. 240eb10989Smrg 250eb10989Smrg*/ 260eb10989Smrg 270eb10989Smrg#include "def.h" 280eb10989Smrg#ifdef hpux 290eb10989Smrg#define sigvec sigvector 300eb10989Smrg#endif /* hpux */ 310eb10989Smrg 320eb10989Smrg#include <signal.h> 330eb10989Smrg#include <stdarg.h> 34fadff096Smrg#include <unistd.h> 350eb10989Smrg 3663165362Smrg#ifdef __sun 37fadff096Smrg#include <sys/utsname.h> 3863165362Smrg#endif 3963165362Smrg 400eb10989Smrg#ifdef DEBUG 41fadff096Smrgint _debugmask; 420eb10989Smrg#endif 430eb10989Smrg 440eb10989Smrg/* #define DEBUG_DUMP */ 450eb10989Smrg#ifdef DEBUG_DUMP 460eb10989Smrg#define DBG_PRINT(file, fmt, args) fprintf(file, fmt, args) 470eb10989Smrg#else 480eb10989Smrg#define DBG_PRINT(file, fmt, args) /* empty */ 490eb10989Smrg#endif 500eb10989Smrg 510eb10989Smrg#define DASH_INC_PRE "#include \"" 520eb10989Smrg#define DASH_INC_POST "\"" 530eb10989Smrg 54fadff096Smrgstatic const char *ProgramName; 550eb10989Smrg 5663165362Smrg#include "imakemdep.h" 570eb10989Smrg 58fadff096Smrgstruct inclist inclist[MAXFILES], 59fadff096Smrg *inclistp = inclist, 60fadff096Smrg *inclistnext = inclist, 61fadff096Smrg maininclist; 62fadff096Smrg 63fadff096Smrgstatic char *filelist[MAXFILES]; 64fadff096Smrgconst char *includedirs[MAXDIRS + 1], 65fadff096Smrg **includedirsnext = includedirs; 66fadff096Smrgchar *notdotdot[MAXDIRS]; 67fadff096Smrgstatic int cmdinc_count = 0; 68fadff096Smrgstatic char *cmdinc_list[2 * MAXINCFILES]; 69fadff096Smrgconst char *objprefix = ""; 70fadff096Smrgconst char *objsuffix = OBJSUFFIX; 71fadff096Smrgstatic const char *startat = "# DO NOT DELETE"; 72fadff096Smrgint width = 78; 73fadff096Smrgstatic boolean append = FALSE; 74fadff096Smrgboolean printed = FALSE; 75fadff096Smrgboolean verbose = FALSE; 76fadff096Smrgboolean show_where_not = FALSE; 77fadff096Smrg 780eb10989Smrg/* Warn on multiple includes of same file */ 79fadff096Smrgboolean warn_multiple = FALSE; 800eb10989Smrg 810eb10989Smrgstatic void setfile_cmdinc(struct filepointer *filep, long count, char **list); 82fadff096Smrgstatic char *base_name(const char *file); 8363165362Smrgstatic void redirect(const char *line, const char *makefile); 840eb10989Smrg 85079e7944Smrgstatic void _X_NORETURN 86fadff096Smrgcatch(int sig) 870eb10989Smrg{ 88fadff096Smrg fflush(stdout); 89fadff096Smrg fatalerr("got signal %d\n", sig); 900eb10989Smrg} 910eb10989Smrg 92079e7944Smrg#if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(Lynx_22) || defined(__CYGWIN__) 930eb10989Smrg#define USGISH 940eb10989Smrg#endif 950eb10989Smrg 960eb10989Smrg#ifndef USGISH 970eb10989Smrg#ifdef X_NOT_POSIX 980eb10989Smrg#define sigaction sigvec 990eb10989Smrg#define sa_handler sv_handler 1000eb10989Smrg#define sa_mask sv_mask 1010eb10989Smrg#define sa_flags sv_flags 1020eb10989Smrg#endif 10363165362Smrgstatic struct sigaction sig_act; 1040eb10989Smrg#endif /* USGISH */ 1050eb10989Smrg 1060eb10989Smrgint 1070eb10989Smrgmain(int argc, char *argv[]) 1080eb10989Smrg{ 109fadff096Smrg char **fp = filelist; 110fadff096Smrg const char **incp = includedirs; 111fadff096Smrg char *p; 112fadff096Smrg struct inclist *ip; 113fadff096Smrg char *makefile = NULL; 114fadff096Smrg struct filepointer *filecontent; 115fadff096Smrg const char *endmarker = NULL; 116fadff096Smrg char *defincdir = NULL; 117fadff096Smrg char **undeflist = NULL; 118fadff096Smrg int numundefs = 0, i; 119fadff096Smrg 120fadff096Smrg ProgramName = argv[0]; 121fadff096Smrg 122fadff096Smrg for (const struct predef_symtab *psymp = predefs ; 123fadff096Smrg psymp->s_name != NULL ; psymp++) { 124fadff096Smrg define2(psymp->s_name, psymp->s_value, &maininclist); 125fadff096Smrg } 12663165362Smrg#ifdef __sun 127fadff096Smrg /* Solaris predefined values that are computed, not hardcoded */ 128fadff096Smrg { 129fadff096Smrg struct utsname name; 130fadff096Smrg 131fadff096Smrg if (uname(&name) >= 0) { 132fadff096Smrg char osrevdef[SYS_NMLN + SYS_NMLN + 5]; 133fadff096Smrg 134fadff096Smrg snprintf(osrevdef, sizeof(osrevdef), "__%s_%s", 135fadff096Smrg name.sysname, name.release); 136fadff096Smrg 137fadff096Smrg for (p = osrevdef; *p != '\0'; p++) { 138fadff096Smrg if (!isalnum(*p)) { 139fadff096Smrg *p = '_'; 140fadff096Smrg } 141fadff096Smrg } 142fadff096Smrg define2(osrevdef, "1", &maininclist); 143fadff096Smrg } 144fadff096Smrg } 14563165362Smrg#endif 146fadff096Smrg if (argc == 2 && argv[1][0] == '@') { 147fadff096Smrg struct stat ast; 148fadff096Smrg int afd; 149fadff096Smrg char *args; 150fadff096Smrg char **nargv; 151fadff096Smrg int nargc; 152fadff096Smrg char quotechar = '\0'; 153fadff096Smrg 154fadff096Smrg nargc = 1; 155fadff096Smrg if ((afd = open(argv[1] + 1, O_RDONLY)) < 0) 156fadff096Smrg fatalerr("cannot open \"%s\"\n", argv[1] + 1); 157fadff096Smrg fstat(afd, &ast); 158fadff096Smrg args = malloc(ast.st_size + 1); 159fadff096Smrg if (args == NULL) 160fadff096Smrg fatalerr("malloc()/realloc() failure in %s()\n", __func__); 161fadff096Smrg if ((ast.st_size = read(afd, args, ast.st_size)) < 0) 162fadff096Smrg fatalerr("failed to read %s\n", argv[1] + 1); 163fadff096Smrg args[ast.st_size] = '\0'; 164fadff096Smrg close(afd); 165fadff096Smrg for (p = args; *p; p++) { 166fadff096Smrg if (quotechar) { 167fadff096Smrg if (quotechar == '\\' || (*p == quotechar && p[-1] != '\\')) 168fadff096Smrg quotechar = '\0'; 169fadff096Smrg continue; 170fadff096Smrg } 171fadff096Smrg switch (*p) { 172fadff096Smrg case '\\': 173fadff096Smrg case '"': 174fadff096Smrg case '\'': 175fadff096Smrg quotechar = *p; 176fadff096Smrg break; 177fadff096Smrg case ' ': 178fadff096Smrg case '\n': 179fadff096Smrg *p = '\0'; 180fadff096Smrg if (p > args && p[-1]) 181fadff096Smrg nargc++; 182fadff096Smrg break; 183fadff096Smrg } 184fadff096Smrg } 185fadff096Smrg if (p[-1]) 186fadff096Smrg nargc++; 187fadff096Smrg nargv = mallocarray(nargc, sizeof(char *)); 188fadff096Smrg if (nargv == NULL) 189fadff096Smrg fatalerr("malloc()/realloc() failure in %s()\n", __func__); 190fadff096Smrg nargv[0] = argv[0]; 191fadff096Smrg argc = 1; 192fadff096Smrg for (p = args; argc < nargc; p += strlen(p) + 1) 193fadff096Smrg if (*p) 194fadff096Smrg nargv[argc++] = p; 195fadff096Smrg argv = nargv; 196fadff096Smrg } 197fadff096Smrg for (argc--, argv++; argc; argc--, argv++) { 198fadff096Smrg /* if looking for endmarker then check before parsing */ 199fadff096Smrg if (endmarker && strcmp(endmarker, *argv) == 0) { 200fadff096Smrg endmarker = NULL; 201fadff096Smrg continue; 202fadff096Smrg } 203fadff096Smrg if (**argv != '-') { 204fadff096Smrg /* treat +thing as an option for C++ */ 205fadff096Smrg if (endmarker && **argv == '+') 206fadff096Smrg continue; 207fadff096Smrg if (fp >= filelist + MAXFILES) { 208fadff096Smrg fatalerr("Too many source files. Limit is %i files.\n", 209fadff096Smrg MAXFILES); 210fadff096Smrg } 211fadff096Smrg *fp++ = argv[0]; 212fadff096Smrg continue; 213fadff096Smrg } 214fadff096Smrg switch (argv[0][1]) { 215fadff096Smrg case '-': 216fadff096Smrg endmarker = &argv[0][2]; 217fadff096Smrg if (endmarker[0] == '\0') 218fadff096Smrg endmarker = "--"; 219fadff096Smrg break; 220fadff096Smrg case 'D': 221fadff096Smrg if (argv[0][2] == '\0') { 222fadff096Smrg if (argc < 2) 223fadff096Smrg fatalerr("Missing argument for -D\n"); 224fadff096Smrg argv++; 225fadff096Smrg argc--; 226fadff096Smrg } 227fadff096Smrg for (p = argv[0] + 2; *p; p++) 228fadff096Smrg if (*p == '=') { 229fadff096Smrg *p = ' '; 230fadff096Smrg break; 231fadff096Smrg } 232fadff096Smrg define(argv[0] + 2, &maininclist); 233fadff096Smrg break; 234fadff096Smrg case 'I': 235fadff096Smrg if (incp >= includedirs + MAXDIRS) 236fadff096Smrg fatalerr("Too many -I flags.\n"); 237fadff096Smrg *incp++ = argv[0] + 2; 238fadff096Smrg if (**(incp - 1) == '\0') { 239fadff096Smrg if (argc < 2) 240fadff096Smrg fatalerr("Missing argument for -I\n"); 241fadff096Smrg *(incp - 1) = *(++argv); 242fadff096Smrg argc--; 243fadff096Smrg } 244fadff096Smrg break; 245fadff096Smrg case 'U': 246fadff096Smrg /* Undef's override all -D's so save them up */ 247fadff096Smrg numundefs++; 248fadff096Smrg if (numundefs == 1) 249fadff096Smrg undeflist = malloc(sizeof(char *)); 250fadff096Smrg else 251fadff096Smrg undeflist = reallocarray(undeflist, numundefs, sizeof(char *)); 252fadff096Smrg if (undeflist == NULL) 253fadff096Smrg fatalerr("malloc()/realloc() failure in %s()\n", __func__); 254fadff096Smrg if (argv[0][2] == '\0') { 255fadff096Smrg if (argc < 2) 256fadff096Smrg fatalerr("Missing argument for -U\n"); 257fadff096Smrg argv++; 258fadff096Smrg argc--; 259fadff096Smrg } 260fadff096Smrg undeflist[numundefs - 1] = argv[0] + 2; 261fadff096Smrg break; 262fadff096Smrg case 'Y': 263fadff096Smrg defincdir = argv[0] + 2; 264fadff096Smrg break; 265fadff096Smrg /* do not use if endmarker processing */ 266fadff096Smrg case 'a': 267fadff096Smrg if (endmarker) 268fadff096Smrg break; 269fadff096Smrg append = TRUE; 270fadff096Smrg break; 271fadff096Smrg case 'w': 272fadff096Smrg if (endmarker) 273fadff096Smrg break; 274fadff096Smrg if (argv[0][2] == '\0') { 275fadff096Smrg if (argc < 2) 276fadff096Smrg fatalerr("Missing argument for -w\n"); 277fadff096Smrg argv++; 278fadff096Smrg argc--; 279fadff096Smrg width = atoi(argv[0]); 280fadff096Smrg } 281fadff096Smrg else 282fadff096Smrg width = atoi(argv[0] + 2); 283fadff096Smrg break; 284fadff096Smrg case 'o': 285fadff096Smrg if (endmarker) 286fadff096Smrg break; 287fadff096Smrg if (argv[0][2] == '\0') { 288fadff096Smrg if (argc < 2) 289fadff096Smrg fatalerr("Missing argument for -o\n"); 290fadff096Smrg argv++; 291fadff096Smrg argc--; 292fadff096Smrg objsuffix = argv[0]; 293fadff096Smrg } 294fadff096Smrg else 295fadff096Smrg objsuffix = argv[0] + 2; 296fadff096Smrg break; 297fadff096Smrg case 'p': 298fadff096Smrg if (endmarker) 299fadff096Smrg break; 300fadff096Smrg if (argv[0][2] == '\0') { 301fadff096Smrg if (argc < 2) 302fadff096Smrg fatalerr("Missing argument for -p\n"); 303fadff096Smrg argv++; 304fadff096Smrg argc--; 305fadff096Smrg objprefix = argv[0]; 306fadff096Smrg } 307fadff096Smrg else 308fadff096Smrg objprefix = argv[0] + 2; 309fadff096Smrg break; 310fadff096Smrg case 'v': 311fadff096Smrg if (endmarker) 312fadff096Smrg break; 313fadff096Smrg verbose = TRUE; 3140eb10989Smrg#ifdef DEBUG 315fadff096Smrg if (argv[0][2]) 316fadff096Smrg _debugmask = atoi(argv[0] + 2); 3170eb10989Smrg#endif 318fadff096Smrg break; 319fadff096Smrg case 's': 320fadff096Smrg if (endmarker) 321fadff096Smrg break; 322fadff096Smrg startat = argv[0] + 2; 323fadff096Smrg if (*startat == '\0') { 324fadff096Smrg if (argc < 2) 325fadff096Smrg fatalerr("Missing argument for -s\n"); 326fadff096Smrg startat = *(++argv); 327fadff096Smrg argc--; 328fadff096Smrg } 329fadff096Smrg if (*startat != '#') 330fadff096Smrg fatalerr("-s flag's value should start %s\n", "with '#'."); 331fadff096Smrg break; 332fadff096Smrg case 'f': 333fadff096Smrg if (endmarker) 334fadff096Smrg break; 335fadff096Smrg makefile = argv[0] + 2; 336fadff096Smrg if (*makefile == '\0') { 337fadff096Smrg if (argc < 2) 338fadff096Smrg fatalerr("Missing argument for -f\n"); 339fadff096Smrg makefile = *(++argv); 340fadff096Smrg argc--; 341fadff096Smrg } 342fadff096Smrg break; 343fadff096Smrg 344fadff096Smrg case 'm': 345fadff096Smrg warn_multiple = TRUE; 346fadff096Smrg break; 347fadff096Smrg 348fadff096Smrg /* Ignore -O, -g so we can just pass ${CFLAGS} to 349fadff096Smrg makedepend 350fadff096Smrg */ 351fadff096Smrg case 'O': 352fadff096Smrg case 'g': 353fadff096Smrg break; 354fadff096Smrg case 'i': 355fadff096Smrg if (strcmp(&argv[0][1], "include") == 0) { 356fadff096Smrg char *buf; 357fadff096Smrg 358fadff096Smrg if (argc < 2) 359fadff096Smrg fatalerr("option -include is missing its parameter\n"); 360fadff096Smrg if (cmdinc_count >= MAXINCFILES) 361fadff096Smrg fatalerr("Too many -include flags.\n"); 362fadff096Smrg argc--; 363fadff096Smrg argv++; 364fadff096Smrg buf = malloc(strlen(DASH_INC_PRE) + 365fadff096Smrg strlen(argv[0]) + strlen(DASH_INC_POST) + 1); 366fadff096Smrg if (!buf) 367fadff096Smrg fatalerr("out of memory at -include string\n"); 368fadff096Smrg cmdinc_list[2 * cmdinc_count + 0] = argv[0]; 369fadff096Smrg cmdinc_list[2 * cmdinc_count + 1] = buf; 370fadff096Smrg cmdinc_count++; 371fadff096Smrg break; 372fadff096Smrg } 373fadff096Smrg /* intentional fall through */ 374fadff096Smrg default: 375fadff096Smrg if (endmarker) 376fadff096Smrg break; 377fadff096Smrg /* fatalerr("unknown opt = %s\n", argv[0]); */ 378fadff096Smrg warning("ignoring option %s\n", argv[0]); 379fadff096Smrg } 380fadff096Smrg } 381fadff096Smrg /* Now do the undefs from the command line */ 382fadff096Smrg for (i = 0; i < numundefs; i++) 383fadff096Smrg undefine(undeflist[i], &maininclist); 384fadff096Smrg if (numundefs > 0) 385fadff096Smrg free(undeflist); 386fadff096Smrg 387fadff096Smrg if (!defincdir) { 3880eb10989Smrg#ifdef PREINCDIR 389fadff096Smrg if (incp >= includedirs + MAXDIRS) 390fadff096Smrg fatalerr("Too many -I flags.\n"); 391fadff096Smrg *incp++ = PREINCDIR; 3920eb10989Smrg#endif 393fadff096Smrg if (incp >= includedirs + MAXDIRS) 394fadff096Smrg fatalerr("Too many -I flags.\n"); 395fadff096Smrg *incp++ = INCLUDEDIR; 3960eb10989Smrg 3970eb10989Smrg#ifdef EXTRAINCDIR 398fadff096Smrg if (incp >= includedirs + MAXDIRS) 399fadff096Smrg fatalerr("Too many -I flags.\n"); 400fadff096Smrg *incp++ = EXTRAINCDIR; 4010eb10989Smrg#endif 4020eb10989Smrg 4030eb10989Smrg#ifdef POSTINCDIR 404fadff096Smrg if (incp >= includedirs + MAXDIRS) 405fadff096Smrg fatalerr("Too many -I flags.\n"); 406fadff096Smrg *incp++ = POSTINCDIR; 4070eb10989Smrg#endif 408fadff096Smrg } 409fadff096Smrg else if (*defincdir) { 410fadff096Smrg if (incp >= includedirs + MAXDIRS) 411fadff096Smrg fatalerr("Too many -I flags.\n"); 412fadff096Smrg *incp++ = defincdir; 413fadff096Smrg } 4140eb10989Smrg 415fadff096Smrg redirect(startat, makefile); 4160eb10989Smrg 417fadff096Smrg /* 418fadff096Smrg * catch signals. 419fadff096Smrg */ 4200eb10989Smrg#ifdef USGISH 4210eb10989Smrg/* should really reset SIGINT to SIG_IGN if it was. */ 4220eb10989Smrg#ifdef SIGHUP 423fadff096Smrg signal(SIGHUP, catch); 4240eb10989Smrg#endif 425fadff096Smrg signal(SIGINT, catch); 4260eb10989Smrg#ifdef SIGQUIT 427fadff096Smrg signal(SIGQUIT, catch); 4280eb10989Smrg#endif 429fadff096Smrg signal(SIGILL, catch); 4300eb10989Smrg#ifdef SIGBUS 431fadff096Smrg signal(SIGBUS, catch); 4320eb10989Smrg#endif 433fadff096Smrg signal(SIGSEGV, catch); 4340eb10989Smrg#ifdef SIGSYS 435fadff096Smrg signal(SIGSYS, catch); 4360eb10989Smrg#endif 4370eb10989Smrg#else 438fadff096Smrg sig_act.sa_handler = catch; 4390eb10989Smrg#if defined(_POSIX_SOURCE) || !defined(X_NOT_POSIX) 440fadff096Smrg sigemptyset(&sig_act.sa_mask); 441fadff096Smrg sigaddset(&sig_act.sa_mask, SIGINT); 442fadff096Smrg sigaddset(&sig_act.sa_mask, SIGQUIT); 4430eb10989Smrg#ifdef SIGBUS 444fadff096Smrg sigaddset(&sig_act.sa_mask, SIGBUS); 4450eb10989Smrg#endif 446fadff096Smrg sigaddset(&sig_act.sa_mask, SIGILL); 447fadff096Smrg sigaddset(&sig_act.sa_mask, SIGSEGV); 448fadff096Smrg sigaddset(&sig_act.sa_mask, SIGHUP); 449fadff096Smrg sigaddset(&sig_act.sa_mask, SIGPIPE); 4500eb10989Smrg#ifdef SIGSYS 451fadff096Smrg sigaddset(&sig_act.sa_mask, SIGSYS); 4520eb10989Smrg#endif 4530eb10989Smrg#else 454fadff096Smrg sig_act.sa_mask = ((1 << (SIGINT - 1)) 455fadff096Smrg | (1 << (SIGQUIT - 1)) 4560eb10989Smrg#ifdef SIGBUS 457fadff096Smrg | (1 << (SIGBUS - 1)) 4580eb10989Smrg#endif 459fadff096Smrg | (1 << (SIGILL - 1)) 460fadff096Smrg | (1 << (SIGSEGV - 1)) 461fadff096Smrg | (1 << (SIGHUP - 1)) 462fadff096Smrg | (1 << (SIGPIPE - 1)) 4630eb10989Smrg#ifdef SIGSYS 464fadff096Smrg | (1 << (SIGSYS - 1)) 4650eb10989Smrg#endif 466fadff096Smrg ); 467fadff096Smrg#endif /* _POSIX_SOURCE */ 468fadff096Smrg sig_act.sa_flags = 0; 469fadff096Smrg sigaction(SIGHUP, &sig_act, (struct sigaction *) 0); 470fadff096Smrg sigaction(SIGINT, &sig_act, (struct sigaction *) 0); 471fadff096Smrg sigaction(SIGQUIT, &sig_act, (struct sigaction *) 0); 472fadff096Smrg sigaction(SIGILL, &sig_act, (struct sigaction *) 0); 4730eb10989Smrg#ifdef SIGBUS 474fadff096Smrg sigaction(SIGBUS, &sig_act, (struct sigaction *) 0); 4750eb10989Smrg#endif 476fadff096Smrg sigaction(SIGSEGV, &sig_act, (struct sigaction *) 0); 4770eb10989Smrg#ifdef SIGSYS 478fadff096Smrg sigaction(SIGSYS, &sig_act, (struct sigaction *) 0); 4790eb10989Smrg#endif 480fadff096Smrg#endif /* USGISH */ 481fadff096Smrg 482fadff096Smrg /* 483fadff096Smrg * now peruse through the list of files. 484fadff096Smrg */ 485fadff096Smrg for (fp = filelist; *fp; fp++) { 486fadff096Smrg DBG_PRINT(stderr, "file: %s\n", *fp); 487fadff096Smrg filecontent = getfile(*fp); 488fadff096Smrg setfile_cmdinc(filecontent, cmdinc_count, cmdinc_list); 489fadff096Smrg ip = newinclude(*fp, NULL, NULL); 490fadff096Smrg 491fadff096Smrg find_includes(filecontent, ip, ip, 0, FALSE); 492fadff096Smrg freefile(filecontent); 493fadff096Smrg recursive_pr_include(ip, ip->i_file, base_name(*fp)); 494fadff096Smrg inc_clean(); 495fadff096Smrg } 496fadff096Smrg if (printed) 497fadff096Smrg printf("\n"); 498fadff096Smrg return 0; 4990eb10989Smrg} 5000eb10989Smrg 5010eb10989Smrgstruct filepointer * 50263165362Smrggetfile(const char *file) 5030eb10989Smrg{ 504fadff096Smrg int fd; 505fadff096Smrg struct filepointer *content; 506fadff096Smrg struct stat st; 507fadff096Smrg 508fadff096Smrg content = malloc(sizeof(struct filepointer)); 509fadff096Smrg if (content == NULL) 510fadff096Smrg fatalerr("malloc()/realloc() failure in %s()\n", __func__); 511fadff096Smrg content->f_name = file; 512fadff096Smrg if ((fd = open(file, O_RDONLY)) < 0) { 513fadff096Smrg warning("cannot open \"%s\"\n", file); 514fadff096Smrg content->f_p = content->f_base = content->f_end = malloc(1); 515fadff096Smrg if (content->f_p == NULL) 516fadff096Smrg fatalerr("malloc()/realloc() failure in %s()\n", __func__); 517fadff096Smrg *content->f_p = '\0'; 518fadff096Smrg return (content); 519fadff096Smrg } 520fadff096Smrg fstat(fd, &st); 521fadff096Smrg content->f_base = malloc(st.st_size + 1); 522fadff096Smrg if (content->f_base == NULL) 523fadff096Smrg fatalerr("malloc()/realloc() failure in %s()\n", __func__); 524fadff096Smrg if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0) 525fadff096Smrg fatalerr("failed to read %s\n", file); 526fadff096Smrg close(fd); 527fadff096Smrg content->f_len = st.st_size + 1; 528fadff096Smrg content->f_p = content->f_base; 529fadff096Smrg content->f_end = content->f_base + st.st_size; 530fadff096Smrg *content->f_end = '\0'; 531fadff096Smrg content->f_line = 0; 532fadff096Smrg content->cmdinc_count = 0; 533fadff096Smrg content->cmdinc_list = NULL; 534fadff096Smrg content->cmdinc_line = 0; 535fadff096Smrg return (content); 5360eb10989Smrg} 5370eb10989Smrg 5380eb10989Smrgvoid 539fadff096Smrgsetfile_cmdinc(struct filepointer *filep, long count, char **list) 5400eb10989Smrg{ 541fadff096Smrg filep->cmdinc_count = count; 542fadff096Smrg filep->cmdinc_list = list; 543fadff096Smrg filep->cmdinc_line = 0; 5440eb10989Smrg} 5450eb10989Smrg 5460eb10989Smrgvoid 5470eb10989Smrgfreefile(struct filepointer *fp) 5480eb10989Smrg{ 549fadff096Smrg free(fp->f_base); 550fadff096Smrg free(fp); 5510eb10989Smrg} 5520eb10989Smrg 5530eb10989Smrgint 554fadff096Smrgmatch(const char *str, const char *const *list) 5550eb10989Smrg{ 556fadff096Smrg int i; 5570eb10989Smrg 558fadff096Smrg for (i = 0; *list; i++, list++) 559fadff096Smrg if (strcmp(str, *list) == 0) 560fadff096Smrg return (i); 561fadff096Smrg return (-1); 5620eb10989Smrg} 5630eb10989Smrg 5640eb10989Smrg/* 5650eb10989Smrg * Get the next line. We only return lines beginning with '#' since that 5660eb10989Smrg * is all this program is ever interested in. 5670eb10989Smrg */ 568fadff096Smrgchar * 569fadff096Smrggetnextline(struct filepointer *filep) 5700eb10989Smrg{ 571fadff096Smrg char *p, /* walking pointer */ 572fadff096Smrg *eof, /* end of file pointer */ 573fadff096Smrg *bol; /* beginning of line pointer */ 574fadff096Smrg long lineno; /* line number */ 575fadff096Smrg 576fadff096Smrg /* 577fadff096Smrg * Fake the "-include" line files in form of #include to the 578fadff096Smrg * start of each file. 579fadff096Smrg */ 580fadff096Smrg if (filep->cmdinc_line < filep->cmdinc_count) { 581fadff096Smrg char *inc = filep->cmdinc_list[2 * filep->cmdinc_line + 0]; 582fadff096Smrg char *buf = filep->cmdinc_list[2 * filep->cmdinc_line + 1]; 583fadff096Smrg 584fadff096Smrg filep->cmdinc_line++; 585fadff096Smrg sprintf(buf, "%s%s%s", DASH_INC_PRE, inc, DASH_INC_POST); 586fadff096Smrg DBG_PRINT(stderr, "%s\n", buf); 587fadff096Smrg return (buf); 588fadff096Smrg } 589fadff096Smrg 590fadff096Smrg p = filep->f_p; 591fadff096Smrg eof = filep->f_end; 592fadff096Smrg if (p >= eof) 593fadff096Smrg return ((char *) NULL); 594fadff096Smrg lineno = filep->f_line; 595fadff096Smrg 596fadff096Smrg for (bol = p--; ++p < eof;) { 597fadff096Smrg if ((bol == p) && ((*p == ' ') || (*p == '\t'))) { 598fadff096Smrg /* Consume leading white-spaces for this line */ 599fadff096Smrg while (((p + 1) < eof) && ((*p == ' ') || (*p == '\t'))) { 600fadff096Smrg p++; 601fadff096Smrg bol++; 602fadff096Smrg } 603fadff096Smrg } 604fadff096Smrg 605fadff096Smrg if (*p == '/' && (p + 1) < eof && *(p + 1) == '*') { 606fadff096Smrg /* Consume C comments */ 607fadff096Smrg *(p++) = ' '; 608fadff096Smrg *(p++) = ' '; 609fadff096Smrg while (p < eof && *p) { 610fadff096Smrg if (*p == '*' && (p + 1) < eof && *(p + 1) == '/') { 611fadff096Smrg *(p++) = ' '; 612fadff096Smrg *(p++) = ' '; 613fadff096Smrg break; 614fadff096Smrg } 615fadff096Smrg if (*p == '\n') 616fadff096Smrg lineno++; 617fadff096Smrg *(p++) = ' '; 618fadff096Smrg } 619fadff096Smrg --p; 620fadff096Smrg } 621fadff096Smrg else if (*p == '/' && (p + 1) < eof && *(p + 1) == '/') { 622fadff096Smrg /* Consume C++ comments */ 623fadff096Smrg *(p++) = ' '; 624fadff096Smrg *(p++) = ' '; 625fadff096Smrg while (p < eof && *p) { 626fadff096Smrg if (*p == '\\' && (p + 1) < eof && *(p + 1) == '\n') { 627fadff096Smrg *(p++) = ' '; 628fadff096Smrg lineno++; 629fadff096Smrg } 630fadff096Smrg else if (*p == '?' && (p + 3) < eof && 631fadff096Smrg *(p + 1) == '?' && 632fadff096Smrg *(p + 2) == '/' && *(p + 3) == '\n') { 633fadff096Smrg *(p++) = ' '; 634fadff096Smrg *(p++) = ' '; 635fadff096Smrg *(p++) = ' '; 636fadff096Smrg lineno++; 637fadff096Smrg } 638fadff096Smrg else if (*p == '\n') 639fadff096Smrg break; /* to process end of line */ 640fadff096Smrg *(p++) = ' '; 641fadff096Smrg } 642fadff096Smrg --p; 643fadff096Smrg } 644fadff096Smrg else if (*p == '\\' && (p + 1) < eof && *(p + 1) == '\n') { 645fadff096Smrg /* Consume backslash line terminations */ 646fadff096Smrg *(p++) = ' '; 647fadff096Smrg *p = ' '; 648fadff096Smrg lineno++; 649fadff096Smrg } 650fadff096Smrg else if (*p == '?' && (p + 3) < eof && 651fadff096Smrg *(p + 1) == '?' && *(p + 2) == '/' && *(p + 3) == '\n') { 652fadff096Smrg /* Consume trigraph'ed backslash line terminations */ 653fadff096Smrg *(p++) = ' '; 654fadff096Smrg *(p++) = ' '; 655fadff096Smrg *(p++) = ' '; 656fadff096Smrg *p = ' '; 657fadff096Smrg lineno++; 658fadff096Smrg } 659fadff096Smrg else if (*p == '\n') { 660fadff096Smrg lineno++; 661fadff096Smrg if (*bol == '#') { 662fadff096Smrg char *cp; 663fadff096Smrg 664fadff096Smrg *(p++) = '\0'; 665fadff096Smrg /* punt lines with just # (yacc generated) */ 666fadff096Smrg for (cp = bol + 1; *cp && (*cp == ' ' || *cp == '\t'); cp++); 667fadff096Smrg if (*cp) 668fadff096Smrg goto done; 669fadff096Smrg --p; 670fadff096Smrg } 671fadff096Smrg bol = p + 1; 672fadff096Smrg } 673fadff096Smrg } 674fadff096Smrg if (*bol != '#') 675fadff096Smrg bol = NULL; 676fadff096Smrg done: 677fadff096Smrg filep->f_p = p; 678fadff096Smrg filep->f_line = lineno; 6790eb10989Smrg#ifdef DEBUG_DUMP 680fadff096Smrg if (bol) 681fadff096Smrg DBG_PRINT(stderr, "%s\n", bol); 6820eb10989Smrg#endif 683fadff096Smrg return (bol); 6840eb10989Smrg} 6850eb10989Smrg 6860eb10989Smrg/* 6870eb10989Smrg * Strip the file name down to what we want to see in the Makefile. 6880eb10989Smrg * It will have objprefix and objsuffix around it. 6890eb10989Smrg */ 690fadff096Smrgchar * 691fadff096Smrgbase_name(const char *in_file) 6920eb10989Smrg{ 693fadff096Smrg char *p; 694fadff096Smrg char *file = strdup(in_file); 695fadff096Smrg 696fadff096Smrg if (file == NULL) 697fadff096Smrg fatalerr("strdup() failure in %s()\n", __func__); 698fadff096Smrg 699fadff096Smrg p = strrchr(file, '.'); 7000eb10989Smrg 701fadff096Smrg if (p != NULL) 702fadff096Smrg *p = '\0'; 703fadff096Smrg return (file); 7040eb10989Smrg} 7050eb10989Smrg 706079e7944Smrg#ifndef HAVE_RENAME 707fadff096Smrgint 708fadff096Smrgrename(char *from, char *to) 7090eb10989Smrg{ 710fadff096Smrg (void) unlink(to); 711fadff096Smrg if (link(from, to) == 0) { 712fadff096Smrg unlink(from); 713fadff096Smrg return 0; 714fadff096Smrg } 715fadff096Smrg else { 716fadff096Smrg return -1; 7170eb10989Smrg } 7180eb10989Smrg} 719fadff096Smrg#endif /* !HAVE_RENAME */ 7200eb10989Smrg 72163165362Smrgstatic void 72263165362Smrgredirect(const char *line, const char *makefile) 7230eb10989Smrg{ 724fadff096Smrg struct stat st; 725fadff096Smrg FILE *fdin, *fdout; 726fadff096Smrg char backup[BUFSIZ], 727fadff096Smrg buf[BUFSIZ]; 728fadff096Smrg boolean found = FALSE; 729fadff096Smrg size_t len; 730fadff096Smrg 731fadff096Smrg /* 732fadff096Smrg * if makefile is "-" then let it pour onto stdout. 733fadff096Smrg */ 734fadff096Smrg if (makefile && *makefile == '-' && *(makefile + 1) == '\0') { 735fadff096Smrg puts(line); 736fadff096Smrg return; 737fadff096Smrg } 738fadff096Smrg 739fadff096Smrg /* 740fadff096Smrg * use a default if makefile is not specified. 741fadff096Smrg */ 742fadff096Smrg if (!makefile) { 743fadff096Smrg if (stat("Makefile", &st) == 0) 744fadff096Smrg makefile = "Makefile"; 745fadff096Smrg else if (stat("makefile", &st) == 0) 746fadff096Smrg makefile = "makefile"; 747fadff096Smrg else 748fadff096Smrg fatalerr("[mM]akefile is not present\n"); 749fadff096Smrg } 750fadff096Smrg else { 751fadff096Smrg if (stat(makefile, &st) != 0) 752fadff096Smrg fatalerr("\"%s\" is not present\n", makefile); 753fadff096Smrg } 754fadff096Smrg 755fadff096Smrg snprintf(backup, sizeof(backup), "%s.bak", makefile); 756fadff096Smrg unlink(backup); 757fadff096Smrg 758fadff096Smrg /* rename() won't work on WIN32, CYGWIN, or CIFS if src file is open */ 759fadff096Smrg if (rename(makefile, backup) < 0) 760fadff096Smrg fatalerr("cannot rename %s to %s\n", makefile, backup); 761fadff096Smrg if ((fdin = fopen(backup, "r")) == NULL) { 762fadff096Smrg if (rename(backup, makefile) < 0) 763fadff096Smrg warning("renamed %s to %s, but can't move it back\n", 764fadff096Smrg makefile, backup); 765fadff096Smrg fatalerr("cannot open \"%s\"\n", makefile); 766fadff096Smrg } 767fadff096Smrg if ((fdout = freopen(makefile, "w", stdout)) == NULL) 768fadff096Smrg fatalerr("cannot open \"%s\"\n", backup); 769fadff096Smrg len = strlen(line); 770fadff096Smrg while (!found && fgets(buf, BUFSIZ, fdin)) { 771fadff096Smrg if (*buf == '#' && strncmp(line, buf, len) == 0) 772fadff096Smrg found = TRUE; 773fadff096Smrg fputs(buf, fdout); 774fadff096Smrg } 775fadff096Smrg if (!found) { 776fadff096Smrg if (verbose) 777fadff096Smrg warning("Adding new delimiting line \"%s\" and dependencies...\n", 778fadff096Smrg line); 779fadff096Smrg puts(line); /* same as fputs(fdout); but with newline */ 780fadff096Smrg } 781fadff096Smrg else if (append) { 782fadff096Smrg while (fgets(buf, BUFSIZ, fdin)) { 783fadff096Smrg fputs(buf, fdout); 784fadff096Smrg } 785fadff096Smrg } 786fadff096Smrg fclose(fdin); 787fadff096Smrg fflush(fdout); 7880eb10989Smrg#ifndef HAVE_FCHMOD 789fadff096Smrg chmod(makefile, st.st_mode); 7900eb10989Smrg#else 791fadff096Smrg fchmod(fileno(fdout), st.st_mode); 792fadff096Smrg#endif /* HAVE_FCHMOD */ 7930eb10989Smrg} 7940eb10989Smrg 7950eb10989Smrgvoid 79663165362Smrgfatalerr(const char *msg, ...) 7970eb10989Smrg{ 798fadff096Smrg va_list args; 799fadff096Smrg 800fadff096Smrg fprintf(stderr, "%s: error: ", ProgramName); 801fadff096Smrg va_start(args, msg); 802fadff096Smrg vfprintf(stderr, msg, args); 803fadff096Smrg va_end(args); 804fadff096Smrg exit(1); 8050eb10989Smrg} 8060eb10989Smrg 8070eb10989Smrgvoid 80863165362Smrgwarning(const char *msg, ...) 8090eb10989Smrg{ 810fadff096Smrg va_list args; 811fadff096Smrg 812fadff096Smrg fprintf(stderr, "%s: warning: ", ProgramName); 813fadff096Smrg va_start(args, msg); 814fadff096Smrg vfprintf(stderr, msg, args); 815fadff096Smrg va_end(args); 8160eb10989Smrg} 8170eb10989Smrg 8180eb10989Smrgvoid 81963165362Smrgwarning1(const char *msg, ...) 8200eb10989Smrg{ 821fadff096Smrg va_list args; 822fadff096Smrg 823fadff096Smrg va_start(args, msg); 824fadff096Smrg vfprintf(stderr, msg, args); 825fadff096Smrg va_end(args); 8260eb10989Smrg} 827