diff --git a/src/dbtools/msi.c b/src/dbtools/msi.c index 1f88c1519..3e8445558 100644 --- a/src/dbtools/msi.c +++ b/src/dbtools/msi.c @@ -1,18 +1,13 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2010 UChicago Argonne LLC, 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 +* EPICS Base 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 - */ + +/* msi - macro substitutions and include */ #include #include @@ -21,17 +16,12 @@ #include #include -#include #include #include #include #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); @@ -50,12 +40,11 @@ static void inputErrPrint(void *inputPvt); 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 opt_V = 0; +/*Global variables */ +static int dontWarnUndef = 1; int main(int argc,char **argv) @@ -67,76 +56,96 @@ int main(int argc,char **argv) char *substitutionName=0; char *templateName=0; int i; + int optScoped=1; 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); + 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,"msi: 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); + dontWarnUndef = 0; + narg = 1; /* no argument for this option */ + } else if(strncmp(argv[1],"-c",2)==0) { + optScoped = 0; + narg = 1; /* no argument for this option */ + } else { + usageExit(); } - } 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); - opt_V = 1; - narg = 1; /* no argument for this option */ - } else { - usageExit(); - } - argc -= narg; - for(i=1; i2) { - fprintf(stderr,"too many filename arguments\n"); - usageExit(); + fprintf(stderr,"msi: Too many arguments\n"); + usageExit(); } if(argc==2) { templateName = calloc(strlen(argv[1])+1,sizeof(char)); strcpy(templateName,argv[1]); } if(!substitutionName) { - makeSubstitutions(inputPvt,macPvt,templateName); + makeSubstitutions(inputPvt,macPvt,templateName); } else { - void *substitutePvt; + void *substitutePvt; char *filename = 0; + int isGlobal, isFile; - substituteOpen(&substitutePvt,substitutionName); - while(substituteGetNextSet(substitutePvt,&filename)) { - if(templateName) filename = templateName; - if(!filename) { - fprintf(stderr,"no template file\n"); - usageExit(); + 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,"msi: No template file\n"); + usageExit(); + } + while((pval = substituteGetReplacements(substitutePvt))){ + if (optScoped) macPushScope(macPvt); + addMacroReplacements(macPvt,pval); + makeSubstitutions(inputPvt,macPvt,filename); + if (optScoped) macPopScope(macPvt); + } } - macPushScope(macPvt); - while((pval = substituteGetReplacements(substitutePvt))){ - addMacroReplacements(macPvt,pval); - makeSubstitutions(inputPvt,macPvt,filename); - } - macPopScope(macPvt); - } + } while (isGlobal || isFile); substituteDestruct(substitutePvt); } inputDestruct(inputPvt); free((void *)templateName); free((void *)substitutionName); - return(exitStatus); + return 0; } void usageExit(void) { - fprintf(stderr,"usage: msi -V -opath -Ipath ... -Msub ... -Ssubfile template\n"); - fprintf(stderr," Specifying path will replace the default '.'\n"); - fprintf(stderr," stdin is used if template is not given\n"); + 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 save output to \n"); + fprintf(stderr," -I add to include file search path\n"); + fprintf(stderr," -M add to (global) macro definitions\n"); + fprintf(stderr," ( is of the form VAR=VALUE,...)\n"); + fprintf(stderr," -S expand a substitution file\n"); + fprintf(stderr," -c macro definitions are scoped (in substitution files)\n"); exit(1); } @@ -146,16 +155,18 @@ static void addMacroReplacements(MAC_HANDLE *macPvt,char *pval) long status; status = macParseDefns(macPvt,pval,&pairs); - if(!status) { - fprintf(stderr,"Error macParseDefns error\n"); + if(status==-1) { + fprintf(stderr,"msi: Error from macParseDefns\n"); usageExit(); } - status = macInstallMacros(macPvt,pairs); - if(!status) { - fprintf(stderr,"Error macInstallMacros error\n"); - usageExit(); + if(status) { + status = macInstallMacros(macPvt,pairs); + if(!status) { + fprintf(stderr,"Error from macInstallMacros\n"); + usageExit(); + } + free((void *)pairs); } - free((void *)pairs); } typedef enum {cmdInclude,cmdSubstitute} cmdType; @@ -165,99 +176,97 @@ 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; + 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; + 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; - } + 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,"msi: Logic error in 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: Undefined macros present%s\n", - opt_V ? "" : ", use msi -V to list"); - unexpWarned++; - } - } + if (expand) { + n = macExpandString(macPvt,input,buffer,MAX_BUFFER_SIZE-1); + fputs(buffer,stdout); + if (!dontWarnUndef && n<0) { + fprintf(stderr,"msi: Warning, undefined macros present\n"); + dontWarnUndef++; + } + } } } typedef struct inputFile{ - ELLNODE node; - char *filename; - FILE *fp; - int lineNum; + ELLNODE node; + char *filename; + FILE *fp; + int lineNum; }inputFile; typedef struct pathNode { - ELLNODE node; - char *directory; + ELLNODE node; + char *directory; } pathNode; typedef struct inputData { - ELLLIST inputFileList; - ELLLIST pathList; - char inputBuffer[MAX_BUFFER_SIZE]; + ELLLIST inputFileList; + ELLLIST pathList; + char inputBuffer[MAX_BUFFER_SIZE]; }inputData; static void inputOpenFile(inputData *pinputData,char *filename); @@ -266,7 +275,7 @@ static void inputCloseAllFiles(inputData *pinputData); static void inputConstruct(void **ppvt) { - inputData *pinputData; + inputData *pinputData; pinputData = calloc(1,sizeof(inputData)); ellInit(&pinputData->inputFileList); @@ -276,59 +285,59 @@ static void inputConstruct(void **ppvt) static void inputDestruct(void *pvt) { - inputData *pinputData = (inputData *)pvt; - pathNode *ppathNode; + 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); + 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; + 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,"."); - } + 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; + inputData *pinputData = (inputData *)pvt; inputCloseAllFiles(pinputData); inputOpenFile(pinputData,fileName); @@ -336,94 +345,94 @@ static void inputBegin(void *pvt,char *fileName) static char *inputNextLine(void *pvt) { - inputData *pinputData = (inputData *)pvt; - inputFile *pinputFile; - char *pline; + 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); + if(pline) { + ++pinputFile->lineNum; + return(pline); + } + inputCloseFile(pinputData); } return(0); } static void inputNewIncludeFile(void *pvt,char *name) { - inputData *pinputData = (inputData *)pvt; + inputData *pinputData = (inputData *)pvt; inputOpenFile(pinputData,name); } static void inputErrPrint(void *pvt) { - inputData *pinputData = (inputData *)pvt; - inputFile *pinputFile; + inputData *pinputData = (inputData *)pvt; + inputFile *pinputFile; - fprintf(stderr,"input: %s which is ",pinputData->inputBuffer); + fprintf(stderr,"input: '%s' at ",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,"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," 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; + ELLLIST *ppathList = &pinputData->pathList; + pathNode *ppathNode = 0; + inputFile *pinputFile; + char *fullname = 0; + FILE *fp = 0; if(!filename) { - fp = stdin; + fp = stdin; } else if((ellCount(ppathList)==0) || strchr(filename,'/')){ - fp = fopen(filename,"r"); + 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); - } + 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); + fprintf(stderr,"msi: Can't open file '%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); + 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->filename = calloc(1,strlen("stdin")+1); + strcpy(pinputFile->filename,"stdin"); } pinputFile->fp = fp; ellInsert(&pinputData->inputFileList,0,&pinputFile->node); @@ -437,17 +446,17 @@ static void inputCloseFile(inputData *pinputData) if(!pinputFile) return; ellDelete(&pinputData->inputFileList,&pinputFile->node); if(fclose(pinputFile->fp)) - fprintf(stderr,"fclose failed: file %s\n",pinputFile->filename); + fprintf(stderr,"msi: Can't close input file '%s'\n",pinputFile->filename); free(pinputFile->filename); free(pinputFile); } static void inputCloseAllFiles(inputData *pinputData) { - inputFile *pinputFile; + inputFile *pinputFile; while((pinputFile=(inputFile *)ellFirst(&pinputData->inputFileList))){ - inputCloseFile(pinputData); + inputCloseFile(pinputData); } } @@ -457,29 +466,29 @@ typedef enum { }tokenType; typedef struct subFile { - char *substitutionName; - FILE *fp; - int lineNum; - char inputBuffer[MAX_BUFFER_SIZE]; - char *pnextChar; - tokenType token; - char string[MAX_BUFFER_SIZE]; + 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; + 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; + subFile *psubFile; + int isFile; + char *filename; + int isPattern; + ELLLIST patternList; + size_t size; + size_t curLength; + char *macroReplacements; }subInfo; static char *subGetNextLine(subFile *psubFile); @@ -491,10 +500,10 @@ static void catMacroReplacements(subInfo *psubInfo,const char *value); void freeSubFile(subInfo *psubInfo) { - subFile *psubFile = psubInfo->psubFile; + subFile *psubFile = psubInfo->psubFile; if(psubFile->fp) { if(fclose(psubFile->fp)) - fprintf(stderr,"fclose failed on substitution file\n"); + fprintf(stderr,"msi: Can't close substitution file\n"); } free((void *)psubFile); free((void *)psubInfo->filename); @@ -503,18 +512,18 @@ void freeSubFile(subInfo *psubInfo) void freePattern(subInfo *psubInfo) { - patternNode *ppatternNode; + patternNode *ppatternNode; while((ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList))) { - ellDelete(&psubInfo->patternList,&ppatternNode->node); - free(ppatternNode->var); - free(ppatternNode); + ellDelete(&psubInfo->patternList,&ppatternNode->node); + free(ppatternNode->var); + free(ppatternNode); } psubInfo->isPattern = 0; } static void substituteDestruct(void *pvt) { - subInfo *psubInfo = (subInfo *)pvt; + subInfo *psubInfo = (subInfo *)pvt; freeSubFile(psubInfo); freePattern(psubInfo); @@ -524,9 +533,9 @@ static void substituteDestruct(void *pvt) static void substituteOpen(void **ppvt,char *substitutionName) { - subInfo *psubInfo; - subFile *psubFile; - FILE *fp; + subInfo *psubInfo; + subFile *psubFile; + FILE *fp; psubInfo = calloc(1,sizeof(subInfo)); *ppvt = (void *)psubInfo; @@ -535,23 +544,36 @@ static void substituteOpen(void **ppvt,char *substitutionName) ellInit(&psubInfo->patternList); fp = fopen(substitutionName,"r"); if(!fp) { - fprintf(stderr,"Could not open %s\n",substitutionName); + fprintf(stderr,"msi: Can't open file '%s'\n",substitutionName); exit(1); } psubFile->substitutionName = substitutionName; psubFile->fp = fp; - psubFile->lineNum = 0; + psubFile->lineNum = 1; 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; + subInfo *psubInfo = (subInfo *)pvt; + subFile *psubFile = psubInfo->psubFile; + patternNode *ppatternNode; *filename = 0; while(psubFile->token==tokenSeparater) subGetNextToken(psubFile); @@ -559,7 +581,7 @@ static int substituteGetNextSet(void *pvt,char **filename) if(psubFile->token==tokenString && strcmp(psubFile->string,"file")==0) { psubInfo->isFile = 1; if(subGetNextToken(psubFile)!=tokenString) { - subFileErrPrint(psubFile,"Expecting filename"); + subFileErrPrint(psubFile,"Parse error, expecting filename"); exit(1); } freePattern(psubInfo); @@ -573,7 +595,7 @@ static int substituteGetNextSet(void *pvt,char **filename) } while(subGetNextToken(psubFile)==tokenSeparater); if(psubFile->token!=tokenLBrace) { - subFileErrPrint(psubFile,"Expecting {"); + subFileErrPrint(psubFile,"Parse error, expecting {"); exit(1); } subGetNextToken(psubFile); @@ -581,30 +603,30 @@ static int substituteGetNextSet(void *pvt,char **filename) *filename = psubInfo->filename; while(psubFile->token==tokenSeparater) subGetNextToken(psubFile); if(psubFile->token==tokenLBrace) return(1); - if(psubFile->token==tokenRBrace) return(0); + if(psubFile->token==tokenRBrace) return(1); if(psubFile->token!=tokenString || strcmp(psubFile->string,"pattern")!=0) { - subFileErrPrint(psubFile,"Expecting pattern"); + subFileErrPrint(psubFile,"Parse error, expecting pattern"); exit(1); } freePattern(psubInfo); psubInfo->isPattern = 1; while(subGetNextToken(psubFile)==tokenSeparater); if(psubFile->token!=tokenLBrace) { - subFileErrPrint(psubFile,"Expecting {"); - exit(1); + subFileErrPrint(psubFile,"Parse error, 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!=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); + subFileErrPrint(psubFile,"Parse error, expecting }"); + exit(1); } subGetNextToken(psubFile); return(1); @@ -612,8 +634,8 @@ static int substituteGetNextSet(void *pvt,char **filename) static char *substituteGetReplacements(void *pvt) { - subInfo *psubInfo = (subInfo *)pvt; - subFile *psubFile = psubInfo->psubFile; + subInfo *psubInfo = (subInfo *)pvt; + subFile *psubFile = psubInfo->psubFile; patternNode *ppatternNode; if(psubInfo->macroReplacements) psubInfo->macroReplacements[0] = 0; @@ -630,48 +652,49 @@ static char *substituteGetReplacements(void *pvt) if(psubFile->token==tokenEOF) return(0); if(psubFile->token!=tokenLBrace) return(0); if(psubInfo->isPattern) { - int gotFirstPattern = 0; + int gotFirstPattern = 0; while(subGetNextToken(psubFile)==tokenSeparater); - ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList); - while(1) { + 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"); + subFileErrPrint(psubFile,"Parse error, illegal token"); exit(-1); } - if(gotFirstPattern) catMacroReplacements(psubInfo,","); - gotFirstPattern = 1; + if(gotFirstPattern) catMacroReplacements(psubInfo,","); + gotFirstPattern = 1; if(ppatternNode) { - catMacroReplacements(psubInfo,ppatternNode->var); - catMacroReplacements(psubInfo,"="); - catMacroReplacements(psubInfo,psubFile->string); + catMacroReplacements(psubInfo,ppatternNode->var); + catMacroReplacements(psubInfo,"="); + catMacroReplacements(psubInfo,psubFile->string); ppatternNode = (patternNode *)ellNext(&ppatternNode->node); } else { - subFileErrPrint(psubFile,"more values than patterns"); + subFileErrPrint(psubFile,"Warning, too many values given"); } while(subGetNextToken(psubFile)==tokenSeparater); - } + } } else while(1) { switch(subGetNextToken(psubFile)) { - case tokenRBrace: + 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); - } + case tokenSeparater: + catMacroReplacements(psubInfo,","); + break; + case tokenString: + catMacroReplacements(psubInfo,psubFile->string); + break; + default: + subFileErrPrint(psubFile,"Parse error, illegal token"); + exit(1); + } } } @@ -679,17 +702,15 @@ static char *subGetNextLine(subFile *psubFile) { char *pline; - pline = fgets(psubFile->inputBuffer,MAX_BUFFER_SIZE,psubFile->fp); - ++psubFile->lineNum; - while(pline && psubFile->inputBuffer[0]=='#') { - pline = fgets(psubFile->inputBuffer,MAX_BUFFER_SIZE,psubFile->fp); + 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->token = tokenEOF; + psubFile->inputBuffer[0] = 0; + psubFile->pnextChar = 0; + return(0); } psubFile->pnextChar = &psubFile->inputBuffer[0]; return(&psubFile->inputBuffer[0]); @@ -697,64 +718,64 @@ static char *subGetNextLine(subFile *psubFile) 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); + fprintf(stderr,"msi: %s\n",message); + fprintf(stderr," in substitution file '%s' at line %d:\n %s", + psubFile->substitutionName, + psubFile->lineNum,psubFile->inputBuffer); } static tokenType subGetNextToken(subFile *psubFile) { - char *p; - char *pto; + 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);} + 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); + psubFile->token = tokenLBrace; + psubFile->pnextChar = ++p; + return(tokenLBrace); } if(*p=='}') { - psubFile->token = tokenRBrace; - psubFile->pnextChar = ++p; - return(tokenRBrace); + 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); + 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); + 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]; @@ -767,7 +788,7 @@ static tokenType subGetNextToken(subFile *psubFile) static void catMacroReplacements(subInfo *psubInfo,const char *value) { - size_t len = strlen(value); + size_t len = strlen(value); if(psubInfo->size <= (psubInfo->curLength + len)) { size_t newsize = psubInfo->size + MAX_BUFFER_SIZE;