home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume2 / usp < prev    next >
Internet Message Format  |  1991-08-07  |  34KB

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