Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1443 lines
42 KiB

4 years ago
  1. /*** NMAKE.C - main module *****************************************************
  2. *
  3. * Copyright (c) 1988-1990, Microsoft Corporation. All rights reserved.
  4. *
  5. * Purpose:
  6. * This is the main module of nmake
  7. *
  8. * Revision History:
  9. * 01-Feb-1994 HV Move messages to external file.
  10. * 15-Nov-1993 JdR Major speed improvements
  11. * 15-Oct-1993 HV Use tchar.h instead of mbstring.h directly, change STR*() to _ftcs*()
  12. * 10-May-1993 HV Add include file mbstring.h
  13. * Change the str* functions to STR*
  14. * 26-Mar-1992 HV Rewrite filename() to use _splitpath()
  15. * 06-Oct-1992 GBS Removed extern for _pgmptr
  16. * 08-Jun-1992 SS add IDE feedback support
  17. * 08-Jun-1992 SS Port to DOSX32
  18. * 29-May-1990 SB Fix precedence of predefined inference rules ...
  19. * 25-May-1990 SB Various fixes: 1> New inference rules for fortran and pascal;
  20. * 2> Resolving ties in timestamps in favour of building;
  21. * 3> error U1058 does not echo the filename anymore (ctrl-c
  22. * caused filename and lineno to be dispalyed and this was
  23. * trouble for PWB
  24. * 01-May-1990 SB Add predefined rules and inference rules for FORTRAN
  25. * 23-Apr-1990 SB Add predefined rules and inference rules for COBOL
  26. * 20-Apr-1990 SB Don't show lineno for CTRL+C handler error
  27. * 17-Apr-1990 SB Pass copy of makeflags to putenv() else freeing screws the
  28. * DGROUP.
  29. * 23-Feb-1990 SB chdir(MAKEDIR) to avoid returning to bad directory in DOS
  30. * 02-Feb-1990 SB change fopen() to FILEOPEN()
  31. * 31-Jan-1990 SB Postpone defineMAcro("MAKE") to doMAke(); Put freshly
  32. * allocated strings in the macro table as freeStructures()
  33. * free's the macroTable[]
  34. * 24-Jan-1990 SB Add byte to call for sprintf() for "@del ..." case for /z
  35. * 29-Dec-1989 SB ignore /Z when /T also specified
  36. * 29-Dec-1989 SB nmake -? was giving error with TMP directory nonexistent
  37. * 19-Dec-1989 SB nmake /z requests
  38. * 14-Dec-1989 SB Trunc MAKEFLAGS averts GPF;Silently ignore /z in protect mode
  39. * 12-Dec-1989 SB =c, =d for NMAKE /Z
  40. * 08-Dec-1989 SB /NZ causes /N to override /Z; add #define TEST_RUNTIME stuff
  41. * 01-Dec-1989 SB Contains an hack #ifdef'ed for Overlayed version
  42. * 22-Nov-1989 SB Changed free() to FREE()
  43. * 17-Nov-1989 SB defined INCL_NOPM; generate del commands to del temps
  44. * 19-Oct-1989 SB ifdef SLASHK'ed stuff for -k
  45. * 04-Sep-1989 SB echoing and redirection problem for -z fixed
  46. * 17-Aug-1989 SB added #ifdef DEBUG's and error -nz incompatible
  47. * 31-Jul-1989 SB Added check of return value -1 (error in spawning) for -help
  48. * remove -z option help message
  49. * 12-Jul-1989 SB readEnvironmentVars() was not using environ variable but an
  50. * old pointer (envPtr) to it. In the meantime environ was
  51. * getting updated. Safer to use environ directly.
  52. * 29-Jun-1989 SB freeStructures() now deletes inlineFileList also
  53. * 28-Jun-1989 SB changed deletion of inline files to end of mainmain() instead of
  54. * doMake() to avoid deletion when a child make quits.
  55. * 19-Jun-1989 SB modified .bas.obj to have ';' at end of cmd line
  56. * 21-May-1989 SB freeRules() gets another parameter to avoid bogus messages
  57. * 18-May-1989 SB change delScriptFiles() to do unlink instead of calling
  58. * execLine. Thus, ^C handling is better now. No more hangs
  59. * 15-May-1989 SB Added /make support; inherit /nologo
  60. * 13-May-1989 SB Changed delScriptFiles(); added MAKEDIR; Added BASIC rules
  61. * Changed chkPrecious()
  62. * 01-May-1989 SB Changed FILEINFO to void *; OS/2 Version 1.2 support
  63. * 17-Apr-1989 SB on -help spawn 'qh /u nmake' instead. rc = 3 signals error
  64. * 14-Apr-1989 SB no 'del inlinefile' cmd for -n. -z now gives 'goto NmakeExit'
  65. * CC and AS allocated of the heap and not from Data Segment
  66. * 05-Apr-1989 SB made all funcs NEAR; Reqd to make all function calls NEAR
  67. * 27-Mar-1989 SB Changed unlinkTmpFiles() to delScriptFiles()
  68. * 10-Mar-1989 SB Removed blank link from PWB.SHL output
  69. * 09-Mar-1989 SB changed param in call to findRule. fBuf is allocated on the
  70. * heap in useDefaultMakefile()
  71. * 24-Feb-1989 SB Inherit MAKEFLAGS to Env for XMake Compatibility
  72. * 22-Feb-1989 SB Ignore '-' or '/' in parseCommandLine()
  73. * 16-Feb-1989 SB add delScriptFiles() to delete temp script files at the
  74. * end of the make. Also called on ^c and ^break
  75. * 15-Feb-1989 SB Rewrote useDefaultMakefile(); MAKEFLAGS can contain all flags
  76. * now
  77. * 13-Feb-1989 SB Rewrote filename() for OS/2 1.2 support, now returns BOOL.
  78. * 3-Feb-1989 SB Renamed freeUnusedRules() to freeRules(); moved prototype to
  79. * proto.h
  80. * 9-Jan-1989 SB Improved /help;added -?
  81. * 3-Jan-1989 SB Changes for /help and /nologo
  82. * 5-Dec-1988 SB Made chkPrecious() CDECL as signal() expects it
  83. * main has CDECL too; cleaned prototypes (added void)
  84. * 30-Nov-1988 SB Added for 'z' option in setFlags() and chkPrecious()
  85. * 10-Nov-1988 SB Removed '#ifndef IBM' as IBM ver has a separate tree
  86. * 21-Oct-1988 SB Added fInheritUserEnv to inherit macro definitions
  87. * 22-Sep-1988 RB Changed a lingering reference of /B to /A.
  88. * 15-Sep-1988 RB Move some def's out to GLOBALS.
  89. * 17-Aug-1988 RB Clean up.
  90. * 15-Aug-1988 RB /B ==> /A for XMAKE compatibility.
  91. * 11-Jul-1988 rj Removed OSMODE definition.
  92. * Removed NMAKE & NMAKEFLAGS (sob!).
  93. * 8-Jul-1988 rj Added OSMODE definition.
  94. * 7-Jul-1988 rj #ifndef IBM'ed NMAKE & NMAKEFLAGS
  95. * 6-Jul-1988 rj Ditched shell, argVector, moved getComSpec to build.c.
  96. * 5-Jul-1988 rj Fixed (*pfSPAWN) declarations.
  97. * 28-Jun-1988 rj Added NMAKEFLAGS predefined macro.
  98. * 24-Jun-1988 rj Added NMAKE predefined macro.
  99. * Added doError flag to unlinkTmpFiles call.
  100. * 23-Jun-1988 rj Fixed okToDelete to delete less often.
  101. * 22-Jun-1988 rj Make chkPrecious use error messages
  102. * 25-May-1988 rb Make InitLeadByte() smarter.
  103. * 20-May-1988 rb Change built-in macro names.
  104. * 18-May-1988 rb Remove comment about built-in rules and macros.
  105. * 17-May-1988 rb Load built-in rules in right place.
  106. * 16-May-1988 rb Conditionalize recursive make feature.
  107. * 8-May-1988 rb Better initialization of system shell.
  108. *
  109. *******************************************************************************/
  110. #include "nmake.h"
  111. #include "nmmsg.h"
  112. #include "proto.h"
  113. #include "globals.h"
  114. #include "grammar.h"
  115. #define INCL_NOPM
  116. #define INCL_DOSSIGNALS
  117. #if !defined(DOS) && !defined(FLAT)
  118. #include <os2.h>
  119. #endif
  120. #define MAX(A,B) (A) > (B) ? (A) : (B)
  121. /* ----------------------------------------------------------------------------
  122. * prototypes for main and all functions static to this module
  123. */
  124. void __cdecl main(unsigned, char**, char**);
  125. LOCAL void NEAR readEnvironmentVars(void);
  126. LOCAL void NEAR readMakeFiles(void);
  127. LOCAL void NEAR useDefaultMakefile(void);
  128. LOCAL BOOL NEAR filename(const char*, char**);
  129. LOCAL void NEAR freeStructures(void);
  130. LOCAL void NEAR loadBuiltInRules(void);
  131. //void pascal chkPrecious(USHORT, USHORT);
  132. LOCAL void __cdecl chkPrecious(int sig);
  133. LOCAL void NEAR InitializeEnv(void);
  134. LOCAL UCHAR NEAR isPrecious(char*);
  135. void NEAR removeTrailChars(char *);
  136. extern void CDECL NEAR makeIdeMessage (unsigned, unsigned,...);
  137. void CDECL NEAR usage (void);
  138. /* ----------------------------------------------------------------------------
  139. * global variables that live in this module but that are also used in
  140. * other modules:
  141. */
  142. #ifdef DEBUG
  143. char *dummy="dummy";
  144. #endif
  145. char * makeStr = NULL; /* this make invocation name */
  146. #ifdef DOS
  147. char * startupDir;
  148. #endif
  149. char NEAR fileStr[MAXNAME];
  150. char * initSavPtr = NULL; /* save area for initialized vars */
  151. unsigned saveBytes = 0;
  152. char ** envPtr = NULL;
  153. UCHAR okToDelete = FALSE; /* do not del unless exec'ing cmd */
  154. #if defined(FLAT)
  155. UCHAR fRunningUnderTNT = FALSE;
  156. extern UCHAR FIsTNT(void);
  157. #endif
  158. char * builtInTarg[] = {".SUFFIXES",
  159. ".c.obj",
  160. ".c.exe",
  161. ".cpp.obj",
  162. ".cpp.exe",
  163. ".cxx.obj",
  164. ".cxx.exe",
  165. ".asm.obj",
  166. ".asm.exe",
  167. ".bas.obj",
  168. ".cbl.obj",
  169. ".cbl.exe",
  170. ".for.obj",
  171. ".for.exe",
  172. ".pas.obj",
  173. ".pas.exe",
  174. ".rc.res",
  175. NULL};
  176. char * bltInCmd0[] = {".exe", ".obj", ".asm", ".c", ".cpp", ".cxx",
  177. ".bas", ".cbl", ".for", ".pas", ".res", ".rc",
  178. NULL};
  179. char * bltInCmd1[] = {"$(CC) $(CFLAGS) /c $*.c", NULL};
  180. char * bltInCmd2[] = {"$(CC) $(CFLAGS) $*.c", NULL};
  181. char * bltInCmd3[] = {"$(CPP) $(CPPFLAGS) /c $*.cpp", NULL};
  182. char * bltInCmd4[] = {"$(CPP) $(CPPFLAGS) $*.cpp", NULL};
  183. char * bltInCmd5[] = {"$(CXX) $(CXXFLAGS) /c $*.cxx", NULL};
  184. char * bltInCmd6[] = {"$(CXX) $(CXXFLAGS) $*.cxx", NULL};
  185. char * bltInCmd7[] = {"$(AS) $(AFLAGS) /c $*.asm", NULL};
  186. char * bltInCmd8[] = {"$(AS) $(AFLAGS) $*.asm", NULL};
  187. char * bltInCmd9[] = {"$(BC) $(BFLAGS) $*.bas;", NULL};
  188. char * bltInCmd10[] = {"$(COBOL) $(COBFLAGS) $*.cbl;", NULL};
  189. char * bltInCmd11[] = {"$(COBOL) $(COBFLAGS) $*.cbl, $*.exe;", NULL};
  190. char * bltInCmd12[] = {"$(FOR) /c $(FFLAGS) $*.for", NULL};
  191. char * bltInCmd13[] = {"$(FOR) $(FFLAGS) $*.for", NULL};
  192. char * bltInCmd14[] = {"$(PASCAL) /c $(PFLAGS) $*.pas", NULL};
  193. char * bltInCmd15[] = {"$(PASCAL) $(PFLAGS) $*.pas", NULL};
  194. char * bltInCmd16[] = {"$(RC) $(RFLAGS) /r $*", NULL};
  195. char ** builtInCom[] = {bltInCmd0, bltInCmd1, bltInCmd2, bltInCmd3,
  196. bltInCmd4, bltInCmd5, bltInCmd6, bltInCmd7,
  197. bltInCmd8, bltInCmd9, bltInCmd10, bltInCmd11,
  198. bltInCmd12, bltInCmd13, bltInCmd14, bltInCmd15,
  199. bltInCmd16, NULL};
  200. /* ----------------------------------------------------------------------------
  201. * Local to this module
  202. */
  203. #ifndef NO_OPTION_Z
  204. LOCAL char nmakeExitLabelCmd[] = ":NMAKEEXIT";
  205. #endif
  206. /* --------------------------------------------------------------------
  207. * main
  208. *
  209. * actions: saves the initial global variables in a
  210. * block. calls doMake() and then delTempScriptFiles()
  211. */
  212. void __cdecl
  213. main(
  214. unsigned argc,
  215. char *argv[],
  216. char *envp[]) /* environment variables */
  217. {
  218. extern unsigned saveBytes;
  219. extern char **envPtr;
  220. int status; /* returned by doMake */
  221. extern char *makeStr;
  222. #ifdef OS2_SIGNALS
  223. PUSHORT prev;
  224. unsigned long _FAR *pfnsig;
  225. #endif
  226. InitializeEnv();
  227. #if defined(FLAT)
  228. fRunningUnderTNT = FIsTNT();
  229. #endif
  230. initCharmap();
  231. initMacroTable(macroTable);
  232. #ifdef DEBUG_MEMORY
  233. //This puts 0xff in all free entries in the heap
  234. _heapset(0xff);
  235. #endif
  236. envPtr = envp;
  237. #ifdef DEBUG_COMMANDLINE
  238. {
  239. int iArg = argc;
  240. char **chchArg = argv;
  241. for (; iArg--; chchArg++)
  242. printf("'%s' ", *chchArg);
  243. printf("\n");
  244. }
  245. #endif
  246. #ifdef TEST_RUNTIME
  247. //Tests RunTime error R6001
  248. {char near *foo = NULL; *foo = '1';}
  249. #endif
  250. #ifdef DOS
  251. startupDir = getCurDir();
  252. #endif
  253. #ifdef FLAT
  254. resultbuf_size = sizeof(struct _finddata_t);
  255. #ifdef NT
  256. ext_size = CCHMAXPATHCOMP;
  257. filename_size = CCHMAXPATHCOMP;
  258. filenameext_size = CCHMAXPATH;
  259. #endif
  260. #else
  261. /* If OS/2 1.2 and beyond then allowed max sizes vary
  262. */
  263. if (_osmajor < 10 || _osmode == DOS_MODE)
  264. resultbuf_size = sizeof(struct find_t);
  265. else if (_osminor < 20)
  266. resultbuf_size = sizeof(struct FileFindBuf);
  267. else {
  268. ext_size = CCHMAXPATHCOMP;
  269. filename_size = CCHMAXPATHCOMP;
  270. filenameext_size = CCHMAXPATH;
  271. resultbuf_size = sizeof(struct _FILEFINDBUF);
  272. }
  273. #endif
  274. if (!makeStr) /* extract file name */
  275. if (!filename(_ftcscpy(fileStr, _pgmptr), &makeStr))
  276. makeStr = "NMAKE";
  277. // Initialize the message file
  278. SetErrorFile("nmake.err", _pgmptr, 1); // 1=Search Exe Path
  279. #if defined(SELF_RECURSE)
  280. initSavPtr = (char *)allocate(saveBytes = (&endOfSave - &startOfSave));
  281. memmove(initSavPtr, &startOfSave, saveBytes);
  282. #endif
  283. /* set up handler for .PRECIOUS the handler tries to remove the
  284. * current target when control-C'd, unless it is "precious"
  285. */
  286. #ifdef OS2_SIGNALS
  287. This commented out part was trial for using OS/2 function calls
  288. It still has some problems
  289. DOSSETSIGHANDLER(chkPrecious, pfnsig, prev, SIGA_ACCEPT, SIG_CTRLC);
  290. if (_osmode == OS2_MODE) {
  291. DOSSETSIGHANDLER(chkPrecious, NULL, NULL, SIGA_ACCEPT, SIG_CTRLBREAK);
  292. DOSSETSIGHANDLER(chkPrecious, NULL, NULL, SIGA_ACCEPT, SIG_KILLPROCESS);
  293. }
  294. #endif
  295. signal(SIGINT, chkPrecious);
  296. signal(SIGTERM, chkPrecious);
  297. makeIdeMessage(0, 0);
  298. status = doMake(argc, argv, NULL);
  299. #ifndef NO_OPTION_Z
  300. /* If -Z is specified then NMAKE needs to have errorLevel check in the
  301. * batch file. So add the goto label for exit and print the Reverse batch
  302. * file
  303. */
  304. if (ON(gFlags, F1_REVERSE_BATCH_FILE)) {
  305. STRINGLIST *revCmd;
  306. //Adds ':NMAKEEXIT' to jump to end when error occurs
  307. revCmd = makeNewStrListElement();
  308. revCmd->text = nmakeExitLabelCmd;
  309. prependItem(&revList, revCmd);
  310. //'=c' means echo at current line
  311. revCmd = makeNewStrListElement();
  312. revCmd->text = makeString("=c");
  313. appendItem(&revList, revCmd);
  314. //'=d' turns echoing on (unless preceeded by @)
  315. revCmd = makeNewStrListElement();
  316. revCmd->text = makeString("=d");
  317. appendItem(&revList, revCmd);
  318. }
  319. #endif
  320. delScriptFiles();
  321. #ifndef NO_OPTION_Z
  322. if (ON(gFlags, F1_REVERSE_BATCH_FILE))
  323. printReverseFile();
  324. #endif
  325. #ifdef MEMORY_DEBUG
  326. mem_status();
  327. #endif
  328. #ifdef HEAP_DIAGNOSTICS
  329. printHeapDiagnostics();
  330. #endif
  331. #ifdef NMK_DEBUG
  332. fprintf(stderr, "Exiting...\n");
  333. #endif
  334. if (!fSlashKStatus)
  335. //error when slashK specified
  336. status = 1;
  337. #if !defined(NDEBUG) && !defined(NT_BUILD)
  338. printStats();
  339. #endif
  340. exit(status);
  341. }
  342. //
  343. // On some systems, the environment strings may be allocated as one large block,
  344. // making it expensive to manipulate them. In that case, we copy each environment
  345. // strings to its own allocation and release the large block
  346. //
  347. LOCAL void NEAR
  348. InitializeEnv(
  349. void
  350. ) {
  351. #if !defined(FLAT)
  352. char **ppch = copyEnviron(environ);
  353. free(*environ);
  354. free(environ);
  355. environ = ppch;
  356. #endif
  357. }
  358. extern void NEAR endNameList(void);
  359. extern void NEAR addItemToList(void);
  360. extern void NEAR assignDependents(void);
  361. extern void NEAR assignBuildCommands(void);
  362. /* loadBuiltInRules() -- Loads built in Rules to the NMAKE Tables
  363. *
  364. * Modifies:
  365. * fInheritUserEnv -- is set to TRUE to inherit CC, AS
  366. *
  367. * Notes:
  368. * Does this by calls to defineMacro(), which calls putMacro(). Since,
  369. * fInheritUserEnv is set to TRUE, putMacro() will add to the Environment.
  370. */
  371. LOCAL void NEAR
  372. loadBuiltInRules(void)
  373. {
  374. char *tempTarg;
  375. char **tempCom;
  376. unsigned index;
  377. char *macroName, *macroValue;
  378. extern char *makestr;
  379. /* We dynamically allocate CC and AS because they need to be freed in a
  380. * recursive MAKE
  381. */
  382. macroName = makeString("CC");
  383. macroValue = makeString("cl");
  384. defineMacro(macroName, macroValue, 0);
  385. macroName = makeString("CXX");
  386. macroValue = makeString("cl");
  387. defineMacro(macroName, macroValue, 0);
  388. macroName = makeString("CPP");
  389. macroValue = makeString("cl");
  390. defineMacro(macroName, macroValue, 0);
  391. macroName = makeString("AS");
  392. macroValue = makeString("ml");
  393. defineMacro(macroName, macroValue, 0);
  394. macroName = makeString("BC");
  395. macroValue = makeString("bc");
  396. defineMacro(macroName, macroValue, 0);
  397. macroName = makeString("COBOL");
  398. macroValue = makeString("cobol");
  399. defineMacro(macroName, macroValue, 0);
  400. macroName = makeString("FOR");
  401. macroValue = makeString("fl");
  402. defineMacro(macroName, macroValue, 0);
  403. macroName = makeString("PASCAL");
  404. macroValue = makeString("pl");
  405. defineMacro(macroName, macroValue, 0);
  406. macroName = makeString("RC");
  407. macroValue = makeString("rc");
  408. defineMacro(macroName, macroValue, 0);
  409. macroName = makeString("MAKE");
  410. macroValue = makeString(makeStr);
  411. /* From environment so it won't get exported ; user can reset MAKE
  412. */
  413. defineMacro(macroName, macroValue, M_ENVIRONMENT_DEF|M_WARN_IF_RESET);
  414. for (index = 0; tempTarg = builtInTarg[index]; index++) {
  415. name = makeString(tempTarg);
  416. _ftcscpy(buf, ":");
  417. endNameList();
  418. for (tempCom=builtInCom[index];*tempCom;tempCom++) {
  419. _ftcscpy(buf, *tempCom);
  420. addItemToList();
  421. }
  422. if (index == 0)
  423. assignDependents();
  424. assignBuildCommands();
  425. }
  426. }
  427. /* ----------------------------------------------------------------------------
  428. * doMake()
  429. *
  430. * actions: prints a version message
  431. * reads the environment variable MAKEFLAGS
  432. * if MAKEFLAGS defined
  433. * defines MAKEFLAGS to have that value w/in nmake
  434. * sets a flag for each option if MAKEFLAGS defined
  435. * else defines the macro MAKEFLAGS to be NULL
  436. * parses commandline (adding option letters to MAKEFLAGS)
  437. * reads all environment variables
  438. * reads tools.ini
  439. * reads makefile(s) (if -e flag set, new definitions in
  440. * makefile won't override environment variable defs)
  441. * prints information if -p flag
  442. * processes makefile(s)
  443. * prints information if -d flag and not -p flag (using both
  444. * is overkill)
  445. *
  446. * In effect, the order for making assignments is (1 = least binding,
  447. * 4 = most binding):
  448. *
  449. * 1) TOOLS.INI
  450. * 2) environment (if -e flag, makefile)
  451. * 3) makefile (if -e flag, environment)
  452. * 4) command line
  453. *
  454. * The user can put anything he wants in the MAKEFLAGS environment variable.
  455. * I don't check it for illegal flag values, because there are many xmake
  456. * flags that we don't support. He shouldn't have to change his MAKEFLAGS
  457. * to use nmake. Xmake always puts 'b' in MAKEFLAGS for "backward com-
  458. * patibility" (or "botch") for the original Murray Hill version of make.
  459. * It doesn't make sense to use -f in MAKEFLAGS, thus it is disallowed.
  460. * It also makes little sense to let the default flags be -r, -p, or -d,
  461. * so they aren't allowed in MAKEFLAGS, either.
  462. *
  463. * Even though DOS only uses uppercase in environment variables, this
  464. * program may be ported to xenix in the future, thus we allow for the
  465. * possibility that MAKEFLAGS and commandline options will be in upper
  466. * and/or lower case.
  467. *
  468. * modifies: init global flag set if tools.ini is being parsed...
  469. */
  470. int NEAR
  471. doMake(argc, argv, parentBlkPtr)
  472. unsigned argc;
  473. char *argv[];
  474. char *parentBlkPtr; /* state of parent, restored prior to return */
  475. {
  476. int status = 0;
  477. char *p;
  478. extern char *makeStr; /* the initial make invok name */
  479. extern unsigned saveBytes;
  480. char *makeDir, *curDir;
  481. #ifdef DEBUG_ALL
  482. printf ("DEBUG: In doMake\n");
  483. #endif
  484. #if !defined(SELF_RECURSE)
  485. assert(parentBlkPtr == NULL);
  486. #endif
  487. /*
  488. * Load built-ins here rather than in main(). Otherwise in a recursive
  489. * make, doMake() will initialize rules to some value which has been
  490. * freed by sortRules(). [RB]
  491. * UNDONE: why is sortRules() not setting rules to NULL? [RB]
  492. */
  493. #ifdef DEBUG
  494. heapdump(__FILE__, __LINE__);
  495. #endif
  496. inlineFileList = (STRINGLIST *)NULL;
  497. makeDir = makeString("MAKEDIR");
  498. curDir = getCurDir();
  499. defineMacro(makeDir, curDir, 0);
  500. //TEMPFIX: We are truncating MAKEFLAGS environment variable to its limit
  501. //to avoid GP Faults
  502. if (p = getenv("MAKEFLAGS")) /* but not MAKEFLAGS */
  503. _ftcsncpy(makeflags+10, p, _ftcslen(makeflags + 10));
  504. /*
  505. * fInheritUserEnv is set to TRUE so that the changes made get inherited
  506. */
  507. fInheritUserEnv = (BOOL)TRUE;
  508. //
  509. // 07-05-92 BryanT Simply adding global strings to the macro array
  510. // causes problems later when you go to free them
  511. // from a recursive $(MAKE). Both the macro name
  512. // and the macro's value must be created with
  513. // makeString.
  514. defineMacro(makeString("MAKEFLAGS"), makeString(makeflags+10), M_NON_RESETTABLE|M_ENVIRONMENT_DEF);
  515. for (;p && *p; p++) /* set flags in MAKEFLAGS */
  516. setFlags(*p, TRUE); /* TRUE says turn bits ON */
  517. #ifdef DEBUG_ALL
  518. heapdump(__FILE__, __LINE__);
  519. #endif
  520. parseCommandLine(--argc, ++argv); /* skip over program name */
  521. #ifdef DEBUG_ALL
  522. printf ("DEBUG: Command Line parsed\n");
  523. #endif
  524. #ifndef NO_OPTION_Z
  525. if (ON(gFlags, F1_REVERSE_BATCH_FILE) &&
  526. (ON(flags, F2_NO_EXECUTE) || ON(gFlags, F1_TOUCH_TARGETS)))
  527. // We ignore /Z option when /N or /T is also specified
  528. setFlags('Z', FALSE);
  529. #endif
  530. #ifdef DEAD_CODE
  531. makeError(0, CMDLINE_N_Z_INCOMPATIBLE, makeStr);
  532. #endif
  533. if (!bannerDisplayed) displayBanner(); /* version number, etc. */
  534. if (OFF(gFlags, F1_IGNORE_EXTERN_RULES)) { /* read tools.ini */
  535. #ifdef DEBUG_ALL
  536. printf ("DEBUG: Read Tools.ini\n");
  537. #endif
  538. loadBuiltInRules();
  539. #ifdef DEBUG_ALL
  540. printf ("DEBUG: loadBuiltInRules\n");
  541. #endif
  542. fName = "tools.ini";
  543. #ifdef DEBUG_ALL
  544. heapdump(__FILE__, __LINE__);
  545. #endif
  546. if (tagOpen("INIT", fName, makeStr)) {
  547. ++line;
  548. init = TRUE; /* tools.ini being parsed */
  549. #ifdef DEBUG_ALL
  550. heapdump(__FILE__, __LINE__);
  551. #endif
  552. #ifdef DEBUG_ALL
  553. printf ("DEBUG: Start Parse\n");
  554. #endif
  555. parse();
  556. #ifdef DEBUG_ALL
  557. printf ("DEBUG: Parsed\n");
  558. #endif
  559. if (fclose(file) == EOF)
  560. makeError(0, ERROR_CLOSING_FILE, fName);
  561. }
  562. }
  563. #ifdef DEBUG_ALL
  564. heapdump(__FILE__, __LINE__);
  565. #endif
  566. #ifdef DEBUG_ALL
  567. printf ("after tagopen\n");
  568. #endif
  569. // For XMake Compatibility MAKEFLAGS should always be inherited to the Env
  570. // Put copy of makeflags so that the environment can be freed on return
  571. // from a recursive make
  572. if (PutEnv(makeString(makeflags)) == -1)
  573. makeError(0, OUT_OF_ENV_SPACE);
  574. #ifdef DEBUG_ALL
  575. printf ("after putenv\n");
  576. #endif
  577. if (!makeFiles) useDefaultMakefile(); /* if no -f makefile given*/
  578. #ifdef DEBUG_ALL
  579. printf ("DEBUG: Used default\n");
  580. #endif
  581. readEnvironmentVars();
  582. readMakeFiles(); /* read description files */
  583. #ifdef DEBUG_ALL
  584. printf ("DEBUG: Read makefile\n");
  585. #endif
  586. currentLine = 0; /* reset line after done */
  587. sortRules(); /* reading files (for */
  588. if (ON(gFlags, F1_PRINT_INFORMATION)) { /* error messages) */
  589. showMacros();
  590. showRules();
  591. showTargets();
  592. }
  593. /* free buffer used for conditional processing - not required now */
  594. if (lbufPtr)
  595. FREE(lbufPtr);
  596. #ifdef DEBUG_ALL
  597. heapdump(__FILE__, __LINE__);
  598. #endif
  599. status = processTree();
  600. #if defined(SELF_RECURSE)
  601. /* restore state of the parent into the global area */
  602. if (parentBlkPtr) {
  603. /* free the space used up for this make invocation */
  604. /* free the rule list, the macroTable, the targetTable */
  605. freeStructures();
  606. memmove(&startOfSave, parentBlkPtr, saveBytes);
  607. FREE(parentBlkPtr);
  608. }
  609. #endif
  610. #ifdef DEBUG_ALL
  611. heapdump(__FILE__, __LINE__);
  612. #endif
  613. //We ignore retval from chdir because we cannot do anything if it fails
  614. //This accomplishes a 'cd $(MAKEDIR)'.
  615. _chdir(curDir);
  616. return(status);
  617. }
  618. /*** filename -- filename part of a name ***************************************
  619. *
  620. * Scope:
  621. * Local
  622. *
  623. * Purpose:
  624. * A complete file name is of the form <drive:><path><filename><.ext>. This
  625. * function returns the filename part of the name.
  626. *
  627. * Input:
  628. * src -- The complete file name
  629. * dst -- filename part of the complete file name
  630. *
  631. * Output:
  632. * Returns TRUE if src has a filename part & FALSE otherwise
  633. *
  634. * Assumes:
  635. * That the file name could have either '/' or '\' as path separator.
  636. *
  637. * Modifies Globals:
  638. * None.
  639. *
  640. * Uses Globals:
  641. * None.
  642. *
  643. * Notes:
  644. * Allocates memory for filename part. Function was rewritten to support OS/2
  645. * Ver 1.2 filenames.
  646. *
  647. * HV: One concern when I rewrite filename() to use _splitpath(): I declared
  648. * szFilename with size _MAX_FNAME, which could blow up the stack if _MAX_FNAME
  649. * is too large.
  650. *
  651. *******************************************************************************/
  652. LOCAL BOOL NEAR
  653. filename(const char *src, char **dst)
  654. {
  655. char szFilename[_MAX_FNAME]; // The filename part
  656. // Split the full pathname to components
  657. _splitpath(src, NULL, NULL, szFilename, NULL);
  658. // Allocate & copy the filename part to the return string
  659. *dst = makeString(szFilename);
  660. // Finished
  661. return (BOOL) _ftcslen(*dst);
  662. }
  663. /* ----------------------------------------------------------------------------
  664. * readMakeFiles()
  665. *
  666. * actions: walks through the list calling parse on each makefile
  667. * resets the line number before parsing each file
  668. * removes name of parsed file from list
  669. * frees removed element's storage space
  670. *
  671. * modifies: file global file pointer (FILE*)
  672. * fName global pointer to file name (char*)
  673. * line global line number used and updated by the
  674. * lexer
  675. * init global flag reset for parsing makefiles
  676. * ( files other than tools.ini )
  677. * makeFiles in main() by modifying contents of local
  678. * pointer (list)
  679. *
  680. * We keep from fragmenting memory by not allocating and then freeing space
  681. * for the (probably few) names in the files and targets lists. Instead
  682. * we use the space already allocated for the argv[] vars, and use the space
  683. * we alloc for the commandfile vars. The commandfile vars that could be
  684. * freed here, but they aren't because we can't tell them from the argv[]
  685. * vars. They will be freed at the end of the program.
  686. */
  687. LOCAL void NEAR
  688. readMakeFiles(void)
  689. {
  690. STRINGLIST *q;
  691. for (q = makeFiles; q ; q = q->next) { /* for each name in list */
  692. if ((q->text)[0] == '-' && !(q->text)[1]) {
  693. fName = makeString("STDIN");
  694. file = stdin;
  695. }
  696. else {
  697. fName = makeString(q->text);
  698. if (!(file = FILEOPEN(fName, "rt"))) /* open to read, text mode*/
  699. makeError(0, CANT_OPEN_FILE, fName);
  700. }
  701. line = 0;
  702. init = FALSE; /* not parsing tools.ini */
  703. parse();
  704. if (file != stdin && fclose(file) == EOF)
  705. makeError(0, ERROR_CLOSING_FILE, fName);
  706. }
  707. //free the list of makefiles
  708. freeStringList(makeFiles);
  709. }
  710. /*** readEnvironmentVars - Read in environment variables into Macro table ******
  711. *
  712. * Scope:
  713. * Local.
  714. *
  715. * Purpose:
  716. * Reads environment variables into the NMAKE macro Table. It walks through envp
  717. * using environ making entries in NMAKE's hash table of macros for each string
  718. * in the table.
  719. *
  720. * Input:
  721. *
  722. * Output:
  723. *
  724. * Errors/Warnings:
  725. *
  726. * Assumes:
  727. * That the env contains strings of the form "VAR=value" i.e. '=' present.
  728. *
  729. * Modifies Globals:
  730. * fInheritUserEnv - set to false.
  731. *
  732. * Uses Globals:
  733. * environ - Null terminated table of pointers to environment variable
  734. * definitions of the form "name=value" (Std C Runtime variable)
  735. *
  736. * Notes:
  737. * If the user specifies "set name=value" as a build command for a target being
  738. * built, the change in the environment will not be reflected in nmake's set of
  739. * defined variables in the macro table.
  740. *
  741. * Undone/Incomplete:
  742. * 1> Probably do not need envPtr global in NMAKE. (to be removed)
  743. * 2> Probably don't need fInheritUserEnv (see PutMacro)
  744. *
  745. *******************************************************************************/
  746. LOCAL void NEAR
  747. readEnvironmentVars(void)
  748. {
  749. char *macro, *value;
  750. char *t;
  751. char **envPtr;
  752. envPtr = environ;
  753. for (;*envPtr; ++envPtr) {
  754. if (t = _ftcschr(*envPtr, '=')) { /* should always be TRUE */
  755. if (!_ftcsnicmp(*envPtr, "MAKEFLAGS", 8))
  756. continue;
  757. *t = '\0';
  758. // Don't add empty names.
  759. if (**envPtr == '\0')
  760. continue;
  761. // ALLOC: here we make copies of the macro name and value to define
  762. macro = _ftcsupr(makeString(*envPtr));
  763. value = makeString(t+1);
  764. *t = '=';
  765. fInheritUserEnv = (BOOL)FALSE;
  766. if (!defineMacro(macro, value, M_ENVIRONMENT_DEF)) {
  767. // ALLOC: here we free the copies if they were not added.
  768. FREE(macro);
  769. FREE(value);
  770. }
  771. }
  772. }
  773. }
  774. /* ----------------------------------------------------------------------------
  775. * parseCommandLine()
  776. *
  777. * arguments: argc count of arguments in argv vector
  778. * argv table of pointers to commandline arguments
  779. *
  780. * actions: reads a command file if necessary
  781. * sets switches
  782. * defines macros
  783. * makes a list of makefiles to read
  784. * makes a list of targets to build
  785. *
  786. * modifies: makeFiles in main() by modifying contents of parameter
  787. * pointer (list) to STRINGLIST pointer
  788. * (makeFiles)
  789. * makeTargets in main() by modifying contents of param
  790. * pointer (targets) to STRINGLIST pointer
  791. * fInheritUserEnv set to TRUE so that user defined changes in the
  792. * environment variables get inherited by the Env
  793. *
  794. * nmake doesn't make new copies of command line macro values or environment
  795. * variables, but instead uses pointers to the space already allocated.
  796. * This can cause problems if the envp, the environment pointer, is accessed
  797. * elsewhere in the program (because the vector's strings will contain '\0'
  798. * where they used to contain '='). I don't foresee any need for envp[] to
  799. * be used elsewhere. Even if we did need to use the environment, we could
  800. * access the environ variable or use getenv().
  801. *
  802. * I don't care what the current DOS "switch" character is -- I always
  803. * let the user give either.
  804. */
  805. char *helpArguments[] = {"QH", "/u", "NMAKE.EXE", NULL };
  806. void NEAR
  807. parseCommandLine(argc, argv)
  808. unsigned argc;
  809. char *argv[];
  810. {
  811. extern char *makeStr;
  812. STRINGLIST *p;
  813. char *s;
  814. char *t;
  815. FILE *out;
  816. BOOL fHelp = FALSE;
  817. BOOL fQuestion = FALSE;
  818. for (; argc; --argc, ++argv) {
  819. if (**argv == '@') /* cmdfile*/
  820. readCommandFile((char*)*argv+1);
  821. else if (**argv == '-'|| **argv == '/') { /* switch */
  822. s = *argv + 1;
  823. if (!_ftcsicmp(s, "help")) {
  824. fHelp = TRUE;
  825. break;
  826. }
  827. // if '-' and '/' specified then ignores it
  828. for (; *s; ++s) {
  829. if (!_ftcsicmp(s, "nologo")) {
  830. setFlags(s[2], TRUE);
  831. break;
  832. }
  833. #ifdef HEAP
  834. else if (!_ftcsicmp(s, "debug")) {
  835. fHeapChk = TRUE;
  836. break;
  837. }
  838. #endif
  839. else if (*s == '?') {
  840. fQuestion = TRUE;
  841. break;
  842. }
  843. else if (*s == 'f' || *s == 'F') {
  844. char *mkfl = s+1;
  845. //if '/ffoo' then use 'foo'; else use next argument
  846. if (!*mkfl && (!--argc || !*++argv || !*(mkfl = *argv)))
  847. makeError(0, CMDLINE_F_NO_FILENAME);
  848. p = makeNewStrListElement();
  849. p->text = makeString(mkfl);
  850. appendItem(&makeFiles, p);
  851. break;
  852. }
  853. else if (*s == 'x' || *s == 'X') {
  854. char *errfl = s+1;
  855. //if '/xfoo' then use 'foo'; else use next argument
  856. if (!*errfl && (!--argc || !*++argv || !*(errfl = *argv)))
  857. makeError(0, CMDLINE_X_NO_FILENAME);
  858. if (*errfl == '-' && !errfl[1])
  859. _dup2(_fileno(stdout), _fileno(stderr));
  860. else {
  861. #if 0 /* C5 runtime bug */
  862. if (freopen(errfl, "wt", stderr) == NULL)
  863. makeError(0, CANT_OPEN_FILE, errfl);
  864. #else
  865. if ((out = fopen(errfl, "wt")) == NULL)
  866. makeError(0, CANT_WRITE_FILE, errfl);
  867. _dup2(_fileno(out), _fileno(stderr));
  868. fclose(out);
  869. #endif
  870. }
  871. break;
  872. }
  873. else
  874. setFlags(*s, TRUE);
  875. } // of for
  876. }
  877. else {
  878. if (s = _ftcschr(*argv, '=')) { /* macro */
  879. if (s == *argv)
  880. //User has specified "=value"
  881. makeError(0, CMDLINE_NO_MACRONAME);
  882. *s = '\0';
  883. for (t = s++ - 1; WHITESPACE(*t); --t)
  884. ;
  885. *(t+1) = '\0';
  886. fInheritUserEnv = (BOOL)TRUE;
  887. defineMacro(makeString(*argv+_ftcsspn(*argv, " \t")),
  888. makeString( s+_ftcsspn(s," \t")),
  889. M_NON_RESETTABLE);
  890. }
  891. else {
  892. removeTrailChars(*argv);
  893. if (**argv) {
  894. p = makeNewStrListElement(); /* target */
  895. p->text = makeString(*argv); /* needs to be on heap [rm]*/
  896. appendItem(&makeTargets, p);
  897. }
  898. }
  899. *argv = NULL; /* so we won't try to free*/
  900. } /* this space if process-*/
  901. } /* ing command file stuff*/
  902. if (fHelp) {
  903. #ifdef QUICKHELP
  904. int rc = _spawnvp(P_WAIT, "QH.EXE", helpArguments);
  905. //Qh /u returns error code 3 if a cmd line topic is not found
  906. //If the spawn fails spawnvp will return -1 and we need -help
  907. //message, also
  908. //Qh never returns -1
  909. if (rc == 3 || rc == -1) {
  910. usage();
  911. }
  912. #else
  913. usage();
  914. #endif
  915. exit(0);
  916. }
  917. else if (fQuestion) {
  918. usage();
  919. exit(0);
  920. }
  921. }
  922. /*** useDefaultMakefile -- tries to use the default makefile *******************
  923. *
  924. * Scope:
  925. * Local
  926. *
  927. * Purpose:
  928. * When no makefile has been specified by the user, set up the default makefile
  929. * to be used.
  930. *
  931. * Input:
  932. * Output:
  933. * Errors/Warnings:
  934. * CMDLINE_NO_MAKEFILE -- 'makefile' does not exist & no target specified
  935. *
  936. * Assumes:
  937. * Modifies Globals:
  938. * makeTargets -- if 'makefile' does not exist then the first target is removed
  939. * from this list,
  940. * makeFiles -- if 'makefile' does not exist then the first target is attached
  941. * to this list.
  942. *
  943. * Uses Globals:
  944. * makeTargets -- the list of targets to be made
  945. *
  946. * Notes:
  947. * Given a commandline not containing a '-f makefile', this is how NMAKE
  948. * behaves --
  949. * If ['makefile' exists] then use it as the makefile,
  950. * if [(the first target exists and has no extension) or
  951. * (if it exists and has an extension for which no inference rule
  952. * exists)]
  953. * then use it as the makefile.
  954. *
  955. *******************************************************************************/
  956. LOCAL void NEAR
  957. useDefaultMakefile(void)
  958. {
  959. STRINGLIST *p;
  960. char *s,
  961. *ext;
  962. char nameBuf[MAXNAME];
  963. void *dBuf = _alloca(resultbuf_size);
  964. //if 'makefile' exists then use it
  965. if (!_access("makefile", READ)) {
  966. p = makeNewStrListElement();
  967. p->text = makeString("makefile");
  968. makeFiles = p;
  969. }
  970. //check first target
  971. else if (makeTargets) {
  972. s = makeTargets->text;
  973. if (_access(s, READ) || //1st target does not exist
  974. ((ext = _ftcsrchr(s, '.'))
  975. && findRule(nameBuf, s, ext, dBuf))) { //has no ext or inf rule
  976. return;
  977. }
  978. p = makeTargets;
  979. makeTargets = makeTargets->next; //one less target
  980. makeFiles = p; //1st target is the makefile
  981. }
  982. //if -p and no makefile, simply give information ...
  983. else if (OFF(gFlags, F1_PRINT_INFORMATION))
  984. makeError(0, CMDLINE_NO_MAKEFILE); //no 'makefile' or target
  985. }
  986. /* ----------------------------------------------------------------------------
  987. * setFlags()
  988. *
  989. * arguments: line current line number in makefile (or 0
  990. * if still parsing commandline)
  991. * c letter presumed to be a commandline option
  992. * value TRUE if flag should be turned on, FALSE for off
  993. *
  994. * actions: checks to see if c is a valid option-letter
  995. * if no, error, halt
  996. * if value is TRUE, sets corresponding flag bit
  997. * and adds flag letter to MAKEFLAGS macro def
  998. * else if flag is resettable, clears corresponding bit
  999. * and removes letter from MAKEFLAGS macro def
  1000. *
  1001. * modifies: flags external resettable-flags
  1002. * gFlags external non-resettable flags
  1003. * (MAKEFLAGS nmake internal macrodefs)
  1004. *
  1005. * Only the flags w/in the "flags" variable can be turned off. Once the
  1006. * bits in "gFlags" are set, they remain unchanged. The bits in "flags"
  1007. * are modified via the !CMDSWITCHES directive.
  1008. */
  1009. void NEAR
  1010. setFlags(c, value)
  1011. char c;
  1012. BOOL value;
  1013. {
  1014. /*
  1015. * Use lexer's line count. If this gets called w/in
  1016. * mkfil, might be from directive, which never makes it
  1017. * to the parser, so parser's line count might be out
  1018. * of sync.
  1019. */
  1020. char d = c;
  1021. UCHAR arg;
  1022. UCHAR *f;
  1023. char *s;
  1024. extern char *makeStr;
  1025. extern MACRODEF * NEAR pMacros;
  1026. extern STRINGLIST * NEAR pValues;
  1027. f = &flags;
  1028. switch(c = (char) _totupper(c)) {
  1029. case 'A': arg = F2_FORCE_BUILD; break;
  1030. case 'B': fRebuildOnTie = TRUE; return;
  1031. case 'C': arg = F1_CRYPTIC_OUTPUT;
  1032. f = &gFlags;
  1033. bannerDisplayed = TRUE;
  1034. break;
  1035. case 'D': arg = F2_DISPLAY_FILE_DATES; break;
  1036. case 'E': arg = F1_USE_ENVIRON_VARS; f = &gFlags; break;
  1037. case 'I': arg = F2_IGNORE_EXIT_CODES; break;
  1038. case 'K': fOptionK = TRUE; return;
  1039. case 'L': arg = F1_NO_LOGO;
  1040. f = &gFlags;
  1041. bannerDisplayed = TRUE;
  1042. break;
  1043. #if defined(DOS) && !defined(FLAT)
  1044. case 'M': fNoEmsXms = TRUE; return;
  1045. #endif
  1046. case 'N': arg = F2_NO_EXECUTE; break;
  1047. case 'O': fDescRebuildOrder = TRUE; return;
  1048. case 'P': arg = F1_PRINT_INFORMATION; f = &gFlags; break;
  1049. case 'Q': arg = F1_QUESTION_STATUS; f = &gFlags; break;
  1050. case 'R': arg = F1_IGNORE_EXTERN_RULES; f = &gFlags; break;
  1051. case 'S': arg = F2_NO_ECHO; break;
  1052. case 'T': arg = F1_TOUCH_TARGETS; f = &gFlags; break;
  1053. #if defined(SELF_RECURSE)
  1054. case 'V': fInheritMacros = TRUE; return;
  1055. #endif
  1056. #ifndef NO_OPTION_Z
  1057. case 'Z':
  1058. //Silently ignore /Z in protect mode
  1059. #if defined(DOS) && !defined(FLAT)
  1060. arg = F1_REVERSE_BATCH_FILE;
  1061. f = &gFlags;
  1062. bannerDisplayed = TRUE;
  1063. #endif
  1064. break;
  1065. #endif
  1066. case ' ': return; /* recursive make problem */
  1067. default: makeError(0, CMDLINE_BAD_OPTION, d);
  1068. }
  1069. if (!pMacros) {
  1070. pMacros = findMacro("MAKEFLAGS");
  1071. pValues = pMacros->values;
  1072. }
  1073. if (value) {
  1074. SET(*f, arg); /* set bit in flags variable */
  1075. if (c == 'Q') SET(*f, F1_CRYPTIC_OUTPUT);
  1076. if (!_ftcschr(pValues->text, c)) { /* don't want to dup any chars*/
  1077. if (s = _ftcschr(pValues->text, ' ')) /*append ch to MAKEFLAGS */
  1078. *s = c;
  1079. if (PutEnv(makeString(makeflags)) == -1) /*pValues->text pts into makeflags*/
  1080. makeError(line, OUT_OF_ENV_SPACE);
  1081. }
  1082. }
  1083. else if (f == &flags
  1084. #ifndef NO_OPTION_Z
  1085. || ON(gFlags, F1_REVERSE_BATCH_FILE)
  1086. #endif
  1087. ) {
  1088. /* make sure pointer is valid (we can't change gFlags, except if /Z */
  1089. CLEAR(*f, arg);
  1090. if (s = _ftcschr(pValues->text, c)) /* adjust MAKEFLAGS */
  1091. do {
  1092. *s = *(s+1); /* move remaining chars over */
  1093. } while (*(++s));
  1094. if (PutEnv(makeString(makeflags)) == -1)
  1095. makeError(line, OUT_OF_ENV_SPACE);
  1096. }
  1097. }
  1098. #if defined(SELF_RECURSE)
  1099. extern void NEAR freeList(STRINGLIST*);
  1100. extern void NEAR freeMacroTable(MACRODEF *table[]);
  1101. LOCAL void NEAR
  1102. freeStructures(void)
  1103. {
  1104. unsigned num;
  1105. MAKEOBJECT *tmpObjectT;
  1106. MAKEOBJECT *objectT;
  1107. BUILDLIST *buildL, *tmpBuildL;
  1108. freeMacroTable(macroTable);
  1109. freeRules(rules, FALSE); //don't warn about rules in .SUFFIXES
  1110. rules = NULL;
  1111. for (num=0;(num < MAXTARGET);num++) {
  1112. objectT = targetTable[num];
  1113. while (tmpObjectT = objectT) {
  1114. objectT = objectT->next;
  1115. buildL = tmpObjectT->buildList;
  1116. while (tmpBuildL = buildL) {
  1117. buildL = buildL->next;
  1118. block = tmpBuildL->buildBlock;
  1119. //
  1120. // 15-May-92 BryanT Macros are freed from the macroTable.
  1121. // Don't do it here... Commands and
  1122. // dependents are freed by endNameList.
  1123. // Not here
  1124. //
  1125. // freeList(block->dependents);
  1126. // freeList(block->buildCommands);
  1127. // freeList(block->dependentMacros);
  1128. // freeList(block->buildMacros);
  1129. FREE(block);
  1130. FREE(tmpBuildL);
  1131. }
  1132. FREE(tmpObjectT->name);
  1133. FREE(tmpObjectT);
  1134. }
  1135. }
  1136. freeList(inlineFileList); //The Global inline file list
  1137. freeList(dotSuffixList);
  1138. FREE(fName);
  1139. }
  1140. #endif
  1141. /*
  1142. * chkPrecious -- handle ^c or ^Break
  1143. *
  1144. * Actions: unlink all non-precious files and unrequired scriptFiles
  1145. * quit with error message (makeError unlinks temp. files)
  1146. */
  1147. #ifdef OS2_SIGNALS
  1148. void pascal
  1149. #else
  1150. LOCAL void __cdecl
  1151. #endif
  1152. chkPrecious(
  1153. #ifdef OS2_SIGNALS
  1154. USHORT usSigArg,
  1155. USHORT usSigNum
  1156. #else
  1157. int sig
  1158. #endif
  1159. ) {
  1160. extern UCHAR okToDelete;
  1161. #ifdef OS2_SIGNALS
  1162. USHORT fAction;
  1163. #endif
  1164. #ifdef DOS
  1165. //change directory to startup directory; ignore error code ... we
  1166. //cannot handle it
  1167. chdir(startupDir);
  1168. #endif
  1169. /* disable ctrl-C during handler */
  1170. #ifdef OS2_SIGNALS
  1171. DOSSETSIGHANDLER(NULL, NULL, &fAction, SIGA_IGNORE, SIG_CTRLC);
  1172. if (_osmode == OS2_MODE) {
  1173. DOSSETSIGHANDLER(NULL, NULL, &fAction, SIGA_IGNORE, SIG_CTRLBREAK);
  1174. DOSSETSIGHANDLER(NULL, NULL, &fAction, SIGA_IGNORE, SIG_KILLPROCESS);
  1175. }
  1176. #endif
  1177. signal(SIGINT, SIG_IGN);
  1178. signal(SIGTERM, SIG_IGN);
  1179. delScriptFiles();
  1180. #ifdef OS2_SIGNALS
  1181. DosExit(EXIT_PROCESS, 0L);
  1182. #endif
  1183. if (okToDelete
  1184. #ifndef NO_OPTION_Z
  1185. && OFF(gFlags, F1_REVERSE_BATCH_FILE)
  1186. #endif
  1187. && OFF(flags, F2_NO_EXECUTE)
  1188. && OFF(gFlags, F1_TOUCH_TARGETS)
  1189. && dollarAt
  1190. && _access(dollarAt, 0x00) // existence check
  1191. && !isPrecious(dollarAt))
  1192. if (_unlink(dollarAt) == 0)
  1193. makeError(line, REMOVED_TARGET, dollarAt);
  1194. makeError(0, USER_INTERRUPT);
  1195. }
  1196. LOCAL UCHAR NEAR
  1197. isPrecious(p)
  1198. char *p;
  1199. {
  1200. STRINGLIST *temp;
  1201. for (temp = dotPreciousList; temp; temp = temp->next)
  1202. if (!_ftcsicmp(temp->text, p))
  1203. return(1);
  1204. return(0);
  1205. }
  1206. /*** delScriptFiles -- deletes script files ************************************
  1207. *
  1208. * Scope:
  1209. * Global
  1210. *
  1211. * Purpose:
  1212. * Since script files may be reused in the makefile the script files which have
  1213. * NOKEEP action specified are deleted at the end of the make.
  1214. *
  1215. * Input:
  1216. *
  1217. * Output:
  1218. *
  1219. * Errors/Warnings:
  1220. *
  1221. * Assumes:
  1222. *
  1223. * Modifies Globals:
  1224. *
  1225. * Uses Globals:
  1226. * delList -- the list of script files to be deleted
  1227. *
  1228. * Notes:
  1229. * We ignore the exit code as a result of a delete because the system will
  1230. * inform the user that a delete failed.
  1231. *
  1232. *******************************************************************************/
  1233. void NEAR
  1234. delScriptFiles(void)
  1235. {
  1236. STRINGLIST *del;
  1237. #ifndef NO_OPTION_Z
  1238. STRINGLIST *revCmd;
  1239. #endif
  1240. _fcloseall();
  1241. #ifndef NO_OPTION_Z
  1242. if (ON(gFlags, F1_REVERSE_BATCH_FILE)) {
  1243. revCmd = makeNewStrListElement();
  1244. revCmd->text = makeString(":ABEND");
  1245. prependItem(&revList, revCmd);
  1246. }
  1247. #endif
  1248. for (del = delList; del;del = del->next) {
  1249. #ifndef NO_OPTION_Z
  1250. if (ON(gFlags, F1_REVERSE_BATCH_FILE)) {
  1251. revCmd = makeNewStrListElement();
  1252. revCmd->text = (char *)allocate(5 + _ftcslen(del->text) + 5 + 1);
  1253. sprintf(revCmd->text, "@del %s >nul", del->text);
  1254. //UNDONE: Is the next one more efficient than prev ? Investigate
  1255. //_ftcscat(_ftcscat(_ftcscpy(revCmd->text, "del "), del->text), " >nul");
  1256. prependItem(&revList, revCmd);
  1257. }
  1258. else
  1259. #endif
  1260. _unlink(del->text);
  1261. //UNDONE: Investigate whether next is really needed
  1262. if (ON(flags, F2_NO_EXECUTE)) {
  1263. printf("\tdel %s\n", del->text);
  1264. fflush(stdout);
  1265. }
  1266. }
  1267. }
  1268. /*** removeTrailChars - removes trailing blanks and dots ***********************
  1269. *
  1270. * Scope:
  1271. * Local.
  1272. *
  1273. * Purpose:
  1274. * OS/2 1.2 filenames dictate removal of trailing blanks and periods. This
  1275. * function removes them from filenames provided to it.
  1276. *
  1277. * Input:
  1278. * szFile - name of file
  1279. *
  1280. * Output:
  1281. *
  1282. * Errors/Warnings:
  1283. *
  1284. * Assumes:
  1285. *
  1286. * Modifies Globals:
  1287. *
  1288. * Uses Globals:
  1289. *
  1290. * Notes:
  1291. * This function handles Quoted filenames as well. It maintains the quotes if
  1292. * they were present. This is basically for OS/2 1.2 filename support.
  1293. *
  1294. *******************************************************************************/
  1295. void NEAR
  1296. removeTrailChars(szFile)
  1297. char *szFile;
  1298. {
  1299. char *t = szFile + _ftcslen(szFile) - 1;
  1300. BOOL fQuoted = FALSE;
  1301. if (*szFile == '"' && *t == '"') {
  1302. //Quoted so set flag
  1303. t--;
  1304. fQuoted = TRUE;
  1305. }
  1306. //Scan backwards for trailing characters
  1307. while (t > szFile && (*t == ' ' || *t == '.'))
  1308. t--;
  1309. //t points to last non-trailing character
  1310. //If it was quoted add quotes to the end
  1311. if (fQuoted)
  1312. *++t = '"';
  1313. t[1] = '\0';
  1314. }