Leaked source code of windows server 2003
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.

755 lines
18 KiB

  1. //
  2. // mbrmake - Source Browser Source Data Base builder
  3. // (C) 1988 By Microsoft
  4. //
  5. // 29-Aug-1989 dw Minor fixes to aid in C 6 conversion
  6. //
  7. //
  8. #define LINT_ARGS
  9. // rjsa #include <signal.h>
  10. #include <process.h>
  11. #include <direct.h>
  12. #include <stdlib.h>
  13. // get version.h from mb
  14. #include "..\..\inc\version.h"
  15. #include "sbrvers.h"
  16. #include "sbrfdef.h"
  17. #include "mbrmake.h"
  18. #include <sys\types.h>
  19. #include <sys\stat.h>
  20. #include <tools.h>
  21. // this fixes the bogosity in config.h that gets included by tools.h
  22. // it will set DEBUG = 0 for a non-debug version...
  23. //
  24. // -rm
  25. #ifdef DEBUG
  26. #if DEBUG == 0
  27. #undef DEBUG
  28. #endif
  29. #endif
  30. static VOID TruncateSBR(char *lszName);
  31. static VOID ProcessSBR(char *lszName);
  32. static VOID MarkNewSBR(char *lszName);
  33. #ifdef DEBUG
  34. WORD near OptD = 0;
  35. #endif
  36. FILE * near streamOut = stdout;
  37. BOOL near OptEs = FALSE; // exclude system files
  38. BOOL near OptEm = FALSE; // exclude macro expansions
  39. BOOL near OptIu = FALSE; // include unreference symbols
  40. BOOL near OptV = FALSE; // verbose output
  41. BOOL near OptN = FALSE; // no incremental behaviour
  42. char near c_cwd[PATH_BUF]; // current working directory
  43. char near patbuf[PATH_BUF];
  44. MOD FAR * near modRes; // VM cache
  45. MODSYM FAR * near modsymRes;
  46. SYM FAR * near symRes;
  47. PROP FAR * near propRes;
  48. DEF FAR * near defRes;
  49. REF FAR * near refRes;
  50. CAL FAR * near calRes;
  51. CBY FAR * near cbyRes;
  52. ORD FAR * near ordRes;
  53. SBR FAR * near sbrRes;
  54. char FAR * near textRes;
  55. OCR FAR * near ocrRes;
  56. BYTE near fCase = FALSE; // TRUE for case compare
  57. BYTE near MaxSymLen = 0; // longest symbol len
  58. LSZ near lszFName; // Current input file
  59. LSZ near OutputFileName = NULL; // output file name
  60. FILE * near OutFile; // output file handle
  61. BOOL near fOutputBroken = FALSE; // we have dirtied the database
  62. VA near vaRootMod = vaNil; // module list
  63. VA near vaCurMod = vaNil; // current module
  64. VA near rgVaSym[MAXSYMPTRTBLSIZ]; // symbol list array
  65. EXCLINK FAR * near pExcludeFileList = NULL; // exclude file list
  66. struct mlist {
  67. int erno;
  68. char *text;
  69. };
  70. struct mlist WarnMsg[] = {
  71. 4500, "UNKNOWN WARNING\n\tContact Microsoft Product Support Services",
  72. 4501, "ignoring unknown option '%s'",
  73. 4502, "truncated .SBR file '%s' not in database",
  74. };
  75. struct mlist ErrorMsg[] = {
  76. 1500, "UNKNOWN ERROR\n\tContact Microsoft Product Support Services",
  77. 1501, "unknown character '%c' in option '%s'",
  78. 1502, "incomplete specification for option '%s'",
  79. 1503, "cannot write to file '%s'",
  80. 1504, "cannot position in file '%s'",
  81. 1505, "cannot read from file '%s'",
  82. 1506, "cannot open file '%s'",
  83. 1507, "cannot open temporary file '%s'",
  84. 1508, "cannot delete temporary file '%s'",
  85. 1509, "out of heap space",
  86. 1510, "corrupt .SBR file '%s'",
  87. 1511, "invalid response file specification",
  88. 1512, "database capacity exceeded",
  89. 1513, "nonincremental update requires all .SBR files",
  90. 1514, "all .SBR files truncated and not in database",
  91. };
  92. VOID
  93. Error (int imsg, char *parg)
  94. // print error number and message
  95. //
  96. {
  97. printf ("mbrmake: error U%d : ",ErrorMsg[imsg].erno);
  98. printf (ErrorMsg[imsg].text, parg);
  99. printf ("\n");
  100. Fatal();
  101. }
  102. VOID
  103. Error2 (int imsg, char achar, char *parg)
  104. // print error number and message with argument
  105. //
  106. {
  107. printf ("mbrmake: error U%d : ",ErrorMsg[imsg].erno);
  108. printf (ErrorMsg[imsg].text, achar, parg);
  109. printf ("\n");
  110. Fatal();
  111. }
  112. VOID
  113. Warning (int imsg, char *parg)
  114. // print warning number and message
  115. //
  116. {
  117. printf ("mbrmake: warning U%d : ",WarnMsg[imsg].erno);
  118. printf (WarnMsg[imsg].text, parg);
  119. printf ("\n");
  120. }
  121. VOID
  122. Fatal ()
  123. // fatal error, attempt to shut down and exit
  124. // if we already tried to shut down -- just abort without doing anything
  125. {
  126. static BOOL fTwice;
  127. if (!fTwice) {
  128. fTwice = TRUE;
  129. if (fOutputBroken) {
  130. if (OutFile) fclose(OutFile);
  131. if (OutputFileName != NULL) unlink(OutputFileName);
  132. }
  133. CloseVM();
  134. }
  135. exit(4);
  136. }
  137. VOID
  138. sigint ()
  139. {
  140. // signal(SIGBREAK, sigint);
  141. // signal(SIGINT, sigint);
  142. Fatal ();
  143. }
  144. LSZ
  145. LszDup(LSZ lsz)
  146. // like strdup only using LpvAllocCb to get the memory
  147. //
  148. {
  149. LSZ lszDup;
  150. lszDup = LpvAllocCb(strlen(lsz)+1);
  151. strcpy(lszDup, lsz);
  152. return lszDup;
  153. }
  154. LSZ
  155. LszDupNewExt(LSZ pname, LSZ pext)
  156. // duplicate the given filename changing the extension to be the given
  157. //
  158. {
  159. int i, len, elen;
  160. LSZ lsz;
  161. len = strlen(pname);
  162. elen = strlen(pext);
  163. // I know this looks like I should be doing a runtime call but nothing
  164. // does quite what I want here and I know that C6 will make great
  165. // code for this loop [rm]
  166. // find the first '.' starting from the back
  167. for (i=len; --i >= 0; )
  168. if (pname[i] == '.')
  169. break;
  170. // check to make sure we've got a real base name and not just all extension
  171. //
  172. if (i > 0) {
  173. // replace the extension with what's in pext
  174. lsz = LpvAllocCb(i + 1 + elen + 1); // base + dot + ext + nul
  175. memcpy(lsz, pname, i+1);
  176. strcpy(lsz+i+1, pext);
  177. }
  178. else {
  179. // just stick the extension on the end...
  180. lsz = LpvAllocCb(len + 1 + elen + 1); // fullname + dot + ext + nul
  181. strcpy(lsz, pname);
  182. strcat(lsz, ".");
  183. strcat(lsz, pext);
  184. }
  185. return lsz;
  186. }
  187. VOID
  188. AddExcludeFileList(LSZ pname)
  189. // add the specifed filename to the exclusion list
  190. //
  191. {
  192. EXCLINK FAR *pexc;
  193. pexc = (EXCLINK FAR *)LpvAllocCb(sizeof(EXCLINK));
  194. pexc->pxfname = LszDup(ToAbsPath(pname, c_cwd));
  195. if (pExcludeFileList == NULL)
  196. pexc->xnext = NULL;
  197. else
  198. pexc->xnext = pExcludeFileList;
  199. pExcludeFileList = pexc;
  200. }
  201. BOOL
  202. FValidHeader()
  203. // Read in the header of a .sbr file -- return TRUE if it is valid
  204. //
  205. {
  206. // test if this is a truncated (i.e. already installed) .sbr file
  207. //
  208. if (GetSBRRec() == S_EOF)
  209. return FALSE;
  210. if (r_rectyp != SBR_REC_HEADER)
  211. SBRCorrupt("header not correct record type");
  212. if (r_lang == SBR_L_C)
  213. fCase = TRUE;
  214. if (r_majv != 1 || r_minv != 1)
  215. SBRCorrupt("incompatible .sbr format\n");
  216. #ifdef DEBUG
  217. if (OptD & 1) DecodeSBR();
  218. #endif
  219. return TRUE;
  220. }
  221. #ifdef PROFILE
  222. // profile prototypes and typedefs
  223. #include "casts.h"
  224. #include "profile.h"
  225. #endif
  226. VOID __cdecl
  227. main (argc, argv)
  228. int argc;
  229. char *argv[];
  230. {
  231. int i;
  232. char *parg;
  233. long lArgPosn;
  234. #ifdef PROFILE
  235. PROFINIT(PT_USER|PT_USEKP, (FPC)NULL);
  236. PROFCLEAR(PT_USER);
  237. PROFON(PT_USER);
  238. #endif
  239. // signal(SIGBREAK, sigint);
  240. // signal(SIGINT, sigint);
  241. printf("Microsoft (R) mbrmake Utility ");
  242. printf(VERS(rmj, rmm, rup));
  243. printf(CPYRIGHT);
  244. if (argc == 1) Usage();
  245. getcwd(c_cwd, sizeof(c_cwd));
  246. ToBackSlashes(c_cwd);
  247. parg = ParseArgs(argc, argv);
  248. if (!parg)
  249. Usage();
  250. InitVM();
  251. for (i=0; i < MAXSYMPTRTBLSIZ; i++) // init symbol lists
  252. rgVaSym[i] = vaNil;
  253. lArgPosn = GetArgPosn();
  254. do {
  255. ToBackSlashes(parg);
  256. if (forfile(parg, A_ALL, MarkNewSBR, NULL) == 0)
  257. Error(ERR_OPEN_FAILED, parg);
  258. }
  259. while (parg = NextArg());
  260. if (!OptN && FOpenBSC(OutputFileName)) {
  261. InstallBSC();
  262. CloseBSC();
  263. }
  264. else
  265. NumberSBR();
  266. SetArgPosn(lArgPosn);
  267. parg = NextArg();
  268. do {
  269. if (forfile(parg, A_ALL, ProcessSBR, NULL) == 0)
  270. Error(ERR_OPEN_FAILED, parg);
  271. }
  272. while (parg = NextArg());
  273. // this sort must happen before all the other calls below as they
  274. // use the sorted version of the list and not the raw symbols
  275. SortAtoms(); // create a sorted version of the atoms
  276. #ifdef DEBUG
  277. if (OptD & 128) DebugDump();
  278. #endif
  279. CleanUp (); // General cleaning
  280. #ifdef DEBUG
  281. if (OptD & 16) DebugDump();
  282. #endif
  283. WriteBSC (OutputFileName); // write .bsc Source Data Base
  284. #ifdef PROFILE
  285. PROFOFF(PT_USER);
  286. PROFDUMP(PT_USER, (FPC)"mbrmake.pro");
  287. PROFFREE(PT_USER);
  288. #endif
  289. if (!OptN) {
  290. // truncate the .sbr files now
  291. SetArgPosn(lArgPosn);
  292. parg = NextArg();
  293. do {
  294. if (forfile(parg, A_ALL, TruncateSBR, NULL) == 0)
  295. Error(ERR_OPEN_FAILED, parg);
  296. }
  297. while (parg = NextArg());
  298. // touch the .bsc file so it has a date later than all the .sbrs
  299. {
  300. FILE *fh;
  301. int buf = 0;
  302. if (!(fh = fopen(OutputFileName, "ab"))) {
  303. Error(ERR_OPEN_FAILED, OutputFileName);
  304. }
  305. if (fwrite(&buf, 1, 1, fh)==0) {
  306. Error(ERR_WRITE_FAILED, OutputFileName);
  307. }
  308. fclose(fh);
  309. }
  310. }
  311. CloseVM();
  312. exit (0);
  313. }
  314. static VOID
  315. ProcessSBR(char *lszName)
  316. // process one .sbr file with the given name
  317. //
  318. {
  319. lszFName = LszDup(lszName);
  320. if ((fhCur = open(lszFName, O_BINARY|O_RDONLY)) == -1) {
  321. Error(ERR_OPEN_FAILED, lszFName);
  322. }
  323. isbrCur = gSBR(VaSbrFrName(lszFName)).isbr;
  324. if (OptV)
  325. printf("Processing: %s ..\n", lszFName);
  326. if (!FValidHeader()) {
  327. FreeLpv (lszFName);
  328. close(fhCur);
  329. return;
  330. }
  331. // Add .SBR data to lists
  332. InstallSBR ();
  333. FreeOrdList (); // free ordinal aliases
  334. close(fhCur);
  335. FreeLpv (lszFName);
  336. }
  337. static VOID
  338. TruncateSBR(char *lszName)
  339. // once the .sbr file is used -- truncate it
  340. //
  341. {
  342. int fh;
  343. if (unlink(lszName) == -1) {
  344. Error(ERR_OPEN_FAILED, lszFName);
  345. }
  346. if ((fh = open(lszName, O_CREAT|O_BINARY, S_IREAD|S_IWRITE)) == -1) {
  347. Error(ERR_OPEN_FAILED, lszFName);
  348. }
  349. close(fh);
  350. }
  351. VOID
  352. Usage()
  353. {
  354. #ifdef DEBUG
  355. printf("usage: mbrmake [-Emu] [-Ei ...] [-vd] [-help] [-o <.BSC>] [@<file>] <.sbr>...\n\n");
  356. #else
  357. printf("usage: mbrmake [-Emu] [-Ei ...] [-v] [-help] [-o <.BSC>] [@<file>] <.sbr>...\n\n");
  358. #endif
  359. printf(" @<file> Get arguments from specified file\n");
  360. printf(" /E... Exclude:\n");
  361. printf(" s system files\n");
  362. printf(" i <file> named include file <file>\n");
  363. printf(" i ( <files> ) named include file list <files>\n");
  364. printf(" m macro expanded symbols\n");
  365. printf(" /I... Include:\n");
  366. printf(" u unreferenced symbols\n");
  367. printf(" /o <file> output source database name\n");
  368. printf(" /n no incremental (full builds, .sbr's preserved)\n");
  369. printf(" /v verbose output\n");
  370. printf(" /help Quick Help\n");
  371. #ifdef DEBUG
  372. printf(" /d show debugging information\n");
  373. printf(" 1 sbrdump .sbr files as they come in\n");
  374. printf(" 2 show every duplicate MbrAddAtom\n");
  375. printf(" 4 emit warning on forward referenced ordinal\n");
  376. printf(" 8 show prop data as new items are added\n");
  377. printf(" 16 bscdump database after cleanup\n");
  378. printf(" 32 emit information about what cleanup is doing\n");
  379. printf(" 64 emit list of sorted modules after sorting\n");
  380. printf(" 128 bscdump database before cleanup\n");
  381. printf(" 256 give info about duplicate/excluded modules\n");
  382. #endif
  383. exit(1);
  384. }
  385. FILE *fileResp;
  386. int cargs;
  387. char ** vargs;
  388. int iarg = 1;
  389. long lFilePosnLast;
  390. LONG
  391. GetArgPosn()
  392. // save the current position on the command line
  393. //
  394. {
  395. if (fileResp)
  396. return lFilePosnLast;
  397. else
  398. return (LONG)iarg - 1;
  399. }
  400. VOID
  401. SetArgPosn(LONG lArgPosn)
  402. // restore the command line parsing position
  403. //
  404. {
  405. if (fileResp) {
  406. fseek(fileResp, lArgPosn, SEEK_SET);
  407. iarg = 0;
  408. }
  409. else
  410. iarg = (int)lArgPosn;
  411. }
  412. char *
  413. NextArg()
  414. // get the next argument from the response file or the command line
  415. //
  416. {
  417. static char buf[PATH_BUF];
  418. char *pch;
  419. int c;
  420. BOOL fQuote = FALSE;
  421. if (iarg >= cargs)
  422. return NULL;
  423. if (fileResp) {
  424. pch = buf;
  425. lFilePosnLast = ftell(fileResp);
  426. for (;;) {
  427. c = getc(fileResp);
  428. switch (c) {
  429. case '"':
  430. if (fQuote) {
  431. *pch = '\0';
  432. return buf;
  433. }
  434. else {
  435. fQuote = TRUE;
  436. continue;
  437. }
  438. case EOF:
  439. iarg = cargs;
  440. if (pch == buf)
  441. return NULL;
  442. *pch = '\0';
  443. return buf;
  444. case ' ':
  445. case '\t':
  446. case '\r':
  447. case '\f':
  448. case '\n':
  449. if (fQuote)
  450. goto quoted;
  451. if (pch == buf)
  452. continue;
  453. *pch = '\0';
  454. return buf;
  455. default:
  456. quoted:
  457. if (pch < buf + sizeof(buf) - 1)
  458. *pch++ = (char)c;
  459. break;
  460. }
  461. }
  462. }
  463. else
  464. return vargs[iarg++];
  465. }
  466. char *
  467. ParseArgs(int argc, char **argv)
  468. // parse the command line or response file
  469. //
  470. {
  471. char *respName;
  472. char *pchWord;
  473. int len;
  474. cargs = argc;
  475. vargs = argv;
  476. for (;;) {
  477. pchWord = NextArg();
  478. if (pchWord == NULL)
  479. return pchWord;
  480. if (pchWord[0] == '@') {
  481. if (fileResp)
  482. Error(ERR_BAD_RESPONSE, "");
  483. else if (pchWord[1])
  484. respName = pchWord+1;
  485. else if (!(respName = NextArg()))
  486. Error(ERR_BAD_RESPONSE, "");
  487. fileResp = fopen(respName, "r");
  488. if (!fileResp)
  489. Error(ERR_OPEN_FAILED, respName);
  490. cargs++;
  491. continue;
  492. }
  493. if (pchWord[0] != '-' && pchWord[0] != '/')
  494. return pchWord;
  495. switch (pchWord[1]) {
  496. case 'n':
  497. OptN = TRUE;
  498. break;
  499. case 'o':
  500. if (pchWord[2])
  501. pchWord += 2;
  502. else if (!(pchWord = NextArg()))
  503. Usage();
  504. OutputFileName = LszDupNewExt (pchWord, "bsc");
  505. break;
  506. #ifdef DEBUG
  507. case 'd':
  508. OptD = 1;
  509. if (pchWord[2]) OptD = atoi(pchWord+2);
  510. break;
  511. #endif
  512. case 'E':
  513. switch (pchWord[2]) {
  514. case 0:
  515. Error (ERR_MISSING_OPTION, pchWord);
  516. break;
  517. case 'm':
  518. OptEm = TRUE;
  519. break;
  520. case 's':
  521. OptEs = TRUE;
  522. break;
  523. default:
  524. Error2 (ERR_UNKNOWN_OPTION, pchWord[2], pchWord);
  525. break;
  526. case 'i':
  527. if (pchWord[3])
  528. pchWord += 3;
  529. else
  530. pchWord = NextArg();
  531. if (!pchWord)
  532. Error (ERR_MISSING_OPTION, "-Ei");
  533. if (pchWord[0] != '(') {
  534. AddExcludeFileList(pchWord);
  535. break;
  536. }
  537. if (pchWord[1])
  538. pchWord++;
  539. else
  540. pchWord = NextArg();
  541. for ( ;pchWord != NULL; pchWord = NextArg()) {
  542. len = strlen(pchWord);
  543. if (pchWord[len-1] != ')') {
  544. AddExcludeFileList(pchWord);
  545. }
  546. else if (len > 1) {
  547. pchWord[len-1] = 0;
  548. AddExcludeFileList(pchWord);
  549. break;
  550. }
  551. else
  552. break;
  553. }
  554. if (pchWord == NULL)
  555. Error (ERR_MISSING_OPTION, "-Ei (...");
  556. }
  557. break;
  558. case 'I':
  559. switch (pchWord[2]) {
  560. case 'u':
  561. OptIu = TRUE;
  562. break;
  563. default:
  564. Error2 (ERR_UNKNOWN_OPTION, pchWord[2], pchWord);
  565. break;
  566. }
  567. break;
  568. case 'H':
  569. case 'h':
  570. if ((strcmpi (pchWord+1, "help")) == 0) {
  571. if (spawnlp (P_WAIT, "qh", "-u", "mbrmake.exe", NULL))
  572. Usage();
  573. exit (0);
  574. }
  575. break;
  576. case 'v':
  577. OptV = TRUE;
  578. break;
  579. default:
  580. Warning (WARN_OPTION_IGNORED, pchWord);
  581. break;
  582. }
  583. }
  584. }
  585. static VOID
  586. MarkNewSBR(char *lszName)
  587. // mark the specified SBR file as requiring update
  588. //
  589. {
  590. int fh;
  591. char ch;
  592. if (!OutputFileName)
  593. OutputFileName = LszDupNewExt (lszName, "bsc");
  594. if ((fh = open(lszName, O_BINARY|O_RDONLY)) == -1) {
  595. Error(ERR_OPEN_FAILED, lszFName);
  596. }
  597. // if the file has non zero length then it is being updated -- else
  598. // it is just a stub that will not affect the database this time around
  599. //
  600. if (read(fh, &ch, 1) != 1)
  601. VaSbrAdd(SBR_NEW, lszName); // to remain in .bsc
  602. else
  603. VaSbrAdd(SBR_NEW|SBR_UPDATE, lszName); // to be re-installed in .bsc
  604. close (fh);
  605. }