Update all parsers and related files to ctags p6.1.20240421.0
[geany-mirror.git] / ctags / main / args.c
blob6bd66464fe6454097dd3d8a8fcb16627cc25094f
1 /*
2 * Copyright (c) 1999-2002, Darren Hiebert
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License version 2 or (at your option) any later version.
7 * This module contains functions for reading command line arguments.
8 */
11 * INCLUDE FILES
13 #include "general.h" /* must always come first */
15 #include <stdio.h>
16 #include <string.h>
17 #include <ctype.h>
19 #include "args_p.h"
20 #include "debug.h"
21 #include "routines.h"
22 #include "vstring.h"
25 * FUNCTION DEFINITIONS
28 static char *nextStringArg (const char** const next)
30 char* result = NULL;
31 const char* start;
33 Assert (*next != NULL);
34 for (start = *next ; isspace ((unsigned char) *start) ; ++start)
36 if (*start == '\0')
37 *next = start;
38 else
40 size_t length;
41 const char* end;
43 for (end = start; *end != '\0' && ! isspace ((unsigned char) *end); ++end)
45 length = end - start;
46 Assert (length > 0);
47 result = xMalloc (length + 1, char);
48 strncpy (result, start, length);
49 result [length] = '\0';
50 *next = end;
52 return result;
55 static char* nextStringLine (const char** const next)
57 char* result = NULL;
58 size_t length;
59 const char* end;
61 Assert (*next != NULL);
62 for (end = *next ; *end != '\n' && *end != '\0' ; ++end)
64 length = end - *next;
65 if (length > 0)
67 result = xMalloc (length + 1, char);
68 strncpy (result, *next, length);
69 result [length] = '\0';
71 if (*end == '\n')
72 ++end;
73 else if (*end == '\r')
75 ++end;
76 if (*end == '\n')
77 ++end;
79 *next = end;
80 return result;
83 static char* nextString (const Arguments* const current, const char** const next)
85 char* result;
86 if (current->lineMode)
87 result = nextStringLine (next);
88 else
89 result = nextStringArg (next);
90 return result;
93 static char* nextFileArg (FILE* const fp)
95 char* result = NULL;
96 Assert (fp != NULL);
97 if (! feof (fp))
99 vString* vs = vStringNew ();
100 int c;
102 c = fgetc (fp);
103 while (isspace (c));
105 if (c != EOF)
109 vStringPut (vs, c);
110 c = fgetc (fp);
111 } while (c != EOF && ! isspace (c));
112 Assert (vStringLength (vs) > 0);
113 result = xMalloc (vStringLength (vs) + 1, char);
114 strcpy (result, vStringValue (vs));
116 vStringDelete (vs);
118 return result;
121 static char* nextFileLine (FILE* const fp)
123 char* result = NULL;
124 Assert (fp != NULL);
125 if (! feof (fp))
127 vString* vs = vStringNew ();
128 int c;
130 c = fgetc (fp);
131 while (c != EOF)
133 if (c != '\n' && c != '\r')
134 vStringPut (vs, c);
135 else if (vStringLength (vs) > 0)
136 break;
137 c = fgetc (fp);
139 if (c != EOF || vStringLength (vs) > 0)
141 if (c == '\r')
143 c = fgetc (fp);
144 if (c != '\n')
145 c = ungetc (c, fp);
147 vStringStripTrailing (vs);
148 vStringStripLeading (vs);
149 result = xMalloc (vStringLength (vs) + 1, char);
150 strcpy (result, vStringValue (vs));
152 vStringDelete (vs);
154 return result;
157 static bool isCommentLine (char* line)
159 while (isspace((unsigned char) *line))
160 ++line;
161 return (*line == '#');
164 static bool isOptscriptLine (char *line)
166 size_t len = strlen (line);
167 if (len < 2)
168 return false;
169 if (line [len - 1] == '{' && line [len - 2] == '{')
170 return true;
171 return false;
174 static char* nextOptscriptLines (FILE* const fp, char *line)
176 vString *vstr = vStringNewInit (line);
177 vStringPut (vstr, '\n');
178 eFree (line);
180 /* \n}}, \n=>1, }=>2, }=>3 */
181 int endMarkers = 0;
182 int c;
183 while (true)
185 c = fgetc (fp);
186 if (c == EOF)
187 break;
189 if (c == '\r' || c == '\n')
191 if (c == '\r')
193 c = fgetc (fp);
194 if (c != '\n')
196 ungetc(c, fp);
197 c = '\n';
200 if (c == '\n')
202 vStringPut (vstr, c);
203 if (endMarkers != 1)
204 endMarkers = 1;
207 else if (c == '}')
209 vStringPut (vstr, c);
210 if (endMarkers == 1 || endMarkers == 2)
211 endMarkers++;
212 if (endMarkers == 3)
213 break;
215 else
217 endMarkers = 0;
218 vStringPut (vstr, c);
222 if (c == EOF)
224 switch (endMarkers)
226 case 0:
227 vStringPut (vstr, '\n');
228 /* Fall through */
229 case 1:
230 vStringPut (vstr, '}');
231 /* Fall through */
232 case 2:
233 vStringPut (vstr, '}');
234 default:
235 break;
239 c = fgetc (fp);
240 while (c != EOF)
242 if (c == '\n')
243 break;
244 if (c == '\r')
246 c = fgetc (fp);
247 if (c == '\n')
248 break;
249 ungetc (c, fp);
251 c = fgetc (fp);
253 return vStringDeleteUnwrap (vstr);
256 static char* nextFileLineSkippingComments (FILE* const fp)
258 char* result;
259 bool comment;
260 bool optscript;
264 result = nextFileLine (fp);
265 comment = false;
266 optscript = false;
267 if (result)
269 comment = isCommentLine (result);
270 optscript = isOptscriptLine (result);
272 if (comment)
273 eFree (result);
274 else if (optscript)
275 result = nextOptscriptLines (fp, result);
276 } while (comment);
278 return result;
281 static char* nextFileString (const Arguments* const current, FILE* const fp)
283 char* result;
284 if (current->lineMode)
285 result = nextFileLineSkippingComments (fp);
286 else
287 result = nextFileArg (fp);
288 return result;
291 extern Arguments* argNewFromString (const char* const string)
293 Arguments* result = xMalloc (1, Arguments);
294 memset (result, 0, sizeof (Arguments));
295 result->type = ARG_STRING;
296 result->u.stringArgs.next = string;
297 result->item = nextString (result, &result->u.stringArgs.next);
298 return result;
301 extern Arguments* argNewFromArgv (char* const* const argv)
303 Arguments* result = xMalloc (1, Arguments);
304 memset (result, 0, sizeof (Arguments));
305 result->type = ARG_ARGV;
306 result->u.argvArgs.argv = argv;
307 result->u.argvArgs.item = result->u.argvArgs.argv;
308 result->item = *result->u.argvArgs.item;
309 return result;
312 extern Arguments* argNewFromFile (FILE* const fp)
314 Arguments* result = xMalloc (1, Arguments);
315 memset (result, 0, sizeof (Arguments));
316 result->type = ARG_FILE;
317 result->u.fileArgs.fp = fp;
318 result->item = nextFileString (result, result->u.fileArgs.fp);
319 return result;
322 extern Arguments* argNewFromLineFile (FILE* const fp)
324 Arguments* result = xMalloc (1, Arguments);
325 memset (result, 0, sizeof (Arguments));
326 result->type = ARG_FILE;
327 result->lineMode = true;
328 result->u.fileArgs.fp = fp;
329 result->item = nextFileString (result, result->u.fileArgs.fp);
330 return result;
333 extern char *argItem (const Arguments* const current)
335 Assert (current != NULL);
336 Assert (! argOff (current));
337 return current->item;
340 extern bool argOff (const Arguments* const current)
342 Assert (current != NULL);
343 return (bool) (current->item == NULL);
346 extern void argSetWordMode (Arguments* const current)
348 Assert (current != NULL);
349 current->lineMode = false;
352 extern void argSetLineMode (Arguments* const current)
354 Assert (current != NULL);
355 current->lineMode = true;
358 extern void argForth (Arguments* const current)
360 Assert (current != NULL);
361 Assert (! argOff (current));
362 switch (current->type)
364 case ARG_STRING:
365 if (current->item != NULL)
366 eFree (current->item);
367 current->item = nextString (current, &current->u.stringArgs.next);
368 break;
369 case ARG_ARGV:
370 ++current->u.argvArgs.item;
371 current->item = *current->u.argvArgs.item;
372 break;
373 case ARG_FILE:
374 if (current->item != NULL)
375 eFree (current->item);
376 current->item = nextFileString (current, current->u.fileArgs.fp);
377 break;
378 default:
379 Assert ("Invalid argument type" == NULL);
380 break;
384 extern void argDelete (Arguments* const current)
386 Assert (current != NULL);
387 if ((current->type == ARG_STRING
388 || current->type == ARG_FILE) && current->item != NULL)
389 eFree (current->item);
390 memset (current, 0, sizeof (Arguments));
391 eFree (current);