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.
13 #include "general.h" /* must always come first */
25 * FUNCTION DEFINITIONS
28 static char *nextStringArg (const char** const next
)
33 Assert (*next
!= NULL
);
34 for (start
= *next
; isspace ((unsigned char) *start
) ; ++start
)
43 for (end
= start
; *end
!= '\0' && ! isspace ((unsigned char) *end
); ++end
)
47 result
= xMalloc (length
+ 1, char);
48 strncpy (result
, start
, length
);
49 result
[length
] = '\0';
55 static char* nextStringLine (const char** const next
)
61 Assert (*next
!= NULL
);
62 for (end
= *next
; *end
!= '\n' && *end
!= '\0' ; ++end
)
67 result
= xMalloc (length
+ 1, char);
68 strncpy (result
, *next
, length
);
69 result
[length
] = '\0';
73 else if (*end
== '\r')
83 static char* nextString (const Arguments
* const current
, const char** const next
)
86 if (current
->lineMode
)
87 result
= nextStringLine (next
);
89 result
= nextStringArg (next
);
93 static char* nextFileArg (FILE* const fp
)
99 vString
* vs
= vStringNew ();
111 } while (c
!= EOF
&& ! isspace (c
));
112 Assert (vStringLength (vs
) > 0);
113 result
= xMalloc (vStringLength (vs
) + 1, char);
114 strcpy (result
, vStringValue (vs
));
121 static char* nextFileLine (FILE* const fp
)
127 vString
* vs
= vStringNew ();
133 if (c
!= '\n' && c
!= '\r')
135 else if (vStringLength (vs
) > 0)
139 if (c
!= EOF
|| vStringLength (vs
) > 0)
147 vStringStripTrailing (vs
);
148 vStringStripLeading (vs
);
149 result
= xMalloc (vStringLength (vs
) + 1, char);
150 strcpy (result
, vStringValue (vs
));
157 static bool isCommentLine (char* line
)
159 while (isspace((unsigned char) *line
))
161 return (*line
== '#');
164 static bool isOptscriptLine (char *line
)
166 size_t len
= strlen (line
);
169 if (line
[len
- 1] == '{' && line
[len
- 2] == '{')
174 static char* nextOptscriptLines (FILE* const fp
, char *line
)
176 vString
*vstr
= vStringNewInit (line
);
177 vStringPut (vstr
, '\n');
180 /* \n}}, \n=>1, }=>2, }=>3 */
189 if (c
== '\r' || c
== '\n')
202 vStringPut (vstr
, c
);
209 vStringPut (vstr
, c
);
210 if (endMarkers
== 1 || endMarkers
== 2)
218 vStringPut (vstr
, c
);
227 vStringPut (vstr
, '\n');
230 vStringPut (vstr
, '}');
233 vStringPut (vstr
, '}');
253 return vStringDeleteUnwrap (vstr
);
256 static char* nextFileLineSkippingComments (FILE* const fp
)
264 result
= nextFileLine (fp
);
269 comment
= isCommentLine (result
);
270 optscript
= isOptscriptLine (result
);
275 result
= nextOptscriptLines (fp
, result
);
281 static char* nextFileString (const Arguments
* const current
, FILE* const fp
)
284 if (current
->lineMode
)
285 result
= nextFileLineSkippingComments (fp
);
287 result
= nextFileArg (fp
);
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
);
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
;
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
);
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
);
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
)
365 if (current
->item
!= NULL
)
366 eFree (current
->item
);
367 current
->item
= nextString (current
, ¤t
->u
.stringArgs
.next
);
370 ++current
->u
.argvArgs
.item
;
371 current
->item
= *current
->u
.argvArgs
.item
;
374 if (current
->item
!= NULL
)
375 eFree (current
->item
);
376 current
->item
= nextFileString (current
, current
->u
.fileArgs
.fp
);
379 Assert ("Invalid argument type" == NULL
);
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
));