# build/spec.c

Go to the documentation of this file.

    00001
    00006 #include "system.h"
    00007
    00008 #include "buildio.h"
    00009 #include "debug.h"
    00010
    00011 /*@-redecl@*/
    00012 extern int specedit;
    00013 /*@=redecl@*/
    00014
    00015 #define SKIPWHITE(_x)   {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
    00016 #define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
    00017
    00018 /*@access Header @*/    /* compared with NULL */
    00019
    00023 static inline
    00024 /*@null@*/ struct TriggerFileEntry * freeTriggerFiles(/*@only@*/ /*@null@*/ struct TriggerFileEntry * p)
    00025         /*@modifies p @*/
    00026 {
    00027     struct TriggerFileEntry *o, *q = p;
    00028
    00029     while (q != NULL) {
    00030         o = q;
    00031         q = q->next;
    00032         o->fileName = _free(o->fileName);
    00033         o->script = _free(o->script);
    00034         o->prog = _free(o->prog);
    00035         o = _free(o);
    00036     }
    00037     return NULL;
    00038 }
    00039
    00045 static inline
    00046 /*@null@*/ struct Source * freeSources(/*@only@*/ /*@null@*/ struct Source * s)
    00047         /*@modifies s @*/
    00048 {
    00049     struct Source *r, *t = s;
    00050
    00051     while (t != NULL) {
    00052         r = t;
    00053         t = t->next;
    00054         r->fullSource = _free(r->fullSource);
    00055         r = _free(r);
    00056     }
    00057     return NULL;
    00058 }
    00059
    00060 int lookupPackage(Spec spec, const char *name, int flag, /*@out@*/Package *pkg)
    00061 {
    00062     const char *pname;
    00063     const char *fullName;
    00064     Package p;
    00065
    00066     /* "main" package */
    00067     if (name == NULL) {
    00068         if (pkg)
    00069             *pkg = spec->packages;
    00070         return 0;
    00071     }
    00072
    00073     /* Construct package name */
    00074   { char *n;
    00075     if (flag == PART_SUBNAME) {
    00076         (void) headerNVR(spec->packages->header, &pname, NULL, NULL);
    00077         fullName = n = alloca(strlen(pname) + 1 + strlen(name) + 1);
    00078         while (*pname != '\0') *n++ = *pname++;
    00079         *n++ = '-';
    00080     } else {
    00081         fullName = n = alloca(strlen(name)+1);
    00082     }
    00083     /*@-mayaliasunique@*/
    00084     strcpy(n, name);
    00085     /*@=mayaliasunique@*/
    00086   }
    00087
    00088     /* Locate package with fullName */
    00089     for (p = spec->packages; p != NULL; p = p->next) {
    00090         (void) headerNVR(p->header, &pname, NULL, NULL);
    00091         if (pname && (! strcmp(fullName, pname))) {
    00092             break;
    00093         }
    00094     }
    00095
    00096     if (pkg)
    00097         /*@-dependenttrans@*/ *pkg = p; /*@=dependenttrans@*/
    00098     return ((p == NULL) ? 1 : 0);
    00099 }
    00100
    00101 Package newPackage(Spec spec)
    00102 {
    00103     Package p;
    00104     Package pp;
    00105
    00106     p = xcalloc(1, sizeof(*p));
    00107
    00108     p->header = headerNew();
    00109     p->icon = NULL;
    00110
    00111     p->autoProv = 1;
    00112     p->autoReq = 1;
    00113
    00114 #if 0
    00115     p->reqProv = NULL;
    00116     p->triggers = NULL;
    00117     p->triggerScripts = NULL;
    00118 #endif
    00119
    00120     p->triggerFiles = NULL;
    00121
    00122     p->fileFile = NULL;
    00123     p->fileList = NULL;
    00124
    00125     p->cpioList = NULL;
    00126
    00127     p->preInFile = NULL;
    00128     p->postInFile = NULL;
    00129     p->preUnFile = NULL;
    00130     p->postUnFile = NULL;
    00131     p->verifyFile = NULL;
    00132
    00133     p->specialDoc = NULL;
    00134
    00135     if (spec->packages == NULL) {
    00136         spec->packages = p;
    00137     } else {
    00138         /* Always add package to end of list */
    00139         for (pp = spec->packages; pp->next != NULL; pp = pp->next)
    00140             {};
    00141         pp->next = p;
    00142     }
    00143     p->next = NULL;
    00144
    00145     return p;
    00146 }
    00147
    00148 Package freePackage(Package pkg)
    00149 {
    00150     if (pkg == NULL) return NULL;
    00151
    00152     pkg->preInFile = _free(pkg->preInFile);
    00153     pkg->postInFile = _free(pkg->postInFile);
    00154     pkg->preUnFile = _free(pkg->preUnFile);
    00155     pkg->postUnFile = _free(pkg->postUnFile);
    00156     pkg->verifyFile = _free(pkg->verifyFile);
    00157
    00158     pkg->header = headerFree(pkg->header);
    00159     pkg->fileList = freeStringBuf(pkg->fileList);
    00160     pkg->fileFile = _free(pkg->fileFile);
    00161     if (pkg->cpioList) {
    00162         TFI_t fi = pkg->cpioList;
    00163         pkg->cpioList = NULL;
    00164         freeFi(fi);
    00165         fi = _free(fi);
    00166     }
    00167
    00168     pkg->specialDoc = freeStringBuf(pkg->specialDoc);
    00169     pkg->icon = freeSources(pkg->icon);
    00170     pkg->triggerFiles = freeTriggerFiles(pkg->triggerFiles);
    00171
    00172     pkg = _free(pkg);
    00173     return NULL;
    00174 }
    00175
    00176 Package freePackages(Package packages)
    00177 {
    00178     Package p;
    00179
    00180     while ((p = packages) != NULL) {
    00181         packages = p->next;
    00182         p->next = NULL;
    00183         p = freePackage(p);
    00184     }
    00185     return NULL;
    00186 }
    00187
    00190 static inline /*@owned@*/ struct Source *findSource(Spec spec, int num, int flag)
    00191         /*@*/
    00192 {
    00193     struct Source *p;
    00194
    00195     for (p = spec->sources; p != NULL; p = p->next)
    00196         if ((num == p->num) && (p->flags & flag)) return p;
    00197
    00198     return NULL;
    00199 }
    00200
    00201 int parseNoSource(Spec spec, const char * field, int tag)
    00202 {
    00203     const char *f, *fe;
    00204     const char *name;
    00205     int num, flag;
    00206
    00207     if (tag == RPMTAG_NOSOURCE) {
    00208         flag = RPMBUILD_ISSOURCE;
    00209         name = "source";
    00210     } else {
    00211         flag = RPMBUILD_ISPATCH;
    00212         name = "patch";
    00213     }
    00214
    00215     fe = field;
    00216     for (f = fe; *f != '\0'; f = fe) {
    00217         struct Source *p;
    00218
    00219         SKIPWHITE(f);
    00220         if (*f == '\0')
    00221             break;
    00222         fe = f;
    00223         SKIPNONWHITE(fe);
    00224         if (*fe != '\0') fe++;
    00225
    00226         if (parseNum(f, &num)) {
    00227             rpmError(RPMERR_BADSPEC, _("line %d: Bad number: %s\n"),
    00228                      spec->lineNum, f);
    00229             return RPMERR_BADSPEC;
    00230         }
    00231
    00232         if (! (p = findSource(spec, num, flag))) {
    00233             rpmError(RPMERR_BADSPEC, _("line %d: Bad no%s number: %d\n"),
    00234                      spec->lineNum, name, num);
    00235             return RPMERR_BADSPEC;
    00236         }
    00237
    00238         p->flags |= RPMBUILD_ISNO;
    00239
    00240     }
    00241
    00242     return 0;
    00243 }
    00244
    00245 int addSource(Spec spec, Package pkg, const char *field, int tag)
    00246 {
    00247     struct Source *p;
    00248     int flag = 0;
    00249     char *name = NULL;
    00250     char *nump;
    00251     const char *fieldp = NULL;
    00252     char buf[BUFSIZ];
    00253     int num = 0;
    00254
    00255     buf[0] = '\0';
    00256     /*@-branchstate@*/
    00257     switch (tag) {
    00258       case RPMTAG_SOURCE:
    00259         flag = RPMBUILD_ISSOURCE;
    00260         name = "source";
    00261         fieldp = spec->line + 6;
    00262         break;
    00263       case RPMTAG_PATCH:
    00264         flag = RPMBUILD_ISPATCH;
    00265         name = "patch";
    00266         fieldp = spec->line + 5;
    00267         break;
    00268       case RPMTAG_ICON:
    00269         flag = RPMBUILD_ISICON;
    00270         fieldp = NULL;
    00271         break;
    00272     }
    00273     /*@=branchstate@*/
    00274
    00275     /* Get the number */
    00276     if (tag != RPMTAG_ICON) {
    00277         /* We already know that a ':' exists, and that there */
    00278         /* are no spaces before it.                          */
    00279         /* This also now allows for spaces and tabs between  */
    00280         /* the number and the ':'                            */
    00281
    00282         nump = buf;
    00283         while ((*fieldp != ':') && (*fieldp != ' ') && (*fieldp != '\t')) {
    00284             *nump++ = *fieldp++;
    00285         }
    00286         *nump = '\0';
    00287
    00288         nump = buf;
    00289         SKIPSPACE(nump);
    00290         if (nump == NULL || *nump == '\0') {
    00291             num = 0;
    00292         } else {
    00293             if (parseNum(buf, &num)) {
    00294                 rpmError(RPMERR_BADSPEC, _("line %d: Bad %s number: %s\n"),
    00295                          spec->lineNum, name, spec->line);
    00296                 return RPMERR_BADSPEC;
    00297             }
    00298         }
    00299     }
    00300
    00301     /* Create the entry and link it in */
    00302     p = xmalloc(sizeof(*p));
    00303     p->num = num;
    00304     p->fullSource = xstrdup(field);
    00305     p->flags = flag;
    00306     p->source = strrchr(p->fullSource, '/');
    00307     if (p->source) {
    00308         p->source++;
    00309     } else {
    00310         p->source = p->fullSource;
    00311     }
    00312
    00313     if (tag != RPMTAG_ICON) {
    00314         p->next = spec->sources;
    00315         spec->sources = p;
    00316     } else {
    00317         p->next = pkg->icon;
    00318         pkg->icon = p;
    00319     }
    00320
    00321     spec->numSources++;
    00322
    00323     if (tag != RPMTAG_ICON) {
    00324         /*@-nullpass@*/         /* LCL: varargs needs null annotate. */
    00325         const char *body = rpmGetPath("%{_sourcedir}/", p->source, NULL);
    00326         /*@=nullpass@*/
    00327
    00328         sprintf(buf, "%s%d",
    00329                 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
    00330         addMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
    00331         sprintf(buf, "%sURL%d",
    00332                 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
    00333         addMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
    00334         body = _free(body);
    00335     }
    00336
    00337     return 0;
    00338 }
    00339
    00342 static inline /*@only@*/ /*@null@*/ speclines newSl(void)
    00343         /*@*/
    00344 {
    00345     speclines sl = NULL;
    00346     /*@-branchstate@*/
    00347     if (specedit) {
    00348         sl = xmalloc(sizeof(*sl));
    00349         sl->sl_lines = NULL;
    00350         sl->sl_nalloc = 0;
    00351         sl->sl_nlines = 0;
    00352     }
    00353     /*@=branchstate@*/
    00354     return sl;
    00355 }
    00356
    00359 static inline /*@null@*/ speclines freeSl(/*@only@*/ /*@null@*/ speclines sl)
    00360         /*@modifies sl @*/
    00361 {
    00362     int i;
    00363     if (sl == NULL) return NULL;
    00364     for (i = 0; i < sl->sl_nlines; i++)
    00365         /*@-unqualifiedtrans@*/
    00366         sl->sl_lines[i] = _free(sl->sl_lines[i]);
    00367         /*@=unqualifiedtrans@*/
    00368     sl->sl_lines = _free(sl->sl_lines);
    00369     return _free(sl);
    00370 }
    00371
    00374 static inline /*@only@*/ /*@null@*/ spectags newSt(void)
    00375         /*@*/
    00376 {
    00377     spectags st = NULL;
    00378     /*@-branchstate@*/
    00379     if (specedit) {
    00380         st = xmalloc(sizeof(*st));
    00381         st->st_t = NULL;
    00382         st->st_nalloc = 0;
    00383         st->st_ntags = 0;
    00384     }
    00385     /*@=branchstate@*/
    00386     return st;
    00387 }
    00388
    00391 static inline /*@null@*/ spectags freeSt(/*@only@*/ /*@null@*/ spectags st)
    00392         /*@modifies st @*/
    00393 {
    00394     int i;
    00395     if (st == NULL) return NULL;
    00396     for (i = 0; i < st->st_ntags; i++) {
    00397         spectag t = st->st_t + i;
    00398         t->t_lang = _free(t->t_lang);
    00399         t->t_msgid = _free(t->t_msgid);
    00400     }
    00401     st->st_t = _free(st->st_t);
    00402     return _free(st);
    00403 }
    00404
    00405 Spec newSpec(void)
    00406 {
    00407     Spec spec = xcalloc(1, sizeof(*spec));
    00408
    00409     spec->specFile = NULL;
    00410     spec->sourceRpmName = NULL;
    00411
    00412     spec->sl = newSl();
    00413     spec->st = newSt();
    00414
    00415     spec->fileStack = NULL;
    00416     spec->lbuf[0] = '\0';
    00417     spec->line = spec->lbuf;
    00418     spec->nextline = NULL;
    00419     spec->nextpeekc = '\0';
    00420     spec->lineNum = 0;
    00421     spec->readStack = xcalloc(1, sizeof(*spec->readStack));
    00422     spec->readStack->next = NULL;
    00423     spec->readStack->reading = 1;
    00424
    00425     spec->rootURL = NULL;
    00426     spec->prep = NULL;
    00427     spec->build = NULL;
    00428     spec->install = NULL;
    00429     spec->clean = NULL;
    00430
    00431     spec->sources = NULL;
    00432     spec->packages = NULL;
    00433     spec->noSource = 0;
    00434     spec->numSources = 0;
    00435
    00436     spec->sourceHeader = NULL;
    00437
    00438     spec->sourceCpioList = NULL;
    00439
    00440     spec->gotBuildRootURL = 0;
    00441     spec->buildRootURL = NULL;
    00442     spec->buildSubdir = NULL;
    00443
    00444     spec->passPhrase = NULL;
    00445     spec->timeCheck = 0;
    00446     spec->cookie = NULL;
    00447
    00448     spec->buildRestrictions = headerNew();
    00449     spec->BANames = NULL;
    00450     spec->BACount = 0;
    00451     spec->recursing = 0;
    00452     spec->BASpecs = NULL;
    00453
    00454     spec->force = 0;
    00455     spec->anyarch = 0;
    00456
    00457 /*@i@*/ spec->macros = rpmGlobalMacroContext;
    00458
    00459     return spec;
    00460 }
    00461
    00462 Spec freeSpec(Spec spec)
    00463 {
    00464     struct ReadLevelEntry *rl;
    00465
    00466     if (spec == NULL) return NULL;
    00467
    00468     spec->sl = freeSl(spec->sl);
    00469     spec->st = freeSt(spec->st);
    00470
    00471     spec->prep = freeStringBuf(spec->prep);
    00472     spec->build = freeStringBuf(spec->build);
    00473     spec->install = freeStringBuf(spec->install);
    00474     spec->clean = freeStringBuf(spec->clean);
    00475
    00476     spec->buildRootURL = _free(spec->buildRootURL);
    00477     spec->buildSubdir = _free(spec->buildSubdir);
    00478     spec->rootURL = _free(spec->rootURL);
    00479     spec->specFile = _free(spec->specFile);
    00480     spec->sourceRpmName = _free(spec->sourceRpmName);
    00481
    00482 #ifdef  DEAD
    00483   { struct OpenFileInfo *ofi;
    00484     while (spec->fileStack) {
    00485         ofi = spec->fileStack;
    00486         spec->fileStack = ofi->next;
    00487         ofi->next = NULL;
    00488         ofi->fileName = _free(ofi->fileName);
    00489         ofi = _free(ofi);
    00490     }
    00491   }
    00492 #else
    00493     closeSpec(spec);
    00494 #endif
    00495
    00496     while (spec->readStack) {
    00497         rl = spec->readStack;
    00498         /*@-dependenttrans@*/
    00499         spec->readStack = rl->next;
    00500         /*@=dependenttrans@*/
    00501         rl->next = NULL;
    00502         rl = _free(rl);
    00503     }
    00504
    00505     spec->sourceHeader = headerFree(spec->sourceHeader);
    00506
    00507     if (spec->sourceCpioList) {
    00508         TFI_t fi = spec->sourceCpioList;
    00509         spec->sourceCpioList = NULL;
    00510         freeFi(fi);
    00511         fi = _free(fi);
    00512     }
    00513
    00514     spec->buildRestrictions = headerFree(spec->buildRestrictions);
    00515
    00516     if (!spec->recursing) {
    00517         if (spec->BASpecs != NULL)
    00518         while (spec->BACount--) {
    00519             /*@-unqualifiedtrans@*/
    00520             spec->BASpecs[spec->BACount] =
    00521                         freeSpec(spec->BASpecs[spec->BACount]);
    00522             /*@=unqualifiedtrans@*/
    00523         }
    00524         /*@-compdef@*/
    00525         spec->BASpecs = _free(spec->BASpecs);
    00526         /*@=compdef@*/
    00527     }
    00528     spec->BANames = _free(spec->BANames);
    00529
    00530     spec->passPhrase = _free(spec->passPhrase);
    00531     spec->cookie = _free(spec->cookie);
    00532
    00533     spec->sources = freeSources(spec->sources);
    00534     spec->packages = freePackages(spec->packages);
    00535
    00536     spec = _free(spec);
    00537
    00538     return spec;
    00539 }
    00540
    00541 /*@only@*/ struct OpenFileInfo * newOpenFileInfo(void)
    00542 {
    00543     struct OpenFileInfo *ofi;
    00544
    00545     ofi = xmalloc(sizeof(*ofi));
    00546     ofi->fd = NULL;
    00547     ofi->fileName = NULL;
    00548     ofi->lineNum = 0;
    00549     ofi->readBuf[0] = '\0';
    00550     ofi->readPtr = NULL;
    00551     ofi->next = NULL;
    00552
    00553     return ofi;
    00554 }