/* Copyright (c) Xerox Corporation 1993. All rights reserved. */ /* tread.c -- Low-level Tioga reader routines. David Nichols December, 1990 */ #include <stdio.h> /* for NULL */ #include <ctype.h> #include "tioga.h" #include "tread.h" #define TRUE 1 #define FALSE 0 extern char *malloc(); extern char *realloc(); long GetLength(); char *strsav(); unsigned char trailerID[] = { 0205, 0227 }; unsigned char commentID[] = { 0, 0 }; unsigned char controlID[] = { 0235, 0312 }; tread←Init(r, buf, len, procs, data) struct tread←Reader *r; char *buf; long len; struct tread←Procs *procs; char *data; { unsigned char *p; unsigned char *ubuf = (unsigned char *)buf; long propLen, textLen, commentLen, totalControlLen, totalSize; r->procs = procs; r->data = data; r->buf = buf; r->totalLen = len; /* Find the three main parts and verify that the lengths are ok. */ p = ubuf + len - tioga←TrailerLen; if (CheckID(&p, trailerID) < 0) return -1; propLen = GetLength(&p); textLen = GetLength(&p); totalSize = GetLength(&p); if (totalSize != len || propLen > len || textLen > len) return -1; p = ubuf + textLen; if (CheckID(&p, commentID) < 0) return -1; commentLen = GetLength(&p); p = ubuf + textLen + commentLen; if (CheckID(&p, controlID) < 0) return -1; totalControlLen = GetLength(&p); if (len != textLen + commentLen + totalControlLen) return -1; /* Find start and end of each section of the file. */ r->text.next = ubuf; r->text.limit = r->text.next + textLen; r->com.next = ubuf + textLen + tioga←CommentHeaderLen; r->com.limit = ubuf + textLen + commentLen; r->control.next = ubuf + textLen + commentLen + tioga←ControlHeaderLen; r->control.limit = ubuf + len - tioga←TrailerLen; /* Other reader state initialization. */ r->strLen = 0; r->str = NULL; /* First format is the null format. */ r->nFormats = 1; r->formats[0] = NULL; /* First look is the empty look. */ r->nLooks = 1; r->looks[0] = 0; /* First property is NIL. */ r->nProps = 1; r->props[0] = NULL; /* Preload system atoms. */ tread←AddProp(r, "prefix"); tread←AddProp(r, "postfix"); return 0; } static int CheckID(pp, id) unsigned char **pp; unsigned char *id; { unsigned char *s = *pp; int ok = TRUE; int i; for (i = 0; i < tioga←IDLen; ++i) { if (*s++ != *id++) ok = FALSE; } *pp = s; return ok ? 0 : -1; } /* Get next opcode from file. */ enum tioga←ControlOp tread←GetOp(r) struct tread←Reader *r; { if (r->control.next < r->control.limit) return (enum tioga←ControlOp) *r->control.next++; else return endOfFile; } static int EnsureStrLen(r, len) struct tread←Reader *r; long len; { if (r->strLen == 0) { r->strLen = len; r->str = (unsigned char *) malloc(len); } else if (len > r->strLen) { r->strLen = len; r->str = (unsigned char *) realloc(r->str, r->strLen); } if (r->str == NULL) { tioga←Error("Out of memory.\n"); return -1; } return 0; } /* Get text from control stream. */ tread←GetStr(r) struct tread←Reader *r; { long len = *r->control.next++; return tread←SGetRope(r, &r->control, len); } /* Get text from a specific stream. */ tread←SGetRope(r, s, len) struct tread←Reader *r; struct tread←Stream *s; long len; { long i; if (EnsureStrLen(r, len + 1) < 0) return -1; for (i = 0; i < len; ++i) { if (s->next >= s->limit) { tioga←Error("Rope too long.\n"); return -1; } r->str[i] = *s->next++; } r->str[len] = 0; return 0; } /* Add a new format, and return its index. */ int tread←AddFormat(r, format) struct tread←Reader *r; char *format; { int i; /* Index zero reserved for null format. */ if (format == NULL || format[0] == 0) return 0; for (i = 1; i < r->nFormats; ++i) { if (strcmp(r->formats[i], format) == 0) return i; } if (r->nFormats < tioga←NumFormats) { r->formats[r->nFormats] = strsav(format); ++r->nFormats; return r->nFormats - 1; } else { tioga←Error("Too many formats.\n"); return 0; } } /* Add a new looks vector, and return its index. */ int tread←AddLooks(r, l) struct tread←Reader *r; long l; { int i; /* Index zero reserved for empty looks. */ if (l == 0) return 0; for (i = 1; i < r->nLooks; ++i) { if (r->looks[i] == l) return i; } if (r->nLooks < tioga←NumLooks) { r->looks[r->nLooks] = l; ++r->nLooks; return r->nLooks - 1; } else { tioga←Error("Too many looks.\n"); return 0; } } /* Add a new property name, and return its index. */ int tread←AddProp(r, propName) struct tread←Reader *r; char *propName; { int i; char *p; /* Index zero reserved for NIL. */ if (propName == NULL || propName[0] == 0) return 0; for (i = 1; i < r->nProps; ++i) { if (strcmp(r->props[i], propName) == 0) return i; } if (r->nProps < tioga←NumProps) { r->props[r->nProps] = strsav(propName); for (p = r->props[r->nProps]; *p != 0; ++p) { /* Can't use tolower due to ATK problems. */ if ('A' <= *p && *p <= 'Z') *p = *p - 'A' + 'a'; } ++r->nProps; return r->nProps - 1; } else { tioga←Error("Too many properties..\n"); return 0; } } /* Get a byte from the control stream. */ int tread←GetByte(r) struct tread←Reader *r; { if (r->control.next < r->control.limit) return *r->control.next++; return 0; } /* Get an integer from the control stream. */ long tread←GetInt(r) struct tread←Reader *r; { long result = 0; int nBits = 0; while (*r->control.next & 0x80) { result |= (*r->control.next++ & 0x7f) << nBits; nBits += 7; } result |= (*r->control.next++ & 0x7f) << nBits; return result; } static long GetLength(pp) unsigned char **pp; { unsigned char *s = *pp; long result = 0; result |= *s++ << 8; result |= *s++; result |= *s++ << 24; result |= *s++ << 16; *pp = s; return result; } /* Allocate a copy of s and return it. */ char *strsav(s) char *s; { char *p = malloc(strlen(s)+1); if (p == NULL) return NULL; strcpy(p, s); return p; }