/* Copyright (C) 1991, Marcus J. Ranum. All rights reserved. */ #ifndef lint static char RCSid[] = "$Header: /usr/users/mjr/hacks/umud/DB/RCS/oif.c,v 1.3 91/08/19 16:21:51 mjr Exp $"; #endif /* configure all options BEFORE including system stuff. */ #include "config.h" #include <stdio.h> #include <varargs.h> /* WARNING - broken versions of printf may fail on large OIF objects the manual page for printf and fprintf says (on some machines - SunOs3.5 specifically) that fields longer than 128 get truncated. this would totally screw everything up, but the code has been tested with fields longer than BUFSIZ with no trouble at all. if you find yourself on a machine that has trouble with this, you'll need to unroll the fprintf()s into fputc()s. */ #include "mud.h" #include "sbuf.h" #ifdef COMPRESS_OIF /* Compression routines - lifted from TinyMUD and modified for use in Unter */ #include "comp.h" static int compress_on = 1; static char ctab[128][128]; /* the way in which compression is handled for toggling is gross, but this is necessary to make loaddb work. */ void comp_on(onoff) int onoff; { compress_on = onoff; } void comp_init() { int i; int j; for(i = 0; i < 128; i++) for(j = 0; j < 128; j++) ctab[i][j] = 0; for(i = 0; i < 128; i++) ctab[ctok[i][0]][ctok[i][1]] = i | 0x80; } /* VARARGS1 */ static int comp_len(va_alist) va_dcl { va_list ap; char c; char *p; char *nxp; int nomor = 0; int skipone = 0; char nxt; int size = 0; va_start(ap); while(1) { nxp = (char *)0; if(nomor) break; p = va_arg(ap,char *); if(p == (char *)0) break; looked_ahead: while(*p != '\0') { /* out of string? lookahead */ if((nxt = p[1]) == '\0') { nxp = va_arg(ap,char *); if(nxp != (char *)0) nxt = *nxp; else nomor++; } if((c = ctab[p[0]][nxt]) != '\0') { size++; /* looked ahead? */ if(nxp == (char *)0) p += 2; else { p++; skipone++; } } else { size++; p++; } } if(nxp != (char *)0) { p = nxp; nxp = (char *)0; if(skipone){ p++; skipone = 0; } goto looked_ahead; } } va_end(ap); return(size); } /* VARARGS1 */ comp_toFILE(fp,va_alist) FILE *fp; va_dcl { va_list ap; char c; char *p; char *nxp; int nomor = 0; int skipone = 0; char nxt; va_start(ap); while(1) { nxp = (char *)0; if(nomor) break; p = va_arg(ap,char *); if(p == (char *)0) break; looked_ahead: while(*p != '\0') { /* out of string? lookahead */ if((nxt = p[1]) == '\0') { nxp = va_arg(ap,char *); if(nxp != (char *)0) nxt = *nxp; else nomor++; } if((c = ctab[p[0]][nxt]) != '\0') { if(fputc(c,fp) == EOF) return(1); /* looked ahead? */ if(nxp == (char *)0) p += 2; else { p++; skipone++; } } else { if(fputc(*p,fp) == EOF) return(1); p++; } } if(nxp != (char *)0) { p = nxp; nxp = (char *)0; if(skipone){ p++; skipone = 0; } goto looked_ahead; } } va_end(ap); return(0); } static char * sbuf_fdecomp(s,f) FILE *f; Sbuf *s; { char c; if(f == (FILE *)0 || s == (Sbuf *)0 || ferror(f)) return((char *)0); sbuf_reset(s); while(1) { c = getc(f); if(feof(f) || ferror(f)) { if(s->bp == s->buf) return((char *)0); sbuf_put('\0',s); return(sbuf_buf(s)); } if(c == '\n') { sbuf_put('\0',s); return(sbuf_buf(s)); } if(c & 0x80) { sbuf_put(ctok[c & 0x7f][0],s); sbuf_put(ctok[c & 0x7f][1],s); } else sbuf_put(c,s); } } #endif /* Return the object size of the given object when in OIF format */ int oif_objsiz(o,n) Obj *o; char *n; { int ret = 0; int a; #ifdef COMPRESS_OIF if(compress_on) { ret = comp_len("object ",n,"\n",(char *)0); for(a = 0; a < o->ocnt; a++) ret += comp_len(o->oap[a],"\n",(char *)0); ret += comp_len("endobj\n",(char *)0); return(ret); } #endif /* otherwise "object " "endobj" + name length + 2 newlines */ ret = 15 + strlen(n); for(a = 0; a < o->ocnt; a++) ret += (strlen(o->oap[a]) + 1); return(ret); } /* oif an object to the given stream. */ oiftoFILE(o,f,nam) Obj *o; FILE *f; char *nam; { int a; #ifdef COMPRESS_OIF if(compress_on) { if(comp_toFILE(f,"object ",nam,"\n",(char *)0) == EOF) return(1); for(a = 0; a < o->ocnt; a++) if(comp_toFILE(f,o->oap[a],"\n",(char *)0) == EOF) return(1); if(comp_toFILE(f,"endobj\n",(char *)0) == EOF) return(1); return(0); } #endif if(fprintf(f,"object %s\n",nam) == EOF) return(1); for(a = 0; a < o->ocnt; a++) if(fprintf(f,"%s\n",o->oap[a]) == EOF) return(1); if(fputs("endobj\n",f) == EOF) return(1); if(ferror(f)) return(1); return(0); } /* read an oif object from the given stream. */ Obj * oiffromFILE(f,nbuf) FILE *f; char *nbuf; { Obj *ret = (Obj *)0; Sbuf suf; char *cp; sbuf_initstatic(&suf); /* read an "object..." line */ #ifdef COMPRESS_OIF if(compress_on) cp = sbuf_fdecomp(&suf,f); else #endif cp = sbuf_fgets(&suf,f); if(cp == (char *)0 || strncmp(cp,"object",6)) { #ifdef OIF_DEBUG if(cp != (char *)0) fprintf(stderr,"expected object header, got %s\n",cp); #endif sbuf_freestatic(&suf); return((Obj *)0); } /* if a name is given, take it */ if(cp[6] == ' ' && nbuf != (char *)0 && cp[7] != '\0') strncpy(nbuf,&cp[7],MAXOID); if((ret = objnew()) == (Obj *)0) { sbuf_freestatic(&suf); return((Obj *)0); } while(1) { sbuf_reset(&suf); #ifdef COMPRESS_OIF if(compress_on) cp = sbuf_fdecomp(&suf,f); else #endif cp = sbuf_fgets(&suf,f); if(cp == (char *)0) { #ifdef OIF_DEBUG if(cp != (char *)0) fprintf(stderr,"expected attr, got %s\n",cp); #endif objfree(ret); sbuf_freestatic(&suf); return((Obj *)0); } if(!strcmp(cp,"endobj")) { sbuf_freestatic(&suf); return(ret); } /* not the end of an object, and not too big, so stuff it */ if(objstuffattr(ret,cp,sbuf_len(&suf))) goto reject; } reject: objfree(ret); sbuf_freestatic(&suf); return((Obj *)0); } /* oif an object to the given string (with the given length) */ oiftoSTRING(o,buf,nam,len) Obj *o; char *buf; char *nam; int len; { int a; if( len < oif_objsiz(o,nam) ) return 1; strcpy(buf,"object "); strcat(buf,nam); strcat(buf,"\n"); for(a = 0; a < o->ocnt; a++) { strcat(buf,o->oap[a]); strcat(buf,"\n"); } strcat(buf,"endobj\n"); return(0); } /* read an oif object from the given string. */ Obj * oiffromSTRING(string,nbuf) char *string; char *nbuf; { Obj *ret = (Obj *)0; char *cp,*np; int len; if( !string ) return( (Obj *)0 ); if( strncmp(string,"object", 6 ) ) return( (Obj *)0 ); /* if a name is given, take it */ if(string[6] == ' ' && nbuf != (char *)0 && string[7] != '\0') { for( cp = &string[7], len = 0; *cp && len < MAXOID && *cp != '\n'; len++ ) *nbuf++ = *cp++; if( len < MAXOID ) *nbuf = '\0'; } else cp = &string[6]; cp = index(cp,'\n'); if( !cp ) /* error! No newline */ return( (Obj *)0 ); if((ret = objnew()) == (Obj *)0) return((Obj *)0); cp++; while(1) { /* * cp points to the beginning of the next "line" */ if(!strcmp(cp,"endobj\n")) return(ret); /* find out where the end of the line is */ np = index(cp,'\n'); np = index(cp,'\n'); if( !np ) /* no newline! */ goto reject; /* not the end of an object, and not too big, so stuff it */ if(objstuffattr(ret,cp,np-cp)) goto reject; cp = np+1; } reject: objfree(ret); return((Obj *)0); }