|
|
1.1 ! root 1: /* ! 2: * readPCL.c ! 3: * 3/31/93 ! 4: * ! 5: * Usage: readPCL [ -n ] [ infile [ outfile ]] ! 6: * Option: ! 7: * -n Produce nroff output; ! 8: * e.g. "troff foo.r | readPCL -n | nroff -x | more" ! 9: * Exit status: ! 10: * 0 success ! 11: * 1 unrecognized escape sequences seen ! 12: * 2 fatal error, e.g. file not found ! 13: * Requires floating point output: cc readPCL.c -f ! 14: * ! 15: * Expand PCL commands into readable text. ! 16: * This currently handles a very small subset of PCL-5, ! 17: * including only commands which the troff PCL output writer writes. ! 18: * Reference: HP "LaserJet III Technical Reference Manual", App. B. ! 19: */ ! 20: ! 21: #include <stdio.h> ! 22: #include <ctype.h> ! 23: ! 24: #define VERSION "1.2" ! 25: #define ESC '\033' ! 26: #define NVALUE 80 /* max parameter value length */ ! 27: ! 28: /* ! 29: * Parameterized commands. ! 30: * Very small subset of those available. ! 31: * PVCMD command format depends on parameter value, ! 32: * PCMD command format does not; ! 33: * the PVCMD list gets searched first. ! 34: */ ! 35: typedef struct pvcmd { ! 36: char pv_char; ! 37: char pv_group; ! 38: int pv_value; ! 39: char pv_param; ! 40: char *pv_fmt; ! 41: } PVCMD; ! 42: typedef struct pcmd { ! 43: char p_char; ! 44: char p_group; ! 45: char p_param; ! 46: char *p_fmt; ! 47: } PCMD; ! 48: ! 49: /* Parameterized commands with fixed values. */ ! 50: PVCMD pvcmds[] = { ! 51: { '(', 's', 0, 'p', "fixed" }, ! 52: { '(', 's', 1, 'p', "proportional" }, ! 53: { '(', 's', 0, 's', "upright" }, ! 54: { '(', 's', 1, 's', "italic" }, ! 55: { '&', 'l', 0, 'h', "page eject" } ! 56: }; ! 57: #define NPVCMDS (sizeof(pvcmds) / sizeof(pvcmds[0])) ! 58: ! 59: /* Parameterized commands with arbitrary values; format expects double arg. */ ! 60: PCMD pcmds[] = { ! 61: { '&', 'a', 'h', "h=%g" }, ! 62: { '&', 'a', 'v', "v=%g" }, ! 63: { '&', 'l', 'e', "top margin=%g" }, ! 64: { '(', '0', 'u', "symset=ASCII" }, ! 65: { '(', 's', 'b', "weight=%g" }, ! 66: { '(', 's', 'h', "pitch=%g" }, ! 67: { '(', 's', 't', "typeface=%g" }, ! 68: { '(', 's', 'v', "pointsize=%g" } ! 69: }; ! 70: #define NPCMDS (sizeof(pcmds) / sizeof(pcmds[0])) ! 71: ! 72: /* ! 73: * Two-character commands. ! 74: * Small subset of those available. ! 75: */ ! 76: typedef struct tcmd { ! 77: char t_char; ! 78: char *t_fmt; ! 79: } TCMD; ! 80: TCMD tcmds[] = { ! 81: { '9', "clear" }, ! 82: { 'E', "reset" } ! 83: }; ! 84: #define NTCMDS (sizeof(tcmds) / sizeof(tcmds[0])) ! 85: ! 86: /* External. */ ! 87: extern double atof(); ! 88: ! 89: /* Forward. */ ! 90: extern void error( /* char *fmt, ... */ ); ! 91: extern void escape( /* void */ ); ! 92: extern void esc_param( /* int c */ ); ! 93: extern void esc_two( /* int c */ ); ! 94: extern void fatal( /* char *fmt, ... */ ); ! 95: extern void lookup( /* int c, int group, double val, int param */ ); ! 96: extern FILE *openfile( /* char *name, char *mode */ ); ! 97: extern void usage( /* void */ ); ! 98: extern double value( /* void */ ); ! 99: ! 100: /* Globals. */ ! 101: int nflag; /* nroff output */ ! 102: int status; /* exit status */ ! 103: FILE *ifp = stdin; /* input FILE */ ! 104: FILE *ofp = stdout; /* output FILE */ ! 105: ! 106: int ! 107: main(argc, argv) int argc; char *argv[]; ! 108: { ! 109: register char *s; ! 110: register int c; ! 111: ! 112: /* Look for options. */ ! 113: if (argc > 1 && argv[1][0] == '-') { ! 114: for (s = &argv[1][1]; *s != '\0'; s++) { ! 115: switch(*s) { ! 116: case 'n': ++nflag; break; ! 117: case 'V': ! 118: fprintf(stderr, "readPCL: V" VERSION "\n"); ! 119: break; ! 120: default: usage(); break; ! 121: } ! 122: } ! 123: --argc; ! 124: ++argv; ! 125: } ! 126: ! 127: /* Open files. */ ! 128: if (argc > 1) ! 129: ifp = openfile(argv[1], "rb"); ! 130: if (argc > 2) ! 131: ofp = openfile(argv[2], "w"); ! 132: ! 133: /* Process. */ ! 134: if (nflag) ! 135: fprintf(ofp, ".nf\n"); ! 136: while ((c = getc(ifp)) != EOF) { ! 137: if (c == ESC) ! 138: escape(); ! 139: else ! 140: putc(c, ofp); ! 141: } ! 142: ! 143: /* Done. */ ! 144: if (ifp != stdin) ! 145: fclose(ifp); ! 146: if (ofp != stdout) ! 147: fclose(ofp); ! 148: exit(status); ! 149: } ! 150: ! 151: /* ! 152: * Print an unrecognized escape sequence to the output text ! 153: * and an error message to stderr. ! 154: * Bump the error count. ! 155: */ ! 156: /* VARARGS */ ! 157: void ! 158: error(fmt) char *fmt; ! 159: { ! 160: status = 1; ! 161: fprintf(ofp, "ESC %r", &fmt); ! 162: fprintf(stderr, "readPCL: unrecognized ESC sequence: ESC %r", &fmt); ! 163: } ! 164: ! 165: /* ! 166: * Handle an escape sequence. ! 167: */ ! 168: void ! 169: escape() ! 170: { ! 171: register int c; ! 172: ! 173: putc('\n', ofp); ! 174: if (nflag) ! 175: fprintf(ofp, "\\fB"); ! 176: putc('{', ofp); ! 177: if ((c = getc(ifp)) >= 33 && c <= 47) ! 178: esc_param(c); /* parameterized */ ! 179: else if (c >= 48 && c <= 126) ! 180: esc_two(c); /* two-character */ ! 181: else ! 182: error("%c (0x%X)", c, c); ! 183: putc('}', ofp); ! 184: if (nflag) ! 185: fprintf(ofp, "\\fP"); ! 186: } ! 187: ! 188: /* ! 189: * Parameterized escape sequence starting with c. ! 190: */ ! 191: void ! 192: esc_param(c) register int c; ! 193: { ! 194: int group, param, done; ! 195: double val; ! 196: ! 197: group = getc(ifp); ! 198: for (done = 0; !done; ) { ! 199: val = value(); ! 200: param = getc(ifp); ! 201: if (param >= 64 && param <= 94) { ! 202: ++done; ! 203: param += 32; ! 204: } ! 205: lookup(c, group, val, param); ! 206: if (!done) ! 207: putc(';', ofp); ! 208: } ! 209: } ! 210: ! 211: /* ! 212: * Two-character escape sequence starting with c. ! 213: */ ! 214: void ! 215: esc_two(c) register int c; ! 216: { ! 217: register TCMD *p; ! 218: ! 219: for (p = tcmds; p < &tcmds[NPCMDS]; p++) { ! 220: if (c == p->t_char) { ! 221: fprintf(ofp, p->t_fmt); ! 222: return; ! 223: } ! 224: } ! 225: error("%c (0x%X)", c, c); ! 226: } ! 227: ! 228: /* ! 229: * Print a fatal error message and die. ! 230: */ ! 231: /* VARARGS */ ! 232: void ! 233: fatal(fmt) char *fmt; ! 234: { ! 235: fprintf(stderr, "readPCL: %r\n", &fmt); ! 236: exit(2); ! 237: } ! 238: ! 239: /* ! 240: * Look up a parameterized command. ! 241: * Print either a formatted message or an error message. ! 242: */ ! 243: void ! 244: lookup(c, group, val, param) int c, group; double val; int param; ! 245: { ! 246: register PVCMD *pvp; ! 247: register PCMD *pcp; ! 248: ! 249: /* Look for commands with matching value first. */ ! 250: for (pvp = pvcmds; pvp < &pvcmds[NPVCMDS]; pvp++) { ! 251: if (c == pvp->pv_char ! 252: && group == pvp->pv_group ! 253: && (int)val == pvp->pv_value ! 254: && param == pvp->pv_param) { ! 255: fprintf(ofp, pvp->pv_fmt); ! 256: return; ! 257: } ! 258: } ! 259: ! 260: /* Then look for commands with arbitrary value. */ ! 261: for (pcp = pcmds; pcp < &pcmds[NPCMDS]; pcp++) { ! 262: if (c == pcp->p_char ! 263: && group == pcp->p_group ! 264: && param == pcp->p_param) { ! 265: fprintf(ofp, pcp->p_fmt, val); ! 266: return; ! 267: } ! 268: } ! 269: ! 270: /* Not found. */ ! 271: error("%c %c %g %c", c, group, val, param); ! 272: } ! 273: ! 274: /* ! 275: * Open a FILE. ! 276: */ ! 277: FILE * ! 278: openfile (name, mode) char *name; char *mode; ! 279: { ! 280: register FILE *fp; ! 281: ! 282: if ((fp = fopen(name, mode)) == NULL) ! 283: fatal("cannot open file \"%s\"", name); ! 284: return fp; ! 285: } ! 286: ! 287: /* ! 288: * Print a usage message and die. ! 289: */ ! 290: void ! 291: usage() ! 292: { ! 293: fprintf(stderr, ! 294: "Usage: readPCL [ -n ] [ infile [ outfile ]]\n" ! 295: "Option:\n" ! 296: "\t-n\tProduce nroff output;\n" ! 297: "\t\te.g. \"troff foo.r | readPCL -n | nroff -x | more\"\n" ! 298: ); ! 299: exit(1); ! 300: } ! 301: ! 302: /* ! 303: * Read a PCL value field: ! 304: * ASCII number consisting of optional sign, digits and optional decimal point. ! 305: * Return 0.0 if the value is missing. ! 306: */ ! 307: double ! 308: value() ! 309: { ! 310: char buf[NVALUE]; ! 311: register char *cp; ! 312: register int c, s, dotseen; ! 313: double d; ! 314: ! 315: /* Handle optional sign. */ ! 316: dotseen = s = 0; ! 317: if ((c = getc(ifp)) == '-') ! 318: ++s; ! 319: else if (c != '+') ! 320: ungetc(c, ifp); ! 321: ! 322: /* Read the number into buf[]. */ ! 323: for (cp = buf; isdigit(c = getc(ifp)) || (c=='.' && (dotseen++ == 0)); ) ! 324: *cp++ = c; ! 325: *cp = '\0'; ! 326: ungetc(c, ifp); ! 327: ! 328: /* Return converted value; note that atof("") returns 0.0. */ ! 329: d = atof(buf); ! 330: return (s) ? -d : d; ! 331: } ! 332: ! 333: /* end of readPCL.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.