diff options
Diffstat (limited to 'Build/source/utils/t1utils/t1utils-src/t1disasm.c')
-rw-r--r-- | Build/source/utils/t1utils/t1utils-src/t1disasm.c | 760 |
1 files changed, 0 insertions, 760 deletions
diff --git a/Build/source/utils/t1utils/t1utils-src/t1disasm.c b/Build/source/utils/t1utils/t1utils-src/t1disasm.c deleted file mode 100644 index 4382f6839b7..00000000000 --- a/Build/source/utils/t1utils/t1utils-src/t1disasm.c +++ /dev/null @@ -1,760 +0,0 @@ -/* t1disasm - * - * This program `disassembles' Adobe Type-1 font programs in either PFB or PFA - * format. It produces a human readable/editable pseudo-PostScript file by - * performing eexec and charstring decryption as specified in the `Adobe Type 1 - * Font Format' version 1.1 (the `black book'). There is a companion program, - * t1asm, which `assembles' such a pseudo-PostScript file into either PFB or - * PFA format. - * - * 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:55:08 ilh - * Added support for additional PostScript after the closefile command - * (ie., some fonts have {restore}if' after the cleartomark). Also, - * removed hardwired charstring start command (-| or RD) in favor of - * automatically determining it. - * - * Revision 1.3 92/06/23 10:57:53 ilh - * MSDOS porting by Kai-Uwe Herbing (herbing@netmbx.netmbx.de) - * incoporated. - * - * Revision 1.2 92/05/22 12:05:33 ilh - * Fixed bug where we were counting on sprintf to return its first - * argument---not true in ANSI C. This bug was detected by Piet - * Tutelaers (rcpt@urc.tue.nl). Also, fixed (signed) integer overflow - * error when testing high-order bit of integer for possible - * sign-extension by making comparison between unsigned integers. - * - * Revision 1.1 92/05/22 12:04:07 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 <assert.h> -#include <lcdf/clp.h> -#include "t1lib.h" -#include "t1asmhelp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef unsigned char byte; - -static FILE *ofp; -static int unknown = 0; - -/* decryption stuff */ -static const uint32_t c1 = 52845; -static const uint32_t c2 = 22719; -static uint16_t cr_default = 4330; -static uint16_t er_default = 55665; - -static int error_count = 0; - - -/* Subroutine to output strings. */ - -static void -output(const char *string) -{ - fprintf(ofp, "%s", string); -} - -/* Subroutine to neatly format output of charstring tokens. If token = "\n", - then a newline is output. If at start of line (start == 1), prefix token - with tab, otherwise a space. */ - -static void -output_token(const char *token) -{ - static int start = 1; - if (strcmp(token, "\n") == 0) { - fprintf(ofp, "\n"); - start = 1; - } else { - fprintf(ofp, "%s%s", start ? "\t" : " ", token); - start = 0; - } -} - -/* Subroutine to decrypt and ASCII-ify tokens in charstring data. The - charstring decryption machinery is fired up, skipping the first lenIV - bytes, and the decrypted tokens are expanded into human-readable form. */ - -static void -decrypt_charstring(unsigned char *line, int len) -{ - int i; - int32_t val; - char buf[20]; - - /* decrypt charstring */ - if (lenIV >= 0) { - /* only decrypt if lenIV >= 0 -- negative lenIV means unencrypted - charstring. Thanks to Tom Kacvinsky <tjk@ams.org> */ - uint16_t cr = cr_default; - byte plain; - for (i = 0; i < len; i++) { - byte cipher = line[i]; - plain = (byte)(cipher ^ (cr >> 8)); - cr = (uint16_t)((cipher + cr) * c1 + c2); - line[i] = plain; - } - line += lenIV; - len -= lenIV; - } - - /* handle each charstring command */ - for (i = 0; i < len; i++) { - byte b = line[i]; - - if (b >= 32) { - if (b >= 32 && b <= 246) - val = b - 139; - else if (b >= 247 && b <= 250) { - i++; - val = (b - 247)*256 + 108 + line[i]; - } else if (b >= 251 && b <= 254) { - i++; - val = -(b - 251)*256 - 108 - line[i]; - } else { - uint32_t uval; - uval = (uint32_t) line[i+1] << 24; - uval |= (uint32_t) line[i+2] << 16; - uval |= (uint32_t) line[i+3] << 8; - uval |= (uint32_t) line[i+4] << 0; - /* in case an int32 is larger than four bytes---sign extend */ -#if INT_MAX > 0x7FFFFFFFUL - if (uval & 0x80000000U) - uval |= ~0x7FFFFFFFU; -#endif - val = (int32_t) uval; - i += 4; - } - sprintf(buf, "%d", val); - output_token(buf); - - } else { - switch (b) { - case 0: output_token("error"); break; /* special */ - case 1: output_token("hstem"); break; - case 3: output_token("vstem"); break; - case 4: output_token("vmoveto"); break; - case 5: output_token("rlineto"); break; - case 6: output_token("hlineto"); break; - case 7: output_token("vlineto"); break; - case 8: output_token("rrcurveto"); break; - case 9: output_token("closepath"); break; /* Type 1 ONLY */ - case 10: output_token("callsubr"); break; - case 11: output_token("return"); break; - case 13: output_token("hsbw"); break; /* Type 1 ONLY */ - case 14: output_token("endchar"); break; - case 16: output_token("blend"); break; /* Type 2 */ - case 18: output_token("hstemhm"); break; /* Type 2 */ - case 19: output_token("hintmask"); break; /* Type 2 */ - case 20: output_token("cntrmask"); break; /* Type 2 */ - case 21: output_token("rmoveto"); break; - case 22: output_token("hmoveto"); break; - case 23: output_token("vstemhm"); break; /* Type 2 */ - case 24: output_token("rcurveline"); break; /* Type 2 */ - case 25: output_token("rlinecurve"); break; /* Type 2 */ - case 26: output_token("vvcurveto"); break; /* Type 2 */ - case 27: output_token("hhcurveto"); break; /* Type 2 */ - case 28: { /* Type 2 */ - /* short integer */ - val = (line[i+1] & 0xff) << 8; - val |= (line[i+2] & 0xff); - i += 2; - if (val & 0x8000) - val |= ~0x7FFF; - sprintf(buf, "%d", val); - output_token(buf); - } - case 29: output_token("callgsubr"); break; /* Type 2 */ - case 30: output_token("vhcurveto"); break; - case 31: output_token("hvcurveto"); break; - case 12: - i++; - b = line[i]; - switch (b) { - case 0: output_token("dotsection"); break; /* Type 1 ONLY */ - case 1: output_token("vstem3"); break; /* Type 1 ONLY */ - case 2: output_token("hstem3"); break; /* Type 1 ONLY */ - case 3: output_token("and"); break; /* Type 2 */ - case 4: output_token("or"); break; /* Type 2 */ - case 5: output_token("not"); break; /* Type 2 */ - case 6: output_token("seac"); break; /* Type 1 ONLY */ - case 7: output_token("sbw"); break; /* Type 1 ONLY */ - case 8: output_token("store"); break; /* Type 2 */ - case 9: output_token("abs"); break; /* Type 2 */ - case 10: output_token("add"); break; /* Type 2 */ - case 11: output_token("sub"); break; /* Type 2 */ - case 12: output_token("div"); break; - case 13: output_token("load"); break; /* Type 2 */ - case 14: output_token("neg"); break; /* Type 2 */ - case 15: output_token("eq"); break; /* Type 2 */ - case 16: output_token("callothersubr"); break; /* Type 1 ONLY */ - case 17: output_token("pop"); break; /* Type 1 ONLY */ - case 18: output_token("drop"); break; /* Type 2 */ - case 20: output_token("put"); break; /* Type 2 */ - case 21: output_token("get"); break; /* Type 2 */ - case 22: output_token("ifelse"); break; /* Type 2 */ - case 23: output_token("random"); break; /* Type 2 */ - case 24: output_token("mul"); break; /* Type 2 */ - case 26: output_token("sqrt"); break; /* Type 2 */ - case 27: output_token("dup"); break; /* Type 2 */ - case 28: output_token("exch"); break; /* Type 2 */ - case 29: output_token("index"); break; /* Type 2 */ - case 30: output_token("roll"); break; /* Type 2 */ - case 33: output_token("setcurrentpoint"); break;/* Type 1 ONLY */ - case 34: output_token("hflex"); break; /* Type 2 */ - case 35: output_token("flex"); break; /* Type 2 */ - case 36: output_token("hflex1"); break; /* Type 2 */ - case 37: output_token("flex1"); break; /* Type 2 */ - default: - sprintf(buf, "escape_%d", b); - unknown++; - output_token(buf); - break; - } - break; - default: - sprintf(buf, "UNKNOWN_%d", b); - unknown++; - output_token(buf); - break; - } - output_token("\n"); - } - } - if (i > len) { - output("\terror\n"); - error("disassembly error: charstring too short"); - } -} - - -/* Disassembly font_reader functions */ - -static int in_eexec = 0; -static unsigned char *save = 0; -static int save_len = 0; -static int save_cap = 0; - -static void -append_save(const unsigned char *line, int len) -{ - if (line == save) { - assert(len <= save_cap); - save_len = len; - return; - } - if (save_len + len >= save_cap) { - unsigned char *new_save; - if (!save_cap) save_cap = 1024; - while (save_len + len >= save_cap) save_cap *= 2; - new_save = (unsigned char *)malloc(save_cap); - if (!new_save) - fatal_error("out of memory"); - memcpy(new_save, save, save_len); - free(save); - save = new_save; - } - memcpy(save + save_len, line, len); - save_len += len; -} - - -static unsigned char* -check_eexec_charstrings_begin(unsigned char* line, int line_len) -{ - unsigned char* line_end = line + line_len; - line = memmem(line, line_len, "/CharStrings ", 13); - if (!line) - return 0; - line += 13; - while (line < line_end && isspace(*line)) - ++line; - if (line == line_end || !isdigit(*line)) - return 0; - while (line < line_end && isdigit(*line)) - ++line; - if (line == line_end || !isspace(*line)) - return 0; - while (line < line_end && isspace(*line)) - ++line; - if (line_end - line < 14 || memcmp(line, "dict dup begin", 14) != 0) - return 0; - line += 14; - while (line < line_end && isspace(*line)) - ++line; - if (line == line_end || *line != '/') - return 0; - return line; -} - - -/* returns 1 if next \n should be deleted */ - -static int -eexec_line(unsigned char *line, int line_len) -{ - int cs_start_len = strlen(cs_start); - int pos; - int first_space; - int digits; - int cut_newline = 0; - - /* append this data to the end of `save' if necessary */ - if (save_len) { - append_save(line, line_len); - line = save; - line_len = save_len; - save_len = 0; - } - - if (!line_len) - return 0; - - /* Look for charstring start */ - - /* skip first word */ - for (pos = 0; pos < line_len && isspace(line[pos]); pos++) - ; - while (pos < line_len && !isspace(line[pos])) - pos++; - if (pos >= line_len) - goto not_charstring; - - /* skip spaces */ - first_space = pos; - while (pos < line_len && isspace(line[pos])) - pos++; - if (pos >= line_len || !isdigit(line[pos])) - goto not_charstring; - - /* skip number */ - digits = pos; - while (pos < line_len && isdigit(line[pos])) - pos++; - - /* check for subr (another number) */ - if (pos < line_len - 1 && isspace(line[pos]) && isdigit(line[pos+1])) { - first_space = pos; - digits = pos + 1; - for (pos = digits; pos < line_len && isdigit(line[pos]); pos++) - ; - } - - /* check for charstring start */ - if (pos + 2 + cs_start_len < line_len - && pos > digits - && line[pos] == ' ' - && strncmp((const char *)(line + pos + 1), cs_start, cs_start_len) == 0 - && line[pos + 1 + cs_start_len] == ' ') { - /* check if charstring is long enough */ - int cs_len = atoi((const char *)(line + digits)); - if (pos + 2 + cs_start_len + cs_len < line_len) { - /* long enough! */ - if (line[line_len - 1] == '\r') { - line[line_len - 1] = '\n'; - cut_newline = 1; - } - fprintf(ofp, "%.*s {\n", first_space, line); - decrypt_charstring(line + pos + 2 + cs_start_len, cs_len); - pos += 2 + cs_start_len + cs_len; - fprintf(ofp, "\t}%.*s", line_len - pos, line + pos); - return cut_newline; - } else { - /* not long enough! */ - append_save(line, line_len); - return 0; - } - } - - /* otherwise, just output the line */ - not_charstring: - /* 6.Oct.2003 - Werner Lemberg reports a stupid Omega font that behaves - badly: a charstring definition follows "/Charstrings ... begin", ON THE - SAME LINE. */ - { - unsigned char* csbegin = check_eexec_charstrings_begin(line, line_len); - if (csbegin) { - int len = csbegin - line; - fprintf(ofp, "%.*s\n", len, line); - return eexec_line(csbegin, line_len - len); - } - } - - if (line[line_len - 1] == '\r') { - line[line_len - 1] = '\n'; - cut_newline = 1; - } - set_lenIV((char*) line, line_len); - set_cs_start((char*) line, line_len); - fprintf(ofp, "%.*s", line_len, line); - - /* look for `currentfile closefile' to see if we should stop decrypting */ - if (memmem(line, line_len, "currentfile closefile", 21) != 0) - in_eexec = -1; - - return cut_newline; -} - -static int -all_zeroes(const char *string) -{ - if (*string != '0') - return 0; - while (*string == '0') - string++; - return *string == '\0' || *string == '\n'; -} - -static void -disasm_output_ascii(char *line, int len) -{ - int was_in_eexec = in_eexec; - (void) len; /* avoid warning */ - in_eexec = 0; - - /* if we came from a binary section, we need to process that too */ - if (was_in_eexec > 0) { - unsigned char zero = 0; - eexec_line(&zero, 0); - } - - /* if we just came from the "ASCII part" of an eexec section, we need to - process the saved lines */ - if (was_in_eexec < 0) { - int i = 0; - int save_char = 0; /* note: save[] is unsigned char * */ - - while (i < save_len) { - /* grab a line */ - int start = i; - while (i < save_len && save[i] != '\r' && save[i] != '\n') - i++; - if (i < save_len) { - if (i < save_len - 1 && save[i] == '\r' && save[i+1] == '\n') - save_char = -1; - else - save_char = save[i+1]; - save[i] = '\n'; - save[i+1] = 0; - } else - save[i] = 0; - - /* output it */ - disasm_output_ascii((char *)(save + start), -1); - - /* repair damage */ - if (i < save_len) { - if (save_char >= 0) { - save[i+1] = save_char; - i++; - } else - i += 2; - } - } - save_len = 0; - } - - if (!all_zeroes(line)) - output(line); -} - -/* collect until '\n' or end of binary section */ - -static void -disasm_output_binary(unsigned char *data, int len) -{ - static int ignore_newline; - static uint16_t er; - - byte plain; - int i; - - /* in the ASCII portion of a binary section, just save this data */ - if (in_eexec < 0) { - append_save(data, len); - return; - } - - /* eexec initialization */ - if (in_eexec == 0) { - er = er_default; - ignore_newline = 0; - in_eexec = 0; - } - if (in_eexec < 4) { - for (i = 0; i < len && in_eexec < 4; i++, in_eexec++) { - byte cipher = data[i]; - plain = (byte)(cipher ^ (er >> 8)); - er = (uint16_t)((cipher + er) * c1 + c2); - data[i] = plain; - } - data += i; - len -= i; - } - - /* now make lines: collect until '\n' or '\r' and pass them off to - eexec_line. */ - i = 0; - while (in_eexec > 0) { - int start = i; - - for (; i < len; i++) { - byte cipher = data[i]; - plain = (byte)(cipher ^ (er >> 8)); - er = (uint16_t)((cipher + er) * c1 + c2); - data[i] = plain; - if (plain == '\r' || plain == '\n') - break; - } - - if (ignore_newline && start < i && data[start] == '\n') { - ignore_newline = 0; - continue; - } - - if (i >= len) { - if (start < len) - append_save(data + start, i - start); - break; - } - - i++; - ignore_newline = eexec_line(data + start, i - start); - } - - /* if in_eexec < 0, we have some plaintext lines sitting around in a binary - section of the PFB. save them for later */ - if (in_eexec < 0 && i < len) - append_save(data + i, len - i); -} - -static void -disasm_output_end(void) -{ - /* take care of leftover saved data */ - static char crap[1] = ""; - disasm_output_ascii(crap, 0); -} - - -/***** - * Command line - **/ - -#define OUTPUT_OPT 301 -#define VERSION_OPT 302 -#define HELP_OPT 303 - -static Clp_Option options[] = { - { "help", 0, HELP_OPT, 0, 0 }, - { "output", 'o', OUTPUT_OPT, Clp_ValString, 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); - fputc('\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); - fputc('\n', stderr); - error_count++; - va_end(val); -} - -static void -short_usage(void) -{ - fprintf(stderr, "Usage: %s [INPUT [OUTPUT]]\n\ -Try `%s --help' for more information.\n", - program_name, program_name); -} - -static void -usage(void) -{ - printf("\ -`T1disasm' translates a PostScript Type 1 font in PFB or PFA format into a\n\ -human-readable, human-editable form. The result is written to the standard\n\ -output unless an OUTPUT file is given.\n\ -\n\ -Usage: %s [OPTION]... [INPUT [OUTPUT]]\n\ -\n\ -Options:\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[]) -{ - struct font_reader fr; - int c; - FILE *ifp = 0; - const char *ifp_filename = "<stdin>"; - - 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) { - - output_file: - case OUTPUT_OPT: - if (ofp) - fatal_error("output file already specified"); - if (strcmp(clp->vstr, "-") == 0) - ofp = stdout; - else { - ofp = fopen(clp->vstr, "w"); - if (!ofp) fatal_error("%s: %s", clp->vstr, strerror(errno)); - } - break; - - case HELP_OPT: - usage(); - exit(0); - break; - - case VERSION_OPT: - printf("t1disasm (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 { - ifp_filename = clp->vstr; - ifp = fopen(clp->vstr, "rb"); - if (!ifp) fatal_error("%s: %s", clp->vstr, strerror(errno)); - } - break; - - case Clp_Done: - goto done; - - case Clp_BadOption: - short_usage(); - exit(1); - break; - - } - } - - done: - if (!ifp) ifp = stdin; - if (!ofp) ofp = stdout; - -#if defined(_MSDOS) || defined(_WIN32) - /* As we might be processing a PFB (binary) input file, we must set its file - mode to binary. */ - _setmode(_fileno(ifp), _O_BINARY); - _setmode(_fileno(ofp), _O_BINARY); -#endif - - /* prepare font reader */ - fr.output_ascii = disasm_output_ascii; - fr.output_binary = disasm_output_binary; - fr.output_end = disasm_output_end; - - /* peek at first byte to see if it is the PFB marker 0x80 */ - c = getc(ifp); - ungetc(c, ifp); - - /* do the file */ - if (c == PFB_MARKER) - process_pfb(ifp, ifp_filename, &fr); - else if (c == '%') - process_pfa(ifp, ifp_filename, &fr); - else - fatal_error("%s does not start with font marker (`%%' or 0x80)", ifp_filename); - - fclose(ifp); - fclose(ofp); - - if (unknown) - error((unknown > 1 - ? "encountered %d unknown charstring commands" - : "encountered %d unknown charstring command"), - unknown); - - return (error_count ? 1 : 0); -} |