|
|
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.