f58138b24a762676f7dc0b9c7c3484a5f0cdfa22
[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         memset(szLine, 0, uBytes);\r
61 \r
62         unsigned uBytesCopied = 0;\r
63 \r
64 // Loop until end of line or end of file.\r
65         for (;;)\r
66                 {\r
67                 char c;\r
68                 bool bEof = GetChar(c);\r
69                 if (bEof)\r
70                         return true;\r
71                 if ('\r' == c)\r
72                         continue;\r
73                 if ('\n' == c)\r
74                         return false;\r
75                 if (uBytesCopied < uBytes - 1)\r
76                         szLine[uBytesCopied++] = (char) c;\r
77                 else\r
78                         Quit("TextFile::GetLine: input buffer too small, line %u",\r
79                           m_uLineNr);\r
80                 }\r
81         }\r
82 \r
83 // As GetLine, but trim leading and trailing blanks; skip empty lines\r
84 bool TextFile::GetTrimLine(char szLine[], unsigned uBytes)\r
85         {\r
86         for (;;)\r
87                 {\r
88                 bool bEOF = GetLine(szLine, uBytes);\r
89                 if (bEOF)\r
90                         return true;\r
91                 TrimBlanks(szLine);\r
92                 if (0 != szLine[0])\r
93                         break;\r
94                 }\r
95         return false;\r
96         }\r
97 \r
98 void TextFile::Rewind()\r
99         {\r
100         fseek(m_ptrFile, 0, SEEK_SET);\r
101         m_uLineNr = 1;\r
102         m_bLastCharWasEOL = true;\r
103         }\r
104 \r
105 void TextFile::PutChar(char c)\r
106         {\r
107         int i = fputc(c, m_ptrFile);\r
108         assert(i == c);\r
109         if ('\n' == c)\r
110                 {\r
111                 ++m_uLineNr;\r
112                 m_uColNr = 1;\r
113                 }\r
114         else\r
115                 ++m_uColNr;\r
116         }\r
117 \r
118 void TextFile::PutString(const char szLine[])\r
119         {\r
120         int iError = fputs(szLine, m_ptrFile);\r
121         assert(iError >= 0);\r
122         }\r
123 \r
124 void TextFile::PutFormat(const char szFormat[], ...)\r
125         {\r
126         char szStr[4096];\r
127         va_list ArgList;\r
128         va_start(ArgList, szFormat);\r
129         vsprintf(szStr, szFormat, ArgList);\r
130         PutString(szStr);\r
131         }\r
132 \r
133 void TextFile::GetLineX(char szLine[], unsigned uBytes)\r
134         {\r
135         bool bEof = GetLine(szLine, uBytes);\r
136         if (bEof)\r
137                 Quit("end-of-file in GetLineX");\r
138         }\r
139 \r
140 bool TextFile::GetToken(char szToken[], unsigned uBytes, const char szCharTokens[])\r
141         {\r
142 // Skip leading white space\r
143         char c;\r
144         for (;;)\r
145                 {\r
146                 bool bEof = GetChar(c);\r
147                 if (bEof)\r
148                         return true;\r
149                 if (!isspace(c))\r
150                         break;\r
151                 }\r
152 \r
153 // Check for special case single-character tokens\r
154         if (0 != strchr(szCharTokens, c))\r
155                 {\r
156                 assert(uBytes >= 2);\r
157                 szToken[0] = c;\r
158                 szToken[1] = 0;\r
159                 return false;\r
160                 }\r
161 \r
162 // Loop until token terminated by white space, EOF or special\r
163         unsigned uBytesCopied = 0;\r
164         for (;;)\r
165                 {\r
166                 if (uBytesCopied < uBytes - 1)\r
167                         szToken[uBytesCopied++] = c;\r
168                 else\r
169                         Quit("TextFile::GetToken: input buffer too small, line %u",\r
170                           m_uLineNr);\r
171                 bool bEof = GetChar(c);\r
172                 if (bEof)\r
173                         {\r
174                         szToken[uBytesCopied] = 0;\r
175                         return true;\r
176                         }\r
177         // Check for special case single-character tokens\r
178                 if (0 != strchr(szCharTokens, c))\r
179                         {\r
180                         PushBack(c);\r
181                         assert(uBytesCopied > 0 && uBytesCopied < uBytes);\r
182                         szToken[uBytesCopied] = 0;\r
183                         return false;\r
184                         }\r
185                 if (isspace(c))\r
186                         {\r
187                         assert(uBytesCopied > 0 && uBytesCopied < uBytes);\r
188                         szToken[uBytesCopied] = 0;\r
189                         return false;\r
190                         }\r
191                 }\r
192         }\r
193 \r
194 void TextFile::GetTokenX(char szToken[], unsigned uBytes, const char szCharTokens[])\r
195         {\r
196         bool bEof = GetToken(szToken, uBytes, szCharTokens);\r
197         if (bEof)\r
198                 Quit("End-of-file in GetTokenX");\r
199         }\r
200 \r
201 void TextFile::Skip()\r
202         {\r
203         for (;;)\r
204                 {\r
205                 char c;\r
206                 bool bEof = GetChar(c);\r
207                 if (bEof || '\n' == c)\r
208                         return;\r
209                 assert(isspace(c));\r
210                 }\r
211         }\r
212 \r
213 #ifdef _WIN32\r
214 \r
215 TEXTFILEPOS TextFile::GetPos()\r
216         {\r
217         fpos_t p;\r
218         int i = fgetpos(m_ptrFile, &p);\r
219         assert(0 == i);\r
220         assert(p >= 0);\r
221         TEXTFILEPOS Pos;\r
222         Pos.uOffset = (unsigned) p;\r
223         Pos.uLineNr = m_uLineNr;\r
224         Pos.uColNr = m_uColNr;\r
225         return Pos;\r
226         }\r
227 \r
228 void TextFile::SetPos(TEXTFILEPOS Pos)\r
229         {\r
230         fpos_t p = (fpos_t) Pos.uOffset;\r
231         int i = fsetpos(m_ptrFile, &p);\r
232         assert(0 == i);\r
233         m_uLineNr = Pos.uLineNr;\r
234         m_uColNr = Pos.uColNr;\r
235         }\r
236 \r
237 #else\r
238 \r
239 TEXTFILEPOS TextFile::GetPos()\r
240         {\r
241         TEXTFILEPOS Pos;\r
242         Pos.uOffset = ftell(m_ptrFile);\r
243         Pos.uLineNr = m_uLineNr;\r
244         Pos.uColNr = m_uColNr;\r
245         return Pos;\r
246         }\r
247 \r
248 void TextFile::SetPos(TEXTFILEPOS Pos)\r
249         {\r
250         fseek(m_ptrFile, Pos.uOffset, SEEK_SET);\r
251         m_uLineNr = Pos.uLineNr;\r
252         m_uColNr = Pos.uColNr;\r
253         }\r
254 \r
255 #endif\r
256 \r
257 bool TextFile::GetChar(char &c)\r
258         {\r
259         if (-1 != m_cPushedBack)\r
260                 {\r
261                 c = (char) m_cPushedBack;\r
262                 m_cPushedBack = -1;\r
263                 return false;\r
264                 }\r
265 \r
266         int ic = fgetc(m_ptrFile);\r
267         if (ic < 0)\r
268                 {\r
269                 if (feof(m_ptrFile))\r
270                         {\r
271                 // Hack to fix up a non-empty text file that is missing\r
272                 // and end-of-line character in the last line.\r
273                         if (!m_bLastCharWasEOL && m_uLineNr > 0)\r
274                                 {\r
275                                 c = '\n';\r
276                                 m_bLastCharWasEOL = true;\r
277                                 return false;\r
278                                 }\r
279                         return true;\r
280                         }\r
281                 Quit("TextFile::GetChar, error %s", strerror(errno));\r
282                 }\r
283         c = (char) ic;\r
284         if ('\n' == c)\r
285                 {\r
286                 m_bLastCharWasEOL = true;\r
287                 ++m_uLineNr;\r
288                 m_uColNr = 1;\r
289                 }\r
290         else\r
291                 {\r
292                 m_bLastCharWasEOL = false;\r
293                 ++m_uColNr;\r
294                 }\r
295         return false;\r
296         }\r
297 \r
298 void TextFile::GetCharX(char &c)\r
299         {\r
300         bool bEof = GetChar(c);\r
301         if (bEof)\r
302                 Quit("End-of-file in GetCharX");\r
303         }\r
304 \r
305 void TextFile::GetNonblankChar(char &c)\r
306         {\r
307         do\r
308                 {\r
309                 bool bEof = GetChar(c);\r
310                 if (bEof)\r
311                         Quit("End-of-file in GetCharX");\r
312                 }\r
313         while (isspace(c));\r
314         }\r
315 \r
316 void TextFile::SkipLine()\r
317         {\r
318         if (m_bLastCharWasEOL)\r
319                 return;\r
320         for (;;)\r
321                 {\r
322                 char c;\r
323                 bool bEof = GetChar(c);\r
324                 if (bEof)\r
325                         Quit("End-of-file in SkipLine");\r
326                 if ('\n' == c)\r
327                         break;\r
328                 }\r
329         }\r
330 \r
331 void TextFile::SkipWhite()\r
332         {\r
333         bool bEof = SkipWhiteX();\r
334         if (bEof)\r
335                 Quit("End-of-file skipping white space");\r
336         }\r
337 \r
338 bool TextFile::SkipWhiteX()\r
339         {\r
340         for (;;)\r
341                 {\r
342                 char c;\r
343                 bool bEof = GetChar(c);\r
344                 if (bEof)\r
345                         return true;\r
346                 if (!isspace(c))\r
347                         {\r
348                         PushBack(c);\r
349                         break;\r
350                         }\r
351                 }\r
352         return false;\r
353         }\r