From d55e5536d62055613ffd174df77db41b7ff386ed Mon Sep 17 00:00:00 2001 From: cvs2svn Date: Thu, 18 Dec 1997 16:39:03 +0000 Subject: [PATCH 01/32] Standard project directories initialized by cvs2svn. From 9519e920353d2370debeca75bb1f0c6a018ddfee Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Thu, 18 Dec 1997 16:39:03 +0000 Subject: [PATCH 02/32] First version --- Makefile | 10 + Makefile.Unix | 16 ++ msi.c | 654 ++++++++++++++++++++++++++++++++++++++++++++++++++ pattern | 9 + substitute | 2 + template | 4 + testfile | 13 + testfile1 | 4 + 8 files changed, 712 insertions(+) create mode 100644 Makefile create mode 100644 Makefile.Unix create mode 100644 msi.c create mode 100644 pattern create mode 100644 substitute create mode 100644 template create mode 100644 testfile create mode 100644 testfile1 diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..d3a001c71 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +# +# $Id$ +# + +EPICS=../../.. + +include $(EPICS)/config/CONFIG_EXTENSIONS + +include $(EPICS)/config/RULES_ARCHS + diff --git a/Makefile.Unix b/Makefile.Unix new file mode 100644 index 000000000..e9ccd1dff --- /dev/null +++ b/Makefile.Unix @@ -0,0 +1,16 @@ +EPICS = ../../../.. +include Target.include +include $(EPICS)/config/CONFIG_EXTENSIONS + +DEPLIBS = $(EPICS_BASE_LIB)/libCom.a $(EPICS_EXTENSIONS_LIB)/libpprsyd.a +USR_LDLIBS = -lpprsyd -lCom +USR_INCLUDES = -I$(EPICS_EXTENSIONS_INCLUDE) +USR_CFLAGS = -L$(EPICS_EXTENSIONS_LIB) + +#CMPLR = OLD + +SRCS.c= ../msi.c +PROD = msi + +include $(EPICS)/config/RULES.Unix + diff --git a/msi.c b/msi.c new file mode 100644 index 000000000..4b1a6aab8 --- /dev/null +++ b/msi.c @@ -0,0 +1,654 @@ +/*msi - macro sunstitutions and include */ +/***************************************************************** + COPYRIGHT NOTIFICATION +***************************************************************** + +(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO + +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +**********************************************************************/ + +/* + * Modification Log: + * ----------------- + * .01 08DEC97 mrk Original version + */ + +#include +#include +#include +#include +#include + +#include +#include + +#define MAX_BUFFER_SIZE 1024 + +/*Forward references to local routines*/ +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 substituteConstruct(void **substitutePvt); +static void substituteDestruct(void *substitutePvt); +static void substituteOpen(void *substitutePvt,char *substitutionName); +static char *substituteGetReplacements(void *substitutePvt); +#define USAGEEXIT \ +{\ + fprintf(stderr,"usage: msi -V -Idir ... -Msub ... -Ssubfile template \n");\ + exit(1);\ +} + +int main(int argc,char **argv) +{ + void *inputPvt; + MAC_HANDLE *macPvt; + char *pval; + int narg; + char *substitutionName=0; + char *templateName=0; + int i; + + inputConstruct(&inputPvt); + macCreateHandle(&macPvt,0); + macSuppressWarning(macPvt,TRUE); + 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],"-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,FALSE); + narg = 1; /* no argument for this option */ + } else { + USAGEEXIT + } + argc -= narg; + for(i=1; i2) { + fprintf(stderr,"too many files\n"); + USAGEEXIT + } + if(argc==2) templateName = argv[1]; + if(!substitutionName) { + makeSubstitutions(inputPvt,macPvt,templateName); + } else { + void *substitutePvt; + + if(!templateName) { + fprintf(stderr,"stdin not legal with substitution file\n"); + USAGEEXIT + } + substituteConstruct(&substitutePvt); + substituteOpen(substitutePvt,substitutionName); + while(pval = substituteGetReplacements(substitutePvt)){ + addMacroReplacements(macPvt,pval); + makeSubstitutions(inputPvt,macPvt,templateName); + } + substituteDestruct(substitutePvt); + } + inputDestruct(inputPvt); + return(0); +} + +static void addMacroReplacements(MAC_HANDLE *macPvt,char *pval) +{ + char **pairs; + long status; + + status = macParseDefns(macPvt,pval,&pairs); + status = macInstallMacros(macPvt,pairs); + free((void *)pairs); +} + + +#define cmdNumberOf 2 +typedef enum {cmdInclude,cmdSubstitute} cmdType; +static char *cmdName[cmdNumberOf] = {"include","substitute"}; +static void makeSubstitutions(void *inputPvt,void *macPvt,char *templateName) +{ + char *input; + static char buffer[MAX_BUFFER_SIZE]; + int n; + char *subStringLocation; + + inputBegin(inputPvt,templateName); + while(input = inputNextLine(inputPvt)) { + int expand=TRUE; + 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< cmdNumberOf; i++) { + if(strstr(command,cmdName[i])) { + cmdind = i; + } + } + if(cmdind<0) goto endif; + p = command + strlen(cmdName[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; + } + if(*p==0) goto endif; + pend = p; + 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 = FALSE; + } +endif: + if(expand) { + n = macExpandString(macPvt,input,buffer,MAX_BUFFER_SIZE-1); + if(n<0) { + inputErrPrint(inputPvt); + } else { + printf("%s",buffer); + } + } + } +} + +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 char *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; + + pdir = path; + while(pdir) { + if(*pdir == ':') { + pdir++; + continue; + } + ppathNode = (pathNode *)calloc(1,sizeof(pathNode)); + ellAdd(ppathList,&ppathNode->node); + pcolon = strchr(pdir,':'); + len = (pcolon ? (pcolon - pdir) : strlen(pdir)); + ppathNode->directory = (char *)calloc(1,len+1); + strncpy(ppathNode->directory,pdir,len); + pdir = (pcolon ? (pcolon+1) : 0); + } + return; +} + +static void inputBegin(void *pvt,char *fileName) +{ + inputData *pinputData = (inputData *)pvt; + inputFile *pinputFile; + + 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 char *inputOpenFile(inputData *pinputData,char *filename) +{ + ELLLIST *ppathList = &pinputData->pathList; + pathNode *ppathNode = 0; + inputFile *pinputFile; + char *fullname; + 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); + return(0); + } + 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); + return(0); +} + +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 { + 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 isPattern; + ELLLIST patternList; + char macroReplacements[MAX_BUFFER_SIZE]; +}subInfo; + +static char *subGetNextLine(subFile *psubFile); +static tokenType subGetNextToken(subFile *psubFile); +static void subFileErrPrint(subFile *psubFile,char * message); + +static void substituteConstruct(void **pvt) +{ + subFile *psubFile; + subInfo *psubInfo; + + psubInfo = calloc(1,sizeof(subInfo)); + psubFile = calloc(1,sizeof(subFile)); + ellInit(&psubInfo->patternList); + psubInfo->psubFile = psubFile; + *pvt = psubInfo; + return; +} + +static void substituteDestruct(void *pvt) +{ + subInfo *psubInfo = (subInfo *)pvt; + subFile *psubFile = psubInfo->psubFile; + patternNode *ppatternNode; + + if(fclose(psubFile->fp)) + fprintf(stderr,"fclose failed on substitution file\n"); + while(ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList)) { + ellDelete(&psubInfo->patternList,&ppatternNode->node); + free(ppatternNode->var); + free(ppatternNode); + } + free((void *)psubFile); + free((void *)psubInfo); + return; +} + +static void substituteOpen(void *pvt,char *substitutionName) +{ + subInfo *psubInfo = (subInfo *)pvt; + subFile *psubFile = psubInfo->psubFile; + FILE *fp; + patternNode *ppatternNode; + + fp = fopen(substitutionName,"r"); + if(!fp) { + fprintf(stderr,"Could not open %s\n",substitutionName); + exit(1); + } + psubFile->fp = fp; + psubFile->lineNum = 0; + psubFile->inputBuffer[0] = 0; + psubFile->pnextChar = &psubFile->inputBuffer[0]; + while(subGetNextToken(psubFile)==tokenSeparater); + if(psubFile->token!=tokenString + || strcmp(psubFile->string,"pattern")!=0) { + psubInfo->isPattern = FALSE; + return; + } + psubInfo->isPattern = TRUE; + while(subGetNextToken(psubFile)==tokenSeparater); + if(psubFile->token!=tokenLBrace) { + subFileErrPrint(psubFile,"Expecting {"); + exit(1); + } + while(TRUE) { + subGetNextToken(psubFile); + if(psubFile->token==tokenSeparater) continue; + if(psubFile->token==tokenString) { + ppatternNode = calloc(1,sizeof(patternNode)); + ellAdd(&psubInfo->patternList,&ppatternNode->node); + ppatternNode->var = calloc(strlen(psubFile->string)+1,sizeof(char)); + strcpy(ppatternNode->var,psubFile->string); + continue; + } + break; + } + if(psubFile->token!=tokenRBrace) { + subFileErrPrint(psubFile,"Expecting }"); + exit(1); + } + return; +} + +static char *substituteGetReplacements(void *pvt) +{ + subInfo *psubInfo = (subInfo *)pvt; + subFile *psubFile = psubInfo->psubFile; + char *pNext; + patternNode *ppatternNode; + + pNext = &psubInfo->macroReplacements[0]; + psubInfo->macroReplacements[0] = 0; + if(psubFile->token!=tokenLBrace) + while(subGetNextToken(psubFile)==tokenSeparater); + if(psubFile->token==tokenEOF) return(0); + if(psubFile->token!=tokenLBrace) { + subFileErrPrint(psubFile,"Expecting {"); + exit(1); + } + if(psubInfo->isPattern) { + int gotFirstPattern = FALSE; + + ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList); + if(!ppatternNode) { + subFileErrPrint(psubFile,"No patterns"); + exit(1); + } + while(TRUE) { + switch(subGetNextToken(psubFile)) { + case tokenSeparater: continue; + case tokenRBrace: return(psubInfo->macroReplacements); + case tokenString: + if(gotFirstPattern) { + strcat(psubInfo->macroReplacements,","); + } + gotFirstPattern = TRUE; + strcat(psubInfo->macroReplacements,ppatternNode->var); + strcat(psubInfo->macroReplacements,"="); + strcat(psubInfo->macroReplacements,psubFile->string); + break; + default: + subFileErrPrint(psubFile,"Illegal token"); + exit(1); + } + ppatternNode = (patternNode *)ellNext(&ppatternNode->node); + + } + } else while(TRUE) { + switch(subGetNextToken(psubFile)) { + case tokenRBrace: return(psubInfo->macroReplacements); + case tokenSeparater: + strcat(psubInfo->macroReplacements,","); + break; + case tokenString: + strcat(psubInfo->macroReplacements,psubFile->string); + break; + default: + subFileErrPrint(psubFile,"Illegal token"); + exit(1); + } + } +} + +static char *subGetNextLine(subFile *psubFile) +{ + char *pline; + + pline = fgets(psubFile->inputBuffer,MAX_BUFFER_SIZE,psubFile->fp); + while(pline && psubFile->inputBuffer[0]=='#') + pline = fgets(psubFile->inputBuffer,MAX_BUFFER_SIZE,psubFile->fp); + if(!pline) { + psubFile->token = tokenEOF; + psubFile->inputBuffer[0] = 0; + psubFile->pnextChar = 0; + return(0); + } + psubFile->pnextChar = &psubFile->inputBuffer[0]; + ++psubFile->lineNum; + return(&psubFile->inputBuffer[0]); +} + +static void subFileErrPrint(subFile *psubFile,char * message) +{ + fprintf(stderr,"substitution file line %d: %s", + psubFile->lineNum,psubFile->inputBuffer); + fprintf(stderr,"%s\n",message); +} + + +static tokenType subGetNextToken(subFile *psubFile) +{ + char *p; + char *pto; + + p = psubFile->pnextChar; + if(!p) return(tokenEOF); + if(*p==0 || *p=='\n') { + p = subGetNextLine(psubFile); + if(!p) return(tokenEOF); + } + if(*p=='{') { + psubFile->token = tokenLBrace; + psubFile->pnextChar = ++p; + return(tokenLBrace); + } + if(*p=='}') { + psubFile->token = tokenRBrace; + psubFile->pnextChar = ++p; + return(tokenRBrace); + } + if(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) { + 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*/ + pto = &psubFile->string[0]; + while(!isspace(*p) && (strspn(p,"\",{}")==0)) *pto++ = *p++; + *pto = 0; + psubFile->pnextChar = p; + psubFile->token = tokenString; + return(tokenString); +} diff --git a/pattern b/pattern new file mode 100644 index 000000000..e847f7d9f --- /dev/null +++ b/pattern @@ -0,0 +1,9 @@ +#test of a pattern + pattern {a,b} +{xxx,"yyy"} + {zzz , ttt} + +{ + vvv + zzz +} diff --git a/substitute b/substitute new file mode 100644 index 000000000..c249b940e --- /dev/null +++ b/substitute @@ -0,0 +1,2 @@ +{a=xxx,b="yyy"} +{a=zzz , b=ttt} diff --git a/template b/template new file mode 100644 index 000000000..38ced3cb2 --- /dev/null +++ b/template @@ -0,0 +1,4 @@ +# comment line +$(a) +this is a test $(b) +$(d) diff --git a/testfile b/testfile new file mode 100644 index 000000000..845648365 --- /dev/null +++ b/testfile @@ -0,0 +1,13 @@ +This is a test file +This is second line +include "testfile1" +a=${a} +b=$(b) +substitute "a=aaa,b=bbb" +a=${a} +b=$(b) +substitute "a=\"aa\"" +${a} +$(a) +This is last line +%report diff --git a/testfile1 b/testfile1 new file mode 100644 index 000000000..3a61424bc --- /dev/null +++ b/testfile1 @@ -0,0 +1,4 @@ +This is testfile1 +in testfile1 $(a)=a +in testfile1 $(b)=b +end of testfile1 From 84f08a153a9f7c6e87cc74147bb0d1cd58ed717f Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Mon, 14 Dec 1998 14:46:26 +0000 Subject: [PATCH 03/32] fix imcompatibilities with subtool --- Makefile | 17 +++++++++++------ Makefile.Host | 11 +++++++++++ Makefile.Unix | 4 ++-- msi.c | 53 ++++++++++++++++++++++++++++++++++----------------- substitute | 7 +++++-- 5 files changed, 65 insertions(+), 27 deletions(-) create mode 100644 Makefile.Host diff --git a/Makefile b/Makefile index d3a001c71..39cb7cad1 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,15 @@ # # $Id$ # - -EPICS=../../.. - -include $(EPICS)/config/CONFIG_EXTENSIONS - -include $(EPICS)/config/RULES_ARCHS +TOP = ../.. +ifneq ($(wildcard $(TOP)/config)x,x) + # New Makefile.Host config file location + include $(TOP)/config/CONFIG_EXTENSIONS + include $(TOP)/config/RULES_ARCHS +else + # Old Makefile.Unix config file location + EPICS=../../.. + include $(EPICS)/config/CONFIG_EXTENSIONS + include $(EPICS)/config/RULES_ARCHS +endif diff --git a/Makefile.Host b/Makefile.Host new file mode 100644 index 000000000..65fea75e8 --- /dev/null +++ b/Makefile.Host @@ -0,0 +1,11 @@ +TOP = ../../.. +include $(TOP)/config/CONFIG_EXTENSIONS + + +PROD_LIBS += Com + +SRCS.c= ../msi.c +PROD = msi + +include $(TOP)/config/RULES.Host + diff --git a/Makefile.Unix b/Makefile.Unix index e9ccd1dff..f33d079ce 100644 --- a/Makefile.Unix +++ b/Makefile.Unix @@ -2,8 +2,8 @@ EPICS = ../../../.. include Target.include include $(EPICS)/config/CONFIG_EXTENSIONS -DEPLIBS = $(EPICS_BASE_LIB)/libCom.a $(EPICS_EXTENSIONS_LIB)/libpprsyd.a -USR_LDLIBS = -lpprsyd -lCom +DEPLIBS = $(EPICS_BASE_LIB)/libCom.a +USR_LDLIBS = -lCom USR_INCLUDES = -I$(EPICS_EXTENSIONS_INCLUDE) USR_CFLAGS = -L$(EPICS_EXTENSIONS_LIB) diff --git a/msi.c b/msi.c index 4b1a6aab8..744544a52 100644 --- a/msi.c +++ b/msi.c @@ -47,8 +47,10 @@ static void substituteOpen(void *substitutePvt,char *substitutionName); static char *substituteGetReplacements(void *substitutePvt); #define USAGEEXIT \ {\ - fprintf(stderr,"usage: msi -V -Idir ... -Msub ... -Ssubfile template \n");\ - exit(1);\ + fprintf(stderr,"usage: msi -V -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");\ + exit(1);\ } int main(int argc,char **argv) @@ -219,7 +221,6 @@ typedef struct inputData { char inputBuffer[MAX_BUFFER_SIZE]; }inputData; - static char *inputOpenFile(inputData *pinputData,char *filename); static void inputCloseFile(inputData *pinputData); static void inputCloseAllFiles(inputData *pinputData); @@ -256,20 +257,32 @@ static void inputAddPath(void *pvt, char *path) const char *pcolon; const char *pdir; int len; + int emptyName; pdir = path; - while(pdir) { - if(*pdir == ':') { - pdir++; - continue; - } + /*an empty name at beginning, middle, or end means current directory*/ + while(pdir && *pdir) { + emptyName = ((*pdir == ':') ? TRUE : FALSE); + if(emptyName) ++pdir; ppathNode = (pathNode *)calloc(1,sizeof(pathNode)); ellAdd(ppathList,&ppathNode->node); - pcolon = strchr(pdir,':'); - len = (pcolon ? (pcolon - pdir) : strlen(pdir)); - ppathNode->directory = (char *)calloc(1,len+1); - strncpy(ppathNode->directory,pdir,len); - pdir = (pcolon ? (pcolon+1) : 0); + 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=TRUE; + } + } + if(emptyName) { + ppathNode->directory = (char *)calloc(2,sizeof(char)); + strcpy(ppathNode->directory,"."); + } } return; } @@ -406,6 +419,7 @@ typedef enum { }tokenType; typedef struct subFile { + char *substitutionName; FILE *fp; int lineNum; char inputBuffer[MAX_BUFFER_SIZE]; @@ -473,6 +487,7 @@ static void substituteOpen(void *pvt,char *substitutionName) fprintf(stderr,"Could not open %s\n",substitutionName); exit(1); } + psubFile->substitutionName = substitutionName; psubFile->fp = fp; psubFile->lineNum = 0; psubFile->inputBuffer[0] = 0; @@ -517,9 +532,10 @@ static char *substituteGetReplacements(void *pvt) pNext = &psubInfo->macroReplacements[0]; psubInfo->macroReplacements[0] = 0; - if(psubFile->token!=tokenLBrace) - while(subGetNextToken(psubFile)==tokenSeparater); - if(psubFile->token==tokenEOF) return(0); + while(psubFile->token!=tokenLBrace) { + if(psubFile->token==tokenEOF) return(0); + subGetNextToken(psubFile); + } if(psubFile->token!=tokenLBrace) { subFileErrPrint(psubFile,"Expecting {"); exit(1); @@ -588,7 +604,8 @@ static char *subGetNextLine(subFile *psubFile) static void subFileErrPrint(subFile *psubFile,char * message) { - fprintf(stderr,"substitution file line %d: %s", + fprintf(stderr,"substitution file %s line %d: %s", + psubFile->substitutionName, psubFile->lineNum,psubFile->inputBuffer); fprintf(stderr,"%s\n",message); } @@ -604,7 +621,9 @@ static tokenType subGetNextToken(subFile *psubFile) if(*p==0 || *p=='\n') { p = subGetNextLine(psubFile); if(!p) return(tokenEOF); + else return(tokenSeparater); } + while(isspace(*p)) p++; if(*p=='{') { psubFile->token = tokenLBrace; psubFile->pnextChar = ++p; diff --git a/substitute b/substitute index c249b940e..22c98bb0e 100644 --- a/substitute +++ b/substitute @@ -1,2 +1,5 @@ -{a=xxx,b="yyy"} -{a=zzz , b=ttt} +{a=111,b="222"} +{ a = aaa , b=bbb} +{a= aaa +b= bbb +} From 9780eeb9fe12a4c61c1a911a8318024ce264b4f0 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Tue, 13 Apr 1999 14:12:01 +0000 Subject: [PATCH 04/32] in substutition file count comments lines --- msi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/msi.c b/msi.c index 744544a52..e4fc976d0 100644 --- a/msi.c +++ b/msi.c @@ -589,8 +589,10 @@ static char *subGetNextLine(subFile *psubFile) char *pline; pline = fgets(psubFile->inputBuffer,MAX_BUFFER_SIZE,psubFile->fp); - while(pline && psubFile->inputBuffer[0]=='#') + while(pline && psubFile->inputBuffer[0]=='#') { pline = fgets(psubFile->inputBuffer,MAX_BUFFER_SIZE,psubFile->fp); + ++psubFile->lineNum; + } if(!pline) { psubFile->token = tokenEOF; psubFile->inputBuffer[0] = 0; From cbfac53f5a30152e13483b5267c6199b58723a48 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Tue, 13 Apr 1999 17:49:15 +0000 Subject: [PATCH 05/32] add msi.html --- Makefile.Host | 2 + msi.html | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 242 insertions(+) create mode 100644 msi.html diff --git a/Makefile.Host b/Makefile.Host index 65fea75e8..684d1d8e6 100644 --- a/Makefile.Host +++ b/Makefile.Host @@ -4,6 +4,8 @@ include $(TOP)/config/CONFIG_EXTENSIONS PROD_LIBS += Com +HTMLS += msi.html + SRCS.c= ../msi.c PROD = msi diff --git a/msi.html b/msi.html new file mode 100644 index 000000000..ddec90752 --- /dev/null +++ b/msi.html @@ -0,0 +1,240 @@ + + + + + + + +

+msi: Macro Substitution and Include Tool

+Marty Kraimer +
Argonne National Laboratory - Advanced Photon Source +
Original: December 1997 +

+Introduction

+msi is a general purpose macro substitution/include tool. It accepts as +input an ascii template file. It looks for lines containing two reserved +command names: include and substitute. It also looks for and performs substitutions +on macros of the form $(var) and ${var}. It uses the macLib, an epics base +library created by William Lupton, to perform the substitutions. + +

msi also allows substitutions to be specified via a separate substitution +file. This substitution file has the same format as the substitution file +accepted by  subtool, which is provided with epics base. Subtool, +however, does not support include files. +
  +

+Command Syntax:

+ +
msi -V -Idir -Msub -Ssubfile template
+NOTE: All parameters are optional and a space is optional between  +-I, -M, and -S  and the  associated value. Output is written +to stdout. + +

Where: + +

-V +

    If this parameter is specified then an error message is generated for +all undefined macros.
+-I dir +
    This parameter, which may be repeated, specifies a search path for +include commands. For example:
+ +
+    msi -I "/home/phoebus/MRK/examples:." -I".." template
+ +
+specifies the search path:
+ +
+    /home/phoebus/MRK/examples:.:..
+ +
-M substitutions +
    This parameter, which may be repeated, specifies marco substitutions. +For example:
+ +
+    msi -M "a=aval,b=bval" -M"c=cval" template
+ +
    specifies that in the template file each occurrence of:
+ +
    +
    +$(a) or ${a} is replaced by aval
    + +
    +$(b) or ${b} is replaced by bval
    + +
    +$(c) or ${c} is replaced by cval
    + +
    Note that substitutions may also be specified in the template file +and via an optional substitution file.
+-S subfile +
    The substitution file. See below for format.
+template +
    The input file. If no file is specified then input is taken from stdin, +i.e. msi can be used as a filter. See below for a description of commands +that can be imbedded in the template file.
+NOTE: Just issuing the command: +
    msi
+ +
    Is a valid command, i.e. no options and the input file is  stdin. +To see the usage just issue the command with an invalid switch. For example: +
    msi -?
    +
+ +

+Template File Format

+This file contains the text to be read and written to stdout after macro +substitution is performed. If no file is given then input is read from +stdin. In addition the file can have lines containing include and substitute +commands. The format of these commands are: +
    include "file"
+ +
    substitute "var=value,var=value,..."
+For example let the command be: +
    msi template
+and file includeFile contain: +
    first name is ${first}
+    family name is ${family}
+and template is +
  +
    substitute "first=Marty,family=Kraimer"
+    include "includeFile"
+    substitute "first=Irma,family=Kraimer"
+    include "includeFile"
+then the following is written to stdout. +
    first name is Marty
+    family name is Kraimer
+    first name is Irma
+    family name is Kraimer
+ +

+Substitution File Format

+The optional substitution file has two formats: regular and pattern. Lets +discuss  each separately + +

regular format: +

+{var1=value1,var2=value2,...}
+ +
+{var1=value1,var2=value2,...}
+ +
+...
+ +
After reading each set of replacements within braces,   the +template file is read and macro substitution performed. + +

pattern  format: +

+pattern {var1,var2,...}
+ +
+{value1,value2,...}
+ +
+{value1,value2,...}
+ +

+Regular substitution example

+Let the command be: +
    msi -S substitute template
+and the template file +
    first name is ${first}
+    family name is ${family}
+and file substitute +
    {first=Marty,family=Kraimer}
+    {first=Irma,family=Kraimer}
+then the following is written to stdout. +
    first name is Marty
+    family name is Kraimer
+    first name is Irma
+    family name is Kraimer
+ +

+Pattern substitution example

+Let the command be: +
    msi -S pattern template
+and pattern file +
    pattern {first,last}
+    {first=Marty,family=Kraimer}
+    {first=Irma,family=Kraimer}
+then the following is written to stdout. +
    first name is Marty
+    family name is Kraimer
+    first name is Irma
+    family name is Kraimer
+ +

+Some Details

+Building msi +
    msi is built as a normal extensions product. It should be built with +base version 3.13.0beta11 or later.
+ +
+Line length limits
+ +
    All buffers containing input or output lines are set for a maximum +line length of 1024. Longer input or output lines will cause msi to fail.
+macLib +
    Currently the only macLib documentation is in macLibNOTES and macLibREADME +which are in base/src/libCom.
+template file syntax +
    except for lines containing include or substitute commands each line +is just passed to macLib. Lines containing these commands MUST be of the +form:
+ +
        include "<file name>"
+ +
        or
+ +
        substitute "<substitutions>"
+ +
    White space is allowed before and after the command and after the quoted +string. If imbedded quotes are needed the \ character can be used as an +escape character. For example:
+ +
        substitute "a=\"val\""
+ +
    specifies the substitution
+ +
        a=val
+ +
    If a line does have the above syntax it is just passed to macLib for +processing without any notification. Thus the input line:
+ +
        include "myfile" #include file
+ +
    would just be passed to macLib, i.e. it would NOT be considered an +include command.
+substitution  file syntax +
    A comment line may appear anywhere and is just ignored. A comment line +is any line beginning with the character #, which MUST be the very first +character of the comment line. + +

    For items within braces separators may be given between items. A separator +is either white space or a comma. White space is any of the following: +space, formfeed, newline, carriage return, tab, vertical tab. + +

    Each item within braces can be an alphanumeric token or a quoted string. +The characters \" can be used for imbedded quotes. The rules for non quoted +strings are actually more relaxed but any item that is not an alphanumeric +string should be given as a quoted string. + +

    Thus +

        {a=aa b=bb c="\"cc\""}
    +and +
        {a=aa,b=bb,c="\"cc\""}
    +and +
        {
    +        a="aa"
    +        b="bb",
    +        c="\"cc\""
    +    }
    +are all equivalent.
+ + + From 999ef9fd5086392b258f5e9f83de4cea5317c287 Mon Sep 17 00:00:00 2001 From: cvs2svn Date: Tue, 13 Apr 1999 17:49:16 +0000 Subject: [PATCH 06/32] This commit was manufactured by cvs2svn to create tag 'MSI-R1-1'. From 3e6e54d80103347490c76ac4b7871aa489dcc222 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Mon, 3 May 1999 13:21:09 +0000 Subject: [PATCH 07/32] provide support for dbTemplate expansion --- msi.c | 280 ++++++++++++++++++++++++++---------------- msi.html | 368 +++++++++++++++++++++++++++++++------------------------ 2 files changed, 384 insertions(+), 264 deletions(-) diff --git a/msi.c b/msi.c index e4fc976d0..70e97d505 100644 --- a/msi.c +++ b/msi.c @@ -28,6 +28,7 @@ of this distribution. #define MAX_BUFFER_SIZE 1024 /*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); @@ -41,17 +42,10 @@ static void inputNewIncludeFile(void *inputPvt,char *name); static void inputErrPrint(void *inputPvt); /*Routines that read the substitution file */ -static void substituteConstruct(void **substitutePvt); static void substituteDestruct(void *substitutePvt); -static void substituteOpen(void *substitutePvt,char *substitutionName); +static void substituteOpen(void **substitutePvt,char *substitutionName); +static int substituteGetNextSet(void *substitutePvt,char **filename); static char *substituteGetReplacements(void *substitutePvt); -#define USAGEEXIT \ -{\ - fprintf(stderr,"usage: msi -V -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");\ - exit(1);\ -} int main(int argc,char **argv) { @@ -80,48 +74,71 @@ int main(int argc,char **argv) macSuppressWarning(macPvt,FALSE); narg = 1; /* no argument for this option */ } else { - USAGEEXIT + usageExit(); } argc -= narg; for(i=1; i2) { fprintf(stderr,"too many files\n"); - USAGEEXIT + usageExit(); + } + if(argc==2) { + templateName = calloc(strlen(argv[1])+1,sizeof(char)); + strcpy(templateName,argv[1]); } - if(argc==2) templateName = argv[1]; if(!substitutionName) { makeSubstitutions(inputPvt,macPvt,templateName); } else { void *substitutePvt; + char *filename = 0; - if(!templateName) { - fprintf(stderr,"stdin not legal with substitution file\n"); - USAGEEXIT - } - substituteConstruct(&substitutePvt); - substituteOpen(substitutePvt,substitutionName); - while(pval = substituteGetReplacements(substitutePvt)){ - addMacroReplacements(macPvt,pval); - makeSubstitutions(inputPvt,macPvt,templateName); - } + substituteOpen(&substitutePvt,substitutionName); + while(substituteGetNextSet(substitutePvt,&filename)) { + if(templateName) filename = templateName; + if(!filename) { + fprintf(stderr,"no template file\n"); + usageExit(); + } + while(pval = substituteGetReplacements(substitutePvt)){ + addMacroReplacements(macPvt,pval); + makeSubstitutions(inputPvt,macPvt,filename); + } + } substituteDestruct(substitutePvt); } inputDestruct(inputPvt); + free((void *)templateName); + free((void *)substitutionName); return(0); } +void usageExit(void) +{ + fprintf(stderr,"usage: msi -V -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"); + exit(1); +} + static void addMacroReplacements(MAC_HANDLE *macPvt,char *pval) { char **pairs; long status; status = macParseDefns(macPvt,pval,&pairs); + if(!status) { + fprintf(stderr,"Error macParseDefns error\n"); + usageExit(); + } status = macInstallMacros(macPvt,pairs); + if(!status) { + fprintf(stderr,"Error macInstallMacros error\n"); + usageExit(); + } free((void *)pairs); } - #define cmdNumberOf 2 typedef enum {cmdInclude,cmdSubstitute} cmdType; static char *cmdName[cmdNumberOf] = {"include","substitute"}; @@ -172,8 +189,11 @@ static void makeSubstitutions(void *inputPvt,void *macPvt,char *templateName) } ++p; } - if(*p==0) goto endif; 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) { @@ -221,10 +241,10 @@ typedef struct inputData { char inputBuffer[MAX_BUFFER_SIZE]; }inputData; -static char *inputOpenFile(inputData *pinputData,char *filename); +static void inputOpenFile(inputData *pinputData,char *filename); static void inputCloseFile(inputData *pinputData); static void inputCloseAllFiles(inputData *pinputData); - + static void inputConstruct(void **ppvt) { inputData *pinputData; @@ -248,7 +268,7 @@ static void inputDestruct(void *pvt) } free(pvt); } - + static void inputAddPath(void *pvt, char *path) { inputData *pinputData = (inputData *)pvt; @@ -344,7 +364,7 @@ static void inputErrPrint(void *pvt) fprintf(stderr,"\n"); } -static char *inputOpenFile(inputData *pinputData,char *filename) +static void inputOpenFile(inputData *pinputData,char *filename) { ELLLIST *ppathList = &pinputData->pathList; pathNode *ppathNode = 0; @@ -372,7 +392,8 @@ static char *inputOpenFile(inputData *pinputData,char *filename) } if(!fp) { fprintf(stderr,"Could not open %s\n",filename); - return(0); + inputErrPrint((void *)pinputData); + exit(1); } pinputFile = calloc(1,sizeof(inputFile)); if(ppathNode) { @@ -388,9 +409,8 @@ static char *inputOpenFile(inputData *pinputData,char *filename) } pinputFile->fp = fp; ellInsert(&pinputData->inputFileList,0,&pinputFile->node); - return(0); } - + static void inputCloseFile(inputData *pinputData) { inputFile *pinputFile; @@ -435,6 +455,8 @@ typedef struct patternNode { typedef struct subInfo { subFile *psubFile; + int isFile; + char *filename; int isPattern; ELLLIST patternList; char macroReplacements[MAX_BUFFER_SIZE]; @@ -443,61 +465,105 @@ typedef struct subInfo { static char *subGetNextLine(subFile *psubFile); static tokenType subGetNextToken(subFile *psubFile); static void subFileErrPrint(subFile *psubFile,char * message); - -static void substituteConstruct(void **pvt) -{ - subFile *psubFile; - subInfo *psubInfo; +static void freeSubFile(subInfo *psubInfo); +static void freePattern(subInfo *psubInfo); - psubInfo = calloc(1,sizeof(subInfo)); - psubFile = calloc(1,sizeof(subFile)); - ellInit(&psubInfo->patternList); - psubInfo->psubFile = psubFile; - *pvt = psubInfo; - return; +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; } -static void substituteDestruct(void *pvt) +void freePattern(subInfo *psubInfo) { - subInfo *psubInfo = (subInfo *)pvt; - subFile *psubFile = psubInfo->psubFile; patternNode *ppatternNode; - - if(fclose(psubFile->fp)) - fprintf(stderr,"fclose failed on substitution file\n"); while(ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList)) { ellDelete(&psubInfo->patternList,&ppatternNode->node); free(ppatternNode->var); free(ppatternNode); } - free((void *)psubFile); - free((void *)psubInfo); - return; + psubInfo->isPattern = FALSE; } -static void substituteOpen(void *pvt,char *substitutionName) +static void substituteDestruct(void *pvt) { subInfo *psubInfo = (subInfo *)pvt; subFile *psubFile = psubInfo->psubFile; + + freePattern(psubInfo); + freeSubFile(psubInfo); + free((void *)psubInfo); + return; +} + +static void substituteOpen(void **ppvt,char *substitutionName) +{ + subInfo *psubInfo; + subFile *psubFile; FILE *fp; patternNode *ppatternNode; + 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); + exit(1); } psubFile->substitutionName = substitutionName; psubFile->fp = fp; psubFile->lineNum = 0; psubFile->inputBuffer[0] = 0; psubFile->pnextChar = &psubFile->inputBuffer[0]; - while(subGetNextToken(psubFile)==tokenSeparater); + subGetNextToken(psubFile); + return; +} + +static int substituteGetNextSet(void *pvt,char **filename) +{ + subInfo *psubInfo = (subInfo *)pvt; + subFile *psubFile = psubInfo->psubFile; + FILE *fp; + patternNode *ppatternNode; + + *filename = 0; + while(psubFile->token==tokenSeparater) subGetNextToken(psubFile); + if(psubFile->token==tokenEOF) return(FALSE); + if(psubFile->token==tokenString && strcmp(psubFile->string,"file")==0) { + psubInfo->isFile = TRUE; + if(subGetNextToken(psubFile)!=tokenString) { + subFileErrPrint(psubFile,"Expecting filename"); + exit(1); + } + freePattern(psubInfo); + free((void *)psubInfo->filename); + psubInfo->filename = calloc(strlen(psubFile->string)+1,sizeof(char)); + strcpy(psubInfo->filename,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(TRUE); if(psubFile->token!=tokenString || strcmp(psubFile->string,"pattern")!=0) { - psubInfo->isPattern = FALSE; - return; + subFileErrPrint(psubFile,"Expecting pattern"); + exit(1); } + freePattern(psubInfo); psubInfo->isPattern = TRUE; while(subGetNextToken(psubFile)==tokenSeparater); if(psubFile->token!=tokenLBrace) { @@ -505,22 +571,19 @@ static void substituteOpen(void *pvt,char *substitutionName) exit(1); } while(TRUE) { - subGetNextToken(psubFile); - if(psubFile->token==tokenSeparater) continue; - if(psubFile->token==tokenString) { - ppatternNode = calloc(1,sizeof(patternNode)); - ellAdd(&psubInfo->patternList,&ppatternNode->node); - ppatternNode->var = calloc(strlen(psubFile->string)+1,sizeof(char)); - strcpy(ppatternNode->var,psubFile->string); - continue; - } - break; + 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); } - return; + subGetNextToken(psubFile); + return(TRUE); } static char *substituteGetReplacements(void *pvt) @@ -532,45 +595,50 @@ static char *substituteGetReplacements(void *pvt) pNext = &psubInfo->macroReplacements[0]; psubInfo->macroReplacements[0] = 0; - while(psubFile->token!=tokenLBrace) { - if(psubFile->token==tokenEOF) return(0); - subGetNextToken(psubFile); - } - if(psubFile->token!=tokenLBrace) { - subFileErrPrint(psubFile,"Expecting {"); - exit(1); + while(psubFile->token==tokenSeparater) subGetNextToken(psubFile); + if(psubFile->token==tokenRBrace && psubInfo->isFile) { + psubInfo->isFile = FALSE; + 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 = FALSE; + while(subGetNextToken(psubFile)==tokenSeparater); ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList); - if(!ppatternNode) { - subFileErrPrint(psubFile,"No patterns"); - exit(1); - } while(TRUE) { - switch(subGetNextToken(psubFile)) { - case tokenSeparater: continue; - case tokenRBrace: return(psubInfo->macroReplacements); - case tokenString: - if(gotFirstPattern) { - strcat(psubInfo->macroReplacements,","); - } - gotFirstPattern = TRUE; - strcat(psubInfo->macroReplacements,ppatternNode->var); - strcat(psubInfo->macroReplacements,"="); - strcat(psubInfo->macroReplacements,psubFile->string); - break; - default: - subFileErrPrint(psubFile,"Illegal token"); - exit(1); - } - ppatternNode = (patternNode *)ellNext(&ppatternNode->node); - + 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) strcat(psubInfo->macroReplacements,","); + gotFirstPattern = TRUE; + if(ppatternNode) { + strcat(psubInfo->macroReplacements,ppatternNode->var); + strcat(psubInfo->macroReplacements,"="); + strcat(psubInfo->macroReplacements,psubFile->string); + ppatternNode = (patternNode *)ellNext(&ppatternNode->node); + } else { + subFileErrPrint(psubFile,"more values than patterns"); + } + while(subGetNextToken(psubFile)==tokenSeparater); } } else while(TRUE) { - switch(subGetNextToken(psubFile)) { - case tokenRBrace: return(psubInfo->macroReplacements); + switch(subGetNextToken(psubFile)) { + case tokenRBrace: + subGetNextToken(psubFile); + return(psubInfo->macroReplacements); case tokenSeparater: strcat(psubInfo->macroReplacements,","); break; @@ -589,6 +657,7 @@ 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); ++psubFile->lineNum; @@ -600,7 +669,6 @@ static char *subGetNextLine(subFile *psubFile) return(0); } psubFile->pnextChar = &psubFile->inputBuffer[0]; - ++psubFile->lineNum; return(&psubFile->inputBuffer[0]); } @@ -619,11 +687,11 @@ static tokenType subGetNextToken(subFile *psubFile) char *pto; p = psubFile->pnextChar; - if(!p) return(tokenEOF); - if(*p==0 || *p=='\n') { + if(!p) { psubFile->token = tokenEOF; return(tokenEOF);} + if(*p==0 || *p=='\n' || *p=='#') { p = subGetNextLine(psubFile); - if(!p) return(tokenEOF); - else return(tokenSeparater); + if(!p) { psubFile->token = tokenEOF; return(tokenEOF);} + else { psubFile->token = tokenSeparater; return(tokenSeparater);} } while(isspace(*p)) p++; if(*p=='{') { @@ -636,7 +704,7 @@ static tokenType subGetNextToken(subFile *psubFile) psubFile->pnextChar = ++p; return(tokenRBrace); } - if(isspace(*p) || *p==',') { + if(*p==0 || isspace(*p) || *p==',') { while(isspace(*p) || *p==',') p++; psubFile->token = tokenSeparater; psubFile->pnextChar = p; @@ -647,7 +715,7 @@ static tokenType subGetNextToken(subFile *psubFile) pto = &psubFile->string[0]; *pto++ = *p++; while(*p!='"') { - if(*p==0) { + if(*p==0 || *p=='\n') { subFileErrPrint(psubFile,"Strings must be on single line\n"); exit(1); } @@ -665,7 +733,7 @@ static tokenType subGetNextToken(subFile *psubFile) psubFile->token = tokenString; return(tokenString); } - /*Now take anything up to next non String token*/ + /*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; diff --git a/msi.html b/msi.html index ddec90752..eb9a6a027 100644 --- a/msi.html +++ b/msi.html @@ -1,240 +1,292 @@ - - - - - - + + + + + + + -

-msi: Macro Substitution and Include Tool

+

+msi: Macro Substitution and Include Tool

Marty Kraimer -
Argonne National Laboratory - Advanced Photon Source -
Original: December 1997 -

-Introduction

+
Argonne National Laboratory - Advanced Photon Source +
Original:  April 26, 1999 +

+Introduction

msi is a general purpose macro substitution/include tool. It accepts as input an ascii template file. It looks for lines containing two reserved command names: include and substitute. It also looks for and performs substitutions on macros of the form $(var) and ${var}. It uses the macLib, an epics base library created by William Lupton, to perform the substitutions. +

msi also allows substitutions to be specified via a separate substitution +file. This substitution file allows the same format as the substitution +files accepted by dbLoadTemplate or subtool. +
  +

+Command Syntax:

-

msi also allows substitutions to be specified via a separate substitution -file. This substitution file has the same format as the substitution file -accepted by  subtool, which is provided with epics base. Subtool, -however, does not support include files. -
  -

-Command Syntax:

- -
msi -V -Idir -Msub -Ssubfile template
+
msi -V -Idir -Msub -Ssubfile template
NOTE: All parameters are optional and a space is optional between  -I, -M, and -S  and the  associated value. Output is written to stdout. +

Where: +

-V +

    If this parameter is specified then an undefined macro is considered +an error. An error message is generated and the line containing the macro +is not written to stdout.
+-I dir +
    This parameter, which may be repeated, specifies a search path for +include commands. For example:
-

Where: +

+    msi -I "/home/phoebus/MRK/examples:." -I".." template
-

-V -

    If this parameter is specified then an error message is generated for -all undefined macros.
--I dir -
    This parameter, which may be repeated, specifies a search path for -include commands. For example:
+
+specifies the search path:
-
-    msi -I "/home/phoebus/MRK/examples:." -I".." template
+
+    /home/phoebus/MRK/examples:.:..
-
-specifies the search path:
+
-M substitutions +
    This parameter, which may be repeated, specifies marco substitutions. +For example:
-
-    /home/phoebus/MRK/examples:.:..
+
+    msi -M "a=aval,b=bval" -M"c=cval" template
-
-M substitutions -
    This parameter, which may be repeated, specifies marco substitutions. -For example:
+
    specifies that in the template file each occurrence of:
-
-    msi -M "a=aval,b=bval" -M"c=cval" template
+
    +
    +$(a) or ${a} is replaced by aval
    -
      specifies that in the template file each occurrence of:
    +
    +$(b) or ${b} is replaced by bval
    -
      -
      -$(a) or ${a} is replaced by aval
      - -
      -$(b) or ${b} is replaced by bval
      - -
      -$(c) or ${c} is replaced by cval
      - -
      Note that substitutions may also be specified in the template file -and via an optional substitution file.
    +
    +$(c) or ${c} is replaced by cval
    +
-S subfile -
    The substitution file. See below for format.
+
    The substitution file. See below for format.
template -
    The input file. If no file is specified then input is taken from stdin, +
      The input file. If no file is specified then input is taken from stdin, i.e. msi can be used as a filter. See below for a description of commands -that can be imbedded in the template file.
    -NOTE: Just issuing the command: -
        msi
    +that can be imbedded in the template file.
+NOTE: It is not possible to display usage by just typing msi since +executing the command with no arguments i s a valid command. To show usage +specify an illegal switch, e.g. +
    +
    msi -help
    +
-
    Is a valid command, i.e. no options and the input file is  stdin. -To see the usage just issue the command with an invalid switch. For example: -
    msi -?
    -
- -

-Template File Format

+

+Template File Format

This file contains the text to be read and written to stdout after macro substitution is performed. If no file is given then input is read from stdin. In addition the file can have lines containing include and substitute commands. The format of these commands are: -
    include "file"
+
    include "file"
-
    substitute "var=value,var=value,..."
+
    substitute "var=value,var=value,..."
For example let the command be: -
    msi template
+
    msi template
and file includeFile contain: -
    first name is ${first}
-    family name is ${family}
+
    first name is ${first}
+    family name is ${family}
and template is -
  -
    substitute "first=Marty,family=Kraimer"
+
  +
    substitute "first=Marty,family=Kraimer"
     include "includeFile"
     substitute "first=Irma,family=Kraimer"
-    include "includeFile"
+    include "includeFile"
then the following is written to stdout. -
    first name is Marty
+
    first name is Marty
     family name is Kraimer
     first name is Irma
-    family name is Kraimer
+    family name is Kraimer
-

-Substitution File Format

-The optional substitution file has two formats: regular and pattern. Lets -discuss  each separately +

+Substitution File Format

+The optional substitution file has three formats: regular, pattern, and +dbTemplate format. Lets discuss  each separately +
  +

+regular format

-

regular format: -

-{var1=value1,var2=value2,...}
+
+
{var1=value1,var2=value2,...}
+{var1=value1,var2=value2,...}
+...
+
+After reading each set of replacements within braces,   the template +file is read and macro substitution performed. +
  +

+pattern  format:

-
-{var1=value1,var2=value2,...}
+
+
pattern {var1,var2,...}
+{value1,value2,...}
+{value1,value2,...}
+pattern {var1,var2,...}
+{value1,value2,...}
+{value1,value2,...}
+
+This is the same as the regular format: +
+
{var1=value1,var2=value2}
+...
+
-
-...
+

+dbTemplate Format

-
After reading each set of replacements within braces,   the -template file is read and macro substitution performed. +
+
file template {
+    pattern format or regular format
+}
-

pattern  format: -

-pattern {var1,var2,...}
- -
-{value1,value2,...}
- -
-{value1,value2,...}
- -

-Regular substitution example

+
file template {
+    pattern format or regular format
+}
+
+For thedbTemplate format, the command line template argument is optional. +If it specified it is used, otherwise the file template is used. This format +is an extension of the format accepted by dbLoadTemplate. It allows templates +to be  expanded on the host rather via dbLoadTemplate. +

+Regular substitution example

Let the command be: -
    msi -S substitute template
-and the template file -
    first name is ${first}
-    family name is ${family}
-and file substitute -
    {first=Marty,family=Kraimer}
-    {first=Irma,family=Kraimer}
-then the following is written to stdout. -
    first name is Marty
+
    msi -S substitute template
+template is +
    first name is ${first}
+    family name is ${family}
+substitute is +
    {first=Marty,family=Kraimer}
+    {first=Irma,family=Kraimer}
+The following is written to stdout. +
    first name is Marty
     family name is Kraimer
     first name is Irma
-    family name is Kraimer
+    family name is Kraimer
-

-Pattern substitution example

+

+Pattern substitution example

Let the command be: -
    msi -S pattern template
-and pattern file -
    pattern {first,last}
-    {first=Marty,family=Kraimer}
-    {first=Irma,family=Kraimer}
-then the following is written to stdout. -
    first name is Marty
+
    msi -S pattern template
+pattern is +
    pattern {first,last}
+    {Marty,Kraimer}
+    {Irma,Kraimer}
+template is the same as in the previous example. +

The following is written to stdout. +

    first name is Marty
     family name is Kraimer
     first name is Irma
-    family name is Kraimer
+    family name is Kraimer
-

-Some Details

+

+dbTemplate example

+Let the command be +
+
msi -S xxx.substitutions
+
+xxx.substitutions is +
+
file template {
+    pattern {first,last}
+    {Marty,Kraimer}
+    {Irma,Kraimer}
+    pattern {last,first}
+    {Smith,Bill}
+    {Smith,Mary}
+}
+file template {
+    {first=Marty,last=Kraimer}
+    {first=Irma,last=Kraimer}
+}
+
+template is the same as in the previous example.. +

The following is written to stdout +

+
first name is Marty
+family name is Kraimer
+first name is Irma
+family name is Kraimer
+first name is Bill
+last name is Smith
+first name is Mary
+last name is Smith
+first name is Marty
+family name is Kraimer
+first name is Irma
+family name is Kraimer
+
+ +

+Some Details

Building msi -
    msi is built as a normal extensions product. It should be built with -base version 3.13.0beta11 or later.
+
    msi is built as a normal extensions product. It should be built with +base version 3.13.0beta11 or later.
-
-Line length limits
+
+Line length limits
-
    All buffers containing input or output lines are set for a maximum -line length of 1024. Longer input or output lines will cause msi to fail.
+
    All buffers containing input or output lines are set for a maximum +line length of 1024. Longer input or output lines will cause msi to fail.
macLib -
    Currently the only macLib documentation is in macLibNOTES and macLibREADME -which are in base/src/libCom.
+
    Currently the only macLib documentation is in macLibNOTES and macLibREADME +which are in base/src/libCom.
template file syntax -
    except for lines containing include or substitute commands each line +
      except for lines containing include or substitute commands each line is just passed to macLib. Lines containing these commands MUST be of the -form:
    +form:
-
        include "<file name>"
+
        include "<file name>"
-
        or
+
        or
-
        substitute "<substitutions>"
+
        substitute "<substitutions>"
-
    White space is allowed before and after the command and after the quoted +
      White space is allowed before and after the command and after the quoted string. If imbedded quotes are needed the \ character can be used as an -escape character. For example:
    +escape character. For example:
-
        substitute "a=\"val\""
+
        substitute "a=\"val\""
-
    specifies the substitution
+
    specifies the substitution
-
        a=val
+
        a=val
-
    If a line does have the above syntax it is just passed to macLib for -processing without any notification. Thus the input line:
+
    If a line does have the above syntax it is just passed to macLib for +processing without any notification. Thus the input line:
-
        include "myfile" #include file
+
        include "myfile" #include file
-
    would just be passed to macLib, i.e. it would NOT be considered an -include command.
+
    would just be passed to macLib, i.e. it would NOT be considered an +include command.
substitution  file syntax -
    A comment line may appear anywhere and is just ignored. A comment line +
      A comment line may appear anywhere and is just ignored. A comment line is any line beginning with the character #, which MUST be the very first character of the comment line. - -

      For items within braces separators may be given between items. A separator +

      For items within braces separators may be given between items. A separator is either white space or a comma. White space is any of the following: space, formfeed, newline, carriage return, tab, vertical tab. - -

      Each item within braces can be an alphanumeric token or a quoted string. +

      Each item within braces can be an alphanumeric token or a quoted string. The characters \" can be used for imbedded quotes. The rules for non quoted strings are actually more relaxed but any item that is not an alphanumeric string should be given as a quoted string. - -

      Thus -

          {a=aa b=bb c="\"cc\""}
      +

      Thus +

          {a=aa b=bb c="\"cc\""}
      and -
          {a=aa,b=bb,c="\"cc\""}
      +
          {a=aa,b=bb,c="\"cc\""}
      and -
          {
      +
          {
               a="aa"
               b="bb",
               c="\"cc\""
      -    }
      -are all equivalent.
    +    } +are all equivalent.
- - + + From 086703a07a70d197a45085c28f3c7398c0b98672 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Thu, 6 Jan 2000 22:03:28 +0000 Subject: [PATCH 08/32] make MAX_BUFFER_SIZE larger; allow empty substitutions --- msi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/msi.c b/msi.c index 70e97d505..766c73a8f 100644 --- a/msi.c +++ b/msi.c @@ -25,7 +25,7 @@ of this distribution. #include #include -#define MAX_BUFFER_SIZE 1024 +#define MAX_BUFFER_SIZE 4096 /*Forward references to local routines*/ static void usageExit(void); @@ -558,6 +558,7 @@ static int substituteGetNextSet(void *pvt,char **filename) *filename = psubInfo->filename; while(psubFile->token==tokenSeparater) subGetNextToken(psubFile); if(psubFile->token==tokenLBrace) return(TRUE); + if(psubFile->token==tokenRBrace) return(FALSE); if(psubFile->token!=tokenString || strcmp(psubFile->string,"pattern")!=0) { subFileErrPrint(psubFile,"Expecting pattern"); From 34431b0a811f3c9fc855a40dc3af5d397dc21256 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Wed, 5 Apr 2000 14:22:21 +0000 Subject: [PATCH 09/32] allow substitutions buffer to grow --- msi.c | 48 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/msi.c b/msi.c index 766c73a8f..f8308c423 100644 --- a/msi.c +++ b/msi.c @@ -459,7 +459,9 @@ typedef struct subInfo { char *filename; int isPattern; ELLLIST patternList; - char macroReplacements[MAX_BUFFER_SIZE]; + size_t size; + size_t curLength; + char *macroReplacements; }subInfo; static char *subGetNextLine(subFile *psubFile); @@ -467,6 +469,7 @@ 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) { @@ -591,11 +594,10 @@ static char *substituteGetReplacements(void *pvt) { subInfo *psubInfo = (subInfo *)pvt; subFile *psubFile = psubInfo->psubFile; - char *pNext; patternNode *ppatternNode; - pNext = &psubInfo->macroReplacements[0]; - psubInfo->macroReplacements[0] = 0; + if(psubInfo->macroReplacements) psubInfo->macroReplacements[0] = 0; + psubInfo->curLength = 0; while(psubFile->token==tokenSeparater) subGetNextToken(psubFile); if(psubFile->token==tokenRBrace && psubInfo->isFile) { psubInfo->isFile = FALSE; @@ -623,12 +625,12 @@ static char *substituteGetReplacements(void *pvt) subFileErrPrint(psubFile,"Illegal token"); exit(-1); } - if(gotFirstPattern) strcat(psubInfo->macroReplacements,","); + if(gotFirstPattern) catMacroReplacements(psubInfo,","); gotFirstPattern = TRUE; if(ppatternNode) { - strcat(psubInfo->macroReplacements,ppatternNode->var); - strcat(psubInfo->macroReplacements,"="); - strcat(psubInfo->macroReplacements,psubFile->string); + catMacroReplacements(psubInfo,ppatternNode->var); + catMacroReplacements(psubInfo,"="); + catMacroReplacements(psubInfo,psubFile->string); ppatternNode = (patternNode *)ellNext(&ppatternNode->node); } else { subFileErrPrint(psubFile,"more values than patterns"); @@ -641,10 +643,10 @@ static char *substituteGetReplacements(void *pvt) subGetNextToken(psubFile); return(psubInfo->macroReplacements); case tokenSeparater: - strcat(psubInfo->macroReplacements,","); + catMacroReplacements(psubInfo,","); break; case tokenString: - strcat(psubInfo->macroReplacements,psubFile->string); + catMacroReplacements(psubInfo,psubFile->string); break; default: subFileErrPrint(psubFile,"Illegal token"); @@ -742,3 +744,29 @@ static tokenType subGetNextToken(subFile *psubFile) 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 %d\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; +} From db2724bbc9c655e5518dafd95d7494f2db2971fe Mon Sep 17 00:00:00 2001 From: "Janet B. Anderson" Date: Fri, 2 Aug 2002 15:39:51 +0000 Subject: [PATCH 10/32] Added license information. --- LICENSE | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ Makefile | 21 ++++++++--------- Makefile.Host | 8 +++++++ Makefile.Unix | 16 ------------- msi.c | 18 +++++++-------- 5 files changed, 90 insertions(+), 37 deletions(-) create mode 100644 LICENSE delete mode 100644 Makefile.Unix diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..9f03a0c48 --- /dev/null +++ b/LICENSE @@ -0,0 +1,64 @@ +Copyright (c) 2002 University of Chicago. All rights reserved. + +msi is distributed subject to the following license conditions: + + SOFTWARE LICENSE AGREEMENT + Software: Macro Substitution and Include Tool (msi) + + 1. The "Software", below, refers to msi (in either source code, or + binary form and accompanying documentation). Each licensee is + addressed as "you" or "Licensee." + + 2. The copyright holders shown above and their third-party licensors + hereby grant Licensee a royalty-free nonexclusive license, subject to + the limitations stated herein and U.S. Government license rights. + + 3. You may modify and make a copy or copies of the Software for use + within your organization, if you meet the following conditions: + a. Copies in source code must include the copyright notice and this + Software License Agreement. + b. Copies in binary form must include the copyright notice and this + Software License Agreement in the documentation and/or other + materials provided with the copy. + + 4. You may modify a copy or copies of the Software or any portion of it, + thus forming a work based on the Software, and distribute copies of + such work outside your organization, if you meet all of the following + conditions: + a. Copies in source code must include the copyright notice and this + Software License Agreement; + b. Copies in binary form must include the copyright notice and this + Software License Agreement in the documentation and/or other + materials provided with the copy; + c. Modified copies and works based on the Software must carry + prominent notices stating that you changed specified portions of + the Software. + + 5. Portions of the Software resulted from work developed under a U.S. + Government contract and are subject to the following license: the + Government is granted for itself and others acting on its behalf a + paid-up, nonexclusive, irrevocable worldwide license in this computer + software to reproduce, prepare derivative works, and perform publicly + and display publicly. + + 6. WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS" WITHOUT WARRANTY + OF ANY KIND. THE COPYRIGHT HOLDERS, THEIR THIRD PARTY LICENSORS, THE + UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND THEIR + EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE, TITLE OR NON-INFRINGEMENT, (2) DO NOT ASSUME + ANY LEGAL LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, + OR USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF THE + SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4) DO NOT WARRANT + THAT THE SOFTWARE WILL FUNCTION UNINTERRUPTED, THAT IT IS ERROR-FREE + OR THAT ANY ERRORS WILL BE CORRECTED. + + 7. LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT HOLDERS, THEIR + THIRD PARTY LICENSORS, THE UNITED STATES, THE UNITED STATES DEPARTMENT + OF ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT, INCIDENTAL, + CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF ANY KIND OR NATURE, + INCLUDING BUT NOT LIMITED TO LOSS OF PROFITS OR LOSS OF DATA, FOR ANY + REASON WHATSOEVER, WHETHER SUCH LIABILITY IS ASSERTED ON THE BASIS OF + CONTRACT, TORT (INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR + OTHERWISE, EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE + POSSIBILITY OF SUCH LOSS OR DAMAGES. diff --git a/Makefile b/Makefile index 39cb7cad1..c4e78f1c4 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,14 @@ +#************************************************************************* +# 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. +#************************************************************************* # # $Id$ # TOP = ../.. -ifneq ($(wildcard $(TOP)/config)x,x) - # New Makefile.Host config file location - include $(TOP)/config/CONFIG_EXTENSIONS - include $(TOP)/config/RULES_ARCHS -else - # Old Makefile.Unix config file location - EPICS=../../.. - include $(EPICS)/config/CONFIG_EXTENSIONS - include $(EPICS)/config/RULES_ARCHS -endif - +include $(TOP)/config/CONFIG_EXTENSIONS +include $(TOP)/config/RULES_ARCHS diff --git a/Makefile.Host b/Makefile.Host index 684d1d8e6..1e5493b63 100644 --- a/Makefile.Host +++ b/Makefile.Host @@ -1,3 +1,11 @@ +#************************************************************************* +# 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. +#************************************************************************* TOP = ../../.. include $(TOP)/config/CONFIG_EXTENSIONS diff --git a/Makefile.Unix b/Makefile.Unix deleted file mode 100644 index f33d079ce..000000000 --- a/Makefile.Unix +++ /dev/null @@ -1,16 +0,0 @@ -EPICS = ../../../.. -include Target.include -include $(EPICS)/config/CONFIG_EXTENSIONS - -DEPLIBS = $(EPICS_BASE_LIB)/libCom.a -USR_LDLIBS = -lCom -USR_INCLUDES = -I$(EPICS_EXTENSIONS_INCLUDE) -USR_CFLAGS = -L$(EPICS_EXTENSIONS_LIB) - -#CMPLR = OLD - -SRCS.c= ../msi.c -PROD = msi - -include $(EPICS)/config/RULES.Unix - diff --git a/msi.c b/msi.c index f8308c423..88d5ed506 100644 --- a/msi.c +++ b/msi.c @@ -1,14 +1,12 @@ +/*************************************************************************\ +* 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 */ -/***************************************************************** - COPYRIGHT NOTIFICATION -***************************************************************** - -(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO - -This software was developed under a United States Government license -described on the COPYRIGHT_UniversityOfChicago file included as part -of this distribution. -**********************************************************************/ /* * Modification Log: From 0b6dfa961d9c9685ccd65ab38005a8b69797f151 Mon Sep 17 00:00:00 2001 From: cvs2svn Date: Fri, 2 Aug 2002 15:39:52 +0000 Subject: [PATCH 11/32] This commit was manufactured by cvs2svn to create tag 'MSI-R1-2'. From e79662e0e101e30a897a8871ddd2c8b4a951bac5 Mon Sep 17 00:00:00 2001 From: "W. Eric Norum" Date: Thu, 14 Aug 2003 13:52:35 +0000 Subject: [PATCH 12/32] Add -o command-line option to specify output file. Perform environment variable macro expansion of substitution file names. --- msi.c | 17 ++++++++++++++--- msi.html | 32 +++++++++++++++++++------------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/msi.c b/msi.c index 88d5ed506..82ae20aaf 100644 --- a/msi.c +++ b/msi.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -63,6 +64,11 @@ int main(int argc,char **argv) 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) { @@ -113,7 +119,7 @@ int main(int argc,char **argv) void usageExit(void) { - fprintf(stderr,"usage: msi -V -Ipath ... -Msub ... -Ssubfile template\n"); + 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"); exit(1); @@ -547,8 +553,13 @@ static int substituteGetNextSet(void *pvt,char **filename) } freePattern(psubInfo); free((void *)psubInfo->filename); - psubInfo->filename = calloc(strlen(psubFile->string)+1,sizeof(char)); - strcpy(psubInfo->filename,psubFile->string); + 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 {"); diff --git a/msi.html b/msi.html index eb9a6a027..328e8f0f0 100644 --- a/msi.html +++ b/msi.html @@ -25,15 +25,18 @@ files accepted by dbLoadTemplate or subtool.

Command Syntax:

-
msi -V -Idir -Msub -Ssubfile template
+
msi -V -ofile -Idir -Msub -Ssubfile template
NOTE: All parameters are optional and a space is optional between  --I, -M, and -S  and the  associated value. Output is written -to stdout. +-o, -I, -M, and -S  and the  associated value. Output is written +to stdout unless the -o option is given.

Where:

-V

    If this parameter is specified then an undefined macro is considered an error. An error message is generated and the line containing the macro -is not written to stdout.
+is not written to the output. +-o file +
    Output will be written to the specifed file rather than to the standard output.
+ -I dir
    This parameter, which may be repeated, specifies a search path for include commands. For example:
@@ -71,7 +74,7 @@ $(c) or ${c} is replaced by cval template
    The input file. If no file is specified then input is taken from stdin, i.e. msi can be used as a filter. See below for a description of commands -that can be imbedded in the template file.
+that can be embedded in the template file. NOTE: It is not possible to display usage by just typing msi since executing the command with no arguments i s a valid command. To show usage specify an illegal switch, e.g. @@ -81,7 +84,7 @@ specify an illegal switch, e.g.

Template File Format

-This file contains the text to be read and written to stdout after macro +This file contains the text to be read and written to the output after macro substitution is performed. If no file is given then input is read from stdin. In addition the file can have lines containing include and substitute commands. The format of these commands are: @@ -99,7 +102,7 @@ and template is     include "includeFile"     substitute "first=Irma,family=Kraimer"     include "includeFile" -then the following is written to stdout. +then the following is written to the output.
    first name is Marty
     family name is Kraimer
     first name is Irma
@@ -150,10 +153,13 @@ dbTemplate Format
     pattern format or regular format
 }
-For thedbTemplate format, the command line template argument is optional. +For the template format, the command line template argument is optional. If it specified it is used, otherwise the file template is used. This format is an extension of the format accepted by dbLoadTemplate. It allows templates to be  expanded on the host rather via dbLoadTemplate. +The file name may appear inside double quotation marks; these are only required +if the name contains any environment variable macros of the form ${MOTOR} which +will be expanded before the file is opened.

Regular substitution example

Let the command be: @@ -164,7 +170,7 @@ Let the command be: substitute is
    {first=Marty,family=Kraimer}
     {first=Irma,family=Kraimer}
-The following is written to stdout. +The following is written to the output.
    first name is Marty
     family name is Kraimer
     first name is Irma
@@ -179,7 +185,7 @@ Let the command be:
     {Marty,Kraimer}
     {Irma,Kraimer}
template is the same as in the previous example. -

The following is written to stdout. +

The following is written to the output.

    first name is Marty
     family name is Kraimer
     first name is Irma
@@ -207,7 +213,7 @@ file template {
 }
template is the same as in the previous example.. -

The following is written to stdout +

The following is written to the output

first name is Marty
 family name is Kraimer
@@ -249,7 +255,7 @@ form:
 
        substitute "<substitutions>"
    White space is allowed before and after the command and after the quoted -string. If imbedded quotes are needed the \ character can be used as an +string. If embedded quotes are needed the \ character can be used as an escape character. For example:
        substitute "a=\"val\""
@@ -273,7 +279,7 @@ character of the comment line. is either white space or a comma. White space is any of the following: space, formfeed, newline, carriage return, tab, vertical tab.

Each item within braces can be an alphanumeric token or a quoted string. -The characters \" can be used for imbedded quotes. The rules for non quoted +The characters \" can be used for embedded quotes. The rules for non quoted strings are actually more relaxed but any item that is not an alphanumeric string should be given as a quoted string.

Thus From 3b47c2f4ece8c2e0c58bacce7ad5da6e249f7bd0 Mon Sep 17 00:00:00 2001 From: cvs2svn Date: Thu, 14 Aug 2003 13:52:36 +0000 Subject: [PATCH 13/32] This commit was manufactured by cvs2svn to create tag 'MSI-R1-3'. From 7ad050fba67b0925bb08e48be82881da673e31ec Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Tue, 11 May 2004 14:44:21 +0000 Subject: [PATCH 14/32] remove warnings from GNU compiler --- msi.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/msi.c b/msi.c index 82ae20aaf..b223518d5 100644 --- a/msi.c +++ b/msi.c @@ -104,7 +104,7 @@ int main(int argc,char **argv) fprintf(stderr,"no template file\n"); usageExit(); } - while(pval = substituteGetReplacements(substitutePvt)){ + while((pval = substituteGetReplacements(substitutePvt))){ addMacroReplacements(macPvt,pval); makeSubstitutions(inputPvt,macPvt,filename); } @@ -151,10 +151,9 @@ static void makeSubstitutions(void *inputPvt,void *macPvt,char *templateName) char *input; static char buffer[MAX_BUFFER_SIZE]; int n; - char *subStringLocation; inputBegin(inputPvt,templateName); - while(input = inputNextLine(inputPvt)) { + while((input = inputNextLine(inputPvt))) { int expand=TRUE; char *p; char *command = 0; @@ -265,7 +264,7 @@ static void inputDestruct(void *pvt) pathNode *ppathNode; inputCloseAllFiles(pinputData); - while(ppathNode = (pathNode *)ellFirst(&pinputData->pathList)) { + while((ppathNode = (pathNode *)ellFirst(&pinputData->pathList))) { ellDelete(&pinputData->pathList,&ppathNode->node); free((void *)ppathNode->directory); free((void *)ppathNode); @@ -314,7 +313,6 @@ static void inputAddPath(void *pvt, char *path) static void inputBegin(void *pvt,char *fileName) { inputData *pinputData = (inputData *)pvt; - inputFile *pinputFile; inputCloseAllFiles(pinputData); inputOpenFile(pinputData,fileName); @@ -326,7 +324,7 @@ static char *inputNextLine(void *pvt) inputFile *pinputFile; char *pline; - while(pinputFile = (inputFile *)ellFirst(&pinputData->inputFileList)) { + while((pinputFile = (inputFile *)ellFirst(&pinputData->inputFileList))) { pline = fgets(pinputData->inputBuffer,MAX_BUFFER_SIZE,pinputFile->fp); if(pline) { ++pinputFile->lineNum; @@ -373,7 +371,7 @@ static void inputOpenFile(inputData *pinputData,char *filename) ELLLIST *ppathList = &pinputData->pathList; pathNode *ppathNode = 0; inputFile *pinputFile; - char *fullname; + char *fullname = 0; FILE *fp = 0; if(!filename) { @@ -432,7 +430,7 @@ static void inputCloseAllFiles(inputData *pinputData) { inputFile *pinputFile; - while(pinputFile=(inputFile *)ellFirst(&pinputData->inputFileList)){ + while((pinputFile=(inputFile *)ellFirst(&pinputData->inputFileList))){ inputCloseFile(pinputData); } } @@ -490,7 +488,7 @@ void freeSubFile(subInfo *psubInfo) void freePattern(subInfo *psubInfo) { patternNode *ppatternNode; - while(ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList)) { + while((ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList))) { ellDelete(&psubInfo->patternList,&ppatternNode->node); free(ppatternNode->var); free(ppatternNode); @@ -501,10 +499,8 @@ void freePattern(subInfo *psubInfo) static void substituteDestruct(void *pvt) { subInfo *psubInfo = (subInfo *)pvt; - subFile *psubFile = psubInfo->psubFile; freePattern(psubInfo); - freeSubFile(psubInfo); free((void *)psubInfo); return; } @@ -514,7 +510,6 @@ static void substituteOpen(void **ppvt,char *substitutionName) subInfo *psubInfo; subFile *psubFile; FILE *fp; - patternNode *ppatternNode; psubInfo = calloc(1,sizeof(subInfo)); *ppvt = (void *)psubInfo; @@ -539,7 +534,6 @@ static int substituteGetNextSet(void *pvt,char **filename) { subInfo *psubInfo = (subInfo *)pvt; subFile *psubFile = psubInfo->psubFile; - FILE *fp; patternNode *ppatternNode; *filename = 0; From d813690363acf5234fbfb74b9739da7191ec4020 Mon Sep 17 00:00:00 2001 From: "W. Eric Norum" Date: Thu, 3 Jun 2004 21:09:20 +0000 Subject: [PATCH 15/32] Limit scope of macro definitions to a single template file. --- msi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/msi.c b/msi.c index b223518d5..de578e309 100644 --- a/msi.c +++ b/msi.c @@ -104,10 +104,12 @@ int main(int argc,char **argv) fprintf(stderr,"no template file\n"); usageExit(); } + macPushScope(macPvt); while((pval = substituteGetReplacements(substitutePvt))){ addMacroReplacements(macPvt,pval); makeSubstitutions(inputPvt,macPvt,filename); } + macPopScope(macPvt); } substituteDestruct(substitutePvt); } From 6a9163988d4b1ceb0c1229474cd3f699002e01ab Mon Sep 17 00:00:00 2001 From: "W. Eric Norum" Date: Thu, 3 Jun 2004 21:34:55 +0000 Subject: [PATCH 16/32] 1) Always print expanded line regardless of the state of the -V flag and the presence or absence of undefined macros. 2) Exit with status 2 if warnings are enabled (-V) and one or more macros is undefined. --- msi.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/msi.c b/msi.c index de578e309..6cee34fbe 100644 --- a/msi.c +++ b/msi.c @@ -45,6 +45,10 @@ static void substituteDestruct(void *substitutePvt); static void substituteOpen(void **substitutePvt,char *substitutionName); static int substituteGetNextSet(void *substitutePvt,char **filename); static char *substituteGetReplacements(void *substitutePvt); + +/*Exit status*/ +static int exitStatus = 0; + int main(int argc,char **argv) { @@ -116,7 +120,7 @@ int main(int argc,char **argv) inputDestruct(inputPvt); free((void *)templateName); free((void *)substitutionName); - return(0); + return(exitStatus); } void usageExit(void) @@ -219,10 +223,10 @@ static void makeSubstitutions(void *inputPvt,void *macPvt,char *templateName) endif: if(expand) { n = macExpandString(macPvt,input,buffer,MAX_BUFFER_SIZE-1); + fputs(buffer,stdout); if(n<0) { inputErrPrint(inputPvt); - } else { - printf("%s",buffer); + exitStatus = 2; } } } From 8e417d3032dc508f65be97fc720e464fceea3a28 Mon Sep 17 00:00:00 2001 From: "W. Eric Norum" Date: Fri, 4 Jun 2004 13:59:40 +0000 Subject: [PATCH 17/32] Add exit status description. --- msi.html | 315 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 164 insertions(+), 151 deletions(-) diff --git a/msi.html b/msi.html index 328e8f0f0..82c168791 100644 --- a/msi.html +++ b/msi.html @@ -1,103 +1,108 @@ - + - - + + - -

-msi: Macro Substitution and Include Tool

-Marty Kraimer -
Argonne National Laboratory - Advanced Photon Source -
Original:  April 26, 1999 -

-Introduction

-msi is a general purpose macro substitution/include tool. It accepts as -input an ascii template file. It looks for lines containing two reserved -command names: include and substitute. It also looks for and performs substitutions + +

msi: Macro Substitution and Include Tool

+Marty Kraimer
+Argonne National Laboratory - Advanced Photon Source
+Original:  April 26, 1999 + +

Introduction

+msi is a general purpose macro substitution/include tool. It accepts as input +an ascii template file. It looks for lines containing two reserved command +names: include and substitute. It also looks for and performs substitutions on macros of the form $(var) and ${var}. It uses the macLib, an epics base library created by William Lupton, to perform the substitutions. +

msi also allows substitutions to be specified via a separate substitution -file. This substitution file allows the same format as the substitution -files accepted by dbLoadTemplate or subtool. -
  -

-Command Syntax:

+file. This substitution file allows the same format as the substitution files +accepted by dbLoadTemplate or subtool.

+

Command Syntax:

msi -V -ofile -Idir -Msub -Ssubfile template
-NOTE: All parameters are optional and a space is optional between  --o, -I, -M, and -S  and the  associated value. Output is written -to stdout unless the -o option is given. -

Where: -

-V -

    If this parameter is specified then an undefined macro is considered -an error. An error message is generated and the line containing the macro -is not written to the output.
--o file -
    Output will be written to the specifed file rather than to the standard output.
+NOTE: All parameters are optional and a space is optional between  -o, +-I, -M, and -S  and the  associated value. Output is written to +stdout unless the -o option is given. --I dir -
    This parameter, which may be repeated, specifies a search path for -include commands. For example:
- -
-    msi -I "/home/phoebus/MRK/examples:." -I".." template
- -
-specifies the search path:
- -
-    /home/phoebus/MRK/examples:.:..
- -
-M substitutions -
    This parameter, which may be repeated, specifies marco substitutions. -For example:
- -
-    msi -M "a=aval,b=bval" -M"c=cval" template
- -
    specifies that in the template file each occurrence of:
+

Where:

+

-V

    -
    -$(a) or ${a} is replaced by aval
    + If this parameter is specified then an undefined macro is considered an + error. An error message is generated and when msi terminates it will do so + with an exit status of 2. -
    -$(b) or ${b} is replaced by bval
    +

    +
+-o file +
    + Output will be written to the specifed file rather than to the standard + output. -
    -$(c) or ${c} is replaced by cval
    +

    +
+-I dir +
    + This parameter, which may be repeated, specifies a search path for include + commands. For example:
+
+
    msi -I "/home/phoebus/MRK/examples:." -I".." + template
+
+
specifies the search path:
+
    /home/phoebus/MRK/examples:.:..
+
+-M substitutions +
    + This parameter, which may be repeated, specifies marco substitutions. For + example:
+
+
    msi -M "a=aval,b=bval" -M"c=cval" + template
+
+
    + specifies that in the template file each occurrence of:
+
    +
    +
    $(a) or ${a} is replaced by aval
    +
    +
    $(b) or ${b} is replaced by bval
    +
    $(c) or ${c} is replaced by cval
-S subfile -
    The substitution file. See below for format.
+
    + The substitution file. See below for format.
template -
    The input file. If no file is specified then input is taken from stdin, -i.e. msi can be used as a filter. See below for a description of commands -that can be embedded in the template file.
+
    + The input file. If no file is specified then input is taken from stdin, + i.e. msi can be used as a filter. See below for a description of commands + that can be embedded in the template file.
NOTE: It is not possible to display usage by just typing msi since executing the command with no arguments i s a valid command. To show usage specify an illegal switch, e.g.
    -
    msi -help
+
msi -help
-

-Template File Format

+

Template File Format

This file contains the text to be read and written to the output after macro -substitution is performed. If no file is given then input is read from -stdin. In addition the file can have lines containing include and substitute +substitution is performed. If no file is given then input is read from stdin. +In addition the file can have lines containing include and substitute commands. The format of these commands are:
    include "file"
-
    substitute "var=value,var=value,..."
For example let the command be:
    msi template
and file includeFile contain:
    first name is ${first}
     family name is ${family}
-and template is -
  +and template is
    substitute "first=Marty,family=Kraimer"
     include "includeFile"
     substitute "first=Irma,family=Kraimer"
@@ -108,27 +113,26 @@ then the following is written to the output.
     first name is Irma
     family name is Kraimer
-

-Substitution File Format

+

Substitution File Format

The optional substitution file has three formats: regular, pattern, and -dbTemplate format. Lets discuss  each separately -
  -

-regular format

+dbTemplate format. Lets discuss  each separately
+  + +

regular format

-
{var1=value1,var2=value2,...}
+  
{var1=value1,var2=value2,...}
 {var1=value1,var2=value2,...}
 ...
-After reading each set of replacements within braces,   the template -file is read and macro substitution performed. -
  -

-pattern  format:

+After reading each set of replacements within braces,   the +template file is read and macro substitution performed.
+  + +

pattern  format:

-
pattern {var1,var2,...}
+  
pattern {var1,var2,...}
 {value1,value2,...}
 {value1,value2,...}
 pattern {var1,var2,...}
@@ -136,32 +140,31 @@ pattern {var1,var2,...}
 {value1,value2,...}
This is the same as the regular format: +
-
{var1=value1,var2=value2}
+  
{var1=value1,var2=value2}
 ...
-

-dbTemplate Format

+

dbTemplate Format

-
file template {
+  
file template {
     pattern format or regular format
 }
- -
file template {
+  
file template {
     pattern format or regular format
 }
-For the template format, the command line template argument is optional. -If it specified it is used, otherwise the file template is used. This format -is an extension of the format accepted by dbLoadTemplate. It allows templates -to be  expanded on the host rather via dbLoadTemplate. -The file name may appear inside double quotation marks; these are only required -if the name contains any environment variable macros of the form ${MOTOR} which -will be expanded before the file is opened. -

-Regular substitution example

+For the template format, the command line template argument is optional. If +it specified it is used, otherwise the file template is used. This format is +an extension of the format accepted by dbLoadTemplate. It allows templates to +be  expanded on the host rather via dbLoadTemplate. The file name may +appear inside double quotation marks; these are only required if the name +contains any environment variable macros of the form ${MOTOR} which will be +expanded before the file is opened. + +

Regular substitution example

Let the command be:
    msi -S substitute template
template is @@ -176,8 +179,7 @@ The following is written to the output.     first name is Irma     family name is Kraimer
-

-Pattern substitution example

+

Pattern substitution example

Let the command be:
    msi -S pattern template
pattern is @@ -185,21 +187,23 @@ Let the command be:     {Marty,Kraimer}     {Irma,Kraimer} template is the same as in the previous example. -

The following is written to the output. + +

The following is written to the output.

    first name is Marty
     family name is Kraimer
     first name is Irma
     family name is Kraimer
-

-dbTemplate example

+

dbTemplate example

Let the command be +
-
msi -S xxx.substitutions
+
msi -S xxx.substitutions
xxx.substitutions is +
-
file template {
+  
file template {
     pattern {first,last}
     {Marty,Kraimer}
     {Irma,Kraimer}
@@ -213,9 +217,11 @@ file template {
 }
template is the same as in the previous example.. -

The following is written to the output + +

The following is written to the output

+
-
first name is Marty
+  
first name is Marty
 family name is Kraimer
 first name is Irma
 family name is Kraimer
@@ -229,60 +235,61 @@ first name is Irma
 family name is Kraimer
-

-Some Details

+

Some Details

Building msi -
    msi is built as a normal extensions product. It should be built with -base version 3.13.0beta11 or later.
- -
-Line length limits
- -
    All buffers containing input or output lines are set for a maximum -line length of 1024. Longer input or output lines will cause msi to fail.
+
    + msi is built as a normal extensions product. It should be built with base + version 3.13.0beta11 or later.
+
+
Line length limits
+
+
    + All buffers containing input or output lines are set for a maximum line + length of 1024. Longer input or output lines will cause msi to fail.
macLib -
    Currently the only macLib documentation is in macLibNOTES and macLibREADME -which are in base/src/libCom.
+
    + Currently the only macLib documentation is in macLibNOTES and macLibREADME + which are in base/src/libCom.
template file syntax -
    except for lines containing include or substitute commands each line -is just passed to macLib. Lines containing these commands MUST be of the +
      + except for lines containing include or substitute commands each line is + just passed to macLib. Lines containing these commands MUST be of the form:
    - -
            include "<file name>"
    - +
            include "<file name>"
            or
    - -
            substitute "<substitutions>"
    - -
      White space is allowed before and after the command and after the quoted -string. If embedded quotes are needed the \ character can be used as an -escape character. For example:
    - +
            substitute "<substitutions>"
    +
      + White space is allowed before and after the command and after the quoted + string. If embedded quotes are needed the \ character can be used as an + escape character. For example:
            substitute "a=\"val\""
    - -
      specifies the substitution
    - +
      + specifies the substitution
            a=val
    - -
      If a line does have the above syntax it is just passed to macLib for -processing without any notification. Thus the input line:
    - +
      + If a line does have the above syntax it is just passed to macLib for + processing without any notification. Thus the input line:
            include "myfile" #include file
    +
      + would just be passed to macLib, i.e. it would NOT be considered an include + command.
    +substitution  file syntax +
      + A comment line may appear anywhere and is just ignored. A comment line is + any line beginning with the character #, which MUST be the very first + character of the comment line. -
        would just be passed to macLib, i.e. it would NOT be considered an -include command.
      -substitution  file syntax -
        A comment line may appear anywhere and is just ignored. A comment line -is any line beginning with the character #, which MUST be the very first -character of the comment line. -

        For items within braces separators may be given between items. A separator -is either white space or a comma. White space is any of the following: -space, formfeed, newline, carriage return, tab, vertical tab. -

        Each item within braces can be an alphanumeric token or a quoted string. -The characters \" can be used for embedded quotes. The rules for non quoted -strings are actually more relaxed but any item that is not an alphanumeric -string should be given as a quoted string. -

        Thus +

        For items within braces separators may be given between items. A + separator is either white space or a comma. White space is any of the + following: space, formfeed, newline, carriage return, tab, vertical tab.

        + +

        Each item within braces can be an alphanumeric token or a quoted string. + The characters \" can be used for embedded quotes. The rules for non quoted + strings are actually more relaxed but any item that is not an alphanumeric + string should be given as a quoted string.

        + +

        Thus

        +
          {a=aa b=bb c="\"cc\""}
      and
          {a=aa,b=bb,c="\"cc\""}
      @@ -292,7 +299,13 @@ and         b="bb",         c="\"cc\""     } -are all equivalent.
    +are all equivalent. +

    + +

    Exit Status

    +

    0 - Success.

    +

    1 - Can't open/create file, or other I/O error.

    +

    2 - -V option specified and one or more undefined macros were encountered.

    From d5d828aa7ba8c38e3b3cfb93a46dd88c877cda52 Mon Sep 17 00:00:00 2001 From: "W. Eric Norum" Date: Mon, 14 Jun 2004 18:02:00 +0000 Subject: [PATCH 18/32] Let this compile and run (with reduced capability) on R3.13. --- msi.c | 4 ++++ msi.html | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/msi.c b/msi.c index 6cee34fbe..278746682 100644 --- a/msi.c +++ b/msi.c @@ -26,6 +26,10 @@ #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); diff --git a/msi.html b/msi.html index 82c168791..86ec39018 100644 --- a/msi.html +++ b/msi.html @@ -161,8 +161,9 @@ it specified it is used, otherwise the file template is used. This format is an extension of the format accepted by dbLoadTemplate. It allows templates to be  expanded on the host rather via dbLoadTemplate. The file name may appear inside double quotation marks; these are only required if the name -contains any environment variable macros of the form ${MOTOR} which will be -expanded before the file is opened. +contains any environment variable macros of the form ${ENV_VAR} which will be +expanded before the file is opened. Environment variable macro expansion +is available when msi is linked with EPICS base R3.14.3 or newer.

    Regular substitution example

    Let the command be: From b14965dee5f607d5d3a0af422b6b7dc1015ffd90 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 17 Jun 2004 16:19:47 +0000 Subject: [PATCH 19/32] Build with R3.14 rules if available (not tested...) --- Makefile | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c4e78f1c4..635fdf5ee 100644 --- a/Makefile +++ b/Makefile @@ -10,5 +10,20 @@ # $Id$ # TOP = ../.. -include $(TOP)/config/CONFIG_EXTENSIONS -include $(TOP)/config/RULES_ARCHS + +# If a /configure directory exists, build with 3.14 rules, else +# use /config and the 3.13 rules. +ifeq (0, $(words $(notdir $(wildcard $(TOP)/configure)))) + include $(TOP)/config/CONFIG_EXTENSIONS + include $(TOP)/config/RULES_ARCHS +else + include $(TOP)/configure/CONFIG + + PROD = msi + HTMLS = msi.html + + msi_SRCS = msi.c + PROD_LIBS += Com + + include $(TOP)/configure/RULES +endif From 42b80245b34bdb828ca29ebb4c153ac9fec96e39 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 17 Jun 2004 18:22:06 +0000 Subject: [PATCH 20/32] Significantly revised, added stuff about default values. --- msi.html | 579 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 350 insertions(+), 229 deletions(-) diff --git a/msi.html b/msi.html index 86ec39018..639553968 100644 --- a/msi.html +++ b/msi.html @@ -6,215 +6,400 @@ +

    msi: Macro Substitution and Include Tool

    -Marty Kraimer
    -Argonne National Laboratory - Advanced Photon Source
    -Original:  April 26, 1999 + +
    +

    Version 1.4, June 2004
    +Marty Kraimer (Advanced Photon Source, Argonne National Laboratory)

    +

    Introduction

    -msi is a general purpose macro substitution/include tool. It accepts as input -an ascii template file. It looks for lines containing two reserved command -names: include and substitute. It also looks for and performs substitutions -on macros of the form $(var) and ${var}. It uses the macLib, an epics base -library created by William Lupton, to perform the substitutions. + +

    msi is a general purpose macro substitution/include tool. It accepts as +input an ascii template file. It looks for lines containing two reserved +command names: include and substitute. It also looks for and performs +substitutions on macros of the form $(var) and ${var}. It uses macLib, an EPICS +Base library created by William Lupton, to perform the substitutions.

    msi also allows substitutions to be specified via a separate substitution file. This substitution file allows the same format as the substitution files -accepted by dbLoadTemplate or subtool.

    +accepted by dbLoadTemplate or subtool.

    Command Syntax:

    +
    msi -V -ofile -Idir -Msub -Ssubfile template
    -NOTE: All parameters are optional and a space is optional between  -o, --I, -M, and -S  and the  associated value. Output is written to -stdout unless the -o option is given. -

    Where:

    +

    All parameters are optional. The -o, -I, -M, and -S switches may be +separated from their associated value string by spaces if desired. Output will +be written to stdout unless the -o option is given.

    -

    -V

    -
      - If this parameter is specified then an undefined macro is considered an - error. An error message is generated and when msi terminates it will do so - with an exit status of 2. +

      Switches have the following meanings:

      -

      -
    --o file -
      - Output will be written to the specifed file rather than to the standard - output. - -

      -
    --I dir -
      - This parameter, which may be repeated, specifies a search path for include - commands. For example:
    -
        msi -I "/home/phoebus/MRK/examples:." -I".." - template
    +
    -V
    +
    If this parameter is specified then any undefined macro discovered in + the template file which does not have an associated default value is + considered an error. An error message is generated and when msi terminates + it will do so with an exit status of 2.
    + +
    -o file
    +
    Output will be written to the specifed file rather than to the standard + output.
    + +
    -I dir
    +
    This parameter, which may be repeated, specifies a search path for + include commands. For example: + +
    +
    msi -I "/home/phoebus/MRK/examples:." -I".." template
    +
    + + specifies that all named files should be searched for in the following + locations in the order given: + +
      +
    1. /home/phoebus/MRK/examples
    2. +
    3. . (the current directory)
    4. +
    5. .. (the parent of the current directory)
    6. +
    +
    + +
    -M substitutions
    +
    This parameter specifies macro values for the template instance. + Multiple macro values can be specified in one substitution parameter, or in + multiple -M parameters. For example: + +
    +
    msi -M "a=aval,b=bval" -Mc=cval template
    +
    + + specifies that in the template file each occurrence of: + +
    +
    $(a) or ${a} is replaced by aval
    +
    $(b) or ${b} is replaced by bval
    +
    $(c) or ${c} is replaced by cval
    +
    +
    + +
    -S subfile
    +
    The substitution file. See below for format.
    + +
    template
    +
    The input file. If no file is specified then input is taken from + stdin, i.e. msi can be used as a filter. See below for a description of + commands that can be embedded in the template file.
    -
    specifies the search path:
    -
        /home/phoebus/MRK/examples:.:..
    -
    --M substitutions -
      - This parameter, which may be repeated, specifies marco substitutions. For - example:
    -
    -
        msi -M "a=aval,b=bval" -M"c=cval" - template
    -
    -
      - specifies that in the template file each occurrence of:
    -
      -
      -
      $(a) or ${a} is replaced by aval
      -
      -
      $(b) or ${b} is replaced by bval
      -
      $(c) or ${c} is replaced by cval
      -
    --S subfile -
      - The substitution file. See below for format.
    -template -
      - The input file. If no file is specified then input is taken from stdin, - i.e. msi can be used as a filter. See below for a description of commands - that can be embedded in the template file.
    -NOTE: It is not possible to display usage by just typing msi since -executing the command with no arguments i s a valid command. To show usage -specify an illegal switch, e.g. -
      -
    + +

    It is not possible to display usage by just typing msi since +executing the command with no arguments is a valid command. To show usage +specify an illegal switch, e.g.

    + +
    msi -help
    +
    + +

    Exit Status

    + +
    +
    0
    Success. +
    1
    Can't open/create file, or other I/O error. +
    2
    Undefined macros encountered with the -V option specified. +

    Template File Format

    -This file contains the text to be read and written to the output after macro + +

    This file contains the text to be read and written to the output after macro substitution is performed. If no file is given then input is read from stdin. -In addition the file can have lines containing include and substitute -commands. The format of these commands are: -

        include "file"
    -
        substitute "var=value,var=value,..."
    -For example let the command be: -
        msi template
    -and file includeFile contain: -
        first name is ${first}
    -    family name is ${family}
    -and template is
    -  -
        substitute "first=Marty,family=Kraimer"
    -    include "includeFile"
    -    substitute "first=Irma,family=Kraimer"
    -    include "includeFile"
    -then the following is written to the output. -
        first name is Marty
    -    family name is Kraimer
    -    first name is Irma
    -    family name is Kraimer
    +Variable instances to be substituted by macro values are expressed in the +template using the syntax $(name) or +${name}. If msi has been built with EPICS Base version +3.14.7 or later, the template can also provide default values to be used when a +macro has not been given a value, using the syntax +$(name=default) or +${name=default}.

    + +

    For example, using the command

    + +
    +
    msi -M name=Marty template
    +
    + +

    where the file template contains

    + +
    +
    My name is $(name)
    +My age is $(age=none of your business)
    +
    + +

    results in this output:

    + +
    +
    My name is Marty
    +My age is none of your business
    +
    + +

    Macro variables and their default values can be expressed in terms of other +macros if necessary, to almost any level of complexity. Recursive definitions +will generate warning messages on stderr and result in undefined output.

    + +

    The template file is read and processed one line at a time, where the +maximum length of a line before and/or after macro expansion is 1023 characters +— longer input or output lines will cause msi to fail. Within the context +of a single line, macro expansion does not occur when the variable instance +appears inside a single-quoted string, or where the dollar sign $ is +preceded by a back-slash character \, but as with the standard Unix +shells, variables inside double quoted strings are expanded properly.

    + +

    However neither back-slash characters nor quotes or either variety are +removed when generating the output file, so depending on what is being output +the single quote behaviour may not be useful and may even be a hinderance. It +cannot be disabled in the current version of msi.

    + +

    Template file commands

    + +

    In addition to the regular text and variable instances described above, the +template file may also contain commands which allow the insertion of other +template files and the ability to set macro values inside the template file +itself. These commands are:

    + +
    +
    include "file"
    +substitute "var=value,var=value,..."
    +
    + +

    Lines containing commands must be in one of these forms:

    + +
      +
    • include "filename"
    • +
    • substitute "name1=value1, name2=value2, ..."
    • +
    + +

    White space is allowed before and after the command verb, and after the +quoted string. If embedded quotes are needed, the backslash character +\ can be used as an escape character. For example

    + +
    +
    substitute "a=\"val\""
    +
    + +

    specifies that (unless a is subsequently redefined) wherever a +$(a) macro appears in the template below this point, the text +"val" (including the double quote characters) will appear in the +output instead.

    + +

    If a line does match either syntax above it is just passed to macLib for +processing without any notification. Thus the input line:

    + +
    +
    include "myfile" #include file
    +
    + +

    would just be passed to macLib, i.e. it would not be considered an +include command.

    + +

    As an example of these commands, let the Unix command be:

    + +
    +
    msi template
    +
    + +

    and file includeFile contain:

    + +
    +
    first name is ${first}
    +family name is ${family}
    +
    + +

    and template is

    + +
    +
    substitute "first=Marty,family=Kraimer"
    +include "includeFile"
    +substitute "first=Irma,family=Kraimer"
    +include "includeFile"
    +
    + +

    then the following is written to the output.

    + +
    +
    first name is Marty
    +family name is Kraimer
    +first name is Irma
    +family name is Kraimer
    +
    + +

    Note that on an IOC when using the dbLoadTemplate command, the +template file does not support the substitute command, although +include is supported.

    Substitution File Format

    -The optional substitution file has three formats: regular, pattern, and -dbTemplate format. Lets discuss  each separately
    -  -

    regular format

    +

    The optional substitution file has three formats: regular, pattern, and +dbTemplate format. We will discuss each separately.

    + +

    Regular format

    -
    {var1=value1,var2=value2,...}
    -{var1=value1,var2=value2,...}
    -...
    +
    {var1=set1_val1, var2=set1_val2, ...}
    +{var2=set2_val2, var1=set2_val1, ...}
    +{var1=set3_val1, var2=set3_val2, ...}
    +{var2=set4_val2, var1=set4_val1, ...}
    -After reading each set of replacements within braces,   the -template file is read and macro substitution performed.
    -  -

    pattern  format:

    +

    The template file is output with macro substitutions performed once for each +set of braces containing macro replacement values.

    + +

    Pattern format

    -
    pattern {var1,var2,...}
    -{value1,value2,...}
    -{value1,value2,...}
    -pattern {var1,var2,...}
    -{value1,value2,...}
    -{value1,value2,...}
    +
    pattern {var1, var2, ...}
    +{set1_val1, set1_val2, ...}
    +{set2_val1, set2_val2, ...}
    +pattern {var2, var1, ...}
    +{set3_val2, set3_val1, ...}
    +{set4_val2, set4_val2, ...}
    -This is the same as the regular format: -
    -
    {var1=value1,var2=value2}
    -...
    -
    +

    This produces the same result as the regular format example above.

    dbTemplate Format

    +

    This format is an extension of the format accepted by the EPICS IOC command +dbLoadTemplate, and allows templates to be expanded on the host rather +by using dbLoadTemplate at IOC boot time.

    +
    -
    file template {
    -    pattern format or regular format
    -}
    -
    file template {
    -    pattern format or regular format
    +
    file template {
    +    pattern format or regular format
    +}
    +file "${WHERE}/template2" {
    +    pattern format or regular format
     }
    -For the template format, the command line template argument is optional. If -it specified it is used, otherwise the file template is used. This format is -an extension of the format accepted by dbLoadTemplate. It allows templates to -be  expanded on the host rather via dbLoadTemplate. The file name may -appear inside double quotation marks; these are only required if the name -contains any environment variable macros of the form ${ENV_VAR} which will be -expanded before the file is opened. Environment variable macro expansion -is available when msi is linked with EPICS base R3.14.3 or newer. + +

    For the dbTemplate format, the template filename does not have to be given +on the command line, and is usually specified in the substitutions file +instead. If a template filename is given on the command line it will override +the filenames listed in the substitutions files.

    + +

    Syntax for all formats

    + +

    A comment line may appear anywhere in a substitution file, and will be +ignored. A comment line is any line beginning with the character #, +which must be the very first character on the line.

    + +

    For definitions within braces given in any of the file formats, a separator +must be given between items. A separator is either a comma, or one or more of +the standard white space characters (space, formfeed, newline, carriage return, +tab or vertical tab).

    + +

    Each item within braces can be an alphanumeric token, or a double-quoted +string. A back-slash character \ can be used to escape a quote +character needed inside a quoted string. These three sets of substitutions are +all equivalent:

    + +
    +
    {a=aa b=bb c="\"cc\""}
    +{b="bb",a=aa,c="\"cc\""}
    +{
    +    c="\"cc\""
    +    b=bb
    +    a="aa"
    +}
    +
    + +

    Within a substitutions file, the file name may appear inside double +quotation marks; these are only required if the name contains environment +variable macros of the form ${ENV_VAR} or $(ENV_VAR), which will be expanded +before the file is opened. Environment variable macro expansion is only +available when msi has been built using EPICS base R3.14.3 or newer.

    Regular substitution example

    -Let the command be: -
        msi -S substitute template
    -template is -
        first name is ${first}
    -    family name is ${family}
    -substitute is -
        {first=Marty,family=Kraimer}
    -    {first=Irma,family=Kraimer}
    -The following is written to the output. -
        first name is Marty
    -    family name is Kraimer
    -    first name is Irma
    -    family name is Kraimer
    + +

    Let the command be:

    + +
    +
    msi -S substitute template
    +
    + +

    The file template contains

    + +
    +
    first name is ${first}
    +family name is ${family}
    +
    + +

    and the file substitute is

    + +
    +
    {first=Marty,family=Kraimer}
    +{first=Irma,family=Kraimer}
    +
    + +

    The following is the output produced:

    + +
    +
    first name is Marty
    +family name is Kraimer
    +first name is Irma
    +family name is Kraimer
    +

    Pattern substitution example

    -Let the command be: -
        msi -S pattern template
    -pattern is -
        pattern {first,last}
    -    {Marty,Kraimer}
    -    {Irma,Kraimer}
    -template is the same as in the previous example. -

    The following is written to the output.

    -
        first name is Marty
    -    family name is Kraimer
    -    first name is Irma
    -    family name is Kraimer
    +

    Let the command be:

    + +
    +
    msi -S pattern template
    +
    + +

    The file pattern contains

    + +
    +
    pattern {first,last}
    +{Marty,Kraimer}
    +{Irma,Kraimer}
    +
    + +

    and template is the same as the previous example:

    + +
    +
    first name is ${first}
    +family name is ${family}
    +
    + +

    This is the output:

    + +
    +
    first name is Marty
    +family name is Kraimer
    +first name is Irma
    +family name is Kraimer
    +

    dbTemplate example

    Let the command be
    -
    msi -S xxx.substitutions
    +
    msi -S xxx.substitutions
    + xxx.substitutions is
    -
    file template {
    -    pattern {first,last}
    -    {Marty,Kraimer}
    -    {Irma,Kraimer}
    -    pattern {last,first}
    -    {Smith,Bill}
    -    {Smith,Mary}
    +
    file template {
    +pattern {first,last}
    +{Marty,Kraimer}
    +{Irma,Kraimer}
    +pattern {last,first}
    +{Smith,Bill}
    +{Smith,Mary}
     }
     file template {
    -    {first=Marty,last=Kraimer}
    -    {first=Irma,last=Kraimer}
    +{first=Marty,last=Kraimer}
    +{first=Irma,last=Kraimer}
     }
    template is the same as in the previous example.. @@ -222,7 +407,7 @@ file template {

    The following is written to the output

    -
    first name is Marty
    +
    first name is Marty
     family name is Kraimer
     first name is Irma
     family name is Kraimer
    @@ -236,77 +421,13 @@ first name is Irma
     family name is Kraimer
    -

    Some Details

    -Building msi -
      - msi is built as a normal extensions product. It should be built with base - version 3.13.0beta11 or later.
    -
    -
    Line length limits
    -
    -
      - All buffers containing input or output lines are set for a maximum line - length of 1024. Longer input or output lines will cause msi to fail.
    -macLib -
      - Currently the only macLib documentation is in macLibNOTES and macLibREADME - which are in base/src/libCom.
    -template file syntax -
      - except for lines containing include or substitute commands each line is - just passed to macLib. Lines containing these commands MUST be of the -form:
    -
            include "<file name>"
    -
            or
    -
            substitute "<substitutions>"
    -
      - White space is allowed before and after the command and after the quoted - string. If embedded quotes are needed the \ character can be used as an - escape character. For example:
    -
            substitute "a=\"val\""
    -
      - specifies the substitution
    -
            a=val
    -
      - If a line does have the above syntax it is just passed to macLib for - processing without any notification. Thus the input line:
    -
            include "myfile" #include file
    -
      - would just be passed to macLib, i.e. it would NOT be considered an include - command.
    -substitution  file syntax -
      - A comment line may appear anywhere and is just ignored. A comment line is - any line beginning with the character #, which MUST be the very first - character of the comment line. +

      Building msi

      -

      For items within braces separators may be given between items. A - separator is either white space or a comma. White space is any of the - following: space, formfeed, newline, carriage return, tab, vertical tab.

      +

      msi is built as a normal extensions product, and can be built with any +version of EPICS Base from 3.13.0beta11 onwards. Base version 3.14.3 or later +is required if the ability to expand environment variables in filenames is +needed. Base version 3.14.7 or later is required to allow the use of default +macro values in template files.

      -

      Each item within braces can be an alphanumeric token or a quoted string. - The characters \" can be used for embedded quotes. The rules for non quoted - strings are actually more relaxed but any item that is not an alphanumeric - string should be given as a quoted string.

      - -

      Thus

      -
    -
        {a=aa b=bb c="\"cc\""}
    -and -
        {a=aa,b=bb,c="\"cc\""}
    -and -
        {
    -        a="aa"
    -        b="bb",
    -        c="\"cc\""
    -    }
    -are all equivalent. - -

    - -

    Exit Status

    -

    0 - Success.

    -

    1 - Can't open/create file, or other I/O error.

    -

    2 - -V option specified and one or more undefined macros were encountered.

    From 460ba036f3b91bf43e48ba3b6587f5995227554e Mon Sep 17 00:00:00 2001 From: "Janet B. Anderson" Date: Fri, 8 Oct 2004 15:20:49 +0000 Subject: [PATCH 21/32] Build msi only for host target. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 635fdf5ee..899de4dd4 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ ifeq (0, $(words $(notdir $(wildcard $(TOP)/configure)))) else include $(TOP)/configure/CONFIG - PROD = msi + PROD_HOST = msi HTMLS = msi.html msi_SRCS = msi.c From 9b3af852af10c7b76a152c25f5ced0dffcb12e24 Mon Sep 17 00:00:00 2001 From: "Janet B. Anderson" Date: Fri, 18 May 2007 16:16:49 +0000 Subject: [PATCH 22/32] Converted to R3.14 Makefiles. --- Makefile | 19 ++++++------------- Makefile.Host | 21 --------------------- 2 files changed, 6 insertions(+), 34 deletions(-) delete mode 100644 Makefile.Host diff --git a/Makefile b/Makefile index 899de4dd4..5ab39416a 100644 --- a/Makefile +++ b/Makefile @@ -11,19 +11,12 @@ # TOP = ../.. -# If a /configure directory exists, build with 3.14 rules, else -# use /config and the 3.13 rules. -ifeq (0, $(words $(notdir $(wildcard $(TOP)/configure)))) - include $(TOP)/config/CONFIG_EXTENSIONS - include $(TOP)/config/RULES_ARCHS -else - include $(TOP)/configure/CONFIG +include $(TOP)/configure/CONFIG - PROD_HOST = msi - HTMLS = msi.html +PROD_HOST = msi +HTMLS = msi.html - msi_SRCS = msi.c - PROD_LIBS += Com +msi_SRCS = msi.c +PROD_LIBS += Com - include $(TOP)/configure/RULES -endif +include $(TOP)/configure/RULES diff --git a/Makefile.Host b/Makefile.Host deleted file mode 100644 index 1e5493b63..000000000 --- a/Makefile.Host +++ /dev/null @@ -1,21 +0,0 @@ -#************************************************************************* -# 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. -#************************************************************************* -TOP = ../../.. -include $(TOP)/config/CONFIG_EXTENSIONS - - -PROD_LIBS += Com - -HTMLS += msi.html - -SRCS.c= ../msi.c -PROD = msi - -include $(TOP)/config/RULES.Host - From 83d06f25694d7141e260d8a305040ba4eb45bc7b Mon Sep 17 00:00:00 2001 From: "Janet B. Anderson" Date: Mon, 25 Jun 2007 19:59:12 +0000 Subject: [PATCH 23/32] Initial version. --- README.1st | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 README.1st diff --git a/README.1st b/README.1st new file mode 100644 index 000000000..60ebbddde --- /dev/null +++ b/README.1st @@ -0,0 +1,2 @@ +The extension distribution file should be unziped and untared +in the extensions/src directory. From 1d9bcafe440dd1a119d71358b123aae75d88633b Mon Sep 17 00:00:00 2001 From: cvs2svn Date: Mon, 25 Jun 2007 19:59:13 +0000 Subject: [PATCH 24/32] This commit was manufactured by cvs2svn to create tag 'MSI-R1-4'. From 0e45345891d8d1034b235016db47c5b21d4dde94 Mon Sep 17 00:00:00 2001 From: "W. Eric Norum" Date: Tue, 29 Apr 2008 23:04:29 +0000 Subject: [PATCH 25/32] Headers no longer provide TRUE/FALSE defines. --- msi.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/msi.c b/msi.c index 278746682..0f316629e 100644 --- a/msi.c +++ b/msi.c @@ -66,7 +66,7 @@ int main(int argc,char **argv) inputConstruct(&inputPvt); macCreateHandle(&macPvt,0); - macSuppressWarning(macPvt,TRUE); + macSuppressWarning(macPvt,1); while((argc>1) && (argv[1][0] == '-')) { narg = (strlen(argv[1])==2) ? 2 : 1; pval = (narg==1) ? (argv[1]+2) : argv[2]; @@ -83,7 +83,7 @@ int main(int argc,char **argv) substitutionName = calloc(strlen(pval)+1,sizeof(char)); strcpy(substitutionName,pval); } else if(strncmp(argv[1],"-V",2)==0) { - macSuppressWarning(macPvt,FALSE); + macSuppressWarning(macPvt,0); narg = 1; /* no argument for this option */ } else { usageExit(); @@ -164,7 +164,7 @@ static void makeSubstitutions(void *inputPvt,void *macPvt,char *templateName) inputBegin(inputPvt,templateName); while((input = inputNextLine(inputPvt))) { - int expand=TRUE; + int expand=1; char *p; char *command = 0; @@ -222,7 +222,7 @@ static void makeSubstitutions(void *inputPvt,void *macPvt,char *templateName) exit(1); } free(copy); - expand = FALSE; + expand = 0; } endif: if(expand) { @@ -295,7 +295,7 @@ static void inputAddPath(void *pvt, char *path) pdir = path; /*an empty name at beginning, middle, or end means current directory*/ while(pdir && *pdir) { - emptyName = ((*pdir == ':') ? TRUE : FALSE); + emptyName = ((*pdir == ':') ? 1 : 0); if(emptyName) ++pdir; ppathNode = (pathNode *)calloc(1,sizeof(pathNode)); ellAdd(ppathList,&ppathNode->node); @@ -309,7 +309,7 @@ static void inputAddPath(void *pvt, char *path) /*unless at end skip past first colon*/ if(pdir && *(pdir+1)!=0) ++pdir; } else { /*must have been trailing : */ - emptyName=TRUE; + emptyName=1; } } if(emptyName) { @@ -503,7 +503,7 @@ void freePattern(subInfo *psubInfo) free(ppatternNode->var); free(ppatternNode); } - psubInfo->isPattern = FALSE; + psubInfo->isPattern = 0; } static void substituteDestruct(void *pvt) @@ -548,9 +548,9 @@ static int substituteGetNextSet(void *pvt,char **filename) *filename = 0; while(psubFile->token==tokenSeparater) subGetNextToken(psubFile); - if(psubFile->token==tokenEOF) return(FALSE); + if(psubFile->token==tokenEOF) return(0); if(psubFile->token==tokenString && strcmp(psubFile->string,"file")==0) { - psubInfo->isFile = TRUE; + psubInfo->isFile = 1; if(subGetNextToken(psubFile)!=tokenString) { subFileErrPrint(psubFile,"Expecting filename"); exit(1); @@ -573,21 +573,21 @@ static int substituteGetNextSet(void *pvt,char **filename) } *filename = psubInfo->filename; while(psubFile->token==tokenSeparater) subGetNextToken(psubFile); - if(psubFile->token==tokenLBrace) return(TRUE); - if(psubFile->token==tokenRBrace) return(FALSE); + if(psubFile->token==tokenLBrace) return(1); + if(psubFile->token==tokenRBrace) return(0); if(psubFile->token!=tokenString || strcmp(psubFile->string,"pattern")!=0) { subFileErrPrint(psubFile,"Expecting pattern"); exit(1); } freePattern(psubInfo); - psubInfo->isPattern = TRUE; + psubInfo->isPattern = 1; while(subGetNextToken(psubFile)==tokenSeparater); if(psubFile->token!=tokenLBrace) { subFileErrPrint(psubFile,"Expecting {"); exit(1); } - while(TRUE) { + while(1) { while(subGetNextToken(psubFile)==tokenSeparater); if(psubFile->token!=tokenString) break; ppatternNode = calloc(1,sizeof(patternNode)); @@ -600,7 +600,7 @@ static int substituteGetNextSet(void *pvt,char **filename) exit(1); } subGetNextToken(psubFile); - return(TRUE); + return(1); } static char *substituteGetReplacements(void *pvt) @@ -613,7 +613,7 @@ static char *substituteGetReplacements(void *pvt) psubInfo->curLength = 0; while(psubFile->token==tokenSeparater) subGetNextToken(psubFile); if(psubFile->token==tokenRBrace && psubInfo->isFile) { - psubInfo->isFile = FALSE; + psubInfo->isFile = 0; free((void *)psubInfo->filename); psubInfo->filename = 0; freePattern(psubInfo); @@ -623,11 +623,11 @@ static char *substituteGetReplacements(void *pvt) if(psubFile->token==tokenEOF) return(0); if(psubFile->token!=tokenLBrace) return(0); if(psubInfo->isPattern) { - int gotFirstPattern = FALSE; + int gotFirstPattern = 0; while(subGetNextToken(psubFile)==tokenSeparater); ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList); - while(TRUE) { + while(1) { if(psubFile->token==tokenRBrace) { if(ppatternNode) subFileErrPrint(psubFile,"less values than patterns"); @@ -639,7 +639,7 @@ static char *substituteGetReplacements(void *pvt) exit(-1); } if(gotFirstPattern) catMacroReplacements(psubInfo,","); - gotFirstPattern = TRUE; + gotFirstPattern = 1; if(ppatternNode) { catMacroReplacements(psubInfo,ppatternNode->var); catMacroReplacements(psubInfo,"="); @@ -650,7 +650,7 @@ static char *substituteGetReplacements(void *pvt) } while(subGetNextToken(psubFile)==tokenSeparater); } - } else while(TRUE) { + } else while(1) { switch(subGetNextToken(psubFile)) { case tokenRBrace: subGetNextToken(psubFile); From a117a73987c23f40654e4dd08a7c7690e81c15c7 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 22 May 2008 18:55:08 +0000 Subject: [PATCH 26/32] Make undefined macros a warning, not an error; only report once. --- msi.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/msi.c b/msi.c index 0f316629e..5f241d053 100644 --- a/msi.c +++ b/msi.c @@ -161,6 +161,7 @@ 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))) { @@ -225,12 +226,12 @@ static void makeSubstitutions(void *inputPvt,void *macPvt,char *templateName) expand = 0; } endif: - if(expand) { + if (expand) { n = macExpandString(macPvt,input,buffer,MAX_BUFFER_SIZE-1); fputs(buffer,stdout); - if(n<0) { - inputErrPrint(inputPvt); - exitStatus = 2; + if (!unexpWarned && n<0) { + fprintf(stderr,"Warning: unexpanded macros in ouput\n"); + unexpWarned++; } } } @@ -510,6 +511,7 @@ static void substituteDestruct(void *pvt) { subInfo *psubInfo = (subInfo *)pvt; + freeSubFile(psubInfo); freePattern(psubInfo); free((void *)psubInfo); return; @@ -770,7 +772,7 @@ static void catMacroReplacements(subInfo *psubInfo,const char *value) newsize = psubInfo->curLength + len + 1; newbuf = calloc(1,newsize); if(!newbuf) { - fprintf(stderr,"calloc failed for size %d\n",newsize); + fprintf(stderr,"calloc failed for size %u\n",newsize); exit(1); } if(psubInfo->macroReplacements) { From 97ccca54743cc0a8fd1513e8702b041999b76a2b Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 10 Nov 2008 20:46:27 +0000 Subject: [PATCH 27/32] Cleanup, warnings. --- msi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/msi.c b/msi.c index 5f241d053..e6b5ec422 100644 --- a/msi.c +++ b/msi.c @@ -20,7 +20,8 @@ #include #include #include - + +#include #include #include @@ -92,7 +93,7 @@ int main(int argc,char **argv) for(i=1; i2) { - fprintf(stderr,"too many files\n"); + fprintf(stderr,"too many filename arguments\n"); usageExit(); } if(argc==2) { @@ -153,9 +154,8 @@ static void addMacroReplacements(MAC_HANDLE *macPvt,char *pval) free((void *)pairs); } -#define cmdNumberOf 2 typedef enum {cmdInclude,cmdSubstitute} cmdType; -static char *cmdName[cmdNumberOf] = {"include","substitute"}; +static const char *cmdNames[] = {"include","substitute"}; static void makeSubstitutions(void *inputPvt,void *macPvt,char *templateName) { char *input; @@ -181,13 +181,13 @@ static void makeSubstitutions(void *inputPvt,void *macPvt,char *templateName) int cmdind=-1; int i; - for(i=0; i< cmdNumberOf; i++) { - if(strstr(command,cmdName[i])) { + for(i=0; i< NELEMENTS(cmdNames); i++) { + if(strstr(command,cmdNames[i])) { cmdind = i; } } if(cmdind<0) goto endif; - p = command + strlen(cmdName[cmdind]); + p = command + strlen(cmdNames[cmdind]); /*skip whitespace after command*/ while(*p && (isspace(*p))) ++p; /*Next character must be quote*/ @@ -772,7 +772,7 @@ static void catMacroReplacements(subInfo *psubInfo,const char *value) newsize = psubInfo->curLength + len + 1; newbuf = calloc(1,newsize); if(!newbuf) { - fprintf(stderr,"calloc failed for size %u\n",newsize); + fprintf(stderr,"calloc failed for size %Zu\n",newsize); exit(1); } if(psubInfo->macroReplacements) { From 02d21255f5192dec361bb78546590562c65f0340 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 10 Nov 2008 20:47:06 +0000 Subject: [PATCH 28/32] Modified for release 1.5 --- msi.html | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/msi.html b/msi.html index 639553968..7fd58c6a5 100644 --- a/msi.html +++ b/msi.html @@ -10,25 +10,25 @@

    msi: Macro Substitution and Include Tool

    -

    Version 1.4, June 2004
    -Marty Kraimer (Advanced Photon Source, Argonne National Laboratory)

    +

    Version 1.5, 10th November, 2008

    Introduction

    -

    msi is a general purpose macro substitution/include tool. It accepts as -input an ascii template file. It looks for lines containing two reserved -command names: include and substitute. It also looks for and performs -substitutions on macros of the form $(var) and ${var}. It uses macLib, an EPICS -Base library created by William Lupton, to perform the substitutions.

    +

    msi is a general purpose macro substitution/include tool. It accepts as input +an ascii template file. It looks for lines containing two reserved command +names: include and substitute. It also looks for and performs +substitutions on macros of the form $(var) and ${var}. It uses the macLib +routines from EPICS Base to perform the substitutions, so it also accepts the +default value and value definition syntax that macLib implements.

    msi also allows substitutions to be specified via a separate substitution file. This substitution file allows the same format as the substitution files -accepted by dbLoadTemplate or subtool.

    +accepted by the EPICS IOC's dbLoadTemplate command.

    Command Syntax:

    -
    msi -V -ofile -Idir -Msub -Ssubfile template
    +
    msi -V -ooutfile -Idir -Msubs -Ssubfile template

    All parameters are optional. The -o, -I, -M, and -S switches may be separated from their associated value string by spaces if desired. Output will @@ -52,14 +52,14 @@ be written to stdout unless the -o option is given.

    include commands. For example:
    -
    msi -I "/home/phoebus/MRK/examples:." -I".." template
    +
    msi -I /home/mrk/examples:. -I.. template
    specifies that all named files should be searched for in the following locations in the order given:
      -
    1. /home/phoebus/MRK/examples
    2. +
    3. /home/mrk/examples
    4. . (the current directory)
    5. .. (the parent of the current directory)
    @@ -146,13 +146,13 @@ will generate warning messages on stderr and result in undefined output.

    The template file is read and processed one line at a time, where the maximum length of a line before and/or after macro expansion is 1023 characters -— longer input or output lines will cause msi to fail. Within the context +— longer input or output lines will cause msi to fail. Within the context of a single line, macro expansion does not occur when the variable instance appears inside a single-quoted string, or where the dollar sign $ is preceded by a back-slash character \, but as with the standard Unix shells, variables inside double quoted strings are expanded properly.

    -

    However neither back-slash characters nor quotes or either variety are +

    However neither back-slash characters nor quotes of either variety are removed when generating the output file, so depending on what is being output the single quote behaviour may not be useful and may even be a hinderance. It cannot be disabled in the current version of msi.

    From d0c061cf1f8be528cb2bfd05dc0a7ab0faab2715 Mon Sep 17 00:00:00 2001 From: cvs2svn Date: Mon, 10 Nov 2008 20:47:07 +0000 Subject: [PATCH 29/32] This commit was manufactured by cvs2svn to create tag 'MSI-R1-5'. From 359a4571f561abe86bf015dc8a80e29f6da39dfc Mon Sep 17 00:00:00 2001 From: "Janet B. Anderson" Date: Tue, 22 Sep 2009 16:34:47 +0000 Subject: [PATCH 30/32] Modified test of warning message. --- msi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/msi.c b/msi.c index e6b5ec422..faa825b1a 100644 --- a/msi.c +++ b/msi.c @@ -230,7 +230,8 @@ endif: n = macExpandString(macPvt,input,buffer,MAX_BUFFER_SIZE-1); fputs(buffer,stdout); if (!unexpWarned && n<0) { - fprintf(stderr,"Warning: unexpanded macros in ouput\n"); + fprintf(stderr, "Warning: Some macros cannot be expanded:\n" + " %s\n", input); unexpWarned++; } } From 0164402bad568ccd380397103921621e9bd01765 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 28 Oct 2009 19:30:02 +0000 Subject: [PATCH 31/32] Need epicsVersion.h to support macEnvExpand() properly. --- msi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/msi.c b/msi.c index faa825b1a..65c8fe5b6 100644 --- a/msi.c +++ b/msi.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include From 8c6f940e1f50ccc4d530823607a3d0186dbe4ee0 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 28 Oct 2009 19:47:00 +0000 Subject: [PATCH 32/32] Improve warning message, suggest using -V flag. --- msi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/msi.c b/msi.c index 65c8fe5b6..1f88c1519 100644 --- a/msi.c +++ b/msi.c @@ -55,6 +55,8 @@ static char *substituteGetReplacements(void *substitutePvt); /*Exit status*/ static int exitStatus = 0; +int opt_V = 0; + int main(int argc,char **argv) { @@ -86,6 +88,7 @@ int main(int argc,char **argv) 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(); @@ -231,8 +234,8 @@ endif: n = macExpandString(macPvt,input,buffer,MAX_BUFFER_SIZE-1); fputs(buffer,stdout); if (!unexpWarned && n<0) { - fprintf(stderr, "Warning: Some macros cannot be expanded:\n" - " %s\n", input); + fprintf(stderr, "Warning: Undefined macros present%s\n", + opt_V ? "" : ", use msi -V to list"); unexpWarned++; } }