- Main Page
- Related Pages
- Modules
- Data Structures
- Files

# build/spec.c

Go to the documentation of this file.

    00001
    00006 #include "system.h"
    00007
    00008 #include <rpmio.h>
    00009 #include "buildio.h"
    00010 #include "rpmds.h"
    00011 #include "rpmfi.h"
    00012 #include "rpmts.h"
    00013
    00014 #include "debug.h"
    00015
    00016 /*@-redecl@*/
    00017 extern int specedit;
    00018 /*@=redecl@*/
    00019
    00020 #define SKIPWHITE(_x)   {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
    00021 #define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
    00022
    00023 /*@access Header @*/    /* compared with NULL */
    00024 /*@access rpmfi @*/     /* compared with NULL */
    00025
    00030 static inline
    00031 /*@null@*/ struct TriggerFileEntry * freeTriggerFiles(/*@only@*/ /*@null@*/ struct TriggerFileEntry * p)
    00032         /*@modifies p @*/
    00033 {
    00034     struct TriggerFileEntry *o, *q = p;
    00035
    00036     while (q != NULL) {
    00037         o = q;
    00038         q = q->next;
    00039         o->fileName = _free(o->fileName);
    00040         o->script = _free(o->script);
    00041         o->prog = _free(o->prog);
    00042         o = _free(o);
    00043     }
    00044     return NULL;
    00045 }
    00046
    00052 static inline
    00053 /*@null@*/ struct Source * freeSources(/*@only@*/ /*@null@*/ struct Source * s)
    00054         /*@modifies s @*/
    00055 {
    00056     struct Source *r, *t = s;
    00057
    00058     while (t != NULL) {
    00059         r = t;
    00060         t = t->next;
    00061         r->fullSource = _free(r->fullSource);
    00062         r = _free(r);
    00063     }
    00064     return NULL;
    00065 }
    00066
    00067 rpmRC lookupPackage(Spec spec, const char *name, int flag, /*@out@*/Package *pkg)
    00068 {
    00069     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00070     const char *fullName;
    00071     Package p;
    00072     int xx;
    00073
    00074     /* "main" package */
    00075     if (name == NULL) {
    00076         if (pkg)
    00077             *pkg = spec->packages;
    00078         return RPMRC_OK;
    00079     }
    00080
    00081     /* Construct package name */
    00082   { char *n;
    00083     if (flag == PART_SUBNAME) {
    00084         he->tag = RPMTAG_NAME;
    00085         xx = headerGet(spec->packages->header, he, 0);
    00086         fullName = n = alloca(strlen(he->p.str) + 1 + strlen(name) + 1);
    00087         n = stpcpy(n, he->p.str);
    00088         he->p.ptr = _free(he->p.ptr);
    00089         *n++ = '-';
    00090         *n = '\0';
    00091     } else {
    00092         fullName = n = alloca(strlen(name)+1);
    00093     }
    00094     /*@-mayaliasunique@*/
    00095     strcpy(n, name);
    00096     /*@=mayaliasunique@*/
    00097   }
    00098
    00099     /* Locate package with fullName */
    00100     for (p = spec->packages; p != NULL; p = p->next) {
    00101         he->tag = RPMTAG_NAME;
    00102         xx = headerGet(p->header, he, 0);
    00103         if (he->p.str && !strcmp(fullName, he->p.str)) {
    00104             he->p.ptr = _free(he->p.ptr);
    00105             break;
    00106         }
    00107         he->p.ptr = _free(he->p.ptr);
    00108     }
    00109
    00110     if (pkg)
    00111         /*@-dependenttrans@*/ *pkg = p; /*@=dependenttrans@*/
    00112     return ((p == NULL) ? RPMRC_FAIL : RPMRC_OK);
    00113 }
    00114
    00115 Package newPackage(Spec spec)
    00116 {
    00117     Package p;
    00118     Package pp;
    00119
    00120     p = xcalloc(1, sizeof(*p));
    00121
    00122     p->header = headerNew();
    00123     p->ds = NULL;
    00124
    00125     p->autoProv = ((_rpmbuildFlags & 0x1) != 0);
    00126     p->autoReq = ((_rpmbuildFlags & 0x2) != 0);
    00127
    00128 #if 0
    00129     p->reqProv = NULL;
    00130     p->triggers = NULL;
    00131     p->triggerScripts = NULL;
    00132 #endif
    00133
    00134     p->triggerFiles = NULL;
    00135
    00136     p->fileFile = NULL;
    00137     p->fileList = NULL;
    00138
    00139     p->cpioList = NULL;
    00140
    00141     p->preInFile = NULL;
    00142     p->postInFile = NULL;
    00143     p->preUnFile = NULL;
    00144     p->postUnFile = NULL;
    00145     p->verifyFile = NULL;
    00146     p->sanityCheckFile = NULL;
    00147
    00148     p->specialDoc = NULL;
    00149
    00150     if (spec->packages == NULL) {
    00151         spec->packages = p;
    00152     } else {
    00153         /* Always add package to end of list */
    00154         for (pp = spec->packages; pp->next != NULL; pp = pp->next)
    00155             {};
    00156         pp->next = p;
    00157     }
    00158     p->next = NULL;
    00159
    00160     return p;
    00161 }
    00162
    00163 Package freePackage(Package pkg)
    00164 {
    00165     if (pkg == NULL) return NULL;
    00166
    00167     pkg->preInFile = _free(pkg->preInFile);
    00168     pkg->postInFile = _free(pkg->postInFile);
    00169     pkg->preUnFile = _free(pkg->preUnFile);
    00170     pkg->postUnFile = _free(pkg->postUnFile);
    00171     pkg->verifyFile = _free(pkg->verifyFile);
    00172     pkg->sanityCheckFile = _free(pkg->sanityCheckFile);
    00173
    00174     pkg->header = headerFree(pkg->header);
    00175     pkg->ds = rpmdsFree(pkg->ds);
    00176     pkg->fileList = freeStringBuf(pkg->fileList);
    00177     pkg->fileFile = _free(pkg->fileFile);
    00178     if (pkg->cpioList) {
    00179         rpmfi fi = pkg->cpioList;
    00180         pkg->cpioList = NULL;
    00181         fi = rpmfiFree(fi);
    00182     }
    00183
    00184     pkg->specialDoc = freeStringBuf(pkg->specialDoc);
    00185     pkg->triggerFiles = freeTriggerFiles(pkg->triggerFiles);
    00186
    00187     pkg = _free(pkg);
    00188     return NULL;
    00189 }
    00190
    00191 Package freePackages(Package packages)
    00192 {
    00193     Package p;
    00194
    00195     while ((p = packages) != NULL) {
    00196         packages = p->next;
    00197         p->next = NULL;
    00198         p = freePackage(p);
    00199     }
    00200     return NULL;
    00201 }
    00202
    00205 static inline /*@owned@*/ struct Source *findSource(Spec spec, int num, int flag)
    00206         /*@*/
    00207 {
    00208     struct Source *p;
    00209
    00210     for (p = spec->sources; p != NULL; p = p->next)
    00211         if ((num == p->num) && (p->flags & flag)) return p;
    00212
    00213     return NULL;
    00214 }
    00215
    00218 int SpecSourceCount(Spec spec)
    00219 {
    00220     return spec->numSources;
    00221 }
    00222
    00225 SpecSource getSource(Spec spec, int num)
    00226     /* @ */
    00227 {
    00228     struct Source *p = spec->sources;
    00229     int i;
    00230
    00231     for (i = 0; i < num; i++)
    00232         if ((p = p->next) == NULL) return NULL;
    00233
    00234     return p;
    00235 }
    00236
    00239 const char * specSourceName(SpecSource source)
    00240 {
    00241     return source->source;
    00242 }
    00243
    00246 const char * specFullSourceName(SpecSource source)
    00247 {
    00248     return source->fullSource;
    00249 }
    00250
    00253 int specSourceNum(SpecSource source)
    00254 {
    00255     return source->num;
    00256 }
    00257
    00260 int specSourceFlags(SpecSource source)
    00261 {
    00262     return source->flags;
    00263 }
    00264
    00265 int parseNoSource(Spec spec, const char * field, int tag)
    00266 {
    00267     const char *f, *fe;
    00268     const char *name;
    00269     uint32_t num, flag;
    00270
    00271     if (tag == RPMTAG_NOSOURCE) {
    00272         flag = RPMFILE_SOURCE;
    00273         name = "source";
    00274     } else {
    00275         flag = RPMFILE_PATCH;
    00276         name = "patch";
    00277     }
    00278
    00279     fe = field;
    00280     for (f = fe; *f != '\0'; f = fe) {
    00281         struct Source *p;
    00282
    00283         SKIPWHITE(f);
    00284         if (*f == '\0')
    00285             break;
    00286         fe = f;
    00287         SKIPNONWHITE(fe);
    00288         if (*fe != '\0') fe++;
    00289
    00290         if (parseNum(f, &num)) {
    00291             rpmlog(RPMLOG_ERR, _("line %d: Bad number: %s\n"),
    00292                      spec->lineNum, f);
    00293             return RPMRC_FAIL;
    00294         }
    00295
    00296         if (! (p = findSource(spec, num, flag))) {
    00297             rpmlog(RPMLOG_ERR, _("line %d: Bad no%s number: %d\n"),
    00298                      spec->lineNum, name, num);
    00299             return RPMRC_FAIL;
    00300         }
    00301
    00302         p->flags |= RPMFILE_GHOST;
    00303
    00304     }
    00305
    00306     return 0;
    00307 }
    00308
    00309 int addSource(Spec spec, /*@unused@*/ Package pkg, const char *field, int tag)
    00310 {
    00311     struct Source *p;
    00312     int flag = 0;
    00313     const char *name = NULL;
    00314     const char *mdir = NULL;
    00315     char *nump;
    00316     const char *fieldp = NULL;
    00317     char buf[BUFSIZ];
    00318     uint32_t num = 0;
    00319
    00320     buf[0] = '\0';
    00321     switch (tag) {
    00322     case RPMTAG_SOURCE:
    00323         flag = RPMFILE_SOURCE;
    00324         name = "source";
    00325         fieldp = spec->line + (sizeof("Source")-1);
    00326         break;
    00327     case RPMTAG_PATCH:
    00328         flag = RPMFILE_PATCH;
    00329         name = "patch";
    00330         fieldp = spec->line + (sizeof("Patch")-1);
    00331         break;
    00332     case RPMTAG_ICON:
    00333         flag = RPMFILE_ICON;
    00334         name = "icon";
    00335         fieldp = NULL;
    00336         break;
    00337     default:
    00338 assert(0);
    00339         /*@notreached@*/ break;
    00340     }
    00341 #if !defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
    00342     mdir = getSourceDir(flag);
    00343 assert(mdir != NULL);
    00344 #endif
    00345
    00346     /* Get the number */
    00347     if (fieldp != NULL) {
    00348         /* We already know that a ':' exists, and that there */
    00349         /* are no spaces before it.                          */
    00350         /* This also now allows for spaces and tabs between  */
    00351         /* the number and the ':'                            */
    00352
    00353         nump = buf;
    00354         while ((*fieldp != ':') && (*fieldp != ' ') && (*fieldp != '\t'))
    00355             *nump++ = *fieldp++;
    00356         *nump = '\0';
    00357
    00358         nump = buf;
    00359         SKIPSPACE(nump);
    00360         if (nump == NULL || *nump == '\0')
    00361             num = 0;
    00362         else if (parseNum(buf, &num)) {
    00363             rpmlog(RPMLOG_ERR, _("line %d: Bad %s number: %s\n"),
    00364                          spec->lineNum, name, spec->line);
    00365             return RPMRC_FAIL;
    00366         }
    00367     }
    00368
    00369     /* Create the entry and link it in */
    00370     p = xmalloc(sizeof(*p));
    00371     p->num = num;
    00372     p->fullSource = xstrdup(field);
    00373     p->flags = flag;
    00374     p->source = strrchr(p->fullSource, '/');
    00375     if (p->source)
    00376         p->source++;
    00377     else
    00378         p->source = p->fullSource;
    00379
    00380     p->next = spec->sources;
    00381     spec->sources = p;
    00382
    00383     spec->numSources++;
    00384
    00385     /* XXX FIXME: need to add ICON* macros. */
    00386 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
    00387     mdir = getSourceDir(flag, p->source);
    00388 #endif
    00389     if (tag != RPMTAG_ICON) {
    00390         const char *body = rpmGenPath(NULL, mdir, p->source);
    00391
    00392         sprintf(buf, "%s%d",
    00393                 (flag & RPMFILE_PATCH) ? "PATCH" : "SOURCE", num);
    00394         addMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
    00395         sprintf(buf, "%sURL%d",
    00396                 (flag & RPMFILE_PATCH) ? "PATCH" : "SOURCE", num);
    00397         addMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
    00398         body = _free(body);
    00399     }
    00400
    00401     return 0;
    00402 }
    00403
    00406 static inline /*@only@*/ /*@null@*/ speclines newSl(void)
    00407         /*@*/
    00408 {
    00409     speclines sl = NULL;
    00410     if (specedit) {
    00411         sl = xmalloc(sizeof(*sl));
    00412         sl->sl_lines = NULL;
    00413         sl->sl_nalloc = 0;
    00414         sl->sl_nlines = 0;
    00415     }
    00416     return sl;
    00417 }
    00418
    00421 static inline /*@null@*/ speclines freeSl(/*@only@*/ /*@null@*/ speclines sl)
    00422         /*@modifies sl @*/
    00423 {
    00424     int i;
    00425     if (sl == NULL) return NULL;
    00426     for (i = 0; i < sl->sl_nlines; i++)
    00427         /*@-unqualifiedtrans@*/
    00428         sl->sl_lines[i] = _free(sl->sl_lines[i]);
    00429         /*@=unqualifiedtrans@*/
    00430     sl->sl_lines = _free(sl->sl_lines);
    00431     return _free(sl);
    00432 }
    00433
    00436 static inline /*@only@*/ /*@null@*/ spectags newSt(void)
    00437         /*@*/
    00438 {
    00439     spectags st = NULL;
    00440     if (specedit) {
    00441         st = xmalloc(sizeof(*st));
    00442         st->st_t = NULL;
    00443         st->st_nalloc = 0;
    00444         st->st_ntags = 0;
    00445     }
    00446     return st;
    00447 }
    00448
    00451 static inline /*@null@*/ spectags freeSt(/*@only@*/ /*@null@*/ spectags st)
    00452         /*@modifies st @*/
    00453 {
    00454     int i;
    00455     if (st == NULL) return NULL;
    00456     for (i = 0; i < st->st_ntags; i++) {
    00457         spectag t = st->st_t + i;
    00458         t->t_lang = _free(t->t_lang);
    00459         t->t_msgid = _free(t->t_msgid);
    00460     }
    00461     st->st_t = _free(st->st_t);
    00462     return _free(st);
    00463 }
    00464
    00465 Spec newSpec(void)
    00466 {
    00467     Spec spec = xcalloc(1, sizeof(*spec));
    00468
    00469     spec->specFile = NULL;
    00470
    00471     spec->sl = newSl();
    00472     spec->st = newSt();
    00473
    00474     spec->fileStack = NULL;
    00475     spec->lbuf_len = (size_t)rpmExpandNumeric("%{?_spec_line_buffer_size}%{!?_spec_line_buffer_size:100000}");
    00476     spec->lbuf = (char *)xcalloc(1, spec->lbuf_len);
    00477     spec->line = spec->lbuf;
    00478     spec->nextline = NULL;
    00479     spec->nextpeekc = '\0';
    00480     spec->lineNum = 0;
    00481     spec->readStack = xcalloc(1, sizeof(*spec->readStack));
    00482     spec->readStack->next = NULL;
    00483     spec->readStack->reading = 1;
    00484
    00485     spec->rootURL = NULL;
    00486     spec->prep = NULL;
    00487     spec->build = NULL;
    00488     spec->install = NULL;
    00489     spec->check = NULL;
    00490     spec->clean = NULL;
    00491     spec->foo = NULL;
    00492     spec->nfoo = 0;
    00493
    00494     spec->sources = NULL;
    00495     spec->packages = NULL;
    00496     spec->noSource = 0;
    00497     spec->numSources = 0;
    00498
    00499     spec->sourceRpmName = NULL;
    00500     spec->sourcePkgId = NULL;
    00501     spec->sourceHeader = headerNew();
    00502     spec->sourceCpioList = NULL;
    00503
    00504     spec->buildSubdir = NULL;
    00505
    00506     spec->passPhrase = NULL;
    00507     spec->timeCheck = 0;
    00508     spec->cookie = NULL;
    00509
    00510     spec->BANames = NULL;
    00511     spec->BACount = 0;
    00512     spec->recursing = 0;
    00513     spec->BASpecs = NULL;
    00514
    00515     spec->force = 0;
    00516     spec->anyarch = 0;
    00517
    00518 /*@i@*/ spec->macros = rpmGlobalMacroContext;
    00519
    00520     spec->_parseRCPOT = parseRCPOT;     /* XXX hack around backward linkage. */
    00521
    00522     return spec;
    00523 }
    00524
    00525 Spec freeSpec(Spec spec)
    00526 {
    00527     struct ReadLevelEntry *rl;
    00528
    00529     if (spec == NULL) return NULL;
    00530
    00531     spec->lbuf = _free(spec->lbuf);
    00532
    00533     spec->sl = freeSl(spec->sl);
    00534     spec->st = freeSt(spec->st);
    00535
    00536     spec->prep = freeStringBuf(spec->prep);
    00537     spec->build = freeStringBuf(spec->build);
    00538     spec->install = freeStringBuf(spec->install);
    00539     spec->check = freeStringBuf(spec->check);
    00540     spec->clean = freeStringBuf(spec->clean);
    00541     spec->foo = tagStoreFree(spec->foo, spec->nfoo);
    00542     spec->nfoo = 0;
    00543
    00544     spec->buildSubdir = _free(spec->buildSubdir);
    00545     spec->rootURL = _free(spec->rootURL);
    00546     spec->specFile = _free(spec->specFile);
    00547
    00548 #ifdef  DEAD
    00549   { struct OpenFileInfo *ofi;
    00550     while (spec->fileStack) {
    00551         ofi = spec->fileStack;
    00552         spec->fileStack = ofi->next;
    00553         ofi->next = NULL;
    00554         ofi->fileName = _free(ofi->fileName);
    00555         ofi = _free(ofi);
    00556     }
    00557   }
    00558 #else
    00559     closeSpec(spec);
    00560 #endif
    00561
    00562     while (spec->readStack) {
    00563         rl = spec->readStack;
    00564         /*@-dependenttrans@*/
    00565         spec->readStack = rl->next;
    00566         /*@=dependenttrans@*/
    00567         rl->next = NULL;
    00568         rl = _free(rl);
    00569     }
    00570
    00571     spec->sourceRpmName = _free(spec->sourceRpmName);
    00572     spec->sourcePkgId = _free(spec->sourcePkgId);
    00573     spec->sourceHeader = headerFree(spec->sourceHeader);
    00574
    00575     if (spec->sourceCpioList) {
    00576         rpmfi fi = spec->sourceCpioList;
    00577         spec->sourceCpioList = NULL;
    00578         fi = rpmfiFree(fi);
    00579     }
    00580
    00581     if (!spec->recursing) {
    00582         if (spec->BASpecs != NULL)
    00583         while (spec->BACount--) {
    00584             /*@-unqualifiedtrans@*/
    00585             spec->BASpecs[spec->BACount] =
    00586                         freeSpec(spec->BASpecs[spec->BACount]);
    00587             /*@=unqualifiedtrans@*/
    00588         }
    00589         /*@-compdef@*/
    00590         spec->BASpecs = _free(spec->BASpecs);
    00591         /*@=compdef@*/
    00592     }
    00593     spec->BANames = _free(spec->BANames);
    00594
    00595     spec->passPhrase = _free(spec->passPhrase);
    00596     spec->cookie = _free(spec->cookie);
    00597
    00598     spec->sources = freeSources(spec->sources);
    00599     spec->packages = freePackages(spec->packages);
    00600
    00601     spec = _free(spec);
    00602
    00603     return spec;
    00604 }
    00605
    00606 /*@only@*/
    00607 struct OpenFileInfo * newOpenFileInfo(void)
    00608 {
    00609     struct OpenFileInfo *ofi;
    00610
    00611     ofi = xmalloc(sizeof(*ofi));
    00612     ofi->fd = NULL;
    00613     ofi->fileName = NULL;
    00614     ofi->lineNum = 0;
    00615     ofi->readBuf[0] = '\0';
    00616     ofi->readPtr = NULL;
    00617     ofi->next = NULL;
    00618
    00619     return ofi;
    00620 }
    00621
    00626 static void
    00627 printNewSpecfile(Spec spec)
    00628         /*@globals fileSystem @*/
    00629         /*@modifies spec->sl->sl_lines[], spec->packages->header, fileSystem @*/
    00630 {
    00631     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00632     Header h;
    00633     speclines sl = spec->sl;
    00634     spectags st = spec->st;
    00635     const char * msgstr = NULL;
    00636     int i, j;
    00637     int xx;
    00638
    00639     if (sl == NULL || st == NULL)
    00640         return;
    00641
    00642     for (i = 0; i < st->st_ntags; i++) {
    00643         spectag t = st->st_t + i;
    00644         const char * tn = tagName(t->t_tag);
    00645         const char * errstr;
    00646         char fmt[1024];
    00647
    00648         fmt[0] = '\0';
    00649         if (t->t_msgid == NULL)
    00650             h = spec->packages->header;
    00651         else {
    00652             Package pkg;
    00653             char *fe;
    00654
    00655             strcpy(fmt, t->t_msgid);
    00656             for (fe = fmt; *fe && *fe != '('; fe++)
    00657                 {} ;
    00658             if (*fe == '(') *fe = '\0';
    00659             h = NULL;
    00660             for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
    00661                 h = pkg->header;
    00662                 he->tag = RPMTAG_NAME;
    00663                 xx = headerGet(h, he, 0);
    00664                 if (!strcmp(he->p.str, fmt)) {
    00665                     he->p.ptr = _free(he->p.ptr);
    00666                     /*@innerbreak@*/ break;
    00667                 }
    00668                 he->p.ptr = _free(he->p.ptr);
    00669             }
    00670             if (pkg == NULL || h == NULL)
    00671                 h = spec->packages->header;
    00672         }
    00673
    00674         if (h == NULL)
    00675             continue;
    00676
    00677         fmt[0] = '\0';
    00678         (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tn), "}");
    00679         msgstr = _free(msgstr);
    00680
    00681         /* XXX this should use queryHeader(), but prints out tn as well. */
    00682         msgstr = headerSprintf(h, fmt, NULL, rpmHeaderFormats, &errstr);
    00683         if (msgstr == NULL) {
    00684             rpmlog(RPMLOG_ERR, _("can't query %s: %s\n"), tn, errstr);
    00685             return;
    00686         }
    00687
    00688         switch(t->t_tag) {
    00689         case RPMTAG_SUMMARY:
    00690         case RPMTAG_GROUP:
    00691             /*@-unqualifiedtrans@*/
    00692             sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
    00693             /*@=unqualifiedtrans@*/
    00694             if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
    00695                 continue;
    00696             {   char *buf = xmalloc(strlen(tn) + sizeof(": ") + strlen(msgstr));
    00697                 (void) stpcpy( stpcpy( stpcpy(buf, tn), ": "), msgstr);
    00698                 sl->sl_lines[t->t_startx] = buf;
    00699             }
    00700             /*@switchbreak@*/ break;
    00701         case RPMTAG_DESCRIPTION:
    00702             for (j = 1; j < t->t_nlines; j++) {
    00703                 if (*sl->sl_lines[t->t_startx + j] == '%')
    00704                     /*@innercontinue@*/ continue;
    00705                 /*@-unqualifiedtrans@*/
    00706                 sl->sl_lines[t->t_startx + j] =
    00707                         _free(sl->sl_lines[t->t_startx + j]);
    00708                 /*@=unqualifiedtrans@*/
    00709             }
    00710             if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
    00711                 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
    00712                 continue;
    00713             }
    00714             sl->sl_lines[t->t_startx + 1] = xstrdup(msgstr);
    00715             if (t->t_nlines > 2)
    00716                 sl->sl_lines[t->t_startx + 2] = xstrdup("\n\n");
    00717             /*@switchbreak@*/ break;
    00718         }
    00719     }
    00720     msgstr = _free(msgstr);
    00721
    00722     for (i = 0; i < sl->sl_nlines; i++) {
    00723         const char * s = sl->sl_lines[i];
    00724         if (s == NULL)
    00725             continue;
    00726         printf("%s", s);
    00727         if (strchr(s, '\n') == NULL && s[strlen(s)-1] != '\n')
    00728             printf("\n");
    00729     }
    00730 }
    00731
    00740 static int _specQuery(rpmts ts, QVA_t qva, const char *specName,
    00741                 /*@null@*/ const char *target)
    00742         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
    00743         /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
    00744 {
    00745     Spec spec = NULL;
    00746     Package pkg;
    00747     int res = 1;        /* assume error */
    00748     int anyarch = (target == NULL) ? 1 : 0;
    00749     char * passPhrase = "";
    00750     int recursing = 0;
    00751     char *cookie = NULL;
    00752     int verify = 0;
    00753     int xx;
    00754
    00755     /*@-mods@*/ /* FIX: make spec abstract */
    00756     if (parseSpec(ts, specName, "/", recursing, passPhrase,
    00757                 cookie, anyarch, 1, verify)
    00758       || (spec = rpmtsSetSpec(ts, NULL)) == NULL)
    00759     {
    00760         rpmlog(RPMLOG_ERR,
    00761             _("query of specfile %s failed, can't parse\n"),
    00762             specName);
    00763         goto exit;
    00764     }
    00765     /*@=mods@*/
    00766
    00767     res = 0;
    00768     if (specedit) {
    00769         printNewSpecfile(spec);
    00770         goto exit;
    00771     }
    00772
    00773     switch (qva->qva_source) {
    00774     case RPMQV_SPECSRPM:
    00775         xx = initSourceHeader(spec, NULL);
    00776         xx = qva->qva_showPackage(qva, ts, spec->sourceHeader);
    00777         break;
    00778     default:
    00779     case RPMQV_SPECFILE:
    00780         for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
    00781             /* If no target was specified, display all packages.
    00782              * Packages with empty file lists are not produced.
    00783              */
    00784             /* XXX DIEDIEDIE: this logic looks flawed. */
    00785             if (target == NULL || pkg->fileList != NULL)
    00786                 xx = qva->qva_showPackage(qva, ts, pkg->header);
    00787         }
    00788         break;
    00789     }
    00790
    00791 exit:
    00792     spec = freeSpec(spec);
    00793     return res;
    00794 }
    00795
    00796 int rpmspecQuery(rpmts ts, QVA_t qva, const char * arg)
    00797 {
    00798     int res = 1;
    00799     const char * targets = rpmcliTargets;
    00800     char *target;
    00801     const char * t;
    00802     const char * te;
    00803     int nqueries = 0;
    00804
    00805     if (qva->qva_showPackage == NULL)
    00806         goto exit;
    00807
    00808     if (targets == NULL) {
    00809         res = _specQuery(ts, qva, arg, NULL);
    00810         nqueries++;
    00811         goto exit;
    00812     }
    00813
    00814     rpmlog(RPMLOG_DEBUG,
    00815         _("Query specfile for platform(s): %s\n"), targets);
    00816     for (t = targets; *t != '\0'; t = te) {
    00817         /* Parse out next target platform. */
    00818         if ((te = strchr(t, ',')) == NULL)
    00819             te = t + strlen(t);
    00820         target = alloca(te-t+1);
    00821         strncpy(target, t, (te-t));
    00822         target[te-t] = '\0';
    00823         if (*te != '\0')
    00824             te++;
    00825
    00826         /* Query spec for this target platform. */
    00827         rpmlog(RPMLOG_DEBUG, _("    target platform: %s\n"), target);
    00828         /* Read in configuration for target. */
    00829         if (t != targets) {
    00830             rpmFreeMacros(NULL);
    00831             rpmFreeRpmrc();
    00832             (void) rpmReadConfigFiles(NULL, target);
    00833         }
    00834         res = _specQuery(ts, qva, arg, target);
    00835         nqueries++;
    00836         if (res) break;
    00837     }
    00838
    00839 exit:
    00840     /* Restore original configuration. */
    00841     if (nqueries > 1) {
    00842         t = targets;
    00843         if ((te = strchr(t, ',')) == NULL)
    00844             te = t + strlen(t);
    00845         target = alloca(te-t+1);
    00846         strncpy(target, t, (te-t));
    00847         target[te-t] = '\0';
    00848         if (*te != '\0')
    00849             te++;
    00850         rpmFreeMacros(NULL);
    00851         rpmFreeRpmrc();
    00852         (void) rpmReadConfigFiles(NULL, target);
    00853     }
    00854     return res;
    00855 }