From 697abf3ed78b97ef735b0dffbdee88b74eca03cf Mon Sep 17 00:00:00 2001 From: cuz Date: Fri, 9 Mar 2001 21:59:23 +0000 Subject: [PATCH] Added command line response files git-svn-id: svn://svn.cc65.org/cc65/trunk@616 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ar65/main.c | 39 ++++----- src/ca65/main.c | 6 +- src/cc65/main.c | 6 +- src/cl65/main.c | 8 +- src/common/chartype.c | 8 ++ src/common/chartype.h | 3 + src/common/cmdline.c | 183 +++++++++++++++++++++++++++++++++++++----- src/common/cmdline.h | 8 +- src/common/xmalloc.c | 18 ++++- src/da65/main.c | 12 +-- src/ld65/main.c | 6 +- src/od65/main.c | 10 +-- 12 files changed, 238 insertions(+), 69 deletions(-) diff --git a/src/ar65/main.c b/src/ar65/main.c index c8a4a7ce1..6cb8fa4bd 100644 --- a/src/ar65/main.c +++ b/src/ar65/main.c @@ -6,20 +6,20 @@ /* */ /* */ /* */ -/* (C) 1998 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ -/* */ -/* */ +/* (C) 1998-2001 Ullrich von Bassewitz */ +/* Wacholderweg 14 */ +/* D-70597 Stuttgart */ +/* EMail: uz@musoftware.de */ +/* */ +/* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ -/* */ +/* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ -/* */ +/* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ @@ -28,7 +28,7 @@ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ -/* */ +/* */ /*****************************************************************************/ @@ -38,8 +38,9 @@ #include #include -#include "../common/cmdline.h" -#include "../common/version.h" +/* common */ +#include "cmdline.h" +#include "version.h" #include "global.h" #include "add.h" @@ -78,19 +79,19 @@ int main (int argc, char* argv []) int I; /* Initialize the cmdline module */ - InitCmdLine (argc, argv, "ar65"); + InitCmdLine (&argc, &argv, "ar65"); /* We must have a file name */ - if (argc < 2) { + if (ArgCount < 2) { Usage (); } /* Check the parameters */ I = 1; - while (I < argc) { + while (I < ArgCount) { /* Get the argument */ - const char* Arg = argv [I]; + const char* Arg = ArgVec [I]; /* Check for an option */ if (strlen (Arg) != 1) { @@ -99,15 +100,15 @@ int main (int argc, char* argv []) switch (Arg [0]) { case 'a': - AddObjFiles (argc - I - 1, &argv [I+1]); + AddObjFiles (ArgCount - I - 1, &ArgVec[I+1]); break; case 'd': - DelObjFiles (argc - I - 1, &argv [I+1]); + DelObjFiles (ArgCount - I - 1, &ArgVec [I+1]); break; case 'l': - ListObjFiles (argc - I - 1, &argv [I+1]); + ListObjFiles (ArgCount - I - 1, &ArgVec [I+1]); break; case 'v': @@ -115,7 +116,7 @@ int main (int argc, char* argv []) break; case 'x': - ExtractObjFiles (argc - I - 1, &argv [I+1]); + ExtractObjFiles (ArgCount - I - 1, &ArgVec [I+1]); break; case 'V': diff --git a/src/ca65/main.c b/src/ca65/main.c index 1d90ea75e..b01b50166 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -508,7 +508,7 @@ int main (int argc, char* argv []) int I; /* Initialize the cmdline module */ - InitCmdLine (argc, argv, "ca65"); + InitCmdLine (&argc, &argv, "ca65"); /* Enter the base lexical level. We must do that here, since we may * define symbols using -D. @@ -517,10 +517,10 @@ int main (int argc, char* argv []) /* Check the parameters */ I = 1; - while (I < argc) { + while (I < ArgCount) { /* Get the argument */ - const char* Arg = argv [I]; + const char* Arg = ArgVec [I]; /* Check for an option */ if (Arg [0] == '-') { diff --git a/src/cc65/main.c b/src/cc65/main.c index ea83acca1..1b9735e90 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -455,19 +455,19 @@ int main (int argc, char* argv[]) const char* InputFile = 0; /* Initialize the cmdline module */ - InitCmdLine (argc, argv, "cc65"); + InitCmdLine (&argc, &argv, "cc65"); /* Initialize the default segment names */ InitSegNames (); /* Parse the command line */ I = 1; - while (I < argc) { + while (I < ArgCount) { const char* P; /* Get the argument */ - const char* Arg = argv [I]; + const char* Arg = ArgVec[I]; /* Check for an option */ if (Arg [0] == '-') { diff --git a/src/cl65/main.c b/src/cl65/main.c index cad66f0ce..bb2a87e59 100644 --- a/src/cl65/main.c +++ b/src/cl65/main.c @@ -733,7 +733,7 @@ int main (int argc, char* argv []) int I; /* Initialize the cmdline module */ - InitCmdLine (argc, argv, "cl65"); + InitCmdLine (&argc, &argv, "cl65"); /* Initialize the command descriptors */ CmdInit (&CC65, "cc65"); @@ -743,13 +743,13 @@ int main (int argc, char* argv []) /* Our default target is the C64 instead of "none" */ Target = TGT_C64; - + /* Check the parameters */ I = 1; - while (I < argc) { + while (I < ArgCount) { /* Get the argument */ - const char* Arg = argv [I]; + const char* Arg = ArgVec[I]; /* Check for an option */ if (Arg [0] == '-') { diff --git a/src/common/chartype.c b/src/common/chartype.c index 193dc3200..73f7a6ee4 100644 --- a/src/common/chartype.c +++ b/src/common/chartype.c @@ -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 */ { diff --git a/src/common/chartype.h b/src/common/chartype.h index 3292da75e..a1cdfc56d 100644 --- a/src/common/chartype.h +++ b/src/common/chartype.h @@ -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 */ diff --git a/src/common/cmdline.c b/src/common/cmdline.c index e0b4d6116..597f3778f 100644 --- a/src/common/cmdline.c +++ b/src/common/cmdline.c @@ -33,9 +33,14 @@ +#include #include +#include +/* 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; } diff --git a/src/common/cmdline.h b/src/common/cmdline.h index bb582e451..ce8f1e1ba 100644 --- a/src/common/cmdline.h +++ b/src/common/cmdline.h @@ -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 - + diff --git a/src/common/xmalloc.c b/src/common/xmalloc.c index bce75988f..7b1bd6e87 100644 --- a/src/common/xmalloc.c +++ b/src/common/xmalloc.c @@ -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; + + } } diff --git a/src/da65/main.c b/src/da65/main.c index 070c762dd..cf33b8188 100644 --- a/src/da65/main.c +++ b/src/da65/main.c @@ -314,10 +314,10 @@ int main (int argc, char* argv []) /* Program long options */ static const LongOpt OptTab[] = { { "--cpu", 1, OptCPU }, - { "--formfeeds", 0, OptFormFeeds }, - { "--help", 0, OptHelp }, + { "--formfeeds", 0, OptFormFeeds }, + { "--help", 0, OptHelp }, { "--pagelength", 1, OptPageLength }, - { "--start-addr", 1, OptStartAddr }, + { "--start-addr", 1, OptStartAddr }, { "--verbose", 0, OptVerbose }, { "--version", 0, OptVersion }, }; @@ -325,14 +325,14 @@ int main (int argc, char* argv []) int I; /* Initialize the cmdline module */ - InitCmdLine (argc, argv, "da65"); + InitCmdLine (&argc, &argv, "da65"); /* Check the parameters */ I = 1; - while (I < argc) { + while (I < ArgCount) { /* Get the argument */ - const char* Arg = argv [I]; + const char* Arg = ArgVec[I]; /* Check for an option */ if (Arg [0] == '-') { diff --git a/src/ld65/main.c b/src/ld65/main.c index 415c39ab6..6bc07dac0 100644 --- a/src/ld65/main.c +++ b/src/ld65/main.c @@ -297,7 +297,7 @@ int main (int argc, char* argv []) int I; /* Initialize the cmdline module */ - InitCmdLine (argc, argv, "ld65"); + InitCmdLine (&argc, &argv, "ld65"); /* Evaluate the CC65_LIB environment variable */ LibPath = getenv ("CC65_LIB"); @@ -313,10 +313,10 @@ int main (int argc, char* argv []) /* Check the parameters */ I = 1; - while (I < argc) { + while (I < ArgCount) { /* Get the argument */ - const char* Arg = argv [I]; + const char* Arg = ArgVec[I]; /* Check for an option */ if (Arg [0] == '-') { diff --git a/src/od65/main.c b/src/od65/main.c index 9387e2640..5acb5afe2 100644 --- a/src/od65/main.c +++ b/src/od65/main.c @@ -77,7 +77,7 @@ static void Usage (void) " -V\t\t\tPrint the version number and exit\n" "\n" "Long options:\n" - " --dump-all\t\tDump all object file information\n" + " --dump-all\t\tDump all object file information\n" " --dump-dbgsyms\tDump debug symbols\n" " --dump-exports\tDump exported symbols\n" " --dump-files\t\tDump the source files\n" @@ -104,7 +104,7 @@ static void OptDumpDbgSyms (const char* Opt, const char* Arg) /* Dump debug symbols contained in the object file */ { What |= D_DBGSYMS; -} +} @@ -255,14 +255,14 @@ int main (int argc, char* argv []) int I; /* Initialize the cmdline module */ - InitCmdLine (argc, argv, "od65"); + InitCmdLine (&argc, &argv, "od65"); /* Check the parameters */ I = 1; - while (I < argc) { + while (I < ArgCount) { /* Get the argument */ - const char* Arg = argv [I]; + const char* Arg = ArgVec[I]; /* Check for an option */ if (Arg [0] == '-') { -- 2.39.5