diff options
Diffstat (limited to 'Build/source/utils/t1utils/t1utils-src/t1asm.c')
-rw-r--r-- | Build/source/utils/t1utils/t1utils-src/t1asm.c | 810 |
1 files changed, 0 insertions, 810 deletions
diff --git a/Build/source/utils/t1utils/t1utils-src/t1asm.c b/Build/source/utils/t1utils/t1utils-src/t1asm.c deleted file mode 100644 index 67a6ced2234..00000000000 --- a/Build/source/utils/t1utils/t1utils-src/t1asm.c +++ /dev/null @@ -1,810 +0,0 @@ -/* t1asm -*- c-basic-offset: 2 -*- - * - * This program `assembles' Adobe Type-1 font programs in pseudo-PostScript - * form into either PFB or PFA format. The human readable/editable input is - * charstring- and eexec-encrypted as specified in the `Adobe Type 1 Font - * Format' version 1.1 (the `black book'). There is a companion program, - * t1disasm, which `disassembles' PFB and PFA files into a pseudo-PostScript - * file. - * - * Copyright (c) 1992 by I. Lee Hetherington, all rights reserved. - * Copyright (c) 1998-2017 Eddie Kohler - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, subject to the - * conditions listed in the Click LICENSE file, which is available in full at - * http://github.com/kohler/click/blob/master/LICENSE. The conditions - * include: you must preserve this copyright notice, and you cannot mention - * the copyright holders in advertising related to the Software without - * their permission. The Software is provided WITHOUT ANY WARRANTY, EXPRESS - * OR IMPLIED. This notice is a summary of the Click LICENSE file; the - * license in that file is binding. - * - * New change log in `NEWS'. Old change log: - * - * Revision 1.4 92/07/10 10:53:09 ilh - * Added support for additional PostScript after the closefile command - * (ie., some fonts have {restore}if after the cleartomark). - * - * Revision 1.3 92/06/23 10:58:25 ilh - * MSDOS porting by Kai-Uwe Herbing (herbing@netmbx.netmbx.de) - * incoporated. - * - * Revision 1.2 92/05/22 11:54:45 ilh - * Fixed bug where integers larger than 32000 could not be encoded in - * charstrings. Now integer range is correct for four-byte - * twos-complement integers: -(1<<31) <= i <= (1<<31)-1. Bug detected by - * Piet Tutelaers (rcpt@urc.tue.nl). - * - * Revision 1.1 92/05/22 11:48:46 ilh - * initial version - * - * Ported to Microsoft C/C++ Compiler and MS-DOS operating system by - * Kai-Uwe Herbing (herbing@netmbx.netmbx.de) on June 12, 1992. Code - * specific to the MS-DOS version is encapsulated with #ifdef _MSDOS - * ... #endif, where _MSDOS is an identifier, which is automatically - * defined, if you compile with the Microsoft C/C++ Compiler. - * - */ - -/* Note: this is ANSI C. */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#if defined(_MSDOS) || defined(_WIN32) -# include <fcntl.h> -# include <io.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <limits.h> -#include <stdarg.h> -#include <errno.h> -#include <lcdf/clp.h> -#include "t1lib.h" -#include "t1asmhelp.h" - -#define LINESIZE 512 - -#ifdef __cplusplus -extern "C" { -#endif - -typedef unsigned char byte; - -static FILE *ifp; -static FILE *ofp; -static struct pfb_writer w; -static int blocklen = -1; - -/* flags */ -static int pfb = 1; -static int active = 0; -static int ever_active = 0; -static int start_charstring = 0; -static int in_eexec = 0; - -/* need to add 1 as space for \0 */ -static char line[LINESIZE + 1]; - -/* for charstring buffering */ -static byte *charstring_buf, *charstring_bp; -static int charstring_bufsiz; - -/* decryption stuff */ -static uint16_t er, cr; -static const uint32_t c1 = 52845; -static const uint32_t c2 = 22719; - -/* table of charstring commands */ -static struct command { - const char *name; - int one, two; -} command_table[] = { - { "abs", 12, 9 }, /* Type 2 */ - { "add", 12, 10 }, /* Type 2 */ - { "and", 12, 3 }, /* Type 2 */ - { "blend", 16, -1 }, /* Type 2 */ - { "callgsubr", 29, -1 }, /* Type 2 */ - { "callother", 12, 16 }, /* Type 1 ONLY */ - { "callothersubr", 12, 16 }, /* Type 1 ONLY */ - { "callsubr", 10, -1 }, - { "closepath", 9, -1 }, /* Type 1 ONLY */ - { "cntrmask", 20, -1 }, /* Type 2 */ - { "div", 12, 12 }, - { "dotsection", 12, 0 }, /* Type 1 ONLY */ - { "drop", 12, 18 }, /* Type 2 */ - { "dup", 12, 27 }, /* Type 2 */ - { "endchar", 14, -1 }, - { "eq", 12, 15 }, /* Type 2 */ - { "error", 0, -1 }, /* special */ - { "escape", 12, -1 }, /* special */ - { "exch", 12, 28 }, /* Type 2 */ - { "flex", 12, 35 }, /* Type 2 */ - { "flex1", 12, 37 }, /* Type 2 */ - { "get", 12, 21 }, /* Type 2 */ - { "hflex", 12, 34 }, /* Type 2 */ - { "hflex1", 12, 36 }, /* Type 2 */ - { "hhcurveto", 27, -1 }, /* Type 2 */ - { "hintmask", 19, -1 }, /* Type 2 */ - { "hlineto", 6, -1 }, - { "hmoveto", 22, -1 }, - { "hsbw", 13, -1 }, /* Type 1 ONLY */ - { "hstem", 1, -1 }, - { "hstem3", 12, 2 }, /* Type 1 ONLY */ - { "hstemhm", 18, -1 }, /* Type 2 */ - { "hvcurveto", 31, -1 }, - { "ifelse", 12, 22 }, /* Type 2 */ - { "index", 12, 29 }, /* Type 2 */ - { "load", 12, 13 }, /* Type 2 */ - { "mul", 12, 24 }, /* Type 2 */ - { "neg", 12, 14 }, /* Type 2 */ - { "not", 12, 5 }, /* Type 2 */ - { "or", 12, 4 }, /* Type 2 */ - { "pop", 12, 17 }, /* Type 1 ONLY */ - { "put", 12, 20 }, /* Type 2 */ - { "random", 12, 23 }, /* Type 2 */ - { "rcurveline", 24, -1 }, /* Type 2 */ - { "return", 11, -1 }, - { "rlinecurve", 25, -1 }, /* Type 2 */ - { "rlineto", 5, -1 }, - { "rmoveto", 21, -1 }, - { "roll", 12, 30 }, /* Type 2 */ - { "rrcurveto", 8, -1 }, - { "sbw", 12, 7 }, /* Type 1 ONLY */ - { "seac", 12, 6 }, /* Type 1 ONLY */ - { "setcurrentpoint", 12, 33 }, /* Type 1 ONLY */ - { "sqrt", 12, 26 }, /* Type 2 */ - { "store", 12, 8 }, /* Type 2 */ - { "sub", 12, 11 }, /* Type 2 */ - { "vhcurveto", 30, -1 }, - { "vlineto", 7, -1 }, - { "vmoveto", 4, -1 }, - { "vstem", 3, -1 }, - { "vstem3", 12, 1 }, /* Type 1 ONLY */ - { "vstemhm", 23, -1 }, /* Type 2 */ - { "vvcurveto", 26, -1 }, /* Type 2 */ -}; /* alphabetical */ - -/* Two separate encryption functions because eexec and charstring encryption - must proceed in parallel. */ - -static byte eencrypt(byte plain) -{ - byte cipher; - - cipher = (byte)(plain ^ (er >> 8)); - er = (uint16_t)((cipher + er) * c1 + c2); - return cipher; -} - -static byte cencrypt(byte plain) -{ - byte cipher; - - /* Thanks to Tom Kacvinsky <tjk@ams.org> who reported that lenIV == -1 means - unencrypted charstrings. */ - if (lenIV < 0) return plain; - - cipher = (byte)(plain ^ (cr >> 8)); - cr = (uint16_t)((cipher + cr) * c1 + c2); - return cipher; -} - -/* This function outputs a single byte. If output is in PFB format then output - is buffered through blockbuf[]. If output is in PFA format, then output - will be hexadecimal if in_eexec is set, ASCII otherwise. */ - -static void output_byte(byte b) -{ - static const char *hexchar = "0123456789abcdef"; - static int hexcol = 0; - - if (pfb) { - /* PFB */ - PFB_OUTPUT_BYTE(&w, b); - } else { - /* PFA */ - if (in_eexec) { - /* trim hexadecimal lines to `blocklen' columns */ - if (hexcol >= blocklen) { - putc('\n', ofp); - hexcol = 0; - } - putc(hexchar[(b >> 4) & 0xf], ofp); - putc(hexchar[b & 0xf], ofp); - hexcol += 2; - } else { - putc(b, ofp); - } - } -} - -/* This function outputs a byte through possible eexec encryption. */ - -static void eexec_byte(byte b) -{ - if (in_eexec) - output_byte(eencrypt(b)); - else - output_byte(b); -} - -/* This function outputs a null-terminated string through possible eexec - encryption. */ - -static void eexec_string(const char *string) -{ - while (*string) - eexec_byte(*string++); -} - -/* This function gets ready for the eexec-encrypted data. If output is in - PFB format then flush current ASCII block and get ready for binary block. - We start encryption with four random (zero) bytes. */ - -static void eexec_start(char *string) -{ - eexec_string("currentfile eexec\n"); - if (pfb && w.blocktyp != PFB_BINARY) { - pfb_writer_output_block(&w); - w.blocktyp = PFB_BINARY; - } - - in_eexec = 1; - er = 55665; - eexec_byte(0); - eexec_byte(0); - eexec_byte(0); - eexec_byte(0); - eexec_string(string); -} - -/* 25.Aug.1999 -- Return 1 if this line actually looks like the start of a - charstring. We use the heuristic that it should start with `/' (a name) or - `dup' (a subroutine). Previous heuristic caused killa bad output. */ - -static int check_line_charstring(void) -{ - char *p = line; - while (isspace((unsigned char) *p)) - p++; - return (*p == '/' || (p[0] == 'd' && p[1] == 'u' && p[2] == 'p')); -} - -/* This function returns an input line of characters. A line is terminated by - length (including terminating null) greater than LINESIZE, \r, \n, \r\n, or - when active (looking for charstrings) by '{'. When terminated by a newline - the newline is put into line[]. When terminated by '{', the '{' is not put - into line[], and the flag start_charstring is set to 1. */ - -static void t1utils_getline(void) -{ - int c; - char *p = line; - int comment = 0; - start_charstring = 0; - - while (p < line + LINESIZE) { - c = getc(ifp); - - if (c == EOF) - break; - else if (c == '%') - comment = 1; - else if (active && !comment && c == '{') { - /* 25.Aug.1999 -- new check for whether we should stop be active */ - if (check_line_charstring()) { - start_charstring = 1; - break; - } else - active = 0; - } - - *p++ = (char) c; - - /* end of line processing: change CR or CRLF into LF, and exit */ - if (c == '\r') { - c = getc(ifp); - if (c != '\n') - ungetc(c, ifp); - p[-1] = '\n'; - break; - } else if (c == '\n') - break; - } - - *p = '\0'; -} - -/* This function wraps-up the eexec-encrypted data and writes ASCII trailer. - If output is in PFB format then this entails flushing binary block and - starting an ASCII block. */ - -static void eexec_end(void) -{ - int i, j; - - if (!pfb) - putc('\n', ofp); - else if (w.blocktyp != PFB_ASCII) { - pfb_writer_output_block(&w); - w.blocktyp = PFB_ASCII; - } - - in_eexec = active = 0; - - for (i = 0; i < 8; i++) { - for (j = 0; j < 64; j++) - eexec_byte('0'); - eexec_byte('\n'); - } -} - -/* This function is used by the binary search, bsearch(), for command names in - the command table. */ - -static int CDECL command_compare(const void *key, const void *item) -{ - return strcmp((const char *) key, ((const struct command *) item)->name); -} - -/* This function returns 1 if the string is an integer and 0 otherwise. */ - -static int is_integer(char *string) -{ - if (isdigit((unsigned char) string[0]) || string[0] == '-' || string[0] == '+') { - while (*++string && isdigit((unsigned char) *string)) - ; /* deliberately empty */ - if (!*string) - return 1; - } - return 0; -} - -/* This function initializes charstring encryption. Note that this is called - at the beginning of every charstring. */ - -static void charstring_start(void) -{ - int i; - - if (!charstring_buf) { - charstring_bufsiz = 65536; - if (!(charstring_buf = (byte *) malloc(charstring_bufsiz))) - fatal_error("out of memory"); - } - - charstring_bp = charstring_buf; - cr = 4330; - for (i = 0; i < lenIV; i++) - *charstring_bp++ = cencrypt((byte) 0); -} - -/* This function encrypts and buffers a single byte of charstring data. */ - -static void charstring_byte(int v) -{ - byte b = (byte)(v & 0xff); - if (charstring_bp - charstring_buf == charstring_bufsiz) { - charstring_bufsiz *= 2; - if (!(charstring_buf = (byte *) realloc(charstring_buf, charstring_bufsiz))) - fatal_error("out of memory"); - charstring_bp = charstring_buf + charstring_bufsiz / 2; - } - *charstring_bp++ = cencrypt(b); -} - -/* This function outputs buffered, encrypted charstring data through possible - eexec encryption. */ - -static void charstring_end(void) -{ - byte *bp; - - sprintf(line, "%d ", (int) (charstring_bp - charstring_buf)); - eexec_string(line); - sprintf(line, "%s ", cs_start); - eexec_string(line); - for (bp = charstring_buf; bp < charstring_bp; bp++) - eexec_byte(*bp); -} - -/* This function generates the charstring representation of an integer. */ - -static void charstring_int(int num) -{ - int x; - - if (num >= -107 && num <= 107) { - charstring_byte(num + 139); - } else if (num >= 108 && num <= 1131) { - x = num - 108; - charstring_byte(x / 256 + 247); - charstring_byte(x % 256); - } else if (num >= -1131 && num <= -108) { - x = abs(num) - 108; - charstring_byte(x / 256 + 251); - charstring_byte(x % 256); - } else if (num >= (-2147483647-1) && num <= 2147483647) { - charstring_byte(255); - charstring_byte(num >> 24); - charstring_byte(num >> 16); - charstring_byte(num >> 8); - charstring_byte(num); - } else { - error("can't format huge number `%d'", num); - /* output 0 instead */ - charstring_byte(139); - } -} - -/* This function returns one charstring token. It ignores comments. */ - -static void get_charstring_token(void) -{ - int c = getc(ifp); - while (isspace(c)) - c = getc(ifp); - - if (c == '%') { - while (c != EOF && c != '\r' && c != '\n') - c = getc(ifp); - get_charstring_token(); - - } else if (c == '}') { - line[0] = '}'; - line[1] = 0; - - } else { - char *p = line; - while (p < line + LINESIZE) { - *p++ = c; - c = getc(ifp); - if (c == EOF || isspace(c) || c == '%' || c == '}') { - ungetc(c, ifp); - break; - } - } - *p = 0; - } -} - - -/* This function parses an entire charstring into integers and commands, - outputting bytes through the charstring buffer. */ - -static void parse_charstring(void) -{ - struct command *cp; - - charstring_start(); - while (!feof(ifp)) { - get_charstring_token(); - if (line[0] == '}') - break; - if (is_integer(line)) { - charstring_int(atoi(line)); - } else { - int one; - int two; - int ok = 0; - - cp = (struct command *) - bsearch((void *) line, (void *) command_table, - sizeof(command_table) / sizeof(struct command), - sizeof(struct command), - command_compare); - - if (cp) { - one = cp->one; - two = cp->two; - ok = 1; - - } else if (strncmp(line, "escape_", 7) == 0) { - /* Parse the `escape' keyword requested by Lee Chun-Yu and Werner - Lemberg */ - one = 12; - if (sscanf(line + 7, "%d", &two) == 1) - ok = 1; - - } else if (strncmp(line, "UNKNOWN_", 8) == 0) { - /* Allow unanticipated UNKNOWN commands. */ - one = 12; - if (sscanf(line + 8, "12_%d", &two) == 1) - ok = 1; - else if (sscanf(line + 8, "%d", &one) == 1) { - two = -1; - ok = 1; - } - } - - if (!ok) - error("unknown charstring command `%s'", line); - else if (one < 0 || one > 255) - error("bad charstring command number `%d'", one); - else if (two > 255) - error("bad charstring command number `%d'", two); - else if (two < 0) - charstring_byte(one); - else { - charstring_byte(one); - charstring_byte(two); - } - } - } - charstring_end(); -} - - -/***** - * Command line - **/ - -#define BLOCK_LEN_OPT 300 -#define OUTPUT_OPT 301 -#define VERSION_OPT 302 -#define HELP_OPT 303 -#define PFB_OPT 304 -#define PFA_OPT 305 - -static Clp_Option options[] = { - { "block-length", 'l', BLOCK_LEN_OPT, Clp_ValInt, 0 }, - { "help", 0, HELP_OPT, 0, 0 }, - { "line-length", 0, BLOCK_LEN_OPT, Clp_ValInt, 0 }, - { "output", 'o', OUTPUT_OPT, Clp_ValString, 0 }, - { "pfa", 'a', PFA_OPT, 0, 0 }, - { "pfb", 'b', PFB_OPT, 0, 0 }, - { "version", 0, VERSION_OPT, 0, 0 }, -}; -static const char *program_name; - -void -fatal_error(const char *message, ...) -{ - va_list val; - va_start(val, message); - fprintf(stderr, "%s: ", program_name); - vfprintf(stderr, message, val); - putc('\n', stderr); - va_end(val); - exit(1); -} - -void -error(const char *message, ...) -{ - va_list val; - va_start(val, message); - fprintf(stderr, "%s: ", program_name); - vfprintf(stderr, message, val); - putc('\n', stderr); - va_end(val); -} - -static void -short_usage(void) -{ - fprintf(stderr, "Usage: %s [OPTION]... [INPUT [OUTPUT]]\n\ -Try `%s --help' for more information.\n", - program_name, program_name); -} - -static void -usage(void) -{ - printf("\ -`T1asm' translates a human-readable version of a PostScript Type 1 font into\n\ -standard PFB or PFA format. The result is written to the standard output\n\ -unless an OUTPUT file is given.\n\ -\n\ -Usage: %s [OPTION]... [INPUT [OUTPUT]]\n\ -\n\ -Options:\n\ - -a, --pfa Output font in ASCII (PFA) format.\n\ - -b, --pfb Output font in binary (PFB) format. This is\n\ - the default.\n\ - -l, --block-length NUM Set max block length for PFB output.\n\ - -l, --line-length NUM Set max encrypted line length for PFA output.\n\ - -o, --output=FILE Write output to FILE.\n\ - -h, --help Print this message and exit.\n\ - --version Print version number and warranty and exit.\n\ -\n\ -Report bugs to <ekohler@gmail.com>.\n", program_name); -} - -#ifdef __cplusplus -} -#endif - - -int main(int argc, char *argv[]) -{ - char *p, *q; - - Clp_Parser *clp = - Clp_NewParser(argc, (const char * const *)argv, sizeof(options) / sizeof(options[0]), options); - program_name = Clp_ProgramName(clp); - - /* interpret command line arguments using CLP */ - while (1) { - int opt = Clp_Next(clp); - switch (opt) { - - case BLOCK_LEN_OPT: - blocklen = clp->val.i; - break; - - output_file: - case OUTPUT_OPT: - if (ofp) - fatal_error("output file already specified"); - if (strcmp(clp->vstr, "-") == 0) - ofp = stdout; - else if (!(ofp = fopen(clp->vstr, "w"))) - fatal_error("%s: %s", clp->vstr, strerror(errno)); - break; - - case PFB_OPT: - pfb = 1; - break; - - case PFA_OPT: - pfb = 0; - break; - - case HELP_OPT: - usage(); - exit(0); - break; - - case VERSION_OPT: - printf("t1asm (LCDF t1utils) %s\n", VERSION); - printf("Copyright (C) 1992-2017 I. Lee Hetherington, Eddie Kohler et al.\n\ -This is free software; see the source for copying conditions.\n\ -There is NO warranty, not even for merchantability or fitness for a\n\ -particular purpose.\n"); - exit(0); - break; - - case Clp_NotOption: - if (ifp && ofp) - fatal_error("too many arguments"); - else if (ifp) - goto output_file; - if (strcmp(clp->vstr, "-") == 0) - ifp = stdin; - else if (!(ifp = fopen(clp->vstr, "r"))) - fatal_error("%s: %s", clp->vstr, strerror(errno)); - break; - - case Clp_Done: - goto done; - - case Clp_BadOption: - short_usage(); - exit(1); - break; - - } - } - - done: - if (!pfb) { - if (blocklen == -1) - blocklen = 64; - else if (blocklen < 8) { - blocklen = 8; - error("warning: line length raised to %d", blocklen); - } else if (blocklen > 1024) { - blocklen = 1024; - error("warning: line length lowered to %d", blocklen); - } - } - - if (!ifp) ifp = stdin; - if (!ofp) ofp = stdout; - - if (pfb) - init_pfb_writer(&w, blocklen, ofp); - -#if defined(_MSDOS) || defined(_WIN32) - /* If we are processing a PFB (binary) output */ - /* file, we must set its file mode to binary. */ - _setmode(_fileno(ofp), _O_BINARY); -#endif - - /* Finally, we loop until no more input. Some special things to look for are - the `currentfile eexec' line, the beginning of the `/Subrs' or - `/CharStrings' definition, the definition of `/lenIV', and the definition - of the charstring start command which has `...string currentfile...' in - it. - - Being careful: Check with `/Subrs' and `/CharStrings' to see that a - number follows the token -- otherwise, the token is probably nested in a - subroutine a la Adobe Jenson, and we shouldn't pay attention to it. - - Bugs: Occurrence of `/Subrs 9' in a comment will fool t1asm. - - Thanks to Tom Kacvinsky <tjk@ams.org> who reported that some fonts come - without /Subrs sections and provided a patch. */ - - while (!feof(ifp) && !ferror(ifp)) { - t1utils_getline(); - - if (!ever_active) { - if (strncmp(line, "currentfile eexec", 17) == 0 && isspace((unsigned char) line[17])) { - /* Allow arbitrary whitespace after "currentfile eexec". - Thanks to Tom Kacvinsky <tjk@ams.org> for reporting this. - Note: strlen("currentfile eexec") == 17. */ - for (p = line + 18; isspace((unsigned char) *p); p++) - ; - eexec_start(p); - continue; - } else if (strncmp(line, "/lenIV", 6) == 0) { - set_lenIV(line, strlen(line)); - } else if ((p = strstr(line, "string currentfile"))) { - set_cs_start(line, strlen(line)); - } - } - - if (!active) { - if ((p = strstr(line, "/Subrs")) && isdigit((unsigned char) p[7])) - ever_active = active = 1; - else if ((p = strstr(line, "/CharStrings")) && isdigit((unsigned char) p[13])) - ever_active = active = 1; - } - if ((p = strstr(line, "currentfile closefile"))) { - /* 2/14/99 -- happy Valentine's day! -- don't look for `mark - currentfile closefile'; the `mark' might be on a different line */ - /* 1/3/2002 -- happy new year! -- Luc Devroye reports a failure with - some printers when `currentfile closefile' is followed by space */ - p += sizeof("currentfile closefile") - 1; - for (q = p; isspace((unsigned char) *q) && *q != '\n'; q++) - /* nada */; - if (q == p && !*q) - error("warning: `currentfile closefile' line too long"); - else if (q != p) { - if (*q != '\n') - error("text after `currentfile closefile' ignored"); - *p++ = '\n'; - *p++ = '\0'; - } - eexec_string(line); - break; - } - - eexec_string(line); - - /* output line data */ - if (start_charstring) { - if (!cs_start[0]) - fatal_error("couldn't find charstring start command"); - parse_charstring(); - } - } - - /* Handle remaining PostScript after the eexec section */ - if (in_eexec) - eexec_end(); - - /* There may be additional code. */ - while (!feof(ifp) && !ferror(ifp)) { - t1utils_getline(); - eexec_string(line); - } - - if (pfb) - pfb_writer_end(&w); - - /* the end! */ - if (!ever_active) - error("warning: no charstrings found in input file"); - fclose(ifp); - fclose(ofp); - return 0; -} |