+++ /dev/null
-#include "muscle.h"\r
-#include "textfile.h"\r
-#include <errno.h>\r
-\r
-TextFile::TextFile(const char szFileName[], bool bWrite)\r
- {\r
- FILE *ptrFile = 0;\r
- if (bWrite)\r
- {\r
- if (0 == strcmp(szFileName, "-"))\r
- ptrFile = stdout;\r
- else\r
- ptrFile = fopen(szFileName, "wb");\r
- }\r
- else\r
- {\r
- if (0 == strcmp(szFileName, "-"))\r
- ptrFile = stdin;\r
- else\r
- ptrFile = fopen(szFileName, "rb");\r
- }\r
- if (0 == ptrFile)\r
- Quit("Cannot open '%s' errno=%d\n", szFileName, errno);\r
- Init(ptrFile, szFileName);\r
- }\r
-\r
-void TextFile::Init(FILE *ptrFile, const char *ptrFileName)\r
- {\r
- m_ptrFile = ptrFile;\r
- m_ptrName = strdup(ptrFileName);\r
- m_uLineNr = 1;\r
- m_uColNr = 0;\r
- m_bLastCharWasEOL = true;\r
- m_cPushedBack = -1;\r
-#if DEBUG\r
- setbuf(m_ptrFile, 0);\r
-#endif\r
- }\r
-\r
-TextFile::TextFile(FILE *ptrFile, const char *ptrFileName)\r
- {\r
- Init(ptrFile, "-");\r
- }\r
-\r
-TextFile::~TextFile()\r
- {\r
- if (m_ptrFile &&\r
- m_ptrFile != stdin && m_ptrFile != stdout && m_ptrFile != stderr)\r
- fclose(m_ptrFile);\r
- free(m_ptrName);\r
- }\r
-\r
-// Get line from file.\r
-// Return true if end-of-file, quit if line too long.\r
-bool TextFile::GetLine(char szLine[], unsigned uBytes)\r
- {\r
- if (0 == uBytes)\r
- Quit("TextFile::GetLine, buffer zero size");\r
-\r
- \r
- int FillVal = 0; // suppress warning from gcc that I don't understand\r
- memset(szLine, FillVal, (size_t) uBytes);\r
-\r
- unsigned uBytesCopied = 0;\r
-\r
-// Loop until end of line or end of file.\r
- for (;;)\r
- {\r
- char c;\r
- bool bEof = GetChar(c);\r
- if (bEof)\r
- return true;\r
- if ('\r' == c)\r
- continue;\r
- if ('\n' == c)\r
- return false;\r
- if (uBytesCopied < uBytes - 1)\r
- szLine[uBytesCopied++] = (char) c;\r
- else\r
- Quit("TextFile::GetLine: input buffer too small, line %u",\r
- m_uLineNr);\r
- }\r
- }\r
-\r
-// As GetLine, but trim leading and trailing blanks; skip empty lines\r
-bool TextFile::GetTrimLine(char szLine[], unsigned uBytes)\r
- {\r
- if (uBytes == 0)\r
- Quit("GetTrimLine");\r
- for (;;)\r
- {\r
- bool bEOF = GetLine(szLine, uBytes);\r
- if (bEOF)\r
- return true;\r
- TrimBlanks(szLine);\r
- if (0 != szLine[0])\r
- break;\r
- }\r
- return false;\r
- }\r
-\r
-void TextFile::Rewind()\r
- {\r
- fseek(m_ptrFile, 0, SEEK_SET);\r
- m_uLineNr = 1;\r
- m_bLastCharWasEOL = true;\r
- }\r
-\r
-void TextFile::PutChar(char c)\r
- {\r
- int i = fputc(c, m_ptrFile);\r
- assert(i == c);\r
- if ('\n' == c)\r
- {\r
- ++m_uLineNr;\r
- m_uColNr = 1;\r
- }\r
- else\r
- ++m_uColNr;\r
- }\r
-\r
-void TextFile::PutString(const char szLine[])\r
- {\r
- int iError = fputs(szLine, m_ptrFile);\r
- assert(iError >= 0);\r
- }\r
-\r
-void TextFile::PutFormat(const char szFormat[], ...)\r
- {\r
- char szStr[4096];\r
- va_list ArgList;\r
- va_start(ArgList, szFormat);\r
- vsprintf(szStr, szFormat, ArgList);\r
- PutString(szStr);\r
- }\r
-\r
-void TextFile::GetLineX(char szLine[], unsigned uBytes)\r
- {\r
- if (uBytes == 0)\r
- Quit("GetLineX");\r
- bool bEof = GetLine(szLine, uBytes);\r
- if (bEof)\r
- Quit("end-of-file in GetLineX");\r
- }\r
-\r
-bool TextFile::GetToken(char szToken[], unsigned uBytes, const char szCharTokens[])\r
- {\r
-// Skip leading white space\r
- char c;\r
- for (;;)\r
- {\r
- bool bEof = GetChar(c);\r
- if (bEof)\r
- return true;\r
- if (!isspace(c))\r
- break;\r
- }\r
-\r
-// Check for special case single-character tokens\r
- if (0 != strchr(szCharTokens, c))\r
- {\r
- assert(uBytes >= 2);\r
- szToken[0] = c;\r
- szToken[1] = 0;\r
- return false;\r
- }\r
-\r
-// Loop until token terminated by white space, EOF or special\r
- unsigned uBytesCopied = 0;\r
- for (;;)\r
- {\r
- if (uBytesCopied < uBytes - 1)\r
- szToken[uBytesCopied++] = c;\r
- else\r
- Quit("TextFile::GetToken: input buffer too small, line %u",\r
- m_uLineNr);\r
- bool bEof = GetChar(c);\r
- if (bEof)\r
- {\r
- szToken[uBytesCopied] = 0;\r
- return true;\r
- }\r
- // Check for special case single-character tokens\r
- if (0 != strchr(szCharTokens, c))\r
- {\r
- PushBack(c);\r
- assert(uBytesCopied > 0 && uBytesCopied < uBytes);\r
- szToken[uBytesCopied] = 0;\r
- return false;\r
- }\r
- if (isspace(c))\r
- {\r
- assert(uBytesCopied > 0 && uBytesCopied < uBytes);\r
- szToken[uBytesCopied] = 0;\r
- return false;\r
- }\r
- }\r
- }\r
-\r
-void TextFile::GetTokenX(char szToken[], unsigned uBytes, const char szCharTokens[])\r
- {\r
- bool bEof = GetToken(szToken, uBytes, szCharTokens);\r
- if (bEof)\r
- Quit("End-of-file in GetTokenX");\r
- }\r
-\r
-void TextFile::Skip()\r
- {\r
- for (;;)\r
- {\r
- char c;\r
- bool bEof = GetChar(c);\r
- if (bEof || '\n' == c)\r
- return;\r
- assert(isspace(c));\r
- }\r
- }\r
-\r
-#ifdef _WIN32\r
-\r
-TEXTFILEPOS TextFile::GetPos()\r
- {\r
- fpos_t p;\r
- int i = fgetpos(m_ptrFile, &p);\r
- assert(0 == i);\r
- assert(p >= 0);\r
- TEXTFILEPOS Pos;\r
- Pos.uOffset = (unsigned) p;\r
- Pos.uLineNr = m_uLineNr;\r
- Pos.uColNr = m_uColNr;\r
- return Pos;\r
- }\r
-\r
-void TextFile::SetPos(TEXTFILEPOS Pos)\r
- {\r
- fpos_t p = (fpos_t) Pos.uOffset;\r
- int i = fsetpos(m_ptrFile, &p);\r
- assert(0 == i);\r
- m_uLineNr = Pos.uLineNr;\r
- m_uColNr = Pos.uColNr;\r
- }\r
-\r
-#else\r
-\r
-TEXTFILEPOS TextFile::GetPos()\r
- {\r
- TEXTFILEPOS Pos;\r
- Pos.uOffset = ftell(m_ptrFile);\r
- Pos.uLineNr = m_uLineNr;\r
- Pos.uColNr = m_uColNr;\r
- return Pos;\r
- }\r
-\r
-void TextFile::SetPos(TEXTFILEPOS Pos)\r
- {\r
- fseek(m_ptrFile, Pos.uOffset, SEEK_SET);\r
- m_uLineNr = Pos.uLineNr;\r
- m_uColNr = Pos.uColNr;\r
- }\r
-\r
-#endif\r
-\r
-bool TextFile::GetChar(char &c)\r
- {\r
- if (-1 != m_cPushedBack)\r
- {\r
- c = (char) m_cPushedBack;\r
- m_cPushedBack = -1;\r
- return false;\r
- }\r
-\r
- int ic = fgetc(m_ptrFile);\r
- if (ic < 0)\r
- {\r
- if (feof(m_ptrFile))\r
- {\r
- // Hack to fix up a non-empty text file that is missing\r
- // and end-of-line character in the last line.\r
- if (!m_bLastCharWasEOL && m_uLineNr > 0)\r
- {\r
- c = '\n';\r
- m_bLastCharWasEOL = true;\r
- return false;\r
- }\r
- return true;\r
- }\r
- Quit("TextFile::GetChar, error %s", strerror(errno));\r
- }\r
- c = (char) ic;\r
- if ('\n' == c)\r
- {\r
- m_bLastCharWasEOL = true;\r
- ++m_uLineNr;\r
- m_uColNr = 1;\r
- }\r
- else\r
- {\r
- m_bLastCharWasEOL = false;\r
- ++m_uColNr;\r
- }\r
- return false;\r
- }\r
-\r
-void TextFile::GetCharX(char &c)\r
- {\r
- bool bEof = GetChar(c);\r
- if (bEof)\r
- Quit("End-of-file in GetCharX");\r
- }\r
-\r
-void TextFile::GetNonblankChar(char &c)\r
- {\r
- do\r
- {\r
- bool bEof = GetChar(c);\r
- if (bEof)\r
- Quit("End-of-file in GetCharX");\r
- }\r
- while (isspace(c));\r
- }\r
-\r
-void TextFile::SkipLine()\r
- {\r
- if (m_bLastCharWasEOL)\r
- return;\r
- for (;;)\r
- {\r
- char c;\r
- bool bEof = GetChar(c);\r
- if (bEof)\r
- Quit("End-of-file in SkipLine");\r
- if ('\n' == c)\r
- break;\r
- }\r
- }\r
-\r
-void TextFile::SkipWhite()\r
- {\r
- bool bEof = SkipWhiteX();\r
- if (bEof)\r
- Quit("End-of-file skipping white space");\r
- }\r
-\r
-bool TextFile::SkipWhiteX()\r
- {\r
- for (;;)\r
- {\r
- char c;\r
- bool bEof = GetChar(c);\r
- if (bEof)\r
- return true;\r
- if (!isspace(c))\r
- {\r
- PushBack(c);\r
- break;\r
- }\r
- }\r
- return false;\r
- }\r