Added command line response files
git-svn-id: svn://svn.cc65.org/cc65/trunk@616 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -86,6 +86,14 @@ int IsBlank (char C)
|
||||
|
||||
|
||||
|
||||
int IsSpace (char C)
|
||||
/* Check for any white space characters */
|
||||
{
|
||||
return (C == ' ' || C == '\n' || C == '\r' || C == '\t' || C == '\v' || C == '\f');
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsDigit (char C)
|
||||
/* Check for a digit */
|
||||
{
|
||||
|
||||
@@ -67,6 +67,9 @@ int IsAscii (char C);
|
||||
int IsBlank (char C);
|
||||
/* Check for a space or tab */
|
||||
|
||||
int IsSpace (char C);
|
||||
/* Check for any white space characters */
|
||||
|
||||
int IsDigit (char C);
|
||||
/* Check for a digit */
|
||||
|
||||
|
||||
@@ -33,9 +33,14 @@
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* common */
|
||||
#include "abend.h"
|
||||
#include "chartype.h"
|
||||
#include "xmalloc.h"
|
||||
#include "cmdline.h"
|
||||
|
||||
|
||||
@@ -50,8 +55,112 @@
|
||||
const char* ProgName;
|
||||
|
||||
/* The program argument vector */
|
||||
static char** ArgVec = 0;
|
||||
static unsigned ArgCount = 0;
|
||||
char** ArgVec = 0;
|
||||
unsigned ArgCount = 0;
|
||||
|
||||
/* Struct to pass the command line */
|
||||
typedef struct {
|
||||
char** Vec; /* The argument vector */
|
||||
unsigned Count; /* Actual number of arguments */
|
||||
unsigned Size; /* Number of argument allocated */
|
||||
} CmdLine;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Helper functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static void NewCmdLine (CmdLine* L)
|
||||
/* Initialize a CmdLine struct */
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
/* Initialize the struct */
|
||||
L->Size = 8;
|
||||
L->Count = 0;
|
||||
L->Vec = xmalloc (L->Size * sizeof (L->Vec[0]));
|
||||
|
||||
/* Copy the arguments. We have to allocate them on free store, otherwise
|
||||
* we would have to keep track which one is on free store and which not,
|
||||
* which is a lot more overhead.
|
||||
*/
|
||||
for (I = 0; I < L->Count; ++I) {
|
||||
L->Vec[I] = xstrdup (ArgVec[I]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void AddArg (CmdLine* L, const char* Arg)
|
||||
/* Add one argument to the list */
|
||||
{
|
||||
if (L->Size <= L->Count) {
|
||||
/* No space left, reallocate */
|
||||
unsigned NewSize = L->Size * 2;
|
||||
char** NewVec = xmalloc (NewSize * sizeof (L->Vec[0]));
|
||||
memcpy (NewVec, L->Vec, L->Count * sizeof (L->Vec[0]));
|
||||
xfree (L->Vec);
|
||||
L->Vec = NewVec;
|
||||
L->Size = NewSize;
|
||||
}
|
||||
|
||||
/* We have space left, add a copy of the argument */
|
||||
L->Vec [L->Count++] = xstrdup (Arg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ExpandFile (CmdLine* L, const char* Name)
|
||||
/* Add the contents of a file to the command line. Each line is a separate
|
||||
* argument with leading and trailing whitespace removed.
|
||||
*/
|
||||
{
|
||||
char Buf [256];
|
||||
|
||||
/* Try to open the file for reading */
|
||||
FILE* F = fopen (Name, "r");
|
||||
if (F == 0) {
|
||||
AbEnd ("Cannot open \"%s\": %s", Name, strerror (errno));
|
||||
}
|
||||
|
||||
/* File is open, read all lines */
|
||||
while (fgets (Buf, sizeof (Buf), F) != 0) {
|
||||
|
||||
/* Get a pointer to the buffer */
|
||||
const char* B = Buf;
|
||||
|
||||
/* Skip trailing whitespace (this will also kill the newline that is
|
||||
* appended by fgets().
|
||||
*/
|
||||
unsigned Len = strlen (Buf);
|
||||
while (Len > 0 && IsSpace (Buf [Len-1])) {
|
||||
--Len;
|
||||
}
|
||||
Buf [Len] = '\0';
|
||||
|
||||
/* Skip leading spaces */
|
||||
while (IsSpace (*B)) {
|
||||
++B;
|
||||
}
|
||||
|
||||
/* Skip empty lines to work around problems with some editors */
|
||||
if (*B == '\0') {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add anything not empty to the command line */
|
||||
AddArg (L, B);
|
||||
|
||||
}
|
||||
|
||||
/* Close the file, ignore errors here since we had the file open for
|
||||
* reading only.
|
||||
*/
|
||||
(void) fclose (F);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -61,35 +170,69 @@ static unsigned ArgCount = 0;
|
||||
|
||||
|
||||
|
||||
void InitCmdLine (unsigned aArgCount, char* aArgVec[], const char* aProgName)
|
||||
void InitCmdLine (unsigned* aArgCount, char** aArgVec[], const char* aProgName)
|
||||
/* Initialize command line parsing. aArgVec is the argument array terminated by
|
||||
* a NULL pointer (as usual), ArgCount is the number of valid arguments in the
|
||||
* array. Both arguments are remembered in static storage.
|
||||
*/
|
||||
{
|
||||
/* Remember the argument vector */
|
||||
ArgCount = aArgCount;
|
||||
ArgVec = aArgVec;
|
||||
CmdLine L;
|
||||
unsigned I;
|
||||
|
||||
/* Get the program name from argv[0] but strip a path */
|
||||
if (ArgVec[0] == 0) {
|
||||
/* Use the default name given */
|
||||
ProgName = aProgName;
|
||||
if (*(aArgVec)[0] == 0) {
|
||||
/* Use the default name given */
|
||||
ProgName = aProgName;
|
||||
} else {
|
||||
/* Strip a path */
|
||||
ProgName = strchr (ArgVec[0], '\0');
|
||||
while (ProgName > ArgVec[0]) {
|
||||
--ProgName;
|
||||
/* Strip a path */
|
||||
const char* FirstArg = (*aArgVec)[0];
|
||||
ProgName = strchr (FirstArg, '\0');
|
||||
while (ProgName > FirstArg) {
|
||||
--ProgName;
|
||||
if (*ProgName == '/' || *ProgName == '\\') {
|
||||
++ProgName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ProgName[0] == '\0') {
|
||||
/* Use the default */
|
||||
ProgName = aProgName;
|
||||
++ProgName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ProgName[0] == '\0') {
|
||||
/* Use the default */
|
||||
ProgName = aProgName;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make a CmdLine struct */
|
||||
NewCmdLine (&L);
|
||||
|
||||
/* Walk over the parameters and add them to the CmdLine struct. Add a
|
||||
* special handling for arguments preceeded by the '@' sign - these are
|
||||
* actually files containing arguments.
|
||||
*/
|
||||
for (I = 0; I < *aArgCount; ++I) {
|
||||
|
||||
/* Get the next argument */
|
||||
char* Arg = (*aArgVec)[I];
|
||||
|
||||
/* Is this a file argument? */
|
||||
if (Arg && Arg[0] == '@') {
|
||||
|
||||
/* Expand the file */
|
||||
ExpandFile (&L, Arg+1);
|
||||
|
||||
} else {
|
||||
|
||||
/* No file, just add a copy */
|
||||
AddArg (&L, Arg);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Store the new argument list in a safe place... */
|
||||
ArgCount = L.Count;
|
||||
ArgVec = L.Vec;
|
||||
|
||||
/* ...and pass back the changed data also */
|
||||
*aArgCount = L.Count;
|
||||
*aArgVec = L.Vec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -51,6 +51,10 @@
|
||||
/* Program name - is set after call to InitCmdLine */
|
||||
extern const char* ProgName;
|
||||
|
||||
/* The program argument vector */
|
||||
extern char** ArgVec;
|
||||
extern unsigned ArgCount;
|
||||
|
||||
/* Structure defining a long option */
|
||||
typedef struct LongOpt LongOpt;
|
||||
struct LongOpt {
|
||||
@@ -67,7 +71,7 @@ struct LongOpt {
|
||||
|
||||
|
||||
|
||||
void InitCmdLine (unsigned aArgCount, char* aArgVec[], const char* aProgName);
|
||||
void InitCmdLine (unsigned* aArgCount, char** aArgVec[], const char* aProgName);
|
||||
/* Initialize command line parsing. aArgVec is the argument array terminated by
|
||||
* a NULL pointer (as usual), ArgCount is the number of valid arguments in the
|
||||
* array. Both arguments are remembered in static storage.
|
||||
@@ -95,6 +99,6 @@ void LongOption (int* ArgNum, const LongOpt* OptTab, unsigned OptCount);
|
||||
/* End of cmdline.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -75,11 +75,21 @@ void xfree (const void* Block)
|
||||
char* xstrdup (const char* S)
|
||||
/* Duplicate a string on the heap. The function checks for out of memory */
|
||||
{
|
||||
/* Get the length of the string */
|
||||
unsigned Len = strlen (S) + 1;
|
||||
/* Allow dup'ing of NULL strings */
|
||||
if (S) {
|
||||
|
||||
/* Allocate memory and return a copy */
|
||||
return memcpy (xmalloc (Len), S, Len);
|
||||
/* Get the length of the string */
|
||||
unsigned Len = strlen (S) + 1;
|
||||
|
||||
/* Allocate memory and return a copy */
|
||||
return memcpy (xmalloc (Len), S, Len);
|
||||
|
||||
} else {
|
||||
|
||||
/* Return a NULL pointer */
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user