/*  A new version of optcfg
 *  Copyright (C) 1994  K.Asayama TPM03937@pcvan.or.jp
 *
 *                                    Written by K.Asayama   May 30,1994
 *
 *  This program creates 'S' version's of *.CFG for dviprt.
 *
 *  Usage: noptcfg <input-file 1> [<input-file 2> ... <input-file n>]
 */
/* $Id: OPTCFG_.C 1.1 1994/08/30 02:27:02 kaz Exp kaz $ */

#ifndef UNIX
#include <io.h> /* access() */
#endif
#include "s_cfgbld.h"

#define OPTCFG_VERSION "3.1 beta-p1"
#define LAST_MODIFIED "94/08/31"

#define READBUF_SIZE 2048
#define CODEBUF_SIZE 10000
#define MAX_PATH 256

private uchar readbuf[READBUF_SIZE];
private uchar codebuf[CODEBUF_SIZE];

private int quiet_f = 0;

private char *version_message =
  "OPTCFG version " OPTCFG_VERSION " (" LAST_MODIFIED ")\n";
private char *revision_message = "$Revision: 1.1 $\n";
private char *copyright_message =
  "Copyright (C) 1994 Kazunori Asayama.\n"
  "    This program converts printer-definition-files for the TeX printer\n"
  "  driver, dviprt.\n"
  ;
char *usage_message =
  "Usage: optcfg [options] SOURCE-1 [SOURCE-2 ... SOURCE-n]\n"
  "Options:\n"
  "  -r  *.cfg -> *.src\n"
  "  -c  *.src -> *.c\n"
  "  -rc *.cfg -> *.c\n"
  "  -q  quiet mode.\n"
  "Examples:\n"
  "  optcfg escp_24.src         `escp_24.src' -> `escp_24.cfg'\n"
  "  optcfg -r escp_24.cfg      `escp_24.cfg' -> `escp_24.src'\n"
  "  optcfg -rc escp_24.cfg pc-pr_24.cfg\n"
  "                             `escp_24.cfg' -> `escp_24.c'\n"
  "                             `pc-pr_24.cfg'-> `pc-pr_24.c'\n"
  ;

/* forward declarations */
private int
  make_filename(P6(char *, char *,  char *,char *,char *,char *));
private int yes(P0());
     
int
main
  D2(int ,argc, char **, argv)
{
  int i;
  char ifname[MAX_PATH],ofname[MAX_PATH],dirname[MAX_PATH];
  char *sext,*dext;
  int rev = 0;
  int (*read_func)  (P6(char *,dviprt_cfg_t *,uchar *,int,uchar *,int));
  int (*write_func) (P5(char *,char *,dviprt_cfg_t *,uchar *,int));
  dviprt_cfg_t cfg;
  enum { O_DEFAULT,O_C, } ;
  int o_type = O_DEFAULT;
  dviprt_cfg_i info;
  
  info.line_no = -1;
  info.fname = "Argument";
  
  if (argc <= 1) {
    dviprt_setmessagestream(stdout);
    dviprt_printmessage(version_message,-1);
    dviprt_printmessage(copyright_message,-1);
    dviprt_printmessage(usage_message,-1);
    exit(0);
  }
  for (i=1;i<argc && *argv[i] == '-';i++) {
    char *parg = argv[i]+1;
    while (*parg) {
      switch (*parg) {
      case 'V':
	dviprt_setmessagestream(stdout);
	dviprt_printmessage(version_message,-1);
	dviprt_printmessage(revision_message,-1);
	exit(0);
      case 'r':
	rev = 1;
	break;
      case 'c':
	o_type = O_C;
	break;
      case 'q':
	quiet_f = 1;
	break;
      default:
	sprintf(dviprt_message_buffer,"Unknown flag `%s'.\n",argv[i]);
	dviprt_printcfgerror(&info,dviprt_message_buffer,-1);
      type_help:
	dviprt_printcfgerror(&info,"Type 'optcfg' for help.\n",-1);
	exit(1);
      }
      parg++;
    }
  }
  if (i >= argc) {
    dviprt_printcfgerror(&info,"No input.\n",-1);
    goto type_help;
  }
  
  if (rev) {
    sext = ".cfg";
    read_func = dviprt_readcfg;
  }
  else {
    sext = ".src";
    read_func = dviprt_readsrc;
  }
  
  if (o_type != O_DEFAULT || !rev)
    quiet_f = 1;
  
  switch (o_type) {
  case O_DEFAULT:
    if (rev) {
      dext = ".src";
      write_func = dviprt_writesrc;
    }
    else {
      dext = ".cfg";
      write_func = dviprt_writecfg;
    }
    break;
  case O_C:
    dext = ".c";
    write_func = dviprt_writec;
    break;
  default:
    dviprt_printerror("Sorry. Internal error.\n",-1);
    exit(1);
    ; /* internal error. */
  }
  
  for ( ;i<argc;i++) {
    int code;
    
    info.fname = argv[i];
    code = make_filename(ifname,ofname,dirname,argv[i],sext,dext);
    if (code<0) {
      dviprt_printcfgerror(&info,"File not found.\n",-1);
      exit(1);
    }
    
    
    info.fname = ifname;
    code = read_func(ifname,&cfg,codebuf,CODEBUF_SIZE,readbuf,READBUF_SIZE);
    if (code) {
      dviprt_printmessage("Stopped.\n",-1);
      exit(1);
    }
    
    info.fname = ofname;
    if (!quiet_f) {
      if (access(ofname,0) == 0) {
        dviprt_printcfgwarning(&info,
			       "This file already exists. Overwrite ? (y/n) ",
			       -1);
        if (!yes()) {
          dviprt_printmessage("O.K. Stopped.\n",-1);
          exit(1);
        }
      }
    }
    
    strcpy(readbuf,"This file was generated from ");
    strcat(readbuf,ifname);
    strcat(readbuf," by optcfg automatically.");
    code = strlen(readbuf) + 1;
    code = write_func(ofname,readbuf,&cfg,readbuf+code,READBUF_SIZE-code);
    if (code<0) {
      dviprt_printmessage("Stopped.\n",-1);
      exit(1);
    }
    else {
      sprintf(dviprt_message_buffer,"Wrote on '%s'.\n",ofname);
      dviprt_printmessage(dviprt_message_buffer,-1);
    }
  }
  return 0;
}

/*--- internal routines ---*/
private int
make_filename
  D6(char *, fname, char *, ofname,  char *, dirname, char *, base,
     char *, srcext, char *, dstext)
{
  char *pext;
  
  strcpy(fname,base);
#ifdef __MSDOS__
  pext = fname;
  while (*pext) {
    if (*pext == '/') *pext ='\\';
    pext++;
  }
# define DIRSEP '\\'
#else
# define DIRSEP '/'
#endif
  
  if (access(fname,0)) {
    strcat(fname,srcext);
    if (access(fname,0))
      return -1;
  }
  strcpy(ofname,fname);
  pext = strrchr(ofname,DIRSEP);
  if (pext == NULL) {
    pext = ofname;
#ifdef __MSDOS__
    if (strlen(ofname) >= 2 && ofname[1] == ':') {
      strncpy(dirname,ofname,2);
    }
    else
#endif
      {
	dirname[0] = 0;
      }
  }
  else {
    strncpy(dirname,ofname,(int)(pext-ofname));
    dirname[pext-ofname] = 0;
  }
  pext = strchr(pext,'.');
  if (pext == NULL) {
    strcat(ofname,dstext);
  }
  else {
    strcpy(pext,dstext);
  }
#undef DIRSEP
  
  return 0;
}

private int
yes
  D0()
{
  int c;
  for ( ; ; ) {
    c = fgetc(stdin);
    if (c == 'y' || c == 'Y') { c = 1; break; }
    else if (c == 'n' || c == 'N') { c = 0; break; }
  }
  return c;
}


/************************** Library routines. *************************/


/***** From rcfg.c *****/
/* $Id: RCFG.C 1.1 1994/08/30 02:27:02 kaz Exp kaz $ */


/*--- forward declarations ---*/
private int dviprt_read_S_cfg(P2(dviprt_cfg_t *,dviprt_cfg_i *));
private int dviprt_read_QR_cfg(P2(dviprt_cfg_t *,dviprt_cfg_i *));
     
/*--- library functions ---*/
int 
dviprt_readcfg
  D6(char *,ifname,dviprt_cfg_t *,pcfg,
     uchar *,pcodebuf,int,codebuf_s,
     uchar *,pworkbuf,int,workbuf_s)
{
  int code;
  int ver;
  dviprt_cfg_i info;
  
  info.fname = ifname;
  info.line_no = -1;
  if (ifname) {
    info.file = fopen(ifname,gp_fmode_rb);
    if (info.file == NULL) {
      dviprt_printcfgerror(&info,"Cannot open.\n",-1);
      return CFG_ERROR_FILE_OPEN;
    }
  }
  else {
    info.file = stdin;
  }
  
  fseek(info.file,16,0);
  ver = fgetc(info.file);
  fseek(info.file,0,0);
  info.codebuf = pcodebuf;
  info.readbuf = pworkbuf;
  info.codebuf_size = codebuf_s;
  info.readbuf_size = workbuf_s;
  code = (ver == 'S') ? dviprt_read_S_cfg(pcfg,&info) 
    : dviprt_read_QR_cfg(pcfg,&info);
  
  if (ifname) fclose(info.file);
  return code;
}

/*--- internal routines ---*/
private int 
dviprt_read_S_cfg
  D2(dviprt_cfg_t *,pcfg, dviprt_cfg_i *,pinfo)
{
  FILE *ifp;
  long intoff,stroff,codeoff;
  int i,count;
  uchar *pbuf,*rbuf;
  int code;
  char *ptype;
  int n;
  
  if ((code = dviprt_setcfgbuffer_(pinfo,100,0)) < 0) return code;
  dviprt_initcfg_(pcfg,pinfo);
  
  ifp = pinfo->file;
  rbuf = pinfo->readbuf;
  
  if (fread(rbuf,20,1,ifp) < 1) {
    dviprt_printcfgerror(pinfo,"Read error.\n",-1);
  }
  if (rbuf[17] != 0xff || rbuf[18] != 0xff) {
  not_cfg:
    dviprt_printcfgerror(pinfo,"This file does not seem *.CFG.\n",-1);
    return CFG_ERROR_OTHER;
  }
  if (memcmp(rbuf,CFG_MAGIC_NUMBER,2))
    goto not_cfg;
  pcfg->version = rbuf[2] | ((uint)rbuf[3] << 8);
  if (pcfg->version > CFG_VERSION) {
    sprintf(dviprt_message_buffer,
	    "This *.CFG file is too new version(ver.%u).\n",pcfg->version);
    dviprt_printcfgerror(pinfo,dviprt_message_buffer,-1);
    return CFG_ERROR_OTHER;
  }
  
#define bytes2long(p) ((p)[0] | ((long)(p)[1]<<8) | \
		       ((long)(p)[2]<<16) | ((long)(p)[3]<<24))
  intoff = bytes2long(rbuf+4);
  stroff = bytes2long(rbuf+8);
  codeoff = bytes2long(rbuf+12);
#undef bytes2long
  
  fseek(ifp,intoff,0);
  count = fgetc(ifp);
  fread(rbuf,count*3,1,ifp);
  
  pbuf = rbuf;
  for (i=0;i<count;i++) {
    n = pbuf[0];
    if (n >= CFG_INTEGER_TYPE_COUNT) {
      ptype = "integer";
    unknown_no:
      sprintf(dviprt_message_buffer,
	      "Unknown %s type value No.%d is found.\n",ptype,n);
      dviprt_printcfgerror(pinfo,dviprt_message_buffer,-1);
      return CFG_ERROR_OTHER;
    }
    pcfg->integer[n] = pbuf[1] | ((uint)pbuf[2]<<8);
    pbuf += 3;
  }
  
  fseek(ifp,stroff,0);
  count = fgetc(ifp);
  pbuf = NULL;
  for (i=0;i<count;i++) {
    int l;
    fread(rbuf,3,1,ifp);
    n = rbuf[0];
    l = rbuf[1] | ((uint)rbuf[2]<<8);
    if (n >= CFG_STRINGS_TYPE_COUNT) {
      ptype = "strings";
      goto unknown_no;
    }
    if (pinfo->codebuf == NULL) {
      pcfg->strings[n] = (uchar *)malloc(l+1);
      if (pcfg->strings[n] == NULL) {
      no_memory:
        dviprt_printcfgerror(pinfo,"Memory exhausted.\n",-1);
        return CFG_ERROR_MEMORY;
      }
    }
    else {
      pcfg->strings[n] = pinfo->pcodebuf;
      pinfo->pcodebuf += (l+1);
    }
    fread(pcfg->strings[n],l,1,ifp);
    *(pcfg->strings[n]+l) = 0;
  }
  
  fseek(ifp,codeoff,0);
  count = fgetc(ifp);
  for (i=0;i<count;i++) {
    int l;
    fread(rbuf,3,1,ifp);
    n = rbuf[0];
    l = rbuf[1] | ((uint)rbuf[2]<<8);
    
    if (n >= CFG_PRTCODE_TYPE_COUNT) {
      ptype = "printer code";
      goto unknown_no;
    }
    if (pinfo->codebuf == NULL) {
      pcfg->prtcode[n] = (uchar *)malloc(l+1);
      if (pcfg->prtcode[n] == NULL)
        goto no_memory;
    }
    else {
      pcfg->prtcode[n] = pinfo->pcodebuf;
      pinfo->pcodebuf += (l+1);
    }
    fread(pcfg->prtcode[n],l,1,ifp);
    *(pcfg->prtcode[n]+l) = 0;
    pcfg->prtcode_size[n] = l;
  }
  dviprt_resetcfgbuffer_(pinfo);
  return 0;
}

private int 
dviprt_read_QR_cfg
  D2(dviprt_cfg_t *,pcfg,dviprt_cfg_i *,pinfo)
{
#define	TYPE_BIT		0xc0
  
#define	NO_NUM			0
#define	BINARY_LTOH		1
#define	BINARY_HTOL		2
#define	DECIMAL_3		3
#define	DECIMAL_4		4
#define	DECIMAL_5		5
#define	DECIMAL_V		6
  
#define	TOTAL_BYTE		0x80
#define	ISO_NUMBER		0x40
#define	DIVIDEBY_2		0x10
#define	DIVIDE_ALL		0x30
#define	MULT_CONST		0x08
  enum {
    BIT_IMAGE_MODE,
    NORML_MODE,
    SEND_BIT_IMAGE,
    SKIP_SPACES,
    LINE_FEED,
    FORM_FEED,
    AFTER_BIT_IMAGE,
    BIT_ROW_HEADER,
  };
  uchar *cfg_buf,*ptr;
  int ch, type, f_cont, f_type, pos, i, j, k, lens;
  int f_r_format;
  long offset;
  int old2new[] = {
    CFG_BIT_IMAGE_MODE,
    CFG_NORMAL_MODE,
    CFG_SEND_BIT_IMAGE,
    CFG_SKIP_SPACES,
    CFG_LINE_FEED,
    CFG_FORM_FEED,
    CFG_AFTER_BIT_IMAGE,
    CFG_BIT_ROW_HEADER,
  };
  
  ch =dviprt_setcfgbuffer_(pinfo,300,TEMP_CODEBUF_SIZE);
  if (ch < 0) return CFG_ERROR_MEMORY;
  dviprt_initcfg_(pcfg,pinfo);
  cfg_buf = pinfo->readbuf;
  if (fread(cfg_buf,30,1,pinfo->file) < 1) {
    dviprt_printcfgerror(pinfo,"Read error.\n",-1);
  }
  if (cfg_buf[16] == 'P') {
    dviprt_printcfgerror(pinfo,"This is made by old version.\n",-1);
    return CFG_ERROR_OTHER;
  }
  else if (cfg_buf[16] == 'Q')
    f_r_format = 0;
  else if (cfg_buf[16] == 'R')
    f_r_format = 1;
  else
    f_r_format = -1;
  if (f_r_format == -1 || cfg_buf[18] != 0xff) {
    dviprt_printcfgerror(pinfo,"This is not the *.CFG file for dviprt.\n",-1);
    return CFG_ERROR_OTHER;
  }
  cfg_buf[16] = '\0';
  pcfg->version = 0;
  if (pinfo->temp_codebuf_f) {
    pcfg->strings[CFG_NAME] = malloc(strlen(cfg_buf)+1);
    if (pcfg->strings[CFG_NAME] == NULL) {
    no_memory:
      dviprt_printcfgerror(pinfo,"Memory exhausted.\n",-1);
      return CFG_ERROR_MEMORY;
    }
  }
  else {
    pcfg->strings[CFG_NAME] = pinfo->pcodebuf;
    pinfo->pcodebuf += strlen(cfg_buf);
    pinfo->pcodebuf++;
  }
  strcpy(pcfg->strings[CFG_NAME],cfg_buf);
  
  pcfg->integer[CFG_UPPER_POS] =
    (cfg_buf[17] & (CFG_LEFT_IS_LOW|CFG_NON_MOVING));
  pcfg->integer[CFG_ENCODE] =
    (cfg_buf[17] & 0x10) ? CFG_ENCODE_HEX : CFG_ENCODE_NULL;
  pcfg->integer[CFG_PINS] = ((uint) (cfg_buf[17]) & 0x0f);
  
  ptr = cfg_buf+23;
  pcfg->integer[CFG_MINIMAL_UNIT] = (uint)ptr[0] | ((uint)ptr[1]<<8);
  pcfg->integer[CFG_MAXIMAL_UNIT] = (uint)ptr[2] | ((uint)ptr[3]<<8);
  pcfg->integer[CFG_DPI] =
    f_r_format ? ((uint)ptr[4] | ((uint)ptr[5]<<8)) : 180;
  if (cfg_buf[20])
    pcfg->integer[CFG_CONSTANT] = cfg_buf[20];
  offset = cfg_buf[19];
  fseek(pinfo->file,offset,0);
  
  for (i = 0; i <= BIT_ROW_HEADER; i++) {
    uchar *pstart,*plength;
    uchar prev = 1;
    if (pinfo->temp_codebuf_f) {
      pinfo->pcodebuf = pinfo->codebuf;
    }
    pstart = pinfo->pcodebuf;
    do {
      lens = fgetc(pinfo->file);
      if (lens == EOF) break;
      fread(cfg_buf,lens+3,1,pinfo->file);
      ptr = cfg_buf;
      f_cont = *ptr++;
      pos = *ptr++;
      f_type = *ptr++;
      type = f_type & 0x7;
      
      for (j = 0; j < lens; j++) {
	ch = *ptr++;
	if (pos == j && type != NO_NUM) {
	  uchar *pfmt = pinfo->pcodebuf++;
	  plength = pinfo->pcodebuf++;
	  *pinfo->pcodebuf++ = CFG_VAL_DEFAULT;
	  *plength = 1;
	  j++;
	  ptr++;
	  switch (type) {
	  case (BINARY_LTOH):
	    *pfmt = CFG_FMT_BIT | CFG_FMT_BIN_LTOH | 2;
	    break;
	  case (BINARY_HTOL):
	    *pfmt = CFG_FMT_BIT | CFG_FMT_BIN_HTOL | 2;
	    break;
	  case (DECIMAL_3):
	    *pfmt = CFG_FMT_BIT | CFG_FMT_DECIMAL | 3;
	    j++;
	    ptr++;
	    break;
	  case (DECIMAL_4):
	    *pfmt = CFG_FMT_BIT | CFG_FMT_DECIMAL | 4;
	    j += 2;
	    ptr += 2;
	    break;
	  case (DECIMAL_5):
	    *pfmt = CFG_FMT_BIT | CFG_FMT_DECIMAL | 5;
	    j += 3;
	    ptr += 3;
	    break;
	  case (DECIMAL_V):
	    *pfmt = CFG_FMT_BIT | CFG_FMT_DECIMAL;
	    j++;
	    ptr++;
	    break;
	  default:
	    sprintf(dviprt_message_buffer,"Unknown format %02X",type);
	    dviprt_printcfgerror(pinfo,dviprt_message_buffer,-1);
	    goto ex_func;
	  }
	  if (f_type & TOTAL_BYTE) {
	    *pinfo->pcodebuf++ = CFG_VAL_PINS_BYTE;
	    *pinfo->pcodebuf++ = CFG_OP_MUL;
	    (*plength) += 2;
	  }
	  if ((k = (f_type & DIVIDE_ALL)) != 0) {
	    *pinfo->pcodebuf = 0;
	    for (; k > 0; k -= DIVIDEBY_2) {
	      (*pinfo->pcodebuf)++;
	    }
	    pinfo->pcodebuf++;
	    *pinfo->pcodebuf++ = CFG_OP_SHR;
	    (*plength) += 2;
	  }
	  if (f_type & ISO_NUMBER) {
	    *pfmt |= CFG_FMT_ISO_BIT;
	  }
	  if (f_type & MULT_CONST) {
	    *pinfo->pcodebuf++ = CFG_VAL_CONSTANT;
	    *pinfo->pcodebuf++ = CFG_OP_MUL;
	    (*plength) += 2;
	  }
	  prev = 1;
	}
	else {
	  if (prev == 1 || *plength >= 127) {
	    plength = pinfo->pcodebuf++;
	    *plength = 0;
	  }
	  (*plength)++;
	  *pinfo->pcodebuf++ = ch;
	  prev = 0;
	}
      }
    } while (f_cont & 0x80);
    *pinfo->pcodebuf++ = 0;
    { int n = old2new[i];
      uint l = pinfo->pcodebuf-pstart;
      pcfg->prtcode_size[n] = l - 1;
      if (pinfo->temp_codebuf_f) { /* allocate buffer */
     	pcfg->prtcode[n] = (uchar *)malloc(l);
        if (pcfg->prtcode[n] == NULL)
          goto no_memory;
	memcpy(pcfg->prtcode[n],pstart,l);
      }
      else {
	pcfg->prtcode[n] = pstart;
      }
    }
  }
 ex_func:
  dviprt_resetcfgbuffer_(pinfo);
  return 0;
}
/***** End of rcfg.c *****/


/***** From rsrc.c *****/
/* $Id: RSRC.C 1.1 1994/08/30 02:27:02 kaz Exp kaz $ */


typedef struct {
  char *name;
  signed char type;
  uchar no;
  uchar spec_f;
  uchar req_f;
  char *info;
} dviprt_cfg_item_t;

typedef struct {
  long min;
  long max;
} dviprt_cfg_limit_t;

/*--- forward declarations ---*/
private int dviprt_set_select
  (P4(dviprt_cfg_item_t *,uchar **,dviprt_cfg_t *,dviprt_cfg_i *));
private int dviprt_set_integer
  (P4(dviprt_cfg_item_t *, uchar *, dviprt_cfg_t *,dviprt_cfg_i *));
private int dviprt_set_strings
  (P4(dviprt_cfg_item_t *,uchar *,dviprt_cfg_t *,dviprt_cfg_i *));
private int dviprt_set_rpexpr
  (P6(dviprt_cfg_item_t *,uchar *,int , dviprt_cfg_t *,dviprt_cfg_i *,int));
private int dviprt_set_code
  (P4(dviprt_cfg_item_t *,uchar *,dviprt_cfg_t *,dviprt_cfg_i *));

private long dviprt_oct2long(P3(uchar *,uchar *,uchar **));
private long dviprt_dec2long(P3(uchar *,uchar *,uchar **));
private long dviprt_hex2long(P3(uchar *,uchar *,uchar **));
     
private int dviprt_printtokenerror(P4(dviprt_cfg_i *,char *,int ,int));
     
/*--- macros ---*/
#define strlcmp(tmplt,str,len) \
  (!(strncmp(tmplt,str,(int)(len)) == 0 && (int)(len) == strlen(tmplt)))
#define set_version(pcfg,v) ((pcfg)->version = MAX(v,(pcfg)->version))
     
enum {
  ERROR_UNKNOWN_VALUE,ERROR_UNKNOWN_FORMAT,ERROR_UNKNOWN_ESCSEQ,
  ERROR_OUTOFRANGE,
  ERROR_INVALID_VALUE,
  ERROR_COMPLICATED_EXPR,
  ERROR_INCOMPLETE,
};

/*--- library functions ---*/
int 
dviprt_readsrc
  D6(char *, fname, dviprt_cfg_t *, pcfg,
     uchar *,pcodebuf,int ,codebuf_s,
     uchar *,pworkbuf,int ,workbuf_s)
{
  dviprt_cfg_i info;
  int code;
  FILE *ifp;
  dviprt_cfg_item_t *pitem;
  int enc = CFG_ENCODE_NULL;
  enum { T_INTEGER,T_STRINGS,T_CODE,T_SELECT,T_UPPERPOS};
  static dviprt_cfg_limit_t pins_limit = { 8, 128 };
  static dviprt_cfg_limit_t positive_limit = { 1, 0x7fff };
  static dviprt_cfg_limit_t nonnegative_limit = { 0, 0x7fff};
  static dviprt_cfg_item_t dviprt_items[] = {
    {NULL,T_STRINGS,CFG_NAME,0,1,NULL},
    {NULL,T_INTEGER,CFG_PINS,0,1,(char*)&pins_limit},
    {NULL,T_INTEGER,CFG_MINIMAL_UNIT,0,0,(char*)&positive_limit},
    {NULL,T_INTEGER,CFG_MAXIMAL_UNIT,0,0,(char*)&positive_limit},
    {NULL,T_INTEGER,CFG_DPI,0,0,(char*)&positive_limit},
    {NULL,T_INTEGER,CFG_CONSTANT,0,0,(char*)&nonnegative_limit},
    {NULL,T_INTEGER,CFG_Y_DPI,0,0,(char*)&positive_limit},
    {NULL,T_CODE,CFG_BIT_IMAGE_MODE,0,1,NULL},
    {NULL,T_CODE,CFG_SEND_BIT_IMAGE,0,1,NULL},
    {NULL,T_CODE,CFG_BIT_ROW_HEADER,0,0,NULL},
    {NULL,T_CODE,CFG_AFTER_BIT_IMAGE,0,0,NULL},
    {NULL,T_CODE,CFG_LINE_FEED,0,0,NULL},
    {NULL,T_CODE,CFG_FORM_FEED,0,0,NULL},
    {NULL,T_CODE,CFG_NORMAL_MODE,0,1,NULL},
    {NULL,T_CODE,CFG_SKIP_SPACES,0,1,NULL},
    {NULL,T_UPPERPOS,CFG_UPPER_POS,0,1,NULL},
    {NULL,T_SELECT,CFG_ENCODE,0,0,(char*)dviprt_encodename},
    {NULL,-1},
  };
  static dviprt_cfg_item_t encode_info = {
    "encode",T_STRINGS,CFG_ENCODE_INFO,0,0,NULL
    };
  int prtcode_output_bytes[CFG_PRTCODE_TYPE_COUNT];
  
  info.line_no = -1;
  info.fname = fname;
  if (fname) {
    info.file = fopen(fname,"r");
    if (info.file == NULL) {
      dviprt_printcfgerror(&info,"Cannot open.\n",-1);
      return CFG_ERROR_FILE_OPEN;
    }
  }
  else {
    ifp = stdin;
  }
  ifp = info.file;
  
  info.codebuf = pcodebuf;
  info.readbuf = pworkbuf;
  info.codebuf_size = codebuf_s;
  info.readbuf_size = workbuf_s;
  /* allocate buffer */
  if (dviprt_setcfgbuffer_(&info,TEMP_READBUF_SIZE,TEMP_CODEBUF_SIZE) < 0) {
    fclose(info.file);
    return CFG_ERROR_MEMORY;
  }
  
  /* initialize */
  dviprt_initcfg_(pcfg,&info);
  for (pitem = dviprt_items;pitem->type>=0;pitem++) {
    if (pitem->name == NULL) {
      switch (pitem->type) {
      case T_INTEGER:
      case T_SELECT:
      case T_UPPERPOS:
        pitem->name = dviprt_integername[pitem->no];
        break;
      case T_STRINGS:
        pitem->name = dviprt_stringsname[pitem->no];
        break;
      case T_CODE:
        pitem->name = dviprt_prtcodename[pitem->no];
        break;
      }
    }
    pitem->spec_f = 0;
  }
  encode_info.spec_f = 0;
  { int i;
    for (i=0;i<CFG_PRTCODE_TYPE_COUNT;i++)
      prtcode_output_bytes[i] = 0;
  }
  
  pcfg->version = 1;
  for ( ; ; ) {
    uchar *pbuf = info.readbuf;
    uchar *pchar;
    
    if (fgets(info.readbuf,info.readbuf_size,ifp) == NULL) break;
    info.line_no++;
    {
      int len = strlen(pbuf);
      if ((pbuf[0] < 'a' || pbuf[0] > 'z') && pbuf[0] != '_') {
        while (pbuf[len-1] != '\n') {
          if (fgets(info.readbuf,info.readbuf_size,ifp) == NULL)
            goto end_scan;
          len = strlen(pbuf);
        }
        continue;
      }
      if ( len > 0 && pbuf[len-1] == '\n')
        pbuf[len-1] = 0;
    }
    while (*pbuf && *pbuf != ':') pbuf++;
    if (*pbuf != ':') {
      dviprt_printcfgerror(&info,"Character ':' is expected.\n",-1);
      code = CFG_ERROR_SYNTAX;
      goto end_process;
    }
    pchar = pbuf-1;
    while (pchar >= info.readbuf && isspace(*pchar)) pchar--;
    *++pchar = 0;
    pbuf++;
    for (pitem = dviprt_items;pitem->name;pitem++) {
      if (strcmp(pitem->name,info.readbuf) == 0) break;
    }
    if (pitem->name == NULL) {
      dviprt_printcfgerror(&info,"Unknown item `",-1);
      dviprt_printmessage(info.readbuf,-1);
      dviprt_printmessage("'.\n",-1);
      code = CFG_ERROR_RANGE;
      goto end_process;
    }
  parse_more:
    while (*pbuf && isspace(*pbuf)) pbuf++;
    if (pitem->spec_f) {
      dviprt_printcfgerror(&info,NULL,0);
      sprintf(dviprt_message_buffer,
	      "Item `%s' is specified twice.\n",pitem->name);
      dviprt_printmessage(dviprt_message_buffer,-1);
      code = CFG_ERROR_SYNTAX;
      goto end_process;
    }
    switch (pitem->type) {
    case T_INTEGER:
      if ((code = dviprt_set_integer(pitem,pbuf,pcfg,&info)) < 0)
        goto end_process;
      if (pitem->no == CFG_PINS) {
        if (pcfg->integer[CFG_PINS] % 8) {
          dviprt_printcfgerror(&info,"Value must be a multiple of 8.\n",-1);
          code = CFG_ERROR_RANGE;
          goto end_process;
        }
        pcfg->integer[CFG_PINS] /= 8;
      }
      break;
    case T_STRINGS:
      if (info.temp_codebuf_f)
        info.pcodebuf = info.codebuf;
      if ((code = dviprt_set_strings(pitem,pbuf,pcfg,&info)) < 0)
    	goto end_process;
      if (info.temp_codebuf_f) {
        pcfg->strings[pitem->no] =
          (uchar*)malloc(strlen(pcfg->strings[pitem->no])+1);
        if (pcfg->strings[pitem->no] == NULL) {
          goto no_more_memory;
        }
        strcpy(pcfg->strings[pitem->no],info.codebuf);
      }
      break;
    case T_CODE:
      if (info.temp_codebuf_f)
        info.pcodebuf = info.codebuf;
      if ((code = dviprt_set_code(pitem,pbuf,pcfg,&info)) < 0)
        goto end_process;
      prtcode_output_bytes[pitem->no] = code;
      if (info.temp_codebuf_f) {
        pcfg->prtcode[pitem->no] =
          (uchar*)malloc(pcfg->prtcode_size[pitem->no]+1);
        if (pcfg->prtcode[pitem->no] == NULL) {
        no_more_memory:
          dviprt_printcfgerror(&info,"Memory exhausted.\n",-1);
          code = CFG_ERROR_MEMORY;
          goto end_process;
        }
        memcpy(pcfg->prtcode[pitem->no],info.codebuf,
	       pcfg->prtcode_size[pitem->no]+1);
      }
      break;
    case T_SELECT:
      if ((code = dviprt_set_select(pitem,&pbuf,pcfg,&info)) < 0)
        goto end_process;
      if (pitem->no == CFG_ENCODE) {
        pitem = &encode_info;
        goto parse_more;
      }
      break;
    case T_UPPERPOS:
      { uchar *ptmp;
        uchar upos=0;
        uchar opt = 0;
        if (*pbuf == 0) {
          dviprt_printcfgerror(&info,"No value.\n",-1);
          code = CFG_ERROR_SYNTAX;
          goto end_process;
        }
        while (*pbuf) {
          ptmp = pbuf;
          while (*ptmp && !isspace(*ptmp)) ptmp++;
          if (!strlcmp("HIGH_BIT",pbuf,ptmp-pbuf))
            upos = CFG_TOP_IS_HIGH;
          else if (!strlcmp("LOW_BIT",pbuf,ptmp-pbuf))
            upos = CFG_TOP_IS_LOW;
          else if (!strlcmp("LEFT_IS_HIGH",pbuf,ptmp-pbuf))
            upos = CFG_LEFT_IS_HIGH;
          else if (!strlcmp("LEFT_IS_LOW",pbuf,ptmp-pbuf))
            upos = CFG_LEFT_IS_LOW;
          else if (!strlcmp("NON_MOVING",pbuf,ptmp-pbuf))
            opt = CFG_NON_MOVING;
          else if (!strlcmp("HEX_MODE",pbuf,ptmp-pbuf))
            enc = CFG_ENCODE_HEX;
          else {
            dviprt_printtokenerror(&info,pbuf,(int)(ptmp-pbuf),ERROR_UNKNOWN_VALUE);
            code = CFG_ERROR_RANGE;
            goto end_process;
          }
          pbuf = ptmp;
          while (*pbuf && isspace(*pbuf)) pbuf++;
        }
        pcfg->integer[CFG_UPPER_POS] = upos | opt;
      }
      break;
    }
    pitem->spec_f = 1;
  }
 end_scan:
  
  info.line_no = -1;
  code = 0;
  for (pitem = dviprt_items;pitem->name;pitem++) {
    if (!pitem->spec_f && pitem->req_f) {
      sprintf(dviprt_message_buffer,"%s not found.\n",pitem->name);
      dviprt_printcfgerror(&info,dviprt_message_buffer,-1);
      code++;
    }
  }
  if (code) { code = CFG_ERROR_RANGE; goto end_process; }
  
  if (pcfg->prtcode[CFG_LINE_FEED] == NULL) {
    pcfg->prtcode[CFG_LINE_FEED] = info.pcodebuf;
    memcpy(info.pcodebuf,"\002\x0d\x0a\000",4);
    info.pcodebuf += 4;
    pcfg->prtcode_size[CFG_LINE_FEED] = 3;
  }
  if (pcfg->prtcode[CFG_FORM_FEED] == NULL) {
    pcfg->prtcode[CFG_FORM_FEED] = info.pcodebuf;
    memcpy(info.pcodebuf,"\002\x0d\x0c\000",4);
    info.pcodebuf += 4;
    pcfg->prtcode_size[CFG_FORM_FEED] = 3;
  }
  if (pcfg->integer[CFG_DPI] < 0 && pcfg->integer[CFG_Y_DPI] < 0) {
    pcfg->integer[CFG_DPI] = 180;
  }
  else if (pcfg->integer[CFG_DPI] < 0 || pcfg->integer[CFG_Y_DPI] < 0) {
    if (pcfg->integer[CFG_DPI] < 0)
      pcfg->integer[CFG_DPI] = pcfg->integer[CFG_Y_DPI];
    pcfg->integer[CFG_Y_DPI] = -1;
  }
  else if (pcfg->integer[CFG_DPI] == pcfg->integer[CFG_Y_DPI]) {
    pcfg->integer[CFG_Y_DPI] = -1;
  }
  else if (pcfg->integer[CFG_Y_DPI] >= 0) { /* has y_dpi. */
    set_version(pcfg,2);
  }
  if (pcfg->integer[CFG_ENCODE] < 0) {
    pcfg->integer[CFG_ENCODE] = enc;
  }
  if (pcfg->integer[CFG_MAXIMAL_UNIT] < 0) {
    pcfg->integer[CFG_MAXIMAL_UNIT] = 0x7fff;
  }
  if (pcfg->integer[CFG_MINIMAL_UNIT] < 0) {
    uint v;
    v = (MAX(prtcode_output_bytes[CFG_SEND_BIT_IMAGE],0) +
         MAX(prtcode_output_bytes[CFG_AFTER_BIT_IMAGE],0) +
         MAX(prtcode_output_bytes[CFG_SKIP_SPACES],0))
      / (pcfg->integer[CFG_PINS]*8) +
	MAX(prtcode_output_bytes[CFG_BIT_ROW_HEADER],0);
    if (v == 0) v = 1;
    pcfg->integer[CFG_MINIMAL_UNIT] = v;
  }
  
  for (pitem = dviprt_items;pitem->type>=0;pitem++) {
    if (pitem->spec_f == 0) {
      sprintf(dviprt_message_buffer,": %s:",pitem->name);
      switch (pitem->type) {
      case T_INTEGER:
        if (pcfg->integer[pitem->no] >= 0) {
          uint v = pcfg->integer[pitem->no];
          dviprt_printmessage(fname,-1);
          dviprt_printmessage(dviprt_message_buffer,-1);
          sprintf(dviprt_message_buffer," %d\n",v);
          dviprt_printmessage(dviprt_message_buffer,-1);
        }
        break;
      default: break; /* do nothing */
      }
    }
  }
  
 end_process:
  if (fname) fclose(ifp);
  dviprt_resetcfgbuffer_(&info);
  
  return code;
}

/*--- internal routines ---*/
private int 
dviprt_set_integer
  D4(dviprt_cfg_item_t *, pitem,uchar *, buf,
     dviprt_cfg_t *, pcfg,dviprt_cfg_i *, pinfo)
{
  uchar *pbuf = buf;
  long v = 0;
  long max = -1 ,min = -1;
  
  if (pitem->info != NULL) {
    dviprt_cfg_limit_t *plimit = (dviprt_cfg_limit_t *)pitem->info;
    min = plimit->min;
    max = plimit->max;
  }
  if (min < 0) min = 0;
  if (max < 0) max = 0xffff;
  if (*pbuf == 0) {
    dviprt_printcfgerror(pinfo,"No value.\n",-1);
    return CFG_ERROR_SYNTAX;
  }
  while (*pbuf) {
    if (!isdigit(*pbuf)) {
      if (isspace(*pbuf)) break;
      else goto invalid_val;
    }
    v = v*10 + *pbuf - '0';
    if (v > max) {
    out_of_range:
      dviprt_printtokenerror(pinfo,buf,strlen(buf),ERROR_OUTOFRANGE);
      dviprt_printcfgerror(pinfo,"",-1);
      sprintf(dviprt_message_buffer,
	      "(%u <= value <= %u).\n",(uint)min,(uint)max);
      dviprt_printmessage(dviprt_message_buffer,-1);
      return CFG_ERROR_RANGE;
    }
    pbuf++;
  }
  if (v < min) goto out_of_range;
  
  while (*pbuf) {
    if (!isspace(*pbuf)) {
    invalid_val:
      dviprt_printtokenerror(pinfo,buf,strlen(buf),ERROR_INVALID_VALUE);
      return CFG_ERROR_RANGE;
    }
    pbuf++;
  }
  pcfg->integer[pitem->no] = v;
  
  return 0;
}

private int 
dviprt_set_strings
  D4(dviprt_cfg_item_t *, pitem,uchar *, buf,
     dviprt_cfg_t *, pcfg, dviprt_cfg_i *, pinfo)
{
  uchar *pend;
  long len;
  pend = buf+strlen(buf)-1;
  while (pend >= buf && isspace(*pend)) pend--;
  pend++;
  len = pend - buf;
  if (len > 0x7fffL) {
    dviprt_printcfgerror(pinfo,"Too long strings.\n",-1);
    return CFG_ERROR_RANGE;
  }
  
  pcfg->strings[pitem->no] = pinfo->pcodebuf;
  strncpy(pinfo->pcodebuf,buf,(int)len);
  pinfo->pcodebuf[len] = 0;
  pinfo->pcodebuf += len;
  pinfo->pcodebuf++;
  return 0;
}

private int
dviprt_set_select
  D4(dviprt_cfg_item_t *, pitem, uchar **, buf,
     dviprt_cfg_t *, pcfg, dviprt_cfg_i *, pinfo)
{
  int i;
  uchar *ptmp = *buf;
  uchar *pstart = *buf;
  uchar **opt;
  if (*pstart == 0) {
    dviprt_printcfgerror(pinfo,"No value.\n",-1);
    return CFG_ERROR_SYNTAX;
  }
  while (*ptmp && !isspace(*ptmp)) ptmp++;
  
  for (i=0,opt=(uchar**)pitem->info;*opt;i++,opt++) {
    if (!strlcmp(*opt,pstart,ptmp-pstart)) {
      pcfg->integer[pitem->no] = i;
      *buf = ptmp;
      return 0;
    }
  }
  dviprt_printtokenerror(pinfo,pstart,(int)(ptmp-pstart),ERROR_UNKNOWN_VALUE);
  return CFG_ERROR_RANGE;
}

#define CFG_TOKEN_ERROR     -1
#define CFG_TOKEN_LIMIT_BIT 0x100
#define CFG_TOKEN_FMT       0x200

private int 
dviprt_get_codetype_token
  D5(dviprt_cfg_i *, pinfo, uchar *, pstart, uchar *, pend,
     uchar *, stopescseqchars,uchar *, limitchars)
{
  while (pstart < pend && isspace(*pstart)) pstart++;
  if (pstart >= pend) {
    pinfo->token = pinfo->endtoken = pstart;
    return CFG_TOKEN_LIMIT_BIT;
  }
  else if (strchr(limitchars,*pstart)) {
    pinfo->token = pstart;
    pinfo->endtoken = pstart+1;
    return CFG_TOKEN_LIMIT_BIT | *pstart;
  }
  else if (*pstart == '\\') {
    int c;
    long v;
    uchar *pexpr,*pnext;
    
    pexpr = pinfo->token = pstart++;
    while (pstart < pend && !isspace(*pstart) &&
           *pstart != '\\' && !strchr(stopescseqchars,*pstart)) {
      pstart++;
    }
    pinfo->endtoken = pstart;
    if (pinfo->token + 1 == pinfo->endtoken) { /* '\\' only */
      return '\\';
    }
    pexpr++;
    if (pinfo->endtoken - pexpr == 1) {
      if (isdigit(*pexpr)) goto parse_decimal_numb;
      switch (*pexpr) {
      case 't': c = '\t'; break; /* tab */
      case 'v': c = '\v'; break; /* tab */
      case 'n': c = '\n'; break; /* line feed */
      case 'f': c = '\f'; break; /* form feed */
      case 'r': c = '\r'; break; /* carrige return */
      case 'e': c = 0x1b; break; /* escape code */
      case 's': c = 0x20; break; /* space */
      default:
        dviprt_printtokenerror(pinfo,pinfo->token,2,ERROR_UNKNOWN_ESCSEQ);
        return CFG_TOKEN_ERROR;
      }
      return c;
    }
    else if (!strlcmp("SP",pexpr,pinfo->endtoken - pexpr))
      return 0x20;
    else if (!strlcmp("ESC",pexpr,pinfo->endtoken - pexpr))
      return 0x1b;
    switch (*pexpr) {
    case 'x':
    case 'X':
      v = dviprt_hex2long(pexpr+1,pinfo->endtoken,&pnext);
    check_numb_range:
      if (pstart != pnext) {
        dviprt_printtokenerror(pinfo,pinfo->token,
			       (int)(pinfo->endtoken - pinfo->token), ERROR_INVALID_VALUE);
        return CFG_TOKEN_ERROR;
      }
      if (v >= 256) {
        dviprt_printtokenerror(pinfo,pinfo->token,
			       (int)(pinfo->endtoken - pinfo->token), ERROR_OUTOFRANGE);
        return CFG_TOKEN_ERROR;
      }
      pinfo->endtoken = pnext;
      return v;
    case '0':
      v = dviprt_oct2long(pexpr,pinfo->endtoken,&pnext);
      goto check_numb_range;
    case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
    parse_decimal_numb:
      v = dviprt_dec2long(pexpr,pinfo->endtoken,&pnext);
      goto check_numb_range;
    default:
      return CFG_TOKEN_FMT;
    }
  }
  else {
    pinfo->token = pstart;
    pinfo->endtoken = pstart+1;
    return *pstart;
  }
}

private long 
dviprt_dec2long
  D3(uchar *,start,uchar *,end,uchar **, next)
{
  long v = 0;
  while (start < end) {
    int c = *start;
    if (isdigit(c)) v = v*10 + c - '0';
    else break;
    start++;
  }
  *next = start;
  return v;
}

private long 
dviprt_oct2long
  D3(uchar *,start,uchar *,end,uchar **, next)
{
  long v = 0;
  while (start < end) {
    int c = *start;
    if (c >= '0' && c <= '7') v = v*8 + c - '0';
    else break;
    start++;
  }
  *next = start;
  return v;
}

private long 
dviprt_hex2long
  D3(uchar *,start,uchar *,end,uchar **, next)
{
  long v = 0;
  while (start < end) {
    int c = *start;
    if (isdigit(c)) v = v*16 + c - '0';
    else if (c >= 'A' && c <= 'F') v = v*16 + c - 'A' + 10;
    else if (c >= 'a' && c <= 'f') v = v*16 + c - 'a' + 10;
    else break;
    start++;
  }
  *next = start;
  return v;
}

private int 
dviprt_set_rpexpr
  D6(dviprt_cfg_item_t *,pitem,uchar *, pbuf,int ,len,
     dviprt_cfg_t *, pcfg, dviprt_cfg_i *, pinfo,int , sp)
{
  uchar *pend = pbuf + len;
  uchar *plastop = NULL;
  int code;
  
  /* get left expr */
  while (pbuf < pend) {
    int par_count = 0;
    uchar *pcur = pbuf;
    while (pcur < pend) {
      if (*pcur == '(') par_count++;
      else if (*pcur == ')') par_count--;
      else if (!isdigit(*pcur) && !isalpha(*pcur) && par_count == 0) {
        /* operator */
        plastop = pcur;
      }
      pcur++;
    }
    if (par_count != 0) {
      dviprt_printtokenerror(pinfo,pbuf,(int)(pend-pbuf),ERROR_INCOMPLETE);
      return CFG_ERROR_SYNTAX;
    }
    if (plastop == NULL) {
      if (*pbuf != '(') break;
      pbuf++;
      pend--;
    }
    else break;
  }
  
  if (plastop == NULL) { /* no operator */
    ulong v;
    uchar *pdummy;
    if (*pbuf == '0') {
      uchar a,b,c;
      v = dviprt_oct2long(pbuf,pend,&pdummy);
    check_intval:
      if (pdummy != pend) goto unknown_value;
      if (v > 0xffff) {
	dviprt_printtokenerror(pinfo,pbuf,(int)(pend-pbuf),ERROR_OUTOFRANGE);
	return CFG_ERROR_RANGE;
      }
      a = v & 0x7f;
      b = (v>>7) & 0x7f;
      c = (v>>14) & 0x03;
      if (c) {
        *pinfo->pcodebuf++ = c;
        *pinfo->pcodebuf++ = 14;
        *pinfo->pcodebuf++ = CFG_OP_SHL;
      }
      if (b) {
        *pinfo->pcodebuf++ = b;
        *pinfo->pcodebuf++ = 7;
        *pinfo->pcodebuf++ = CFG_OP_SHL;
        if (c) *pinfo->pcodebuf++ = CFG_OP_OR;
      }
      if (a) {
        *pinfo->pcodebuf++ = a;
        if (b || c) *pinfo->pcodebuf++ = CFG_OP_OR;
      }
      code = 0;
    }
    else if (isdigit(*pbuf)) {
      v = dviprt_dec2long(pbuf,pend,&pdummy);
      goto check_intval;
    }
    else if (pend - pbuf > 1 && (*pbuf == 'x' || *pbuf == 'X')) {
      v = dviprt_hex2long(pbuf+1,pend,&pdummy);
      goto check_intval;
    }
    else if (pend - pbuf > 1) {
    unknown_value:
      dviprt_printtokenerror(pinfo,pbuf,(int)(pend-pbuf),ERROR_UNKNOWN_VALUE);
      return CFG_ERROR_RANGE;
    }
    else {
      switch (*pbuf) {
      case 'd': v = CFG_VAL_DEFAULT;
        if (pitem->no != CFG_SEND_BIT_IMAGE &&
            pitem->no != CFG_BIT_ROW_HEADER &&
            pitem->no != CFG_AFTER_BIT_IMAGE &&
            pitem->no != CFG_SKIP_SPACES)
          goto unavailable_value;
        break;
      case 'c': v = CFG_VAL_CONSTANT; break;
      case 'w': v = CFG_VAL_WIDTH; break;
      case 'h': v = CFG_VAL_HEIGHT; break;
      case 'r': v = CFG_VAL_X_DPI; break;
      case 'R': v = CFG_VAL_Y_DPI; break;
      case 'p': v = CFG_VAL_PAGE; break;
      case 'x': v = CFG_VAL_X_POS; break;
      case 'y': v = CFG_VAL_Y_POS; break;
      case 'v': v = CFG_VAL_PINS_BYTE; break;
      case 's':
        v = CFG_VAL_DATASIZE;
        if (pitem->no != CFG_SEND_BIT_IMAGE &&
            pitem->no != CFG_BIT_ROW_HEADER &&
            pitem->no != CFG_AFTER_BIT_IMAGE) {
        unavailable_value:
          dviprt_printcfgerror(pinfo,"",-1);
          sprintf(dviprt_message_buffer,"Variable `%c' in ",(int)*pbuf);
          dviprt_printmessage(dviprt_message_buffer,-1);
          dviprt_printmessage(pbuf,(int)(pend-pbuf));
          sprintf(dviprt_message_buffer," cannot be used in %s.\n",pitem->name);
          dviprt_printmessage(dviprt_message_buffer,-1);
          return CFG_ERROR_RANGE;
        }
        break;
      default:
        goto unknown_value;
      }
      *pinfo->pcodebuf++ = v;
      code = 0;
    }
  }
  else { /* has operator */
    uchar op;
    
    code = dviprt_set_rpexpr(pitem,pbuf,(int)(plastop-pbuf),pcfg,pinfo,sp+1);
    if (code < 0) return code;
    code = dviprt_set_rpexpr(pitem,plastop+1,(int)(pend-plastop-1),pcfg,pinfo,sp+2);
    if (code < 0) return code;
    
    switch (*plastop) {
    case '+': op = CFG_OP_ADD; break;
    case '-': op = CFG_OP_SUB; break;
    case '*': op = CFG_OP_MUL; break;
    case '/': op = CFG_OP_DIV; break;
    case '%': op = CFG_OP_MOD; break;
    case '<': op = CFG_OP_SHL; break;
    case '>': op = CFG_OP_SHR; break;
    case '&': op = CFG_OP_AND; break;
    case '|': op = CFG_OP_OR ; break;
    case '^': op = CFG_OP_XOR; break;
    default:
      dviprt_printcfgerror(pinfo,NULL,0);
      sprintf(dviprt_message_buffer,"Unknown operator %c in ",(int)*pbuf);
      dviprt_printmessage(dviprt_message_buffer,-1);
      dviprt_printmessage(pbuf,(int)(pend-pbuf));
      dviprt_printmessage(".\n",-1);
      return CFG_ERROR_SYNTAX;
    }
    *pinfo->pcodebuf++ = op;
  }
  
  return code;
}

private int 
dviprt_set_code
  D4(dviprt_cfg_item_t *,pitem, uchar *, buf,
     dviprt_cfg_t *, pcfg, dviprt_cfg_i *, pinfo)
{
  long prev_line;
  int prev_type = 1;
  uchar *pcount;
  uchar *pcode_begin;
  uchar *rbuf;
  int obytes = 0;
  
  prev_line = ftell(pinfo->file);
  pcode_begin = pinfo->pcodebuf;
  rbuf = pinfo->readbuf;
  
  for ( ; ; ) {
    while (*buf) {
      int c;
      c = dviprt_get_codetype_token(pinfo,buf,buf+strlen(buf),",","");
      if (c == CFG_TOKEN_LIMIT_BIT) break; /* no elements remain */
      else if (c == CFG_TOKEN_ERROR) return CFG_ERROR_SYNTAX;
      if ( c < 256) {        /* character code (raw data) */
        if (prev_type) {
        new_unit:
          pcount = pinfo->pcodebuf++;
          (*pcount) = 0;
          prev_type = 0;
        }
        if (*pcount == 127) goto new_unit;
        (*pcount)++;
        *pinfo->pcodebuf++ = c;
        buf = pinfo->endtoken;
        obytes++;
      }
      else if (c == CFG_TOKEN_FMT) { /* format */
        uchar *pexpr = pinfo->token;
        int div=0,iso=0,mul=0,tl=0;
        int cols=0;
	int fmt;
        uchar *plength;
        uchar *pstart;
        
        buf = pinfo->token+1;
        
        /* formats */
        switch (*buf) {
        case 'b': fmt = CFG_FMT_BIN_LTOH; break;
        case 'B': fmt = CFG_FMT_BIN_HTOL; break;
        case 'H': fmt = CFG_FMT_HEX_UPPER; break;
        case 'h': fmt = CFG_FMT_HEX_LOWER; break;
        case 'd': fmt = CFG_FMT_DECIMAL; break;
        case 'o': fmt = CFG_FMT_OCTAL; break;
        case 's':
          buf++;
          if (*buf != 't') goto unknown_format;
          fmt = CFG_FMT_STRINGS;
          break;
        default:
        unknown_format:
          dviprt_printtokenerror(pinfo,pexpr,(int)(pinfo->endtoken-pexpr),
				 ERROR_UNKNOWN_FORMAT);
          return CFG_ERROR_SYNTAX;
        }
        buf++;
	
        /* columns */
        if (fmt == CFG_FMT_STRINGS) ;
        else {
          if (buf >= pinfo->endtoken) {
            dviprt_printtokenerror(pinfo,pexpr,(int)(pinfo->token-pexpr),ERROR_INCOMPLETE);
            return CFG_ERROR_SYNTAX;
          }
          
          if (!(*buf >= '1' && *buf <= '7') && *buf != '?') {
          invalid_cols:
            dviprt_printtokenerror(pinfo,pexpr,(int)(pinfo->endtoken-pexpr),
				   ERROR_UNKNOWN_FORMAT);
            return CFG_ERROR_SYNTAX;
          }
          cols = (*buf == '?') ? 0 : *buf - '0';
          if (cols == 0 &&
              (fmt == CFG_FMT_BIN_LTOH || fmt == CFG_FMT_BIN_HTOL))
            goto invalid_cols;
	  
          buf++;
          obytes += (cols == 0) ? 5 : cols;
        }
        
        /* additional format */
        while (buf < pinfo->endtoken) {
          switch (*buf) {
          case 'D': div++; break;
          case 'I': iso++; break;
          case 'M': mul++; break;
          case 'T': tl++; break;
          default:
            dviprt_printtokenerror(pinfo,pexpr,(int)(buf-pexpr),ERROR_UNKNOWN_FORMAT);
            return CFG_ERROR_SYNTAX;
          }
          if (div > 3 || iso > 1 || mul > 1 || tl > 1) {
            dviprt_printtokenerror(pinfo,pexpr,(int)(buf-pexpr),ERROR_UNKNOWN_FORMAT);
            return CFG_ERROR_SYNTAX;
          }
          buf++;
        }
        *pinfo->pcodebuf++ =
          CFG_FMT_BIT | fmt | (iso ? CFG_FMT_ISO_BIT : 0) | cols;
        plength = pinfo->pcodebuf;
        pinfo->pcodebuf++;
        pstart = pinfo->pcodebuf;
        
        if (*buf == ',' && *(buf+1) != '\"') {
	  int code;
          buf++;
          pinfo->token = buf;
          while (*pinfo->token && *pinfo->token != ',' &&
                 *pinfo->token != '\\' && !isspace(*pinfo->token))
            pinfo->token++;
	  if (pinfo->token == buf) {
            dviprt_printcfgerror(pinfo,"No expression is specified in ",-1);
            dviprt_printmessage(pexpr,(int)(buf-pexpr));
            dviprt_printmessage(".\n",-1);
            return CFG_ERROR_SYNTAX;
          }
          if ((code = dviprt_set_rpexpr(pitem,buf,(int)(pinfo->token-buf),pcfg,pinfo,0)) < 0)
  	    return code;
          buf = pinfo->token;
        }
        else {
          *pinfo->pcodebuf++ = CFG_VAL_DEFAULT;
        }
        if (mul) {
          *pinfo->pcodebuf++ = CFG_VAL_CONSTANT;
          *pinfo->pcodebuf++ = CFG_OP_MUL;
        }
        if (tl) {
          *pinfo->pcodebuf++ = CFG_VAL_PINS_BYTE;
          *pinfo->pcodebuf++ = CFG_OP_MUL;
        }
        if (div) {
          *pinfo->pcodebuf++ = div;
          *pinfo->pcodebuf++ = CFG_OP_SHR;
        }
	{
	  int length = pinfo->pcodebuf-pstart;
	  if (length > 255) {
	    dviprt_printtokenerror(pinfo,pexpr,(int)(buf-pexpr),ERROR_COMPLICATED_EXPR);
	    return CFG_ERROR_RANGE;
	  }
	  *plength++ = length & 0xff;
	}
        if (fmt == CFG_FMT_STRINGS) {
          uchar *pslen = pinfo->pcodebuf++;
          int len;
          if (strlen(buf) < 2 || *buf != ',' || *(buf+1) != '\"') {
	    dviprt_printcfgerror(pinfo,"No strings specified in ",-1);
	    dviprt_printmessage(pexpr,(int)(buf-pexpr));
	    dviprt_printmessage(".\n",-1);
            return CFG_ERROR_SYNTAX;
          }
          buf += 2;
          for (len=0; ;len++) {
            c = dviprt_get_codetype_token(pinfo,buf,buf+strlen(buf),"\"","\"");
            if (c == CFG_TOKEN_ERROR) return CFG_ERROR_SYNTAX;
            else if (c == CFG_TOKEN_FMT) {
              dviprt_printcfgerror(pinfo,"The format ",-1);
              dviprt_printmessage(pinfo->token,
				  (int)(pinfo->endtoken-pinfo->token));
              dviprt_printmessage(" cannot to be specified here.\n",-1);
              return CFG_ERROR_SYNTAX;
            }
            else if (c & CFG_TOKEN_LIMIT_BIT) {
              if ((c & 0xff) != '\"') {
                dviprt_printcfgerror(pinfo,
				     "Strings must be enclosed with "
				     "double quotations (\").\n",-1);
                return CFG_ERROR_SYNTAX;
              }
              buf = pinfo->endtoken;
              break;
            }
            *pinfo->pcodebuf++ = c;
            buf = pinfo->endtoken;
          }
          if (len > 255) {
            dviprt_printcfgerror(pinfo,"Too long strings.\n",-1);
            return CFG_ERROR_RANGE;
          }
	  *pslen = len;
	}
        prev_type = 1;
      }
      else {
	dviprt_printcfgerror(pinfo,"Parse error. Unexpected token ",-1);
	dviprt_printmessage(pinfo->token,(int)(pinfo->endtoken-pinfo->token));
	dviprt_printmessage(".\n",-1);
	return CFG_ERROR_SYNTAX;
      }
    }
  next_line:
    if (fgets(rbuf,pinfo->readbuf_size,pinfo->file) == NULL) break;
    if (!isspace(rbuf[0]) && rbuf[0] != ';') {
      fseek(pinfo->file,prev_line,0);
      break;
    }
    prev_line = ftell(pinfo->file);
    pinfo->line_no++;
    buf = rbuf;
    while (*buf && isspace(*buf)) buf++;
    if (*buf == ';')
      goto next_line; /* comment */
    {
      int len = strlen(rbuf);
      if (len > 0 && rbuf[len-1] == '\n')
        rbuf[len-1] = 0;
    }
  }
  pcfg->prtcode[pitem->no] = pcode_begin;
  pcfg->prtcode_size[pitem->no] = (pinfo->pcodebuf - pcode_begin) & 0xffff;
  *pinfo->pcodebuf++ = 0;
  return obytes;
}

private char *
dviprt_src_errorno2message
  D1(int ,type)
{
  switch (type) {
  case ERROR_OUTOFRANGE:
    return "Out of range.\n";
  case ERROR_UNKNOWN_VALUE:
    return "Unknown value.\n";
  case ERROR_UNKNOWN_ESCSEQ:
    return "Unknown escape sequence.\n";
  case ERROR_COMPLICATED_EXPR:
    return "Too complicated expression.\n";
  case ERROR_INCOMPLETE:
    return "Incomplete specification.\n";
  case ERROR_UNKNOWN_FORMAT:
    return "Unknown format.\n";
  case ERROR_INVALID_VALUE:
    return "Invalid value.\n";
  default:
    return NULL;
  }
}

private int 
dviprt_printtokenerror
  D4(dviprt_cfg_i *,pinfo,char *,token,int ,len,int ,type)
{
  char *msg;
  
  dviprt_printcfgerror(pinfo,token,len);
  dviprt_printmessage("\n",-1);
  
  if ((msg = dviprt_src_errorno2message(type)) != NULL)
    dviprt_printcfgerror(pinfo,msg,-1);
  return 0;
}

#undef strlcmp
#undef set_version
/***** End of rsrc.c *****/


/***** From util.c *****/
/* $Id: UTIL.C 1.1 1994/08/30 02:27:02 kaz Exp kaz $ */


char *dviprt_integername[] = { CFG_INTEGER_NAME, NULL };
char *dviprt_stringsname[] = { CFG_STRINGS_NAME, NULL };
char *dviprt_prtcodename[] = { CFG_PRTCODE_NAME, NULL };
char *dviprt_encodename[] = { CFG_ENCODE_NAME, NULL };

private FILE *dviprt_messagestream = stderr;

/*--- library functions ---*/
int
dviprt_setmessagestream
  D1(FILE *, fp)
{
  dviprt_messagestream = fp;
  return 0;
}

/*--- internal routines ---*/
int 
dviprt_initcfg_
  D2(dviprt_cfg_t *, pcfg,dviprt_cfg_i *, pinfo)
{
  int i;
  
  for (i=0;i<CFG_INTEGER_TYPE_COUNT;i++)
    pcfg->integer[i] = -1;
  for (i=0;i<CFG_STRINGS_TYPE_COUNT;i++)
    pcfg->strings[i] = NULL;
  for (i=0;i<CFG_PRTCODE_TYPE_COUNT;i++) {
    pcfg->prtcode[i] = NULL;
    pcfg->prtcode_size[i] = 0;
  }
  pinfo->pcodebuf = pinfo->codebuf;
  pinfo->line_no = 0;
  return 0;
}

int 
dviprt_setcfgbuffer_
  D3(dviprt_cfg_i *,pinfo, int , rsize, int , csize)
{
  pinfo->temp_readbuf_f = pinfo->temp_codebuf_f = 0;
  
  if (pinfo->readbuf == NULL) {
    pinfo->readbuf_size = rsize;
    if (rsize>0) {
      pinfo->temp_readbuf_f = 1;
      pinfo->readbuf = (uchar *)malloc(rsize);
      if (pinfo->readbuf == NULL) {
      no_mem:
        dviprt_printmessage(pinfo->fname,-1);
        dviprt_printmessage("Memory exhausted.\n",-1);
        return CFG_ERROR_MEMORY;
      }
    }
  }
  if (pinfo->codebuf == NULL) {
    pinfo->codebuf_size = csize;
    if (csize>0) {
      pinfo->temp_codebuf_f = 1;
      pinfo->codebuf = (uchar *)malloc(csize);
      if (pinfo->codebuf == NULL) goto no_mem;
    }
  }
  return 0;
}

int 
dviprt_resetcfgbuffer_
  D1(dviprt_cfg_i *,pinfo)
{
  if (pinfo->temp_readbuf_f) free(pinfo->readbuf);
  if (pinfo->temp_codebuf_f) free(pinfo->codebuf);
  pinfo->temp_codebuf_f = pinfo->temp_readbuf_f = 0;
  return 0;
}

char dviprt_message_buffer[128];

int
dviprt_printmessage
  D2(char *,str,int ,len)
{
  if (dviprt_messagestream && str) {
    if (len >= 0) fwrite(str,len,1,dviprt_messagestream);
    else fputs(str,dviprt_messagestream);
    fflush(dviprt_messagestream);
  }
  return 0;
}

private int
dviprt_printcfgerrorheader
  D1(dviprt_cfg_i *, pinfo)
{
  if (pinfo) {
    char *fn = pinfo->fname;
    if (fn == NULL) fn = "-";
    dviprt_printmessage(fn,-1);
    dviprt_printmessage(": ",-1);
    if (pinfo->line_no>0) {
      sprintf(dviprt_message_buffer,"%d: ",pinfo->line_no);
      dviprt_printmessage(dviprt_message_buffer,-1);
    }
  }
  return 0;
}

int
dviprt_printerror
  D2(char *,msg,int ,len)
{
  dviprt_printmessage("*ERROR* ",-1);
  dviprt_printmessage(msg,len);
  return 0;
}

int 
dviprt_printcfgerror
  D3(dviprt_cfg_i *,pinfo, char *,msg, int , len)
{
  dviprt_printcfgerrorheader(pinfo);
  dviprt_printerror(msg,len);
  return 0;
}

int
dviprt_printwarning
  D2(char *,msg,int ,len)
{
  dviprt_printmessage("*WARNING* ",-1);
  dviprt_printmessage(msg,len);
  return 0;
}

int 
dviprt_printcfgwarning
  D3(dviprt_cfg_i *,pinfo, char *,msg, int , len)
{
  dviprt_printcfgerrorheader(pinfo);
  dviprt_printwarning(msg,len);
  return 0;
}
/***** End of util.c *****/


/***** From wcfg.c *****/
/* $Id: WCFG.C 1.1 1994/08/30 02:27:02 kaz Exp kaz $ */


/*--- library functions ---*/
int
dviprt_writecfg
  D5(char *, ofname, char *,comment, dviprt_cfg_t *,pcfg,
     uchar *,dummy1,int ,dummy2)
{
  FILE *ofp;
  int count[3] = {0,0,0};
  long pos[3];
  long pointpos;
  dviprt_cfg_i info;
  int i;
  
  for (i=0;i<CFG_INTEGER_TYPE_COUNT;i++)
    if (pcfg->integer[i] >= 0) count[0]++;
  for (i=0;i<CFG_STRINGS_TYPE_COUNT;i++)
    if (pcfg->strings[i] != NULL) count[1]++;
  for (i=0;i<CFG_PRTCODE_TYPE_COUNT;i++)
    if (pcfg->prtcode[i] != NULL) count[2]++;
  
  info.line_no = -1;
  info.fname = ofname;
  
  if (ofname) {
    char fmode[4];
    strcpy(fmode,gp_fmode_wb);
    strcat(fmode,"+");
    ofp = fopen(ofname,fmode);
    if (ofp == NULL) {
      dviprt_printcfgerror(&info,"Cannot open.\n",-1);
      return CFG_ERROR_FILE_OPEN;
    }
  }
  else {
    ofp = stdout;
  }
  fwrite(CFG_MAGIC_NUMBER,2,1,ofp);
  fputc(pcfg->version&0xff,ofp);
  fputc((pcfg->version>>8)&0xff,ofp);
  fflush(ofp);
  pointpos = ftell(ofp);
  fwrite("\0\0\0\0\0\0\0\0\0\0\0\0",12,1,ofp);
  fputs("S\xff\xff",ofp);
  
  /* Write integer value */
  fflush(ofp);
  pos[0] = ftell(ofp);
  fputc(count[0],ofp);
  for (i=0;i<CFG_INTEGER_TYPE_COUNT;i++) {
    if (pcfg->integer[i] >= 0) {
      fputc(i,ofp);
      fputc((int)pcfg->integer[i]&0xff,ofp);
      fputc((int)(pcfg->integer[i]>>8)&0xff,ofp);
    }
  }
  fflush(ofp);
  pos[1] = ftell(ofp);
  fputc(count[1],ofp);
  for (i=0;i<CFG_STRINGS_TYPE_COUNT;i++) {
    if (pcfg->strings[i] != NULL) {
      int l = strlen(pcfg->strings[i]);
      fputc(i,ofp);
      fputc(l&0xff,ofp);
      fputc((l>>8)&0xff,ofp);
      fputs(pcfg->strings[i],ofp);
    }
  }
  fflush(ofp);
  pos[2] = ftell(ofp);
  fputc(count[2],ofp);
  for (i=0;i<CFG_PRTCODE_TYPE_COUNT;i++) {
    if (pcfg->prtcode[i] != NULL) {
      uint l = pcfg->prtcode_size[i];
      fputc(i,ofp);
      fputc(l&0xff,ofp);
      fputc((l>>8)&0xff,ofp);
      fwrite(pcfg->prtcode[i],l,1,ofp);
    }
  }
  /* write pointer */
  fseek(ofp,pointpos,0);
  for (i=0;i<3;i++) {
    int j;
    for (j=0;j<4;j++) {
      fputc((int)(pos[i]&0xff),ofp);
      pos[i] >>= 8;
    }
  }
  if (ofname) fclose(ofp);
  return 0;
}
/***** End of wcfg.c *****/


/***** From wsrc.c *****/
/* $Id: WSRC.C 1.1 1994/08/30 02:27:02 kaz Exp kaz $ */


#define PRINT_ITEM_FORMAT "%-18s :"
#define SOURCE_LINE_WIDTH 64

/*--- forward declarations ---*/
private int dviprt_printrpexpr(P4(long *,int,dviprt_cfg_t *,dviprt_cfg_i *));
private int dviprt_printcode(P3(uchar *,dviprt_cfg_t *,dviprt_cfg_i *));

/*--- library functions ---*/
int
dviprt_writesrc
  D5(char *, ofname,char *, comment,dviprt_cfg_t *, pcfg,
     uchar *,pwork,int ,work_size)
{
  FILE *ofp;
  uchar *pbuf=NULL;
  int code = 0;
  int i;
  int enc = CFG_ENCODE_NULL;
  int upper_pos = 0;
  dviprt_cfg_i info;
  
  info.readbuf = pwork;
  info.readbuf_size = work_size;
  info.fname = ofname;
  if ((code =
       dviprt_setcfgbuffer_(&info,sizeof(long)*(CFG_STACK_DEPTH+10),0)) < 0)
    return code;
  
  if (ofname) {
    ofp = fopen(ofname,"w");
    if (ofp == NULL) {
      dviprt_printcfgerror(&info,"Cannot open.\n",-1);
      return CFG_ERROR_FILE_OPEN;
    }
  }
  else {
    ofp = stdout;
  }
  info.file = ofp;
  
  dviprt_print_headercomment_(comment,"; ","",ofp);
  
  for (i=0;i<CFG_INTEGER_TYPE_COUNT;i++) {
    if (pcfg->integer[i] >= 0L) {
      uint v = pcfg->integer[i];
      if (i == CFG_PINS) v *= 8;
      switch (i) {
      case CFG_PINS:
      case CFG_MINIMAL_UNIT:
      case CFG_MAXIMAL_UNIT:
      case CFG_DPI:
      case CFG_Y_DPI:
      case CFG_CONSTANT:
        fprintf(ofp,PRINT_ITEM_FORMAT " %u\n",dviprt_integername[i],v);
        break;
      case CFG_ENCODE:
        enc = v; break;
      case CFG_UPPER_POS:
        upper_pos = v; break;
      }
    }
  }
  switch (upper_pos & 0xc0) {
  case CFG_TOP_IS_HIGH:
    pbuf = "HIGH_BIT"; break;
  case CFG_TOP_IS_LOW:
    pbuf = "LOW_BIT"; break;
  case CFG_LEFT_IS_HIGH:
    pbuf = "LEFT_IS_HIGH"; break;
  case CFG_LEFT_IS_LOW:
    pbuf = "LEFT_IS_LOW"; break;
  }
  fprintf(ofp,PRINT_ITEM_FORMAT " %s","upper_position",pbuf);
  if (upper_pos & CFG_NON_MOVING)
    fprintf(ofp," NON_MOVING");
  fprintf(ofp,"\n");
  
  for (i=0;i<CFG_STRINGS_TYPE_COUNT;i++) {
    if (pcfg->strings[i] != NULL) {
      if (i != CFG_ENCODE_INFO) {
        fprintf(ofp,PRINT_ITEM_FORMAT " %s\n",
		dviprt_stringsname[i],pcfg->strings[i]);
      }
    }
  }
  if (enc != CFG_ENCODE_NULL) {
    fprintf(ofp,PRINT_ITEM_FORMAT " %s","encode",dviprt_encodename[enc]);
    if (pcfg->strings[CFG_ENCODE_INFO] && *pcfg->strings[CFG_ENCODE_INFO])
      fprintf(ofp," %s",pcfg->strings[CFG_ENCODE_INFO]);
    fprintf(ofp,"\n");
  }
  
  for (i=0;i<CFG_PRTCODE_TYPE_COUNT;i++) {
    if (pcfg->prtcode[i] != NULL) {
      fprintf(ofp,PRINT_ITEM_FORMAT,dviprt_prtcodename[i]);
      if (dviprt_printcode(pcfg->prtcode[i],pcfg,&info) < 0) {
        code = -1;
        break;
      }
    }
  }
  
  if (ofname) fclose(ofp);
  dviprt_resetcfgbuffer_(&info);
  return code;
}

/*--- internal routines ---*/
private int
dviprt_printcchar
  D4(FILE *, fp, int , c,int , col, int *, prev)
{
  if (col == 0) fputc('\t',fp);
  if (isprint(c) && !isspace(c) && c != '\\') {
    if (col == 0 && c == ';') goto es;
    else {
      if (*prev) {
        if (col) fputc(' ',fp);
        col++;
      }
      fputc(c,fp);
      *prev = 0;
      col++;
      return col;
    }
  }
  else {
  es:
    if (col) { fputc(' ',fp); col++; }
    fputc('\\',fp);
    col += 2;
    switch (c) {
    case '\n': fputs("n\n",fp); *prev = 0; col = 0; break;
    case '\r': fputc('r',fp); break;
    case '\f': fputc('f',fp); break;
    case '\t': fputc('t',fp); break;
    case ' ': fputc('s',fp); break;
    case '\\': fputc(' ',fp); break;
    case 0x1b: fputc('e',fp); break;
    default: fprintf(fp,"x%02X",c); col += 2; break;
    }
    *prev = 1;
  }
  if (col > SOURCE_LINE_WIDTH) { fputc('\n',fp); *prev = 0; col = 0; }
  return col;
}

private int
dviprt_printcode
  D3(uchar *, pcode,dviprt_cfg_t *, pcfg, dviprt_cfg_i *, pinfo)
{
  int col = 12;
  int prev = 1;
  long *pinteger;
  FILE *fp;
  
  fp = pinfo->file;
  pinteger = (long*)pinfo->readbuf;
  while (*pcode) {
    if (!(*pcode & CFG_FMT_BIT)) {
      int len;
      for (len=*pcode++;len; len--,pcode++) {
        col = dviprt_printcchar(fp,*pcode,col,&prev);
      }
    }
    else {
      uchar fmt = *pcode++;
      int len = *pcode++;
      int sp = -1;
      int code;
      for ( ;len>0;len--,pcode++) {
        if ((*pcode & CFG_EXPR_TYPE_BIT) == CFG_VAL) {
          pinteger[++sp] = *pcode | 0x10000L;
        }
        else if ((*pcode & CFG_EXPR_TYPE_BIT) == CFG_OP) {
          if (sp >= 1 &&
              !(pinteger[sp] & 0x10000L) &&
              !(pinteger[sp-1] & 0x10000L)) {
            uint v1 = pinteger[sp-1];
            uint v2 = pinteger[sp];
            sp--;
            switch (*pcode) {
            case CFG_OP_ADD: v1 += v2; break;
            case CFG_OP_SUB: v1 -= v2; break;
            case CFG_OP_MUL: v1 *= v2; break;
            case CFG_OP_DIV:
              if (v2 == 0) {
              div_by_zero:
                dviprt_printcfgerror(pinfo,
				     "Divided by zero while evaluating the expression.\n",-1);
                return CFG_ERROR_DIV0;
              }
              v1 /= v2; break;
            case CFG_OP_MOD:
              if (v2 == 0) goto div_by_zero;
              v1 %= v2; break;
            case CFG_OP_SHL: v1 <<= v2; break;
            case CFG_OP_SHR: v1 >>= v2; break;
            case CFG_OP_AND: v1 &= v2; break;
            case CFG_OP_OR : v1 |= v2; break;
            case CFG_OP_XOR: v1 ^= v2; break;
            default:
              sprintf(dviprt_message_buffer,
		      "Unknown operator %02X.\n",(int)*pcode);
              dviprt_printcfgerror(pinfo,dviprt_message_buffer,-1);
              return CFG_ERROR_OTHER;
            }
            pinteger[sp] = v1 & 0xffff;
          }
          else
            pinteger[++sp] = (uint )*pcode | 0x10000L;
        }
        else {
          pinteger[++sp] = (uint )*pcode;
        }
      }
      fputc(col == 0 ? '\t' : ' ',fp);
      col++;
      
      if ((fmt & CFG_FMT_FORMAT_BIT) == CFG_FMT_STRINGS) {
        fputs("\\st,",fp);
        col += 4;
      }
      else {
        fputc('\\',fp);
        switch (fmt & CFG_FMT_FORMAT_BIT) {
        case CFG_FMT_BIN_LTOH: code = 'b'; break;
        case CFG_FMT_BIN_HTOL: code = 'B'; break;
        case CFG_FMT_HEX_UPPER: code = 'H'; break;
        case CFG_FMT_HEX_LOWER: code = 'h'; break;
        case CFG_FMT_DECIMAL: code = 'd'; break;
        case CFG_FMT_OCTAL: code = 'o'; break;
        default:
          sprintf(dviprt_message_buffer,"Unknown output format %02X.\n",
		  (int)fmt & CFG_FMT_FORMAT_BIT);
          dviprt_printcfgerror(pinfo,dviprt_message_buffer,-1);
          return CFG_ERROR_OTHER;
        }
        fputc(code,fp);
        code = (fmt & CFG_FMT_COLUMN_BIT);
        if (code==0) fputc('?',fp);
        else fputc('0'+code,fp);
        if (fmt & CFG_FMT_ISO_BIT) fputc('I',fp);
        fputc(',',fp);
        col += 5;
      }
      code = dviprt_printrpexpr(pinteger,sp+1,pcfg,pinfo);
      if (code<0) return code;
      col += code;
      if ((fmt & CFG_FMT_FORMAT_BIT) == CFG_FMT_STRINGS) {
        int l = *pcode++;
        fputs(",\"",fp);
        col++;
        prev = 0;
        for ( ;l>0;l--) {
          col += dviprt_printcchar(fp,*pcode,1,&prev);
          pcode++;
        }
        prev = 1;
        fputc('\"',fp);
        col++;
      }
      if (col > SOURCE_LINE_WIDTH) { fputc('\n',fp); col = 0; }
      prev = 1;
    }
  }
  if (col) fputc('\n',fp);
  return 0;
}

private int
dviprt_printrpexpr
  D4(long *, pexpr, int , len, dviprt_cfg_t *, pcfg, dviprt_cfg_i *,pinfo)
{
  int outlen;
  FILE *fp;
  
  fp = pinfo->file;
  pexpr += (len-1);
  if (len == 1) {
    if (!(*pexpr & 0x10000L))
      outlen = fprintf(fp,"%u",(int)(*pexpr)&0xffff);
    else if ((*pexpr & CFG_EXPR_TYPE_BIT) == CFG_VAL) {
      int c = *pexpr & 0xffff;
      switch (c) {
      case CFG_VAL_DEFAULT: c = 'd'; break;
      case CFG_VAL_CONSTANT: c = 'c'; break;
      case CFG_VAL_WIDTH: c = 'w'; break;
      case CFG_VAL_HEIGHT: c = 'h'; break;
      case CFG_VAL_PAGE: c = 'p'; break;
      case CFG_VAL_DATASIZE: c = 's'; break;
      case CFG_VAL_X_DPI: c = 'r'; break;
      case CFG_VAL_Y_DPI: c = 'R'; break;
      case CFG_VAL_PINS_BYTE: c = 'v'; break;
      case CFG_VAL_X_POS: c = 'x'; break;
      case CFG_VAL_Y_POS: c = 'y'; break;
      default:
        sprintf(dviprt_message_buffer,"\nUnknown value %02X.\n",c);
        dviprt_printcfgerror(pinfo,dviprt_message_buffer,-1);
        return -1;
      }
      fputc(c,fp);
      outlen = 1;
    }
    else {
    too_few_operand:
      dviprt_printcfgerror(pinfo,"Invalid expression found.\n",-1);
      dviprt_printcfgerror(pinfo,"(The operator has too few operand(s)).\n",-1);
      return CFG_ERROR_OTHER;
    }
  }
  else {
    int op = *pexpr & 0xffff;
    int op_count = 0;
    int numb_count = 0;
    int rlen=0;
    long *prexpr;
    pexpr--;
    len--;
    while (op_count+1 != numb_count && len > 0) {
      if (*pexpr & 0x10000L && (*pexpr & CFG_EXPR_TYPE_BIT) == CFG_OP)
        op_count++;
      else
        numb_count++;
      pexpr--;
      len--;
      rlen++;
    }
    if (op_count+1 != numb_count) goto too_few_operand;
    prexpr = pexpr+1;
    outlen = dviprt_printrpexpr(pexpr-len+1,len,pcfg,pinfo); /* print L expr */
    if (outlen < 0) return outlen;
    switch (op) {
    case CFG_OP_ADD: op = '+'; break;
    case CFG_OP_SUB: op = '-'; break;
    case CFG_OP_MUL: op = '*'; break;
    case CFG_OP_DIV: op = '/'; break;
    case CFG_OP_MOD: op = '%'; break;
    case CFG_OP_SHL: op = '<'; break;
    case CFG_OP_SHR: op = '>'; break;
    case CFG_OP_AND: op = '&'; break;
    case CFG_OP_OR : op = '|'; break;
    case CFG_OP_XOR: op = '^'; break;
    default:
      sprintf(dviprt_message_buffer,"Unknown operator %02X.\n",op);
      dviprt_printcfgerror(pinfo,dviprt_message_buffer,-1);
      return CFG_ERROR_OTHER;
    }
    fputc(op,fp);
    if (rlen > 1) { fputc('(',fp); outlen++; }
    len = dviprt_printrpexpr(prexpr,rlen,pcfg,pinfo);
    if (len < 0) return len;
    outlen += len;
    if (rlen > 1) { fputc(')',fp); outlen++; }
  }
  return outlen;
}
/***** End of wsrc.c *****/


/***** From wc.c *****/
/* $Id: WC.C 1.1 1994/08/30 02:27:02 kaz Exp kaz $ */


/*--- forward declarations ---*/
private int dviprt_dump_c(P4(dviprt_cfg_t *,int ,char *,FILE *));
     
/*--- library functions ---*/
int
dviprt_writec
  D5(char *,ofname,char *,comment,dviprt_cfg_t *,pcfg,
     uchar *,dummy1,int, dummy2)
{
  FILE *ofp;
  int i;
  dviprt_cfg_i info;
  
  info.fname = ofname;
  info.line_no = -1;
  if (ofname) {
    ofp = fopen(ofname,"w");
    if (ofp == NULL) {
      dviprt_printcfgerror(&info,"Cannot open.\n",-1);
      return CFG_ERROR_FILE_OPEN;
    }
  }
  else {
    ofp = stdout;
  }
  
  dviprt_print_headercomment_(comment,"/* "," */",ofp);
  fputs("{\n",ofp);
  
  fprintf(ofp,"\t%d, /* version */\n",pcfg->version);
  fputs("\t{\n",ofp);
  for (i=0;i<CFG_INTEGER_TYPE_COUNT;i++) {
    fprintf(ofp,"\t\t%ld,\t/* %s (",pcfg->integer[i],dviprt_integername[i]);
    if (pcfg->integer[i] < 0) {
      fprintf(ofp,"undefined");
    }
    else {
      fprintf(ofp,"%04lx in hex",pcfg->integer[i]);
    }
    fprintf(ofp,") */\n");
  }
  fputs("\t},\n\t{\n",ofp);
  for (i=0;i<CFG_STRINGS_TYPE_COUNT;i++) {
    fputs("\t\t",ofp);
    if (pcfg->strings[i])
      fprintf(ofp,"\"%s\"",pcfg->strings[i]);
    else fputs("NULL",ofp);
    fprintf(ofp,",\t/* %s %s*/\n",dviprt_stringsname[i],
	    pcfg->strings[i] ? "" : "(undefined) ");
  }
  fputs("\t},\n\t{\n",ofp);
  for (i=0;i<CFG_PRTCODE_TYPE_COUNT;i++) {
    if (pcfg->prtcode[i]) {
      dviprt_dump_c(pcfg,i,"\t\t",ofp);
    }
    else {
      fprintf(ofp,"\t\tNULL,\t/* %s (undefined) */\n", dviprt_prtcodename[i]);
    }
  }
  fputs("\t},\n\t{\n",ofp);
  fputs("\t\t",ofp);
  for (i=0;i<CFG_PRTCODE_TYPE_COUNT;i++) {
    if (pcfg->prtcode[i]) {
      fprintf(ofp,"%d, ",pcfg->prtcode_size[i]);
    }
    else {
      fputs("0, ",ofp);
    }
  }
  fputc('\n',ofp);
  fputs("\t},\n",ofp);
  fputs("}\n",ofp);
  if (ofname) fclose(ofp);
  return 0;
}

/*--- internal routines ---*/
private int dviprt_dump_c
  D4(dviprt_cfg_t *,pcfg,int ,no,char *, header,FILE *,fp)
{
  int prev = -1;
  uchar *pcode;
  int len;
  int ln = 0,col = 0;
  
  pcode = pcfg->prtcode[no];
  len = pcfg->prtcode_size[no];
  fputs(header,fp);
  fputs("\"",fp);
  for ( ;len>0;len--,pcode++) {
    if (*pcode == '\"') {
      fputs("\\\"",fp);
      prev = 0;
      col += 2;
    }
    else if (*pcode == '\\') {
      fputs("\\\\",fp);
      prev = 0;
      col += 2;
    }
    else if (isprint(*pcode) && !isspace(*pcode)) {
      if (prev == 1) {
        fputs("\"",fp);
        col++;
        if (ln == 0 && col > 20) {
          fprintf(fp,"\t\t/* %s */\n\t",dviprt_prtcodename[no]);
          fputs(header,fp);
          ln++;
          col = 0;
        }
        else if (col > 40) {
          fputs("\n\t",fp);
          fputs(header,fp);
          ln++;
          col = 0;
        }
        else {
          fputc(' ',fp);
          col++;
        }
        fprintf(fp,"\"");
        col++;
      }
      fputc(*pcode,fp);
      col++;
      prev = 0;
    }
    else {
      fprintf(fp,"\\x%02x",(unsigned int)*pcode);
      prev = 1;
      col += 4;
    }
  }
  fputs("\",",fp);
  if (ln == 0) {
    fprintf(fp,"\t\t/* %s */",dviprt_prtcodename[no]);
  }
  fputc('\n',fp);
  return 0;
}
/***** End of wc.c *****/


/***** From wutil.c *****/
/* $Id: WUTIL.C 1.1 1994/08/30 02:27:18 kaz Exp kaz $ */


/*--- internal routines ---*/
int
dviprt_print_headercomment_
  D4(char *,comment,char *,h,char *,f,FILE *,fp)
{
  int col;
  
  if (comment == 0) return 0;
  
  col = 0;
  while (*comment) {
    if (col == 0) fputs(h,fp);
    while (*comment && *comment != '\n') {
      fputc(*comment,fp);
      col++;
      comment++;
    }
    if (*comment) {
      fputs(f,fp);
      fputc('\n',fp);
      col = 0;
      comment++;
    }
  }
  if (col) {
    fputs(f,fp);
    fputc('\n',fp);
  }
  return 0;
}
/***** End of wutil.c *****/


/*************************** End of library. **************************/
