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.

921 lines
22 KiB

  1. /* dos prompting-style user interface
  2. **
  3. ** currently supports interfaces for:
  4. ** masm, cref
  5. **
  6. ** written by:
  7. ** randy nevin, microsoft, 5/15/85
  8. **
  9. ** 10/90 - Quick conversion to 32 bit by Jeff Spencer
  10. **
  11. ** (c)copyright microsoft corp 1985
  12. */
  13. #include <stdio.h>
  14. #include <ctype.h>
  15. #include <string.h>
  16. #include <malloc.h>
  17. #include <stdlib.h>
  18. void terminate( unsigned short message, char *arg1, char *arg2, char *arg3 );
  19. #if defined OS2_2 || defined OS2_NT /* OS2 2.0 or NT? */
  20. /* Use common MSDOS code also */
  21. #define MSDOS
  22. #define FLATMODEL
  23. #define FAR
  24. #define PASCAL
  25. #else
  26. #define FAR far
  27. #define PASCAL pascal
  28. #endif
  29. #ifdef MSDOS
  30. #include <dos.h>
  31. #endif
  32. #ifdef MASM
  33. #include "asmmsg.h"
  34. #else
  35. #include "crefmsg.h"
  36. #endif
  37. #define GLOBAL /* C functions and external vars global by default */
  38. #define LOCAL static
  39. #define EXTERNAL extern
  40. #define MASTER 0 /* file name must be present, and is inherited */
  41. #define INHERIT 1 /* if no file name, inherit from Master */
  42. #define NUL 2 /* file name is NUL.ext if not given */
  43. #define SLASHORDASH 0
  44. #define SLASHONLY 1
  45. #define DASHONLY 2
  46. #define TOLOWER(c) (c | 0x20) /* works only for alpha inputs */
  47. #ifdef MSDOS
  48. #define SEPARATOR '\\'
  49. #define ALTSEPARATOR '/'
  50. #if !defined CPDOS && !defined OS2_2 && !defined OS2_NT
  51. #define ARGMAX 128 /* maximum length of all arguments */
  52. #else
  53. #define ARGMAX 512 /* maximum length of all arguments */
  54. #endif
  55. LOCAL char Nul[] = "NUL";
  56. // extern char *getenv();
  57. #ifdef MASM
  58. LOCAL unsigned char switchar = SLASHORDASH;
  59. EXTERNAL short errorcode;
  60. #else
  61. LOCAL unsigned char switchar = SLASHONLY;
  62. #endif
  63. #define ERRFILE stdout
  64. #else
  65. #define SEPARATOR '/'
  66. #define ARGMAX 5120 /* maximum length of all arguments */
  67. LOCAL char Nul[] = "nul";
  68. LOCAL unsigned char switchar = DASHONLY;
  69. #define ERRFILE stderr
  70. #endif
  71. #if defined MSDOS && !defined FLATMODEL
  72. extern char near * pascal __NMSG_TEXT();
  73. extern char FAR * pascal __FMSG_TEXT();
  74. #endif
  75. #if defined MSDOS && defined FLATMODEL
  76. /* For FLATMODEL map message functions to the replacements */
  77. #define __NMSG_TEXT NMsgText
  78. #define __FMSG_TEXT FMsgText
  79. extern char * NMsgText();
  80. extern char * FMsgText();
  81. #endif
  82. #ifdef MASM
  83. #define FILES 4 /* number to prompt for */
  84. #define EX_HEAP 8 /* exit code if heap fails */
  85. #define EX_DSYM 10 /* error defining symbol from command line */
  86. #define PX87 1
  87. #define CVLINE 1
  88. #define CVSYMBOLS 2
  89. #define TERMINATE(message, exitCode)\
  90. terminate((exitCode << 12) | message, 0, 0, 0)
  91. #define TERMINATE1(message, exitCode, a1)\
  92. terminate((exitCode << 12) | message, a1, 0, 0)
  93. #ifdef MSDOS
  94. LOCAL char *Prompt[FILES] = {
  95. "Source filename [",
  96. "Object filename [",
  97. "Source listing [",
  98. "Cross-reference ["
  99. };
  100. #endif
  101. LOCAL char *Ext[FILES] = { /* default extensions */
  102. #ifdef MSDOS
  103. ".ASM",
  104. ".OBJ",
  105. ".LST",
  106. ".CRF"
  107. #else
  108. ".asm",
  109. ".obj",
  110. ".lst",
  111. ".crf"
  112. #endif
  113. };
  114. LOCAL unsigned char Default[FILES] = { /* default root file name */
  115. MASTER,
  116. INHERIT,
  117. NUL,
  118. NUL
  119. };
  120. #endif
  121. #ifdef CREF
  122. #define FILES 2 /* number to prompt for */
  123. #define EX_HEAP 1 /* exit code if heap fails */
  124. #ifdef MSDOS
  125. LOCAL char *Prompt[FILES] = {
  126. "Cross-reference [",
  127. "Listing ["
  128. };
  129. #endif
  130. LOCAL char *Ext[FILES] = { /* default extensions */
  131. #ifdef MSDOS
  132. ".CRF",
  133. ".REF"
  134. #else
  135. ".crf",
  136. ".ref"
  137. #endif
  138. };
  139. LOCAL unsigned char Default[FILES] = { /* default root file name */
  140. MASTER,
  141. INHERIT
  142. };
  143. #endif
  144. GLOBAL char *file[FILES]; /* results show up here; caller knows how many */
  145. LOCAL char *Buffer;
  146. LOCAL char *Master = NULL;
  147. LOCAL unsigned char Nfile = 0; /* file[Nfile] is the next one to set */
  148. LOCAL unsigned char FirstLine = 1; /* defaults are different for first line */
  149. extern unsigned short warnlevel; /* warning level */
  150. extern unsigned short codeview; /* codeview obj level */
  151. extern char loption; /* listing options */
  152. extern char crefopt; /* cross reference options */
  153. #ifdef MSDOS
  154. #if defined OS2_2 || defined OS2_NT
  155. /* OS2 2.0 command line variables will go here */
  156. #else
  157. #if defined CPDOS
  158. /* OS2 1.X variables */
  159. EXTERNAL unsigned _aenvseg;
  160. EXTERNAL unsigned _acmdln;
  161. #else
  162. /* DOS variables */
  163. EXTERNAL unsigned _psp; /* segment addr of program segment prefix */
  164. #endif
  165. #endif
  166. #endif
  167. #ifdef MASM
  168. LOCAL unsigned char lflag = 0;
  169. LOCAL unsigned char cflag = 0;
  170. EXTERNAL char terse;
  171. EXTERNAL unsigned short errornum;
  172. EXTERNAL char lbuf[256 + 512 + 1];
  173. void PASCAL error_line (struct _iobuf *, unsigned char *, short);
  174. #else
  175. char lbuf[512];
  176. #endif
  177. #ifndef MSDOS
  178. EXTERNAL char *gets();
  179. #endif
  180. //EXTERNAL char *strcat(), *strcpy(), *_strdup(), *strchr(), *strrchr();
  181. LOCAL int DoArgs(); /* defined below */
  182. LOCAL int DoName(); /* defined below */
  183. LOCAL int DoNull(); /* defined below */
  184. LOCAL char *DoSwitch(); /* defined below */
  185. LOCAL HeapError(); /* defined below */
  186. #ifdef MSDOS
  187. LOCAL DoPrompt(); /* defined below */
  188. LOCAL TryAgain(); /* defined below */
  189. #endif
  190. GLOBAL void
  191. UserInterface (
  192. /* get file names & switches from args and subsequent prompts */
  193. int argc,
  194. char **argv,
  195. char *banner
  196. ){
  197. register char *p;
  198. register unsigned length;
  199. #if defined MSDOS && !defined OS2_2 && !defined OS2_NT
  200. char FAR *q;
  201. #else
  202. unsigned count;
  203. #endif
  204. Buffer = lbuf;
  205. #ifdef MASM
  206. #ifdef MSDOS
  207. if ((p = getenv("MASM"))) { /* do initialization vars first */
  208. strcpy( Buffer, p ); /* fetch them into the buffer */
  209. DoArgs(); /* process them */
  210. }
  211. #endif
  212. #endif
  213. p = Buffer;
  214. #if defined MSDOS && !defined OS2_2 && !defined OS2_NT
  215. #if defined CPDOS
  216. /* this is how we get the command line if we're on CPDOS */
  217. FP_SEG( q ) = _aenvseg;
  218. FP_OFF( q ) = _acmdln;
  219. while (*q++) ; /* skip argv[0] */
  220. while (isspace( *q )) /* skip blanks between argv[0] and argv[1] */
  221. q++;
  222. length = sizeof(lbuf) - 1;
  223. while (length-- && (*p++ = *q++)) /* copy command line arguments */
  224. ;
  225. #else
  226. /* this is how we get the command line if we're on MSDOS */
  227. FP_SEG( q ) = _psp;
  228. FP_OFF( q ) = 0x80;
  229. length = *q++ & 0xFF;
  230. while (length--)
  231. *p++ = *q++;
  232. *p = '\0';
  233. #endif
  234. #else
  235. /* this is how we get the command line if we're on XENIX or OS2 2.0 */
  236. argv++;
  237. count = ARGMAX - 1;
  238. while (--argc) { /* concatenate args */
  239. if ((length = strlen( *argv )) > count) /* don't overflow */
  240. length = count;
  241. strncpy( p, *argv++, length );
  242. p += length;
  243. if ((count -= length) && *argv) { /* separator */
  244. *p++ = ' ';
  245. count--;
  246. }
  247. }
  248. #if !defined OS2_2 && !defined OS2_NT
  249. *p++ = ';';
  250. #endif
  251. *p = '\0';
  252. #endif
  253. #ifdef CREF
  254. printf( "%s", banner );
  255. #endif
  256. DoArgs();
  257. #ifdef MASM
  258. if (!terse)
  259. printf( "%s", banner );
  260. #endif
  261. #ifdef MSDOS
  262. FirstLine = 0;
  263. while (Nfile < FILES)
  264. DoPrompt();
  265. #endif
  266. if (Master && Master != Nul)
  267. free( Master );
  268. }
  269. LOCAL int
  270. DoArgs ()
  271. /* process concatenated args looking for file names and switches */
  272. {
  273. register char *p;
  274. register char *q;
  275. char *filename = NULL;
  276. for (p = Buffer; *p; p++)
  277. #ifdef MSDOS
  278. if (*p == '/'
  279. && (switchar == SLASHONLY || switchar == SLASHORDASH)
  280. || *p == '-'
  281. && (switchar == DASHONLY || switchar == SLASHORDASH))
  282. #else
  283. if (*p == '-')
  284. #endif
  285. { /* application dependent switch */
  286. #ifdef MSDOS
  287. if (switchar == SLASHORDASH)
  288. switchar = *p == '/' ? SLASHONLY : DASHONLY;
  289. #endif
  290. p = DoSwitch( p );
  291. } else if (*p == ';') { /* use defaults for everything else */
  292. if (DoName( filename )) { /* possibly NULL */
  293. #ifdef MSDOS
  294. TryAgain();
  295. return( 1 );
  296. #else
  297. #ifdef MASM
  298. printf( __NMSG_TEXT(ER_EXS) );
  299. #else
  300. printf( __NMSG_TEXT(ER_EXC) );
  301. #endif
  302. exit( 1 );
  303. #endif
  304. }
  305. FirstLine = 0; /* ...and away we go! */
  306. while (Nfile < FILES)
  307. if (DoNull()) {
  308. #ifdef MSDOS
  309. TryAgain();
  310. return( 1 );
  311. #else
  312. #ifdef MASM
  313. printf( __NMSG_TEXT(ER_EXS) );
  314. #else
  315. printf( __NMSG_TEXT(ER_EXC) );
  316. #endif
  317. exit( 1 );
  318. #endif
  319. }
  320. return( 0 );
  321. } else if (*p == ',') { /* file name separator */
  322. if (DoName( filename )) { /* possibly NULL */
  323. #ifdef MSDOS
  324. TryAgain();
  325. return( 1 );
  326. #else
  327. #ifdef MASM
  328. printf( __NMSG_TEXT(ER_EXS) );
  329. #else
  330. printf( __NMSG_TEXT(ER_EXC) );
  331. #endif
  332. exit( 1 );
  333. #endif
  334. }
  335. filename = NULL;
  336. } else if (!isspace( *p )) { /* gather filename */
  337. q = p + 1;
  338. while (*q && *q != ';' && *q != ',' && !isspace( *q )) {
  339. #ifdef MSDOS
  340. if (*q == '/')
  341. if (switchar == SLASHONLY)
  342. break;
  343. else if (switchar == SLASHORDASH) {
  344. switchar = SLASHONLY;
  345. break;
  346. }
  347. #endif
  348. q++;
  349. }
  350. if (filename) { /* already have one */
  351. if (DoName( filename )) {
  352. #ifdef MSDOS
  353. TryAgain();
  354. return( 1 );
  355. #else
  356. #ifdef MASM
  357. printf( __NMSG_TEXT(ER_EXS) );
  358. #else
  359. printf( __NMSG_TEXT(ER_EXC) );
  360. #endif
  361. exit( 1 );
  362. #endif
  363. }
  364. }
  365. if (!(filename = malloc( (size_t)(q - p + 1) )))
  366. HeapError();
  367. else { /* remember file name */
  368. strncpy( filename, p, (size_t)(q - p) );
  369. filename[q - p] = '\0';
  370. }
  371. p = q - 1; /* go to end of file name */
  372. }
  373. if (filename && DoName( filename )) {
  374. #ifdef MSDOS
  375. TryAgain();
  376. return( 1 );
  377. #else
  378. #ifdef MASM
  379. printf( __NMSG_TEXT(ER_EXS) );
  380. #else
  381. printf( __NMSG_TEXT(ER_EXC) );
  382. #endif
  383. exit( 1 );
  384. #endif
  385. }
  386. return( 0 );
  387. }
  388. LOCAL int
  389. DoName ( filename )
  390. /* enter filename as next file name, if appropriate (possibly NULL) */
  391. char *filename;
  392. {
  393. register char *p;
  394. register char *q;
  395. int cb;
  396. if (Nfile >= FILES) { /* too many file names */
  397. if (filename) {
  398. fputs(__NMSG_TEXT(ER_EXT), ERRFILE );
  399. free( filename );
  400. }
  401. return( 0 );
  402. }
  403. if (!filename) /* try (MASTER)/INHERIT/NUL */
  404. return( DoNull() );
  405. if (p = strrchr( filename, SEPARATOR ))
  406. p++;
  407. #ifdef MSDOS
  408. else if ((p = strrchr( filename, ':' )) && /* look for drive specifier */
  409. p[1] != 0 )
  410. p++;
  411. #endif
  412. else
  413. p = filename;
  414. #ifdef MSDOS
  415. if (q = strrchr( p, ALTSEPARATOR ))
  416. p = q + 1;
  417. #endif
  418. /* p points to first char of filename past last '\' or ':', if any */
  419. if (!*p) /* last char of filename is '\' or ':'; assume directory */
  420. switch (Default[Nfile]) {
  421. case MASTER:
  422. #ifdef MSDOS
  423. fputs(__NMSG_TEXT(ER_INV),ERRFILE );
  424. #endif
  425. free( filename );
  426. return( 1 );
  427. break;
  428. default:
  429. /* case NUL: */
  430. #ifdef MSDOS
  431. if (!FirstLine) {
  432. if (!(p = malloc( strlen( filename )
  433. + strlen( Nul )
  434. + strlen( Ext[Nfile] ) + 1 )))
  435. HeapError();
  436. strcat( strcat( strcpy( p, filename ), Nul ), Ext[Nfile] );
  437. break;
  438. }
  439. /* else just treat as inherited from Master */
  440. #endif
  441. case INHERIT:
  442. if (!Master)
  443. Master = Nul;
  444. if (!(p = malloc( strlen( filename )
  445. + strlen( Master )
  446. + strlen( Ext[Nfile] ) + 1 )))
  447. HeapError();
  448. strcat( strcat( strcpy( p, filename ), Master ), Ext[Nfile] );
  449. break;
  450. } else { /* some sort of file name is present */
  451. if (Default[Nfile] == MASTER) /* save Master file name */
  452. if (q = strchr( p, '.' )) {
  453. if (!(Master = malloc( (size_t)(q - p + 1) )))
  454. HeapError();
  455. strncpy( Master, p, (size_t)(q - p) );
  456. Master[q - p] = '\0';
  457. } else if (!(Master = _strdup( p )))
  458. HeapError();
  459. if (strchr( p, '.' )) { /* extension present */
  460. if (!(p = _strdup( filename )))
  461. HeapError();
  462. } else { /* supply default extension */
  463. cb = 0;
  464. if (p[1] == ':' && p[2] == 0)
  465. cb = strlen(Master);
  466. if (!(p = malloc( strlen( filename )
  467. + strlen( Ext[Nfile] ) + 1 + cb ) ))
  468. HeapError();
  469. strcat(strcat(strcpy( p,
  470. filename ),
  471. (cb)? Master: ""),
  472. Ext[Nfile] );
  473. }
  474. }
  475. file[Nfile++] = p;
  476. free( filename );
  477. return( 0 );
  478. }
  479. LOCAL int
  480. DoNull ()
  481. /* select the default name (depends on if FirstLine or not) */
  482. {
  483. char *p;
  484. switch (Default[Nfile]) {
  485. case MASTER:
  486. #ifdef MSDOS
  487. fputs(__NMSG_TEXT(ER_INV),ERRFILE );
  488. #endif
  489. return( 1 );
  490. break;
  491. default:
  492. /* case NUL: */
  493. if (!FirstLine
  494. #ifdef MASM
  495. && !(lflag && Nfile == 2)
  496. && !(cflag && Nfile == 3)
  497. #endif
  498. ) {
  499. if (!(p = malloc( strlen( Nul ) + 1
  500. + strlen( Ext[Nfile] ) )))
  501. HeapError();
  502. strcat( strcpy( p, Nul ), Ext[Nfile] );
  503. break;
  504. }
  505. /* else just treat as inherited from Master */
  506. case INHERIT:
  507. if (!Master)
  508. Master = Nul;
  509. if (!(p = malloc( strlen( Master ) + 1
  510. + strlen( Ext[Nfile] ) )))
  511. HeapError();
  512. strcat( strcpy( p, Master ), Ext[Nfile] );
  513. break;
  514. }
  515. file[Nfile++] = p;
  516. return( 0 );
  517. }
  518. #ifdef MASM
  519. #define FALSE 0
  520. #define TRUE 1
  521. #ifdef MSDOS
  522. #define DEF_OBJBUFSIZ 8
  523. #endif
  524. #define CASEU 0
  525. #define CASEL 1
  526. #define CASEX 2
  527. #define INCLUDEMAX 10
  528. #define EX_ARGE 1
  529. #ifdef MSDOS
  530. EXTERNAL unsigned short obufsiz;
  531. #endif
  532. EXTERNAL char segalpha;
  533. EXTERNAL char debug;
  534. EXTERNAL char fltemulate;
  535. EXTERNAL char X87type;
  536. EXTERNAL char inclcnt;
  537. EXTERNAL char *inclpath[];
  538. EXTERNAL char caseflag;
  539. EXTERNAL char dumpsymbols;
  540. EXTERNAL char verbose;
  541. EXTERNAL char origcond;
  542. EXTERNAL char listconsole;
  543. EXTERNAL char checkpure;
  544. int PASCAL definesym();
  545. /* process masm switches */
  546. LOCAL char * DoSwitch ( p )
  547. register char *p;
  548. {
  549. char *q;
  550. char *r;
  551. char c;
  552. int i;
  553. switch (TOLOWER(*++p)) {
  554. case 'a':
  555. segalpha = TRUE;
  556. break;
  557. #ifdef MSDOS
  558. case 'b':
  559. for (p++; isdigit(p[1]); p++);
  560. break;
  561. #endif
  562. case 'c':
  563. cflag = TRUE;
  564. if (isalpha (p[1])) {
  565. if (TOLOWER(*++p) == 's')
  566. crefopt++;
  567. else {
  568. TERMINATE1(ER_UNS, EX_ARGE, (char *)*p );
  569. return 0;
  570. }
  571. }
  572. break;
  573. case 'd':
  574. if (!*++p || isspace( *p ) || *p == ',' || *p == ';') {
  575. debug = TRUE;
  576. p--;
  577. } else {
  578. for (q = p + 1; *q && !isspace( *q )
  579. && *q != '=' && *q != ','
  580. && *q != ';'; q++)
  581. ;
  582. if (*q == '=') {
  583. q++;
  584. while (*q && !isspace( *q )
  585. && *q != ',' && *q != ';')
  586. q++;
  587. }
  588. c = *q;
  589. *q = '\0';
  590. definesym( p );
  591. if (errorcode) {
  592. error_line (ERRFILE, "command line", 0);
  593. if (errornum)
  594. exit (EX_DSYM);
  595. }
  596. *q = c;
  597. p = q - 1;
  598. }
  599. break;
  600. case 'e':
  601. fltemulate = TRUE;
  602. X87type = PX87;
  603. break;
  604. case 'h':
  605. #ifdef FLATMODEL
  606. printf("%s\n", __FMSG_TEXT(ER_HDUSE));
  607. #else
  608. printf("%Fs\n", __FMSG_TEXT(ER_HDUSE));
  609. #endif
  610. for (i = ER_H01; i <= ER_H18; i++)
  611. #ifdef FLATMODEL
  612. printf( "\n/%s", __FMSG_TEXT(i));
  613. #else
  614. printf( "\n/%Fs", __FMSG_TEXT(i));
  615. #endif
  616. exit( 0 ); /* let him start again */
  617. break;
  618. case 'i':
  619. for (q = ++p; *q &&
  620. !isspace( *q ) && *q != ',' && *q != ';' &&
  621. *q != (switchar == DASHONLY? '-': '/'); q++)
  622. ;
  623. if (q == p)
  624. TERMINATE(ER_PAT, EX_ARGE );
  625. if (inclcnt < INCLUDEMAX - 1) {
  626. if (!(r = malloc( (size_t)(q - p + 1) )))
  627. HeapError();
  628. strncpy( r, p, (size_t)(q - p) );
  629. r[q - p] = '\0';
  630. inclpath[inclcnt++] = r;
  631. }
  632. p = q - 1;
  633. break;
  634. case 'l':
  635. lflag = TRUE;
  636. if (isalpha (p[1])) {
  637. if (TOLOWER(*++p) == 'a')
  638. loption++;
  639. else {
  640. TERMINATE1(ER_UNS, EX_ARGE, (char *)*p );
  641. return 0;
  642. }
  643. }
  644. break;
  645. case 'm':
  646. switch (TOLOWER(*++p)) {
  647. case 'l':
  648. caseflag = CASEL;
  649. break;
  650. case 'u':
  651. caseflag = CASEU;
  652. break;
  653. case 'x':
  654. caseflag = CASEX;
  655. break;
  656. default:
  657. TERMINATE1(ER_UNC, EX_ARGE, (char *)*p );
  658. return 0;
  659. }
  660. break;
  661. case 'n':
  662. dumpsymbols = FALSE;
  663. break;
  664. case 'p':
  665. checkpure = TRUE;
  666. break;
  667. case 'r': /* old switch ignored */
  668. break;
  669. case 's':
  670. segalpha = FALSE;
  671. break;
  672. case 't':
  673. terse = TRUE;
  674. verbose = FALSE;
  675. break;
  676. case 'v':
  677. verbose = TRUE;
  678. terse = FALSE;
  679. break;
  680. case 'w':
  681. if (! isdigit(p[1]) ||
  682. (warnlevel = (unsigned short)(atoi(&p[1]) > 2))) {
  683. TERMINATE(ER_WAN, EX_ARGE );
  684. return 0;
  685. }
  686. for (p++; isdigit(p[1]); p++);
  687. break;
  688. case 'x':
  689. origcond = TRUE;
  690. break;
  691. case 'z': /* Zd or Zi apply to codeview */
  692. if (TOLOWER(p[1]) == 'd') {
  693. codeview = CVLINE;
  694. p++;
  695. break;
  696. } else if (TOLOWER(p[1]) == 'i') {
  697. codeview = CVSYMBOLS;
  698. p++;
  699. break;
  700. }
  701. /* else its just a Z */
  702. listconsole = TRUE;
  703. break;
  704. default:
  705. TERMINATE1(ER_UNS, EX_ARGE, (char *)*p );
  706. return 0;
  707. }
  708. return( p );
  709. }
  710. #endif
  711. #ifdef CREF
  712. LOCAL char *
  713. DoSwitch ( /* p */ )
  714. /* process cref switches (presently, none) */
  715. /* char *p; */
  716. {
  717. fprintf( stderr, "cref has no switches\n" );
  718. exit( 1 );
  719. }
  720. #endif
  721. #ifdef MSDOS
  722. LOCAL
  723. DoPrompt ()
  724. /* prompt user for a file name (any number of optional switches) */
  725. {
  726. unsigned char oldNfile;
  727. fputs(Prompt[Nfile], stderr );
  728. switch (Default[Nfile]) {
  729. case MASTER:
  730. break;
  731. case INHERIT:
  732. fputs(Master, stderr );
  733. break;
  734. default:
  735. /* case NUL: */
  736. fputs(Nul, stderr );
  737. break;
  738. }
  739. fprintf(stderr, "%s]: ", Ext[Nfile] );
  740. if (!gets( Buffer )) {
  741. fputs(__NMSG_TEXT(ER_SIN),ERRFILE );
  742. #ifdef MASM
  743. exit( EX_ARGE );
  744. #else
  745. exit( 1 );
  746. #endif
  747. }
  748. oldNfile = Nfile;
  749. if (!DoArgs() && oldNfile == Nfile && DoNull())
  750. TryAgain();
  751. return (0);
  752. }
  753. #endif
  754. LOCAL
  755. HeapError ()
  756. /* malloc() has failed; exit program */
  757. {
  758. #ifdef CREF
  759. fprintf(ERRFILE,__NMSG_TEXT(ER_HEP));
  760. exit(EX_HEAP);
  761. #else
  762. TERMINATE(ER_HEP, EX_HEAP);
  763. #endif
  764. return (0);
  765. }
  766. #ifdef MSDOS
  767. LOCAL
  768. TryAgain ()
  769. /* user caused fatal error; start reprompting from beginning */
  770. {
  771. if (Master && Master != Nul) {
  772. free( Master );
  773. Master = NULL;
  774. }
  775. while (Nfile)
  776. free( file[--Nfile] );
  777. return(0);
  778. }
  779. #endif