#include "defns.i" #include "extern.i" #define Space(s) (s == ' ' || s == '\t') #define SkipComment while ( ( c = getchar() ) != '\n' ) #define EndLine while ( getchar() != '\n' ) Boolean ReadType() /* -------- */ { char Delim; TypeInfo T; Delim = ReadName(Name); if ( ! *Name ) return false; else if ( Delim != ':' ) Error(1, Name); T = (TypeInfo) malloc(sizeof(struct _type_rec)); T->Name = CopyString(Name); T->NValues = 0; T->Value = Nil; do { while ( (Delim = ReadName(Name)) == '\n' ) ; if ( T->NValues % 100 == 0 ) { T->Value = (Const *) Resize(T->Value, (T->NValues + 100) * sizeof(Const)); } T->Value[ T->NValues++ ] = FindConstant(Name, false); } while ( Delim == ',' ); if ( Delim != '.' ) Error(2, Name, T->Name); EndLine; Type[++MaxType] = T; return true; } ReadTypes() /* --------- */ { int i, j; TypeInfo T; while ( ReadType() ) ; ForEach(i, 1, MaxType) { T = Type[i]; T->CollSeq = (short *) malloc((MaxConst+1) * sizeof(short)); ForEach(j, 0, MaxConst) { T->CollSeq[j] = 0; } ForEach(j, 0, T->NValues-1) { T->CollSeq[T->Value[j]] = j+1; } } } Tuple ReadTuple(R) /* --------- */ Relation R; { char c; int N, i; Tuple T; N = R->Arity; if ( (c = ReadName(Name)) == '.' || c == ';' ) return Nil; T = (Tuple) malloc((N+1) * sizeof(Const)); T[1] = FindConstant(Name, true); ForEach(i, 2, N) { c = ReadName(Name); T[i] = FindConstant(Name, true); } if ( c != ':' && c != '\n' ) ReadToEOLN; ForEach(i, 1, N) { if ( ! Type[R->Type[i]]->CollSeq[T[i]] ) Error(4, ConstName[T[i]], Type[R->Type[i]]->Name); } return T; } Tuple *ReadTuples(R, Plus) /* ---------- */ Relation R; Boolean Plus; { Tuple T, D[MAXTUPLES], *TheTuples; char c; int i, ND = 0; while ( T = ReadTuple(R) ) { if ( ND >= MAXTUPLES ) { printf("ERROR: more than %d %s tuples\nRecompile with larger MAXTUPLES\n", MAXTUPLES, Plus ? "positive" : "negative"); exit(); } T[0] = Plus ? PosMark : 0; D[ND++] = T; } TheTuples = (Tuple *) malloc((ND+1) * sizeof(Tuple)); ForEach(i, 0, ND-1) { TheTuples[i] = D[i]; } TheTuples[ND] = Nil; return TheTuples; } Relation ReadRelation() /* ------------ */ { Relation R; char Delim, c; int Key[100], NKeys = 0, i; if ( ReadName(Name) != '(' ) return Nil; R = (Relation) malloc(sizeof(struct _rel_rec)); R->Name = CopyString(Name); R->Arity = 0; do { Delim = ReadName(Name); R->Type[++R->Arity] = FindType(Name); } while ( Delim != ')' ); /* Read and store access keys */ do { do { c = getchar(); } while ( Space(c) ) ; if ( c != '\n' ) { Key[NKeys] = 0; ForEach(i, 1, R->Arity) { if ( c == '-' ) Key[NKeys] |= (1 << i); c = getchar(); } NKeys++; } } while ( c == '/'); R->NKeys = NKeys; if ( NKeys ) { R->Key = (int *) malloc(NKeys * sizeof(int)); memcpy(R->Key, Key, NKeys * sizeof(int)); } /*ReadToEOLN;*/ R->Pos = ReadTuples(R, true); if ( SectionDelim == '.' ) { R->Neg = R->Opt = Nil; } else { R->Neg = ReadTuples(R, false); } return R; } /******************************************************************/ /* */ /* Read a name into string s, returning terminating delimiter. */ /* - Embedded spaces are permitted, but multiple spaces are */ /* replaced by a single space. */ /* - Any character after a \ is a valid character. */ /* - The remainder of a line following '|' is ignored. */ /* */ /******************************************************************/ char ReadName(s) /* --------- */ char *s; { register char *Sp = s; register int c; /* Skip to first non-space character */ while ( ( c = getchar() ) == '|' || Space(c) ) if ( c == '|' ) SkipComment; /* Return period if no names to read */ if ( c == EOF ) { return (SectionDelim = '.'); } else if ( c == ';' || c == '.' ) { getchar(); return (SectionDelim = c); } /* Read in characters up to the next delimiter */ while ( c != ',' && c != '\n' && c != '|' && c != EOF && c != '(' && c != ')' && c != ':' && c != '.' ) { if ( c == '\\' ) c = getchar(); *Sp++ = c; if ( c == ' ' ) while ( ( c = getchar() ) == ' ' ); else c = getchar(); } if ( c == '|' ) { SkipComment; c = '\n'; } /* Strip trailing spaces */ while ( Space(*(Sp-1)) ) Sp--; *Sp++ = '\0'; return c; } /* Find a constant in the list of constants, using binary chop search */ Const FindConstant(N, MustBeThere) /* ------------ */ char *N; Boolean MustBeThere; { int i, Hi=MaxConst+1, Lo=0, Differ=1; while ( Lo < Hi-1 ) { Differ = strcmp(N, ConstName[SortedConst[i = (Hi + Lo)/2]]); if ( ! Differ ) return SortedConst[i]; else if ( Differ > 0 ) Lo = i; else Hi = i; } if ( MustBeThere ) Error(3, N); /* This is a new constant -- record it */ if ( MaxConst % 1000 == 0 ) { ConstName = (char **) Resize(ConstName, (MaxConst + 1000) * sizeof(char *)); SortedConst = (Const *) Resize(SortedConst, (MaxConst + 1000) * sizeof(int)); } MaxConst++; Lo++; for ( i = MaxConst ; i > Lo ; i-- ) { SortedConst[i] = SortedConst[i-1]; } SortedConst[Lo] = MaxConst; ConstName[MaxConst] = CopyString(N); return MaxConst; } /* Find a type by name */ int FindType(N) /* -------- */ char *N; { int i; TypeInfo T; ForEach(i, 1, MaxType) { if ( ! strcmp(N, Type[i]->Name) ) return i; } Error(5, N); } PrintTuples(N, TT, ShowClass) /* ----------- */ int N; Tuples TT; Boolean ShowClass; { if ( ! TT ) return; while ( *TT ) { printf("\t\t"); PrintTuple(*TT, N); if ( ShowClass ) { printf(": %c", (Positive(*TT) ? '+' : '-') ); } putchar('\n'); TT++; } } PrintTuple(C, N) /* ---------- */ Tuple C; int N; { int i; ForEach(i, 1, N) { printf("%s", ConstName[C[i]]); if ( i < N ) putchar(','); } } PrintLiteral(R, RSign, A) /* -------------- */ Relation R; Boolean RSign; Vars A; { int i, v; if ( ! RSign ) printf("~"); printf("%s", R->Name); ForEach(i, 1, R->Arity) { v = A[i]; printf("%c%c", (i > 1 ? ',' : '('), (v ? Variable[v] : '*')); } printf(")"); } PrintClause(R, C) /* --------------- */ Relation R; Clause C; { int Lit; Literal L; PrintLiteral(R, true, DefVars); for ( Lit = 0 ; (L = C[Lit]) ; Lit++ ) { if ( Lit == 0 ) { printf(" :- "); } else { printf(", "); } PrintLiteral(L->Rel, L->Sign, L->Args); } newline; } PrintDefinition(R) /* --------------- */ Relation R; { int Cl; Literal L; newline; for ( Cl = 0 ; R->Def[Cl] ; Cl++ ) { PrintClause(R, R->Def[Cl]); } } Number(T) /* ------ */ Tuple *T; { int Count = 0; if ( ! T ) return 0; while ( *T++ ) { Count++; } return Count; } /* Free up a bunch of tuples */ Discard(TT, TuplesToo) /* ------- */ Tuples TT; Boolean TuplesToo; { Tuple *P; if ( TuplesToo ) { for ( P = TT ; *P ; P++ ) { free(*P); } } free(TT); } char *CopyString(s) /* ---------- */ char *s; { char *new; int l; l = strlen(s) + 1; new = malloc(l); memcpy(new, s, l); return new; } Error(n, s1, s2) /* ----- */ int n; char *s1, *s2; { switch ( n ) { case 1: printf("Illegal delimiter after %s\n", s1); exit(); case 2: printf("Something wrong after %s in type %s\n", s1, s2); exit(); case 3: printf("Undeclared constant %s\n", s1); exit(); case 4: printf("Constant %s is not of type %s\n", s1, s2); exit(); case 5: printf("Undeclared type %s\n", s1); exit(); } }