Files
sics/exebuf.c
koennecke 0e2605b570 First commit towards replacing pCon-> with someFunc(pCon)
This is accompanied with the removal of dead code in conman.c and else
2016-10-31 08:33:36 +01:00

424 lines
9.7 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"
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;
}