3 * Handle spec data structure.
18 #define SKIPWHITE(_x) {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
19 #define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
21 /*@access Header @*/ /* compared with NULL */
22 /*@access rpmfi @*/ /* compared with NULL */
25 * @param p trigger entry chain
29 /*@null@*/ struct TriggerFileEntry * freeTriggerFiles(/*@only@*/ /*@null@*/ struct TriggerFileEntry * p)
32 struct TriggerFileEntry *o, *q = p;
37 o->fileName = _free(o->fileName);
38 o->script = _free(o->script);
39 o->prog = _free(o->prog);
46 * Destroy source component chain.
47 * @param s source component chain
51 /*@null@*/ struct Source * freeSources(/*@only@*/ /*@null@*/ struct Source * s)
54 struct Source *r, *t = s;
59 r->fullSource = _free(r->fullSource);
66 int lookupPackage(Spec spec, const char *name, int flag, /*@out@*/Package *pkg)
75 *pkg = spec->packages;
79 /* Construct package name */
81 if (flag == PART_SUBNAME) {
82 (void) headerNVR(spec->packages->header, &pname, NULL, NULL);
83 fullName = n = alloca(strlen(pname) + 1 + strlen(name) + 1);
84 while (*pname != '\0') *n++ = *pname++;
87 fullName = n = alloca(strlen(name)+1);
94 /* Locate package with fullName */
95 for (p = spec->packages; p != NULL; p = p->next) {
96 (void) headerNVR(p->header, &pname, NULL, NULL);
97 if (pname && (! strcmp(fullName, pname))) {
103 /*@-dependenttrans@*/ *pkg = p; /*@=dependenttrans@*/
104 return ((p == NULL) ? 1 : 0);
108 Package newPackage(Spec spec)
113 p = xcalloc(1, sizeof(*p));
115 p->header = headerNew();
124 p->triggerScripts = NULL;
127 p->triggerFiles = NULL;
135 p->postInFile = NULL;
137 p->postUnFile = NULL;
138 p->verifyFile = NULL;
140 p->specialDoc = NULL;
142 if (spec->packages == NULL) {
145 /* Always add package to end of list */
146 for (pp = spec->packages; pp->next != NULL; pp = pp->next)
155 Package freePackage(Package pkg)
157 if (pkg == NULL) return NULL;
159 pkg->preInFile = _free(pkg->preInFile);
160 pkg->postInFile = _free(pkg->postInFile);
161 pkg->preUnFile = _free(pkg->preUnFile);
162 pkg->postUnFile = _free(pkg->postUnFile);
163 pkg->verifyFile = _free(pkg->verifyFile);
165 pkg->header = headerFree(pkg->header);
166 pkg->fileList = freeStringBuf(pkg->fileList);
167 pkg->fileFile = _free(pkg->fileFile);
169 rpmfi fi = pkg->cpioList;
170 pkg->cpioList = NULL;
174 pkg->specialDoc = freeStringBuf(pkg->specialDoc);
175 pkg->icon = freeSources(pkg->icon);
176 pkg->triggerFiles = freeTriggerFiles(pkg->triggerFiles);
182 Package freePackages(Package packages)
186 while ((p = packages) != NULL) {
196 static inline /*@owned@*/ struct Source *findSource(Spec spec, int num, int flag)
201 for (p = spec->sources; p != NULL; p = p->next)
202 if ((num == p->num) && (p->flags & flag)) return p;
208 int parseNoSource(Spec spec, const char * field, int tag)
214 if (tag == RPMTAG_NOSOURCE) {
215 flag = RPMBUILD_ISSOURCE;
218 flag = RPMBUILD_ISPATCH;
223 for (f = fe; *f != '\0'; f = fe) {
231 if (*fe != '\0') fe++;
233 if (parseNum(f, &num)) {
234 rpmError(RPMERR_BADSPEC, _("line %d: Bad number: %s\n"),
236 return RPMERR_BADSPEC;
239 if (! (p = findSource(spec, num, flag))) {
240 rpmError(RPMERR_BADSPEC, _("line %d: Bad no%s number: %d\n"),
241 spec->lineNum, name, num);
242 return RPMERR_BADSPEC;
245 p->flags |= RPMBUILD_ISNO;
254 int addSource(Spec spec, Package pkg, const char *field, int tag)
260 const char *fieldp = NULL;
268 flag = RPMBUILD_ISSOURCE;
270 fieldp = spec->line + 6;
273 flag = RPMBUILD_ISPATCH;
275 fieldp = spec->line + 5;
278 flag = RPMBUILD_ISICON;
285 if (tag != RPMTAG_ICON) {
286 /* We already know that a ':' exists, and that there */
287 /* are no spaces before it. */
288 /* This also now allows for spaces and tabs between */
289 /* the number and the ':' */
292 while ((*fieldp != ':') && (*fieldp != ' ') && (*fieldp != '\t')) {
299 if (nump == NULL || *nump == '\0') {
302 if (parseNum(buf, &num)) {
303 rpmError(RPMERR_BADSPEC, _("line %d: Bad %s number: %s\n"),
304 spec->lineNum, name, spec->line);
305 return RPMERR_BADSPEC;
310 /* Create the entry and link it in */
311 p = xmalloc(sizeof(*p));
313 p->fullSource = xstrdup(field);
315 p->source = strrchr(p->fullSource, '/');
319 p->source = p->fullSource;
322 if (tag != RPMTAG_ICON) {
323 p->next = spec->sources;
332 if (tag != RPMTAG_ICON) {
333 /*@-nullpass@*/ /* LCL: varargs needs null annotate. */
334 const char *body = rpmGetPath("%{_sourcedir}/", p->source, NULL);
338 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
339 addMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
340 sprintf(buf, "%sURL%d",
341 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
342 addMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
352 static inline /*@only@*/ /*@null@*/ speclines newSl(void)
358 sl = xmalloc(sizeof(*sl));
370 static inline /*@null@*/ speclines freeSl(/*@only@*/ /*@null@*/ speclines sl)
374 if (sl == NULL) return NULL;
375 for (i = 0; i < sl->sl_nlines; i++)
376 /*@-unqualifiedtrans@*/
377 sl->sl_lines[i] = _free(sl->sl_lines[i]);
378 /*@=unqualifiedtrans@*/
379 sl->sl_lines = _free(sl->sl_lines);
386 static inline /*@only@*/ /*@null@*/ spectags newSt(void)
392 st = xmalloc(sizeof(*st));
403 static inline /*@null@*/ spectags freeSt(/*@only@*/ /*@null@*/ spectags st)
407 if (st == NULL) return NULL;
408 for (i = 0; i < st->st_ntags; i++) {
409 spectag t = st->st_t + i;
410 t->t_lang = _free(t->t_lang);
411 t->t_msgid = _free(t->t_msgid);
413 st->st_t = _free(st->st_t);
419 Spec spec = xcalloc(1, sizeof(*spec));
421 spec->specFile = NULL;
426 spec->fileStack = NULL;
428 spec->lbuf[0] = '\0';
430 spec->line = spec->lbuf;
431 spec->nextline = NULL;
432 spec->nextpeekc = '\0';
434 spec->readStack = xcalloc(1, sizeof(*spec->readStack));
435 spec->readStack->next = NULL;
436 spec->readStack->reading = 1;
438 spec->rootURL = NULL;
441 spec->install = NULL;
445 spec->sources = NULL;
446 spec->packages = NULL;
448 spec->numSources = 0;
450 spec->sourceRpmName = NULL;
451 spec->sourcePkgId = NULL;
452 spec->sourceHeader = NULL;
453 spec->sourceCpioList = NULL;
455 spec->gotBuildRootURL = 0;
456 spec->buildRootURL = NULL;
457 spec->buildSubdir = NULL;
459 spec->passPhrase = NULL;
463 spec->buildRestrictions = headerNew();
464 spec->BANames = NULL;
467 spec->BASpecs = NULL;
472 /*@i@*/ spec->macros = rpmGlobalMacroContext;
477 Spec freeSpec(Spec spec)
479 struct ReadLevelEntry *rl;
481 if (spec == NULL) return NULL;
483 spec->sl = freeSl(spec->sl);
484 spec->st = freeSt(spec->st);
486 spec->prep = freeStringBuf(spec->prep);
487 spec->build = freeStringBuf(spec->build);
488 spec->install = freeStringBuf(spec->install);
489 spec->check = freeStringBuf(spec->check);
490 spec->clean = freeStringBuf(spec->clean);
492 spec->buildRootURL = _free(spec->buildRootURL);
493 spec->buildSubdir = _free(spec->buildSubdir);
494 spec->rootURL = _free(spec->rootURL);
495 spec->specFile = _free(spec->specFile);
498 { struct OpenFileInfo *ofi;
499 while (spec->fileStack) {
500 ofi = spec->fileStack;
501 spec->fileStack = ofi->next;
503 ofi->fileName = _free(ofi->fileName);
511 while (spec->readStack) {
512 rl = spec->readStack;
513 /*@-dependenttrans@*/
514 spec->readStack = rl->next;
515 /*@=dependenttrans@*/
520 spec->sourceRpmName = _free(spec->sourceRpmName);
521 spec->sourcePkgId = _free(spec->sourcePkgId);
522 spec->sourceHeader = headerFree(spec->sourceHeader);
524 if (spec->sourceCpioList) {
525 rpmfi fi = spec->sourceCpioList;
526 spec->sourceCpioList = NULL;
530 spec->buildRestrictions = headerFree(spec->buildRestrictions);
532 if (!spec->recursing) {
534 if (spec->BASpecs != NULL)
535 while (spec->BACount--) {
536 /*@-unqualifiedtrans@*/
537 spec->BASpecs[spec->BACount] =
538 freeSpec(spec->BASpecs[spec->BACount]);
539 /*@=unqualifiedtrans@*/
543 spec->BASpecs = _free(spec->BASpecs);
546 spec->BANames = _free(spec->BANames);
548 spec->passPhrase = _free(spec->passPhrase);
549 spec->cookie = _free(spec->cookie);
551 spec->sources = freeSources(spec->sources);
552 spec->packages = freePackages(spec->packages);
560 struct OpenFileInfo * newOpenFileInfo(void)
562 struct OpenFileInfo *ofi;
564 ofi = xmalloc(sizeof(*ofi));
566 ofi->fileName = NULL;
569 ofi->readBuf[0] = '\0';
578 * Print copy of spec file, filling in Group/Description/Summary from specspo.
579 * @param spec spec file control structure
582 printNewSpecfile(Spec spec)
583 /*@globals fileSystem @*/
584 /*@modifies spec->sl->sl_lines[], fileSystem @*/
587 speclines sl = spec->sl;
588 spectags st = spec->st;
589 const char * msgstr = NULL;
592 if (sl == NULL || st == NULL)
596 for (i = 0; i < st->st_ntags; i++) {
597 spectag t = st->st_t + i;
598 const char * tn = tagName(t->t_tag);
603 if (t->t_msgid == NULL)
604 h = spec->packages->header;
610 strcpy(fmt, t->t_msgid);
611 for (fe = fmt; *fe && *fe != '('; fe++)
613 if (*fe == '(') *fe = '\0';
616 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
619 (void) headerNVR(h, &pkgname, NULL, NULL);
620 if (!strcmp(pkgname, fmt))
621 /*@innerbreak@*/ break;
623 if (pkg == NULL || h == NULL)
624 h = spec->packages->header;
632 (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tn), "}");
634 msgstr = _free(msgstr);
636 /* XXX this should use queryHeader(), but prints out tn as well. */
637 msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
638 if (msgstr == NULL) {
639 rpmError(RPMERR_QFMT, _("can't query %s: %s\n"), tn, errstr);
647 /*@-unqualifiedtrans@*/
648 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
649 /*@=unqualifiedtrans@*/
650 if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
652 { char *buf = xmalloc(strlen(tn) + sizeof(": ") + strlen(msgstr));
653 (void) stpcpy( stpcpy( stpcpy(buf, tn), ": "), msgstr);
654 sl->sl_lines[t->t_startx] = buf;
656 /*@switchbreak@*/ break;
657 case RPMTAG_DESCRIPTION:
658 for (j = 1; j < t->t_nlines; j++) {
659 if (*sl->sl_lines[t->t_startx + j] == '%')
660 /*@innercontinue@*/ continue;
661 /*@-unqualifiedtrans@*/
662 sl->sl_lines[t->t_startx + j] =
663 _free(sl->sl_lines[t->t_startx + j]);
664 /*@=unqualifiedtrans@*/
666 if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
667 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
670 sl->sl_lines[t->t_startx + 1] = xstrdup(msgstr);
672 sl->sl_lines[t->t_startx + 2] = xstrdup("\n\n");
673 /*@switchbreak@*/ break;
678 msgstr = _free(msgstr);
681 for (i = 0; i < sl->sl_nlines; i++) {
682 const char * s = sl->sl_lines[i];
686 if (strchr(s, '\n') == NULL && s[strlen(s)-1] != '\n')
692 int rpmspecQuery(rpmts ts, QVA_t qva, const char * arg)
696 char * buildRoot = NULL;
698 char * passPhrase = "";
705 if (qva->qva_showPackage == NULL)
709 /*@-mods@*/ /* FIX: make spec abstract */
710 if (parseSpec(ts, arg, "/", buildRoot, recursing, passPhrase,
711 cookie, anyarch, force)
712 || (spec = rpmtsSetSpec(ts, NULL)) == NULL)
714 rpmError(RPMERR_QUERY,
715 _("query of specfile %s failed, can't parse\n"), arg);
723 printNewSpecfile(spec);
727 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next)
728 xx = qva->qva_showPackage(qva, ts, pkg->header);
731 spec = freeSpec(spec);