Merge pull request #11 from esorton/bugfix/add-constexpr-keyword-to-arduino-ctags
[arduino-ctags.git] / args.c
bloba9336d2751979e9fe567af9b93742fff0e44b3cc
1 /*
2 * $Id: args.c 536 2007-06-02 06:09:00Z elliotth $
4 * Copyright (c) 1999-2002, Darren Hiebert
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License.
9 * This module contains functions for reading command line arguments.
13 * INCLUDE FILES
15 #include "general.h" /* must always come first */
17 #include <stdio.h>
18 #include <string.h>
19 #include <ctype.h>
21 #include "args.h"
22 #include "debug.h"
23 #include "routines.h"
26 * FUNCTION DEFINITIONS
29 static char *nextStringArg (const char** const next)
31 char* result = NULL;
32 const char* start;
34 Assert (*next != NULL);
35 for (start = *next ; isspace ((int) *start) ; ++start)
37 if (*start == '\0')
38 *next = start;
39 else
41 size_t length;
42 const char* end;
44 for (end = start ; *end != '\0' && ! isspace ((int) *end) ; ++end)
46 length = end - start;
47 Assert (length > 0);
48 result = xMalloc (length + 1, char);
49 strncpy (result, start, length);
50 result [length] = '\0';
51 *next = end;
53 return result;
56 static char* nextStringLine (const char** const next)
58 char* result = NULL;
59 size_t length;
60 const char* end;
62 Assert (*next != NULL);
63 for (end = *next ; *end != '\n' && *end != '\0' ; ++end)
65 length = end - *next;
66 if (length > 0)
68 result = xMalloc (length + 1, char);
69 strncpy (result, *next, length);
70 result [length] = '\0';
72 if (*end == '\n')
73 ++end;
74 else if (*end == '\r')
76 ++end;
77 if (*end == '\n')
78 ++end;
80 *next = end;
81 return result;
84 static char* nextString (const Arguments* const current, const char** const next)
86 char* result;
87 if (current->lineMode)
88 result = nextStringLine (next);
89 else
90 result = nextStringArg (next);
91 return result;
94 static char* nextFileArg (FILE* const fp)
96 char* result = NULL;
97 Assert (fp != NULL);
98 if (! feof (fp))
100 vString* vs = vStringNew ();
101 int c;
103 c = fgetc (fp);
104 while (isspace (c));
106 if (c != EOF)
110 vStringPut (vs, c);
111 c = fgetc (fp);
112 } while (c != EOF && ! isspace (c));
113 vStringTerminate (vs);
114 Assert (vStringLength (vs) > 0);
115 result = xMalloc (vStringLength (vs) + 1, char);
116 strcpy (result, vStringValue (vs));
118 vStringDelete (vs);
120 return result;
123 static char* nextFileLine (FILE* const fp)
125 char* result = NULL;
126 if (! feof (fp))
128 vString* vs = vStringNew ();
129 int c;
131 Assert (fp != NULL);
132 c = fgetc (fp);
133 while (c != EOF)
135 if (c != '\n' && c != '\r')
136 vStringPut (vs, c);
137 else if (vStringLength (vs) > 0)
138 break;
139 c = fgetc (fp);
141 if (c != EOF || vStringLength (vs) > 0)
143 if (c == '\r')
145 c = fgetc (fp);
146 if (c != '\n')
147 c = ungetc (c, fp);
149 vStringTerminate (vs);
150 vStringStripTrailing (vs);
151 result = xMalloc (vStringLength (vs) + 1, char);
152 strcpy (result, vStringValue (vs));
154 vStringDelete (vs);
156 return result;
159 static char* nextFileString (const Arguments* const current, FILE* const fp)
161 char* result;
162 if (current->lineMode)
163 result = nextFileLine (fp);
164 else
165 result = nextFileArg (fp);
166 return result;
169 extern Arguments* argNewFromString (const char* const string)
171 Arguments* result = xMalloc (1, Arguments);
172 memset (result, 0, sizeof (Arguments));
173 result->type = ARG_STRING;
174 result->u.stringArgs.string = string;
175 result->u.stringArgs.item = string;
176 result->u.stringArgs.next = string;
177 result->item = nextString (result, &result->u.stringArgs.next);
178 return result;
181 extern Arguments* argNewFromArgv (char* const* const argv)
183 Arguments* result = xMalloc (1, Arguments);
184 memset (result, 0, sizeof (Arguments));
185 result->type = ARG_ARGV;
186 result->u.argvArgs.argv = argv;
187 result->u.argvArgs.item = result->u.argvArgs.argv;
188 result->item = *result->u.argvArgs.item;
189 return result;
192 extern Arguments* argNewFromFile (FILE* const fp)
194 Arguments* result = xMalloc (1, Arguments);
195 memset (result, 0, sizeof (Arguments));
196 result->type = ARG_FILE;
197 result->u.fileArgs.fp = fp;
198 result->item = nextFileString (result, result->u.fileArgs.fp);
199 return result;
202 extern Arguments* argNewFromLineFile (FILE* const fp)
204 Arguments* result = xMalloc (1, Arguments);
205 memset (result, 0, sizeof (Arguments));
206 result->type = ARG_FILE;
207 result->lineMode = TRUE;
208 result->u.fileArgs.fp = fp;
209 result->item = nextFileString (result, result->u.fileArgs.fp);
210 return result;
213 extern char *argItem (const Arguments* const current)
215 Assert (current != NULL);
216 Assert (! argOff (current));
217 return current->item;
220 extern boolean argOff (const Arguments* const current)
222 Assert (current != NULL);
223 return (boolean) (current->item == NULL);
226 extern void argSetWordMode (Arguments* const current)
228 Assert (current != NULL);
229 current->lineMode = FALSE;
232 extern void argSetLineMode (Arguments* const current)
234 Assert (current != NULL);
235 current->lineMode = TRUE;
238 extern void argForth (Arguments* const current)
240 Assert (current != NULL);
241 Assert (! argOff (current));
242 switch (current->type)
244 case ARG_STRING:
245 if (current->item != NULL)
246 eFree (current->item);
247 current->u.stringArgs.item = current->u.stringArgs.next;
248 current->item = nextString (current, &current->u.stringArgs.next);
249 break;
250 case ARG_ARGV:
251 ++current->u.argvArgs.item;
252 current->item = *current->u.argvArgs.item;
253 break;
254 case ARG_FILE:
255 if (current->item != NULL)
256 eFree (current->item);
257 current->item = nextFileString (current, current->u.fileArgs.fp);
258 break;
259 default:
260 Assert ("Invalid argument type" == NULL);
261 break;
265 extern void argDelete (Arguments* const current)
267 Assert (current != NULL);
268 if (current->type == ARG_STRING && current->item != NULL)
269 eFree (current->item);
270 memset (current, 0, sizeof (Arguments));
271 eFree (current);
274 /* vi:set tabstop=4 shiftwidth=4: */