diff --git a/config/RULES.Db b/config/RULES.Db index b4946c7aa..90b76ed08 100644 --- a/config/RULES.Db +++ b/config/RULES.Db @@ -12,11 +12,7 @@ # MAKEBPT = $(EPICS_BASE_HOST_BIN)/makeBpt$(EXE) -ifndef MSI -# Tool from R3.14 extensions bin, R3.13 extensions bin, or user path -MSI = $(firstword $(wildcard $(EPICS_EXTENSIONS_HOST_BIN)/msi$(HOSTEXE) \ - $(EPICS_EXTENSIONS)/bin/$(HOST_ARCH)/msi$(HOSTEXE)) msi$(HOSTEXE)) -endif +MSI = $(EPICS_BASE_HOST_BIN)/msi$(HOSTEXE) DBEXPAND = $(EPICS_BASE_HOST_BIN)/dbExpand$(EXE) DBST = dbst diff --git a/configure/CONFIG_BASE b/configure/CONFIG_BASE index 7ee5a5b89..9a9793093 100644 --- a/configure/CONFIG_BASE +++ b/configure/CONFIG_BASE @@ -112,8 +112,5 @@ ifndef DBST DBST = dbst endif -ifndef MSI -MSI = msi -endif - +MSI = $(EPICS_BASE_HOST_BIN)/msi$(HOSTEXE) diff --git a/src/dbtools/Makefile b/src/dbtools/Makefile index 38ed52c9e..8655a5337 100644 --- a/src/dbtools/Makefile +++ b/src/dbtools/Makefile @@ -11,6 +11,11 @@ TOP=../.. include $(TOP)/configure/CONFIG +PROD_HOST += msi + +msi_SRCS = msi.c +msi_LIBS += Com + INC += dbLoadTemplate.h INC += dbtoolsIocRegister.h diff --git a/src/dbtools/msi.c b/src/dbtools/msi.c new file mode 100644 index 000000000..525d4f25b --- /dev/null +++ b/src/dbtools/msi.c @@ -0,0 +1,798 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* This file is distributed subject to a Software License Agreement found +* in the file LICENSE that is included with this distribution. +\*************************************************************************/ +/*msi - macro sunstitutions and include */ + +/* + * Modification Log: + * ----------------- + * .01 08DEC97 mrk Original version + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MAX_BUFFER_SIZE 4096 + +#if ((EPICS_VERSION <= 3) && (EPICS_REVISION <= 13)) +#define macEnvExpand(x) strdup(x) +#endif + +/*Forward references to local routines*/ +static void usageExit(void); +static void addMacroReplacements(MAC_HANDLE *macPvt,char *pval); +static void makeSubstitutions(void *inputPvt,void *macPvt,char *templateName); + +/*Routines that read the template files */ +static void inputConstruct(void **inputPvt); +static void inputDestruct(void *inputPvt); +static void inputAddPath(void *inputPvt, char *pval); +static void inputBegin(void *inputPvt,char *fileName); +static char *inputNextLine(void *inputPvt); +static void inputNewIncludeFile(void *inputPvt,char *name); +static void inputErrPrint(void *inputPvt); + +/*Routines that read the substitution file */ +static void substituteDestruct(void *substitutePvt); +static void substituteOpen(void **substitutePvt,char *substitutionName); +static int substituteGetNextSet(void *substitutePvt,char **filename); +static char *substituteGetReplacements(void *substitutePvt); + +/*Exit status*/ +static int exitStatus = 0; + +int opt_V = 0; + + +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,1); + while((argc>1) && (argv[1][0] == '-')) { + narg = (strlen(argv[1])==2) ? 2 : 1; + pval = (narg==1) ? (argv[1]+2) : argv[2]; + if(strncmp(argv[1],"-I",2)==0) { + inputAddPath(inputPvt,pval); + } else if(strncmp(argv[1],"-o",2)==0) { + if(freopen(pval,"w",stdout)==NULL) { + fprintf(stderr,"Can't open %s for writing: %s\n", pval, strerror(errno)); + exit(1); + } + } else if(strncmp(argv[1],"-M",2)==0) { + addMacroReplacements(macPvt,pval); + } else if(strncmp(argv[1],"-S",2)==0) { + substitutionName = calloc(strlen(pval)+1,sizeof(char)); + strcpy(substitutionName,pval); + } else if(strncmp(argv[1],"-V",2)==0) { + macSuppressWarning(macPvt,0); + opt_V = 1; + narg = 1; /* no argument for this option */ + } else { + usageExit(); + } + argc -= narg; + for(i=1; i2) { + fprintf(stderr,"too many filename arguments\n"); + usageExit(); + } + if(argc==2) { + templateName = calloc(strlen(argv[1])+1,sizeof(char)); + strcpy(templateName,argv[1]); + } + if(!substitutionName) { + makeSubstitutions(inputPvt,macPvt,templateName); + } else { + void *substitutePvt; + char *filename = 0; + + substituteOpen(&substitutePvt,substitutionName); + while(substituteGetNextSet(substitutePvt,&filename)) { + if(templateName) filename = templateName; + if(!filename) { + fprintf(stderr,"no template file\n"); + usageExit(); + } + macPushScope(macPvt); + while((pval = substituteGetReplacements(substitutePvt))){ + addMacroReplacements(macPvt,pval); + makeSubstitutions(inputPvt,macPvt,filename); + } + macPopScope(macPvt); + } + substituteDestruct(substitutePvt); + } + errlogFlush(); + inputDestruct(inputPvt); + free((void *)templateName); + free((void *)substitutionName); + return(exitStatus); +} + +void usageExit(void) +{ + fprintf(stderr,"usage: msi -V -opath -Ipath ... -Msub ... -Ssubfile template\n"); + fprintf(stderr," Specifying path will replace the default '.'\n"); + fprintf(stderr," stdin is used if template is not given\n"); + 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); +} + +typedef enum {cmdInclude,cmdSubstitute} cmdType; +static const char *cmdNames[] = {"include","substitute"}; +static void makeSubstitutions(void *inputPvt,void *macPvt,char *templateName) +{ + char *input; + static char buffer[MAX_BUFFER_SIZE]; + int n; + static int unexpWarned = 0; + + inputBegin(inputPvt,templateName); + while((input = inputNextLine(inputPvt))) { + int expand=1; + char *p; + char *command = 0; + + p = input; + /*skip whitespace at beginning of line*/ + while(*p && (isspace(*p))) ++p; + /*Look for i or s */ + if(*p && (*p=='i' || *p=='s')) command = p; + if(command) { + char *pstart; + char *pend; + char *copy; + int cmdind=-1; + int i; + + for(i=0; i< NELEMENTS(cmdNames); i++) { + if(strstr(command,cmdNames[i])) { + cmdind = i; + } + } + if(cmdind<0) goto endif; + p = command + strlen(cmdNames[cmdind]); + /*skip whitespace after command*/ + while(*p && (isspace(*p))) ++p; + /*Next character must be quote*/ + if((*p==0) || (*p!='"')) goto endif; + pstart = ++p; + /*Look for end quote*/ + while(*p && (*p!='"')) { + /*allow escape for imbeded quote*/ + if((*p=='\\') && *(p+1)=='"') { + p += 2; continue; + } else { + if(*p=='"') break; + } + ++p; + } + pend = p; + if(*p==0) goto endif; + /*skip quote and any trailing blanks*/ + while(*++p==' ') ; + if(*p != '\n' && *p !=0) goto endif; + copy = calloc(pend-pstart+1,sizeof(char)); + strncpy(copy,pstart,pend-pstart); + switch(cmdind) { + case cmdInclude: + inputNewIncludeFile(inputPvt,copy); + break; + case cmdSubstitute: + addMacroReplacements(macPvt,copy); + break; + default: + fprintf(stderr,"Logic Error: makeSubstitutions\n"); + inputErrPrint(inputPvt); + exit(1); + } + free(copy); + expand = 0; + } +endif: + if (expand) { + n = macExpandString(macPvt,input,buffer,MAX_BUFFER_SIZE-1); + fputs(buffer,stdout); + if (!unexpWarned && n<0) { + const char * pErrMsg = "Warning: Undefined macros present, use msi -V to list\n"; + if ( opt_V ) { + exitStatus = 2; + pErrMsg = "Error: Undefined macros present\n"; + } + fprintf( stderr, pErrMsg ); + unexpWarned++; + } + } + } +} + +typedef struct inputFile{ + ELLNODE node; + char *filename; + FILE *fp; + int lineNum; +}inputFile; + +typedef struct pathNode { + ELLNODE node; + char *directory; +} pathNode; + +typedef struct inputData { + ELLLIST inputFileList; + ELLLIST pathList; + char inputBuffer[MAX_BUFFER_SIZE]; +}inputData; + +static void inputOpenFile(inputData *pinputData,char *filename); +static void inputCloseFile(inputData *pinputData); +static void inputCloseAllFiles(inputData *pinputData); + +static void inputConstruct(void **ppvt) +{ + inputData *pinputData; + + pinputData = calloc(1,sizeof(inputData)); + ellInit(&pinputData->inputFileList); + ellInit(&pinputData->pathList); + *ppvt = pinputData; +} + +static void inputDestruct(void *pvt) +{ + inputData *pinputData = (inputData *)pvt; + pathNode *ppathNode; + + inputCloseAllFiles(pinputData); + while((ppathNode = (pathNode *)ellFirst(&pinputData->pathList))) { + ellDelete(&pinputData->pathList,&ppathNode->node); + free((void *)ppathNode->directory); + free((void *)ppathNode); + } + free(pvt); +} + +static void inputAddPath(void *pvt, char *path) +{ + inputData *pinputData = (inputData *)pvt; + ELLLIST *ppathList = &pinputData->pathList; + pathNode *ppathNode; + const char *pcolon; + const char *pdir; + int len; + int emptyName; + + pdir = path; + /*an empty name at beginning, middle, or end means current directory*/ + while(pdir && *pdir) { + emptyName = ((*pdir == ':') ? 1 : 0); + if(emptyName) ++pdir; + ppathNode = (pathNode *)calloc(1,sizeof(pathNode)); + ellAdd(ppathList,&ppathNode->node); + if(!emptyName) { + pcolon = strchr(pdir,':'); + len = (pcolon ? (pcolon - pdir) : strlen(pdir)); + if(len>0) { + ppathNode->directory = (char *)calloc(len+1,sizeof(char)); + strncpy(ppathNode->directory,pdir,len); + pdir = pcolon; + /*unless at end skip past first colon*/ + if(pdir && *(pdir+1)!=0) ++pdir; + } else { /*must have been trailing : */ + emptyName=1; + } + } + if(emptyName) { + ppathNode->directory = (char *)calloc(2,sizeof(char)); + strcpy(ppathNode->directory,"."); + } + } + return; +} + +static void inputBegin(void *pvt,char *fileName) +{ + inputData *pinputData = (inputData *)pvt; + + inputCloseAllFiles(pinputData); + inputOpenFile(pinputData,fileName); +} + +static char *inputNextLine(void *pvt) +{ + inputData *pinputData = (inputData *)pvt; + inputFile *pinputFile; + char *pline; + + while((pinputFile = (inputFile *)ellFirst(&pinputData->inputFileList))) { + pline = fgets(pinputData->inputBuffer,MAX_BUFFER_SIZE,pinputFile->fp); + if(pline) { + ++pinputFile->lineNum; + return(pline); + } + inputCloseFile(pinputData); + } + return(0); +} + +static void inputNewIncludeFile(void *pvt,char *name) +{ + inputData *pinputData = (inputData *)pvt; + + inputOpenFile(pinputData,name); +} + +static void inputErrPrint(void *pvt) +{ + inputData *pinputData = (inputData *)pvt; + inputFile *pinputFile; + + fprintf(stderr,"input: %s which is ",pinputData->inputBuffer); + pinputFile = (inputFile *)ellFirst(&pinputData->inputFileList); + while(pinputFile) { + fprintf(stderr,"line %d of ",pinputFile->lineNum); + if(pinputFile->filename) { + fprintf(stderr," file %s\n",pinputFile->filename); + } else { + fprintf(stderr,"stdin:\n"); + } + pinputFile = (inputFile *)ellNext(&pinputFile->node); + if(pinputFile) { + fprintf(stderr," which is included from "); + } else { + fprintf(stderr,"\n"); + } + } + fprintf(stderr,"\n"); +} + +static void inputOpenFile(inputData *pinputData,char *filename) +{ + ELLLIST *ppathList = &pinputData->pathList; + pathNode *ppathNode = 0; + inputFile *pinputFile; + char *fullname = 0; + FILE *fp = 0; + + if(!filename) { + fp = stdin; + } else if((ellCount(ppathList)==0) || strchr(filename,'/')){ + fp = fopen(filename,"r"); + } else { + ppathNode = (pathNode *)ellFirst(ppathList); + while(ppathNode) { + fullname = calloc(strlen(filename)+strlen(ppathNode->directory) +2, + sizeof(char)); + strcpy(fullname,ppathNode->directory); + strcat(fullname,"/"); + strcat(fullname,filename); + fp = fopen(fullname,"r"); + if(fp) break; + free((void *)fullname); + ppathNode = (pathNode *)ellNext(&ppathNode->node); + } + } + if(!fp) { + fprintf(stderr,"Could not open %s\n",filename); + inputErrPrint((void *)pinputData); + exit(1); + } + pinputFile = calloc(1,sizeof(inputFile)); + if(ppathNode) { + pinputFile->filename = calloc(1,strlen(fullname)+1); + strcpy(pinputFile->filename,fullname); + free((void *)fullname); + } else if(filename) { + pinputFile->filename = calloc(1,strlen(filename)+1); + strcpy(pinputFile->filename,filename); + } else { + pinputFile->filename = calloc(1,strlen("stdin")+1); + strcpy(pinputFile->filename,"stdin"); + } + pinputFile->fp = fp; + ellInsert(&pinputData->inputFileList,0,&pinputFile->node); +} + +static void inputCloseFile(inputData *pinputData) +{ + inputFile *pinputFile; + + pinputFile = (inputFile *)ellFirst(&pinputData->inputFileList); + if(!pinputFile) return; + ellDelete(&pinputData->inputFileList,&pinputFile->node); + if(fclose(pinputFile->fp)) + fprintf(stderr,"fclose failed: file %s\n",pinputFile->filename); + free(pinputFile->filename); + free(pinputFile); +} + +static void inputCloseAllFiles(inputData *pinputData) +{ + inputFile *pinputFile; + + while((pinputFile=(inputFile *)ellFirst(&pinputData->inputFileList))){ + inputCloseFile(pinputData); + } +} + +/*start of code that handles substitution file*/ +typedef enum { + tokenLBrace,tokenRBrace,tokenSeparater,tokenString,tokenEOF +}tokenType; + +typedef struct subFile { + char *substitutionName; + FILE *fp; + int lineNum; + char inputBuffer[MAX_BUFFER_SIZE]; + char *pnextChar; + tokenType token; + char string[MAX_BUFFER_SIZE]; +} subFile; + +typedef struct patternNode { + ELLNODE node; + char *var; +}patternNode; + +typedef struct subInfo { + subFile *psubFile; + int isFile; + char *filename; + int isPattern; + ELLLIST patternList; + size_t size; + size_t curLength; + char *macroReplacements; +}subInfo; + +static char *subGetNextLine(subFile *psubFile); +static tokenType subGetNextToken(subFile *psubFile); +static void subFileErrPrint(subFile *psubFile,char * message); +static void freeSubFile(subInfo *psubInfo); +static void freePattern(subInfo *psubInfo); +static void catMacroReplacements(subInfo *psubInfo,const char *value); + +void freeSubFile(subInfo *psubInfo) +{ + subFile *psubFile = psubInfo->psubFile; + if(psubFile->fp) { + if(fclose(psubFile->fp)) + fprintf(stderr,"fclose failed on substitution file\n"); + } + free((void *)psubFile); + free((void *)psubInfo->filename); + psubInfo->psubFile = 0; +} + +void freePattern(subInfo *psubInfo) +{ + patternNode *ppatternNode; + while((ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList))) { + ellDelete(&psubInfo->patternList,&ppatternNode->node); + free(ppatternNode->var); + free(ppatternNode); + } + psubInfo->isPattern = 0; +} + +static void substituteDestruct(void *pvt) +{ + subInfo *psubInfo = (subInfo *)pvt; + + freeSubFile(psubInfo); + freePattern(psubInfo); + free((void *)psubInfo); + return; +} + +static void substituteOpen(void **ppvt,char *substitutionName) +{ + subInfo *psubInfo; + subFile *psubFile; + FILE *fp; + + psubInfo = calloc(1,sizeof(subInfo)); + *ppvt = (void *)psubInfo; + psubFile = calloc(1,sizeof(subFile)); + psubInfo->psubFile = psubFile; + ellInit(&psubInfo->patternList); + fp = fopen(substitutionName,"r"); + if(!fp) { + fprintf(stderr,"Could not open %s\n",substitutionName); + exit(1); + } + psubFile->substitutionName = substitutionName; + psubFile->fp = fp; + psubFile->lineNum = 0; + psubFile->inputBuffer[0] = 0; + psubFile->pnextChar = &psubFile->inputBuffer[0]; + subGetNextToken(psubFile); + return; +} + +static int substituteGetNextSet(void *pvt,char **filename) +{ + subInfo *psubInfo = (subInfo *)pvt; + subFile *psubFile = psubInfo->psubFile; + patternNode *ppatternNode; + + *filename = 0; + while(psubFile->token==tokenSeparater) subGetNextToken(psubFile); + if(psubFile->token==tokenEOF) return(0); + if(psubFile->token==tokenString && strcmp(psubFile->string,"file")==0) { + psubInfo->isFile = 1; + if(subGetNextToken(psubFile)!=tokenString) { + subFileErrPrint(psubFile,"Expecting filename"); + exit(1); + } + freePattern(psubInfo); + free((void *)psubInfo->filename); + if(psubFile->string[0]=='"'&&psubFile->string[strlen(psubFile->string)-1]=='"') { + psubFile->string[strlen(psubFile->string)-1]='\0'; + psubInfo->filename = macEnvExpand(psubFile->string+1); + } + else { + psubInfo->filename = macEnvExpand(psubFile->string); + } + while(subGetNextToken(psubFile)==tokenSeparater); + if(psubFile->token!=tokenLBrace) { + subFileErrPrint(psubFile,"Expecting {"); + exit(1); + } + subGetNextToken(psubFile); + } + *filename = psubInfo->filename; + while(psubFile->token==tokenSeparater) subGetNextToken(psubFile); + if(psubFile->token==tokenLBrace) return(1); + if(psubFile->token==tokenRBrace) return(0); + if(psubFile->token!=tokenString + || strcmp(psubFile->string,"pattern")!=0) { + subFileErrPrint(psubFile,"Expecting pattern"); + exit(1); + } + freePattern(psubInfo); + psubInfo->isPattern = 1; + while(subGetNextToken(psubFile)==tokenSeparater); + if(psubFile->token!=tokenLBrace) { + subFileErrPrint(psubFile,"Expecting {"); + exit(1); + } + while(1) { + while(subGetNextToken(psubFile)==tokenSeparater); + if(psubFile->token!=tokenString) break; + ppatternNode = calloc(1,sizeof(patternNode)); + ellAdd(&psubInfo->patternList,&ppatternNode->node); + ppatternNode->var = calloc(strlen(psubFile->string)+1,sizeof(char)); + strcpy(ppatternNode->var,psubFile->string); + } + if(psubFile->token!=tokenRBrace) { + subFileErrPrint(psubFile,"Expecting }"); + exit(1); + } + subGetNextToken(psubFile); + return(1); +} + +static char *substituteGetReplacements(void *pvt) +{ + subInfo *psubInfo = (subInfo *)pvt; + subFile *psubFile = psubInfo->psubFile; + patternNode *ppatternNode; + + if(psubInfo->macroReplacements) psubInfo->macroReplacements[0] = 0; + psubInfo->curLength = 0; + while(psubFile->token==tokenSeparater) subGetNextToken(psubFile); + if(psubFile->token==tokenRBrace && psubInfo->isFile) { + psubInfo->isFile = 0; + free((void *)psubInfo->filename); + psubInfo->filename = 0; + freePattern(psubInfo); + subGetNextToken(psubFile); + return(0); + } + if(psubFile->token==tokenEOF) return(0); + if(psubFile->token!=tokenLBrace) return(0); + if(psubInfo->isPattern) { + int gotFirstPattern = 0; + + while(subGetNextToken(psubFile)==tokenSeparater); + ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList); + while(1) { + if(psubFile->token==tokenRBrace) { + if(ppatternNode) + subFileErrPrint(psubFile,"less values than patterns"); + subGetNextToken(psubFile); + return(psubInfo->macroReplacements); + } + if(psubFile->token!=tokenString) { + subFileErrPrint(psubFile,"Illegal token"); + exit(-1); + } + if(gotFirstPattern) catMacroReplacements(psubInfo,","); + gotFirstPattern = 1; + if(ppatternNode) { + catMacroReplacements(psubInfo,ppatternNode->var); + catMacroReplacements(psubInfo,"="); + catMacroReplacements(psubInfo,psubFile->string); + ppatternNode = (patternNode *)ellNext(&ppatternNode->node); + } else { + subFileErrPrint(psubFile,"more values than patterns"); + } + while(subGetNextToken(psubFile)==tokenSeparater); + } + } else while(1) { + switch(subGetNextToken(psubFile)) { + case tokenRBrace: + subGetNextToken(psubFile); + return(psubInfo->macroReplacements); + case tokenSeparater: + catMacroReplacements(psubInfo,","); + break; + case tokenString: + catMacroReplacements(psubInfo,psubFile->string); + break; + default: + subFileErrPrint(psubFile,"Illegal token"); + exit(1); + } + } +} + +static char *subGetNextLine(subFile *psubFile) +{ + char *pline; + + 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; + } + if(!pline) { + psubFile->token = tokenEOF; + psubFile->inputBuffer[0] = 0; + psubFile->pnextChar = 0; + return(0); + } + psubFile->pnextChar = &psubFile->inputBuffer[0]; + return(&psubFile->inputBuffer[0]); +} + +static void subFileErrPrint(subFile *psubFile,char * message) +{ + fprintf(stderr,"substitution file %s line %d: %s", + psubFile->substitutionName, + psubFile->lineNum,psubFile->inputBuffer); + fprintf(stderr,"%s\n",message); +} + + +static tokenType subGetNextToken(subFile *psubFile) +{ + char *p; + char *pto; + + p = psubFile->pnextChar; + if(!p) { psubFile->token = tokenEOF; return(tokenEOF);} + if(*p==0 || *p=='\n' || *p=='#') { + p = subGetNextLine(psubFile); + if(!p) { psubFile->token = tokenEOF; return(tokenEOF);} + else { psubFile->token = tokenSeparater; return(tokenSeparater);} + } + while(isspace(*p)) p++; + if(*p=='{') { + psubFile->token = tokenLBrace; + psubFile->pnextChar = ++p; + return(tokenLBrace); + } + if(*p=='}') { + psubFile->token = tokenRBrace; + psubFile->pnextChar = ++p; + return(tokenRBrace); + } + if(*p==0 || isspace(*p) || *p==',') { + while(isspace(*p) || *p==',') p++; + psubFile->token = tokenSeparater; + psubFile->pnextChar = p; + return(tokenSeparater); + } + /*now handle quoted strings*/ + if(*p=='"') { + pto = &psubFile->string[0]; + *pto++ = *p++; + while(*p!='"') { + if(*p==0 || *p=='\n') { + subFileErrPrint(psubFile,"Strings must be on single line\n"); + exit(1); + } + /*allow escape for imbeded quote*/ + if((*p=='\\') && *(p+1)=='"') { + *pto++ = *p++; + *pto++ = *p++; + continue; + } + *pto++ = *p++; + } + *pto++ = *p++; + psubFile->pnextChar = p; + *pto = 0; + psubFile->token = tokenString; + return(tokenString); + } + /*Now take anything up to next non String token and not space*/ + pto = &psubFile->string[0]; + while(!isspace(*p) && (strspn(p,"\",{}")==0)) *pto++ = *p++; + *pto = 0; + psubFile->pnextChar = p; + psubFile->token = tokenString; + return(tokenString); +} + +static void catMacroReplacements(subInfo *psubInfo,const char *value) +{ + size_t len = strlen(value); + + if(psubInfo->size <= (psubInfo->curLength + len)) { + size_t newsize = psubInfo->size + MAX_BUFFER_SIZE; + char *newbuf; + + if(newsize <= psubInfo->curLength + len) + newsize = psubInfo->curLength + len + 1; + newbuf = calloc(1,newsize); + if(!newbuf) { + fprintf(stderr,"calloc failed for size %Zu\n",newsize); + exit(1); + } + if(psubInfo->macroReplacements) { + memcpy(newbuf,psubInfo->macroReplacements,psubInfo->curLength); + free(psubInfo->macroReplacements); + } + psubInfo->size = newsize; + psubInfo->macroReplacements = newbuf; + } + strcat(psubInfo->macroReplacements,value); + psubInfo->curLength += len; +}