1 /*****************************************************************************/
2 /* */
3 /* (C) Copyright 1994 Alberto Pasquale */
4 /* Portions (C) Copyright 1999 Per Lundberg */
5 /* */
6 /* A L L R I G H T S R E S E R V E D */
7 /* */
8 /*****************************************************************************/
9 /* */
10 /* How to contact the author: Alberto Pasquale of 2:332/504@fidonet */
11 /* Viale Verdi 106 */
12 /* 41100 Modena */
13 /* Italy */
14 /* */
15 /*****************************************************************************/
16
17 /* ParseTxt.Cpp */
18
19 #include "apgenlib.hpp"
20 #include <stddef.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24
25 #define __min(a,b) (((a) < (b)) ? (a) : (b))
26 #define __max(a,b) (((a) > (b)) ? (a) : (b))
27
28
29
skipspace(const char * s)30 static const char *skipspace (const char *s)
31 {
32 while (1) {
33 switch (*s) {
34 case ' ':
35 case '\t':
36 case '\n':
37 break;
38 default:
39 return s;
40 }
41 s++;
42 }
43 }
44
45
46 #define OutQuotes 0x00 // for GetName state machine
47 #define InQuotes 0x01
48
49
GetName(const char * & src,char * dest,int maxlen,int action,BOOL * HasSpace)50 int GetName (const char *&src, char *dest, int maxlen, int action, BOOL *HasSpace)
51 {
52 int len = 0;
53 const char *s = src;
54 char *d = dest;
55 char l = 0;
56 int status = OutQuotes;
57 BOOL Space = FALSE;
58
59 s += strspn (s, " \t\n"); // skip leading space
60
61 if (dest) { // copy up to maxlen-1 chars, plus terminating NULL
62 while (len < (maxlen-1)) {
63 switch (*s) {
64
65 case '\t':
66 case ' ' :
67 if (status == OutQuotes)
68 goto gn_exit;
69 else { // InQuotes
70 *(d++) = ' '; // tab converted to blank
71 s++;
72 len++;
73 Space = TRUE;
74 }
75 break;
76
77 case '\"':
78 s++;
79 if (status == OutQuotes)
80 status = InQuotes;
81 else {
82 if (*s != '"') // closing quotes found
83 status = OutQuotes;
84 else { // this is a quoted quotes char
85 *(d++) = *(s++);
86 len ++;
87 }
88 }
89 break;
90
91 case '\n':
92 case '\0':
93 goto gn_exit;
94
95 default :
96 *(d++) = *(s++);
97 len ++;
98 }
99 }
100 }
101
102 while (1) { // skip rest of src
103 switch (*s) {
104 case '\t':
105 case ' ' :
106 if (status == OutQuotes)
107 goto gn_exit;
108 else { // InQuotes
109 l = *(s++);
110 if (!dest) {
111 len++;
112 Space = TRUE;
113 }
114 }
115 break;
116
117 case '\"':
118 s++;
119 if (status == OutQuotes)
120 status = InQuotes;
121 else {
122 if (*s != '"') // closing quotes found
123 status = OutQuotes;
124 else { // this is a quoted quotes char
125 l = *(s++);
126 if (!dest)
127 len ++;
128 }
129 }
130 break;
131
132 case '\n':
133 case '\0':
134 goto gn_exit;
135
136 default :
137 l = *(s++);
138 if (!dest)
139 len ++;
140 }
141 }
142
143 gn_exit:
144
145 if (HasSpace)
146 *HasSpace = Space;
147
148 if (dest) {
149 if (!(action & GN_SrcFix))
150 src = skipspace (s); // skip to next non-space character
151
152 if (action & GN_BSlash) {
153 if ((len > 0) && (*(d-1) != DIRSEP)) {
154 if (len == maxlen - 1) {
155 d--;
156 len--;
157 if (*(d-1) != DIRSEP) {
158 *(d++) = DIRSEP;
159 len++;
160 }
161 } else {
162 *(d++) = DIRSEP;
163 len++;
164 }
165 }
166 }
167
168 if (action & GN_UBSlash) {
169 if ((len > 0) && (*(d-1) == DIRSEP))
170 d--;
171 len--;
172 }
173
174 *d = '\0'; // terminate destination
175
176 if (action & GN_MkDir)
177 if (mkdirpath (dest) == -1)
178 return -1;
179 } else { // dest == NULL
180 if (action & GN_BSlash)
181 if ((len > 0) && (l != DIRSEP))
182 len++;
183
184 if (action & GN_UBSlash)
185 if ((len > 0) && (l == DIRSEP))
186 len--;
187 }
188
189 return len;
190 }
191
192
GetStatName(const char * & src,int action,int * len,BOOL * HasSpace)193 char *GetStatName (const char *&src, int action, int *len, BOOL *HasSpace)
194 {
195 static char namebuf[PATH_MAX];
196 int namelen;
197
198 namelen = GetName (src, namebuf, PATH_MAX, action, HasSpace);
199 if (len)
200 *len = namelen;
201 if (namelen == -1) // error
202 return NULL;
203 if ((namelen == 0) && !(action & GN_Empty))
204 return NULL;
205 return namebuf;
206 }
207
208
GetAllocName(const char * & src,int action,int * len,BOOL * HasSpace)209 char *GetAllocName (const char *&src, int action, int *len, BOOL *HasSpace)
210 {
211 int namelen;
212 char *dest;
213
214 namelen = GetName (src, NULL, 0, action, HasSpace);
215 if (len)
216 *len = namelen;
217 if ((namelen == 0) && !(action & GN_Empty))
218 return NULL;
219 dest = new char[namelen+1];
220 if (GetName (src, dest, namelen+1, action) == -1) { // error
221 delete[] dest;
222 return NULL;
223 }
224 return dest;
225 }
226
227
strbslash(char * dir)228 void strbslash (char *dir)
229 {
230 int l;
231
232 l=strlen(dir);
233 if ((l > 0) && (dir[l-1]!=DIRSEP)) {
234 dir[l]=DIRSEP;
235 dir[l+1]=0;
236 }
237 }
238
239
strubslash(char * dir)240 void strubslash (char *dir)
241 {
242 int l = strlen (dir);
243 if ((l > 0) && (dir[l-1] == DIRSEP))
244 dir[l-1]='\0';
245 }
246
247
GetLn(const char * src,char * dest,int maxlen)248 int GetLn (const char *src, char *dest, int maxlen)
249 {
250 src += strspn (src, " \t\n"); // skip leading space
251
252 if (*src == '\"') // get string
253 return GetName (src, dest, maxlen);
254
255 // get whole line
256
257 #ifndef __QNXNTO__
258 char *e = strchr (src, 0); // points to terminating NULL
259 #else
260 char *e = strchr ((char *)src, 0); // points to terminating NULL
261 #endif // __QNXNTO__
262
263 while (e > src) { // skip trailing space
264 if ((*(e-1) == '\n') || (*(e-1) == '\t') || (*(e-1) == ' '))
265 e--;
266 else
267 break;
268 }
269
270 int len = __min (maxlen-1, (int) (e - src));
271
272 if (dest) {
273 for (int i = 0; i < len; i++)
274 *(dest++) = *(src++);
275
276 *dest = '\0'; // NULL termination
277 }
278
279 return len;
280 }
281
282
GetStatLn(const char * src,int action,int * len)283 char *GetStatLn (const char *src, int action, int *len)
284 {
285 static char linebuf[PATH_MAX];
286 int linelen;
287
288 linelen = GetLn (src, linebuf, PATH_MAX);
289 if (len)
290 *len = linelen;
291 if ((linelen == 0) && !(action & GL_Empty))
292 return NULL;
293 return linebuf;
294 }
295
296
GetAllocLn(const char * src,int action,int * len)297 char *GetAllocLn (const char *src, int action, int *len)
298 {
299 int linelen;
300 char *dest;
301
302 linelen = GetLn (src);
303 if (len)
304 *len = linelen;
305 if ((linelen == 0) && !(action & GL_Empty))
306 return NULL;
307 dest = new char[linelen+1];
308 GetLn (src, dest);
309 return dest;
310 }
311