home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / sources / misc / 4128 < prev    next >
Encoding:
Text File  |  1992-11-23  |  55.5 KB  |  1,971 lines

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: richid@owlnet.rice.edu (Richard Parvin Jernigan)
  4. Subject:  v33i123:  mbase - MetalBase 5.0, Portable database engine, Part05/08
  5. Message-ID: <1992Nov23.232524.7609@sparky.imd.sterling.com>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: 7c0f340c8c6f6f5ba8ed9c2f701e46da
  8. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  9. Organization: Sterling Software
  10. References: <csm-v33i119=mbase.165613@sparky.IMD.Sterling.COM>
  11. Date: Mon, 23 Nov 1992 23:25:24 GMT
  12. Approved: kent@sparky.imd.sterling.com
  13. Lines: 1956
  14.  
  15. Submitted-by: richid@owlnet.rice.edu (Richard Parvin Jernigan)
  16. Posting-number: Volume 33, Issue 123
  17. Archive-name: mbase/part05
  18. Environment: AMIGA, MS-DOS, HP-UX, XENIX, UNIX, ULTRIX, SGI, SU, Curses
  19. Supersedes: mbase: Volume 28, Issue 40-44
  20.  
  21. #! /bin/sh
  22. # This is a shell archive.  Remove anything before this line, then feed it
  23. # into a shell via "sh file" or similar.  To overwrite existing files,
  24. # type "sh file -c".
  25. # Contents:  dox/build.dox sample/makefile src/create.c src/entry.c
  26. #   src/form_wr.c src/util2.c
  27. # Wrapped by kent@sparky on Mon Nov 23 16:33:14 1992
  28. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  29. echo If this archive is complete, you will see the following message:
  30. echo '          "shar: End of archive 5 (of 8)."'
  31. if test -f 'dox/build.dox' -a "${1}" != "-c" ; then 
  32.   echo shar: Will not clobber existing file \"'dox/build.dox'\"
  33. else
  34.   echo shar: Extracting \"'dox/build.dox'\" \(10995 characters\)
  35.   sed "s/^X//" >'dox/build.dox' <<'END_OF_FILE'
  36. XBuild Documentation                                               MetalBase 5.0
  37. X-------------------------------------------------------------------------------
  38. X
  39. X                                  Function
  40. X
  41. XRelations are built from schema files, which decribe the relation in a more
  42. Xhuman-friendly syntax.  Schema for MetalBase 4.0 and up relations take the
  43. Xfollowing form (Words in brackets are optional syntax, words enclosed in <>
  44. Xare sample entries):
  45. X
  46. X        [relation] <equipment>
  47. X
  48. X        field <customer>         [type] <string> [length/*] <5> ;
  49. X        field <num_purchased>    [type] <ushort> ;
  50. X        field <part_number>      [type] <char>   [length/*] <4> ;
  51. X        field <shop_address>     [type] <char>   [length/*] <11> ;
  52. X        field <price_code>       [type] <money> ;
  53. X        field <transaction>      [type] <serial> [<start 100>] ;
  54. X
  55. X        index customer [on] customer                 [<with duplicates>] ;
  56. X        index part     [on] part_number,price_code   [with duplicates] ;
  57. X        index ix_price [on] price_code               [<with duplicates>] ;
  58. X
  59. X        [<typedef <equ> >] ;
  60. X
  61. X        end
  62. X
  63. XAh, but note:  4.1 and up expect to find SEMICOLONS after every line save
  64. X"Relation..." and "End"!  It's okay if they're not there, but better get
  65. Xin the habit, 'cause report and form will choke heavily without their
  66. Xsemicolons.
  67. X
  68. XBuild is the program which reads these schema and creates MetalBase-format
  69. Xrelations from them; in addition, build released with mbase 4.0 and up can
  70. Xcreate C-style header files for interface with metalbase routines; these look
  71. Xsomewhat like this:
  72. X
  73. X   #ifndef EQUIPMENT_H
  74. X   #define EQUIPMENT_H
  75. X
  76. X   /*
  77. X    * This file was created by MetalBase version 5.0 to reflect the structure
  78. X    * of the relation "equipment".
  79. X    *
  80. X    * MetalBase 5.0 released October 1992 by virtual!richid@owlnet.rice.edu
  81. X    *
  82. X    */
  83. X
  84. X   typedef struct
  85. X    { char    customer[5];          /* field customer type string length 5   */
  86. X      ushort  num_purch;            /* field num_purch type ushort           */
  87. X      char    part_numb[4];         /* field part_numb type string length 4  */
  88. X      char    shop_addr[11];        /* field shop_addr type string length 11 */
  89. X      double  price_code;           /* field price_code type money           */
  90. X      long    trans;                /* field trans type serial start 100     */
  91. X      } equipment_str;
  92. X
  93. X   #ifndef MODULE
  94. X      equipment_str equipment_rec;
  95. X   #else
  96. X      extern equipment_str equipment_rec;
  97. X   #endif
  98. X
  99. X   #endif
  100. X
  101. XThe headers created by build include actual data (the reference to
  102. X      equipment_str equipment_rec
  103. Xabove), that should be local to only one module of a multiple .c-program
  104. Xexecutable; all the others should have the headers' variables declared as
  105. Xexternal.  So the headers use #ifdefs and check for the definition of MODULE--
  106. Xif it's there, variables are declared external, if not, they're declared local.
  107. XThat way, variables always go in this one piece of .c code.
  108. X
  109. X
  110. X                             Command-Line Options
  111. X
  112. XBuild's command line is rather simple:
  113. X      build [-q] [-h] schemaname
  114. X   Where
  115. X      -q indicates no output should be sent; all questions are assumed to
  116. X         be answered by their defaults.
  117. X      -h indiciates the header file should be created.  When used with -q,
  118. X         this overrides the "No" default answer for build's question; when
  119. X         used without, the header will be created without the user being
  120. X         asked interactively.
  121. X
  122. XThe schemaname may optionally be terminated in .s; if it is missing, it is
  123. Xadded by build.  MetalBase requires that schema be terminated in .s, and
  124. Xrelations in .rel.
  125. X
  126. X
  127. X                                   Format
  128. X
  129. XThe build utility released with versions 3.1 and higher supports comments at
  130. Xthe end of the "field" and "index" lines, and that's it--that's totally
  131. Xpathetic.  5.0 accepts comments anywhere, like a makefile--anything after a
  132. X# is ignored.  Likewise are form and report.  Empty lines are ignored.
  133. X
  134. X        # Comments
  135. X
  136. X        [relation] <equipment>   # Another comment.
  137. X
  138. X        field <custo...
  139. X
  140. X    The first line of a schema simply tells the computer what to call the new
  141. Xrelation.  The word 'relation' is optional, as is all text enclosed in
  142. Xbrackets in the description way up above.
  143. X    The second section of a schema describes the fields of which every record
  144. Xin the relation will be composed.  The word immediately following 'field' is
  145. Xsimply a name for the field.  Fields may be any of twelve types:
  146. X
  147. X       string/char/character    short             unsigned short
  148. X       long                     unsigned long     float
  149. X       double                   money             time
  150. X       date                     serial            phone
  151. X
  152. X   MetalBase 4.0 and up surpass 3.2 in that they understand the following
  153. X   fields that 3.2 just didn't know about:
  154. X      phone  - This corresponds to the typedef mb_phone, which is actually
  155. X               20 characters.  Fields stored in this type of field are parsed
  156. X               before writing into the database, and sorted correctly
  157. X               regardless of missing or extra pieces of data (extensions,
  158. X               area codes, etc).
  159. X      money  - Fields of this type are actually doubles which are automatically
  160. X               rounded by MetalBase before adding them to a relation.  There
  161. X               is no typedef to support this--use double.
  162. X      time   - MetalBase uses a long to contain a 24-hour clock (including
  163. X               precision to microseconds, though the built-in date-n-time
  164. X               routines only go to seconds), and sorts and stores these
  165. X               appropriately.  There is a typedef (mb_time) for these fields.
  166. X      date   - MetalBase uses a long to contain a date, with range from the
  167. X               year -4096 to 4096, and precision down to the day.  Routines
  168. X               are also included to obtain the current date and time, and
  169. X               to manipulate these formats.  There is a typedef (mb_date) for
  170. X               these fields... use mb_date and mb_time fields as if they were
  171. X               longs, for purposes of returning and passing values.
  172. X      serial - Something that has really been missing from MetalBase.  Each
  173. X               relation now has a counter, and every time a new record is
  174. X               added, the counter goes up--it never goes back down.  If the
  175. X               relation has a serial field, it is automatically filled in by
  176. X               the system--set to this counter's value at the time of addition.
  177. X               In this way, each record can be stamped with a serial code for
  178. X               reference--guaranteed to be unique, record to record (and
  179. X               appropriately, any index containing a serial field as part of
  180. X               itself is automatically marked 'no duplicates allowed').  Serial
  181. X               numbers start at zero unless the parameter "start xxx" is
  182. X               specified in the schema.  Serials are represented as longs;
  183. X               there is no typedef.
  184. X
  185. X   The next point of interest is the number after 'length' or '*' in a
  186. Xcharacter field... this number indicates the number of characters in that
  187. Xfield.  MetalBase will allow any positive integer here your computer can
  188. Xhandle, and if any length, or the sum of all lengths, is indeed large, _build_
  189. Xwill prompt you to add certain lines to the beginning of your code to warn the
  190. Xsystem of excessive-length records.
  191. X
  192. X    After all fields have been declared, indicies are placed on fields and
  193. Xcombinations of fields.  MetalBase requires that you have at least one index
  194. Xin any relation (this is only logical--a database without indicies is nothing
  195. Xmore than a text file).  After the word 'index' in each line, the index must
  196. Xbe given a name (whether or not it is used it up to the programmer), followed
  197. Xby names of fields to be indexed, separated by commas (note that this is VERY
  198. XDIFFERENT from previous versions of MetalBase.  Because version 4.0 and up read
  199. Xrecords directly into structures, the vertical bar ("|") is no longer used at
  200. Xall).  If more than one field name appears, MetalBase will declare that index
  201. Xcomposite.
  202. X
  203. X    Occasionally certain data should not be repeated... for instance, a
  204. Xperson obviously cannot visit a physician's office twice at the same time.  In
  205. Xthis case, were a relation defined as consisting of the fields "name" and
  206. X"visit_time", an index would be declared on "name,time" WITHOUT including the
  207. Xwords 'with duplicates', as seen above.  If such a relation were built,
  208. XMetalBase would not allow the space-time continuum to be stretched, as
  209. Xdescribed previously.  Including the words 'with duplicates' after the
  210. Xdefinition of an index removes this error-catching system, for that index
  211. Xalone.  Use of the duplicate-catching system is entirely a case-to-case
  212. Xdecision... there is little difference in the amount of time used between
  213. Ximplementing and not implementing it.
  214. X
  215. X    If the schema described previously exists as "/usr/joe/equip.s", the
  216. Xcommand BUILD, a utility included for use with MetalBase, will create a
  217. Xrelation called "equipment.rel" under the directory "/usr/joe".  A sample
  218. Xoutput of BUILD is as follows:
  219. X
  220. X        % build /usr/joe/equip.s
  221. X        Building relation equipment under current directory
  222. X
  223. X        Fields___________________________________________________
  224. X        customer [char *5]            num_purchased [ushort]
  225. X        part_number [char *4]         shop_address [char *11]
  226. X        price_code [money]            transaction [serial @100]
  227. X
  228. X        Indicies_________________________________________________
  229. X        customer.....customer................Duplicates allowed
  230. X        part.........part_number,price_code..Duplicates not allowed
  231. X        ix_price.....price_code..............Duplicates allowed
  232. X
  233. X        Continue with the creation of the relation [Y/n] ? <y>
  234. X        Create header file for this relation       [y/N] ? <y>
  235. X
  236. X        Header file created.
  237. X        Relation created--zero entries.
  238. X
  239. X        % ls -C /usr/joe
  240. X        equip.s         equipment.rel       equipment.h
  241. X        %
  242. X
  243. X    Once a relation has been built, it contains no entries, and is ready for
  244. Xuse.  BUILD's sole use is the creation of relations... other utilities
  245. X(discussed later) must be used for maintenance of relations (if needed).
  246. X
  247. X    A recent addition to build's operation is its ability to create header
  248. Xfiles for your programs.  When interacting with MetalBase routines, you must
  249. Xpass pointers to structures where data can be placed--build now creates these
  250. Xstructures for you, removing chances for error along with mindless tedium.
  251. XNote that, as in the above example, the line 'typedef equ' has caused the
  252. Xstructure to be named as:
  253. X
  254. X         typedef struct { ... } equ;
  255. X         equ  equ_rec;
  256. X
  257. XIf this line (typedef equ) were not present in the schema, the structure
  258. Xwould have been named with:
  259. X
  260. X         typedef struct { ... } equipment_str;
  261. X         equipment_str  equipment_rec;
  262. X
  263. XThat is, the relation name appended with "_str".
  264. X
  265. END_OF_FILE
  266.   if test 10995 -ne `wc -c <'dox/build.dox'`; then
  267.     echo shar: \"'dox/build.dox'\" unpacked with wrong size!
  268.   fi
  269.   # end of 'dox/build.dox'
  270. fi
  271. if test -f 'sample/makefile' -a "${1}" != "-c" ; then 
  272.   echo shar: Will not clobber existing file \"'sample/makefile'\"
  273. else
  274.   echo shar: Extracting \"'sample/makefile'\" \(725 characters\)
  275.   sed "s/^X//" >'sample/makefile' <<'END_OF_FILE'
  276. X#
  277. X#  METALBASE 5.0
  278. X#
  279. X#  Released October 1st, 1992 by Huan-Ti [ virtual!root@owlnet.rice.edu ]
  280. X#                                        [ t-richj@microsoft.com ]
  281. X#
  282. X#  Makefile for demonstration program  -- *nix expected
  283. X#
  284. X#
  285. X#  If mbase.h and stdinc.h aren't in /usr/include or /usr/local/include,
  286. X#  put them there or add -Idirectory to CFLAGS=.
  287. X
  288. Xall : sample bench
  289. X
  290. X
  291. Xbench : bench.o
  292. X    cc -f -o bench bench.o -lmb
  293. X
  294. Xbench.o : bench.c bench.h
  295. X    cc -c $(CFLAGS) bench.c
  296. X
  297. Xbench.h : bench.s
  298. X    ./build -qh bench.s
  299. X
  300. X
  301. Xsample : sample.o
  302. X    cc -f -o sample sample.o -lmb -lcurses -lterm
  303. X
  304. Xsample.o : sample.c sample.h sample_fm.h
  305. X    cc -c $(CFLAGS) sample.c
  306. X
  307. Xsample.h : sample.s
  308. X    ./build -qh sample.s
  309. X
  310. Xsample_fm.h : sample.frm
  311. X    ./form sample
  312. X
  313. END_OF_FILE
  314.   if test 725 -ne `wc -c <'sample/makefile'`; then
  315.     echo shar: \"'sample/makefile'\" unpacked with wrong size!
  316.   fi
  317.   # end of 'sample/makefile'
  318. fi
  319. if test -f 'src/create.c' -a "${1}" != "-c" ; then 
  320.   echo shar: Will not clobber existing file \"'src/create.c'\"
  321. else
  322.   echo shar: Extracting \"'src/create.c'\" \(8713 characters\)
  323.   sed "s/^X//" >'src/create.c' <<'END_OF_FILE'
  324. X/*
  325. X * METALBASE 5.0
  326. X *
  327. X * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
  328. X *                                       [ t-richj@microsoft.com ]
  329. X */
  330. X
  331. X#define CREATE_C
  332. X#include "mbase.h"
  333. X#include "internal.h"
  334. X
  335. X/*
  336. X ******************************************************************************
  337. X *
  338. X */
  339. X
  340. Xrelation *
  341. Xmb_new ()
  342. X{
  343. X   relation *rel;
  344. X
  345. X   if ((rel = New (relation)) == RNULL)
  346. X      relerr (MB_NO_MEMORY, RNULL);
  347. X
  348. X   rel->num_i  = 0;
  349. X   rel->num_f  = 0;
  350. X   rel->serial = 0L;
  351. X
  352. X   relerr (MB_OKAY, rel);
  353. X}
  354. X
  355. Xmb_err
  356. Xmb_addindex (rel, name, dups, desc)
  357. Xrelation    *rel;
  358. Xchar             *name,      *desc;
  359. Xint                     dups;
  360. X{
  361. X   char  *pch, *line, temp[128], t2[5];
  362. X   int    i;
  363. X
  364. X   if (_identify (rel) != -1 || dups < 0 || dups > 1 ||
  365. X       ! name || ! *name || ! desc || *desc < '0' || *desc > '9')
  366. X      {
  367. X      baderr (MB_BAD_INDEX);
  368. X      }
  369. X
  370. X   rel->itype[rel->num_i] = dups;  /* 1 == dups, 0 == nodups */
  371. X
  372. X   strcpy (rel->iname[rel->num_i], name);
  373. X   strcpy (rel->idxs[rel->num_i], "000");
  374. X
  375. X   strcpy (temp, desc);
  376. X   line  = temp;
  377. X
  378. X   for (i = 0; i < MAX_IDX-1; i++)
  379. X      {
  380. X      if ((pch = strchr (line, ',')) == NULL)
  381. X         break;
  382. X      *pch = 0;
  383. X
  384. X      sprintf (t2, "%03d", atoi (line));
  385. X      strcat (rel->idxs[rel->num_i], t2);
  386. X
  387. X      line = pch+1;
  388. X      }
  389. X
  390. X   sprintf (t2, "%03d", atoi (line));
  391. X   strcat (rel->idxs[rel->num_i], t2);
  392. X
  393. X   sprintf (t2, "%03d", i+1);
  394. X   strncpy (rel->idxs[rel->num_i], t2, 3);
  395. X
  396. X   rel->num_i ++;
  397. X
  398. X   baderr (MB_OKAY);
  399. X}
  400. X
  401. Xmb_err
  402. Xmb_addfield (rel, name, type, arg)
  403. Xrelation    *rel;
  404. Xchar             *name;
  405. Xftype                   type;
  406. Xlong                          arg;
  407. X{
  408. X   strcpy (rel->name[rel->num_f], name);
  409. X
  410. X   if (type == T_SERIAL)
  411. X      {
  412. X      rel->serial = arg;  /* serial is temporary storage for NextSerial */
  413. X      }
  414. X
  415. X   switch (rel->type[rel->num_f] = type)
  416. X      {
  417. X      case T_CHAR:    rel->siz [rel->num_f] = (int)arg;  break;
  418. X      case T_SHORT:   rel->siz [rel->num_f] =  2;        break;
  419. X      case T_USHORT:  rel->siz [rel->num_f] =  2;        break;
  420. X      case T_LONG:    rel->siz [rel->num_f] =  4;        break;
  421. X      case T_ULONG:   rel->siz [rel->num_f] =  4;        break;
  422. X      case T_FLOAT:   rel->siz [rel->num_f] =  4;        break;
  423. X      case T_DOUBLE:  rel->siz [rel->num_f] =  8;        break;
  424. X      case T_MONEY:   rel->siz [rel->num_f] =  8;        break;
  425. X      case T_TIME:    rel->siz [rel->num_f] =  4;        break;
  426. X      case T_DATE:    rel->siz [rel->num_f] =  4;        break;
  427. X      case T_SERIAL:  rel->siz [rel->num_f] =  4;        break;
  428. X      }
  429. X
  430. X   rel->num_f ++;
  431. X
  432. X   baderr (MB_OKAY);
  433. X}
  434. X
  435. X
  436. X/*
  437. X ******************************************************************************
  438. X *
  439. X */
  440. X
  441. Xmb_err
  442. Xmb_create (rel, name, mem)
  443. Xrelation  *rel;
  444. Xchar           *name;
  445. Xint                   mem;
  446. X{
  447. X   char   temp[35];
  448. X   int    i, R, n, j;
  449. X   short  tshort;
  450. X   long   tlong;
  451. X
  452. X   (void)mem;    /* Reference for compiler's sake; unused in MetalBase 5.0 */
  453. X
  454. X   if (! rel || _identify (rel) != -1)
  455. X      baderr (MB_BAD_REL);
  456. X
  457. X   if (! rel->num_i)   baderr (MB_NO_INDICES);
  458. X   if (! rel->num_f)   baderr (MB_NO_FIELDS);
  459. X
  460. X
  461. X/*
  462. X * See if we can create the file (if it already exists, delete it).
  463. X *
  464. X */
  465. X
  466. X   if (access (name, 0) != -1)
  467. X      unlink (name);
  468. X   if ((R = creatx (name)) == -1)
  469. X      baderr (MB_NO_WRITE);
  470. X   modex (name, 0666);   /* Make the file   -rw-rw-rw-  */
  471. X   close (R);
  472. X
  473. X   if ((R = openx (name, OPENMODE)) == -1)
  474. X      {
  475. X      unlink (name);  /* We made it, but can't open it, so delete it. */
  476. X      baderr (MB_NO_WRITE);
  477. X      }
  478. X
  479. X
  480. X/*
  481. X * Great; we've created the file.  Now fill it out...
  482. X *
  483. X */
  484. X
  485. X   temp[0] = 50;  writx (R, temp, 1);  /* MetalBase 5.0 Signature */
  486. X   temp[0] =  0;  writx (R, temp, 1);  /* Zero users              */
  487. X
  488. X   for (tshort = 0, i = 0; i < 2; i++)
  489. X      write (R, &tshort, 2);           /* Temporary and exclusive locks */
  490. X
  491. X   for (tlong = 0L, i = 0; i < 3; i++)
  492. X      writx (R, &tlong, 4);            /* Pointers to fields,indices,recs */
  493. X
  494. X   writx (R, &tlong, 4);               /* Number of records */
  495. X   writx (R, &rel->serial, 4);         /* Next serial value */
  496. X
  497. X   tshort = (short)rel->num_f;  writx (R, &tshort, 2);  /* Number of fields  */
  498. X   tshort = (short)rel->num_i;  writx (R, &tshort, 2);  /* Number of indices */
  499. X
  500. X   for (i = 0; i < rel->num_i; i++)
  501. X      writx (R, &tlong, 4);       /* Pointers to top of each index tree */
  502. X
  503. X/*
  504. X * That was ugly.  We're now ready to write the fields' descriptions...
  505. X *
  506. X */
  507. X
  508. X   tlong = lseek (R, 0L, 1);               /* Current position?             */
  509. X   lseek (R, POS_FIELDPTR(verCURRENT), 0); /* Pointer to fields' positions  */
  510. X   writx (R, &tlong, 4);
  511. X   lseek (R, tlong, 0);           /* Move back to where we were    */
  512. X
  513. X/*
  514. X * A: var*F.....Fields' descriptions:
  515. X *                 byte    0 : Type (0-10, as listed above)
  516. X *                 bytes 1-2 : Size (short/ used only for char fields)
  517. X *                 bytes 3-? : Name (max len = 20, terminated by '|')
  518. X *
  519. X */
  520. X
  521. X   for (i = 0; i < rel->num_f; i++)
  522. X      {
  523. X      temp[0] = (char)rel->type[i];   writx (R,  temp,   1);
  524. X      tshort  = (short)rel->siz[i];   writx (R, &tshort, 2);
  525. X
  526. X      writx (R, rel->name[i], strlen(rel->name[i]));
  527. X      writx (R, "|", 1);
  528. X      }
  529. X
  530. X/*
  531. X * That was uglier.  We're now ready to write the indices' descriptions...
  532. X *
  533. X */
  534. X
  535. X   tlong = lseek (R, 0L, 1);   /* Current position?             */
  536. X   lseek (R, POS_INDEXPTR, 0); /* Pointer to indices' positions */
  537. X   writx (R, &tlong, 4);
  538. X   lseek (R, tlong, 0);        /* Move back to where we were    */
  539. X
  540. X/*
  541. X * B: var*I.....Indices' descriptions:
  542. X *                 byte    0 : Type (0-1, 0==nodups, 1==dups)
  543. X *                 bytes   1 : Number of fields in this index
  544. X *                 bytes 2-? : Name (max len = 20, terminated by ':')
  545. X *                       --- : Each field's sequential # (as short, 0-based)
  546. X *      1.......Separator ('\n')
  547. X *
  548. X */
  549. X
  550. X   for (i = 0; i < rel->num_i; i++)
  551. X      {
  552. X      strzcpy (temp, rel->idxs[i], 3);
  553. X      n = atoi (temp);
  554. X
  555. X      temp[0] = (char)rel->itype[i];  /* 0==nodups, 1==dups                */
  556. X      temp[1] = (char)n;              /* N==number of fields in this index */
  557. X
  558. X      writx (R, temp, 2);
  559. X
  560. X      writx (R, rel->iname[i], strlen (rel->iname[i]));
  561. X      writx (R, ":", 1);
  562. X
  563. X      for (j = 0; j < n; j++)
  564. X         {
  565. X         strzcpy (temp, &rel->idxs[i][3 + j*3], 3);
  566. X         tshort = (short)atoi (temp);
  567. X         writx (R, &tshort, 2);
  568. X         }
  569. X      }
  570. X
  571. X/*
  572. X * Next, there's the stuff that's new to 5.0-- rel->hack points to the position
  573. X * of all the new stuff.  Included are:
  574. X *    6 bytes (3 * sizeof(short))  - Hacklock positions
  575. X *   60 bytes (30 * sizeof(short)) - Thirty-position service queue
  576. X *   30 bytes (30 * sizeof(char))  - Queue strobes
  577. X *   32 bytes (8 * sizeof(long))   - Reserved for later use
  578. X *
  579. X */
  580. X
  581. X   rel->hack = lseek (R, 0L, 1);  /* Remember current position */
  582. X   tshort = 0;
  583. X   writx (R, &tshort, 2); writx (R, &tshort, 2); writx (R, &tshort, 2);
  584. X
  585. X   writx (R, &tshort, 2); writx (R, &tshort, 2); writx (R, &tshort, 2);
  586. X   writx (R, &tshort, 2); writx (R, &tshort, 2); writx (R, &tshort, 2);
  587. X   writx (R, &tshort, 2); writx (R, &tshort, 2); writx (R, &tshort, 2);
  588. X   writx (R, &tshort, 2); writx (R, &tshort, 2); writx (R, &tshort, 2);
  589. X   writx (R, &tshort, 2); writx (R, &tshort, 2); writx (R, &tshort, 2);
  590. X   writx (R, &tshort, 2); writx (R, &tshort, 2); writx (R, &tshort, 2);
  591. X   writx (R, &tshort, 2); writx (R, &tshort, 2); writx (R, &tshort, 2);
  592. X   writx (R, &tshort, 2); writx (R, &tshort, 2); writx (R, &tshort, 2);
  593. X   writx (R, &tshort, 2); writx (R, &tshort, 2); writx (R, &tshort, 2);
  594. X   writx (R, &tshort, 2); writx (R, &tshort, 2); writx (R, &tshort, 2);
  595. X
  596. X   for (i = 0; i < 30; i++)
  597. X      temp[i] = 0;
  598. X
  599. X   writx (R, temp, 30);
  600. X
  601. X   tlong = 0L;
  602. X   writx (R, &tlong, 4); writx (R, &tlong, 4);  /* RESERVED SPACE */
  603. X   writx (R, &tlong, 4); writx (R, &tlong, 4);  /* RESERVED SPACE */
  604. X   writx (R, &tlong, 4); writx (R, &tlong, 4);  /* RESERVED SPACE */
  605. X   writx (R, &tlong, 4); writx (R, &tlong, 4);  /* RESERVED SPACE */
  606. X
  607. X   writx (R, SNGCR, NUMCR);
  608. X
  609. X   tlong = lseek (R, 0L, 1);   /* Current position?             */
  610. X   lseek (R, POS_RECZERO, 0);  /* Pointer to record #0          */
  611. X   writx (R, &tlong, 4);
  612. X
  613. X   rel->recz = tlong;
  614. X
  615. X   close (R);
  616. X
  617. X   baderr (MB_OKAY);
  618. X}
  619. X
  620. Xint
  621. Xmb_getname (rel, name, fIndex)
  622. Xrelation   *rel;
  623. Xchar            *name;
  624. Xint                    fIndex;
  625. X{
  626. X   int   i;
  627. X
  628. X   if (fIndex)
  629. X      {
  630. X      for (i = 0; i < rel->num_i; i++)
  631. X         if (! strcmp (rel->iname[i], name))
  632. X            return i;
  633. X      }
  634. X   else
  635. X      {
  636. X      for (i = 0; i < rel->num_f; i++)
  637. X         if (! strcmp (rel->name[i], name))
  638. X            return i;
  639. X      }
  640. X
  641. X   return -1;
  642. X}
  643. X
  644. END_OF_FILE
  645.   if test 8713 -ne `wc -c <'src/create.c'`; then
  646.     echo shar: \"'src/create.c'\" unpacked with wrong size!
  647.   fi
  648.   # end of 'src/create.c'
  649. fi
  650. if test -f 'src/entry.c' -a "${1}" != "-c" ; then 
  651.   echo shar: Will not clobber existing file \"'src/entry.c'\"
  652. else
  653.   echo shar: Extracting \"'src/entry.c'\" \(9469 characters\)
  654.   sed "s/^X//" >'src/entry.c' <<'END_OF_FILE'
  655. X/*
  656. X * METALBASE 5.0
  657. X *
  658. X * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
  659. X *                                       [ t-richj@microsoft.com ]
  660. X *
  661. X * Special thanks go to Adrian Corston (adrian@internode.com.au) for his
  662. X * suggestions and code.  While this code is of my penning, the idea and
  663. X * style of implementation for this are direct ports from his own
  664. X * excellent work.
  665. X *
  666. X */
  667. X
  668. X#define ENTRY_C
  669. X#include "mbase.h"
  670. X
  671. X/*
  672. X * Prototypes
  673. X *
  674. X */
  675. X
  676. XWINDOW     *win;
  677. X
  678. X#ifdef LONGARGS
  679. X   int   _std_val  (de_form *);
  680. X   void  _getnext  (de_form *);
  681. X   int   _validopt (de_form *, field *, char);
  682. X#else
  683. X   int   _std_val();
  684. X   void  _getnext();
  685. X   int   _validopt();
  686. X#endif
  687. X
  688. X /***************************************************************************/
  689. X
  690. X/*
  691. X * form->key will be:
  692. X *  -1 == Abort transaction--they hit CTRL-C or CTRL-Q or some such.
  693. X *   1 == Accept transaction--they hit CTRL-A or some such.
  694. X *  Otherwise, it's the key they hit to get out of the field; look at
  695. X *     input.c to see what it returns.
  696. X *
  697. X */
  698. X
  699. Xint
  700. X_std_val (form)
  701. Xde_form  *form;
  702. X{
  703. X   if (form->key == -1 || form->key == 1)  return form->key;
  704. X   return 0;
  705. X}
  706. X
  707. Xvoid
  708. X_getnext (form)
  709. Xde_form  *form;
  710. X{
  711. X   int  mv;
  712. X
  713. X   if (form->key == -1 || form->key == 1)  return;
  714. X
  715. X   form->nextfield = form->curfield;
  716. X
  717. X   switch (form->key)
  718. X    { case '-': case 'k':            mv = -1;  break;
  719. X      case  0 : case '+': case 'j':  mv =  1;  break;
  720. X      default :                      mv =  0;  break;
  721. X    }
  722. X   if (mv == 0)
  723. X      if (form->fields[form->curfield].inout&FM_IN)  return;
  724. X      else
  725. X         mv = 1;
  726. X
  727. X   for (;;)
  728. X    { form->nextfield += mv;
  729. X
  730. X      if (form->nextfield <  0)
  731. X         form->nextfield=form->numfields-1;
  732. X      if (form->nextfield >= form->numfields)
  733. X         form->nextfield=0;
  734. X
  735. X      if (form->fields[form->nextfield].inout & FM_IN)
  736. X         break;
  737. X    }
  738. X}
  739. X
  740. X/*
  741. X * validopt() is used to check a given Choice field, to make sure its data
  742. X * is valid.  It also looks for any Link fields which reference it, and
  743. X * sets/refreshes those.
  744. X *
  745. X */
  746. X
  747. Xint
  748. X_validopt (form, fld, old)
  749. Xde_form   *form;
  750. Xfield           *fld;
  751. Xchar                  old;
  752. X{
  753. X   int   i, j;
  754. X   char  now;
  755. X
  756. X   now = *(char *)(fld->buffer);
  757. X
  758. X   if (now == 0)
  759. X      {
  760. X      i = 10;
  761. X      }
  762. X   else
  763. X      {
  764. X      for (i = 1; i < 10 && fld->opt_arr[i][0] != 0; i++)
  765. X         {
  766. X         if (strchr (fld->opt_arr[i], now) != NULL)
  767. X            break;
  768. X         }
  769. X      if (i == 10 || fld->opt_arr[i][0] == 0)
  770. X         {
  771. X         *((char *)(fld->buffer))   = old;
  772. X         *((char *)(fld->buffer)+1) = 0;
  773. X         if (old != 0)  return 0;
  774. X         i = 10;
  775. X         }
  776. X      }
  777. X
  778. X   for (j = 0; j < form->numfields; j++)
  779. X      if (form->fields[j].option == 2 &&
  780. X          ! strcmp (form->fields[j].opt_arr[0], fld->name))
  781. X      {
  782. X      if (i == 10)
  783. X         *(char *)(form->fields[j].buffer) = 0;
  784. X      else
  785. X         strcpy (form->fields[j].buffer, form->fields[j].opt_arr[i]);
  786. X      fm_refresh (form, &(form->fields[j]));
  787. X      }
  788. X
  789. X   return 1;
  790. X}
  791. X
  792. X /***************************************************************************/
  793. X
  794. Xint
  795. Xfm_fldnum (form, str)
  796. Xde_form   *form;
  797. Xchar            *str;
  798. X{
  799. X   char         *ptr;
  800. X   register int  i;
  801. X
  802. X   if (!form || !str || !*str)  return -1;
  803. X
  804. X   for (i = 0; i < form->numfields; i++)
  805. X      if (! strcmp (form->fields[i].name, str))  return i;
  806. X
  807. X   for (i = 0; i < form->numfields; i++)
  808. X      if ((ptr = strchr (form->fields[i].name, '.')) != NULL)
  809. X         if (! strcmp (ptr+1, str))  return i;
  810. X
  811. X   return -1;
  812. X}
  813. X
  814. X/*
  815. X * formtorel() is great.  It takes any data in a data-entry form and moves
  816. X * it into the appropriate places in a relation's structure... it goes by
  817. X * name, and only those fields in both are copied.  Wonderful toy.  Pass
  818. X * it pointers to the form and relation, and the structure record for the
  819. X * relation.  reltoform() works the same way but backwards, moving data from
  820. X * a relation's record into a form, BUT MAKE SURE YOU CHECK THE ARGUMENTS
  821. X * FIRST.  They're backwards.  On purpose.
  822. X *
  823. X */
  824. X
  825. Xvoid
  826. Xformtorel (form, rel, ptr)
  827. Xde_form   *form;
  828. Xrelation        *rel;
  829. Xdataptr               ptr;
  830. X{
  831. X   char          temp[80], *a, *b;
  832. X   dataptr       frm;
  833. X   register int  i;
  834. X   int           n;
  835. X
  836. X   if (! form || ! rel || ! ptr)  return;
  837. X
  838. X   for (n = 0; n < rel->num_f; n++)
  839. X      {
  840. X      sprintf (temp, "%s.%s", rel->relname, rel->name[n]);
  841. X      if ((frm = fm_data (form, temp)) != NULL)
  842. X         {
  843. X         a=(char *)ptr +rel->start[n];
  844. X         b=(char *)frm;
  845. X         for (i = 0; i < rel->siz[n]; i++, a++, b++)
  846. X            *a = *b;
  847. X         }
  848. X      }
  849. X}
  850. X
  851. Xvoid
  852. Xreltoform (rel, form, ptr)
  853. Xrelation  *rel;
  854. Xde_form        *form;
  855. Xdataptr               ptr;
  856. X{
  857. X   char          temp[80];
  858. X   dataptr       frm;
  859. X   register int  i;
  860. X   int           n;
  861. X
  862. X   if (! form || ! rel || ! ptr)  return;
  863. X
  864. X   for (n = 0; n < rel->num_f; n++)
  865. X    { sprintf (temp, "%s.%s", rel->relname, rel->name[n]);
  866. X      if ((frm = fm_data (form, temp)) != NULL)
  867. X         for (i = 0; i < rel->siz[n]; i++)
  868. X            ((char *)frm)[i] = ((char *)ptr)[i +rel->start[n]];
  869. X    }
  870. X}
  871. X
  872. X/*
  873. X * Refresh a field.  Basically redisplays whatever's in it, and doesn't
  874. X * move your current field number.
  875. X *
  876. X */
  877. X
  878. Xvoid
  879. Xfm_refresh (form, fld)
  880. Xde_form    *form;
  881. Xfield            *fld;
  882. X{
  883. X   if (! fld)  return;
  884. X   move (form->y +fld->y, form->x +fld->x);
  885. X   display (fld->buffer, fld->type, fld->len);
  886. X   if (fld->option == 1)  (void)_validopt (form, fld, 0);
  887. X}
  888. X
  889. X/*
  890. X * Refresh the whole forsaken form.
  891. X *
  892. X */
  893. X
  894. Xvoid
  895. Xfm_refrall (form)
  896. Xde_form    *form;
  897. X{
  898. X   register int  i;
  899. X   field        *fld;
  900. X
  901. X   if (! form)  return;
  902. X
  903. X   for (i = 0; i < form->numfields; i++)
  904. X    { fld = &(form->fields[i]);
  905. X      move (form->y +fld->y, form->x +fld->x);
  906. X      display(form->fields[i].buffer,form->fields[i].type,form->fields[i].len);
  907. X      if (form->fields[i].option == 1)
  908. X         (void)_validopt (form, &form->fields[i], 0);
  909. X    }
  910. X}
  911. X
  912. X/*
  913. X * zero all data in the form.  Yayy.....
  914. X *
  915. X */
  916. X
  917. Xvoid
  918. Xfm_zero (form)
  919. Xde_form *form;
  920. X{
  921. X   register int  i;
  922. X   dataptr       ptr;
  923. X
  924. X   for (i = 0; i < form->numfields; i++)
  925. X      {
  926. X      ptr = form->fields[i].buffer;
  927. X      switch (form->fields[i].type)
  928. X         {
  929. X         case T_SHORT:   *(short  *)ptr = (short) 0;  break;
  930. X         case T_USHORT:  *(ushort *)ptr = (ushort)0;  break;
  931. X         case T_TIME:
  932. X         case T_DATE:
  933. X         case T_SERIAL:
  934. X         case T_LONG:    *(long   *)ptr = (long)  0;  break;
  935. X         case T_ULONG:   *(ulong  *)ptr = (ulong) 0;  break;
  936. X         case T_FLOAT:   *(float  *)ptr = (float) 0;  break;
  937. X         case T_DOUBLE:
  938. X         case T_MONEY:   *(double *)ptr = (double)0;  break;
  939. X         default:        *(char   *)ptr = 0;          break;
  940. X         }
  941. X      }
  942. X}
  943. X
  944. X/*
  945. X * Give fm_data a form pointer, and a name (like "sample.custnum"), and it
  946. X * will return a pointer to the buffer used to contain sample.custnum's number
  947. X * for data-entry.  Useful, eh?
  948. X *
  949. X */
  950. X
  951. Xdataptr
  952. Xfm_data (form, str)
  953. Xde_form *form;
  954. Xchar          *str;
  955. X{
  956. X   int  i;
  957. X   if (! form || ! str)  return NULL;
  958. X   if ((i = fm_fldnum (form, str)) < 0)  return NULL;
  959. X   return form->fields[i].buffer;
  960. X}
  961. X
  962. X/*
  963. X * Set a mode... those basically just determine which fields you can get into
  964. X * and which you can't.  Logically, it helps to remember what you're doing
  965. X * on the data-entry form in the first place too.
  966. X *
  967. X */
  968. X
  969. Xvoid
  970. Xfm_mode (form, n)
  971. Xde_form *form;
  972. Xint            n;
  973. X{
  974. X   register int  i;
  975. X   if (!form || n < 0 || n > form->nummodes)  return;
  976. X   form->curmode = n;
  977. X   for (i = 0; i < form->numfields; i++)
  978. X      if (form->curmode == 0)
  979. X         form->fields[i].inout = FM_INOUT;
  980. X      else
  981. X         form->fields[i].inout = form->fields[i].mode[form->curmode-1];
  982. X}
  983. X
  984. X/*
  985. X * do_form()'s flow:
  986. X *   display the data-entry form
  987. X *   call fm_mode() to set the current mode
  988. X *   call fm_refrall()
  989. X *   set valid_fn if it's not set already
  990. X *   .-> call input() on the appropriate field  <---------------.
  991. X *   |   if in a choice field, verify its validity --(invalid)--'
  992. X *   |   call _getnext() to set the next field
  993. X *   |   call (*valid_fn)() to validate the transaction:
  994. X *   `---- if returns 0
  995. X *
  996. X */
  997. X
  998. X   /* do_form()  returns 0 if failed, -1 if aborted, and 1 if accepted. */
  999. X
  1000. Xint
  1001. Xdo_form (form)
  1002. Xde_form *form;
  1003. X{
  1004. X   register int  i;
  1005. X   int           wedidit = 0;
  1006. X   char          buffer;
  1007. X   field        *fld;
  1008. X
  1009. X   if (!form)  return 0;
  1010. X
  1011. X   if (! win)
  1012. X    { wedidit = 1;  init_curses();
  1013. X      savetty(); raw(); noecho(); nl();
  1014. X    }
  1015. X   clear(); refresh();
  1016. X
  1017. X   for (i = 0; i < form->numlines; i++)
  1018. X      mvaddstr (i+form->y, form->x, form->_scrn[i]);
  1019. X   refresh();
  1020. X
  1021. X   fm_mode    (form, form->curmode);
  1022. X   fm_refrall (form);
  1023. X
  1024. X   if (form->valid_fn == (int (*)())0)  form->valid_fn = _std_val;
  1025. X
  1026. X   for (;;)
  1027. X      {
  1028. X      fld = &(form->fields[form->curfield]);
  1029. X      move (form->y +fld->y, form->x +fld->x);
  1030. X      if (fld->option == 1)  buffer = *(char *)(fld->buffer);
  1031. X
  1032. X      do   form->key = input (fld->buffer, fld->type, fld->len);
  1033. X      while (fld->option == 1 && !_validopt (form, fld, buffer));
  1034. X
  1035. X      _getnext (form);
  1036. X      if ((i = (*form->valid_fn)(form)) != 0)  break;
  1037. X      form->key = '.';
  1038. X
  1039. X      form->curfield = form->nextfield;
  1040. X      _getnext (form);
  1041. X      form->curfield = form->nextfield;
  1042. X      }
  1043. X
  1044. X/*
  1045. X * The second _getnext() function is used to ensure the user hasn't placed
  1046. X * us on a bad field--one which we normally couldn't get to.
  1047. X *
  1048. X */
  1049. X
  1050. X   if (wedidit)
  1051. X      {
  1052. X      clear(); refresh(); resetty(); endwin();
  1053. X      win = (WINDOW *)0;
  1054. X      }
  1055. X   return i;
  1056. X}
  1057. X
  1058. END_OF_FILE
  1059.   if test 9469 -ne `wc -c <'src/entry.c'`; then
  1060.     echo shar: \"'src/entry.c'\" unpacked with wrong size!
  1061.   fi
  1062.   # end of 'src/entry.c'
  1063. fi
  1064. if test -f 'src/form_wr.c' -a "${1}" != "-c" ; then 
  1065.   echo shar: Will not clobber existing file \"'src/form_wr.c'\"
  1066. else
  1067.   echo shar: Extracting \"'src/form_wr.c'\" \(9304 characters\)
  1068.   sed "s/^X//" >'src/form_wr.c' <<'END_OF_FILE'
  1069. X/*
  1070. X * METALBASE 5.0
  1071. X *
  1072. X * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
  1073. X *                                       [ t-richj@microsoft.com ]
  1074. X *
  1075. X * Special thanks go to Adrian Corston (adrian@internode.com.au) for his
  1076. X * suggestions and code.  While this code is of my penning, the idea and
  1077. X * style of implementation for this are direct ports from his own
  1078. X * excellent work.
  1079. X *
  1080. X */
  1081. X
  1082. X#include "mbase.h"
  1083. X
  1084. X#ifndef MAXnREL
  1085. X#define MAXnREL 20    /* Max # of relations in any given DE form */
  1086. X#endif
  1087. X#ifndef MAXnFLD
  1088. X#define MAXnFLD 40    /* Max # of fields in any given DE form    */
  1089. X#endif
  1090. X
  1091. X/*
  1092. X * Definitions
  1093. X *
  1094. X */
  1095. X
  1096. X#define LPARQ "("
  1097. X#define LBRCQ "{"   /* These are pulled out   */
  1098. X#define LBKT  '['   /* so that vi's ()/[]/{}  */
  1099. X#define LBRC  '{'   /* matchin works properly */
  1100. X#define RBRC  '}'   /* in moving through the  */
  1101. X#define RBKT  ']'   /* code.                  */
  1102. X#define RBRCQ "}"
  1103. X#define RPARQ ")"
  1104. X
  1105. X#define fieldopt(x) (*(options[x]))
  1106. X#define fieldmode(x) (*(modes[x]))
  1107. X#define wrdata(x)   write (H, x, strlen(x));
  1108. X#define wrline(x) { wrdata(x); wrdata(SNGCR); }
  1109. X
  1110. X/*
  1111. X * Prototypes
  1112. X *
  1113. X */
  1114. X
  1115. X#ifdef LONGARGS
  1116. X   extern void  id_field     (char *, char *);
  1117. X          void  writeit      (void);
  1118. X          void  wr_header    (void);
  1119. X          void  wr_buffer    (void);
  1120. X          void  wr_mode      (void);
  1121. X          void  wr_option    (void);
  1122. X          void  wr_field     (void);
  1123. X          void  wr_screen    (void);
  1124. X          void  wr_form      (void);
  1125. X          void  strqucpy     (char *, char *);
  1126. X#else
  1127. X   extern void  id_field();
  1128. X          void  writeit();
  1129. X          void  wr_header();
  1130. X          void  wr_header();
  1131. X          void  wr_buffer();
  1132. X          void  wr_mode();
  1133. X          void  wr_option();
  1134. X          void  wr_field();
  1135. X          void  wr_screen();
  1136. X          void  wr_form();
  1137. X          void  strqucpy();
  1138. X#endif
  1139. X
  1140. Xtypedef char optlist[10][40];
  1141. Xtypedef int  modelist[20];
  1142. X
  1143. X/*
  1144. X * Global Variables
  1145. X *
  1146. X */
  1147. X
  1148. Xint  H;
  1149. X
  1150. Xextern char      formname[30];
  1151. Xextern char      displ[25][140];
  1152. Xextern int       num_l, pos_y, pos_x, num_f, num_m;
  1153. X
  1154. Xextern field     fld[MAXnFLD];
  1155. Xextern int       lens[MAXnFLD];
  1156. Xextern optlist  *options[MAXnFLD];
  1157. Xextern modelist *modes[MAXnFLD];
  1158. X
  1159. Xvoid
  1160. Xwriteit ()
  1161. X{
  1162. X   int   i;
  1163. X   char  temp[128], *ptr;
  1164. X
  1165. X   if ((ptr = strrchr (formname, '.')) != NULL)  *ptr = 0;
  1166. X
  1167. X   sprintf (temp, "%-1.5s_fm.h", formname);
  1168. X
  1169. X   if ((H = openx (temp, O_RDWR)) != -1)
  1170. X    { close  (H);
  1171. X      unlink (temp);
  1172. X    }
  1173. X   if ((H = creatx (temp)) == -1)
  1174. X    { fprintf (stderr, "cannot create %s -- aborted%s", temp, SNGCR);
  1175. X      mb_exit (10);
  1176. X    }
  1177. X   modex (temp, 0666);   /* Make the file   -rw-rw-rw-  */
  1178. X
  1179. X   wr_header ();
  1180. X   wr_buffer ();
  1181. X   wr_mode   ();
  1182. X   wr_option ();
  1183. X   wr_field  ();
  1184. X   wr_screen ();
  1185. X   wr_form   ();
  1186. X
  1187. X   close (H);
  1188. X
  1189. X   for (i = 0; i < MAXnFLD; i++)
  1190. X    {
  1191. X      if (options[i] != (optlist *)0)
  1192. X       { free (options[i]);
  1193. X         options[i] = (optlist *)0;
  1194. X       }
  1195. X      if (modes[i] != (modelist *)0)
  1196. X       { free (modes[i]);
  1197. X         modes[i] = (modelist *)0;
  1198. X       }
  1199. X    }
  1200. X
  1201. X   printf ("%-1.5s_fm.h written successfully\n", formname);
  1202. X}
  1203. X
  1204. Xvoid
  1205. Xwr_header ()
  1206. X{
  1207. X   char  temp[128];
  1208. X   int   i;
  1209. X
  1210. X   for (i = 0; formname[i] != 0; i++)
  1211. X      temp[i] = toupper (formname[i]);
  1212. X   temp[i] = 0;
  1213. X   strcat (temp, "_FM_H");
  1214. X
  1215. X   wrdata ("#");  wrdata ("ifndef ");  wrline (temp);
  1216. X   wrdata ("#");  wrdata ("define ");  wrline (temp);  wrdata (SNGCR);
  1217. X
  1218. X   wrdata ("/");  wrline ("*");
  1219. X   wrline (" * This file was created by MetalBase version 5.0 from the data-entry");
  1220. X   wrdata (" * template \"");  wrdata (formname);  wrdata (".frm");  wrline ("\"");
  1221. X   wrline (" *");
  1222. X   wrline (" * MetalBase 5.0 released October 1st by richid@owlnet.rice.edu");
  1223. X   wrline (" *");
  1224. X   wrdata (" *");  wrline ("/");
  1225. X   wrdata (SNGCR);
  1226. X
  1227. X   wrdata ("#");  wrline ("ifdef MODULE");
  1228. X   wrdata ("   extern de_form ");  wrdata (formname);  wrline ("_fm;");
  1229. X   wrdata ("#");  wrline ("else");
  1230. X}
  1231. X
  1232. Xvoid
  1233. Xwr_buffer ()
  1234. X{
  1235. X   char  temp[128];
  1236. X   int   i;
  1237. X
  1238. X   for (i = 0; i < num_f; i++)
  1239. X      {
  1240. X      wrdata ("   ");
  1241. X      switch (fld[i].type)
  1242. X         {
  1243. X         case T_SHORT:   wrdata ("short    ");  break;
  1244. X         case T_USHORT:  wrdata ("ushort   ");  break;
  1245. X         case T_LONG:    wrdata ("long     ");  break;
  1246. X         case T_ULONG:   wrdata ("ulong    ");  break;
  1247. X         case T_FLOAT:   wrdata ("float    ");  break;
  1248. X         case T_DOUBLE:  wrdata ("double   ");  break;
  1249. X         case T_MONEY:   wrdata ("double   ");  break;
  1250. X         case T_TIME:    wrdata ("mb_time  ");  break;
  1251. X         case T_DATE:    wrdata ("mb_date  ");  break;
  1252. X         case T_SERIAL:  wrdata ("long     ");  break;
  1253. X         case T_PHONE:   wrdata ("mb_phone ");  break;
  1254. X         default:        wrdata ("char     ");  break;
  1255. X         }
  1256. X
  1257. X      if (fld[i].type == T_CHAR)
  1258. X         sprintf (temp, "%s_f%d[%2d] = ", formname, i, lens[i]);
  1259. X      else
  1260. X         sprintf (temp, "%s_f%d     = ",  formname, i);
  1261. X      wrdata (temp);
  1262. X
  1263. X      switch (fld[i].type)
  1264. X         {
  1265. X         case T_SHORT:   wrdata ("(short)0");     break;
  1266. X         case T_USHORT:  wrdata ("(ushort)0");    break;
  1267. X         case T_LONG:    wrdata ("0L");           break;
  1268. X         case T_ULONG:   wrdata ("(ulong)0L");    break;
  1269. X         case T_FLOAT:   wrdata ("(float)0.0");   break;
  1270. X         case T_DOUBLE:  wrdata ("(double)0.0");  break;
  1271. X         case T_MONEY:   wrdata ("(double)0.0");  break;
  1272. X         case T_TIME:    wrdata ("(mb_time)0");   break;
  1273. X         case T_DATE:    wrdata ("(mb_date)0");   break;
  1274. X         case T_SERIAL:  wrdata ("0L");           break;
  1275. X         default:        wrdata ("\"\"");         break;
  1276. X         }
  1277. X      wrline (";");
  1278. X      }
  1279. X   wrdata (SNGCR);
  1280. X}
  1281. X
  1282. Xvoid
  1283. Xwr_mode ()
  1284. X{
  1285. X   char  temp[128];
  1286. X   int   i, j;
  1287. X
  1288. X   for (i = 0; i < num_f; i++)
  1289. X    {
  1290. X      sprintf (temp, "   int %s_m%d[%d] = ", formname, i, num_m);
  1291. X      wrdata  (temp);
  1292. X      wrdata  (LBRCQ);
  1293. X      wrdata  (" ");
  1294. X
  1295. X      for (j = 0; j < num_m; j++)
  1296. X       {
  1297. X         if (fieldmode(i)[j] == FM_INOUT)  strcpy (temp, "FM_INOUT");
  1298. X         if (fieldmode(i)[j] == FM_IN)     strcpy (temp, "FM_IN");
  1299. X         if (fieldmode(i)[j] == FM_OUT)    strcpy (temp, "FM_OUT");
  1300. X         if (j < num_m-1)  strcat (temp, ",");
  1301. X         strcat (temp, "     ");  temp[10] = 0;
  1302. X         wrdata (temp);
  1303. X       }
  1304. X      wrdata  (" ");
  1305. X      wrdata  (RBRCQ);
  1306. X      wrline  (";");
  1307. X    }
  1308. X
  1309. X   wrdata (SNGCR);
  1310. X}
  1311. X
  1312. Xvoid
  1313. Xwr_option ()
  1314. X{
  1315. X   char  temp[128];
  1316. X   int   i, j;
  1317. X
  1318. X   for (i = 0; i < num_f; i++)
  1319. X      if (options[i] != (optlist *)0)
  1320. X       {
  1321. X         for (j = 1; j < 10; j++)
  1322. X            if (fieldopt(i)[j][0] == 0)  break;
  1323. X         sprintf (temp, "   char *%s_o%d[%d] = ", formname, i, j+1);
  1324. X         wrdata (temp);
  1325. X         wrdata (LBRCQ);
  1326. X         for (j = 0; j < 10; j++)
  1327. X            if (j != 0 && fieldopt(i)[j][0] == 0)  break;
  1328. X            else
  1329. X             {
  1330. X               if (j != 0)  wrdata (",");
  1331. X               wrdata (" \"");
  1332. X               wrdata (fieldopt(i)[j]);
  1333. X               wrdata ("\"");
  1334. X             }
  1335. X         wrdata (", \"\" ");
  1336. X         wrdata (RBRCQ);
  1337. X         wrline (";");
  1338. X       }
  1339. X   wrdata (SNGCR);
  1340. X}
  1341. X
  1342. Xvoid
  1343. Xwr_field ()
  1344. X{
  1345. X   char  temp[128];
  1346. X   int   i;
  1347. X
  1348. X   sprintf (temp, "   field %s_f[%d] =", formname, num_f);
  1349. X   wrline  (temp);
  1350. X
  1351. X   for (i = 0; i < num_f; i++)
  1352. X    {
  1353. X      if (i == 0)
  1354. X       { wrdata ("    ");  wrdata (LBRCQ);  wrdata (" "); }
  1355. X      else
  1356. X       { wrline (",");  wrdata ("      "); }
  1357. X
  1358. X      wrdata (LBRCQ);  wrdata (" ");
  1359. X
  1360. X      sprintf (temp, "%2d, %2d, %2d,", fld[i].y, fld[i].x, fld[i].len);
  1361. X      wrdata  (temp);
  1362. X      sprintf (temp, " %2d, 0, %d,", fld[i].type, fld[i].option);
  1363. X      wrdata  (temp);
  1364. X      sprintf (temp, " %s_m%d,", formname, i);
  1365. X      wrdata  (temp);
  1366. X      wrdata ( (fld[i].type==T_CHAR || fld[i].type==T_PHONE) ? "  " : " &" );
  1367. X      sprintf (temp, "%s_f%d, \"%s\",", formname, i, fld[i].name);
  1368. X      wrdata  (temp);
  1369. X      if (options[i] == (optlist *)0)  strcpy (temp, " NULL ");
  1370. X      else
  1371. X         sprintf (temp, " %s_o%d ", formname, i);
  1372. X      wrdata  (temp);
  1373. X      wrdata  (RBRCQ);
  1374. X    }
  1375. X   wrdata (" ");  wrdata (RBRCQ);  wrline (";");
  1376. X
  1377. X   wrdata (SNGCR);
  1378. X}
  1379. X
  1380. Xvoid
  1381. Xwr_screen ()
  1382. X{
  1383. X   char  temp[128];
  1384. X   int   i;
  1385. X
  1386. X   sprintf (temp, "   char *%s_s[%d] =", formname, num_l);
  1387. X   wrline (temp);
  1388. X
  1389. X   for (i = 0; i < num_l; i++)
  1390. X    {
  1391. X      if (i == 0)
  1392. X       { wrdata ("    ");   wrdata (LBRCQ);   wrdata (" ");
  1393. X       }
  1394. X      else
  1395. X       { wrline (",");   wrdata ("      ");
  1396. X       }
  1397. X
  1398. X      wrdata ("\"");
  1399. X      strqucpy (temp, displ[i]);
  1400. X      wrdata (temp);
  1401. X      wrdata ("\"");
  1402. X    }
  1403. X   wrdata ("  ");
  1404. X   wrdata (RBRCQ);
  1405. X   wrline (";");
  1406. X   wrdata (SNGCR);
  1407. X}
  1408. X
  1409. Xvoid
  1410. Xstrqucpy (oa, ob)
  1411. Xchar     *oa,*ob;
  1412. X{
  1413. X   register char *a, *b;
  1414. X   for (a=oa, b=ob; *b; a++,b++)
  1415. X      {
  1416. X      if (*b == '\"')
  1417. X         {
  1418. X         *a = '\\';
  1419. X         a++;
  1420. X         }
  1421. X      *a = *b;
  1422. X      }
  1423. X   *a = 0;
  1424. X}
  1425. X
  1426. Xvoid
  1427. Xwr_form ()
  1428. X{
  1429. X   char  temp[128];
  1430. X
  1431. X   wrdata ("   de_form "); wrdata (formname); wrline ("_fm =");
  1432. X   wrdata ("    ");  wrdata (LBRCQ);
  1433. X
  1434. X   sprintf (temp, " 1, 0, 0, 0, %d, %d, (int_fn)0, %d,", num_f, num_m, num_l);
  1435. X   wrdata  (temp);
  1436. X   sprintf (temp, " %d, %d, %s_f, %s_s ", pos_y, pos_x, formname, formname);
  1437. X   wrdata  (temp);
  1438. X   wrdata  (RBRCQ);
  1439. X   wrline  (";");
  1440. X
  1441. X   wrdata (SNGCR);
  1442. X   wrdata ("#");  wrline ("endif");  wrdata (SNGCR);
  1443. X   wrdata ("#");  wrline ("endif");  wrdata (SNGCR);
  1444. X}
  1445. X
  1446. END_OF_FILE
  1447.   if test 9304 -ne `wc -c <'src/form_wr.c'`; then
  1448.     echo shar: \"'src/form_wr.c'\" unpacked with wrong size!
  1449.   fi
  1450.   # end of 'src/form_wr.c'
  1451. fi
  1452. if test -f 'src/util2.c' -a "${1}" != "-c" ; then 
  1453.   echo shar: Will not clobber existing file \"'src/util2.c'\"
  1454. else
  1455.   echo shar: Extracting \"'src/util2.c'\" \(11746 characters\)
  1456.   sed "s/^X//" >'src/util2.c' <<'END_OF_FILE'
  1457. X/*
  1458. X * METALBASE 5.0
  1459. X *
  1460. X * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
  1461. X *                                       [ t-richj@microsoft.com ]
  1462. X */
  1463. X
  1464. X#define UTIL_C
  1465. X#include "mbase.h"
  1466. X#include "internal.h"
  1467. X
  1468. Xextern int       _started;
  1469. Xextern relation *_list[MAX_REL];
  1470. X
  1471. X/****************************************************************************/
  1472. X
  1473. Xmb_err
  1474. X_balance (rel, rcd, idx, bal)  /* CACHED */
  1475. Xrelation *rel;
  1476. Xlong           rcd;
  1477. Xint                 idx, bal;
  1478. X{
  1479. X   long   rep, rp;
  1480. X   cache *ptr;
  1481. X
  1482. X   if (! (rep = _find_seq (rel, 0L, rcd, idx, NUM_BAL(bal))) )
  1483. X      baderr (MB_CORRUPT);
  1484. X
  1485. X   ptr = _read_cache (rel, rep, idx);
  1486. X   rp = ptr->parent;
  1487. X
  1488. X   _dislink (rel, rep, idx, rcd);
  1489. X   _replace (rel, rcd, rep, idx);
  1490. X   _drop    (rel, rcd, idx, rep);
  1491. X
  1492. X   if (rp != rcd)  _check (rel, rp, rep, idx);  /* Stop at _rep_ */
  1493. X
  1494. X   ptr = _read_cache (rel, rcd, idx);
  1495. X   rp = ptr->parent;
  1496. X
  1497. X   _check (rel, rp, rep, idx);
  1498. X
  1499. X   baderr (MB_OKAY);
  1500. X}
  1501. X
  1502. Xvoid
  1503. X_dislink (rel, pos, idx, end)  /* CACHED */
  1504. Xrelation *rel;
  1505. Xlong           pos,      end;
  1506. Xint                 idx;
  1507. X{
  1508. X   char   temp[5];
  1509. X   long   ch, par, tmp;
  1510. X   int    dir = 0, tdir;
  1511. X   cache *ptr;
  1512. X
  1513. X   ptr = _read_cache (rel, pos, idx); /* There will be one child, at most */
  1514. X   ch = ptr->left;
  1515. X   if (ch)
  1516. X      dir = -1;
  1517. X   else
  1518. X      {
  1519. X      ch = ptr->right;     /* We already read in this record! */
  1520. X      dir = (ch ? 1 : 0);
  1521. X      }
  1522. X
  1523. X   par = ptr->parent;
  1524. X   temp[0] = (char)((int)ptr->parbal & PARDIR);
  1525. X   tdir = temp[0]?1:-1;
  1526. X
  1527. X   ptr = _read_cache (rel, par, idx);
  1528. X   ptr->changed = 1;
  1529. X   if (par == 0L)
  1530. X      {
  1531. X      _changeqcache (ptr, num, ch);
  1532. X      }
  1533. X   else
  1534. X      {
  1535. X      if (temp[0]) _changeqcache (ptr, right, ch);
  1536. X      else         _changeqcache (ptr, left,  ch);
  1537. X      }
  1538. X
  1539. X   if (ch)
  1540. X      {
  1541. X      ptr = _read_cache (rel, ch, idx);
  1542. X      _change_cache (ptr, parent, par);
  1543. X      temp[0] = ptr->parbal;
  1544. X      temp[0] = (char)((int)(temp[0] & BAL) | (tdir == 1 ? PARDIR : 0));
  1545. X
  1546. X      _change_cache (ptr, parbal, temp[0]);
  1547. X      }
  1548. X
  1549. X   for (tmp=par, dir=tdir; tmp != 0L; )   /* Update balances: */
  1550. X      {
  1551. X      ptr = _read_cache (rel, tmp, idx);
  1552. X      temp[0] = ptr->parbal;
  1553. X      temp[0] = (char)((int)(temp[0] & PARDIR) | ((temp[0] & BAL) - dir));
  1554. X
  1555. X      _change_cache (ptr, parbal, temp[0]);
  1556. X
  1557. X      dir = (temp[0] & PARDIR) ? 1 : -1;
  1558. X      if (tmp == end)  break;
  1559. X
  1560. X      tmp = ptr->parent;
  1561. X      }
  1562. X}
  1563. X
  1564. Xvoid
  1565. X_replace (rel, old, new, idx)  /* CACHED */
  1566. Xrelation *rel;
  1567. Xlong           old, new;
  1568. Xint                      idx;
  1569. X{
  1570. X   char   pba;
  1571. X   long   lef, rig, par;
  1572. X   cache *ptr;
  1573. X
  1574. X   ptr = _read_cache (rel, old, idx);
  1575. X      lef = ptr->left;
  1576. X      rig = ptr->right;
  1577. X      par = ptr->parent;
  1578. X      pba = ptr->parbal;
  1579. X   ptr = _read_cache (rel, new, idx);
  1580. X      _change_cache (ptr, left,   lef);
  1581. X      _changeqcache (ptr, right,  rig);
  1582. X      _changeqcache (ptr, parent, par);
  1583. X      _changeqcache (ptr, parbal, pba);
  1584. X
  1585. X   if (par == 0L)   /* Parent */
  1586. X      {
  1587. X      ptr = _read_cache (rel, 0L, idx);
  1588. X      _change_cache (ptr, num, new);
  1589. X      }
  1590. X   else
  1591. X      {
  1592. X      ptr = _read_cache (rel, par, idx);
  1593. X      if (pba & PARDIR)  _changeqcache (ptr, right, new);
  1594. X      else               _changeqcache (ptr, left,  new);
  1595. X      ptr->changed = 1;
  1596. X      }
  1597. X
  1598. X   if (lef != 0L)  /* Left child */
  1599. X      {
  1600. X      ptr = _read_cache (rel, lef, idx);
  1601. X      _change_cache (ptr, parent, new);
  1602. X      }
  1603. X
  1604. X   if (rig != 0L)  /* Right child */
  1605. X      {
  1606. X      ptr = _read_cache (rel, rig, idx);
  1607. X      _change_cache (ptr, parent, new);
  1608. X      }
  1609. X
  1610. X   _zero (rel, old, idx);  /* Remove old record's pointers */
  1611. X}
  1612. X
  1613. Xvoid
  1614. X_zero    (rel, pos, idx)  /* CACHED */
  1615. Xrelation *rel;
  1616. Xlong           pos;
  1617. Xint                 idx;
  1618. X{
  1619. X   cache *ptr;
  1620. X   ptr = _read_cache (rel, pos, idx);
  1621. X   _change_cache (ptr, parbal, BAL_EV);
  1622. X   _changeqcache (ptr, left,   0L);
  1623. X   _changeqcache (ptr, right,  0L);
  1624. X   _changeqcache (ptr, parent, 0L);
  1625. X}
  1626. X
  1627. Xlong
  1628. X_find_ends (rel, idx, dir)  /* CACHED */
  1629. Xrelation   *rel;
  1630. Xint              idx, dir;
  1631. X{
  1632. X   long    pos, tmp;
  1633. X   cache  *ptr;
  1634. X
  1635. X   _strobe (rel, 0);  /* Don't let anyone think we're dead */
  1636. X
  1637. X   ptr = _read_cache (rel, 0L, idx);
  1638. X   pos = ptr->num;
  1639. X
  1640. X   if (pos == 0L)  return 0L;
  1641. X
  1642. X   for (tmp = pos; ; pos = tmp)
  1643. X      {
  1644. X      ptr = _read_cache (rel, tmp, idx);
  1645. X      tmp = _cache_field (ptr, dir);
  1646. X
  1647. X      if (tmp == 0L)  return pos;
  1648. X      }
  1649. X}
  1650. X
  1651. Xlong
  1652. X_search  (rel, pos, idx, act, comp)  /* CACHED */
  1653. Xrelation *rel;
  1654. Xlong           pos;
  1655. Xint                 idx;
  1656. Xmb_action                act;
  1657. Xdataptr                       comp;
  1658. X{
  1659. X   long     x;
  1660. X   int      r,  dir;
  1661. X   dataptr  rec;
  1662. X   cache   *ptr;
  1663. X
  1664. X   if (pos == 0L)  return 0;
  1665. X
  1666. X   _strobe (rel, 0);  /* Don't let anyone think we're dead */
  1667. X
  1668. X   ptr = _read_cache (rel, pos, idx);
  1669. X
  1670. X   dir = r = _compare (rel, comp, rec=_rec(rel,pos), idx);
  1671. X   free (rec);
  1672. X
  1673. X   if (dir == 0)
  1674. X    { if (act == GTHN || act == LTEQ)                 dir =  1;
  1675. X      if (act == GTEQ || act == LTHN || act == EQUL)  dir = -1;
  1676. X    }
  1677. X
  1678. X   if ((x = _search (rel, (dir==1)?ptr->right:ptr->left, idx,act,comp)) != 0L)
  1679. X      return x;
  1680. X
  1681. X   if  (act != GTHN && act != LTHN  && r    ==  0)  return pos;
  1682. X   if ((act == GTEQ || act == GTHN) && dir  == -1)  return pos;
  1683. X   if ((act == LTEQ || act == LTHN) && dir  ==  1)  return pos;
  1684. X
  1685. X   return 0L;
  1686. X}
  1687. X
  1688. Xlong
  1689. X_find_seq (rel, top, rcd, idx, dir)  /* CACHED */
  1690. Xrelation  *rel;
  1691. Xlong            top, rcd;
  1692. Xint                       idx, dir;
  1693. X{
  1694. X   char   temp[5];
  1695. X   long   pos, tmp;
  1696. X   cache *ptr;
  1697. X
  1698. X   _strobe (rel, 0);  /* Don't let anyone think we're dead */
  1699. X
  1700. X   ptr = _read_cache (rel, rcd, idx);
  1701. X   pos = _cache_field (ptr, dir);
  1702. X
  1703. X   if (pos == 0L)
  1704. X      {
  1705. X      if (rcd == top)  return 0L;      /* hit top=no sequential available */
  1706. X      for (pos = rcd; ; pos = tmp)
  1707. X         {
  1708. X         ptr = _read_cache (rel, pos, idx);
  1709. X         tmp = ptr->parent;
  1710. X
  1711. X         if (tmp == top)  return 0L;    /* hit top=no sequential available */
  1712. X
  1713. X         temp[0] = ptr->parbal;
  1714. X         if (dir == ((temp[0] & PARDIR) ? -1 : 1))  return tmp;
  1715. X         } 
  1716. X      } 
  1717. X
  1718. X   for (dir = 0-dir; ; pos = tmp)
  1719. X      {
  1720. X      ptr = _read_cache (rel, pos, idx);
  1721. X      tmp = _cache_field (ptr, dir);
  1722. X      if (tmp == 0L)  return pos;
  1723. X      }
  1724. X}
  1725. X
  1726. Xlong
  1727. X_delete  (rel, bad)  /* CACHED */
  1728. Xrelation *rel;
  1729. Xlong           bad;
  1730. X{
  1731. X   static   int  lastmove = -1;
  1732. X   register int  i;
  1733. X   long          bp, rep, rp;
  1734. X   char          buf[5];
  1735. X   int           bal;
  1736. X   cache        *ptr;
  1737. X
  1738. X   _free_cache ();
  1739. X
  1740. X   for (i = 0; i < rel->num_i; i++)
  1741. X      {
  1742. X      ptr = _read_cache (rel, bad, i);
  1743. X      bp     = ptr->parent;
  1744. X      buf[0] = ptr->parbal;
  1745. X
  1746. X      bal= buf[0] & BAL;
  1747. X
  1748. X      if (bal != BAL_EV)
  1749. X         rep = _find_seq (rel, bad, bad, i, NUM_BAL(bal));
  1750. X      else
  1751. X         if (! (rep = _find_seq (rel, bad, bad, i, togg (lastmove))))
  1752. X            rep = _find_seq (rel, bad, bad, i, togg (lastmove));
  1753. X
  1754. X      if (! rep)
  1755. X         {
  1756. X         _dislink (rel, bad, i, 0L);
  1757. X         }
  1758. X      else
  1759. X         {
  1760. X         ptr = _read_cache (rel, rep, i);
  1761. X         rp = ptr->parent;
  1762. X
  1763. X         _dislink (rel, rep, i, 0L);
  1764. X         _replace (rel, bad, rep, i);
  1765. X         if (rp != bad)
  1766. X            if (_check (rel, rp, bp, i))
  1767. X               {
  1768. X               _flush_cache (rel, i);
  1769. X               longerr (mb_errno, -1L);
  1770. X               }
  1771. X         }
  1772. X
  1773. X      if (_check (rel, bp, 0L, i))
  1774. X         {
  1775. X         _flush_cache (rel, i);
  1776. X         longerr (mb_errno, -1L);
  1777. X         }
  1778. X
  1779. X      _flush_cache (rel, i);
  1780. X      }
  1781. X}
  1782. X
  1783. Xint
  1784. X_compare (rel, ptra, ptrb, idx)  /* -1 == ptra < ptrb */
  1785. Xrelation *rel;
  1786. Xdataptr        ptra, ptrb;
  1787. Xint                        idx;
  1788. X{
  1789. X   register int  i;
  1790. X   int           mx, n, p;
  1791. X   char          temp[5];
  1792. X
  1793. X   strzcpy (temp, rel->idxs[idx], 3);  mx = atoi (temp);
  1794. X
  1795. X   for (i = 0; i < mx; i++)
  1796. X      {
  1797. X      strzcpy (temp, &rel->idxs[idx][3*i +3], 3);  p = atoi (temp);
  1798. X      if ((n = _comp_fld (rel, ptra, ptrb, p)) != 0)  return n;
  1799. X      }
  1800. X
  1801. X   return 0;
  1802. X}
  1803. X
  1804. Xvoid
  1805. X_dumprec (rel, rec)  /* rec must not be encrypted */
  1806. Xrelation *rel;
  1807. Xdataptr        rec;
  1808. X{
  1809. X   char          buf[128], temp[80], *p;
  1810. X   register int  i;
  1811. X
  1812. X   buf[0] = 0;
  1813. X   for (i=0; i<rel->num_f; i++)
  1814. X      {
  1815. X      p=(char *)rec +rel->start[i];
  1816. X      switch (rel->type[i])
  1817. X         {
  1818. X         case T_CHAR:    strzcpy (temp, p, rel->siz[i]);               break;
  1819. X         case T_SHORT:   sprintf (temp,    "%d",  (int)*(short  *)p);  break;
  1820. X         case T_USHORT:  sprintf (temp,    "%u",  (int)*(ushort *)p);  break;
  1821. X         case T_LONG:    sprintf (temp,   "%ld", *(long   *)p);        break;
  1822. X         case T_ULONG:   sprintf (temp,   "%lu", *(ulong  *)p);        break;
  1823. X         case T_FLOAT:   sprintf (temp,    "%f", *(float  *)p);        break;
  1824. X         case T_DOUBLE:  sprintf (temp,   "%lf", *(double *)p);        break;
  1825. X         case T_MONEY:   sprintf (temp,"%-.2lf", *(double *)p);        break;
  1826. X         case T_TIME:    sprintf (temp,   "%ld", *(long   *)p);        break;
  1827. X         case T_DATE:    sprintf (temp,   "%ld", *(long   *)p);        break;
  1828. X         case T_SERIAL:  sprintf (temp,   "%ld", *(long   *)p);        break;
  1829. X         case T_PHONE:   strzcpy (temp, p, 20);                        break;
  1830. X         }
  1831. X      if (strlen (buf) + strlen (temp) > 126)  break;
  1832. X      strcat (buf, temp);
  1833. X      strcat (buf, "|");
  1834. X      }
  1835. X
  1836. X   printf ("%s\n", buf);
  1837. X}
  1838. X
  1839. Xint
  1840. X_comp_fld (rel, ptra, ptrb, fld)
  1841. Xrelation  *rel;
  1842. Xdataptr         ptra, ptrb;
  1843. Xint                         fld;
  1844. X{
  1845. X   char  *a, *b;
  1846. X   int    n;
  1847. X
  1848. X   n = rel->siz[fld];
  1849. X
  1850. X   _cryptf ((dataptr)(a = (char *)ptra +rel->start[fld]), n, rel->mask);
  1851. X   _cryptf ((dataptr)(b = (char *)ptrb +rel->start[fld]), n, rel->mask);
  1852. X
  1853. X   switch (rel->type[fld])
  1854. X      {
  1855. X      case T_SHORT:   n = _comp_short  ((short  *)a, (short  *)b);     break;
  1856. X      case T_USHORT:  n = _comp_ushort ((ushort *)a, (ushort *)b);     break;
  1857. X      case T_LONG:    n = _comp_long   ((long   *)a, (long   *)b);     break;
  1858. X      case T_ULONG:   n = _comp_ulong  ((ulong  *)a, (ulong  *)b);     break;
  1859. X      case T_FLOAT:   n = _comp_float  ((float  *)a, (float  *)b);     break;
  1860. X      case T_DOUBLE:  n = _comp_double ((double *)a, (double *)b);     break;
  1861. X      case T_MONEY:   n = _comp_double ((double *)a, (double *)b);     break;
  1862. X      case T_TIME:    n = _comp_long   ((long   *)a, (long   *)b);     break;
  1863. X      case T_DATE:    n = _comp_long   ((long   *)a, (long   *)b);     break;
  1864. X      case T_SERIAL:  n = _comp_long   ((long   *)a, (long   *)b);     break;
  1865. X      case T_PHONE:   n = _comp_string (a, b, n);  break;
  1866. X      default:        n = _comp_string (a, b, n);  break;
  1867. X      }
  1868. X
  1869. X   _cryptf ((dataptr)a, rel->siz[fld], rel->mask);
  1870. X   _cryptf ((dataptr)b, rel->siz[fld], rel->mask);
  1871. X
  1872. X   return n;
  1873. X}
  1874. X
  1875. Xint
  1876. X_comp_short (a, b)
  1877. Xshort       *a,*b;
  1878. X{
  1879. X   return ((*a < *b) ? -1 : (*a > *b) ? 1 : 0);
  1880. X}
  1881. X
  1882. Xint
  1883. X_comp_ushort (a, b)
  1884. Xushort       *a,*b;
  1885. X{
  1886. X   return ((*a < *b) ? -1 : (*a > *b) ? 1 : 0);
  1887. X}
  1888. X
  1889. Xint
  1890. X_comp_long (a, b)
  1891. Xlong       *a,*b;
  1892. X{
  1893. X   return ((*a < *b) ? -1 : (*a > *b) ? 1 : 0);
  1894. X}
  1895. X
  1896. Xint
  1897. X_comp_ulong (a, b)
  1898. Xulong       *a,*b;
  1899. X{
  1900. X   return ((*a < *b) ? -1 : (*a > *b) ? 1 : 0);
  1901. X}
  1902. X
  1903. Xint
  1904. X_comp_float (a, b)
  1905. Xfloat       *a,*b;
  1906. X{
  1907. X   return ((*a < *b) ? -1 : (*a > *b) ? 1 : 0);
  1908. X}
  1909. X
  1910. Xint
  1911. X_comp_double (a, b)
  1912. Xdouble       *a,*b;
  1913. X{
  1914. X   return ((*a < *b) ? -1 : (*a > *b) ? 1 : 0);
  1915. X}
  1916. X
  1917. Xint
  1918. X_comp_string (a, b, n)
  1919. Xchar         *a,*b;
  1920. Xint                 n;
  1921. X{
  1922. X   int  i;
  1923. X   i = strncmp (a,b,n);            /* THIS WON'T RETURN -1,0,1!! It returns  */
  1924. X   return (i < 0) ? -1 : (i > 0);  /* different amounts on different systems */
  1925. X}
  1926. X
  1927. Xdataptr
  1928. X_rec     (rel, rcd)
  1929. Xrelation *rel;
  1930. Xlong           rcd;
  1931. X{
  1932. X   dataptr a;
  1933. X   a = (dataptr)malloc (1+ rel->rec_len);
  1934. X   return _memrec (rel, rcd, a);
  1935. X}
  1936. X
  1937. Xdataptr
  1938. X_memrec  (rel, rcd, a)
  1939. Xrelation *rel;
  1940. Xlong           rcd;
  1941. Xdataptr             a;
  1942. X{
  1943. X   GO_RECID   (rel, rcd);
  1944. X   readx      (rel->relcode, a, rel->rec_len);
  1945. X   return a;
  1946. X}
  1947. X
  1948. END_OF_FILE
  1949.   if test 11746 -ne `wc -c <'src/util2.c'`; then
  1950.     echo shar: \"'src/util2.c'\" unpacked with wrong size!
  1951.   fi
  1952.   # end of 'src/util2.c'
  1953. fi
  1954. echo shar: End of archive 5 \(of 8\).
  1955. cp /dev/null ark5isdone
  1956. MISSING=""
  1957. for I in 1 2 3 4 5 6 7 8 ; do
  1958.     if test ! -f ark${I}isdone ; then
  1959.     MISSING="${MISSING} ${I}"
  1960.     fi
  1961. done
  1962. if test "${MISSING}" = "" ; then
  1963.     echo You have unpacked all 8 archives.
  1964.     rm -f ark[1-9]isdone
  1965. else
  1966.     echo You still must unpack the following archives:
  1967.     echo "        " ${MISSING}
  1968. fi
  1969. exit 0
  1970. exit 0 # Just in case...
  1971.