diff options
author | Peter Breitenlohner <peb@mppmu.mpg.de> | 2010-05-10 09:07:22 +0000 |
---|---|---|
committer | Peter Breitenlohner <peb@mppmu.mpg.de> | 2010-05-10 09:07:22 +0000 |
commit | 754df1717eab9c3d5063f4017635939418458ddb (patch) | |
tree | 31b094abe54f58db13be56d5e81da95301165850 /Build/source/utils | |
parent | 1d5494267ca6f31a1055cc56571b714ae7f68b05 (diff) |
t1utils 1.35
git-svn-id: svn://tug.org/texlive/trunk@18183 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils')
31 files changed, 9044 insertions, 15 deletions
diff --git a/Build/source/utils/README b/Build/source/utils/README index 70414c3b236..b845756e0e7 100644 --- a/Build/source/utils/README +++ b/Build/source/utils/README @@ -22,7 +22,7 @@ psutils p17 - checked 25nov06 (Fabrice made small modifications for Windows, it seems) http://www.ctan.org/support/psutils/ -t1utils 1.34 - checked 2mar08 (needs 1.35) +t1utils 1.35 - checked 10may10 http://www.lcdf.org/type/ tpic2pdftex 1.97 - checked 9may10 diff --git a/Build/source/utils/t1utils/configure b/Build/source/utils/t1utils/configure index 61b4c4db9d6..7336860e310 100755 --- a/Build/source/utils/t1utils/configure +++ b/Build/source/utils/t1utils/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.65 for t1utils for TeX Live 1.34. +# Generated by GNU Autoconf 2.65 for t1utils for TeX Live 1.35. # # Report bugs to <tex-k@tug.org>. # @@ -552,12 +552,12 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='t1utils for TeX Live' PACKAGE_TARNAME='t1utils-for-tex-live' -PACKAGE_VERSION='1.34' -PACKAGE_STRING='t1utils for TeX Live 1.34' +PACKAGE_VERSION='1.35' +PACKAGE_STRING='t1utils for TeX Live 1.35' PACKAGE_BUGREPORT='tex-k@tug.org' PACKAGE_URL='' -ac_unique_file="t1utils-1.34/t1ascii.c" +ac_unique_file="t1utils-1.35/t1ascii.c" # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> @@ -1240,7 +1240,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures t1utils for TeX Live 1.34 to adapt to many kinds of systems. +\`configure' configures t1utils for TeX Live 1.35 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1307,7 +1307,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of t1utils for TeX Live 1.34:";; + short | recursive ) echo "Configuration of t1utils for TeX Live 1.35:";; esac cat <<\_ACEOF @@ -1399,7 +1399,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -t1utils for TeX Live configure 1.34 +t1utils for TeX Live configure 1.35 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. @@ -2002,7 +2002,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by t1utils for TeX Live $as_me 1.34, which was +It was created by t1utils for TeX Live $as_me 1.35, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ @@ -2814,7 +2814,7 @@ fi # Define the identity of the package. PACKAGE='t1utils-for-tex-live' - VERSION='1.34' + VERSION='1.35' cat >>confdefs.h <<_ACEOF @@ -4656,7 +4656,7 @@ ac_config_headers="$ac_config_headers config.h" -T1UTILS_TREE=t1utils-1.34 +T1UTILS_TREE=t1utils-1.35 @@ -5187,7 +5187,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by t1utils for TeX Live $as_me 1.34, which was +This file was extended by t1utils for TeX Live $as_me 1.35, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5253,7 +5253,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -t1utils for TeX Live config.status 1.34 +t1utils for TeX Live config.status 1.35 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" diff --git a/Build/source/utils/t1utils/configure.ac b/Build/source/utils/t1utils/configure.ac index 31301cf0382..ff5a5a54e32 100644 --- a/Build/source/utils/t1utils/configure.ac +++ b/Build/source/utils/t1utils/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. dnl -dnl Copyright (C) 2009 Peter Breitenlohner <tex-live@tug.org> +dnl Copyright (C) 2009, 2010 Peter Breitenlohner <tex-live@tug.org> dnl dnl This file is free software; the copyright holder dnl gives unlimited permission to copy and/or distribute it, @@ -12,7 +12,7 @@ dnl Adapted for TeX Live from t1utils-1.34/configure.in dnl dnl ********************************************************************* dnl -m4_define([t1utils_version], [1.34])[]dnl using unmodified t1utils source tree +m4_define([t1utils_version], [1.35])[]dnl using unmodified t1utils source tree AC_INIT([t1utils for TeX Live], t1utils_version, [tex-k@tug.org]) AC_PREREQ([2.65]) AC_CONFIG_SRCDIR([t1utils-]t1utils_version[/t1ascii.c]) diff --git a/Build/source/utils/t1utils/t1utils-1.35-PATCHES/ChangeLog b/Build/source/utils/t1utils/t1utils-1.35-PATCHES/ChangeLog new file mode 100644 index 00000000000..682e8c32f38 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35-PATCHES/ChangeLog @@ -0,0 +1,19 @@ +2010-05-10 Peter Breitenlohner <peb@mppmu.mpg.de> + + Adapt to t1utils-1.35. + * patch-01-getline (removed): Now handled in original sources. + * patch-02-static, patch-03-warnings: Adapted. + +2009-08-23 Peter Breitenlohner <peb@mppmu.mpg.de> + + * patch-03-warnings (new): Avoid more compiler warnings. + +2009-08-19 Peter Breitenlohner <peb@mppmu.mpg.de> + + * patch-02-static (new): Avoid warnings when compiling with + 'gcc --Wmissing-prototypes'. + +2009-06-12 Francois Charette <firmicus@ankabut.net> + + * patch-01-getline (new): Avoid getline name conflict. + diff --git a/Build/source/utils/t1utils/t1utils-1.35-PATCHES/TL-Changes b/Build/source/utils/t1utils/t1utils-1.35-PATCHES/TL-Changes new file mode 100644 index 00000000000..8316545e927 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35-PATCHES/TL-Changes @@ -0,0 +1,17 @@ +Changes applied to the t1utils-1.35 tree as obtained from: + http://www.lcdf.org/type/ + +Removed: + Makefile.in + aclocal.m4 + config.guess + config.sub + configure + depcomp + install-sh + missing + mkinstalldirs + +Moved this file to ../: + strerror.c + diff --git a/Build/source/utils/t1utils/t1utils-1.35-PATCHES/patch-02-static b/Build/source/utils/t1utils/t1utils-1.35-PATCHES/patch-02-static new file mode 100644 index 00000000000..db97652ff50 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35-PATCHES/patch-02-static @@ -0,0 +1,185 @@ + Declare all functions used in only one file as static. + +diff -ur t1utils-1.35.orig/clp.c t1utils-1.35/clp.c +--- t1utils-1.35.orig/clp.c 2008-12-07 02:17:20.000000000 +0100 ++++ t1utils-1.35/clp.c 2010-05-10 10:06:31.835158049 +0200 +@@ -612,7 +612,7 @@ + return old_utf8; + } + +-int ++static int + Clp_OptionChar(Clp_Parser *clp, int c) + { + Clp_Internal *cli = clp->internal; +@@ -1184,7 +1184,7 @@ + } + + +-int ++static int + finish_string_list(Clp_Parser *clp, int val_type, int flags, + Clp_Option *items, int nitems, int itemscap) + { +diff -ur t1utils-1.35.orig/t1ascii.c t1utils-1.35/t1ascii.c +--- t1utils-1.35.orig/t1ascii.c 2008-12-07 02:17:20.000000000 +0100 ++++ t1utils-1.35/t1ascii.c 2010-05-10 09:55:47.000000000 +0200 +@@ -100,7 +100,7 @@ + putc('\n', stderr); + } + +-void ++static void + short_usage(void) + { + fprintf(stderr, "Usage: %s [OPTION]... [INPUT [OUTPUT]]\n\ +@@ -108,7 +108,7 @@ + program_name, program_name); + } + +-void ++static void + usage(void) + { + printf("\ +diff -ur t1utils-1.35.orig/t1asm.c t1utils-1.35/t1asm.c +--- t1utils-1.35.orig/t1asm.c 2009-10-18 19:08:25.000000000 +0200 ++++ t1utils-1.35/t1asm.c 2010-05-10 09:55:47.000000000 +0200 +@@ -572,7 +572,7 @@ + putc('\n', stderr); + } + +-void ++static void + short_usage(void) + { + fprintf(stderr, "Usage: %s [OPTION]... [INPUT [OUTPUT]]\n\ +@@ -580,7 +580,7 @@ + program_name, program_name); + } + +-void ++static void + usage(void) + { + printf("\ +diff -ur t1utils-1.35.orig/t1binary.c t1utils-1.35/t1binary.c +--- t1utils-1.35.orig/t1binary.c 2008-12-07 02:17:20.000000000 +0100 ++++ t1utils-1.35/t1binary.c 2010-05-10 09:55:47.000000000 +0200 +@@ -132,7 +132,7 @@ + } + + +-void ++static void + short_usage(void) + { + fprintf(stderr, "Usage: %s [OPTION]... [INPUT [OUTPUT]]\n\ +@@ -141,7 +141,7 @@ + } + + +-void ++static void + usage(void) + { + printf("\ +diff -ur t1utils-1.35.orig/t1disasm.c t1utils-1.35/t1disasm.c +--- t1utils-1.35.orig/t1disasm.c 2008-12-07 02:17:20.000000000 +0100 ++++ t1utils-1.35/t1disasm.c 2010-05-10 09:55:47.000000000 +0200 +@@ -640,7 +640,7 @@ + error_count++; + } + +-void ++static void + short_usage(void) + { + fprintf(stderr, "Usage: %s [INPUT [OUTPUT]]\n\ +@@ -648,7 +648,7 @@ + program_name, program_name); + } + +-void ++static void + usage(void) + { + printf("\ +diff -ur t1utils-1.35.orig/t1mac.c t1utils-1.35/t1mac.c +--- t1utils-1.35.orig/t1mac.c 2008-12-07 02:17:20.000000000 +0100 ++++ t1utils-1.35/t1mac.c 2010-05-10 09:55:47.000000000 +0200 +@@ -778,7 +778,7 @@ + } + + +-void ++static void + short_usage(void) + { + fprintf(stderr, "Usage: %s [OPTION]... [INPUT [OUTPUT]]\n\ +@@ -787,7 +787,7 @@ + } + + +-void ++static void + usage(void) + { + printf("\ +diff -ur t1utils-1.35.orig/t1unmac.c t1utils-1.35/t1unmac.c +--- t1utils-1.35.orig/t1unmac.c 2008-12-07 02:17:20.000000000 +0100 ++++ t1utils-1.35/t1unmac.c 2010-05-10 09:55:47.000000000 +0200 +@@ -259,7 +259,7 @@ + putc('\n', stderr); + } + +-void ++static void + short_usage(void) + { + fprintf(stderr, "Usage: %s [OPTION]... INPUT [OUTPUT]\n\ +@@ -267,7 +267,7 @@ + program_name, program_name); + } + +-void ++static void + usage(void) + { + printf("\ +@@ -388,7 +388,7 @@ + #define APPLESINGLE_MAGIC 0x00051600 + #define APPLEDOUBLE_MAGIC 0x00051607 + +-const char * ++static const char * + check_appledouble(FILE *ifp) + { + int i; +@@ -400,7 +400,7 @@ + return 0; + } + +-const char * ++static const char * + translate_binhex(FILE *f, FILE *tmpf) + { + int i, c = 0, last_char, after_x90, bits, bitpos; +@@ -486,7 +486,7 @@ + return 0; + } + +-int ++static int + check_binhex_crc(FILE *f, int offset, int length) + { + int crc = 0; +@@ -501,7 +501,7 @@ + return crc == 0; + } + +-const char * ++static const char * + check_binhex(FILE *f) + { + int fname_len, data_len, rsrc_len, off; diff --git a/Build/source/utils/t1utils/t1utils-1.35-PATCHES/patch-03-warnings b/Build/source/utils/t1utils/t1utils-1.35-PATCHES/patch-03-warnings new file mode 100644 index 00000000000..ab6c2964cae --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35-PATCHES/patch-03-warnings @@ -0,0 +1,226 @@ + Avoid compiler warnings: + ANSI C function definitions. + Declare various (param and other) strings as const. + +diff -ur t1utils-1.35.orig/clp.c t1utils-1.35/clp.c +--- t1utils-1.35.orig/clp.c 2010-05-10 10:06:31.000000000 +0200 ++++ t1utils-1.35/clp.c 2010-05-10 10:36:50.091602641 +0200 +@@ -275,7 +275,7 @@ + } + + static int +-decode_utf8(const char *s, char **cp) ++decode_utf8(const char *s, const char **cp) + { + int c; + if ((unsigned char) *s <= 0x7F) /* 1 byte: 0x000000-0x00007F */ +@@ -319,14 +319,14 @@ + /* nothing */; + } + if (cp) +- *cp = (char *) s; ++ *cp = s; + return c; + } + + static int + utf8_charlen(const char *s) + { +- char *sout; ++ const char *sout; + (void) decode_utf8(s, &sout); + return sout - s; + } +@@ -364,7 +364,7 @@ + if ((cli->long1pos || cli->long1neg) && io->ilong) { + const char *name = o->long_name + io->ilongoff; + if (cli->utf8) { +- int c = decode_utf8(name, (char **) &name); ++ int c = decode_utf8(name, &name); + if (!*name && c && c != U_REPLACEMENT) + return c; + } else if (name[0] && !name[1]) +@@ -1068,22 +1068,28 @@ + static int + parse_int(Clp_Parser *clp, const char *arg, int complain, void *user_data) + { +- char *val; ++ const char *val; ++ char *temp; + if (*arg == 0 || isspace((unsigned char) *arg) + || (user_data != 0 && *arg == '-')) +- val = (char *) arg; ++ val = arg; + else if (user_data != 0) { /* unsigned */ + #if HAVE_STRTOUL +- clp->val.u = strtoul(arg, &val, 0); ++ clp->val.u = strtoul(arg, &temp, 0); ++ val = temp; + #else + /* don't bother really trying to do it right */ + if (arg[0] == '-') +- val = (char *) arg; +- else +- clp->val.u = strtol(arg, &val, 0); ++ val = arg; ++ else { ++ clp->val.u = strtol(arg, &temp, 0); ++ val = temp; ++ } + #endif +- } else +- clp->val.i = strtol(arg, &val, 0); ++ } else { ++ clp->val.i = strtol(arg, &temp, 0); ++ val = temp; ++ } + if (*arg != 0 && *val == 0) + return 1; + else if (complain) { +@@ -1098,12 +1104,15 @@ + static int + parse_double(Clp_Parser *clp, const char *arg, int complain, void *user_data) + { +- char *val; ++ const char *val; ++ char *temp; + (void)user_data; + if (*arg == 0 || isspace((unsigned char) *arg)) +- val = (char *) arg; +- else +- clp->val.d = strtod(arg, &val); ++ val = arg; ++ else { ++ clp->val.d = strtod(arg, &temp); ++ val = temp; ++ } + if (*arg != 0 && *val == 0) + return 1; + else if (complain) +@@ -1516,7 +1525,7 @@ + { + int c; + if (clp->internal->utf8) { +- char *s; ++ const char *s; + c = decode_utf8(text, &s); + *ocharskip = s - text; + } else { +diff -ur t1utils-1.35.orig/t1ascii.c t1utils-1.35/t1ascii.c +--- t1utils-1.35.orig/t1ascii.c 2010-05-10 09:55:47.000000000 +0200 ++++ t1utils-1.35/t1ascii.c 2010-05-10 10:08:33.942078828 +0200 +@@ -172,7 +172,7 @@ + } + + static void +-pfa_output_end() ++pfa_output_end(void) + { + } + +diff -ur t1utils-1.35.orig/t1asm.c t1utils-1.35/t1asm.c +--- t1utils-1.35.orig/t1asm.c 2010-05-10 09:55:47.000000000 +0200 ++++ t1utils-1.35/t1asm.c 2010-05-10 10:08:33.942078828 +0200 +@@ -266,7 +266,7 @@ + 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() ++static int check_line_charstring(void) + { + char *p = line; + while (isspace(*p)) +@@ -280,7 +280,7 @@ + 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() ++static void t1utils_getline(void) + { + int c; + char *p = line; +@@ -367,7 +367,7 @@ + /* This function initializes charstring encryption. Note that this is called + at the beginning of every charstring. */ + +-static void charstring_start() ++static void charstring_start(void) + { + int i; + +@@ -390,7 +390,7 @@ + /* This function outputs buffered, encrypted charstring data through possible + eexec encryption. */ + +-static void charstring_end() ++static void charstring_end(void) + { + byte *bp; + +@@ -433,7 +433,7 @@ + + /* This function returns one charstring token. It ignores comments. */ + +-static void get_charstring_token() ++static void get_charstring_token(void) + { + int c = getc(ifp); + while (isspace(c)) +@@ -466,7 +466,7 @@ + /* This function parses an entire charstring into integers and commands, + outputting bytes through the charstring buffer. */ + +-static void parse_charstring() ++static void parse_charstring(void) + { + struct command *cp; + +diff -ur t1utils-1.35.orig/t1binary.c t1utils-1.35/t1binary.c +--- t1utils-1.35.orig/t1binary.c 2010-05-10 09:55:47.000000000 +0200 ++++ t1utils-1.35/t1binary.c 2010-05-10 10:08:33.942078828 +0200 +@@ -85,7 +85,7 @@ + } + + static void +-pfb_output_end() ++pfb_output_end(void) + { + pfb_writer_end(&w); + } +diff -ur t1utils-1.35.orig/t1disasm.c t1utils-1.35/t1disasm.c +--- t1utils-1.35.orig/t1disasm.c 2010-05-10 09:55:47.000000000 +0200 ++++ t1utils-1.35/t1disasm.c 2010-05-10 10:08:33.942078828 +0200 +@@ -332,11 +332,11 @@ + /* 23.Feb.2004 - use 'memstr', not strstr, because the strings input to + eexec_line aren't null terminated! Reported by Werner Lemberg. */ + +-static const unsigned char * +-oog_memstr(const unsigned char *line, int line_len, const char *pattern, int pattern_len) ++static unsigned char * ++oog_memstr(unsigned char *line, int line_len, const char *pattern, int pattern_len) + { +- const unsigned char *try; +- const unsigned char *last = line + line_len - pattern_len + 1; ++ unsigned char *try; ++ unsigned char *last = line + line_len - pattern_len + 1; + while (line < last + && (try = memchr(line, (unsigned char)*pattern, last - line))) { + if (memcmp(try, pattern, pattern_len) == 0) +@@ -432,7 +432,7 @@ + badly: a charstring definition follows "/Charstrings ... begin", ON THE + SAME LINE. */ + { +- const char *CharStrings = (const char *) ++ char *CharStrings = (char *) + oog_memstr(line, line_len, "/CharStrings ", 13); + int crap, n; + char should_be_slash = 0; +@@ -595,7 +595,7 @@ + } + + static void +-disasm_output_end() ++disasm_output_end(void) + { + /* take care of leftover saved data */ + static char crap[1] = ""; diff --git a/Build/source/utils/t1utils/t1utils-1.35/INSTALL b/Build/source/utils/t1utils/t1utils-1.35/INSTALL new file mode 100644 index 00000000000..95d84c820fb --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/INSTALL @@ -0,0 +1,176 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/Build/source/utils/t1utils/t1utils-1.35/Makefile.am b/Build/source/utils/t1utils/t1utils-1.35/Makefile.am new file mode 100644 index 00000000000..a440fc1b522 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/Makefile.am @@ -0,0 +1,49 @@ +## Process this file with automake to produce Makefile.in +AUTOMAKE_OPTIONS = foreign check-news + +bin_PROGRAMS = t1ascii t1binary t1asm t1disasm t1unmac t1mac +man_MANS = t1ascii.1 t1binary.1 t1asm.1 t1disasm.1 t1unmac.1 t1mac.1 + +t1ascii_SOURCES = include/lcdf/clp.h include/lcdf/inttypes.h \ + clp.c t1lib.h t1lib.c t1ascii.c +t1binary_SOURCES = include/lcdf/clp.h include/lcdf/inttypes.h \ + clp.c t1lib.h t1lib.c t1binary.c +t1asm_SOURCES = include/lcdf/clp.h include/lcdf/inttypes.h \ + clp.c t1lib.h t1lib.c t1asm.c +t1disasm_SOURCES = include/lcdf/clp.h include/lcdf/inttypes.h \ + clp.c t1lib.h t1lib.c t1disasm.c +t1unmac_SOURCES = include/lcdf/clp.h include/lcdf/inttypes.h \ + clp.c t1lib.h t1lib.c t1unmac.c +t1mac_SOURCES = include/lcdf/clp.h include/lcdf/inttypes.h \ + clp.c t1lib.h t1lib.c t1mac.c + +AM_CPPFLAGS = -I$(top_srcdir)/include +LDADD = @LIBOBJS@ + +EXTRA_DIST = $(man_MANS) t1utils.spec + +srclinks: + cd $(top_srcdir); test -d include/lcdf || mkdir -p include/lcdf + cd $(top_srcdir); for i in clp.h inttypes.h; do \ + ln -sf ../../../liblcdf/include/lcdf/$$i include/lcdf/$$i; done + cd $(top_srcdir); for i in clp.c strerror.c; do \ + ln -sf ../liblcdf/liblcdf/$$i $$i; done + +versionize: + perl -pi -e "s/^\\.ds V.*/.ds V $(VERSION)/;" t1ascii.1 t1binary.1 t1disasm.1 t1asm.1 t1unmac.1 t1mac.1 + perl -pi -e 's/^Version:(\s*).*/Version:$${1}$(VERSION)/; s/$(PACKAGE)-[\w.]+\.tar\.gz/$(PACKAGE)-$(VERSION).tar.gz/;' t1utils.spec + perl -pi -e 's/VERSION [\d.ab]+/VERSION $(VERSION)/;' README + +rpm: dist + buildarch=`rpm --showrc | awk '/^build arch/ { print $$4; }'` ; \ + mkdir -p /tmp/rpm-t1u/SOURCES /tmp/rpm-t1u/RPMS/$$buildarch \ + /tmp/rpm-t1u/BUILD ; \ + echo 'include: /usr/lib/rpm/rpmrc' > /tmp/rpm-t1u/rc ; \ + echo 'macrofiles: /usr/lib/rpm/macros:/tmp/rpm-t1u/macros' >> /tmp/rpm-t1u/rc ; \ + echo '%_topdir /tmp/rpm-t1u' > /tmp/rpm-t1u/macros ; \ + cp $(PACKAGE)-$(VERSION).tar.gz /tmp/rpm-t1u/SOURCES ; \ + rpmbuild --rcfile /tmp/rpm-t1u/rc -bb t1utils.spec ; \ + cp /tmp/rpm-t1u/RPMS/$$buildarch/*.rpm . + rm -rf /tmp/rpm-t1u + +.PHONY: srclinks versionize rpm diff --git a/Build/source/utils/t1utils/t1utils-1.35/NEWS b/Build/source/utils/t1utils/t1utils-1.35/NEWS new file mode 100644 index 00000000000..2e352d91c3c --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/NEWS @@ -0,0 +1,301 @@ +T1utils NEWS + +Version 1.35 22.Oct.2009 + +* Don't use "getline" as a symbol (reported by Karl Berry and + C.M. Connelly). + + +Version 1.34 1.Mar.2008 + +* Add '--enable-multiplatform' (requested by Karl Berry). + + +Version 1.33 8.Jan.2008 + +* Several minor cleanups. + + +Version 1.32 23.Feb.2004 + +* t1disasm: Avoid memory corruption bug (strings passed to eexec_line are + not null terminated). Reported by Werner Lemberg. + + +Version 1.31 8.Feb.2004 + +* All: Support fonts where the eexec-encrypted portion is binary, and the + first ciphertext byte is 0. Reported by Werner Lemberg. + + +Version 1.30 6.Jan.2004 + +* All: Support fonts, such as those in PostScript files printed by + acroread, where "currentfile eexec" is not followed by a newline. + + +Version 1.29 6.Oct.2003 + +* t1disasm: Support odd fonts where a character is defined on the + "/CharStrings" line. Reported by Werner Lemberg. + + +Version 1.28 7.Aug.2003 + +* Address build problems reported by Nelson H.F. Beebe. + + +Version 1.27 26.Mar.2003 + +* t1ascii: Add optional warning when output lines are longer than 255 + characters. Requested by Werner Lemberg <wl@gnu.org>. + + +Version 1.26 16.Apr.2002 + +* t1mac: Fix buglet (C++ comment, and temporary file left behind). Reported + by Vladimir Volovich <vvv@vsu.ru>. + + +Version 1.25 3.Jan.2002 + +* t1asm: Beware extra characters after `currentfile closefile'. Reported by + Luc Devroye <luc@cs.mcgill.ca>. + + +Version 1.24 6.Sep.2001 + +* Fixed compilation bugs on various platforms reported by Nelson H. F. + Beebe <beebe@math.utah.edu>. + + +Version 1.23 18.Jun.2001 + +* Fixed Macintosh file bugs: the MacBinary CRC was calculated incorrectly, + and extended finder flags were set to random values in BinHex output. + Reported, and patch provided, by Tom Kacvinsky <tjk@ams.org>. + + +Version 1.22 6.Mar.2001 + +* Fixed bug on processing PFA fonts with DOS line endings. The symptom was + t1binary producing strange/unusable fonts. Problem: the all-zeros line, + which signals the end of the font's binary section, was not being + recognized because of an extra '\r'. This has been a bug since version + 1.13 -- chagrin! Problem reported by Han The Thanh + <thanh@informatics.muni.cz>. + + +Version 1.21 9.Feb.2001 + +* t1ascii, t1asm, t1unmac: Raised minimum PFA line length to 8. The Adobe + spec may imply that there cannot be whitespace within the first 8 bytes + of an ASCII-encoded eexec section; it's somewhat ambiguous. Reported by + Rainer Menzner <Rainer.Menzner@neuroinformatik.ruhr-uni-bochum.de>. + + +Version 1.20 22.Jun.2000 + +* t1asm: Fixed bug where `t1asm -a' would give a `warning: line length + raised to 4' error message. Reported by Tom Kacvinsky <tjk@ams.org>. + + +Version 1.19 3.May.2000 + +* t1mac: Generated Macintosh fonts now use a custom-drawn icon set, rather + than Adobe's default. They also have a t1utils-specific creator signature + (T1UT), and their file information mentions t1utils. + +* t1mac: Added the `--filename' option. + + +Version 1.18 2.May.2000 + +* t1mac: Fixed bug where generated files appeared corrupted to Macintoshes. + Reported by Marten Thavenius <marten.thavenius@bahnhof.se>. + + +Version 1.17 27.Apr.2000 + +* Added new program, `t1mac', which translates PFA or PFB fonts into + Macintosh-style fonts. T1mac can output in MacBinary, AppleSingle, + AppleDouble, or BinHex format. Suggested by Marten Thavenius + <marten.thavenius@bahnhof.se>. + +* t1unmac: Added support for BinHex. + +* t1unmac: Fixed bugs in manual page and program options. + + +Version 1.16 25.Apr.2000 + +* t1unmac: Supports AppleSingle and AppleDouble files with the + `--applesingle/double' option. Requested by Kent Boortz + <kent@erix.ericsson.se>. + + +Version 1.15 4.Apr.2000 + +* t1ascii, t1binary, and t1disasm: Fixed bad error message. + +* t1unmac: Generates PFB fonts by default. + + +Version 1.14 25.Aug.1999 + +* t1asm: Version 1.13 produced complete crap output. My test cases were too + limited to catch this. Found by Rainer Menzner + <Rainer.Menzner@neuroinformatik.ruhr-uni-bochum.de>. + + +Version 1.13 2.Aug.1999 + +* t1disasm: Complete rewrite. It now uses t1lib.c functions; the goal is to + handle PFA and PFB fonts consistently. This has been extensively tested, + but there may be bugs. + +* t1disasm, t1asm: Fixed to support fonts with multiple Subrs and + CharStrings sections, like some old Oblique fonts. + +* PFA minimum line length raised to 4. + +* t1ascii, t1binary, t1disasm: Changes in t1lib.c to support reading binary + PFA fonts. Requested by Tom Kacvinsky <tjk@ams.org>. + + +Version 1.12 1.Aug.1999 + +* t1ascii, t1binary, t1asm, t1disasm: Support fonts with whitespace + following the "currentfile eexec" line. Embedded fonts in PostScript + generated by Acrobat Reader have this property. Reported by Tom Kacvinsky + <tjk@ams.org>. + +* t1ascii, t1asm, t1unmac: Use lowercase hex digits instead of uppercase. + +* t1unmac: Added `--line-length' option for PFA output. + + +Version 1.11 29.May.1999 + +* Bug fix in t1asm/t1disasm: if a `readhexstring' procedure was defined, we + got confused. Reported by Luc Devroye <luc@CS.McGill.CA>. + +* t1binary now has a maximum block length of 2^32 - 1. "Feature" requested + by Werner Lemberg <wl@gnu.org>. + +* t1ascii and t1binary each accept both PFA and PFB fonts. If you pass an + ASCII font (PFA) to t1ascii, it will output it mostly unchanged, and + similarly for PFB fonts and t1binary. The `-l' options will still take + effect, so you can use `t1ascii -l 60' to shorten the encrypted line + lengths of a PFA font. t1ascii also does some newline translation + (changes carriage returns to newlines). + + +Version 1.10.1 12.Apr.1999 + +* t1asm: Fixed bug when `-l' option wasn't provided. Caught by Giuseppe + Ghibò <ghibo@caesar.polito.it>. + + +Version 1.10 11.Apr.1999 + +* t1asm/t1disasm: Provide support for Type1C (Compact Font Format) font + files. These fonts have unencrypted character strings, signalled by a + negative lenIV value. Suggestion and patch thanks to Tom Kacvinsky + <tjk@ams.org>. + +* t1ascii/t1asm: Added `-l/--line-length' option to control maximum + encrypted line length. Suggestion thanks to Giuseppe Ghibò + <ghibo@caesar.polito.it>. + + +Version 1.9 14.Feb.1999 + +* t1asm/t1disasm: Be more robust on fonts that don't end in `mark + currentfile closefile'. John Vromans <JVromans@squirrel.nl> provided a + font that ended with `mark' on one line and `currentfile closefile' on + another; t1asm and t1disasm did not recognize the encrypted section of + the font had ended, and generated some garbage. + + +Version 1.8 2.Jan.1999 + +* Added some more Type 2 commands (flex, flex1, hflex, hflex1) from a + revision of the Type 2 spec. (I wouldn't have known about this except for + CurveSoft's revised t1utils package, available at + http://www.curvesoft.com. These t1utils are more up-to-date than theirs, + however.) + +* t1asm: Fixed one Type 2 command's translation (cntrmask was incorrectly + mapped to 18, not 20). + + +Version 1.7.2 11.Dec.1998 + +* Integrated patches from Jan-Jaap van der Heijden + <J.J.vanderHeijden@student.utwente.nl> to support building t1utils under + 32-bit Windows. + + +Version 1.7.1 5.Dec.1998 + +* The t1utils package now uses automake. + + +Version 1.7 27.Nov.1998 + +* t1asm: Should now work with fonts that have no /Subrs sections. Previously, + assembling such a font would silently fail; all the character definitions + would be mistaken for procedures and t1asm wouldn't translate them. Problem + noticed and fix suggested by Tom Kacvinsky <tjk@ams.org>. + +* t1disasm: Removed spurious debugging output and improved warning message + about unknown charstring commands. + +* Changed fgetc/fputc into getc/putc. + + +Version 1.6 27.Sep.1998 + +* `--help' now prints to stdout, following the GNU Coding Standards. + +* Makefiles: Added `make uninstall' target, enabled `./configure's + program name transformations, made VPATH builds possible. + + +Version 1.5.2 6.Aug.1998 + +* t1asm/t1disasm: Changed unknown charstring commands at the request of + Werner Lemberg and LEE Chun-Yu. An unknown escape in the charstring, like + 12 X, is translated to "escape_X" rather than "UNKNOWN_12_X". + + +Version 1.5.1 31.May.1998 + +* t1unmac did not actually understand the -r and -b options. Fixed. + +* t1unmac: Added better diagnostics to help you diagnose seeking problems. + + +Version 1.5 5.Mar.1998 + +* Initial release with Eddie Kohler as maintainer. + +* All: Updated to the GNU program behavior standards (long options, --help, + --version). Banners removed. Added more error messages. + +* t1binary: Removed fixed limit on line length. + +* t1binary: Supports Macintosh files, whose lines end in `\r'. + +* t1binary: Supports an odd number of hex digits in a line. + +* t1asm/t1disasm: Added support for Type 2 commands like `blend' and `add', + which also appear in some multiple master fonts like Adobe Jenson. + +* t1asm/t1disasm: Added support for unknown charstring commands. t1disasm + translates an unknown command #X to "UNKNOWN_X", and t1asm does the reverse. + +* t1asm/t1unmac: Changed default output to PFB. + +* t1unmac: Used to be called `unpost'. `t1unmac' is a much better name. diff --git a/Build/source/utils/t1utils/t1utils-1.35/README b/Build/source/utils/t1utils/t1utils-1.35/README new file mode 100644 index 00000000000..697cf10056d --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/README @@ -0,0 +1,81 @@ +T1UTILS VERSION 1.35 NOTES +========================== + + You need an ANSI C compiler, such as gcc. + + Just type `./configure', then `make'. `make install' will build and +install the utilities and their manual pages. + + `./configure' accepts the usual options. See `INSTALL' for more +details. The most commonly used option is `--prefix', which can be used +to install the utilities in a place other than /usr/local. + + Changes since version 1.2 (c) 1998-2008 Eddie Kohler, under the same +redistribution copyright as I. Lee Hetherington's. See below for I. Lee +Hetherington's original README from 1992, updated slightly for today's +t1utils. + +Eddie Kohler +ekohler@gmail.com + +#################################################################### + +t1utils is a collection of simple type-1 font manipulation programs. +Together, they allow you to convert between PFA (ASCII) and PFB (binary) +formats, disassemble PFA or PFB files into human-readable form, reassemble +them into PFA or PFB format. Additionally you can extract font resources +from a Macintosh font file (ATM/Laserwriter), or create a Macintosh Type 1 +font file from a PFA or PFB font. + +There are currently six programs: + +t1ascii converts PFB files to PFA format. + +t1binary converts PFA files to PFB format. + +t1disasm disassembles a type-1 font (PFA or PFB format) into a + raw, human-readable text form for subsequent hand + editing, tweaking, hint fixing, etc... + +t1asm assembles type-1 font into PFA or PFB format from + human-readable form produced by t1disasm. + +t1unmac extracts POST resources from a Macintosh type-1 file + (ATM/Laserwriter) into PFA or PFB format for use outside + the Macintosh environment. The Macintosh file should be + stored in MacBinary, AppleSingle, AppleDouble, or BinHex + format, or as a raw resource fork. Note that t1unmac does + not have to run on a Macintosh, but makes Macintosh type-1 + fonts available to Unix machines and PCs. + +t1mac creates a Macintosh Type 1 file from a PFA or PFB-format + Type 1 font. Writes the Macintosh file in MacBinary, + AppleSingle, AppleDouble, or BinHex format, or as a raw + resource fork. WARNING: This will not suffice to use the + new font on a Macintosh, as Macintoshes cannot read raw + Type 1 fonts. You will need to create a font suitcase + containing bitmap fonts if you do not have such a suitcase + for the font already. T1utils cannot help you do this. + +... + +Thanks to Kai-Uwe Herbing (herbing@netmbx.netmbx.de) for the MS-DOS +port (Microsoft C/C++ compiler). + +The copyright on all of the tools in t1utils looks like: + + Copyright (c) 1992 by I. Lee Hetherington, all rights + reserved. + + Permission is hereby granted to use, modify, and distribute + this program for any purpose provided this copyright notice + and the one below remain intact. + +Note that these tools should not be used to illegally copy type-1 font +programs. Typeface design is an intricate art that should be +rewarded. + +I. Lee Hetherington +ilh@lcs.mit.edu + +#################################################################### diff --git a/Build/source/utils/t1utils/t1utils-1.35/clp.c b/Build/source/utils/t1utils/t1utils-1.35/clp.c new file mode 100644 index 00000000000..ea1fd38dc84 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/clp.c @@ -0,0 +1,2341 @@ +/* -*- related-file-name: "../include/lcdf/clp.h" -*- */ +/* clp.c - Complete source code for CLP. + * This file is part of CLP, the command line parser package. + * + * Copyright (c) 1997-2008 Eddie Kohler, ekohler@gmail.com + * + * 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://www.pdos.lcs.mit.edu/click/license.html. 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 + * legally binding. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <lcdf/clp.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <assert.h> +#include <stdarg.h> +#include <ctype.h> + +/* By default, assume we have strtoul. */ +#if !defined(HAVE_STRTOUL) && !defined(HAVE_CONFIG_H) +# define HAVE_STRTOUL 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @file clp.h + * @brief Functions for parsing command line options. + * + * The CLP functions are used to parse command line arugments into options. + * It automatically handles value parsing, error messages, long options with + * minimum prefix matching, short options, and negated options. + * + * The CLP model works like this. + * + * <ol> + * <li>The user declares an array of Clp_Option structures that define the + * options their program accepts.</li> + * <li>The user creates a Clp_Parser object using Clp_NewParser(), passing in + * the command line arguments to parse and the Clp_Option structures.</li> + * <li>A loop repeatedly calls Clp_Next() to parse the arguments.</li> + * </ol> + * + * Unlike many command line parsing libraries, CLP steps through all arguments + * one at a time, rather than slurping up all options at once. This makes it + * meaningful to give an option more than once. + * + * Here's an example. + * + * @code + * #define ANIMAL_OPT 1 + * #define VEGETABLE_OPT 2 + * #define MINERALS_OPT 3 + * #define USAGE_OPT 4 + * + * static const Clp_Option options[] = { + * { "animal", 'a', ANIMAL_OPT, Clp_ValString, 0 }, + * { "vegetable", 'v', VEGETABLE_OPT, Clp_ValString, Clp_Negate | Clp_Optional }, + * { "minerals", 'm', MINERALS_OPT, Clp_ValInt, 0 }, + * { "usage", 0, USAGE_OPT, 0, 0 } + * }; + * + * int main(int argc, char *argv[]) { + * Clp_Parser *clp = Clp_NewParser(argc, argv, + * sizeof(options) / sizeof(options[0]), options); + * int opt; + * while ((opt = Clp_Next(clp)) != Clp_Done) + * switch (opt) { + * case ANIMAL_OPT: + * fprintf(stderr, "animal is %s\n", clp->val.s); + * break; + * case VEGETABLE_OPT: + * if (clp->negated) + * fprintf(stderr, "no vegetables!\n"); + * else if (clp->have_val) + * fprintf(stderr, "vegetable is %s\n", clp->val.s); + * else + * fprintf(stderr, "vegetables OK\n"); + * break; + * case MINERALS_OPT: + * fprintf(stderr, "%d minerals\n", clp->val.i); + * break; + * case USAGE_OPT: + * fprintf(stderr, "Usage: 20q [--animal=ANIMAL] [--vegetable[=VEGETABLE]] [--minerals=N]\n"); + * break; + * case Clp_NotOption: + * fprintf(stderr, "non-option %s\n", clp->vstr); + * break; + * } + * } + * } + * @endcode + * + * Here are a couple of executions. + * + * <pre> + * % ./20q --animal=cat + * animal is cat + * % ./20q --animal=cat -a dog -afish --animal bird --an=snake + * animal is cat + * animal is dog + * animal is fish + * animal is bird + * animal is snake + * % ./20q --no-vegetables + * no vegetables! + * % ./20q -v + * vegetables OK + * % ./20q -vkale + * vegetable is kale + * % ./20q -m10 + * 10 minerals + * % ./20q -m foo + * '-m' expects an integer, not 'foo' + * </pre> + */ + + +/* Option types for Clp_SetOptionChar */ +#define Clp_DoubledLong (Clp_LongImplicit * 2) + +#define Clp_InitialValType 8 +#define MAX_AMBIGUOUS_VALUES 4 + +typedef struct { + int val_type; + Clp_ValParseFunc func; + int flags; + void *user_data; +} Clp_ValType; + +typedef struct { + unsigned ilong : 1; + unsigned ishort : 1; + unsigned imandatory : 1; + unsigned ioptional : 1; + unsigned ipos : 1; + unsigned ineg : 1; + unsigned iprefmatch : 1; + unsigned lmmpos_short : 1; + unsigned lmmneg_short : 1; + unsigned char ilongoff; + int lmmpos; + int lmmneg; +} Clp_InternOption; + + +#define Clp_OptionCharsSize 5 + +typedef struct { + int c; + int type; +} Clp_Oclass; +#define Clp_OclassSize 10 + +typedef struct Clp_Internal { + const Clp_Option *opt; + Clp_InternOption *iopt; + int nopt; + unsigned opt_generation; + + Clp_ValType *valtype; + int nvaltype; + + const char * const *argv; + int argc; + + Clp_Oclass oclass[Clp_OclassSize]; + int noclass; + int long1pos; + int long1neg; + int utf8; + + char option_chars[Clp_OptionCharsSize]; + const char *xtext; + + const char *program_name; + void (*error_handler)(Clp_Parser *, const char *); + + int option_processing; + int current_option; + + unsigned char is_short; + unsigned char whole_negated; /* true if negated by an option character */ + unsigned char could_be_short; + unsigned char current_short; + unsigned char negated_by_no; + + int ambiguous; + int ambiguous_values[MAX_AMBIGUOUS_VALUES]; +} Clp_Internal; + + +struct Clp_ParserState { + const char * const *argv; + int argc; + + char option_chars[Clp_OptionCharsSize]; + const char *xtext; + + int option_processing; + + unsigned opt_generation; + int current_option; + unsigned char is_short; + unsigned char whole_negated; + unsigned char current_short; + unsigned char negated_by_no; +}; + + +typedef struct Clp_StringList { + + Clp_Option *items; + Clp_InternOption *iopt; + int nitems; + + int allow_int; + int nitems_invalid_report; + +} Clp_StringList; + + +static int parse_string(Clp_Parser *, const char *, int, void *); +static int parse_int(Clp_Parser *, const char *, int, void *); +static int parse_bool(Clp_Parser *, const char *, int, void *); +static int parse_double(Clp_Parser *, const char *, int, void *); +static int parse_string_list(Clp_Parser *, const char *, int, void *); + +static int ambiguity_error(Clp_Parser *, int, int *, const Clp_Option *, + const Clp_InternOption *, const char *, const char *, + ...); + + +/******* + * utf8 + **/ + +#define U_REPLACEMENT 0xFFFD + +static char * +encode_utf8(char *s, int n, int c) +{ + if (c < 0 || c >= 0x110000 || (c >= 0xD800 && c <= 0xDFFF)) + c = U_REPLACEMENT; + if (c <= 0x7F && n >= 1) + *s++ = c; + else if (c <= 0x7FF && n >= 2) { + *s++ = 0xC0 | (c >> 6); + goto char1; + } else if (c <= 0xFFFF && n >= 3) { + *s++ = 0xE0 | (c >> 12); + goto char2; + } else if (n >= 4) { + *s++ = 0xF0 | (c >> 18); + *s++ = 0x80 | ((c >> 12) & 0x3F); + char2: + *s++ = 0x80 | ((c >> 6) & 0x3F); + char1: + *s++ = 0x80 | (c & 0x3F); + } + return s; +} + +static int +decode_utf8(const char *s, const char **cp) +{ + int c; + if ((unsigned char) *s <= 0x7F) /* 1 byte: 0x000000-0x00007F */ + c = *s++; + else if ((unsigned char) *s <= 0xC1) /* bad/overlong encoding */ + goto replacement; + else if ((unsigned char) *s <= 0xDF) { /* 2 bytes: 0x000080-0x0007FF */ + if ((s[1] & 0xC0) != 0x80) /* bad encoding */ + goto replacement; + c = (*s++ & 0x1F) << 6; + goto char1; + } else if ((unsigned char) *s <= 0xEF) { /* 3 bytes: 0x000800-0x00FFFF */ + if ((s[1] & 0xC0) != 0x80 /* bad encoding */ + || (s[2] & 0xC0) != 0x80 /* bad encoding */ + || ((unsigned char) *s == 0xE0 /* overlong encoding */ + && (s[1] & 0xE0) == 0x80) + || ((unsigned char) *s == 0xED /* encoded surrogate */ + && (s[1] & 0xE0) == 0xA0)) + goto replacement; + c = (*s++ & 0x0F) << 12; + goto char2; + } else if ((unsigned char) *s <= 0xF4) { /* 4 bytes: 0x010000-0x10FFFF */ + if ((s[1] & 0xC0) != 0x80 /* bad encoding */ + || (s[2] & 0xC0) != 0x80 /* bad encoding */ + || (s[3] & 0xC0) != 0x80 /* bad encoding */ + || ((unsigned char) *s == 0xF0 /* overlong encoding */ + && (s[1] & 0xF0) == 0x80) + || ((unsigned char) *s == 0xF4 /* encoded value > 0x10FFFF */ + && (unsigned char) s[1] >= 0x90)) + goto replacement; + c = (*s++ & 0x07) << 18; + c += (*s++ & 0x3F) << 12; + char2: + c += (*s++ & 0x3F) << 6; + char1: + c += (*s++ & 0x3F); + } else { + replacement: + c = U_REPLACEMENT; + for (s++; (*s & 0xC0) == 0x80; s++) + /* nothing */; + } + if (cp) + *cp = s; + return c; +} + +static int +utf8_charlen(const char *s) +{ + const char *sout; + (void) decode_utf8(s, &sout); + return sout - s; +} + +static int +clp_utf8_charlen(const Clp_Internal *cli, const char *s) +{ + return (cli->utf8 ? utf8_charlen(s) : 1); +} + + +/******* + * Clp_NewParser, etc. + **/ + +static int +min_different_chars(const char *s, const char *t) + /* Returns the minimum number of bytes required to distinguish + s from t. + If s is shorter than t, returns strlen(s). */ +{ + const char *sfirst = s; + while (*s && *t && *s == *t) + s++, t++; + if (!*s) + return s - sfirst; + else + return s - sfirst + 1; +} + +static int +long_as_short(const Clp_Internal *cli, const Clp_Option *o, + Clp_InternOption *io, int failure) +{ + if ((cli->long1pos || cli->long1neg) && io->ilong) { + const char *name = o->long_name + io->ilongoff; + if (cli->utf8) { + int c = decode_utf8(name, &name); + if (!*name && c && c != U_REPLACEMENT) + return c; + } else if (name[0] && !name[1]) + return (unsigned char) name[0]; + } + return failure; +} + +static void +compare_options(Clp_Parser *clp, const Clp_Option *o1, Clp_InternOption *io1, + const Clp_Option *o2, Clp_InternOption *io2) +{ + Clp_Internal *cli = clp->internal; + int short1, shortx1; + + /* ignore meaningless combinations */ + if ((!io1->ishort && !io1->ilong) || (!io2->ishort && !io2->ilong) + || !((io1->ipos && io2->ipos) || (io1->ineg && io2->ineg)) + || o1->option_id == o2->option_id) + return; + + /* look for duplication of short options */ + short1 = (io1->ishort ? o1->short_name : -1); + shortx1 = long_as_short(cli, o1, io1, -2); + if (short1 >= 0 || shortx1 >= 0) { + int short2 = (io2->ishort ? o2->short_name : -3); + int shortx2 = long_as_short(cli, o2, io2, -4); + if (short1 == short2) + Clp_OptionError(clp, "CLP internal error: more than 1 option has short name %`%c%'", short1); + else if ((short1 == shortx2 || shortx1 == short2 || shortx1 == shortx2) + && ((io1->ipos && io2->ipos && cli->long1pos) + || (io1->ineg && io2->ineg && cli->long1neg))) + Clp_OptionError(clp, "CLP internal error: 1-char long name conflicts with short name %`%c%'", (short1 == shortx2 ? shortx2 : shortx1)); + } + + /* analyze longest minimum match */ + if (io1->ilong) { + const char *name1 = o1->long_name + io1->ilongoff; + + /* long name's first character matches short name */ + if (io2->ishort && !io1->iprefmatch) { + int name1char = (cli->utf8 ? decode_utf8(name1, 0) : (unsigned char) *name1); + if (name1char == o2->short_name) { + if (io1->ipos && io2->ipos) + io1->lmmpos_short = 1; + if (io1->ineg && io2->ineg) + io1->lmmneg_short = 1; + } + } + + /* match long name to long name */ + if (io2->ilong) { + const char *name2 = o2->long_name + io2->ilongoff; + if (strcmp(name1, name2) == 0) + Clp_OptionError(clp, "CLP internal error: duplicate long name %`%s%'", name1); + if (io1->ipos && io2->ipos && !strncmp(name1, name2, io1->lmmpos) + && (!io1->iprefmatch || strncmp(name1, name2, strlen(name1)))) + io1->lmmpos = min_different_chars(name1, name2); + if (io1->ineg && io2->ineg && !strncmp(name1, name2, io1->lmmneg) + && (!io1->iprefmatch || strncmp(name1, name2, strlen(name1)))) + io1->lmmneg = min_different_chars(name1, name2); + } + } +} + +/** @param argc number of arguments + * @param argv argument array + * @param nopt number of option definitions + * @param opt option definition array + * @return the parser + * + * The new Clp_Parser that will parse the arguments in @a argv according to + * the option definitions in @a opt. + * + * The Clp_Parser is created with the following characteristics: + * + * <ul> + * <li>The "-" character introduces short options (<tt>Clp_SetOptionChar(clp, + * '-', Clp_Short)</tt>).</li> + * <li>Clp_ProgramName is set from the first argument in @a argv, if any. The + * first argument returned by Clp_Next() will be the second argument in @a + * argv. Note that this behavior differs from Clp_SetArguments.</li> + * <li>UTF-8 support is on iff the <tt>LANG</tt> environment variable contains + * one of the substrings "UTF-8", "UTF8", or "utf8".</li> + * <li>The Clp_ValString, Clp_ValStringNotOption, Clp_ValInt, Clp_ValUnsigned, + * Clp_ValBool, and Clp_ValDouble types are installed.</li> + * <li>Errors are reported to standard error.</li> + * </ul> + * + * To override these characteristics, either call functions like + * Clp_SetUTF8(), or create your Clp_Parser with no arguments or options + * (<tt>Clp_NewParser(0, 0, 0, 0)</tt>) and set the arguments and options + * later. + * + * Returns NULL if there isn't enough memory to construct the parser. + * + * @note The CLP library will not modify the contents of @a argv or @a opt. + * The calling program must not modify @a opt. It may modify @a argv in + * limited cases. + */ +Clp_Parser * +Clp_NewParser(int argc, const char * const *argv, int nopt, const Clp_Option *opt) +{ + Clp_Parser *clp = (Clp_Parser *)malloc(sizeof(Clp_Parser)); + Clp_Internal *cli = (Clp_Internal *)malloc(sizeof(Clp_Internal)); + Clp_InternOption *iopt = (Clp_InternOption *)malloc(sizeof(Clp_InternOption) * nopt); + if (!clp || !cli || !iopt) + goto failed; + + clp->negated = 0; + clp->have_val = 0; + clp->vstr = 0; + clp->user_data = 0; + clp->internal = cli; + + cli->opt = opt; + cli->nopt = nopt; + cli->iopt = iopt; + cli->opt_generation = 0; + cli->error_handler = 0; + + /* Assign program name (now so we can call Clp_OptionError) */ + if (argc > 0) { + const char *slash = strrchr(argv[0], '/'); + cli->program_name = slash ? slash + 1 : argv[0]; + } else + cli->program_name = 0; + + /* Assign arguments, skipping program name */ + Clp_SetArguments(clp, argc - 1, argv + 1); + + /* Initialize UTF-8 status and option classes */ + { + char *s = getenv("LANG"); + cli->utf8 = (s && (strstr(s, "UTF-8") != 0 || strstr(s, "UTF8") != 0 + || strstr(s, "utf8") != 0)); + } + cli->oclass[0].c = '-'; + cli->oclass[0].type = Clp_Short; + cli->noclass = 1; + cli->long1pos = cli->long1neg = 0; + + /* Add default type parsers */ + cli->valtype = (Clp_ValType *)malloc(sizeof(Clp_ValType) * Clp_InitialValType); + if (!cli->valtype) + goto failed; + cli->nvaltype = 0; + + Clp_AddType(clp, Clp_ValString, 0, parse_string, 0); + Clp_AddType(clp, Clp_ValStringNotOption, Clp_DisallowOptions, parse_string, 0); + Clp_AddType(clp, Clp_ValInt, 0, parse_int, 0); + Clp_AddType(clp, Clp_ValUnsigned, 0, parse_int, (void *)cli); + Clp_AddType(clp, Clp_ValBool, 0, parse_bool, 0); + Clp_AddType(clp, Clp_ValDouble, 0, parse_double, 0); + + /* Set options */ + Clp_SetOptions(clp, nopt, opt); + + return clp; + + failed: + if (cli && cli->valtype) + free(cli->valtype); + if (cli) + free(cli); + if (clp) + free(clp); + if (iopt) + free(iopt); + return 0; +} + +/** @param clp the parser + * + * All memory associated with @a clp is freed. */ +void +Clp_DeleteParser(Clp_Parser *clp) +{ + int i; + Clp_Internal *cli; + if (!clp) + return; + + cli = clp->internal; + + /* get rid of any string list types */ + for (i = 0; i < cli->nvaltype; i++) + if (cli->valtype[i].func == parse_string_list) { + Clp_StringList *clsl = (Clp_StringList *)cli->valtype[i].user_data; + free(clsl->items); + free(clsl->iopt); + free(clsl); + } + + free(cli->valtype); + free(cli->iopt); + free(cli); + free(clp); +} + + +/** @param clp the parser + * @param errh error handler function + * @return previous error handler function + * + * The error handler function is called when CLP encounters an error while + * parsing the command line. It is called with the arguments "<tt>(*errh)(@a + * clp, s)</tt>", where <tt>s</tt> is a description of the error terminated by + * a newline. The <tt>s</tt> descriptions produced by CLP itself are prefixed + * by the program name, if any. */ +Clp_ErrorHandler +Clp_SetErrorHandler(Clp_Parser *clp, void (*errh)(Clp_Parser *, const char *)) +{ + Clp_Internal *cli = clp->internal; + Clp_ErrorHandler old = cli->error_handler; + cli->error_handler = errh; + return old; +} + +/** @param clp the parser + * @param utf8 does the parser support UTF-8? + * @return previous UTF-8 mode + * + * In UTF-8 mode, all input strings (arguments and long names for options) are + * assumed to be encoded via UTF-8, and all character names + * (Clp_SetOptionChar() and short names for options) may cover the whole + * Unicode range. Out of UTF-8 mode, all input strings are treated as binary, + * and all character names must be unsigned char values. + * + * Furthermore, error messages in UTF-8 mode may contain Unicode quote + * characters. */ +int +Clp_SetUTF8(Clp_Parser *clp, int utf8) +{ + Clp_Internal *cli = clp->internal; + int i, j, old_utf8 = cli->utf8; + cli->utf8 = utf8; + for (i = 0; i < cli->nopt; ++i) { + cli->iopt[i].lmmpos = cli->iopt[i].lmmneg = 1; + cli->iopt[i].lmmpos_short = cli->iopt[i].lmmneg_short = 0; + for (j = 0; j < cli->nopt; ++j) + compare_options(clp, &cli->opt[i], &cli->iopt[i], + &cli->opt[j], &cli->iopt[j]); + } + return old_utf8; +} + +static int +Clp_OptionChar(Clp_Parser *clp, int c) +{ + Clp_Internal *cli = clp->internal; + int i, oclass = 0; + if (cli->noclass > 0 && cli->oclass[0].c == 0) + oclass = cli->oclass[0].type; + for (i = 0; i < cli->noclass; ++i) + if (cli->oclass[i].c == c) + oclass = cli->oclass[i].type; + return oclass; +} + +/** @param clp the parser + * @param c character + * @param type option character treatment + * @return previous option character treatment, or -1 on error + * + * @a type specifies how CLP treats arguments that begin with character @a c. + * Possibilities are: + * + * <dl> + * <dt>Clp_NotOption (or 0)</dt> + * <dd>The argument cannot be an option.</dd> + * <dt>Clp_Long</dt> + * <dd>The argument is a long option.</dd> + * <dt>Clp_Short</dt> + * <dd>The argument is a set of short options.</dd> + * <dt>Clp_Short|Clp_Long</dt> + * <dd>The argument is either a long option or, if no matching long option is + * found, a set of short options.</dd> + * <dt>Clp_LongNegated</dt> + * <dd>The argument is a negated long option. For example, after + * Clp_SetOptionChar(@a clp, '^', Clp_LongNegated), the argument "^foo" is + * equivalent to "--no-foo".</dd> + * <dt>Clp_ShortNegated</dt> + * <dd>The argument is a set of negated short options.</dd> + * <dt>Clp_ShortNegated|Clp_LongNegated</dt> + * <dd>The argument is either a negated long option or, if no matching long + * option is found, a set of negated short options.</dd> + * <dt>Clp_LongImplicit</dt> + * <dd>The argument may be a long option, where the character @a c is actually + * part of the long option name. For example, after Clp_SetOptionChar(@a clp, + * 'f', Clp_LongImplicit), the argument "foo" may be equivalent to + * "--foo".</dd> + * </dl> + * + * In UTF-8 mode, @a c may be any Unicode character. Otherwise, @a c must be + * an unsigned char value. The special character 0 assigns @a type to @em + * every character. + * + * It is an error if @a c is out of range, @a type is illegal, or there are + * too many character definitions stored in @a clp already. The function + * returns -1 on error. + * + * A double hyphen "--" always introduces a long option. This behavior cannot + * currently be changed with Clp_SetOptionChar(). + */ +int +Clp_SetOptionChar(Clp_Parser *clp, int c, int type) +{ + int i, j, long1pos, long1neg; + int old = Clp_OptionChar(clp, c); + Clp_Internal *cli = clp->internal; + + if (type != Clp_NotOption && type != Clp_Short && type != Clp_Long + && type != Clp_ShortNegated && type != Clp_LongNegated + && type != Clp_LongImplicit && type != (Clp_Short | Clp_Long) + && type != (Clp_ShortNegated | Clp_LongNegated)) + return -1; + if (c < 0 || c >= (cli->utf8 ? 0x110000 : 256)) + return -1; + + if (c == 0) + cli->noclass = 0; + for (i = 0; i < cli->noclass; ++i) + if (cli->oclass[i].c == c) + break; + if (i == Clp_OclassSize) + return -1; + + cli->oclass[i].c = c; + cli->oclass[i].type = type; + if (cli->noclass == i) + cli->noclass = i + 1; + + long1pos = long1neg = 0; + for (i = 0; i < cli->noclass; ++i) { + if ((cli->oclass[i].type & Clp_Short) + && (cli->oclass[i].type & Clp_Long)) + long1pos = 1; + if ((cli->oclass[i].type & Clp_ShortNegated) + && (cli->oclass[i].type & Clp_LongNegated)) + long1neg = 1; + } + + if (long1pos != cli->long1pos || long1neg != cli->long1neg) { + /* Must recheck option set */ + cli->long1pos = long1pos; + cli->long1neg = long1neg; + for (i = 0; i < cli->nopt; ++i) { + cli->iopt[i].lmmpos = cli->iopt[i].lmmneg = 1; + cli->iopt[i].lmmpos_short = cli->iopt[i].lmmneg_short = 0; + for (j = 0; j < cli->nopt; ++j) + compare_options(clp, &cli->opt[i], &cli->iopt[i], + &cli->opt[j], &cli->iopt[j]); + } + } + + return old; +} + +/** @param clp the parser + * @param nopt number of option definitions + * @param opt option definition array + * @return 0 on success, -1 on failure + * + * Installs the option definitions in @a opt. Future option parsing will + * use @a opt to search for options. + * + * Also checks @a opt's option definitions for validity. "CLP internal + * errors" are reported via Clp_OptionError() if: + * + * <ul> + * <li>An option has a negative ID.</li> + * <li>Two different short options have the same name.</li> + * <li>Two different long options have the same name.</li> + * <li>A short and a long option are ambiguous, in that some option character + * might introduce either a short or a long option (e.g., Clp_SetOptionChar(@a + * clp, '-', Clp_Long|Clp_Short)), and a short name equals a long name.</li> + * </ul> + * + * If necessary memory cannot be allocated, this function returns -1 without + * modifying the parser. + * + * @note The CLP library will not modify the contents of @a argv or @a opt. + * The calling program must not modify @a opt either until another call to + * Clp_SetOptions() or the parser is destroyed. + */ +int +Clp_SetOptions(Clp_Parser *clp, int nopt, const Clp_Option *opt) +{ + Clp_Internal *cli = clp->internal; + Clp_InternOption *iopt; + int i, j; + static unsigned opt_generation = 0; + + if (nopt > cli->nopt) { + iopt = (Clp_InternOption *)malloc(sizeof(Clp_InternOption) * nopt); + if (!iopt) + return -1; + free(cli->iopt); + cli->iopt = iopt; + } + + cli->opt = opt; + cli->nopt = nopt; + cli->opt_generation = ++opt_generation; + iopt = cli->iopt; + cli->current_option = -1; + + /* Massage the options to make them usable */ + for (i = 0; i < nopt; i++) { + /* Ignore negative option_ids, which are internal to CLP */ + if (opt[i].option_id < 0) { + Clp_OptionError(clp, "CLP internal error: option %d has negative option_id", i); + iopt[i].ilong = iopt[i].ishort = iopt[i].ipos = iopt[i].ineg = 0; + continue; + } + + /* Set flags based on input flags */ + iopt[i].ilong = (opt[i].long_name != 0 && opt[i].long_name[0] != 0); + iopt[i].ishort = (opt[i].short_name > 0 + && opt[i].short_name < (cli->utf8 ? 0x110000 : 256)); + iopt[i].ipos = 1; + iopt[i].ineg = (opt[i].flags & Clp_Negate) != 0; + iopt[i].imandatory = (opt[i].flags & Clp_Mandatory) != 0; + iopt[i].ioptional = (opt[i].flags & Clp_Optional) != 0; + iopt[i].iprefmatch = (opt[i].flags & Clp_PreferredMatch) != 0; + iopt[i].ilongoff = 0; + + /* Enforce invariants */ + if (opt[i].val_type <= 0) + iopt[i].imandatory = iopt[i].ioptional = 0; + if (opt[i].val_type > 0 && !iopt[i].ioptional) + iopt[i].imandatory = 1; + + /* Options that start with 'no-' should be changed to OnlyNegated */ + if (iopt[i].ilong && strncmp(opt[i].long_name, "no-", 3) == 0) { + iopt[i].ipos = 0; + iopt[i].ineg = 1; + iopt[i].ilongoff = 3; + if (strncmp(opt[i].long_name + 3, "no-", 3) == 0) + Clp_OptionError(clp, "CLP internal error: option %d begins with \"no-no-\"", i); + } else if (opt[i].flags & Clp_OnlyNegated) { + iopt[i].ipos = 0; + iopt[i].ineg = 1; + } + } + + /* Check option set */ + for (i = 0; i < nopt; ++i) { + iopt[i].lmmpos = iopt[i].lmmneg = 1; + iopt[i].lmmpos_short = iopt[i].lmmneg_short = 0; + for (j = 0; j < nopt; ++j) + compare_options(clp, &opt[i], &iopt[i], &opt[j], &iopt[j]); + } + + return 0; +} + +/** @param clp the parser + * @param argc number of arguments + * @param argv argument array + * + * Installs the arguments in @a argv for parsing. Future option parsing will + * analyze @a argv. + * + * Unlike Clp_NewParser(), this function does not treat @a argv[0] specially. + * The first subsequent call to Clp_Next() will analyze @a argv[0]. + * + * This function also sets option processing to on, as by + * Clp_SetOptionProcessing(@a clp, 1). + * + * @note The CLP library will not modify the contents of @a argv. The calling + * program should not generally modify the element of @a argv that CLP is + * currently analyzing. + */ +void +Clp_SetArguments(Clp_Parser *clp, int argc, const char * const *argv) +{ + Clp_Internal *cli = clp->internal; + + cli->argc = argc + 1; + cli->argv = argv - 1; + + cli->is_short = 0; + cli->whole_negated = 0; + cli->option_processing = 1; + cli->current_option = -1; +} + + +/** @param clp the parser + * @param on whether to search for options + * @return previous option processing setting + * + * When option processing is off, every call to Clp_Next() returns + * Clp_NotOption. By default the option <tt>"--"</tt> turns off option + * processing and is otherwise ignored. + */ +int +Clp_SetOptionProcessing(Clp_Parser *clp, int on) +{ + Clp_Internal *cli = clp->internal; + int old = cli->option_processing; + cli->option_processing = on; + return old; +} + + +/******* + * functions for Clp_Option lists + **/ + +/* the ever-glorious argcmp */ + +static int +argcmp(const char *ref, const char *arg, int min_match, int fewer_dashes) + /* Returns 0 if ref and arg don't match. + Returns -1 if ref and arg match, but fewer than min_match characters. + Returns len if ref and arg match min_match or more characters; + len is the number of characters that matched in arg. + Allows arg to contain fewer dashes than ref iff fewer_dashes != 0. + + Examples: + argcmp("x", "y", 1, 0) --> 0 / just plain wrong + argcmp("a", "ax", 1, 0) --> 0 / ...even though min_match == 1 + and the 1st chars match + argcmp("box", "bo", 3, 0) --> -1 / ambiguous + argcmp("cat", "c=3", 1, 0) --> 1 / handles = arguments + */ +{ + const char *refstart = ref; + const char *argstart = arg; + assert(min_match > 0); + + compare: + while (*ref && *arg && *arg != '=' && *ref == *arg) + ref++, arg++; + + /* Allow arg to contain fewer dashes than ref */ + if (fewer_dashes && *ref == '-' && ref[1] && ref[1] == *arg) { + ref++; + goto compare; + } + + if (*arg && *arg != '=') + return 0; + else if (ref - refstart < min_match) + return -1; + else + return arg - argstart; +} + +static int +find_prefix_opt(Clp_Parser *clp, const char *arg, + int nopt, const Clp_Option *opt, + const Clp_InternOption *iopt, + int *ambiguous, int *ambiguous_values) + /* Looks for an unambiguous match of 'arg' against one of the long + options in 'opt'. Returns positive if it finds one; otherwise, returns + -1 and possibly changes 'ambiguous' and 'ambiguous_values' to keep + track of at most MAX_AMBIGUOUS_VALUES possibilities. */ +{ + int i, fewer_dashes = 0, first_ambiguous = *ambiguous; + int negated = clp && clp->negated; + int first_charlen = (clp ? clp_utf8_charlen(clp->internal, arg) : 1); + + retry: + for (i = 0; i < nopt; i++) { + int len, lmm; + if (!iopt[i].ilong || (negated ? !iopt[i].ineg : !iopt[i].ipos)) + continue; + + lmm = (negated ? iopt[i].lmmneg : iopt[i].lmmpos); + if (clp && clp->internal->could_be_short + && (negated ? iopt[i].lmmneg_short : iopt[i].lmmpos_short)) + lmm = (first_charlen >= lmm ? first_charlen + 1 : lmm); + len = argcmp(opt[i].long_name + iopt[i].ilongoff, arg, lmm, fewer_dashes); + if (len > 0) + return i; + else if (len < 0) { + if (*ambiguous < MAX_AMBIGUOUS_VALUES) + ambiguous_values[*ambiguous] = i; + (*ambiguous)++; + } + } + + /* If there were no partial matches, try again with fewer_dashes true */ + if (*ambiguous == first_ambiguous && !fewer_dashes) { + fewer_dashes = 1; + goto retry; + } + + return -1; +} + + +/***** + * Argument parsing + **/ + +static int +val_type_binsearch(Clp_Internal *cli, int val_type) +{ + unsigned l = 0, r = cli->nvaltype; + while (l < r) { + unsigned m = l + (r - l) / 2; + if (cli->valtype[m].val_type == val_type) + return m; + else if (cli->valtype[m].val_type < val_type) + l = m + 1; + else + r = m; + } + return l; +} + +/** @param clp the parser + * @param val_type value type ID + * @param flags value type flags + * @param parser parser function + * @param user_data user data for @a parser function + * @return 0 on success, -1 on failure + * + * Defines argument type @a val_type in parser @a clp. The parsing function + * @a parser will be passed argument values for type @a val_type. It should + * parse the argument into values (usually in @a clp->val, but sometimes + * elsewhere), report errors if necessary, and return whether the parse was + * successful. + * + * Any prior argument parser match @a val_type is removed. @a val_type must + * be greater than zero. + * + * @a flags specifies additional parsing flags. At the moment the only + * relevant flag is Clp_DisallowOptions, which means that separated values + * must not look like options. For example, assume argument + * <tt>--a</tt>/<tt>-a</tt> has mandatory value type Clp_ValStringNotOption + * (which has Clp_DisallowOptions). Then: + * + * <ul> + * <li><tt>--a=--b</tt> will parse with value <tt>--b</tt>.</li> + * <li><tt>-a--b</tt> will parse with value <tt>--b</tt>.</li> + * <li><tt>--a --b</tt> will not parse, since the mandatory value looks like + * an option.</li> + * <li><tt>-a --b</tt> will not parse, since the mandatory value looks like + * an option.</li> + * </ul> + */ +int +Clp_AddType(Clp_Parser *clp, int val_type, int flags, + Clp_ValParseFunc parser, void *user_data) +{ + Clp_Internal *cli = clp->internal; + int vtpos; + + if (val_type <= 0 || !parser) + return -1; + + vtpos = val_type_binsearch(cli, val_type); + + if (vtpos == cli->nvaltype || cli->valtype[vtpos].val_type != val_type) { + if (cli->nvaltype != 0 && (cli->nvaltype % Clp_InitialValType) == 0) { + Clp_ValType *new_valtype = + (Clp_ValType *) realloc(cli->valtype, sizeof(Clp_ValType) * (cli->nvaltype + Clp_InitialValType)); + if (!new_valtype) + return -1; + cli->valtype = new_valtype; + } + memmove(&cli->valtype[vtpos + 1], &cli->valtype[vtpos], + sizeof(Clp_ValType) * (cli->nvaltype - vtpos)); + cli->nvaltype++; + cli->valtype[vtpos].func = 0; + } + + if (cli->valtype[vtpos].func == parse_string_list) { + Clp_StringList *clsl = (Clp_StringList *) cli->valtype[vtpos].user_data; + free(clsl->items); + free(clsl->iopt); + free(clsl); + } + + cli->valtype[vtpos].val_type = val_type; + cli->valtype[vtpos].func = parser; + cli->valtype[vtpos].flags = flags; + cli->valtype[vtpos].user_data = user_data; + return 0; +} + + +/******* + * Default argument parsers + **/ + +static int +parse_string(Clp_Parser *clp, const char *arg, int complain, void *user_data) +{ + (void)complain, (void)user_data; + clp->val.s = arg; + return 1; +} + +static int +parse_int(Clp_Parser *clp, const char *arg, int complain, void *user_data) +{ + const char *val; + char *temp; + if (*arg == 0 || isspace((unsigned char) *arg) + || (user_data != 0 && *arg == '-')) + val = arg; + else if (user_data != 0) { /* unsigned */ +#if HAVE_STRTOUL + clp->val.u = strtoul(arg, &temp, 0); + val = temp; +#else + /* don't bother really trying to do it right */ + if (arg[0] == '-') + val = arg; + else { + clp->val.u = strtol(arg, &temp, 0); + val = temp; + } +#endif + } else { + clp->val.i = strtol(arg, &temp, 0); + val = temp; + } + if (*arg != 0 && *val == 0) + return 1; + else if (complain) { + const char *message = user_data != 0 + ? "%`%O%' expects a nonnegative integer, not %`%s%'" + : "%`%O%' expects an integer, not %`%s%'"; + return Clp_OptionError(clp, message, arg); + } else + return 0; +} + +static int +parse_double(Clp_Parser *clp, const char *arg, int complain, void *user_data) +{ + const char *val; + char *temp; + (void)user_data; + if (*arg == 0 || isspace((unsigned char) *arg)) + val = arg; + else { + clp->val.d = strtod(arg, &temp); + val = temp; + } + if (*arg != 0 && *val == 0) + return 1; + else if (complain) + return Clp_OptionError(clp, "%`%O%' expects a real number, not %`%s%'", arg); + else + return 0; +} + +static int +parse_bool(Clp_Parser *clp, const char *arg, int complain, void *user_data) +{ + int i; + char lcarg[6]; + (void)user_data; + if (strlen(arg) > 5 || strchr(arg, '=') != 0) + goto error; + + for (i = 0; arg[i] != 0; i++) + lcarg[i] = tolower((unsigned char) arg[i]); + lcarg[i] = 0; + + if (argcmp("yes", lcarg, 1, 0) > 0 + || argcmp("true", lcarg, 1, 0) > 0 + || argcmp("1", lcarg, 1, 0) > 0) { + clp->val.i = 1; + return 1; + } else if (argcmp("no", lcarg, 1, 0) > 0 + || argcmp("false", lcarg, 1, 0) > 0 + || argcmp("1", lcarg, 1, 0) > 0) { + clp->val.i = 0; + return 1; + } + + error: + if (complain) + Clp_OptionError(clp, "%`%O%' expects a true-or-false value, not %`%s%'", arg); + return 0; +} + + +/***** + * Clp_AddStringListType + **/ + +static int +parse_string_list(Clp_Parser *clp, const char *arg, int complain, void *user_data) +{ + Clp_StringList *sl = (Clp_StringList *)user_data; + int idx, ambiguous = 0; + int ambiguous_values[MAX_AMBIGUOUS_VALUES + 1]; + + /* actually look for a string value */ + idx = find_prefix_opt + (0, arg, sl->nitems, sl->items, sl->iopt, + &ambiguous, ambiguous_values); + if (idx >= 0) { + clp->val.i = sl->items[idx].option_id; + return 1; + } + + if (sl->allow_int) { + if (parse_int(clp, arg, 0, 0)) + return 1; + } + + if (complain) { + const char *complaint = (ambiguous ? "ambiguous" : "invalid"); + if (!ambiguous) { + ambiguous = sl->nitems_invalid_report; + for (idx = 0; idx < ambiguous; idx++) + ambiguous_values[idx] = idx; + } + return ambiguity_error + (clp, ambiguous, ambiguous_values, sl->items, sl->iopt, + "", "option %`%O%' value %`%s%' is %s", arg, complaint); + } else + return 0; +} + + +static int +finish_string_list(Clp_Parser *clp, int val_type, int flags, + Clp_Option *items, int nitems, int itemscap) +{ + int i, j; + Clp_StringList *clsl = (Clp_StringList *)malloc(sizeof(Clp_StringList)); + Clp_InternOption *iopt = (Clp_InternOption *)malloc(sizeof(Clp_InternOption) * nitems); + if (!clsl || !iopt) + goto error; + + clsl->items = items; + clsl->iopt = iopt; + clsl->nitems = nitems; + clsl->allow_int = (flags & Clp_AllowNumbers) != 0; + + if (nitems < MAX_AMBIGUOUS_VALUES && nitems < itemscap && clsl->allow_int) { + items[nitems].long_name = "any integer"; + clsl->nitems_invalid_report = nitems + 1; + } else if (nitems > MAX_AMBIGUOUS_VALUES + 1) + clsl->nitems_invalid_report = MAX_AMBIGUOUS_VALUES + 1; + else + clsl->nitems_invalid_report = nitems; + + for (i = 0; i < nitems; i++) { + iopt[i].ilong = iopt[i].ipos = 1; + iopt[i].ishort = iopt[i].ineg = iopt[i].ilongoff = iopt[i].iprefmatch = 0; + iopt[i].lmmpos = 1; + iopt[i].lmmpos_short = 0; + } + for (i = 0; i < nitems; i++) + for (j = 0; j < nitems; j++) + compare_options(clp, &items[i], &iopt[i], &items[j], &iopt[j]); + + if (Clp_AddType(clp, val_type, 0, parse_string_list, clsl) >= 0) + return 0; + + error: + if (clsl) + free(clsl); + if (iopt) + free(iopt); + return -1; +} + +/** @param clp the parser + * @param val_type value type ID + * @param flags string list flags + * @return 0 on success, -1 on failure + * + * Defines argument type @a val_type in parser @a clp. The parsing function + * sets @a clp->val.i to an integer. The value string is matched against + * strings provided in the ellipsis arguments. For example, the + * Clp_AddStringListType() call below has the same effect as the + * Clp_AddStringListTypeVec() call: + * + * For example: + * @code + * Clp_AddStringListType(clp, 100, Clp_AllowNumbers, "cat", 1, + * "cattle", 2, "dog", 3, (const char *) NULL); + * + * const char * const strs[] = { "cat", "cattle", "dog" }; + * const int vals[] = { 1, 2, 3 }; + * Clp_AddStringListTypeVec(clp, 100, Clp_AllowNumbers, 3, strs, vals); + * @endcode + * + * @note The CLP library will not modify any of the passed-in strings. The + * calling program must not modify or free them either until the parser is + * destroyed. + */ +int +Clp_AddStringListType(Clp_Parser *clp, int val_type, int flags, ...) +{ + int nitems = 0; + int itemscap = 5; + Clp_Option *items = (Clp_Option *)malloc(sizeof(Clp_Option) * itemscap); + + va_list val; + va_start(val, flags); + + if (!items) + goto error; + + /* slurp up the arguments */ + while (1) { + int value; + char *name = va_arg(val, char *); + if (!name) + break; + value = va_arg(val, int); + + if (nitems >= itemscap) { + Clp_Option *new_items; + itemscap *= 2; + new_items = (Clp_Option *)realloc(items, sizeof(Clp_Option) * itemscap); + if (!new_items) + goto error; + items = new_items; + } + + items[nitems].long_name = name; + items[nitems].option_id = value; + items[nitems].flags = 0; + nitems++; + } + + va_end(val); + if (finish_string_list(clp, val_type, flags, items, nitems, itemscap) >= 0) + return 0; + + error: + va_end(val); + if (items) + free(items); + return -1; +} + +/** @param clp the parser + * @param val_type value type ID + * @param flags string list flags + * @param nstrs number of strings in list + * @param strs array of strings + * @param vals array of values + * @return 0 on success, -1 on failure + * + * Defines argument type @a val_type in parser @a clp. The parsing function + * sets @a clp->val.i to an integer. The value string is matched against the + * @a strs. If there's a unique match, the corresponding entry from @a vals + * is returned. Unique prefix matches also work. Finally, if @a flags + * contains the Clp_AllowNumbers flag, then integers are also accepted. + * + * For example: + * @code + * const char * const strs[] = { "cat", "cattle", "dog" }; + * const int vals[] = { 1, 2, 3 }; + * Clp_AddStringListTypeVec(clp, 100, Clp_AllowNumbers, 3, strs, vals); + * @endcode + * + * Say that option <tt>--animal</tt> takes value type 100. Then: + * + * <ul> + * <li><tt>--animal=cat</tt> will succeed and set @a clp->val.i = 1.</li> + * <li><tt>--animal=cattle</tt> will succeed and set @a clp->val.i = 2.</li> + * <li><tt>--animal=dog</tt> will succeed and set @a clp->val.i = 3.</li> + * <li><tt>--animal=d</tt> will succeed and set @a clp->val.i = 3.</li> + * <li><tt>--animal=c</tt> will fail, since <tt>c</tt> is ambiguous.</li> + * <li><tt>--animal=4</tt> will succeed and set @a clp->val.i = 4.</li> + * </ul> + * + * @note The CLP library will not modify the contents of @a strs or @a vals. + * The calling program can modify the @a strs array, but the actual strings + * (for instance, @a strs[0] and @a strs[1]) must not be modified or freed + * until the parser is destroyed. + */ +int +Clp_AddStringListTypeVec(Clp_Parser *clp, int val_type, int flags, + int nstrs, const char * const *strs, + const int *vals) + /* An alternate way to make a string list type. See Clp_AddStringListType + for the basics; this coalesces the strings and values into two arrays, + rather than spreading them out into a variable argument list. */ +{ + int i; + int itemscap = (nstrs < 5 ? 5 : nstrs); + Clp_Option *items = (Clp_Option *)malloc(sizeof(Clp_Option) * itemscap); + if (!items) + return -1; + + /* copy over items */ + for (i = 0; i < nstrs; i++) { + items[i].long_name = strs[i]; + items[i].option_id = vals[i]; + items[i].flags = 0; + } + + if (finish_string_list(clp, val_type, flags, items, nstrs, itemscap) >= 0) + return 0; + else { + free(items); + return -1; + } +} + + +/******* + * Returning information + **/ + +const char * +Clp_ProgramName(Clp_Parser *clp) +{ + return clp->internal->program_name; +} + +/** @param clp the parser + * @param name new program name + * @return previous program name + * + * The calling program should not modify or free @a name until @a clp itself + * is destroyed. */ +const char * +Clp_SetProgramName(Clp_Parser *clp, const char *name) +{ + const char *old = clp->internal->program_name; + clp->internal->program_name = name; + return old; +} + + +/****** + * Clp_ParserStates + **/ + +/** @return the parser state + * + * A Clp_ParserState object can store a parsing state of a Clp_Parser object. + * This state specifies exactly how far the Clp_Parser has gotten in parsing + * an argument list. The Clp_SaveParser() and Clp_RestoreParser() functions + * can be used to save this state and then restore it later, allowing a + * Clp_Parser to switch among argument lists. + * + * The initial state is empty, in that after Clp_RestoreParser(clp, state), + * Clp_Next(clp) would return Clp_Done. + * + * Parser states can be saved and restored among different parser objects. + * + * @sa Clp_DeleteParserState, Clp_SaveParser, Clp_RestoreParser + */ +Clp_ParserState * +Clp_NewParserState(void) +{ + Clp_ParserState *state = (Clp_ParserState *)malloc(sizeof(Clp_ParserState)); + if (state) { + state->argv = 0; + state->argc = 0; + state->option_chars[0] = 0; + state->xtext = 0; + state->option_processing = 0; + state->opt_generation = 0; + state->current_option = -1; + state->is_short = 0; + state->whole_negated = 0; + state->current_short = 0; + state->negated_by_no = 0; + } + return state; +} + +/** @param state parser state + * + * The memory associated with @a state is freed. + */ +void +Clp_DeleteParserState(Clp_ParserState *state) +{ + free(state); +} + +/** @param clp the parser + * @param state parser state + * @sa Clp_NewParserState, Clp_RestoreParser + */ +void +Clp_SaveParser(const Clp_Parser *clp, Clp_ParserState *state) +{ + Clp_Internal *cli = clp->internal; + state->argv = cli->argv; + state->argc = cli->argc; + memcpy(state->option_chars, cli->option_chars, Clp_OptionCharsSize); + state->xtext = cli->xtext; + + state->option_processing = cli->option_processing; + state->opt_generation = cli->opt_generation; + state->current_option = cli->current_option; + state->is_short = cli->is_short; + state->whole_negated = cli->whole_negated; + state->current_short = cli->current_short; + state->negated_by_no = cli->negated_by_no; +} + + +/** @param clp the parser + * @param state parser state + * + * The parser state in @a state is restored into @a clp. The next call to + * Clp_Next() will return the same result as it would have at the time @a + * state was saved (probably by Clp_SaveParser(@a clp, @a state)). + * + * A parser state contains information about arguments (argc and argv; see + * Clp_SetArguments()) and option processing (Clp_SetOptionProcessing()), but + * not about options (Clp_SetOptions()). Changes to options and value types + * are preserved across Clp_RestoreParser(). + * + * @sa Clp_NewParserState, Clp_SaveParser + */ +void +Clp_RestoreParser(Clp_Parser *clp, const Clp_ParserState *state) +{ + Clp_Internal *cli = clp->internal; + cli->argv = state->argv; + cli->argc = state->argc; + memcpy(cli->option_chars, state->option_chars, Clp_OptionCharsSize); + cli->xtext = state->xtext; + cli->option_processing = state->option_processing; + cli->is_short = state->is_short; + cli->whole_negated = state->whole_negated; + cli->current_short = state->current_short; + cli->negated_by_no = state->negated_by_no; + if (cli->opt_generation == state->opt_generation) + cli->current_option = state->current_option; + else + cli->current_option = -1; +} + + +/******* + * Clp_Next and its helpers + **/ + +static void +set_option_text(Clp_Internal *cli, const char *text, int n_option_chars) +{ + assert(n_option_chars < Clp_OptionCharsSize); + memcpy(cli->option_chars, text, n_option_chars); + cli->option_chars[n_option_chars] = 0; + cli->xtext = text + n_option_chars; +} + +static int +get_oclass(Clp_Parser *clp, const char *text, int *ocharskip) +{ + int c; + if (clp->internal->utf8) { + const char *s; + c = decode_utf8(text, &s); + *ocharskip = s - text; + } else { + c = (unsigned char) text[0]; + *ocharskip = 1; + } + return Clp_OptionChar(clp, c); +} + +static int +next_argument(Clp_Parser *clp, int want_argument) + /* Moves clp to the next argument. + Returns 1 if it finds another option. + Returns 0 if there aren't any more arguments. + Returns 0, sets clp->have_val = 1, and sets clp->vstr to the argument + if the next argument isn't an option. + If want_argument > 0, it'll look for an argument. + want_argument == 1: Accept arguments that start with Clp_NotOption + or Clp_LongImplicit. + want_argument == 2: Accept ALL arguments. + + Where is the option stored when this returns? + Well, cli->argv[0] holds the whole of the next command line argument. + cli->option_chars holds a string: what characters began the option? + It is generally "-" or "--". + cli->text holds the text of the option: + for short options, cli->text[0] is the relevant character; + for long options, cli->text holds the rest of the option. */ +{ + Clp_Internal *cli = clp->internal; + const char *text; + int oclass, ocharskip; + + /* clear relevant flags */ + clp->have_val = 0; + clp->vstr = 0; + cli->could_be_short = 0; + + /* if we're in a string of short options, move up one char in the string */ + if (cli->is_short) { + cli->xtext += clp_utf8_charlen(cli, cli->xtext); + if (cli->xtext[0] == 0) + cli->is_short = 0; + else if (want_argument > 0) { + /* handle -O[=]argument case */ + clp->have_val = 1; + if (cli->xtext[0] == '=') + clp->vstr = cli->xtext + 1; + else + clp->vstr = cli->xtext; + cli->is_short = 0; + return 0; + } + } + + /* if in short options, we're all set */ + if (cli->is_short) + return 1; + + /** if not in short options, move to the next argument **/ + cli->whole_negated = 0; + cli->xtext = 0; + + if (cli->argc <= 1) + return 0; + + cli->argc--; + cli->argv++; + text = cli->argv[0]; + + if (want_argument > 1) + goto not_option; + + if (text[0] == '-' && text[1] == '-') { + oclass = Clp_DoubledLong; + ocharskip = 2; + } else + oclass = get_oclass(clp, text, &ocharskip); + + /* If this character could introduce either a short or a long option, + try a long option first, but remember that short's a possibility for + later. */ + if ((oclass & (Clp_Short | Clp_ShortNegated)) + && (oclass & (Clp_Long | Clp_LongNegated))) { + oclass &= ~(Clp_Short | Clp_ShortNegated); + if (text[ocharskip]) + cli->could_be_short = 1; + } + + switch (oclass) { + + case Clp_Short: + cli->is_short = 1; + goto check_singleton; + + case Clp_ShortNegated: + cli->is_short = 1; + cli->whole_negated = 1; + goto check_singleton; + + case Clp_Long: + goto check_singleton; + + case Clp_LongNegated: + cli->whole_negated = 1; + goto check_singleton; + + check_singleton: + /* For options introduced with one character, option-char, + '[option-char]' alone is NOT an option. */ + if (!text[ocharskip]) + goto not_option; + set_option_text(cli, text, ocharskip); + break; + + case Clp_LongImplicit: + /* LongImplict: option_chars == "" (since all chars are part of the + option); restore head -> text of option */ + if (want_argument > 0) + goto not_option; + set_option_text(cli, text, 0); + break; + + case Clp_DoubledLong: + set_option_text(cli, text, ocharskip); + break; + + not_option: + case Clp_NotOption: + cli->is_short = 0; + clp->have_val = 1; + clp->vstr = text; + return 0; + + default: + assert(0 /* CLP misconfiguration: bad option type */); + + } + + return 1; +} + + +static void +switch_to_short_argument(Clp_Parser *clp) +{ + Clp_Internal *cli = clp->internal; + const char *text = cli->argv[0]; + int ocharskip, oclass = get_oclass(clp, text, &ocharskip); + assert(cli->could_be_short); + cli->is_short = 1; + cli->whole_negated = (oclass & Clp_ShortNegated ? 1 : 0); + set_option_text(cli, cli->argv[0], ocharskip); +} + + +static int +find_long(Clp_Parser *clp, const char *arg) + /* If arg corresponds to one of clp's options, finds that option & + returns it. If any argument is given after an = sign in arg, sets + clp->have_val = 1 and clp->vstr to that argument. Sets cli->ambiguous + to 1 iff there was no match because the argument was ambiguous. */ +{ + Clp_Internal *cli = clp->internal; + int optno, len, lmm; + const Clp_Option *opt = cli->opt; + const Clp_InternOption *iopt; + int first_negative_ambiguous; + + /* Look for a normal option. */ + optno = find_prefix_opt + (clp, arg, cli->nopt, opt, cli->iopt, + &cli->ambiguous, cli->ambiguous_values); + if (optno >= 0) + goto worked; + + /* If we can't find it, look for a negated option. */ + /* I know this is silly, but it makes me happy to accept + --no-no-option as a double negative synonym for --option. :) */ + first_negative_ambiguous = cli->ambiguous; + while (arg[0] == 'n' && arg[1] == 'o' && arg[2] == '-') { + arg += 3; + clp->negated = !clp->negated; + optno = find_prefix_opt + (clp, arg, cli->nopt, opt, cli->iopt, + &cli->ambiguous, cli->ambiguous_values); + if (optno >= 0) + goto worked; + } + + /* No valid option was found; return 0. Mark the ambiguous values found + through '--no' by making them negative. */ + { + int i, max = cli->ambiguous; + if (max > MAX_AMBIGUOUS_VALUES) max = MAX_AMBIGUOUS_VALUES; + for (i = first_negative_ambiguous; i < max; i++) + cli->ambiguous_values[i] = -cli->ambiguous_values[i] - 1; + } + return -1; + + worked: + iopt = &cli->iopt[optno]; + lmm = (clp->negated ? iopt->lmmneg : iopt->lmmpos); + if (cli->could_be_short + && (clp->negated ? iopt->lmmneg_short : iopt->lmmpos_short)) { + int first_charlen = clp_utf8_charlen(cli, arg); + lmm = (first_charlen >= lmm ? first_charlen + 1 : lmm); + } + len = argcmp(opt[optno].long_name + iopt->ilongoff, arg, lmm, 1); + assert(len > 0); + if (arg[len] == '=') { + clp->have_val = 1; + clp->vstr = arg + len + 1; + } + return optno; +} + + +static int +find_short(Clp_Parser *clp, const char *text) + /* If short_name corresponds to one of clp's options, returns it. */ +{ + Clp_Internal *cli = clp->internal; + const Clp_Option *opt = cli->opt; + const Clp_InternOption *iopt = cli->iopt; + int i, c; + if (clp->internal->utf8) + c = decode_utf8(text, 0); + else + c = (unsigned char) *text; + + for (i = 0; i < cli->nopt; i++) + if (iopt[i].ishort && opt[i].short_name == c + && (clp->negated ? iopt[i].ineg : iopt[i].ipos)) + return i; + + return -1; +} + + +/** @param clp the parser + * @return option ID of next option + * + * Parse the next argument from the argument list, store information about + * that argument in the fields of @a clp, and return the option's ID. + * + * If an argument was successfully parsed, that option's ID is returned. + * Other possible return values are: + * + * <dl> + * <dt>Clp_Done</dt> + * <dd>There are no more arguments.</dd> + * <dt>Clp_NotOption</dt> + * <dd>The next argument was not an option. The argument's text is @a + * clp->vstr (and @a clp->val.s).</dd> + * <dt>Clp_BadOption</dt> + * <dd>The next argument was a bad option: either an option that wasn't + * understood, or an option lacking a required value, or an option whose value + * couldn't be parsed. The option has been skipped.</dd> + * <dt>Clp_Error</dt> + * <dd>There was an internal error. This should never occur unless a user + * messes with, for example, a Clp_Option array.</dd> + * </dl> + * + * The fields of @a clp are set as follows. + * + * <dl> + * <dt><tt>negated</tt></dt> + * <dd>1 if the option was negated, 0 if it wasn't.</dd> + * <dt><tt>have_val</tt></dt> + * <dd>1 if the option had a value, 0 if it didn't. Note that negated options + * are not allowed to have values.</dd> + * <dt><tt>vstr</tt></dt> + * <dd>The value string, if any. NULL if there was no value.</dd> + * <dt><tt>val</tt></dt> + * <dd>An option's value type will parse the value string into this + * union.</dd> + * </dl> + * + * The parsed argument is shifted off the argument list, so that sequential + * calls to Clp_Next() step through the arugment list. + */ +int +Clp_Next(Clp_Parser *clp) +{ + Clp_Internal *cli = clp->internal; + int optno; + const Clp_Option *opt; + Clp_ParserState clpsave; + int vtpos, complain; + + /* Set up clp */ + cli->current_option = -1; + cli->ambiguous = 0; + + /* Get the next argument or option */ + if (!next_argument(clp, cli->option_processing ? 0 : 2)) { + clp->val.s = clp->vstr; + return clp->have_val ? Clp_NotOption : Clp_Done; + } + + clp->negated = cli->whole_negated; + if (cli->is_short) + optno = find_short(clp, cli->xtext); + else + optno = find_long(clp, cli->xtext); + + /* If there's ambiguity between long & short options, and we couldn't + find a long option, look for a short option */ + if (optno < 0 && cli->could_be_short) { + switch_to_short_argument(clp); + optno = find_short(clp, cli->xtext); + } + + /* If we didn't find an option... */ + if (optno < 0 || (clp->negated && !cli->iopt[optno].ineg)) { + /* default processing for the "--" option: turn off option processing + and return the next argument */ + if (strcmp(cli->argv[0], "--") == 0) { + Clp_SetOptionProcessing(clp, 0); + return Clp_Next(clp); + } + + /* otherwise, report some error or other */ + if (cli->ambiguous) + ambiguity_error(clp, cli->ambiguous, cli->ambiguous_values, + cli->opt, cli->iopt, cli->option_chars, + "option %`%s%s%' is ambiguous", + cli->option_chars, cli->xtext); + else if (cli->is_short && !cli->could_be_short) + Clp_OptionError(clp, "unrecognized option %`%s%C%'", + cli->option_chars, cli->xtext); + else + Clp_OptionError(clp, "unrecognized option %`%s%s%'", + cli->option_chars, cli->xtext); + + return Clp_BadOption; + } + + /* Set the current option */ + cli->current_option = optno; + cli->current_short = cli->is_short; + cli->negated_by_no = clp->negated && !cli->whole_negated; + + /* The no-argument (or should-have-no-argument) case */ + if (clp->negated + || (!cli->iopt[optno].imandatory && !cli->iopt[optno].ioptional)) { + if (clp->have_val) { + Clp_OptionError(clp, "%`%O%' can't take an argument"); + return Clp_BadOption; + } else + return cli->opt[optno].option_id; + } + + /* Get an argument if we need one, or if it's optional */ + /* Sanity-check the argument type. */ + opt = &cli->opt[optno]; + if (opt->val_type <= 0) + return Clp_Error; + vtpos = val_type_binsearch(cli, opt->val_type); + if (vtpos == cli->nvaltype || cli->valtype[vtpos].val_type != opt->val_type) + return Clp_Error; + + /* complain == 1 only if the argument was explicitly given, + or it is mandatory. */ + complain = (clp->have_val != 0) || cli->iopt[optno].imandatory; + Clp_SaveParser(clp, &clpsave); + + if (cli->iopt[optno].imandatory && !clp->have_val) { + /* Mandatory argument case */ + /* Allow arguments to options to start with a dash, but only if the + argument type allows it by not setting Clp_DisallowOptions */ + int disallow = (cli->valtype[vtpos].flags & Clp_DisallowOptions) != 0; + next_argument(clp, disallow ? 1 : 2); + if (!clp->have_val) { + int got_option = cli->xtext != 0; + Clp_RestoreParser(clp, &clpsave); + if (got_option) + Clp_OptionError(clp, "%`%O%' requires a non-option argument"); + else + Clp_OptionError(clp, "%`%O%' requires an argument"); + return Clp_BadOption; + } + + } else if (cli->is_short && !clp->have_val + && cli->xtext[clp_utf8_charlen(cli, cli->xtext)]) + /* The -[option]argument case: + Assume that the rest of the current string is the argument. */ + next_argument(clp, 1); + + /* Parse the argument */ + if (clp->have_val) { + Clp_ValType *atr = &cli->valtype[vtpos]; + if (atr->func(clp, clp->vstr, complain, atr->user_data) <= 0) { + /* parser failed */ + clp->have_val = 0; + if (cli->iopt[optno].imandatory) + return Clp_BadOption; + else + Clp_RestoreParser(clp, &clpsave); + } + } + + return opt->option_id; +} + + +/** @param clp the parser + * @param allow_options whether options will be allowed + * + * Remove and return the next argument from @a clp's argument array. If there + * are no arguments left, or if the next argument is an option and @a + * allow_options != 0, then returns null. + */ +const char * +Clp_Shift(Clp_Parser *clp, int allow_options) + /* Returns the next argument from the argument list without parsing it. + If there are no more arguments, returns 0. */ +{ + Clp_ParserState clpsave; + Clp_SaveParser(clp, &clpsave); + next_argument(clp, allow_options ? 2 : 1); + if (!clp->have_val) + Clp_RestoreParser(clp, &clpsave); + return clp->vstr; +} + + +/******* + * Clp_OptionError + **/ + +typedef struct Clp_BuildString { + char *text; + char *pos; + int capacity; + int bad; +} Clp_BuildString; + +static Clp_BuildString * +new_build_string(void) +{ + Clp_BuildString *bs = (Clp_BuildString *)malloc(sizeof(Clp_BuildString)); + if (!bs) goto bad; + bs->text = (char *)malloc(256); + if (!bs->text) goto bad; + bs->pos = bs->text; + bs->capacity = 256; + bs->bad = 0; + return bs; + + bad: + if (bs) free(bs); + return 0; +} + +static void +free_build_string(Clp_BuildString *bs) +{ + if (bs) free(bs->text); + free(bs); +} + +static int +grow_build_string(Clp_BuildString *bs, int want) +{ + char *new_text; + int ipos = bs->pos - bs->text; + int new_capacity = bs->capacity; + while (want >= new_capacity) + new_capacity *= 2; + new_text = (char *)realloc(bs->text, new_capacity); + if (!new_text) { + bs->bad = 1; + return 0; + } else { + bs->text = new_text; + bs->pos = bs->text + ipos; + bs->capacity = new_capacity; + return 1; + } +} + +#define ENSURE_BUILD_STRING(bs, space) \ + ((((bs)->pos - (bs)->text) + (space) >= (bs)->capacity) \ + || grow_build_string((bs), ((bs)->pos - (bs)->text) + (space))) + +static void +append_build_string(Clp_BuildString *bs, const char *s, int l) +{ + if (l < 0) + l = strlen(s); + if (ENSURE_BUILD_STRING(bs, l)) { + memcpy(bs->pos, s, l); + bs->pos += l; + } +} + + +static Clp_BuildString * +Clp_VaOptionError(Clp_Parser *clp, Clp_BuildString *bs, + const char *fmt, va_list val) +{ + Clp_Internal *cli = clp->internal; + const char *percent; + int c; + + if (!bs) + bs = new_build_string(); + if (!bs) + return 0; + if (cli->program_name && cli->program_name[0]) { + append_build_string(bs, cli->program_name, -1); + append_build_string(bs, ": ", 2); + } + + for (percent = strchr(fmt, '%'); percent; percent = strchr(fmt, '%')) { + append_build_string(bs, fmt, percent - fmt); + switch (*++percent) { + + case 's': { + const char *s = va_arg(val, const char *); + if (s) + append_build_string(bs, s, -1); + else + append_build_string(bs, "(null)", 6); + break; + } + + case 'C': { + const char *s = va_arg(val, const char *); + if (cli->utf8) + c = decode_utf8(s, 0); + else + c = (unsigned char) *s; + goto char_c; + } + + case 'c': + c = va_arg(val, int); + goto char_c; + + char_c: + if (ENSURE_BUILD_STRING(bs, 4)) { + if (c >= 32 && c <= 126) + *bs->pos++ = c; + else if (c < 32) { + *bs->pos++ = '^'; + *bs->pos++ = c + 64; + } else if (cli->utf8 && c >= 127 && c < 0x110000) { + bs->pos = encode_utf8(bs->pos, 4, c); + } else if (c >= 127 && c <= 255) { + sprintf(bs->pos, "\\%03o", c & 0xFF); + bs->pos += 4; + } else { + *bs->pos++ = '\\'; + *bs->pos++ = '?'; + } + } + break; + + case 'd': { + int d = va_arg(val, int); + if (ENSURE_BUILD_STRING(bs, 32)) { + sprintf(bs->pos, "%d", d); + bs->pos = strchr(bs->pos, 0); + } + break; + } + + case 'O': { + int optno = cli->current_option; + const Clp_Option *opt = &cli->opt[optno]; + if (optno < 0) + append_build_string(bs, "(no current option!)", -1); + else if (cli->current_short) { + append_build_string(bs, cli->option_chars, -1); + if (ENSURE_BUILD_STRING(bs, 5)) { + if (cli->utf8) + bs->pos = encode_utf8(bs->pos, 5, opt->short_name); + else + *bs->pos++ = opt->short_name; + } + } else if (cli->negated_by_no) { + append_build_string(bs, cli->option_chars, -1); + append_build_string(bs, "no-", 3); + append_build_string(bs, opt->long_name + cli->iopt[optno].ilongoff, -1); + } else { + append_build_string(bs, cli->option_chars, -1); + append_build_string(bs, opt->long_name + cli->iopt[optno].ilongoff, -1); + } + break; + } + + case '%': + if (ENSURE_BUILD_STRING(bs, 1)) + *bs->pos++ = '%'; + break; + + case '`': + append_build_string(bs, (cli->utf8 ? "\342\200\230" : "'"), -1); + break; + + case '\'': + append_build_string(bs, (cli->utf8 ? "\342\200\231" : "'"), -1); + break; + + default: + if (ENSURE_BUILD_STRING(bs, 2)) { + *bs->pos++ = '%'; + *bs->pos++ = *percent; + } + break; + + } + fmt = ++percent; + } + + append_build_string(bs, fmt, -1); + append_build_string(bs, "\n", 1); + + return bs; +} + +static void +do_error(Clp_Parser *clp, Clp_BuildString *bs) +{ + const char *text; + if (bs && !bs->bad) { + *bs->pos = 0; + text = bs->text; + } else + text = "out of memory\n"; + + if (clp->internal->error_handler != 0) + (*clp->internal->error_handler)(clp, text); + else + fputs(text, stderr); +} + +/** @param clp the parser + * @param format error format + * + * Format an error message from @a format and any additional arguments in the + * ellipsis. The resulting error string by printing it to standard error or + * passing it to Clp_SetErrorHandler. + * + * The following format characters are accepted: + * + * <dl> + * <dt><tt>%</tt><tt>c</tt></dt> + * <dd>A character (type <tt>int</tt>). Control characters are printed in + * caret notation. If the parser is in UTF-8 mode, the character is formatted + * in UTF-8. Otherwise, special characters are printed with backslashes and + * octal notation.</dd> + * <dt><tt>%</tt><tt>s</tt></dt> + * <dd>A string (type <tt>const char *</tt>).</dd> + * <dt><tt>%</tt><tt>C</tt></dt> + * <dd>The argument is a string (type <tt>const char *</tt>). The first + * character in this string is printed. If the parser is in UTF-8 mode, this + * may involve multiple bytes.</dd> + * <dt><tt>%</tt><tt>d</tt></dt> + * <dd>An integer (type <tt>int</tt>). Printed in decimal.</dd> + * <dt><tt>%</tt><tt>O</tt></dt> + * <dd>The current option. No values are read from the argument list; the + * current option is defined in the Clp_Parser object itself.</dd> + * <dt><tt>%%</tt></dt> + * <dd>Prints a percent character.</dd> + * <dt><tt>%</tt><tt>`</tt></dt> + * <dd>In UTF-8 mode, prints a left single quote. Otherwise prints a single + * quote.</dd> + * <dt><tt>%</tt><tt>'</tt></dt> + * <dd>In UTF-8 mode, prints a right single quote. Otherwise prints a single + * quote.</dd> + * </dl> + * + * Note that no flag characters, precision, or field width characters are + * currently supported. + * + * @sa Clp_SetErrorHandler + */ +int +Clp_OptionError(Clp_Parser *clp, const char *format, ...) +{ + Clp_BuildString *bs; + va_list val; + va_start(val, format); + bs = Clp_VaOptionError(clp, 0, format, val); + va_end(val); + do_error(clp, bs); + free_build_string(bs); + return 0; +} + +static int +ambiguity_error(Clp_Parser *clp, int ambiguous, int *ambiguous_values, + const Clp_Option *opt, const Clp_InternOption *iopt, + const char *prefix, const char *fmt, ...) +{ + Clp_Internal *cli = clp->internal; + Clp_BuildString *bs; + int i; + va_list val; + va_start(val, fmt); + bs = Clp_VaOptionError(clp, 0, fmt, val); + if (!bs) goto done; + + if (clp->internal->program_name && clp->internal->program_name[0]) { + append_build_string(bs, clp->internal->program_name, -1); + append_build_string(bs, ": ", 2); + } + append_build_string(bs, "(Possibilities are", -1); + + for (i = 0; i < ambiguous && i < MAX_AMBIGUOUS_VALUES; i++) { + int value = ambiguous_values[i]; + const char *no_dash = ""; + if (value < 0) + value = -(value + 1), no_dash = "no-"; + if (i == 0) + append_build_string(bs, " ", 1); + else if (i == ambiguous - 1) + append_build_string(bs, (i == 1 ? " and " : ", and "), -1); + else + append_build_string(bs, ", ", 2); + append_build_string(bs, (cli->utf8 ? "\342\200\230" : "'"), -1); + append_build_string(bs, prefix, -1); + append_build_string(bs, no_dash, -1); + append_build_string(bs, opt[value].long_name + iopt[value].ilongoff, -1); + append_build_string(bs, (cli->utf8 ? "\342\200\231" : "'"), -1); + } + + if (ambiguous > MAX_AMBIGUOUS_VALUES) + append_build_string(bs, ", and others", -1); + append_build_string(bs, ".)\n", -1); + va_end(val); + + done: + do_error(clp, bs); + free_build_string(bs); + return 0; +} + +static int +copy_string(char *buf, int buflen, int bufpos, const char *what) +{ + int l = strlen(what); + if (l > buflen - bufpos - 1) + l = buflen - bufpos - 1; + memcpy(buf + bufpos, what, l); + return l; +} + +/** @param clp the parser + * @param buf output buffer + * @param len length of output buffer + * @return number of characters written to the buffer, not including the terminating NUL + * + * A string that looks like the last option parsed by @a clp is extracted into + * @a buf. The correct option characters are put into the string first, + * followed by the option text. The output buffer is null-terminated unless + * @a len == 0. + * + * @sa Clp_CurOptionName + */ +int +Clp_CurOptionNameBuf(Clp_Parser *clp, char *buf, int len) +{ + Clp_Internal *cli = clp->internal; + int optno = cli->current_option; + int pos = 0; + if (optno < 0) + pos += copy_string(buf, len, pos, "(no current option!)"); + else if (cli->current_short) { + pos += copy_string(buf, len, pos, cli->option_chars); + if (cli->utf8) + pos = (encode_utf8(buf + pos, len - pos - 1, cli->opt[optno].short_name) - buf); + else if (pos < len - 1) + buf[pos++] = cli->opt[optno].short_name; + } else if (cli->negated_by_no) { + pos += copy_string(buf, len, pos, cli->option_chars); + pos += copy_string(buf, len, pos, "no-"); + pos += copy_string(buf, len, pos, cli->opt[optno].long_name + cli->iopt[optno].ilongoff); + } else { + pos += copy_string(buf, len, pos, cli->option_chars); + pos += copy_string(buf, len, pos, cli->opt[optno].long_name + cli->iopt[optno].ilongoff); + } + if (pos < len) + buf[pos] = 0; + return pos; +} + +/** @param clp the parser + * @return string describing the current option + * + * This function acts like Clp_CurOptionNameBuf(), but returns a pointer into + * a static buffer that will be rewritten on the next call to + * Clp_CurOptionName(). + * + * @note This function is not thread safe. + * + * @sa Clp_CurOptionName + */ +const char * +Clp_CurOptionName(Clp_Parser *clp) +{ + static char buf[256]; + Clp_CurOptionNameBuf(clp, buf, 256); + return buf; +} + +#ifdef __cplusplus +} +#endif diff --git a/Build/source/utils/t1utils/t1utils-1.35/config.h.in b/Build/source/utils/t1utils/t1utils-1.35/config.h.in new file mode 100644 index 00000000000..d52eb2d2319 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/config.h.in @@ -0,0 +1,98 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +#ifndef T1UTILS_CONFIG_H +#define T1UTILS_CONFIG_H + +/* Define if intXX_t types are not available. */ +#undef HAVE_FAKE_INT_TYPES + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if the system has the type `uintptr_t'. */ +#undef HAVE_UINTPTR_T + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have u_intXX_t types but not uintXX_t types. */ +#undef HAVE_U_INT_TYPES + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* The size of `unsigned int', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_INT + +/* The size of `unsigned long', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_LONG + +/* The size of `void *', as computed by sizeof. */ +#undef SIZEOF_VOID_P + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +#include <lcdf/inttypes.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Prototype strerror if we don't have it. */ +#if !HAVE_STRERROR +char *strerror(int errno); +#endif + +#ifdef __cplusplus +} +/* Get rid of a possible inline macro under C++. */ +# define inline inline +#endif + +#endif /* T1UTILS_CONFIG_H */ diff --git a/Build/source/utils/t1utils/t1utils-1.35/configure.ac b/Build/source/utils/t1utils/t1utils-1.35/configure.ac new file mode 100644 index 00000000000..8df136fdcf5 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/configure.ac @@ -0,0 +1,118 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(t1ascii.c) +AM_INIT_AUTOMAKE(t1utils, 1.35) +AM_CONFIG_HEADER(config.h) +AM_MAINTAINER_MODE + +AC_PROG_CC +AC_C_CONST + +AC_ARG_ENABLE(warnings, +[ --enable-warnings compile with -Wall], +if test "$enableval" = yes ; then + CFLAGS="$CFLAGS -W -Wall" +fi) + + +dnl +dnl strerror()? +dnl + +AC_REPLACE_FUNCS(strerror) + + +dnl +dnl integer types +dnl + +AC_CHECK_HEADERS(inttypes.h, have_inttypes_h=yes, have_inttypes_h=no) +AC_CHECK_HEADERS(sys/types.h, have_sys_types_h=yes, have_sys_types_h=no) + +if test $have_inttypes_h = no -a $have_sys_types_h = yes; then + AC_CACHE_CHECK([for uintXX_t typedefs], ac_cv_uint_t, + [AC_EGREP_HEADER(dnl +changequote(<<,>>)<<(^|[^a-zA-Z_0-9])uint32_t[^a-zA-Z_0-9]>>changequote([,]), + sys/types.h, ac_cv_uint_t=yes, ac_cv_uint_t=no)]) +fi +if test $have_inttypes_h = no -a $have_sys_types_h = yes -a "$ac_cv_uint_t" = no; then + AC_CACHE_CHECK([for u_intXX_t typedefs], ac_cv_u_int_t, + [AC_EGREP_HEADER(dnl +changequote(<<,>>)<<(^|[^a-zA-Z_0-9])u_int32_t[^a-zA-Z_0-9]>>changequote([,]), + sys/types.h, ac_cv_u_int_t=yes, ac_cv_u_int_t=no)]) +fi +if test $have_inttypes_h = yes -o "$ac_cv_uint_t" = yes; then + : +elif test "$ac_cv_u_int_t" = yes; then + AC_DEFINE(HAVE_U_INT_TYPES, 1, [Define if you have u_intXX_t types but not uintXX_t types.]) +else + AC_MSG_WARN([ +========================================= + +Neither uint32_t nor u_int32_t defined by <inttypes.h> or <sys/types.h>! +Assuming "short" has 16 bits and "int" has 32 bits. + +=========================================]) + AC_DEFINE(HAVE_FAKE_INT_TYPES, 1, [Define if intXX_t types are not available.]) +fi + +AC_CHECK_TYPES(uintptr_t, [], [], +[#if HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#if HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +]) + +AC_CHECK_SIZEOF(void *) +AC_CHECK_SIZEOF(unsigned long) +AC_CHECK_SIZEOF(unsigned int) + + +dnl +dnl verbatim portions of the header +dnl + +AH_TOP([#ifndef T1UTILS_CONFIG_H +#define T1UTILS_CONFIG_H]) + +AH_BOTTOM([#include <lcdf/inttypes.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Prototype strerror if we don't have it. */ +#if !HAVE_STRERROR +char *strerror(int errno); +#endif + +#ifdef __cplusplus +} +/* Get rid of a possible inline macro under C++. */ +# define inline inline +#endif + +#endif /* T1UTILS_CONFIG_H */]) + + +dnl +dnl Multiplatform output directories (for teTeX and TeX Live) +dnl + +AC_CANONICAL_HOST +AC_ARG_ENABLE([multiplatform], + [AS_HELP_STRING([--enable-multiplatform], + [put executables into bin/PLATFORM and libraries into lib/PLATFORM])]) +if test "x$enable_multiplatform" = xyes; then + test "x$bindir" = 'x${exec_prefix}/bin' && bindir="$bindir/$host" + test "x$libdir" = 'x${exec_prefix}/lib' && libdir="$libdir/$host" +fi + + +dnl +dnl Output +dnl + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/Build/source/utils/t1utils/t1utils-1.35/include/lcdf/clp.h b/Build/source/utils/t1utils/t1utils-1.35/include/lcdf/clp.h new file mode 100644 index 00000000000..bcec630fe49 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/include/lcdf/clp.h @@ -0,0 +1,298 @@ +/* -*- related-file-name: "../../liblcdf/clp.c" -*- */ +#ifndef LCDF_CLP_H +#define LCDF_CLP_H +#ifdef __cplusplus +extern "C" { +#endif + +/* clp.h - Public interface to CLP. + * This file is part of CLP, the command line parser package. + * + * Copyright (c) 1997-2008 Eddie Kohler, ekohler@gmail.com + * + * 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://www.pdos.lcs.mit.edu/click/license.html. 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 + * legally binding. */ + +typedef struct Clp_Option Clp_Option; +typedef struct Clp_Parser Clp_Parser; +typedef struct Clp_ParserState Clp_ParserState; + + +/** @brief Option description. + * + * CLP users declare arrays of Clp_Option structures to specify what options + * should be parsed. + * @sa Clp_NewParser, Clp_SetOptions */ +struct Clp_Option { + const char *long_name; /**< Name of long option, or NULL if the option + has no long name. */ + int short_name; /**< Character defining short option, or 0 if + the option has no short name. */ + int option_id; /**< User-specified ID defining option, + returned by Clp_Next. */ + int val_type; /**< ID of option's value type, or 0 if option + takes no value. */ + int flags; /**< Option parsing flags. */ +}; + +/** @name Value types + * These values describe the type of an option's argument and are used in + * the Clp_Option val_type field. For example, if an option took integers, its + * Clp_Option structure would have val_type set to Clp_ValInt. */ +/**@{*/ +#define Clp_NoVal 0 /**< @brief Option takes no value. */ +#define Clp_ValString 1 /**< @brief Option value is an + arbitrary string. */ +#define Clp_ValStringNotOption 2 /**< @brief Option value is a + non-option string. + + See Clp_DisallowOptions. */ +#define Clp_ValBool 3 /**< @brief Option value is a + boolean. + + Accepts "true", "false", "yes", "no", "1", and "0", or any + prefixes thereof. The match is case-insensitive. */ +#define Clp_ValInt 4 /**< @brief Option value is a + signed int. + + Accepts an optional "+" or "-" sign, followed by one or more + digits. The digits may be include a "0x" or "0X" prefix, for + a hexidecimal number, or a "0" prefix, for an octal number; + otherwise it is decimal. */ +#define Clp_ValUnsigned 5 /**< @brief Option value is an + unsigned int. + + Accepts an optional "+" sign, followed by one or more + digits. The digits may be include a "0x" or "0X" prefix, for + a hexidecimal number, or a "0" prefix, for an octal number; + otherwise it is decimal. */ +#define Clp_ValDouble 6 /**< @brief Option value is a + double. + Accepts a real number as defined by strtod(). */ +#define Clp_ValFirstUser 10 /**< @brief Value types >= + Clp_ValFirstUser are available + for user types. */ +/**@}*/ + +/** @name Option flags + * These flags are used in the Clp_Option flags field. */ +/**@{*/ +#define Clp_Mandatory (1<<0) /**< @brief Option flag: value + is mandatory. + + It is an error if the option has no value. This is the + default if an option has arg_type != 0 and the Clp_Optional + flag is not provided. */ +#define Clp_Optional (1<<1) /**< @brief Option flag: value + is optional. */ +#define Clp_Negate (1<<2) /**< @brief Option flag: option + may be negated. + + --no-[long_name] will be accepted in argument lists. */ +#define Clp_OnlyNegated (1<<3) /**< @brief Option flag: option + <em>must</em> be negated. + + --no-[long_name] will be accepted in argument lists, but + --[long_name] will not. This is the default if long_name + begins with "no-". */ +#define Clp_PreferredMatch (1<<4) /**< @brief Option flag: prefer this + option when matching. + + Prefixes of --[long_name] should map to this option, even if + other options begin with --[long_name]. */ +/**@}*/ + +/** @name Option character types + * These flags are used in to define character types in Clp_SetOptionChar(). */ +/**@{*/ +/* Clp_NotOption 0 */ +#define Clp_Short (1<<0) /**< @brief Option character begins + a set of short options. */ +#define Clp_Long (1<<1) /**< @brief Option character begins + a long option. */ +#define Clp_ShortNegated (1<<2) /**< @brief Option character begins + a set of negated short options. */ +#define Clp_LongNegated (1<<3) /**< @brief Option character begins + a negated long option. */ +#define Clp_LongImplicit (1<<4) /**< @brief Option character can begin + a long option, and is part of that + long option. */ +/**@}*/ + +#define Clp_NotOption 0 /**< @brief Clp_Next value: argument + was not an option. */ +#define Clp_Done -1 /**< @brief Clp_Next value: there are + no more arguments. */ +#define Clp_BadOption -2 /**< @brief Clp_Next value: argument + was an erroneous option. */ +#define Clp_Error -3 /**< @brief Clp_Next value: internal + CLP error. */ + +#define Clp_ValSize 40 /**< @brief Minimum size of the + Clp_Parser val.cs field. */ +#define Clp_ValIntSize 10 /**< @brief Minimum size of the + Clp_Parser val.is field. */ + + +/** @brief A value parsing function. + * @param clp the parser + * @param vstr the value to be parsed + * @param complain if nonzero, report error messages via Clp_OptionError + * @param user_data user data passed to Clp_AddType() + * @return 1 if parsing succeeded, 0 otherwise + */ +typedef int (*Clp_ValParseFunc)(Clp_Parser *clp, const char *vstr, + int complain, void *user_data); + +/** @brief A function for reporting option errors. + * @param clp the parser + * @param message error message + */ +typedef void (*Clp_ErrorHandler)(Clp_Parser *clp, const char *message); + + +/** @brief Command line parser. + * + * A Clp_Parser object defines an instance of CLP, including allowed options, + * value types, and current arguments. + * @sa Clp_NewParser, Clp_SetOptions, Clp_SetArguments */ +struct Clp_Parser { + int negated; /**< Whether the last option was negated. */ + + int have_val; /**< Whether the last option had a value. */ + const char *vstr; /**< The string value provided with the last + option. */ + + union { + int i; + unsigned u; + double d; + const char *s; + void *pv; +#ifdef HAVE_INT64_TYPES + int64_t i64; + uint64_t u64; +#endif + char cs[Clp_ValSize]; + unsigned char ucs[Clp_ValSize]; + int is[Clp_ValIntSize]; + unsigned us[Clp_ValIntSize]; + } val; /**< The parsed value provided with the last + option. */ + + void *user_data; /**< Uninterpreted by CLP; users can set + arbitrarily. */ + + struct Clp_Internal *internal; +}; + +/** @cond never */ +#if __GNUC__ >= 4 +# define CLP_SENTINEL __attribute__((sentinel)) +#else +# define CLP_SENTINEL /* nothing */ +#endif +/** @endcond never */ + + +/** @brief Create a new Clp_Parser. */ +Clp_Parser *Clp_NewParser(int argc, const char * const *argv, + int nopt, const Clp_Option *opt); + +/** @brief Destroy a Clp_Parser object. */ +void Clp_DeleteParser(Clp_Parser *clp); + + +/** @brief Return @a clp's program name. */ +const char *Clp_ProgramName(Clp_Parser *clp); + +/** @brief Set @a clp's program name. */ +const char *Clp_SetProgramName(Clp_Parser *clp, const char *name); + + +/** @brief Set @a clp's error handler function. */ +Clp_ErrorHandler Clp_SetErrorHandler(Clp_Parser *clp, Clp_ErrorHandler errh); + +/** @brief Set @a clp's UTF-8 mode. */ +int Clp_SetUTF8(Clp_Parser *clp, int utf8); + +/** @brief Set @a clp's treatment of character @a c. */ +int Clp_SetOptionChar(Clp_Parser *clp, int c, int type); + +/** @brief Set @a clp's option definitions. */ +int Clp_SetOptions(Clp_Parser *clp, int nopt, const Clp_Option *opt); + +/** @brief Set @a clp's arguments. */ +void Clp_SetArguments(Clp_Parser *clp, int argc, const char * const *argv); + +/** @brief Set whether @a clp is searching for options. */ +int Clp_SetOptionProcessing(Clp_Parser *clp, int on); + + +#define Clp_DisallowOptions (1<<0) /**< @brief Value type flag: value + can't be an option string. + + See Clp_AddType(). */ + +/** @brief Define a new value type for @a clp. */ +int Clp_AddType(Clp_Parser *clp, int val_type, int flags, + Clp_ValParseFunc parser, void *user_data); + + +#define Clp_AllowNumbers (1<<0) /**< @brief String list flag: allow + explicit numbers. + + See Clp_AddStringListType() and Clp_AddStringListTypeVec(). */ + +/** @brief Define a new string list value type for @a clp. */ +int Clp_AddStringListTypeVec(Clp_Parser *clp, int val_type, int flags, + int nstrs, const char * const *strs, + const int *vals); + +/** @brief Define a new string list value type for @a clp. */ +int Clp_AddStringListType(Clp_Parser *clp, int val_type, int flags, ...) + CLP_SENTINEL; + + +/** @brief Parse and return the next argument from @a clp. */ +int Clp_Next(Clp_Parser *clp); + +/** @brief Return the next argument from @a clp without option parsing. */ +const char *Clp_Shift(Clp_Parser *clp, int allow_options); + + +/** @brief Create a new Clp_ParserState. */ +Clp_ParserState *Clp_NewParserState(void); + +/** @brief Destroy a Clp_ParserState object. */ +void Clp_DeleteParserState(Clp_ParserState *state); + +/** @brief Save @a clp's current state in @a state. */ +void Clp_SaveParser(const Clp_Parser *clp, Clp_ParserState *state); + +/** @brief Restore parser state from @a state into @a clp. */ +void Clp_RestoreParser(Clp_Parser *clp, const Clp_ParserState *state); + + +/** @brief Report a parser error. */ +int Clp_OptionError(Clp_Parser *clp, const char *format, ...); + +/** @brief Extract the current option as a string. */ +int Clp_CurOptionNameBuf(Clp_Parser *clp, char *buf, int len); + +/** @brief Extract the current option as a string. */ +const char *Clp_CurOptionName(Clp_Parser *clp); + +#undef CLP_SENTINEL +#ifdef __cplusplus +} +#endif +#endif diff --git a/Build/source/utils/t1utils/t1utils-1.35/include/lcdf/inttypes.h b/Build/source/utils/t1utils/t1utils-1.35/include/lcdf/inttypes.h new file mode 100644 index 00000000000..b88e9e9faf0 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/include/lcdf/inttypes.h @@ -0,0 +1,34 @@ +#ifndef LCDF_INTTYPES_H +#define LCDF_INTTYPES_H +/* Define known-width integer types. */ + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#elif defined(HAVE_SYS_TYPES_H) +# include <sys/types.h> +# ifdef HAVE_U_INT_TYPES +typedef u_int8_t uint8_t; +typedef u_int16_t uint16_t; +typedef u_int32_t uint32_t; +# endif +#endif + +#ifdef HAVE_FAKE_INT_TYPES +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +#endif + +#ifndef HAVE_UINTPTR_T +# if SIZEOF_VOID_P == SIZEOF_UNSIGNED_INT +typedef unsigned int uintptr_t; +# elif SIZEOF_VOID_P == SIZEOF_UNSIGNED_LONG +typedef unsigned long uintptr_t; +# endif +#endif + +/* Note: Windows compilers call these types '[un]signed __int8', etc. */ +#endif diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1ascii.1 b/Build/source/utils/t1utils/t1utils-1.35/t1ascii.1 new file mode 100644 index 00000000000..5f23d0be5da --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1ascii.1 @@ -0,0 +1,51 @@ +.ds V 1.35 +.de M +.BR "\\$1" "(\\$2)\\$3" +.. +.TH T1ASCII 1 "" "Version \*V" +.SH NAME +t1ascii \- convert PostScript Type 1 font from binary to ASCII +.SH SYNOPSIS +.B t1ascii +\%[\fB\-l\fR \fIlength\fR] +\%[\fIinput\fR [\fIoutput\fR]] +.SH DESCRIPTION +.BR t1ascii +converts Adobe Type 1 font programs in PFB (binary) format to PFA +(hexadecimal) format. If the file +.I output +is not specified output goes to the standard output. +If the file +.I input +is not specified input comes from the standard input. +' +.SH OPTIONS +.TP 5 +.BI \-\-line\-length= "num\fR, " \-l " num" +Set the maximum length of encrypted lines in the output to +.I num. +(These are the lines consisting wholly of hexadecimal digits.) The default +is 64. +' +.TP 5 +.BR \-\-warnings ", " \-w +Warn when the input font contains lines longer than 255 characters. +Long lines don't strictly conform to Adobe's Document Structuring +Conventions, and may cause problems with older software. +' +.SH "SEE ALSO" +.LP +.M t1binary 1 , +.M t1unmac 1 , +.M t1mac 1 , +.M t1asm 1 , +.M t1disasm 1 +.LP +.I "Adobe Type 1 Font Format" +.SH AUTHORS +Lee Hetherington (ilh@lcs.mit.edu) +.br +Eddie Kohler (ekohler@gmail.com) +.PP +Ported to Microsoft C/C++ Compiler and MS-DOS operating system by +Kai-Uwe Herbing (herbing@netmbx.netmbx.de). diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1ascii.c b/Build/source/utils/t1utils/t1utils-1.35/t1ascii.c new file mode 100644 index 00000000000..3e174816b4e --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1ascii.c @@ -0,0 +1,306 @@ +/* t1ascii + * + * This program takes an Adobe Type-1 font program in binary (PFB) format and + * converts it to ASCII (PFA) format. + * + * Copyright (c) 1992 by I. Lee Hetherington, all rights reserved. + * + * Permission is hereby granted to use, modify, and distribute this program + * for any purpose provided this copyright notice and the one below remain + * intact. + * + * I. Lee Hetherington (ilh@lcs.mit.edu) + * + * 1.5 and later versions contain changes by, and are maintained by, + * Eddie Kohler <ekohler@gmail.com>. + * + * New change log in `NEWS'. Old change log: + * + * Revision 1.2 92/06/23 10:58:43 ilh + * MSDOS porting by Kai-Uwe Herbing (herbing@netmbx.netmbx.de) + * incoporated. + * + * Revision 1.1 92/05/22 11:47:24 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" + +#ifdef __cplusplus +extern "C" { +#endif + +static FILE *ofp; +static int line_length = 64; + + +/***** + * Command line + **/ + +#define OUTPUT_OPT 301 +#define VERSION_OPT 302 +#define HELP_OPT 303 +#define LINE_LEN_OPT 304 +#define WARNINGS_OPT 305 + +static Clp_Option options[] = { + { "help", 0, HELP_OPT, 0, 0 }, + { "line-length", 'l', LINE_LEN_OPT, Clp_ValInt, 0 }, + { "output", 'o', OUTPUT_OPT, Clp_ValString, 0 }, + { "version", 0, VERSION_OPT, 0, 0 }, + { "warnings", 'w', WARNINGS_OPT, 0, Clp_Negate } +}; +static const char *program_name; +static const char *ifp_filename = "<stdin>"; +static int line_length_warning = -1; + +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); + 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); +} + +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("\ +`T1ascii' translates a PostScript Type 1 font from compact binary (PFB) to\n\ +ASCII (PFA) format. The result is written to the standard output unless an\n\ +OUTPUT file is given.\n\ +\n\ +Usage: %s [OPTION]... [INPUT [OUTPUT]]\n\ +\n\ +Options:\n\ + -l, --line-length=NUM Set max encrypted line length (default 64).\n\ + -o, --output=FILE Write output to FILE.\n\ + -w, --warnings Warn on too-long lines.\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); +} + + +/***** + * PFA font_reader functions + **/ + +static int hexcol = 0; + +static void +pfa_output_ascii(char *data, int len) +{ + if (hexcol) { + putc('\n', ofp); + hexcol = 0; + } + if (line_length_warning == 0 && len > 256) { + line_length_warning = 1; + fprintf(stderr, "%s: warning: %s has lines longer than 255 characters\n%s: (This may cause problems with older printers.)\n", program_name, ifp_filename, program_name); + } + fputs(data, ofp); + if (len && data[len - 1] != '\n') { + int p = len - 2; + while (p > 0 && data[p] != '\n') + p--; + hexcol = (p ? len - p - 1 : hexcol + len); + } +} + +static void +pfa_output_binary(unsigned char *data, int len) +{ + static const char *hexchar = "0123456789abcdef"; + for (; len > 0; len--, data++) { + /* trim hexadecimal lines to line_length columns */ + if (hexcol >= line_length) { + putc('\n', ofp); + hexcol = 0; + } + putc(hexchar[(*data >> 4) & 0xf], ofp); + putc(hexchar[*data & 0xf], ofp); + hexcol += 2; + } +} + +static void +pfa_output_end(void) +{ +} + +#ifdef __cplusplus +} +#endif + + +/***** + * main() + **/ + +int +main(int argc, char *argv[]) +{ + struct font_reader fr; + int c; + FILE *ifp = 0; + + 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 LINE_LEN_OPT: + line_length = clp->val.i; + if (line_length < 8) { + line_length = 8; + error("warning: line length raised to %d", line_length); + } else if (line_length > 1024) { + line_length = 1024; + error("warning: line length lowered to %d", line_length); + } + break; + + 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 WARNINGS_OPT: + line_length_warning = (clp->negated ? -1 : 0); + break; + + case HELP_OPT: + usage(); + exit(0); + break; + + case VERSION_OPT: + printf("t1ascii (LCDF t1utils) %s\n", VERSION); + printf("Copyright (C) 1992-2003 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_filename = "<stdin>"; + 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 (line_length > 255 && line_length_warning == 0) + fprintf(stderr, "%s: warning: selected --line-length is greater than 255\n", program_name); + +#if defined(_MSDOS) || defined(_WIN32) + /* As we are processing a PFB (binary) input */ + /* file, we must set its file mode to binary. */ + _setmode(_fileno(ifp), _O_BINARY); +#endif + + /* prepare font reader */ + fr.output_ascii = pfa_output_ascii; + fr.output_binary = pfa_output_binary; + fr.output_end = pfa_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); + return 0; +} diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1asm.1 b/Build/source/utils/t1utils/t1utils-1.35/t1asm.1 new file mode 100644 index 00000000000..6ed9ba2c11a --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1asm.1 @@ -0,0 +1,96 @@ +.ds V 1.35 +.de M +.BR "\\$1" "(\\$2)\\$3" +.. +.TH T1ASM 1 "" "Version \*V" +.SH NAME +t1asm \- assemble PostScript Type 1 font +.SH SYNOPSIS +.B t1asm +\%[\fB\-a\fR|\fB\-b\fR] +\%[\fB\-l\fR \fIlength\fR] +\%[\fIinput\fR [\fIoutput\fR]] +.SH DESCRIPTION +.B t1asm +assembles Adobe Type 1 font programs into either PFA (hexadecimal) or PFB +(binary) formats from a human-readable form. If the file +.I output +is not specified output goes to the standard output. If the file +.I input +is not specified input comes from the standard input. + +.B t1asm +tokenizes the charstring data and performs eexec and charstring encryption +as specified in the ``black book,'' +.I "Adobe Type 1 Font Format." + +The input must have a line of the form +.RS +.nf +.ft B +/-|{string currentfile exch readstring pop}executeonly def +.ft R +.fi +.RE +which defines the command, in this case `\-|', that is to start charstring +data. It is an error not to define such a command. Another common name for +this command is `RD'. + +After the start of the +.B Subrs +array in the input, all open braces `{' not in a comment begin a +charstring. Such a charstring is terminated by the next non-comment close +brace `}'. Within such a charstring, only comments, integers, and valid +charstring commands are allowed. Valid charstring command names can be +found in +.I "Adobe Type 1 Font Format" +and other documents describing the newer Type 2 opcodes. The format within +a charstring is unimportant as long as integers and commands are separated +by at least a one whitespace (space, tab, newline) character. Note that +within charstrings, comments are discarded because they cannot be encoded. +.SH OPTIONS +.TP 5 +.BR \-\-pfa ", " \-a +Output in PFA (ASCII) format. +.TP 5 +.BR \-\-pfb ", " \-b +Output in PFB (binary) format. This is the default. +.TP +.BI \-\-block\-length= "num\fR, " \-l " num" +PFB only: Set the maximum output block length to +.I num. +The default length is as large as memory allows. +.TP +.BI \-\-line\-length= "num\fR, " \-l " num" +PFA only: Set the maximum length of encrypted lines in the output to +.I num. +(These are the lines consisting wholly of hexadecimal digits.) The default +is 64. +.SH EXAMPLES +.LP +.nf +% t1asm Utopia-Regular.raw > Utopia-Regular.pfb +% t1asm -a Utopia-Regular.raw > Utopia-Regular.pfa +.fi +.SH "SEE ALSO" +.LP +.M t1disasm 1 , +.M t1ascii 1 , +.M t1binary 1 , +.M t1unmac 1 , +.M t1mac 1 +.LP +.I "Adobe Type 1 Font Format" +is available free from Adobe as a PDF file. +http://partners.adobe.com/asn/developer/PDFS/TN/T1_SPEC.PDF +.LP +.I "The Type 2 Charstring Format," +also available from Adobe as a PDF file, describes the newer Type 2 +operators, which are also used in some multiple-master Type 1 fonts like +Adobe Jenson and Kepler. +http://partners.adobe.com/asn/developer/PDFS/TN/5177.Type2.pdf +' +.SH AUTHORS +Lee Hetherington (ilh@lcs.mit.edu) +.br +Eddie Kohler (ekohler@gmail.com) diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1asm.c b/Build/source/utils/t1utils/t1utils-1.35/t1asm.c new file mode 100644 index 00000000000..1b7850daa52 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1asm.c @@ -0,0 +1,808 @@ +/* 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. + * + * Permission is hereby granted to use, modify, and distribute this program + * for any purpose provided this copyright notice and the one below remain + * intact. + * + * I. Lee Hetherington (ilh@lcs.mit.edu) + * + * 1.5 and later versions contain changes by, and are maintained by, + * Eddie Kohler <ekohler@gmail.com>. + * + * 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" + +#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]; + +/* lenIV and charstring start command */ +static int lenIV = 4; +static char cs_start[10]; + +/* for charstring buffering */ +static byte charstring_buf[65535]; +static byte *charstring_bp; + +/* decryption stuff */ +static uint16_t er, cr; +static uint16_t c1 = 52845, 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 */ + { "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(*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(string[0]) || string[0] == '-' || string[0] == '+') { + while (*++string && isdigit(*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; + + 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 > (int)sizeof(charstring_buf)) + fatal_error("charstring buffer overflow"); + *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); + 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); +} + +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, *r; + + 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-2003 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. */ + if (pfb) + _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(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(*p); p++) + ; + eexec_start(p); + continue; + } else if (strncmp(line, "/lenIV", 6) == 0) { + lenIV = atoi(line + 6); + } else if ((p = strstr(line, "string currentfile")) + && strstr(line, "readstring")) { /* enforce `readstring' */ + /* locate the name of the charstring start command */ + *p = '\0'; /* damage line[] */ + q = strrchr(line, '/'); + if (q) { + r = cs_start; + ++q; + while (!isspace(*q) && *q != '{') + *r++ = *q++; + *r = '\0'; + } + *p = 's'; /* repair line[] */ + } + } + + if (!active) { + if ((p = strstr(line, "/Subrs")) && isdigit(p[7])) + ever_active = active = 1; + else if ((p = strstr(line, "/CharStrings")) && isdigit(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(*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; +} diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1binary.1 b/Build/source/utils/t1utils/t1utils-1.35/t1binary.1 new file mode 100644 index 00000000000..b33cbe2b6d4 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1binary.1 @@ -0,0 +1,42 @@ +.ds V 1.35 +.de M +.BR "\\$1" "(\\$2)\\$3" +.. +.TH T1BINARY 1 "" "Version \*V" +.SH NAME +t1binary \- convert PostScript Type 1 font from ASCII to binary +.SH SYNOPSIS +.B t1binary +\%[\fB\-l\fR \fIlength\fR] +\%[\fIinput\fR [\fIoutput\fR]] +.SH DESCRIPTION +.B t1binary +converts Adobe Type 1 font programs in PFA (hexadecimal) format to PFB +(binary) format. If the file +.I output +is not specified output goes to the standard output. +If the file +.I input +is not specified input comes from the standard input. +.SH OPTIONS +.TP 5 +.BI \-\-block\-length= "length\fR, " \-l " length" +Set the maximum length of sections in PFB output to +.I length. +The default length is as large as memory allows. +.SH "SEE ALSO" +.LP +.M t1ascii 1 , +.M t1unmac 1 , +.M t1mac 1 , +.M t1disasm 1 , +.M t1asm 1 +.LP +.I "Adobe Type 1 Font Format" +.SH AUTHORS +Lee Hetherington (ilh@lcs.mit.edu) +.br +Eddie Kohler (ekohler@gmail.com) +.PP +Ported to Microsoft C/C++ Compiler and MS-DOS operating system by +Kai-Uwe Herbing (herbing@netmbx.netmbx.de). diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1binary.c b/Build/source/utils/t1utils/t1utils-1.35/t1binary.c new file mode 100644 index 00000000000..614bb811004 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1binary.c @@ -0,0 +1,280 @@ +/* t1binary + * + * This program takes an Adobe Type-1 font program in ASCII (PFA) format and + * converts it to binary (PFB) format. + * + * Copyright (c) 1992 by I. Lee Hetherington, all rights reserved. + * + * Permission is hereby granted to use, modify, and distribute this program + * for any purpose provided this copyright notice and the one below remain + * intact. + * + * I. Lee Hetherington (ilh@lcs.mit.edu) + * + * 1.5 and later versions contain changes by, and are maintained by, + * Eddie Kohler <ekohler@gmail.com>. + * + * New change log in `NEWS'. Old change log: + * + * Revision 1.2 92/06/23 10:58:08 ilh + * MSDOS porting by Kai-Uwe Herbing (herbing@netmbx.netmbx.de) + * incoporated. + * + * Revision 1.1 92/05/22 11:58:17 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" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char byte; + +/* for PFB block buffering */ +static struct pfb_writer w; + + +/* PFB font_reader functions */ + +static void +pfb_output_ascii(char *s, int len) +{ + if (w.blocktyp == PFB_BINARY) { + pfb_writer_output_block(&w); + w.blocktyp = PFB_ASCII; + } + for (; len > 0; len--, s++) + PFB_OUTPUT_BYTE(&w, (byte)*s); +} + +static void +pfb_output_binary(unsigned char *s, int len) +{ + if (w.blocktyp == PFB_ASCII) { + pfb_writer_output_block(&w); + w.blocktyp = PFB_BINARY; + } + for (; len > 0; len--, s++) + PFB_OUTPUT_BYTE(&w, *s); +} + +static void +pfb_output_end(void) +{ + pfb_writer_end(&w); +} + + +/***** + * Command line + **/ + +#define BLOCK_LEN_OPT 300 +#define OUTPUT_OPT 301 +#define VERSION_OPT 302 +#define HELP_OPT 303 + +static Clp_Option options[] = { + { "block-length", 'l', BLOCK_LEN_OPT, Clp_ValInt, 0 }, + { "help", 0, HELP_OPT, 0, 0 }, + { "length", 0, BLOCK_LEN_OPT, Clp_ValInt, 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); + putc('\n', stderr); + 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); +} + + +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("\ +`T1binary' translates a PostScript Type 1 font from ASCII (PFA) to compact\n\ +binary (PFB) format. The result is written to the standard output unless an\n\ +OUTPUT file is given.\n\ +\n\ +Usage: %s [OPTION]... [INPUT [OUTPUT]]\n\ +\n\ +Options:\n\ + -l, --block-length=NUM Set max output block length.\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[]) +{ + int c; + FILE *ifp = 0, *ofp = 0; + const char *ifp_filename = "<stdin>"; + struct font_reader fr; + int max_blocklen = -1; + + 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: + max_blocklen = clp->val.i; + if (max_blocklen <= 0) { + max_blocklen = 1; + error("warning: block length raised to %d", max_blocklen); + } + break; + + 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, "wb"); + if (!ofp) fatal_error("%s: %s", clp->vstr, strerror(errno)); + } + break; + + case HELP_OPT: + usage(); + exit(0); + break; + + case VERSION_OPT: + printf("t1binary (LCDF t1utils) %s\n", VERSION); + printf("Copyright (C) 1992-2003 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, "r"); + 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 are processing a PFB (binary) output */ + /* file, we must set its file mode to binary. */ + _setmode(_fileno(ofp), _O_BINARY); +#endif + + /* prepare font reader and pfb writer */ + fr.output_ascii = pfb_output_ascii; + fr.output_binary = pfb_output_binary; + fr.output_end = pfb_output_end; + init_pfb_writer(&w, max_blocklen, ofp); + + /* 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 (!w.binary_blocks_written) + fatal_error("no binary blocks written! Are you sure this was a font?"); + + return 0; +} diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1disasm.1 b/Build/source/utils/t1utils/t1utils-1.35/t1disasm.1 new file mode 100644 index 00000000000..3115ee2d493 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1disasm.1 @@ -0,0 +1,96 @@ +.ds V 1.35 +.de M +.BR "\\$1" "(\\$2)\\$3" +.. +.TH T1DISASM 1 "" "Version \*V" +.SH NAME +t1disasm \- disassemble PostScript Type 1 font +.SH SYNOPSIS +.B t1disasm +\%[\fIinput\fR [\fIoutput\fR]] +.SH DESCRIPTION +.B t1disasm +disassembles Adobe Type 1 font programs in either PFA (hexadecimal) or PFB +(binary) formats into human-readable form. If the file +.I output +is not specified output goes to the standard output. +If the file +.I input +is not specified input comes from the standard input. + +.B t1disasm +performs eexec and charstring decryption as specified in the ``black +book'', +.I "Adobe Type 1 Font Format." +Additionally, the charstring binary tokens are expanded into human-readable +text form, using the names given in the black book and later documents +describing Type 2 opcodes. +.SH EXAMPLES +.LP +.nf +% t1disasm Utopia-Regular.pfb Utopia-Regular.raw +% t1disasm Utopia-Regular.pfa Utopia-Regular.raw +.fi + +In +.B Subrs +entries in Utopia-Regular.raw will look like +.RS +.nf +.ft B +dup 5 { + 8 111 vstem + \-12 128 hstem + 707 \-20 hstem + return + } | +.ft R +.fi +.RE +and the +.B CharStrings +entries like +.RS +.nf +.ft B +/exclam { + 58 242 hsbw + 6 callsubr + 5 4 callsubr + 63 707 rmoveto + \-54 0 \-5 \-22 4 \-45 rrcurveto + 40 \-431 rlineto + 29 hlineto + 42 431 rlineto + 4 45 \-5 22 \-55 0 rrcurveto + closepath + 6 4 callsubr + \-719 vmoveto + 243 callsubr + endchar + } |\- +.ft R +.fi +.RE +.SH "SEE ALSO" +.LP +.M t1asm 1 , +.M t1ascii 1 , +.M t1binary 1 , +.M t1unmac 1 , +.M t1mac 1 +.LP +.I "Adobe Type 1 Font Format" +is available free from Adobe as a PDF file: +http://partners.adobe.com/asn/developer/PDFS/TN/T1_SPEC.PDF +.LP +.I "The Type 2 Charstring Format," +also available from Adobe as a PDF file, describes the newer Type 2 +operators, which are also used in some multiple-master Type 1 fonts like +Adobe Jenson and Kepler: +http://partners.adobe.com/asn/developer/PDFS/TN/5177.Type2.pdf +' +.SH AUTHORS +Lee Hetherington (ilh@lcs.mit.edu) +.br +Eddie Kohler (ekohler@gmail.com) diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1disasm.c b/Build/source/utils/t1utils/t1utils-1.35/t1disasm.c new file mode 100644 index 00000000000..b77db4d29b1 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1disasm.c @@ -0,0 +1,779 @@ +/* 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. + * + * Permission is hereby granted to use, modify, and distribute this program + * for any purpose provided this copyright notice and the one below remain + * intact. + * + * I. Lee Hetherington (ilh@lcs.mit.edu) + * + * 1.5 and later versions contain changes by, and are maintained by, + * Eddie Kohler <ekohler@gmail.com>. + * + * 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 <lcdf/clp.h> +#include "t1lib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char byte; + +static FILE *ofp; +static int lenIV = 4; +static char cs_start[10]; +static int unknown = 0; + +/* decryption stuff */ +static uint16_t c1 = 52845, c2 = 22719; +static uint16_t cr_default = 4330; +static uint16_t er_default = 55665; + +static int error_count = 0; + + +/* If the line contains an entry of the form `/lenIV <num>' then set the global + lenIV to <num>. This indicates the number of random bytes at the beginning + of each charstring. */ + +static void +set_lenIV(char *line) +{ + char *p = strstr(line, "/lenIV "); + + /* Allow lenIV to be negative. Thanks to Tom Kacvinsky <tjk@ams.org> */ + if (p && (isdigit(p[7]) || p[7] == '+' || p[7] == '-')) { + lenIV = atoi(p + 7); + } +} + +static void +set_cs_start(char *line) +{ + char *p, *q, *r; + + if ((p = strstr(line, "string currentfile"))) { + /* enforce presence of `readstring' -- 5/29/99 */ + if (!strstr(line, "readstring")) + return; + /* locate the name of the charstring start command */ + *p = '\0'; /* damage line[] */ + q = strrchr(line, '/'); + if (q) { + r = cs_start; + ++q; + while (!isspace(*q) && *q != '{') + *r++ = *q++; + *r = '\0'; + } + *p = 's'; /* repair line[] */ + } +} + +/* 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 { + val = (line[i+1] & 0xff) << 24; + val |= (line[i+2] & 0xff) << 16; + val |= (line[i+3] & 0xff) << 8; + val |= (line[i+4] & 0xff) << 0; + /* in case an int32 is larger than four bytes---sign extend */ +#if INT_MAX > 0x7FFFFFFFUL + if (val & 0x80000000) + val |= ~0x7FFFFFFF; +#endif + 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 (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; +} + +/* 23.Feb.2004 - use 'memstr', not strstr, because the strings input to + eexec_line aren't null terminated! Reported by Werner Lemberg. */ + +static unsigned char * +oog_memstr(unsigned char *line, int line_len, const char *pattern, int pattern_len) +{ + unsigned char *try; + unsigned char *last = line + line_len - pattern_len + 1; + while (line < last + && (try = memchr(line, (unsigned char)*pattern, last - line))) { + if (memcmp(try, pattern, pattern_len) == 0) + return try; + else + line = try + 1; + } + return 0; +} + +/* 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; + } + + 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); + save_len = 0; + return cut_newline; + } else { + /* not long enough! */ + if (line != save) + 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. */ + { + char *CharStrings = (char *) + oog_memstr(line, line_len, "/CharStrings ", 13); + int crap, n; + char should_be_slash = 0; + if (CharStrings + && sscanf(CharStrings + 12, " %d dict dup begin %c%n", &crap, &should_be_slash, &n) >= 2 + && should_be_slash == '/') { + int len = (CharStrings + 12 + n - 1) - (char *) line; + fprintf(ofp, "%.*s\n", len, line); + return eexec_line((unsigned char *) (CharStrings + 12 + n - 1), line_len - len); + } + } + + if (line[line_len - 1] == '\r') { + line[line_len - 1] = '\n'; + cut_newline = 1; + } + set_lenIV((char *)line); + set_cs_start((char *)line); + fprintf(ofp, "%.*s", line_len, line); + save_len = 0; + + /* look for `currentfile closefile' to see if we should stop decrypting */ + if (oog_memstr(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); + 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++; +} + +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-2003 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); +#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); +} diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1lib.c b/Build/source/utils/t1utils/t1utils-1.35/t1lib.c new file mode 100644 index 00000000000..0dac40eddc0 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1lib.c @@ -0,0 +1,441 @@ +/* t1lib + * + * This file contains functions for reading PFA and PFB files. + * + * (C) 1999-2008 Eddie Kohler <ekohler@gmail.com>, after code by + * I. Lee Hetherington <ilh@lcs.mit.edu>. All rights reserved. + * + * Permission is hereby granted to use, modify, and distribute this program + * for any purpose provided this copyright notice remains intact. + * + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include "t1lib.h" +#ifdef __cplusplus +extern "C" { +#endif + +#define PFA_ASCII 1 +#define PFA_EEXEC_TEST 2 +#define PFA_HEX 3 +#define PFA_BINARY 4 + +/* This function returns the value (0-15) of a single hex digit. It returns + 0 for an invalid hex digit. */ + +static int +hexval(char c) +{ + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + else if (c >= '0' && c <= '9') + return c - '0'; + else + return 0; +} + +/* This function translates a string of hexadecimal digits into binary data. + We allow an odd number of digits. Returns length of binary data. */ + +static int +translate_hex_string(char *s, char *saved_orphan) +{ + int c1 = *saved_orphan; + char *start = s; + char *t = s; + for (; *s; s++) { + if (isspace(*s)) + continue; + if (c1) { + *t++ = (hexval(c1) << 4) + hexval(*s); + c1 = 0; + } else + c1 = *s; + } + *saved_orphan = c1; + return t - start; +} + +/* This function returns 1 if the string contains all '0's. */ + +static int +all_zeroes(char *s) +{ + if (*s == '\0' || *s == '\n') + return 0; + while (*s == '0') + s++; + return *s == '\0' || *s == '\n'; +} + +/* This function handles the entire file. */ + +#define LINESIZE 1024 + +void +process_pfa(FILE *ifp, const char *ifp_filename, struct font_reader *fr) +{ + /* Loop until no more input. We need to look for `currentfile eexec' to + start eexec section (hex to binary conversion) and line of all zeros to + switch back to ASCII. */ + + /* Don't use fgets() in case line-endings are indicated by bare \r's, as + occurs in Macintosh fonts. */ + + /* 2.Aug.1999 - At the behest of Tom Kacvinsky <tjk@ams.org>, support + binary PFA fonts. */ + + char buffer[LINESIZE]; + int c = 0; + int blocktyp = PFA_ASCII; + char saved_orphan = 0; + (void)ifp_filename; + + while (c != EOF) { + char *line = buffer, *last = buffer; + int crlf = 0; + c = getc(ifp); + while (c != EOF && c != '\r' && c != '\n' && last < buffer + LINESIZE - 1) { + *last++ = c; + c = getc(ifp); + } + + /* handle the end of the line */ + if (last == buffer + LINESIZE - 1) + /* buffer overrun: don't append newline even if we have it */ + ungetc(c, ifp); + else if (c == '\r' && blocktyp != PFA_BINARY) { + /* change CR or CR/LF into LF, unless reading binary data! (This + condition was wrong before, caused Thanh problems - + 6.Mar.2001) */ + c = getc(ifp); + if (c != '\n') + ungetc(c, ifp), crlf = 1; + else + crlf = 2; + *last++ = '\n'; + } else if (c != EOF) + *last++ = c; + + *last = 0; + + /* now that we have the line, handle it */ + if (blocktyp == PFA_ASCII) { + if (strncmp(line, "currentfile eexec", 17) == 0 && isspace(line[17])) { + char saved_p; + /* assert(line == buffer); */ + for (line += 18; isspace(*line); line++) + /* nada */; + saved_p = *line; + *line = 0; + fr->output_ascii(buffer, line - buffer); + *line = saved_p; + blocktyp = PFA_EEXEC_TEST; + if (!*line) + continue; + } else { + fr->output_ascii(line, last - line); + continue; + } + } + + /* check immediately after "currentfile eexec" for ASCII or binary */ + if (blocktyp == PFA_EEXEC_TEST) { + /* 8.Feb.2004: fix bug if first character in a binary eexec block + is 0, reported by Werner Lemberg */ + for (; line < last && isspace(*line); line++) + /* nada */; + if (line == last) + continue; + else if (last >= line + 4 && isxdigit(line[0]) && isxdigit(line[1]) + && isxdigit(line[2]) && isxdigit(line[3])) + blocktyp = PFA_HEX; + else + blocktyp = PFA_BINARY; + memmove(buffer, line, last - line + 1); + last = buffer + (last - line); + line = buffer; + /* patch up crlf fix */ + if (blocktyp == PFA_BINARY && crlf) { + last[-1] = '\r'; + if (crlf == 2) + *last++ = '\n'; + } + } + + /* blocktyp == PFA_HEX || blocktyp == PFA_BINARY */ + if (all_zeroes(line)) { /* XXX not safe */ + fr->output_ascii(line, last - line); + blocktyp = PFA_ASCII; + } else if (blocktyp == PFA_HEX) { + int len = translate_hex_string(line, &saved_orphan); + if (len) + fr->output_binary((unsigned char *)line, len); + } else + fr->output_binary((unsigned char *)line, last - line); + } + + fr->output_end(); +} + +/* Process a PFB file. */ + +/* XXX Doesn't handle "currentfile eexec" as intelligently as process_pfa + does. */ + +static int +handle_pfb_ascii(struct font_reader *fr, char *line, int len) +{ + /* Divide PFB_ASCII blocks into lines */ + int start = 0; + + while (1) { + int pos = start; + + while (pos < len && line[pos] != '\n' && line[pos] != '\r') + pos++; + + if (pos >= len) { + if (pos == start) + return 0; + else if (start == 0 && pos == LINESIZE - 1) { + line[pos] = 0; + fr->output_ascii(line, pos); + return 0; + } else { + memmove(line, line + start, pos - start); + return pos - start; + } + + } else if (pos < len - 1 && line[pos] == '\r' && line[pos+1] == '\n') { + line[pos] = '\n'; + line[pos+1] = 0; + fr->output_ascii(line + start, pos + 1 - start); + start = pos + 2; + + } else { + char save = line[pos+1]; + line[pos] = '\n'; + line[pos+1] = 0; + fr->output_ascii(line + start, pos + 1 - start); + line[pos+1] = save; + start = pos + 1; + } + } +} + + +void +process_pfb(FILE *ifp, const char *ifp_filename, struct font_reader *fr) +{ + int blocktyp = 0; + int block_len = 0; + int c = 0; + int filepos = 0; + int linepos = 0; + char line[LINESIZE]; + + while (1) { + while (block_len == 0) { + c = getc(ifp); + blocktyp = getc(ifp); + if (c != PFB_MARKER + || (blocktyp != PFB_ASCII && blocktyp != PFB_BINARY + && blocktyp != PFB_DONE)) { + if (c == EOF || blocktyp == EOF) + error("%s corrupted: no end-of-file marker", ifp_filename); + else + error("%s corrupted: bad block marker at position %d", + ifp_filename, filepos); + blocktyp = PFB_DONE; + } + if (blocktyp == PFB_DONE) + goto done; + + block_len = getc(ifp) & 0xFF; + block_len |= (getc(ifp) & 0xFF) << 8; + block_len |= (getc(ifp) & 0xFF) << 16; + block_len |= (getc(ifp) & 0xFF) << 24; + if (feof(ifp)) { + error("%s corrupted: bad block length at position %d", + ifp_filename, filepos); + blocktyp = PFB_DONE; + goto done; + } + filepos += 6; + } + + /* read the block in its entirety, in LINESIZE chunks */ + while (block_len > 0) { + int rest = LINESIZE - 1 - linepos; /* leave space for '\0' */ + int n = (block_len > rest ? rest : block_len); + int actual = fread(line + linepos, 1, n, ifp); + if (actual != n) { + error("%s corrupted: block short by %d bytes at position %d", + ifp_filename, block_len - actual, filepos); + block_len = actual; + } + + if (blocktyp == PFB_BINARY) + fr->output_binary((unsigned char *)line, actual); + else + linepos = handle_pfb_ascii(fr, line, linepos + actual); + + block_len -= actual; + filepos += actual; + } + + /* handle any leftover line */ + if (linepos > 0) { + line[linepos] = 0; + fr->output_ascii(line, linepos); + linepos = 0; + } + } + + done: + c = getc(ifp); + if (c != EOF) + error("%s corrupted: data after PFB end marker at position %d", + ifp_filename, filepos - 2); + fr->output_end(); +} + + +#define DEFAULT_BLOCKLEN (1L<<12) + +void +init_pfb_writer(struct pfb_writer *w, int blocklen, FILE *f) +{ + w->len = DEFAULT_BLOCKLEN; + w->buf = (unsigned char *)malloc(w->len); + if (!w->buf) + fatal_error("out of memory"); + w->max_len = (blocklen <= 0 ? 0xFFFFFFFFU : (unsigned)blocklen); + w->pos = 0; + w->blocktyp = PFB_ASCII; + w->binary_blocks_written = 0; + w->f = f; +} + +void +pfb_writer_output_block(struct pfb_writer *w) +{ + /* do nothing if nothing in block */ + if (w->pos == 0) + return; + + /* output four-byte block length */ + putc(PFB_MARKER, w->f); + putc(w->blocktyp, w->f); + putc((int)(w->pos & 0xff), w->f); + putc((int)((w->pos >> 8) & 0xff), w->f); + putc((int)((w->pos >> 16) & 0xff), w->f); + putc((int)((w->pos >> 24) & 0xff), w->f); + + /* output block data */ + fwrite(w->buf, 1, w->pos, w->f); + + /* mark block buffer empty and uninitialized */ + w->pos = 0; + if (w->blocktyp == PFB_BINARY) + w->binary_blocks_written++; +} + +void +pfb_writer_grow_buf(struct pfb_writer *w) +{ + if (w->len < w->max_len) { + /* grow w->buf */ + unsigned new_len = w->len * 2; + unsigned char *new_buf; + if (new_len > w->max_len) + new_len = w->max_len; + new_buf = (unsigned char *)malloc(new_len); + if (!new_buf) { + error("out of memory; continuing with a smaller block size"); + w->max_len = w->len; + pfb_writer_output_block(w); + } else { + memcpy(new_buf, w->buf, w->len); + free(w->buf); + w->buf = new_buf; + w->len = new_len; + } + + } else + /* buf already the right size, just output the block */ + pfb_writer_output_block(w); +} + +void +pfb_writer_end(struct pfb_writer *w) +{ + if (w->pos) + pfb_writer_output_block(w); + putc(PFB_MARKER, w->f); + putc(PFB_DONE, w->f); +} + +/* This CRC table and routine were borrowed from macutils-2.0b3 */ + +static unsigned short crctab[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0, +}; + +/* + * Update a CRC check on the given buffer. + */ + +int +crcbuf(int crc, unsigned int len, const char *buf) +{ + const unsigned char *ubuf = (const unsigned char *)buf; + while (len--) + crc = ((crc << 8) & 0xFF00) ^ crctab[((crc >> 8) & 0xFF) ^ *ubuf++]; + return crc; +} + +#ifdef __cplusplus +} +#endif diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1lib.h b/Build/source/utils/t1utils/t1utils-1.35/t1lib.h new file mode 100644 index 00000000000..93859fea731 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1lib.h @@ -0,0 +1,56 @@ +#ifndef T1LIB_H +#define T1LIB_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +# pragma warning (disable: 4007 4096) +# define CDECL __cdecl +#else +# define CDECL +#endif + +#define PFB_MARKER 128 +#define PFB_ASCII 1 +#define PFB_BINARY 2 +#define PFB_DONE 3 + +struct font_reader { + void (*output_ascii)(char *, int); + void (*output_binary)(unsigned char *, int); + void (*output_end)(); +}; + +void process_pfa(FILE *, const char *filename, struct font_reader *); +void process_pfb(FILE *, const char *filename, struct font_reader *); + +struct pfb_writer { + unsigned char *buf; + unsigned len; + unsigned max_len; + unsigned pos; + int blocktyp; + int binary_blocks_written; + FILE *f; +}; + +void init_pfb_writer(struct pfb_writer *, int, FILE *); +void pfb_writer_output_block(struct pfb_writer *); +void pfb_writer_grow_buf(struct pfb_writer *); +void pfb_writer_end(struct pfb_writer *); +#define PFB_OUTPUT_BYTE(w, b) do { \ + if ((w)->pos >= (w)->len) pfb_writer_grow_buf(w); \ + (w)->buf[(w)->pos++] = (b); \ + } while (0) + +int crcbuf(int crc, unsigned int len, const char *buf); + +/* whoever uses this code must provide a definition for these functions */ +extern void error(const char *, ...); +extern void fatal_error(const char *, ...); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1mac.1 b/Build/source/utils/t1utils/t1utils-1.35/t1mac.1 new file mode 100644 index 00000000000..872acb7c27b --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1mac.1 @@ -0,0 +1,62 @@ +.ds V 1.35 +.de M +.BR "\\$1" "(\\$2)\\$3" +.. +.TH T1MAC 1 "" "Version \*V" +.SH NAME +t1mac \- translate a PFA or PFB PostScript Type 1 font into Macintosh format +.SH SYNOPSIS +.B t1mac +\%[\fB\-\-macbinary\fR | \fB\-\-applesingle\fR | +\fB\-\-appledouble\fR | \fB\-\-binhex\fR | \fB\-\-raw\fR] +\%[\fB\-\-filename\fR \fIname\fR] +\%[\fIinput\fR [\fIoutput\fR]] +.SH DESCRIPTION +.B t1mac +reads a PFA (hexadecimal) or PFB (binary) PostScript Type 1 font file and +generates an equivalent Macintosh Type 1 font file. The output file can be +in MacBinary II, AppleSingle, AppleDouble, or BinHex format, or it can be a +raw resource fork. The default is MacBinary II; use an option to choose a +different format. If the +.I output +file is not specified output goes to the standard output. +.PP +WARNING: The output of +.B t1mac +is not sufficient to use the font, since Macintoshes can't read raw Type 1 +fonts. You will need to create a font suitcase containing bitmap fonts if +you do not have such a suitcase for the font already. +.B t1mac +cannot help you do this. +.SH OPTIONS +.TP 5 +.BR \-\-raw ", " \-r +Indicates that output should be a raw resource fork. +.TP 5 +.BR \-\-macbinary +Indicates that output should be in MacBinary I or II format. This is the +default. +.TP 5 +.BR \-\-applesingle +Indicates that output should be in AppleSingle format. +.TP 5 +.BR \-\-appledouble +Indicates that output should be in AppleDouble format. +.TP 5 +.BR \-\-binhex +Indicates that output should be in BinHex 4.0 format. +.TP 5 +.BR \-\-filename "=\fIname\fR, " \-n " \fIname\fR" +Sets the Macintosh filename of the output font to \fIname\fR. The default +is to construct the filename from the font's name using established +Macintosh conventions. This option is not useful when output is a raw +resource fork. +.SH "SEE ALSO" +.LP +.M t1unmac 1 , +.M t1ascii 1 , +.M t1binary 1 , +.M t1asm 1 , +.M t1disasm 1 +.SH AUTHORS +Eddie Kohler (ekohler@gmail.com) diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1mac.c b/Build/source/utils/t1utils/t1utils-1.35/t1mac.c new file mode 100644 index 00000000000..18521d3de60 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1mac.c @@ -0,0 +1,1019 @@ +/* t1mac + * + * This program converts Type 1 fonts in PFA or PFB format into Macintosh Type + * 1 fonts stored in MacBinary (I or II), AppleSingle, AppleDouble, BinHex, or + * raw resource fork format. + * + * Copyright (c) 2000-2003 by Eddie Kohler, all rights reserved. + * + * Permission is hereby granted to use, modify, and distribute this program + * for any purpose provided this copyright notice and the one below remain + * intact. */ + +/* 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 <time.h> +#include <lcdf/clp.h> +#include "t1lib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char byte; + +/* resource fork layout */ +#define RFORK_HEADERLEN 256 +#define RFORK_MAP_RESERVEDLEN 22 +#define RFORK_MAP_HEADERLEN 28 +#define RFORK_RTYPE_LEN 8 +#define RFORK_RSRC_LEN 12 + +/* Macintosh times are # seconds since 1/1/1904, not 1/1/1970 */ +#define MAC_TIME_DELTA 2082844800 + +/* POST resource information */ +#define POST_ASCII 1 +#define POST_BINARY 2 +#define POST_END 5 + +/* Adobe font file information */ +#define T1_FILETYPE 0x4C57464E /* LWFN */ +#define T1_FILECREATOR 0x54315554 /* T1UT */ +#define T1_FINDERFLAGS 33 /* Bundle + Inited */ + +#define MAX_RSRC_LEN 2048 +static byte rbuf[MAX_RSRC_LEN]; +static int rbufpos; +static int blocktyp; + +static char *font_name; + +/* information about the resources being built */ +typedef struct Rsrc { + int32_t type; + int id; + int attrs; + int data_offset; + uint32_t data_len; + int next_in_type; + int next_type; +} Rsrc; +static Rsrc *rsrc = 0; +static int nrsrc = 0; +static int rsrc_cap = 0; +static int cur_post_id = 0; + +/* output resource fork */ +static FILE *rfork_f = 0; + +/* ICN# data */ +static const unsigned char icon_bw_data[] = { +0,0,0,0,255,255,255,255,128,0,0,1,128,0,0,1,128,0,0,1, +128,0,0,1,128,0,0,1,128,0,0,1,128,0,0,1,128,0,0,33, +128,0,0,97,128,0,0,225,128,0,1,225,128,0,3,225,128,0,7,225, +128,0,15,225,128,0,31,225,128,0,55,225,159,128,103,249,144,128,199,9, +240,129,135,15,0,131,7,0,0,134,7,0,15,140,7,240,8,31,255,240, +8,63,255,240,8,96,7,240,8,192,7,240,9,192,15,240,11,224,31,240, +15,240,63,240,15,255,255,240,0,0,0,0,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,240,255,255,15,240,255,255,15,0,255,255,0,0,255,255,0, +15,255,255,240,15,255,255,240,15,255,255,240,15,255,255,240,15,255,255,240, +15,255,255,240,15,255,255,240,15,255,255,240,15,255,255,240,}; + +static const unsigned char small_icon_bw_data[] = { +255,255,128,1,128,1,128,1,128,5,128,13,128,29,128,61,128,125,184,253, +201,179,59,60,39,252,44,60,60,124,63,252,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,207,243,63,252,63,252,63,252, +63,252,63,252,}; + +static const unsigned char icon_8_data[] = { +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,105,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,105, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,105,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,105,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,5,92,92,92,92,105, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,5,5,92,92,92,92,105,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,5,5,5,92, +92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,5,5,5,5,92,92,92,92,105,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,5,5, +5,5,5,92,92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,5,5,5,5,5,5,92,92,92,92,105, +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +5,5,5,5,5,5,5,92,92,92,92,105,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,5,5,5,5,5,5,5,5,92, +92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,5,5,92,5,5,5,5,5,5,92,92,92,92,105,92,92,92,105, +105,105,105,105,92,92,92,92,92,92,92,92,92,5,5,92,92,5,5,105, +105,105,105,105,92,92,92,105,92,92,92,105,0,0,0,0,92,92,92,92, +92,92,92,92,5,5,92,92,92,5,5,105,0,0,0,0,92,92,92,105, +105,105,105,105,0,0,0,0,92,92,92,92,92,92,92,5,5,92,92,92, +92,5,5,105,0,0,0,0,105,105,105,105,0,0,0,0,0,0,0,0, +92,92,92,92,92,92,5,5,92,92,92,92,92,5,5,105,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,92,92,92,92,92,5,5,92, +92,92,92,92,92,5,5,105,0,0,0,0,0,0,0,0,0,0,0,0, +92,92,92,92,92,92,92,92,5,5,92,92,92,92,92,92,92,5,5,5, +5,5,5,92,0,0,0,0,0,0,0,0,92,92,92,92,92,92,92,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,105,0,0,0,0, +0,0,0,0,92,92,92,92,92,92,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,105,0,0,0,0,0,0,0,0,92,92,92,92, +92,5,5,92,92,92,92,92,92,92,92,92,92,5,5,5,5,5,5,105, +0,0,0,0,0,0,0,0,92,92,92,92,5,5,92,92,92,92,92,92, +92,92,92,92,92,5,5,5,5,5,5,105,0,0,0,0,0,0,0,0, +92,92,92,5,5,5,92,92,92,92,92,92,92,92,92,92,5,5,5,5, +5,5,5,105,0,0,0,0,0,0,0,0,92,92,5,5,5,5,5,92, +92,92,92,92,92,92,92,5,5,5,5,5,5,5,5,105,0,0,0,0, +0,0,0,0,92,5,5,5,5,5,5,5,92,92,92,92,92,92,5,5, +5,5,5,5,5,5,5,105,0,0,0,0,0,0,0,0,92,105,105,105, +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, +0,0,0,0,}; + +static const unsigned char small_icon_8_data[] = { +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,92,92,92,92,105,92,92,92,92,92,92,92,92, +92,92,92,92,92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92, +92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92,92,5,92,105, +92,92,92,92,92,92,92,92,92,92,92,92,5,5,92,105,92,92,92,92, +92,92,92,92,92,92,92,5,5,5,92,105,92,92,92,92,92,92,92,92, +92,92,5,5,5,5,92,105,92,92,92,92,92,92,92,92,92,5,92,5, +5,5,92,105,92,105,105,105,92,92,92,92,5,92,92,5,105,105,92,105, +92,105,0,0,92,92,92,5,92,92,92,5,0,0,105,105,0,0,92,92, +92,92,5,92,92,92,92,5,5,5,0,0,0,0,92,92,92,5,5,5, +5,5,5,5,5,5,0,0,0,0,92,92,5,92,92,92,92,92,92,5, +5,5,0,0,0,0,92,5,5,92,92,92,92,92,5,5,5,5,0,0, +0,0,5,5,5,5,105,105,105,5,5,5,5,5,0,0,}; + +static const unsigned char icon_4_data[] = { +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,69,69,69,69, +69,69,69,69,69,69,69,69,69,69,69,69,84,84,84,84,84,84,84,84, +84,84,84,84,84,84,84,85,69,69,69,69,69,69,69,69,69,69,69,69, +69,69,69,69,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,85, +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,84,84,84,84, +84,84,84,84,84,84,84,84,84,84,84,85,69,69,69,69,69,69,69,69, +69,69,69,69,69,69,69,69,84,84,84,84,84,84,84,84,84,84,84,84, +84,84,84,85,69,69,69,69,69,69,69,69,69,69,69,69,69,21,69,69, +84,84,84,84,84,84,84,84,84,84,84,84,81,20,84,85,69,69,69,69, +69,69,69,69,69,69,69,69,17,21,69,69,84,84,84,84,84,84,84,84, +84,84,84,81,17,20,84,85,69,69,69,69,69,69,69,69,69,69,69,17, +17,21,69,69,84,84,84,84,84,84,84,84,84,84,81,17,17,20,84,85, +69,69,69,69,69,69,69,69,69,69,17,17,17,21,69,69,84,84,84,84, +84,84,84,84,84,81,17,17,17,20,84,85,69,69,69,69,69,69,69,69, +69,17,65,17,17,21,69,69,84,85,85,85,84,84,84,84,81,20,81,21, +85,85,84,85,69,69,0,0,69,69,69,69,17,69,65,21,0,0,69,69, +85,85,0,0,84,84,84,81,20,84,81,21,0,0,85,85,0,0,0,0, +69,69,69,17,69,69,65,21,0,0,0,0,0,0,0,0,84,84,81,20, +84,84,81,21,0,0,0,0,0,0,69,69,69,69,17,69,69,69,65,17, +17,30,0,0,0,0,84,84,84,81,17,17,17,17,17,17,17,21,0,0, +0,0,69,69,69,17,17,17,17,17,17,17,17,21,0,0,0,0,84,84, +81,20,84,84,84,84,81,17,17,21,0,0,0,0,69,69,17,69,69,69, +69,69,65,17,17,21,0,0,0,0,84,81,17,84,84,84,84,84,17,17, +17,21,0,0,0,0,69,17,17,21,69,69,69,65,17,17,17,21,0,0, +0,0,81,17,17,17,84,84,84,17,17,17,17,21,0,0,0,0,229,85, +85,85,85,85,85,85,85,85,85,85,0,0,}; + +static const unsigned char small_icon_4_data[] = { +84,84,84,84,84,84,84,85,69,69,69,69,69,69,69,69,84,84,84,84, +84,84,84,85,69,69,69,69,69,69,69,69,84,84,84,84,84,84,81,85, +69,69,69,69,69,69,17,69,84,84,84,84,84,81,17,85,69,69,69,69, +69,17,17,69,84,84,84,84,81,81,17,85,69,85,69,69,21,65,85,69, +85,0,84,81,84,81,0,85,0,69,69,21,69,65,17,0,0,84,81,17, +17,17,17,0,0,69,21,69,69,65,17,0,0,81,20,84,84,17,17,0, +0,17,17,85,81,17,17,0,}; + + +/* fseek with fatal_error */ + +static void +reposition(FILE *fi, int32_t absolute) +{ + if (fseek(fi, absolute, 0) == -1) + fatal_error("can't seek to position %d", absolute); +} + +/* Some functions to write one, two, three, and four byte integers in 68000 + byte order (most significant byte first). */ + +static void +write_one(int c, FILE *f) +{ + putc(c, f); +} + +static void +write_two(int c, FILE *f) +{ + putc((c >> 8) & 255, f); + putc(c & 255, f); +} + +static void +write_three(int32_t c, FILE *f) +{ + putc((c >> 16) & 255, f); + putc((c >> 8) & 255, f); + putc(c & 255, f); +} + +static void +write_four(int32_t c, FILE *f) +{ + putc((c >> 24) & 255, f); + putc((c >> 16) & 255, f); + putc((c >> 8) & 255, f); + putc(c & 255, f); +} + +/* Some functions to store one, two, three, and four byte integers in 68000 + byte order (most significant byte first). */ + +static void +store_one(int c, char *s) +{ + s[0] = (char)(c & 255); +} + +static void +store_two(int c, char *s) +{ + s[0] = (char)((c >> 8) & 255); + s[1] = (char)(c & 255); +} + +static void +store_four(int32_t c, char *s) +{ + s[0] = (char)((c >> 24) & 255); + s[1] = (char)((c >> 16) & 255); + s[2] = (char)((c >> 8) & 255); + s[3] = (char)(c & 255); +} + +static void +output_new_rsrc(const char *rtype, int rid, int attrs, + const char *data, uint32_t len) +{ + Rsrc *r; + if (nrsrc >= rsrc_cap) { + rsrc_cap = (rsrc_cap ? rsrc_cap * 2 : 256); + r = (Rsrc *)malloc(sizeof(Rsrc) * rsrc_cap); + if (!r) + fatal_error("out of memory"); + memcpy(r, rsrc, sizeof(Rsrc) * nrsrc); + free(rsrc); + rsrc = r; + } + r = &rsrc[nrsrc]; + nrsrc++; + + /* prepare resource record */ + { + const unsigned char *b = (const unsigned char *)rtype; + r->type = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; + } + r->id = rid; + r->attrs = attrs; + if (nrsrc == 1) + r->data_offset = 0; + else + r->data_offset = rsrc[nrsrc-2].data_offset + rsrc[nrsrc-2].data_len + 4; + r->data_len = len; + r->next_in_type = r->next_type = -2; + + /* resource consists of length, then data */ + write_four(r->data_len, rfork_f); + fwrite(data, 1, len, rfork_f); +} + +static void +init_current_post(void) +{ + rbufpos = 2; + cur_post_id = 501; + blocktyp = POST_ASCII; +} + +static void +output_current_post(void) +{ + if (blocktyp != POST_END && rbufpos <= 2) + return; + rbuf[0] = blocktyp; + rbuf[1] = 0; + output_new_rsrc("POST", cur_post_id, 0, (char *)rbuf, rbufpos); + rbufpos = 2; + cur_post_id++; +} + +/* font_reader functions */ + +static void +t1mac_output_data(byte *s, int len) +{ + while (len > 0) { + int n; + /* In some Mac fonts, the ASCII sections terminate with a line-end */ + if (rbufpos >= MAX_RSRC_LEN + || (blocktyp == POST_ASCII && len + rbufpos > MAX_RSRC_LEN && rbufpos)) + output_current_post(); + n = (len + rbufpos <= MAX_RSRC_LEN ? len : MAX_RSRC_LEN - rbufpos); + memcpy(rbuf + rbufpos, s, n); + rbufpos += n; + s += n; + len -= n; + } +} + +static void +t1mac_output_ascii(char *s, int len) +{ + if (blocktyp == POST_BINARY) { + output_current_post(); + blocktyp = POST_ASCII; + } + /* Mac line endings */ + if (len > 0 && s[len-1] == '\n') + s[len-1] = '\r'; + t1mac_output_data((byte *)s, len); + if (strncmp(s, "/FontName", 9) == 0) { + for (s += 9; isspace(*s); s++) ; + if (*s == '/') { + const char *t = ++s; + while (*t && !isspace(*t)) t++; + free(font_name); + font_name = (char *)malloc(t - s + 1); + memcpy(font_name, s, t - s); + font_name[t - s] = 0; + } + } +} + +static void +t1mac_output_binary(unsigned char *s, int len) +{ + if (blocktyp == POST_ASCII) { + output_current_post(); + blocktyp = POST_BINARY; + } + t1mac_output_data(s, len); +} + +static void +t1mac_output_end(void) +{ + output_current_post(); + blocktyp = POST_END; + output_current_post(); +} + + +/* finish off the resource fork */ + +static uint32_t +complete_rfork(void) +{ + uint32_t reflist_offset, total_data_len; + uint32_t typelist_len; + int i, j, ntypes; + + /* analyze resources */ + { + int last_type = -1; + ntypes = 0; + for (i = 0; i < nrsrc; i++) + if (rsrc[i].next_in_type == -2) { + int last = -1; + if (last_type >= 0) + rsrc[last_type].next_type = i; + for (j = i; j < nrsrc; j++) + if (rsrc[j].type == rsrc[i].type) { + if (last >= 0) + rsrc[last].next_in_type = j; + last = j; + } + rsrc[last].next_in_type = -1; + last_type = i; + ntypes++; + } + } + + /* have just finished writing data */ + /* now write resource map */ + for (i = 0; i < RFORK_MAP_RESERVEDLEN; i++) + putc(0, rfork_f); /* reserved */ + write_two(0, rfork_f); /* resource fork attributes */ + typelist_len = ntypes * RFORK_RTYPE_LEN + 2; + write_two(RFORK_MAP_HEADERLEN, rfork_f); /* offset from start of map to typelist */ + write_two(RFORK_MAP_HEADERLEN + typelist_len + nrsrc * RFORK_RSRC_LEN, rfork_f); /* offset from start of map to namelist */ + + /* output type map */ + write_two(ntypes - 1, rfork_f);/* number of types - 1 */ + reflist_offset = typelist_len; + for (i = 0; i >= 0; i = rsrc[i].next_type) { + int n_in_type = 0; + for (j = i; j >= 0; j = rsrc[j].next_in_type) + n_in_type++; + write_four(rsrc[i].type, rfork_f); /* resource type */ + write_two(n_in_type - 1, rfork_f); /* number in type - 1 */ + write_two(reflist_offset, rfork_f); /* offset to reflist from start of typelist */ + reflist_offset += n_in_type * RFORK_RSRC_LEN; + } + + /* output reference list */ + for (i = 0; i >= 0; i = rsrc[i].next_type) + for (j = i; j >= 0; j = rsrc[j].next_in_type) { + write_two(rsrc[j].id, rfork_f); /* ID */ + write_two(-1, rfork_f); /* offset to name */ + write_one(rsrc[j].attrs, rfork_f); /* attributes */ + write_three(rsrc[j].data_offset, rfork_f); /* offset to data from start of data */ + write_four(0, rfork_f); /* reserved */ + } + + /* finally, patch up resource fork header */ + { + total_data_len = rsrc[nrsrc-1].data_offset + rsrc[nrsrc-1].data_len + 4; + reposition(rfork_f, 0); + write_four(RFORK_HEADERLEN, rfork_f); /* offset from rfork to data */ + write_four(RFORK_HEADERLEN + total_data_len, rfork_f); /* offset from rfork to map */ + write_four(total_data_len, rfork_f); /* length of data */ + write_four(RFORK_MAP_HEADERLEN + reflist_offset, rfork_f); /* length of map */ + } + + return RFORK_HEADERLEN + total_data_len + RFORK_MAP_HEADERLEN + reflist_offset; +} + + +/* write a MacBinary II file */ + +static void +output_raw(FILE *rf, int32_t len, FILE *f) +{ + char buf[2048]; + reposition(rf, 0); + while (len > 0) { + int n = (len < 2048 ? len : 2048); + fread(buf, 1, n, rf); + fwrite(buf, 1, n, f); + len -= n; + } +} + +static void +output_macbinary(FILE *rf, int32_t rf_len, const char *filename, FILE *f) +{ + int i, len = strlen(filename); + char buf[128]; + if (len < 1 || len > 63) + fatal_error("filename length must be between 1 and 63"); + store_one(0, buf+0); /* old version number */ + store_one(len, buf+1); /* filename length */ + memset(buf+2, 0, 63); /* filename padding */ + memcpy(buf+2, filename, len); /* filename */ + store_four(T1_FILETYPE, buf+65); /* file type */ + store_four(T1_FILECREATOR, buf+69); /* file creator */ + store_one(T1_FINDERFLAGS, buf+73); /* finder flags */ + store_one(0, buf+74); /* zero byte */ + store_two(0, buf+75); /* vertical position in window */ + store_two(0, buf+77); /* horizontal position in window */ + store_two(0, buf+79); /* window or folder ID */ + store_one(0, buf+81); /* protected flag */ + store_one(0, buf+82); /* zero byte */ + store_four(0, buf+83); /* data fork length */ + store_four(rf_len, buf+87); /* resource fork length */ + { + time_t t = time(0) + MAC_TIME_DELTA; + store_four(t, buf+91); /* creation date */ + store_four(t, buf+95); /* modification date */ + } + store_two(0, buf+99); /* GetInfo comment length */ + store_one(0, buf+101); /* finder flags part 2 */ + memset(buf+102, 0, 116 - 102); /* padding */ + store_four(0, buf+116); /* total length when unpacked */ + store_two(0, buf+120); /* length of secondary header */ + store_one(129, buf+122); /* version number */ + store_one(129, buf+123); /* minimum acceptable version number */ + store_two(crcbuf(0, 124, buf), buf+124); /* CRC */ + store_two(0, buf+126); /* padding to 128 bytes */ + + /* write out the header */ + fwrite(buf, 1, 128, f); + + /* now write resource fork */ + output_raw(rf, rf_len, f); + for (i = rf_len % 128; i && i < 128; i++) + putc(0, f); +} + + +/* write an AppleSingle file */ + +#define APPLESINGLE_MAGIC 0x00051600 +#define APPLEDOUBLE_MAGIC 0x00051607 +#define APPLESINGLE_VERSION 0x00020000 +#define APPLESINGLE_TIME_DELTA 883612800 +#define APPLESINGLE_HEADERLEN 26 +#define APPLESINGLE_ENTRYLEN 12 +#define APPLESINGLE_DFORK_ENTRY 1 +#define APPLESINGLE_RFORK_ENTRY 2 +#define APPLESINGLE_DATES_ENTRY 8 +#define APPLESINGLE_DATES_LEN 16 +#define APPLESINGLE_FINDERINFO_ENTRY 9 +#define APPLESINGLE_FINDERINFO_LEN 32 +#define APPLESINGLE_REALNAME_ENTRY 3 + +static void +output_applesingle(FILE *rf, int32_t rf_len, const char *filename, FILE *f, + int appledouble) +{ + uint32_t offset; + int i, nentries, len = strlen(filename); + if (appledouble) /* magic number */ + write_four(APPLEDOUBLE_MAGIC, f); + else + write_four(APPLESINGLE_MAGIC, f); + write_four(APPLESINGLE_VERSION, f); /* version number */ + for (i = 0; i < 4; i++) + write_four(0, f); /* filler */ + nentries = (appledouble ? 4 : 5); + write_two(nentries, f); /* number of entries */ + + /* real name entry */ + offset = APPLESINGLE_HEADERLEN + nentries * APPLESINGLE_ENTRYLEN; + write_four(APPLESINGLE_REALNAME_ENTRY, f); + write_four(offset, f); + write_four(len, f); + offset += len; + + /* time entry */ + write_four(APPLESINGLE_DATES_ENTRY, f); + write_four(offset, f); + write_four(APPLESINGLE_DATES_LEN, f); + offset += APPLESINGLE_DATES_LEN; + + /* finder info entry */ + write_four(APPLESINGLE_FINDERINFO_ENTRY, f); + write_four(offset, f); + write_four(APPLESINGLE_FINDERINFO_LEN, f); + offset += APPLESINGLE_FINDERINFO_LEN; + + /* resource fork entry */ + write_four(APPLESINGLE_RFORK_ENTRY, f); + write_four(offset, f); + write_four(rf_len, f); + offset += rf_len; + + /* data fork entry */ + if (!appledouble) { + write_four(APPLESINGLE_DFORK_ENTRY, f); + write_four(offset, f); + write_four(0, f); + } + + /* real name data */ + fwrite(filename, 1, len, f); + + /* time data */ + i = time(0) - APPLESINGLE_TIME_DELTA; + write_four(i, f); /* creation date */ + write_four(i, f); /* modification date */ + write_four(0x80000000, f); /* backup date */ + write_four(0, f); /* access date */ + + /* finder info data */ + write_four(T1_FILETYPE, f); /* file type */ + write_four(T1_FILECREATOR, f); /* file creator */ + write_one(T1_FINDERFLAGS, f); /* finder flags */ + write_one(0, f); /* extended finder flags */ + write_two(0, f); /* vertical position in window */ + write_two(0, f); /* horizontal position in window */ + write_two(0, f); /* window or folder ID */ + write_four(0, f); /* icon ID and reserved */ + write_four(0, f); /* reserved */ + write_one(0, f); /* script flag */ + write_one(0, f); /* reserved */ + write_two(0, f); /* comment ID */ + write_four(0, f); /* put away */ + + /* resource fork data */ + output_raw(rf, rf_len, f); +} + + +/* write a BinHex file */ + +static void +binhex_buffer(const byte *s, int len, FILE *f) +{ + static int col = 1; + static int bits = 0; + static int bitspos = 2; + static const char *table = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr"; + byte buf[5]; + int c, i, left; + + if (!s && bitspos > 2) { /* output the remaining bits */ + s = (const byte *)"\0"; + len = 1; + } + + for (left = len; left > 0; left--, s++) { + int pos; + if (s[0] == 0x90) { + buf[0] = 0x90; + buf[1] = 0x00; + pos = 2; + } else { + buf[0] = s[0]; + pos = 1; + } + + /* find a run */ + if (left > 2 && s[0] == s[1] && s[0] == s[2]) { + for (i = 3; i < left && i < 255; i++) + if (s[i] != s[0]) + break; + buf[pos] = 0x90; + buf[pos+1] = i; + pos += 2; + s += i - 1; + left -= i - 1; + } + + /* store those characters */ + for (i = 0; i < pos; i++) { + bits |= buf[i]; + while (bitspos >= 0) { + c = (bits >> bitspos) & 0x3F; + putc(table[c], f); + if (++col == 63) { + putc('\n', f); + col = 0; + } + bitspos -= 6; + } + bits <<= 8; + bitspos += 8; + } + } +} + +static void +output_binhex(FILE *rf, int32_t rf_len, const char *filename, FILE *f) +{ + int crc, len = strlen(filename); + char buf[2048]; + + if (len < 1 || len > 63) + fatal_error("filename length must be between 1 and 63"); + store_one(len, buf+0); /* filename length */ + memcpy(buf+1, filename, len); /* filename */ + store_one(0, buf+1+len); /* version */ + store_four(T1_FILETYPE, buf+2+len); /* file type */ + store_four(T1_FILECREATOR, buf+6+len); /* file creator */ + store_one(T1_FINDERFLAGS, buf+10+len); /* finder flags */ + store_one(0, buf+11+len); /* extended finder flags */ + store_four(0, buf+12+len); /* length of data fork */ + store_four(rf_len, buf+16+len); /* length of resource fork */ + store_two(crcbuf(0, 20+len, buf), buf+20+len); /* CRC */ + store_two(0, buf+22+len); /* data fork CRC */ + + /* output BinHex comment */ + fputs("(This file must be converted with BinHex 4.0)\n:", f); + + /* BinHex the header */ + binhex_buffer((const byte *)buf, 24+len, f); + + /* resource fork data */ + reposition(rf, 0); + crc = 0; + while (rf_len > 0) { + int n = (rf_len < 2048 ? rf_len : 2048); + fread(buf, 1, n, rf); + crc = crcbuf(crc, n, buf); /* update CRC */ + binhex_buffer((const byte *)buf, n, f); + rf_len -= n; + } + store_two(crc, buf); /* resource fork CRC */ + binhex_buffer((const byte *)buf, 2, f); + binhex_buffer(0, 0, f); /* get rid of any remaining bits */ + fputs(":\n", f); /* trailer */ +} + + +/***** + * command line + **/ + +#define OUTPUT_OPT 301 +#define VERSION_OPT 302 +#define HELP_OPT 303 +#define MACBINARY_OPT 304 +#define RAW_OPT 305 +#define APPLESINGLE_OPT 306 +#define APPLEDOUBLE_OPT 307 +#define BINHEX_OPT 308 +#define FILENAME_OPT 309 + +static Clp_Option options[] = { + { "appledouble", 0, APPLEDOUBLE_OPT, 0, 0 }, + { "applesingle", 0, APPLESINGLE_OPT, 0, 0 }, + { "binhex", 0, BINHEX_OPT, 0, 0 }, + { "help", 0, HELP_OPT, 0, 0 }, + { "macbinary", 0, MACBINARY_OPT, 0, 0 }, + { "filename", 'n', FILENAME_OPT, Clp_ValString, 0 }, + { "output", 'o', OUTPUT_OPT, Clp_ValString, 0 }, + { "raw", 'r', RAW_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); + 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); +} + + +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("\ +`T1mac' translates a PostScript Type 1 font from PFA or PFB format into\n\ +Macintosh Type 1 format. The result can be written in MacBinary II format (the\n\ +default), AppleSingle format, AppleDouble format, or BinHex format, or as a\n\ +raw resource fork. It is sent to the standard output unless an OUTPUT file is\n\ +given.\n\ +\n\ +Usage: %s [OPTION]... [INPUT [OUTPUT]]\n\ +\n\ +Options:\n\ + -r, --raw Output is a raw Macintosh resource fork.\n\ + --macbinary Output is in MacBinary format (default).\n\ + --applesingle Output is in AppleSingle format.\n\ + --appledouble Output is in AppleDouble format.\n\ + --binhex Output is in BinHex format.\n\ + -n, --filename NAME Macintosh font filename will be NAME.\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[]) +{ + int i, c; + FILE *ifp = 0, *ofp = 0; + const char *ifp_filename = "<stdin>"; + const char *ofp_filename = "<stdout>"; + const char *set_font_name = 0; + struct font_reader fr; + uint32_t rfork_len; + int raw = 0, macbinary = 1, applesingle = 0, appledouble = 0, binhex = 0; + + 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 RAW_OPT: + raw = 1; + macbinary = applesingle = appledouble = binhex = 0; + break; + + case MACBINARY_OPT: + macbinary = 1; + raw = applesingle = appledouble = binhex = 0; + break; + + case APPLESINGLE_OPT: + applesingle = 1; + raw = macbinary = appledouble = binhex = 0; + break; + + case APPLEDOUBLE_OPT: + appledouble = 1; + raw = macbinary = applesingle = binhex = 0; + break; + + case BINHEX_OPT: + binhex = 1; + raw = macbinary = applesingle = appledouble = 0; + break; + + output_file: + case OUTPUT_OPT: + if (ofp) + fatal_error("output file already specified"); + if (strcmp(clp->vstr, "-") == 0) + ofp = stdout; + else { + ofp_filename = clp->vstr; + ofp = fopen(ofp_filename, "wb"); + if (!ofp) fatal_error("%s: %s", ofp_filename, strerror(errno)); + } + break; + + case FILENAME_OPT: + if (set_font_name) + fatal_error("Macintosh font filename already specified"); + set_font_name = clp->vstr; + break; + + case HELP_OPT: + usage(); + exit(0); + break; + + case VERSION_OPT: + printf("t1mac (LCDF t1utils) %s\n", VERSION); + printf("Copyright (C) 2000-2003 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, "r"); + 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 are processing a PFB (binary) output */ + /* file, we must set its file mode to binary. */ + _setmode(_fileno(ofp), _O_BINARY); +#endif + + /* prepare font reader */ + fr.output_ascii = t1mac_output_ascii; + fr.output_binary = t1mac_output_binary; + fr.output_end = t1mac_output_end; + + /* prepare resource fork file */ + rfork_f = tmpfile(); + if (!rfork_f) + fatal_error("cannot open temorary file: %s", strerror(errno)); + for (i = 0; i < RFORK_HEADERLEN; i++) + putc(0, rfork_f); + init_current_post(); + + /* 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); + if (ifp != stdin) + fclose(ifp); + + /* check if anything was read */ + if (nrsrc == 0) + error("no POST resources written -- are you sure this was a font?"); + + /* output large B/W icon */ + output_new_rsrc("ICN#", 256, 32, (const char *)icon_bw_data, 256); + /* output FREF */ + output_new_rsrc("FREF", 256, 32, "LWFN\0\0\0", 7); + /* output BNDL */ + output_new_rsrc("BNDL", 256, 32, "T1UT\0\0\0\1FREF\0\0\0\0\1\0ICN#\0\0\0\0\1\0", 28); + /* output other icons */ + output_new_rsrc("icl8", 256, 32, (const char *)icon_8_data, 1024); + output_new_rsrc("icl4", 256, 32, (const char *)icon_4_data, 512); + output_new_rsrc("ics#", 256, 32, (const char *)small_icon_bw_data, 64); + output_new_rsrc("ics8", 256, 32, (const char *)small_icon_8_data, 256); + output_new_rsrc("ics4", 256, 32, (const char *)small_icon_4_data, 128); + /* output T1UT (signature) */ + output_new_rsrc("T1UT", 0, 0, "DConverted by t1mac (t1utils) \251Eddie Kohler http://www.lcdf.org/type/", 69); + + /* finish off resource file */ + rfork_len = complete_rfork(); + + /* prepare font name */ + if (!set_font_name && font_name) { + int part = 0, len = 0; + char *x, *s; + for (x = s = font_name; *s; s++) + if (isupper(*s) || isdigit(*s)) { + *x++ = *s; + part++; + len = 1; + } else if (islower(*s)) { + if (len < (part <= 1 ? 5 : 3)) + *x++ = *s; + len++; + } + *x++ = 0; + set_font_name = font_name; + } else if (!set_font_name) + set_font_name = "Unknown Font"; + + /* now, output the file */ + if (macbinary) + output_macbinary(rfork_f, rfork_len, set_font_name, ofp); + else if (raw) + output_raw(rfork_f, rfork_len, ofp); + else if (applesingle || appledouble) + output_applesingle(rfork_f, rfork_len, set_font_name, ofp, appledouble); + else if (binhex) + output_binhex(rfork_f, rfork_len, set_font_name, ofp); + else + fatal_error("strange output format"); + fclose(rfork_f); + + if (ofp != stdout) + fclose(ofp); + return 0; +} diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1unmac.1 b/Build/source/utils/t1utils/t1utils-1.35/t1unmac.1 new file mode 100644 index 00000000000..1814a5ec684 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1unmac.1 @@ -0,0 +1,79 @@ +.ds V 1.35 +.de M +.BR "\\$1" "(\\$2)\\$3" +.. +.TH T1UNMAC 1 "" "Version \*V" +.SH NAME +t1unmac \- translate a Mac PostScript Type 1 font into PFA or PFB format +.SH SYNOPSIS +.B t1unmac +\%[\fB\-a\fR|\fB\-b\fR] +\%[\fB\-r\fR] +\%[\fIinput\fR [\fIoutput\fR]] +.SH DESCRIPTION +.B t1unmac +extracts POST resources from a Macintosh PostScript font file and creates a +PFA (hexadecimal) or PFB (binary) font file. The file +.I input +should be in MacBinary I or II, AppleSingle, AppleDouble, or BinHex format, +or it can be a raw resource fork. If the file is a raw resource fork, you +need to give the `\-\-raw' option; otherwise +.B t1unmac +should automatically figure out what kind of file you have. If the file +.I output +is not specified output goes to the standard output. +.SH OPTIONS +.TP 5 +.BR \-\-pfa ", " \-a +Output in PFA (ASCII) format. +.TP 5 +.BR \-\-pfb ", " \-b +Output in PFB (binary) format. This is the default. +.TP 5 +.BR \-\-raw ", " \-r +Indicates that the input is a raw resource fork. +.TP 5 +.BR \-\-macbinary +Indicates that the input is in MacBinary I or II format. +.TP 5 +.BR \-\-applesingle +Indicates that the input is in AppleSingle format. +.TP 5 +.BR \-\-appledouble +Indicates that the input is in AppleDouble format. +.TP 5 +.BR \-\-binhex +Indicates that the input is in BinHex 4.0 format. +.TP +.BI \-\-block\-length= "num\fR, " \-l " num" +PFB only: Set the maximum output block length to +.I num. +The default length is as large as memory allows. +.TP +.BI \-\-line\-length= "num\fR, " \-l " num" +PFA only: Set the maximum length of encrypted lines in the output to +.I num. +(These are the lines consisting wholly of hexadecimal digits.) The default +is 64. +.SH EXAMPLES +.LP +On Mac OS X, you can use +.B t1unmac +to translate a font into PFA or PFB format as follows: +.nf +% \fBt1unmac\fR \-\-raw FONTFILENAME/..namedfork/rsrc > OUTPUT +.fi +.SH "SEE ALSO" +.LP +.M t1mac 1 , +.M t1ascii 1 , +.M t1binary 1 , +.M t1asm 1 , +.M t1disasm 1 +.SH AUTHORS +Lee Hetherington (ilh@lcs.mit.edu) +.br +Eddie Kohler (ekohler@gmail.com) +.PP +Ported to Microsoft C/C++ Compiler and MS-DOS operating system by +Kai-Uwe Herbing (herbing@netmbx.netmbx.de). diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1unmac.c b/Build/source/utils/t1utils/t1utils-1.35/t1unmac.c new file mode 100644 index 00000000000..73d524f2878 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1unmac.c @@ -0,0 +1,918 @@ +/* t1unmac/unpost + * + * This program converts Macintosh Type 1 fonts stored in MacBinary (I or II), + * AppleSingle, AppleDouble, BinHex, or raw resource fork format to PFA and + * PFB formats. + * + * Copyright (c) 1992 by I. Lee Hetherington, all rights reserved. + * + * Permission is hereby granted to use, modify, and distribute this program + * for any purpose provided this copyright notice and the one below remain + * intact. + * + * I. Lee Hetherington (ilh@lcs.mit.edu) + * + * 1.5 and later versions contain changes by, and are maintained by, + * Eddie Kohler <ekohler@gmail.com>. + * + * New change log in `NEWS'. Old change log: + * + * Revision 1.2 92/06/23 10:57:33 ilh + * MSDOS porting by Kai-Uwe Herbing (herbing@netmbx.netmbx.de) + * incoporated. + * + * Revision 1.1 92/05/22 12:07:49 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 <getopt.h> +# include <io.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <lcdf/clp.h> +#include "t1lib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Some functions to read one, two, three, and four byte integers in 68000 + byte order (most significant byte first). */ + +static int +read_one(FILE *fi) +{ + return getc(fi); +} + +static int +read_two(FILE *fi) +{ + int val; + + val = getc(fi); + val = (val << 8) | getc(fi); + + return val; +} + +static int32_t +read_three(FILE *fi) +{ + int32_t val; + + val = getc(fi); + val = (val << 8) | getc(fi); + val = (val << 8) | getc(fi); + + return val; +} + +static int32_t +read_four(FILE *fi) +{ + int32_t val; + + val = getc(fi); + val = (val << 8) | getc(fi); + val = (val << 8) | getc(fi); + val = (val << 8) | getc(fi); + + return val; +} + +/* reposition a file with error messages */ + +static void +reposition(FILE *fi, int32_t absolute) +{ + if (fseek(fi, absolute, 0) == -1) + fatal_error("can't seek to position %d\n\ + (The Mac file may be corrupted, or you may need the `-r' option.)", + absolute); +} + +static int blocklen = -1; + +static int hex_column = 0; /* current column of hex ASCII output */ + +static void +output_hex_byte(FILE *fo, int b) +{ + static const char *hex = "0123456789abcdef"; + + if (hex_column >= blocklen) { + putc('\n', fo); + hex_column = 0; + } + putc(hex[b >> 4], fo); + putc(hex[b & 0xf], fo); + hex_column += 2; +} + +/* Function to extract a particular POST resource. Offset points to the four + byte length which is followed by the data. The first byte of the POST data + specifies resource type: 1 for ASCII, 2 for binary, and 5 for end. The + second byte is always zero. */ + + +/* Function to write four byte length to PFB file: least significant byte + first. */ + +static int +extract_data(FILE *fi, FILE *fo, struct pfb_writer *w, int32_t offset, int pfb) +{ + enum PS_type { PS_ascii = 1, PS_binary = 2, PS_end = 5 }; + static int last_type = -1; + static int skip_newline = 0; + int32_t len; + int more = 1; + int i, c; + + reposition(fi, offset); + len = read_four(fi) - 2; /* subtract type field */ + + switch ((enum PS_type)read_one(fi)) { + + case PS_ascii: { + (void) read_one(fi); + if (last_type != PFB_ASCII && pfb) { + pfb_writer_output_block(w); + w->blocktyp = PFB_ASCII; + } + for (i = 0; i < len; i++) { + c = read_one(fi); + if (c == '\n' && skip_newline) { + skip_newline = 0; + continue; + } + if (c == '\r') { + c = '\n'; + skip_newline = 1; + } else + skip_newline = 0; + if (pfb) + PFB_OUTPUT_BYTE(w, c); + else + putc(c, fo); + } + last_type = PFB_ASCII; + break; + } + + case PS_binary: { + (void) read_one(fi); + if (last_type != PFB_BINARY && pfb) { + pfb_writer_output_block(w); + w->blocktyp = PFB_BINARY; + } else if (last_type != PFB_BINARY) + hex_column = 0; + if (pfb) { + while (len--) + PFB_OUTPUT_BYTE(w, read_one(fi)); + } else { + while (len--) + output_hex_byte(fo, read_one(fi)); + } + last_type = PFB_BINARY; + break; + } + + case PS_end: + more = 0; + break; + + } + + return more; +} + + +/***** + * Command line + **/ + +#define OUTPUT_OPT 301 +#define VERSION_OPT 302 +#define HELP_OPT 303 +#define PFB_OPT 304 +#define PFA_OPT 305 +#define MACBINARY_OPT 306 +#define RAW_OPT 307 +#define LINE_LEN_OPT 308 +#define APPLEDOUBLE_OPT 309 +#define BINHEX_OPT 310 + +static Clp_Option options[] = { + { "applesingle", 0, APPLEDOUBLE_OPT, 0, 0 }, + { "appledouble", 0, APPLEDOUBLE_OPT, 0, 0 }, + { "binhex", 0, BINHEX_OPT, 0, 0 }, + { "block-length", 0, LINE_LEN_OPT, Clp_ValUnsigned, 0 }, + { "help", 0, HELP_OPT, 0, 0 }, + { "line-length", 'l', LINE_LEN_OPT, Clp_ValUnsigned, 0 }, + { "macbinary", 0, MACBINARY_OPT, 0, 0 }, + { "output", 'o', OUTPUT_OPT, Clp_ValString, 0 }, + { "pfa", 'a', PFA_OPT, 0, 0 }, + { "pfb", 'b', PFB_OPT, 0, 0 }, + { "raw", 'r', RAW_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); + 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); +} + +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("\ +`T1unmac' extracts a PostScript Type 1 font from a Macintosh font file. It can\n\ +read MacBinary, AppleSingle, AppleDouble, or BinHex files, or raw Macintosh\n\ +resource forks. The result is written to the standard output unless an OUTPUT\n\ +file is given.\n\ +\n\ +Usage: %s [OPTION]... INPUT [OUTPUT]\n\ +\n\ +Options:\n\ + -r, --raw Input is a raw Macintosh resource fork.\n\ + --macbinary Input is in MacBinary format.\n\ + --applesingle Input is in AppleSingle format.\n\ + --appledouble Input is in AppleDouble format.\n\ + --binhex Input is in BinHex format.\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); +} + + +static const char * +check_macbinary(FILE *ifp) +{ + int i, j; + char buf[124]; + + /* check "version" bytes at offsets 0 and 74 */ + reposition(ifp, 0); + if (read_one(ifp) != 0) + return "bad version byte"; + reposition(ifp, 74); + if (read_one(ifp) != 0) + return "bad version byte"; + +#if 0 + /* write out bullshit */ + {int t; + reposition(ifp, 65); + t = read_four(ifp); + fprintf(stderr, "Type %c%c%c%c\n", (t>>24)&255, (t>>16)&255, (t>>8)&255, t&255); + t = read_four(ifp); + fprintf(stderr, "Creator %c%c%c%c\n", (t>>24)&255, (t>>16)&255, (t>>8)&255, t&255); + t = read_one(ifp); + fprintf(stderr, "Finder flags 1 %02x\n", t); + read_one(ifp); + t = read_two(ifp); + fprintf(stderr, "horizpos %04x\n", t); + t = read_two(ifp); + fprintf(stderr, "vertpos %04x\n", t); + t = read_two(ifp); + fprintf(stderr, "folder id %d\n", t); + t = read_one(ifp); + fprintf(stderr, "protected? %x\n", t); + t = read_one(ifp); + t = read_four(ifp); + fprintf(stderr, "data len %d\n", t); + t = read_four(ifp); + fprintf(stderr, "rsrc len %d\n", t); + t = read_four(ifp); + { + struct tm *crap; + fprintf(stderr, "creation date %x\n", t); + t -= 2082844800; + fprintf(stderr, " %s\n", ctime(&t)); + t = read_four(ifp); + fprintf(stderr, "modification date %x\n", t); + t -= 2082844800; + fprintf(stderr, " %s\n", ctime(&t)); + t = read_two(ifp); + } + fprintf(stderr, "getinfo len %d\n", t); + t = read_one(ifp); + fprintf(stderr, "finderflags 2 %02x\n", t); + reposition(ifp, 116); + t = read_four(ifp); + fprintf(stderr, "total len %d\n", t); + t = read_two(ifp); + fprintf(stderr, "secondary header len %d\n", t); + t = read_one(ifp); + fprintf(stderr, "version %d\n", t); + t = read_one(ifp); + fprintf(stderr, "version %d\n", t); + } +#endif + + /* check file length */ + reposition(ifp, 1); + i = read_one(ifp); + if (i > 63) + return "bad length"; + reposition(ifp, 83); + i = read_four(ifp); + j = read_four(ifp); + if (i < 0 || j < 0 || i >= 0x800000 || j >= 0x800000) + return "bad length"; + + /* check CRC */ + reposition(ifp, 0); + fread(buf, 1, 124, ifp); + if (crcbuf(0, 124, buf) != read_two(ifp)) { + reposition(ifp, 82); + if (read_one(ifp) != 0) + return "bad checksum"; + } + + return 0; +} + +#define APPLESINGLE_MAGIC 0x00051600 +#define APPLEDOUBLE_MAGIC 0x00051607 + +static const char * +check_appledouble(FILE *ifp) +{ + int i; + reposition(ifp, 0); + i = read_four(ifp); + if (i != APPLEDOUBLE_MAGIC && i != APPLESINGLE_MAGIC) + return "bad magic number"; + + return 0; +} + +static const char * +translate_binhex(FILE *f, FILE *tmpf) +{ + int i, c = 0, last_char, after_x90, bits, bitpos; + unsigned char value_table[256]; + + /* prepare value table */ + { + const char *table = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr"; + for (i = 0; i < 256; i++) + value_table[i] = 255; + for (i = 0; *table; i++, table++) + value_table[(unsigned char)*table] = i; + } + + /* skip to comment */ + { + const char *comment = "(This file must be converted with BinHex"; + while (!feof(f)) { + const char *s; + for (s = comment; *s; s++) { + c = getc(f); + if (c != *s) + break; + } + /* skip to end of line */ + while (c >= 0 && c != '\n' && c != '\r') + c = getc(f); + /* stop if read comment */ + if (!*s) + goto found_comment; + } + /* failed */ + return "no comment"; + } + + found_comment: + /* skip spaces, look for ':' */ + for (c = ' '; isspace(c); c = getc(f)) ; + if (c != ':') + return "no file-start character"; + + /* found ':', process until you find another ':' */ + last_char = -1; + after_x90 = bits = 0; + bitpos = 10; + for (c = getc(f); c >= 0; c = getc(f)) + if (!isspace(c)) { + /* add 6 bits to bits */ + if (value_table[c] == 255) + break; + bits |= (value_table[c] << bitpos); + bitpos -= 6; + + /* output character(s) */ + if (bitpos <= 2) { + int d = bits >> 8; + bits = (bits << 8) & 0xFF00; + bitpos += 8; + if (after_x90) { + /* handle compression */ + if (d == 0) { + last_char = 0x90; + putc(0x90, tmpf); + } else + for (i = 1; i < d; i++) + putc(last_char, tmpf); + after_x90 = 0; + } else if (d == 0x90) + after_x90 = 1; + else { + last_char = d; + putc(d, tmpf); + } + } + } + + if (c < 0) + return "unexpected EOF"; + else if (c != ':') + return "bad character"; + + fflush(tmpf); + return 0; +} + +static int +check_binhex_crc(FILE *f, int offset, int length) +{ + int crc = 0; + char buf[2048]; + reposition(f, offset); + while (length > 0) { + int n = (length < 2048 ? length : 2048); + fread(buf, 1, n, f); + crc = crcbuf(crc, n, buf); + length -= n; + } + return crc == 0; +} + +static const char * +check_binhex(FILE *f) +{ + int fname_len, data_len, rsrc_len, off; + + /* check lengths */ + reposition(f, 0); + fname_len = read_one(f); + if (fname_len < 1 || fname_len > 63) + return "bad length"; + reposition(f, 1 + fname_len + 11); + data_len = read_four(f); + rsrc_len = read_four(f); + if (data_len < 0 || rsrc_len < 0 || data_len >= 0x800000 || rsrc_len >= 0x800000) + return "bad length"; + + /* check version */ + reposition(f, 1 + fname_len); + if (read_one(f) != 0) + return "bad version"; + + /* check CRC */ + off = 1 + fname_len + 21; + if (!check_binhex_crc(f, 0, off)) + return "bad header CRC"; + if (!check_binhex_crc(f, off, data_len + 2)) + return "bad data CRC"; + if (!check_binhex_crc(f, off + data_len + 2, rsrc_len + 2)) + return "bad resource fork CRC"; + + return 0; +} + +#ifdef __cplusplus +} +#endif + + +int +main(int argc, char *argv[]) +{ + FILE *ifp = 0; + FILE *ofp = 0; + struct pfb_writer w; + const char *ifp_name = "<stdin>"; + int32_t res_offset, res_data_offset, res_map_offset, type_list_offset; + int32_t post_type; + int num_types, num_extracted = 0, pfb = 1; + int raw = 0, appledouble = 0, binhex = 0, macbinary = 0; + + 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 RAW_OPT: + raw = 1; + appledouble = binhex = macbinary = 0; + break; + + case MACBINARY_OPT: + macbinary = 1; + raw = appledouble = binhex = 0; + break; + + case APPLEDOUBLE_OPT: + appledouble = 1; + raw = binhex = macbinary = 0; + break; + + case BINHEX_OPT: + binhex = 1; + raw = appledouble = macbinary = 0; + break; + + 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 PFB_OPT: + pfb = 1; + break; + + case PFA_OPT: + pfb = 0; + break; + + case LINE_LEN_OPT: + blocklen = clp->val.i; + break; + + case HELP_OPT: + usage(); + exit(0); + break; + + case VERSION_OPT: + printf("t1unmac (LCDF t1utils) %s\n", VERSION); + printf("Copyright (C) 1992-2003 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_name = 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) + _setmode(_fileno(ifp), _O_BINARY); + /* If we are processing a PFB (binary) output */ + /* file, we must set its file mode to binary. */ + if (pfb) + _setmode(_fileno(ofp), _O_BINARY); +#endif + + if (pfb) + init_pfb_writer(&w, blocklen, ofp); + else { + 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); + } + } + + /* check for non-seekable input */ + if (fseek(ifp, 0, 0)) { + char buf[2048]; + FILE *tmp = tmpfile(); + if (!tmp) + fatal_error("cannot open temporary file: %s", strerror(errno)); + while (!feof(ifp)) { + int i = fread(buf, 1, 2048, ifp); + if (i > 0) + fwrite(buf, 1, i, tmp); + } + if (ferror(ifp)) + fatal_error("%s: %s", ifp_name, strerror(errno)); + reposition(tmp, 0); + fflush(tmp); + if (ifp != stdin) + fclose(ifp); + ifp = tmp; + } + + /* check for empty file */ + fseek(ifp, 0, 2); + if (ftell(ifp) == 0) + fatal_error("%s: empty file\n\ + (Try re-transferring the files using MacBinary format.)", + ifp_name); + + reposition(ifp, 0); + if (!raw && !appledouble && !binhex && !macbinary) { + /* check magic number, try to figure out what it is */ + int i, magic; + magic = read_four(ifp); + reposition(ifp, 0); + + if (magic == APPLESINGLE_MAGIC || magic == APPLEDOUBLE_MAGIC) + appledouble = 1; + else if ((magic & 0xFF000000) == 0) + macbinary = 1; + else { + binhex = 1; + for (i = 0; i < 4; i++, magic >>= 8) + if (!isprint(magic & 0xFF) && !isspace(magic & 0xFF)) + /* not an ASCII character, assume not BinHex */ + binhex = 0; + } + + if (!appledouble && !macbinary && !binhex) + fatal_error("%s: unknown file type", ifp_name); + } + + if (raw) { + /* raw resource file */ + res_offset = 0; + + } else if (macbinary) { /* MacBinary (I or II) file */ + const char *check; + int32_t data_fork_size; + + /* check integrity of file */ + check = check_macbinary(ifp); + if (check) + fatal_error("%s: not a MacBinary file (%s)", ifp_name, check); + + /* read data and resource fork sizes in MacBinary header */ + reposition(ifp, 83); + data_fork_size = read_four(ifp); + (void) read_four(ifp); + + /* round data_fork_size up to multiple of 128 */ + if (data_fork_size % 128) + data_fork_size += 128 - data_fork_size % 128; + + res_offset = 128 + data_fork_size; + + } else if (appledouble) { /* AppleDouble file */ + const char *check; + const char *applewhat; + int i, n; + + /* check integrity */ + check = check_appledouble(ifp); + if (check) + fatal_error("%s: not an AppleDouble file (%s)", ifp_name, check); + reposition(ifp, 0); + if (read_four(ifp) == APPLESINGLE_MAGIC) + applewhat = "AppleSingle"; + else + applewhat = "AppleDouble"; + + /* find offset to resource and/or data fork */ + reposition(ifp, 24); + n = read_two(ifp); + res_offset = -1; + for (i = 0; i < n; i++) { + int type = read_four(ifp); + if (type == 0) + fatal_error("%s: bad %s file (bad entry descriptor)", ifp_name, applewhat); + if (type == 2) /* resource fork entry */ + res_offset = read_four(ifp); + else + (void) read_four(ifp); + (void) read_four(ifp); + } + if (res_offset < 0) + fatal_error("%s: bad %s file (no resource fork)", ifp_name, applewhat); + + } else if (binhex) { /* BinHex file */ + const char *check; + FILE *tmpf = tmpfile(); + if (!tmpf) + fatal_error("cannot open temporary file: %s", strerror(errno)); + + /* check integrity */ + check = translate_binhex(ifp, tmpf); + if (check) + fatal_error("%s: not a BinHex file (%s)", ifp_name, check); + check = check_binhex(tmpf); + if (check) + fatal_error("%s: bad BinHex file (%s)", ifp_name, check); + + /* find resource offset */ + reposition(tmpf, 0); + res_offset = read_one(tmpf); + reposition(tmpf, 1 + res_offset + 11); + res_offset += 22 + read_four(tmpf) + 2; + if (ifp != stdin) + fclose(ifp); + ifp = tmpf; + + } else { + fatal_error("%s: strange format", ifp_name); + exit(1); + } + + /* read offsets from resource fork header */ + reposition(ifp, res_offset); + res_data_offset = res_offset + read_four(ifp); + res_map_offset = res_offset + read_four(ifp); + + /* read type list offset from resource map header */ + reposition(ifp, res_map_offset + 24); + type_list_offset = res_map_offset + read_two(ifp); + + /* read type list */ + reposition(ifp, type_list_offset); + num_types = read_two(ifp) + 1; + + /* find POST type */ + post_type = (int32_t)('P' & 0xff) << 24; + post_type |= (int32_t)('O' & 0xff) << 16; + post_type |= (int32_t)('S' & 0xff) << 8; + post_type |= (int32_t)('T' & 0xff); + + while (num_types--) { + if (read_four(ifp) == post_type) { + int nrsrc = 1 + read_two(ifp); + int list_offset = type_list_offset + read_two(ifp); + int rsrc_pos = 0; + int want_id = 501; + int second_time = 1; + reposition(ifp, list_offset); + /* read resources sequentially, starting with ID 501, until we encounter + an "end" resource or we can't find the next resource */ + while (rsrc_pos < nrsrc) { + int offset = ftell(ifp); + int id = read_two(ifp); + if (id == want_id) { + (void) read_two(ifp); + (void) read_one(ifp); + num_extracted++; + if (!extract_data(ifp, ofp, &w, res_data_offset + read_three(ifp), pfb)) + break; + second_time = 0; + want_id++; + } + reposition(ifp, offset + 12); + rsrc_pos++; + if (rsrc_pos >= nrsrc && !second_time) { + reposition(ifp, list_offset); + rsrc_pos = 0; + } + } + break; + } else { + (void) read_two(ifp); + (void) read_two(ifp); + } + } + +#if 0 + system("/bin/rm -f /tmp/x.*"); + { + FILE *f; + int i; + reposition(ifp, res_offset + 16); + if ((f = fopen("/tmp/x.systemarea", "wb"))) { + for (i = res_offset + 16; i < res_data_offset; i++) { + putc(getc(ifp), f); + } + fclose(f); + } + } + reposition(ifp, type_list_offset); + num_types = read_two(ifp) + 1; + while (num_types--) { + int t = read_four(ifp); + int num_of_type = 1 + read_two(ifp); + int32_t save_offset = ftell(ifp) + 2; + reposition(ifp, type_list_offset + read_two(ifp)); + while (num_of_type--) { + FILE *f; + char buf[2048]; + int x, i, attrs; + x = ftell(ifp); + i = read_two(ifp); /* ID */ + read_two(ifp); + attrs = read_one(ifp); + sprintf(buf, "/tmp/x.%c%c%c%c.%d", (t>>24)&255, (t>>16)&255, (t>>8)&255, t&255, i); + fprintf(stderr, "%c%c%c%c.%d %d", (t>>24)&255, (t>>16)&255, (t>>8)&255, t&255, i, attrs); + if ((f = fopen(buf, "wb"))) { + int l; + reposition(ifp, res_data_offset + read_three(ifp)); + l = read_four(ifp); + fprintf(stderr, " %d\n", l); + while (l > 0) { + int n = (l < 2048 ? l : 2048); + fread(buf, 1, n, ifp); + fwrite(buf, 1, n, f); + l -= n; + } + fclose(f); + } + reposition(ifp, x + 12); + } + reposition(ifp, save_offset); + } +#endif + + if (pfb) + pfb_writer_end(&w); + if (num_extracted == 0) + error("%s: not a Type 1 font (no POST resources)", ifp_name); + + fclose(ifp); + fclose(ofp); + return 0; +} diff --git a/Build/source/utils/t1utils/t1utils-1.35/t1utils.spec b/Build/source/utils/t1utils/t1utils-1.35/t1utils.spec new file mode 100644 index 00000000000..362193d6968 --- /dev/null +++ b/Build/source/utils/t1utils/t1utils-1.35/t1utils.spec @@ -0,0 +1,53 @@ +Summary: Programs for manipulating PostScript Type 1 fonts + +Name: t1utils +Version: 1.35 +Release: 1 +Source: http://www.lcdf.org/type/t1utils-1.35.tar.gz + +URL: http://www.lcdf.org/type/ + +Group: Utilities/Printing +Vendor: Little Cambridgeport Design Factory +Packager: Eddie Kohler <ekohler@gmail.com> +License: freely modifiable and distributable + +BuildRoot: /tmp/t1utils-build + +%description +The t1utils package is a set of programs for +manipulating PostScript Type 1 fonts. It contains +programs to change between binary PFB format (for +storage), ASCII PFA format (for printing), a +human-readable and -editable ASCII format, and +Macintosh resource forks. + +%prep +%setup + +%build +%configure +make + +%install +[ "$RPM_BUILD_ROOT" != "/" ] && [ -d $RPM_BUILD_ROOT ] && rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT +make DESTDIR=$RPM_BUILD_ROOT install + +%clean +[ "$RPM_BUILD_ROOT" != "/" ] && [ -d $RPM_BUILD_ROOT ] && rm -rf $RPM_BUILD_ROOT + +%files +%attr(-,root,root) %doc NEWS README +%attr(0755,root,root) %{_bindir}/t1ascii +%attr(0755,root,root) %{_bindir}/t1binary +%attr(0755,root,root) %{_bindir}/t1asm +%attr(0755,root,root) %{_bindir}/t1disasm +%attr(0755,root,root) %{_bindir}/t1unmac +%attr(0755,root,root) %{_bindir}/t1mac +%attr(0644,root,root) %{_mandir}/man1/t1ascii.1* +%attr(0644,root,root) %{_mandir}/man1/t1binary.1* +%attr(0644,root,root) %{_mandir}/man1/t1asm.1* +%attr(0644,root,root) %{_mandir}/man1/t1disasm.1* +%attr(0644,root,root) %{_mandir}/man1/t1unmac.1* +%attr(0644,root,root) %{_mandir}/man1/t1mac.1* |