1: /* $Header$ */
   2: 
   3: /*
   4:  * Author: Peter J. Nicklin
   5:  */
   6: #include <stdio.h>
   7: #include "hash.h"
   8: #include "macro.h"
   9: #include "null.h"
  10: #include "path.h"
  11: #include "pdb.h"
  12: #include "pdset.h"
  13: #include "pdlist.h"
  14: #include "pdtyp.h"
  15: #include "pld.h"
  16: #include "slist.h"
  17: #include "slslist.h"
  18: #include "spms.h"
  19: #include "truefalse.h"
  20: #include "yesno.h"
  21: 
  22: #define INCRPDIRS    50     /* amount to increase pdir ptr array */
  23: #define MAXPDIRS    100     /* initial size of proj dir ptr array */
  24: 
  25: extern char *PGN;           /* program name */
  26: extern PDTYP PDIRTYP;           /* project directory type labels list */
  27: 
  28: static int Ipdirs;          /* attribute block array index */
  29: static int Maxpdirs = MAXPDIRS;     /* maximum no. of project dirs */
  30: static int Ntypes;          /* number of unique type labels */
  31: static PDSET **Pdarray;         /* project dir attribute block array */
  32: static short *Maptyp;           /* unique type label mapping array */
  33: static TYPES *Typstat;          /* type label statistics */
  34: 
  35: /*
  36:  * add_pdset() adds a project directory to the set of project directories
  37:  * which satisfy a boolean project directory type label expression. Only
  38:  * those type labels which satisfy the boolean expression are included with
  39:  * the project directory. To determine which type labels qualify, the
  40:  * postfix expression is scanned from right to left. Type labels within a
  41:  * negated expression are ignored. For example, in the postfix equivalent
  42:  * of expression "src & !(cmd | lib)" (that is: src cmd lib | ! &),
  43:  * even if both "src" and "cmd" are found, "src" is the only type label
  44:  * which could qualify.
  45:  */
  46: void
  47: add_pdset(postfix, ppathname, pathname, project)
  48:     register PDTYP *postfix;    /* postfix expression struct */
  49:     char *ppathname;        /* project directory project pathname */
  50:     char *pathname;         /* project directory pathname */
  51:     char *project;          /* project directory's project */
  52: {
  53:     register int i;         /* postfix expression index */
  54:     register int opcount;       /* count of expected operands */
  55:     char *pdtcpy();         /* copy project directory type label */
  56:     char *realloc();        /* reallocate memory block */
  57:     char type[TYPESIZE];        /* project dir type label buffer */
  58:     PDSET *savepdir();      /* save pdir attribute blk somewhere */
  59:     void savetype();        /* save type label */
  60: 
  61:     if (Ipdirs >= Maxpdirs)
  62:         {
  63:         Maxpdirs += INCRPDIRS;
  64:         if ((Pdarray = (PDSET **) realloc((char *)Pdarray,
  65:                    (unsigned)Maxpdirs*sizeof(PDSET *))) == NULL)
  66:             nomorecore();
  67:         }
  68:     Pdarray[Ipdirs] = savepdir(ppathname, pathname, project);
  69: 
  70:     opcount = 0;
  71:     for (i = (postfix->pfxsize)-1; i >= 0;)
  72:         {
  73:         switch ((postfix->pfx)[i].p_class)
  74:             {
  75:             case B_ID:
  76:                 if ((postfix->pfx)[i].p_sw == TRUE)
  77:                     {
  78:                     pdtcpy(type, (postfix->pfx)[i].p_label);
  79:                     savetype(type, i);
  80:                     }
  81:                 break;
  82:             case B_OR:
  83:             case B_AND:
  84:                 if ((postfix->pfx)[i].p_sw == FALSE)
  85:                     opcount += 2;
  86:                 break;
  87:             case B_NOT:
  88:                 /* always skip !subexpr */
  89:                 opcount += 1;
  90:                 break;
  91:             }
  92:         /* skip false subexpression */
  93:         for (--i; opcount > 0; i--)
  94:             switch ((postfix->pfx)[i].p_class)
  95:                 {
  96:                 case B_ID:
  97:                     opcount -= 1;
  98:                     break;
  99:                 case B_OR:
 100:                 case B_AND:
 101:                     opcount += 1;
 102:                     break;
 103:                 case B_NOT:
 104:                     break;
 105:                 }
 106:         }
 107:     Ipdirs++;
 108: }
 109: 
 110: 
 111: 
 112: /*
 113:  * build_pdset() builds a set of project directories which satisfy a boolean
 114:  * project directory type label expression.
 115:  */
 116: build_pdset(ppathname, pathname)
 117:     char *ppathname;        /* project root dir project pathname */
 118:     char *pathname;         /* regular project root dir pathname */
 119: {
 120:     extern int ERRSTATUS;       /* pexec error status */
 121:     extern SLIST *ENVLIST;      /* project environment variable list */
 122:     char ppathbuf[PPATHSIZE];   /* project pathname buffer */
 123:     char *ppathcat();       /* project pathname concatenation */
 124:     char *pv;           /* PROJECT environment variable */
 125:     char *slprepend();      /* prepend key */
 126:     char *slsprepend();     /* prepend key+string */
 127:     int closepdb();         /* close database */
 128:     int errpdb();           /* print database error message */
 129:     int pdtmatch();         /* match project dir type label expr */
 130:     int status = 0;         /* return status */
 131:     PATH *pd;           /* pathname struct pointer */
 132:     PATH *readpld();        /* read project link directory entry */
 133:     PDB *openpdb();         /* open database */
 134:     PDB *pldp;          /* project link directory stream */
 135:     SLSBLK *pblk;           /* project list block */
 136:     SLSLIST *plist;         /* project list */
 137:     SLSLIST *slsinit();     /* initialize list */
 138:     void add_pdset();       /* add to set of project dirs */
 139:     void slsrm();           /* remove list item */
 140: 
 141:     if ((pv = slprepend(pathname, ENVLIST)) == NULL)
 142:         pxexit();
 143:     plist = slsinit();
 144: 
 145:     /* read PLDNAME project link directory */
 146:     if ((pldp = openpdb(PLDNAME, pathname, "r")) == NULL)
 147:         return(errpdb((PDB *) NULL));
 148:     while ((pd = readpld(pldp)) != NULL)
 149:         {
 150:         if (EQUAL(pd->p_alias, PARENTPROJECT))
 151:             continue;
 152: 
 153:         if (EQUAL(pd->p_alias, CURPROJECT))
 154:             {
 155:             if (pdtmatch(&PDIRTYP, pd->p_type) == YES)
 156:                 add_pdset(&PDIRTYP, ppathname, pd->p_path, pv);
 157:             }
 158:         else if (pd->p_mode == P_IFPROOT)
 159:             {
 160:             if (slsprepend(pd->p_alias, pd->p_path, plist) == NULL)
 161:                 pxexit();
 162:             }
 163:         else if (pdtmatch(&PDIRTYP, pd->p_type) == YES)
 164:             {
 165:             ppathcat(ppathbuf, ppathname, pd->p_alias);
 166:             add_pdset(&PDIRTYP, ppathbuf, pd->p_path, pv);
 167:             }
 168:         }
 169:     if (closepdb(pldp) != 0)
 170:         status = ERRSTATUS;
 171: 
 172:     /* build project directory type label tree for subprojects */
 173:     for (pblk = plist->head; pblk != NULL; pblk = pblk->next)
 174:         {
 175:         ppathcat(ppathbuf, ppathname, pblk->key);
 176:         status |= build_pdset(ppathbuf, pblk->string);
 177:         }
 178:     slsrm(CNULL, plist);
 179: 
 180:     return(status);
 181: }
 182: 
 183: 
 184: 
 185: /*
 186:  * check_pdset() detects conflicting type label priorities by
 187:  * checking that project directories are sorted into ascending
 188:  * order according to priority. An error message is printed and
 189:  * 1 returned on conflict, otherwise zero.
 190:  */
 191: check_pdset()
 192: {
 193:     register int iPd;       /* proj dir block array index */
 194:     register int ityp;      /* type label block index */
 195:     register int lastpr;        /* previous type label priority */
 196:     register int prior;     /* project dir type label priority */
 197:     register PDSET **ptrPd;     /* Pdarray block array pointer */
 198:     int nsortyp;            /* no. type label categories to sort */
 199: 
 200:     nsortyp = 0;
 201:     for (ityp = 0; ityp < Ntypes; ityp++)
 202:         if (Typstat[ityp].t_sort)
 203:             nsortyp++;
 204:     if (nsortyp < 2)
 205:         return(0);
 206: 
 207:     for (ityp = 0; ityp < Ntypes; ityp++)
 208:         if (Typstat[ityp].t_sort)
 209:             {
 210:             for (ptrPd=Pdarray, iPd=Ipdirs; iPd > 0; ptrPd++, iPd--)
 211:                 if ((*ptrPd)->typblk[ityp].t_exist)
 212:                     {
 213:                     lastpr = (*ptrPd)->typblk[ityp].t_prior;
 214:                     break;
 215:                     }
 216:             for (ptrPd++, iPd--; iPd > 0; ptrPd++, iPd--)
 217:                 {
 218:                 if ((*ptrPd)->typblk[ityp].t_exist)
 219:                     {
 220:                     prior = (*ptrPd)->typblk[ityp].t_prior;
 221:                     if (prior < lastpr)
 222:                         goto conflict;
 223:                     lastpr = prior;
 224:                     }
 225:                 }
 226:             }
 227:     return(0);
 228: conflict:
 229:     fprintf(stderr, "%s:", PGN);
 230:     for (ityp = Ntypes-1; ityp >= 0; ityp--)
 231:         if (Typstat[ityp].t_sort)
 232:             fprintf(stderr, (nsortyp-- > 1) ? " %s," :
 233:                 " %s: conflicting type label priorities\n",
 234:                 Typstat[ityp].t_name);
 235:     return(1);
 236: }
 237: 
 238: 
 239: 
 240: /*
 241:  * debug_pdset() prints the sorted project directories together with
 242:  * the type labels that satisfy the boolean expression.
 243:  */
 244: void
 245: debug_pdset()
 246: {
 247:     int iPd;            /* project dir block array index */
 248:     int ityp;           /* type label statistics array index */
 249: 
 250:     for (iPd = 0; iPd < Ipdirs; iPd++)
 251:         {
 252:         fprintf(stderr, "%s:", Pdarray[iPd]->ppath);
 253:         for (ityp = 0; ityp < Ntypes; ityp++)
 254:             if (Pdarray[iPd]->typblk[ityp].t_exist)
 255:                 fprintf(stderr," %s.%d",Typstat[ityp].t_name,
 256:                     Pdarray[iPd]->typblk[ityp].t_prior);
 257:         putc('\n', stderr);
 258:         }
 259: }
 260: 
 261: 
 262: 
 263: /*
 264:  * exec_pdset() executes a set of project directories. Returns non-zero
 265:  * error status if error.
 266:  */
 267: exec_pdset()
 268: {
 269:     extern int ERRSTATUS;       /* pexec error status */
 270:     extern int EXECUTE;     /* execute command? */
 271:     extern int PRINT_HEADING;   /* print headings for project dirs */
 272:     int ch_dir();           /* change current working directory */
 273:     int execcmd();          /* execute command in directory */
 274:     int iPd;            /* project dir block array index */
 275:     int status = 0;         /* return status */
 276:     void print_title();     /* print project directory title */
 277: 
 278:     for (iPd = 0; iPd < Ipdirs; iPd++)
 279:         {
 280:         if (PRINT_HEADING == YES)
 281:             print_title(Pdarray[iPd]->ppath);
 282:         if (ch_dir(Pdarray[iPd]->rpath) == NO)
 283:             status = ERRSTATUS;
 284:         else if (EXECUTE == YES)
 285:             status |= execcmd(Pdarray[iPd]->project);
 286:         }
 287:     return(status);
 288: }
 289: 
 290: 
 291: 
 292: /*
 293:  * init_pdset() allocates an array of pointers (Pdarray) to project
 294:  * directory attribute blocks, and calculates the maximum number of type
 295:  * labels to be stored with each project directory based on the number of
 296:  * unique type labels in the boolean postfix type expression. An array
 297:  * (Typstat) is also created to maintain statistics on each brand of
 298:  * label.
 299:  *
 300:  * Hash table lookup is used in forming unique type labels and a
 301:  * mapping array is used to map the labels from the boolean postfix
 302:  * type label expression to the unique representation.
 303:  */
 304: #define UNIQTYPHASHSIZE     41
 305: 
 306: void
 307: init_pdset()
 308: {
 309:     register int i;         /* postfix type expression index */
 310:     char *malloc();         /* memory allocator */
 311:     char *pfxcpy();         /* copy string prefix */
 312:     char type[TYPESIZE];        /* project dir type label buffer */
 313:     HASH *htinit();         /* initialize hash table */
 314:     HASH *uniqtyp;          /* hash table of unique type labels */
 315:     HASHBLK *htb;           /* hash table block pointer */
 316:     HASHBLK *htinstall();       /* install hash table entry */
 317:     HASHBLK *htlookup();        /* find hash table entry */
 318:     int nid;            /* no. of ids in boolean expression */
 319: 
 320:     /* project directory attribute block pointer array */
 321:     if ((Pdarray = (PDSET **) malloc((unsigned)Maxpdirs*sizeof(PDSET *))) == NULL)
 322:         nomorecore();
 323: 
 324:     /* create postfix expression -> unique type label mapping array */
 325:     if ((Maptyp = (short *) malloc((unsigned)PDIRTYP.pfxsize*sizeof(short))) == NULL)
 326:         nomorecore();
 327: 
 328:     /* create type label statistics array (estimate size first) */
 329:     nid = 0;
 330:     for (i = (PDIRTYP.pfxsize)-1; i >= 0; i--)
 331:         if ((PDIRTYP.pfx)[i].p_class == B_ID)
 332:             nid++;
 333:     if ((Typstat = (TYPES *) malloc((unsigned)nid*sizeof(TYPES))) == NULL)
 334:         nomorecore();
 335: 
 336:     /* unique type label determination */
 337:     uniqtyp = htinit(UNIQTYPHASHSIZE);
 338:     for (i = (PDIRTYP.pfxsize)-1; i >= 0; i--)
 339:         {
 340:         if ((PDIRTYP.pfx)[i].p_class != B_ID)
 341:             continue;
 342:         pfxcpy(type, (PDIRTYP.pfx)[i].p_id);
 343:         if ((htb = htlookup(type, uniqtyp)) != NULL)
 344:             {
 345:             Maptyp[i] = htb->h_val;
 346:             }
 347:         else    {
 348:             if ((htb = htinstall(type,"",Ntypes,uniqtyp)) == NULL)
 349:                 nomorecore();
 350:             Maptyp[i] = Ntypes;
 351:             Typstat[Ntypes].t_name = htb->h_key;
 352:             Typstat[Ntypes].t_ntl = Typstat[Ntypes].t_sort = 0;
 353:             Ntypes++;
 354:             }
 355:         }
 356: }
 357: 
 358: 
 359: 
 360: /*
 361:  * pdbcmp() compares the type label priorities and project pathnames
 362:  * for two project directories. Type label priorities override the
 363:  * lexicographical relationship of the project pathnames. Conflicting
 364:  * priorities are not detected. For example, a conflict occurs if the
 365:  * first directory has type labels print.1 and update.2, whereas the
 366:  * second directory has type labels print.2 and update.1. Returns
 367:  * an integer less than, equal to, or greater than zero, depending on
 368:  * the relative priorities of the type labels or lexicographical ordering
 369:  * of the project pathnames.
 370:  */
 371: pdbcmp(b1, b2)
 372:     PDSET **b1;         /* project directory block pointer */
 373:     PDSET **b2;         /* project directory block pointer */
 374: {
 375:     register TYPBLK *t1;        /* type label block pointer */
 376:     register TYPBLK *t2;        /* type label block pointer */
 377:     register TYPES *ty;     /* type statistics array pointer */
 378:     register int comp;      /* block comparison */
 379:     register int ityp;      /* type label block index */
 380:     register int ntypes;        /* number of unique type labels */
 381:     int strcmp();           /* string comparison */
 382: 
 383:     comp = 0;
 384:     ntypes = Ntypes;
 385:     t1 = (*b1)->typblk;
 386:     t2 = (*b2)->typblk;
 387:     ty = Typstat;
 388: 
 389:     for (ityp = 0; ityp < ntypes; ityp++)
 390:         {
 391:         if (ty->t_sort && t1->t_exist && t2->t_exist)
 392:             if ((comp = t1->t_prior - t2->t_prior) != 0)
 393:                 return(comp);
 394:         t1++, t2++, ty++;
 395:         }
 396:     return(strcmp((*b1)->ppath, (*b2)->ppath));
 397: }
 398: 
 399: 
 400: 
 401: /*
 402:  * savepdir() saves a block of project directory attributes somewhere
 403:  * and returns a pointer to the somewhere, or dies if out of memory.
 404:  */
 405: PDSET *
 406: savepdir(ppathname, pathname, project)
 407:     char *ppathname;        /* project directory project pathname */
 408:     char *pathname;         /* project directory regular pathname */
 409:     char *project;          /* project directory's project */
 410: {
 411:     char *calloc();         /* initialize memory to zero */
 412:     char *malloc();         /* memory allocator */
 413:     char *strcpy();         /* string copy */
 414:     int strlen();           /* string length */
 415:     PDSET *pdbptr;          /* pointer to proj directory block */
 416: 
 417:     if ((pdbptr = (PDSET *) malloc(sizeof(PDSET))) == NULL ||
 418:         (pdbptr->ppath = malloc((unsigned)(strlen(ppathname)+1))) == NULL ||
 419:         (pdbptr->rpath = malloc((unsigned)(strlen(pathname)+1))) == NULL ||
 420:         (pdbptr->typblk = (TYPBLK *) calloc((unsigned)Ntypes,sizeof(TYPBLK))) == NULL)
 421:         nomorecore();
 422:     strcpy(pdbptr->rpath, pathname);
 423:     strcpy(pdbptr->ppath, ppathname);
 424:     pdbptr->project = project;
 425:     return(pdbptr);
 426: }
 427: 
 428: 
 429: 
 430: /*
 431:  * savetype() records the priorities of the type labels attached to each
 432:  * directory, and also the total number of each type label.
 433:  */
 434: void
 435: savetype(type, idx)
 436:     char *type;         /* project dir type label */
 437:     int idx;            /* boolean type expression id index */
 438: {
 439:     register char *ptyptr;      /* pointer to type label priority */
 440:     register int priority;      /* type label priority */
 441:     register int uniqid;        /* unique type label number */
 442:     char *index();          /* first occurrence of character */
 443:     int atoi();         /* string to decimal integer */
 444: 
 445:     uniqid = Maptyp[idx];
 446:     ptyptr = index(type, '.');
 447:     priority = (ptyptr == NULL) ? 0 : atoi(++ptyptr);
 448:     if (Typstat[uniqid].t_ntl == 0)
 449:         {
 450:         Typstat[uniqid].t_itlp = priority;
 451:         }
 452:     else    {
 453:         if (priority != Typstat[uniqid].t_itlp)
 454:             Typstat[uniqid].t_sort = 1;
 455:         }
 456:     Typstat[uniqid].t_ntl++;
 457: 
 458:     Pdarray[Ipdirs]->typblk[uniqid].t_exist++;
 459:     Pdarray[Ipdirs]->typblk[uniqid].t_prior = priority;
 460: }
 461: 
 462: 
 463: 
 464: /*
 465:  * sort_pdset() sorts the set of project directories alpahabetically
 466:  * and by type label priorities.
 467:  */
 468: void
 469: sort_pdset()
 470: {
 471:     int pdbcmp();           /* compare project dir blocks */
 472: 
 473:     qsort((char *)Pdarray, Ipdirs, sizeof(PDSET *), pdbcmp);
 474: }

Defined functions

add_pdset defined in line 46; used 3 times
build_pdset defined in line 116; used 3 times
check_pdset defined in line 191; used 2 times
debug_pdset defined in line 244; used 2 times
exec_pdset defined in line 267; used 2 times
init_pdset defined in line 306; used 2 times
pdbcmp defined in line 371; used 2 times
savepdir defined in line 405; used 2 times
savetype defined in line 434; used 2 times
sort_pdset defined in line 468; used 2 times

Defined variables

Ipdirs defined in line 28; used 9 times
Maptyp defined in line 32; used 4 times
Maxpdirs defined in line 29; used 4 times
Ntypes defined in line 30; used 12 times
Pdarray defined in line 31; used 14 times
Typstat defined in line 33; used 15 times

Defined macros

INCRPDIRS defined in line 22; used 1 times
  • in line 63
MAXPDIRS defined in line 23; used 1 times
  • in line 29
UNIQTYPHASHSIZE defined in line 304; used 1 times
Last modified: 1985-07-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2081
Valid CSS Valid XHTML 1.0 Strict