3 * Handle spec data structure.
15 /*@-exportheadervar@*/
16 extern struct MacroContext_s rpmGlobalMacroContext;
17 /*@=exportheadervar@*/
19 #define SKIPWHITE(_x) {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
20 #define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
22 /*@access Header @*/ /* compared with NULL */
28 /*@null@*/ struct TriggerFileEntry * freeTriggerFiles(/*@only@*/ /*@null@*/ struct TriggerFileEntry * p)
30 struct TriggerFileEntry *o, *q = p;
35 o->fileName = _free(o->fileName);
36 o->script = _free(o->script);
37 o->prog = _free(o->prog);
44 * Destroy source component chain.
45 * @param source component chain
49 /*@null@*/ struct Source * freeSources(/*@only@*/ /*@null@*/ struct Source * s)
51 struct Source *r, *t = s;
56 r->fullSource = _free(r->fullSource);
62 int lookupPackage(Spec spec, const char *name, int flag, /*@out@*/Package *pkg)
71 *pkg = spec->packages;
75 /* Construct package name */
77 if (flag == PART_SUBNAME) {
78 (void) headerNVR(spec->packages->header, &pname, NULL, NULL);
79 fullName = n = alloca(strlen(pname) + 1 + strlen(name) + 1);
80 while (*pname != '\0') *n++ = *pname++;
83 fullName = n = alloca(strlen(name)+1);
90 /* Locate package with fullName */
91 for (p = spec->packages; p != NULL; p = p->next) {
92 (void) headerNVR(p->header, &pname, NULL, NULL);
93 if (pname && (! strcmp(fullName, pname))) {
99 /*@-dependenttrans@*/ *pkg = p; /*@=dependenttrans@*/
100 return ((p == NULL) ? 1 : 0);
103 Package newPackage(Spec spec)
108 p = xcalloc(1, sizeof(*p));
110 p->header = headerNew();
119 p->triggerScripts = NULL;
122 p->triggerFiles = NULL;
130 p->postInFile = NULL;
132 p->postUnFile = NULL;
133 p->verifyFile = NULL;
135 p->specialDoc = NULL;
137 if (spec->packages == NULL) {
140 /* Always add package to end of list */
141 for (pp = spec->packages; pp->next != NULL; pp = pp->next)
150 Package freePackage(Package p)
152 if (p == NULL) return NULL;
154 p->preInFile = _free(p->preInFile);
155 p->postInFile = _free(p->postInFile);
156 p->preUnFile = _free(p->preUnFile);
157 p->postUnFile = _free(p->postUnFile);
158 p->verifyFile = _free(p->verifyFile);
160 p->header = headerFree(p->header);
161 p->fileList = freeStringBuf(p->fileList);
162 p->fileFile = _free(p->fileFile);
164 TFI_t fi = p->cpioList;
170 p->specialDoc = freeStringBuf(p->specialDoc);
171 p->icon = freeSources(p->icon);
172 p->triggerFiles = freeTriggerFiles(p->triggerFiles);
178 Package freePackages(Package packages)
182 while ((p = packages) != NULL) {
192 static inline /*@owned@*/ struct Source *findSource(Spec spec, int num, int flag)
196 for (p = spec->sources; p != NULL; p = p->next)
197 if ((num == p->num) && (p->flags & flag)) return p;
202 int parseNoSource(Spec spec, const char * field, int tag)
208 if (tag == RPMTAG_NOSOURCE) {
209 flag = RPMBUILD_ISSOURCE;
212 flag = RPMBUILD_ISPATCH;
217 for (f = fe; *f != '\0'; f = fe) {
225 if (*fe != '\0') fe++;
227 if (parseNum(f, &num)) {
228 rpmError(RPMERR_BADSPEC, _("line %d: Bad number: %s\n"),
230 return RPMERR_BADSPEC;
233 if (! (p = findSource(spec, num, flag))) {
234 rpmError(RPMERR_BADSPEC, _("line %d: Bad no%s number: %d\n"),
235 spec->lineNum, name, num);
236 return RPMERR_BADSPEC;
239 p->flags |= RPMBUILD_ISNO;
246 int addSource(Spec spec, Package pkg, const char *field, int tag)
252 const char *fieldp = NULL;
259 flag = RPMBUILD_ISSOURCE;
261 fieldp = spec->line + 6;
264 flag = RPMBUILD_ISPATCH;
266 fieldp = spec->line + 5;
269 flag = RPMBUILD_ISICON;
275 if (tag != RPMTAG_ICON) {
276 /* We already know that a ':' exists, and that there */
277 /* are no spaces before it. */
278 /* This also now allows for spaces and tabs between */
279 /* the number and the ':' */
282 while ((*fieldp != ':') && (*fieldp != ' ') && (*fieldp != '\t')) {
289 if (nump == NULL || *nump == '\0') {
292 if (parseNum(buf, &num)) {
293 rpmError(RPMERR_BADSPEC, _("line %d: Bad %s number: %s\n"),
294 spec->lineNum, name, spec->line);
295 return RPMERR_BADSPEC;
300 /* Create the entry and link it in */
301 p = xmalloc(sizeof(struct Source));
303 p->fullSource = xstrdup(field);
305 p->source = strrchr(p->fullSource, '/');
309 p->source = p->fullSource;
312 if (tag != RPMTAG_ICON) {
313 p->next = spec->sources;
322 if (tag != RPMTAG_ICON) {
323 /*@-nullpass@*/ /* LCL: varargs needs null annotate. */
324 const char *body = rpmGetPath("%{_sourcedir}/", p->source, NULL);
328 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
329 addMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
330 sprintf(buf, "%sURL%d",
331 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
332 addMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
341 static inline /*@only@*/ /*@null@*/ speclines newSl(void)
345 sl = xmalloc(sizeof(*sl));
355 static inline /*@null@*/ speclines freeSl(/*@only@*/ /*@null@*/ speclines sl)
358 if (sl == NULL) return NULL;
359 for (i = 0; i < sl->sl_nlines; i++)
360 /*@-unqualifiedtrans@*/
361 sl->sl_lines[i] = _free(sl->sl_lines[i]);
362 /*@=unqualifiedtrans@*/
363 sl->sl_lines = _free(sl->sl_lines);
369 static inline /*@only@*/ /*@null@*/ spectags newSt(void)
373 st = xmalloc(sizeof(*st));
383 static inline /*@null@*/ spectags freeSt(/*@only@*/ /*@null@*/ spectags st)
386 if (st == NULL) return NULL;
387 for (i = 0; i < st->st_ntags; i++) {
388 spectag t = st->st_t + i;
389 t->t_lang = _free(t->t_lang);
390 t->t_msgid = _free(t->t_msgid);
392 st->st_t = _free(st->st_t);
398 Spec spec = xcalloc(1, sizeof(*spec));
400 spec->specFile = NULL;
401 spec->sourceRpmName = NULL;
406 spec->fileStack = NULL;
407 spec->lbuf[0] = '\0';
408 spec->line = spec->lbuf;
409 spec->nextline = NULL;
410 spec->nextpeekc = '\0';
412 spec->readStack = xcalloc(1, sizeof(*spec->readStack));
413 spec->readStack->next = NULL;
414 spec->readStack->reading = 1;
416 spec->rootURL = NULL;
419 spec->install = NULL;
422 spec->sources = NULL;
423 spec->packages = NULL;
425 spec->numSources = 0;
427 spec->sourceHeader = NULL;
429 spec->sourceCpioList = NULL;
431 spec->gotBuildRootURL = 0;
432 spec->buildRootURL = NULL;
433 spec->buildSubdir = NULL;
435 spec->passPhrase = NULL;
439 spec->buildRestrictions = headerNew();
440 spec->BANames = NULL;
443 spec->BASpecs = NULL;
448 spec->macros = &rpmGlobalMacroContext;
453 Spec freeSpec(Spec spec)
455 struct ReadLevelEntry *rl;
457 if (spec == NULL) return NULL;
459 spec->sl = freeSl(spec->sl);
460 spec->st = freeSt(spec->st);
462 spec->prep = freeStringBuf(spec->prep);
463 spec->build = freeStringBuf(spec->build);
464 spec->install = freeStringBuf(spec->install);
465 spec->clean = freeStringBuf(spec->clean);
467 spec->buildRootURL = _free(spec->buildRootURL);
468 spec->buildSubdir = _free(spec->buildSubdir);
469 spec->rootURL = _free(spec->rootURL);
470 spec->specFile = _free(spec->specFile);
471 spec->sourceRpmName = _free(spec->sourceRpmName);
474 { struct OpenFileInfo *ofi;
475 while (spec->fileStack) {
476 ofi = spec->fileStack;
477 spec->fileStack = ofi->next;
479 ofi->fileName = _free(ofi->fileName);
487 while (spec->readStack) {
488 rl = spec->readStack;
489 /*@-dependenttrans@*/
490 spec->readStack = rl->next;
491 /*@=dependenttrans@*/
496 spec->sourceHeader = headerFree(spec->sourceHeader);
498 if (spec->sourceCpioList) {
499 TFI_t fi = spec->sourceCpioList;
500 spec->sourceCpioList = NULL;
505 spec->buildRestrictions = headerFree(spec->buildRestrictions);
507 if (!spec->recursing) {
508 if (spec->BASpecs != NULL)
509 while (spec->BACount--) {
510 /*@-unqualifiedtrans@*/
511 spec->BASpecs[spec->BACount] =
512 freeSpec(spec->BASpecs[spec->BACount]);
513 /*@=unqualifiedtrans@*/
516 spec->BASpecs = _free(spec->BASpecs);
519 spec->BANames = _free(spec->BANames);
521 spec->passPhrase = _free(spec->passPhrase);
522 spec->cookie = _free(spec->cookie);
524 spec->sources = freeSources(spec->sources);
525 spec->packages = freePackages(spec->packages);
532 /*@only@*/ struct OpenFileInfo * newOpenFileInfo(void)
534 struct OpenFileInfo *ofi;
536 ofi = xmalloc(sizeof(struct OpenFileInfo));
538 ofi->fileName = NULL;
540 ofi->readBuf[0] = '\0';