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