472 lines
10 KiB
C
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
|