Files
sics/splitter.c
2014-03-14 09:48:14 +01:00

472 lines
10 KiB
C

/*---------------------------------------------------------------------------
Splitter: a module to break a line in a list of words,
thereby determining type and storing results in a List.
Mark Koennecke October 1996
Fixed a line overrun in SplitText
Mark Koennecke, July 2011
Free for non commercial use, no warranties of any kind taken.
---------------------------------------------------------------------------*/
#include "fortify.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "tcl.h"
#include "splitter.h"
typedef enum _CharType { eSpace, eNum, eeText, eQuote } CharType;
/* ------------------------ local prototypes ------------------------------*/
static TokenList *CreateToken(TokenList * pN, TokenList * P);
static CharType CheckSpecial(char *pWord);
static int isEnd(char c);
/*=========================================================================*/
static TokenList *CreateToken(TokenList * pN, TokenList * pP)
{
TokenList *pRes = NULL;
pRes = (TokenList *) malloc(sizeof(TokenList));
if (!pRes)
return NULL;
pRes->fVal = .0;
pRes->iVal = 0;
pRes->Type = eUndefined;
pRes->text = NULL;
pRes->pNext = pN;
if (pN) {
pN->pPrevious = pRes;
}
pRes->pPrevious = pP;
if (pP) {
pP->pNext = pRes;
}
return pRes;
}
/*---------------------------------------------------------------------------*/
static CharType CheckSpecial(char *pWord)
{
CharType eRes = eeText;
int iFlag = 0;
if (isspace(pWord[0]))
return (eSpace);
if (isdigit(pWord[0]))
return (eNum);
/* simple cases */
if (pWord[0] == '*')
return (eeText);
if (pWord[0] == '/')
return (eeText);
if (pWord[0] == '\\')
return (eeText);
if (pWord[0] == ']')
return (eeText);
if (pWord[0] == '[')
return (eeText);
if (pWord[0] == '"')
return (eQuote);
/* difficult cases, next characters will be searched for decision */
if (pWord[0] == '-')
iFlag = 1;
if (pWord[0] == '+')
iFlag = 1;
if (pWord[0] == '.')
iFlag = 1;
if (iFlag == 1) {
if (isdigit(pWord[1])) {
return (eNum);
} else if (isalpha(pWord[1])) {
return (eeText);
} else if (!isspace(pWord[1])) {
pWord++;
return (CheckSpecial(pWord));
}
}
return (eeText);
}
/*--------------------------------------------------------------------------*/
static int isEnd(char c)
{
if ((c == '\0') || (c == '\n') || (c == '\r')) {
return 2;
} else if (c == ' ') {
return 1;
} else {
return 0;
}
}
/*--------------------------------------------------------------------------*/
TokenList *SplitText(char *pLine)
{
TokenList *pList = NULL;
TokenList *pCurrent;
char pBueffel[256];
char *pChar;
CharType eWhat;
int i, n;
if (!pLine)
return NULL;
pChar = pLine;
/* loop through line */
while (isEnd(*pChar) != 2) {
eWhat = CheckSpecial(pChar);
/* skip spaces */
if (eWhat == eSpace) {
pChar++;
continue;
}
/* no space, read word in first place */
if (eWhat == eQuote) {
i = 0;
pChar++;
while ((isEnd(*pChar) != 2) && (*pChar != '"')
&& i < 250) {
if (*pChar == '\\') {
pBueffel[i] = Tcl_Backslash(pChar, &n);
pChar += n;
} else {
pBueffel[i] = *pChar;
pChar++;
}
i++;
}
pBueffel[i] = '\0';
/* pChar++; */
eWhat = eeText;
} else {
i = 0;
while (!isEnd(*pChar) && i < 250) {
pBueffel[i] = *pChar;
i++;
pChar++;
}
pBueffel[i] = '\0';
}
if (pList == NULL) {
pList = CreateToken(NULL, NULL);
pCurrent = pList;
} else {
pCurrent = CreateToken(NULL, pCurrent);
}
if (!pCurrent)
return NULL;
/* copyy text always */
pCurrent->text = strdup(pBueffel);
if (eWhat == eeText) {
pCurrent->Type = eText;
} else if (eWhat == eNum) {
/* float ? */
if (strchr(pBueffel, '.') == NULL) {
pCurrent->Type = eInt;
sscanf(pBueffel, "%ld", &(pCurrent->iVal));
} else {
pCurrent->Type = eFloat;
sscanf(pBueffel, "%f", &(pCurrent->fVal));
}
}
/* pChar++;*/
if (isEnd(*pChar) == 2)
break;
} /* eof big while */
return pList;
}
/*--------------------------------------------------------------------------*/
void DeleteTokenList(TokenList * pToken)
{
TokenList *pCurrent;
TokenList *pTemp;
pCurrent = pToken;
while (pCurrent != NULL) {
pTemp = pCurrent->pNext;
if (pCurrent->text) {
free(pCurrent->text);
}
free(pCurrent);
pCurrent = pTemp;
}
}
/*--------------------------------------------------------------------------*/
TokenList *SplitArguments(int argc, char *argv[])
{
int i, ii;
TokenList *pList = NULL;
TokenList *pCurrent;
CharType eWhat;
/* loop through arguments */
for (i = 0; i < argc; i++) {
/* figure out what we have */
for (ii = 0; ii < strlen(argv[i]); ii++) {
eWhat = CheckSpecial(argv[i]);
/* skip whitespace */
if (eWhat != eSpace)
break;
}
/* Create Token */
if (pList == NULL) {
pList = CreateToken(NULL, pList);
pCurrent = pList;
} else {
pCurrent = CreateToken(NULL, pCurrent);
}
if (!pCurrent)
return NULL;
/* copy text always */
pCurrent->text = strdup(argv[i]);
/* numbers */
if (eWhat == eNum) {
/* float ? */
if (strchr(argv[i], '.') == NULL) {
pCurrent->Type = eInt;
/* sscanf(argv[i],"%d",&(pCurrent->iVal));
*/ pCurrent->iVal = atoi(argv[i]);
} else {
pCurrent->Type = eFloat;
sscanf(argv[i], "%f", &(pCurrent->fVal));
}
} else { /* all else is text */
pCurrent->Type = eText;
}
}
return pList;
}
/*--------------------------------------------------------------------------*/
int Text2Arg(char *pLine, int *argc, char **argv[])
{
TokenList *pList = NULL;
TokenList *pCurrent = NULL;
char **margv = NULL;
int margc = 0;
int i = 0;
/* split to a TokenList */
pList = SplitText(pLine);
if (!pList) {
return 0;
}
/* figure out how many args */
pCurrent = pList;
while (pCurrent) {
margc++;
pCurrent = pCurrent->pNext;
}
/* allocate memory */
margv = (char **) malloc((margc + 2) * sizeof(char *));
if (!margv) {
DeleteTokenList(pList);
return 0;
}
/* copy to argc, argv */
*argc = margc;
pCurrent = pList;
i = 0;
while (pCurrent) {
margv[i] = strdup(pCurrent->text);
i++;
pCurrent = pCurrent->pNext;
}
/* done, clean up etc */
margv[i] = NULL;
*argv = margv;
DeleteTokenList(pList);
return 1;
}
/*---------------------------------------------------------------------------*/
int Arg2Text(int argc, char *argv[], char *buf, int iBufLen)
{
int i, iBufCount = 0;
strcpy(buf, "\0");
if (argc < 1) {
return 1;
}
if (strlen(argv[0]) < iBufLen) {
strcpy(buf, argv[0]);
iBufCount += strlen(argv[0]);
} else {
return 0;
}
for (i = 1; i < argc; i++) {
iBufCount += strlen(argv[i]) + 1;
if (iBufCount >= iBufLen) {
return 0;
}
strcat(buf, " ");
strcat(buf, argv[i]);
}
return 1;
}
/*--------------------------------------------------------------------------*/
int GetShellLine(FILE * fd, char *Buffer, int iBufLen)
{
char *pChar = NULL;
while (fgets(Buffer, iBufLen - 1, fd) != NULL) {
if (Buffer[0] != '#') {
return 1;
}
}
return EOF;
}
/*---------------------------------------------------------------------*/
int isNumeric(char *pText)
{
int i, ii, iGood;
static char pNum[13] = { "1234567890.+-" };
for (i = 0; i < strlen(pText); i++) {
for (ii = 0; ii < 13; ii++) {
iGood = 0;
if (pText[i] == pNum[ii]) {
iGood = 1;
break;
}
}
if (!iGood) {
return 0;
}
}
return 1;
}
/*--------------------------------------------------------------------------*/
char *Arg2Tcl0(int argc, char *argv[], char *buffer, int buffersize,
char *prepend)
{
int l;
char *res, *args, *fr;
args = Tcl_Merge(argc, (const char **)argv);
if (args == NULL)
return NULL;
fr = args;
l = strlen(args);
if (prepend) {
l += strlen(prepend) + 1;
if (l >= buffersize) {
res = calloc(l, 1);
if (res == NULL)
return NULL;
} else {
res = buffer;
}
strcpy(res, prepend);
strcat(res, " ");
strcat(res, args);
} else {
if (l >= buffersize) {
res = strdup(args);
} else {
res = buffer;
strcpy(res, args);
}
}
Tcl_Free(fr);
return res;
}
/*--------------------------------------------------------------------------*/
char *Arg2Tcl(int argc, char *argv[], char *buffer, int buffersize)
{
return Arg2Tcl0(argc, argv, buffer, buffersize, NULL);
}
/*----------------------------------------------------------------------------*/
char *sicsNextNumber(char *pStart, char pNumber[80])
{
int charCount = 0;
pNumber[0] = '\0';
/* advance to first digit */
while (isspace(*pStart) && *pStart != '\0') {
pStart++;
}
if (*pStart == '\0') {
return NULL;
}
/* copy */
while (!isspace(*pStart) && *pStart != '\0' && charCount < 78) {
pNumber[charCount] = *pStart;
pStart++;
charCount++;
}
pNumber[charCount] = '\0';
return pStart;
}
/*============================================================================
Testprogram, can be activated by defining MAIN
*/
#ifdef MAIN
int main(int argc, char *argv[])
{
TokenList *pList = NULL;
TokenList *pCurrent;
pList = SplitText("Hallo 22 mal 0.8 Furz");
pCurrent = pList;
while (pCurrent) {
if (pCurrent->Type == eText) {
printf("TextToken = %s\n", pCurrent->text);
} else if (pCurrent->Type == eFloat) {
printf("FloatToken = %f\n", pCurrent->fVal);
} else if (pCurrent->Type == eInt) {
printf("IntToken = %d\n", pCurrent->iVal);
} else {
puts("ERRRRRRRRRROOOOOOOOOOOORRRRRRR!!!!!!!!");
}
pCurrent = pCurrent->pNext;
}
DeleteTokenList(pList);
}
#endif