home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume02 / usp < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  33.5 KB

  1. From mipos3!intelca!oliveb!ames!necntc!ncoast!allbery Sat Feb  6 16:05:08 PST 1988
  2. Article 287 of comp.sources.misc:
  3. Path: td2cad!mipos3!intelca!oliveb!ames!necntc!ncoast!allbery
  4. From: allbery@ncoast.UUCP (Brandon S. Allbery)
  5. Newsgroups: comp.sources.misc
  6. Subject: v02i037: UNIFY(r) Selection Preprocessor
  7. Message-ID: <7164@ncoast.UUCP>
  8. Date: 31 Jan 88 04:19:33 GMT
  9. Sender: allbery@ncoast.UUCP
  10. Organization: Cleveland Public Access UN*X, Cleveland, Oh
  11. Lines: 1371
  12. Approved: allbery@ncoast.UUCP
  13. X-Archive: comp.sources.misc/8801/35
  14. Comp.sources.misc: Volume 2, Issue 37
  15. Submitted-By: The Moderator <allbery@ncoast.UUCP>
  16. Archive-Name: usp
  17.  
  18. Comp.sources.misc: Volume 2, Issue 37
  19. Submitted-By: The Moderator <allbery@ncoast.UUCP>
  20. Archive-Name: usp
  21.  
  22. I decided that as long as I was posting some of my UNIFY(r) stuff, I'd throw
  23. this in.  This is a preprocessor for C programs which allows certain things
  24. to be done much more easily than usual:  in particular, coding queries now
  25. uses a single unified syntax rather than having to choose between ten or so
  26. functions.  It also allows you to specify literal dates and times and get the
  27. current date and time in a much more natural way.  It also replaces the "upp"
  28. C preprocessor, although you must use USP syntax instead of upp.  There is a
  29. man page in here describing the commands accepted by USP.
  30.  
  31. Oh -- just in case anyone's interested, I wrote one of these (watered down a
  32. bit) for Informix 3.3.  While it's watered down as far as selection ability,
  33. it at least builds all those blasted "struct dbview"s and such for you.  It
  34. reduced a 14-page program to 4 pages (I kid you not!).
  35.  
  36. #--------------------------------CUT HERE-------------------------------------
  37. #! /bin/sh
  38. #
  39. # This is a shell archive.  Save this into a file, edit it
  40. # and delete all lines above this comment.  Then give this
  41. # file to sh by executing the command "sh file".  The files
  42. # will be extracted into the current directory owned by
  43. # you with default permissions.
  44. #
  45. # The files contained herein are:
  46. #
  47. # -rw-r--r--  1 allbery users       378 Jan 30 20:59 Makefile
  48. # -rw-r--r--  1 allbery users      7392 Jan 30 20:59 genpgm.c
  49. # -rw-r--r--  1 allbery users      6043 Jan 30 20:59 usp.man
  50. # -rw-r--r--  1 allbery users     11761 Jan 30 20:59 usp.y
  51. # -rw-r--r--  1 allbery users      3438 Jan 30 20:59 usptok.l
  52. #
  53. echo 'x - Makefile'
  54. if test -f Makefile; then echo 'shar: not overwriting Makefile'; else
  55. sed 's/^X//' << '________This_Is_The_END________' > Makefile
  56. XSHELL = /bin/sh
  57. XCFLAGS = -O -I/appl/u32/include -DUNIFY32
  58. XYFLAGS = -d
  59. X
  60. XOBJ = usp.o usptok.o genpgm.o
  61. X
  62. Xusp: $(OBJ)
  63. X    UNIFY=/appl/u32/lib PATH=/appl/u32/bin:$$PATH uld usp $(OBJ) -ll
  64. X
  65. Xusptok.o: y.tab.h
  66. Xy.tab.h usp.o: usp.y
  67. X
  68. Xtester: usp TESTER
  69. X    DBPATH=/coesys/bin usp < TESTER > t1.c
  70. X    cc -O -c t1.c
  71. X    UNIFY=/appl/u32/lib PATH=/appl/u32/bin:$$PATH uld t1 t1.o
  72. X#    DBPATH=/coesys/bin t1
  73. ________This_Is_The_END________
  74. if test `wc -l < Makefile` -ne 17; then
  75.     echo 'shar: Makefile was damaged during transit (should have been 17 bytes)'
  76. fi
  77. fi        ; : end of overwriting check
  78. echo 'x - genpgm.c'
  79. if test -f genpgm.c; then echo 'shar: not overwriting genpgm.c'; else
  80. sed 's/^X//' << '________This_Is_The_END________' > genpgm.c
  81. X#include <stdio.h>
  82. X#include <varargs.h>
  83. X#include <dbtypes.h>
  84. X
  85. Xextern FILE *yyin, *yyout;
  86. Xextern FILE *tmpfile();
  87. Xextern char *recname();
  88. Xextern char *fldsyn();
  89. Xextern char *fldname();
  90. Xextern char *strchr();
  91. X
  92. Xstatic FILE *htf = (FILE *) 0;
  93. Xstatic FILE *stf = (FILE *) 0;
  94. Xstatic char vname[] = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  95. Xint nlflag = 1;
  96. Xstatic int diddate, dosync;
  97. Xchar *srcfile = "-";
  98. Xextern int indent, _ign_, yylineno;
  99. Xstatic int *typetab = (int *) 0;
  100. X
  101. X/*VARARGS PRINTFLIKE1*/
  102. Xputhead(va_alist)
  103. Xva_dcl {
  104. X    char *fmt;
  105. X    va_list args;
  106. X
  107. X    va_start(args);
  108. X    fmt = va_arg(args, char *);
  109. X    vfprintf(htf, fmt, args);
  110. X    va_end(args);
  111. X    if (fmt[strlen(fmt) - 1] == '\n')
  112. X        syncf(htf);
  113. X}
  114. X
  115. X/*VARARGS PRINTFLIKE1*/
  116. Xputsel(va_alist)
  117. Xva_dcl {
  118. X    char *fmt;
  119. X    va_list args;
  120. X    static char buf[5120];
  121. X
  122. X    va_start(args);
  123. X    fmt = va_arg(args, char *);
  124. X    vsprintf(buf, fmt, args);
  125. X    va_end(args);
  126. X    __emit(buf);
  127. X}
  128. X
  129. Xstatic __emit(buf)
  130. Xchar *buf; {
  131. X    for (; *buf != '\0'; buf++) {
  132. X        if (*buf == '\1') {
  133. X            syncf(stf);
  134. X            lead(indent);
  135. X            continue;
  136. X        }
  137. X        putc(*buf, stf);
  138. X    }
  139. X}
  140. X
  141. Xsyncf(fp)
  142. XFILE *fp; {
  143. X    fprintf(fp, "#line %d", yylineno);
  144. X    if (yyin != stdin)
  145. X        fprintf(fp, " \"%s\"", srcfile);
  146. X    putc('\n', fp);
  147. X}
  148. X
  149. Xstatic lead(cnt) {
  150. X    while (cnt > 8) {
  151. X        putc('\t', stf);
  152. X        cnt -= 8;
  153. X    }
  154. X    while (cnt-- > 0)
  155. X        putc(' ', stf);
  156. X}
  157. X
  158. Xdumpf(fp, dest)
  159. XFILE *fp, *dest; {
  160. X    int ch;
  161. X
  162. X    yyin = fp;
  163. X    nlflag = 1;
  164. X    diddate = 0;
  165. X    dosync = 1;
  166. X    if (typetab != (int *) 0) {
  167. X        free((char *) typetab);
  168. X        typetab = 0;
  169. X    }
  170. X    if (htf == (FILE *) 0 && (htf = tmpfile()) == (FILE *) 0) {
  171. X        yyerror("can't open temp file for header");
  172. X        exit(2);
  173. X    }
  174. X    fprintf(htf, "static int __i__er_ = 0;\n");
  175. X    if (stf == (FILE *) 0 && (stf = tmpfile()) == (FILE *) 0) {
  176. X        yyerror("can't open temp file for code");
  177. X        exit(2);
  178. X    }
  179. X    while ((ch = input()) != 0) {
  180. X        if (ch == '$') {
  181. X             if (nlflag && indent == 0) {
  182. X                indent = 1;    /* '$' == space for output */
  183. X                if ((ch = input()) != '\t')
  184. X                    putc(' ', stf);
  185. X                while (ch == ' ' || ch == '\t') {
  186. X                    putc(ch, stf);
  187. X                    ch = input();
  188. X                }
  189. X                unput(ch);
  190. X                _ign_ = 1;
  191. X                yyparse();
  192. X                _ign_ = 0;
  193. X                nlflag = 0;
  194. X                dosync = 1;
  195. X            }
  196. X            else {    /* embedded record/field ref */
  197. X                char vbuf[256];
  198. X                int cnt;
  199. X                char *cp;
  200. X
  201. X                cnt = 0;
  202. X                nlflag = 0;
  203. X                while ((ch = input()) != 0 && strchr(vname, ch) != (char *) 0)
  204. X                    vbuf[cnt++] = ch;
  205. X                if (cnt == 0 && ch == '(') {
  206. X                    parsedate();
  207. X                    continue;
  208. X                }
  209. X                unput(ch);
  210. X                if (cnt == 0) {
  211. X                    putc('$', stf);
  212. X                    continue;
  213. X                }
  214. X                vbuf[cnt] = '\0';
  215. X                for (cnt = numrecs(); cnt > 0; cnt--) {
  216. X                    if ((cp = recname(cnt)) == (char *) 0)
  217. X                        continue;
  218. X                    else if (strcmp(cp, vbuf) == 0)
  219. X                        break;
  220. X                }
  221. X                if (cnt != 0) {
  222. X                    fprintf(stf, "%d", cnt);
  223. X                    continue;
  224. X                }
  225. X                for (cnt = numflds(); cnt > 0; cnt--) {
  226. X                    if ((cp = fldname(cnt)) == (char *) 0)
  227. X                        continue;
  228. X                    else if (strcmp(cp, vbuf) == 0)
  229. X                        break;
  230. X                }
  231. X                if (cnt != 0)
  232. X                    fprintf(stf, "%d", cnt);
  233. X                else {
  234. X                    yyerror("unrecognized record/field name `%s'", vbuf);
  235. X                    fputs(vbuf, stf);
  236. X                }
  237. X            }
  238. X        }
  239. X        else {
  240. X            if (ch != '\n' && ch != ' ' && ch != '\t')
  241. X                nlflag = 0;
  242. X            else if (ch == '\n') {
  243. X                indent = 0;
  244. X                nlflag = 1;
  245. X            }
  246. X            putc(ch, stf);
  247. X            if (dosync && ch == '\n') {
  248. X                syncf(stf);
  249. X                dosync = 0;
  250. X            }
  251. X        }
  252. X    }
  253. X    rewind(htf);
  254. X    rewind(stf);
  255. X    while ((ch = getc(htf)) != EOF)
  256. X        putc(ch, dest);
  257. X    putc('\n', dest);
  258. X    while ((ch = getc(stf)) != EOF)
  259. X        putc(ch, dest);
  260. X    fclose(htf);
  261. X    fclose(stf);
  262. X    htf = (FILE *) 0;
  263. X    stf = (FILE *) 0;
  264. X}
  265. X
  266. Xmain(argc, argv)
  267. Xchar **argv; {
  268. X    char fname[1024];
  269. X    FILE *inf, *outf;
  270. X    int arg, len;
  271. X
  272. X    srcfile = "-";
  273. X    if (argc < 2)
  274. X        dumpf(stdin, stdout);
  275. X    else
  276. X        for (arg = 1; argv[arg] != (char *) 0; arg++) {
  277. X            strcpy(fname, argv[arg]);
  278. X            len = strlen(fname);
  279. X            if (fname[len - 2] == '.' && fname[len - 1] == 'c')
  280. X                strcpy(fname + len - 1, "usp.c");
  281. X            else
  282. X                strcat(fname, ".c");
  283. X            if ((inf = fopen(argv[arg], "r")) == (FILE *) 0) {
  284. X                perror(argv[arg]);
  285. X                continue;
  286. X            }
  287. X            if ((outf = fopen(fname, "w")) == (FILE *) 0) {
  288. X                perror(fname);
  289. X                fclose(inf);
  290. X                continue;
  291. X            }
  292. X            srcfile = argv[arg];
  293. X            dumpf(inf, outf);
  294. X            fclose(inf);
  295. X            fclose(outf);
  296. X        }
  297. X    exit(0);
  298. X}
  299. X
  300. Xchar *utype(type, len) {
  301. X    static char buf[256];
  302. X
  303. X    switch (type) {
  304. X    case INT:
  305. X    case DATE:
  306. X    case HR:
  307. X        strcpy(buf, "short %s");
  308. X        break;
  309. X    case LONG:
  310. X    case AMT:
  311. X        strcpy(buf, "long %s");
  312. X        break;
  313. X    case HAMT:
  314. X    case FLT:
  315. X        strcpy(buf, "double %s");
  316. X        break;
  317. X    case STRNG:
  318. X        len++;
  319. X    case COMB:
  320. X        typeset(len);
  321. X        sprintf(buf, "_str_%d %%s", len);
  322. X        break;
  323. X    }
  324. X    return buf;
  325. X}
  326. X
  327. X/*
  328. X * Make an entry in the typeset table.  Do nothing if it's in there already.
  329. X */
  330. X
  331. Xtypeset(len) {
  332. X    int cnt;
  333. X
  334. X    for (cnt = 0; typetab != (int *) 0 && typetab[cnt] != 0; cnt++)
  335. X        if (typetab[cnt] == len)
  336. X            return;
  337. X    cnt += 2;
  338. X    if ((typetab = (int *) (typetab == (int *) 0? malloc(cnt * sizeof (int)): realloc(typetab, cnt * sizeof (int)))) == (int *) 0) {
  339. X        yyerror("out of memory for defined type table");
  340. X        exit(1);
  341. X    }
  342. X    typetab[cnt - 2] = len;
  343. X    typetab[cnt - 1] = 0;
  344. X    puthead("typedef char _str_%d[%d];\n", len, len);
  345. X}
  346. X
  347. X/*
  348. X * input() next call will start a date, to a ')'.  Parse the date, eat the
  349. X * ')', and output the internal (short) value of the date.  `/' only.
  350. X * Actually, times are handled as well; the deciding factor is whether
  351. X * a '/' or a ':' is used.
  352. X *
  353. X * Three special cases: (nulldate), "hour", and "today".  (I can't specify
  354. X * nulldate's form in a comment for obvious reasons; the string is the standard
  355. X * UNIFY one.)
  356. X */
  357. X
  358. Xparsedate() {
  359. X    char dbuf[256], term[2];
  360. X    int ch, cnt;
  361. X    int date[3], ck[3];
  362. X    short d;
  363. X
  364. X    for (cnt = 0; (ch = input()) != 0 && ch != '\n' && ch != ')'; cnt++)
  365. X        dbuf[cnt] = ch;
  366. X    dbuf[cnt] = '\0';
  367. X    if (ch != ')' || cnt == 0) {
  368. X        yyerror("unterminated or empty date/time constant");
  369. X        fprintf(stf, "$(%s", dbuf);
  370. X        return;
  371. X    }
  372. X    if (strcmp(dbuf, "**/**/**") == 0) {
  373. X        fprintf(stf, "%d", NULLDATE);
  374. X        return;
  375. X    }
  376. X    if (strcmp(dbuf, "today") == 0) {
  377. 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))");
  378. X        if (!diddate)
  379. X            puthead("#include <time.h>\nstatic int _u__today[3];\nstatic long _u__now;\nstatic struct tm *_u__date;\n");
  380. X        diddate = 1;
  381. X        return;
  382. X    }
  383. X    if (strcmp(dbuf, "hour") == 0) {
  384. X        fprintf(stf, "(_u__now = time((long *) 0), _u__date = localtime(&_u__now), _u__date->tm_hour * 100 + _u__date->tm_min)");
  385. X        if (!diddate)
  386. X            puthead("#include <time.h>\nstatic int _u__today[3];\nstatic long _u__now;\nstatic struct tm *_u__date;\n");
  387. X        diddate = 1;
  388. X        return;
  389. X    }
  390. X    dbuf[cnt++] = ')';    /* hack for sscanf checking */
  391. X    dbuf[cnt] = '\0';
  392. X    if ((cnt = sscanf(dbuf, "%d:%d%[)]", &date[0], &date[1], term)) == 3) {
  393. X        if (date[0] < 0 || date[0] > 23) {
  394. X            yyerror("syntax error in time/hour");
  395. X            fprintf(stf, "$(%s", dbuf);
  396. X            return;
  397. X        }
  398. X        if (date[1] < 0 || date[1] > 59) {
  399. X            yyerror("syntax error in time/minute");
  400. X            fprintf(stf, "$(%s", dbuf);
  401. X            return;
  402. X        }
  403. X        fprintf(stf, "%d", date[0] * 100 + date[1]);
  404. X        return;
  405. X    }
  406. X    if ((cnt = sscanf(dbuf, "%d/%d/%d%[)]", &date[0], &date[1], &date[2], term)) != 4) {
  407. X        yyerror("syntax error in date (section %d)", cnt);
  408. X        fprintf(stf, "$(%s", dbuf);
  409. X        return;
  410. X    }
  411. X    d = kday(date);
  412. X    kdate(d, ck);
  413. X    if (!ivcmp(ck, date, sizeof date)) {
  414. X        yyerror("invalid date spec");
  415. X        d = NULLDATE;
  416. X    }
  417. X    fprintf(stf, "%d", d);
  418. X}
  419. ________This_Is_The_END________
  420. if test `wc -l < genpgm.c` -ne 338; then
  421.     echo 'shar: genpgm.c was damaged during transit (should have been 338 bytes)'
  422. fi
  423. fi        ; : end of overwriting check
  424. echo 'x - usp.man'
  425. if test -f usp.man; then echo 'shar: not overwriting usp.man'; else
  426. sed 's/^X//' << '________This_Is_The_END________' > usp.man
  427. X'''
  428. X''' USP (UNIFY(r) Selection Preprocessor)
  429. X'''
  430. X.TH USP 1L
  431. X.SH NAME
  432. Xusp \- unify(R) selection preprocessor
  433. X.SH SYNOPSIS
  434. X.B usp <
  435. X.I file.c
  436. X.B >
  437. X.I outfile.c
  438. X.SH DESCRIPTION
  439. X.I Usp
  440. Xis a preprocessor for C programs which use the Unify\*R C HLI.  It obviates
  441. Xthe need for the Unify preprocessor,
  442. X.BR upp ,
  443. Xand the include file
  444. X.IR file.h ,
  445. Xwhile providing more features including automatic date translation and a
  446. Xsimple selection language.
  447. X.SH USAGE
  448. X.SS Invocation
  449. XAt present, the
  450. X.B usp
  451. Xcommand reads a C program from standard input and writes a modified copy of
  452. Xthe program to standard output.  The modifications are triggered by a dollar
  453. Xsign character
  454. X.BR ($) .
  455. XThe output file is preceded by definitions used by the succeeding code.
  456. X.SS Syntax
  457. X.BR Usp 's
  458. Xtranslation capabilities are triggered by a dollar sign character.  If the
  459. Xcharacter appears in column 1 of a line, it triggers a command translation.
  460. XIf the character is in any other column, it triggers a record, field or date
  461. Xtranslation.
  462. X.SS Command syntax
  463. XThe 
  464. X.B usp
  465. Xcommand processor recognizes a limited subset of commands associated with
  466. Xdata selection and retrieval.  The command syntax is described by the
  467. Xfollowing BNF syntax:
  468. X.de Bs
  469. X.in +15
  470. X.ll -5
  471. X.sp 2
  472. X.ns
  473. X..
  474. X.de Bn
  475. X.ti -10
  476. X.sp
  477. X\\$1 ::= \\$2
  478. X.if \w\\$3 | \\$3
  479. X.if \w\\$4 | \\$4
  480. X.if \w\\$5 | \\$5
  481. X.if \w\\$6 | \\$6
  482. X.if \w\\$7 | \\$7
  483. X.if \w\\$8 | \\$8
  484. X.if \w\\$9 | \\$9
  485. X..
  486. X.de Be
  487. X.in -15
  488. X.ll +5
  489. X.sp 2
  490. X.ns
  491. X..
  492. X.Bs
  493. X.Bn <command> <define> <get> <put> <foreach> <select> <sort>
  494. X.Bn <define> "define <variable> { like <field> | <type> } ;"
  495. X.Bn <get> "get <variable> = <field> ;"
  496. X.Bn <put> "put <field> = <variable> ;"
  497. X.Bn <foreach> "foreach <selection> {"
  498. X.Bn <select> "select { <selection> | interrupt <switch> }"
  499. X.Bn <sort> "sort messages <switch>"
  500. X.Bn <selection> "<record> [[of <record>] [where <condition>] [by <keys>] | key <const>]"
  501. X.Bn <switch> on off
  502. X.Bn <condition> <basic> "<condition> and <basic>"
  503. X.Bn <basic> "<field> <op> <variable>"
  504. X.Bn <op> = ^= > >= < <=
  505. X.Bn <type> "numeric <integer>" "amount <integer>" "float <integer>" "string <integer>" date time
  506. X.Bn <field> "[<record>.]<fsyn>"
  507. X.Bn <variable> "[&]<identifier>" <string>
  508. X.Bn <keys> <key> "<keys> , <key>"
  509. X.Bn <key> <field> "<key> -> <field>"
  510. X.Be
  511. XNote that
  512. X.BR <integer> , " <string>" ", and " <identifier>
  513. Xare standard C constructs; refer to a C programming manual for more information.
  514. X.SS Commands
  515. XThe following commands are accepted by 
  516. X.BR usp :
  517. X.RS 5
  518. X.IP "define <variable>" 5
  519. XDefine a variable, either "like" a database field or as a Unify\*R type.  This
  520. Xis basically a convenience.
  521. X.IP "get <variable> = <field>" 5
  522. XAssign the contents of a database field to a variable.  This is essentially a
  523. X.IR gfield ,
  524. Xwith the exception that a string field will automatically be null-terminated
  525. Xat the end of its defined length.  This requires that a string variable be
  526. Xdefined one character longer than the corresponding Unify\*R field; the
  527. X.B define
  528. Xcommand already does this.
  529. X.IP "put <field> = <variable>" 5
  530. XThe inverse of
  531. X.BR get ;
  532. Xit does a
  533. X.I pfield
  534. Xoperation.  It will call
  535. X.I error
  536. Xif the operation fails.
  537. X.IP "foreach <selection>" 5
  538. XThe first of the selection commands; it is capable of dealing with multiple
  539. Xreturned records.  It begins a loop which, in the generated program, is a
  540. X.I for
  541. Xloop.  See
  542. X.I Selections
  543. Xfor more information.
  544. X.IP "select <selection>" 5
  545. XThe other selection command; it returns exactly one record.
  546. X.IP "select interrupt <switch>" 5
  547. Xcontrols whether queries may be interrupted; if a 
  548. X.B foreach
  549. Xquery is interupted, the enclosed loop is not executed.
  550. X.IP "sort messages <switch>" 5
  551. XThe
  552. X.B sort messages
  553. Xcommand controls whether the sorting versions of the
  554. X.B foreach
  555. Xcommand will display the messages
  556. X.IR Selecting , " Sorting" ", and " Formatting" .
  557. X.RE
  558. X.SS Selections
  559. XA
  560. X.B selection
  561. Xis a specification of which rows of which table will be returned by a query.
  562. XIt is not as complex as is possible with
  563. X.BR SQL ,
  564. Xbut is complex enough to simplify many programming projects.
  565. X.P
  566. XThe basic form of a selection is shown by the BNF syntax above.  The only
  567. Xsemantic conditions are as follows:
  568. X.RS 5
  569. X.IP -
  570. XThe syntax
  571. X.B foreach ... key
  572. Xis illegal;
  573. X.IP -
  574. XThe syntax
  575. X.B select ... by
  576. Xis illegal; and
  577. X.IP -
  578. XThe `&' character is required on non-string variables.
  579. X.RE
  580. X.P
  581. XThe `of' keyword exploits explicit relationships.  It also determines
  582. Xautomatically whether the relationship is being followed in a one-to-many or a
  583. Xmany-to-one direction.
  584. X.P
  585. XSorting is always in ascending order; the "->" syntax is used to follow
  586. Xexplicit relationship chains.  See the descrition of the
  587. X.I unisort
  588. Xfunction in the Unify\*R Programmer's manual, but note that the "->" chain is
  589. Xreversed in order from the sort array.
  590. X.SS Non-command syntax
  591. XThe 
  592. X.B usp
  593. Xprocessor also translates bjects when it sees a `$' character in the middle of
  594. Xa line.  In this case, the character following the $ is inspected.  If it is a
  595. Xleft parenthesis `(', then the object is a date.  Dates have the following syntax:
  596. X.RS 20
  597. X.sp
  598. X$(mm/dd/yy)
  599. X.br
  600. X$(**/**/**)
  601. X.br
  602. X$(today)
  603. X.sp
  604. X.RE
  605. XThe `$(today)' syntax expands to a static function call.
  606. X.P
  607. XIf the character following the `$' is not a left parenthesis, then the following
  608. Xidentifier is interpreted as a record or short field name.  If it cannot be
  609. Xtranslated as either, an error occurs.
  610. X.SH "SEE ALSO"
  611. XThe Unify\*R Programmer's Manual
  612. X.SH ACKNOWLEDGEMENTS
  613. XUnify is a registered trademark of Unify Corporation.
  614. X.SH BUGS
  615. XIt is likely that hand-coding selections would produce more optimal code,
  616. Xalthough 
  617. X.B usp
  618. Xtries valiantly and recognizes at least twelve kinds of queries.
  619. X.P
  620. XThe 
  621. X.B $field
  622. Xconstruct should allow
  623. X.I field.record
  624. Xsyntax.  This, alas, would require a much more complex parser.
  625. X.P
  626. XAll programs have a two-line definition prepended to them, whether the
  627. Xdefinition is used or not.
  628. X.P
  629. XIf two separate source files for a program use the `$(today)' structure, each
  630. Xfile will have a static function prepended to it.  This is somewhat wasteful
  631. Xbut avoids having to link a special library into the program.
  632. ________This_Is_The_END________
  633. if test `wc -l < usp.man` -ne 205; then
  634.     echo 'shar: usp.man was damaged during transit (should have been 205 bytes)'
  635. fi
  636. fi        ; : end of overwriting check
  637. echo 'x - usp.y'
  638. if test -f usp.y; then echo 'shar: not overwriting usp.y'; else
  639. sed 's/^X//' << '________This_Is_The_END________' > usp.y
  640. X%token FOREACH OF WHERE BY AND BETWEEN kNOT DEFINE LIKE STRING AMOUNT kDATE
  641. X%token TIME NUMERIC FLOAT GET PUT SORT MESSAGES INTERRUPT OFF ON KEY SELECT
  642. X%token GE LE NE PTR
  643. X%token tRECORD tFIELD tCONST tNUM
  644. X
  645. X%union {
  646. X    char str[256];
  647. X    int fld;
  648. X    int rec;
  649. X    int opcode;
  650. X    struct {
  651. X        int nfld;
  652. X        int *spec;
  653. X    } sort;
  654. X    int flag;
  655. X    int num;
  656. X}
  657. X
  658. X%type <fld> field of
  659. X%type <rec> tRECORD
  660. X%type <str> tCONST tFIELD type varlist
  661. X%type <sort> sortspec
  662. X%type <opcode> op
  663. X%type <flag> by not switch where key
  664. X%type <num> tNUM selection
  665. X
  666. X%{
  667. X
  668. X#include <unisel.h>
  669. X#include <fdesc.h>
  670. X#include <dbtypes.h>
  671. X
  672. Xint crec, jrec, jfld;
  673. Xlong seqn = 0L, xseq = 0L;
  674. Xint didumsg = 0, didusdcl = 0, didssdcl = 0;
  675. X
  676. Xextern char *malloc();
  677. Xextern char *realloc();
  678. Xextern char *recname();
  679. Xextern char *fldsyn();
  680. X
  681. X#define SEL_REL        8
  682. X#define SEL_VALUE    4
  683. X#define SEL_KEY        2
  684. X#define SEL_SORT    1
  685. X
  686. X%}
  687. X
  688. X%%
  689. X
  690. Xcommand        : FOREACH selection '{'
  691. X            {
  692. X                if ($2 & SEL_KEY) {
  693. X                    yyerror("`foreach ... key' makes no sense");
  694. X                    YYERROR;
  695. X                }
  696. X                switch ($2) {
  697. X                case 0:
  698. X                    putsel("for (__i__er_ = seqacc(%d, 1); __i__er_ == 0; __i__er_ = seqacc(%d, 2)) {", crec, crec);
  699. X                    break;
  700. X                case SEL_VALUE:
  701. X                case SEL_REL|SEL_VALUE:
  702. X                    putsel("\n\1for ((__i__er_ != 0? __i__er_: (__i__er_ = frstsel(__f_%d))); __i__er_ > 0; __i__er_ = nextsel(__f_%d)) {", seqn, seqn);
  703. X                    break;
  704. X                case SEL_REL:
  705. X                    if (jfld < 0) {
  706. X                        yyerror("cannot use `foreach' on join to parent");
  707. X                        YYERROR;
  708. X                    }
  709. X                    putsel("\n\1for (__i__er_ = nextrec(%d, %d); __i__er_ == 0; __i__er_ = nextrec(%d, %d)) {", reckey(jrec), jfld, reckey(jrec), jfld);
  710. X                    break;
  711. X                case SEL_REL|SEL_SORT:
  712. X                case SEL_REL|SEL_VALUE|SEL_SORT:
  713. X                case SEL_VALUE|SEL_SORT:
  714. X                case SEL_SORT:
  715. X                    putsel("\n\1for (__i__er_ = sfrstrec(%d, %d); __i__er_ == 0; __i__er_ = snextrec(%d, %d)) {", reckey(jrec), jfld, reckey(jrec), jfld);
  716. X                    break;
  717. X                }
  718. X                YYACCEPT;
  719. X            }
  720. X        | DEFINE varlist type ';'
  721. X            {
  722. X                char vbuf[1024];
  723. X
  724. X                sprintf(vbuf, $3, $2);
  725. X                putsel("%s;", vbuf);
  726. X                YYACCEPT;
  727. X            }
  728. X        | GET tCONST '=' field ';'
  729. X            {
  730. X                FLDESC fd;
  731. X                char *cp;
  732. X
  733. X                if ($2[0] == '"') {
  734. X                    yyerror("syntax error");
  735. X                    YYERROR;
  736. X                }
  737. X                fldesc($4, &fd);
  738. X                if (fd.f_typ != STRNG && fd.f_typ != COMB && $2[0] != '&')
  739. X                    cp = "&";
  740. X                else
  741. X                    cp = "";
  742. X                putsel("gfield(%d, %s%s)", $4, cp, $2);
  743. X                if (fd.f_typ == STRNG)
  744. X                    putsel(", %s[%d] = '\\0'", $2, fd.f_len);
  745. X                putsel(";");
  746. X                YYACCEPT;
  747. X            }
  748. X        | PUT field '=' tCONST ';'
  749. X            {
  750. X                FLDESC fd;
  751. X                char *cp;
  752. X
  753. X                fldesc($2, &fd);
  754. X                if (fd.f_typ != STRNG && fd.f_typ != COMB && $4[0] != '&')
  755. X                    cp = "&";
  756. X                else
  757. X                    cp = "";
  758. X                putsel("if ((__i__er_ = pfield(%d, %s%s)) != 0)\n\1\terror(\"pfield %s\", __i__er_);", $2, cp, $4);
  759. X                YYACCEPT;
  760. X            }
  761. X        | SORT MESSAGES switch ';'
  762. X            {
  763. X                if (!didumsg)
  764. X                    puthead("extern int _No_Umsgs;\n");
  765. X                didumsg = 1;
  766. X                putsel("_No_Umsgs = %d;", !$3);
  767. X                YYACCEPT;
  768. X            }
  769. X        | SELECT select_cmd ';'
  770. X            {
  771. X                YYACCEPT;
  772. X            }
  773. X        ;
  774. X
  775. Xselect_cmd    : INTERRUPT switch
  776. X            {
  777. X                putsel("setintr(%d);", ($2? INTR_ON: INTR_OFF));
  778. X
  779. X            }
  780. X        | selection
  781. X            {
  782. X                if ($1 & SEL_SORT) {
  783. X                    yyerror("you cannot use a `by' phrase in a `select' statement");
  784. X                    YYERROR;
  785. X                }
  786. X                switch ($1) {
  787. X                case 0:
  788. X                    puthead("static long __n_%d;\n", seqn);
  789. 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);
  790. X                    putsel("\n\1seqacc(%d, 1);", crec);
  791. X                    break;
  792. X                case SEL_KEY:
  793. X                    break;
  794. X                case SEL_REL:
  795. X                    if (jfld < 0)
  796. X                        break;
  797. 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);
  798. X                    /*FALLTHROUGH*/
  799. X                default:
  800. X                    putsel("\n\1if ((__i__er_ = frstrec(__f_%d)) != 0)\n\1\terror(\"frstrec %s\", __i__er_);", seqn, recname(crec));
  801. X                }
  802. X            }
  803. X        ;
  804. X
  805. Xswitch        : OFF
  806. X            {
  807. X                $$ = 0;
  808. X            }
  809. X        | ON
  810. X            {
  811. X                $$ = 1;
  812. X            }
  813. X        ;
  814. X
  815. Xselection    : tRECORD
  816. X            {
  817. X                seqn++;
  818. X                crec = $1;
  819. X            }
  820. X          of where key by
  821. X              {
  822. X                int v;
  823. X                char vbuf[256];
  824. X                FLDESC fd;
  825. X
  826. X                v = ($3 == 0? 0: SEL_REL)|($4? SEL_VALUE: 0)|($5? SEL_KEY: 0)|($6? SEL_SORT: 0);
  827. X                if ($5 && ($3 != 0 || $4 || $6)) {
  828. X                    yyerror("cannot use `key' with `of' or `where'");
  829. X                    YYERROR;
  830. X                }
  831. X                if ($3 < 0 && ($4 || $6)) {
  832. X                    yyerror("cannot use `where' or `by' on join to parent");
  833. X                    YYERROR;
  834. X                }
  835. X                switch (v) {
  836. X                case SEL_REL:
  837. X                    if ($3 < 0)
  838. X                        putsel("if ((__i__er_ = faccess(%d, %d)) != 0)\n\1\terror(\"faccess %s\", __i__er_);", crec, - $3, recname(crec));
  839. X                    else {
  840. X                        puthead("static long __n_%d;\n", seqn);
  841. 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));
  842. X                        putsel("\n\1setsize(%d, %d, &__n_%d);", reckey(jrec), $3, seqn);
  843. X                    }
  844. X                    jfld = $3;
  845. X                    break;
  846. X                case SEL_REL|SEL_SORT:
  847. X                    if (!didssdcl) {
  848. X                        didssdcl = 1;
  849. X                        puthead("static int (*__no_f__[])() = {0, 0, 0, 0};\n");
  850. X                    }
  851. X                    putsel("(void) unisort(%d, %d, __s_%d, __no_f__);", jrec, $3, seqn);
  852. X                    jfld = $3;
  853. X                    break;
  854. X                case 0:
  855. X                case SEL_KEY:
  856. X                    break;
  857. X                case SEL_REL|SEL_VALUE:
  858. X                    fldesc(reckey(jrec), &fd);
  859. X                    sprintf(vbuf, utype(fd.f_typ, (fd.f_typ == FLT? fd.f_len * 10: fd.f_len)), "__j_%d");
  860. X                    puthead("static ");
  861. X                    puthead(vbuf, ++xseq);
  862. X                    puthead(";\n");
  863. X                    fldesc($3, &fd);
  864. X                    putsel("gfield(%d, __j_%d);\n\1entsitm(%d, __j_%d, (char *) 0, %d);\n\1", fd.f_rpfld, xseq, $3, xseq, EQ);
  865. X                    /*FALLTHROUGH*/
  866. X                case SEL_VALUE:
  867. X                    if (!didusdcl) {
  868. X                        didusdcl = 1;
  869. X                        puthead("extern struct uselfil *opensf();\n");
  870. X                    }
  871. 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);
  872. X                    putsel("mktemp(__t_%d);\n\1if (__f_%d != (struct uselfil *) 0)\n\1\tclosesf(__f_%d);\n\1", seqn, seqn, seqn);
  873. 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));
  874. 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);
  875. X                    break;
  876. X                case SEL_REL|SEL_VALUE|SEL_SORT:
  877. X                    fldesc(reckey(jrec), &fd);
  878. X                    sprintf(vbuf, utype(fd.f_typ, (fd.f_typ == FLT? fd.f_len * 10: fd.f_len)), "__j_%d");
  879. X                    puthead("static ");
  880. X                    puthead(vbuf, ++xseq);
  881. X                    puthead(";\n");
  882. X                    fldesc($3, &fd);
  883. X                    putsel("gfield(%d, __j_%d);\n\1entsitm(%d, __j_%d, (char *) 0, %d);\n\1", fd.f_rpfld, xseq, $3, xseq, EQ);
  884. X                    /*FALLTHROUGH*/
  885. X                case SEL_SORT:
  886. X                case SEL_VALUE|SEL_SORT:
  887. X                    if (!didssdcl) {
  888. X                        didssdcl = 1;
  889. X                        puthead("static int (*__no_f__[])() = {0, 0, 0, 0};\n");
  890. X                    }
  891. 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));
  892. X                    jfld = SS;
  893. X                    jrec = crec;
  894. X                    break;
  895. X                default:
  896. X                    yyerror("illegal combination of selection phrases (%d)", v);
  897. X                    YYERROR;
  898. X                }
  899. X                $$ = v;
  900. X            }
  901. X        ;
  902. X
  903. Xwhere        : /* none */
  904. X            {
  905. X                $$ = 0;
  906. X            }
  907. X        | WHERE selfield
  908. X            {
  909. X                $$ = 1;
  910. X            }
  911. X        ;
  912. X
  913. Xof        : /* none */
  914. X            {
  915. X                $$ = 0;
  916. X            }
  917. X        | OF tRECORD
  918. X            {
  919. X                int cnt;
  920. X                FLDESC fd;
  921. X
  922. X                for (cnt = numflds(); cnt > 0; cnt--)
  923. X                    if (!fldesc(cnt, &fd))
  924. X                        continue;
  925. X                    else if (fd.f_rec == crec && fd.f_rprec == $2)
  926. X                        break;
  927. X                    else if (fd.f_rec == $2 && fd.f_rprec == crec)
  928. X                        break;
  929. X                if (cnt == 0) {
  930. X                    yyerror("record type %s does not join to %s", recname($2), recname(crec));
  931. X                    YYERROR;
  932. X                }
  933. X                jrec = $2;
  934. X                $$ = (fd.f_rec == crec? cnt: -cnt);
  935. X            }
  936. X        ;
  937. X
  938. Xkey        : /* none */
  939. X            {
  940. X                $$ = 0;
  941. X            }
  942. X        | KEY tCONST
  943. X            {
  944. X                FLDESC fd;
  945. X                char *cp;
  946. X                int thekey;
  947. X
  948. X                if ((thekey = reckey(crec)) == 0) {
  949. X                    yyerror("record type %s has no key", recname(crec));
  950. X                    YYERROR;
  951. X                }
  952. X                fldesc(thekey, &fd);
  953. X                if (fd.f_typ != STRNG && fd.f_typ != COMB && $2[0] != '&')
  954. X                    cp = "&";
  955. X                else
  956. X                    cp = "";
  957. X                putsel("if ((__i__er_ = acckey(%d, %s%s)) != 0)\n\1\terror(\"acckey %s\", __i__er_);", crec, cp, $2, recname(crec));
  958. X                $$ = 1;
  959. X            }
  960. X        ;
  961. X
  962. Xselfield    : sel
  963. X        | selfield AND sel
  964. X        ;
  965. X
  966. Xsel        : field op tCONST
  967. X            {
  968. X                FLDESC fd;
  969. X
  970. X                fldesc($1, &fd);
  971. X                if (fd.f_rec != crec) {
  972. X                    yyerror("field %s is not in record type %s", fldsyn($1), recname(crec));
  973. X                    YYERROR;
  974. X                }
  975. X                putsel("entsitm(%d, %s, (char *) 0, %d);\n\1", $1, $3, $2);
  976. X            }
  977. X        | field not BETWEEN tCONST AND tCONST
  978. X            {
  979. X                FLDESC fd;
  980. X
  981. X                fldesc($1, &fd);
  982. X                if (fd.f_rec != crec) {
  983. X                    yyerror("field %s is not in record type %s", fldsyn($1), recname(crec));
  984. X                    YYERROR;
  985. X                }
  986. X                putsel("entsitm(%d, %s, %s, %d);\n\1", $1, $4, $6, ($2? NOT: EQ));
  987. X            }
  988. X        ;
  989. X
  990. Xnot        : /* none */
  991. X            {
  992. X                $$ = 0;
  993. X            }
  994. X        | kNOT
  995. X            {
  996. X                $$ = 1;
  997. X            }
  998. X        ;
  999. X
  1000. Xby        : /* none */
  1001. X            {
  1002. X                $$ = 0;
  1003. X            }
  1004. X        | BY
  1005. X            {
  1006. X                puthead("static int __s_%d[] = {\n", seqn);
  1007. X            }
  1008. X          sortlist
  1009. X            {
  1010. X                puthead("-1};\n");
  1011. X                $$ = 1;
  1012. X            }
  1013. X        ;
  1014. X
  1015. Xsortlist    : sort
  1016. X        | sortlist ',' sort
  1017. X        ;
  1018. X
  1019. Xsort        : sortspec
  1020. X            {
  1021. X                int cnt;
  1022. X
  1023. X                for (cnt = $1.nfld; cnt > 0; cnt--)
  1024. X                    puthead(" %d,", $1.spec[cnt - 1]);
  1025. X                puthead(" 0,\n");
  1026. X                free($1.spec);
  1027. X            }
  1028. X        ;
  1029. X
  1030. Xsortspec    : field
  1031. X            {
  1032. X                FLDESC fd;
  1033. X
  1034. X                fldesc($1, &fd);
  1035. X                if (fd.f_rec != crec) {
  1036. X                    yyerror("field %s is not in record type %s", fldsyn($1), recname(crec));
  1037. X                    YYERROR;
  1038. X                }
  1039. X                $$.nfld = 1;
  1040. X                if (($$.spec = (int *) malloc(sizeof (int))) == (int *) 0) {
  1041. X                    yyerror("out of memory in firstsort");
  1042. X                    YYERROR;
  1043. X                }
  1044. X                 $$.spec[0] = $1;
  1045. X            }
  1046. X        | sortspec PTR field
  1047. X            {
  1048. X                FLDESC fd, jfd;
  1049. X
  1050. X                fldesc($3, &fd);
  1051. X                fldesc($1.spec[$$.nfld - 1], &jfd);
  1052. X                if (jfd.f_rprec != fd.f_rec) {
  1053. X                    yyerror("no explicit relationship between %s and %s.%s", fldsyn($1), recname(fd.f_rec), fldsyn(reckey(fd.f_rec)));
  1054. X                    YYERROR;
  1055. X                }
  1056. X                $$ = $1;
  1057. X                if (($$.spec = (int *) realloc($$.spec, (unsigned) ++$$.nfld * sizeof (int))) == (int *) 0) {
  1058. X                    yyerror("out of memory in nextsort");
  1059. X                    YYERROR;
  1060. X                }
  1061. X                $$.spec[$$.nfld - 1] = $3;
  1062. X            }
  1063. X        ;
  1064. X
  1065. Xfield        : tFIELD
  1066. X            {
  1067. X                int cnt;
  1068. X                char *cp;
  1069. X
  1070. X                for (cnt = 1; cnt <= numflds(); cnt++) {
  1071. X                    if ((cp = fldsyn(cnt)) == (char *) 0)
  1072. X                        continue;
  1073. X                    if (strcmp(cp, $1) == 0)
  1074. X                        break;
  1075. X                }
  1076. X                $$ = cnt;
  1077. X            }
  1078. X        | tRECORD '.' tFIELD
  1079. X            {
  1080. X                FLDESC fd;
  1081. X                int cnt;
  1082. X                char *cp;
  1083. X
  1084. X                for (cnt = numflds(); cnt > 0; cnt--) {
  1085. X                    if ((cp = fldsyn(cnt)) == (char *) 0)
  1086. X                        continue;
  1087. X                    if (strcmp(cp, $3) != 0)
  1088. X                        continue;
  1089. X                    fldesc(cnt, &fd);
  1090. X                    if (fd.f_rec == $1)
  1091. X                        break;
  1092. X                }
  1093. X                if (cnt == 0) {
  1094. X                    yyerror("field %s is not in record type %s", $3, recname($1));
  1095. X                    YYERROR;
  1096. X                }
  1097. X                $$ = cnt;
  1098. X            }
  1099. X        ;
  1100. X
  1101. Xop        : '>'
  1102. X            {
  1103. X                $$ = GT;
  1104. X            }
  1105. X        | '='
  1106. X            {
  1107. X                $$ = EQ;
  1108. X            }
  1109. X        | '<'
  1110. X            {
  1111. X                $$ = LT;
  1112. X            }
  1113. X        | LE
  1114. X            {
  1115. X                $$ = LTE;
  1116. X            }
  1117. X        | GE
  1118. X            {
  1119. X                $$ = GTE;
  1120. X            }
  1121. X        | NE
  1122. X            {
  1123. X                $$ = NOT;
  1124. X            }
  1125. X        ;
  1126. X
  1127. Xtype        : LIKE field
  1128. X            {
  1129. X                FLDESC fd;
  1130. X
  1131. X                fldesc($2, &fd);
  1132. X                strcpy($$, utype(fd.f_typ, (fd.f_typ == FLT? fd.f_len * 10: fd.f_len)));
  1133. X            }
  1134. X        | STRING tNUM
  1135. X            {
  1136. X                strcpy($$, utype(STRNG, $2));
  1137. X            }
  1138. X        | NUMERIC tNUM
  1139. X            {
  1140. X                strcpy($$, utype(($2 > 4? LONG: INT), $2));
  1141. X            }
  1142. X        | AMOUNT tNUM
  1143. X            {
  1144. X                strcpy($$, utype(($2 > 7? HAMT: AMT), $2));
  1145. X            }
  1146. X        | FLOAT tNUM
  1147. X            {
  1148. X                strcpy($$, utype(FLT, $2));
  1149. X            }
  1150. X        | kDATE
  1151. X            {
  1152. X                strcpy($$, utype(DATE, 0));
  1153. X            }
  1154. X        | TIME
  1155. X            {
  1156. X                strcpy($$, utype(HR, 0));
  1157. X            }
  1158. X        ;
  1159. X
  1160. Xvarlist        : tCONST
  1161. X            {
  1162. X                if ($1[0] == '"' || $1[0] == '&') {
  1163. X                    yyerror("syntax error");
  1164. X                    YYERROR;
  1165. X                }
  1166. X                strcpy($$, $1);
  1167. X            }
  1168. X        | varlist ',' tCONST
  1169. X            {
  1170. X                if ($3[0] == '"' || $3[0] == '&') {
  1171. X                    yyerror("syntax error");
  1172. X                    YYERROR;
  1173. X                }
  1174. X                strcpy($$, $1);
  1175. X                strcat($$, ", ");
  1176. X                strcat($$, $3);
  1177. X            }
  1178. X        ;
  1179. X
  1180. X%%
  1181. ________This_Is_The_END________
  1182. if test `wc -l < usp.y` -ne 541; then
  1183.     echo 'shar: usp.y was damaged during transit (should have been 541 bytes)'
  1184. fi
  1185. fi        ; : end of overwriting check
  1186. echo 'x - usptok.l'
  1187. if test -f usptok.l; then echo 'shar: not overwriting usptok.l'; else
  1188. sed 's/^X//' << '________This_Is_The_END________' > usptok.l
  1189. X%{
  1190. X
  1191. X#include "y.tab.h"
  1192. X
  1193. X#undef input
  1194. X#undef unput
  1195. X
  1196. Xchar _curline[1024];
  1197. Xchar _unput[1024];
  1198. Xint _curcol;
  1199. Xint _curunp = 0;
  1200. Xint indent = 0;
  1201. Xint _ign_ = 0;
  1202. Xextern int nlflag;
  1203. Xextern char *srcfile;
  1204. X
  1205. Xstatic g_input() {
  1206. X    if (_curunp > 0) {
  1207. X        if (_unput[--_curunp] == '\n')
  1208. X            yylineno++;
  1209. X        return _unput[_curunp];
  1210. X    }
  1211. X    while (_curline[_curcol] == '\0') {
  1212. X        if (fgets(_curline, sizeof _curline, yyin) == (char *) 0)
  1213. X            return 0;
  1214. X        _curcol = 0;
  1215. X    }
  1216. X    if (_curline[_curcol] == '\n')
  1217. X        yylineno++;
  1218. X    return _curline[_curcol++];
  1219. X}
  1220. X        
  1221. Xinput() {
  1222. X    int ch;
  1223. X
  1224. X    ch = g_input();
  1225. X    if (!_ign_ && nlflag) {
  1226. X        if (ch == ' ')
  1227. X            indent++;
  1228. X        else if (ch == '\t')
  1229. X            do {
  1230. X                indent++;
  1231. X            } while (indent % 8 != 0);
  1232. X    }
  1233. X    return ch;
  1234. X}
  1235. X
  1236. Xunput(c) {
  1237. X    if (_curunp == 0 && _curcol > 0 && _curline[_curcol - 1] == c)
  1238. X        _curcol--;
  1239. X    else if (_curunp == sizeof _unput) {
  1240. X        yyerror("internal error: pushback overflow, char %o (octal)", c);
  1241. X        exit(1);
  1242. X    }
  1243. X    else
  1244. X        _unput[_curunp++] = c;
  1245. X    if (c == '\n') {
  1246. X        yylineno--;
  1247. X        nlflag = 0;
  1248. X    }
  1249. X}
  1250. X
  1251. Xextern char *scanon();
  1252. Xextern char *fldsyn();
  1253. Xextern char *recname();
  1254. X
  1255. X#include <dbtypes.h>
  1256. X
  1257. X%}
  1258. X
  1259. X%%
  1260. X
  1261. Xdefine { return DEFINE; }
  1262. Xlike { return LIKE; }
  1263. Xnumeric { return NUMERIC; }
  1264. Xstring { return STRING; }
  1265. Xfloat { return FLOAT; }
  1266. Xamount { return AMOUNT; }
  1267. Xdate { return kDATE; }
  1268. Xtime { return TIME; }
  1269. Xget { return GET; }
  1270. Xput { return PUT; }
  1271. Xforeach { return FOREACH; }
  1272. Xof { return OF; }
  1273. Xwhere { return WHERE; }
  1274. Xby { return BY; }
  1275. Xand { return AND; }
  1276. Xbetween { return BETWEEN; }
  1277. Xnot { return kNOT; }
  1278. Xselect { return SELECT; }
  1279. Xkey { return KEY; }
  1280. Xsort { return SORT; }
  1281. Xmessages { return MESSAGES; }
  1282. Xinterrupt { return INTERRUPT; }
  1283. Xon { return ON; }
  1284. Xoff { return OFF; }
  1285. X">=" { return GE; }
  1286. X"<=" { return LE; }
  1287. X"!=" { return NE; }
  1288. X"^=" { return NE; }
  1289. X"->" { return PTR; }
  1290. X\&?[A-Za-z_][A-Za-z0-9_]* {
  1291. X    int cnt;
  1292. X    char *p;
  1293. X
  1294. X    strcpy(yylval.str, yytext);
  1295. X    for (cnt = numrecs(); cnt > 0; cnt--) {
  1296. X        if ((p = recname(cnt)) == (char *) 0)
  1297. X            continue;
  1298. X        if (strcmp(p, yytext) == 0) {
  1299. X            yylval.rec = cnt;
  1300. X            return tRECORD;
  1301. X        }
  1302. X    }
  1303. X    for (cnt = numflds(); cnt > 0; cnt--) {
  1304. X        if ((p = fldsyn(cnt)) == (char *) 0)
  1305. X            continue;
  1306. X        if (strcmp(p, yytext) == 0)
  1307. X            return tFIELD;
  1308. X    }
  1309. X    return tCONST;
  1310. X}
  1311. X-?[0-9]+ {
  1312. X    yylval.num = atoi(yytext);
  1313. X    return tNUM;
  1314. X}
  1315. X\"([^\\n]*\\\")*[^"\n"]*\" {
  1316. X    strcpy(yylval.str, yytext);
  1317. X    return tCONST;
  1318. X}
  1319. X[ \t\n]+ ;
  1320. X. return *yytext;
  1321. X
  1322. X%%
  1323. X
  1324. X#include <varargs.h>
  1325. X
  1326. Xchar *scanon(buf)
  1327. Xregister char *buf; {
  1328. X    static char cbuf[1024];
  1329. X    register short bufc;
  1330. X    char ibuf;
  1331. X
  1332. X    ibuf = *buf;
  1333. X    bufc = 0;
  1334. X    for (buf++; *buf != '\0'; buf++) {
  1335. X        if (*buf == '\\')
  1336. X            cbuf[bufc++] = *++buf;
  1337. X        else if (*buf == ibuf)
  1338. X            break;
  1339. X        else
  1340. X            cbuf[bufc++] = *buf;
  1341. X    }
  1342. X    cbuf[bufc] = '\0';
  1343. X    if (*buf == ibuf && *++buf != '\0')
  1344. X        yyerror("internal error (canon trailing text \"%s\")", buf);
  1345. X    return cbuf;
  1346. X}
  1347. X
  1348. Xyyerror(va_alist)
  1349. Xva_dcl {
  1350. X    va_list args;
  1351. X    char *format;
  1352. X    short uc;
  1353. X
  1354. X    va_start(args);
  1355. X    format = va_arg(args, char *);
  1356. X    fprintf(stderr, "\n\"%s\", line %d: ", srcfile, yylineno);
  1357. X    vfprintf(stderr, format, args);
  1358. X    va_end(args);
  1359. X    fprintf(stderr, "\n> ");
  1360. X    if (_curunp == 0) {
  1361. X        short col;
  1362. X
  1363. X        fprintf(stderr, "%s>-", _curline);
  1364. X        for (uc = 0, col = 2; uc < _curcol - 1; uc++) {
  1365. X            if (_curline[uc] == '\t') {
  1366. X                do {
  1367. X                    putc('-', stderr);
  1368. X                } while (++col % 8 != 0);
  1369. X            }
  1370. X            else {
  1371. X                putc('-', stderr);
  1372. X                col++;
  1373. X            }
  1374. X        }
  1375. X        fprintf(stderr, "^\n");
  1376. X    }
  1377. X     else {
  1378. X        for (uc = _curunp; uc > 0; uc--)
  1379. X            putc(_unput[uc - 1], stderr);
  1380. X        fprintf(stderr, "\n>-^\n");
  1381. X    }
  1382. X}
  1383. ________This_Is_The_END________
  1384. if test `wc -l < usptok.l` -ne 194; then
  1385.     echo 'shar: usptok.l was damaged during transit (should have been 194 bytes)'
  1386. fi
  1387. fi        ; : end of overwriting check
  1388. exit 0
  1389.  
  1390.  
  1391.