257 lines
5.6 KiB
C
257 lines
5.6 KiB
C
|
/*
|
||
|
*
|
||
|
* Copyright (c) 1999-2001, Darren Hiebert
|
||
|
*
|
||
|
* This source code is released for free distribution under the terms of the
|
||
|
* GNU General Public License.
|
||
|
*
|
||
|
* This module contains functions for reading command line arguments.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* INCLUDE FILES
|
||
|
*/
|
||
|
#include "general.h" /* must always come first */
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
#include "args.h"
|
||
|
#include "main.h"
|
||
|
|
||
|
/*
|
||
|
* FUNCTION DEFINITIONS
|
||
|
*/
|
||
|
|
||
|
static char *nextStringArg (const char** const next)
|
||
|
{
|
||
|
char* result = NULL;
|
||
|
const char* start;
|
||
|
|
||
|
Assert (*next != NULL);
|
||
|
for (start = *next ; isspace ((int) *start) ; ++start)
|
||
|
;
|
||
|
if (*start == '\0')
|
||
|
*next = start;
|
||
|
else
|
||
|
{
|
||
|
size_t length;
|
||
|
const char* end;
|
||
|
|
||
|
for (end = start ; *end != '\0' && ! isspace ((int) *end) ; ++end)
|
||
|
;
|
||
|
length = end - start;
|
||
|
Assert (length > 0);
|
||
|
result = xMalloc (length + 1, char);
|
||
|
strncpy (result, start, length);
|
||
|
result [length] = '\0';
|
||
|
*next = end;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static char* nextStringLine (const char** const next)
|
||
|
{
|
||
|
char* result = NULL;
|
||
|
size_t length;
|
||
|
const char* end;
|
||
|
|
||
|
Assert (*next != NULL);
|
||
|
for (end = *next ; *end != '\n' && *end != '\0' ; ++end)
|
||
|
;
|
||
|
length = end - *next;
|
||
|
if (length > 0)
|
||
|
{
|
||
|
result = xMalloc (length + 1, char);
|
||
|
strncpy (result, *next, length);
|
||
|
result [length] = '\0';
|
||
|
}
|
||
|
if (*end == '\n')
|
||
|
++end;
|
||
|
*next = end;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static char* nextString (const Arguments* const current, const char** const next)
|
||
|
{
|
||
|
char* result;
|
||
|
if (current->lineMode)
|
||
|
result = nextStringLine (next);
|
||
|
else
|
||
|
result = nextStringArg (next);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static char* nextFileArg (FILE* const fp)
|
||
|
{
|
||
|
char* result = NULL;
|
||
|
Assert (fp != NULL);
|
||
|
if (! feof (fp))
|
||
|
{
|
||
|
vString* vs = vStringNew ();
|
||
|
int c;
|
||
|
do
|
||
|
c = fgetc (fp);
|
||
|
while (isspace (c));
|
||
|
|
||
|
if (c != EOF)
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
vStringPut (vs, c);
|
||
|
c = fgetc (fp);
|
||
|
} while (c != EOF && ! isspace (c));
|
||
|
vStringTerminate (vs);
|
||
|
Assert (vStringLength (vs) > 0);
|
||
|
result = xMalloc (vStringLength (vs) + 1, char);
|
||
|
strcpy (result, vStringValue (vs));
|
||
|
}
|
||
|
vStringDelete (vs);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static char* nextFileLine (FILE* const fp)
|
||
|
{
|
||
|
char* result = NULL;
|
||
|
if (! feof (fp))
|
||
|
{
|
||
|
vString* vs = vStringNew ();
|
||
|
int c;
|
||
|
|
||
|
Assert (fp != NULL);
|
||
|
c = fgetc (fp);
|
||
|
while (c != EOF && c != '\n')
|
||
|
{
|
||
|
vStringPut (vs, c);
|
||
|
c = fgetc (fp);
|
||
|
}
|
||
|
vStringTerminate (vs);
|
||
|
if (vStringLength (vs) > 0)
|
||
|
{
|
||
|
result = xMalloc (vStringLength (vs) + 1, char);
|
||
|
strcpy (result, vStringValue (vs));
|
||
|
}
|
||
|
vStringDelete (vs);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static char* nextFileString (const Arguments* const current, FILE* const fp)
|
||
|
{
|
||
|
char* result;
|
||
|
if (current->lineMode)
|
||
|
result = nextFileLine (fp);
|
||
|
else
|
||
|
result = nextFileArg (fp);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
extern Arguments* argNewFromString (const char* const string)
|
||
|
{
|
||
|
Arguments* result = xMalloc (1, Arguments);
|
||
|
memset (result, 0, sizeof (Arguments));
|
||
|
result->type = ARG_STRING;
|
||
|
result->u.stringArgs.string = string;
|
||
|
result->u.stringArgs.item = string;
|
||
|
result->u.stringArgs.next = string;
|
||
|
result->item = nextString (result, &result->u.stringArgs.next);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
extern Arguments* argNewFromArgv (char* const* const argv)
|
||
|
{
|
||
|
Arguments* result = xMalloc (1, Arguments);
|
||
|
memset (result, 0, sizeof (Arguments));
|
||
|
result->type = ARG_ARGV;
|
||
|
result->u.argvArgs.argv = argv;
|
||
|
result->u.argvArgs.item = result->u.argvArgs.argv;
|
||
|
result->item = *result->u.argvArgs.item;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
extern Arguments* argNewFromFile (FILE* const fp)
|
||
|
{
|
||
|
Arguments* result = xMalloc (1, Arguments);
|
||
|
memset (result, 0, sizeof (Arguments));
|
||
|
result->type = ARG_FILE;
|
||
|
result->u.fileArgs.fp = fp;
|
||
|
result->item = nextFileString (result, result->u.fileArgs.fp);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
extern Arguments* argNewFromLineFile (FILE* const fp)
|
||
|
{
|
||
|
Arguments* result = xMalloc (1, Arguments);
|
||
|
memset (result, 0, sizeof (Arguments));
|
||
|
result->type = ARG_FILE;
|
||
|
result->lineMode = TRUE;
|
||
|
result->u.fileArgs.fp = fp;
|
||
|
result->item = nextFileString (result, result->u.fileArgs.fp);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
extern char *argItem (const Arguments* const current)
|
||
|
{
|
||
|
Assert (current != NULL);
|
||
|
Assert (! argOff (current));
|
||
|
return current->item;
|
||
|
}
|
||
|
|
||
|
extern boolean argOff (const Arguments* const current)
|
||
|
{
|
||
|
Assert (current != NULL);
|
||
|
return (boolean) (current->item == NULL);
|
||
|
}
|
||
|
|
||
|
extern void argSetWordMode (Arguments* const current)
|
||
|
{
|
||
|
Assert (current != NULL);
|
||
|
current->lineMode = FALSE;
|
||
|
}
|
||
|
|
||
|
extern void argSetLineMode (Arguments* const current)
|
||
|
{
|
||
|
Assert (current != NULL);
|
||
|
current->lineMode = TRUE;
|
||
|
}
|
||
|
|
||
|
extern void argForth (Arguments* const current)
|
||
|
{
|
||
|
Assert (current != NULL);
|
||
|
Assert (! argOff (current));
|
||
|
switch (current->type)
|
||
|
{
|
||
|
case ARG_STRING:
|
||
|
if (current->item != NULL)
|
||
|
eFree (current->item);
|
||
|
current->u.stringArgs.item = current->u.stringArgs.next;
|
||
|
current->item = nextString (current, ¤t->u.stringArgs.next);
|
||
|
break;
|
||
|
case ARG_ARGV:
|
||
|
++current->u.argvArgs.item;
|
||
|
current->item = *current->u.argvArgs.item;
|
||
|
break;
|
||
|
case ARG_FILE:
|
||
|
if (current->item != NULL)
|
||
|
eFree (current->item);
|
||
|
current->item = nextFileString (current, current->u.fileArgs.fp);
|
||
|
break;
|
||
|
default:
|
||
|
Assert ("Invalid argument type" == NULL);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
extern void argDelete (Arguments* const current)
|
||
|
{
|
||
|
Assert (current != NULL);
|
||
|
if (current->type == ARG_STRING && current->item != NULL)
|
||
|
eFree (current->item);
|
||
|
memset (current, 0, sizeof (Arguments));
|
||
|
eFree (current);
|
||
|
}
|
||
|
|
||
|
/* vi:set tabstop=8 shiftwidth=4: */
|