1 /*
2 * $Id: args.c 536 2007-06-02 06:09:00Z elliotth $
3 *
4 * Copyright (c) 1999-2002, Darren Hiebert
5 *
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License.
8 *
9 * This module contains functions for reading command line arguments.
10 */
11
12 /*
13 * INCLUDE FILES
14 */
15 #include "general.h" /* must always come first */
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <ctype.h>
20
21 #include "args.h"
22 #include "debug.h"
23 #include "routines.h"
24
25 /*
26 * FUNCTION DEFINITIONS
27 */
28
nextStringArg(const char ** const next)29 static char *nextStringArg (const char** const next)
30 {
31 char* result = NULL;
32 const char* start;
33
34 Assert (*next != NULL);
35 for (start = *next ; isspace ((int) *start) ; ++start)
36 ;
37 if (*start == '\0')
38 *next = start;
39 else
40 {
41 size_t length;
42 const char* end;
43
44 for (end = start ; *end != '\0' && ! isspace ((int) *end) ; ++end)
45 ;
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;
52 }
53 return result;
54 }
55
nextStringLine(const char ** const next)56 static char* nextStringLine (const char** const next)
57 {
58 char* result = NULL;
59 size_t length;
60 const char* end;
61
62 Assert (*next != NULL);
63 for (end = *next ; *end != '\n' && *end != '\0' ; ++end)
64 ;
65 length = end - *next;
66 if (length > 0)
67 {
68 result = xMalloc (length + 1, char);
69 strncpy (result, *next, length);
70 result [length] = '\0';
71 }
72 if (*end == '\n')
73 ++end;
74 else if (*end == '\r')
75 {
76 ++end;
77 if (*end == '\n')
78 ++end;
79 }
80 *next = end;
81 return result;
82 }
83
nextString(const Arguments * const current,const char ** const next)84 static char* nextString (const Arguments* const current, const char** const next)
85 {
86 char* result;
87 if (current->lineMode)
88 result = nextStringLine (next);
89 else
90 result = nextStringArg (next);
91 return result;
92 }
93
nextFileArg(FILE * const fp)94 static char* nextFileArg (FILE* const fp)
95 {
96 char* result = NULL;
97 Assert (fp != NULL);
98 if (! feof (fp))
99 {
100 vString* vs = vStringNew ();
101 int c;
102 do
103 c = fgetc (fp);
104 while (isspace (c));
105
106 if (c != EOF)
107 {
108 do
109 {
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));
117 }
118 vStringDelete (vs);
119 }
120 return result;
121 }
122
nextFileLine(FILE * const fp)123 static char* nextFileLine (FILE* const fp)
124 {
125 char* result = NULL;
126 if (! feof (fp))
127 {
128 vString* vs = vStringNew ();
129 int c;
130
131 Assert (fp != NULL);
132 c = fgetc (fp);
133 while (c != EOF)
134 {
135 if (c != '\n' && c != '\r')
136 vStringPut (vs, c);
137 else if (vStringLength (vs) > 0)
138 break;
139 c = fgetc (fp);
140 }
141 if (c != EOF || vStringLength (vs) > 0)
142 {
143 if (c == '\r')
144 {
145 c = fgetc (fp);
146 if (c != '\n')
147 c = ungetc (c, fp);
148 }
149 vStringTerminate (vs);
150 vStringStripTrailing (vs);
151 result = xMalloc (vStringLength (vs) + 1, char);
152 strcpy (result, vStringValue (vs));
153 }
154 vStringDelete (vs);
155 }
156 return result;
157 }
158
nextFileString(const Arguments * const current,FILE * const fp)159 static char* nextFileString (const Arguments* const current, FILE* const fp)
160 {
161 char* result;
162 if (current->lineMode)
163 result = nextFileLine (fp);
164 else
165 result = nextFileArg (fp);
166 return result;
167 }
168
argNewFromString(const char * const string)169 extern Arguments* argNewFromString (const char* const string)
170 {
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;
179 }
180
argNewFromArgv(char * const * const argv)181 extern Arguments* argNewFromArgv (char* const* const argv)
182 {
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;
190 }
191
argNewFromFile(FILE * const fp)192 extern Arguments* argNewFromFile (FILE* const fp)
193 {
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;
200 }
201
argNewFromLineFile(FILE * const fp)202 extern Arguments* argNewFromLineFile (FILE* const fp)
203 {
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;
211 }
212
argItem(const Arguments * const current)213 extern char *argItem (const Arguments* const current)
214 {
215 Assert (current != NULL);
216 Assert (! argOff (current));
217 return current->item;
218 }
219
argOff(const Arguments * const current)220 extern boolean argOff (const Arguments* const current)
221 {
222 Assert (current != NULL);
223 return (boolean) (current->item == NULL);
224 }
225
argSetWordMode(Arguments * const current)226 extern void argSetWordMode (Arguments* const current)
227 {
228 Assert (current != NULL);
229 current->lineMode = FALSE;
230 }
231
argSetLineMode(Arguments * const current)232 extern void argSetLineMode (Arguments* const current)
233 {
234 Assert (current != NULL);
235 current->lineMode = TRUE;
236 }
237
argForth(Arguments * const current)238 extern void argForth (Arguments* const current)
239 {
240 Assert (current != NULL);
241 Assert (! argOff (current));
242 switch (current->type)
243 {
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, ¤t->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;
262 }
263 }
264
argDelete(Arguments * const current)265 extern void argDelete (Arguments* const current)
266 {
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);
272 }
273
274 /* vi:set tabstop=4 shiftwidth=4: */
275