Source code of Windows XP (NT5)
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.

1198 lines
38 KiB

  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. #include "precomp.h"
  109. #pragma hdrstop
  110. #include "verstamp.h"
  111. void readEnvironmentVars(void);
  112. void readMakeFiles(void);
  113. void useDefaultMakefile(void);
  114. BOOL filename(const char*, char**);
  115. void __cdecl chkPrecious(int sig);
  116. UCHAR isPrecious(char*);
  117. void removeTrailChars(char *);
  118. void usage (void);
  119. char *makeStr; // this make invocation name
  120. UCHAR okToDelete; // do not del unless exec'ing cmd
  121. #ifdef _M_IX86
  122. UCHAR fRunningUnderChicago;
  123. extern UCHAR FIsChicago(void);
  124. #endif
  125. const char * const builtInTarg[] = {
  126. ".SUFFIXES",
  127. ".c.obj",
  128. ".c.exe",
  129. ".cpp.obj",
  130. ".cpp.exe",
  131. ".cxx.obj",
  132. ".cxx.exe",
  133. #if defined(_M_IX86) || defined(_M_MRX000)
  134. ".asm.obj",
  135. ".asm.exe",
  136. #endif
  137. #if !defined(_M_IX86)
  138. ".s.obj",
  139. #endif
  140. ".bas.obj",
  141. ".cbl.obj",
  142. ".cbl.exe",
  143. ".f.obj",
  144. ".f.exe",
  145. ".f90.obj",
  146. ".f90.exe",
  147. ".for.obj",
  148. ".for.exe",
  149. ".pas.obj",
  150. ".pas.exe",
  151. ".rc.res",
  152. NULL
  153. };
  154. const char * const bltInCmd0[] = {
  155. ":",
  156. ".exe",
  157. ".obj",
  158. #if defined(_M_IX86) || defined(_M_MRX000)
  159. ".asm",
  160. #endif
  161. #if !defined(_M_IX86)
  162. ".s",
  163. #endif
  164. ".c",
  165. ".cpp",
  166. ".cxx",
  167. ".bas",
  168. ".cbl",
  169. ".f",
  170. ".f90",
  171. ".for",
  172. ".pas",
  173. ".res",
  174. ".rc",
  175. NULL
  176. };
  177. // Single colon (":") specifies ordinary rules
  178. // Double colon ("::") specifies batch rules
  179. const char * const bltInCmd1[] = {":", "$(CC) $(CFLAGS) /c $<", NULL};
  180. const char * const bltInCmd2[] = {":", "$(CC) $(CFLAGS) $<", NULL};
  181. const char * const bltInCmd3[] = {":", "$(CPP) $(CPPFLAGS) /c $<", NULL};
  182. const char * const bltInCmd4[] = {":", "$(CPP) $(CPPFLAGS) $<", NULL};
  183. const char * const bltInCmd5[] = {":", "$(CXX) $(CXXFLAGS) /c $<", NULL};
  184. const char * const bltInCmd6[] = {":", "$(CXX) $(CXXFLAGS) $<", NULL};
  185. #if defined(_M_IX86) || defined(_M_MRX000)
  186. const char * const bltInCmd7[] = {":", "$(AS) $(AFLAGS) /c $*.asm", NULL};
  187. const char * const bltInCmd8[] = {":", "$(AS) $(AFLAGS) $*.asm", NULL};
  188. #endif
  189. #if !defined(_M_IX86)
  190. #if defined(_M_MRX000)
  191. const char * const bltInCmd9[] = {":", "$(AS) $(AFLAGS) /c $*.s", NULL};
  192. #else
  193. const char * const bltInCmd9[] = {":", "$(AS) $(AFLAGS) $*.s", NULL};
  194. #endif
  195. #endif
  196. const char * const bltInCmd10[] = {":", "$(BC) $(BFLAGS) $*.bas;", NULL};
  197. const char * const bltInCmd11[] = {":", "$(COBOL) $(COBFLAGS) $*.cbl;", NULL};
  198. const char * const bltInCmd12[] = {":", "$(COBOL) $(COBFLAGS) $*.cbl, $*.exe;", NULL};
  199. const char * const bltInCmd13[] = {":", "$(FOR) /c $(FFLAGS) $*.f", NULL};
  200. const char * const bltInCmd14[] = {":", "$(FOR) $(FFLAGS) $*.f", NULL};
  201. const char * const bltInCmd15[] = {":", "$(FOR) /c $(FFLAGS) $*.f90", NULL};
  202. const char * const bltInCmd16[] = {":", "$(FOR) $(FFLAGS) $*.f90", NULL};
  203. const char * const bltInCmd17[] = {":", "$(FOR) /c $(FFLAGS) $*.for", NULL};
  204. const char * const bltInCmd18[] = {":", "$(FOR) $(FFLAGS) $*.for", NULL};
  205. const char * const bltInCmd19[] = {":", "$(PASCAL) /c $(PFLAGS) $*.pas", NULL};
  206. const char * const bltInCmd20[] = {":", "$(PASCAL) $(PFLAGS) $*.pas", NULL};
  207. const char * const bltInCmd21[] = {":", "$(RC) $(RFLAGS) /r $*", NULL};
  208. const char * const * const builtInCom[] = {
  209. bltInCmd0,
  210. bltInCmd1,
  211. bltInCmd2,
  212. bltInCmd3,
  213. bltInCmd4,
  214. bltInCmd5,
  215. bltInCmd6,
  216. #if defined(_M_IX86) || defined(_M_MRX000)
  217. bltInCmd7,
  218. bltInCmd8,
  219. #endif
  220. #if !defined(_M_IX86)
  221. bltInCmd9,
  222. #endif
  223. bltInCmd10,
  224. bltInCmd11,
  225. bltInCmd12,
  226. bltInCmd13,
  227. bltInCmd14,
  228. bltInCmd15,
  229. bltInCmd16,
  230. bltInCmd17,
  231. bltInCmd18,
  232. bltInCmd19,
  233. bltInCmd20,
  234. bltInCmd21,
  235. NULL
  236. };
  237. // main
  238. //
  239. // actions: saves the initial global variables in a
  240. // block. calls doMake() and then delTempScriptFiles()
  241. void __cdecl
  242. main(
  243. unsigned argc,
  244. char *argv[],
  245. char *envp[]
  246. )
  247. {
  248. int status; // returned by doMake
  249. #ifdef _M_IX86
  250. fRunningUnderChicago = FIsChicago();
  251. #endif
  252. initCharmap();
  253. initMacroTable(macroTable);
  254. #ifdef DEBUG_COMMANDLINE
  255. {
  256. int iArg = argc;
  257. char **chchArg = argv;
  258. for (; iArg--; chchArg++) {
  259. printf("'%s' ", *chchArg);
  260. }
  261. printf("\n");
  262. }
  263. #endif
  264. if (!makeStr) {
  265. // extract file name
  266. if (!filename(_pgmptr, &makeStr)) {
  267. makeStr = "NMAKE";
  268. }
  269. }
  270. // set up handler for .PRECIOUS the handler tries to remove the
  271. // current target when control-C'd, unless it is "precious"
  272. signal(SIGINT, chkPrecious);
  273. signal(SIGTERM, chkPrecious);
  274. status = doMake(argc, argv, NULL);
  275. delScriptFiles();
  276. if (!fSlashKStatus) {
  277. status = 1; // error when slashK specified
  278. }
  279. #if !defined(NDEBUG)
  280. printStats();
  281. #endif
  282. exit(status);
  283. }
  284. extern void endNameList(void);
  285. extern void addItemToList(void);
  286. extern void assignDependents(void);
  287. extern void assignBuildCommands(void);
  288. // loadBuiltInRules() -- Loads built in Rules to the NMAKE Tables
  289. //
  290. // Modifies:
  291. // fInheritUserEnv -- is set to TRUE to inherit CC, AS
  292. //
  293. // Notes:
  294. // Does this by calls to defineMacro(), which calls putMacro(). Since,
  295. // fInheritUserEnv is set to TRUE, putMacro() will add to the Environment.
  296. void
  297. loadBuiltInRules(
  298. void
  299. )
  300. {
  301. const char *tempTarg;
  302. const char * const *tempCom;
  303. unsigned index;
  304. char *macroName, *macroValue;
  305. extern char *makestr;
  306. // We dynamically allocate CC and AS because they need to be freed in a
  307. // recursive MAKE
  308. macroName = makeString("CC");
  309. macroValue = makeString("cl");
  310. defineMacro(macroName, macroValue, 0);
  311. macroName = makeString("CXX");
  312. macroValue = makeString("cl");
  313. defineMacro(macroName, macroValue, 0);
  314. macroName = makeString("CPP");
  315. macroValue = makeString("cl");
  316. defineMacro(macroName, macroValue, 0);
  317. macroName = makeString("AS");
  318. #if defined(_M_ALPHA)
  319. macroValue = makeString("asaxp");
  320. #else
  321. // UNDONE: What is appropriate for IA64?
  322. macroValue = makeString("ml");
  323. #endif
  324. defineMacro(macroName, macroValue, 0);
  325. macroName = makeString("BC");
  326. macroValue = makeString("bc");
  327. defineMacro(macroName, macroValue, 0);
  328. macroName = makeString("COBOL");
  329. macroValue = makeString("cobol");
  330. defineMacro(macroName, macroValue, 0);
  331. macroName = makeString("FOR");
  332. macroValue = makeString("fl32");
  333. defineMacro(macroName, macroValue, 0);
  334. macroName = makeString("PASCAL");
  335. macroValue = makeString("pl");
  336. defineMacro(macroName, macroValue, 0);
  337. macroName = makeString("RC");
  338. macroValue = makeString("rc");
  339. defineMacro(macroName, macroValue, 0);
  340. macroName = makeString("_NMAKE_VER");
  341. macroValue = makeString(VER_PRODUCTVERSION_STR);
  342. defineMacro(macroName, macroValue, 0);
  343. macroName = makeString("MAKE");
  344. macroValue = makeString(makeStr);
  345. // From environment so it won't get exported ; user can reset MAKE
  346. defineMacro(macroName, macroValue, M_ENVIRONMENT_DEF|M_WARN_IF_RESET);
  347. for (index = 0; tempTarg = builtInTarg[index]; index++) {
  348. name = makeString(tempTarg);
  349. tempCom = builtInCom[index];
  350. // tempCom should now contain a single or double colon
  351. assert (tempCom && *tempCom && **tempCom == ':');
  352. _tcscpy(buf, *tempCom);
  353. endNameList();
  354. for (tempCom++; *tempCom; tempCom++) {
  355. _tcscpy(buf, *tempCom);
  356. addItemToList();
  357. }
  358. if (index == 0) {
  359. assignDependents();
  360. }
  361. assignBuildCommands();
  362. }
  363. }
  364. // doMake()
  365. //
  366. // actions: prints a version message
  367. // reads the environment variable MAKEFLAGS
  368. // if MAKEFLAGS defined
  369. // defines MAKEFLAGS to have that value w/in nmake
  370. // sets a flag for each option if MAKEFLAGS defined
  371. // else defines the macro MAKEFLAGS to be NULL
  372. // parses commandline (adding option letters to MAKEFLAGS)
  373. // reads all environment variables
  374. // reads tools.ini
  375. // reads makefile(s) (if -e flag set, new definitions in
  376. // makefile won't override environment variable defs)
  377. // prints information if -p flag
  378. // processes makefile(s)
  379. // prints information if -d flag and not -p flag (using both
  380. // is overkill)
  381. //
  382. // In effect, the order for making assignments is (1 = least binding,
  383. // 4 = most binding):
  384. //
  385. // 1) TOOLS.INI
  386. // 2) environment (if -e flag, makefile)
  387. // 3) makefile (if -e flag, environment)
  388. // 4) command line
  389. //
  390. // The user can put anything he wants in the MAKEFLAGS environment variable.
  391. // I don't check it for illegal flag values, because there are many xmake
  392. // flags that we don't support. He shouldn't have to change his MAKEFLAGS
  393. // to use nmake. Xmake always puts 'b' in MAKEFLAGS for "backward com-
  394. // patibility" (or "botch") for the original Murray Hill version of make.
  395. // It doesn't make sense to use -f in MAKEFLAGS, thus it is disallowed.
  396. // It also makes little sense to let the default flags be -r, -p, or -d,
  397. // so they aren't allowed in MAKEFLAGS, either.
  398. //
  399. // Even though DOS only uses uppercase in environment variables, this
  400. // program may be ported to xenix in the future, thus we allow for the
  401. // possibility that MAKEFLAGS and commandline options will be in upper
  402. // and/or lower case.
  403. //
  404. // modifies: init global flag set if tools.ini is being parsed...
  405. int
  406. doMake(
  407. unsigned argc,
  408. char *argv[],
  409. char *parentBlkPtr // state of parent, restored prior to return
  410. )
  411. {
  412. int status = 0;
  413. char *p;
  414. extern char *makeStr; // the initial make invok name
  415. char *makeDir, *curDir;
  416. #ifdef DEBUG_ALL
  417. printf ("DEBUG: In doMake\n");
  418. #endif
  419. assert(parentBlkPtr == NULL);
  420. // Load built-ins here rather than in main(). Otherwise in a recursive
  421. // make, doMake() will initialize rules to some value which has been
  422. // freed by sortRules(). [RB]
  423. // UNDONE: why is sortRules() not setting rules to NULL? [RB]
  424. inlineFileList = (STRINGLIST *)NULL;
  425. makeDir = makeString("MAKEDIR");
  426. curDir = getCurDir();
  427. // Use M_LITERAL flag to prevent nmake from trying to
  428. // interpret $ in path as an embedded macro. [DS 14983]
  429. defineMacro(makeDir, curDir, M_LITERAL);
  430. // TEMPFIX: We are truncating MAKEFLAGS environment variable to its limit
  431. // to avoid GP Faults
  432. if (p = getenv("MAKEFLAGS")) { // but not MAKEFLAGS
  433. _tcsncpy(makeflags+10, p, _tcslen(makeflags + 10));
  434. }
  435. // fInheritUserEnv is set to TRUE so that the changes made get inherited
  436. fInheritUserEnv = TRUE;
  437. // 07-05-92 BryanT Simply adding global strings to the macro array
  438. // causes problems later when you go to free them
  439. // from a recursive $(MAKE). Both the macro name
  440. // and the macro's value must be created with
  441. // makeString.
  442. defineMacro(makeString("MAKEFLAGS"), makeString(makeflags+10), M_NON_RESETTABLE|M_ENVIRONMENT_DEF);
  443. for (;p && *p; p++) { // set flags in MAKEFLAGS
  444. setFlags(*p, TRUE); // TRUE says turn bits ON
  445. }
  446. parseCommandLine(--argc, ++argv); // skip over program name
  447. #ifdef DEBUG_ALL
  448. printf ("DEBUG: Command Line parsed\n");
  449. #endif
  450. if (!bannerDisplayed) {
  451. displayBanner(); // version number, etc.
  452. }
  453. if (OFF(gFlags, F1_IGNORE_EXTERN_RULES)) { // read tools.ini
  454. #ifdef DEBUG_ALL
  455. printf ("DEBUG: Read Tools.ini\n");
  456. #endif
  457. loadBuiltInRules();
  458. #ifdef DEBUG_ALL
  459. printf ("DEBUG: loadBuiltInRules\n");
  460. #endif
  461. fName = "tools.ini";
  462. if (tagOpen("INIT", fName, makeStr)) {
  463. ++line;
  464. init = TRUE; // tools.ini being parsed
  465. #ifdef DEBUG_ALL
  466. printf ("DEBUG: Start Parse\n");
  467. #endif
  468. parse();
  469. #ifdef DEBUG_ALL
  470. printf ("DEBUG: Parsed\n");
  471. #endif
  472. if (fclose(file) == EOF)
  473. makeError(0, ERROR_CLOSING_FILE, fName);
  474. }
  475. }
  476. #ifdef DEBUG_ALL
  477. printf ("after tagopen\n");
  478. #endif
  479. // For XMake Compatibility MAKEFLAGS should always be inherited to the Env
  480. // Put copy of makeflags so that the environment can be freed on return
  481. // from a recursive make
  482. if (PutEnv(makeString(makeflags)) == -1) {
  483. makeError(0, OUT_OF_ENV_SPACE);
  484. }
  485. #ifdef DEBUG_ALL
  486. printf ("after putenv\n");
  487. #endif
  488. if (!makeFiles) {
  489. useDefaultMakefile(); // if no -f makefile given
  490. }
  491. readEnvironmentVars();
  492. readMakeFiles(); // read description files
  493. #ifdef DEBUG_ALL
  494. printf ("DEBUG: Read makefile\n");
  495. #endif
  496. currentLine = 0; // reset line after done
  497. sortRules(); // reading files (for error messages)
  498. if (ON(gFlags, F1_PRINT_INFORMATION)) {
  499. showMacros();
  500. showRules();
  501. showTargets();
  502. }
  503. // free buffer used for conditional processing - not required now
  504. if (lbufPtr) {
  505. FREE(lbufPtr);
  506. }
  507. status = processTree();
  508. // We ignore retval from chdir because we cannot do anything if it fails
  509. // This accomplishes a 'cd $(MAKEDIR)'.
  510. _chdir(curDir);
  511. return(status);
  512. }
  513. // filename -- filename part of a name
  514. //
  515. // Scope: Local
  516. //
  517. // Purpose:
  518. // A complete file name is of the form <drive:><path><filename><.ext>. This
  519. // function returns the filename part of the name.
  520. //
  521. // Input: src -- The complete file name
  522. // dst -- filename part of the complete file name
  523. //
  524. // Output: Returns TRUE if src has a filename part & FALSE otherwise
  525. //
  526. // Assumes: That the file name could have either '/' or '\' as path separator.
  527. //
  528. // Notes:
  529. // Allocates memory for filename part. Function was rewritten to support OS/2
  530. // Ver 1.2 filenames.
  531. //
  532. // HV: One concern when I rewrite filename() to use _splitpath(): I declared
  533. // szFilename with size _MAX_FNAME, which could blow up the stack if _MAX_FNAME
  534. // is too large.
  535. BOOL
  536. filename(
  537. const char *src,
  538. char **dst
  539. )
  540. {
  541. char szFilename[_MAX_FNAME]; // The filename part
  542. // Split the full pathname to components
  543. _splitpath(src, NULL, NULL, szFilename, NULL);
  544. // Allocate & copy the filename part to the return string
  545. *dst = makeString(szFilename);
  546. // Finished
  547. return (BOOL) _tcslen(*dst);
  548. }
  549. // readMakeFiles()
  550. //
  551. // actions: walks through the list calling parse on each makefile
  552. // resets the line number before parsing each file
  553. // removes name of parsed file from list
  554. // frees removed element's storage space
  555. //
  556. // modifies: file global file pointer (FILE*)
  557. // fName global pointer to file name (char*)
  558. // line global line number used and updated by the lexer
  559. // init global flag reset for parsing makefiles
  560. // ( files other than tools.ini )
  561. // makeFiles in main() by modifying contents of local pointer (list)
  562. //
  563. // We keep from fragmenting memory by not allocating and then freeing space
  564. // for the (probably few) names in the files and targets lists. Instead
  565. // we use the space already allocated for the argv[] vars, and use the space
  566. // we alloc for the commandfile vars. The commandfile vars that could be
  567. // freed here, but they aren't because we can't tell them from the argv[]
  568. // vars. They will be freed at the end of the program.
  569. void
  570. readMakeFiles(
  571. void
  572. )
  573. {
  574. STRINGLIST *q;
  575. for (q = makeFiles; q ; q = q->next) { // for each name in list
  576. if ((q->text)[0] == '-' && !(q->text)[1]) {
  577. fName = makeString("STDIN");
  578. file = stdin;
  579. } else {
  580. fName = makeString(q->text);
  581. if (!(file = FILEOPEN(fName, "rt"))) // open to read, text mode
  582. makeError(0, CANT_OPEN_FILE, fName);
  583. if (!IsValidMakefile(file))
  584. makeError(0, CANT_SUPPORT_UNICODE, fName);
  585. }
  586. line = 0;
  587. init = FALSE; // not parsing tools.ini
  588. parse();
  589. if (file != stdin && fclose(file) == EOF)
  590. makeError(0, ERROR_CLOSING_FILE, fName);
  591. }
  592. // free the list of makefiles
  593. freeStringList(makeFiles);
  594. }
  595. // readEnvironmentVars - Read in environment variables into Macro table
  596. //
  597. // Scope: Local.
  598. //
  599. // Purpose:
  600. // Reads environment variables into the NMAKE macro Table. It walks through envp
  601. // using environ making entries in NMAKE's hash table of macros for each string
  602. // in the table.
  603. //
  604. // Assumes: That the env contains strings of the form "VAR=value" i.e. '=' present.
  605. //
  606. // Modifies Globals: fInheritUserEnv - set to false.
  607. //
  608. // Uses Globals:
  609. // environ - Null terminated table of pointers to environment variable
  610. // definitions of the form "name=value" (Std C Runtime variable)
  611. //
  612. // Notes:
  613. // If the user specifies "set name=value" as a build command for a target being
  614. // built, the change in the environment will not be reflected in nmake's set of
  615. // defined variables in the macro table.
  616. //
  617. // Undone/Incomplete:
  618. // 1> Probably do not need envPtr global in NMAKE. (to be removed)
  619. // 2> Probably don't need fInheritUserEnv (see PutMacro)
  620. void
  621. readEnvironmentVars(
  622. void
  623. )
  624. {
  625. char *macro, *value;
  626. char *t;
  627. char **envPtr;
  628. envPtr = environ;
  629. for (;*envPtr; ++envPtr) {
  630. if (t = _tcschr(*envPtr, '=')) { // should always be TRUE
  631. if (!_tcsnicmp(*envPtr, "MAKEFLAGS", 8))
  632. continue;
  633. *t = '\0';
  634. // Don't add empty names.
  635. if (**envPtr == '\0')
  636. continue;
  637. // ALLOC: here we make copies of the macro name and value to define
  638. macro = _tcsupr(makeString(*envPtr));
  639. value = makeString(t+1);
  640. *t = '=';
  641. fInheritUserEnv = (BOOL)FALSE;
  642. if (!defineMacro(macro, value, M_ENVIRONMENT_DEF)) {
  643. // ALLOC: here we free the copies if they were not added.
  644. FREE(macro);
  645. FREE(value);
  646. }
  647. }
  648. }
  649. }
  650. // parseCommandLine()
  651. //
  652. // arguments: argc count of arguments in argv vector
  653. // argv table of pointers to commandline arguments
  654. //
  655. // actions: reads a command file if necessary
  656. // sets switches
  657. // defines macros
  658. // makes a list of makefiles to read
  659. // makes a list of targets to build
  660. //
  661. // modifies: makeFiles in main() by modifying contents of parameter
  662. // pointer (list) to STRINGLIST pointer
  663. // (makeFiles)
  664. // makeTargets in main() by modifying contents of param
  665. // pointer (targets) to STRINGLIST pointer
  666. // fInheritUserEnv set to TRUE so that user defined changes in the
  667. // environment variables get inherited by the Env
  668. //
  669. // nmake doesn't make new copies of command line macro values or environment
  670. // variables, but instead uses pointers to the space already allocated.
  671. // This can cause problems if the envp, the environment pointer, is accessed
  672. // elsewhere in the program (because the vector's strings will contain '\0'
  673. // where they used to contain '='). I don't foresee any need for envp[] to
  674. // be used elsewhere. Even if we did need to use the environment, we could
  675. // access the environ variable or use getenv().
  676. //
  677. // I don't care what the current DOS "switch" character is -- I always
  678. // let the user give either.
  679. void
  680. parseCommandLine(
  681. unsigned argc,
  682. char *argv[]
  683. )
  684. {
  685. STRINGLIST *p;
  686. char *s;
  687. char *t;
  688. FILE *out;
  689. BOOL fUsage = FALSE;
  690. for (; argc; --argc, ++argv) {
  691. if (**argv == '@') { // cmdfile
  692. readCommandFile((char *) *argv+1);
  693. } else if (**argv == '-'|| **argv == '/') { // switch
  694. s = *argv + 1;
  695. if (!_tcsicmp(s, "help")) {
  696. fUsage = TRUE;
  697. break;
  698. }
  699. // if '-' and '/' specified then ignores it
  700. for (; *s; ++s) {
  701. if (!_tcsicmp(s, "nologo")) {
  702. setFlags(s[2], TRUE);
  703. break;
  704. } else if (*s == '?') {
  705. fUsage = TRUE;
  706. break;
  707. } else if (*s == 'f' || *s == 'F') {
  708. char *mkfl = s+1;
  709. //if '/ffoo' then use 'foo'; else use next argument
  710. if (!*mkfl && (!--argc || !*++argv || !*(mkfl = *argv))) {
  711. makeError(0, CMDLINE_F_NO_FILENAME);
  712. }
  713. p = makeNewStrListElement();
  714. p->text = makeString(mkfl);
  715. appendItem(&makeFiles, p);
  716. break;
  717. } else if (*s == 'x' || *s == 'X') {
  718. char *errfl = s+1;
  719. //if '/xfoo' then use 'foo'; else use next argument
  720. if (!*errfl && (!--argc || !*++argv || !*(errfl = *argv))) {
  721. makeError(0, CMDLINE_X_NO_FILENAME);
  722. }
  723. if (*errfl == '-' && !errfl[1]) {
  724. _dup2(_fileno(stdout), _fileno(stderr));
  725. } else {
  726. if ((out = fopen(errfl, "wt")) == NULL) {
  727. makeError(0, CANT_WRITE_FILE, errfl);
  728. }
  729. _dup2(_fileno(out), _fileno(stderr));
  730. fclose(out);
  731. }
  732. break;
  733. } else {
  734. setFlags(*s, TRUE);
  735. }
  736. }
  737. } else {
  738. if (s = _tcschr(*argv, '=')) { // macro
  739. if (s == *argv) {
  740. makeError(0, CMDLINE_NO_MACRONAME); // User has specified "=value"
  741. }
  742. *s = '\0';
  743. for (t = s++ - 1; WHITESPACE(*t); --t)
  744. ;
  745. *(t+1) = '\0';
  746. fInheritUserEnv = (BOOL)TRUE;
  747. defineMacro(makeString(*argv+_tcsspn(*argv, " \t")),
  748. makeString( s+_tcsspn(s," \t")),
  749. M_NON_RESETTABLE);
  750. } else {
  751. removeTrailChars(*argv);
  752. if (**argv) {
  753. p = makeNewStrListElement(); // target
  754. // use quotes around name if it contains spaces [vs98 1935]
  755. if (_tcschr(*argv, ' ')) {
  756. p->text = makeQuotedString(*argv);
  757. }
  758. else {
  759. p->text = makeString(*argv); // needs to be on heap [rm]
  760. }
  761. appendItem(&makeTargets, p);
  762. }
  763. }
  764. *argv = NULL; // so we won't try to free this space
  765. } // if processing command file stuff
  766. }
  767. if (fUsage) {
  768. usage();
  769. exit(0);
  770. }
  771. }
  772. // useDefaultMakefile -- tries to use the default makefile
  773. //
  774. // Scope:
  775. // Local
  776. //
  777. // Purpose:
  778. // When no makefile has been specified by the user, set up the default makefile
  779. // to be used.
  780. //
  781. // Input:
  782. // Output:
  783. // Errors/Warnings:
  784. // CMDLINE_NO_MAKEFILE -- 'makefile' does not exist & no target specified
  785. //
  786. // Assumes:
  787. // Modifies Globals:
  788. // makeTargets -- if 'makefile' does not exist then the first target is removed
  789. // from this list,
  790. // makeFiles -- if 'makefile' does not exist then the first target is attached
  791. // to this list.
  792. //
  793. // Uses Globals:
  794. // makeTargets -- the list of targets to be made
  795. //
  796. // Notes:
  797. // Given a commandline not containing a '-f makefile', this is how NMAKE
  798. // behaves --
  799. // If ['makefile' exists] then use it as the makefile,
  800. // if [(the first target exists and has no extension) or
  801. // (if it exists and has an extension for which no inference rule
  802. // exists)]
  803. // then use it as the makefile.
  804. void
  805. useDefaultMakefile(
  806. void
  807. )
  808. {
  809. STRINGLIST *p;
  810. char *s, *ext;
  811. char nameBuf[MAXNAME];
  812. struct _finddata_t finddata;
  813. if (!_access("makefile", READ)) {
  814. // if 'makefile' exists then use it
  815. p = makeNewStrListElement();
  816. p->text = makeString("makefile");
  817. makeFiles = p;
  818. } else if (makeTargets) {
  819. //check first target
  820. s = makeTargets->text;
  821. if (_access(s, READ) || // 1st target does not exist
  822. ((ext = _tcsrchr(s, '.'))
  823. && findRule(nameBuf, s, ext, &finddata))) { //has no ext or inf rule
  824. return;
  825. }
  826. p = makeTargets;
  827. makeTargets = makeTargets->next; // one less target
  828. makeFiles = p; // 1st target is the makefile
  829. } else if (OFF(gFlags, F1_PRINT_INFORMATION)) {
  830. //if -p and no makefile, simply give information ...
  831. makeError(0, CMDLINE_NO_MAKEFILE); // no 'makefile' or target
  832. }
  833. }
  834. // setFlags()
  835. //
  836. // arguments: line current line number in makefile (or 0
  837. // if still parsing commandline)
  838. // c letter presumed to be a commandline option
  839. // value TRUE if flag should be turned on, FALSE for off
  840. //
  841. // actions: checks to see if c is a valid option-letter
  842. // if no, error, halt
  843. // if value is TRUE, sets corresponding flag bit
  844. // and adds flag letter to MAKEFLAGS macro def
  845. // else if flag is resettable, clears corresponding bit
  846. // and removes letter from MAKEFLAGS macro def
  847. //
  848. // modifies: flags external resettable-flags
  849. // gFlags external non-resettable flags
  850. // (MAKEFLAGS nmake internal macrodefs)
  851. //
  852. // Only the flags w/in the "flags" variable can be turned off. Once the
  853. // bits in "gFlags" are set, they remain unchanged. The bits in "flags"
  854. // are modified via the !CMDSWITCHES directive.
  855. void
  856. setFlags(
  857. char c,
  858. BOOL value
  859. )
  860. {
  861. // Use lexer's line count. If this gets called w/in mkfil, might be from
  862. // directive, which never makes it to the parser, so parser's line count
  863. // might be out of sync.
  864. char d = c;
  865. UCHAR arg;
  866. UCHAR *f;
  867. char *s;
  868. extern char *makeStr;
  869. extern MACRODEF * pMacros;
  870. extern STRINGLIST * pValues;
  871. f = &flags;
  872. switch(c = (char) _totupper(c)) {
  873. case 'A':
  874. arg = F2_FORCE_BUILD;
  875. break;
  876. case 'B':
  877. fRebuildOnTie = TRUE;
  878. return;
  879. case 'C':
  880. arg = F1_CRYPTIC_OUTPUT;
  881. f = &gFlags;
  882. bannerDisplayed = TRUE;
  883. break;
  884. case 'D':
  885. arg = F2_DISPLAY_FILE_DATES;
  886. break;
  887. case 'E':
  888. arg = F1_USE_ENVIRON_VARS;
  889. f = &gFlags;
  890. break;
  891. case 'I':
  892. arg = F2_IGNORE_EXIT_CODES;
  893. break;
  894. case 'K':
  895. fOptionK = TRUE;
  896. return;
  897. case 'L':
  898. arg = F1_NO_LOGO;
  899. f = &gFlags;
  900. bannerDisplayed = TRUE;
  901. break;
  902. case 'N':
  903. arg = F2_NO_EXECUTE;
  904. break;
  905. case 'O':
  906. fDescRebuildOrder = TRUE;
  907. return;
  908. case 'P':
  909. arg = F1_PRINT_INFORMATION;
  910. f = &gFlags;
  911. break;
  912. case 'Q':
  913. arg = F1_QUESTION_STATUS;
  914. f = &gFlags;
  915. break;
  916. case 'R':
  917. arg = F1_IGNORE_EXTERN_RULES;
  918. f = &gFlags;
  919. break;
  920. case 'S':
  921. arg = F2_NO_ECHO;
  922. break;
  923. case 'T':
  924. arg = F1_TOUCH_TARGETS;
  925. f = &gFlags;
  926. break;
  927. case 'U':
  928. arg = F2_DUMP_INLINE;
  929. break;
  930. case 'Y':
  931. arg = F1_NO_BATCH;
  932. f = &gFlags;
  933. break;
  934. case ' ':
  935. return; // recursive make problem
  936. default:
  937. makeError(0, CMDLINE_BAD_OPTION, d);
  938. }
  939. if (!pMacros) {
  940. pMacros = findMacro("MAKEFLAGS");
  941. pValues = pMacros->values;
  942. }
  943. if (value) {
  944. SET(*f, arg); // set bit in flags variable
  945. if (c == 'Q') SET(*f, F1_CRYPTIC_OUTPUT);
  946. if (!_tcschr(pValues->text, c)) { // don't want to dup any chars
  947. if (s = _tcschr(pValues->text, ' ')) // append ch to MAKEFLAGS
  948. *s = c;
  949. if (PutEnv(makeString(makeflags)) == -1) // pValues->text pts into makeflags
  950. makeError(line, OUT_OF_ENV_SPACE);
  951. }
  952. } else if (f == &flags
  953. ) {
  954. // make sure pointer is valid (we can't change gFlags, except if /Z
  955. CLEAR(*f, arg);
  956. if (s = _tcschr(pValues->text, c)) // adjust MAKEFLAGS
  957. do {
  958. *s = *(s+1); // move remaining chars over
  959. } while (*(++s));
  960. if (PutEnv(makeString(makeflags)) == -1)
  961. makeError(line, OUT_OF_ENV_SPACE);
  962. }
  963. }
  964. // chkPrecious -- handle ^c or ^Break
  965. //
  966. // Actions: unlink all non-precious files and unrequired scriptFiles
  967. // quit with error message (makeError unlinks temp. files)
  968. void __cdecl
  969. chkPrecious(
  970. int sig
  971. )
  972. {
  973. // disable ctrl-C during handler
  974. signal(SIGINT, SIG_IGN);
  975. signal(SIGTERM, SIG_IGN);
  976. if (okToDelete &&
  977. OFF(flags, F2_NO_EXECUTE) &&
  978. OFF(gFlags, F1_TOUCH_TARGETS) &&
  979. dollarAt &&
  980. _access(dollarAt, 0x00) && // existence check
  981. !isPrecious(dollarAt)
  982. ) {
  983. if (_unlink(dollarAt) == 0)
  984. makeError(line, REMOVED_TARGET, dollarAt);
  985. }
  986. makeError(0, USER_INTERRUPT);
  987. delScriptFiles();
  988. }
  989. UCHAR
  990. isPrecious(
  991. char *p
  992. )
  993. {
  994. STRINGLIST *temp;
  995. for (temp = dotPreciousList; temp; temp = temp->next)
  996. if (!_tcsicmp(temp->text, p))
  997. return(1);
  998. return(0);
  999. }
  1000. // delScriptFiles -- deletes script files
  1001. //
  1002. // Scope: Global
  1003. //
  1004. // Purpose:
  1005. // Since script files may be reused in the makefile the script files which have
  1006. // NOKEEP action specified are deleted at the end of the make.
  1007. //
  1008. // Uses Globals: delList -- the list of script files to be deleted
  1009. //
  1010. // Notes:
  1011. // We ignore the exit code as a result of a delete because the system will
  1012. // inform the user that a delete failed.
  1013. void
  1014. delScriptFiles(
  1015. void
  1016. )
  1017. {
  1018. STRINGLIST *del;
  1019. _fcloseall();
  1020. for (del = delList; del;del = del->next) {
  1021. _unlink(del->text);
  1022. // UNDONE: Investigate whether next is really needed
  1023. if (ON(flags, F2_NO_EXECUTE)) {
  1024. printf("\tdel %s\n", del->text);
  1025. fflush(stdout);
  1026. }
  1027. }
  1028. }
  1029. // removeTrailChars - removes trailing blanks and dots
  1030. //
  1031. // Scope: Local.
  1032. //
  1033. // Purpose:
  1034. // OS/2 1.2 filenames dictate removal of trailing blanks and periods. This
  1035. // function removes them from filenames provided to it.
  1036. //
  1037. // Input: szFile - name of file
  1038. //
  1039. // Notes:
  1040. // This function handles Quoted filenames as well. It maintains the quotes if
  1041. // they were present. This is basically for OS/2 1.2 filename support.
  1042. void
  1043. removeTrailChars(
  1044. char *szFile
  1045. )
  1046. {
  1047. char *t = szFile + _tcslen(szFile) - 1;
  1048. BOOL fQuoted = FALSE;
  1049. if (*szFile == '"' && *t == '"') {
  1050. // Quoted so set flag
  1051. t--;
  1052. fQuoted = TRUE;
  1053. }
  1054. // Scan backwards for trailing characters
  1055. while (t > szFile && (*t == ' ' || *t == '.'))
  1056. t--;
  1057. // t points to last non-trailing character. It it was quited, add quotes
  1058. // to the end
  1059. if (fQuoted)
  1060. *++t = '"';
  1061. t[1] = '\0';
  1062. }