3 * Handle spec data structure.
18 #define SKIPSPACE(s) { while (*(s) && xisspace(*(s))) (s)++; }
19 #define SKIPWHITE(_x) {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
20 #define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
23 * @param p trigger entry chain
27 struct TriggerFileEntry * freeTriggerFiles(struct TriggerFileEntry * p)
29 struct TriggerFileEntry *o, *q = p;
34 o->fileName = _free(o->fileName);
35 o->script = _free(o->script);
36 o->prog = _free(o->prog);
43 * Destroy source component chain.
44 * @param s source component chain
48 struct Source * freeSources(struct Source * s)
50 struct Source *r, *t = s;
55 r->fullSource = _free(r->fullSource);
61 int lookupPackage(rpmSpec spec, const char *name, int flag,Package *pkg)
70 *pkg = spec->packages;
74 /* Construct package name */
76 if (flag == PART_SUBNAME) {
77 (void) headerNVR(spec->packages->header, &pname, NULL, NULL);
78 fullName = n = alloca(strlen(pname) + 1 + strlen(name) + 1);
79 while (*pname != '\0') *n++ = *pname++;
82 fullName = n = alloca(strlen(name)+1);
87 /* Locate package with fullName */
88 for (p = spec->packages; p != NULL; p = p->next) {
89 (void) headerNVR(p->header, &pname, NULL, NULL);
90 if (pname && (! strcmp(fullName, pname))) {
97 return ((p == NULL) ? 1 : 0);
100 Package newPackage(rpmSpec spec)
105 p = xcalloc(1, sizeof(*p));
107 p->header = headerNew();
117 p->triggerScripts = NULL;
120 p->triggerFiles = NULL;
128 p->postInFile = NULL;
130 p->postUnFile = NULL;
131 p->verifyFile = NULL;
133 p->specialDoc = NULL;
135 if (spec->packages == NULL) {
138 /* Always add package to end of list */
139 for (pp = spec->packages; pp->next != NULL; pp = pp->next)
148 Package freePackage(Package pkg)
150 if (pkg == NULL) return NULL;
152 pkg->preInFile = _free(pkg->preInFile);
153 pkg->postInFile = _free(pkg->postInFile);
154 pkg->preUnFile = _free(pkg->preUnFile);
155 pkg->postUnFile = _free(pkg->postUnFile);
156 pkg->verifyFile = _free(pkg->verifyFile);
158 pkg->header = headerFree(pkg->header);
159 pkg->ds = rpmdsFree(pkg->ds);
160 pkg->fileList = freeStringBuf(pkg->fileList);
161 pkg->fileFile = _free(pkg->fileFile);
163 rpmfi fi = pkg->cpioList;
164 pkg->cpioList = NULL;
168 pkg->specialDoc = freeStringBuf(pkg->specialDoc);
169 pkg->icon = freeSources(pkg->icon);
170 pkg->triggerFiles = freeTriggerFiles(pkg->triggerFiles);
176 Package freePackages(Package packages)
180 while ((p = packages) != NULL) {
190 static inline struct Source *findSource(rpmSpec spec, int num, int flag)
194 for (p = spec->sources; p != NULL; p = p->next)
195 if ((num == p->num) && (p->flags & flag)) return p;
200 int parseNoSource(rpmSpec spec, const char * field, int tag)
206 if (tag == RPMTAG_NOSOURCE) {
207 flag = RPMBUILD_ISSOURCE;
210 flag = RPMBUILD_ISPATCH;
215 for (f = fe; *f != '\0'; f = fe) {
223 if (*fe != '\0') fe++;
225 if (parseNum(f, &num)) {
226 rpmlog(RPMLOG_ERR, _("line %d: Bad number: %s\n"),
231 if (! (p = findSource(spec, num, flag))) {
232 rpmlog(RPMLOG_ERR, _("line %d: Bad no%s number: %d\n"),
233 spec->lineNum, name, num);
237 p->flags |= RPMBUILD_ISNO;
244 int addSource(rpmSpec spec, Package pkg, const char *field, int tag)
250 const char *fieldp = NULL;
257 flag = RPMBUILD_ISSOURCE;
259 fieldp = spec->line + 6;
262 flag = RPMBUILD_ISPATCH;
264 fieldp = spec->line + 5;
267 flag = RPMBUILD_ISICON;
273 if (tag != RPMTAG_ICON) {
274 /* We already know that a ':' exists, and that there */
275 /* are no spaces before it. */
276 /* This also now allows for spaces and tabs between */
277 /* the number and the ':' */
280 while ((*fieldp != ':') && (*fieldp != ' ') && (*fieldp != '\t')) {
287 if (nump == NULL || *nump == '\0') {
290 if (parseNum(buf, &num)) {
291 rpmlog(RPMLOG_ERR, _("line %d: Bad %s number: %s\n"),
292 spec->lineNum, name, spec->line);
298 /* Create the entry and link it in */
299 p = xmalloc(sizeof(*p));
301 p->fullSource = xstrdup(field);
303 p->source = strrchr(p->fullSource, '/');
307 p->source = p->fullSource;
310 if (tag != RPMTAG_ICON) {
311 p->next = spec->sources;
320 if (tag != RPMTAG_ICON) {
321 const char *body = rpmGetPath("%{_sourcedir}/", p->source, NULL);
324 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
325 addMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
326 sprintf(buf, "%sURL%d",
327 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
328 addMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
337 static inline speclines newSl(void)
341 sl = xmalloc(sizeof(*sl));
351 static inline speclines freeSl(speclines sl)
354 if (sl == NULL) return NULL;
355 for (i = 0; i < sl->sl_nlines; i++)
356 sl->sl_lines[i] = _free(sl->sl_lines[i]);
357 sl->sl_lines = _free(sl->sl_lines);
363 static inline spectags newSt(void)
367 st = xmalloc(sizeof(*st));
377 static inline spectags freeSt(spectags st)
380 if (st == NULL) return NULL;
381 for (i = 0; i < st->st_ntags; i++) {
382 spectag t = st->st_t + i;
383 t->t_lang = _free(t->t_lang);
384 t->t_msgid = _free(t->t_msgid);
386 st->st_t = _free(st->st_t);
390 rpmSpec newSpec(void)
392 rpmSpec spec = xcalloc(1, sizeof(*spec));
394 spec->specFile = NULL;
399 spec->fileStack = NULL;
400 spec->lbuf[0] = '\0';
401 spec->line = spec->lbuf;
402 spec->nextline = NULL;
403 spec->nextpeekc = '\0';
405 spec->readStack = xcalloc(1, sizeof(*spec->readStack));
406 spec->readStack->next = NULL;
407 spec->readStack->reading = 1;
409 spec->rootURL = NULL;
412 spec->install = NULL;
416 spec->sources = NULL;
417 spec->packages = NULL;
419 spec->numSources = 0;
421 spec->sourceRpmName = NULL;
422 spec->sourcePkgId = NULL;
423 spec->sourceHeader = NULL;
424 spec->sourceCpioList = NULL;
426 spec->gotBuildRootURL = 0;
427 spec->buildRootURL = NULL;
428 spec->buildSubdir = NULL;
430 spec->passPhrase = NULL;
434 spec->buildRestrictions = headerNew();
435 spec->BANames = NULL;
438 spec->BASpecs = NULL;
443 spec->macros = rpmGlobalMacroContext;
448 rpmSpec freeSpec(rpmSpec spec)
450 struct ReadLevelEntry *rl;
452 if (spec == NULL) return NULL;
454 spec->sl = freeSl(spec->sl);
455 spec->st = freeSt(spec->st);
457 spec->prep = freeStringBuf(spec->prep);
458 spec->build = freeStringBuf(spec->build);
459 spec->install = freeStringBuf(spec->install);
460 spec->check = freeStringBuf(spec->check);
461 spec->clean = freeStringBuf(spec->clean);
463 spec->buildRootURL = _free(spec->buildRootURL);
464 spec->buildSubdir = _free(spec->buildSubdir);
465 spec->rootURL = _free(spec->rootURL);
466 spec->specFile = _free(spec->specFile);
469 { struct OpenFileInfo *ofi;
470 while (spec->fileStack) {
471 ofi = spec->fileStack;
472 spec->fileStack = ofi->next;
474 ofi->fileName = _free(ofi->fileName);
482 while (spec->readStack) {
483 rl = spec->readStack;
484 spec->readStack = rl->next;
489 spec->sourceRpmName = _free(spec->sourceRpmName);
490 spec->sourcePkgId = _free(spec->sourcePkgId);
491 spec->sourceHeader = headerFree(spec->sourceHeader);
493 if (spec->sourceCpioList) {
494 rpmfi fi = spec->sourceCpioList;
495 spec->sourceCpioList = NULL;
499 spec->buildRestrictions = headerFree(spec->buildRestrictions);
501 if (!spec->recursing) {
502 if (spec->BASpecs != NULL)
503 while (spec->BACount--) {
504 spec->BASpecs[spec->BACount] =
505 freeSpec(spec->BASpecs[spec->BACount]);
507 spec->BASpecs = _free(spec->BASpecs);
509 spec->BANames = _free(spec->BANames);
511 spec->passPhrase = _free(spec->passPhrase);
512 spec->cookie = _free(spec->cookie);
514 spec->sources = freeSources(spec->sources);
515 spec->packages = freePackages(spec->packages);
522 struct OpenFileInfo * newOpenFileInfo(void)
524 struct OpenFileInfo *ofi;
526 ofi = xmalloc(sizeof(*ofi));
528 ofi->fileName = NULL;
530 ofi->readBuf[0] = '\0';
538 * Print copy of spec file, filling in Group/Description/Summary from specspo.
539 * @param spec spec file control structure
542 printNewSpecfile(rpmSpec spec)
545 speclines sl = spec->sl;
546 spectags st = spec->st;
547 const char * msgstr = NULL;
550 if (sl == NULL || st == NULL)
553 for (i = 0; i < st->st_ntags; i++) {
554 spectag t = st->st_t + i;
555 const char * tn = rpmTagGetName(t->t_tag);
560 if (t->t_msgid == NULL)
561 h = spec->packages->header;
566 strcpy(fmt, t->t_msgid);
567 for (fe = fmt; *fe && *fe != '('; fe++)
569 if (*fe == '(') *fe = '\0';
571 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
574 (void) headerNVR(h, &pkgname, NULL, NULL);
575 if (!strcmp(pkgname, fmt))
578 if (pkg == NULL || h == NULL)
579 h = spec->packages->header;
586 (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tn), "}");
587 msgstr = _free(msgstr);
589 /* XXX this should use queryHeader(), but prints out tn as well. */
590 msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
591 if (msgstr == NULL) {
592 rpmlog(RPMLOG_ERR, _("can't query %s: %s\n"), tn, errstr);
599 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
600 if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
602 { char *buf = xmalloc(strlen(tn) + sizeof(": ") + strlen(msgstr));
603 (void) stpcpy( stpcpy( stpcpy(buf, tn), ": "), msgstr);
604 sl->sl_lines[t->t_startx] = buf;
607 case RPMTAG_DESCRIPTION:
608 for (j = 1; j < t->t_nlines; j++) {
609 if (*sl->sl_lines[t->t_startx + j] == '%')
611 sl->sl_lines[t->t_startx + j] =
612 _free(sl->sl_lines[t->t_startx + j]);
614 if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
615 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
618 sl->sl_lines[t->t_startx + 1] = xstrdup(msgstr);
620 sl->sl_lines[t->t_startx + 2] = xstrdup("\n\n");
624 msgstr = _free(msgstr);
626 for (i = 0; i < sl->sl_nlines; i++) {
627 const char * s = sl->sl_lines[i];
631 if (strchr(s, '\n') == NULL && s[strlen(s)-1] != '\n')
636 int rpmspecQuery(rpmts ts, QVA_t qva, const char * arg)
640 char * buildRoot = NULL;
642 char * passPhrase = "";
649 if (qva->qva_showPackage == NULL)
652 /* FIX: make spec abstract */
653 if (parseSpec(ts, arg, "/", buildRoot, recursing, passPhrase,
654 cookie, anyarch, force)
655 || (spec = rpmtsSetSpec(ts, NULL)) == NULL)
658 _("query of specfile %s failed, can't parse\n"), arg);
664 printNewSpecfile(spec);
668 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next)
669 xx = qva->qva_showPackage(qva, ts, pkg->header);
672 spec = freeSpec(spec);