diff -urN rpm-5.4.13/build/parseSpec.c rpm-5.4.13-rpmspec/build/parseSpec.c --- rpm-5.4.13/build/parseSpec.c 2013-10-22 20:18:34.483039876 +0200 +++ rpm-5.4.13-rpmspec/build/parseSpec.c 2013-10-22 18:52:02.550664732 +0200 @@ -474,6 +474,11 @@ spec->line[0] = '\0'; } + /* Collect parsed line */ + if (spec->parsed == NULL) + spec->parsed = rpmiobNew(0); + spec->parsed = rpmiobAppend(spec->parsed, spec->line, 1); + /*@-compmempass@*/ /* FIX: spec->readStack->next should be dependent */ return 0; /*@=compmempass@*/ diff -urN rpm-5.4.13/build/rpmspec.h rpm-5.4.13-rpmspec/build/rpmspec.h --- rpm-5.4.13/build/rpmspec.h 2013-10-22 20:18:34.449706143 +0200 +++ rpm-5.4.13-rpmspec/build/rpmspec.h 2013-10-22 18:44:37.729692113 +0200 @@ -193,6 +193,8 @@ /*@only@*/ rpmiob clean; /*!< %clean scriptlet. */ + rpmiob parsed; + size_t nfoo; /*@only@*/ /*@relnull@*/ tagStore_t foo; --- rpm-5.4.13/build/spec.c~ 2013-07-27 02:16:06.000000000 +0200 +++ rpm-5.4.13/build/spec.c 2013-10-23 13:01:36.596670702 +0200 @@ -562,6 +562,7 @@ spec->install = rpmiobFree(spec->install); spec->check = rpmiobFree(spec->check); spec->clean = rpmiobFree(spec->clean); + spec->parsed = rpmiobFree(spec->parsed); spec->foo = tagStoreFree(spec->foo, spec->nfoo); spec->nfoo = 0; diff -urN rpm-5.4.13/tools/Makefile.am rpm-5.4.13-rpmspec/tools/Makefile.am --- rpm-5.4.13/tools/Makefile.am 2013-10-22 20:18:34.426372530 +0200 +++ rpm-5.4.13-rpmspec/tools/Makefile.am 2013-10-22 20:02:30.365350944 +0200 @@ -61,7 +61,7 @@ pkgbin_PROGRAMS = \ @WITH_AUGEAS_AUGTOOL@ chroot cp @WITH_CUDF_CUDFTOOL@ find mtree \ @WITH_SEMANAGE_SEMODULE@ wget \ - rpmcache rpmdigest rpmrepo rpmspecdump \ + rpmcache rpmdigest rpmrepo rpmspecdump rpmspec \ rpmcmp rpmdeps sqlite3 @WITH_KEYUTILS_RPMKEY@ @WITH_LIBELF_DEBUGEDIT@ if WITH_DB pkgbin_PROGRAMS += dbconvert @@ -195,6 +195,9 @@ rpmspecdump_SOURCES = rpmspecdump.c rpmspecdump_LDADD = $(RPMBUILD_LDADD_COMMON) +rpmspec_SOURCES = rpmspec.c +rpmspec_LDADD = $(RPMBUILD_LDADD_COMMON) + semodule_SOURCES = semodule.c semodule_LDADD = $(RPMIO_LDADD_COMMON) diff -urN rpm-5.4.13/tools/rpmspec.c rpm-5.4.13-rpmspec/tools/rpmspec.c --- rpm-5.4.13/tools/rpmspec.c 1970-01-01 01:00:00.000000000 +0100 +++ rpm-5.4.13-rpmspec/tools/rpmspec.c 2013-10-22 20:00:06.075242852 +0200 @@ -0,0 +1,176 @@ +#include "system.h" +const char *__progname; + +#define _AUTOHELP + +#if defined(IAM_RPM) || defined(__LCLINT__) +#define IAM_RPMBT +#define IAM_RPMDB +#define IAM_RPMEIU +#define IAM_RPMQV +#define IAM_RPMK +#endif + +#include +#include +#include + +#include +#include +#include "rpmdb.h" + +#include "rpmversion.h" +#include "rpmps.h" +#include "rpmts.h" + +#include + +#ifdef IAM_RPMBT +#include "build.h" +#define GETOPT_REBUILD 1003 +#define GETOPT_RECOMPILE 1004 +#endif + +#include + +#include "debug.h" + +enum modes { + MODE_UNKNOWN = 0, + MODE_QUERY = (1 << 0), + MODE_PARSE = (1 << 1), +}; + +static int mode = MODE_UNKNOWN; +static rpmQVSources source = RPMQV_RPM; +static const char *target = NULL; +static char *queryformat = NULL; + +static struct poptOption specOptsTable[] = { + { "parse", 'P', POPT_ARG_VAL, &mode, MODE_PARSE, + N_("parse spec file(s) to stdout"), NULL }, + { "query", 'q', POPT_ARG_VAL, &mode, MODE_QUERY, + N_("query spec file(s)"), NULL }, + { "rpms", 0, POPT_ARG_VAL, &source, RPMQV_RPM, + N_("operate on binary rpms generated by spec (default)"), NULL }, + { "srpm", 0, POPT_ARG_VAL, &source, RPMQV_SPECSRPM, + N_("operate on source rpm generated by spec"), NULL }, + { "target", 0, POPT_ARG_STRING, &target, 0, + N_("override target platform"), NULL }, + { "queryformat", 0, POPT_ARG_STRING, &queryformat, 0, + N_("use the following query format"), "QUERYFORMAT" }, + { "qf", 0, (POPT_ARG_STRING | POPT_ARGFLAG_DOC_HIDDEN), &queryformat, 0, + NULL, NULL }, + POPT_TABLEEND +}; + +/* the structure describing the options we take and the defaults */ +static struct poptOption optionsTable[] = { + { NULL, '\0', POPT_ARG_INCLUDE_TABLE, specOptsTable, 0, + N_("Spec options:"), NULL }, + + { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0, + N_("Common options for all rpm modes and executables:"), NULL }, + + POPT_AUTOALIAS + POPT_AUTOHELP + POPT_TABLEEND +}; + +/*@exits@*/ static void argerror(const char * desc) + /*@globals __assert_program_name, fileSystem @*/ + /*@modifies fileSystem @*/ +{ + fprintf(stderr, _("%s: %s\n"), __progname, desc); + exit(EXIT_FAILURE); +} + +#ifdef DYING /* XXX rpmIsVerbose alone stops usage spewage with every --eval */ +static void printVersion(FILE * fp) + /*@globals rpmEVR, fileSystem @*/ + /*@modifies *fp, fileSystem @*/ +{ + fprintf(fp, "%s (" RPM_NAME ") %s\n", __progname, rpmEVR); + if (rpmIsVerbose()) + fprintf(fp, "rpmlib 0x%08x,0x%08x,0x%08x\n", + rpmlibVersion(), rpmlibTimestamp(), rpmlibVendor()); +} + +static void printUsage(poptContext con, FILE * fp, int flags) + /*@globals rpmEVR, fileSystem, internalState @*/ + /*@modifies *fp, fileSystem, internalState @*/ +{ + printVersion(fp); + fprintf(fp, "\n"); + + if (rpmIsVerbose()) + poptPrintHelp(con, fp, flags); + else + poptPrintUsage(con, fp, flags); +} +#endif + +int main(int argc, char *argv[]) +{ + rpmts ts = NULL; + QVA_t qva = &rpmQVKArgs; + + poptContext optCon; + int ec = 0; + + optCon = rpmcliInit(argc, argv, optionsTable); + + if (target) { + rpmFreeMacros(NULL); + rpmFreeRpmrc(); + rpmcliConfigured(); + } + + ts = rpmtsCreate(); + switch (mode) { + + case MODE_QUERY: + if (!poptPeekArg(optCon)) + argerror(_("no arguments given for query")); + + qva->qva_queryFormat = queryformat; + qva->qva_source = source; + qva->qva_specQuery = rpmspecQuery; + ec = rpmcliQuery(ts, qva, (const char **) poptGetArgs(optCon)); + break; + + case MODE_PARSE: { + const char * spath; + if (!poptPeekArg(optCon)) + argerror(_("no arguments given for parse")); + + while ((spath = poptGetArg(optCon)) != NULL) { + int ret = parseSpec(ts, spath, "/", 0, NULL, NULL, 1, 1, 0); + if (ret != 0) { + ec++; + continue; + } + Spec spec = rpmtsSpec(ts); + fprintf(stdout, "%s", rpmiobStr(spec->parsed)); + } + break; + } + + case MODE_UNKNOWN: +#ifdef DYING /* XXX rpmIsVerbose alone stops usage spewage with every --eval */ + if (poptPeekArg(optCon) != NULL || argc <= 1 || rpmIsVerbose()) { + printUsage(optCon, stderr, 0); + ec = argc; + } +#endif + break; + } + + rpmtsFree(ts); + + free(qva->qva_queryFormat); + + rpmcliFini(optCon); + + return ec; +}