/** * Implementation file for the exe buffer buffer handling system. * * copyright: see file COPYRIGHT * * More information in exe.tex * * Mark Koennecke, November 2004 */ #include #include #include #include "lld_str.h" #include "fortify.h" #include "sics.h" #include "exebuf.h" #include "dynstring.h" #include "exebuf.i" #include "status.h" char *ConID(SConnection *pCon); /* in conman.c */ /*-----------------------------------------------------------------------*/ pExeBuf exeBufCreate(char *name) { pExeBuf pNew = NULL; pNew = (pExeBuf) malloc(sizeof(ExeBuf)); if (pNew == NULL) { return NULL; } memset(pNew, 0, sizeof(ExeBuf)); pNew->name = strdup(name); pNew->bufferContent = CreateDynString(1024, 1024); if (!pNew->bufferContent) { return NULL; } return pNew; } /*----------------------------------------------------------------------*/ void exeBufKill(void *data) { exeBufDelete((pExeBuf) data); } /*-----------------------------------------------------------------------*/ void exeBufDelete(pExeBuf self) { if (self == NULL) { return; } if (self->name != NULL) { free(self->name); self->name = NULL; } if (self->bufferContent != NULL) { DeleteDynString(self->bufferContent); self->bufferContent = NULL; } free(self); } /*----------------------------------------------------------------------*/ int exeBufAppend(pExeBuf self, char *line) { int status; assert(self); status = DynStringConcat(self->bufferContent, line); if (strrchr(line, (int) '\n') == NULL) { DynStringConcatChar(self->bufferContent, '\n'); } return status; } /*-----------------------------------------------------------------------*/ static char *locateName(char *filename) { char *pPtr; int i; pPtr = filename + strlen(filename) - 1; for (i = strlen(filename) - 1; i > 0; i--, pPtr--) { if (*pPtr == '/') { pPtr++; return pPtr; } } return filename; } /*---------------------------------------------------------------------- If this is MOUNTAINBATCH file, replace ocurrences of @nl@ with \n ------------------------------------------------------------------------*/ static void fixMountainBatch(pExeBuf self) { char *pPtr, *pData, *pNL; pPtr = GetCharArray(self->bufferContent); if(strstr(pPtr, "#MOUNTAINBATCH") != pPtr){ /* nothing to do */ return; } pData = strdup(pPtr); DynStringClear(self->bufferContent); pPtr = pData; while((pNL = strstr(pPtr,"@nl@")) != NULL){ *pNL = '\n'; *(pNL+1) = '\0'; DynStringConcat(self->bufferContent, pPtr); pPtr = pNL +4; } DynStringConcat(self->bufferContent,pPtr); free(pData); } /*-----------------------------------------------------------------------*/ int exeBufLoad(pExeBuf self, char *filename) { char line[256], *pPtr; FILE *fd = NULL; int status, idx, gtsebatch = 0; assert(self); fd = fopen(filename, "r"); if (fd == NULL) { return 0; } while (fgets(line, 255, fd) != NULL) { /* Do not use exeBufAppend here. Lines longer than 255 would get newline characters within the line */ status = DynStringConcat(self->bufferContent, line); if (status != 1) { fclose(fd); return 0; } } fclose(fd); /** * make sure that there is a \n at the end */ idx = GetDynStringLength(self->bufferContent); pPtr = GetCharArray(self->bufferContent); if(pPtr[idx-1] != '\n'){ DynStringConcat(self->bufferContent,"\n"); } if (self->name != NULL) { free(self->name); } self->name = strdup(locateName(filename)); fixMountainBatch(self); return 1; } /*----------------------------------------------------------------------*/ int exeBufSave(pExeBuf self, char *filename) { FILE *fd = NULL; fd = fopen(filename, "w"); if (fd == NULL) { return 0; } fputs(GetCharArray(self->bufferContent), fd); fclose(fd); self->name = strdup(locateName(filename)); return 1; } /*================ process batch buffer ==============================*/ static pDynString findBlockEnd(pExeBuf self) { pDynString command = NULL; char *buffer = NULL; int i, j; assert(self); command = CreateDynString(80, 80); if (command == NULL) { return NULL; } buffer = GetCharArray(self->bufferContent); if (self->end != -1) { self->start = self->end + 1; } j = strlen(buffer); for (i = self->start; i < j; i++) { DynStringConcatChar(command, buffer[i]); if (buffer[i] == '\n') { self->lineno++; if (Tcl_CommandComplete(GetCharArray(command))) { self->end = i; return command; } } } DeleteDynString(command); return NULL; } /*-----------------attempt at a faster version ------------------------------- * But this only saves on the ConcatChar side of things...... * * */ static pDynString findBlockEndExp(pExeBuf self) { pDynString command = NULL; char *buffer = NULL; char *cStart, *cEnd; int i, len; assert(self); command = CreateDynString(80, 80); if (command == NULL) { return NULL; } buffer = GetCharArray(self->bufferContent); if (self->end != -1) { self->start = self->end + 1; } cStart = buffer +self->start; cEnd = strchr(cStart,'\n'); while(cEnd != NULL){ len = cEnd - cStart+1; DynStringConcatBytes(command,cStart, len); self->lineno++; if (Tcl_CommandComplete(GetCharArray(command))) { self->end += len; return command; } cStart = cEnd+1; cEnd = strchr(cStart,'\n'); } DeleteDynString(command); return NULL; } /*---------------------------------------------------------------------*/ int exeBufProcess(pExeBuf self, SicsInterp * pSics, SConnection * pCon, pICallBack pCall, int echo) { pDynString command = NULL; Tcl_Interp *pTcl = NULL; int status; static int weWantLogging = 1; char *cmd; char cmdName[128]; char *ende; int l; assert(self); assert(pSics); self->start = 0; self->end = -1; self->lineno = 0; pTcl = InterpGetTcl(pSics); if (pCall != NULL) { InvokeCallBack(pCall, BATCHSTART, self->name); } if (echo) { SCsetMacro(pCon, 0); } while ((command = findBlockEnd(self)) != NULL) { if (pCall != NULL) { InvokeCallBack(pCall, BATCHAREA, NULL); } cmd = GetCharArray(command); if (echo) { /* find first word */ while (*cmd == ' ') { cmd++; } ende = cmd; while (*ende > ' ') { ende++; } l = ende - cmd; if (l < sizeof cmdName) { strncpy(cmdName, cmd, l); cmdName[l] = '\0'; if (FindCommand(pSics, cmdName) != NULL) { /* print only SICS commands */ SCPrintf(pCon, eLog, "%s:%d>> %s", self->name, self->lineno, cmd); } else { /* debugging */ /* SCPrintf(pCon, eValue, "%s:%d>> %s",self->name,self->lineno,cmd); */ } } } Log(INFO,"com","%s:batch:%s", ConID(pCon), cmd); status = Tcl_Eval(pTcl, cmd); if (status != TCL_OK) { if (SCGetSicsError(pCon) == 0) { /* Tcl Error */ if (strlen(pTcl->result) >= 2) { SCPrintf(pCon, eError, "ERROR: Tcl reported: %s", pTcl->result); } } else { SCWrite(pCon, pTcl->result, eError); SCSetSicsError(pCon,0); } SCWrite(pCon, "ERROR: above error was in block:", eError); SCWrite(pCon, cmd, eError); SCWrite(pCon, "ERROR: end of Tcl error block", eError); } DeleteDynString(command); if (SCGetInterrupt(pCon) >= eAbortBatch) { SCWrite(pCon, "ERROR: batch processing interrupted", eError); if (pCall != NULL) { InvokeCallBack(pCall, BATCHEND, self->name); } return 0; } else { SCSetInterrupt(pCon, eContinue); } } if (pCall != NULL) { InvokeCallBack(pCall, BATCHEND, self->name); } return 1; } /*---------------------------------------------------------------------*/ int exeBufProcessErrList(pExeBuf self, SicsInterp * pSics, SConnection * pCon, int errList) { pDynString command = NULL; Tcl_Interp *pTcl = NULL; int status; static int weWantLogging = 1; char *cmd; char cmdName[128]; char *error; char msg[132]; char *ende; int l; assert(self); assert(pSics); self->start = 0; self->end = -1; self->lineno = 0; pTcl = InterpGetTcl(pSics); while ((command = findBlockEnd(self)) != NULL) { cmd = GetCharArray(command); status = Tcl_Eval(pTcl, cmd); if (status != TCL_OK) { LLDstringAppend(errList, cmd); error = (char *) Tcl_GetStringResult(pTcl); snprintf(msg, sizeof msg, "#ERR: %s\n", error); LLDstringAppend(errList, msg); } DeleteDynString(command); if (SCGetInterrupt(pCon) >= eAbortBatch) { SCWrite(pCon, "ERROR: batch processing interrupted", eError); return 0; } else { SCSetInterrupt(pCon, eContinue); } } return 1; } /*------------------------------------------------------------------------*/ void exeBufRange(pExeBuf self, int *start, int *end, int *lineno) { assert(self); *start = self->start; *end = self->end; *lineno = self->lineno; } /*------------------------------------------------------------------------*/ pDynString exeBufText(pExeBuf self, int start, int end) { pDynString result = NULL; char *pPtr; int i; assert(self); result = CreateDynString(256, 132); if (result == NULL) { return NULL; } pPtr = GetCharArray(self->bufferContent); if (end >= strlen(pPtr)) { end = strlen(pPtr) - 1; } for (i = start; i < end; i++) { DynStringConcatChar(result, pPtr[i]); } return result; } /*-----------------------------------------------------------------------*/ char *exeBufName(pExeBuf self) { assert(self); return self->name; }