316 lines
7.2 KiB
C
316 lines
7.2 KiB
C
/**
|
|
* Implementation file for the exe buffer buffer handling system.
|
|
*
|
|
* copyright: see file COPYRIGHT
|
|
*
|
|
* More information in exe.tex
|
|
*
|
|
* Mark Koennecke, November 2004
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <tcl.h>
|
|
#include "lld_str.h"
|
|
#include "fortify.h"
|
|
#include "sics.h"
|
|
#include "exebuf.h"
|
|
#include "dynstring.h"
|
|
#include "exebuf.i"
|
|
#include "status.h"
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
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;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
int exeBufLoad(pExeBuf self, char *filename){
|
|
char line[256];
|
|
FILE *fd = NULL;
|
|
int status;
|
|
|
|
assert(self);
|
|
fd = fopen(filename,"r");
|
|
if(fd == NULL){
|
|
return 0;
|
|
}
|
|
while(fgets(line,255,fd) != NULL){
|
|
status = exeBufAppend(self,line);
|
|
if(status != 1){
|
|
fclose(fd);
|
|
return 0;
|
|
}
|
|
}
|
|
fclose(fd);
|
|
if(self->name != NULL){
|
|
free(self->name);
|
|
}
|
|
self->name = strdup(locateName(filename));
|
|
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;
|
|
|
|
assert(self);
|
|
|
|
command = CreateDynString(80,80);
|
|
if(command == NULL){
|
|
return NULL;
|
|
}
|
|
buffer = GetCharArray(self->bufferContent);
|
|
if(self->end != -1){
|
|
self->start = self->end + 1;
|
|
}
|
|
for(i = self->start; i < strlen(buffer); 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;
|
|
}
|
|
/*---------------------------------------------------------------------*/
|
|
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, eValue, "%s:%d>> %s",self->name,self->lineno,cmd);
|
|
}
|
|
}
|
|
}
|
|
|
|
status = Tcl_Eval(pTcl,cmd);
|
|
if(status != TCL_OK){
|
|
if(pCon->sicsError == 0){
|
|
/*
|
|
Tcl Error
|
|
*/
|
|
if(strlen(pTcl->result) >= 2){
|
|
SCWrite(pCon,pTcl->result,eError);
|
|
}
|
|
SCWrite(pCon,"ERROR: Tcl error in block:",eError);
|
|
SCWrite(pCon,GetCharArray(command),eError);
|
|
SCWrite(pCon,"ERROR: end of Tcl error block",eError);
|
|
} else {
|
|
/*
|
|
SICS error: has already been reported
|
|
*/
|
|
pCon->sicsError = 0;
|
|
}
|
|
}
|
|
DeleteDynString(command);
|
|
if(SCGetInterrupt(pCon) >= eAbortBatch){
|
|
SCWrite(pCon,"ERROR: batch processing interrupted",eError);
|
|
SetStatus(eEager);
|
|
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);
|
|
SetStatus(eEager);
|
|
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;
|
|
}
|
|
|
|
|