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