home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume33 / mbase / part05 < prev    next >
Encoding:
Text File  |  1992-11-23  |  55.3 KB  |  1,965 lines

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