2002-03-25 23:16:26 +03:00
/** \ingroup rpmbuild
* \ file build / parsePreamble . c
* Parse tags in global section from spec file .
*/
# include "system.h"
2002-03-26 01:02:39 +03:00
# include "rpmio_internal.h"
# include "rpmbuild.h"
2002-03-25 23:16:26 +03:00
# include "debug.h"
/*@access FD_t @*/ /* compared with NULL */
/**
*/
/*@observer@*/ /*@unchecked@*/
static rpmTag copyTagsDuringParse [ ] = {
RPMTAG_EPOCH ,
RPMTAG_VERSION ,
RPMTAG_RELEASE ,
RPMTAG_LICENSE ,
RPMTAG_PACKAGER ,
RPMTAG_DISTRIBUTION ,
RPMTAG_DISTURL ,
RPMTAG_VENDOR ,
RPMTAG_ICON ,
RPMTAG_URL ,
RPMTAG_CHANGELOGTIME ,
RPMTAG_CHANGELOGNAME ,
RPMTAG_CHANGELOGTEXT ,
RPMTAG_PREFIXES ,
2002-06-13 15:28:05 +04:00
RPMTAG_BUILDHOST ,
2002-03-25 23:16:26 +03:00
RPMTAG_RHNPLATFORM ,
0
} ;
/**
*/
/*@observer@*/ /*@unchecked@*/
static rpmTag requiredTags [ ] = {
RPMTAG_NAME ,
RPMTAG_VERSION ,
RPMTAG_RELEASE ,
RPMTAG_SUMMARY ,
RPMTAG_GROUP ,
RPMTAG_LICENSE ,
0
} ;
/**
*/
static void addOrAppendListEntry ( Header h , int_32 tag , char * line )
/*@modifies h @*/
{
int xx ;
int argc ;
const char * * argv ;
xx = poptParseArgvString ( line , & argc , & argv ) ;
if ( argc )
xx = headerAddOrAppendEntry ( h , tag , RPM_STRING_ARRAY_TYPE , argv , argc ) ;
argv = _free ( argv ) ;
}
/* Parse a simple part line that only take -n <pkg> or <pkg> */
/* <pkg> is return in name as a pointer into a static buffer */
/**
*/
static int parseSimplePart ( char * line , /*@out@*/ char * * name , /*@out@*/ int * flag )
/*@globals internalState@*/
/*@modifies *name, *flag, internalState @*/
{
char * tok ;
char linebuf [ BUFSIZ ] ;
static char buf [ BUFSIZ ] ;
strcpy ( linebuf , line ) ;
/* Throw away the first token (the %xxxx) */
( void ) strtok ( linebuf , " \t \n " ) ;
if ( ! ( tok = strtok ( NULL , " \t \n " ) ) ) {
* name = NULL ;
return 0 ;
}
if ( ! strcmp ( tok , " -n " ) ) {
if ( ! ( tok = strtok ( NULL , " \t \n " ) ) )
return 1 ;
* flag = PART_NAME ;
} else {
* flag = PART_SUBNAME ;
}
strcpy ( buf , tok ) ;
* name = buf ;
return ( strtok ( NULL , " \t \n " ) ) ? 1 : 0 ;
}
/**
*/
2002-03-26 01:57:16 +03:00
static inline const char * parseReqProv ( const char * s )
2002-03-25 23:16:26 +03:00
{
2002-03-26 01:57:16 +03:00
if ( ! s | |
! strcasecmp ( s , " no " ) | |
! strcasecmp ( s , " false " ) | |
! strcasecmp ( s , " off " ) | |
! strcmp ( s , " 0 " ) ) {
return xstrdup ( " " ) ;
}
return xstrdup ( s ) ;
2002-03-25 23:16:26 +03:00
}
typedef struct tokenBits_s {
/*@observer@*/ /*@null@*/ const char * name ;
rpmsenseFlags bits ;
} * tokenBits ;
/**
*/
/*@observer@*/ /*@unchecked@*/
static struct tokenBits_s installScriptBits [ ] = {
{ " interp " , RPMSENSE_INTERP } ,
{ " prereq " , RPMSENSE_PREREQ } ,
{ " preun " , RPMSENSE_SCRIPT_PREUN } ,
{ " pre " , RPMSENSE_SCRIPT_PRE } ,
{ " postun " , RPMSENSE_SCRIPT_POSTUN } ,
{ " post " , RPMSENSE_SCRIPT_POST } ,
{ " rpmlib " , RPMSENSE_RPMLIB } ,
{ " verify " , RPMSENSE_SCRIPT_VERIFY } ,
{ NULL , 0 }
} ;
/**
*/
/*@observer@*/ /*@unchecked@*/
static struct tokenBits_s buildScriptBits [ ] = {
{ " prep " , RPMSENSE_SCRIPT_PREP } ,
{ " build " , RPMSENSE_SCRIPT_BUILD } ,
{ " install " , RPMSENSE_SCRIPT_INSTALL } ,
{ " clean " , RPMSENSE_SCRIPT_CLEAN } ,
{ NULL , 0 }
} ;
/**
*/
static int parseBits ( const char * s , const tokenBits tokbits ,
/*@out@*/ rpmsenseFlags * bp )
/*@modifies *bp @*/
{
tokenBits tb ;
const char * se ;
rpmsenseFlags bits = RPMSENSE_ANY ;
int c = 0 ;
if ( s ) {
while ( * s ! = ' \0 ' ) {
while ( ( c = * s ) & & xisspace ( c ) ) s + + ;
se = s ;
while ( ( c = * se ) & & xisalpha ( c ) ) se + + ;
if ( s = = se )
break ;
for ( tb = tokbits ; tb - > name ; tb + + ) {
if ( tb - > name ! = NULL & &
strlen ( tb - > name ) = = ( se - s ) & & ! strncmp ( tb - > name , s , ( se - s ) ) )
/*@innerbreak@*/ break ;
}
if ( tb - > name = = NULL )
break ;
bits | = tb - > bits ;
while ( ( c = * se ) & & xisspace ( c ) ) se + + ;
if ( c ! = ' , ' )
break ;
s = + + se ;
}
}
if ( c = = 0 & & bp ) * bp = bits ;
return ( c ? RPMERR_BADSPEC : 0 ) ;
}
/**
*/
static inline char * findLastChar ( char * s )
/*@*/
{
char * res = s ;
while ( * s ! = ' \0 ' ) {
if ( ! xisspace ( * s ) )
res = s ;
s + + ;
}
/*@-temptrans -retalias@*/
return res ;
/*@=temptrans =retalias@*/
}
/**
*/
static int isMemberInEntry ( Header h , const char * name , rpmTag tag )
/*@*/
{
HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
HFD_t hfd = headerFreeData ;
const char * * names ;
rpmTagType type ;
int count ;
if ( ! hge ( h , tag , & type , ( void * * ) & names , & count ) )
return - 1 ;
while ( count - - ) {
if ( ! xstrcasecmp ( names [ count ] , name ) )
break ;
}
names = hfd ( names , type ) ;
return ( count > = 0 ? 1 : 0 ) ;
}
/**
*/
static int checkForValidArchitectures ( Spec spec )
/*@*/
{
# ifndef DYING
const char * arch = NULL ;
const char * os = NULL ;
rpmGetArchInfo ( & arch , NULL ) ;
rpmGetOsInfo ( & os , NULL ) ;
# else
const char * arch = rpmExpand ( " %{_target_cpu} " , NULL ) ;
const char * os = rpmExpand ( " %{_target_os} " , NULL ) ;
# endif
if ( isMemberInEntry ( spec - > buildRestrictions ,
arch , RPMTAG_EXCLUDEARCH ) = = 1 ) {
rpmError ( RPMERR_BADSPEC , _ ( " Architecture is excluded: %s \n " ) , arch ) ;
return RPMERR_BADSPEC ;
}
if ( isMemberInEntry ( spec - > buildRestrictions ,
arch , RPMTAG_EXCLUSIVEARCH ) = = 0 ) {
rpmError ( RPMERR_BADSPEC , _ ( " Architecture is not included: %s \n " ) , arch ) ;
return RPMERR_BADSPEC ;
}
if ( isMemberInEntry ( spec - > buildRestrictions ,
os , RPMTAG_EXCLUDEOS ) = = 1 ) {
rpmError ( RPMERR_BADSPEC , _ ( " OS is excluded: %s \n " ) , os ) ;
return RPMERR_BADSPEC ;
}
if ( isMemberInEntry ( spec - > buildRestrictions ,
os , RPMTAG_EXCLUSIVEOS ) = = 0 ) {
rpmError ( RPMERR_BADSPEC , _ ( " OS is not included: %s \n " ) , os ) ;
return RPMERR_BADSPEC ;
}
return 0 ;
}
/**
* Check that required tags are present in header .
* @ param h header
* @ param NVR package name - version - release
* @ return 0 if OK
*/
static int checkForRequired ( Header h , const char * NVR )
/*@modifies h @*/ /* LCL: parse error here with modifies */
{
int res = 0 ;
rpmTag * p ;
for ( p = requiredTags ; * p ! = 0 ; p + + ) {
if ( ! headerIsEntry ( h , * p ) ) {
rpmError ( RPMERR_BADSPEC ,
_ ( " %s field must be present in package: %s \n " ) ,
tagName ( * p ) , NVR ) ;
res = 1 ;
}
}
return res ;
}
/**
* Check that no duplicate tags are present in header .
* @ param h header
* @ param NVR package name - version - release
* @ return 0 if OK
*/
static int checkForDuplicates ( Header h , const char * NVR )
/*@modifies h @*/
{
int res = 0 ;
int lastTag , tag ;
HeaderIterator hi ;
for ( hi = headerInitIterator ( h ) , lastTag = 0 ;
headerNextIterator ( hi , & tag , NULL , NULL , NULL ) ;
lastTag = tag )
{
if ( tag ! = lastTag )
continue ;
rpmError ( RPMERR_BADSPEC , _ ( " Duplicate %s entries in package: %s \n " ) ,
tagName ( tag ) , NVR ) ;
res = 1 ;
}
hi = headerFreeIterator ( hi ) ;
return res ;
}
/**
*/
/*@observer@*/ /*@unchecked@*/
static struct optionalTag {
rpmTag ot_tag ;
/*@observer@*/ /*@null@*/ const char * ot_mac ;
} optionalTags [ ] = {
2005-10-06 03:42:30 +04:00
{ RPMTAG_VENDOR , " %{?vendor} " } ,
{ RPMTAG_PACKAGER , " %{?packager} " } ,
{ RPMTAG_DISTRIBUTION , " %{?distribution} " } ,
{ RPMTAG_DISTURL , " %{?disturl} " } ,
{ RPMTAG_BUILDHOST , " %{?buildhost} " } ,
2002-03-25 23:16:26 +03:00
{ - 1 , NULL }
} ;
/**
*/
static void fillOutMainPackage ( Header h )
/*@globals rpmGlobalMacroContext @*/
/*@modifies h, rpmGlobalMacroContext @*/
{
struct optionalTag * ot ;
for ( ot = optionalTags ; ot - > ot_mac ! = NULL ; ot + + ) {
if ( ! headerIsEntry ( h , ot - > ot_tag ) ) {
const char * val = rpmExpand ( ot - > ot_mac , NULL ) ;
2005-10-06 03:42:30 +04:00
if ( val & & * val ! = ' \0 ' )
2002-03-25 23:16:26 +03:00
( void ) headerAddEntry ( h , ot - > ot_tag , RPM_STRING_TYPE , ( void * ) val , 1 ) ;
val = _free ( val ) ;
}
}
}
2003-07-20 16:51:57 +04:00
# ifdef ENABLE_ICON_TAG
2002-03-25 23:16:26 +03:00
/**
*/
static int readIcon ( Header h , const char * file )
/*@globals rpmGlobalMacroContext,
fileSystem @ */
/*@modifies h, rpmGlobalMacroContext, fileSystem @*/
{
const char * fn = NULL ;
char * icon ;
FD_t fd ;
int rc = 0 ;
off_t size ;
size_t nb , iconsize ;
/* XXX use rpmGenPath(rootdir, "%{_sourcedir}/", file) for icon path. */
fn = rpmGetPath ( " %{_sourcedir}/ " , file , NULL ) ;
fd = Fopen ( fn , " r.ufdio " ) ;
if ( fd = = NULL | | Ferror ( fd ) ) {
rpmError ( RPMERR_BADSPEC , _ ( " Unable to open icon %s: %s \n " ) ,
fn , Fstrerror ( fd ) ) ;
rc = RPMERR_BADSPEC ;
goto exit ;
}
size = fdSize ( fd ) ;
iconsize = ( size > = 0 ? size : ( 8 * BUFSIZ ) ) ;
if ( iconsize = = 0 ) {
( void ) Fclose ( fd ) ;
rc = 0 ;
goto exit ;
}
icon = xmalloc ( iconsize + 1 ) ;
* icon = ' \0 ' ;
nb = Fread ( icon , sizeof ( icon [ 0 ] ) , iconsize , fd ) ;
if ( Ferror ( fd ) | | ( size > = 0 & & nb ! = size ) ) {
rpmError ( RPMERR_BADSPEC , _ ( " Unable to read icon %s: %s \n " ) ,
fn , Fstrerror ( fd ) ) ;
rc = RPMERR_BADSPEC ;
}
( void ) Fclose ( fd ) ;
if ( rc )
goto exit ;
if ( ! strncmp ( icon , " GIF " , sizeof ( " GIF " ) - 1 ) ) {
( void ) headerAddEntry ( h , RPMTAG_GIF , RPM_BIN_TYPE , icon , iconsize ) ;
} else if ( ! strncmp ( icon , " /* XPM " , sizeof ( " /* XPM " ) - 1 ) ) {
( void ) headerAddEntry ( h , RPMTAG_XPM , RPM_BIN_TYPE , icon , iconsize ) ;
} else {
rpmError ( RPMERR_BADSPEC , _ ( " Unknown icon type: %s \n " ) , file ) ;
rc = RPMERR_BADSPEC ;
goto exit ;
}
icon = _free ( icon ) ;
exit :
fn = _free ( fn ) ;
return rc ;
}
2003-07-20 16:51:57 +04:00
# endif /* ENABLE_ICON_TAG */
2002-03-25 23:16:26 +03:00
spectag stashSt ( Spec spec , Header h , int tag , const char * lang )
{
HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
spectag t = NULL ;
if ( spec - > st ) {
spectags st = spec - > st ;
if ( st - > st_ntags = = st - > st_nalloc ) {
st - > st_nalloc + = 10 ;
st - > st_t = xrealloc ( st - > st_t , st - > st_nalloc * sizeof ( * ( st - > st_t ) ) ) ;
}
t = st - > st_t + st - > st_ntags + + ;
t - > t_tag = tag ;
t - > t_startx = spec - > lineNum - 1 ;
t - > t_nlines = 1 ;
t - > t_lang = xstrdup ( lang ) ;
t - > t_msgid = NULL ;
if ( ! ( t - > t_lang & & strcmp ( t - > t_lang , RPMBUILD_DEFAULT_LANG ) ) ) {
char * n ;
if ( hge ( h , RPMTAG_NAME , NULL , ( void * * ) & n , NULL ) ) {
char buf [ 1024 ] ;
sprintf ( buf , " %s(%s) " , n , tagName ( tag ) ) ;
t - > t_msgid = xstrdup ( buf ) ;
}
}
}
/*@-usereleased -compdef@*/
return t ;
/*@=usereleased =compdef@*/
}
# define SINGLE_TOKEN_ONLY \
if ( multiToken ) { \
rpmError ( RPMERR_BADSPEC , _ ( " line %d: Tag takes single token only: %s \n " ) , \
spec - > lineNum , spec - > line ) ; \
return RPMERR_BADSPEC ; \
}
/*@-redecl@*/
extern int noLang ;
/*@=redecl@*/
/**
*/
static int handlePreambleTag ( Spec spec , Package pkg , int tag , const char * macro ,
const char * lang )
/*@globals rpmGlobalMacroContext,
fileSystem @ */
/*@modifies spec->macros, spec->st, spec->buildRootURL,
spec - > sources , spec - > numSources , spec - > noSource ,
spec - > buildRestrictions , spec - > BANames , spec - > BACount ,
spec - > line , spec - > gotBuildRootURL ,
pkg - > header , pkg - > autoProv , pkg - > autoReq , pkg - > icon ,
rpmGlobalMacroContext , fileSystem @ */
{
HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
HFD_t hfd = headerFreeData ;
char * field = spec - > line ;
char * end ;
char * * array ;
int multiToken = 0 ;
rpmsenseFlags tagflags ;
rpmTagType type ;
int len ;
int num ;
int rc ;
int xx ;
if ( field = = NULL ) return RPMERR_BADSPEC ; /* XXX can't happen */
/* Find the start of the "field" and strip trailing space */
while ( ( * field ) & & ( * field ! = ' : ' ) )
field + + ;
if ( * field ! = ' : ' ) {
rpmError ( RPMERR_BADSPEC , _ ( " line %d: Malformed tag: %s \n " ) ,
spec - > lineNum , spec - > line ) ;
return RPMERR_BADSPEC ;
}
field + + ;
SKIPSPACE ( field ) ;
if ( ! * field ) {
/* Empty field */
rpmError ( RPMERR_BADSPEC , _ ( " line %d: Empty tag: %s \n " ) ,
spec - > lineNum , spec - > line ) ;
return RPMERR_BADSPEC ;
}
end = findLastChar ( field ) ;
* ( end + 1 ) = ' \0 ' ;
/* See if this is multi-token */
end = field ;
SKIPNONSPACE ( end ) ;
if ( * end ! = ' \0 ' )
multiToken = 1 ;
switch ( tag ) {
case RPMTAG_NAME :
case RPMTAG_VERSION :
case RPMTAG_RELEASE :
case RPMTAG_URL :
case RPMTAG_RHNPLATFORM :
SINGLE_TOKEN_ONLY ;
/* These macros are for backward compatibility */
if ( tag = = RPMTAG_VERSION ) {
if ( strchr ( field , ' - ' ) ! = NULL ) {
rpmError ( RPMERR_BADSPEC , _ ( " line %d: Illegal char '-' in %s: %s \n " ) ,
spec - > lineNum , " version " , spec - > line ) ;
return RPMERR_BADSPEC ;
}
addMacro ( spec - > macros , " PACKAGE_VERSION " , NULL , field , RMIL_OLDSPEC ) ;
} else if ( tag = = RPMTAG_RELEASE ) {
if ( strchr ( field , ' - ' ) ! = NULL ) {
rpmError ( RPMERR_BADSPEC , _ ( " line %d: Illegal char '-' in %s: %s \n " ) ,
spec - > lineNum , " release " , spec - > line ) ;
return RPMERR_BADSPEC ;
}
addMacro ( spec - > macros , " PACKAGE_RELEASE " , NULL , field , RMIL_OLDSPEC - 1 ) ;
}
( void ) headerAddEntry ( pkg - > header , tag , RPM_STRING_TYPE , field , 1 ) ;
break ;
case RPMTAG_GROUP :
case RPMTAG_SUMMARY :
( void ) stashSt ( spec , pkg - > header , tag , lang ) ;
/*@fallthrough@*/
case RPMTAG_DISTRIBUTION :
case RPMTAG_VENDOR :
case RPMTAG_LICENSE :
case RPMTAG_PACKAGER :
2002-06-13 15:28:05 +04:00
case RPMTAG_BUILDHOST :
2002-03-25 23:16:26 +03:00
if ( ! * lang )
( void ) headerAddEntry ( pkg - > header , tag , RPM_STRING_TYPE , field , 1 ) ;
else if ( ! ( noLang & & strcmp ( lang , RPMBUILD_DEFAULT_LANG ) ) )
( void ) headerAddI18NString ( pkg - > header , tag , field , lang ) ;
break ;
case RPMTAG_BUILDROOT :
SINGLE_TOKEN_ONLY ;
{ const char * buildRoot = NULL ;
const char * buildRootURL = spec - > buildRootURL ;
/*
* Note : rpmGenPath should guarantee a " canonical " path . That means
* that the following pathologies should be weeded out :
* //bin//sh
* //usr//bin/
* / . . / . / . . / usr / . . / bin //./sh
*/
if ( buildRootURL = = NULL ) {
buildRootURL = rpmGenPath ( NULL , " %{?buildroot:%{buildroot}} " , NULL ) ;
if ( strcmp ( buildRootURL , " / " ) ) {
spec - > buildRootURL = buildRootURL ;
2002-03-26 01:57:16 +03:00
spec - > gotBuildRootURL = 1 ;
2002-03-25 23:16:26 +03:00
}
}
2002-03-26 01:57:16 +03:00
macro = NULL ;
2002-03-25 23:16:26 +03:00
buildRootURL = rpmGenPath ( NULL , spec - > buildRootURL , NULL ) ;
( void ) urlPath ( buildRootURL , & buildRoot ) ;
/*@-branchstate@*/
if ( * buildRoot = = ' \0 ' ) buildRoot = " / " ;
/*@=branchstate@*/
if ( ! strcmp ( buildRoot , " / " ) ) {
rpmError ( RPMERR_BADSPEC ,
_ ( " BuildRoot can not be \" / \" : %s \n " ) , spec - > buildRootURL ) ;
buildRootURL = _free ( buildRootURL ) ;
return RPMERR_BADSPEC ;
}
buildRootURL = _free ( buildRootURL ) ;
} break ;
case RPMTAG_PREFIXES :
addOrAppendListEntry ( pkg - > header , tag , field ) ;
xx = hge ( pkg - > header , tag , & type , ( void * * ) & array , & num ) ;
while ( num - - ) {
len = strlen ( array [ num ] ) ;
if ( array [ num ] [ len - 1 ] = = ' / ' & & len > 1 ) {
rpmError ( RPMERR_BADSPEC ,
_ ( " line %d: Prefixes must not end with \" / \" : %s \n " ) ,
spec - > lineNum , spec - > line ) ;
array = hfd ( array , type ) ;
return RPMERR_BADSPEC ;
}
}
array = hfd ( array , type ) ;
break ;
case RPMTAG_DOCDIR :
SINGLE_TOKEN_ONLY ;
if ( field [ 0 ] ! = ' / ' ) {
rpmError ( RPMERR_BADSPEC ,
_ ( " line %d: Docdir must begin with '/': %s \n " ) ,
spec - > lineNum , spec - > line ) ;
return RPMERR_BADSPEC ;
}
macro = NULL ;
delMacro ( NULL , " _docdir " ) ;
addMacro ( NULL , " _docdir " , NULL , field , RMIL_SPEC ) ;
break ;
case RPMTAG_EPOCH :
SINGLE_TOKEN_ONLY ;
if ( parseNum ( field , & num ) ) {
rpmError ( RPMERR_BADSPEC ,
_ ( " line %d: Epoch/Serial field must be a number: %s \n " ) ,
spec - > lineNum , spec - > line ) ;
return RPMERR_BADSPEC ;
}
xx = headerAddEntry ( pkg - > header , tag , RPM_INT32_TYPE , & num , 1 ) ;
break ;
case RPMTAG_AUTOREQPROV :
2002-03-26 01:57:16 +03:00
pkg - > autoReq = parseReqProv ( field ) ;
pkg - > autoProv = xstrdup ( pkg - > autoReq ) ;
2002-03-25 23:16:26 +03:00
break ;
case RPMTAG_AUTOREQ :
2002-03-26 01:57:16 +03:00
pkg - > autoReq = parseReqProv ( field ) ;
2002-03-25 23:16:26 +03:00
break ;
case RPMTAG_AUTOPROV :
2002-03-26 01:57:16 +03:00
pkg - > autoProv = parseReqProv ( field ) ;
2002-03-25 23:16:26 +03:00
break ;
case RPMTAG_SOURCE :
case RPMTAG_PATCH :
SINGLE_TOKEN_ONLY ;
macro = NULL ;
if ( ( rc = addSource ( spec , pkg , field , tag ) ) )
return rc ;
break ;
case RPMTAG_ICON :
SINGLE_TOKEN_ONLY ;
if ( ( rc = addSource ( spec , pkg , field , tag ) ) )
return rc ;
2003-07-20 16:51:57 +04:00
# ifdef ENABLE_ICON_TAG
2002-03-26 01:57:16 +03:00
if ( ! spec - > preprocess_mode ) {
if ( ( rc = readIcon ( pkg - > header , field ) ) )
return RPMERR_BADSPEC ;
}
2003-07-20 16:51:57 +04:00
# endif /* ENABLE_ICON_TAG */
2002-03-25 23:16:26 +03:00
break ;
case RPMTAG_NOSOURCE :
case RPMTAG_NOPATCH :
spec - > noSource = 1 ;
if ( ( rc = parseNoSource ( spec , field , tag ) ) )
return rc ;
break ;
case RPMTAG_BUILDPREREQ :
case RPMTAG_BUILDREQUIRES :
if ( ( rc = parseBits ( lang , buildScriptBits , & tagflags ) ) ) {
rpmError ( RPMERR_BADSPEC ,
_ ( " line %d: Bad %s: qualifiers: %s \n " ) ,
spec - > lineNum , tagName ( tag ) , spec - > line ) ;
return rc ;
}
if ( ( rc = parseRCPOT ( spec , pkg , field , tag , 0 , tagflags ) ) )
return rc ;
break ;
case RPMTAG_REQUIREFLAGS :
case RPMTAG_PREREQ :
if ( ( rc = parseBits ( lang , installScriptBits , & tagflags ) ) ) {
rpmError ( RPMERR_BADSPEC ,
_ ( " line %d: Bad %s: qualifiers: %s \n " ) ,
spec - > lineNum , tagName ( tag ) , spec - > line ) ;
return rc ;
}
if ( ( rc = parseRCPOT ( spec , pkg , field , tag , 0 , tagflags ) ) )
return rc ;
break ;
case RPMTAG_BUILDCONFLICTS :
case RPMTAG_CONFLICTFLAGS :
case RPMTAG_OBSOLETEFLAGS :
case RPMTAG_PROVIDEFLAGS :
tagflags = RPMSENSE_ANY ;
if ( ( rc = parseRCPOT ( spec , pkg , field , tag , 0 , tagflags ) ) )
return rc ;
break ;
case RPMTAG_EXCLUDEARCH :
case RPMTAG_EXCLUSIVEARCH :
case RPMTAG_EXCLUDEOS :
case RPMTAG_EXCLUSIVEOS :
addOrAppendListEntry ( spec - > buildRestrictions , tag , field ) ;
break ;
case RPMTAG_BUILDARCHS :
if ( ( rc = poptParseArgvString ( field ,
& ( spec - > BACount ) ,
& ( spec - > BANames ) ) ) ) {
rpmError ( RPMERR_BADSPEC ,
_ ( " line %d: Bad BuildArchitecture format: %s \n " ) ,
spec - > lineNum , spec - > line ) ;
return RPMERR_BADSPEC ;
}
if ( ! spec - > BACount )
spec - > BANames = _free ( spec - > BANames ) ;
break ;
default :
rpmError ( RPMERR_INTERNAL , _ ( " Internal error: Bogus tag %d \n " ) , tag ) ;
return RPMERR_INTERNAL ;
}
if ( macro )
addMacro ( spec - > macros , macro , NULL , field , RMIL_SPEC ) ;
return 0 ;
}
/* This table has to be in a peculiar order. If one tag is the */
/* same as another, plus a few letters, it must come first. */
/**
*/
typedef struct PreambleRec_s {
rpmTag tag ;
int len ;
int multiLang ;
/*@observer@*/ /*@null@*/ const char * token ;
} * PreambleRec ;
/*@unchecked@*/
static struct PreambleRec_s preambleList [ ] = {
{ RPMTAG_NAME , 0 , 0 , " name " } ,
{ RPMTAG_VERSION , 0 , 0 , " version " } ,
{ RPMTAG_RELEASE , 0 , 0 , " release " } ,
{ RPMTAG_EPOCH , 0 , 0 , " epoch " } ,
{ RPMTAG_EPOCH , 0 , 0 , " serial " } ,
{ RPMTAG_SUMMARY , 0 , 1 , " summary " } ,
{ RPMTAG_LICENSE , 0 , 0 , " copyright " } ,
{ RPMTAG_LICENSE , 0 , 0 , " license " } ,
{ RPMTAG_DISTRIBUTION , 0 , 0 , " distribution " } ,
{ RPMTAG_DISTURL , 0 , 0 , " disturl " } ,
2002-06-13 15:28:05 +04:00
{ RPMTAG_BUILDHOST , 0 , 0 , " buildhost " } ,
2002-03-25 23:16:26 +03:00
{ RPMTAG_VENDOR , 0 , 0 , " vendor " } ,
{ RPMTAG_GROUP , 0 , 1 , " group " } ,
{ RPMTAG_PACKAGER , 0 , 0 , " packager " } ,
{ RPMTAG_URL , 0 , 0 , " url " } ,
{ RPMTAG_SOURCE , 0 , 0 , " source " } ,
{ RPMTAG_PATCH , 0 , 0 , " patch " } ,
{ RPMTAG_NOSOURCE , 0 , 0 , " nosource " } ,
{ RPMTAG_NOPATCH , 0 , 0 , " nopatch " } ,
{ RPMTAG_EXCLUDEARCH , 0 , 0 , " excludearch " } ,
{ RPMTAG_EXCLUSIVEARCH , 0 , 0 , " exclusivearch " } ,
{ RPMTAG_EXCLUDEOS , 0 , 0 , " excludeos " } ,
{ RPMTAG_EXCLUSIVEOS , 0 , 0 , " exclusiveos " } ,
{ RPMTAG_ICON , 0 , 0 , " icon " } ,
{ RPMTAG_PROVIDEFLAGS , 0 , 0 , " provides " } ,
{ RPMTAG_REQUIREFLAGS , 0 , 1 , " requires " } ,
{ RPMTAG_PREREQ , 0 , 1 , " prereq " } ,
{ RPMTAG_CONFLICTFLAGS , 0 , 0 , " conflicts " } ,
{ RPMTAG_OBSOLETEFLAGS , 0 , 0 , " obsoletes " } ,
{ RPMTAG_PREFIXES , 0 , 0 , " prefixes " } ,
{ RPMTAG_PREFIXES , 0 , 0 , " prefix " } ,
{ RPMTAG_BUILDROOT , 0 , 0 , " buildroot " } ,
{ RPMTAG_BUILDARCHS , 0 , 0 , " buildarchitectures " } ,
{ RPMTAG_BUILDARCHS , 0 , 0 , " buildarch " } ,
{ RPMTAG_BUILDCONFLICTS , 0 , 0 , " buildconflicts " } ,
{ RPMTAG_BUILDPREREQ , 0 , 1 , " buildprereq " } ,
{ RPMTAG_BUILDREQUIRES , 0 , 1 , " buildrequires " } ,
{ RPMTAG_AUTOREQPROV , 0 , 0 , " autoreqprov " } ,
{ RPMTAG_AUTOREQ , 0 , 0 , " autoreq " } ,
{ RPMTAG_AUTOPROV , 0 , 0 , " autoprov " } ,
{ RPMTAG_DOCDIR , 0 , 0 , " docdir " } ,
{ RPMTAG_RHNPLATFORM , 0 , 0 , " rhnplatform " } ,
/*@-nullassign@*/ /* LCL: can't add null annotation */
{ 0 , 0 , 0 , 0 }
/*@=nullassign@*/
} ;
/**
*/
static inline void initPreambleList ( void )
/*@globals preambleList @*/
/*@modifies preambleList @*/
{
PreambleRec p ;
for ( p = preambleList ; p - > token ! = NULL ; p + + )
if ( p - > token ) p - > len = strlen ( p - > token ) ;
}
/**
*/
static int findPreambleTag ( Spec spec , /*@out@*/ int * tag ,
/*@null@*/ /*@out@*/ const char * * macro , /*@out@*/ char * lang )
/*@modifies *tag, *macro, *lang @*/
{
PreambleRec p ;
char * s ;
if ( preambleList [ 0 ] . len = = 0 )
initPreambleList ( ) ;
for ( p = preambleList ; p - > token ! = NULL ; p + + ) {
if ( p - > token & & ! xstrncasecmp ( spec - > line , p - > token , p - > len ) )
break ;
}
if ( p - > token = = NULL )
return 1 ;
s = spec - > line + p - > len ;
SKIPSPACE ( s ) ;
switch ( p - > multiLang ) {
default :
case 0 :
/* Unless this is a source or a patch, a ':' better be next */
if ( p - > tag ! = RPMTAG_SOURCE & & p - > tag ! = RPMTAG_PATCH ) {
if ( * s ! = ' : ' ) return 1 ;
}
* lang = ' \0 ' ;
break ;
case 1 : /* Parse optional ( <token> ). */
if ( * s = = ' : ' ) {
strcpy ( lang , RPMBUILD_DEFAULT_LANG ) ;
break ;
}
if ( * s ! = ' ( ' ) return 1 ;
s + + ;
SKIPSPACE ( s ) ;
while ( ! xisspace ( * s ) & & * s ! = ' ) ' )
* lang + + = * s + + ;
* lang = ' \0 ' ;
SKIPSPACE ( s ) ;
if ( * s ! = ' ) ' ) return 1 ;
s + + ;
SKIPSPACE ( s ) ;
if ( * s ! = ' : ' ) return 1 ;
break ;
}
* tag = p - > tag ;
if ( macro )
/*@-onlytrans -observertrans -dependenttrans@*/ /* FIX: double indirection. */
* macro = p - > token ;
/*@=onlytrans =observertrans =dependenttrans@*/
return 0 ;
}
int parsePreamble ( Spec spec , int initialPackage )
{
int nextPart ;
int tag , rc , xx ;
char * name , * linep ;
int flag ;
Package pkg ;
char NVR [ BUFSIZ ] ;
char lang [ BUFSIZ ] ;
strcpy ( NVR , " (main package) " ) ;
pkg = newPackage ( spec ) ;
if ( ! initialPackage ) {
/* There is one option to %package: <pkg> or -n <pkg> */
if ( parseSimplePart ( spec - > line , & name , & flag ) ) {
rpmError ( RPMERR_BADSPEC , _ ( " Bad package specification: %s \n " ) ,
spec - > line ) ;
return RPMERR_BADSPEC ;
}
if ( ! lookupPackage ( spec , name , flag , NULL ) ) {
rpmError ( RPMERR_BADSPEC , _ ( " Package already exists: %s \n " ) ,
spec - > line ) ;
return RPMERR_BADSPEC ;
}
/* Construct the package */
if ( flag = = PART_SUBNAME ) {
const char * mainName ;
xx = headerNVR ( spec - > packages - > header , & mainName , NULL , NULL ) ;
sprintf ( NVR , " %s-%s " , mainName , name ) ;
} else
strcpy ( NVR , name ) ;
xx = headerAddEntry ( pkg - > header , RPMTAG_NAME , RPM_STRING_TYPE , NVR , 1 ) ;
}
2005-10-06 19:24:35 +04:00
if ( ( rc = readLine ( spec , STRIP_TRAILINGSPACE | STRIP_COMMENTS ) ) = = 1 ) {
2002-03-25 23:16:26 +03:00
nextPart = PART_NONE ;
} else {
if ( rc )
return rc ;
while ( ! ( nextPart = isPart ( spec - > line ) ) ) {
const char * macro ;
/* Skip blank lines */
linep = spec - > line ;
SKIPSPACE ( linep ) ;
if ( * linep ! = ' \0 ' ) {
if ( findPreambleTag ( spec , & tag , & macro , lang ) ) {
rpmError ( RPMERR_BADSPEC , _ ( " line %d: Unknown tag: %s \n " ) ,
spec - > lineNum , spec - > line ) ;
return RPMERR_BADSPEC ;
}
if ( handlePreambleTag ( spec , pkg , tag , macro , lang ) )
return RPMERR_BADSPEC ;
if ( spec - > BANames & & ! spec - > recursing )
return PART_BUILDARCHITECTURES ;
}
if ( ( rc =
2005-10-06 19:24:35 +04:00
readLine ( spec , STRIP_TRAILINGSPACE | STRIP_COMMENTS ) ) = = 1 ) {
2002-03-25 23:16:26 +03:00
nextPart = PART_NONE ;
break ;
}
if ( rc )
return rc ;
}
}
/* Do some final processing on the header */
if ( ! spec - > gotBuildRootURL & & spec - > buildRootURL ) {
rpmError ( RPMERR_BADSPEC , _ ( " Spec file can't use BuildRoot \n " ) ) ;
return RPMERR_BADSPEC ;
}
2002-03-26 01:57:16 +03:00
if ( ! spec - > buildRootURL ) {
spec - > buildRootURL = rpmGenPath ( NULL , " %{?buildroot:%{buildroot}} " , NULL ) ;
if ( strcmp ( spec - > buildRootURL , " / " ) )
spec - > gotBuildRootURL = 1 ;
else
{
spec - > buildRootURL = NULL ;
rpmError ( RPMERR_BADSPEC , _ ( " Neither spec file nor macros define BuildRoot " ) ) ;
return RPMERR_BADSPEC ;
}
}
2002-03-25 23:16:26 +03:00
/* XXX Skip valid arch check if not building binary package */
if ( ! spec - > anyarch & & checkForValidArchitectures ( spec ) )
return RPMERR_BADSPEC ;
if ( pkg = = spec - > packages )
fillOutMainPackage ( pkg - > header ) ;
if ( checkForDuplicates ( pkg - > header , NVR ) )
return RPMERR_BADSPEC ;
if ( pkg ! = spec - > packages )
headerCopyTags ( spec - > packages - > header , pkg - > header ,
( int_32 * ) copyTagsDuringParse ) ;
if ( checkForRequired ( pkg - > header , NVR ) )
return RPMERR_BADSPEC ;
return nextPart ;
}