Sorry for replying to myself, but I found that the restriction that global
substitution sets must precede file substitution sets is too, well,
restrictive. In fact, I found a place where we use the /dev/null trick twice
in two separate locations in the same substitution files.
I have attached a new version of msi.c that allows mixing file and global
sections. The semantics is that definitions inside a global section are
valid from the point of definition to the rest of the file, except where
overwritten by other global definitions or shadowed by local ones (in file
sections).
(Also attached is a patch relative to the last version I sent.)
Cheers
Ben
Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
Hahn-Meitner-Platz 1, 14109 Berlin
Vorsitzende des Aufsichtsrates: Prof. Dr. Dr. h.c. mult. Joachim Treusch
Stellvertretende Vorsitzende: Dr. Beatrix Vierkorn-Rudolph Geschäftsführer: Prof. Dr. Anke Rita Kaysser-Pyzalla, Prof. Dr. Dr. h.c. Wolfgang Eberhardt, Dr. Ulrich Breuer
Sitz der Gesellschaft: Berlin Handelsregister: AG Charlottenburg, 89 HRB 5583
Disclaimer automatically attached by the E-Mail Security Appliance
mail0.bessy.de 08/23/10 at Helmholtz-Zentrum Berlin GmbH.
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* This file is distributed subject to a Software License Agreement found
* in the file LICENSE that is included with this distribution.
\*************************************************************************/
/*msi - macro sunstitutions and include */
/*
* Modification Log:
* -----------------
* .01 08DEC97 mrk Original version
*/
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <dbDefs.h>
#include <macLib.h>
#include <ellLib.h>
#define MAX_BUFFER_SIZE 4096
#if ((EPICS_VERSION <= 3) && (EPICS_REVISION <= 13))
#define macEnvExpand(x) strdup(x)
#endif
/*Forward references to local routines*/
static void usageExit(void);
static void addMacroReplacements(MAC_HANDLE *macPvt,char *pval);
static void makeSubstitutions(void *inputPvt,void *macPvt,char *templateName);
/*Routines that read the template files */
static void inputConstruct(void **inputPvt);
static void inputDestruct(void *inputPvt);
static void inputAddPath(void *inputPvt, char *pval);
static void inputBegin(void *inputPvt,char *fileName);
static char *inputNextLine(void *inputPvt);
static void inputNewIncludeFile(void *inputPvt,char *name);
static void inputErrPrint(void *inputPvt);
/*Routines that read the substitution file */
static void substituteDestruct(void *substitutePvt);
static void substituteOpen(void **substitutePvt,char *substitutionName);
static int substituteGetNextSet(void *substitutePvt,char **filename);
static int substituteGetGlobalSet(void *substitutePvt);
static char *substituteGetReplacements(void *substitutePvt);
/*Exit status*/
static int exitStatus = 0;
int main(int argc,char **argv)
{
void *inputPvt;
MAC_HANDLE *macPvt;
char *pval;
int narg;
char *substitutionName=0;
char *templateName=0;
int i;
int optScoped=0;
inputConstruct(&inputPvt);
macCreateHandle(&macPvt,0);
macSuppressWarning(macPvt,1);
while((argc>1) && (argv[1][0] == '-')) {
narg = (strlen(argv[1])==2) ? 2 : 1;
pval = (narg==1) ? (argv[1]+2) : argv[2];
if(strncmp(argv[1],"-I",2)==0) {
inputAddPath(inputPvt,pval);
} else if(strncmp(argv[1],"-o",2)==0) {
if(freopen(pval,"w",stdout)==NULL) {
fprintf(stderr,"Can't open %s for writing: %s\n", pval, strerror(errno));
exit(1);
}
} else if(strncmp(argv[1],"-M",2)==0) {
addMacroReplacements(macPvt,pval);
} else if(strncmp(argv[1],"-S",2)==0) {
substitutionName = calloc(strlen(pval)+1,sizeof(char));
strcpy(substitutionName,pval);
} else if(strncmp(argv[1],"-V",2)==0) {
macSuppressWarning(macPvt,0);
narg = 1; /* no argument for this option */
} else if(strncmp(argv[1],"-c",2)==0) {
optScoped = 1;
narg = 1; /* no argument for this option */
} else {
usageExit();
}
argc -= narg;
for(i=1; i<argc; i++) argv[i] = argv[i + narg];
}
if(argc>2) {
fprintf(stderr,"too many filename arguments\n");
usageExit();
}
if(argc==2) {
templateName = calloc(strlen(argv[1])+1,sizeof(char));
strcpy(templateName,argv[1]);
}
if(!substitutionName) {
makeSubstitutions(inputPvt,macPvt,templateName);
} else {
void *substitutePvt;
char *filename = 0;
int isGlobal, isFile;
substituteOpen(&substitutePvt,substitutionName);
do {
if ((isGlobal = substituteGetGlobalSet(substitutePvt))) {
pval = substituteGetReplacements(substitutePvt);
if(pval) {
addMacroReplacements(macPvt,pval);
}
} else if ((isFile = substituteGetNextSet(substitutePvt,&filename))) {
if(templateName) filename = templateName;
if(!filename) {
fprintf(stderr,"no template file\n");
usageExit();
}
if (optScoped) macPushScope(macPvt);
while((pval = substituteGetReplacements(substitutePvt))){
addMacroReplacements(macPvt,pval);
makeSubstitutions(inputPvt,macPvt,filename);
}
if (optScoped) macPopScope(macPvt);
}
} while (isGlobal || isFile);
substituteDestruct(substitutePvt);
}
inputDestruct(inputPvt);
free((void *)templateName);
free((void *)substitutionName);
return(exitStatus);
}
void usageExit(void)
{
fprintf(stderr,"usage: msi [options] template\n");
fprintf(stderr,"stdin is used if neither template nor substitution file is given\n");
fprintf(stderr,"options:\n");
fprintf(stderr," -V don't suppress warnings\n");
fprintf(stderr," -o<DIR> place output file in directory <DIR> (default is '.')\n");
fprintf(stderr," -I<DIR> add <DIR> to include file search path\n");
fprintf(stderr," -M<SUBST> add <SUBST> to (global) macro definitions\n");
fprintf(stderr," (<SUBST> is of the form VAR=VALUE,...)\n");
fprintf(stderr," -S<PATH> expand a substitution file\n");
fprintf(stderr," -c macro definitions are scoped (in substitution files)\n");
exit(1);
}
static void addMacroReplacements(MAC_HANDLE *macPvt,char *pval)
{
char **pairs;
long status;
status = macParseDefns(macPvt,pval,&pairs);
if(status==-1) {
fprintf(stderr,"Error macParseDefns error\n");
usageExit();
}
if(status) {
status = macInstallMacros(macPvt,pairs);
if(!status) {
fprintf(stderr,"Error macInstallMacros error\n");
usageExit();
}
free((void *)pairs);
}
}
typedef enum {cmdInclude,cmdSubstitute} cmdType;
static const char *cmdNames[] = {"include","substitute"};
static void makeSubstitutions(void *inputPvt,void *macPvt,char *templateName)
{
char *input;
static char buffer[MAX_BUFFER_SIZE];
int n;
static int unexpWarned = 0;
inputBegin(inputPvt,templateName);
while((input = inputNextLine(inputPvt))) {
int expand=1;
char *p;
char *command = 0;
p = input;
/*skip whitespace at beginning of line*/
while(*p && (isspace(*p))) ++p;
/*Look for i or s */
if(*p && (*p=='i' || *p=='s')) command = p;
if(command) {
char *pstart;
char *pend;
char *copy;
int cmdind=-1;
int i;
for(i=0; i< NELEMENTS(cmdNames); i++) {
if(strstr(command,cmdNames[i])) {
cmdind = i;
}
}
if(cmdind<0) goto endif;
p = command + strlen(cmdNames[cmdind]);
/*skip whitespace after command*/
while(*p && (isspace(*p))) ++p;
/*Next character must be quote*/
if((*p==0) || (*p!='"')) goto endif;
pstart = ++p;
/*Look for end quote*/
while(*p && (*p!='"')) {
/*allow escape for imbeded quote*/
if((*p=='\\') && *(p+1)=='"') {
p += 2; continue;
} else {
if(*p=='"') break;
}
++p;
}
pend = p;
if(*p==0) goto endif;
/*skip quote and any trailing blanks*/
while(*++p==' ') ;
if(*p != '\n' && *p !=0) goto endif;
copy = calloc(pend-pstart+1,sizeof(char));
strncpy(copy,pstart,pend-pstart);
switch(cmdind) {
case cmdInclude:
inputNewIncludeFile(inputPvt,copy);
break;
case cmdSubstitute:
addMacroReplacements(macPvt,copy);
break;
default:
fprintf(stderr,"Logic Error: makeSubstitutions\n");
inputErrPrint(inputPvt);
exit(1);
}
free(copy);
expand = 0;
}
endif:
if (expand) {
n = macExpandString(macPvt,input,buffer,MAX_BUFFER_SIZE-1);
fputs(buffer,stdout);
if (!unexpWarned && n<0) {
fprintf(stderr,"Warning: unexpanded macros in ouput\n");
unexpWarned++;
}
}
}
}
typedef struct inputFile{
ELLNODE node;
char *filename;
FILE *fp;
int lineNum;
}inputFile;
typedef struct pathNode {
ELLNODE node;
char *directory;
} pathNode;
typedef struct inputData {
ELLLIST inputFileList;
ELLLIST pathList;
char inputBuffer[MAX_BUFFER_SIZE];
}inputData;
static void inputOpenFile(inputData *pinputData,char *filename);
static void inputCloseFile(inputData *pinputData);
static void inputCloseAllFiles(inputData *pinputData);
static void inputConstruct(void **ppvt)
{
inputData *pinputData;
pinputData = calloc(1,sizeof(inputData));
ellInit(&pinputData->inputFileList);
ellInit(&pinputData->pathList);
*ppvt = pinputData;
}
static void inputDestruct(void *pvt)
{
inputData *pinputData = (inputData *)pvt;
pathNode *ppathNode;
inputCloseAllFiles(pinputData);
while((ppathNode = (pathNode *)ellFirst(&pinputData->pathList))) {
ellDelete(&pinputData->pathList,&ppathNode->node);
free((void *)ppathNode->directory);
free((void *)ppathNode);
}
free(pvt);
}
static void inputAddPath(void *pvt, char *path)
{
inputData *pinputData = (inputData *)pvt;
ELLLIST *ppathList = &pinputData->pathList;
pathNode *ppathNode;
const char *pcolon;
const char *pdir;
int len;
int emptyName;
pdir = path;
/*an empty name at beginning, middle, or end means current directory*/
while(pdir && *pdir) {
emptyName = ((*pdir == ':') ? 1 : 0);
if(emptyName) ++pdir;
ppathNode = (pathNode *)calloc(1,sizeof(pathNode));
ellAdd(ppathList,&ppathNode->node);
if(!emptyName) {
pcolon = strchr(pdir,':');
len = (pcolon ? (pcolon - pdir) : strlen(pdir));
if(len>0) {
ppathNode->directory = (char *)calloc(len+1,sizeof(char));
strncpy(ppathNode->directory,pdir,len);
pdir = pcolon;
/*unless at end skip past first colon*/
if(pdir && *(pdir+1)!=0) ++pdir;
} else { /*must have been trailing : */
emptyName=1;
}
}
if(emptyName) {
ppathNode->directory = (char *)calloc(2,sizeof(char));
strcpy(ppathNode->directory,".");
}
}
return;
}
static void inputBegin(void *pvt,char *fileName)
{
inputData *pinputData = (inputData *)pvt;
inputCloseAllFiles(pinputData);
inputOpenFile(pinputData,fileName);
}
static char *inputNextLine(void *pvt)
{
inputData *pinputData = (inputData *)pvt;
inputFile *pinputFile;
char *pline;
while((pinputFile = (inputFile *)ellFirst(&pinputData->inputFileList))) {
pline = fgets(pinputData->inputBuffer,MAX_BUFFER_SIZE,pinputFile->fp);
if(pline) {
++pinputFile->lineNum;
return(pline);
}
inputCloseFile(pinputData);
}
return(0);
}
static void inputNewIncludeFile(void *pvt,char *name)
{
inputData *pinputData = (inputData *)pvt;
inputOpenFile(pinputData,name);
}
static void inputErrPrint(void *pvt)
{
inputData *pinputData = (inputData *)pvt;
inputFile *pinputFile;
fprintf(stderr,"input: %s which is ",pinputData->inputBuffer);
pinputFile = (inputFile *)ellFirst(&pinputData->inputFileList);
while(pinputFile) {
fprintf(stderr,"line %d of ",pinputFile->lineNum);
if(pinputFile->filename) {
fprintf(stderr," file %s\n",pinputFile->filename);
} else {
fprintf(stderr,"stdin:\n");
}
pinputFile = (inputFile *)ellNext(&pinputFile->node);
if(pinputFile) {
fprintf(stderr," which is included from ");
} else {
fprintf(stderr,"\n");
}
}
fprintf(stderr,"\n");
}
static void inputOpenFile(inputData *pinputData,char *filename)
{
ELLLIST *ppathList = &pinputData->pathList;
pathNode *ppathNode = 0;
inputFile *pinputFile;
char *fullname = 0;
FILE *fp = 0;
if(!filename) {
fp = stdin;
} else if((ellCount(ppathList)==0) || strchr(filename,'/')){
fp = fopen(filename,"r");
} else {
ppathNode = (pathNode *)ellFirst(ppathList);
while(ppathNode) {
fullname = calloc(strlen(filename)+strlen(ppathNode->directory) +2,
sizeof(char));
strcpy(fullname,ppathNode->directory);
strcat(fullname,"/");
strcat(fullname,filename);
fp = fopen(fullname,"r");
if(fp) break;
free((void *)fullname);
ppathNode = (pathNode *)ellNext(&ppathNode->node);
}
}
if(!fp) {
fprintf(stderr,"Could not open %s\n",filename);
inputErrPrint((void *)pinputData);
exit(1);
}
pinputFile = calloc(1,sizeof(inputFile));
if(ppathNode) {
pinputFile->filename = calloc(1,strlen(fullname)+1);
strcpy(pinputFile->filename,fullname);
free((void *)fullname);
} else if(filename) {
pinputFile->filename = calloc(1,strlen(filename)+1);
strcpy(pinputFile->filename,filename);
} else {
pinputFile->filename = calloc(1,strlen("stdin")+1);
strcpy(pinputFile->filename,"stdin");
}
pinputFile->fp = fp;
ellInsert(&pinputData->inputFileList,0,&pinputFile->node);
}
static void inputCloseFile(inputData *pinputData)
{
inputFile *pinputFile;
pinputFile = (inputFile *)ellFirst(&pinputData->inputFileList);
if(!pinputFile) return;
ellDelete(&pinputData->inputFileList,&pinputFile->node);
if(fclose(pinputFile->fp))
fprintf(stderr,"fclose failed: file %s\n",pinputFile->filename);
free(pinputFile->filename);
free(pinputFile);
}
static void inputCloseAllFiles(inputData *pinputData)
{
inputFile *pinputFile;
while((pinputFile=(inputFile *)ellFirst(&pinputData->inputFileList))){
inputCloseFile(pinputData);
}
}
/*start of code that handles substitution file*/
typedef enum {
tokenLBrace,tokenRBrace,tokenSeparater,tokenString,tokenEOF
}tokenType;
typedef struct subFile {
char *substitutionName;
FILE *fp;
int lineNum;
char inputBuffer[MAX_BUFFER_SIZE];
char *pnextChar;
tokenType token;
char string[MAX_BUFFER_SIZE];
} subFile;
typedef struct patternNode {
ELLNODE node;
char *var;
}patternNode;
typedef struct subInfo {
subFile *psubFile;
int isFile;
char *filename;
int isPattern;
ELLLIST patternList;
size_t size;
size_t curLength;
char *macroReplacements;
}subInfo;
static char *subGetNextLine(subFile *psubFile);
static tokenType subGetNextToken(subFile *psubFile);
static void subFileErrPrint(subFile *psubFile,char * message);
static void freeSubFile(subInfo *psubInfo);
static void freePattern(subInfo *psubInfo);
static void catMacroReplacements(subInfo *psubInfo,const char *value);
void freeSubFile(subInfo *psubInfo)
{
subFile *psubFile = psubInfo->psubFile;
if(psubFile->fp) {
if(fclose(psubFile->fp))
fprintf(stderr,"fclose failed on substitution file\n");
}
free((void *)psubFile);
free((void *)psubInfo->filename);
psubInfo->psubFile = 0;
}
void freePattern(subInfo *psubInfo)
{
patternNode *ppatternNode;
while((ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList))) {
ellDelete(&psubInfo->patternList,&ppatternNode->node);
free(ppatternNode->var);
free(ppatternNode);
}
psubInfo->isPattern = 0;
}
static void substituteDestruct(void *pvt)
{
subInfo *psubInfo = (subInfo *)pvt;
freeSubFile(psubInfo);
freePattern(psubInfo);
free((void *)psubInfo);
return;
}
static void substituteOpen(void **ppvt,char *substitutionName)
{
subInfo *psubInfo;
subFile *psubFile;
FILE *fp;
psubInfo = calloc(1,sizeof(subInfo));
*ppvt = (void *)psubInfo;
psubFile = calloc(1,sizeof(subFile));
psubInfo->psubFile = psubFile;
ellInit(&psubInfo->patternList);
fp = fopen(substitutionName,"r");
if(!fp) {
fprintf(stderr,"Could not open %s\n",substitutionName);
exit(1);
}
psubFile->substitutionName = substitutionName;
psubFile->fp = fp;
psubFile->lineNum = 0;
psubFile->inputBuffer[0] = 0;
psubFile->pnextChar = &psubFile->inputBuffer[0];
subGetNextToken(psubFile);
return;
}
static int substituteGetGlobalSet(void *pvt)
{
subInfo *psubInfo = (subInfo *)pvt;
subFile *psubFile = psubInfo->psubFile;
while(psubFile->token==tokenSeparater) subGetNextToken(psubFile);
if(psubFile->token==tokenString && strcmp(psubFile->string,"global")==0) {
subGetNextToken(psubFile);
return(1);
}
return(0);
}
static int substituteGetNextSet(void *pvt,char **filename)
{
subInfo *psubInfo = (subInfo *)pvt;
subFile *psubFile = psubInfo->psubFile;
patternNode *ppatternNode;
*filename = 0;
while(psubFile->token==tokenSeparater) subGetNextToken(psubFile);
if(psubFile->token==tokenEOF) return(0);
if(psubFile->token==tokenString && strcmp(psubFile->string,"file")==0) {
psubInfo->isFile = 1;
if(subGetNextToken(psubFile)!=tokenString) {
subFileErrPrint(psubFile,"Expecting filename");
exit(1);
}
freePattern(psubInfo);
free((void *)psubInfo->filename);
if(psubFile->string[0]=='"'&&psubFile->string[strlen(psubFile->string)-1]=='"') {
psubFile->string[strlen(psubFile->string)-1]='\0';
psubInfo->filename = macEnvExpand(psubFile->string+1);
}
else {
psubInfo->filename = macEnvExpand(psubFile->string);
}
while(subGetNextToken(psubFile)==tokenSeparater);
if(psubFile->token!=tokenLBrace) {
subFileErrPrint(psubFile,"Expecting {");
exit(1);
}
subGetNextToken(psubFile);
}
*filename = psubInfo->filename;
while(psubFile->token==tokenSeparater) subGetNextToken(psubFile);
if(psubFile->token==tokenLBrace) return(1);
if(psubFile->token==tokenRBrace) return(1);
if(psubFile->token!=tokenString
|| strcmp(psubFile->string,"pattern")!=0) {
subFileErrPrint(psubFile,"Expecting pattern");
exit(1);
}
freePattern(psubInfo);
psubInfo->isPattern = 1;
while(subGetNextToken(psubFile)==tokenSeparater);
if(psubFile->token!=tokenLBrace) {
subFileErrPrint(psubFile,"Expecting {");
exit(1);
}
while(1) {
while(subGetNextToken(psubFile)==tokenSeparater);
if(psubFile->token!=tokenString) break;
ppatternNode = calloc(1,sizeof(patternNode));
ellAdd(&psubInfo->patternList,&ppatternNode->node);
ppatternNode->var = calloc(strlen(psubFile->string)+1,sizeof(char));
strcpy(ppatternNode->var,psubFile->string);
}
if(psubFile->token!=tokenRBrace) {
subFileErrPrint(psubFile,"Expecting }");
exit(1);
}
subGetNextToken(psubFile);
return(1);
}
static char *substituteGetReplacements(void *pvt)
{
subInfo *psubInfo = (subInfo *)pvt;
subFile *psubFile = psubInfo->psubFile;
patternNode *ppatternNode;
if(psubInfo->macroReplacements) psubInfo->macroReplacements[0] = 0;
psubInfo->curLength = 0;
while(psubFile->token==tokenSeparater) subGetNextToken(psubFile);
if(psubFile->token==tokenRBrace && psubInfo->isFile) {
psubInfo->isFile = 0;
free((void *)psubInfo->filename);
psubInfo->filename = 0;
freePattern(psubInfo);
subGetNextToken(psubFile);
return(0);
}
if(psubFile->token==tokenEOF) return(0);
if(psubFile->token!=tokenLBrace) return(0);
if(psubInfo->isPattern) {
int gotFirstPattern = 0;
while(subGetNextToken(psubFile)==tokenSeparater);
ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList);
while(1) {
if(psubFile->token==tokenRBrace) {
if(ppatternNode)
subFileErrPrint(psubFile,"less values than patterns");
subGetNextToken(psubFile);
return(psubInfo->macroReplacements);
}
if(psubFile->token!=tokenString) {
subFileErrPrint(psubFile,"Illegal token");
exit(-1);
}
if(gotFirstPattern) catMacroReplacements(psubInfo,",");
gotFirstPattern = 1;
if(ppatternNode) {
catMacroReplacements(psubInfo,ppatternNode->var);
catMacroReplacements(psubInfo,"=");
catMacroReplacements(psubInfo,psubFile->string);
ppatternNode = (patternNode *)ellNext(&ppatternNode->node);
} else {
subFileErrPrint(psubFile,"more values than patterns");
}
while(subGetNextToken(psubFile)==tokenSeparater);
}
} else while(1) {
switch(subGetNextToken(psubFile)) {
case tokenRBrace:
subGetNextToken(psubFile);
if (!psubInfo->macroReplacements) {
catMacroReplacements(psubInfo,"");
}
return(psubInfo->macroReplacements);
case tokenSeparater:
catMacroReplacements(psubInfo,",");
break;
case tokenString:
catMacroReplacements(psubInfo,psubFile->string);
break;
default:
subFileErrPrint(psubFile,"Illegal token");
exit(1);
}
}
}
static char *subGetNextLine(subFile *psubFile)
{
char *pline;
do {
pline = fgets(psubFile->inputBuffer,MAX_BUFFER_SIZE,psubFile->fp);
++psubFile->lineNum;
} while(pline && psubFile->inputBuffer[0]=='#');
if(!pline) {
psubFile->token = tokenEOF;
psubFile->inputBuffer[0] = 0;
psubFile->pnextChar = 0;
return(0);
}
psubFile->pnextChar = &psubFile->inputBuffer[0];
return(&psubFile->inputBuffer[0]);
}
static void subFileErrPrint(subFile *psubFile,char * message)
{
fprintf(stderr,"substitution file %s line %d: %s",
psubFile->substitutionName,
psubFile->lineNum,psubFile->inputBuffer);
fprintf(stderr,"%s\n",message);
}
static tokenType subGetNextToken(subFile *psubFile)
{
char *p;
char *pto;
p = psubFile->pnextChar;
if(!p) { psubFile->token = tokenEOF; return(tokenEOF);}
if(*p==0 || *p=='\n' || *p=='#') {
p = subGetNextLine(psubFile);
if(!p) { psubFile->token = tokenEOF; return(tokenEOF);}
else { psubFile->token = tokenSeparater; return(tokenSeparater);}
}
while(isspace(*p)) p++;
if(*p=='{') {
psubFile->token = tokenLBrace;
psubFile->pnextChar = ++p;
return(tokenLBrace);
}
if(*p=='}') {
psubFile->token = tokenRBrace;
psubFile->pnextChar = ++p;
return(tokenRBrace);
}
if(*p==0 || isspace(*p) || *p==',') {
while(isspace(*p) || *p==',') p++;
psubFile->token = tokenSeparater;
psubFile->pnextChar = p;
return(tokenSeparater);
}
/*now handle quoted strings*/
if(*p=='"') {
pto = &psubFile->string[0];
*pto++ = *p++;
while(*p!='"') {
if(*p==0 || *p=='\n') {
subFileErrPrint(psubFile,"Strings must be on single line\n");
exit(1);
}
/*allow escape for imbeded quote*/
if((*p=='\\') && *(p+1)=='"') {
*pto++ = *p++;
*pto++ = *p++;
continue;
}
*pto++ = *p++;
}
*pto++ = *p++;
psubFile->pnextChar = p;
*pto = 0;
psubFile->token = tokenString;
return(tokenString);
}
/*Now take anything up to next non String token and not space*/
pto = &psubFile->string[0];
while(!isspace(*p) && (strspn(p,"\",{}")==0)) *pto++ = *p++;
*pto = 0;
psubFile->pnextChar = p;
psubFile->token = tokenString;
return(tokenString);
}
static void catMacroReplacements(subInfo *psubInfo,const char *value)
{
size_t len = strlen(value);
if(psubInfo->size <= (psubInfo->curLength + len)) {
size_t newsize = psubInfo->size + MAX_BUFFER_SIZE;
char *newbuf;
if(newsize <= psubInfo->curLength + len)
newsize = psubInfo->curLength + len + 1;
newbuf = calloc(1,newsize);
if(!newbuf) {
fprintf(stderr,"calloc failed for size %Zu\n",newsize);
exit(1);
}
if(psubInfo->macroReplacements) {
memcpy(newbuf,psubInfo->macroReplacements,psubInfo->curLength);
free(psubInfo->macroReplacements);
}
psubInfo->size = newsize;
psubInfo->macroReplacements = newbuf;
}
strcat(psubInfo->macroReplacements,value);
psubInfo->curLength += len;
}
Mon Aug 23 14:10:38 CEST 2010 [email protected]
* allow global substitution sets anywhere at the top level
diff -rN -u old-msi/msi.c new-msi/msi.c
--- old-msi/msi.c 2010-08-23 14:26:46.112050429 +0200
+++ new-msi/msi.c 2010-08-23 14:26:46.116051044 +0200
@@ -110,27 +110,29 @@
} else {
void *substitutePvt;
char *filename = 0;
+ int isGlobal, isFile;
substituteOpen(&substitutePvt,substitutionName);
- while(substituteGetGlobalSet(substitutePvt)) {
- pval = substituteGetReplacements(substitutePvt);
- if(pval) {
- addMacroReplacements(macPvt,pval);
- }
- }
- while(substituteGetNextSet(substitutePvt,&filename)) {
- if(templateName) filename = templateName;
- if(!filename) {
- fprintf(stderr,"no template file\n");
- usageExit();
+ do {
+ if ((isGlobal = substituteGetGlobalSet(substitutePvt))) {
+ pval = substituteGetReplacements(substitutePvt);
+ if(pval) {
+ addMacroReplacements(macPvt,pval);
+ }
+ } else if ((isFile = substituteGetNextSet(substitutePvt,&filename))) {
+ if(templateName) filename = templateName;
+ if(!filename) {
+ fprintf(stderr,"no template file\n");
+ usageExit();
+ }
+ if (optScoped) macPushScope(macPvt);
+ while((pval = substituteGetReplacements(substitutePvt))){
+ addMacroReplacements(macPvt,pval);
+ makeSubstitutions(inputPvt,macPvt,filename);
+ }
+ if (optScoped) macPopScope(macPvt);
}
- if (optScoped) macPushScope(macPvt);
- while((pval = substituteGetReplacements(substitutePvt))){
- addMacroReplacements(macPvt,pval);
- makeSubstitutions(inputPvt,macPvt,filename);
- }
- if (optScoped) macPopScope(macPvt);
- }
+ } while (isGlobal || isFile);
substituteDestruct(substitutePvt);
}
inputDestruct(inputPvt);
- Replies:
- Re: msi again Andrew Johnson
- References:
- msi again Benjamin Franksen
- Re: msi again Benjamin Franksen
- Navigate by Date:
- Prev:
Re: Asyn and I/O intr scanning Hinko Kocevar
- Next:
RE: Asyn and I/O intr scanning Mark Rivers
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
<2010>
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
Re: msi again Benjamin Franksen
- Next:
Re: msi again Andrew Johnson
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
<2010>
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
|