#include "stdinc.h" #define cr(x) ((x) == 0) ? "\n\n" : "\n" static char *justword[] = { "L-just", "R-just" }; char *word (fle) int fle; { int i; char a[2]; static char buffer [81]; i = 0; while (read (fle, a, 1) == 1) { if (a[0] == ' ' || a[0] == '\n') { if (i != 0) break; } else buffer[i++] = a[0]; }; buffer [i] = 0; return buffer; } char *repeat (ch, nm) int ch, nm; { char buf [MAX_RPT]; buf[(nm = (nm < 0) ? 0 : nm)] = 0; for (nm--; nm >= 0; nm--) buf[nm] = ch; return buf; } pattern (whole, match, skip) char *whole, *match; int skip; { int i, j, m, w; m = strlen (match); w = strlen (whole); for (i = 0; i <= w-m; i++) { for (j = 0; match [j] != 0 && whole[i+j] == match[j]; j++) ; if (match[j] == 0) if (skip-- == 0) return i; }; return -1; } /* Encode and Eval perform base 10 to base 255 conversion, with a bottom value of 1 (As opposed to 0) for the base-255 numbers. Perfect for encoding BIG numbers (See chart) and storing them in 5 bytes on disk, eh? # of characters used______________Maximum integer representable 1 254 2 65024 3 16581374 4 4228250624 5 107820390900.... etc. */ long _eval (st, x) char *st; int x; { long int j; long int n; int a; j = 0; n = 1; while (x > 0) { a = st[--x]; a = fix (a); j += n * (a - 1); n *= 255; }; return j; } char *_encode (num, len) long int num; int len; { register int i; int a; static char buf[10]; len = (len < 9) ? len : 9; for (i = len-1; i >= 0; i--) { a = num % 255; num = (num - a) / 255; buf[i] = a + 1; }; buf[len] = 0; return buf; } main (argc, argv) int argc; char **argv; { char flds[384], lens[384], idxs[20][50]; char rel[80], temp[80], tmp2[80]; int stage, column, num_i, num_f, R; int n, i, fle, st, dups, s, r_len, isright; if (argc != 2) { printf ("%s: Format = '%s%s%s schema.s'\n", argv[0], BOLD, argv[0], NORM); exit (1); }; n = strlen (argv[1]); if (argv[1][n-1] != 's' || argv[1][n-2] != '.') strcat (argv[1], ".s"); sprintf (flds, "|"); sprintf (rel, "%s", argv[1]); sprintf (lens, ""); for (i = strlen(argv[1])-1; i > -1 && argv[1][i] != ':' && argv[1][i] != '/'; i--); r_len = rel[i+1] = 0; if ((fle = open (argv[1], O_RDONLY)) == -1) { fprintf (stderr, "\nCannot open %s%s%s.\n", BOLD, argv[1], NORM); exit (1); }; skip (fle, "relation"); sprintf (temp, "%s", word (fle)); if (strlen (temp) == 0) { fprintf (stderr, "\nFile %s%s%s holds no schema definition.\n", BOLD, argv[1], NORM); exit (1); }; printf ("%s", CLS); printf ("Building relation %s%s%s", BOLD, temp, NORM); if (rel[0] != 0) printf (" under directory %s%s%s\n\n", BOLD, rel, NORM); else printf (" under current directory\n\n"); sprintf (rel, "%s%s.rel", rel, temp); num_f = num_i = 0; column = stage = 1; printf ("%s%-60.60s%s\n", UNDR, "Fields", NORM); do { sprintf (temp, "%s", word (fle)); if (strcmp (temp, "field") == 0) { if (stage == 2) { fprintf (stderr, "%sField %s%s%s declared after indicies.\n", cr (column), BOLD, word (fle), NORM); exit (1); }; sprintf (temp, "%s", word (fle)); if (temp [strlen(temp)-1] == '|') temp[strlen(temp)-1] = 0; sprintf (tmp2, "|%s|", temp); if (pattern (flds, tmp2, 0) != -1) { fprintf (stderr, "%sField %s%s%s declared twice.\n", cr (column), BOLD, temp, NORM); exit (1); }; strcat (flds, temp); strcat (flds, "|"); skip (fle, "length"); sprintf (tmp2, "%03s", word (fle)); strcat (lens, tmp2); if ((isright = skip (fle, "right")) == 1) strcat (lens, "r|"); else { strcat (lens, "l|"); skip (fle, "left"); }; r_len += atoi (tmp2) + 1; sprintf (temp, "%s [%d] %s", temp, atoi (tmp2), justword[isright]); if ((column = 1-column) == 0) printf ("%s%-30.30s%s", SUBD, temp, NORM); else printf ("%s%s%s\n", SUBD, temp, NORM); num_f ++; if (skip (fle, ";") == 1) { do sprintf (temp, "%s", word (fle)); until (strcmp (temp, ";") == 0 || temp[0] == 0); if (temp[0] == 0) { printf ("%s", cr (column)); endoffile (num_f, num_i); stage = 3; }; }; } else if (strcmp (temp, "index") == 0) { if (stage == 1) { if (column == 0) printf ("\n"); if (num_f == 0) { fprintf (stderr, "\nNo fields declared before indicies.\n"); exit (1); }; printf ("\n%s%-60.60s%s\n", UNDR, "Indicies", NORM); stage = 2; column = 1; }; skip (fle, "on"); sprintf (temp, "%s", word (fle)); if (temp[strlen(temp)-1] == '|') temp[strlen(temp)-1] = 0; printf ("%s%s%s%s", SUBD, temp, NORM, repeat ('.', 36-strlen (temp))); dups = 0; if (skip (fle, "with") == 1) { if (skip (fle, "duplicates") == 0) { fprintf (stderr, "?\n\nIncorrect syntax\n"); exit (1); } else { printf ("Duplicates allowed\n"); dups = 1; }; } else printf ("Duplicates not allowed\n"); strcat (temp, "|"); sprintf (tmp2, "%s", ""); s = idxs[num_i][0] = 0; while (temp[s] != 0) { for (i = s, tmp2[0] = '|'; temp[i] != '|'; i++) tmp2 [i-s+1] = temp [i]; tmp2[i-s+1] = '|'; tmp2[i-s+2] = 0; s = i+1; if ((i = pattern (flds, tmp2, 0)) == -1) { sprintf (temp, "%s", &tmp2[1]); temp[strlen(temp)-1] = 0; fprintf (stderr, "\nField %s%s%s undefined\n", BOLD, temp, NORM); exit (1); }; for (st = 0, i++; i >= 0; i--) if (flds[i] == '|') st++; sprintf (tmp2, "%03d|", st); strcat (idxs[num_i], tmp2); }; if (dups == 1) strcat (idxs[num_i], "d"); num_i ++; if (skip (fle, ";") == 1) { do sprintf (temp, "%s", word (fle)); until (strcmp (temp, ";") == 0 || temp[0] == 0); if (temp[0] == 0) { printf ("%s", cr (column)); endoffile (num_f, num_i); stage = 3; }; }; } else if (strcmp (temp, "end") == 0 || temp[0] == 0) { printf ("%s", cr (column)); endoffile (num_f, num_i); stage = 3; } else { fprintf (stderr, "%sIdentifier %s%s%s not recognized.\n", cr (column), BOLD, temp, NORM); exit (1); }; } while (stage != 3); R = open (rel, O_RDWR); if (R != -1) { if (read (R, temp, 1) != -1) if (temp[0] != 1) { fprintf (stderr, "\n%s%s%32.32s%-28.28s%s\n", SUBD, INVR, "*** ERR", "OR ***", NORM); fprintf (stderr, "\n This relation is busy. It cannot be"); fprintf (stderr, " built during use.\n\n"); close (R); exit (1); }; printf ("%s%s%32.32s%-28.28s%s\n", SUBD, INVR, "** WARN", "ING **", NORM); printf ("\n The file about to be created already exists under the\n"); printf (" target directory! This data will be lost!\n\n"); close (R); }; printf ("Continue with the creation of the relation [Y/n] ? "); i = getchar (); printf ("\n"); if (i == 'n' || i == 'N' || i == 'q' || i == 'Q') exit (0); remove (rel); if ((R = open (rel, O_RDWR | O_CREAT)) == -1) { fprintf (stderr, "\n\nCannot open relation -- Aborted\n"); exit (-1); }; #ifdef UNIX sprintf (temp, "chmod 755 %s", rel); system (temp); #endif write (R, _encode (0, 1), 1); write (R, _encode (num_i, 1), 1); write (R, _encode (r_len, 2), 2); for (i = 0; i < num_i; i++) write (R, _encode (0, 4), 4); write (R, ".\001\001\001\001.\n", 7); write (R, lens, strlen(lens)); write (R, "\n", 1); for (i = 0; i < num_i; i++) { write (R, idxs[i], strlen (idxs[i])); write (R, "\n", 1); }; close (R); printf ("Relation created -- zero entries.\n"); } skip (f, s) /* 0 means didn't skip the word, 1 means we did. */ int f; char *s; { int i; char a[2]; i = 0; while (s[i] != 0) { if (read (f, a, 1) != 1) return -1; if (i != 0 || (i == 0 && a[0] != ' ' && a[0] != '\n')) { if (s[i] != a[0]) { lseek (f, -1, 1); break; } else i++; }; } if (s[i] == 0) return 1; return 0; } endoffile (num_f, num_i) int num_f, num_i; { if (num_f == 0) { fprintf (stderr, "No fields declared before end reached\n"); exit (1); }; if (num_i == 0) { fprintf (stderr, "No indicies declared before end reached\n"); exit (1); }; }