BSD 4_3 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 26 Aug 1985 19:19:52 +0000 (11:19 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 26 Aug 1985 19:19:52 +0000 (11:19 -0800)
Work on file usr/contrib/B/src/bed/gram.c
Work on file usr/contrib/B/src/bed/help.c

Synthesized-from: CSRG/cd1/4.3

usr/contrib/B/src/bed/gram.c [new file with mode: 0644]
usr/contrib/B/src/bed/help.c [new file with mode: 0644]

diff --git a/usr/contrib/B/src/bed/gram.c b/usr/contrib/B/src/bed/gram.c
new file mode 100644 (file)
index 0000000..56e5274
--- /dev/null
@@ -0,0 +1,400 @@
+/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+static char rcsid[] = "$Header: gram.c,v 2.5 85/08/22 16:03:16 timo Exp $";
+
+/*
+ * B editor -- All routines referencing the grammar table are in this file.
+ */
+
+#include "b.h"
+#include "feat.h"
+#include "bobj.h"
+#include "node.h"
+#include "gram.h"
+#include "supr.h"
+#include "tabl.h"
+
+extern bool dflag;
+
+#include <ctype.h>
+
+
+/*
+ * Test whether sym is in the given class.
+ */
+
+Visible bool
+isinclass(sym, ci)
+       register int sym;
+       struct classinfo *ci;
+{
+       register classptr cp;
+
+       Assert(ci && ci->c_class);
+       if (sym == Hole)
+               return !isinclass(Optional, ci);
+       for (cp = ci->c_class; *cp; ++cp)
+               if (sym == *cp)
+                       return Yes;
+       return No;
+}
+
+
+/*
+ * Deliver the representation array for the given node.
+ * If the node is actually just a "text" value, construct
+ * one in static storage -- which is overwritten at each call.
+ * In this case there are two deficiencies: the next call to
+ * noderepr which uses the same feature overwrites the reply
+ * value of the previous call, AND if the text value itself
+ * is changed, the representation may change, too.
+ * In practical use this is no problem at all, however.
+ */
+
+Visible string *
+noderepr(n)
+       register node n;
+{
+       register int sym;
+
+       if (n && Type(n) == Tex) {
+               static string buf[2];
+               buf[0] = Str((value)n);
+               return buf;
+       }
+       sym = symbol(n);
+       return table[sym].r_repr;
+}
+
+
+/*
+ * Deliver the prototype node for the given symbol.
+ */
+
+Visible node
+gram(sym)
+       register int sym;
+{
+       Assert(sym == 0 || sym > 0 && sym < TABLEN && table[sym].r_symbol);
+       return table[sym].r_node;
+}
+
+#ifdef SAVEBUF
+
+/*
+ * Deliver the name of a symbol.
+ */
+
+Visible string
+symname(sym)
+       int sym;
+{
+       static char buf[20];
+
+       if (sym >= 0 && sym < TABLEN && table[sym].r_name)
+               return table[sym].r_name;
+       sprintf(buf, "%d", sym);
+       return buf;
+}
+
+
+/*
+ * Find the symbol corresponding to a given name.
+ * Return -1 if not found.
+ */
+
+Visible int
+nametosym(str)
+       register string str;
+{
+       register int sym;
+       register string name;
+
+       for (sym = 0; sym < TABLEN; ++sym) {
+               name = table[sym].r_name;
+               if (name && Strequ(name, str))
+                       return sym;
+       }
+       return -1;
+}
+
+#endif SAVEBUF
+
+/*
+ * Test whether `sym' may replace the node in the path `p'.
+ */
+
+Visible bool
+allowed(p, sym)
+       register path p;
+       register int sym;
+{
+       register path pa = parent(p);
+       register int ich = ichild(p);
+       register int sympa = pa ? symbol(tree(pa)) : Rootsymbol;
+
+       Assert(sympa >= 0 && sympa < TABLEN && ich > 0 && ich <= MAXCHILD);
+       return isinclass(sym, table[sympa].r_class[ich-1]);
+}
+
+
+/*
+ * Initialize (and verify) the grammar table.
+ */
+
+Visible Procedure
+initgram()
+{
+       register int sym;
+       register int nch;
+       register struct classinfo **cp;
+       register struct classinfo *sp;
+       node ch[MAXCHILD];
+
+#ifndef NDEBUG
+       if (dflag)
+               fprintf(stderr, "*** initgram();\n\r");
+#endif NDEBUG
+       /* Set the node pointers in the table and check the representations.
+          The code assumes Optional and Hole are the last
+          symbols in the table, i.e. the first processed by the loop. */
+
+       for (sym = TABLEN-1; sym >= 0; --sym) {
+               if (table[sym].r_symbol != sym) {
+                       if (sym != Hole && sym != Optional && table[sym].r_symbol == 0)
+                               continue; /* Disabled table entry */
+                       syserr("initgram: table order (%s=%d, should be %d)",
+                               table[sym].r_name, table[sym].r_symbol, sym);
+               }
+               cp = table[sym].r_class;
+               for (nch = 0; nch < MAXCHILD && (sp = cp[nch]); ++nch)
+                       ch[nch] =
+                               table[sp->c_class[0] == Optional ?
+                                       Optional : Hole].r_node;
+               table[sym].r_node = newnode(nch, sym, ch);
+               fix((value) table[sym].r_node);
+       }
+
+       initcodes();
+#ifdef USERSUGG
+       initclasses();
+#endif USERSUGG
+}
+
+
+#ifdef USERSUGG
+
+/*
+ * Add built-in commands to the suggestion tables.
+ */
+
+Hidden Procedure
+initclasses()
+{
+       register int i;
+       register int j;
+       register struct table *tp;
+
+       for (i = 0; i < TABLEN; ++i) {
+               tp = &table[i];
+               if (tp->r_symbol != i || i == Suggestion)
+                       continue; /* Dead entry */
+               for (j = 0; j < MAXCHILD && tp->r_class[j]; ++j) {
+                       if (isinclass(Suggestion, tp->r_class[j]))
+                               makesugg(tp->r_class[j]->c_class);
+               }
+       }
+}
+
+
+/*
+ * Extract suggestions from class list.
+ */
+
+Hidden Procedure
+makesugg(cp)
+       classptr cp;
+{
+       struct table *tp;
+       string *rp;
+       char buffer[1000];
+       string bp;
+       string sp;
+       int i;
+       int nch;
+
+       for (; *cp; ++cp) {
+               if (*cp >= TABLEN || *cp < 0)
+                       continue;
+               tp = &table[*cp];
+               rp = tp->r_repr;
+               if (rp[0] && isupper(rp[0][0])) {
+                       bp = buffer;
+                       nch = nchildren(tp->r_node);
+                       for (i = 0; i <= nch; ++i) {
+                               if (rp[i]) {
+                                       for (sp = rp[i]; *sp >= ' '; ++sp)
+                                               *bp++ = *sp;
+                               }
+                               if (i < nch && !isinclass(Optional, tp->r_class[i]))
+                                       *bp++ = '?';
+                       }
+                       if (bp > buffer) {
+                               *bp = 0;
+                               addsugg(buffer, Yes);
+                       }
+               }
+       }
+}
+
+#endif USERSUGG
+
+
+/*
+ * Compaction scheme for characters to save space in grammar tables
+ * by combining characters with similar properties (digits, l.c. letters).
+ */
+
+#define RANGE 128 /* ASCII characters are in {0 .. RANGE-1} */
+
+Visible char code_array[RANGE];
+Visible char invcode_array[RANGE];
+Visible int lastcode;
+
+Hidden Procedure
+initcodes()
+{
+       register int c;
+
+       code_array['\n'] = ++lastcode;
+       invcode_array[lastcode] = '\n';
+       for (c = ' '; c <= '0'; ++c) {
+               code_array[c] = ++lastcode;
+               invcode_array[lastcode] = c;
+       }
+       for (; c <= '9'; ++c)
+               code_array[c] = lastcode;
+       for (; c <= 'a'; ++c) {
+               code_array[c] = ++lastcode;
+               invcode_array[lastcode] = c;
+       }
+       for (; c <= 'z'; ++c)
+               code_array[c] = lastcode;
+       for (; c < RANGE; ++c) {
+               code_array[c] = ++lastcode;
+               invcode_array[lastcode] = c;
+       }
+}
+
+
+/*
+ * Set the root of the grammar to the given symbol.  It must exist.
+ */
+
+Visible Procedure
+setroot(name)
+       string name;
+{
+       register int k;
+       register int i;
+
+       for (k = 1; k < TABLEN; ++k) {
+               if (table[k].r_name && Strequ(name, table[k].r_name)) {
+                       table[Rootsymbol].r_symbol = table[k].r_symbol;
+                       table[Rootsymbol].r_name = table[k].r_name;
+                       for (i = 0; i < MAXCHILD; ++i) {
+                               table[Rootsymbol].r_repr[i] = table[k].r_repr[i];
+                               table[Rootsymbol].r_class[i] = table[k].r_class[i];
+                       }
+                       table[Rootsymbol].r_repr[i] = table[k].r_repr[i];
+                       table[Rootsymbol].r_node = table[k].r_node;
+                       table[Rootsymbol].r_symbol = Rootsymbol;
+                       return;
+               }
+       }
+       syserr("Can't set root of grammar to <%s>", name);
+}
+
+
+/*
+ * The remainder of this file is specific for the currently used grammar.
+ */
+
+
+#include "boot.h" /* Has static data, so should be included only once! */
+#include "syms.h"
+
+Visible struct table *table = b_grammar;
+
+
+/*
+ * Table indicating which symbols are used to form lists of items.
+ * Consulted via predicate 'issublist' in "gram.c".
+ */
+
+Hidden classelem Asublists[] = {
+       E_plus, F_e_plus, 
+       And, And_kw, Or, Or_kw,
+       0,
+};
+
+Hidden struct classinfo sublists[] = {Asublists};
+
+
+/*
+ * Predicate telling whether two symbols can form lists together.
+ * This is important for list whose elements must alternate in some
+ * way, as is the case for [KEYWORD [expression] ]*.
+ *
+ * This code must be in this file, otherwise the names and values
+ * of the symbols would have to be made public.
+ */
+
+Visible bool
+samelevel(sym, sym1)
+       register int sym;
+       register int sym1;
+{
+       register int zzz;
+
+       if (sym1 == sym)
+               return Yes;
+       if (sym1 < sym)
+               zzz = sym, sym = sym1, sym1 = zzz; /* Ensure sym <= sym1 */
+       /* Now always sym < sym1 */
+       return sym == Kw_plus && sym1 == E_plus
+               || sym == F_kw_plus && sym1 == F_e_plus
+               || sym == And && sym1 == And_kw
+               || sym == Or && sym1 == Or_kw;
+}
+
+
+/*
+ * Predicate to tell whether a symbol can form chained lists.
+ * By definition, all right-recursive symbols can do so;
+ * in addition, those listed in the class 'sublists' can do
+ * it, too (this is used for lists formed of alternating members
+ * such as KW expr KW ...).
+ */
+
+Visible bool
+issublist(sym)
+       register int sym;
+{
+       register int i;
+       register string repr;
+
+       Assert(sym < TABLEN);
+       if (isinclass(sym, sublists))
+               return Yes;
+       repr = table[sym].r_repr[0];
+       if (Fw_positive(repr))
+               return No;
+       for (i = 0; i < MAXCHILD && table[sym].r_class[i]; ++i)
+               ;
+       if (i <= 0)
+               return No;
+       repr = table[sym].r_repr[i];
+       if (!Fw_zero(repr))
+               return No;
+       return isinclass(sym, table[sym].r_class[i-1]);
+}
diff --git a/usr/contrib/B/src/bed/help.c b/usr/contrib/B/src/bed/help.c
new file mode 100644 (file)
index 0000000..ed5ce7c
--- /dev/null
@@ -0,0 +1,125 @@
+/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
+static char rcsid[] = "$Header: help.c,v 2.6 85/08/22 16:03:38 timo Exp $";
+
+/*
+ * B editor -- Print help blurb.
+ */
+
+#include "feat.h"
+
+#ifdef HELPFUL
+
+#include "unix.h"
+
+#ifdef IBMPC
+#define getchar() getch()
+#endif IBMPC
+
+#ifdef SIGNAL
+#include <signal.h>
+#endif SIGNAL
+
+#ifdef SGTTY_H
+#include <sgtty.h>
+#endif SGTTY_H
+
+#include "b.h"
+
+string unixerror();
+
+#ifndef HELPBLURB
+#define HELPBLURB "/usr/new/lib/B/Bed_help"
+#endif
+
+#define SOBIT 0200
+
+extern int winheight;
+extern int llength;
+extern int winstart;
+
+
+/*
+ * Interrupt catcher while printing message.
+ */
+
+Hidden int intr;
+
+#ifdef SIGNAL
+Hidden Procedure
+stop()
+{
+       intr = Yes;
+       signal(SIGINT, stop);
+}
+#endif SIGNAL
+
+
+/*
+ * Print help blurb.
+ * This is done through the standard screen interface.
+ * An interrupt during the printing only stops the printing.
+ * The user must type [return] to continue.
+ */
+
+Visible bool
+help()
+{
+       FILE *fp;
+       string helpblurb;
+       char buffer[81];
+       int len = sizeof buffer;
+       string cp;
+#ifdef SIGNAL
+       int (*prevsig)();
+#endif SIGNAL
+#ifdef SGTTY_H
+       struct sgttyb tty;
+#endif SGTTY_H
+       int c;
+       
+       helpblurb = getenv("BED_HELP");
+       if (!helpblurb || !helpblurb[0])
+               helpblurb = HELPBLURB;
+       fp = fopen(helpblurb, "r");
+       if (!fp) {
+               error("Sorry, I can't help [%s]", unixerror(helpblurb));
+               return No;
+       }
+#ifdef SIGNAL
+       intr = No;
+       prevsig = signal(SIGINT, stop);
+#endif SIGNAL
+       if (llength < (sizeof buffer)-1)
+               len = llength+1;
+       while (!intr && fgets(buffer, len, fp)) {
+               cp = index(buffer, '\n');
+               if (cp)
+                       *cp = '\0';
+               trmputdata(winheight, winheight, 0, buffer);
+               trmscrollup(0, winheight, 1);
+               trmsync(winheight, 0);
+       }
+       fclose(fp);
+#ifdef SIGNAL
+       signal(SIGINT, prevsig);
+       if (intr)
+               trmundefined();
+               /* UNIX discards output when interrupted */
+               /* so output position is uncertain */
+#endif SIGNAL
+       trmputdata(winheight, winheight, 0, "");
+       strcpy(buffer, "Press [return] to continue");
+       for (cp = buffer; *cp; )
+               *cp++ |= SOBIT;
+       trmputdata(winheight, winheight, 0, buffer);
+       trmsync(winheight, cp - buffer);
+       c = getchar();
+       while (c != '\n' && c != '\r' && c != EOF) {
+               trmbell();
+               c = getchar();
+       }
+       trmputdata(winheight, winheight, 0, "");
+       winstart = winheight;
+       return Yes;
+}
+#endif HELPFUL