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.

595 lines
26 KiB

  1. /*
  2. ** MKMSG [-h cfile] [-inc afile] [-asm srcfile [-min|-max]] txtfile
  3. **
  4. ** take message file and produce assembler source file. lines in txtfile
  5. ** can be of 6 types:
  6. ** 1) "<<NMSG>>" -- use near segment
  7. ** 2) "<<FMSG>>" -- use far segment
  8. ** 3) "#anything" -- comment line (ignore)
  9. ** 4) "" -- blank line (ignore)
  10. ** 5) "handle<tab>number<tab>message_text"
  11. ** -- message with number and symbolic handle
  12. ** 6) "<tab>number<tab>message_text"
  13. ** -- message with number but no symbolic handle
  14. **
  15. ** the -h file gets "#define handle number" for those messages with handles.
  16. ** the -inc file gets "handle = number" for the same messages. the -asm file
  17. ** gets standard segment definitions, then the messages are placed either in
  18. ** a near segment (MSG) or a far segment (FAR_MSG) depending on if they follow
  19. ** a <<NMSG>> or a <<FMSG>>. if neither is present, <<NMSG>> is assumed. if
  20. ** -min or -max is given with -asm, the minimum or maximum amount of 0-padding
  21. ** is calculated and placed in the .asm file. any combination of the options
  22. ** may be given, and if none are present then the input is only checked for
  23. ** syntactic validity. maximum and minimum amount of padding depends on the
  24. ** length of the individual messages, and is defined in the cp/dos spec
  25. **
  26. ** If the -32 switch is supplied then the -asm file will be compatible
  27. ** with a 32 bit flat model operating system. In which case <<NMSG>> and
  28. ** <<FMSG>> cause the messages to be placed in two tables. The tables are
  29. ** named MSG_tbl and FAR_MSG_tbl respectively. These are within the 32 bit
  30. ** small model data segment.
  31. **
  32. ** NOTE: This file is no longer used for NT MASM. Instead its output was
  33. ** converted to asmmsg.h and asmmsg2.h and slimed. This was the quick and
  34. ** dirty way to be able to compile masm for other processors. (Jeff Spencer)
  35. ** For more info read the header on asmmsg2.h.
  36. **
  37. ** randy nevin, microsoft, 4/86
  38. ** (c)copyright microsoft corp, 1986
  39. **
  40. ** Modified for 32 bit by Jeff Spencer 10/90
  41. */
  42. #include <stdio.h>
  43. #include <ctype.h>
  44. void SetNear( void );
  45. void SetFar( void );
  46. char usage[] =
  47. "usage: MKMSG [-h cfile] [-inc afile] [-asm srcfile [-min|-max]] [-32] txtfile\n";
  48. char ex[] = "expected escape sequence: %s\n";
  49. char n1[] = "HDR segment byte public \'MSG\'\nHDR ends\n";
  50. char n2[] = "MSG segment byte public \'MSG\'\nMSG ends\n";
  51. char n3[] = "PAD segment byte public \'MSG\'\nPAD ends\n";
  52. char n4[] = "EPAD segment byte common \'MSG\'\nEPAD ends\n";
  53. char n5[] = "DGROUP group HDR,MSG,PAD,EPAD\n\n";
  54. char f1[] = "FAR_HDR segment byte public \'FAR_MSG\'\nFAR_HDR ends\n";
  55. char f2[] = "FAR_MSG segment byte public \'FAR_MSG\'\nFAR_MSG ends\n";
  56. char f3[] = "FAR_PAD segment byte public \'FAR_MSG\'\nFAR_PAD ends\n";
  57. char f4[] = "FAR_EPAD segment byte common \'FAR_MSG\'\nFAR_EPAD ends\n";
  58. char f5[] = "FMGROUP group FAR_HDR,FAR_MSG,FAR_PAD,FAR_EPAD\n\n";
  59. int f32Bit = 0; /* -32?, produce 32bit flat model code */
  60. char didnear = 0;
  61. char didfar = 0;
  62. FILE *fasm = NULL; /* -asm stream */
  63. __cdecl main( argc, argv )
  64. int argc;
  65. char **argv;
  66. {
  67. FILE *f; /* the input file */
  68. char *h = NULL; /* -h file name */
  69. FILE *fh = NULL; /* -h stream */
  70. char *inc = NULL; /* -inc file name */
  71. FILE *finc = NULL; /* -inc stream */
  72. char *asm = NULL; /* -asm file name */
  73. int min = 0; /* -min? */
  74. int max = 0; /* -max? */
  75. int asmstate = 0; /* 0=nothing, 1=doing nmsg, 2=doing fmsg */
  76. int instring; /* db "... */
  77. char buf[256]; /* line buffer */
  78. int ch;
  79. int i;
  80. int number; /* index of message number in line */
  81. int msg; /* index of message text in line */
  82. int npad = 0; /* cumulative amount of near padding */
  83. int fpad = 0; /* cumulative amount of far padding */
  84. int length;
  85. double factor;
  86. double result;
  87. argc--; /* skip argv[0] */
  88. argv++;
  89. while (argc && **argv == '-') /* process options */
  90. if (!strcmp( "-h", *argv )) { /* create .h file */
  91. argc--;
  92. argv++;
  93. if (!argc)
  94. printf( "no -h file given\n" );
  95. else if (h) {
  96. printf( "extra -h file %s ignored\n", *argv );
  97. argc--;
  98. argv++;
  99. }
  100. else { /* remember -h file */
  101. h = *argv;
  102. argc--;
  103. argv++;
  104. }
  105. }
  106. else if (!strcmp( "-inc", *argv )) { /* create .inc file */
  107. argc--;
  108. argv++;
  109. if (!argc)
  110. printf( "no -inc file given\n" );
  111. else if (inc) {
  112. printf( "extra -inc file %s ignored\n", *argv );
  113. argc--;
  114. argv++;
  115. }
  116. else { /* remember -inc file */
  117. inc = *argv;
  118. argc--;
  119. argv++;
  120. }
  121. }
  122. else if (!strcmp( "-asm", *argv )) { /* create .asm file */
  123. argc--;
  124. argv++;
  125. if (!argc)
  126. printf( "no -asm file given\n" );
  127. else if (asm) {
  128. printf( "extra -asm file %s ignored\n", *argv );
  129. argc--;
  130. argv++;
  131. }
  132. else { /* remember -asm file */
  133. asm = *argv;
  134. argc--;
  135. argv++;
  136. }
  137. }
  138. else if (!strcmp( "-min", *argv )) { /* minimum padding */
  139. argc--;
  140. argv++;
  141. if (min)
  142. printf( "redundant -min\n" );
  143. min = 1;
  144. }
  145. else if (!strcmp( "-max", *argv )) { /* maximum padding */
  146. argc--;
  147. argv++;
  148. if (max)
  149. printf( "redundant -max\n" );
  150. max = 1;
  151. }
  152. else if (!strcmp( "-32", *argv )) { /* 32bit code */
  153. argc--;
  154. argv++;
  155. f32Bit = 1;
  156. }
  157. else {
  158. printf( "unknown option %s ignored\n", *argv );
  159. argc--;
  160. argv++;
  161. }
  162. if ((min || max) && !asm) {
  163. printf( "-min/-max ignored; no -asm file\n" );
  164. min = max = 0;
  165. }
  166. if (min && max) {
  167. printf( "-min and -max are mutually exclusive; -min chosen\n" );
  168. max = 0;
  169. }
  170. if (!argc) { /* no arguments */
  171. printf( usage );
  172. exit( -1 );
  173. }
  174. if (argc != 1) /* extra arguments */
  175. printf( "ignoring extra arguments\n" );
  176. if (!(f = fopen( *argv, "rb" ))) {
  177. printf( "can't open txtfile %s for binary reading\n", *argv );
  178. exit( -1 );
  179. }
  180. if (asm && !(fasm = fopen( asm, "w" ))) {
  181. printf( "can't open -asm file %s for writing\n", asm );
  182. exit( -1 );
  183. }
  184. if (h && !(fh = fopen( h, "w" ))) {
  185. printf( "can't open -h file %s for writing\n", h );
  186. exit( -1 );
  187. }
  188. if (inc && !(finc = fopen( inc, "w" ))) {
  189. printf( "can't open -inc file %s for writing\n", inc );
  190. exit( -1 );
  191. }
  192. if( fasm && f32Bit ){
  193. fprintf( fasm, "\t.386\n" );
  194. fprintf( fasm, "\t.model small,c\n" );
  195. fprintf( fasm, "\t.data\n\n" );
  196. }
  197. while ((ch = getc( f )) != EOF) /* process lines */
  198. if (ch == '<') { /* <<NMSG>> or <<FMSG>> */
  199. buf[0] = ch;
  200. i = 1;
  201. while ((ch = getc( f )) != EOF && ch != '\r'
  202. && ch != '\n')
  203. if (i < 255)
  204. buf[i++] = ch;
  205. buf[i] = '\0';
  206. if (!strcmp( "<<NMSG>>", buf ))/*near msgs follow*/
  207. if (asmstate == 0) {
  208. if (fasm) {
  209. SetNear();
  210. asmstate = 1;
  211. }
  212. }
  213. else if (asmstate == 1)
  214. printf( "already in nmsg\n" );
  215. else if (asmstate == 2) {
  216. if (fasm) {
  217. if( !f32Bit ){
  218. fprintf( fasm, "FAR_MSG ends\n\n" );
  219. }
  220. SetNear();
  221. asmstate = 1;
  222. }
  223. }
  224. else {
  225. printf( "internal error\n" );
  226. exit( -1 );
  227. }
  228. else if (!strcmp( "<<FMSG>>", buf ))/*far msgs follow*/
  229. if (asmstate == 0) {
  230. if (fasm) {
  231. SetFar();
  232. asmstate = 2;
  233. }
  234. }
  235. else if (asmstate == 1) {
  236. if (fasm) {
  237. if( !f32Bit ){
  238. fprintf( fasm, "MSG ends\n\n" );
  239. }
  240. SetFar();
  241. asmstate = 2;
  242. }
  243. }
  244. else if (asmstate == 2)
  245. printf( "already in fmsg\n" );
  246. else {
  247. printf( "internal error\n" );
  248. exit( -1 );
  249. }
  250. else
  251. printf( "ignoring bad line: %s\n", buf );
  252. }
  253. else if (ch == '#') /* comment line */
  254. while ((ch = getc( f )) != EOF && ch != '\r'
  255. && ch != '\n')
  256. ;
  257. else if (ch != '\r' && ch != '\n') { /* something to do */
  258. buf[0] = ch;
  259. i = 1;
  260. while ((ch = getc( f )) != EOF && ch != '\r'
  261. && ch != '\n')
  262. if (i < 255)
  263. buf[i++] = ch;
  264. buf[i] = '\0';
  265. if (buf[i = 0] != '\t')
  266. while (buf[i] && buf[i] != '\t')
  267. i++;
  268. if (!buf[i]) {
  269. printf( "expected <TAB>: %s\n", buf );
  270. continue;
  271. }
  272. else
  273. i++;
  274. if (!buf[i] || buf[i] == '\t') {
  275. printf( "expected msgnum: %s\n", buf );
  276. continue;
  277. }
  278. number = i;
  279. while (buf[i] && buf[i] != '\t')
  280. i++;
  281. if (buf[i] != '\t') {
  282. printf( "expected <TAB>: %s\n", buf );
  283. continue;
  284. }
  285. msg = ++i;
  286. if (buf[0] != '\t') { /* possible -h and/or -inc */
  287. if (h) {
  288. fprintf( fh, "#define\t" );
  289. for (i = 0; i < msg-1; i++)
  290. putc( buf[i], fh );
  291. putc( '\n', fh );
  292. }
  293. if (inc) {
  294. for (i = 0; i < number; i++)
  295. putc( buf[i], finc );
  296. fprintf( finc, "=\t" );
  297. while (i < msg-1)
  298. putc( buf[i++], finc );
  299. putc( '\n', finc );
  300. }
  301. }
  302. if (fasm) { /* write asmfile */
  303. if (asmstate == 0) {
  304. SetNear();
  305. asmstate = 1;
  306. }
  307. fprintf( fasm, "\tdw\t" );
  308. for (i = number; i < msg-1; i++)
  309. putc( buf[i], fasm );
  310. fprintf( fasm, "\n\tdb\t" );
  311. instring = 0;
  312. for (i = msg, length = 0; buf[i];
  313. i++, length++)
  314. /* allocate message */
  315. if (buf[i] == '\\')
  316. /* C escape sequence */
  317. switch (buf[++i]) {
  318. case 'r':
  319. case 'n':
  320. case 't':
  321. case 'f':
  322. case 'v':
  323. case 'b':
  324. case '\'':
  325. case '"':
  326. case '\\':
  327. if (instring) {
  328. putc( '"',
  329. fasm );
  330. putc( ',',
  331. fasm );
  332. instring = 0;
  333. }
  334. if (buf[i] == 'r')
  335. fprintf( fasm,
  336. "13" );
  337. else if (buf[i] == 'n')
  338. fprintf( fasm,
  339. "10" );
  340. else if (buf[i] == 't')
  341. fprintf( fasm,
  342. "9" );
  343. else if (buf[i] == 'f')
  344. fprintf( fasm,
  345. "12" );
  346. else if (buf[i] == 'v')
  347. fprintf( fasm,
  348. "11" );
  349. else if (buf[i] == 'b')
  350. fprintf( fasm,
  351. "8" );
  352. else if (buf[i] == '\'')
  353. fprintf( fasm,
  354. "39" );
  355. else if (buf[i] == '"')
  356. fprintf( fasm,
  357. "34" );
  358. else if (buf[i] == '\\')
  359. fprintf( fasm,
  360. "92" );
  361. putc( ',', fasm );
  362. break;
  363. case '\0':
  364. printf( ex, buf );
  365. i--;
  366. break;
  367. default:
  368. if (!instring) {
  369. putc( '"',
  370. fasm );
  371. instring = 1;
  372. }
  373. putc( buf[i], fasm );
  374. break;
  375. }
  376. else if (instring)
  377. /* keep building string */
  378. putc( buf[i], fasm );
  379. else { /* start building string */
  380. putc( '"', fasm );
  381. instring = 1;
  382. putc( buf[i], fasm );
  383. }
  384. if (instring) { /* close string */
  385. putc( '"', fasm );
  386. putc( ',', fasm );
  387. }
  388. putc( '0', fasm );
  389. putc( '\n', fasm );
  390. /* calculate padding */
  391. /* depends on msg length */
  392. if (min || max) {
  393. if (min)
  394. if (length <= 10)
  395. factor = 1.01;
  396. else if (length <= 20)
  397. factor = 0.81;
  398. else if (length <= 30)
  399. factor = 0.61;
  400. else if (length <= 50)
  401. factor = 0.41;
  402. else if (length <= 70)
  403. factor = 0.31;
  404. else
  405. factor = 0.30;
  406. else if (length <= 10)
  407. factor = 2.00;
  408. else if (length <= 20)
  409. factor = 1.00;
  410. else if (length <= 30)
  411. factor = 0.80;
  412. else if (length <= 50)
  413. factor = 0.60;
  414. else if (length <= 70)
  415. factor = 0.40;
  416. else
  417. factor = 0.30;
  418. result = (double)length * factor;
  419. if (asmstate == 1) {
  420. npad += (int)result;
  421. if (result
  422. > (float)((int)result))
  423. npad++;
  424. }
  425. else if (asmstate == 2) {
  426. fpad += (int)result;
  427. if (result
  428. > (float)((int)result))
  429. fpad++;
  430. }
  431. }
  432. }
  433. }
  434. if (fasm) { /* finish up asm file */
  435. if( !f32Bit ){
  436. if (asmstate == 1)
  437. fprintf( fasm, "MSG ends\n\n");
  438. else if (asmstate == 2)
  439. fprintf( fasm, "FAR_MSG ends\n\n");
  440. if (npad) { /* add near padding */
  441. fprintf( fasm, "PAD segment\n\tdb\t%d dup(0)\n",
  442. npad );
  443. fprintf( fasm, "PAD ends\n\n" );
  444. }
  445. if (fpad) { /* add far padding */
  446. fprintf( fasm, "FAR_PAD segment\n\tdb\t%d dup(0)\n",
  447. fpad );
  448. fprintf( fasm, "FAR_PAD ends\n\n" );
  449. }
  450. }
  451. fprintf( fasm, "\tend\n" );
  452. fclose( fasm );
  453. }
  454. if (fh)
  455. fclose( fh );
  456. if (finc)
  457. fclose( finc );
  458. fclose( f );
  459. exit( 0 );
  460. }
  461. void SetNear()
  462. {
  463. if( f32Bit ) {
  464. if( !didnear ){
  465. fprintf( fasm, "MSG_tbl EQU $\n" );
  466. fprintf( fasm, "\tpublic MSG_tbl\n" );
  467. didnear++;
  468. }
  469. else{
  470. /* Rather than modify mkmsg to handle mixed NEAR / FAR */
  471. /* I (Jeff Spencer) chose the quick route of limiting it's capabilities */
  472. /* As this capability wasn't needed for MASM 5.1 */
  473. printf( "error - 32 bit version doesn't support alternating NEAR and FAR messages\n" );
  474. exit( -1 );
  475. }
  476. }
  477. else{
  478. if (!didnear) {
  479. didnear++;
  480. fprintf( fasm, n1 );
  481. fprintf( fasm, n2 );
  482. fprintf( fasm, n3 );
  483. fprintf( fasm, n4 );
  484. fprintf( fasm, n5 );
  485. }
  486. fprintf( fasm,
  487. "MSG segment\n" );
  488. }
  489. }
  490. void SetFar()
  491. {
  492. if( f32Bit ){
  493. if( !didfar ){
  494. fprintf( fasm, "FAR_MSG_tbl EQU $\n" );
  495. fprintf( fasm, "\tpublic FAR_MSG_tbl\n" );
  496. didfar++;
  497. }
  498. else{
  499. /* Rather than modify mkmsg to handle mixed NEAR / FAR */
  500. /* I (Jeff Spencer) chose the quick route of limiting it's capabilities */
  501. /* As this capability wasn't needed for MASM 5.1 */
  502. printf( "error - 32 bit version doesn't support alternating NEAR and FAR messages\n" );
  503. exit( -1 );
  504. }
  505. }
  506. else{
  507. if (!didfar) {
  508. didfar++;
  509. fprintf( fasm, f1 );
  510. fprintf( fasm, f2 );
  511. fprintf( fasm, f3 );
  512. fprintf( fasm, f4 );
  513. fprintf( fasm, f5 );
  514. }
  515. fprintf( fasm,
  516. "FAR_MSG segment\n" );
  517. }
  518. }