home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 517a.lha / FontManipulatorForDtp_v2 / source / mkatc / mkatc.c < prev    next >
C/C++ Source or Header  |  1991-06-09  |  19KB  |  702 lines

  1. /* CGFont .atc file builder for PPage etc.  File "mkatc.c".
  2.  * (C) Adrian Aylward 1991
  3.  *
  4.  * You may freely copy, use, and modify this file.
  5.  *
  6.  * This program prints builds a CGFont encoding (.atc) file in the format
  7.  * used by Professional Page from a PostScript style encoding table.
  8.  *
  9.  * The program was tested using Lattice C V5.05.  It has various Lattice
  10.  * dependencies.
  11.  *
  12.  * This is version 1.0.
  13.  */
  14.  
  15. # include <dos.h>
  16. # include <exec/exec.h>
  17. # include <proto/dos.h>
  18. # include <proto/exec.h>
  19. # include <string.h>
  20. # include <setjmp.h>
  21. # include <stdio.h>
  22.  
  23. /* Atc file format */
  24.  
  25. struct atcfile
  26. {   int af_uid;
  27.     unsigned short af_code[256];
  28. };
  29.  
  30. /* External data (initialised to zero) */
  31.  
  32. char *argatcfile;
  33. char *argencodingfile, *argcharcodefile;
  34.  
  35. int optread, optverify, optuid;
  36. int uid;
  37. int lochar, hichar;
  38.  
  39. BPTR newfh;
  40.  
  41. int retcode;
  42.  
  43. # define memsize 10000
  44.  
  45. char *membeg[100], *memptr;
  46. int memsegs, memfree;
  47.  
  48. struct atcmem
  49. {   struct atcfile file;
  50.     int dummy;
  51. };
  52.  
  53. struct atcmem atcmem;
  54.  
  55. struct charentry
  56. {   short code;
  57.     char *str;
  58. };
  59.  
  60. # define charcodesize 2000
  61.  
  62. struct charentry charcode[charcodesize];
  63.  
  64. int charcodelen;
  65.  
  66. char *currentfile;
  67. FILE *currentfptr;
  68.  
  69. # define NOURCH   (EOF - 1)
  70.  
  71. int lineno, urch;
  72. int scanmode;
  73.  
  74. int retcode;
  75. jmp_buf errjmp;
  76.  
  77. # define typeeof     0
  78. # define typeeol     1
  79. # define typesemi    2
  80. # define typepercent 3
  81. # define typename    4
  82. # define typeint     5
  83.  
  84. int tokentype, tokenival;
  85.  
  86. char namebuf[256];
  87.  
  88. /* Encoding vector, initially Adobe StandardEncoding */
  89.  
  90. char *encoding[256] =
  91. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  92.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  93.   "space",         "exclam",        "quotedbl",      "numbersign", /* 20 */
  94.   "dollar",        "percent",       "ampersand",     "quoteright",
  95.   "parenleft",     "parenright",    "asterisk",      "plus",
  96.   "comma",         "hyphen",        "period",        "slash",
  97.   "zero",          "one",           "two",           "three",      /* 30 */
  98.   "four",          "five",          "six",           "seven",
  99.   "eight",         "nine",          "colon",         "semicolon",
  100.   "less",          "equal",         "greater",       "question",
  101.   "at",            "A",             "B",             "C",          /* 40 */
  102.   "D",             "E",             "F",             "G",
  103.   "H",             "I",             "J",             "K",
  104.   "L",             "M",             "N",             "O",
  105.   "P",             "Q",             "R",             "S",          /* 50 */
  106.   "T",             "U",             "V",             "W",
  107.   "X",             "Y",             "Z",             "bracketleft",
  108.   "backslash",     "bracketright",  "asciicircum",   "underscore",
  109.   "quoteleft",     "a",             "b",             "c",          /* 60 */
  110.   "d",             "e",             "f",             "g",
  111.   "h",             "i",             "j",             "k",
  112.   "l",             "m",             "n",             "o",
  113.   "p",             "q",             "r",             "s",          /* 70 */
  114.   "t",             "u",             "v",             "w",
  115.   "x",             "y",             "z",             "braceleft",
  116.   "bar",           "braceright",    "asciitilde",    0,
  117.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  118.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  119.   0,               "exclamdown",    "cent",          "sterling",   /* A0 */
  120.   "fraction",      "yen",           "florin",        "section",
  121.   "currency",      "quotesingle",   "quotedblleft",  "guillemotleft",
  122.   "guilsinglleft", "guilsinglright","fi",            "fl",
  123.   0,               "endash",        "dagger",        "daggerdbl",  /* B0 */
  124.   "periodcentered",0,               "paragraph",     "bullet",
  125.   "quotesinglbase","quotedblbase",  "quotedblright", "guillemotright",
  126.   "ellipsis",      "perthousand",   0,               "questiondown",
  127.   0,               "grave",         "acute",         "circumflex", /* C0 */
  128.   "tilde",         "macron",        "breve",         "dotaccent",
  129.   "dieresis",      0,               "ring",          "cedilla",
  130.   0,               "hungarumlaut",  "ogonek",        "caron",
  131.   "emdash",        0,               0,               0,            /* D0 */
  132.   0,               0,               0,               0,
  133.   0,               0,               0,               0,
  134.   0,               0,               0,               0,
  135.   0,               "AE",            0,               "ordfeminine",/* E0 */
  136.   0,               0,               0,               0,
  137.   "Lslash",        "Oslash",        "OE",            "ordmasculine",
  138.   0,               0,               0,               0,
  139.   0,               "ae",            0,               0,            /* F0 */
  140.   0,               "dotlessi",      0,               0,
  141.   "lslash",        "oslash",        "oe",            "germandbls",
  142.   0,               0,               0,               0
  143. };
  144.  
  145. /* Routines */
  146.  
  147. extern int  strtoint(char **sp, int *ip);
  148. extern void readencoding(void);
  149. extern void readcharcode(void);
  150. extern void rdtoken(void);
  151. extern void skipeol(void);
  152. extern void skipspace(void);
  153. extern int  rdch(void);
  154. extern void unrdch(int ch);
  155. extern void errsyntax(char *f);
  156. extern void errmemory(void);
  157. extern char *makestring(char *str);
  158. extern void *allocmem(int size);
  159. extern void freeall(void);
  160. extern void stub(void);
  161. extern void chkabort(void);
  162.  
  163. /* Main program */
  164.  
  165. void main(int argc, char **argv)
  166. {   char *s;
  167.     int *ip, i, j, ch;
  168.  
  169.     /* Parse arguments.  No workbench startup */
  170.  
  171.     lochar = 32;
  172.     hichar = 255;
  173.  
  174.     if (argc == 0) goto tidyexit;
  175.     argv++;
  176.     argc--;
  177.     if (argc == 0 || (argc == 1 && strcmp(*argv, "?") == 0)) goto query;
  178.  
  179.     while (argc)
  180.     {   s = *argv;
  181.         if (*s != '-') break;
  182.         argv++;
  183.         argc--;
  184.         if (strcmp(s, "--") == 0) break;
  185.         s++;
  186.         for (;;)
  187.         {   ch = *s++;
  188.             if (ch == 0) break;
  189.             switch (ch)
  190.             {   case 'E': case 'e':
  191.                     if (argc == 0) goto badargs;
  192.                     argencodingfile = *argv++;
  193.                     argc--;
  194.                     continue;
  195.  
  196.                 case 'C': case 'c':
  197.                     if (argc == 0) goto badargs;
  198.                     argcharcodefile = *argv++;
  199.                     argc--;
  200.                     continue;
  201.  
  202.                 case 'U': case 'u':
  203.                     optuid = 1;
  204.                     ip = &uid;
  205.                     break;
  206.  
  207.                 case 'R': case 'r':
  208.                     optread = 1;
  209.                     continue;
  210.  
  211.                 case 'v':
  212.                     optverify = 1;
  213.                     continue;
  214.  
  215.                 case 'V':
  216.                     optverify = 2;
  217.                     continue;
  218.  
  219.                 case 'L': case 'l':
  220.                     ip = &lochar;
  221.                     break;
  222.  
  223.                 case 'H': case 'h':
  224.                     ip = &hichar;
  225.                     break;
  226.  
  227.                 default:
  228.                     fprintf(stderr, "mkatc: unknown option \"-%c\"", ch);
  229.                     goto badusage;
  230.             }
  231.             if (!strtoint(&s, ip)) goto badargs;
  232.         }
  233.  
  234.         if (*s == '-' && *(s + 1) == 0) break;
  235.     }
  236.  
  237.     if (lochar > hichar || hichar > 255)
  238.     {   fprintf(stderr, "mkatc: LoChar/HiChar out of range "
  239.                                 "(0 <= Lo <= Hi <= 255)\n");
  240.         goto errorexit;
  241.     }
  242.  
  243.     if (argc != 1) goto badargs;
  244.     argatcfile = argv[0];
  245.  
  246.     if (argencodingfile == NULL) argencodingfile = "PSFonts:encoding.ps";
  247.     if (argcharcodefile == NULL) argcharcodefile = "CGFonts:cgcharcodes";
  248.  
  249.     /* Read the encoding file */
  250.  
  251.     if (optread) goto skipenc;
  252.     currentfile = argencodingfile;
  253.     currentfptr = fopen(currentfile, "r");
  254.     if (currentfptr == NULL)
  255.     {   fprintf(stderr, "mkatc: can't open encoding file %s\n", currentfile);
  256.         goto errorexit;
  257.     }
  258.     readencoding();
  259.     if (retcode != 0) goto errorexit;
  260.     fclose(currentfptr);
  261.     currentfptr = NULL;
  262.  
  263.     /* Read the charcode file */
  264.  
  265. skipenc:
  266.     currentfile = argcharcodefile;
  267.     currentfptr = fopen(currentfile, "r");
  268.     if (currentfptr == NULL)
  269.     {   fprintf(stderr, "mkatc: can't open charcode file %s\n", currentfile);
  270.         goto errorexit;
  271.     }
  272.     readcharcode();
  273.     if (retcode != 0) goto errorexit;
  274.     fclose(currentfptr);
  275.     currentfptr = NULL;
  276.  
  277.     /* Read the old .atc file */
  278.  
  279.     if (optread || !optuid)
  280.     {   newfh = Open(argatcfile, MODE_OLDFILE);
  281.         if (newfh == NULL)
  282.         {   fprintf(stderr, "mkatc: can't open atc file %s\n",
  283.                     argatcfile);
  284.             goto errorexit;
  285.         }
  286.         i = Read(newfh, (UBYTE *) &atcmem, sizeof (atcmem));
  287.         Close(newfh);
  288.         if (i == -1)
  289.         {   fprintf(stderr, "mkatc: error reading atc file %s\n",
  290.                     argatcfile);
  291.             goto errorexit;
  292.         }
  293.         if (i != sizeof (struct atcfile))
  294.         {   fprintf(stderr, "mkatc: atc file %s format error\n",
  295.                     argatcfile);
  296.             goto errorexit;
  297.         }
  298.     }
  299.  
  300.     /* Update the uid */
  301.  
  302.     if (optuid) atcmem.file.af_uid = uid;
  303.     if (optverify)
  304.         fprintf(stdout, "% file \"%s\" uid = %d\n",
  305.                         argatcfile, atcmem.file.af_uid);
  306.  
  307.     /* If reading, we look up the codes in the charcodes */
  308.  
  309.     if (optread)
  310.     {   for (i = 0; i < 256; i++)
  311.         {   ch = atcmem.file.af_code[i];
  312.             if (ch != 0)
  313.             {   for (j = 0; j < charcodelen; j++)
  314.                     if (charcode[j].code == ch)
  315.                     {   s = charcode[j].str;
  316.                         goto gotit1;
  317.                     }
  318.                     fprintf(stderr, "mkatc: character %4d "
  319.                                     "not in charcodes, name unknown\n", ch);
  320.                     retcode = 5;
  321.                     s = "NULL";
  322. gotit1:             if (optverify == 1)
  323.                         fprintf(stdout, "%3d /%-20s %% %4d\n", i, s, ch);
  324.                     if (optverify == 2)
  325.                         fprintf(stdout, "  %-20s %3d %4d\n", s, i, ch);
  326.             }
  327.         }
  328.     }
  329.  
  330.     /* If writing, we look up the names in the charcodes */
  331.  
  332.     else
  333.     {   for (i = 0; i < 256; i++)
  334.         {   ch = 0;
  335.             if (i >= lochar && i <= hichar)
  336.             {   s = encoding[i];
  337.                 if (s != NULL)
  338.                 {   for (j = 0; j < charcodelen; j++)
  339.                         if (strcmp(charcode[j].str, s) == 0)
  340.                         {   ch = charcode[j].code;
  341.                             if (ch == 0) goto skipv2;
  342.                             goto gotit2;
  343.                         }
  344.                     fprintf(stderr, "mkatc: character \"%s\" "
  345.                                     "not in charcodes, omitted\n", s);
  346.                     retcode = 5;
  347.  
  348. gotit2:             if (optverify == 1)
  349.                         fprintf(stdout, "%3d /%-20s %% %4d\n", i, s, ch);
  350.                     if (optverify == 2)
  351.                         fprintf(stdout, "  %-20s %3d %4d\n", s, i, ch);
  352.                 }
  353.             }
  354. skipv2:     atcmem.file.af_code[i] = ch;
  355.         }
  356.     }
  357.  
  358.     /* Write out the new .atc file */
  359.  
  360.     if (!optread)
  361.     {   newfh = Open(argatcfile, MODE_NEWFILE);
  362.         if (newfh == NULL)
  363.         {   fprintf(stderr, "mkatc: can't open atc file %s\n",
  364.                     argatcfile);
  365.             goto errorexit;
  366.         }
  367.         i = Write(newfh, (UBYTE *) &atcmem, sizeof (struct atcfile));
  368.         Close(newfh);
  369.         if (i != sizeof (struct atcfile))
  370.         {   fprintf(stderr, "mkatc: error writing atc file %s\n",
  371.                     argatcfile);
  372.             goto errorexit;
  373.         }
  374.     }
  375.  
  376.     goto tidyexit;
  377.  
  378.     /* Argument errors and usage query */
  379.  
  380. query:
  381.     fprintf(stderr, "Atc file builder.  MkAtc version 1.0\n"
  382.                     "Makes CGFont .atc files from the encoding file\n"
  383.                     "\n"
  384.                     "  Usage:\n"
  385.                     "\n"
  386.                     "    mkatc -options atcfile\n"
  387.                     "\n"
  388.                     "      -e encodingfile  Encoding file name\n"
  389.                     "      -c charcodesfile Character codes file name\n"
  390.                     "      -lnnn            LoChar\n"
  391.                     "      -hnnn            Hichar\n"
  392.                     "      -unnn            Unique id\n"
  393.                     "      -r               Read .atc file, do not update\n"
  394.                     "      -v               Verify encoding table\n"
  395.                     "      -V               Verify encoding, "
  396.                                            "alternative format\n"
  397.                     "\n"
  398.                     "  For example:\n"
  399.                     "\n"
  400.                     "    mkatc cgfonts:Times.atc\n");
  401.     goto tidyexit;
  402.  
  403. badargs:
  404.     fprintf(stderr, "mkatc: arguments bad, or value missing");
  405. badusage:
  406.     retcode = 20;
  407.     fprintf(stderr, ".  Usage:\n"
  408.                     "    mkatc -options atcfile\n");
  409.     goto tidyexit;
  410.  
  411.     /* Tidy up and exit */
  412.  
  413. broken:
  414.     fprintf(stderr, "mkatc: *** Break\n");
  415.     retcode = 10;
  416.     goto tidyexit;
  417.  
  418. errorexit:
  419.     retcode = 20;
  420.  
  421. tidyexit:
  422.     if (currentfptr) fclose(currentfptr);
  423.     currentfptr = NULL;
  424.     freeall();
  425.     exit(retcode);
  426. }
  427.  
  428. /* String to integer conversion; digits only, with error check */
  429.  
  430. int strtoint(char **sp, int *ip)
  431. {   char *s = *sp;
  432.     int i = 0;
  433.     int ch;
  434.     for (;;)
  435.     {   ch = *s;
  436.         if (ch < '0' || ch > '9') break;
  437.         i = i * 10 + (ch - '0');
  438.         s++;
  439.     }
  440.     if (s == *sp)
  441.         return 0;
  442.     else
  443.     {   *sp = s;
  444.         *ip = i;
  445.         return 1;
  446.     }
  447. }
  448.  
  449. /* Read the encoding file */
  450.  
  451. void readencoding(void)
  452. {   char *str;
  453.     int ch;
  454.  
  455.     lineno = 1;
  456.     urch = NOURCH;
  457.  
  458.     retcode = setjmp(errjmp);
  459.     if (retcode != 0) return;
  460.  
  461.     for (;;)
  462.     {   rdtoken();
  463.         if (tokentype == typeeof) break;
  464.         if (tokentype == typeeol) continue;
  465.         if (tokentype != typeint) errsyntax("integer expected");
  466.         ch = tokenival;
  467.         rdtoken();
  468.         if (tokentype != typename) errsyntax("name expected");
  469.         if (namebuf[0] == '/')
  470.            str = makestring(&namebuf[1]);
  471.         else
  472.            str = makestring(&namebuf[0]);
  473.         rdtoken();
  474.         if (tokentype != typeeol) errsyntax("end of line expected");
  475.         if (ch < 0 || ch > 255)
  476.             errsyntax("character code out of range");
  477.         if (strcmp(str, ".notdef") != 0) encoding[ch] = str;
  478.     }
  479. }
  480.  
  481. /* Read the charcode file */
  482.  
  483. void readcharcode(void)
  484. {   char *str;
  485.     int ch;
  486.  
  487.     lineno = 1;
  488.     urch = NOURCH;
  489.  
  490.     retcode = setjmp(errjmp);
  491.     if (retcode != 0) return;
  492.  
  493.     for (;;)
  494.     {   rdtoken();
  495.         if (tokentype == typeeof) break;
  496.         if (tokentype == typeeol) continue;
  497.         if (tokentype != typeint) errsyntax("integer expected");
  498.         ch = tokenival;
  499.         rdtoken();
  500.         if (tokentype != typename) errsyntax("name expected");
  501.         if (namebuf[0] == '/')
  502.            str = makestring(&namebuf[1]);
  503.         else
  504.            str = makestring(&namebuf[0]);
  505.         rdtoken();
  506.         if (tokentype != typeeol) errsyntax("end of line expected");
  507.         if (ch < 0 || ch > 65535)
  508.             errsyntax("character code out of range");
  509.         if (charcodelen >= charcodesize)
  510.             errsyntax("too many characters");
  511.         charcode[charcodelen].code = ch;
  512.         charcode[charcodelen].str = str;
  513.         charcodelen++;
  514.     }
  515. }
  516.  
  517. /* Read the next token */
  518.  
  519. void rdtoken(void)
  520. {   int val, i, j, ch;
  521.     skipspace();
  522.     i = 0;
  523.     for (;;)
  524.     {   ch = rdch();
  525.         if (ch == EOF)
  526.         {   if (i == 0)
  527.             {   tokentype = typeeof;
  528.                 return;
  529.             }
  530.             else
  531.                 break;
  532.         }
  533.         if (ch == '%')
  534.         {   if (i == 0)
  535.             {   skipeol();
  536.                 tokentype = typeeol;
  537.                 return;
  538.             }
  539.             else
  540.                 break;
  541.         }
  542.         if (ch == '\n')
  543.         {   if (i == 0)
  544.             {   tokentype = typeeol;
  545.                 return;
  546.             }
  547.             else
  548.                 break;
  549.         }
  550.         if (ch == ' ' || ch == '\t') break;
  551.         if (i >= 255) errsyntax("token too long");
  552.         namebuf[i++] = ch;
  553.     }
  554.     namebuf[i] = 0;
  555.     unrdch(ch);
  556.     tokentype = typename;
  557.     {   j = 0;
  558.         if (namebuf[0] == '-')
  559.         {   j++;
  560.             if (i <= j) return;
  561.         }
  562.         val = 0;
  563.         while (j < i)
  564.         {   ch = namebuf[j];
  565.             if (ch < '0' || ch > '9') return;
  566.             val = val * 10 + (ch - '0');
  567.             j++;
  568.         }
  569.         if (namebuf[0] == '-') val = -val;
  570.         tokentype = typeint;
  571.         tokenival = val;
  572.     }
  573. }
  574.  
  575. /* Skip to end of line */
  576.  
  577. void skipeol(void)
  578. {   int ch;
  579.     for (;;)
  580.     {   ch = rdch();
  581.         if (ch == EOF)
  582.         {   unrdch(EOF);
  583.             break;
  584.         }
  585.         if (ch == '\n') break;
  586.     }
  587. }
  588.  
  589. /* Skip white space */
  590.  
  591. void skipspace(void)
  592. {   int ch;
  593.     for (;;)
  594.     {   ch = rdch();
  595.         if (ch != ' ' && ch != '\t') break;
  596.     }
  597.     unrdch(ch);
  598. }
  599.  
  600. /* Read next character */
  601.  
  602. int rdch(void)
  603. {   int ch;
  604.     if (urch == NOURCH)
  605.     {   ch = getc(currentfptr);
  606.         if (ch == EOF)
  607.         {   if (ferror(currentfptr)) errsyntax("file read error");
  608.             return EOF;
  609.         }
  610.         if      (ch == '\n')
  611.         {   ch = getc(currentfptr);
  612.             if (ch != '\r' && ch != EOF) ungetc(ch, currentfptr);
  613.             ch = '\n';
  614.             lineno++;
  615.         }
  616.         else if (ch == '\r')
  617.         {   ch = '\n';
  618.             lineno++;
  619.         }
  620.     }
  621.     else
  622.     {   ch = urch;
  623.         urch = NOURCH;
  624.     }
  625.     return ch;
  626. }
  627.  
  628. /* Unread last character */
  629.  
  630. void unrdch(int ch)
  631. {   urch = ch;
  632. }
  633.  
  634. /* Syntax error */
  635.  
  636. void errsyntax(char *str)
  637. {   fprintf(stderr, "mkatc: syntax error in \"%s\", line %d - %s\n",
  638.             currentfile, lineno, str);
  639.     longjmp(errjmp, 20);
  640. }
  641.  
  642. /* Memory allocation error */
  643.  
  644. void errmemory(void)
  645. {   fprintf(stderr, "mkatc: memory exhausted\n");
  646.     longjmp(errjmp, 20);
  647. }
  648.  
  649. /* Make a string */
  650.  
  651. char *makestring(char *str)
  652. {   char *s;
  653.     s = allocmem(strlen(str) + 1);
  654.     if (s == NULL) errmemory();
  655.     strcpy(s, str);
  656.     return s;
  657. }
  658.  
  659. /* Allocate memory */
  660.  
  661. void *allocmem(int size)
  662. {   char *ptr;
  663.     int msize;
  664.     msize = (size + 3) & ~3;
  665.     if (msize > memfree)
  666.     {   if (msize > memsize) return NULL;
  667.         if (memsegs == 100) return NULL;
  668.         ptr = AllocMem(memsize, MEMF_CLEAR);
  669.         if (ptr == NULL) return NULL;
  670.         membeg[memsegs++] = ptr;
  671.         memptr = ptr;
  672.         memfree = memsize;
  673.     }
  674.     ptr = memptr;
  675.     memfree -= msize;
  676.     memptr += msize;
  677.     return (void *) ptr;
  678. }
  679.  
  680. /* Free all memory */
  681.  
  682. void freeall(void)
  683. {   while (memsegs)
  684.     {   memsegs--;
  685.         FreeMem(membeg[memsegs], memsize);
  686.     }
  687. }
  688.  
  689. /* Dummy stub routine */
  690.  
  691. void stub(void)
  692. {   return;
  693. }
  694.  
  695. /* Dummy check abort routine */
  696.  
  697. void chkabort(void)
  698. {   return;
  699. }
  700.  
  701. /* End of file "mkatc.c" */
  702.