00001
00005 static int _debug = 0;
00006
00007 #include "system.h"
00008 #include <stdarg.h>
00009
00010 #if !defined(isblank)
00011 #define isblank(_c) ((_c) == ' ' || (_c) == '\t')
00012 #endif
00013 #define iseol(_c) ((_c) == '\n' || (_c) == '\r')
00014
00015 #define STREQ(_t, _f, _fn) ((_fn) == (sizeof(_t)-1) && !strncmp((_t), (_f), (_fn)))
00016
00017 #ifdef DEBUG_MACROS
00018 #include <sys/types.h>
00019 #include <errno.h>
00020 #include <fcntl.h>
00021 #include <getopt.h>
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #define rpmError fprintf
00026 #define RPMERR_BADSPEC stderr
00027 #undef _
00028 #define _(x) x
00029
00030 #define vmefail() (exit(1), NULL)
00031 #define urlPath(_xr, _r) *(_r) = (_xr)
00032
00033 typedef FILE * FD_t;
00034 #define Fopen(_path, _fmode) fopen(_path, "r");
00035 #define Ferror ferror
00036 #define Fstrerror(_fd) strerror(errno)
00037 #define Fread fread
00038 #define Fclose fclose
00039
00040 #define fdGetFILE(_fd) (_fd)
00041
00042 #else
00043
00044 #include <rpmio_internal.h>
00045 #include <rpmmessages.h>
00046 #include <rpmerr.h>
00047
00048 #endif
00049
00050 #include <rpmmacro.h>
00051
00052 #include "debug.h"
00053
00054
00055
00056
00057
00058 struct MacroContext_s rpmGlobalMacroContext;
00059 struct MacroContext_s rpmCLIMacroContext;
00060
00064 typedef struct MacroBuf_s {
00065 const char * s;
00066 char * t;
00067 size_t nb;
00068 int depth;
00069 int macro_trace;
00070 int expand_trace;
00071 void * spec;
00072 MacroContext mc;
00073 } * MacroBuf;
00074
00075 #define SAVECHAR(_mb, _c) { *(_mb)->t = (_c), (_mb)->t++, (_mb)->nb--; }
00076
00077 static int expandMacro(MacroBuf mb)
00078 ;
00079
00080
00081 #define MAX_MACRO_DEPTH 16
00082 int max_macro_depth = MAX_MACRO_DEPTH;
00083
00084 #ifdef DEBUG_MACROS
00085 int print_macro_trace = 0;
00086 int print_expand_trace = 0;
00087 #else
00088 int print_macro_trace = 0;
00089 int print_expand_trace = 0;
00090 #endif
00091
00092
00093 #define MACRO_CHUNK_SIZE 16
00094
00100 static inline void *
00101 _free( const void * p)
00102
00103 {
00104 if (p != NULL) free((void *)p);
00105 return NULL;
00106 }
00107
00108
00109
00116 static int
00117 compareMacroName(const void * ap, const void * bp)
00118
00119 {
00120 MacroEntry ame = *((MacroEntry *)ap);
00121 MacroEntry bme = *((MacroEntry *)bp);
00122
00123 if (ame == NULL && bme == NULL)
00124 return 0;
00125 if (ame == NULL)
00126 return 1;
00127 if (bme == NULL)
00128 return -1;
00129 return strcmp(ame->name, bme->name);
00130 }
00131
00136 static void
00137 expandMacroTable(MacroContext mc)
00138
00139 {
00140 if (mc->macroTable == NULL) {
00141 mc->macrosAllocated = MACRO_CHUNK_SIZE;
00142 mc->macroTable = (MacroEntry *)
00143 xmalloc(sizeof(*(mc->macroTable)) * mc->macrosAllocated);
00144 mc->firstFree = 0;
00145 } else {
00146 mc->macrosAllocated += MACRO_CHUNK_SIZE;
00147 mc->macroTable = (MacroEntry *)
00148 xrealloc(mc->macroTable, sizeof(*(mc->macroTable)) *
00149 mc->macrosAllocated);
00150 }
00151 memset(&mc->macroTable[mc->firstFree], 0, MACRO_CHUNK_SIZE * sizeof(*(mc->macroTable)));
00152 }
00153
00158 static void
00159 sortMacroTable(MacroContext mc)
00160
00161 {
00162 int i;
00163
00164 if (mc == NULL || mc->macroTable == NULL)
00165 return;
00166
00167 qsort(mc->macroTable, mc->firstFree, sizeof(*(mc->macroTable)),
00168 compareMacroName);
00169
00170
00171 for (i = 0; i < mc->firstFree; i++) {
00172 if (mc->macroTable[i] != NULL)
00173 continue;
00174 mc->firstFree = i;
00175 break;
00176 }
00177 }
00178
00179 void
00180 rpmDumpMacroTable(MacroContext mc, FILE * fp)
00181 {
00182 int nempty = 0;
00183 int nactive = 0;
00184
00185 if (mc == NULL) mc = &rpmGlobalMacroContext;
00186 if (fp == NULL) fp = stderr;
00187
00188 fprintf(fp, "========================\n");
00189 if (mc->macroTable != NULL) {
00190 int i;
00191 for (i = 0; i < mc->firstFree; i++) {
00192 MacroEntry me;
00193 if ((me = mc->macroTable[i]) == NULL) {
00194
00195 nempty++;
00196 continue;
00197 }
00198 fprintf(fp, "%3d%c %s", me->level,
00199 (me->used > 0 ? '=' : ':'), me->name);
00200 if (me->opts && *me->opts)
00201 fprintf(fp, "(%s)", me->opts);
00202 if (me->body && *me->body)
00203 fprintf(fp, "\t%s", me->body);
00204 fprintf(fp, "\n");
00205 nactive++;
00206 }
00207 }
00208 fprintf(fp, _("======================== active %d empty %d\n"),
00209 nactive, nempty);
00210 }
00211
00219 static MacroEntry *
00220 findEntry(MacroContext mc, const char * name, size_t namelen)
00221
00222 {
00223 MacroEntry key, *ret;
00224 struct MacroEntry_s keybuf;
00225 char namebuf[1024];
00226
00227 if (mc == NULL) mc = &rpmGlobalMacroContext;
00228 if (mc->macroTable == NULL || mc->firstFree == 0)
00229 return NULL;
00230
00231 if (namelen > 0) {
00232 strncpy(namebuf, name, namelen);
00233 namebuf[namelen] = '\0';
00234 name = namebuf;
00235 }
00236
00237 key = &keybuf;
00238 memset(key, 0, sizeof(*key));
00239
00240 key->name = (char *)name;
00241
00242 ret = (MacroEntry *) bsearch(&key, mc->macroTable, mc->firstFree,
00243 sizeof(*(mc->macroTable)), compareMacroName);
00244
00245 return ret;
00246 }
00247
00248
00249
00253 static char *
00254 rdcl(char * buf, size_t size, FD_t fd, int escapes)
00255
00256 {
00257 char *q = buf;
00258 size_t nb = 0;
00259 size_t nread = 0;
00260 FILE * f = fdGetFILE(fd);
00261
00262 *q = '\0';
00263 if (f != NULL)
00264 do {
00265
00266 if (fgets(q, size, f) == NULL)
00267 break;
00268 nb = strlen(q);
00269 nread += nb;
00270 for (q += nb - 1; nb > 0 && iseol(*q); q--)
00271 nb--;
00272 if (!(nb > 0 && *q == '\\')) {
00273 *(++q) = '\0';
00274 break;
00275 }
00276 if (escapes) {
00277 q++;
00278 nb++;
00279 }
00280 size -= nb;
00281 if (*q == '\r')
00282 *q = '\n';
00283 *(++q) = '\0';
00284 } while (size > 0);
00285 return (nread > 0 ? buf : NULL);
00286 }
00287
00295 static const char *
00296 matchchar(const char * p, char pl, char pr)
00297
00298 {
00299 int lvl = 0;
00300 char c;
00301
00302 while ((c = *p++) != '\0') {
00303 if (c == '\\') {
00304 p++;
00305 continue;
00306 }
00307 if (c == pr) {
00308 if (--lvl <= 0) return --p;
00309 } else if (c == pl)
00310 lvl++;
00311 }
00312 return (const char *)NULL;
00313 }
00314
00321 static void
00322 printMacro(MacroBuf mb, const char * s, const char * se)
00323
00324 {
00325 const char *senl;
00326 const char *ellipsis;
00327 int choplen;
00328
00329 if (s >= se) {
00330 fprintf(stderr, _("%3d>%*s(empty)"), mb->depth,
00331 (2 * mb->depth + 1), "");
00332 return;
00333 }
00334
00335 if (s[-1] == '{')
00336 s--;
00337
00338
00339 for (senl = se; *senl && !iseol(*senl); senl++)
00340 {};
00341
00342
00343 choplen = 61 - (2 * mb->depth);
00344 if ((senl - s) > choplen) {
00345 senl = s + choplen;
00346 ellipsis = "...";
00347 } else
00348 ellipsis = "";
00349
00350
00351 fprintf(stderr, "%3d>%*s%%%.*s^", mb->depth,
00352 (2 * mb->depth + 1), "", (int)(se - s), s);
00353 if (se[1] != '\0' && (senl - (se+1)) > 0)
00354 fprintf(stderr, "%-.*s%s", (int)(senl - (se+1)), se+1, ellipsis);
00355 fprintf(stderr, "\n");
00356 }
00357
00364 static void
00365 printExpansion(MacroBuf mb, const char * t, const char * te)
00366
00367 {
00368 const char *ellipsis;
00369 int choplen;
00370
00371 if (!(te > t)) {
00372 fprintf(stderr, _("%3d<%*s(empty)\n"), mb->depth, (2 * mb->depth + 1), "");
00373 return;
00374 }
00375
00376
00377 while (te > t && iseol(te[-1]))
00378 te--;
00379 ellipsis = "";
00380 if (mb->depth > 0) {
00381 const char *tenl;
00382
00383
00384 while ((tenl = strchr(t, '\n')) && tenl < te)
00385 t = ++tenl;
00386
00387
00388 choplen = 61 - (2 * mb->depth);
00389 if ((te - t) > choplen) {
00390 te = t + choplen;
00391 ellipsis = "...";
00392 }
00393 }
00394
00395 fprintf(stderr, "%3d<%*s", mb->depth, (2 * mb->depth + 1), "");
00396 if (te > t)
00397 fprintf(stderr, "%.*s%s", (int)(te - t), t, ellipsis);
00398 fprintf(stderr, "\n");
00399 }
00400
00401 #define SKIPBLANK(_s, _c) \
00402 while (((_c) = *(_s)) && isblank(_c)) \
00403 (_s)++;
00404
00405 #define SKIPNONBLANK(_s, _c) \
00406 while (((_c) = *(_s)) && !(isblank(_c) || iseol(_c))) \
00407 (_s)++;
00408
00409 #define COPYNAME(_ne, _s, _c) \
00410 { SKIPBLANK(_s,_c); \
00411 while(((_c) = *(_s)) && (xisalnum(_c) || (_c) == '_')) \
00412 *(_ne)++ = *(_s)++; \
00413 *(_ne) = '\0'; \
00414 }
00415
00416 #define COPYOPTS(_oe, _s, _c) \
00417 { while(((_c) = *(_s)) && (_c) != ')') \
00418 *(_oe)++ = *(_s)++; \
00419 *(_oe) = '\0'; \
00420 }
00421
00422 #define COPYBODY(_be, _s, _c) \
00423 { while(((_c) = *(_s)) && !iseol(_c)) { \
00424 if ((_c) == '\\') \
00425 (_s)++; \
00426 *(_be)++ = *(_s)++; \
00427 } \
00428 *(_be) = '\0'; \
00429 }
00430
00438 static int
00439 expandT(MacroBuf mb, const char * f, size_t flen)
00440
00441 {
00442 char *sbuf;
00443 const char *s = mb->s;
00444 int rc;
00445
00446 sbuf = alloca(flen + 1);
00447 memset(sbuf, 0, (flen + 1));
00448
00449 strncpy(sbuf, f, flen);
00450 sbuf[flen] = '\0';
00451 mb->s = sbuf;
00452 rc = expandMacro(mb);
00453 mb->s = s;
00454 return rc;
00455 }
00456
00457 #if 0
00458
00465 static int
00466 expandS(MacroBuf mb, char * tbuf, size_t tbuflen)
00467
00468 {
00469 const char *t = mb->t;
00470 size_t nb = mb->nb;
00471 int rc;
00472
00473 mb->t = tbuf;
00474 mb->nb = tbuflen;
00475 rc = expandMacro(mb);
00476 mb->t = t;
00477 mb->nb = nb;
00478 return rc;
00479 }
00480 #endif
00481
00489 static int
00490 expandU(MacroBuf mb, char * u, size_t ulen)
00491
00492 {
00493 const char *s = mb->s;
00494 char *t = mb->t;
00495 size_t nb = mb->nb;
00496 char *tbuf;
00497 int rc;
00498
00499 tbuf = alloca(ulen + 1);
00500 memset(tbuf, 0, (ulen + 1));
00501
00502
00503 mb->s = u;
00504
00505 mb->t = tbuf;
00506 mb->nb = ulen;
00507 rc = expandMacro(mb);
00508
00509 tbuf[ulen] = '\0';
00510 if (ulen > mb->nb)
00511 strncpy(u, tbuf, (ulen - mb->nb + 1));
00512
00513 mb->s = s;
00514 mb->t = t;
00515 mb->nb = nb;
00516
00517 return rc;
00518 }
00519
00527 static int
00528 doShellEscape(MacroBuf mb, const char * cmd, size_t clen)
00529
00530 {
00531 char pcmd[BUFSIZ];
00532 FILE *shf;
00533 int rc;
00534 int c;
00535
00536 strncpy(pcmd, cmd, clen);
00537 pcmd[clen] = '\0';
00538 rc = expandU(mb, pcmd, sizeof(pcmd));
00539 if (rc)
00540 return rc;
00541
00542 if ((shf = popen(pcmd, "r")) == NULL)
00543 return 1;
00544 while(mb->nb > 0 && (c = fgetc(shf)) != EOF)
00545 SAVECHAR(mb, c);
00546 (void) pclose(shf);
00547
00548
00549 while (iseol(mb->t[-1])) {
00550 *(mb->t--) = '\0';
00551 mb->nb++;
00552 }
00553 return 0;
00554 }
00555
00564 static const char *
00565 doDefine(MacroBuf mb, const char * se, int level, int expandbody)
00566
00567 {
00568 const char *s = se;
00569 char buf[BUFSIZ], *n = buf, *ne = n;
00570 char *o = NULL, *oe;
00571 char *b, *be;
00572 int c;
00573 int oc = ')';
00574
00575
00576 COPYNAME(ne, s, c);
00577
00578
00579 oe = ne + 1;
00580 if (*s == '(') {
00581 s++;
00582 o = oe;
00583 COPYOPTS(oe, s, oc);
00584 s++;
00585 }
00586
00587
00588 b = be = oe + 1;
00589 SKIPBLANK(s, c);
00590 if (c == '{') {
00591 if ((se = matchchar(s, c, '}')) == NULL) {
00592 rpmError(RPMERR_BADSPEC,
00593 _("Macro %%%s has unterminated body\n"), n);
00594 se = s;
00595 return se;
00596 }
00597 s++;
00598 strncpy(b, s, (se - s));
00599 b[se - s] = '\0';
00600 be += strlen(b);
00601 se++;
00602 s = se;
00603 } else {
00604 COPYBODY(be, s, c);
00605
00606
00607 while (--be >= b && (c = *be) && (isblank(c) || iseol(c)))
00608 {};
00609 *(++be) = '\0';
00610 }
00611
00612
00613 while (iseol(*s))
00614 s++;
00615 se = s;
00616
00617
00618 if (!((c = *n) && (xisalpha(c) || c == '_') && (ne - n) > 2)) {
00619 rpmError(RPMERR_BADSPEC,
00620 _("Macro %%%s has illegal name (%%define)\n"), n);
00621 return se;
00622 }
00623
00624
00625 if (o && oc != ')') {
00626 rpmError(RPMERR_BADSPEC, _("Macro %%%s has unterminated opts\n"), n);
00627 return se;
00628 }
00629
00630 if ((be - b) < 1) {
00631 rpmError(RPMERR_BADSPEC, _("Macro %%%s has empty body\n"), n);
00632 return se;
00633 }
00634
00635 if (expandbody && expandU(mb, b, (&buf[sizeof(buf)] - b))) {
00636 rpmError(RPMERR_BADSPEC, _("Macro %%%s failed to expand\n"), n);
00637 return se;
00638 }
00639
00640 addMacro(mb->mc, n, o, b, (level - 1));
00641
00642 return se;
00643 }
00644
00651 static const char *
00652 doUndefine(MacroContext mc, const char * se)
00653
00654 {
00655 const char *s = se;
00656 char buf[BUFSIZ], *n = buf, *ne = n;
00657 int c;
00658
00659 COPYNAME(ne, s, c);
00660
00661
00662 while (iseol(*s))
00663 s++;
00664 se = s;
00665
00666
00667 if (!((c = *n) && (xisalpha(c) || c == '_') && (ne - n) > 2)) {
00668 rpmError(RPMERR_BADSPEC,
00669 _("Macro %%%s has illegal name (%%undefine)\n"), n);
00670 return se;
00671 }
00672
00673 delMacro(mc, n);
00674
00675 return se;
00676 }
00677
00678 #ifdef DYING
00679 static void
00680 dumpME(const char * msg, MacroEntry me)
00681
00682 {
00683 if (msg)
00684 fprintf(stderr, "%s", msg);
00685 fprintf(stderr, "\tme %p", me);
00686 if (me)
00687 fprintf(stderr,"\tname %p(%s) prev %p",
00688 me->name, me->name, me->prev);
00689 fprintf(stderr, "\n");
00690 }
00691 #endif
00692
00701 static void
00702 pushMacro( MacroEntry * mep,
00703 const char * n, const char * o,
00704 const char * b, int level)
00705
00706 {
00707
00708 MacroEntry prev = (mep && *mep ? *mep : NULL);
00709
00710 MacroEntry me = (MacroEntry) xmalloc(sizeof(*me));
00711
00712
00713 me->prev = prev;
00714
00715 me->name = (prev ? prev->name : xstrdup(n));
00716 me->opts = (o ? xstrdup(o) : NULL);
00717 me->body = xstrdup(b ? b : "");
00718 me->used = 0;
00719 me->level = level;
00720 if (mep)
00721 *mep = me;
00722 else
00723 me = _free(me);
00724 }
00725
00730 static void
00731 popMacro(MacroEntry * mep)
00732
00733 {
00734 MacroEntry me = (*mep ? *mep : NULL);
00735
00736 if (me) {
00737
00738
00739 if ((*mep = me->prev) == NULL)
00740 me->name = _free(me->name);
00741 me->opts = _free(me->opts);
00742 me->body = _free(me->body);
00743 me = _free(me);
00744
00745 }
00746 }
00747
00752 static void
00753 freeArgs(MacroBuf mb)
00754
00755 {
00756 MacroContext mc = mb->mc;
00757 int ndeleted = 0;
00758 int i;
00759
00760 if (mc == NULL || mc->macroTable == NULL)
00761 return;
00762
00763
00764 for (i = 0; i < mc->firstFree; i++) {
00765 MacroEntry *mep, me;
00766 int skiptest = 0;
00767 mep = &mc->macroTable[i];
00768 me = *mep;
00769
00770 if (me == NULL)
00771 continue;
00772 if (me->level < mb->depth)
00773 continue;
00774 if (strlen(me->name) == 1 && strchr("#*0", *me->name)) {
00775 if (*me->name == '*' && me->used > 0)
00776 skiptest = 1;
00777 } else if (!skiptest && me->used <= 0) {
00778 #if NOTYET
00779 rpmError(RPMERR_BADSPEC,
00780 _("Macro %%%s (%s) was not used below level %d\n"),
00781 me->name, me->body, me->level);
00782 #endif
00783 }
00784 popMacro(mep);
00785 if (!(mep && *mep))
00786 ndeleted++;
00787 }
00788
00789
00790 if (ndeleted)
00791 sortMacroTable(mc);
00792 }
00793
00803 static const char *
00804 grabArgs(MacroBuf mb, const MacroEntry me, const char * se, char lastc)
00805
00806 {
00807 char buf[BUFSIZ], *b, *be;
00808 char aname[16];
00809 const char *opts, *o;
00810 int argc = 0;
00811 const char **argv;
00812 int c;
00813
00814
00815 buf[0] = '\0';
00816 b = be = stpcpy(buf, me->name);
00817
00818 addMacro(mb->mc, "0", NULL, buf, mb->depth);
00819
00820 argc = 1;
00821
00822
00823 *be++ = ' ';
00824 while ((c = *se++) != '\0' && c != lastc) {
00825 if (!isblank(c)) {
00826 *be++ = c;
00827 continue;
00828 }
00829
00830 if (be[-1] == ' ')
00831 continue;
00832
00833 *be++ = ' ';
00834 argc++;
00835 }
00836 if (c == '\0') se--;
00837 if (be[-1] != ' ')
00838 argc++, be++;
00839 be[-1] = '\0';
00840 if (*b == ' ') b++;
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851 addMacro(mb->mc, "**", NULL, b, mb->depth);
00852
00853 #ifdef NOTYET
00854
00855 expandU(mb, buf, sizeof(buf));
00856 #endif
00857
00858
00859 argv = (const char **) alloca((argc + 1) * sizeof(char *));
00860 be[-1] = ' ';
00861 be[0] = '\0';
00862 b = buf;
00863 for (c = 0; c < argc; c++) {
00864 argv[c] = b;
00865 b = strchr(b, ' ');
00866 *b++ = '\0';
00867 }
00868
00869 argv[argc] = NULL;
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886 #ifdef __GLIBC__
00887 optind = 1;
00888 #endif
00889
00890 opts = me->opts;
00891
00892
00893 while((c = getopt(argc, (char **)argv, opts)) != -1) {
00894 if (c == '?' || (o = strchr(opts, c)) == NULL) {
00895 rpmError(RPMERR_BADSPEC, _("Unknown option %c in %s(%s)\n"),
00896 (char)c, me->name, opts);
00897 return se;
00898 }
00899 *be++ = '-';
00900 *be++ = c;
00901
00902 if (o[1] == ':') {
00903
00904 *be++ = ' ';
00905 be = stpcpy(be, optarg);
00906 }
00907 *be++ = '\0';
00908 aname[0] = '-'; aname[1] = c; aname[2] = '\0';
00909 addMacro(mb->mc, aname, NULL, b, mb->depth);
00910 if (o[1] == ':') {
00911 aname[0] = '-'; aname[1] = c; aname[2] = '*'; aname[3] = '\0';
00912 addMacro(mb->mc, aname, NULL, optarg, mb->depth);
00913 }
00914 be = b;
00915 }
00916
00917
00918 sprintf(aname, "%d", (argc - optind));
00919 addMacro(mb->mc, "#", NULL, aname, mb->depth);
00920
00921
00922 if (be) {
00923 *be = '\0';
00924 for (c = optind; c < argc; c++) {
00925 sprintf(aname, "%d", (c - optind + 1));
00926 addMacro(mb->mc, aname, NULL, argv[c], mb->depth);
00927 *be++ = ' ';
00928 be = stpcpy(be, argv[c]);
00929 }
00930 }
00931
00932
00933 addMacro(mb->mc, "*", NULL, b, mb->depth);
00934
00935 return se;
00936 }
00937
00945 static void
00946 doOutput(MacroBuf mb, int waserror, const char * msg, size_t msglen)
00947
00948 {
00949 char buf[BUFSIZ];
00950
00951 strncpy(buf, msg, msglen);
00952 buf[msglen] = '\0';
00953 (void) expandU(mb, buf, sizeof(buf));
00954 if (waserror)
00955 rpmError(RPMERR_BADSPEC, "%s\n", buf);
00956 else
00957 fprintf(stderr, "%s", buf);
00958 }
00959
00969 static void
00970 doFoo(MacroBuf mb, int negate, const char * f, size_t fn,
00971 const char * g, size_t glen)
00972
00973 {
00974 char buf[BUFSIZ], *b = NULL, *be;
00975 int c;
00976
00977 buf[0] = '\0';
00978 if (g) {
00979 strncpy(buf, g, glen);
00980 buf[glen] = '\0';
00981 (void) expandU(mb, buf, sizeof(buf));
00982 }
00983 if (STREQ("basename", f, fn)) {
00984 if ((b = strrchr(buf, '/')) == NULL)
00985 b = buf;
00986 #if NOTYET
00987
00988 } else if (STREQ("dirname", f, fn)) {
00989 if ((b = strrchr(buf, '/')) != NULL)
00990 *b = '\0';
00991 b = buf;
00992 #endif
00993 } else if (STREQ("suffix", f, fn)) {
00994 if ((b = strrchr(buf, '.')) != NULL)
00995 b++;
00996 } else if (STREQ("expand", f, fn)) {
00997 b = buf;
00998 } else if (STREQ("verbose", f, fn)) {
00999 if (negate)
01000 b = (rpmIsVerbose() ? NULL : buf);
01001 else
01002 b = (rpmIsVerbose() ? buf : NULL);
01003 } else if (STREQ("url2path", f, fn) || STREQ("u2p", f, fn)) {
01004 (void)urlPath(buf, (const char **)&b);
01005 if (*b == '\0') b = "/";
01006 } else if (STREQ("uncompress", f, fn)) {
01007 rpmCompressedMagic compressed = COMPRESSED_OTHER;
01008 for (b = buf; (c = *b) && isblank(c);)
01009 b++;
01010 for (be = b; (c = *be) && !isblank(c);)
01011 be++;
01012 *be++ = '\0';
01013 #ifndef DEBUG_MACROS
01014 (void) isCompressed(b, &compressed);
01015 #endif
01016 switch(compressed) {
01017 default:
01018 case 0:
01019 sprintf(be, "%%_cat %s", b);
01020 break;
01021 case 1:
01022 sprintf(be, "%%_gzip -dc %s", b);
01023 break;
01024 case 2:
01025 sprintf(be, "%%_bzip2 %s", b);
01026 break;
01027 case 3:
01028 sprintf(be, "%%_unzip %s", b);
01029 break;
01030 }
01031 b = be;
01032 } else if (STREQ("S", f, fn)) {
01033 for (b = buf; (c = *b) && xisdigit(c);)
01034 b++;
01035 if (!c) {
01036 b++;
01037 sprintf(b, "%%SOURCE%s", buf);
01038 } else
01039 b = buf;
01040 } else if (STREQ("P", f, fn)) {
01041 for (b = buf; (c = *b) && xisdigit(c);)
01042 b++;
01043 if (!c) {
01044 b++;
01045 sprintf(b, "%%PATCH%s", buf);
01046 } else
01047 b = buf;
01048 } else if (STREQ("F", f, fn)) {
01049 b = buf + strlen(buf) + 1;
01050 sprintf(b, "file%s.file", buf);
01051 }
01052
01053 if (b) {
01054 (void) expandT(mb, b, strlen(b));
01055 }
01056 }
01057
01064 static int
01065 expandMacro(MacroBuf mb)
01066
01067 {
01068 MacroEntry *mep;
01069 MacroEntry me;
01070 const char *s = mb->s, *se;
01071 const char *f, *fe;
01072 const char *g, *ge;
01073 size_t fn, gn;
01074 char *t = mb->t;
01075 int c;
01076 int rc = 0;
01077 int negate;
01078 char grab;
01079 int chkexist;
01080
01081 if (++mb->depth > max_macro_depth) {
01082 rpmError(RPMERR_BADSPEC,
01083 _("Recursion depth(%d) greater than max(%d)\n"),
01084 mb->depth, max_macro_depth);
01085 mb->depth--;
01086 mb->expand_trace = 1;
01087 return 1;
01088 }
01089
01090 while (rc == 0 && mb->nb > 0 && (c = *s) != '\0') {
01091 s++;
01092
01093 switch(c) {
01094 case '%':
01095 if (*s != '%')
01096 break;
01097 s++;
01098
01099 default:
01100 SAVECHAR(mb, c);
01101 continue;
01102 break;
01103 }
01104
01105
01106 f = fe = NULL;
01107 g = ge = NULL;
01108 if (mb->depth > 1)
01109 t = mb->t;
01110 negate = 0;
01111 grab = '\0';
01112 chkexist = 0;
01113 switch ((c = *s)) {
01114 default:
01115 while (strchr("!?", *s) != NULL) {
01116 switch(*s++) {
01117 case '!':
01118 negate = ((negate + 1) % 2);
01119 break;
01120 case '?':
01121 chkexist++;
01122 break;
01123 }
01124 }
01125 f = se = s;
01126 if (*se == '-')
01127 se++;
01128 while((c = *se) && (xisalnum(c) || c == '_'))
01129 se++;
01130
01131 switch (*se) {
01132 case '*':
01133 se++;
01134 if (*se == '*') se++;
01135 break;
01136 case '#':
01137 se++;
01138 break;
01139 default:
01140 break;
01141 }
01142 fe = se;
01143
01144 if ((c = *fe) && isblank(c))
01145 grab = '\n';
01146 break;
01147 case '(':
01148 if ((se = matchchar(s, c, ')')) == NULL) {
01149 rpmError(RPMERR_BADSPEC,
01150 _("Unterminated %c: %s\n"), (char)c, s);
01151 rc = 1;
01152 continue;
01153 }
01154 if (mb->macro_trace)
01155 printMacro(mb, s, se+1);
01156
01157 s++;
01158 rc = doShellEscape(mb, s, (se - s));
01159 se++;
01160
01161 s = se;
01162 continue;
01163 break;
01164 case '{':
01165 if ((se = matchchar(s, c, '}')) == NULL) {
01166 rpmError(RPMERR_BADSPEC,
01167 _("Unterminated %c: %s\n"), (char)c, s);
01168 rc = 1;
01169 continue;
01170 }
01171 f = s+1;
01172 se++;
01173 while (strchr("!?", *f) != NULL) {
01174 switch(*f++) {
01175 case '!':
01176 negate = ((negate + 1) % 2);
01177 break;
01178 case '?':
01179 chkexist++;
01180 break;
01181 }
01182 }
01183 for (fe = f; (c = *fe) && !strchr(" :}", c);)
01184 fe++;
01185 switch (c) {
01186 case ':':
01187 g = fe + 1;
01188 ge = se - 1;
01189 break;
01190 case ' ':
01191 grab = se[-1];
01192 break;
01193 default:
01194 break;
01195 }
01196 break;
01197 }
01198
01199
01200 fn = (fe - f);
01201 gn = (ge - g);
01202 if ((fe - f) <= 0) {
01203
01204 c = '%';
01205 SAVECHAR(mb, c);
01206 #if 0
01207 rpmError(RPMERR_BADSPEC,
01208 _("A %% is followed by an unparseable macro\n"));
01209 #endif
01210 s = se;
01211 continue;
01212 }
01213
01214 if (mb->macro_trace)
01215 printMacro(mb, s, se);
01216
01217
01218 if (STREQ("global", f, fn)) {
01219 s = doDefine(mb, se, RMIL_GLOBAL, 1);
01220 continue;
01221 }
01222 if (STREQ("define", f, fn)) {
01223 s = doDefine(mb, se, mb->depth, 0);
01224 continue;
01225 }
01226 if (STREQ("undefine", f, fn)) {
01227 s = doUndefine(mb->mc, se);
01228 continue;
01229 }
01230
01231 if (STREQ("echo", f, fn) ||
01232 STREQ("warn", f, fn) ||
01233 STREQ("error", f, fn)) {
01234 int waserror = 0;
01235 if (STREQ("error", f, fn))
01236 waserror = 1;
01237 if (g < ge)
01238 doOutput(mb, waserror, g, gn);
01239 else
01240 doOutput(mb, waserror, f, fn);
01241 s = se;
01242 continue;
01243 }
01244
01245 if (STREQ("trace", f, fn)) {
01246
01247 mb->expand_trace = mb->macro_trace = (negate ? 0 : mb->depth);
01248 if (mb->depth == 1) {
01249 print_macro_trace = mb->macro_trace;
01250 print_expand_trace = mb->expand_trace;
01251 }
01252 s = se;
01253 continue;
01254 }
01255
01256 if (STREQ("dump", f, fn)) {
01257 rpmDumpMacroTable(mb->mc, NULL);
01258 while (iseol(*se))
01259 se++;
01260 s = se;
01261 continue;
01262 }
01263
01264
01265 if (STREQ("basename", f, fn) ||
01266 STREQ("suffix", f, fn) ||
01267 STREQ("expand", f, fn) ||
01268 STREQ("verbose", f, fn) ||
01269 STREQ("uncompress", f, fn) ||
01270 STREQ("url2path", f, fn) ||
01271 STREQ("u2p", f, fn) ||
01272 STREQ("S", f, fn) ||
01273 STREQ("P", f, fn) ||
01274 STREQ("F", f, fn)) {
01275 doFoo(mb, negate, f, fn, g, gn);
01276 s = se;
01277 continue;
01278 }
01279
01280
01281 mep = findEntry(mb->mc, f, fn);
01282 me = (mep ? *mep : NULL);
01283
01284
01285 if (*f == '-') {
01286 if (me)
01287 me->used++;
01288 if ((me == NULL && !negate) ||
01289 (me != NULL && negate)) {
01290 s = se;
01291 continue;
01292 }
01293
01294 if (g && g < ge) {
01295 rc = expandT(mb, g, gn);
01296 } else
01297 if (me && me->body && *me->body) {
01298 rc = expandT(mb, me->body, strlen(me->body));
01299 }
01300 s = se;
01301 continue;
01302 }
01303
01304
01305 if (chkexist) {
01306 if ((me == NULL && !negate) ||
01307 (me != NULL && negate)) {
01308 s = se;
01309 continue;
01310 }
01311 if (g && g < ge) {
01312 rc = expandT(mb, g, gn);
01313 } else
01314 if (me && me->body && *me->body) {
01315 rc = expandT(mb, me->body, strlen(me->body));
01316 }
01317 s = se;
01318 continue;
01319 }
01320
01321 if (me == NULL) {
01322 #ifndef HACK
01323 #if DEAD
01324
01325 if (fn == 1 && *f == '*') {
01326 s = se;
01327 continue;
01328 }
01329 #endif
01330
01331 c = '%';
01332 SAVECHAR(mb, c);
01333 #else
01334 rpmError(RPMERR_BADSPEC,
01335 _("Macro %%%.*s not found, skipping\n"), fn, f);
01336 s = se;
01337 #endif
01338 continue;
01339 }
01340
01341
01342 if (me && me->opts != NULL) {
01343 if (grab != '\0') {
01344 se = grabArgs(mb, me, fe, grab);
01345 } else {
01346 addMacro(mb->mc, "**", NULL, "", mb->depth);
01347 addMacro(mb->mc, "*", NULL, "", mb->depth);
01348 addMacro(mb->mc, "#", NULL, "0", mb->depth);
01349 addMacro(mb->mc, "0", NULL, me->name, mb->depth);
01350 }
01351 }
01352
01353
01354 if (me->body && *me->body) {
01355
01356 mb->s = me->body;
01357
01358 rc = expandMacro(mb);
01359 if (rc == 0)
01360 me->used++;
01361 }
01362
01363
01364 if (me->opts != NULL)
01365 freeArgs(mb);
01366
01367 s = se;
01368 }
01369
01370 *mb->t = '\0';
01371 mb->s = s;
01372 mb->depth--;
01373 if (rc != 0 || mb->expand_trace)
01374 printExpansion(mb, t, mb->t);
01375 return rc;
01376 }
01377
01378
01379
01380 int
01381 expandMacros(void * spec, MacroContext mc, char * s, size_t slen)
01382 {
01383 MacroBuf mb = alloca(sizeof(*mb));
01384 char *tbuf;
01385 int rc;
01386
01387 if (s == NULL || slen == 0)
01388 return 0;
01389 if (mc == NULL) mc = &rpmGlobalMacroContext;
01390
01391 tbuf = alloca(slen + 1);
01392 memset(tbuf, 0, (slen + 1));
01393
01394
01395 mb->s = s;
01396
01397 mb->t = tbuf;
01398 mb->nb = slen;
01399 mb->depth = 0;
01400 mb->macro_trace = print_macro_trace;
01401 mb->expand_trace = print_expand_trace;
01402
01403
01404 mb->spec = spec;
01405 mb->mc = mc;
01406
01407
01408 rc = expandMacro(mb);
01409
01410 if (mb->nb == 0)
01411 rpmError(RPMERR_BADSPEC, _("Target buffer overflow\n"));
01412
01413 tbuf[slen] = '\0';
01414 strncpy(s, tbuf, (slen - mb->nb + 1));
01415
01416 return rc;
01417 }
01418
01419 void
01420 addMacro(MacroContext mc,
01421 const char * n, const char * o, const char * b, int level)
01422 {
01423 MacroEntry * mep;
01424
01425 if (mc == NULL) mc = &rpmGlobalMacroContext;
01426
01427
01428 if ((mep = findEntry(mc, n, 0)) == NULL) {
01429 if (mc->firstFree == mc->macrosAllocated)
01430 expandMacroTable(mc);
01431 if (mc->macroTable != NULL)
01432 mep = mc->macroTable + mc->firstFree++;
01433 }
01434
01435 if (mep != NULL) {
01436
01437 pushMacro(mep, n, o, b, level);
01438
01439
01440 if ((*mep)->prev == NULL)
01441 sortMacroTable(mc);
01442 }
01443 }
01444
01445 void
01446 delMacro(MacroContext mc, const char * n)
01447 {
01448 MacroEntry * mep;
01449
01450 if (mc == NULL) mc = &rpmGlobalMacroContext;
01451
01452 if ((mep = findEntry(mc, n, 0)) != NULL) {
01453 popMacro(mep);
01454
01455 if (!(mep && *mep))
01456 sortMacroTable(mc);
01457 }
01458 }
01459
01460 int
01461 rpmDefineMacro(MacroContext mc, const char * macro, int level)
01462 {
01463 MacroBuf mb = alloca(sizeof(*mb));
01464
01465 memset(mb, 0, sizeof(*mb));
01466
01467
01468 mb->mc = (mc ? mc : &rpmGlobalMacroContext);
01469
01470 (void)doDefine(mb, macro, level, 0);
01471 return 0;
01472 }
01473
01474 void
01475 rpmLoadMacros(MacroContext mc, int level)
01476 {
01477
01478 if (mc == NULL || mc == &rpmGlobalMacroContext)
01479 return;
01480
01481 if (mc->macroTable != NULL) {
01482 int i;
01483 for (i = 0; i < mc->firstFree; i++) {
01484 MacroEntry *mep, me;
01485 mep = &mc->macroTable[i];
01486 me = *mep;
01487
01488 if (me == NULL)
01489 continue;
01490 addMacro(NULL, me->name, me->opts, me->body, (level - 1));
01491 }
01492 }
01493 }
01494
01495 void
01496 rpmInitMacros(MacroContext mc, const char *macrofiles)
01497 {
01498 char *m, *mfile, *me;
01499
01500 if (macrofiles == NULL)
01501 return;
01502 if (mc == NULL) mc = &rpmGlobalMacroContext;
01503
01504 for (mfile = m = xstrdup(macrofiles); mfile && *mfile != '\0'; mfile = me) {
01505 FD_t fd;
01506 char buf[BUFSIZ];
01507
01508 for (me = mfile; (me = strchr(me, ':')) != NULL; me++) {
01509 if (!(me[1] == '/' && me[2] == '/'))
01510 break;
01511 }
01512
01513 if (me && *me == ':')
01514 *me++ = '\0';
01515 else
01516 me = mfile + strlen(mfile);
01517
01518
01519 buf[0] = '\0';
01520 if (mfile[0] == '~' && mfile[1] == '/') {
01521 char *home;
01522 if ((home = getenv("HOME")) != NULL) {
01523 mfile += 2;
01524 strncpy(buf, home, sizeof(buf));
01525 strncat(buf, "/", sizeof(buf) - strlen(buf));
01526 }
01527 }
01528 strncat(buf, mfile, sizeof(buf) - strlen(buf));
01529 buf[sizeof(buf)-1] = '\0';
01530
01531 fd = Fopen(buf, "r.fpio");
01532 if (fd == NULL || Ferror(fd)) {
01533 if (fd) (void) Fclose(fd);
01534 continue;
01535 }
01536
01537
01538 max_macro_depth = 16;
01539
01540 while(rdcl(buf, sizeof(buf), fd, 1) != NULL) {
01541 char c, *n;
01542
01543 n = buf;
01544 SKIPBLANK(n, c);
01545
01546 if (c != '%')
01547 continue;
01548 n++;
01549 (void)rpmDefineMacro(NULL, n, RMIL_MACROFILES);
01550 }
01551 (void) Fclose(fd);
01552 }
01553 m = _free(m);
01554
01555
01556 rpmLoadMacros(&rpmCLIMacroContext, RMIL_CMDLINE);
01557 }
01558
01559
01560 void
01561 rpmFreeMacros(MacroContext mc)
01562 {
01563
01564 if (mc == NULL) mc = &rpmGlobalMacroContext;
01565
01566 if (mc->macroTable != NULL) {
01567 int i;
01568 for (i = 0; i < mc->firstFree; i++) {
01569 MacroEntry me;
01570 while ((me = mc->macroTable[i]) != NULL) {
01571
01572
01573 if ((mc->macroTable[i] = me->prev) == NULL)
01574 me->name = _free(me->name);
01575
01576 me->opts = _free(me->opts);
01577 me->body = _free(me->body);
01578 me = _free(me);
01579 }
01580 }
01581 mc->macroTable = _free(mc->macroTable);
01582 }
01583 memset(mc, 0, sizeof(*mc));
01584 }
01585
01586
01587
01588 int isCompressed(const char * file, rpmCompressedMagic * compressed)
01589 {
01590 FD_t fd;
01591 ssize_t nb;
01592 int rc = -1;
01593 unsigned char magic[4];
01594
01595 *compressed = COMPRESSED_NOT;
01596
01597 fd = Fopen(file, "r.ufdio");
01598 if (fd == NULL || Ferror(fd)) {
01599
01600 rpmError(RPMERR_BADSPEC, _("File %s: %s\n"), file, Fstrerror(fd));
01601 if (fd) (void) Fclose(fd);
01602 return 1;
01603 }
01604 nb = Fread(magic, sizeof(char), sizeof(magic), fd);
01605 if (nb < 0) {
01606 rpmError(RPMERR_BADSPEC, _("File %s: %s\n"), file, Fstrerror(fd));
01607 rc = 1;
01608 } else if (nb < sizeof(magic)) {
01609 rpmError(RPMERR_BADSPEC, _("File %s is smaller than %u bytes\n"),
01610 file, (unsigned)sizeof(magic));
01611 rc = 0;
01612 }
01613 (void) Fclose(fd);
01614 if (rc >= 0)
01615 return rc;
01616
01617 rc = 0;
01618
01619 if ((magic[0] == 'B') && (magic[1] == 'Z')) {
01620 *compressed = COMPRESSED_BZIP2;
01621 } else if ((magic[0] == 0120) && (magic[1] == 0113) &&
01622 (magic[2] == 0003) && (magic[3] == 0004)) {
01623 *compressed = COMPRESSED_ZIP;
01624 } else if (((magic[0] == 0037) && (magic[1] == 0213)) ||
01625 ((magic[0] == 0037) && (magic[1] == 0236)) ||
01626 ((magic[0] == 0037) && (magic[1] == 0036)) ||
01627 ((magic[0] == 0037) && (magic[1] == 0240)) ||
01628 ((magic[0] == 0037) && (magic[1] == 0235))
01629 ) {
01630 *compressed = COMPRESSED_OTHER;
01631 }
01632
01633 return rc;
01634 }
01635
01636
01637
01638 char *
01639 rpmExpand(const char *arg, ...)
01640 {
01641 char buf[BUFSIZ], *p, *pe;
01642 const char *s;
01643 va_list ap;
01644
01645 if (arg == NULL)
01646 return xstrdup("");
01647
01648 buf[0] = '\0';
01649 p = buf;
01650 pe = stpcpy(p, arg);
01651
01652 va_start(ap, arg);
01653 while ((s = va_arg(ap, const char *)) != NULL)
01654 pe = stpcpy(pe, s);
01655 va_end(ap);
01656 (void) expandMacros(NULL, NULL, buf, sizeof(buf));
01657 return xstrdup(buf);
01658 }
01659
01660 int
01661 rpmExpandNumeric(const char *arg)
01662 {
01663 const char *val;
01664 int rc;
01665
01666 if (arg == NULL)
01667 return 0;
01668
01669 val = rpmExpand(arg, NULL);
01670 if (!(val && *val != '%'))
01671 rc = 0;
01672 else if (*val == 'Y' || *val == 'y')
01673 rc = 1;
01674 else if (*val == 'N' || *val == 'n')
01675 rc = 0;
01676 else {
01677 char *end;
01678 rc = strtol(val, &end, 0);
01679 if (!(end && *end == '\0'))
01680 rc = 0;
01681 }
01682 val = _free(val);
01683
01684 return rc;
01685 }
01686
01687
01688 char *rpmCleanPath(char * path)
01689 {
01690 const char *s;
01691 char *se, *t, *te;
01692 int begin = 1;
01693
01694 if (path == NULL)
01695 return NULL;
01696
01697
01698 s = t = te = path;
01699 while (*s != '\0') {
01700
01701 switch(*s) {
01702 case ':':
01703 if (s[1] == '/' && s[2] == '/') {
01704 *t++ = *s++;
01705 *t++ = *s++;
01706 break;
01707 }
01708 begin=1;
01709 break;
01710 case '/':
01711
01712 for (se = te + 1; se < t && *se != '/'; se++)
01713 {};
01714 if (se < t && *se == '/') {
01715 te = se;
01716
01717 }
01718 while (s[1] == '/')
01719 s++;
01720 while (t > path && t[-1] == '/')
01721 t--;
01722 break;
01723 case '.':
01724
01725 if (begin && s[1] == '.') {
01726
01727 *t++ = *s++;
01728 break;
01729 }
01730
01731 if (begin && s[1] == '\0') {
01732 break;
01733 }
01734
01735 if ((t[-1] == '/' && s[1] == '\0') || (t != path && s[1] == '/')) {
01736 s++;
01737 continue;
01738 }
01739
01740 if (!begin && t > path && t[-1] == '/' && s[1] == '.' && (s[2] == '/' || s[2] == '\0')) {
01741 t = te;
01742
01743 if (te > path)
01744 for (--te; te > path && *te != '/'; te--)
01745 {};
01746
01747 s++;
01748 s++;
01749 continue;
01750 }
01751 break;
01752 default:
01753 begin = 0;
01754 break;
01755 }
01756 *t++ = *s++;
01757 }
01758
01759
01760 if (t > &path[1] && t[-1] == '/')
01761 t--;
01762 *t = '\0';
01763
01764
01765 return path;
01766 }
01767
01768
01769
01770 const char *
01771 rpmGetPath(const char *path, ...)
01772 {
01773 char buf[BUFSIZ];
01774 const char * s;
01775 char * t, * te;
01776 va_list ap;
01777
01778 if (path == NULL)
01779 return xstrdup("");
01780
01781 buf[0] = '\0';
01782 t = buf;
01783 te = stpcpy(t, path);
01784 *te = '\0';
01785
01786 va_start(ap, path);
01787 while ((s = va_arg(ap, const char *)) != NULL) {
01788 te = stpcpy(te, s);
01789 *te = '\0';
01790 }
01791 va_end(ap);
01792 (void) expandMacros(NULL, NULL, buf, sizeof(buf));
01793
01794 (void) rpmCleanPath(buf);
01795 return xstrdup(buf);
01796 }
01797
01798
01799
01800 const char * rpmGenPath(const char * urlroot, const char * urlmdir,
01801 const char *urlfile)
01802 {
01803 const char * xroot = rpmGetPath(urlroot, NULL);
01804 const char * root = xroot;
01805 const char * xmdir = rpmGetPath(urlmdir, NULL);
01806 const char * mdir = xmdir;
01807 const char * xfile = rpmGetPath(urlfile, NULL);
01808 const char * file = xfile;
01809 const char * result;
01810 const char * url = NULL;
01811 int nurl = 0;
01812 int ut;
01813
01814 #if 0
01815 if (_debug) fprintf(stderr, "*** RGP xroot %s xmdir %s xfile %s\n", xroot, xmdir, xfile);
01816 #endif
01817 ut = urlPath(xroot, &root);
01818 if (url == NULL && ut > URL_IS_DASH) {
01819 url = xroot;
01820 nurl = root - xroot;
01821 #if 0
01822 if (_debug) fprintf(stderr, "*** RGP ut %d root %s nurl %d\n", ut, root, nurl);
01823 #endif
01824 }
01825 if (root == NULL || *root == '\0') root = "/";
01826
01827 ut = urlPath(xmdir, &mdir);
01828 if (url == NULL && ut > URL_IS_DASH) {
01829 url = xmdir;
01830 nurl = mdir - xmdir;
01831 #if 0
01832 if (_debug) fprintf(stderr, "*** RGP ut %d mdir %s nurl %d\n", ut, mdir, nurl);
01833 #endif
01834 }
01835 if (mdir == NULL || *mdir == '\0') mdir = "/";
01836
01837 ut = urlPath(xfile, &file);
01838 if (url == NULL && ut > URL_IS_DASH) {
01839 url = xfile;
01840 nurl = file - xfile;
01841 #if 0
01842 if (_debug) fprintf(stderr, "*** RGP ut %d file %s nurl %d\n", ut, file, nurl);
01843 #endif
01844 }
01845
01846 if (url && nurl > 0) {
01847 char *t = strncpy(alloca(nurl+1), url, nurl);
01848 t[nurl] = '\0';
01849 url = t;
01850 } else
01851 url = "";
01852
01853 result = rpmGetPath(url, root, "/", mdir, "/", file, NULL);
01854
01855 xroot = _free(xroot);
01856 xmdir = _free(xmdir);
01857 xfile = _free(xfile);
01858 #if 0
01859 if (_debug) fprintf(stderr, "*** RGP result %s\n", result);
01860 #endif
01861 return result;
01862 }
01863
01864
01865
01866 #if defined(DEBUG_MACROS)
01867
01868 #if defined(EVAL_MACROS)
01869
01870 char *macrofiles = "/usr/lib/rpm/macros:/etc/rpm/macros:~/.rpmmacros";
01871
01872 int
01873 main(int argc, char *argv[])
01874 {
01875 int c;
01876 int errflg = 0;
01877 extern char *optarg;
01878 extern int optind;
01879
01880 while ((c = getopt(argc, argv, "f:")) != EOF ) {
01881 switch (c) {
01882 case 'f':
01883 macrofiles = optarg;
01884 break;
01885 case '?':
01886 default:
01887 errflg++;
01888 break;
01889 }
01890 }
01891 if (errflg || optind >= argc) {
01892 fprintf(stderr, "Usage: %s [-f macropath ] macro ...\n", argv[0]);
01893 exit(1);
01894 }
01895
01896 rpmInitMacros(NULL, macrofiles);
01897 for ( ; optind < argc; optind++) {
01898 const char *val;
01899
01900 val = rpmGetPath(argv[optind], NULL);
01901 if (val) {
01902 fprintf(stdout, "%s:\t%s\n", argv[optind], val);
01903 val = _free(val);
01904 }
01905 }
01906 rpmFreeMacros(NULL);
01907 return 0;
01908 }
01909
01910 #else
01911
01912 char *macrofiles = "../macros:./testmacros";
01913 char *testfile = "./test";
01914
01915 int
01916 main(int argc, char *argv[])
01917 {
01918 char buf[BUFSIZ];
01919 FILE *fp;
01920 int x;
01921
01922 rpmInitMacros(NULL, macrofiles);
01923 rpmDumpMacroTable(NULL, NULL);
01924
01925 if ((fp = fopen(testfile, "r")) != NULL) {
01926 while(rdcl(buf, sizeof(buf), fp, 1)) {
01927 x = expandMacros(NULL, NULL, buf, sizeof(buf));
01928 fprintf(stderr, "%d->%s\n", x, buf);
01929 memset(buf, 0, sizeof(buf));
01930 }
01931 fclose(fp);
01932 }
01933
01934 while(rdcl(buf, sizeof(buf), stdin, 1)) {
01935 x = expandMacros(NULL, NULL, buf, sizeof(buf));
01936 fprintf(stderr, "%d->%s\n <-\n", x, buf);
01937 memset(buf, 0, sizeof(buf));
01938 }
01939 rpmFreeMacros(NULL);
01940
01941 return 0;
01942 }
01943 #endif
01944 #endif