|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.