home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume19 / shape / part20 < prev    next >
Text File  |  1989-05-31  |  57KB  |  1,883 lines

  1. Subject:  v19i033:  A software configuration management system, Part20/33
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Axel Mahler <unido!coma!axel>
  7. Posting-number: Volume 19, Issue 33
  8. Archive-name: shape/part20
  9.  
  10.  
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 20 (of 33)."
  19. # Contents:  src/afs/afhash.c src/vfind/vfind.c tutorial/make2shape.ms
  20. # Wrapped by rsalz@papaya.bbn.com on Thu Jun  1 19:27:12 1989
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'src/afs/afhash.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'src/afs/afhash.c'\"
  24. else
  25. echo shar: Extracting \"'src/afs/afhash.c'\" \(17913 characters\)
  26. sed "s/^X//" >'src/afs/afhash.c' <<'END_OF_FILE'
  27. X/*
  28. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  29. X *  and U. Pralle
  30. X * 
  31. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  32. X * WARRANTY for any part of this software to work correctly or as described
  33. X * in the manuals. We do not accept any liability for any kind of damage
  34. X * caused by use of this software, such as loss of data, time, money, or 
  35. X * effort.
  36. X * 
  37. X * Permission is granted to use, copy, modify, or distribute any part of
  38. X * this software as long as this is done without asking for charge, and
  39. X * provided that this copyright notice is retained as part of the source
  40. X * files. You may charge a distribution fee for the physical act of
  41. X * transferring a copy, and you may at your option offer warranty
  42. X * protection in exchange for a fee.
  43. X * 
  44. X * Direct questions to: Tech. Univ. Berlin
  45. X *              Wilfried Koch
  46. X *              Sekr. FR 5-6 
  47. X *              Franklinstr. 28/29
  48. X *              D-1000 Berlin 10, West Germany
  49. X * 
  50. X *              Tel: +49-30-314-22972
  51. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  52. X */
  53. X/*LINTLIBRARY*/
  54. X/*
  55. X *    Shape/AFS
  56. X *
  57. X *    afhash.c -- manage hashtable for user defined attributes
  58. X *
  59. X *    Author: Axel Mahler, TU-Berlin
  60. X *
  61. X *      adapted by: Andreas Lampen, TU-Berlin (andy@coma.UUCP)
  62. X *                          (andy@db0tui62.BITNET)
  63. X *
  64. X *    $Header: afhash.c[1.4] Wed Feb 22 16:27:37 1989 andy@coma published $
  65. X *
  66. X *    EXPORT:
  67. X *    af_hashinit -- initialize hash table
  68. X *      af_hashfree -- detach hash table (free allocated memory)
  69. X *      af_hashsym -- put entry into hashtable
  70. X *      af_fhash -- get hash value
  71. X *      af_replsym -- replace symbol in hashtable
  72. X *      af_delsym -- delete symbol from hashtable
  73. X *      af_symlookup -- look for symbol in hashtable
  74. X *      af_vallookup -- look for single value
  75. X *      af_lhashsyms -- create a list of all symbols in hashtable
  76. X *      af_hashcopy -- copy hashtable
  77. X *    af_match -- test match of user defined attributes
  78. X *      af_dumphtb -- dump hash table
  79. X */
  80. X#include <stdio.h>
  81. X#include <sys/types.h>
  82. X#include <sys/stat.h>
  83. X#include <string.h>
  84. X#ifdef SUNOS_4_0
  85. X#include <strings.h>
  86. X#endif
  87. X
  88. X#include "typeconv.h"
  89. X#include "afsys.h"
  90. X#include "afs.h"
  91. X
  92. X#ifdef CCOLL
  93. Xint af_collcnt = 0;
  94. Xint af_symcount = 0;
  95. X#endif
  96. X
  97. X#ifdef MEMDEBUG
  98. Xextern FILE *memprot;
  99. X#endif
  100. X#ifdef HASHDEBUG
  101. Xextern FILE *hashprot;
  102. X#endif
  103. X
  104. XAf_hashent af_hashentry; /* hashtable entry that was found during last */
  105. X                         /* retrieve operation */
  106. X
  107. X/*=====================================================================
  108. X * af_hashinit -- initialize hash table
  109. X *
  110. X *=====================================================================*/ 
  111. X
  112. XEXPORT af_hashinit (htab, hsize, af_fhash) 
  113. X     Af_hash *htab; 
  114. X     int hsize, (*af_fhash)();
  115. X{
  116. X  char *malloc();
  117. X
  118. X  /* initialize Hash - structure */
  119. X  htab->hsize = hsize;
  120. X  if ((htab->hashtb = (Af_hashent *)malloc ((unsigned) (htab->hsize*sizeof (Af_hashent)))) == NULL)
  121. X    FAIL ("hashinit", "malloc", AF_ESYSERR, ERROR);
  122. X  htab->fhash = af_fhash;
  123. X
  124. X  /* set hashlist all zeros */
  125. X  bzero ((char *)htab->hashtb, htab->hsize*sizeof (Af_hashent));
  126. X  return (AF_OK);
  127. X}
  128. X
  129. X
  130. X/*=====================================================================
  131. X * af_hashfree -- detach hash table (free allocated memory)
  132. X *
  133. X * may be slow; perhaps a memory management with af_malloc would be 
  134. X * better.
  135. X *=====================================================================*/ 
  136. X
  137. XEXPORT af_hashfree (htab)
  138. X     Af_hash *htab;
  139. X{
  140. X  register int  i;
  141. X  Af_hashent    *entry;
  142. X
  143. X  for (i=0; i<htab->hsize; i++)
  144. X    {
  145. X      if (htab->hashtb[i].next)
  146. X    {
  147. X      entry = htab->hashtb[i].next;
  148. X      do
  149. X        {
  150. X#ifdef MEMDEBUG
  151. X          fprintf (memprot, "%x(sym-fr)\n", entry->symbol);
  152. X#endif
  153. X          free (entry->symbol);
  154. X#ifdef MEMDEBUG
  155. X          fprintf (memprot, "%x(e-fr)\n", entry);
  156. X#endif
  157. X          free ((char *)entry); 
  158. X        }
  159. X      while (entry = entry->next);
  160. X    }
  161. X      if (htab->hashtb[i].symbol)
  162. X    {
  163. X#ifdef MEMDEBUG
  164. X      fprintf (memprot, "%x(sym-fr)\n", entry->symbol);
  165. X#endif
  166. X      free (htab->hashtb[i].symbol);
  167. X    }
  168. X    }
  169. X  free ((char *)htab->hashtb);
  170. X  htab->hashtb = (Af_hashent *)0;
  171. X}
  172. X
  173. X
  174. X/*=====================================================================
  175. X * af_hashsym -- put entry into hashtable
  176. X *
  177. X *=====================================================================*/ 
  178. X
  179. XEXPORT char *af_hashsym (htab, symbol, list)
  180. X     Af_hash    *htab; 
  181. X     char       *symbol;
  182. X     Af_revlist *list;
  183. X{
  184. X  /*
  185. X   * put entry into hashtable. Only called, if symbol hasn't been found in 
  186. X   * hashtable. Function returns pointer to the symbol-string.
  187. X   */
  188. X  int symindex;
  189. X  Af_hashent *new, *curptr;
  190. X  char *retptr, *malloc();
  191. X
  192. X#ifdef HASHDEBUG
  193. X  fprintf (hashprot, "HASHSYM: %s\n", symbol);
  194. X#endif
  195. X  symindex = htab->fhash (htab->hsize, symbol);
  196. X  if (!htab->hashtb[symindex].symbol)  /* found entry is not used yet */
  197. X    {
  198. X      if ((htab->hashtb[symindex].symbol = malloc ((unsigned) (strlen (symbol) + sizeof (char)))) == (char *)0)
  199. X    FAIL ("hashsym", "malloc", AF_ESYSERR, (char *)0);
  200. X#ifdef MEMDEBUG
  201. X      fprintf (memprot, "%x(sym-al) %d bytes ", htab->hashtb[symindex].symbol,
  202. X           strlen (symbol) + sizeof (char));
  203. X#endif
  204. X      (void) strcpy (htab->hashtb[symindex].symbol, symbol);
  205. X      htab->hashtb[symindex].revlist = list;
  206. X      htab->hashtb[symindex].next = NULL;
  207. X      retptr = htab->hashtb[symindex].symbol;
  208. X      curptr = &(htab->hashtb[symindex]);
  209. X    }
  210. X  else /* oh boy - a collision! */
  211. X    {
  212. X#ifdef CCOLL
  213. X      af_collcnt++;
  214. X      fprintf (stderr, "%d'th hash-collision (symbol).\n", af_collcnt);
  215. X#endif
  216. X      if ((new = (Af_hashent*)malloc ((unsigned) sizeof (Af_hashent))) == (Af_hashent*)0)
  217. X    FAIL ("hashsym", "malloc", AF_ESYSERR, (char *)0);
  218. X#ifdef MEMDEBUG
  219. X      fprintf (memprot, "%x(e-al) %d bytes ", new, sizeof (Af_hashent));
  220. X#endif
  221. X      if ((new->symbol = malloc ((unsigned) (strlen (symbol) + sizeof (char)))) == (char *)0)
  222. X    FAIL ("hashsym", "malloc", AF_ESYSERR, (char *)0);
  223. X#ifdef MEMDEBUG
  224. X      fprintf (memprot, "%x(sym-al) %d bytes ", new->symbol,
  225. X           strlen (symbol) + sizeof (char));
  226. X#endif
  227. X      (void) strcpy (new->symbol, symbol);
  228. X      new->revlist = list;
  229. X      new->next = NULL;
  230. X      curptr = &htab->hashtb[symindex];
  231. X      while (curptr->next)
  232. X    curptr = curptr->next;
  233. X      curptr->next = new;
  234. X      curptr = curptr->next; /* points to new entry */
  235. X      retptr =  new->symbol;
  236. X    } /* endif */
  237. X
  238. X  /* filter out double values if list == *0 */
  239. X  /* not yet implemented (filter out double values) */
  240. X
  241. X  return (retptr);
  242. X} /* end af_hashsym */
  243. X
  244. X
  245. XEXPORT int af_fhash (htabsiz, hstr) /* from Aho/Ullman */
  246. X     int  htabsiz; 
  247. X     char *hstr;
  248. X{
  249. X  register char *p;
  250. X  register unsigned long hval, g;
  251. X
  252. X  hval = 0;
  253. X  for (p = hstr; (*p!=AF_UDANAMDEL) && (*p!=AF_UDAVALDEL) && (*p!='\0'); p++)
  254. X    {
  255. X      hval = (hval << 4) ^ (*p);
  256. X      if (g = hval & 0xf0000000)
  257. X    {
  258. X      hval = hval ^ (g >> 24);
  259. X      hval = hval ^ g;
  260. X    }
  261. X    }
  262. X  return (hval % htabsiz);
  263. X}
  264. X
  265. X/*=====================================================================
  266. X * af_replsym -- replace symbol in hashtable
  267. X *
  268. X *=====================================================================*/ 
  269. X
  270. XEXPORT char *af_replsym (htab, symbol, list)
  271. X     Af_hash    *htab; 
  272. X     char       *symbol;
  273. X     Af_revlist *list;
  274. X{
  275. X  int symindex;
  276. X  Af_hashent *entry;
  277. X  char *realloc();
  278. X
  279. X#ifdef HASHDEBUG
  280. X  fprintf (hashprot, "REPLSYM: %s\n", symbol);
  281. X#endif
  282. X  symindex = htab->fhash (htab->hsize, symbol);
  283. X  if (htab->hashtb[symindex].symbol)  /* found something */
  284. X    {
  285. X      if (!af_symcmp (&htab->hashtb[symindex], symbol, list))  /* found it ? */
  286. X    { 
  287. X      if ((htab->hashtb[symindex].symbol =
  288. X           realloc (htab->hashtb[symindex].symbol, (unsigned) (strlen (symbol) + sizeof (char)))) == (char *)0)
  289. X        FAIL ("replsym", "realloc", AF_ESYSERR, (char *)0);
  290. X      (void) strcpy (htab->hashtb[symindex].symbol, symbol);
  291. X      htab->hashtb[symindex].revlist = list;
  292. X      return (htab->hashtb[symindex].symbol);
  293. X    }
  294. X      else /* maybe it is somewhere down the gully */ 
  295. X    { 
  296. X      entry = &htab->hashtb[symindex];
  297. X      while (entry->next)
  298. X        {
  299. X          entry = entry->next;
  300. X          if (!af_symcmp (entry, symbol, list))
  301. X        {
  302. X          if ((entry->symbol = 
  303. X               realloc (entry->symbol, (unsigned) (strlen (symbol) + sizeof (char)))) == (char *)0)
  304. X            FAIL ("replsym", "realloc", AF_ESYSERR, (char *)0);
  305. X          (void) strcpy (entry->symbol, symbol);
  306. X          entry->revlist = list;
  307. X          return (entry->symbol);
  308. X        }
  309. X        }
  310. X    }
  311. X    }
  312. X  /* when we reach this point, the symbol hasn't been known */
  313. X
  314. X  /* this should never occur */
  315. X  FAIL ("replsym", "symbol not found", AF_EINTERNAL, (char *)0);
  316. X} /* end af_replsym */
  317. X
  318. X/*=====================================================================
  319. X * af_delsym -- delete symbol from hashtable
  320. X *
  321. X *=====================================================================*/ 
  322. X
  323. XEXPORT af_delsym (htab, symbol, list)
  324. X     Af_hash    *htab; 
  325. X     char       *symbol;
  326. X     Af_revlist *list;
  327. X{
  328. X  int  symindex;
  329. X  Af_hashent *del, *succ;
  330. X  char *malloc();
  331. X
  332. X#ifdef HASHDEBUG
  333. X  fprintf (hashprot, "DELSYM: %s\n", symbol);
  334. X#endif
  335. X  symindex = htab->fhash (htab->hsize, symbol);
  336. X  if (!htab->hashtb[symindex].symbol) /* no entry found (should never occur) */
  337. X    FAIL ("delsym", "symbol not found", AF_EINTERNAL, ERROR); 
  338. X
  339. X  del = &htab->hashtb[symindex];
  340. X  if (!af_symcmp (del, symbol, list))  /* found it ? */
  341. X    {
  342. X#ifdef MEMDEBUG
  343. X      fprintf (memprot, "%x(sym-fr)\n", del->symbol);
  344. X#endif
  345. X      free (del->symbol);
  346. X
  347. X      if (del->next) /* if there are more entries */
  348. X    {
  349. X#ifdef HASHDEBUG
  350. X  fprintf (hashprot, "NEXT: %s\n", del->next->symbol);
  351. X#endif
  352. X      del->symbol = del->next->symbol;
  353. X          del->revlist = del->next->revlist;
  354. X      succ = del->next->next;
  355. X#ifdef MEMDEBUG
  356. X  fprintf (memprot, "%x(e-fr)\n", del->next);
  357. X#endif
  358. X      free ((char *)del->next);
  359. X      del->next = succ;
  360. X    }
  361. X      else
  362. X    {
  363. X      del->symbol = (char *)0;
  364. X          del->revlist = (Af_revlist *)0;
  365. X      del->next = (Af_hashent *)0;
  366. X    }
  367. X      return (AF_OK);
  368. X    }
  369. X  else /* search for entry in gully */
  370. X    {
  371. X      while (del->next)
  372. X    {
  373. X      if (!af_symcmp (del->next, symbol, list))
  374. X        {      
  375. X#ifdef MEMDEBUG
  376. X          fprintf (memprot, "%x(sym-fr)\n", del->next->symbol);
  377. X#endif
  378. X          free (del->next->symbol);
  379. X          succ = del->next->next;
  380. X#ifdef MEMDEBUG
  381. X  fprintf (memprot, "%x(e-fr)\n", del->next);
  382. X#endif
  383. X          free ((char *)del->next);
  384. X          del->next = succ;
  385. X          return (AF_OK);
  386. X        }
  387. X      del = del->next;
  388. X    }
  389. X      FAIL ("delsym", "symbol not found (in gully)", AF_EINTERNAL, ERROR);
  390. X    }
  391. X}
  392. X
  393. X/*=====================================================================
  394. X * af_symlookup -- look for symbol in hashtable
  395. X *
  396. X *=====================================================================*/ 
  397. X
  398. XEXPORT char *af_symlookup (htab, symbol, listin, listout)
  399. X     Af_hash    *htab; 
  400. X     char       *symbol; 
  401. X     Af_revlist *listin, **listout;
  402. X{
  403. X  /* 
  404. X   * Function searches htab for an entry with the given name symbol.
  405. X   * If such an entry exists, a pointer to the symbol string is returned
  406. X   * and the external variable af_cursymval is set to the corresponding
  407. X   * symbolvalue
  408. X   */
  409. X  int where;
  410. X  Af_hashent *targ;
  411. X  bool delivernext = FALSE;
  412. X
  413. X  where = htab->fhash (htab->hsize, symbol);
  414. X  if (htab->hashtb[where].symbol)  /* well, we found at least something */
  415. X    {
  416. X      /* if we search a specific revlist in the gully */
  417. X      if (listin)
  418. X    {
  419. X      if (!af_symcmp (&htab->hashtb[where], symbol, listin))
  420. X        delivernext = TRUE;
  421. X
  422. X      targ = &htab->hashtb[where];
  423. X      while (targ = targ->next)
  424. X        {
  425. X          if (!af_symcmp (targ, symbol, (Af_revlist *)0))
  426. X        {
  427. X          if (delivernext)
  428. X            {
  429. X              af_hashentry = *targ;
  430. X              *listout = targ->revlist;
  431. X              return (targ->symbol);
  432. X            }
  433. X          else
  434. X            if (targ->revlist == listin)
  435. X              delivernext = TRUE;
  436. X        }
  437. X        }
  438. X    }
  439. X      else /* normal case */
  440. X    {
  441. X      if (!af_symcmp (&htab->hashtb[where], symbol, (Af_revlist *)0))
  442. X        { 
  443. X          af_hashentry = htab->hashtb[where];
  444. X          if (listout != (Af_revlist **)0)
  445. X        *listout = htab->hashtb[where].revlist;
  446. X          return htab->hashtb[where].symbol;
  447. X        }
  448. X      else /* maybe it is somewhere down the gully */ 
  449. X        { 
  450. X          targ = &htab->hashtb[where];
  451. X          while (targ->next)
  452. X        {
  453. X          targ = targ->next;
  454. X          if (!af_symcmp (targ, symbol, (Af_revlist *)0))
  455. X            {
  456. X              af_hashentry = *targ;
  457. X              if (listout != (Af_revlist **)0)
  458. X            *listout = targ->revlist;
  459. X              return (targ->symbol);
  460. X            }
  461. X        }
  462. X        }
  463. X    }
  464. X    }
  465. X  /* when we come to this point, the symbol hasn't been known */
  466. X  if (listout != (Af_revlist **)0)
  467. X    *listout = (Af_revlist *)0;
  468. X  return ((char *)0);
  469. X}
  470. X
  471. X/*=====================================================================
  472. X * af_vallookup -- look for single value
  473. X *
  474. X *=====================================================================*/ 
  475. X
  476. XEXPORT char *af_vallookup (entry, value)
  477. X     Af_hashent *entry;
  478. X     char *value; 
  479. X{
  480. X  char *valptr;
  481. X
  482. X  if (valptr = index (entry->symbol, AF_UDANAMDEL))
  483. X    valptr += sizeof (char);
  484. X
  485. X  /* search until value is found */
  486. X  while (af_valcmp (valptr, value))
  487. X    {
  488. X      if ((valptr = index (valptr, AF_UDAVALDEL)) == (char *)0) 
  489. X    return (char *)0;
  490. X      valptr += sizeof (char);
  491. X    }
  492. X
  493. X  return (valptr);
  494. X}
  495. X
  496. X/*=====================================================================
  497. X * af_lhashsyms -- create a list of all symbols in hashtable.
  498. X *                 A (char *)0 terminated pointerlist, listing all
  499. X *                 symbols in the hashtable is created.
  500. X *
  501. X *=====================================================================*/ 
  502. X
  503. XEXPORT af_lhashsyms (htab, symbollist)
  504. X     Af_hash *htab;
  505. X     char    **symbollist;
  506. X{
  507. X  register int i, j=0, size=0;
  508. X  register Af_hashent *h;
  509. X  
  510. X  if (htab->hashtb != (Af_hashent *)0)
  511. X    {
  512. X      for (i = 0; i < htab->hsize; i++)
  513. X    if (htab->hashtb[i].symbol != (char *)0)
  514. X      {
  515. X        h = &htab->hashtb[i];
  516. X        while (h) 
  517. X          {
  518. X        symbollist[j] = h->symbol;
  519. X        size = size + (strlen (h->symbol)+1);
  520. X        j++;
  521. X        h = h->next;
  522. X          }
  523. X      }
  524. X    }
  525. X  symbollist[j] = (char *)0;
  526. X  return (size);
  527. X}
  528. X
  529. X
  530. X/*=====================================================================
  531. X * af_hashcopy -- copy hash table
  532. X *
  533. X *=====================================================================*/ 
  534. X
  535. XEXPORT af_hashcopy (oldhtab, newhtab) 
  536. X     Af_hash *oldhtab, *newhtab;
  537. X{
  538. X  register i;
  539. X  char *af_hashsysm(), *list[AF_MAXUDAS];
  540. X
  541. X
  542. X  /* initialize new hashtable */
  543. X  newhtab->hsize = oldhtab->hsize;
  544. X  newhtab->fhash = oldhtab->fhash;
  545. X
  546. X  /* copy hashtable */
  547. X  (void) af_lhashsyms (oldhtab, list);
  548. X  i=0;
  549. X  while (list[i] != (char *)0)
  550. X    {
  551. X      (void) af_hashsym (newhtab, list[i], (Af_revlist *)0);
  552. X      i++;
  553. X    }
  554. X
  555. X  return (AF_OK);
  556. X}
  557. X
  558. X
  559. X/*===============================================================
  560. X * af_symcmp -- compare contents of hashtable entry
  561. X *              either of the form name=[value ...]
  562. X *              or                 name; listptr;
  563. X *           Return values like strcmp.
  564. X *
  565. X *==============================================================*/
  566. X
  567. XLOCAL af_symcmp (entry, str, listptr)
  568. X     Af_hashent *entry;
  569. X     char       *str;
  570. X     Af_revlist *listptr;
  571. X{
  572. X  char *str1;
  573. X
  574. X  /* if a listpointer is given */
  575. X  if (listptr)
  576. X    {
  577. X      if (entry->revlist == listptr)
  578. X    return (strcmp (entry->symbol, str));
  579. X      else
  580. X    return (1);
  581. X    }
  582. X  else
  583. X    {
  584. X      str1 = entry->symbol;
  585. X      while (*str1 == *str)
  586. X    {
  587. X      if ((*str1 == AF_UDANAMDEL) || (*str1 == '\0'))
  588. X        return (0);
  589. X      str1++;
  590. X      str++;
  591. X    }
  592. X      if (((*str1 == AF_UDANAMDEL) && (*str =='\0')) ||
  593. X      ((*str1 =='\0') && (*str == AF_UDANAMDEL)))
  594. X    return (0);
  595. X      else
  596. X    
  597. Xreturn (*str1 - *str);
  598. X    }
  599. X}
  600. X
  601. X/*===============================================================
  602. X * af_valcmp -- compare single values in a string of the form
  603. X *                          name=[value1 value2 ...]
  604. X *           Return values like strcmp.
  605. X *
  606. X *==============================================================*/
  607. X
  608. XLOCAL af_valcmp (str1, str2)
  609. X     char *str1, *str2;
  610. X{
  611. X  while (*str1 == *str2)
  612. X    {
  613. X      if ((*str1 == AF_UDAVALDEL) || (*str1 == '\0'))
  614. X    return (0);
  615. X      str1++;
  616. X      str2++;
  617. X    }
  618. X  if (((*str1 == AF_UDAVALDEL) && (*str2 =='\0')) ||
  619. X      ((*str1 =='\0') && (*str2 == AF_UDAVALDEL)))
  620. X    return (0);
  621. X  else
  622. X    return (*str1 - *str2);
  623. X}
  624. X
  625. X/*====================================================================
  626. X *    af_match
  627. X *    returnes FALSE if entry matches, else TRUE
  628. X *
  629. X *====================================================================*/
  630. X
  631. XEXPORT af_match (entry, hashtab)
  632. X     char    *entry;
  633. X     Af_hash *hashtab;
  634. X{
  635. X  char *valptr, *af_symlookup(), *af_vallookup();
  636. X
  637. X  /* if user defined attribute does not exist */
  638. X  if ((af_symlookup (hashtab, entry, (Af_revlist *)0, (Af_revlist **)0))
  639. X                                                              == (char*)0)
  640. X      return (ERROR);
  641. X
  642. X  /* else compare values */
  643. X  if (valptr = index (entry, AF_UDANAMDEL))
  644. X    {
  645. X      do
  646. X    {
  647. X      valptr = valptr + sizeof (char);
  648. X      if ((af_vallookup (&af_hashentry, valptr) == (char *)0)
  649. X          && (*valptr != '\0'))
  650. X        return (ERROR);
  651. X    }
  652. X      while (valptr = index (valptr, AF_UDAVALDEL));
  653. X    }
  654. X  return (AF_OK);
  655. X}
  656. X
  657. X/**** DEBUG **** DEBUG **** DEBUG **** DEBUG **** DEBUG **** DEBUG ****/
  658. X
  659. X/*=====================================================================
  660. X * af_dumphtb -- dump hashtable
  661. X *
  662. X *=====================================================================*/ 
  663. X
  664. XEXPORT af_dumphtb (htab) /* for debug purposes */
  665. X     Af_hash *htab;
  666. X{
  667. X  register int i;
  668. X  register Af_hashent *h;
  669. X
  670. X#ifdef CCOLL
  671. X  fprintf (stderr, "Hash-collision statistics:\n");
  672. X  fprintf (stderr, "Table-size: %d\tNo. of symbols: %d\tCollisions: %d\n",
  673. X       htab->hsize, af_symcount, af_collcnt);
  674. X#endif
  675. X
  676. X  for (i = 0; i < htab->hsize; i++)
  677. X    {
  678. X      if (htab->hashtb[i].symbol[0])
  679. X    {
  680. X      h = &htab->hashtb[i];
  681. X      while (h) 
  682. X        {
  683. X          fprintf (stderr, "\nsymbol: (%d) %s -- list: %x", 
  684. X               i, h->symbol, h->revlist);
  685. X          h = h->next;
  686. X        }
  687. X    }
  688. X      else fprintf (stderr, ".");
  689. X    }
  690. X}
  691. X
  692. X
  693. END_OF_FILE
  694. if test 17913 -ne `wc -c <'src/afs/afhash.c'`; then
  695.     echo shar: \"'src/afs/afhash.c'\" unpacked with wrong size!
  696. fi
  697. # end of 'src/afs/afhash.c'
  698. fi
  699. if test -f 'src/vfind/vfind.c' -a "${1}" != "-c" ; then 
  700.   echo shar: Will not clobber existing file \"'src/vfind/vfind.c'\"
  701. else
  702. echo shar: Extracting \"'src/vfind/vfind.c'\" \(17438 characters\)
  703. sed "s/^X//" >'src/vfind/vfind.c' <<'END_OF_FILE'
  704. X/*
  705. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  706. X *  and U. Pralle
  707. X * 
  708. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  709. X * WARRANTY for any part of this software to work correctly or as described
  710. X * in the manuals. We do not accept any liability for any kind of damage
  711. X * caused by use of this software, such as loss of data, time, money, or 
  712. X * effort.
  713. X * 
  714. X * Permission is granted to use, copy, modify, or distribute any part of
  715. X * this software as long as this is done without asking for charge, and
  716. X * provided that this copyright notice is retained as part of the source
  717. X * files. You may charge a distribution fee for the physical act of
  718. X * transferring a copy, and you may at your option offer warranty
  719. X * protection in exchange for a fee.
  720. X * 
  721. X * Direct questions to: Tech. Univ. Berlin
  722. X *              Wilfried Koch
  723. X *              Sekr. FR 5-6 
  724. X *              Franklinstr. 28/29
  725. X *              D-1000 Berlin 10, West Germany
  726. X * 
  727. X *              Tel: +49-30-314-22972
  728. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  729. X */
  730. X/*  LAST EDIT: Mon Feb 20 14:15:16 1989 by Uli Pralle (coma!uli)  */
  731. X/*
  732. X * vfind.c
  733. X */
  734. X#ifndef lint
  735. Xstatic char *AFSid = "$Header: vfind.c[1.6] Tue Feb 21 20:22:53 1989 uli@coma published $";
  736. Xstatic char *Objfile = "vfind.c[1.6] published";
  737. X#ifdef CFFLGS
  738. X  static char *Cflags = CFFLGS;
  739. X#endif
  740. X#endif
  741. X/*
  742. X * Log for /u/shape/dist-tape/src/vfind/vfind.c[1.6]
  743. X *     Tue Feb 21 20:22:53 1989 uli@coma published $
  744. X *  
  745. X *        * Vfind is the same as find(1) except that it has more afs
  746. X *        related primaries such as -eq, -le, -lt, -ge, -gt, -uda,
  747. X *      -symbolic, -locked, -locker, etc.
  748. X *  
  749. X *      * vfind has problems with udas.
  750. X *  
  751. X *      * vfind is part of the shape toolkit release for comp.sources.unix.
  752. X *  
  753. X *  
  754. X */
  755. X
  756. X#include <sys/types.h>
  757. X#include <sys/stat.h>
  758. X#include <sys/dir.h>
  759. X#include <sys/wait.h>
  760. X#include <stdio.h>
  761. X#include <strings.h>
  762. X#include <afs.h>
  763. X#include <afsapp.h>
  764. X#include <ParseArgs.h>
  765. X
  766. X#include "atk.h"
  767. X
  768. Xtypedef struct expr *Expr;    /* short hand */
  769. Xstruct expr {
  770. X  int (*eval)();        /* evaluator */
  771. X  Expr left;            /* left op */
  772. X  Expr right;            /* right op */
  773. X};
  774. X
  775. Xextern char *getwd();
  776. Xextern char *malloc();
  777. Xextern char *re_comp();
  778. X
  779. Xstatic char *progname;            /* av[0] w/o leading path */ 
  780. Xstatic char startdir[MAXPATHLEN+1]; /* dir at beginning of process */
  781. Xstatic char garbage[80];    /* for error messages */
  782. Xstatic int nac;            /* ac after option parsing */
  783. Xstatic char **nav;        /* av after option parsing */
  784. Xstatic int npaths;        /* pathname list */
  785. Xstatic struct expr *exprl;    /* expression list */
  786. Xstatic int idx;            /*  */
  787. Xstatic long now;        /* time in secs */
  788. Xstatic Af_attrs attrs;        /* attr buf */
  789. Xstatic Af_set set, bset;    /* attr set */
  790. Xstatic int Bflag, Pflag, Fflag;
  791. X
  792. X/* Options */
  793. Xstatic int vf_prune_opt () {
  794. X  Pflag++;
  795. X  return 0;
  796. X}
  797. X
  798. Xstatic int vf_version_opt () {
  799. X  char *vfversion();
  800. X  
  801. X  (void) printf ("This is %s version %s.\n", progname, vfversion());
  802. X  (void) printf ("AFS version %s.\n", af_version());
  803. X  return 1;            /* force termination */
  804. X}
  805. X
  806. Xstatic int vf_b_opt () {
  807. X  Bflag++;
  808. X  return 0;
  809. X}
  810. X
  811. Xstatic int vf_f_opt () {
  812. X  Fflag++;
  813. X  return 0;
  814. X}
  815. X
  816. Xstatic int vf_help_opt () {
  817. X  extern OptDesc optdesc[];
  818. X  pa_ShortUsage(progname, optdesc, "path-list expression");
  819. X
  820. X  return 1;
  821. X}
  822. X
  823. XOptDesc optdesc[] = {
  824. X  { "version", OPT_IS_SWITCH, vf_version_opt },
  825. X  { "bpool", OPT_IS_SWITCH, vf_b_opt},
  826. X  { "h", OPT_IS_SWITCH, vf_help_opt},
  827. X  { "prune", OPT_IS_SWITCH, vf_prune_opt},
  828. X  { "force", OPT_IS_SWITCH, vf_f_opt},
  829. X  { (char *) NULL, NULL, NULL },
  830. X};
  831. X
  832. Xvoid byebye(i) {
  833. X  (void) chdir("/tmp");        /* in case of -pg. */
  834. X  exit(i);
  835. X}
  836. X
  837. Xvoid Usage() {
  838. X  (void) fprintf (stderr,"%s: usage: %s path-list expression.\n",
  839. X          progname , progname);
  840. X  byebye(1);
  841. X}
  842. X
  843. X/* primaries */
  844. Xstatic int print () {
  845. X  puts(at_getbndvers(&attrs));
  846. X  return 1;
  847. X}
  848. X
  849. Xchar *mkedpat(pat) char *pat; {
  850. X  char pattern[1024];
  851. X  char *cp;
  852. X  int i;
  853. X
  854. X  if (pat && *(cp = pat) == '\0')
  855. X    return (char *) NULL;
  856. X
  857. X  *pattern = '^';
  858. X  for (i = 1; *cp; cp++) {
  859. X    if (i >= 1024) {
  860. X      (void) fprintf (stderr, "%s: pattern to long.\n", progname);
  861. X      byebye(1);
  862. X    }
  863. X    
  864. X    switch (*cp) {
  865. X    case '?':
  866. X      pattern[i++] = '.';
  867. X      break;
  868. X    case '*':
  869. X      pattern[i++] = '.'; pattern[i++] = '*';
  870. X      break;
  871. X    default:
  872. X      pattern[i++] = *cp;
  873. X      break;
  874. X    }
  875. X  }
  876. X  pattern[i++] = '$'; pattern[i] = '\0';
  877. X  
  878. X  if ((cp = malloc ((unsigned) (strlen(pattern) + 1))) == (char *) NULL) {
  879. X    (void) fprintf (stderr, "%s: out of memory.\n", progname);
  880. X    byebye(1);
  881. X  }
  882. X  return strcpy(cp, pattern);
  883. X}
  884. X
  885. Xstatic int name (exp) Expr exp; {
  886. X  char *cp;
  887. X  
  888. X  if (cp = re_comp ((char *) exp->left)) {
  889. X    (void) fprintf (stderr, "%s: %s\n", progname, cp);
  890. X    byebye(1);
  891. X  }
  892. X
  893. X  return re_exec(at_getfilename(&attrs));
  894. X
  895. X}
  896. X
  897. Xstatic int state (exp) Expr exp; {
  898. X  return attrs.af_state == (int) exp->left;
  899. X}
  900. X
  901. Xstatic int uda (exp) Expr exp; {
  902. X  return (at_matchuda(&attrs, (char *) exp->left));
  903. X}
  904. X
  905. Xstatic int symname (exp) Expr exp; {
  906. X  char symnameuda[AF_UDANAMLEN+1];
  907. X
  908. X  return at_matchuda(&attrs, sprintf(symnameuda, "%s=%s", SYMNAME,
  909. X                     (char *) exp->left));
  910. X}
  911. X
  912. Xstatic int perm (exp) Expr exp; {
  913. X  return (attrs.af_mode & (int) exp->right & 07777) == (int) exp->left;
  914. X}
  915. X
  916. Xstatic int user (exp) Expr exp; {
  917. X  return (!strcmp((char *)exp->left, attrs.af_owner.af_username)
  918. X      && (exp->right ? !strcmp((char *)exp->right,
  919. X                  attrs.af_owner.af_userhost) : 1));
  920. X}
  921. X
  922. Xstatic int locked () {
  923. X  return (attrs.af_locker.af_username[0] != '\0');
  924. X}
  925. X
  926. Xstatic int locker (exp) Expr exp; {
  927. X  return (!strcmp((char *)exp->left, attrs.af_locker.af_username)
  928. X      && (exp->right ? !strcmp((char *)exp->right,
  929. X                  attrs.af_locker.af_userhost) : 1));
  930. X}
  931. X
  932. Xstatic int type (exp) Expr exp; {
  933. X  return (attrs.af_mode&S_IFMT) == (int) exp->left;
  934. X}
  935. X
  936. Xstatic int vl () {
  937. X  printf ("%s %s %s %8d %s %s\n",
  938. X      at_getmode(&attrs),
  939. X      at_getversstate(&attrs, 0),
  940. X      at_getuser(&(attrs.af_owner)),
  941. X      attrs.af_size,
  942. X      at_getdate(&attrs),
  943. X      at_getbndvers(&attrs));
  944. X  return 1;
  945. X}
  946. X
  947. Xstatic int eq (exp) Expr exp; {
  948. X  return (attrs.af_gen == (int) exp->left) &&
  949. X    (attrs.af_rev == (int) exp->right);
  950. X}
  951. X
  952. Xstatic int lt (exp) Expr exp; {
  953. X  return (attrs.af_gen < (int) exp->left ||
  954. X      (attrs.af_gen == (int) exp->left &&
  955. X       attrs.af_rev < (int) exp->right));
  956. X}
  957. X
  958. Xstatic int le (exp) Expr exp; {
  959. X  return lt(exp) || eq(exp);
  960. X}
  961. X
  962. Xstatic int gt (exp) Expr exp; {
  963. X  return (attrs.af_gen > (int) exp->left ||
  964. X      (attrs.af_gen == (int) exp->left &&
  965. X       attrs.af_rev > (int) exp->right));
  966. X}
  967. X
  968. Xstatic int ge (exp) Expr exp; {
  969. X  return gt(exp) || eq(exp);
  970. X}
  971. X
  972. X
  973. X#define SECSPERDAY 86400L
  974. Xstatic int comptime(secs, days, sign)
  975. X     time_t secs;
  976. X     int days;
  977. X     char sign;
  978. X{
  979. X  int d;
  980. X  
  981. X  d = (int) ((now - secs) / SECSPERDAY);
  982. X  switch (sign) {
  983. X  case '+': return (d>days);
  984. X  case '-': return (d < (days * -1));
  985. X  default: return (d==days);
  986. X  }
  987. X}
  988. X
  989. Xstatic int mtime (exp) Expr exp; {
  990. X  return comptime(attrs.af_mtime, (int) exp->left, *(char*)(exp->right));
  991. X}
  992. X
  993. Xstatic int atime (exp) Expr exp; {
  994. X  return comptime(attrs.af_atime, (int) exp->left, *(char*)(exp->right));
  995. X}
  996. X
  997. Xstatic int chngtime (exp) Expr exp; {
  998. X  return comptime(attrs.af_ctime, (int) exp->left, *(char*)(exp->right));
  999. X}
  1000. X
  1001. Xstatic int stime (exp) Expr exp; {
  1002. X  return comptime(attrs.af_stime, (int) exp->left, *(char*)(exp->right));
  1003. X}
  1004. X
  1005. Xstatic int ltime (exp) Expr exp; {
  1006. X  return comptime(attrs.af_ltime, (int) exp->left, *(char*)(exp->right));
  1007. X}
  1008. X
  1009. Xstatic int execute (exp) Expr exp; {
  1010. X  char *pav[40], *arg;
  1011. X  int i, j;
  1012. X  int pid, wpid;
  1013. X  union wait retcode;
  1014. X
  1015. X  i = (int) exp->left;
  1016. X  for (j = 0; strcmp((arg = nav[i++]), ";"); j++)
  1017. X    if (!strcmp(arg, "{}"))
  1018. X      pav[j] = at_getbndvers(&attrs);
  1019. X    else
  1020. X      pav[j] = arg;
  1021. X
  1022. X  pav[j] = (char *) NULL;
  1023. X  if (j == 0) return 1;
  1024. X  
  1025. X  (void) fflush(stdout);
  1026. X  switch (pid = fork()) {
  1027. X  case -1:
  1028. X    perror (sprintf(garbage, "%s: fork failed\n", progname));
  1029. X    byebye(1);
  1030. X    break;
  1031. X  case 0:
  1032. X    (void) chdir(startdir);
  1033. X    /*VARARGS*/
  1034. X    (void) execvp(pav[0], pav);
  1035. X    (void) perror("vfind: exec failed");
  1036. X    (void) kill (getpid(), SIGHUP);
  1037. X    _exit(127);
  1038. X    break;
  1039. X  default:
  1040. X    while ((wpid = wait(&retcode)) != -1 && wpid != pid);
  1041. X    if (retcode.w_status&0177) {
  1042. X      (void) fprintf (stderr, "%s: execution terminated\n", progname);
  1043. X      byebye(1);
  1044. X    }
  1045. X    return (!retcode.w_status);
  1046. X    break;
  1047. X  }
  1048. X  /*NOTREACHED*/
  1049. X}
  1050. X
  1051. Xstatic int not (exp) Expr exp; {
  1052. X  return ! ((*exp->left->eval) (exp->left));
  1053. X}
  1054. X
  1055. Xstatic int and (exp) Expr exp; {
  1056. X  return ((*exp->left->eval) (exp->left) &&
  1057. X      (*exp->right->eval) (exp->right)) ? 1 : 0;
  1058. X}
  1059. X
  1060. Xstatic int or (exp) Expr exp; {
  1061. X  return ((*exp->left->eval) (exp->left) ||
  1062. X      (*exp->right->eval) (exp->right)) ? 1 : 0;
  1063. X}
  1064. X
  1065. X/* constructors */
  1066. Xstatic Expr build(func, l, r)
  1067. X     int (*func)();
  1068. X     Expr l, r;
  1069. X{
  1070. X  Expr this;
  1071. X  if ((this = (Expr) malloc ((unsigned) sizeof (struct expr))) ==
  1072. X      (Expr) NULL) {
  1073. X    (void) fprintf (stderr, "%s: out of memory.\n", progname);
  1074. X    byebye (1);
  1075. X  }
  1076. X
  1077. X  this->eval = func; this->left = l; this->right = r;
  1078. X  return this;
  1079. X}
  1080. X
  1081. Xstatic void skip() {
  1082. X  if (nav[idx])
  1083. X    idx++;
  1084. X  else {
  1085. X    (void) fprintf (stderr, "%s: parsing error\n", progname);
  1086. X    byebye(1);
  1087. X  }
  1088. X}
  1089. X
  1090. Xstatic Expr primary () {
  1091. X  char *prim, *val, *cp;
  1092. X  char c;
  1093. X  int i = 0;
  1094. X  int mode = 0;
  1095. X  int mask = 0;
  1096. X
  1097. X  val = cp = (char *) NULL;
  1098. X  
  1099. X  if (!(prim = nav[idx])) {
  1100. X    (void) fprintf (stderr, "%s: parsing error\n", progname);
  1101. X    byebye(1);
  1102. X  }
  1103. X  
  1104. X  if (*prim != '-') {
  1105. X    (void) fprintf(stderr, "%s: %s is not a primary\n", progname, prim);
  1106. X    byebye(1);
  1107. X  }
  1108. X  prim++;
  1109. X  if (!strcmp (prim, "print"))
  1110. X    return build(print, (Expr) NULL, (Expr) NULL);
  1111. X  if (!strcmp(prim, "ls") || !strcmp(prim, "vl"))
  1112. X    return build(vl, (Expr) NULL, (Expr) NULL);
  1113. X  if (!strcmp(prim, "locked"))
  1114. X    return build(locked, (Expr) NULL, (Expr) NULL);
  1115. X  
  1116. X  skip();
  1117. X  if (!(val = nav[idx])) {
  1118. X    (void) fprintf (stderr, "%s: parsing error\n", progname);
  1119. X    byebye(1);
  1120. X  }
  1121. X  
  1122. X  if (!strcmp (prim, "name"))
  1123. X    return build(name, (Expr) mkedpat(val), (Expr) NULL);
  1124. X  if (!strcmp(prim, "type")) {
  1125. X    c = *val;
  1126. X    i = (c=='b' ? S_IFBLK : c=='c' ? S_IFCHR :
  1127. X     c=='d' ? S_IFDIR : c=='f' ? S_IFREG :
  1128. X     c=='l' ? S_IFLNK : c=='s' ? S_IFSOCK : NULL);
  1129. X      return build(type, (Expr) i, (Expr) NULL);
  1130. X  }
  1131. X  if (!strcmp(prim, "perm")) {
  1132. X    while(c = *val++)
  1133. X      if (c=='-') mask++;
  1134. X      else {
  1135. X    c -= '0'; mode <<= 3; mode += c;
  1136. X      }
  1137. X    return build(perm, (Expr) mode, (Expr) (mask ? mode : 07777));
  1138. X  }
  1139. X  if (!strcmp(prim, "atime"))
  1140. X    return build(atime, (Expr) atoi(val), (Expr) val);
  1141. X  if (!strcmp(prim, "ctime"))
  1142. X    return build(chngtime, (Expr) atoi(val), (Expr) val);
  1143. X  if (!strcmp(prim, "mtime"))
  1144. X    return build(mtime, (Expr) atoi(val), (Expr) val);
  1145. X  if (!strcmp(prim, "stime"))
  1146. X    return build(stime, (Expr) atoi(val), (Expr) val);
  1147. X  if (!strcmp(prim, "ltime"))
  1148. X    return build(ltime, (Expr) atoi(val), (Expr) val);
  1149. X  if (!strcmp(prim, "user")) {
  1150. X    if (cp = rindex(val, '@')) *cp++ = '\0';
  1151. X    return build(user, (Expr) val, (Expr) cp);
  1152. X  }
  1153. X  if (!strcmp(prim, "eq")) {
  1154. X    if (cp = rindex(val, '.')) *cp++ = '\0';
  1155. X    return build(eq, (Expr) atoi(val), (Expr) atoi(cp));
  1156. X  }
  1157. X  if (!strcmp(prim, "le")) {
  1158. X    if (cp = rindex(val, '.')) *cp++ = '\0';
  1159. X    return build(le, (Expr) atoi(val), (Expr) atoi(cp));
  1160. X  }
  1161. X  if (!strcmp(prim, "lt")) {
  1162. X    if (cp = rindex(val, '.')) *cp++ = '\0';
  1163. X    return build(lt, (Expr) atoi(val), (Expr) atoi(cp));
  1164. X  }
  1165. X  if (!strcmp(prim, "ge")) {
  1166. X    if (cp = rindex(val, '.')) *cp++ = '\0';
  1167. X    return build(ge, (Expr) atoi(val), (Expr) atoi(cp));
  1168. X  }
  1169. X  if (!strcmp(prim, "gt")) {
  1170. X    if (cp = rindex(val, '.')) *cp++ = '\0';
  1171. X    return build(gt, (Expr) atoi(val), (Expr) atoi(cp));
  1172. X  }
  1173. X  if (!strcmp(prim, "locker")) {
  1174. X    if (cp = rindex(val, '@')) *cp++ = '\0';
  1175. X    return build(locker, (Expr) val, (Expr) cp);
  1176. X  }
  1177. X  if (!strcmp(prim, "exec") || !strcmp(prim, "ok")) {
  1178. X    i = idx;
  1179. X    while(nav[++idx] && strcmp(nav[idx], ";"));
  1180. X    return build(execute, (Expr) i, (Expr) prim);
  1181. X  }
  1182. X  if (!strcmp(prim, "state"))
  1183. X    return build(state, (Expr) at_string2state(val), (Expr) NULL);
  1184. X  if (!strcmp(prim,"uda"))
  1185. X    return build(uda, (Expr) val, (Expr) NULL);
  1186. X  if (!strcmp(prim,"symbolic"))    
  1187. X    return build(symname, (Expr) val, (Expr) NULL);
  1188. X  (void) fprintf (stderr,"%s: unknown primary %s.\n", progname, prim);
  1189. X  byebye(1);
  1190. X  /*NOTREACHED*/
  1191. X}
  1192. X
  1193. Xstatic Expr alternation();    /* forward declaration */
  1194. X
  1195. Xstatic Expr grouping () {
  1196. X  Expr expr;
  1197. X  
  1198. X  if (!strcmp(nav[idx], "(")){
  1199. X    skip();
  1200. X    expr = alternation();
  1201. X    if (nav[idx] && !strcmp(nav[idx], ")")) {
  1202. X      skip();
  1203. X      return expr;
  1204. X    }
  1205. X    (void) fprintf (stderr, "%s: missing closing ')'.\n", progname);
  1206. X    byebye(1);
  1207. X  }
  1208. X  else {
  1209. X    expr = primary();
  1210. X    skip();        /* primary() does not skip the */
  1211. X                /* processed token, so we do it here. */
  1212. X    return expr;
  1213. X  }
  1214. X  /*NOTREACHED*/
  1215. X}
  1216. X
  1217. Xstatic Expr negation() {
  1218. X  if (nav[idx] && !strcmp(nav[idx], "!")) {
  1219. X    skip();
  1220. X    return build(not, grouping(), (Expr) NULL);
  1221. X  }
  1222. X  else
  1223. X    return grouping();
  1224. X}
  1225. X
  1226. Xstatic Expr concatenation() {
  1227. X  Expr left;
  1228. X  char *this;
  1229. X  
  1230. X  left = negation ();
  1231. X  this = nav[idx];
  1232. X  if (this && (!strcmp(this, "-a") || !strcmp(this, "!") ||
  1233. X           !strcmp(this,"(") || (*this == '-' && strcmp(this, "-o")))){
  1234. X    if (!strcmp(this,"-a")) skip();
  1235. X    return build(and, left, concatenation());
  1236. X  }
  1237. X  else
  1238. X    return left;
  1239. X}
  1240. X
  1241. Xstatic Expr alternation() {
  1242. X  Expr left;
  1243. X  
  1244. X  left = concatenation();
  1245. X  if (nav[idx] && !strcmp(nav[idx], "-o")) {
  1246. X    skip();
  1247. X    return build(or, left, concatenation());
  1248. X  }
  1249. X  else
  1250. X    return left;
  1251. X}
  1252. X
  1253. Xstatic Expr expression() {
  1254. X  return alternation();
  1255. X}
  1256. X
  1257. Xstatic int dselect (d)
  1258. X     struct direct *d;
  1259. X{
  1260. X  char *name = d->d_name;
  1261. X  
  1262. X  if ((name[0] == '.' && name[1] == '\0') ||
  1263. X       (name[0] == '.' && name[1] == '.' && name[2] == '\0'))
  1264. X    return 0;
  1265. X  return 1;
  1266. X}
  1267. X
  1268. Xstatic int adselect (d)
  1269. X     struct direct *d;
  1270. X{
  1271. X  char *name = d->d_name;
  1272. X  
  1273. X  if (d->d_name[d->d_namlen -1] == AF_ARCHEXT)
  1274. X    return 1;
  1275. X  return 0;
  1276. X}
  1277. X
  1278. Xstatic int indp (dp, dpentr, name, len)
  1279. X     struct direct **dp;
  1280. X     char *name;
  1281. X     int len, dpentr;
  1282. X{
  1283. X  int i;
  1284. X  for (i = 0; i < dpentr; i++)
  1285. X    if (dp[i]->d_namlen == len && !strcmp(dp[i]->d_name, name))
  1286. X      return 1;
  1287. X  return 0;
  1288. X}
  1289. X
  1290. Xstatic void traverse (name, afs_is_dir)
  1291. X     char *name;
  1292. X     int afs_is_dir;        /* 1 if symbolic link */
  1293. X{
  1294. X  struct stat buf, abuf;
  1295. X  struct direct **dp, **adp;
  1296. X  int nhits, ahits, i;
  1297. X  static int ncalls;
  1298. X  char *cp;
  1299. X
  1300. X  (void) af_initattrs(&attrs); (void) af_initset(&set);
  1301. X  (void) strcpy(attrs.af_syspath, af_afpath(name));
  1302. X  (void) strcpy(attrs.af_name, af_afname(name));
  1303. X  (void) strcpy(attrs.af_type, af_aftype(name));
  1304. X
  1305. X  if (!afs_is_dir)        /* afs dir is symbolic link */
  1306. X    attrs.af_state = AF_BUSY;
  1307. X
  1308. X  if (af_find(&attrs, &set) == -1) {
  1309. X    (void) af_perror(sprintf(garbage, "%s: af_find(%s)", progname, name));
  1310. X    return;
  1311. X  }
  1312. X  if (Bflag) {
  1313. X    (void) af_initset(&bset);
  1314. X    if (af_bpfind(&attrs, &bset) == -1) {
  1315. X      (void) af_perror(sprintf(garbage, "%s: bp_find(%s)", progname, name));
  1316. X      (void) af_dropset(&set);
  1317. X      return;
  1318. X    }
  1319. X    (void) af_union(&set, &bset, &set); (void) af_dropset(&bset);
  1320. X  }
  1321. X    
  1322. X  nhits = af_nrofkeys(&set);
  1323. X  (void) af_sortset(&set, AF_ATTHUMAN);
  1324. X  for (i = 0; i < nhits; i++) {
  1325. X    if (af_gattrs(&(set.af_klist[i]),&attrs) == -1) {
  1326. X      (void) af_perror(sprintf(garbage,"%s: af_gattrs():",progname));
  1327. X      continue;
  1328. X    }
  1329. X    (*exprl->eval)(exprl);
  1330. X  }
  1331. X  (void) af_dropset(&set);
  1332. X  
  1333. X  if ((lstat(name, &buf) == -1) ||
  1334. X      ((buf.st_mode&S_IFMT) != S_IFDIR) ||
  1335. X      (Pflag && ncalls) || 
  1336. X      !strcmp(name, AF_SUBDIR))
  1337. X    return;
  1338. X
  1339. X  if (chdir(name) == -1)
  1340. X    return;
  1341. X  
  1342. X  if ((nhits = scandir(".", &dp, dselect, NULL)) == -1) {
  1343. X    fprintf (stderr, "%s: can't open dir %s.\n", progname, name);
  1344. X    return;
  1345. X  }
  1346. X  afs_is_dir = (lstat(AF_SUBDIR, &abuf) != -1 &&
  1347. X        (((abuf.st_mode&S_IFMT) == S_IFDIR) || Fflag));
  1348. X  if (afs_is_dir &&
  1349. X      ((ahits = scandir(AF_SUBDIR, &adp, adselect, NULL)) != -1)) {
  1350. X    for (i = 0; i < ahits; i++) {
  1351. X      cp = adp[i]->d_name + 2;
  1352. X      cp[adp[i]->d_namlen -3] = '\0';
  1353. X      if ((cp && *cp) && !indp(dp, nhits, cp, adp[i]->d_namlen - 3)) {
  1354. X    ncalls++; traverse(cp, afs_is_dir); ncalls--;
  1355. X      }
  1356. X      (void) free((char *)adp[i]);
  1357. X    }
  1358. X    (void) free((char *)adp);
  1359. X  }
  1360. X  for (i = 0; i < nhits; i++){
  1361. X    ncalls++; traverse(dp[i]->d_name, afs_is_dir); ncalls--;
  1362. X    (void) free((char *)dp[i]);
  1363. X  }
  1364. X  (void) free((char *)dp);
  1365. X
  1366. X  (void) chdir("..");
  1367. X  return;
  1368. X}
  1369. X
  1370. Xmain (ac, av)
  1371. X     int ac;
  1372. X     char *av[];
  1373. X{
  1374. X  char *cp;
  1375. X  struct stat buf;
  1376. X  int afs_is_dir;
  1377. X  
  1378. X  progname = (cp = rindex(av[0], '/')) ? ++cp : av[0];
  1379. X  if (ParseArgs(ac, av, &nac, &nav, optdesc)) byebye(1);
  1380. X  (void) getwd(startdir); (void) time(&now);
  1381. X  
  1382. X  if (nac < 2) Usage();
  1383. X  for (idx = 0; idx < nac; idx++) /* find path list */
  1384. X    if (*nav[idx] == '-' ||  *nav[idx] == '!' || *nav[idx] == '(') break;
  1385. X  if (!(npaths = idx)){
  1386. X    (void) fprintf (stderr, "%s: no path list.\n", progname); Usage();
  1387. X  }
  1388. X  if (idx == nac) {
  1389. X    (void) fprintf (stderr, "%s: no expression.\n", progname); Usage();
  1390. X  }
  1391. X
  1392. X  if ((exprl = expression()) == (Expr) NULL) byebye(1);
  1393. X  
  1394. X  for (idx = 0 ; idx < npaths; idx++) {    /* for all directories */
  1395. X    (void) chdir(startdir);    /* back to normal */
  1396. X    afs_is_dir = (lstat(sprintf(garbage, "%s/%s", cp = nav[idx], AF_SUBDIR),
  1397. X            &buf) != -1 &&
  1398. X          (((buf.st_mode&S_IFMT) == S_IFDIR) || Fflag));
  1399. X    traverse(cp, afs_is_dir);
  1400. X  }
  1401. X
  1402. X  byebye(0);
  1403. X}
  1404. END_OF_FILE
  1405. if test 17438 -ne `wc -c <'src/vfind/vfind.c'`; then
  1406.     echo shar: \"'src/vfind/vfind.c'\" unpacked with wrong size!
  1407. fi
  1408. # end of 'src/vfind/vfind.c'
  1409. fi
  1410. if test -f 'tutorial/make2shape.ms' -a "${1}" != "-c" ; then 
  1411.   echo shar: Will not clobber existing file \"'tutorial/make2shape.ms'\"
  1412. else
  1413. echo shar: Extracting \"'tutorial/make2shape.ms'\" \(17381 characters\)
  1414. sed "s/^X//" >'tutorial/make2shape.ms' <<'END_OF_FILE'
  1415. X.\"
  1416. X.\" Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  1417. X.\"  and U. Pralle
  1418. X.\" 
  1419. X.\" This software is published on an as-is basis. There is ABSOLUTELY NO
  1420. X.\" WARRANTY for any part of this software to work correctly or as described
  1421. X.\" in the manuals. We do not accept any liability for any kind of damage
  1422. X.\" caused by use of this software, such as loss of data, time, money, or 
  1423. X.\" effort.
  1424. X.\" 
  1425. X.\" Permission is granted to use, copy, modify, or distribute any part of
  1426. X.\" this software as long as this is done without asking for charge, and
  1427. X.\" provided that this copyright notice is retained as part of the source
  1428. X.\" files. You may charge a distribution fee for the physical act of
  1429. X.\" transferring a copy, and you may at your option offer warranty
  1430. X.\" protection in exchange for a fee.
  1431. X.\" 
  1432. X.\" Direct questions to: Tech. Univ. Berlin
  1433. X.\"              Wilfried Koch
  1434. X.\"              Sekr. FR 5-6 
  1435. X.\"              Franklinstr. 28/29
  1436. X.\"              D-1000 Berlin 10, West Germany
  1437. X.\" 
  1438. X.\"              Tel: +49-30-314-22972
  1439. X.\"              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  1440. X.\" 
  1441. X.NH 1
  1442. XA quick guide through shape for make users
  1443. X.PP
  1444. XThis chapter is intended to give users of \fImake\fR a quick guide
  1445. Xhow to change their development environment when switching
  1446. Xfrom the usage of \fImake\fR to \fIshape\fR.
  1447. X.PP
  1448. XThe first step is quite simple. As the shape program is upward
  1449. Xcompatible to make, you can just type \fCshape\fR instead of \fCmake\fR
  1450. Xand shape will fulfill your (make\-)wishes.
  1451. XOoops, we nearly forgot to mention, that you have to create a
  1452. Xsubdirectory named \fCAFS\fR first.
  1453. XYou will later see why.
  1454. X.PP
  1455. XBy using shape instead of make on your old Makefile you can
  1456. Xalready take advantage of one important improvement of shape
  1457. Xwith respect to make.
  1458. XShape is sensible for changes in the compile environment.
  1459. XIf you change for example your compiler flags or preprocessor
  1460. Xdefinitions in the Makefile, shape will recompile all 
  1461. Xfiles that are affected by this change (make does not).
  1462. XFor example, if \fCfoo.o\fR was generated by \fCcc -c -DBSD43\fR
  1463. Xand you change your Makefile in order to produce a version
  1464. Xsuitable for System V so that \fCfoo.c\fR should be
  1465. Xproduced by \fCcc -c -DSYSV\fR, shape recognizes this change,
  1466. Xin contrary to make.
  1467. X.PP
  1468. XYou might ask yourself now "how can shape do this ?".
  1469. XBefore we can give you an answer to this question, you got to learn
  1470. Xto know a few things about the architecture of the shape toolkit.
  1471. XThe whole shape toolkit is implemented on top af an object base (AFS),
  1472. Xthat is able to store software objects (regular UNIX files for instance)
  1473. Xas a bunch
  1474. Xof content data together with an arbitrary number of attributes.
  1475. XThese things are called \fIattributed software objects\fR (ASO).
  1476. XAttributes are strings of the general form \fCname=value\fR.
  1477. XAFS supports a set of standard attributes (examples are:
  1478. Xname, type, version number, owner, author) an unlimited number
  1479. Xof \fIuser defined attributes\fR.
  1480. XEach application may introduce its own user defined attributes.
  1481. XAdditionally, AFS has a built-in version control system that
  1482. Xsupports the storage and identification of different versions
  1483. Xof software objects.
  1484. XFor further details on the object base see afintro (3).
  1485. X.PP
  1486. XShape uses the mechanism of application defined attributes for recording
  1487. Xthe compile
  1488. Xenvironment (the name of the transformation tool and all options and
  1489. Xarguments) of each derived file (you may know be more familiar with
  1490. Xthe term \fI.o file\fR).
  1491. XSo, shape bases its decision whether to recompile a system component
  1492. Xfrom its source not only on comparing the date of last modification
  1493. X(like make does) but also on the comparison of the compile environments.
  1494. X.PP
  1495. XDue to that mechanism, you have to bear one inconvenience on your journey
  1496. Xfrom make to shape. Your first \fCshape\fR call causes all your files
  1497. Xto be recompiled. This is necessary to initialize the object base.
  1498. X.PP
  1499. XBut you get indemnified for that with the next step.
  1500. XSuppose, you want to produce different versions of your system
  1501. Xby setting different compiler options.
  1502. XTypically, you have a local test system that is compiled and linked
  1503. Xwith the \fC-g\fR option (for symbolic debugging) and you publish
  1504. X(install) product versions of your system compiled with \fC-O\fR
  1505. X(optimizing) and the symbol table stripped off.
  1506. X.PP
  1507. XSo you might think, shape recompiles the whole stuff with \fC-O\fR
  1508. Xfor publication and afterwards recompiles it again with \fC-g\fR
  1509. Xfor continuing the work.
  1510. X.br
  1511. XNot true !
  1512. X.br
  1513. XAll derived files generated during a system building operation driven
  1514. Xby shape are stored in a cache named \fIderived object pool\fR
  1515. X(or \fIbinary pool\fR).
  1516. XThe derived object pool is able to store multiple versions of
  1517. Xequally named derived files and to distinguish between them by the
  1518. Xuser defined attributes they have.
  1519. XSo when you want to continue your work after an installation,
  1520. Xyou old \fC.o\fR files are still there and
  1521. Xshape restores them from the derived object pool instead
  1522. Xof regenerating them from their source files.
  1523. X.PP
  1524. XTo prevent your disk from being flooded with derived files, each binary
  1525. Xpool has a limited size (a maximum number of files stored in it).
  1526. XBinary pools are administered in a cache fashion.
  1527. XThe oldest (access date) derived files get removed if no additional
  1528. Xfiles can be inserted due to the size limit.
  1529. XYou can define the size of your private binary pool by setting
  1530. Xthe environment variable \fCAFSBPSIZ\fR to an appropriate value.
  1531. XA reasonable value is (\fI number of your source files * 2 \fR).
  1532. XThe default value is 64.
  1533. X.PP
  1534. XRemember, all your work with shape up to now did not require
  1535. Xany modification of your Makefile.
  1536. XIf you don't like shape up to now \- no problem, \fCrm -rf AFS\fR
  1537. Xremoves all shape specific stuff and you can go on with make.
  1538. XBut if you like it, it is the right time to rename your Makefile to
  1539. X\fCShapefile\fR and begin to implant shape specific things.
  1540. X.NH 2
  1541. XVersion Control
  1542. X.PP
  1543. XBeside the make functionality (system building), a main feature
  1544. Xof the shape toolkit is the integration of a version control
  1545. Xsystem in your system building environment.
  1546. XShape does not only operate on regular UNIX files, but on
  1547. Xmultiple versions of files.
  1548. XFor this reason, we constructed a version control system which is
  1549. Xintegral part of the shape toolkit.
  1550. X.PP
  1551. XThis version control system has a lot of similarities to existing
  1552. Xversion control systems like RCS and SCCS, but also some
  1553. Ximprovements with respect to these systems.
  1554. XYou can read more about the version control in the manual pages.
  1555. XWe just want to mention one important feature of the version control system
  1556. Xhere, that is important to know while reading this chapter.
  1557. X.PP
  1558. XShape's version control system has a built in version status model.
  1559. XThe essential thing for you to know about this is, that there are
  1560. X"busy" and "saved" versions. Saved versions have
  1561. Xa version number that consists of a generation number and
  1562. Xa revision number (eg. 4.3). Saved versions cannot be modified;
  1563. Xonce saved, they are "read only". Busy versions are the place
  1564. Xwhere development takes place. They are alterable and have no
  1565. Xversion number yet. Each regular UNIX file is a busy version
  1566. Xin this sense. Saved versions come into being by making a copy
  1567. Xof a busy version, tagging a version number to it and entering it
  1568. X(as delta) in the appropriate archive file in the AFS subdirectory.
  1569. XThe status model is more complex, but for further reading of this
  1570. Xchapter it is enough when you know the states "busy", "saved"
  1571. Xand "published".
  1572. XPublished versions play a role when you working in a multi
  1573. Xprogrammer team. You can use the publishing mechanism of the
  1574. Xshape toolkit then to make specific versions of the system
  1575. Xcomponent you work on accessible for your co workers.
  1576. X.PP
  1577. XIf you have worked with another version control system before
  1578. Xit is advisable to transform your old version histories to
  1579. Xshape histories.
  1580. XIf you have used RCS before, you can have this be done
  1581. Xautomatically by running the program \fIrcs2afs\fR.
  1582. X.NH 2
  1583. XVersion Selection Rules
  1584. X.PP
  1585. XOk, long enough now, let's dive into shape's selection mechanism.
  1586. XMake's task is it, to produce names \- so called \fItargets\fR.
  1587. XIt does this by traversing a system model consisting of
  1588. X\fItarget \- dependent\fR lines to determine which components
  1589. Xgo into a system and producing targets from their dependents.
  1590. XTargets and dependents may correspond to equally named files in the
  1591. Xfilesystem to which transformation tools are applied.
  1592. XWhen doing make's job, due to the introduction of multiple versions
  1593. Xof files, shape has the additional task to select one
  1594. Xspecific version of each file involved.
  1595. XIf does this by evaluating \fIversion selection rules\fR 
  1596. Xgiven by the
  1597. Xprogrammer in a special part of the Shapefile, called the \fIrule-section\fR.
  1598. XA version selection is driven by evaluating a selection rule
  1599. Xwith the name given as parameter.
  1600. XRemember that each version (software object) has a number of
  1601. Xattributes attached to it. These attributes are the ground,
  1602. Xselection rules operate on.
  1603. XSo let's look at the following rule section:
  1604. X.nf
  1605. X.sp
  1606. X\fC#% RULE-SECTION
  1607. Xdefaultrule:
  1608. X    *, attr (state, busy).
  1609. X#% END-RULE-SECTION\fR
  1610. X.fi
  1611. X.sp
  1612. X.PP
  1613. XA rule section always begins with a comment symbol (\fC#\fR) followed
  1614. Xby a percent sign and the string \fCRULE-SECTION\fR.
  1615. XIt ends accordingly (see example).
  1616. XEach rule begins with the rule name followed by a colon (in the above case
  1617. X\fCdefaultrule:\fR).
  1618. XThe rest ot the selection rule is a named sequence of \fIalternatives\fR,
  1619. Xseparated by semicolons, which form a logical OR expression. Each alternative
  1620. Xconsists of a sequence of \fIpredicates\fR, separated by commas, which form
  1621. Xa logical AND expression. A selection rule succeeds if one of its
  1622. Xalternatives succeeds (i.e. leads to the unique identification of some
  1623. Xdocument instance).
  1624. XIn alternatives, the first predicate (e.g. \fC*\fR or \fC*.c\fR) is usually a
  1625. Xpattern against which the name of a document that has to be retrieved
  1626. Xis matched.  The patterns used by shape have the same structure as those
  1627. Xused by \fCed\fR.
  1628. X.PP
  1629. XThe rule above consists of only one alternative, so do not worry if you
  1630. Xdo not find the semicolon in it.
  1631. XBeside that, you never need to write a rule like this, because it is
  1632. Xthe default rule \- this rule is active if no other selection rule
  1633. Xis given.
  1634. XIt makes exactly what make does: for each name (\fC*\fR) it selects the
  1635. Xbusy version, which is an equally named regular UNIX file.
  1636. XThis rule makes sense if you have no saved versions.
  1637. X.PP
  1638. XTo go on with shape it is necessary that you begin to work with
  1639. Xthe version control system.
  1640. XYou should save a releasable state of
  1641. Xyour work by applying the command \fCsave\fR to all the files
  1642. Xbelonging to your system.
  1643. XThis can probably be done by inserting an entry in your Shapefile
  1644. Xthat looks like
  1645. X.sp
  1646. X.nf
  1647. X\fCsave:
  1648. X    save $(COMPONENTS)\fR
  1649. X.fi
  1650. X.sp
  1651. Xand calling \fCshape save\fR.
  1652. X.PP
  1653. XIf you have done this, a rule like
  1654. X.nf
  1655. X.sp
  1656. X\fC#% RULE-SECTION
  1657. Xreleaserule:
  1658. X    *, attr (state, saved), attrmax (version).
  1659. X#% END-RULE-SECTION\fR
  1660. X.fi
  1661. X.sp
  1662. Xmakes sense for building releases.
  1663. XThis rule selects for each component (\fC*\fR) of your system the
  1664. Xlatest (\fCattrmax (version)\fR) saved (\fCattr (state, saved)\fR)
  1665. Xversion.
  1666. XIf for example there is \fIno\fR saved version of your component
  1667. X\fCfoo.c\fR shape complains about that with the message:
  1668. X\fCshape - selection rule for foo.c failed\fR
  1669. X.PP
  1670. XYou can activate a selection rule by inserting its name in the 
  1671. Xtarget - dependents line of your system at the place of the first dependent.
  1672. XFor example
  1673. X.nf
  1674. X.sp
  1675. X\fCall: releaserule program1 program2\fR
  1676. Xor
  1677. X\fCprogram: releaserule $(COMPONENTS)\fR
  1678. X.sp
  1679. X.fi
  1680. Xcan be meaningful rule activations.
  1681. XOnce set active, a selection rule is inherited to all subtargets.
  1682. XBut be careful, the active selection rule can also be redefined
  1683. Xwith each single target \-
  1684. Xa mechanism that takes a little while to get used to.
  1685. XSo if you are wondering about shape selecting other versions than 
  1686. Xyou expect, check your Shapefile for constructions like:
  1687. X.nf
  1688. X.sp
  1689. X\fCall: releaserule program1 program2\fR
  1690. X
  1691. X\fCprogram1: defaultrule $(COMPONENTS1)\fR
  1692. X
  1693. X\fCprogram2: $(COMPONENTS2)\fR
  1694. X.fi
  1695. X.sp
  1696. XIn this case \fCshape all\fR builds
  1697. X\fCprogram1\fR with \fCdefaultrule\fR (explicitly set) and program2
  1698. Xwith \fCreleaserule\fR (inherited).
  1699. X.PP
  1700. XWe cannot deal with all issues of the selection rule mechanism here;
  1701. Xyou find more details on this in the chapter (.\" to be inserted),
  1702. Xbut just to illustrate the power of expression sleeping in the
  1703. Xselection rule mechanism,
  1704. Xan example for a very complex selection rule.
  1705. XIt does not make very much sense but it shall give you an idea
  1706. Xof what you can express with the selection rule mechanism.
  1707. X.nf
  1708. X.sp
  1709. X\fC#% RULE-SECTION
  1710. X\&...
  1711. Xcomplexrule:
  1712. X    # to be inserted
  1713. X#% END-RULE-SECTION\fR
  1714. X.fi
  1715. X.sp
  1716. X.NH 2
  1717. XVariants
  1718. X.PP
  1719. XAfter having played around with selection rules
  1720. Xyou may turn your attention to another very powerful mechanism of shape.
  1721. XRemember the example from the beginning of this chapter that dealt with
  1722. Xdifferent \fIvariants\fR (<- thats the buzzword) of your system for
  1723. Xdifferent machines.
  1724. XLet's introduce another section in the Shapefile.
  1725. XThe first and the last line of this section look very much like
  1726. Xthese of the rule section with the word \fCVARIANT\fR instead of \fCRULE\fR.
  1727. X.nf
  1728. X.sp
  1729. X\fC#% VARIANT-SECTION
  1730. Xvclass system ::= (bsd, sysV, sunos)
  1731. X
  1732. Xbsd:
  1733. X    vpath = bsd
  1734. X    vflags = -DBSD
  1735. XsysV:
  1736. X    vpath = sysV
  1737. X    vflags = -DSYSV
  1738. Xsunos:
  1739. X    vpath = sunos
  1740. X    vflags = -DSUNOS
  1741. X#% END-VARIANT-SECTION\fR
  1742. X.fi
  1743. X.sp
  1744. X.PP
  1745. XThis helps you to deal on one hand with variants that are generated from
  1746. X\fIone\fR source file by setting different precompiler switched and
  1747. Xon the other hand with variants that are stored in equally named 
  1748. Xfiles in different directories.
  1749. XWith a variant activated, shape passes variant dependent options
  1750. X(vflags: eg. \fC-DBSD\fR) to each transformation tool (eg. \fCcc\fR)
  1751. Xit triggers and it extends its search path for files by the
  1752. Xdirectories named in vpath (eg. the subdirectory \fCbsd\fR).
  1753. X.PP
  1754. XThe activation mechanism for variants is quite similar to the rule
  1755. Xactivation.
  1756. XJust after the rule name you can optionally insert the variant name
  1757. Xpreceded by a plus sign (\fC+\fR).
  1758. XThe following example of a target \- dependent line is suitable for
  1759. Xcalling shape with \fCshape SYSTEM=sunos all\fR. This builds the
  1760. Xbsd variant of your system.
  1761. X.nf
  1762. X.sp
  1763. X\fCall: releaserule +$(SYSTEM) program1 program2\fR
  1764. X.fi
  1765. X.sp
  1766. XIt is advisable to have a line like
  1767. X.nf
  1768. X.sp
  1769. X\fCSYSTEM=bsd\fR
  1770. X.fi
  1771. X.sp
  1772. Xsomewhere in your Shapefile in order to define a default for your
  1773. XSYSTEM macro. You can then omit the definition for SYSTEM on the command
  1774. Xline when you want to build the default variant.
  1775. XOne little hint in respect to activation of variants. When shape
  1776. Xcomes up with an error message like
  1777. X\fCshape - don't know how to shape +blabla\fR, this points to a
  1778. Xspelling mismatch between variant naming and variant activation.
  1779. X.PP
  1780. XIn a variant definition, not only vpath and vflags can be defined.
  1781. XYou can also redefine any macro.
  1782. XAnother typical application is
  1783. X.nf
  1784. X.sp
  1785. X\fC#% VARIANT-SECTION
  1786. Xvclass quality ::= (test, test_profiling, final)
  1787. X
  1788. Xtest:
  1789. X    CFLAGS = -g
  1790. X    LDFLAGS = -g
  1791. Xtest_profiling:
  1792. X    CFLAGS = -pg -g
  1793. X    LDFLAGS = -pg -g
  1794. Xfinal:
  1795. X    CFLAGS = -O
  1796. X    LDFLAGS = -s
  1797. X#% END-VARIANT-SECTION\fR
  1798. X.fi
  1799. X.sp
  1800. Xthat helps to manage the other case of system variants that occured in an
  1801. Xexample earlier in tis paper.
  1802. XWith the targets
  1803. X.nf
  1804. X.sp
  1805. X\fCall: +$(SYSTEM) +test_profiling program1 program2
  1806. X
  1807. Xinstall: +$(SYSTEM) +final program1 program2\fR
  1808. X.fi
  1809. X.sp
  1810. Xyou can build test systems by calling \fCshape all\fR and release systems
  1811. Xby calling \fCshape install\fR.
  1812. X.PP
  1813. XA few words about vclasses (to be inserted).
  1814. XThe name of the vclass is not explicitely used up to now, but there should
  1815. Xbe a equally named Macro (in capital letters) that holds the actual
  1816. Xvariant setting.
  1817. XFor this macro (as said earlier), a default should be defined.
  1818. X.NH 2
  1819. XBuilding up a target raster.
  1820. X.PP
  1821. XRule and variant activations should only be inserted in top level targets.
  1822. XSee the sample Shapefiles for examples.
  1823. X.NH 2
  1824. XMacros
  1825. X.PP
  1826. XMacro naming conventions -> shape manual.
  1827. X.NH 2
  1828. XTransformation Rules
  1829. X.PP
  1830. XLike in make, you can write implicit transformation rules.
  1831. XShape understands make syntax, but we recommend to use
  1832. Xthe extended syntax described in the following paragraph
  1833. X.PP
  1834. XTransformation rules consist of a \fItransformation specification\fR,
  1835. Xand a \fItransformation script\fR. Transformation specifications
  1836. Xdescribe prerequisites and resulting objects of a transformation. The
  1837. Xtransformation script is a template for a shell script that
  1838. Xwill be passed to a shell process upon activation of a transformation.
  1839. XThe syntax for these rules is an extension of Make's default rule
  1840. Xspecification formalism. \*(sh's rule by which the transformation
  1841. Xof a C source object into a '\fC\&.\&o\fR' (speak: dot-o) derived object
  1842. Xis defined looks like:
  1843. X.sp
  1844. X.nf
  1845. X\fC\s-1%.o: %.c : +(CC) +(CFLAGS)
  1846. X    $(CC) -c $(CFLAGS) %.c\s+1\fR
  1847. X.fi
  1848. X.LP
  1849. X.PP
  1850. XA request to produce a derived object \- let's say \fCxyzzy.o\fR \- would,
  1851. Xby evaluating the transformation rule, result in the compilation
  1852. Xof \fCxyzzy.c\fR with the compiler defined by 
  1853. Xthe macro \fCCC\fR, with compile switches defined by \fCCFLAGS\fR.
  1854. XThe percent sign is consistently substituted by the name \(lqxyzzy\(rq
  1855. Xthroughout the transformation rule. The notation \fI$(NAME)\fR substitutes
  1856. Xthe value of the macro \fINAME\fR, while \fI+(NAME)\fR substitutes the
  1857. Xentire macro definition (i.e. \fINAME=value\fR).
  1858. X
  1859. END_OF_FILE
  1860. if test 17381 -ne `wc -c <'tutorial/make2shape.ms'`; then
  1861.     echo shar: \"'tutorial/make2shape.ms'\" unpacked with wrong size!
  1862. fi
  1863. # end of 'tutorial/make2shape.ms'
  1864. fi
  1865. echo shar: End of archive 20 \(of 33\).
  1866. cp /dev/null ark20isdone
  1867. MISSING=""
  1868. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ; do
  1869.     if test ! -f ark${I}isdone ; then
  1870.     MISSING="${MISSING} ${I}"
  1871.     fi
  1872. done
  1873. if test "${MISSING}" = "" ; then
  1874.     echo You have unpacked all 33 archives.
  1875.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1876. else
  1877.     echo You still need to unpack the following archives:
  1878.     echo "        " ${MISSING}
  1879. fi
  1880. ##  End of shell archive.
  1881. exit 0
  1882.