home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lynx2.8.1dev.10.tar.gz / lynx2.8.1dev.10.tar / lynx2-8 / src / chrtrans / makeuctb.c < prev    next >
C/C++ Source or Header  |  1998-03-25  |  17KB  |  765 lines

  1. /*
  2.  *  makeuctb.c, derived from conmakehash.c   - kw
  3.  *
  4.  *    Original comments from conmakehash.c:
  5.  *
  6.  *  Create arrays for initializing the kernel folded tables (using a hash
  7.  *  table turned out to be to limiting...)  Unfortunately we can't simply
  8.  *  preinitialize the tables at compile time since kfree() cannot accept
  9.  *  memory not allocated by kmalloc(), and doing our own memory management
  10.  *  just for this seems like massive overkill.
  11.  *
  12.  *  Copyright (C) 1995 H. Peter Anvin
  13.  *
  14.  *  This program is a part of the Linux kernel, and may be freely
  15.  *  copied under the terms of the GNU General Public License (GPL),
  16.  *  version 2, or at your option any later version.
  17.  */
  18.  
  19. #ifdef NOTDEFINED
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <sysexits.h>
  23. #include <string.h>
  24. #include <ctype.h>
  25. #else
  26. #include <HTUtils.h>
  27. #include <tcp.h>
  28. /*
  29.  *  Don't try to use LYexit().
  30.  */
  31. #ifdef exit
  32. #undef exit
  33. #endif /* exit */
  34. #endif /* NODEFINED */
  35.  
  36. #ifndef TOLOWER
  37. #define TOLOWER(c) (isupper((unsigned char)c) ? tolower((unsigned char)c) : (c))
  38. #endif /* !TOLOWER */
  39.  
  40. #include <UCkd.h>
  41. #include <UCDefs.h>
  42.  
  43. #define MAX_FONTLEN 256
  44.  
  45. /*
  46.  *  We don't deal with UCS4 here. - KW
  47.  */
  48. typedef u16 unicode;
  49.  
  50. PRIVATE void usage ARGS1(
  51.     char *,        argv0)
  52. {
  53.     fprintf(stderr, "Usage: \n");
  54.     fprintf(stderr,
  55.         "        %s chartable [charsetmimename] [charsetdisplayname]\n",
  56.         argv0);
  57.     fprintf(stderr,
  58.         "Utility to convert .tbl into .h files for Lynx compilation.\n");
  59.     exit(EX_USAGE);
  60. }
  61.  
  62. /* copied from HTString.c, not everybody has strncasecmp */
  63. PUBLIC int strncasecomp ARGS3(
  64.     CONST char*,    a,
  65.     CONST char *,    b,
  66.     int,        n)
  67. {
  68.     CONST char *p = a;
  69.     CONST char *q = b;
  70.  
  71.     for (p = a, q = b; ; p++, q++) {
  72.         int diff;
  73.     if (p == (a+n))
  74.         return 0;    /*   Match up to n characters */
  75.     if (!(*p && *q))
  76.         return (*p - *q);
  77.     diff = TOLOWER(*p) - TOLOWER(*q);
  78.     if (diff)
  79.         return diff;
  80.     }
  81.     /*NOTREACHED*/
  82. }
  83.  
  84. PRIVATE int getunicode ARGS1(
  85.     char **,    p0)
  86. {
  87.     char *p = *p0;
  88.  
  89.     while (*p == ' ' || *p == '\t')
  90.     p++;
  91.     
  92.     if (*p == '-') {
  93.     return -2;
  94.     } else if (*p != 'U' || p[1] != '+' ||
  95.            !isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) ||
  96.            !isxdigit(p[5]) || isxdigit(p[6])) {
  97.     return -1;
  98.     }
  99.     *p0 = p+6;
  100.     return strtol((p + 2), 0, 16);
  101. }
  102.  
  103. /*
  104.  *  Massive overkill, but who cares?
  105.  */
  106. unicode unitable[MAX_FONTLEN][255];
  107. int unicount[MAX_FONTLEN];
  108.  
  109. struct unimapdesc_str themap_str = {0, NULL};
  110.  
  111. char *tblname;
  112.  
  113. PRIVATE int RawOrEnc = 0;
  114. PRIVATE int Raw_found = 0;        /* whether explicit R directive found */
  115.  
  116. PRIVATE void addpair_str ARGS2(
  117.     char *,        str,
  118.     int,        un)
  119. {
  120.    int i;
  121.  
  122.     if (un <= 0xfffe) {
  123.     if (!themap_str.entry_ct) {
  124.         /*
  125.          *  Initialize the map for replacement strings.
  126.          */
  127.         themap_str.entries =
  128.       (struct unipair_str *) malloc (2000 * sizeof (struct unipair_str));
  129.         if (!themap_str.entries) {
  130.         fprintf(stderr,
  131.             "%s: Out of memory\n", tblname);
  132.         exit(EX_DATAERR);
  133.         }
  134.     } else {
  135.         /*
  136.          *  Check that it isn't a duplicate.
  137.          */
  138.         for (i = 0 ; i < themap_str.entry_ct; i++) {
  139.         if (themap_str.entries[i].unicode == un ) {
  140.             themap_str.entries[i].replace_str = str;
  141.             return;
  142.         }
  143.         }
  144.     }
  145.  
  146.     /*
  147.      *  Add to list.
  148.      */
  149.     if (themap_str.entry_ct > 1999) {
  150.         fprintf(stderr,
  151.         "ERROR: Only 2000 unicode replacement strings permitted!\n");
  152.         exit(EX_DATAERR);
  153.     }
  154.     themap_str.entries[themap_str.entry_ct].unicode = un;
  155.     themap_str.entries[themap_str.entry_ct].replace_str = str;
  156.     themap_str.entry_ct++;
  157.     }
  158.     /* otherwise: ignore */
  159. }
  160.  
  161. PRIVATE void addpair ARGS2(
  162.     int,    fp,
  163.     int,    un)
  164. {
  165.     int i;
  166.  
  167.     if (!Raw_found) {       /* enc not (yet) explicitly given with 'R' */
  168.     if (fp >= 128) {
  169.         if (RawOrEnc != UCT_ENC_8BIT && RawOrEnc <= UCT_ENC_8859) {
  170.         if (fp < 160) {    /* cannot be 8859 */
  171.             RawOrEnc = UCT_ENC_8BIT;
  172.         } else if (fp != 160 && fp != 173) {
  173.             RawOrEnc = UCT_ENC_8859; /* hmmm.. more tests needed? */
  174.         } else if (unicount[fp] == 0 && fp != un) {
  175.             /* first unicode for fp doesn't map to itself */
  176.             RawOrEnc = UCT_ENC_8BIT;
  177.         } else {
  178.             RawOrEnc = UCT_ENC_8859; /* hmmm.. more tests needed? */
  179.         }
  180.         }
  181.     }
  182.     }
  183.     if (un <= 0xfffe) {
  184.     /*
  185.      *  Check that it isn't a duplicate.
  186.      */
  187.     for (i = 0; i < unicount[fp]; i++) {
  188.         if (unitable[fp][i] == un) {
  189.         return;
  190.         }
  191.     }
  192.  
  193.     /*
  194.      *  Add to list.
  195.      */
  196.     if (unicount[fp] > 254) {
  197.         fprintf(stderr, "ERROR: Only 255 unicodes/glyph permitted!\n");
  198.         exit(EX_DATAERR);
  199.     }
  200.     unitable[fp][unicount[fp]] = un;
  201.     unicount[fp]++;
  202.     }
  203.     /* otherwise: ignore */
  204. }
  205.  
  206. char this_MIMEcharset[UC_MAXLEN_MIMECSNAME +1];
  207. char this_LYNXcharset[UC_MAXLEN_LYNXCSNAME +1];
  208. char id_append[UC_MAXLEN_ID_APPEND +1] = "_";
  209. int this_isDefaultMap = -1;
  210. int useDefaultMap = 1;
  211. int lowest_eight = 999;
  212.  
  213. PUBLIC int main ARGS2(
  214.     int,        argc,
  215.     char **,    argv)
  216. {
  217.     FILE *ctbl;
  218.     char buffer[65536];
  219.     int fontlen;
  220.     int i, nuni, nent;
  221.     int fp0, fp1, un0, un1;
  222.     char *p, *p1;
  223.     char *tbuf, ch;
  224.  
  225.     if (argc < 2 || argc > 4) {
  226.     usage(argv[0]);
  227.     }
  228.  
  229.     if (!strcmp(argv[1], "-")) {
  230.     ctbl = stdin;
  231.     tblname = "stdin";
  232.     } else {
  233.     ctbl = fopen(tblname = argv[1], "r");
  234.     if (!ctbl) {
  235.         perror(tblname);
  236.         exit(EX_NOINPUT);
  237.     }
  238.     }
  239.  
  240.     /*
  241.      *  For now we assume the default font is always 256 characters.
  242.      */
  243.     fontlen = 256;
  244.  
  245.     /*
  246.      *  Initialize table.
  247.      */
  248.     for (i = 0; i < fontlen; i++) {
  249.     unicount[i] = 0;
  250.     }
  251.  
  252.     /*
  253.      *  Now we comes to the tricky part.  Parse the input table.
  254.      */
  255.     while (fgets(buffer, sizeof(buffer), ctbl) != NULL) {
  256.     if ((p = strchr(buffer, '\n')) != NULL) {
  257.         *p = '\0';
  258.     } else {
  259.         fprintf(stderr,
  260.             "%s: Warning: line too long or incomplete.\n",
  261.             tblname);
  262.     }
  263.  
  264.     /*
  265.      *  Syntax accepted:
  266.      *    <fontpos>    <unicode> <unicode> ...
  267.      *    <fontpos>    <unicode range> <unicode range> ...
  268.      *    <fontpos>    idem
  269.      *    <range>        idem
  270.      *    <range>        <unicode range>
  271.      *      <unicode>    :<replace>
  272.      *      <unicode range>    :<replace>
  273.      *      <unicode>    "<C replace>"
  274.      *      <unicode range>    "<C replace>"
  275.      *
  276.      *  where <range> ::= <fontpos>-<fontpos>
  277.      *  and <unicode> ::= U+<h><h><h><h>
  278.      *  and <h> ::= <hexadecimal digit>
  279.      *  and <replace> any string not containing '\n' or '\0'
  280.      *  and <C replace> any string with C backslash escapes.
  281.      */
  282.     p = buffer;
  283.     while (*p == ' ' || *p == '\t') {
  284.         p++;
  285.     }
  286.     if (!(*p) || *p == '#') {
  287.         /*
  288.          *  Skip comment or blank line.
  289.          */
  290.         continue;
  291.     }
  292.  
  293.     switch (*p) {
  294.         /*
  295.          *  Raw Unicode?  I.e. needs some special
  296.          *  processing.  One digit code.
  297.          */
  298.         case 'R':
  299.         if (p[1] == 'a' || p[1] == 'A') {
  300.             buffer[sizeof(buffer) - 1] = '\0';
  301.             if (!strncasecomp(p, "RawOrEnc", 8)) {
  302.             p += 8;
  303.             }
  304.         }
  305.         p++;
  306.         while (*p == ' ' || *p == '\t') {
  307.               p++;
  308.         }
  309.         RawOrEnc = strtol(p,0,10);
  310.         Raw_found = 1;
  311.         continue;
  312.  
  313.         /*
  314.          *  Is this the default table?
  315.          */
  316.          case 'D':
  317.         if (p[1] == 'e' || p[1] == 'E') {
  318.             buffer[sizeof(buffer) - 1] = '\0';
  319.             if (!strncasecomp(p, "Default", 7)) {
  320.             p += 7;
  321.             }
  322.         }
  323.         p++;
  324.         while (*p == ' ' || *p == '\t') {
  325.             p++;
  326.         }
  327.         this_isDefaultMap = (*p == '1' || TOLOWER(*p) == 'y');
  328.         continue;
  329.  
  330.         /*
  331.          *  Is this the default table?
  332.          */
  333.          case 'F':
  334.         if (p[1] == 'a' || p[1] == 'A') {
  335.             buffer[sizeof(buffer) - 1] = '\0';
  336.             if (!strncasecomp(p, "FallBack", 8)) {
  337.             p += 8;
  338.             }
  339.         }
  340.         p++;
  341.         while (*p == ' ' || *p == '\t') {
  342.             p++;
  343.         }
  344.         useDefaultMap = (*p == '1' || tolower(*p) == 'y');
  345.         continue;
  346.  
  347.         case 'M':
  348.         if (p[1] == 'i' || p[1] == 'I') {
  349.             buffer[sizeof(buffer) - 1] = '\0';
  350.             if (!strncasecomp(p, "MIMEName", 8)) {
  351.             p += 8;
  352.             }
  353.         }
  354.         p++;
  355.         while (*p == ' ' || *p == '\t') {
  356.             p++;
  357.         }
  358.         sscanf(p,"%40s",this_MIMEcharset);
  359.         continue;
  360.  
  361.         /*
  362.          *  Display charset name for options screen.
  363.          */
  364.         case 'O':
  365.         if (p[1] == 'p' || p[1] == 'P') {
  366.             buffer[sizeof(buffer) - 1] = '\0';
  367.             if (!strncasecomp(p, "OptionName", 10)) {
  368.             p += 10;
  369.             }
  370.         }
  371.         p++;
  372.         while (*p == ' ' || *p == '\t') {
  373.             p++;
  374.         }
  375.         for (i = 0; *p && i < UC_MAXLEN_LYNXCSNAME; p++, i++) {
  376.             this_LYNXcharset[i] = *p;
  377.         }
  378.         this_LYNXcharset[i] = '\0';
  379.         continue;
  380.     }
  381.  
  382.     if (*p == 'U') {
  383.         un0 = getunicode(&p);
  384.         if (un0 < 0) {
  385.         fprintf(stderr, "Bad input line: %s\n", buffer);
  386.         exit(EX_DATAERR);
  387.         fprintf(stderr,
  388.     "%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n",
  389.             tblname, fp0, fp1);
  390.         exit(EX_DATAERR);
  391.         }
  392.         un1 = un0;
  393.         while (*p == ' ' || *p == '\t') {
  394.         p++;
  395.         }
  396.         if (*p == '-') {
  397.         p++;
  398.         while (*p == ' ' || *p == '\t') {
  399.             p++;
  400.         }
  401.         un1 = getunicode(&p);
  402.         if (un1 < 0 || un1 < un0) {
  403.             fprintf(stderr,
  404.                 "%s: Bad Unicode range U+%x-U+%x\n",
  405.                 tblname, un0, un1);
  406.             fprintf(stderr, "Bad input line: %s\n", buffer);
  407.             exit(EX_DATAERR);
  408.         }
  409.         while (*p == ' ' || *p == '\t') {
  410.             p++;
  411.         }
  412.         }
  413.  
  414.         if (*p != ':' && *p != '"') {
  415.         fprintf(stderr, "No ':' or '\"' where expected: %s\n",
  416.             buffer);
  417.         continue;
  418.         }
  419.  
  420.         tbuf = (char *)malloc(4*strlen(p));
  421.  
  422.         if (!(p1 = tbuf)) {
  423.         fprintf(stderr, "%s: Out of memory\n", tblname);
  424.         exit(EX_DATAERR);
  425.         }
  426.         if (*p == '"') {
  427.         /*
  428.          *  Handle "<C replace>".
  429.          *  Copy chars verbatim until first '"' not \-escaped or
  430.          *  end of buffer.
  431.          */
  432.         int escaped = 0;
  433.         for (ch = *(++p); (ch = *p) != '\0'; p++) {
  434.             if (escaped) {
  435.             escaped = 0;
  436.             } else if (ch == '"') {
  437.             break;
  438.             } else if (ch == '\\') {
  439.             escaped = 1;
  440.             }
  441.             *p1++ = ch;
  442.         }
  443.         if (escaped || ch != '"') {
  444.             fprintf(stderr, "Warning: String not terminated: %s\n",
  445.                 buffer);
  446.             if (escaped)
  447.             *p1++ = '\n';
  448.         }
  449.         } else {
  450.         /*
  451.          *  We had ':'.
  452.          */
  453.         for (ch = *(++p); (ch = *p) != '\0'; p++, p1++) {
  454.             if ((unsigned char)ch < 32 || ch == '\\' || ch == '\"' ||
  455.             (unsigned char)ch >= 127) {
  456.             sprintf(p1, "\\%.3o", (unsigned char)ch); 
  457. #ifdef NOTDEFINED
  458.             fprintf(stderr, "%s\n", tbuf);
  459. #endif /* NOTDEFINED */
  460.             p1 += 3;
  461.             } else {
  462.             *p1 = ch;
  463.             }
  464.         }
  465.         }
  466.         *p1 = '\0';
  467.         for (i = un0; i <= un1; i++) {
  468. #ifdef NOTDEFINED
  469.         printf("U+0x%x:%s\n", i, tbuf); */
  470. #endif /* NOTDEFINED */
  471.         addpair_str(tbuf,i);
  472.         }
  473.         continue;
  474.     }
  475.  
  476.     /*
  477.      *  Input line (after skipping spaces) doesn't start with one
  478.      *  of the specially recognized characters, so try to interpret
  479.      *  it as starting with a fontpos.
  480.      */
  481.     fp0 = strtol(p, &p1, 0);
  482.     if (p1 == p) {
  483.         fprintf(stderr, "Bad input line: %s\n", buffer);
  484.         exit(EX_DATAERR);
  485.         }
  486.     p = p1;
  487.  
  488.     while (*p == ' ' || *p == '\t') {
  489.         p++;
  490.     }
  491.     if (*p == '-') {
  492.         p++;
  493.         fp1 = strtol(p, &p1, 0);
  494.         if (p1 == p) {
  495.         fprintf(stderr, "Bad input line: %s\n", buffer);
  496.         exit(EX_DATAERR);
  497.         }
  498.         p = p1;
  499.         } else {
  500.         fp1 = 0;
  501.     }
  502.  
  503.     if (fp0 < 0 || fp0 >= fontlen) {
  504.         fprintf(stderr,
  505.             "%s: Glyph number (0x%x) larger than font length\n",
  506.             tblname, fp0);
  507.         exit(EX_DATAERR);
  508.     }
  509.     if (fp1 && (fp1 < fp0 || fp1 >= fontlen)) {
  510.         fprintf(stderr,
  511.             "%s: Bad end of range (0x%x)\n",
  512.             tblname, fp1);
  513.         exit(EX_DATAERR);
  514.     }
  515.  
  516.     if (fp1) {
  517.         /*
  518.          *  We have a range; expect the word "idem"
  519.          *  or a Unicode range of the same length.
  520.          */
  521.         while (*p == ' ' || *p == '\t') {
  522.         p++;
  523.         }
  524.         if (!strncmp(p, "idem", 4)) {
  525.         for (i = fp0; i <= fp1; i++) {
  526.             addpair(i,i);
  527.         }
  528.         p += 4;
  529.         } else {
  530.         un0 = getunicode(&p);
  531.         while (*p == ' ' || *p == '\t') {
  532.             p++;
  533.         }
  534.         if (*p != '-') {
  535.             fprintf(stderr,
  536.                 "%s: Corresponding to a range of font positions,",
  537.                 tblname);
  538.             fprintf(stderr,
  539.                 " there should be a Unicode range.\n");
  540.             exit(EX_DATAERR);
  541.             }
  542.         p++;
  543.         un1 = getunicode(&p);
  544.         if (un0 < 0 || un1 < 0) {
  545.             fprintf(stderr,
  546.      "%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n",
  547.                 tblname, fp0, fp1);
  548.             exit(EX_DATAERR);
  549.             }
  550.         if (un1 - un0 != fp1 - fp0) {
  551.             fprintf(stderr,
  552.             "%s: Unicode range U+%x-U+%x not of the same length",
  553.                 tblname, un0, un1);
  554.             fprintf(stderr,
  555.                 " as font position range 0x%x-0x%x\n",
  556.                 fp0, fp1);
  557.             exit(EX_DATAERR);
  558.             }
  559.         for (i = fp0; i <= fp1; i++) {
  560.             addpair(i,un0-fp0+i);
  561.         }
  562.         }
  563.     } else {
  564.         /*
  565.          *  No range; expect a list of unicode values
  566.          *  or unicode ranges for a single font position,
  567.          *  or the word "idem"
  568.          */
  569.         while (*p == ' ' || *p == '\t') {
  570.         p++;
  571.         }
  572.         if (!strncmp(p, "idem", 4)) {
  573.         addpair(fp0,fp0);
  574.         p += 4;
  575.         }
  576.         while ((un0 = getunicode(&p)) >= 0) {
  577.         addpair(fp0, un0);
  578.         while (*p == ' ' || *p == '\t') {
  579.             p++;
  580.         }
  581.         if (*p == '-') {
  582.             p++;
  583.             un1 = getunicode(&p);
  584.             if (un1 < un0) {
  585.             fprintf(stderr,
  586.                 "%s: Bad Unicode range 0x%x-0x%x\n",
  587.                 tblname, un0, un1);
  588.             exit(EX_DATAERR);
  589.             }
  590.             for (un0++; un0 <= un1; un0++) {
  591.             addpair(fp0, un0);
  592.             }
  593.         }
  594.         }
  595.     }
  596.     while (*p == ' ' || *p == '\t') {
  597.         p++;
  598.     }
  599.     if (*p && *p != '#') {
  600.         fprintf(stderr, "%s: trailing junk (%s) ignored\n", tblname, p);
  601.     }
  602.     }
  603.  
  604.     /*
  605.      *  Okay, we hit EOF, now output tables.
  606.      */
  607.     fclose(ctbl);
  608.   
  609.  
  610.     /*
  611.      *  Compute total size of Unicode list.
  612.      */
  613.     nuni = 0;
  614.     for (i = 0 ; i < fontlen ; i++) {
  615.     nuni += unicount[i];
  616.     }
  617.  
  618.     if (argc >= 3) {
  619.     strncpy(this_MIMEcharset,argv[2],UC_MAXLEN_MIMECSNAME);
  620.     } else if (this_MIMEcharset[0] == '\0') {
  621.     strncpy(this_MIMEcharset,tblname,UC_MAXLEN_MIMECSNAME);
  622.     if ((p = strchr(this_MIMEcharset,'.')) != 0) {
  623.         *p = '\0';
  624.     }
  625.     }
  626.     for (p = this_MIMEcharset; *p; p++) {
  627.     *p = TOLOWER(*p);
  628.     }
  629.     if (argc >= 4) {
  630.     strncpy(this_LYNXcharset,argv[3],UC_MAXLEN_LYNXCSNAME);
  631.     } else if (this_LYNXcharset[0] == '\0') {
  632.     strncpy(this_LYNXcharset,this_MIMEcharset,UC_MAXLEN_LYNXCSNAME);
  633.     }
  634.     if ((i = strlen(this_LYNXcharset)) < UC_LEN_LYNXCSNAME) {
  635.     for (; i < UC_LEN_LYNXCSNAME; i++) {
  636.         this_LYNXcharset[i] = ' ';
  637.     }
  638.     this_LYNXcharset[i] = '\0';
  639.     }
  640. #ifdef NOTDEFINED
  641.     fprintf(stderr,"this_MIMEcharset: %s.\n",this_MIMEcharset);
  642.     fprintf(stderr,"this_LYNXcharset: %s.\n",this_LYNXcharset);
  643. #endif /* NOTDEFINED */
  644.     if (this_isDefaultMap == -1) {
  645.     this_isDefaultMap = !strncmp(this_MIMEcharset,"iso-8859-1", 10);
  646.     }
  647.     fprintf(stderr,
  648.             "makeuctb: %s: %stranslation map",
  649.          this_MIMEcharset, (this_isDefaultMap ? "default " : ""));
  650.     if (this_isDefaultMap == 1) {
  651.     *id_append = '\0';
  652.     } else {
  653.     for (i = 0, p = this_MIMEcharset;
  654.          *p && (i < UC_MAXLEN_ID_APPEND-1);
  655.          p++, i++) {
  656.         id_append[i+1] = isalnum(*p) ? *p : '_';
  657.     }
  658.     }
  659.     id_append[i+1] = '\0';
  660.     fprintf(stderr, " (%s).\n", id_append);
  661.  
  662.     printf("\
  663. /*\n\
  664.  *  uni_hash.tbl\n\
  665.  *\n\
  666.  *  Do not edit this file; it was automatically generated by\n\
  667.  *\n\
  668.  *  %s %s\n\
  669.  *\n\
  670.  */\n\
  671. \n\
  672. static u8 dfont_unicount%s[%d] = \n\
  673. {\n\t", argv[0], argv[1], id_append, fontlen);
  674.  
  675.     for (i = 0; i < fontlen; i++) {
  676.     if (i >= 128 && unicount[i] > 0 && i < lowest_eight) {
  677.         lowest_eight = i;
  678.     }
  679.     printf("%3d", unicount[i]);
  680.     if (i == (fontlen - 1)) {
  681.         printf("\n};\n");
  682.     } else if ((i % 8) == 7) {
  683.         printf(",\n\t");
  684.     } else {
  685.         printf(", ");
  686.     }
  687.     }
  688.  
  689.     /*
  690.      *  If lowest_eightbit is anything else but 999,
  691.      *  this can't be 7-bit only.
  692.      */
  693.     if (lowest_eight != 999 && !RawOrEnc) {
  694.     RawOrEnc = UCT_ENC_8BIT;
  695.     }
  696.  
  697.     if (nuni) {
  698.     printf("\nstatic u16 dfont_unitable%s[%d] = \n{\n\t",
  699.            id_append, nuni);
  700.     } else {
  701.     printf("\nstatic u16 dfont_unitable%s[1]; /* dummy */\n", id_append);
  702.     }
  703.  
  704.     fp0 = 0;
  705.     nent = 0;
  706.     for (i = 0; i < nuni; i++) {
  707.     while (nent >= unicount[fp0]) {
  708.         fp0++;
  709.         nent = 0;
  710.     }
  711.     printf("0x%04x", unitable[fp0][nent++]);
  712.     if (i == (nuni - 1)) {
  713.         printf("\n};\n");
  714.     } else if ((i % 8) == 7) {
  715.         printf(",\n\t");
  716.     } else {
  717.         printf(", ");
  718.     }
  719.     }
  720.  
  721.     if (themap_str.entry_ct) {
  722.     printf("\n\
  723. static struct unipair_str repl_map%s[%d] = \n\
  724. {\n\t", id_append, themap_str.entry_ct);
  725.     } else {
  726.     printf("\n\
  727. /* static struct unipair_str repl_map%s[]; */\n", id_append);
  728.     }
  729.     
  730.     for (i = 0; i < themap_str.entry_ct; i++) {
  731.     printf("{0x%x,\"%s\"}",
  732.            themap_str.entries[i].unicode,
  733.            themap_str.entries[i].replace_str);
  734.     if (i == (themap_str.entry_ct - 1)) {
  735.         printf("\n};\n");
  736.     } else if ((i % 4) == 3) {
  737.         printf(",\n\t");
  738.     } else {
  739.         printf(", ");
  740.     }
  741.     }
  742.     if (themap_str.entry_ct) {
  743.     printf("\n\
  744. static struct unimapdesc_str dfont_replacedesc%s = {%d,repl_map%s,",
  745. id_append, themap_str.entry_ct, id_append);
  746.     } else {
  747.     printf("\n\
  748. static struct unimapdesc_str dfont_replacedesc%s = {0,NULL,",id_append);
  749.     }
  750.     printf("%d,%d};\n",
  751.     this_isDefaultMap ? 1 : 0,
  752.     (useDefaultMap && !this_isDefaultMap) ? 1 : 0
  753.     );
  754.  
  755.  
  756.     printf("#define UC_CHARSET_SETUP%s UC_Charset_Setup(\
  757. \"%s\",\\\n\"%s\",\\\n\
  758. dfont_unicount%s,dfont_unitable%s,%d,\\\n\
  759. dfont_replacedesc%s,%d,%d)\n",
  760. id_append, this_MIMEcharset, this_LYNXcharset,
  761. id_append, id_append, nuni, id_append, lowest_eight, RawOrEnc);
  762.  
  763.     exit(EX_OK);
  764. }
  765.