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.

1382 lines
43 KiB

  1. /***************************************************************************
  2. * PAN1PTBL.C - ElseWare PANOSE(tm) Font Mapper penalty database.
  3. *
  4. * $keywords: pan1ptbl.c 1.9 15-Apr-94 3:53:54 PM$
  5. *
  6. * This is a stand-alone program that writes a 'C' style header file
  7. * containing the penalty tables for the font mapper. The tables are
  8. * in MEMORY format, e.g., they use Intel or Motorola byte ordering
  9. * depending on the platform upon which the program is compiled.
  10. *
  11. * This program should accompany ELSEPAN.C, the ElseWare PANOSE Mapper
  12. * source code, which assumes the output from this program is in a file
  13. * named PAN1PTBL.H.
  14. *
  15. * The command-line is as follows:
  16. *
  17. * pan1ptbl [-b] [-v] [-l] [-d] <in-filename> <out-filename>
  18. *
  19. * where:
  20. *
  21. * -b means produce a binary file (instead of a 'C' struct)
  22. * -v means get from and put to version control
  23. * -l means precede the struct with the keyword FAR
  24. * -d means dump the database to the screen
  25. * <in-filename> is the name of the text file containing the
  26. * penalty database (PAN1PTBL.TXT)
  27. * <out-filename> is the name of the output file (PAN1PTBL.H)
  28. *
  29. * The '-b' switch causes the MEMORY representation of the struct to be
  30. * dumped to file (in binary form). The normal behavior (no '-b' switch)
  31. * is to produce a text file containing a C-style declaration of the
  32. * struct.
  33. *
  34. * The '-v' switch presumes the user has Sorcerer's Apprentice, and causes
  35. * a 'vout' of pan1ptbl.h followed by a 'vin' of the newly generated file.
  36. * Notice that Sorcerer's Apprentice ignores the transaction if the file
  37. * is not different from the previous revision.
  38. *
  39. * The '-l' switch causes the database to be declared 'FAR,' which in
  40. * DOS and Windows large model programs causes the data structure to be
  41. * placed in its own data segment.
  42. *
  43. * The '-d' switch causes a textual description of the database to be
  44. * dumped to stdout for debugging purposes.
  45. *
  46. * Copyright (C) 1991-93 ElseWare Corporation. All rights reserved.
  47. ***************************************************************************/
  48. #define ELSE_MAPPER_CORE
  49. #define NOELSEPANDATA
  50. #include "elsepan.h"
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #include <string.h>
  54. #include <time.h>
  55. #ifdef MACINTOSH
  56. #include "osutils.h"
  57. #endif /* MACINTOSH */
  58. #ifdef MACINTOSH
  59. # define SZ_DATABASE "DATABASE"
  60. # define SZ_TABLE "TABLE"
  61. # define PT_strupr(p) uprstring((p), FALSE)
  62. BOOL PT_strcmpi(char *s, char *t) {
  63. uprstring(s, FALSE);
  64. return strcmp(s, t);
  65. }
  66. #else /* WINDOWS */
  67. # define SZ_DATABASE TEXT("Database")
  68. # define SZ_TABLE TEXT("Table")
  69. # define PT_strupr(p) _strupr(p)
  70. # define PT_strcmpi(s, t) _strcmpi(s, t)
  71. #endif
  72. static EW_BOOL bReadDB(FILE *fpin, EW_BOOL bBuildIt);
  73. static EW_BOOL bReadPTbl(FILE *fpin, EW_BOOL bBuildIt,
  74. EW_BOOL bExpectSquare, char *pLnBuf, int iBufSize,
  75. EW_PTBL_MEM *pPTbl, EW_BYTE *pDataBuf);
  76. static int iGetCompressKind(EW_BYTE *pDataBuf,
  77. int iRow, int iCol, int iNoFit);
  78. static EW_BOOL bAddUniqueTable(EW_PTBL_MEM *pPTbl, int iSize);
  79. static int iReadData(FILE *fpin, char *pLnBuf, int iBufSize,
  80. EW_BYTE *pDataBuf);
  81. static EW_BOOL bGetLine(char *pBuf, int iLen, FILE *fpin);
  82. static void vShowDB(void);
  83. static EW_BOOL bShowDupTbl(EW_PTBL_MEM *pPTbl);
  84. static EW_BYTE s_buf[8192];
  85. static EW_USHORT s_unOffs;
  86. static int s_iLnPos;
  87. /***************************************************************************
  88. * FUNCTION: main
  89. *
  90. * PURPOSE: Write the file PAN1PTBL.H, which is a 'C'-style .H file
  91. * containing the declaration of the memory copy of the
  92. * penalty database.
  93. *
  94. * RETURNS: The program returns 0 if it succeeds, 1 if there is a failure.
  95. ***************************************************************************/
  96. int main (
  97. int argc,
  98. char *argv[])
  99. {
  100. int i;
  101. int j;
  102. int iRet = 1;
  103. EW_BOOL bDumpBin = FALSE;
  104. EW_BOOL bDoVCS = FALSE;
  105. EW_BOOL bMakeFar = FALSE;
  106. EW_BOOL bShowDB = FALSE;
  107. time_t ltime;
  108. EW_PDICT_MEM *pHead = (EW_PDICT_MEM *)s_buf;
  109. FILE *fpin;
  110. FILE *fpout;
  111. char *p;
  112. char *pszInFileNm;
  113. char *pszOutFileNm;
  114. char szIncNm[64];
  115. char szTime[64];
  116. printf("ElseWare Penalty Table Maker v1.2\n");
  117. /* Display 'usage' message if the minimum number of parameters
  118. * was not recieved.
  119. */
  120. if( argc < 3 ) {
  121. printf("Usage: pan1ptbl [-b] [-v] [-l] [-d] <infile> <outfile>\n");
  122. printf(" -b means dump in binary form (not C-struct)\n");
  123. printf(" -v means get from and put to version control\n");
  124. printf(" -l means precede the struct with the keyword FAR\n");
  125. printf(" -d dump the database to the screen\n");
  126. printf(" <infile> is the text penalty database (PAN1PTBL.TXT)\n");
  127. printf(" <outfile> is the output file (PAN1PTBL.H)\n");
  128. goto backout0;
  129. }
  130. /* Set flags.
  131. */
  132. for( p = argv[i = 1]; i < (argc - 2 ); p = argv[++i]) {
  133. if( p[0] != '-' ) {
  134. printf("Expected command line flag at '%s,' pan1ptbl aborted.\n", p);
  135. goto backout0;
  136. }
  137. switch( p[1] ) {
  138. case 'b':
  139. case 'B':
  140. bDumpBin = TRUE;
  141. break;
  142. case 'v':
  143. case 'V':
  144. bDoVCS = TRUE;
  145. break;
  146. case 'l':
  147. case 'L':
  148. bMakeFar = TRUE;
  149. break;
  150. case 'd':
  151. case 'D':
  152. bShowDB = TRUE;
  153. break;
  154. default:
  155. printf("Unrecognized command line flag '%s' ignored.\n", p);
  156. break;
  157. }
  158. }
  159. /* Make sure the last few params are not flags (should be
  160. * file names).
  161. */
  162. if( *p == '-' ) {
  163. printf("Expected input file name at '%s,' pan1ptbl ignored.\n", p);
  164. goto backout0;
  165. }
  166. PT_strupr(pszInFileNm = p);
  167. p = argv[argc - 1];
  168. if( *p == '-' ) {
  169. printf("Expected output file name at '%s,' pan1ptbl ignored.\n", p);
  170. goto backout0;
  171. }
  172. PT_strupr(pszOutFileNm = p);
  173. /* Extract the file from version control if we're supposed to
  174. * do that (Sorcerer's Apprentice is assumed).
  175. */
  176. if( bDoVCS ) {
  177. #ifdef WINDOWS
  178. char cmd[128];
  179. sprintf(cmd, "vout %s", pszOutFileNm);
  180. if( system(cmd ) != 0) {
  181. printf("Failed to get %s from version control, pan1ptbl aborted.\n",
  182. pszOutFileNm);
  183. goto backout0;
  184. }
  185. #endif /* WINDOWS */
  186. #ifdef MACINTOSH
  187. printf("VCS mode not valid on the Macintosh. Continuing anyway...\n");
  188. #endif /* MACINTOSH */
  189. }
  190. /* Open the input file.
  191. */
  192. if( !(fpin = fopen(pszInFileNm, "rt" ))) {
  193. printf("Could not open input file %s, pan1ptbl aborted.\n",
  194. pszInFileNm);
  195. goto backout0;
  196. }
  197. /* Create the output file.
  198. */
  199. if( bDumpBin ) {
  200. fpout = fopen(pszOutFileNm, "wb");
  201. } else {
  202. fpout = fopen(pszOutFileNm, "wt");
  203. }
  204. if( !fpout ) {
  205. printf("Could not open output file %s, pan1ptbl aborted.\n",
  206. pszOutFileNm);
  207. if( bDoVCS ) {
  208. #ifdef WINDOWS
  209. char cmd[128];
  210. sprintf(cmd, "vadmin u %s", pszOutFileNm);
  211. if( system(cmd ) != 0) {
  212. printf("Failed to unlock %s from version control.\n",
  213. pszOutFileNm);
  214. }
  215. #endif /* WINDOWS */
  216. }
  217. goto backout1;
  218. }
  219. /* Build the database.
  220. */
  221. s_iLnPos = 0;
  222. if( !bReadDB(fpin, FALSE )) {
  223. goto backout2;
  224. }
  225. rewind(fpin);
  226. s_iLnPos = 0;
  227. if( !bReadDB(fpin, TRUE )) {
  228. goto backout2;
  229. }
  230. printf("%s: %u bytes in database.\n", pszOutFileNm, pHead->unSizeDB);
  231. if( bShowDB ) {
  232. vShowDB();
  233. }
  234. /* If we're writing binary, then dump it now and exit.
  235. */
  236. if( bDumpBin ) {
  237. fwrite(s_buf, pHead->unSizeDB, 1, fpout);
  238. goto webedun;
  239. }
  240. /* 'C' header write.
  241. *
  242. * Write the file containing the 'C' structure that defines
  243. * the penalty database.
  244. */
  245. if( time(&ltime )) {
  246. strcpy(szTime, asctime(localtime(&ltime)));
  247. szTime[strlen(szTime) - 1] = '\0';
  248. } else {
  249. szTime[0] = '\0';
  250. }
  251. strcpy(szIncNm, "__");
  252. if( (p = strrchr(pszOutFileNm, '\\' )) ||
  253. ( p = strrchr(pszOutFileNm, ':' ))) {
  254. strcat(szIncNm, &p[1]);
  255. } else {
  256. strcat(szIncNm, pszOutFileNm);
  257. }
  258. if( p = strchr(szIncNm, '.' )) {
  259. *p = '_';
  260. }
  261. strcat(szIncNm, "__");
  262. if( bDoVCS ) {
  263. fprintf(fpout,
  264. "/*\044change:Updated by PAN1PTBL.EXE on %s.\044*/\n", szTime);
  265. }
  266. fprintf(fpout,
  267. "/***************************************************************************\n");
  268. fprintf(fpout,
  269. " * %s - ElseWare PANOSE(tm) default penalty tables.\n", pszOutFileNm);
  270. fprintf(fpout,
  271. " *\n");
  272. if( bDoVCS ) {
  273. fprintf(fpout,
  274. " * $keywords: pan1ptbl.c 1.9 15-Apr-94 3:53:54 PM$\n");
  275. fprintf(fpout,
  276. " *\n");
  277. }
  278. fprintf(fpout,
  279. " * This file was generated by PAN1PTBL.EXE.\n");
  280. fprintf(fpout,
  281. " *\n");
  282. fprintf(fpout,
  283. " * This file contains the penalty tables for the PANOSE 1.0 font\n");
  284. fprintf(fpout,
  285. " * mapper. It was generated from the file %s.\n", pszInFileNm);
  286. fprintf(fpout,
  287. " *\n");
  288. fprintf(fpout,
  289. " * Penalty database structure version %x.%02x.\n",
  290. PANOSE_PENALTY_VERS / 0x100,
  291. PANOSE_PENALTY_VERS % 0x100);
  292. fprintf(fpout,
  293. " *\n");
  294. if( !bDoVCS ) {
  295. fprintf(fpout,
  296. " * File created %s.\n", szTime);
  297. fprintf(fpout,
  298. " *\n");
  299. }
  300. fprintf(fpout,
  301. " * Copyright( C ) 1992-93 ElseWare Corporation. All rights reserved.\n");
  302. fprintf(fpout,
  303. " ***************************************************************************/\n");
  304. fprintf(fpout,
  305. "\n");
  306. fprintf(fpout,
  307. "#ifndef %s\n", szIncNm);
  308. fprintf(fpout,
  309. "#define %s\n", szIncNm);
  310. fprintf(fpout,
  311. "\n");
  312. fprintf(fpout,
  313. "/***************************************************************************\n");
  314. fprintf(fpout,
  315. " * PENALTY DATABASE\n");
  316. fprintf(fpout,
  317. " *\n");
  318. fprintf(fpout,
  319. " * Below is the default penalty database for the PANOSE font\n");
  320. fprintf(fpout,
  321. " * mapper. It is in the MEMORY format.\n");
  322. fprintf(fpout,
  323. " *\n");
  324. fprintf(fpout,
  325. " * Look at PAN1PTBL.C to see how this is created.\n");
  326. fprintf(fpout,
  327. " ***************************************************************************/\n");
  328. if( bMakeFar ) {
  329. fprintf(fpout,
  330. "EW_BYTE FAR s_panDB[] = {");
  331. } else {
  332. fprintf(fpout,
  333. "EW_BYTE s_panDB[] = {");
  334. }
  335. for( i = 1, p = s_buf; i < (int )pHead->unSizeDB; ) {
  336. fprintf(fpout, "\n ");
  337. for( j = 0; (i < (int )pHead->unSizeDB) &&( j < 10 );
  338. ++i, ++j, ++p) {
  339. fprintf(fpout, " 0x%02x,",( EW_BYTE )*p);
  340. }
  341. }
  342. if( j == 10 ) {
  343. fprintf(fpout, "\n ");
  344. }
  345. fprintf(fpout,
  346. " 0x%02x\n};\n",( EW_BYTE )*p);
  347. fprintf(fpout,
  348. "\n");
  349. fprintf(fpout,
  350. "#endif /* ifndef %s */\n", szIncNm);
  351. if( bDoVCS ) {
  352. fprintf(fpout,
  353. "\n");
  354. fprintf(fpout,
  355. "/***************************************************************************\n");
  356. fprintf(fpout,
  357. " * Revision log:\n");
  358. fprintf(fpout,
  359. " ***************************************************************************/\n");
  360. fprintf(fpout,
  361. "/*\n");
  362. fprintf(fpout,
  363. " * \044log\044\n");
  364. fprintf(fpout,
  365. " */\n");
  366. }
  367. webedun:
  368. fclose(fpout);
  369. fpout = NULL;
  370. /* Return the file to version control.
  371. */
  372. if( bDoVCS ) {
  373. #ifdef WINDOWS
  374. char cmd[128];
  375. sprintf(cmd, "vin -c\"File updated by PAN1PTBL.EXE %s\" %s",
  376. szTime, pszOutFileNm);
  377. if( system(cmd ) != 0) {
  378. printf("Failed to put %s into version control.\n", pszOutFileNm);
  379. }
  380. #endif /* WINDOWS */
  381. }
  382. iRet = 0;
  383. goto backout1;
  384. backout2:
  385. fclose(fpout);
  386. backout1:
  387. fclose(fpin);
  388. backout0:
  389. return( iRet );
  390. }
  391. /***************************************************************************
  392. * FUNCTION: bReadDB
  393. *
  394. * PURPOSE: Read the text penalty database. This routine is called twice:
  395. * once to gather statistics, and then a second time to fill in
  396. * everything else.
  397. *
  398. * RETURNS: The function returns TRUE if parses the whole file without
  399. * detecting errors.
  400. ***************************************************************************/
  401. static EW_BOOL bReadDB(
  402. FILE *fpin,
  403. EW_BOOL bBuildIt)
  404. {
  405. int i;
  406. int j;
  407. int w;
  408. int iNumTbl;
  409. EW_BOOL bUseAtoB;
  410. EW_PDICT_MEM *pHead =( EW_PDICT_MEM * )s_buf;
  411. EW_PIND_MEM *pInd = pHead->pind;
  412. EW_BYTE *pWt = NULL;
  413. EW_ATOB_MEM *pAtoB = NULL;
  414. EW_ATOB_ITEM_MEM *pAtoBItem = NULL;
  415. EW_PTBL_MEM *pPTbl = NULL;
  416. char szBuf[256];
  417. char szKey[128];
  418. /* First pass: init header. On the second pass it contains
  419. * the count of dictionaries in the database.
  420. */
  421. if( bBuildIt ) {
  422. s_unOffs = sizeof(EW_PDICT_MEM) +
  423. ( sizeof(EW_PIND_MEM ) *( pHead->unNumDicts - 1 ));
  424. } else {
  425. pHead->unVersion = PANOSE_PENALTY_VERS;
  426. pHead->unByteOrder = PTBL_BYTE_ORDER;
  427. pHead->unNumDicts = 0;
  428. pHead->unSizeDB = 0;
  429. s_unOffs = sizeof(EW_PDICT_MEM);
  430. }
  431. /* Get the first line.
  432. */
  433. if( !bGetLine(szBuf, sizeof(szBuf ), fpin)) {
  434. printf("No data found in the input file, pan1ptbl aborted.\n");
  435. return( FALSE );
  436. }
  437. /* For each database.
  438. *
  439. * Look for [ Database ]
  440. */
  441. while( (sscanf(szBuf, "[ %s ]", szKey ) == 1) &&
  442. ( PT_strcmpi(szKey, "Database" ) == 0)) {
  443. /* Init vars.
  444. */
  445. iNumTbl = 0;
  446. bUseAtoB = FALSE;
  447. pWt = NULL;
  448. pAtoB = NULL;
  449. pAtoBItem = NULL;
  450. pPTbl = NULL;
  451. /* If we're really building then set up the vars
  452. * to recieve the tables.
  453. */
  454. if( bBuildIt ) {
  455. /* The weight array is always exactly 10 bytes long,
  456. * initialized to all zeroes. The first byte contains
  457. * the weight for the family digit, which does not
  458. * have a penalty table associated with it.
  459. */
  460. pWt = &s_buf[s_unOffs];
  461. pInd->unOffsWts = s_unOffs;
  462. memset(pWt, 0, j =( sizeof(EW_BYTE ) * NUM_PAN_DIGITS));
  463. ++pWt;
  464. s_unOffs += j;
  465. /* For the A-to-B remapping array, the offset
  466. * variable in the index contains the count of
  467. * items from the first pass. Use that to set
  468. * up the array.
  469. */
  470. if( pInd->unOffsAtoB > 0 ) {
  471. pAtoB =( EW_ATOB_MEM * )&s_buf[s_unOffs];
  472. pAtoBItem = pAtoB->AtoBItem;
  473. i = pInd->unOffsAtoB;
  474. pInd->unOffsAtoB = s_unOffs;
  475. memset((char *)pAtoB, 0, j =( sizeof(EW_ATOB_MEM ) +
  476. ( sizeof(EW_ATOB_ITEM_MEM ) *( i - 1 ))));
  477. pAtoB->unNumAtoB = i;
  478. s_unOffs += j;
  479. } else {
  480. i = NUM_PAN_DIGITS - 1;
  481. }
  482. /* Set up penalty table pointer.
  483. */
  484. pPTbl =( EW_PTBL_MEM * )&s_buf[s_unOffs];
  485. pInd->unOffsPTbl = s_unOffs;
  486. memset((char *)pPTbl, 0, j =( sizeof(EW_PTBL_MEM ) * i));
  487. s_unOffs += j;
  488. } else {
  489. pInd->jFamilyA = 0;
  490. pInd->jFamilyB = 0;
  491. pInd->jDefAnyPenalty = 0;
  492. pInd->jDefNoFitPenalty = 10;
  493. pInd->jDefMatchPenalty = 0;
  494. pInd->jReserved = 0;
  495. pInd->unOffsWts = 0;
  496. pInd->unOffsAtoB = 0;
  497. pInd->unOffsPTbl = 0;
  498. }
  499. /* Look for row = <PANOSE-family-digit-for-row>
  500. */
  501. if( !bGetLine(szBuf, sizeof(szBuf ), fpin) ||
  502. ( sscanf(szBuf, "row = %d", &i ) != 1)) {
  503. printf("%d: Expected 'row' statement, pan1ptbl aborted.\n",
  504. s_iLnPos);
  505. return( FALSE );
  506. }
  507. if( (i < PANOSE_NOFIT ) ||( i > MAX_PAN1_FAMILY )) {
  508. printf("%d: Row PANOSE digit out of range, pan1ptbl aborted.\n",
  509. s_iLnPos);
  510. return( FALSE );
  511. }
  512. pInd->jFamilyA = i;
  513. /* Look for col = <PANOSE-family-digit-for-column>
  514. */
  515. if( !bGetLine(szBuf, sizeof(szBuf ), fpin) ||
  516. ( sscanf(szBuf, "col = %d", &i ) != 1)) {
  517. printf("%d: Expected 'col' statement, pan1ptbl aborted.\n",
  518. s_iLnPos);
  519. return( FALSE );
  520. }
  521. if( (i < PANOSE_NOFIT ) ||( i > MAX_PAN1_FAMILY )) {
  522. printf("%d: Column PANOSE digit out of range, pan1ptbl aborted.\n",
  523. s_iLnPos);
  524. return( FALSE );
  525. }
  526. pInd->jFamilyB = i;
  527. /* Read in a table heading:
  528. *
  529. * [ Table : <ind-row> : <ind-col> : <default-weight> ]
  530. */
  531. if( !bGetLine(szBuf, sizeof(szBuf ), fpin)) {
  532. printf("%d: Expected penalty table after database header, pan1ptbl aborted.\n",
  533. s_iLnPos);
  534. return( FALSE );
  535. }
  536. /* For each table.
  537. */
  538. while ((sscanf(szBuf, "[ %s : %d : %d : %d ]",
  539. szKey, &i, &j, &w) == 4) &&( PT_strcmpi(szKey, "Table" ) == 0)) {
  540. /* Make sure indices in range.
  541. */
  542. if( (i <= 0 ) ||( j <= 0 ) ||
  543. ( i >= NUM_PAN_DIGITS ) ||( j >= NUM_PAN_DIGITS )) {
  544. printf("%d: Digit index out of range, pan1ptbl aborted.\n",
  545. s_iLnPos);
  546. return( FALSE );
  547. }
  548. /* Test non-zero weight.
  549. */
  550. if( !w && !bBuildIt ) {
  551. printf("%d: Warning: Weight value of zero.\n", s_iLnPos);
  552. }
  553. /* Detect need for A-to-B remapping array. This happens
  554. * when the row-ind != col-ind or when the inds do not
  555. * count from 1 to 9.
  556. */
  557. if( (i != j ) ||( i != (iNumTbl + 1 ))) {
  558. bUseAtoB = TRUE;
  559. }
  560. /* Attempt to read the table.
  561. *
  562. * This routine bumps s_unOffs.
  563. */
  564. if (!bReadPTbl(fpin, bBuildIt,
  565. ( EW_BOOL )((i == j) &&( pInd->jFamilyA == pInd->jFamilyB )),
  566. szBuf, sizeof(szBuf), pPTbl, &s_buf[s_unOffs])) {
  567. return( FALSE );
  568. }
  569. /* Pick up default weight value and A-to-B settings.
  570. */
  571. if( bBuildIt ) {
  572. *pWt++ = w;
  573. if( pAtoBItem ) {
  574. pAtoBItem->jAttrA = i;
  575. pAtoBItem->jAttrB = j;
  576. {
  577. EW_ATOB_ITEM_MEM *pAtoBCmp = pAtoB->AtoBItem;
  578. for( ; pAtoBCmp < pAtoBItem; ++pAtoBCmp ) {
  579. if( (pAtoBCmp->jAttrA == pAtoBItem->jAttrA ) &&
  580. ( pAtoBCmp->jAttrB == pAtoBItem->jAttrB )) {
  581. printf("%u: Row & col pair used in a previous table, pan1ptbl aborted.\n",
  582. s_iLnPos);
  583. return( FALSE );
  584. }
  585. }
  586. }
  587. ++pAtoBItem;
  588. }
  589. ++pPTbl;
  590. }
  591. ++iNumTbl;
  592. }
  593. /* End of dictionary handling.
  594. */
  595. if( !iNumTbl ) {
  596. printf("%d: Expected penalty table header, pan1ptbl aborted.\n",
  597. s_iLnPos);
  598. return( FALSE );
  599. }
  600. /* Verify count of tables: there should be exactly 9 without
  601. * an A-to-B remapping array.
  602. */
  603. if( bUseAtoB ) {
  604. if( bBuildIt ) {
  605. if( iNumTbl != (int )pAtoB->unNumAtoB) {
  606. printf("%d: Second-pass: Error in AtoB count.\n", s_iLnPos);
  607. return( FALSE );
  608. }
  609. } else if( iNumTbl > (NUM_PAN_DIGITS - 1 )) {
  610. printf("%d: Cannot have more that %u tables, pan1ptbl aborted.\n",
  611. s_iLnPos,( int )(NUM_PAN_DIGITS - 1));
  612. return( FALSE );
  613. } else {
  614. /* Save the count of tables here for second pass.
  615. */
  616. pInd->unOffsAtoB = iNumTbl;
  617. }
  618. } else if( iNumTbl != (NUM_PAN_DIGITS - 1 )) {
  619. printf("%d: Expected exactly %d tables, pan1ptbl aborted.\n",
  620. s_iLnPos,( int )(NUM_PAN_DIGITS - 1));
  621. return( FALSE );
  622. }
  623. /* Bump count of dictionaries, as we successfully read one.
  624. */
  625. if( !bBuildIt ) {
  626. ++pHead->unNumDicts;
  627. s_unOffs += sizeof(EW_PIND_MEM);
  628. }
  629. ++pInd;
  630. }
  631. if( !pHead->unNumDicts ) {
  632. printf("No penalty dictionaries found, pan1ptbl aborted.\n");
  633. return( FALSE );
  634. }
  635. if( bBuildIt ) {
  636. pHead->unSizeDB = s_unOffs;
  637. }
  638. return( TRUE );
  639. }
  640. /***************************************************************************
  641. * FUNCTION: bReadPTbl
  642. *
  643. * PURPOSE: Read, validate, and compress a table.
  644. *
  645. * RETURNS: The function returns TRUE if it succesfully processes the
  646. * table, FALSE if it does not.
  647. ***************************************************************************/
  648. static EW_BOOL bReadPTbl(
  649. FILE *fpin,
  650. EW_BOOL bBuildIt,
  651. EW_BOOL bExpectSquare,
  652. char *pLnBuf,
  653. int iBufSize,
  654. EW_PTBL_MEM *pPTbl,
  655. EW_BYTE *pDataBuf)
  656. {
  657. int i;
  658. int j;
  659. int k;
  660. int iNoFit;
  661. int iCol;
  662. int iRow;
  663. *pDataBuf = 0;
  664. /* Read in the data table.
  665. *
  666. * First line is the column headings.
  667. */
  668. if( !(iCol = iReadData(fpin, pLnBuf, iBufSize, &pDataBuf[1] ))) {
  669. printf("%d: Expected table data, pan1ptbl aborted.\n", s_iLnPos);
  670. return( FALSE );
  671. }
  672. ++iCol;
  673. /* Read the remaining rows, watching for the same number of columns.
  674. */
  675. for (iRow = 1; (i = iReadData(fpin, pLnBuf, iBufSize,
  676. &pDataBuf[iRow * iCol]));
  677. ++iRow) {
  678. if( i != iCol ) {
  679. printf("%d: Inconsistent number of columns, pan1ptbl aborted.\n",
  680. s_iLnPos);
  681. return( FALSE );
  682. }
  683. }
  684. /* Test for table too small.
  685. */
  686. if( (iRow < 5 ) ||( iCol < 5 )) {
  687. printf("%d: The table is too small, pan1ptbl aborted.\n", s_iLnPos);
  688. return( FALSE );
  689. }
  690. /* Look for a square table.
  691. */
  692. if( bExpectSquare && (iRow != iCol )) {
  693. printf("%d: Expected a square table( #row = #col ), pan1ptbl aborted.\n",
  694. s_iLnPos);
  695. return( FALSE );
  696. }
  697. /* Test 'any' penalties. They should all equal zero.
  698. */
  699. for (i = 1, j = iCol;
  700. ( i < j ) &&( (i == 2 ) ||( pDataBuf[iCol + i] == 0 ));
  701. ++i)
  702. ;
  703. if( i >= j ) {
  704. for (i = 1, j = iRow;
  705. ( i < j ) &&( (i == 2 ) ||( pDataBuf[(iCol * i ) + 1] == 0));
  706. ++i)
  707. ;
  708. }
  709. if( i < j ) {
  710. printf("%d: All 'any' penalties should be zero, pan1ptbl aborted.\n",
  711. s_iLnPos);
  712. return( FALSE );
  713. }
  714. /* Test 'no-fit' penalties. They should all have the same value.
  715. */
  716. iNoFit = pDataBuf[iCol + 2];
  717. for (i = 1, j = iCol;
  718. ( i < j ) &&( pDataBuf[(iCol * 2 ) + i] ==( EW_BYTE )iNoFit);
  719. ++i)
  720. ;
  721. if( i >= j ) {
  722. for (i = 1, j = iRow;
  723. ( i < j ) &&( pDataBuf[(iCol * i ) + 2] ==( EW_BYTE )iNoFit);
  724. ++i)
  725. ;
  726. }
  727. if( i < j ) {
  728. printf("%d: All 'no-fit' penalties should match, pan1ptbl aborted.\n",
  729. s_iLnPos);
  730. return( FALSE );
  731. }
  732. /* If we're just scanning, then we're done collecting info.
  733. */
  734. if( !bBuildIt || !pPTbl ) {
  735. return( TRUE );
  736. }
  737. /* Init table.
  738. */
  739. pPTbl->jRangeLast =( (iRow > iCol ) ? iRow : iCol) - 2;
  740. pPTbl->unOffsTbl = 0;
  741. pPTbl->unTblSize = 0;
  742. k = 0;
  743. /* Determine the compression type, and then copy the table
  744. * based upon the type.
  745. */
  746. switch (pPTbl->jCompress =
  747. ( EW_BYTE )iGetCompressKind(pDataBuf, iRow, iCol, iNoFit)) {
  748. case PAN_COMPRESS_C0:
  749. /* C0 compression: suck in the whole table except
  750. * the any and no-fit values. This table is preceded
  751. * by a header containing the row and column dimensions.
  752. */
  753. {
  754. EW_PTBL_C0_MEM *pPC0 =( EW_PTBL_C0_MEM * )&pDataBuf[k];
  755. pPC0->jARangeLast =( EW_BYTE )iRow - 2;
  756. pPC0->jBRangeLast =( EW_BYTE )iCol - 2;
  757. pPC0->jReserved = 0;
  758. k +=( sizeof(EW_PTBL_C0_MEM ) - sizeof(EW_BYTE));
  759. }
  760. for( i = 3; i < iRow; ++i ) {
  761. for( j = 3; j < iCol; ++j, ++k ) {
  762. pDataBuf[k] = pDataBuf[(i * iCol) + j];
  763. }
  764. }
  765. bAddUniqueTable(pPTbl, k);
  766. break;
  767. case PAN_COMPRESS_C1:
  768. /* C1 compression: perfectly symmetrical table with
  769. * penalties increasing the further they are away
  770. * from the diagonal. No additional data stored.
  771. */
  772. break;
  773. case PAN_COMPRESS_C3:
  774. /* C3 compression: same as C2 compression except the
  775. * first byte is the no-fit penalty.
  776. */
  777. pDataBuf[k++] = iNoFit;
  778. case PAN_COMPRESS_C2:
  779. /* C2 compression: symmetrical about the diagonal,
  780. * suck in the lower left corner.
  781. */
  782. for( i = 4; i < iRow; ++i ) {
  783. for( j = 3; j < i; ++j, ++k ) {
  784. pDataBuf[k] = pDataBuf[(i * iCol) + j];
  785. }
  786. }
  787. bAddUniqueTable(pPTbl, k);
  788. break;
  789. case PAN_COMPRESS_C4:
  790. /* C4 compression: similar to C1, except the start
  791. * and increment values are specified.
  792. */
  793. {
  794. EW_PTBL_C4_MEM *pPC4 =( EW_PTBL_C4_MEM * )&pDataBuf[k];
  795. pPC4->jStart = pDataBuf[(iCol * 4) + 3];
  796. pPC4->jIncrement = pDataBuf[(iCol * 5) + 3] - pPC4->jStart;
  797. k += sizeof(EW_PTBL_C4_MEM);
  798. }
  799. bAddUniqueTable(pPTbl, k);
  800. break;
  801. }
  802. return( TRUE );
  803. }
  804. /***************************************************************************
  805. * FUNCTION: iGetCompressKind
  806. *
  807. * PURPOSE: Examine the data table and determine what kind, if any, of
  808. * data compression can be used.
  809. *
  810. * Notice the tables have an extra row and column for the
  811. * headings. The minimum table size should be 5 x 5, which
  812. * is really a 4 x 4 table (the parse loop catches anything
  813. * smaller and aborts).
  814. *
  815. * RETURNS: The function returns the compression id.
  816. ***************************************************************************/
  817. static int iGetCompressKind(
  818. EW_BYTE *pDataBuf,
  819. int iRow,
  820. int iCol,
  821. int iNoFit)
  822. {
  823. int i;
  824. int j;
  825. /* All compression mechanisms require a square table.
  826. */
  827. if( (iRow != iCol ) ||( iCol < 5 )) {
  828. return( PAN_COMPRESS_C0 );
  829. }
  830. /* Test for symmetry around the diagonal.
  831. */
  832. for( i = 3; i < iCol; ++i ) {
  833. /* The diagonal( exact match value ) must be zero.
  834. */
  835. if( pDataBuf[(iCol * i ) + i] != 0) {
  836. return( PAN_COMPRESS_C0 );
  837. }
  838. /* Test for value at( i,j ) ==( j,i ).
  839. */
  840. for( j = i + 1; (j < iCol ); ++j) {
  841. if( pDataBuf[(iCol * i ) + j] != pDataBuf[(iCol * j) + i]) {
  842. return( PAN_COMPRESS_C0 );
  843. }
  844. }
  845. }
  846. /* The table is symmetrical, now walk it looking for a special
  847. * pattern: it starts at a given value and increments by a given
  848. * value. If we find this, then we just store the start and
  849. * increment values.
  850. *
  851. * The table must be atleast 4 x 4 to try this test. Note if
  852. * it is exactly 4 x 4 and the one value in the table is a 1,
  853. * then C1 is the most compact way to store it (the 'else'
  854. * statement below checks for that). Otherwise C2 or C3 is
  855. * the best.
  856. */
  857. if( (iCol > 5 ) &&( iNoFit == 10 )) {
  858. EW_BOOL bFits = TRUE;
  859. EW_BYTE jStart = pDataBuf[(iCol * 4) + 3];
  860. EW_BYTE jInc = pDataBuf[(iCol * 5) + 3] - jStart;
  861. for( i = 5; (i < iCol ) && bFits; ++i) {
  862. for( j = 3; (j < i ) && bFits; ++j) {
  863. bFits =( pDataBuf[(iCol * i ) + j] ==
  864. ( EW_BYTE )(((EW_BYTE)(i - j - 1) * jInc) + jStart));
  865. }
  866. }
  867. /* C1 compression implies( start, inc ) ==( 1, 1 ),
  868. * C4 stores the start and inc values.
  869. */
  870. if( bFits ) {
  871. return( ((jStart == 1 ) &&( jInc == 1 )) ?
  872. PAN_COMPRESS_C1 : PAN_COMPRESS_C4);
  873. }
  874. } else if( (pDataBuf[(iCol * 4 ) + 3] == 1) &&( iNoFit == 10 )) {
  875. return( PAN_COMPRESS_C1 );
  876. }
  877. /* The table is symmetrical about the diagonal, but there
  878. * is no recognized pattern within it, so return C2 or C3
  879. * compression (C3 is C2 compression with a specifier for
  880. * the 'no-fit' value).
  881. */
  882. return( (iNoFit == 10 ) ? PAN_COMPRESS_C2 : PAN_COMPRESS_C3);
  883. }
  884. /***************************************************************************
  885. * FUNCTION: bAddUniqueTable
  886. *
  887. * PURPOSE: Add a unique table to the accumulated penalty database, if
  888. * a table matching this table's data already exists, then re-use
  889. * that data.
  890. *
  891. * Upon entry to this routine, s_unOffs should point to the
  892. * data that is about to be added. This func walks all the
  893. * tables that have already been added looking for duplicate
  894. * data.
  895. *
  896. * This function should be called when we're building the
  897. * database( second pass ).
  898. *
  899. * RETURNS: The function returns TRUE if a new table was added, or FALSE
  900. * if an existing table was re-used.
  901. ***************************************************************************/
  902. static EW_BOOL bAddUniqueTable(
  903. EW_PTBL_MEM *pPTbl,
  904. int iSize)
  905. {
  906. int i;
  907. int j;
  908. int iNumTbl;
  909. EW_PDICT_MEM *pHead =( EW_PDICT_MEM * )s_buf;
  910. EW_PIND_MEM *pInd = pHead->pind;
  911. EW_PTBL_MEM *pPTblTst;
  912. /* Shortcut for C1 compression: it has no data.
  913. */
  914. if( !iSize ) {
  915. return( FALSE );
  916. }
  917. /* This walk is kind of tricky: we are walking a penalty
  918. * database that is in the process of being created. Some
  919. * fields are valid, some are not.
  920. *
  921. * For each dictionary.
  922. */
  923. for( i = 0; i < (int )pHead->unNumDicts; ++i, ++pInd) {
  924. /* If the ptbl offset is NULL, then we've reached the
  925. * end of the filled-in dictionaries.
  926. */
  927. if( !pInd->unOffsPTbl ) {
  928. break;
  929. }
  930. /* Get the count of tables.
  931. */
  932. if( pInd->unOffsAtoB ) {
  933. iNumTbl =( int )((EW_ATOB_MEM *)&s_buf[pInd->unOffsAtoB])->unNumAtoB;
  934. } else {
  935. iNumTbl = NUM_PAN_DIGITS - 1;
  936. }
  937. /* For each penalty table.
  938. */
  939. for( j = 0, pPTblTst = (EW_PTBL_MEM * )&s_buf[pInd->unOffsPTbl];
  940. j < iNumTbl;
  941. ++j, ++pPTblTst) {
  942. /* The last filled-in table should be the one that
  943. * was passed in.
  944. */
  945. if( (pPTblTst >= pPTbl ) || !pPTblTst->jRangeLast) {
  946. break;
  947. }
  948. /* Look for matching data, and return if it is found.
  949. */
  950. if( (pPTblTst->unOffsTbl > 0 ) &&
  951. ( pPTbl->jCompress == pPTblTst->jCompress ) &&
  952. ( iSize == (int )pPTblTst->unTblSize) &&
  953. (memcmp(&s_buf[s_unOffs],
  954. &s_buf[pPTblTst->unOffsTbl], iSize) == 0)) {
  955. pPTbl->unTblSize = iSize;
  956. pPTbl->unOffsTbl = pPTblTst->unOffsTbl;
  957. return( FALSE );
  958. }
  959. }
  960. }
  961. /* No duplicate was found, keep the structure that is currently
  962. * in the buffer.
  963. */
  964. pPTbl->unOffsTbl = s_unOffs;
  965. s_unOffs += pPTbl->unTblSize = iSize;
  966. return( TRUE );
  967. }
  968. /***************************************************************************
  969. * FUNCTION: iReadData
  970. *
  971. * PURPOSE: Read an array of numbers from file.
  972. *
  973. * RETURNS: The function returns the count of numbers it read from the
  974. * line.
  975. ***************************************************************************/
  976. static int iReadData(
  977. FILE *fpin,
  978. char *pLnBuf,
  979. int iBufSize,
  980. EW_BYTE *pDataBuf)
  981. {
  982. int i;
  983. int j = 0;
  984. /* Get the test line.
  985. */
  986. if( !bGetLine(pLnBuf, iBufSize, fpin )) {
  987. return( 0 );
  988. }
  989. /* For each number.
  990. */
  991. while( TRUE ) {
  992. /* Walk white space.
  993. */
  994. for( ; *pLnBuf && ((*pLnBuf == ' ' ) ||( *pLnBuf == '\t' )); ++pLnBuf)
  995. ;
  996. /* Stop if not at a number.
  997. */
  998. if( !*pLnBuf || (*pLnBuf < '0' ) ||( *pLnBuf > '9' )) {
  999. break;
  1000. }
  1001. /* Read the number.
  1002. */
  1003. for( i = 0; *pLnBuf && (*pLnBuf >= '0' ) &&( *pLnBuf <= '9' );
  1004. ++pLnBuf) {
  1005. i =( i * 10 ) +( *pLnBuf - '0' );
  1006. }
  1007. *pDataBuf++ = i;
  1008. ++j;
  1009. }
  1010. /* Sanity check. At this point the buffer should be empty,
  1011. * the end of the line, or the start of a comment.
  1012. */
  1013. if( *pLnBuf && (*pLnBuf >= ' ' ) &&( *pLnBuf != ';' )) {
  1014. return( 0 );
  1015. }
  1016. return( j );
  1017. }
  1018. /***************************************************************************
  1019. * FUNCTION: bGetLine
  1020. *
  1021. * PURPOSE: Read a line from file. Skip blank and comment lines.
  1022. *
  1023. * RETURNS: The function returns TRUE if it finds a line, FALSE if it
  1024. * does not.
  1025. ***************************************************************************/
  1026. static EW_BOOL bGetLine(
  1027. char *pBuf,
  1028. int iLen,
  1029. FILE *fpin)
  1030. {
  1031. int i;
  1032. char ch;
  1033. char *p;
  1034. #define M_EOL(ch)( ((ch ) == '\r') ||( (ch ) == '\n'))
  1035. do {
  1036. /* First read through end of line characters.
  1037. */
  1038. while( ((ch = fgetc(fpin )) != EOF) && M_EOL(ch)) {
  1039. if( ch == '\n' ) {
  1040. ++s_iLnPos;
  1041. }
  1042. }
  1043. if( ch == EOF ) {
  1044. return( FALSE );
  1045. }
  1046. /* Read the line.
  1047. */
  1048. for (i = 1, p = pBuf, *p++ = ch;
  1049. ( i < iLen ) &&( (*p = fgetc(fpin )) != EOF) && !M_EOL(*p);
  1050. ++i, ++p)
  1051. ;
  1052. *p = '\0';
  1053. /* Bump the line counter.
  1054. */
  1055. ++s_iLnPos;
  1056. /* Skip this line if it begins with a comment character.
  1057. */
  1058. } while( pBuf[0] == ';' );
  1059. return( TRUE );
  1060. }
  1061. /***************************************************************************
  1062. * FUNCTION: vShowDB
  1063. *
  1064. * PURPOSE: Dump the database to stdout.
  1065. *
  1066. * RETURNS: Nothing.
  1067. ***************************************************************************/
  1068. static void vShowDB()
  1069. {
  1070. int i;
  1071. int j;
  1072. int k;
  1073. int m;
  1074. int n;
  1075. int iNumPTbl;
  1076. EW_PDICT_MEM *pHead =( EW_PDICT_MEM * )s_buf;
  1077. EW_PIND_MEM *pInd = pHead->pind;
  1078. EW_BYTE *pWt;
  1079. EW_ATOB_MEM *pAtoB;
  1080. EW_ATOB_ITEM_MEM *pAtoBItem;
  1081. EW_PTBL_MEM *pPTbl;
  1082. EW_BYTE *pData;
  1083. printf("\n\nDATABASE DUMP\n");
  1084. printf("~~~~~~~~~~~~~\n");
  1085. printf("vers = 0x%04x\n", pHead->unVersion);
  1086. printf("num dicts = %u\n", pHead->unNumDicts);
  1087. printf("size db = %u\n", pHead->unSizeDB);
  1088. for( i = 0; i < (int )pHead->unNumDicts; ++i, ++pInd) {
  1089. printf("\n=======================================================\n");
  1090. printf("0x%04x:Index entry:\n",
  1091. ( (unsigned )(char *)pInd -( unsigned )(char *)pHead));
  1092. printf("family row = %u\n",( EW_USHORT )pInd->jFamilyA);
  1093. printf("family col = %u\n",( EW_USHORT )pInd->jFamilyB);
  1094. printf("any = %u\n",( EW_USHORT )pInd->jDefAnyPenalty);
  1095. printf("no-fit = %u\n",( EW_USHORT )pInd->jDefNoFitPenalty);
  1096. printf("match = %u\n",( EW_USHORT )pInd->jDefMatchPenalty);
  1097. printf("reserved = %u\n",( EW_USHORT )pInd->jReserved);
  1098. printf("offs wt = 0x%04x\n", pInd->unOffsWts);
  1099. printf("offs atob = 0x%04x\n", pInd->unOffsAtoB);
  1100. printf("offs ptbl = 0x%04x\n", pInd->unOffsPTbl);
  1101. if( pInd->unOffsWts ) {
  1102. pWt =( EW_BYTE * )&s_buf[pInd->unOffsWts];
  1103. printf("\n0x%04x:weights:", pInd->unOffsWts);
  1104. for( j = 0; j < NUM_PAN_DIGITS; ++j, ++pWt ) {
  1105. printf(" %u",( EW_USHORT )*pWt);
  1106. }
  1107. printf("\n");
  1108. } else {
  1109. printf("\nERROR: NO WEIGHTS\n");
  1110. }
  1111. if( pInd->unOffsAtoB ) {
  1112. pAtoB =( EW_ATOB_MEM * )&s_buf[pInd->unOffsAtoB];
  1113. pAtoBItem = pAtoB->AtoBItem;
  1114. printf("\n0x%04x:AtoB:\n", pInd->unOffsAtoB);
  1115. printf("count = %u\n", pAtoB->unNumAtoB);
  1116. for( j = 0; j < (int )pAtoB->unNumAtoB; ++j, ++pAtoBItem) {
  1117. printf("pair = %u, %u\n",( EW_USHORT )pAtoBItem->jAttrA,
  1118. ( EW_USHORT )pAtoBItem->jAttrB);
  1119. }
  1120. iNumPTbl = pAtoB->unNumAtoB;
  1121. } else {
  1122. iNumPTbl = NUM_PAN_DIGITS - 1;
  1123. }
  1124. if( pInd->unOffsPTbl && (iNumPTbl > 0 )) {
  1125. pPTbl =( EW_PTBL_MEM * )&s_buf[pInd->unOffsPTbl];
  1126. for( j = 0; j < iNumPTbl; ++j, ++pPTbl ) {
  1127. printf("\n0x%04x:penalty table:\n",
  1128. ( (unsigned )(char *)pPTbl -( unsigned )(char *)pHead));
  1129. printf("rng last = %u\n",( EW_USHORT )pPTbl->jRangeLast);
  1130. printf("compress = %u\n",( EW_USHORT )pPTbl->jCompress);
  1131. printf("offs tbl = 0x%04x\n", pPTbl->unOffsTbl);
  1132. printf("tbl size = %u\n", pPTbl->unTblSize);
  1133. if( pPTbl->unOffsTbl && !bShowDupTbl(pPTbl )) {
  1134. k = 0;
  1135. pData =( EW_BYTE * )&s_buf[pPTbl->unOffsTbl];
  1136. switch( pPTbl->jCompress ) {
  1137. case PAN_COMPRESS_C0:
  1138. {
  1139. EW_PTBL_C0_MEM *pPC0 =( EW_PTBL_C0_MEM * )&pData[k];
  1140. pData += k =( sizeof(EW_PTBL_C0_MEM ) - sizeof(EW_BYTE));
  1141. printf("Non-symmetrical table, row = %u, col = %u, reserved = %u\n",
  1142. ( EW_USHORT )pPC0->jARangeLast,
  1143. ( EW_USHORT )pPC0->jBRangeLast,
  1144. ( EW_USHORT )pPC0->jReserved);
  1145. printf(" ");
  1146. for( m = 0; m <= (int )pPC0->jBRangeLast; ++m) {
  1147. printf(" %2u", m);
  1148. }
  1149. printf("\n");
  1150. for( m = 0; m <= (int )pPC0->jARangeLast; ++m) {
  1151. printf("%2u", m);
  1152. if( m > 1 ) {
  1153. printf(" ");
  1154. for( n = 2; (n <= (int )pPC0->jBRangeLast) &&
  1155. ( k < (int )pPTbl->unTblSize);
  1156. ++n, ++k, ++pData) {
  1157. printf(" %2u",( EW_USHORT )*pData);
  1158. }
  1159. }
  1160. printf("\n");
  1161. }
  1162. }
  1163. break;
  1164. case PAN_COMPRESS_C1:
  1165. printf("ERROR: TABLE SHOULD BE EMPTY\n");
  1166. break;
  1167. case PAN_COMPRESS_C3:
  1168. printf("no-fit value = %u\n",( EW_USHORT )*pData);
  1169. ++pData, ++k;
  1170. case PAN_COMPRESS_C2:
  1171. printf(" ");
  1172. for( m = 0; m <= (int )pPTbl->jRangeLast; ++m) {
  1173. printf(" %2u", m);
  1174. }
  1175. printf("\n");
  1176. for( m = 0; m <= (int )pPTbl->jRangeLast; ++m) {
  1177. printf("%2u", m);
  1178. if( m > 2 ) {
  1179. printf(" ");
  1180. for( n = 2; (n < m ) &&( k < (int )pPTbl->unTblSize);
  1181. ++n, ++k, ++pData) {
  1182. printf(" %2u",( EW_USHORT )*pData);
  1183. }
  1184. }
  1185. printf("\n");
  1186. }
  1187. break;
  1188. case PAN_COMPRESS_C4:
  1189. {
  1190. EW_PTBL_C4_MEM *pPC4 =( EW_PTBL_C4_MEM * )&pData[k];
  1191. pData += k = sizeof(EW_PTBL_C4_MEM);
  1192. printf("start = %u, increment = %u\n",
  1193. ( EW_USHORT )pPC4->jStart,
  1194. ( EW_USHORT )pPC4->jIncrement);
  1195. }
  1196. break;
  1197. default:
  1198. printf("ERROR: INVALID COMPRESSION TYPE\n");
  1199. break;
  1200. }
  1201. } else if (!pPTbl->unOffsTbl &&
  1202. ( pPTbl->jCompress != PAN_COMPRESS_C1 )) {
  1203. printf("ERROR: NO DATA\n");
  1204. }
  1205. }
  1206. } else {
  1207. printf("\nERROR: NO PENALTIES\n");
  1208. }
  1209. }
  1210. printf("\n=======================================================\n");
  1211. printf("Raw data dump:\n");
  1212. pData =( EW_BYTE * )s_buf;
  1213. printf(" 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
  1214. for( k = 0; k < (int )pHead->unSizeDB; ) {
  1215. printf("0x%04x:", k);
  1216. for( i = 0; (i < 16 ) &&( k < (int )pHead->unSizeDB);
  1217. ++i, ++k, ++pData) {
  1218. printf(" %02x",( EW_USHORT )*pData);
  1219. }
  1220. printf("\n");
  1221. }
  1222. }
  1223. /***************************************************************************
  1224. * FUNCTION: bShowDupTbl
  1225. *
  1226. * PURPOSE: Search for a duplicate table and don't show it twice, instead
  1227. * indicate it is a duplicate table.
  1228. *
  1229. * RETURNS: The function returns TRUE if this is, indeed, a duplicate
  1230. * table, or FALSE if it is not.
  1231. ***************************************************************************/
  1232. static EW_BOOL bShowDupTbl(
  1233. EW_PTBL_MEM *pPTbl)
  1234. {
  1235. int i;
  1236. int j;
  1237. int iNumTbl;
  1238. EW_PDICT_MEM *pHead =( EW_PDICT_MEM * )s_buf;
  1239. EW_PIND_MEM *pInd = pHead->pind;
  1240. EW_PTBL_MEM *pPTblTst;
  1241. /* Quick test for C1 compression.
  1242. */
  1243. if( !pPTbl->unTblSize || !pPTbl->unOffsTbl ) {
  1244. return( FALSE );
  1245. }
  1246. /* For each dictionary.
  1247. */
  1248. for( i = 0; i < (int )pHead->unNumDicts; ++i, ++pInd) {
  1249. /* Get the count of tables.
  1250. */
  1251. if( pInd->unOffsAtoB ) {
  1252. iNumTbl =( int )((EW_ATOB_MEM *)&s_buf[pInd->unOffsAtoB])->unNumAtoB;
  1253. } else {
  1254. iNumTbl = NUM_PAN_DIGITS - 1;
  1255. }
  1256. /* For each penalty table.
  1257. */
  1258. for( j = 0, pPTblTst = (EW_PTBL_MEM * )&s_buf[pInd->unOffsPTbl];
  1259. j < iNumTbl;
  1260. ++j, ++pPTblTst) {
  1261. /* Walk up to the current table.
  1262. */
  1263. if( pPTblTst >= pPTbl ) {
  1264. break;
  1265. }
  1266. /* Look for matching data, and return if it is found.
  1267. */
  1268. if( (pPTblTst->unOffsTbl > 0 ) &&
  1269. ( pPTbl->jRangeLast == pPTblTst->jRangeLast ) &&
  1270. ( pPTbl->jCompress == pPTblTst->jCompress ) &&
  1271. ( pPTbl->unTblSize == pPTblTst->unTblSize ) &&
  1272. ( pPTbl->unOffsTbl == pPTblTst->unOffsTbl )) {
  1273. printf("The data has already dumped( duplicate table ).\n");
  1274. return( TRUE );
  1275. }
  1276. }
  1277. }
  1278. /* No duplicate found.
  1279. */
  1280. return( FALSE );
  1281. }
  1282. /***************************************************************************
  1283. * Revision log:
  1284. ***************************************************************************/
  1285. /*
  1286. * $lgb$
  1287. * 1.0 31-Jan-93 msd PANOSE 1.0 penalties database, textual version.
  1288. * 1.1 31-Jan-93 msd Modified the way a file is written if we know we're checking it in and out of vcs.
  1289. * 1.2 1-Feb-93 msd Fixed a bug with the vcs handling stuff.
  1290. * 1.3 3-Feb-93 msd Removed ctrl-z at EOF. Ifdef'd in Mac code to get this to build as an MPW tool. Ifdef'd out system calls on the Mac.
  1291. * 1.4 3-Feb-93 msd Added generic line-read routine that can handle both mac- and pc-format test files.
  1292. * 1.5 6-Feb-93 msd Init reserved bye in C0 penalty header.
  1293. * 1.6 18-Feb-93 msd Implemented binary file writing, init penalty table byte-ordering variable, and C4 ptbl compression( new version of ptbl ). Identical tables are not repeated.
  1294. * 1.7 26-Feb-93 msd Don't abort on weight values of zero( just warn ). Also repaired line counter.
  1295. * 1.8 1-Apr-93 msd Added _cdecl keyword to main().
  1296. * 1.9 15-Apr-94 jasons Removed cdecl on main for Mac.
  1297. * $lge$
  1298. */