/*--------------------------------------------------------------------------- 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 #include #include #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