home *** CD-ROM | disk | FTP | other *** search
- Subject: v19i033: A software configuration management system, Part20/33
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Axel Mahler <unido!coma!axel>
- Posting-number: Volume 19, Issue 33
- Archive-name: shape/part20
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 20 (of 33)."
- # Contents: src/afs/afhash.c src/vfind/vfind.c tutorial/make2shape.ms
- # Wrapped by rsalz@papaya.bbn.com on Thu Jun 1 19:27:12 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'src/afs/afhash.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/afs/afhash.c'\"
- else
- echo shar: Extracting \"'src/afs/afhash.c'\" \(17913 characters\)
- sed "s/^X//" >'src/afs/afhash.c' <<'END_OF_FILE'
- X/*
- X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
- X * and U. Pralle
- X *
- X * This software is published on an as-is basis. There is ABSOLUTELY NO
- X * WARRANTY for any part of this software to work correctly or as described
- X * in the manuals. We do not accept any liability for any kind of damage
- X * caused by use of this software, such as loss of data, time, money, or
- X * effort.
- X *
- X * Permission is granted to use, copy, modify, or distribute any part of
- X * this software as long as this is done without asking for charge, and
- X * provided that this copyright notice is retained as part of the source
- X * files. You may charge a distribution fee for the physical act of
- X * transferring a copy, and you may at your option offer warranty
- X * protection in exchange for a fee.
- X *
- X * Direct questions to: Tech. Univ. Berlin
- X * Wilfried Koch
- X * Sekr. FR 5-6
- X * Franklinstr. 28/29
- X * D-1000 Berlin 10, West Germany
- X *
- X * Tel: +49-30-314-22972
- X * E-mail: shape@coma.uucp or shape@db0tui62.bitnet
- X */
- X/*LINTLIBRARY*/
- X/*
- X * Shape/AFS
- X *
- X * afhash.c -- manage hashtable for user defined attributes
- X *
- X * Author: Axel Mahler, TU-Berlin
- X *
- X * adapted by: Andreas Lampen, TU-Berlin (andy@coma.UUCP)
- X * (andy@db0tui62.BITNET)
- X *
- X * $Header: afhash.c[1.4] Wed Feb 22 16:27:37 1989 andy@coma published $
- X *
- X * EXPORT:
- X * af_hashinit -- initialize hash table
- X * af_hashfree -- detach hash table (free allocated memory)
- X * af_hashsym -- put entry into hashtable
- X * af_fhash -- get hash value
- X * af_replsym -- replace symbol in hashtable
- X * af_delsym -- delete symbol from hashtable
- X * af_symlookup -- look for symbol in hashtable
- X * af_vallookup -- look for single value
- X * af_lhashsyms -- create a list of all symbols in hashtable
- X * af_hashcopy -- copy hashtable
- X * af_match -- test match of user defined attributes
- X * af_dumphtb -- dump hash table
- X */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <string.h>
- X#ifdef SUNOS_4_0
- X#include <strings.h>
- X#endif
- X
- X#include "typeconv.h"
- X#include "afsys.h"
- X#include "afs.h"
- X
- X#ifdef CCOLL
- Xint af_collcnt = 0;
- Xint af_symcount = 0;
- X#endif
- X
- X#ifdef MEMDEBUG
- Xextern FILE *memprot;
- X#endif
- X#ifdef HASHDEBUG
- Xextern FILE *hashprot;
- X#endif
- X
- XAf_hashent af_hashentry; /* hashtable entry that was found during last */
- X /* retrieve operation */
- X
- X/*=====================================================================
- X * af_hashinit -- initialize hash table
- X *
- X *=====================================================================*/
- X
- XEXPORT af_hashinit (htab, hsize, af_fhash)
- X Af_hash *htab;
- X int hsize, (*af_fhash)();
- X{
- X char *malloc();
- X
- X /* initialize Hash - structure */
- X htab->hsize = hsize;
- X if ((htab->hashtb = (Af_hashent *)malloc ((unsigned) (htab->hsize*sizeof (Af_hashent)))) == NULL)
- X FAIL ("hashinit", "malloc", AF_ESYSERR, ERROR);
- X htab->fhash = af_fhash;
- X
- X /* set hashlist all zeros */
- X bzero ((char *)htab->hashtb, htab->hsize*sizeof (Af_hashent));
- X return (AF_OK);
- X}
- X
- X
- X/*=====================================================================
- X * af_hashfree -- detach hash table (free allocated memory)
- X *
- X * may be slow; perhaps a memory management with af_malloc would be
- X * better.
- X *=====================================================================*/
- X
- XEXPORT af_hashfree (htab)
- X Af_hash *htab;
- X{
- X register int i;
- X Af_hashent *entry;
- X
- X for (i=0; i<htab->hsize; i++)
- X {
- X if (htab->hashtb[i].next)
- X {
- X entry = htab->hashtb[i].next;
- X do
- X {
- X#ifdef MEMDEBUG
- X fprintf (memprot, "%x(sym-fr)\n", entry->symbol);
- X#endif
- X free (entry->symbol);
- X#ifdef MEMDEBUG
- X fprintf (memprot, "%x(e-fr)\n", entry);
- X#endif
- X free ((char *)entry);
- X }
- X while (entry = entry->next);
- X }
- X if (htab->hashtb[i].symbol)
- X {
- X#ifdef MEMDEBUG
- X fprintf (memprot, "%x(sym-fr)\n", entry->symbol);
- X#endif
- X free (htab->hashtb[i].symbol);
- X }
- X }
- X free ((char *)htab->hashtb);
- X htab->hashtb = (Af_hashent *)0;
- X}
- X
- X
- X/*=====================================================================
- X * af_hashsym -- put entry into hashtable
- X *
- X *=====================================================================*/
- X
- XEXPORT char *af_hashsym (htab, symbol, list)
- X Af_hash *htab;
- X char *symbol;
- X Af_revlist *list;
- X{
- X /*
- X * put entry into hashtable. Only called, if symbol hasn't been found in
- X * hashtable. Function returns pointer to the symbol-string.
- X */
- X int symindex;
- X Af_hashent *new, *curptr;
- X char *retptr, *malloc();
- X
- X#ifdef HASHDEBUG
- X fprintf (hashprot, "HASHSYM: %s\n", symbol);
- X#endif
- X symindex = htab->fhash (htab->hsize, symbol);
- X if (!htab->hashtb[symindex].symbol) /* found entry is not used yet */
- X {
- X if ((htab->hashtb[symindex].symbol = malloc ((unsigned) (strlen (symbol) + sizeof (char)))) == (char *)0)
- X FAIL ("hashsym", "malloc", AF_ESYSERR, (char *)0);
- X#ifdef MEMDEBUG
- X fprintf (memprot, "%x(sym-al) %d bytes ", htab->hashtb[symindex].symbol,
- X strlen (symbol) + sizeof (char));
- X#endif
- X (void) strcpy (htab->hashtb[symindex].symbol, symbol);
- X htab->hashtb[symindex].revlist = list;
- X htab->hashtb[symindex].next = NULL;
- X retptr = htab->hashtb[symindex].symbol;
- X curptr = &(htab->hashtb[symindex]);
- X }
- X else /* oh boy - a collision! */
- X {
- X#ifdef CCOLL
- X af_collcnt++;
- X fprintf (stderr, "%d'th hash-collision (symbol).\n", af_collcnt);
- X#endif
- X if ((new = (Af_hashent*)malloc ((unsigned) sizeof (Af_hashent))) == (Af_hashent*)0)
- X FAIL ("hashsym", "malloc", AF_ESYSERR, (char *)0);
- X#ifdef MEMDEBUG
- X fprintf (memprot, "%x(e-al) %d bytes ", new, sizeof (Af_hashent));
- X#endif
- X if ((new->symbol = malloc ((unsigned) (strlen (symbol) + sizeof (char)))) == (char *)0)
- X FAIL ("hashsym", "malloc", AF_ESYSERR, (char *)0);
- X#ifdef MEMDEBUG
- X fprintf (memprot, "%x(sym-al) %d bytes ", new->symbol,
- X strlen (symbol) + sizeof (char));
- X#endif
- X (void) strcpy (new->symbol, symbol);
- X new->revlist = list;
- X new->next = NULL;
- X curptr = &htab->hashtb[symindex];
- X while (curptr->next)
- X curptr = curptr->next;
- X curptr->next = new;
- X curptr = curptr->next; /* points to new entry */
- X retptr = new->symbol;
- X } /* endif */
- X
- X /* filter out double values if list == *0 */
- X /* not yet implemented (filter out double values) */
- X
- X return (retptr);
- X} /* end af_hashsym */
- X
- X
- XEXPORT int af_fhash (htabsiz, hstr) /* from Aho/Ullman */
- X int htabsiz;
- X char *hstr;
- X{
- X register char *p;
- X register unsigned long hval, g;
- X
- X hval = 0;
- X for (p = hstr; (*p!=AF_UDANAMDEL) && (*p!=AF_UDAVALDEL) && (*p!='\0'); p++)
- X {
- X hval = (hval << 4) ^ (*p);
- X if (g = hval & 0xf0000000)
- X {
- X hval = hval ^ (g >> 24);
- X hval = hval ^ g;
- X }
- X }
- X return (hval % htabsiz);
- X}
- X
- X/*=====================================================================
- X * af_replsym -- replace symbol in hashtable
- X *
- X *=====================================================================*/
- X
- XEXPORT char *af_replsym (htab, symbol, list)
- X Af_hash *htab;
- X char *symbol;
- X Af_revlist *list;
- X{
- X int symindex;
- X Af_hashent *entry;
- X char *realloc();
- X
- X#ifdef HASHDEBUG
- X fprintf (hashprot, "REPLSYM: %s\n", symbol);
- X#endif
- X symindex = htab->fhash (htab->hsize, symbol);
- X if (htab->hashtb[symindex].symbol) /* found something */
- X {
- X if (!af_symcmp (&htab->hashtb[symindex], symbol, list)) /* found it ? */
- X {
- X if ((htab->hashtb[symindex].symbol =
- X realloc (htab->hashtb[symindex].symbol, (unsigned) (strlen (symbol) + sizeof (char)))) == (char *)0)
- X FAIL ("replsym", "realloc", AF_ESYSERR, (char *)0);
- X (void) strcpy (htab->hashtb[symindex].symbol, symbol);
- X htab->hashtb[symindex].revlist = list;
- X return (htab->hashtb[symindex].symbol);
- X }
- X else /* maybe it is somewhere down the gully */
- X {
- X entry = &htab->hashtb[symindex];
- X while (entry->next)
- X {
- X entry = entry->next;
- X if (!af_symcmp (entry, symbol, list))
- X {
- X if ((entry->symbol =
- X realloc (entry->symbol, (unsigned) (strlen (symbol) + sizeof (char)))) == (char *)0)
- X FAIL ("replsym", "realloc", AF_ESYSERR, (char *)0);
- X (void) strcpy (entry->symbol, symbol);
- X entry->revlist = list;
- X return (entry->symbol);
- X }
- X }
- X }
- X }
- X /* when we reach this point, the symbol hasn't been known */
- X
- X /* this should never occur */
- X FAIL ("replsym", "symbol not found", AF_EINTERNAL, (char *)0);
- X} /* end af_replsym */
- X
- X/*=====================================================================
- X * af_delsym -- delete symbol from hashtable
- X *
- X *=====================================================================*/
- X
- XEXPORT af_delsym (htab, symbol, list)
- X Af_hash *htab;
- X char *symbol;
- X Af_revlist *list;
- X{
- X int symindex;
- X Af_hashent *del, *succ;
- X char *malloc();
- X
- X#ifdef HASHDEBUG
- X fprintf (hashprot, "DELSYM: %s\n", symbol);
- X#endif
- X symindex = htab->fhash (htab->hsize, symbol);
- X if (!htab->hashtb[symindex].symbol) /* no entry found (should never occur) */
- X FAIL ("delsym", "symbol not found", AF_EINTERNAL, ERROR);
- X
- X del = &htab->hashtb[symindex];
- X if (!af_symcmp (del, symbol, list)) /* found it ? */
- X {
- X#ifdef MEMDEBUG
- X fprintf (memprot, "%x(sym-fr)\n", del->symbol);
- X#endif
- X free (del->symbol);
- X
- X if (del->next) /* if there are more entries */
- X {
- X#ifdef HASHDEBUG
- X fprintf (hashprot, "NEXT: %s\n", del->next->symbol);
- X#endif
- X del->symbol = del->next->symbol;
- X del->revlist = del->next->revlist;
- X succ = del->next->next;
- X#ifdef MEMDEBUG
- X fprintf (memprot, "%x(e-fr)\n", del->next);
- X#endif
- X free ((char *)del->next);
- X del->next = succ;
- X }
- X else
- X {
- X del->symbol = (char *)0;
- X del->revlist = (Af_revlist *)0;
- X del->next = (Af_hashent *)0;
- X }
- X return (AF_OK);
- X }
- X else /* search for entry in gully */
- X {
- X while (del->next)
- X {
- X if (!af_symcmp (del->next, symbol, list))
- X {
- X#ifdef MEMDEBUG
- X fprintf (memprot, "%x(sym-fr)\n", del->next->symbol);
- X#endif
- X free (del->next->symbol);
- X succ = del->next->next;
- X#ifdef MEMDEBUG
- X fprintf (memprot, "%x(e-fr)\n", del->next);
- X#endif
- X free ((char *)del->next);
- X del->next = succ;
- X return (AF_OK);
- X }
- X del = del->next;
- X }
- X FAIL ("delsym", "symbol not found (in gully)", AF_EINTERNAL, ERROR);
- X }
- X}
- X
- X/*=====================================================================
- X * af_symlookup -- look for symbol in hashtable
- X *
- X *=====================================================================*/
- X
- XEXPORT char *af_symlookup (htab, symbol, listin, listout)
- X Af_hash *htab;
- X char *symbol;
- X Af_revlist *listin, **listout;
- X{
- X /*
- X * Function searches htab for an entry with the given name symbol.
- X * If such an entry exists, a pointer to the symbol string is returned
- X * and the external variable af_cursymval is set to the corresponding
- X * symbolvalue
- X */
- X int where;
- X Af_hashent *targ;
- X bool delivernext = FALSE;
- X
- X where = htab->fhash (htab->hsize, symbol);
- X if (htab->hashtb[where].symbol) /* well, we found at least something */
- X {
- X /* if we search a specific revlist in the gully */
- X if (listin)
- X {
- X if (!af_symcmp (&htab->hashtb[where], symbol, listin))
- X delivernext = TRUE;
- X
- X targ = &htab->hashtb[where];
- X while (targ = targ->next)
- X {
- X if (!af_symcmp (targ, symbol, (Af_revlist *)0))
- X {
- X if (delivernext)
- X {
- X af_hashentry = *targ;
- X *listout = targ->revlist;
- X return (targ->symbol);
- X }
- X else
- X if (targ->revlist == listin)
- X delivernext = TRUE;
- X }
- X }
- X }
- X else /* normal case */
- X {
- X if (!af_symcmp (&htab->hashtb[where], symbol, (Af_revlist *)0))
- X {
- X af_hashentry = htab->hashtb[where];
- X if (listout != (Af_revlist **)0)
- X *listout = htab->hashtb[where].revlist;
- X return htab->hashtb[where].symbol;
- X }
- X else /* maybe it is somewhere down the gully */
- X {
- X targ = &htab->hashtb[where];
- X while (targ->next)
- X {
- X targ = targ->next;
- X if (!af_symcmp (targ, symbol, (Af_revlist *)0))
- X {
- X af_hashentry = *targ;
- X if (listout != (Af_revlist **)0)
- X *listout = targ->revlist;
- X return (targ->symbol);
- X }
- X }
- X }
- X }
- X }
- X /* when we come to this point, the symbol hasn't been known */
- X if (listout != (Af_revlist **)0)
- X *listout = (Af_revlist *)0;
- X return ((char *)0);
- X}
- X
- X/*=====================================================================
- X * af_vallookup -- look for single value
- X *
- X *=====================================================================*/
- X
- XEXPORT char *af_vallookup (entry, value)
- X Af_hashent *entry;
- X char *value;
- X{
- X char *valptr;
- X
- X if (valptr = index (entry->symbol, AF_UDANAMDEL))
- X valptr += sizeof (char);
- X
- X /* search until value is found */
- X while (af_valcmp (valptr, value))
- X {
- X if ((valptr = index (valptr, AF_UDAVALDEL)) == (char *)0)
- X return (char *)0;
- X valptr += sizeof (char);
- X }
- X
- X return (valptr);
- X}
- X
- X/*=====================================================================
- X * af_lhashsyms -- create a list of all symbols in hashtable.
- X * A (char *)0 terminated pointerlist, listing all
- X * symbols in the hashtable is created.
- X *
- X *=====================================================================*/
- X
- XEXPORT af_lhashsyms (htab, symbollist)
- X Af_hash *htab;
- X char **symbollist;
- X{
- X register int i, j=0, size=0;
- X register Af_hashent *h;
- X
- X if (htab->hashtb != (Af_hashent *)0)
- X {
- X for (i = 0; i < htab->hsize; i++)
- X if (htab->hashtb[i].symbol != (char *)0)
- X {
- X h = &htab->hashtb[i];
- X while (h)
- X {
- X symbollist[j] = h->symbol;
- X size = size + (strlen (h->symbol)+1);
- X j++;
- X h = h->next;
- X }
- X }
- X }
- X symbollist[j] = (char *)0;
- X return (size);
- X}
- X
- X
- X/*=====================================================================
- X * af_hashcopy -- copy hash table
- X *
- X *=====================================================================*/
- X
- XEXPORT af_hashcopy (oldhtab, newhtab)
- X Af_hash *oldhtab, *newhtab;
- X{
- X register i;
- X char *af_hashsysm(), *list[AF_MAXUDAS];
- X
- X
- X /* initialize new hashtable */
- X newhtab->hsize = oldhtab->hsize;
- X newhtab->fhash = oldhtab->fhash;
- X
- X /* copy hashtable */
- X (void) af_lhashsyms (oldhtab, list);
- X i=0;
- X while (list[i] != (char *)0)
- X {
- X (void) af_hashsym (newhtab, list[i], (Af_revlist *)0);
- X i++;
- X }
- X
- X return (AF_OK);
- X}
- X
- X
- X/*===============================================================
- X * af_symcmp -- compare contents of hashtable entry
- X * either of the form name=[value ...]
- X * or name; listptr;
- X * Return values like strcmp.
- X *
- X *==============================================================*/
- X
- XLOCAL af_symcmp (entry, str, listptr)
- X Af_hashent *entry;
- X char *str;
- X Af_revlist *listptr;
- X{
- X char *str1;
- X
- X /* if a listpointer is given */
- X if (listptr)
- X {
- X if (entry->revlist == listptr)
- X return (strcmp (entry->symbol, str));
- X else
- X return (1);
- X }
- X else
- X {
- X str1 = entry->symbol;
- X while (*str1 == *str)
- X {
- X if ((*str1 == AF_UDANAMDEL) || (*str1 == '\0'))
- X return (0);
- X str1++;
- X str++;
- X }
- X if (((*str1 == AF_UDANAMDEL) && (*str =='\0')) ||
- X ((*str1 =='\0') && (*str == AF_UDANAMDEL)))
- X return (0);
- X else
- X
- Xreturn (*str1 - *str);
- X }
- X}
- X
- X/*===============================================================
- X * af_valcmp -- compare single values in a string of the form
- X * name=[value1 value2 ...]
- X * Return values like strcmp.
- X *
- X *==============================================================*/
- X
- XLOCAL af_valcmp (str1, str2)
- X char *str1, *str2;
- X{
- X while (*str1 == *str2)
- X {
- X if ((*str1 == AF_UDAVALDEL) || (*str1 == '\0'))
- X return (0);
- X str1++;
- X str2++;
- X }
- X if (((*str1 == AF_UDAVALDEL) && (*str2 =='\0')) ||
- X ((*str1 =='\0') && (*str2 == AF_UDAVALDEL)))
- X return (0);
- X else
- X return (*str1 - *str2);
- X}
- X
- X/*====================================================================
- X * af_match
- X * returnes FALSE if entry matches, else TRUE
- X *
- X *====================================================================*/
- X
- XEXPORT af_match (entry, hashtab)
- X char *entry;
- X Af_hash *hashtab;
- X{
- X char *valptr, *af_symlookup(), *af_vallookup();
- X
- X /* if user defined attribute does not exist */
- X if ((af_symlookup (hashtab, entry, (Af_revlist *)0, (Af_revlist **)0))
- X == (char*)0)
- X return (ERROR);
- X
- X /* else compare values */
- X if (valptr = index (entry, AF_UDANAMDEL))
- X {
- X do
- X {
- X valptr = valptr + sizeof (char);
- X if ((af_vallookup (&af_hashentry, valptr) == (char *)0)
- X && (*valptr != '\0'))
- X return (ERROR);
- X }
- X while (valptr = index (valptr, AF_UDAVALDEL));
- X }
- X return (AF_OK);
- X}
- X
- X/**** DEBUG **** DEBUG **** DEBUG **** DEBUG **** DEBUG **** DEBUG ****/
- X
- X/*=====================================================================
- X * af_dumphtb -- dump hashtable
- X *
- X *=====================================================================*/
- X
- XEXPORT af_dumphtb (htab) /* for debug purposes */
- X Af_hash *htab;
- X{
- X register int i;
- X register Af_hashent *h;
- X
- X#ifdef CCOLL
- X fprintf (stderr, "Hash-collision statistics:\n");
- X fprintf (stderr, "Table-size: %d\tNo. of symbols: %d\tCollisions: %d\n",
- X htab->hsize, af_symcount, af_collcnt);
- X#endif
- X
- X for (i = 0; i < htab->hsize; i++)
- X {
- X if (htab->hashtb[i].symbol[0])
- X {
- X h = &htab->hashtb[i];
- X while (h)
- X {
- X fprintf (stderr, "\nsymbol: (%d) %s -- list: %x",
- X i, h->symbol, h->revlist);
- X h = h->next;
- X }
- X }
- X else fprintf (stderr, ".");
- X }
- X}
- X
- X
- END_OF_FILE
- if test 17913 -ne `wc -c <'src/afs/afhash.c'`; then
- echo shar: \"'src/afs/afhash.c'\" unpacked with wrong size!
- fi
- # end of 'src/afs/afhash.c'
- fi
- if test -f 'src/vfind/vfind.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/vfind/vfind.c'\"
- else
- echo shar: Extracting \"'src/vfind/vfind.c'\" \(17438 characters\)
- sed "s/^X//" >'src/vfind/vfind.c' <<'END_OF_FILE'
- X/*
- X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
- X * and U. Pralle
- X *
- X * This software is published on an as-is basis. There is ABSOLUTELY NO
- X * WARRANTY for any part of this software to work correctly or as described
- X * in the manuals. We do not accept any liability for any kind of damage
- X * caused by use of this software, such as loss of data, time, money, or
- X * effort.
- X *
- X * Permission is granted to use, copy, modify, or distribute any part of
- X * this software as long as this is done without asking for charge, and
- X * provided that this copyright notice is retained as part of the source
- X * files. You may charge a distribution fee for the physical act of
- X * transferring a copy, and you may at your option offer warranty
- X * protection in exchange for a fee.
- X *
- X * Direct questions to: Tech. Univ. Berlin
- X * Wilfried Koch
- X * Sekr. FR 5-6
- X * Franklinstr. 28/29
- X * D-1000 Berlin 10, West Germany
- X *
- X * Tel: +49-30-314-22972
- X * E-mail: shape@coma.uucp or shape@db0tui62.bitnet
- X */
- X/* LAST EDIT: Mon Feb 20 14:15:16 1989 by Uli Pralle (coma!uli) */
- X/*
- X * vfind.c
- X */
- X#ifndef lint
- Xstatic char *AFSid = "$Header: vfind.c[1.6] Tue Feb 21 20:22:53 1989 uli@coma published $";
- Xstatic char *Objfile = "vfind.c[1.6] published";
- X#ifdef CFFLGS
- X static char *Cflags = CFFLGS;
- X#endif
- X#endif
- X/*
- X * Log for /u/shape/dist-tape/src/vfind/vfind.c[1.6]
- X * Tue Feb 21 20:22:53 1989 uli@coma published $
- X *
- X * * Vfind is the same as find(1) except that it has more afs
- X * related primaries such as -eq, -le, -lt, -ge, -gt, -uda,
- X * -symbolic, -locked, -locker, etc.
- X *
- X * * vfind has problems with udas.
- X *
- X * * vfind is part of the shape toolkit release for comp.sources.unix.
- X *
- X *
- X */
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <sys/dir.h>
- X#include <sys/wait.h>
- X#include <stdio.h>
- X#include <strings.h>
- X#include <afs.h>
- X#include <afsapp.h>
- X#include <ParseArgs.h>
- X
- X#include "atk.h"
- X
- Xtypedef struct expr *Expr; /* short hand */
- Xstruct expr {
- X int (*eval)(); /* evaluator */
- X Expr left; /* left op */
- X Expr right; /* right op */
- X};
- X
- Xextern char *getwd();
- Xextern char *malloc();
- Xextern char *re_comp();
- X
- Xstatic char *progname; /* av[0] w/o leading path */
- Xstatic char startdir[MAXPATHLEN+1]; /* dir at beginning of process */
- Xstatic char garbage[80]; /* for error messages */
- Xstatic int nac; /* ac after option parsing */
- Xstatic char **nav; /* av after option parsing */
- Xstatic int npaths; /* pathname list */
- Xstatic struct expr *exprl; /* expression list */
- Xstatic int idx; /* */
- Xstatic long now; /* time in secs */
- Xstatic Af_attrs attrs; /* attr buf */
- Xstatic Af_set set, bset; /* attr set */
- Xstatic int Bflag, Pflag, Fflag;
- X
- X/* Options */
- Xstatic int vf_prune_opt () {
- X Pflag++;
- X return 0;
- X}
- X
- Xstatic int vf_version_opt () {
- X char *vfversion();
- X
- X (void) printf ("This is %s version %s.\n", progname, vfversion());
- X (void) printf ("AFS version %s.\n", af_version());
- X return 1; /* force termination */
- X}
- X
- Xstatic int vf_b_opt () {
- X Bflag++;
- X return 0;
- X}
- X
- Xstatic int vf_f_opt () {
- X Fflag++;
- X return 0;
- X}
- X
- Xstatic int vf_help_opt () {
- X extern OptDesc optdesc[];
- X pa_ShortUsage(progname, optdesc, "path-list expression");
- X
- X return 1;
- X}
- X
- XOptDesc optdesc[] = {
- X { "version", OPT_IS_SWITCH, vf_version_opt },
- X { "bpool", OPT_IS_SWITCH, vf_b_opt},
- X { "h", OPT_IS_SWITCH, vf_help_opt},
- X { "prune", OPT_IS_SWITCH, vf_prune_opt},
- X { "force", OPT_IS_SWITCH, vf_f_opt},
- X { (char *) NULL, NULL, NULL },
- X};
- X
- Xvoid byebye(i) {
- X (void) chdir("/tmp"); /* in case of -pg. */
- X exit(i);
- X}
- X
- Xvoid Usage() {
- X (void) fprintf (stderr,"%s: usage: %s path-list expression.\n",
- X progname , progname);
- X byebye(1);
- X}
- X
- X/* primaries */
- Xstatic int print () {
- X puts(at_getbndvers(&attrs));
- X return 1;
- X}
- X
- Xchar *mkedpat(pat) char *pat; {
- X char pattern[1024];
- X char *cp;
- X int i;
- X
- X if (pat && *(cp = pat) == '\0')
- X return (char *) NULL;
- X
- X *pattern = '^';
- X for (i = 1; *cp; cp++) {
- X if (i >= 1024) {
- X (void) fprintf (stderr, "%s: pattern to long.\n", progname);
- X byebye(1);
- X }
- X
- X switch (*cp) {
- X case '?':
- X pattern[i++] = '.';
- X break;
- X case '*':
- X pattern[i++] = '.'; pattern[i++] = '*';
- X break;
- X default:
- X pattern[i++] = *cp;
- X break;
- X }
- X }
- X pattern[i++] = '$'; pattern[i] = '\0';
- X
- X if ((cp = malloc ((unsigned) (strlen(pattern) + 1))) == (char *) NULL) {
- X (void) fprintf (stderr, "%s: out of memory.\n", progname);
- X byebye(1);
- X }
- X return strcpy(cp, pattern);
- X}
- X
- Xstatic int name (exp) Expr exp; {
- X char *cp;
- X
- X if (cp = re_comp ((char *) exp->left)) {
- X (void) fprintf (stderr, "%s: %s\n", progname, cp);
- X byebye(1);
- X }
- X
- X return re_exec(at_getfilename(&attrs));
- X
- X}
- X
- Xstatic int state (exp) Expr exp; {
- X return attrs.af_state == (int) exp->left;
- X}
- X
- Xstatic int uda (exp) Expr exp; {
- X return (at_matchuda(&attrs, (char *) exp->left));
- X}
- X
- Xstatic int symname (exp) Expr exp; {
- X char symnameuda[AF_UDANAMLEN+1];
- X
- X return at_matchuda(&attrs, sprintf(symnameuda, "%s=%s", SYMNAME,
- X (char *) exp->left));
- X}
- X
- Xstatic int perm (exp) Expr exp; {
- X return (attrs.af_mode & (int) exp->right & 07777) == (int) exp->left;
- X}
- X
- Xstatic int user (exp) Expr exp; {
- X return (!strcmp((char *)exp->left, attrs.af_owner.af_username)
- X && (exp->right ? !strcmp((char *)exp->right,
- X attrs.af_owner.af_userhost) : 1));
- X}
- X
- Xstatic int locked () {
- X return (attrs.af_locker.af_username[0] != '\0');
- X}
- X
- Xstatic int locker (exp) Expr exp; {
- X return (!strcmp((char *)exp->left, attrs.af_locker.af_username)
- X && (exp->right ? !strcmp((char *)exp->right,
- X attrs.af_locker.af_userhost) : 1));
- X}
- X
- Xstatic int type (exp) Expr exp; {
- X return (attrs.af_mode&S_IFMT) == (int) exp->left;
- X}
- X
- Xstatic int vl () {
- X printf ("%s %s %s %8d %s %s\n",
- X at_getmode(&attrs),
- X at_getversstate(&attrs, 0),
- X at_getuser(&(attrs.af_owner)),
- X attrs.af_size,
- X at_getdate(&attrs),
- X at_getbndvers(&attrs));
- X return 1;
- X}
- X
- Xstatic int eq (exp) Expr exp; {
- X return (attrs.af_gen == (int) exp->left) &&
- X (attrs.af_rev == (int) exp->right);
- X}
- X
- Xstatic int lt (exp) Expr exp; {
- X return (attrs.af_gen < (int) exp->left ||
- X (attrs.af_gen == (int) exp->left &&
- X attrs.af_rev < (int) exp->right));
- X}
- X
- Xstatic int le (exp) Expr exp; {
- X return lt(exp) || eq(exp);
- X}
- X
- Xstatic int gt (exp) Expr exp; {
- X return (attrs.af_gen > (int) exp->left ||
- X (attrs.af_gen == (int) exp->left &&
- X attrs.af_rev > (int) exp->right));
- X}
- X
- Xstatic int ge (exp) Expr exp; {
- X return gt(exp) || eq(exp);
- X}
- X
- X
- X#define SECSPERDAY 86400L
- Xstatic int comptime(secs, days, sign)
- X time_t secs;
- X int days;
- X char sign;
- X{
- X int d;
- X
- X d = (int) ((now - secs) / SECSPERDAY);
- X switch (sign) {
- X case '+': return (d>days);
- X case '-': return (d < (days * -1));
- X default: return (d==days);
- X }
- X}
- X
- Xstatic int mtime (exp) Expr exp; {
- X return comptime(attrs.af_mtime, (int) exp->left, *(char*)(exp->right));
- X}
- X
- Xstatic int atime (exp) Expr exp; {
- X return comptime(attrs.af_atime, (int) exp->left, *(char*)(exp->right));
- X}
- X
- Xstatic int chngtime (exp) Expr exp; {
- X return comptime(attrs.af_ctime, (int) exp->left, *(char*)(exp->right));
- X}
- X
- Xstatic int stime (exp) Expr exp; {
- X return comptime(attrs.af_stime, (int) exp->left, *(char*)(exp->right));
- X}
- X
- Xstatic int ltime (exp) Expr exp; {
- X return comptime(attrs.af_ltime, (int) exp->left, *(char*)(exp->right));
- X}
- X
- Xstatic int execute (exp) Expr exp; {
- X char *pav[40], *arg;
- X int i, j;
- X int pid, wpid;
- X union wait retcode;
- X
- X i = (int) exp->left;
- X for (j = 0; strcmp((arg = nav[i++]), ";"); j++)
- X if (!strcmp(arg, "{}"))
- X pav[j] = at_getbndvers(&attrs);
- X else
- X pav[j] = arg;
- X
- X pav[j] = (char *) NULL;
- X if (j == 0) return 1;
- X
- X (void) fflush(stdout);
- X switch (pid = fork()) {
- X case -1:
- X perror (sprintf(garbage, "%s: fork failed\n", progname));
- X byebye(1);
- X break;
- X case 0:
- X (void) chdir(startdir);
- X /*VARARGS*/
- X (void) execvp(pav[0], pav);
- X (void) perror("vfind: exec failed");
- X (void) kill (getpid(), SIGHUP);
- X _exit(127);
- X break;
- X default:
- X while ((wpid = wait(&retcode)) != -1 && wpid != pid);
- X if (retcode.w_status&0177) {
- X (void) fprintf (stderr, "%s: execution terminated\n", progname);
- X byebye(1);
- X }
- X return (!retcode.w_status);
- X break;
- X }
- X /*NOTREACHED*/
- X}
- X
- Xstatic int not (exp) Expr exp; {
- X return ! ((*exp->left->eval) (exp->left));
- X}
- X
- Xstatic int and (exp) Expr exp; {
- X return ((*exp->left->eval) (exp->left) &&
- X (*exp->right->eval) (exp->right)) ? 1 : 0;
- X}
- X
- Xstatic int or (exp) Expr exp; {
- X return ((*exp->left->eval) (exp->left) ||
- X (*exp->right->eval) (exp->right)) ? 1 : 0;
- X}
- X
- X/* constructors */
- Xstatic Expr build(func, l, r)
- X int (*func)();
- X Expr l, r;
- X{
- X Expr this;
- X if ((this = (Expr) malloc ((unsigned) sizeof (struct expr))) ==
- X (Expr) NULL) {
- X (void) fprintf (stderr, "%s: out of memory.\n", progname);
- X byebye (1);
- X }
- X
- X this->eval = func; this->left = l; this->right = r;
- X return this;
- X}
- X
- Xstatic void skip() {
- X if (nav[idx])
- X idx++;
- X else {
- X (void) fprintf (stderr, "%s: parsing error\n", progname);
- X byebye(1);
- X }
- X}
- X
- Xstatic Expr primary () {
- X char *prim, *val, *cp;
- X char c;
- X int i = 0;
- X int mode = 0;
- X int mask = 0;
- X
- X val = cp = (char *) NULL;
- X
- X if (!(prim = nav[idx])) {
- X (void) fprintf (stderr, "%s: parsing error\n", progname);
- X byebye(1);
- X }
- X
- X if (*prim != '-') {
- X (void) fprintf(stderr, "%s: %s is not a primary\n", progname, prim);
- X byebye(1);
- X }
- X prim++;
- X if (!strcmp (prim, "print"))
- X return build(print, (Expr) NULL, (Expr) NULL);
- X if (!strcmp(prim, "ls") || !strcmp(prim, "vl"))
- X return build(vl, (Expr) NULL, (Expr) NULL);
- X if (!strcmp(prim, "locked"))
- X return build(locked, (Expr) NULL, (Expr) NULL);
- X
- X skip();
- X if (!(val = nav[idx])) {
- X (void) fprintf (stderr, "%s: parsing error\n", progname);
- X byebye(1);
- X }
- X
- X if (!strcmp (prim, "name"))
- X return build(name, (Expr) mkedpat(val), (Expr) NULL);
- X if (!strcmp(prim, "type")) {
- X c = *val;
- X i = (c=='b' ? S_IFBLK : c=='c' ? S_IFCHR :
- X c=='d' ? S_IFDIR : c=='f' ? S_IFREG :
- X c=='l' ? S_IFLNK : c=='s' ? S_IFSOCK : NULL);
- X return build(type, (Expr) i, (Expr) NULL);
- X }
- X if (!strcmp(prim, "perm")) {
- X while(c = *val++)
- X if (c=='-') mask++;
- X else {
- X c -= '0'; mode <<= 3; mode += c;
- X }
- X return build(perm, (Expr) mode, (Expr) (mask ? mode : 07777));
- X }
- X if (!strcmp(prim, "atime"))
- X return build(atime, (Expr) atoi(val), (Expr) val);
- X if (!strcmp(prim, "ctime"))
- X return build(chngtime, (Expr) atoi(val), (Expr) val);
- X if (!strcmp(prim, "mtime"))
- X return build(mtime, (Expr) atoi(val), (Expr) val);
- X if (!strcmp(prim, "stime"))
- X return build(stime, (Expr) atoi(val), (Expr) val);
- X if (!strcmp(prim, "ltime"))
- X return build(ltime, (Expr) atoi(val), (Expr) val);
- X if (!strcmp(prim, "user")) {
- X if (cp = rindex(val, '@')) *cp++ = '\0';
- X return build(user, (Expr) val, (Expr) cp);
- X }
- X if (!strcmp(prim, "eq")) {
- X if (cp = rindex(val, '.')) *cp++ = '\0';
- X return build(eq, (Expr) atoi(val), (Expr) atoi(cp));
- X }
- X if (!strcmp(prim, "le")) {
- X if (cp = rindex(val, '.')) *cp++ = '\0';
- X return build(le, (Expr) atoi(val), (Expr) atoi(cp));
- X }
- X if (!strcmp(prim, "lt")) {
- X if (cp = rindex(val, '.')) *cp++ = '\0';
- X return build(lt, (Expr) atoi(val), (Expr) atoi(cp));
- X }
- X if (!strcmp(prim, "ge")) {
- X if (cp = rindex(val, '.')) *cp++ = '\0';
- X return build(ge, (Expr) atoi(val), (Expr) atoi(cp));
- X }
- X if (!strcmp(prim, "gt")) {
- X if (cp = rindex(val, '.')) *cp++ = '\0';
- X return build(gt, (Expr) atoi(val), (Expr) atoi(cp));
- X }
- X if (!strcmp(prim, "locker")) {
- X if (cp = rindex(val, '@')) *cp++ = '\0';
- X return build(locker, (Expr) val, (Expr) cp);
- X }
- X if (!strcmp(prim, "exec") || !strcmp(prim, "ok")) {
- X i = idx;
- X while(nav[++idx] && strcmp(nav[idx], ";"));
- X return build(execute, (Expr) i, (Expr) prim);
- X }
- X if (!strcmp(prim, "state"))
- X return build(state, (Expr) at_string2state(val), (Expr) NULL);
- X if (!strcmp(prim,"uda"))
- X return build(uda, (Expr) val, (Expr) NULL);
- X if (!strcmp(prim,"symbolic"))
- X return build(symname, (Expr) val, (Expr) NULL);
- X (void) fprintf (stderr,"%s: unknown primary %s.\n", progname, prim);
- X byebye(1);
- X /*NOTREACHED*/
- X}
- X
- Xstatic Expr alternation(); /* forward declaration */
- X
- Xstatic Expr grouping () {
- X Expr expr;
- X
- X if (!strcmp(nav[idx], "(")){
- X skip();
- X expr = alternation();
- X if (nav[idx] && !strcmp(nav[idx], ")")) {
- X skip();
- X return expr;
- X }
- X (void) fprintf (stderr, "%s: missing closing ')'.\n", progname);
- X byebye(1);
- X }
- X else {
- X expr = primary();
- X skip(); /* primary() does not skip the */
- X /* processed token, so we do it here. */
- X return expr;
- X }
- X /*NOTREACHED*/
- X}
- X
- Xstatic Expr negation() {
- X if (nav[idx] && !strcmp(nav[idx], "!")) {
- X skip();
- X return build(not, grouping(), (Expr) NULL);
- X }
- X else
- X return grouping();
- X}
- X
- Xstatic Expr concatenation() {
- X Expr left;
- X char *this;
- X
- X left = negation ();
- X this = nav[idx];
- X if (this && (!strcmp(this, "-a") || !strcmp(this, "!") ||
- X !strcmp(this,"(") || (*this == '-' && strcmp(this, "-o")))){
- X if (!strcmp(this,"-a")) skip();
- X return build(and, left, concatenation());
- X }
- X else
- X return left;
- X}
- X
- Xstatic Expr alternation() {
- X Expr left;
- X
- X left = concatenation();
- X if (nav[idx] && !strcmp(nav[idx], "-o")) {
- X skip();
- X return build(or, left, concatenation());
- X }
- X else
- X return left;
- X}
- X
- Xstatic Expr expression() {
- X return alternation();
- X}
- X
- Xstatic int dselect (d)
- X struct direct *d;
- X{
- X char *name = d->d_name;
- X
- X if ((name[0] == '.' && name[1] == '\0') ||
- X (name[0] == '.' && name[1] == '.' && name[2] == '\0'))
- X return 0;
- X return 1;
- X}
- X
- Xstatic int adselect (d)
- X struct direct *d;
- X{
- X char *name = d->d_name;
- X
- X if (d->d_name[d->d_namlen -1] == AF_ARCHEXT)
- X return 1;
- X return 0;
- X}
- X
- Xstatic int indp (dp, dpentr, name, len)
- X struct direct **dp;
- X char *name;
- X int len, dpentr;
- X{
- X int i;
- X for (i = 0; i < dpentr; i++)
- X if (dp[i]->d_namlen == len && !strcmp(dp[i]->d_name, name))
- X return 1;
- X return 0;
- X}
- X
- Xstatic void traverse (name, afs_is_dir)
- X char *name;
- X int afs_is_dir; /* 1 if symbolic link */
- X{
- X struct stat buf, abuf;
- X struct direct **dp, **adp;
- X int nhits, ahits, i;
- X static int ncalls;
- X char *cp;
- X
- X (void) af_initattrs(&attrs); (void) af_initset(&set);
- X (void) strcpy(attrs.af_syspath, af_afpath(name));
- X (void) strcpy(attrs.af_name, af_afname(name));
- X (void) strcpy(attrs.af_type, af_aftype(name));
- X
- X if (!afs_is_dir) /* afs dir is symbolic link */
- X attrs.af_state = AF_BUSY;
- X
- X if (af_find(&attrs, &set) == -1) {
- X (void) af_perror(sprintf(garbage, "%s: af_find(%s)", progname, name));
- X return;
- X }
- X if (Bflag) {
- X (void) af_initset(&bset);
- X if (af_bpfind(&attrs, &bset) == -1) {
- X (void) af_perror(sprintf(garbage, "%s: bp_find(%s)", progname, name));
- X (void) af_dropset(&set);
- X return;
- X }
- X (void) af_union(&set, &bset, &set); (void) af_dropset(&bset);
- X }
- X
- X nhits = af_nrofkeys(&set);
- X (void) af_sortset(&set, AF_ATTHUMAN);
- X for (i = 0; i < nhits; i++) {
- X if (af_gattrs(&(set.af_klist[i]),&attrs) == -1) {
- X (void) af_perror(sprintf(garbage,"%s: af_gattrs():",progname));
- X continue;
- X }
- X (*exprl->eval)(exprl);
- X }
- X (void) af_dropset(&set);
- X
- X if ((lstat(name, &buf) == -1) ||
- X ((buf.st_mode&S_IFMT) != S_IFDIR) ||
- X (Pflag && ncalls) ||
- X !strcmp(name, AF_SUBDIR))
- X return;
- X
- X if (chdir(name) == -1)
- X return;
- X
- X if ((nhits = scandir(".", &dp, dselect, NULL)) == -1) {
- X fprintf (stderr, "%s: can't open dir %s.\n", progname, name);
- X return;
- X }
- X afs_is_dir = (lstat(AF_SUBDIR, &abuf) != -1 &&
- X (((abuf.st_mode&S_IFMT) == S_IFDIR) || Fflag));
- X if (afs_is_dir &&
- X ((ahits = scandir(AF_SUBDIR, &adp, adselect, NULL)) != -1)) {
- X for (i = 0; i < ahits; i++) {
- X cp = adp[i]->d_name + 2;
- X cp[adp[i]->d_namlen -3] = '\0';
- X if ((cp && *cp) && !indp(dp, nhits, cp, adp[i]->d_namlen - 3)) {
- X ncalls++; traverse(cp, afs_is_dir); ncalls--;
- X }
- X (void) free((char *)adp[i]);
- X }
- X (void) free((char *)adp);
- X }
- X for (i = 0; i < nhits; i++){
- X ncalls++; traverse(dp[i]->d_name, afs_is_dir); ncalls--;
- X (void) free((char *)dp[i]);
- X }
- X (void) free((char *)dp);
- X
- X (void) chdir("..");
- X return;
- X}
- X
- Xmain (ac, av)
- X int ac;
- X char *av[];
- X{
- X char *cp;
- X struct stat buf;
- X int afs_is_dir;
- X
- X progname = (cp = rindex(av[0], '/')) ? ++cp : av[0];
- X if (ParseArgs(ac, av, &nac, &nav, optdesc)) byebye(1);
- X (void) getwd(startdir); (void) time(&now);
- X
- X if (nac < 2) Usage();
- X for (idx = 0; idx < nac; idx++) /* find path list */
- X if (*nav[idx] == '-' || *nav[idx] == '!' || *nav[idx] == '(') break;
- X if (!(npaths = idx)){
- X (void) fprintf (stderr, "%s: no path list.\n", progname); Usage();
- X }
- X if (idx == nac) {
- X (void) fprintf (stderr, "%s: no expression.\n", progname); Usage();
- X }
- X
- X if ((exprl = expression()) == (Expr) NULL) byebye(1);
- X
- X for (idx = 0 ; idx < npaths; idx++) { /* for all directories */
- X (void) chdir(startdir); /* back to normal */
- X afs_is_dir = (lstat(sprintf(garbage, "%s/%s", cp = nav[idx], AF_SUBDIR),
- X &buf) != -1 &&
- X (((buf.st_mode&S_IFMT) == S_IFDIR) || Fflag));
- X traverse(cp, afs_is_dir);
- X }
- X
- X byebye(0);
- X}
- END_OF_FILE
- if test 17438 -ne `wc -c <'src/vfind/vfind.c'`; then
- echo shar: \"'src/vfind/vfind.c'\" unpacked with wrong size!
- fi
- # end of 'src/vfind/vfind.c'
- fi
- if test -f 'tutorial/make2shape.ms' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'tutorial/make2shape.ms'\"
- else
- echo shar: Extracting \"'tutorial/make2shape.ms'\" \(17381 characters\)
- sed "s/^X//" >'tutorial/make2shape.ms' <<'END_OF_FILE'
- X.\"
- X.\" Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
- X.\" and U. Pralle
- X.\"
- X.\" This software is published on an as-is basis. There is ABSOLUTELY NO
- X.\" WARRANTY for any part of this software to work correctly or as described
- X.\" in the manuals. We do not accept any liability for any kind of damage
- X.\" caused by use of this software, such as loss of data, time, money, or
- X.\" effort.
- X.\"
- X.\" Permission is granted to use, copy, modify, or distribute any part of
- X.\" this software as long as this is done without asking for charge, and
- X.\" provided that this copyright notice is retained as part of the source
- X.\" files. You may charge a distribution fee for the physical act of
- X.\" transferring a copy, and you may at your option offer warranty
- X.\" protection in exchange for a fee.
- X.\"
- X.\" Direct questions to: Tech. Univ. Berlin
- X.\" Wilfried Koch
- X.\" Sekr. FR 5-6
- X.\" Franklinstr. 28/29
- X.\" D-1000 Berlin 10, West Germany
- X.\"
- X.\" Tel: +49-30-314-22972
- X.\" E-mail: shape@coma.uucp or shape@db0tui62.bitnet
- X.\"
- X.NH 1
- XA quick guide through shape for make users
- X.PP
- XThis chapter is intended to give users of \fImake\fR a quick guide
- Xhow to change their development environment when switching
- Xfrom the usage of \fImake\fR to \fIshape\fR.
- X.PP
- XThe first step is quite simple. As the shape program is upward
- Xcompatible to make, you can just type \fCshape\fR instead of \fCmake\fR
- Xand shape will fulfill your (make\-)wishes.
- XOoops, we nearly forgot to mention, that you have to create a
- Xsubdirectory named \fCAFS\fR first.
- XYou will later see why.
- X.PP
- XBy using shape instead of make on your old Makefile you can
- Xalready take advantage of one important improvement of shape
- Xwith respect to make.
- XShape is sensible for changes in the compile environment.
- XIf you change for example your compiler flags or preprocessor
- Xdefinitions in the Makefile, shape will recompile all
- Xfiles that are affected by this change (make does not).
- XFor example, if \fCfoo.o\fR was generated by \fCcc -c -DBSD43\fR
- Xand you change your Makefile in order to produce a version
- Xsuitable for System V so that \fCfoo.c\fR should be
- Xproduced by \fCcc -c -DSYSV\fR, shape recognizes this change,
- Xin contrary to make.
- X.PP
- XYou might ask yourself now "how can shape do this ?".
- XBefore we can give you an answer to this question, you got to learn
- Xto know a few things about the architecture of the shape toolkit.
- XThe whole shape toolkit is implemented on top af an object base (AFS),
- Xthat is able to store software objects (regular UNIX files for instance)
- Xas a bunch
- Xof content data together with an arbitrary number of attributes.
- XThese things are called \fIattributed software objects\fR (ASO).
- XAttributes are strings of the general form \fCname=value\fR.
- XAFS supports a set of standard attributes (examples are:
- Xname, type, version number, owner, author) an unlimited number
- Xof \fIuser defined attributes\fR.
- XEach application may introduce its own user defined attributes.
- XAdditionally, AFS has a built-in version control system that
- Xsupports the storage and identification of different versions
- Xof software objects.
- XFor further details on the object base see afintro (3).
- X.PP
- XShape uses the mechanism of application defined attributes for recording
- Xthe compile
- Xenvironment (the name of the transformation tool and all options and
- Xarguments) of each derived file (you may know be more familiar with
- Xthe term \fI.o file\fR).
- XSo, shape bases its decision whether to recompile a system component
- Xfrom its source not only on comparing the date of last modification
- X(like make does) but also on the comparison of the compile environments.
- X.PP
- XDue to that mechanism, you have to bear one inconvenience on your journey
- Xfrom make to shape. Your first \fCshape\fR call causes all your files
- Xto be recompiled. This is necessary to initialize the object base.
- X.PP
- XBut you get indemnified for that with the next step.
- XSuppose, you want to produce different versions of your system
- Xby setting different compiler options.
- XTypically, you have a local test system that is compiled and linked
- Xwith the \fC-g\fR option (for symbolic debugging) and you publish
- X(install) product versions of your system compiled with \fC-O\fR
- X(optimizing) and the symbol table stripped off.
- X.PP
- XSo you might think, shape recompiles the whole stuff with \fC-O\fR
- Xfor publication and afterwards recompiles it again with \fC-g\fR
- Xfor continuing the work.
- X.br
- XNot true !
- X.br
- XAll derived files generated during a system building operation driven
- Xby shape are stored in a cache named \fIderived object pool\fR
- X(or \fIbinary pool\fR).
- XThe derived object pool is able to store multiple versions of
- Xequally named derived files and to distinguish between them by the
- Xuser defined attributes they have.
- XSo when you want to continue your work after an installation,
- Xyou old \fC.o\fR files are still there and
- Xshape restores them from the derived object pool instead
- Xof regenerating them from their source files.
- X.PP
- XTo prevent your disk from being flooded with derived files, each binary
- Xpool has a limited size (a maximum number of files stored in it).
- XBinary pools are administered in a cache fashion.
- XThe oldest (access date) derived files get removed if no additional
- Xfiles can be inserted due to the size limit.
- XYou can define the size of your private binary pool by setting
- Xthe environment variable \fCAFSBPSIZ\fR to an appropriate value.
- XA reasonable value is (\fI number of your source files * 2 \fR).
- XThe default value is 64.
- X.PP
- XRemember, all your work with shape up to now did not require
- Xany modification of your Makefile.
- XIf you don't like shape up to now \- no problem, \fCrm -rf AFS\fR
- Xremoves all shape specific stuff and you can go on with make.
- XBut if you like it, it is the right time to rename your Makefile to
- X\fCShapefile\fR and begin to implant shape specific things.
- X.NH 2
- XVersion Control
- X.PP
- XBeside the make functionality (system building), a main feature
- Xof the shape toolkit is the integration of a version control
- Xsystem in your system building environment.
- XShape does not only operate on regular UNIX files, but on
- Xmultiple versions of files.
- XFor this reason, we constructed a version control system which is
- Xintegral part of the shape toolkit.
- X.PP
- XThis version control system has a lot of similarities to existing
- Xversion control systems like RCS and SCCS, but also some
- Ximprovements with respect to these systems.
- XYou can read more about the version control in the manual pages.
- XWe just want to mention one important feature of the version control system
- Xhere, that is important to know while reading this chapter.
- X.PP
- XShape's version control system has a built in version status model.
- XThe essential thing for you to know about this is, that there are
- X"busy" and "saved" versions. Saved versions have
- Xa version number that consists of a generation number and
- Xa revision number (eg. 4.3). Saved versions cannot be modified;
- Xonce saved, they are "read only". Busy versions are the place
- Xwhere development takes place. They are alterable and have no
- Xversion number yet. Each regular UNIX file is a busy version
- Xin this sense. Saved versions come into being by making a copy
- Xof a busy version, tagging a version number to it and entering it
- X(as delta) in the appropriate archive file in the AFS subdirectory.
- XThe status model is more complex, but for further reading of this
- Xchapter it is enough when you know the states "busy", "saved"
- Xand "published".
- XPublished versions play a role when you working in a multi
- Xprogrammer team. You can use the publishing mechanism of the
- Xshape toolkit then to make specific versions of the system
- Xcomponent you work on accessible for your co workers.
- X.PP
- XIf you have worked with another version control system before
- Xit is advisable to transform your old version histories to
- Xshape histories.
- XIf you have used RCS before, you can have this be done
- Xautomatically by running the program \fIrcs2afs\fR.
- X.NH 2
- XVersion Selection Rules
- X.PP
- XOk, long enough now, let's dive into shape's selection mechanism.
- XMake's task is it, to produce names \- so called \fItargets\fR.
- XIt does this by traversing a system model consisting of
- X\fItarget \- dependent\fR lines to determine which components
- Xgo into a system and producing targets from their dependents.
- XTargets and dependents may correspond to equally named files in the
- Xfilesystem to which transformation tools are applied.
- XWhen doing make's job, due to the introduction of multiple versions
- Xof files, shape has the additional task to select one
- Xspecific version of each file involved.
- XIf does this by evaluating \fIversion selection rules\fR
- Xgiven by the
- Xprogrammer in a special part of the Shapefile, called the \fIrule-section\fR.
- XA version selection is driven by evaluating a selection rule
- Xwith the name given as parameter.
- XRemember that each version (software object) has a number of
- Xattributes attached to it. These attributes are the ground,
- Xselection rules operate on.
- XSo let's look at the following rule section:
- X.nf
- X.sp
- X\fC#% RULE-SECTION
- Xdefaultrule:
- X *, attr (state, busy).
- X#% END-RULE-SECTION\fR
- X.fi
- X.sp
- X.PP
- XA rule section always begins with a comment symbol (\fC#\fR) followed
- Xby a percent sign and the string \fCRULE-SECTION\fR.
- XIt ends accordingly (see example).
- XEach rule begins with the rule name followed by a colon (in the above case
- X\fCdefaultrule:\fR).
- XThe rest ot the selection rule is a named sequence of \fIalternatives\fR,
- Xseparated by semicolons, which form a logical OR expression. Each alternative
- Xconsists of a sequence of \fIpredicates\fR, separated by commas, which form
- Xa logical AND expression. A selection rule succeeds if one of its
- Xalternatives succeeds (i.e. leads to the unique identification of some
- Xdocument instance).
- XIn alternatives, the first predicate (e.g. \fC*\fR or \fC*.c\fR) is usually a
- Xpattern against which the name of a document that has to be retrieved
- Xis matched. The patterns used by shape have the same structure as those
- Xused by \fCed\fR.
- X.PP
- XThe rule above consists of only one alternative, so do not worry if you
- Xdo not find the semicolon in it.
- XBeside that, you never need to write a rule like this, because it is
- Xthe default rule \- this rule is active if no other selection rule
- Xis given.
- XIt makes exactly what make does: for each name (\fC*\fR) it selects the
- Xbusy version, which is an equally named regular UNIX file.
- XThis rule makes sense if you have no saved versions.
- X.PP
- XTo go on with shape it is necessary that you begin to work with
- Xthe version control system.
- XYou should save a releasable state of
- Xyour work by applying the command \fCsave\fR to all the files
- Xbelonging to your system.
- XThis can probably be done by inserting an entry in your Shapefile
- Xthat looks like
- X.sp
- X.nf
- X\fCsave:
- X save $(COMPONENTS)\fR
- X.fi
- X.sp
- Xand calling \fCshape save\fR.
- X.PP
- XIf you have done this, a rule like
- X.nf
- X.sp
- X\fC#% RULE-SECTION
- Xreleaserule:
- X *, attr (state, saved), attrmax (version).
- X#% END-RULE-SECTION\fR
- X.fi
- X.sp
- Xmakes sense for building releases.
- XThis rule selects for each component (\fC*\fR) of your system the
- Xlatest (\fCattrmax (version)\fR) saved (\fCattr (state, saved)\fR)
- Xversion.
- XIf for example there is \fIno\fR saved version of your component
- X\fCfoo.c\fR shape complains about that with the message:
- X\fCshape - selection rule for foo.c failed\fR
- X.PP
- XYou can activate a selection rule by inserting its name in the
- Xtarget - dependents line of your system at the place of the first dependent.
- XFor example
- X.nf
- X.sp
- X\fCall: releaserule program1 program2\fR
- Xor
- X\fCprogram: releaserule $(COMPONENTS)\fR
- X.sp
- X.fi
- Xcan be meaningful rule activations.
- XOnce set active, a selection rule is inherited to all subtargets.
- XBut be careful, the active selection rule can also be redefined
- Xwith each single target \-
- Xa mechanism that takes a little while to get used to.
- XSo if you are wondering about shape selecting other versions than
- Xyou expect, check your Shapefile for constructions like:
- X.nf
- X.sp
- X\fCall: releaserule program1 program2\fR
- X
- X\fCprogram1: defaultrule $(COMPONENTS1)\fR
- X
- X\fCprogram2: $(COMPONENTS2)\fR
- X.fi
- X.sp
- XIn this case \fCshape all\fR builds
- X\fCprogram1\fR with \fCdefaultrule\fR (explicitly set) and program2
- Xwith \fCreleaserule\fR (inherited).
- X.PP
- XWe cannot deal with all issues of the selection rule mechanism here;
- Xyou find more details on this in the chapter (.\" to be inserted),
- Xbut just to illustrate the power of expression sleeping in the
- Xselection rule mechanism,
- Xan example for a very complex selection rule.
- XIt does not make very much sense but it shall give you an idea
- Xof what you can express with the selection rule mechanism.
- X.nf
- X.sp
- X\fC#% RULE-SECTION
- X\&...
- Xcomplexrule:
- X # to be inserted
- X#% END-RULE-SECTION\fR
- X.fi
- X.sp
- X.NH 2
- XVariants
- X.PP
- XAfter having played around with selection rules
- Xyou may turn your attention to another very powerful mechanism of shape.
- XRemember the example from the beginning of this chapter that dealt with
- Xdifferent \fIvariants\fR (<- thats the buzzword) of your system for
- Xdifferent machines.
- XLet's introduce another section in the Shapefile.
- XThe first and the last line of this section look very much like
- Xthese of the rule section with the word \fCVARIANT\fR instead of \fCRULE\fR.
- X.nf
- X.sp
- X\fC#% VARIANT-SECTION
- Xvclass system ::= (bsd, sysV, sunos)
- X
- Xbsd:
- X vpath = bsd
- X vflags = -DBSD
- XsysV:
- X vpath = sysV
- X vflags = -DSYSV
- Xsunos:
- X vpath = sunos
- X vflags = -DSUNOS
- X#% END-VARIANT-SECTION\fR
- X.fi
- X.sp
- X.PP
- XThis helps you to deal on one hand with variants that are generated from
- X\fIone\fR source file by setting different precompiler switched and
- Xon the other hand with variants that are stored in equally named
- Xfiles in different directories.
- XWith a variant activated, shape passes variant dependent options
- X(vflags: eg. \fC-DBSD\fR) to each transformation tool (eg. \fCcc\fR)
- Xit triggers and it extends its search path for files by the
- Xdirectories named in vpath (eg. the subdirectory \fCbsd\fR).
- X.PP
- XThe activation mechanism for variants is quite similar to the rule
- Xactivation.
- XJust after the rule name you can optionally insert the variant name
- Xpreceded by a plus sign (\fC+\fR).
- XThe following example of a target \- dependent line is suitable for
- Xcalling shape with \fCshape SYSTEM=sunos all\fR. This builds the
- Xbsd variant of your system.
- X.nf
- X.sp
- X\fCall: releaserule +$(SYSTEM) program1 program2\fR
- X.fi
- X.sp
- XIt is advisable to have a line like
- X.nf
- X.sp
- X\fCSYSTEM=bsd\fR
- X.fi
- X.sp
- Xsomewhere in your Shapefile in order to define a default for your
- XSYSTEM macro. You can then omit the definition for SYSTEM on the command
- Xline when you want to build the default variant.
- XOne little hint in respect to activation of variants. When shape
- Xcomes up with an error message like
- X\fCshape - don't know how to shape +blabla\fR, this points to a
- Xspelling mismatch between variant naming and variant activation.
- X.PP
- XIn a variant definition, not only vpath and vflags can be defined.
- XYou can also redefine any macro.
- XAnother typical application is
- X.nf
- X.sp
- X\fC#% VARIANT-SECTION
- Xvclass quality ::= (test, test_profiling, final)
- X
- Xtest:
- X CFLAGS = -g
- X LDFLAGS = -g
- Xtest_profiling:
- X CFLAGS = -pg -g
- X LDFLAGS = -pg -g
- Xfinal:
- X CFLAGS = -O
- X LDFLAGS = -s
- X#% END-VARIANT-SECTION\fR
- X.fi
- X.sp
- Xthat helps to manage the other case of system variants that occured in an
- Xexample earlier in tis paper.
- XWith the targets
- X.nf
- X.sp
- X\fCall: +$(SYSTEM) +test_profiling program1 program2
- X
- Xinstall: +$(SYSTEM) +final program1 program2\fR
- X.fi
- X.sp
- Xyou can build test systems by calling \fCshape all\fR and release systems
- Xby calling \fCshape install\fR.
- X.PP
- XA few words about vclasses (to be inserted).
- XThe name of the vclass is not explicitely used up to now, but there should
- Xbe a equally named Macro (in capital letters) that holds the actual
- Xvariant setting.
- XFor this macro (as said earlier), a default should be defined.
- X.NH 2
- XBuilding up a target raster.
- X.PP
- XRule and variant activations should only be inserted in top level targets.
- XSee the sample Shapefiles for examples.
- X.NH 2
- XMacros
- X.PP
- XMacro naming conventions -> shape manual.
- X.NH 2
- XTransformation Rules
- X.PP
- XLike in make, you can write implicit transformation rules.
- XShape understands make syntax, but we recommend to use
- Xthe extended syntax described in the following paragraph
- X.PP
- XTransformation rules consist of a \fItransformation specification\fR,
- Xand a \fItransformation script\fR. Transformation specifications
- Xdescribe prerequisites and resulting objects of a transformation. The
- Xtransformation script is a template for a shell script that
- Xwill be passed to a shell process upon activation of a transformation.
- XThe syntax for these rules is an extension of Make's default rule
- Xspecification formalism. \*(sh's rule by which the transformation
- Xof a C source object into a '\fC\&.\&o\fR' (speak: dot-o) derived object
- Xis defined looks like:
- X.sp
- X.nf
- X\fC\s-1%.o: %.c : +(CC) +(CFLAGS)
- X $(CC) -c $(CFLAGS) %.c\s+1\fR
- X.fi
- X.LP
- X.PP
- XA request to produce a derived object \- let's say \fCxyzzy.o\fR \- would,
- Xby evaluating the transformation rule, result in the compilation
- Xof \fCxyzzy.c\fR with the compiler defined by
- Xthe macro \fCCC\fR, with compile switches defined by \fCCFLAGS\fR.
- XThe percent sign is consistently substituted by the name \(lqxyzzy\(rq
- Xthroughout the transformation rule. The notation \fI$(NAME)\fR substitutes
- Xthe value of the macro \fINAME\fR, while \fI+(NAME)\fR substitutes the
- Xentire macro definition (i.e. \fINAME=value\fR).
- X
- END_OF_FILE
- if test 17381 -ne `wc -c <'tutorial/make2shape.ms'`; then
- echo shar: \"'tutorial/make2shape.ms'\" unpacked with wrong size!
- fi
- # end of 'tutorial/make2shape.ms'
- fi
- echo shar: End of archive 20 \(of 33\).
- cp /dev/null ark20isdone
- MISSING=""
- 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
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 33 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-