new version of muscle 3.8.31
[jabaws.git] / binaries / src / muscle / textfile.cpp
1 #include "muscle.h"\r
2 #include "textfile.h"\r
3 #include <errno.h>\r
4 \r
5 TextFile::TextFile(const char szFileName[], bool bWrite)\r
6         {\r
7         FILE *ptrFile = 0;\r
8         if (bWrite)\r
9                 {\r
10                 if (0 == strcmp(szFileName, "-"))\r
11                         ptrFile = stdout;\r
12                 else\r
13                         ptrFile = fopen(szFileName, "wb");\r
14                 }\r
15         else\r
16                 {\r
17                 if (0 == strcmp(szFileName, "-"))\r
18                         ptrFile = stdin;\r
19                 else\r
20                         ptrFile = fopen(szFileName, "rb");\r
21                 }\r
22         if (0 == ptrFile)\r
23                 Quit("Cannot open '%s' errno=%d\n", szFileName, errno);\r
24         Init(ptrFile, szFileName);\r
25         }\r
26 \r
27 void TextFile::Init(FILE *ptrFile, const char *ptrFileName)\r
28         {\r
29         m_ptrFile = ptrFile;\r
30         m_ptrName = strdup(ptrFileName);\r
31         m_uLineNr = 1;\r
32         m_uColNr = 0;\r
33         m_bLastCharWasEOL = true;\r
34         m_cPushedBack = -1;\r
35 #if     DEBUG\r
36         setbuf(m_ptrFile, 0);\r
37 #endif\r
38         }\r
39 \r
40 TextFile::TextFile(FILE *ptrFile, const char *ptrFileName)\r
41         {\r
42         Init(ptrFile, "-");\r
43         }\r
44 \r
45 TextFile::~TextFile()\r
46         {\r
47         if (m_ptrFile &&\r
48           m_ptrFile != stdin && m_ptrFile != stdout && m_ptrFile != stderr)\r
49                 fclose(m_ptrFile);\r
50         free(m_ptrName);\r
51         }\r
52 \r
53 // Get line from file.\r
54 // Return true if end-of-file, quit if line too long.\r
55 bool TextFile::GetLine(char szLine[], unsigned uBytes)\r
56         {\r
57         if (0 == uBytes)\r
58                 Quit("TextFile::GetLine, buffer zero size");\r
59 \r
60         \r
61         int FillVal = 0; // suppress warning from gcc that I don't understand\r
62         memset(szLine, FillVal, (size_t) uBytes);\r
63 \r
64         unsigned uBytesCopied = 0;\r
65 \r
66 // Loop until end of line or end of file.\r
67         for (;;)\r
68                 {\r
69                 char c;\r
70                 bool bEof = GetChar(c);\r
71                 if (bEof)\r
72                         return true;\r
73                 if ('\r' == c)\r
74                         continue;\r
75                 if ('\n' == c)\r
76                         return false;\r
77                 if (uBytesCopied < uBytes - 1)\r
78                         szLine[uBytesCopied++] = (char) c;\r
79                 else\r
80                         Quit("TextFile::GetLine: input buffer too small, line %u",\r
81                           m_uLineNr);\r
82                 }\r
83         }\r
84 \r
85 // As GetLine, but trim leading and trailing blanks; skip empty lines\r
86 bool TextFile::GetTrimLine(char szLine[], unsigned uBytes)\r
87         {\r
88         if (uBytes == 0)\r
89                 Quit("GetTrimLine");\r
90         for (;;)\r
91                 {\r
92                 bool bEOF = GetLine(szLine, uBytes);\r
93                 if (bEOF)\r
94                         return true;\r
95                 TrimBlanks(szLine);\r
96                 if (0 != szLine[0])\r
97                         break;\r
98                 }\r
99         return false;\r
100         }\r
101 \r
102 void TextFile::Rewind()\r
103         {\r
104         fseek(m_ptrFile, 0, SEEK_SET);\r
105         m_uLineNr = 1;\r
106         m_bLastCharWasEOL = true;\r
107         }\r
108 \r
109 void TextFile::PutChar(char c)\r
110         {\r
111         int i = fputc(c, m_ptrFile);\r
112         assert(i == c);\r
113         if ('\n' == c)\r
114                 {\r
115                 ++m_uLineNr;\r
116                 m_uColNr = 1;\r
117                 }\r
118         else\r
119                 ++m_uColNr;\r
120         }\r
121 \r
122 void TextFile::PutString(const char szLine[])\r
123         {\r
124         int iError = fputs(szLine, m_ptrFile);\r
125         assert(iError >= 0);\r
126         }\r
127 \r
128 void TextFile::PutFormat(const char szFormat[], ...)\r
129         {\r
130         char szStr[4096];\r
131         va_list ArgList;\r
132         va_start(ArgList, szFormat);\r
133         vsprintf(szStr, szFormat, ArgList);\r
134         PutString(szStr);\r
135         }\r
136 \r
137 void TextFile::GetLineX(char szLine[], unsigned uBytes)\r
138         {\r
139         if (uBytes == 0)\r
140                 Quit("GetLineX");\r
141         bool bEof = GetLine(szLine, uBytes);\r
142         if (bEof)\r
143                 Quit("end-of-file in GetLineX");\r
144         }\r
145 \r
146 bool TextFile::GetToken(char szToken[], unsigned uBytes, const char szCharTokens[])\r
147         {\r
148 // Skip leading white space\r
149         char c;\r
150         for (;;)\r
151                 {\r
152                 bool bEof = GetChar(c);\r
153                 if (bEof)\r
154                         return true;\r
155                 if (!isspace(c))\r
156                         break;\r
157                 }\r
158 \r
159 // Check for special case single-character tokens\r
160         if (0 != strchr(szCharTokens, c))\r
161                 {\r
162                 assert(uBytes >= 2);\r
163                 szToken[0] = c;\r
164                 szToken[1] = 0;\r
165                 return false;\r
166                 }\r
167 \r
168 // Loop until token terminated by white space, EOF or special\r
169         unsigned uBytesCopied = 0;\r
170         for (;;)\r
171                 {\r
172                 if (uBytesCopied < uBytes - 1)\r
173                         szToken[uBytesCopied++] = c;\r
174                 else\r
175                         Quit("TextFile::GetToken: input buffer too small, line %u",\r
176                           m_uLineNr);\r
177                 bool bEof = GetChar(c);\r
178                 if (bEof)\r
179                         {\r
180                         szToken[uBytesCopied] = 0;\r
181                         return true;\r
182                         }\r
183         // Check for special case single-character tokens\r
184                 if (0 != strchr(szCharTokens, c))\r
185                         {\r
186                         PushBack(c);\r
187                         assert(uBytesCopied > 0 && uBytesCopied < uBytes);\r
188                         szToken[uBytesCopied] = 0;\r
189                         return false;\r
190                         }\r
191                 if (isspace(c))\r
192                         {\r
193                         assert(uBytesCopied > 0 && uBytesCopied < uBytes);\r
194                         szToken[uBytesCopied] = 0;\r
195                         return false;\r
196                         }\r
197                 }\r
198         }\r
199 \r
200 void TextFile::GetTokenX(char szToken[], unsigned uBytes, const char szCharTokens[])\r
201         {\r
202         bool bEof = GetToken(szToken, uBytes, szCharTokens);\r
203         if (bEof)\r
204                 Quit("End-of-file in GetTokenX");\r
205         }\r
206 \r
207 void TextFile::Skip()\r
208         {\r
209         for (;;)\r
210                 {\r
211                 char c;\r
212                 bool bEof = GetChar(c);\r
213                 if (bEof || '\n' == c)\r
214                         return;\r
215                 assert(isspace(c));\r
216                 }\r
217         }\r
218 \r
219 #ifdef _WIN32\r
220 \r
221 TEXTFILEPOS TextFile::GetPos()\r
222         {\r
223         fpos_t p;\r
224         int i = fgetpos(m_ptrFile, &p);\r
225         assert(0 == i);\r
226         assert(p >= 0);\r
227         TEXTFILEPOS Pos;\r
228         Pos.uOffset = (unsigned) p;\r
229         Pos.uLineNr = m_uLineNr;\r
230         Pos.uColNr = m_uColNr;\r
231         return Pos;\r
232         }\r
233 \r
234 void TextFile::SetPos(TEXTFILEPOS Pos)\r
235         {\r
236         fpos_t p = (fpos_t) Pos.uOffset;\r
237         int i = fsetpos(m_ptrFile, &p);\r
238         assert(0 == i);\r
239         m_uLineNr = Pos.uLineNr;\r
240         m_uColNr = Pos.uColNr;\r
241         }\r
242 \r
243 #else\r
244 \r
245 TEXTFILEPOS TextFile::GetPos()\r
246         {\r
247         TEXTFILEPOS Pos;\r
248         Pos.uOffset = ftell(m_ptrFile);\r
249         Pos.uLineNr = m_uLineNr;\r
250         Pos.uColNr = m_uColNr;\r
251         return Pos;\r
252         }\r
253 \r
254 void TextFile::SetPos(TEXTFILEPOS Pos)\r
255         {\r
256         fseek(m_ptrFile, Pos.uOffset, SEEK_SET);\r
257         m_uLineNr = Pos.uLineNr;\r
258         m_uColNr = Pos.uColNr;\r
259         }\r
260 \r
261 #endif\r
262 \r
263 bool TextFile::GetChar(char &c)\r
264         {\r
265         if (-1 != m_cPushedBack)\r
266                 {\r
267                 c = (char) m_cPushedBack;\r
268                 m_cPushedBack = -1;\r
269                 return false;\r
270                 }\r
271 \r
272         int ic = fgetc(m_ptrFile);\r
273         if (ic < 0)\r
274                 {\r
275                 if (feof(m_ptrFile))\r
276                         {\r
277                 // Hack to fix up a non-empty text file that is missing\r
278                 // and end-of-line character in the last line.\r
279                         if (!m_bLastCharWasEOL && m_uLineNr > 0)\r
280                                 {\r
281                                 c = '\n';\r
282                                 m_bLastCharWasEOL = true;\r
283                                 return false;\r
284                                 }\r
285                         return true;\r
286                         }\r
287                 Quit("TextFile::GetChar, error %s", strerror(errno));\r
288                 }\r
289         c = (char) ic;\r
290         if ('\n' == c)\r
291                 {\r
292                 m_bLastCharWasEOL = true;\r
293                 ++m_uLineNr;\r
294                 m_uColNr = 1;\r
295                 }\r
296         else\r
297                 {\r
298                 m_bLastCharWasEOL = false;\r
299                 ++m_uColNr;\r
300                 }\r
301         return false;\r
302         }\r
303 \r
304 void TextFile::GetCharX(char &c)\r
305         {\r
306         bool bEof = GetChar(c);\r
307         if (bEof)\r
308                 Quit("End-of-file in GetCharX");\r
309         }\r
310 \r
311 void TextFile::GetNonblankChar(char &c)\r
312         {\r
313         do\r
314                 {\r
315                 bool bEof = GetChar(c);\r
316                 if (bEof)\r
317                         Quit("End-of-file in GetCharX");\r
318                 }\r
319         while (isspace(c));\r
320         }\r
321 \r
322 void TextFile::SkipLine()\r
323         {\r
324         if (m_bLastCharWasEOL)\r
325                 return;\r
326         for (;;)\r
327                 {\r
328                 char c;\r
329                 bool bEof = GetChar(c);\r
330                 if (bEof)\r
331                         Quit("End-of-file in SkipLine");\r
332                 if ('\n' == c)\r
333                         break;\r
334                 }\r
335         }\r
336 \r
337 void TextFile::SkipWhite()\r
338         {\r
339         bool bEof = SkipWhiteX();\r
340         if (bEof)\r
341                 Quit("End-of-file skipping white space");\r
342         }\r
343 \r
344 bool TextFile::SkipWhiteX()\r
345         {\r
346         for (;;)\r
347                 {\r
348                 char c;\r
349                 bool bEof = GetChar(c);\r
350                 if (bEof)\r
351                         return true;\r
352                 if (!isspace(c))\r
353                         {\r
354                         PushBack(c);\r
355                         break;\r
356                         }\r
357                 }\r
358         return false;\r
359         }\r