home *** CD-ROM | disk | FTP | other *** search
- From: allbery@ncoast.UUCP (Brandon S. Allbery)
- Newsgroups: comp.sources.misc
- Subject: v02i037: UNIFY(r) Selection Preprocessor
- Message-ID: <7164@ncoast.UUCP>
- Date: 31 Jan 88 04:19:33 GMT
- Approved: allbery@ncoast.UUCP
-
- Comp.sources.misc: Volume 2, Issue 37
- Submitted-By: The Moderator <allbery@ncoast.UUCP>
- Archive-Name: usp
-
- I decided that as long as I was posting some of my UNIFY(r) stuff, I'd throw
- this in. This is a preprocessor for C programs which allows certain things
- to be done much more easily than usual: in particular, coding queries now
- uses a single unified syntax rather than having to choose between ten or so
- functions. It also allows you to specify literal dates and times and get the
- current date and time in a much more natural way. It also replaces the "upp"
- C preprocessor, although you must use USP syntax instead of upp. There is a
- man page in here describing the commands accepted by USP.
-
- Oh -- just in case anyone's interested, I wrote one of these (watered down a
- bit) for Informix 3.3. While it's watered down as far as selection ability,
- it at least builds all those blasted "struct dbview"s and such for you. It
- reduced a 14-page program to 4 pages (I kid you not!).
-
- #--------------------------------CUT HERE-------------------------------------
- #! /bin/sh
- #
- # This is a shell archive. Save this into a file, edit it
- # and delete all lines above this comment. Then give this
- # file to sh by executing the command "sh file". The files
- # will be extracted into the current directory owned by
- # you with default permissions.
- #
- # The files contained herein are:
- #
- # -rw-r--r-- 1 allbery users 378 Jan 30 20:59 Makefile
- # -rw-r--r-- 1 allbery users 7392 Jan 30 20:59 genpgm.c
- # -rw-r--r-- 1 allbery users 6043 Jan 30 20:59 usp.man
- # -rw-r--r-- 1 allbery users 11761 Jan 30 20:59 usp.y
- # -rw-r--r-- 1 allbery users 3438 Jan 30 20:59 usptok.l
- #
- echo 'x - Makefile'
- if test -f Makefile; then echo 'shar: not overwriting Makefile'; else
- sed 's/^X//' << '________This_Is_The_END________' > Makefile
- XSHELL = /bin/sh
- XCFLAGS = -O -I/appl/u32/include -DUNIFY32
- XYFLAGS = -d
- X
- XOBJ = usp.o usptok.o genpgm.o
- X
- Xusp: $(OBJ)
- X UNIFY=/appl/u32/lib PATH=/appl/u32/bin:$$PATH uld usp $(OBJ) -ll
- X
- Xusptok.o: y.tab.h
- Xy.tab.h usp.o: usp.y
- X
- Xtester: usp TESTER
- X DBPATH=/coesys/bin usp < TESTER > t1.c
- X cc -O -c t1.c
- X UNIFY=/appl/u32/lib PATH=/appl/u32/bin:$$PATH uld t1 t1.o
- X# DBPATH=/coesys/bin t1
- ________This_Is_The_END________
- if test `wc -l < Makefile` -ne 17; then
- echo 'shar: Makefile was damaged during transit (should have been 17 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - genpgm.c'
- if test -f genpgm.c; then echo 'shar: not overwriting genpgm.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > genpgm.c
- X#include <stdio.h>
- X#include <varargs.h>
- X#include <dbtypes.h>
- X
- Xextern FILE *yyin, *yyout;
- Xextern FILE *tmpfile();
- Xextern char *recname();
- Xextern char *fldsyn();
- Xextern char *fldname();
- Xextern char *strchr();
- X
- Xstatic FILE *htf = (FILE *) 0;
- Xstatic FILE *stf = (FILE *) 0;
- Xstatic char vname[] = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
- Xint nlflag = 1;
- Xstatic int diddate, dosync;
- Xchar *srcfile = "-";
- Xextern int indent, _ign_, yylineno;
- Xstatic int *typetab = (int *) 0;
- X
- X/*VARARGS PRINTFLIKE1*/
- Xputhead(va_alist)
- Xva_dcl {
- X char *fmt;
- X va_list args;
- X
- X va_start(args);
- X fmt = va_arg(args, char *);
- X vfprintf(htf, fmt, args);
- X va_end(args);
- X if (fmt[strlen(fmt) - 1] == '\n')
- X syncf(htf);
- X}
- X
- X/*VARARGS PRINTFLIKE1*/
- Xputsel(va_alist)
- Xva_dcl {
- X char *fmt;
- X va_list args;
- X static char buf[5120];
- X
- X va_start(args);
- X fmt = va_arg(args, char *);
- X vsprintf(buf, fmt, args);
- X va_end(args);
- X __emit(buf);
- X}
- X
- Xstatic __emit(buf)
- Xchar *buf; {
- X for (; *buf != '\0'; buf++) {
- X if (*buf == '\1') {
- X syncf(stf);
- X lead(indent);
- X continue;
- X }
- X putc(*buf, stf);
- X }
- X}
- X
- Xsyncf(fp)
- XFILE *fp; {
- X fprintf(fp, "#line %d", yylineno);
- X if (yyin != stdin)
- X fprintf(fp, " \"%s\"", srcfile);
- X putc('\n', fp);
- X}
- X
- Xstatic lead(cnt) {
- X while (cnt > 8) {
- X putc('\t', stf);
- X cnt -= 8;
- X }
- X while (cnt-- > 0)
- X putc(' ', stf);
- X}
- X
- Xdumpf(fp, dest)
- XFILE *fp, *dest; {
- X int ch;
- X
- X yyin = fp;
- X nlflag = 1;
- X diddate = 0;
- X dosync = 1;
- X if (typetab != (int *) 0) {
- X free((char *) typetab);
- X typetab = 0;
- X }
- X if (htf == (FILE *) 0 && (htf = tmpfile()) == (FILE *) 0) {
- X yyerror("can't open temp file for header");
- X exit(2);
- X }
- X fprintf(htf, "static int __i__er_ = 0;\n");
- X if (stf == (FILE *) 0 && (stf = tmpfile()) == (FILE *) 0) {
- X yyerror("can't open temp file for code");
- X exit(2);
- X }
- X while ((ch = input()) != 0) {
- X if (ch == '$') {
- X if (nlflag && indent == 0) {
- X indent = 1; /* '$' == space for output */
- X if ((ch = input()) != '\t')
- X putc(' ', stf);
- X while (ch == ' ' || ch == '\t') {
- X putc(ch, stf);
- X ch = input();
- X }
- X unput(ch);
- X _ign_ = 1;
- X yyparse();
- X _ign_ = 0;
- X nlflag = 0;
- X dosync = 1;
- X }
- X else { /* embedded record/field ref */
- X char vbuf[256];
- X int cnt;
- X char *cp;
- X
- X cnt = 0;
- X nlflag = 0;
- X while ((ch = input()) != 0 && strchr(vname, ch) != (char *) 0)
- X vbuf[cnt++] = ch;
- X if (cnt == 0 && ch == '(') {
- X parsedate();
- X continue;
- X }
- X unput(ch);
- X if (cnt == 0) {
- X putc('$', stf);
- X continue;
- X }
- X vbuf[cnt] = '\0';
- X for (cnt = numrecs(); cnt > 0; cnt--) {
- X if ((cp = recname(cnt)) == (char *) 0)
- X continue;
- X else if (strcmp(cp, vbuf) == 0)
- X break;
- X }
- X if (cnt != 0) {
- X fprintf(stf, "%d", cnt);
- X continue;
- X }
- X for (cnt = numflds(); cnt > 0; cnt--) {
- X if ((cp = fldname(cnt)) == (char *) 0)
- X continue;
- X else if (strcmp(cp, vbuf) == 0)
- X break;
- X }
- X if (cnt != 0)
- X fprintf(stf, "%d", cnt);
- X else {
- X yyerror("unrecognized record/field name `%s'", vbuf);
- X fputs(vbuf, stf);
- X }
- X }
- X }
- X else {
- X if (ch != '\n' && ch != ' ' && ch != '\t')
- X nlflag = 0;
- X else if (ch == '\n') {
- X indent = 0;
- X nlflag = 1;
- X }
- X putc(ch, stf);
- X if (dosync && ch == '\n') {
- X syncf(stf);
- X dosync = 0;
- X }
- X }
- X }
- X rewind(htf);
- X rewind(stf);
- X while ((ch = getc(htf)) != EOF)
- X putc(ch, dest);
- X putc('\n', dest);
- X while ((ch = getc(stf)) != EOF)
- X putc(ch, dest);
- X fclose(htf);
- X fclose(stf);
- X htf = (FILE *) 0;
- X stf = (FILE *) 0;
- X}
- X
- Xmain(argc, argv)
- Xchar **argv; {
- X char fname[1024];
- X FILE *inf, *outf;
- X int arg, len;
- X
- X srcfile = "-";
- X if (argc < 2)
- X dumpf(stdin, stdout);
- X else
- X for (arg = 1; argv[arg] != (char *) 0; arg++) {
- X strcpy(fname, argv[arg]);
- X len = strlen(fname);
- X if (fname[len - 2] == '.' && fname[len - 1] == 'c')
- X strcpy(fname + len - 1, "usp.c");
- X else
- X strcat(fname, ".c");
- X if ((inf = fopen(argv[arg], "r")) == (FILE *) 0) {
- X perror(argv[arg]);
- X continue;
- X }
- X if ((outf = fopen(fname, "w")) == (FILE *) 0) {
- X perror(fname);
- X fclose(inf);
- X continue;
- X }
- X srcfile = argv[arg];
- X dumpf(inf, outf);
- X fclose(inf);
- X fclose(outf);
- X }
- X exit(0);
- X}
- X
- Xchar *utype(type, len) {
- X static char buf[256];
- X
- X switch (type) {
- X case INT:
- X case DATE:
- X case HR:
- X strcpy(buf, "short %s");
- X break;
- X case LONG:
- X case AMT:
- X strcpy(buf, "long %s");
- X break;
- X case HAMT:
- X case FLT:
- X strcpy(buf, "double %s");
- X break;
- X case STRNG:
- X len++;
- X case COMB:
- X typeset(len);
- X sprintf(buf, "_str_%d %%s", len);
- X break;
- X }
- X return buf;
- X}
- X
- X/*
- X * Make an entry in the typeset table. Do nothing if it's in there already.
- X */
- X
- Xtypeset(len) {
- X int cnt;
- X
- X for (cnt = 0; typetab != (int *) 0 && typetab[cnt] != 0; cnt++)
- X if (typetab[cnt] == len)
- X return;
- X cnt += 2;
- X if ((typetab = (int *) (typetab == (int *) 0? malloc(cnt * sizeof (int)): realloc(typetab, cnt * sizeof (int)))) == (int *) 0) {
- X yyerror("out of memory for defined type table");
- X exit(1);
- X }
- X typetab[cnt - 2] = len;
- X typetab[cnt - 1] = 0;
- X puthead("typedef char _str_%d[%d];\n", len, len);
- X}
- X
- X/*
- X * input() next call will start a date, to a ')'. Parse the date, eat the
- X * ')', and output the internal (short) value of the date. `/' only.
- X * Actually, times are handled as well; the deciding factor is whether
- X * a '/' or a ':' is used.
- X *
- X * Three special cases: (nulldate), "hour", and "today". (I can't specify
- X * nulldate's form in a comment for obvious reasons; the string is the standard
- X * UNIFY one.)
- X */
- X
- Xparsedate() {
- X char dbuf[256], term[2];
- X int ch, cnt;
- X int date[3], ck[3];
- X short d;
- X
- X for (cnt = 0; (ch = input()) != 0 && ch != '\n' && ch != ')'; cnt++)
- X dbuf[cnt] = ch;
- X dbuf[cnt] = '\0';
- X if (ch != ')' || cnt == 0) {
- X yyerror("unterminated or empty date/time constant");
- X fprintf(stf, "$(%s", dbuf);
- X return;
- X }
- X if (strcmp(dbuf, "**/**/**") == 0) {
- X fprintf(stf, "%d", NULLDATE);
- X return;
- X }
- X if (strcmp(dbuf, "today") == 0) {
- X fprintf(stf, "(_u__now = time((long *) 0), _u__date = localtime(&_u__now), _u__today[0] = _u__date->tm_mon + 1, _u__today[1] = _u__date->tm_mday, _u__today[2] = _u__date->tm_year, kday(_u__today))");
- X if (!diddate)
- X puthead("#include <time.h>\nstatic int _u__today[3];\nstatic long _u__now;\nstatic struct tm *_u__date;\n");
- X diddate = 1;
- X return;
- X }
- X if (strcmp(dbuf, "hour") == 0) {
- X fprintf(stf, "(_u__now = time((long *) 0), _u__date = localtime(&_u__now), _u__date->tm_hour * 100 + _u__date->tm_min)");
- X if (!diddate)
- X puthead("#include <time.h>\nstatic int _u__today[3];\nstatic long _u__now;\nstatic struct tm *_u__date;\n");
- X diddate = 1;
- X return;
- X }
- X dbuf[cnt++] = ')'; /* hack for sscanf checking */
- X dbuf[cnt] = '\0';
- X if ((cnt = sscanf(dbuf, "%d:%d%[)]", &date[0], &date[1], term)) == 3) {
- X if (date[0] < 0 || date[0] > 23) {
- X yyerror("syntax error in time/hour");
- X fprintf(stf, "$(%s", dbuf);
- X return;
- X }
- X if (date[1] < 0 || date[1] > 59) {
- X yyerror("syntax error in time/minute");
- X fprintf(stf, "$(%s", dbuf);
- X return;
- X }
- X fprintf(stf, "%d", date[0] * 100 + date[1]);
- X return;
- X }
- X if ((cnt = sscanf(dbuf, "%d/%d/%d%[)]", &date[0], &date[1], &date[2], term)) != 4) {
- X yyerror("syntax error in date (section %d)", cnt);
- X fprintf(stf, "$(%s", dbuf);
- X return;
- X }
- X d = kday(date);
- X kdate(d, ck);
- X if (!ivcmp(ck, date, sizeof date)) {
- X yyerror("invalid date spec");
- X d = NULLDATE;
- X }
- X fprintf(stf, "%d", d);
- X}
- ________This_Is_The_END________
- if test `wc -l < genpgm.c` -ne 338; then
- echo 'shar: genpgm.c was damaged during transit (should have been 338 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - usp.man'
- if test -f usp.man; then echo 'shar: not overwriting usp.man'; else
- sed 's/^X//' << '________This_Is_The_END________' > usp.man
- X'''
- X''' USP (UNIFY(r) Selection Preprocessor)
- X'''
- X.TH USP 1L
- X.SH NAME
- Xusp \- unify(R) selection preprocessor
- X.SH SYNOPSIS
- X.B usp <
- X.I file.c
- X.B >
- X.I outfile.c
- X.SH DESCRIPTION
- X.I Usp
- Xis a preprocessor for C programs which use the Unify\*R C HLI. It obviates
- Xthe need for the Unify preprocessor,
- X.BR upp ,
- Xand the include file
- X.IR file.h ,
- Xwhile providing more features including automatic date translation and a
- Xsimple selection language.
- X.SH USAGE
- X.SS Invocation
- XAt present, the
- X.B usp
- Xcommand reads a C program from standard input and writes a modified copy of
- Xthe program to standard output. The modifications are triggered by a dollar
- Xsign character
- X.BR ($) .
- XThe output file is preceded by definitions used by the succeeding code.
- X.SS Syntax
- X.BR Usp 's
- Xtranslation capabilities are triggered by a dollar sign character. If the
- Xcharacter appears in column 1 of a line, it triggers a command translation.
- XIf the character is in any other column, it triggers a record, field or date
- Xtranslation.
- X.SS Command syntax
- XThe
- X.B usp
- Xcommand processor recognizes a limited subset of commands associated with
- Xdata selection and retrieval. The command syntax is described by the
- Xfollowing BNF syntax:
- X.de Bs
- X.in +15
- X.ll -5
- X.sp 2
- X.ns
- X..
- X.de Bn
- X.ti -10
- X.sp
- X\\$1 ::= \\$2
- X.if \w\\$3 | \\$3
- X.if \w\\$4 | \\$4
- X.if \w\\$5 | \\$5
- X.if \w\\$6 | \\$6
- X.if \w\\$7 | \\$7
- X.if \w\\$8 | \\$8
- X.if \w\\$9 | \\$9
- X..
- X.de Be
- X.in -15
- X.ll +5
- X.sp 2
- X.ns
- X..
- X.Bs
- X.Bn <command> <define> <get> <put> <foreach> <select> <sort>
- X.Bn <define> "define <variable> { like <field> | <type> } ;"
- X.Bn <get> "get <variable> = <field> ;"
- X.Bn <put> "put <field> = <variable> ;"
- X.Bn <foreach> "foreach <selection> {"
- X.Bn <select> "select { <selection> | interrupt <switch> }"
- X.Bn <sort> "sort messages <switch>"
- X.Bn <selection> "<record> [[of <record>] [where <condition>] [by <keys>] | key <const>]"
- X.Bn <switch> on off
- X.Bn <condition> <basic> "<condition> and <basic>"
- X.Bn <basic> "<field> <op> <variable>"
- X.Bn <op> = ^= > >= < <=
- X.Bn <type> "numeric <integer>" "amount <integer>" "float <integer>" "string <integer>" date time
- X.Bn <field> "[<record>.]<fsyn>"
- X.Bn <variable> "[&]<identifier>" <string>
- X.Bn <keys> <key> "<keys> , <key>"
- X.Bn <key> <field> "<key> -> <field>"
- X.Be
- XNote that
- X.BR <integer> , " <string>" ", and " <identifier>
- Xare standard C constructs; refer to a C programming manual for more information.
- X.SS Commands
- XThe following commands are accepted by
- X.BR usp :
- X.RS 5
- X.IP "define <variable>" 5
- XDefine a variable, either "like" a database field or as a Unify\*R type. This
- Xis basically a convenience.
- X.IP "get <variable> = <field>" 5
- XAssign the contents of a database field to a variable. This is essentially a
- X.IR gfield ,
- Xwith the exception that a string field will automatically be null-terminated
- Xat the end of its defined length. This requires that a string variable be
- Xdefined one character longer than the corresponding Unify\*R field; the
- X.B define
- Xcommand already does this.
- X.IP "put <field> = <variable>" 5
- XThe inverse of
- X.BR get ;
- Xit does a
- X.I pfield
- Xoperation. It will call
- X.I error
- Xif the operation fails.
- X.IP "foreach <selection>" 5
- XThe first of the selection commands; it is capable of dealing with multiple
- Xreturned records. It begins a loop which, in the generated program, is a
- X.I for
- Xloop. See
- X.I Selections
- Xfor more information.
- X.IP "select <selection>" 5
- XThe other selection command; it returns exactly one record.
- X.IP "select interrupt <switch>" 5
- Xcontrols whether queries may be interrupted; if a
- X.B foreach
- Xquery is interupted, the enclosed loop is not executed.
- X.IP "sort messages <switch>" 5
- XThe
- X.B sort messages
- Xcommand controls whether the sorting versions of the
- X.B foreach
- Xcommand will display the messages
- X.IR Selecting , " Sorting" ", and " Formatting" .
- X.RE
- X.SS Selections
- XA
- X.B selection
- Xis a specification of which rows of which table will be returned by a query.
- XIt is not as complex as is possible with
- X.BR SQL ,
- Xbut is complex enough to simplify many programming projects.
- X.P
- XThe basic form of a selection is shown by the BNF syntax above. The only
- Xsemantic conditions are as follows:
- X.RS 5
- X.IP -
- XThe syntax
- X.B foreach ... key
- Xis illegal;
- X.IP -
- XThe syntax
- X.B select ... by
- Xis illegal; and
- X.IP -
- XThe `&' character is required on non-string variables.
- X.RE
- X.P
- XThe `of' keyword exploits explicit relationships. It also determines
- Xautomatically whether the relationship is being followed in a one-to-many or a
- Xmany-to-one direction.
- X.P
- XSorting is always in ascending order; the "->" syntax is used to follow
- Xexplicit relationship chains. See the descrition of the
- X.I unisort
- Xfunction in the Unify\*R Programmer's manual, but note that the "->" chain is
- Xreversed in order from the sort array.
- X.SS Non-command syntax
- XThe
- X.B usp
- Xprocessor also translates bjects when it sees a `$' character in the middle of
- Xa line. In this case, the character following the $ is inspected. If it is a
- Xleft parenthesis `(', then the object is a date. Dates have the following syntax:
- X.RS 20
- X.sp
- X$(mm/dd/yy)
- X.br
- X$(**/**/**)
- X.br
- X$(today)
- X.sp
- X.RE
- XThe `$(today)' syntax expands to a static function call.
- X.P
- XIf the character following the `$' is not a left parenthesis, then the following
- Xidentifier is interpreted as a record or short field name. If it cannot be
- Xtranslated as either, an error occurs.
- X.SH "SEE ALSO"
- XThe Unify\*R Programmer's Manual
- X.SH ACKNOWLEDGEMENTS
- XUnify is a registered trademark of Unify Corporation.
- X.SH BUGS
- XIt is likely that hand-coding selections would produce more optimal code,
- Xalthough
- X.B usp
- Xtries valiantly and recognizes at least twelve kinds of queries.
- X.P
- XThe
- X.B $field
- Xconstruct should allow
- X.I field.record
- Xsyntax. This, alas, would require a much more complex parser.
- X.P
- XAll programs have a two-line definition prepended to them, whether the
- Xdefinition is used or not.
- X.P
- XIf two separate source files for a program use the `$(today)' structure, each
- Xfile will have a static function prepended to it. This is somewhat wasteful
- Xbut avoids having to link a special library into the program.
- ________This_Is_The_END________
- if test `wc -l < usp.man` -ne 205; then
- echo 'shar: usp.man was damaged during transit (should have been 205 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - usp.y'
- if test -f usp.y; then echo 'shar: not overwriting usp.y'; else
- sed 's/^X//' << '________This_Is_The_END________' > usp.y
- X%token FOREACH OF WHERE BY AND BETWEEN kNOT DEFINE LIKE STRING AMOUNT kDATE
- X%token TIME NUMERIC FLOAT GET PUT SORT MESSAGES INTERRUPT OFF ON KEY SELECT
- X%token GE LE NE PTR
- X%token tRECORD tFIELD tCONST tNUM
- X
- X%union {
- X char str[256];
- X int fld;
- X int rec;
- X int opcode;
- X struct {
- X int nfld;
- X int *spec;
- X } sort;
- X int flag;
- X int num;
- X}
- X
- X%type <fld> field of
- X%type <rec> tRECORD
- X%type <str> tCONST tFIELD type varlist
- X%type <sort> sortspec
- X%type <opcode> op
- X%type <flag> by not switch where key
- X%type <num> tNUM selection
- X
- X%{
- X
- X#include <unisel.h>
- X#include <fdesc.h>
- X#include <dbtypes.h>
- X
- Xint crec, jrec, jfld;
- Xlong seqn = 0L, xseq = 0L;
- Xint didumsg = 0, didusdcl = 0, didssdcl = 0;
- X
- Xextern char *malloc();
- Xextern char *realloc();
- Xextern char *recname();
- Xextern char *fldsyn();
- X
- X#define SEL_REL 8
- X#define SEL_VALUE 4
- X#define SEL_KEY 2
- X#define SEL_SORT 1
- X
- X%}
- X
- X%%
- X
- Xcommand : FOREACH selection '{'
- X {
- X if ($2 & SEL_KEY) {
- X yyerror("`foreach ... key' makes no sense");
- X YYERROR;
- X }
- X switch ($2) {
- X case 0:
- X putsel("for (__i__er_ = seqacc(%d, 1); __i__er_ == 0; __i__er_ = seqacc(%d, 2)) {", crec, crec);
- X break;
- X case SEL_VALUE:
- X case SEL_REL|SEL_VALUE:
- X putsel("\n\1for ((__i__er_ != 0? __i__er_: (__i__er_ = frstsel(__f_%d))); __i__er_ > 0; __i__er_ = nextsel(__f_%d)) {", seqn, seqn);
- X break;
- X case SEL_REL:
- X if (jfld < 0) {
- X yyerror("cannot use `foreach' on join to parent");
- X YYERROR;
- X }
- X putsel("\n\1for (__i__er_ = nextrec(%d, %d); __i__er_ == 0; __i__er_ = nextrec(%d, %d)) {", reckey(jrec), jfld, reckey(jrec), jfld);
- X break;
- X case SEL_REL|SEL_SORT:
- X case SEL_REL|SEL_VALUE|SEL_SORT:
- X case SEL_VALUE|SEL_SORT:
- X case SEL_SORT:
- X putsel("\n\1for (__i__er_ = sfrstrec(%d, %d); __i__er_ == 0; __i__er_ = snextrec(%d, %d)) {", reckey(jrec), jfld, reckey(jrec), jfld);
- X break;
- X }
- X YYACCEPT;
- X }
- X | DEFINE varlist type ';'
- X {
- X char vbuf[1024];
- X
- X sprintf(vbuf, $3, $2);
- X putsel("%s;", vbuf);
- X YYACCEPT;
- X }
- X | GET tCONST '=' field ';'
- X {
- X FLDESC fd;
- X char *cp;
- X
- X if ($2[0] == '"') {
- X yyerror("syntax error");
- X YYERROR;
- X }
- X fldesc($4, &fd);
- X if (fd.f_typ != STRNG && fd.f_typ != COMB && $2[0] != '&')
- X cp = "&";
- X else
- X cp = "";
- X putsel("gfield(%d, %s%s)", $4, cp, $2);
- X if (fd.f_typ == STRNG)
- X putsel(", %s[%d] = '\\0'", $2, fd.f_len);
- X putsel(";");
- X YYACCEPT;
- X }
- X | PUT field '=' tCONST ';'
- X {
- X FLDESC fd;
- X char *cp;
- X
- X fldesc($2, &fd);
- X if (fd.f_typ != STRNG && fd.f_typ != COMB && $4[0] != '&')
- X cp = "&";
- X else
- X cp = "";
- X putsel("if ((__i__er_ = pfield(%d, %s%s)) != 0)\n\1\terror(\"pfield %s\", __i__er_);", $2, cp, $4);
- X YYACCEPT;
- X }
- X | SORT MESSAGES switch ';'
- X {
- X if (!didumsg)
- X puthead("extern int _No_Umsgs;\n");
- X didumsg = 1;
- X putsel("_No_Umsgs = %d;", !$3);
- X YYACCEPT;
- X }
- X | SELECT select_cmd ';'
- X {
- X YYACCEPT;
- X }
- X ;
- X
- Xselect_cmd : INTERRUPT switch
- X {
- X putsel("setintr(%d);", ($2? INTR_ON: INTR_OFF));
- X
- X }
- X | selection
- X {
- X if ($1 & SEL_SORT) {
- X yyerror("you cannot use a `by' phrase in a `select' statement");
- X YYERROR;
- X }
- X switch ($1) {
- X case 0:
- X puthead("static long __n_%d;\n", seqn);
- X putsel("if ((__n_%d = getnrec(%d)) != 1)\n\1\terror(\"seqacc %s returned not exactly one record\", __n_%d);", seqn, crec, recname(crec), seqn);
- X putsel("\n\1seqacc(%d, 1);", crec);
- X break;
- X case SEL_KEY:
- X break;
- X case SEL_REL:
- X if (jfld < 0)
- X break;
- X putsel("\n\1if (__n_%d != 1L)\n\1\terror(\"select %s returned not exactly one record\", __n_%d);\n\1", seqn, recname(crec), seqn);
- X /*FALLTHROUGH*/
- X default:
- X putsel("\n\1if ((__i__er_ = frstrec(__f_%d)) != 0)\n\1\terror(\"frstrec %s\", __i__er_);", seqn, recname(crec));
- X }
- X }
- X ;
- X
- Xswitch : OFF
- X {
- X $$ = 0;
- X }
- X | ON
- X {
- X $$ = 1;
- X }
- X ;
- X
- Xselection : tRECORD
- X {
- X seqn++;
- X crec = $1;
- X }
- X of where key by
- X {
- X int v;
- X char vbuf[256];
- X FLDESC fd;
- X
- X v = ($3 == 0? 0: SEL_REL)|($4? SEL_VALUE: 0)|($5? SEL_KEY: 0)|($6? SEL_SORT: 0);
- X if ($5 && ($3 != 0 || $4 || $6)) {
- X yyerror("cannot use `key' with `of' or `where'");
- X YYERROR;
- X }
- X if ($3 < 0 && ($4 || $6)) {
- X yyerror("cannot use `where' or `by' on join to parent");
- X YYERROR;
- X }
- X switch (v) {
- X case SEL_REL:
- X if ($3 < 0)
- X putsel("if ((__i__er_ = faccess(%d, %d)) != 0)\n\1\terror(\"faccess %s\", __i__er_);", crec, - $3, recname(crec));
- X else {
- X puthead("static long __n_%d;\n", seqn);
- X putsel("if ((__i__er_ = makeset(%d, %d, 1)) != 0)\n\1\terror(\"makeset(%s, %s)\", __i__er_);", reckey(jrec), $3, fldsyn(reckey(jrec)), fldsyn($3));
- X putsel("\n\1setsize(%d, %d, &__n_%d);", reckey(jrec), $3, seqn);
- X }
- X jfld = $3;
- X break;
- X case SEL_REL|SEL_SORT:
- X if (!didssdcl) {
- X didssdcl = 1;
- X puthead("static int (*__no_f__[])() = {0, 0, 0, 0};\n");
- X }
- X putsel("(void) unisort(%d, %d, __s_%d, __no_f__);", jrec, $3, seqn);
- X jfld = $3;
- X break;
- X case 0:
- X case SEL_KEY:
- X break;
- X case SEL_REL|SEL_VALUE:
- X fldesc(reckey(jrec), &fd);
- X sprintf(vbuf, utype(fd.f_typ, (fd.f_typ == FLT? fd.f_len * 10: fd.f_len)), "__j_%d");
- X puthead("static ");
- X puthead(vbuf, ++xseq);
- X puthead(";\n");
- X fldesc($3, &fd);
- X putsel("gfield(%d, __j_%d);\n\1entsitm(%d, __j_%d, (char *) 0, %d);\n\1", fd.f_rpfld, xseq, $3, xseq, EQ);
- X /*FALLTHROUGH*/
- X case SEL_VALUE:
- X if (!didusdcl) {
- X didusdcl = 1;
- X puthead("extern struct uselfil *opensf();\n");
- X }
- X puthead("static struct uselfil *__f_%d = (struct uselfil *) 0;\nstatic char __t_%d[] = \"/tmp/,ts_XXXXXX\";\nstatic long __n_%d;\n\n", seqn, seqn, seqn);
- X putsel("mktemp(__t_%d);\n\1if (__f_%d != (struct uselfil *) 0)\n\1\tclosesf(__f_%d);\n\1", seqn, seqn, seqn);
- X putsel("if ((__i__er_ = unisel(__t_%d, %d, &__n_%d)) != 0 && __i__er_ != -1 && __i__er_ != -7)\n\1\terror(\"unisel %s\", __i__er_);\n\1", seqn, crec, seqn, recname(crec));
- X putsel("if ((int) (__f_%d = opensf(__t_%d)) == -1)\n\1\terror(\"opensf %s\", -1);\n\1unlink(__t_%d);", seqn, seqn, recname(crec), seqn);
- X break;
- X case SEL_REL|SEL_VALUE|SEL_SORT:
- X fldesc(reckey(jrec), &fd);
- X sprintf(vbuf, utype(fd.f_typ, (fd.f_typ == FLT? fd.f_len * 10: fd.f_len)), "__j_%d");
- X puthead("static ");
- X puthead(vbuf, ++xseq);
- X puthead(";\n");
- X fldesc($3, &fd);
- X putsel("gfield(%d, __j_%d);\n\1entsitm(%d, __j_%d, (char *) 0, %d);\n\1", fd.f_rpfld, xseq, $3, xseq, EQ);
- X /*FALLTHROUGH*/
- X case SEL_SORT:
- X case SEL_VALUE|SEL_SORT:
- X if (!didssdcl) {
- X didssdcl = 1;
- X puthead("static int (*__no_f__[])() = {0, 0, 0, 0};\n");
- X }
- X putsel("if ((__i__er_ = selsort(%d, __s_%d, __no_f__)) != 0 && __i__er_ != -1)\n\1\terror(\"unisort %s\", __i__er_);", crec, seqn, recname(crec));
- X jfld = SS;
- X jrec = crec;
- X break;
- X default:
- X yyerror("illegal combination of selection phrases (%d)", v);
- X YYERROR;
- X }
- X $$ = v;
- X }
- X ;
- X
- Xwhere : /* none */
- X {
- X $$ = 0;
- X }
- X | WHERE selfield
- X {
- X $$ = 1;
- X }
- X ;
- X
- Xof : /* none */
- X {
- X $$ = 0;
- X }
- X | OF tRECORD
- X {
- X int cnt;
- X FLDESC fd;
- X
- X for (cnt = numflds(); cnt > 0; cnt--)
- X if (!fldesc(cnt, &fd))
- X continue;
- X else if (fd.f_rec == crec && fd.f_rprec == $2)
- X break;
- X else if (fd.f_rec == $2 && fd.f_rprec == crec)
- X break;
- X if (cnt == 0) {
- X yyerror("record type %s does not join to %s", recname($2), recname(crec));
- X YYERROR;
- X }
- X jrec = $2;
- X $$ = (fd.f_rec == crec? cnt: -cnt);
- X }
- X ;
- X
- Xkey : /* none */
- X {
- X $$ = 0;
- X }
- X | KEY tCONST
- X {
- X FLDESC fd;
- X char *cp;
- X int thekey;
- X
- X if ((thekey = reckey(crec)) == 0) {
- X yyerror("record type %s has no key", recname(crec));
- X YYERROR;
- X }
- X fldesc(thekey, &fd);
- X if (fd.f_typ != STRNG && fd.f_typ != COMB && $2[0] != '&')
- X cp = "&";
- X else
- X cp = "";
- X putsel("if ((__i__er_ = acckey(%d, %s%s)) != 0)\n\1\terror(\"acckey %s\", __i__er_);", crec, cp, $2, recname(crec));
- X $$ = 1;
- X }
- X ;
- X
- Xselfield : sel
- X | selfield AND sel
- X ;
- X
- Xsel : field op tCONST
- X {
- X FLDESC fd;
- X
- X fldesc($1, &fd);
- X if (fd.f_rec != crec) {
- X yyerror("field %s is not in record type %s", fldsyn($1), recname(crec));
- X YYERROR;
- X }
- X putsel("entsitm(%d, %s, (char *) 0, %d);\n\1", $1, $3, $2);
- X }
- X | field not BETWEEN tCONST AND tCONST
- X {
- X FLDESC fd;
- X
- X fldesc($1, &fd);
- X if (fd.f_rec != crec) {
- X yyerror("field %s is not in record type %s", fldsyn($1), recname(crec));
- X YYERROR;
- X }
- X putsel("entsitm(%d, %s, %s, %d);\n\1", $1, $4, $6, ($2? NOT: EQ));
- X }
- X ;
- X
- Xnot : /* none */
- X {
- X $$ = 0;
- X }
- X | kNOT
- X {
- X $$ = 1;
- X }
- X ;
- X
- Xby : /* none */
- X {
- X $$ = 0;
- X }
- X | BY
- X {
- X puthead("static int __s_%d[] = {\n", seqn);
- X }
- X sortlist
- X {
- X puthead("-1};\n");
- X $$ = 1;
- X }
- X ;
- X
- Xsortlist : sort
- X | sortlist ',' sort
- X ;
- X
- Xsort : sortspec
- X {
- X int cnt;
- X
- X for (cnt = $1.nfld; cnt > 0; cnt--)
- X puthead(" %d,", $1.spec[cnt - 1]);
- X puthead(" 0,\n");
- X free($1.spec);
- X }
- X ;
- X
- Xsortspec : field
- X {
- X FLDESC fd;
- X
- X fldesc($1, &fd);
- X if (fd.f_rec != crec) {
- X yyerror("field %s is not in record type %s", fldsyn($1), recname(crec));
- X YYERROR;
- X }
- X $$.nfld = 1;
- X if (($$.spec = (int *) malloc(sizeof (int))) == (int *) 0) {
- X yyerror("out of memory in firstsort");
- X YYERROR;
- X }
- X $$.spec[0] = $1;
- X }
- X | sortspec PTR field
- X {
- X FLDESC fd, jfd;
- X
- X fldesc($3, &fd);
- X fldesc($1.spec[$$.nfld - 1], &jfd);
- X if (jfd.f_rprec != fd.f_rec) {
- X yyerror("no explicit relationship between %s and %s.%s", fldsyn($1), recname(fd.f_rec), fldsyn(reckey(fd.f_rec)));
- X YYERROR;
- X }
- X $$ = $1;
- X if (($$.spec = (int *) realloc($$.spec, (unsigned) ++$$.nfld * sizeof (int))) == (int *) 0) {
- X yyerror("out of memory in nextsort");
- X YYERROR;
- X }
- X $$.spec[$$.nfld - 1] = $3;
- X }
- X ;
- X
- Xfield : tFIELD
- X {
- X int cnt;
- X char *cp;
- X
- X for (cnt = 1; cnt <= numflds(); cnt++) {
- X if ((cp = fldsyn(cnt)) == (char *) 0)
- X continue;
- X if (strcmp(cp, $1) == 0)
- X break;
- X }
- X $$ = cnt;
- X }
- X | tRECORD '.' tFIELD
- X {
- X FLDESC fd;
- X int cnt;
- X char *cp;
- X
- X for (cnt = numflds(); cnt > 0; cnt--) {
- X if ((cp = fldsyn(cnt)) == (char *) 0)
- X continue;
- X if (strcmp(cp, $3) != 0)
- X continue;
- X fldesc(cnt, &fd);
- X if (fd.f_rec == $1)
- X break;
- X }
- X if (cnt == 0) {
- X yyerror("field %s is not in record type %s", $3, recname($1));
- X YYERROR;
- X }
- X $$ = cnt;
- X }
- X ;
- X
- Xop : '>'
- X {
- X $$ = GT;
- X }
- X | '='
- X {
- X $$ = EQ;
- X }
- X | '<'
- X {
- X $$ = LT;
- X }
- X | LE
- X {
- X $$ = LTE;
- X }
- X | GE
- X {
- X $$ = GTE;
- X }
- X | NE
- X {
- X $$ = NOT;
- X }
- X ;
- X
- Xtype : LIKE field
- X {
- X FLDESC fd;
- X
- X fldesc($2, &fd);
- X strcpy($$, utype(fd.f_typ, (fd.f_typ == FLT? fd.f_len * 10: fd.f_len)));
- X }
- X | STRING tNUM
- X {
- X strcpy($$, utype(STRNG, $2));
- X }
- X | NUMERIC tNUM
- X {
- X strcpy($$, utype(($2 > 4? LONG: INT), $2));
- X }
- X | AMOUNT tNUM
- X {
- X strcpy($$, utype(($2 > 7? HAMT: AMT), $2));
- X }
- X | FLOAT tNUM
- X {
- X strcpy($$, utype(FLT, $2));
- X }
- X | kDATE
- X {
- X strcpy($$, utype(DATE, 0));
- X }
- X | TIME
- X {
- X strcpy($$, utype(HR, 0));
- X }
- X ;
- X
- Xvarlist : tCONST
- X {
- X if ($1[0] == '"' || $1[0] == '&') {
- X yyerror("syntax error");
- X YYERROR;
- X }
- X strcpy($$, $1);
- X }
- X | varlist ',' tCONST
- X {
- X if ($3[0] == '"' || $3[0] == '&') {
- X yyerror("syntax error");
- X YYERROR;
- X }
- X strcpy($$, $1);
- X strcat($$, ", ");
- X strcat($$, $3);
- X }
- X ;
- X
- X%%
- ________This_Is_The_END________
- if test `wc -l < usp.y` -ne 541; then
- echo 'shar: usp.y was damaged during transit (should have been 541 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - usptok.l'
- if test -f usptok.l; then echo 'shar: not overwriting usptok.l'; else
- sed 's/^X//' << '________This_Is_The_END________' > usptok.l
- X%{
- X
- X#include "y.tab.h"
- X
- X#undef input
- X#undef unput
- X
- Xchar _curline[1024];
- Xchar _unput[1024];
- Xint _curcol;
- Xint _curunp = 0;
- Xint indent = 0;
- Xint _ign_ = 0;
- Xextern int nlflag;
- Xextern char *srcfile;
- X
- Xstatic g_input() {
- X if (_curunp > 0) {
- X if (_unput[--_curunp] == '\n')
- X yylineno++;
- X return _unput[_curunp];
- X }
- X while (_curline[_curcol] == '\0') {
- X if (fgets(_curline, sizeof _curline, yyin) == (char *) 0)
- X return 0;
- X _curcol = 0;
- X }
- X if (_curline[_curcol] == '\n')
- X yylineno++;
- X return _curline[_curcol++];
- X}
- X
- Xinput() {
- X int ch;
- X
- X ch = g_input();
- X if (!_ign_ && nlflag) {
- X if (ch == ' ')
- X indent++;
- X else if (ch == '\t')
- X do {
- X indent++;
- X } while (indent % 8 != 0);
- X }
- X return ch;
- X}
- X
- Xunput(c) {
- X if (_curunp == 0 && _curcol > 0 && _curline[_curcol - 1] == c)
- X _curcol--;
- X else if (_curunp == sizeof _unput) {
- X yyerror("internal error: pushback overflow, char %o (octal)", c);
- X exit(1);
- X }
- X else
- X _unput[_curunp++] = c;
- X if (c == '\n') {
- X yylineno--;
- X nlflag = 0;
- X }
- X}
- X
- Xextern char *scanon();
- Xextern char *fldsyn();
- Xextern char *recname();
- X
- X#include <dbtypes.h>
- X
- X%}
- X
- X%%
- X
- Xdefine { return DEFINE; }
- Xlike { return LIKE; }
- Xnumeric { return NUMERIC; }
- Xstring { return STRING; }
- Xfloat { return FLOAT; }
- Xamount { return AMOUNT; }
- Xdate { return kDATE; }
- Xtime { return TIME; }
- Xget { return GET; }
- Xput { return PUT; }
- Xforeach { return FOREACH; }
- Xof { return OF; }
- Xwhere { return WHERE; }
- Xby { return BY; }
- Xand { return AND; }
- Xbetween { return BETWEEN; }
- Xnot { return kNOT; }
- Xselect { return SELECT; }
- Xkey { return KEY; }
- Xsort { return SORT; }
- Xmessages { return MESSAGES; }
- Xinterrupt { return INTERRUPT; }
- Xon { return ON; }
- Xoff { return OFF; }
- X">=" { return GE; }
- X"<=" { return LE; }
- X"!=" { return NE; }
- X"^=" { return NE; }
- X"->" { return PTR; }
- X\&?[A-Za-z_][A-Za-z0-9_]* {
- X int cnt;
- X char *p;
- X
- X strcpy(yylval.str, yytext);
- X for (cnt = numrecs(); cnt > 0; cnt--) {
- X if ((p = recname(cnt)) == (char *) 0)
- X continue;
- X if (strcmp(p, yytext) == 0) {
- X yylval.rec = cnt;
- X return tRECORD;
- X }
- X }
- X for (cnt = numflds(); cnt > 0; cnt--) {
- X if ((p = fldsyn(cnt)) == (char *) 0)
- X continue;
- X if (strcmp(p, yytext) == 0)
- X return tFIELD;
- X }
- X return tCONST;
- X}
- X-?[0-9]+ {
- X yylval.num = atoi(yytext);
- X return tNUM;
- X}
- X\"([^\\n]*\\\")*[^"\n"]*\" {
- X strcpy(yylval.str, yytext);
- X return tCONST;
- X}
- X[ \t\n]+ ;
- X. return *yytext;
- X
- X%%
- X
- X#include <varargs.h>
- X
- Xchar *scanon(buf)
- Xregister char *buf; {
- X static char cbuf[1024];
- X register short bufc;
- X char ibuf;
- X
- X ibuf = *buf;
- X bufc = 0;
- X for (buf++; *buf != '\0'; buf++) {
- X if (*buf == '\\')
- X cbuf[bufc++] = *++buf;
- X else if (*buf == ibuf)
- X break;
- X else
- X cbuf[bufc++] = *buf;
- X }
- X cbuf[bufc] = '\0';
- X if (*buf == ibuf && *++buf != '\0')
- X yyerror("internal error (canon trailing text \"%s\")", buf);
- X return cbuf;
- X}
- X
- Xyyerror(va_alist)
- Xva_dcl {
- X va_list args;
- X char *format;
- X short uc;
- X
- X va_start(args);
- X format = va_arg(args, char *);
- X fprintf(stderr, "\n\"%s\", line %d: ", srcfile, yylineno);
- X vfprintf(stderr, format, args);
- X va_end(args);
- X fprintf(stderr, "\n> ");
- X if (_curunp == 0) {
- X short col;
- X
- X fprintf(stderr, "%s>-", _curline);
- X for (uc = 0, col = 2; uc < _curcol - 1; uc++) {
- X if (_curline[uc] == '\t') {
- X do {
- X putc('-', stderr);
- X } while (++col % 8 != 0);
- X }
- X else {
- X putc('-', stderr);
- X col++;
- X }
- X }
- X fprintf(stderr, "^\n");
- X }
- X else {
- X for (uc = _curunp; uc > 0; uc--)
- X putc(_unput[uc - 1], stderr);
- X fprintf(stderr, "\n>-^\n");
- X }
- X}
- ________This_Is_The_END________
- if test `wc -l < usptok.l` -ne 194; then
- echo 'shar: usptok.l was damaged during transit (should have been 194 bytes)'
- fi
- fi ; : end of overwriting check
- exit 0
-