diff options
Diffstat (limited to 'gs/contrib/pcl3/src/pclscan.c')
-rw-r--r-- | gs/contrib/pcl3/src/pclscan.c | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/gs/contrib/pcl3/src/pclscan.c b/gs/contrib/pcl3/src/pclscan.c new file mode 100644 index 000000000..55d7e5d0e --- /dev/null +++ b/gs/contrib/pcl3/src/pclscan.c @@ -0,0 +1,331 @@ +/****************************************************************************** + File: $Id: pclscan.c,v 1.8 2000-10-22 11:05:34+02 Martin Rel $ + Contents: PCL scanner + Author: Martin Lottermoser, Greifswaldstrasse 28, 38124 Braunschweig, + Germany, e-mail: Martin.Lottermoser@t-online.de + +******************************************************************************* +* * +* Copyright (C) 1999, 2000 by Martin Lottermoser * +* All rights reserved * +* * +******************************************************************************/ + +/* Configuration management identification */ +#ifndef lint +static const char + cm_id[] = "@(#)$Id: pclscan.c,v 1.8 2000-10-22 11:05:34+02 Martin Rel $"; +#endif + +/*****************************************************************************/ + +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 500 +#endif +#ifndef _XOPEN_SOURCE_EXTENDED +#define _XOPEN_SOURCE_EXTENDED 1 +#endif + +/* Standard headers */ +#include <errno.h> +#include <nl_types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* Special headers */ +#include "pclscan.h" + +/*****************************************************************************/ + +static nl_catd catd = (nl_catd)-1; /* NLS catalogue descriptor */ + + +static void message(int id, const char *s) +{ + if (catd != (nl_catd)-1) s = catgets(catd, 1, id, s); + /* The check might not be necessary (X/Open requires catgets() to return 's' + if the call is unsuccessful for *any* reason and the possible errors + include EBADF for an invalid 'catd'), but one never knows. */ + + fputs("? pclscan: ", stderr); + fprintf(stderr, s); + fputc('\n', stderr); + + return; +} + +/*****************************************************************************/ + +static const pcl_Octet ESC = '\x1B'; + +/****************************************************************************** + + Function: pcl_is_control_code + + This function returns a non-zero value iff 'c', taken to be an unsigned char + converted to 'int', is a PCL control code. + +******************************************************************************/ + +int pcl_is_control_code(int c) +{ + return + c <= ' ' && ( + c == '\0' || + /* TRG500 does not mention NUL as a control code. */ + c == '\b' || c == '\t' || c == '\n' || c == '\f' || c == '\r' || + c == '\x0E' /* Shift Out (SO) */ || + c == '\x0F' /* Shift In (SI) */ || + c == '\x11' /* Device Control 1 (DC1) */ || + c == '\x13' /* Device Control 3 (DC3) */ || + c == ESC || + c == ' '); +} + +/*****************************************************************************/ + +static int cmp_strings(const void *a, const void *b) +{ + return strncmp((const char *)a, (const char *)b, 3); +} + + +static int default_interpreter(FILE *in, const pcl_Command *cmd) +{ + /* Skip over arguments for those commands which are known to have them */ + if (cmd->kind >= 3) { + if (strncmp((const char *)cmd->chars, "%-X", 3) == 0 && cmd->i == 12345) { + /* Universal Exit Language (UEL)/Start of PJL */ + int c; + + do { + c = fgetc(in); + if (c != '@') break; + do c = fgetc(in); while (c != EOF && c != '\n'); + } while (c != EOF); + if (c != EOF) ungetc(c, in); + } + else if (cmd->i > 0) { + static const char with_args[][4] = { + /* Must be sorted with respect to cmp_strings() */ + "&bW", + "&iW", + "&pX", /* Transparent Print Mode */ + "(sW", /* Download Character */ + ")sW", /* Create Font */ + "*bV", /* Transfer Raster Graphics Data by Plane */ + "*bW", /* Transfer Raster Graphics Data by Row */ + "*dW", /* Palette Configuration */ + "*gW", /* Configure Raster Data */ + "*oW"}; + + if (bsearch(cmd->chars, with_args, + sizeof(with_args)/sizeof(with_args[0]), sizeof(with_args[0]), + &cmp_strings) != NULL) { + int j; + + j = cmd->i; + while (j > 0 && fgetc(in) != EOF) j--; + if (j > 0) { + message(1, "Premature EOF on input."); + return -1; + } + } + } + } + else if (cmd->kind == 2 && cmd->chars[0] == 'Y') { + /* Display Functions Mode ON */ + int c; + + /* Read until EOF or Display Functions Mode OFF */ + do { + do c = fgetc(in); while (c != EOF && c != ESC); + if (c != EOF) c = fgetc(in); + } while (c != EOF && c != 'Z'); + + if (c != 'Z') { + message(1, "Premature EOF on input."); + return -1; + } + } + + return 0; +} + +/*****************************************************************************/ + +static int default_handler(FILE *in) +{ + int c; + + do { + c = fgetc(in); + } while (c != EOF && !pcl_is_control_code(c)); + if (c != EOF) ungetc(c, in); + + return 0; +} + +/****************************************************************************** + + Function: pcl_scan + + This function scans a PCL file, separating it into printer commands and + unknown data, and calling the functions '(*interpreter)()' and '(*handler)()' + with these parts, respectively. + + 'in' must have been opened as a binary file and for reading. + 'interpreter' or 'handler' may be null in which case default routines are + used. + If a non-NULL function pointer is provided for 'interpreter' or 'handler', + the function will be passed the value of 'idata' or 'hdata', respectively. + + This function returns zero on success and a negative value otherwise. + If one of the interpreter or data handler functions returns a negative value, + processing will stop and the value will be returned as the return value of + pcl_scan(). + +******************************************************************************/ + +int pcl_scan(FILE *in, pcl_CommandInterpreter interpreter, void *idata, + pcl_UnknownDataHandler handler, void *hdata) +{ + int + c, + rc = 0; + + /* Open catalogue descriptor */ + catd = catopen("pcltools", 0); + if (catd == (nl_catd)(-1) && errno != ENOENT) + /* A system returning ENOENT if no catalogue is available is for example + Sun Solaris 2.5. */ + fprintf(stderr, + "?-W pclscan: Error trying to open message catalogue: %s.\n", + strerror(errno)); + + /* Loop over input */ + while (rc >= 0 && (c = fgetc(in)) != EOF) { + if (c == ESC) { + pcl_Command command; + + if ((c = fgetc(in)) == EOF) { + rc = -1; + message(1, "Premature EOF on input."); + break; + } + command.chars[0] = c; + if (48 <= c && c <= 126) { + /* Two-character escape sequence */ + command.kind = 2; + if (interpreter == NULL || + (rc = (*interpreter)(in, &command, idata)) > 0) + rc = default_interpreter(in, &command); + } + else { + int continued; + + /* Parameterized escape sequence or garbage. The character we've just + read is the "parameterized character" and it should be in the range + 33-47. */ + + /* Now the group character (should be in the range 96-126, but HP uses + sometimes at least '-', which has the value 45) */ + if ((c = fgetc(in)) == EOF) { + rc = -1; + message(1, "Premature EOF on input."); + break; + } + command.chars[1] = c; + + continued = 0; + do { + /* Now for the value */ + if ((c = fgetc(in)) == EOF) { + rc = -1; + message(1, "Premature EOF on input."); + break; + } + if (c == '+' || c == '-' || '0' <= c && c <= '9') { + if (c == '+' || c == '-') command.prefix = c; + else command.prefix = ' '; + ungetc(c, in); + if (fscanf(in, "%d", &command.i) != 1) { + rc = -1; + message(2, "Syntax error in value field."); + break; + } + + /* Decimal point? */ + if ((c = fgetc(in)) == EOF) { + rc = -1; + message(1, "Premature EOF on input."); + break; + } + command.scale = 0; + command.fraction = 0; + if (c == '.') { + command.scale = 1; + while ((c = fgetc(in)) != EOF && '0' <= c && c <= '9') { + command.fraction = command.fraction*10 + (c - '0'); + command.scale *= 10; + } + if (c == EOF) { + rc = -1; + message(1, "Premature EOF on input."); + break; + } + if (command.prefix == '-') command.fraction = -command.fraction; + } + } + else { + command.prefix = '\0'; /* no value given */ + command.i = 0; + } + + /* Final character */ + if (96 <= c && c <= 126) { + /* Parameter character */ + command.chars[2] = c - ('a' - 'A'); + command.kind = (continued? 6: 4); + continued = 1; + } + else { + /* Termination character (should be in the range 64-94) */ + command.chars[2] = c; + command.kind = (continued? 5: 3); + continued = 0; + } + + if (interpreter == NULL || + (rc = (*interpreter)(in, &command, idata)) > 0) + rc = default_interpreter(in, &command); + } while (rc == 0 && continued); + } + } + else if (pcl_is_control_code(c)) { + pcl_Command command; + + command.chars[0] = c; + command.kind = 1; + command.i = 1; /* number of occurrences */ + + while ((c = fgetc(in)) != EOF && c == command.chars[0]) command.i++; + if (c != EOF) ungetc(c, in); + + if (interpreter == NULL || + (rc = (*interpreter)(in, &command, idata)) > 0) + rc = default_interpreter(in, &command); + } + else { + ungetc(c, in); + if (handler == NULL || (rc = (*handler)(in, hdata)) > 0) + rc = default_handler(in); + } + } + + /* Close catalogue descriptor */ + if (catd != (nl_catd)-1) catclose(catd); + + return rc; +} |