This is psencode.c in view mode; [Download] [Up]
/* psencode.c Copyright (C) 1991 Bill Spitzak and Active Ingredients, Inc. Written by Bill Spitzak. Utility program for compressing postscript into Display PostScript binary encoding. Also see systemnames.c and constants.c! Warning: this code is NOT PORTABLE to a machine that does not use 4 byte integers, or uses low-byte-first, or does not use IEEE standard for storing floats. Decode option and the ability to read already encoded files is not yet implemented. */ /*=======================================================================*/ #include <ansi.h> #define TRUE 1 #define FALSE 0 typedef char flag; /* additions to the C library (NOT PORTABLE to non-GNU libraries!) */ int _sprintf(char *s, const char *format, void *valist) { FILE f; f._flag = _IOSTRG+_IOWRT; f._ptr = s; f._cnt = 32767; _doprnt(format,valist,&f); *f._ptr = 0; return(f._ptr-s); } #define pungetc(p) (++(p)->_cnt, --(p)->_ptr) int hexdigit(int c) { /* convert c to a digit */ if (isdigit(c)) return(c-'0'); else if (isupper(c)) return(c-'A'+10); else if (islower(c)) return(c-'a'+10); else return(INT_MAX); } /* end of C library additions */ /*=======================================================================*/ flag cstrings,decode,eps,encodestrings; /* PostScript parser: */ FILE *infile; char *infilename; int lineno; void error(char *fmt,...) { char buffer[1024]; _sprintf(buffer,fmt,&fmt+1); fprintf(stderr,"%s:%d: %s\n",infilename,lineno,buffer); } #define MAXTOKEN 128 #include "systemnames.c" flag issymbol; /* set true for 1-character symbols */ static int readsymbol(char *buf) { int x; char *p; for (;;) { x = fgetc(infile); if (x < 0) return(FALSE); if (x == '\n') lineno++; if (x > ' ') break; } p = buf; *p++ = x; issymbol = index("()<>[]{}/%#",x) || x>=128 && x<=159; if (!issymbol) { for (;;) { x = fgetc(infile); if (x<0) goto J1; if (x <= ' ' || index("()<>[]{}/%",x) || (x>=128 && x<=159)) break; if (p<buf+MAXTOKEN-1) *p++ = x; } pungetc(infile); } J1: *p++ = 0; return(TRUE); } /* Exactly one token is handled at a time. When you call readtoken again, the buffer for the previous value is thrown away! */ #define BUFSIZE 8192 char buffer[BUFSIZE]; int inttoken; double realtoken; /* NOT A FLOAT! */ /* the types of tokens, and what is put in the buffer */ #define COMMENT 1 /* text of comment with leading % or # */ #define INTEGER 2 /* inttoken is set */ #define REAL 3 /* realtoken is set */ #define STRING 4 /* inttoken is length, contents are value */ #define SYMBOL 5 /* buffer has null-terminated one character */ #define NAME 6 /* buffer has null-terminated name */ #define LITERALNAME 7 /* /foo */ #define IMMEDIATENAME 8 /* //foo */ #define BOOLEANFALSE 9 #define BOOLEANTRUE 10 void readthrueol(char *p) { int x; for (;;) { x = fgetc(infile); if (x < 0 || x == '\n' || x == '\f') break; *p++ = x; } *p++ = 0; if (x == '\n') lineno++; } static int readquoted() { register c,d,x; switch(c = fgetc(infile)) { case '\n': lineno++; return(-1); case 'a' : return('\a'); case 'b' : return('\b'); case 'f' : return('\f'); case 'n' : return('\n'); case 'r' : return('\r'); case 't' : return('\t'); case 'v' : return('\v'); case 'x' : /* read hex */ for (c=x=0; x<3; x++) { d = hexdigit(fgetc(infile)); if (d > 15) {pungetc(infile); break;} c = (c<<4)+d; } break; default: /* read octal */ if (c<'0' || c>'7') break; c -= '0'; for (x=0; x<2; x++) { d = hexdigit(fgetc(infile)); if (d>7) {pungetc(infile); break;} c = (c<<3)+d; } break; } return(c); } void readstring(char *buf) { int x,nest=0; char *p; for (p=buf;;) { x = fgetc(infile); if (x<0) {error("Missing )"); break;} if (x == '\\') {x = readquoted(); if (x<0) continue;} else if (x == '(') nest++; else if (x == ')') if (nest) nest--; else break; *p++ = x; } *p = 0; inttoken = p-buf; } void readhexstring(char *buf) { int x,y,n; char *p; for (p=buf,n=y=0;;) { x = fgetc(infile); if (x<0) {error("Missing >"); break;} if (x=='>') break; if (x=='\n') lineno++; if (x<=' ') continue; x = hexdigit(x); if (x>16) error("Bad hex string"); if (n) {*p++ = x+y; n = 0;} else {y = x<<4; n = 1;} } if (n) *p++ = y; *p = 0; inttoken = p-buf; } int readint(char *buf,int base) { int n=0,x; char *p; if (!*buf) error("Bad integer %s",buf); else for (p=buf; *p; p++) { x = hexdigit(*p); if (x >= base) {error("Bad integer %s",buf); break;} n = n*base+x; } return(n); } int readtoken(void) { char *c,*d; if (!readsymbol(buffer)) return(FALSE); switch (*(unsigned char *)buffer) { case '%': case '#': readthrueol(buffer+1); return(COMMENT); case '(': readstring(buffer); return(STRING); case '<': readhexstring(buffer); return(STRING); case '/': if (!readsymbol(buffer)) {error("/ at eof"); return(FALSE);} if (*buffer=='/') { if (!readsymbol(buffer)) {error("/ at eof"); return(FALSE);} return(IMMEDIATENAME); } return(LITERALNAME); case 'f': if (!strcmp(buffer,"false")) return(BOOLEANFALSE); goto DEFAULT; case 't': if (!strcmp(buffer,"true")) return(BOOLEANTRUE); goto DEFAULT; case '+': case '-': c = buffer+1; goto NUM; case 132: fread(&inttoken,1,4,infile); return(INTEGER); case 134: inttoken = 0; fread((void *)&inttoken+2,1,2,infile); return(INTEGER); case 136: inttoken = (signed char)fgetc(infile); return(INTEGER); case 138: {float r; fread(&r,1,4,infile); realtoken = r; return(REAL);} case 141: return(fgetc(infile) ? BOOLEANTRUE : BOOLEANFALSE); case 142: inttoken = fgetc(infile); fread(buffer,1,inttoken,infile); return(STRING); case 143: inttoken = 0; fread((void *)&inttoken+2,1,2,infile); fread(buffer,1,inttoken,infile); return(STRING); case 145: c = systemnames[fgetc(infile)]; if (!c) {error("Bad system name table index"); return(SYMBOL);} strcpy(buffer,c); return(LITERALNAME); case 146: c = systemnames[fgetc(infile)]; if (!c) {error("Bad system name table index"); return(SYMBOL);} strcpy(buffer,c); return(NAME); default: DEFAULT: if (*(unsigned char *)buffer >= 128 && *(unsigned char *)buffer <= 159) { error("Unknown token type %d\n",*(unsigned char *)buffer); return(SYMBOL); } c = buffer; NUM:if (*c >= '0' && *c <= '9' || *c=='.'&&(*(c+1)>='0'&&*(c+1)<='9')) { for (d=c; *d; d++) { if (*d == '#') { *d = 0; inttoken=readint(d+1,readint(c,10)); if (*buffer == '-') inttoken = -inttoken; return(INTEGER); } if (*d == '.' || *d=='e' || *d=='E') { realtoken = strtod(buffer,&d); if (*d) return(NAME); /* bug in strtod, does not work! */ return(REAL); } } inttoken = readint(c,10); if (*buffer == '-') inttoken = -inttoken; return(INTEGER); } return(issymbol ? SYMBOL : NAME); } } /*==============================================================*/ flag inquotes; int quotelength; int outline; void outchar(unsigned x) { if (!cstrings) {fputc(x,stdout); return;} if (quotelength > 70) { fputs("\"\n",stdout); outline = lineno; quotelength = 0; inquotes = 0; } if (!inquotes) {fputc('"',stdout); inquotes = TRUE;} if (x == '\n') { fputs("\\n\"\n",stdout); quotelength = 0; inquotes = 0; return; } if (x > 126 || x < 32) { fprintf(stdout,"\\%03o",x&255); quotelength += 4; return; } if (x == '\\' || x == '"') {fputc('\\',stdout); quotelength++;} fputc(x,stdout); quotelength++; } void output(void *buf,int len) { if (cstrings) {while(len--) outchar(*(unsigned char *)buf++);} else fwrite((char *)buf,1,len,stdout); } flag neednl,needspace; void outword(char *buf) { if (needspace) { if (outline < lineno) {outchar('\n'); outline = lineno;} else outchar(' '); } output(buf,strlen(buf)); neednl = needspace = TRUE; } void writetoken(int t) { char *c,*e,buf[48]; switch(t) { case COMMENT: if (eps == 2 || eps && (*buffer=='#' || *(buffer+1)=='%' || *(buffer+1)=='!')) { if (neednl) outchar('\n'); output(buffer,strlen(buffer)); outchar('\n'); neednl = needspace = FALSE; outline = lineno; } return; case INTEGER: if (decode) { sprintf(buf,"%d",inttoken); outword(buf); return; } else if (inttoken >= -128 && inttoken < 128) { outchar(136); outchar(inttoken); } else if (inttoken >= -32768 && inttoken < 32768) { outchar(134); output((void *)&inttoken+2,2); } else {outchar(132); output(&inttoken,4);} break; case REAL: if (decode) { /* print it as short as possible, preserve decimal */ if (!realtoken) {outword("0."); return;} if (realtoken < 0) { outword("-"); needspace = FALSE; realtoken = -realtoken;} sprintf(buf,"%g",realtoken); for (c=buf; *c!='.' && *c!='e'; c++) if (!*c) {*c++='.'; *c = 0; break;} if (*buf=='0') outword(buf+1); else outword(buf); return; } {float r=realtoken; outchar(138); output(&r,4);} break; case STRING: if (decode || !encodestrings) { outchar('('); for (c = buffer, e = c+inttoken; c<e; c++) { if (*c=='\\' || *c=='(' || *c==')') outchar('\\'); outchar(*c); } outchar(')'); } else { if (inttoken <= 255) {outchar(142); outchar(inttoken);} else {outchar(143); output((void *)&inttoken+2,2);} output(buffer,inttoken); } break; case SYMBOL: outchar(buffer[0]); break; case NAME: if (!decode && (t=systemindex(buffer))>=0) {outchar(146); outchar(t);} else {outword(buffer); return;} break; case LITERALNAME: if (!decode && (t = systemindex(buffer))>=0) {outchar(145); outchar(t); break;} goto J0; case IMMEDIATENAME: outchar('/'); J0: outchar('/'); output(buffer,strlen(buffer)); neednl = needspace = TRUE; return; case BOOLEANFALSE: if (decode) {outword("false"); return;} outchar(141); outchar(0); break; case BOOLEANTRUE: if (decode) {outword("true"); return;} outchar(141); outchar(1); break; default: error("Unknown token type!"); return; } needspace = FALSE; neednl = TRUE; } /*==============================================================*/ void encodeit(void) { int i; outline = lineno; while (i = readtoken()) writetoken(i); } /*==============================================================*/ int main(int argc,char **argv) { int i; char *p; for (i=1; i<argc; i++) { if (argv[i][0]=='-' && argv[i][1]) for (p=argv[i]+1; *p; p++) switch(*p) { case 'c': cstrings = TRUE; break; case 'd': decode = TRUE; break; case 'e': eps = TRUE; break; case 'E': eps = 2; break; case 's': encodestrings = TRUE; break; default: goto ERROR; } else break; } if (i >= argc) { ERROR: puts( " psencode: PostScript <-> DPS Binary Encoding translator\n" " Written by Bill Spitzak (SPITZAK@MCIMAIL.COM) June 1991\n" " This software is distributed FREE and may not be sold.\n" "\n" "psencode {-xxx} name.ps : translate, send to stdout\n" "\n" "switches:\n" "-c : produce C include file\n" "-d : decode / don't encode\n" "-e : (eps) preserve %% and # comments\n" "-E : preserve all comments\n" "-s : encode strings despite NeXT 2.0 bug\n" ); exit(1); } for (; i<argc; i++) { lineno = 1; if (!strcmp(argv[i],"-")) { infilename = "stdin"; infile = stdin; } else { infilename = argv[i]; infile = fopen(infilename,"r"); } if (!infile) {error(strerror(errno)); exit(1);} else encodeit(); } if (cstrings) { if (inquotes) fputs("\"\n",stdout); } else if (needspace) outchar('\n'); return(0); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.