| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /* $Header: /VSS_Sync/wwlib/argv.cpp 11 8/29/01 10:25p Vss_sync $ */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Library *
- * *
- * $Archive:: /VSS_Sync/wwlib/argv.cpp $*
- * *
- * $Author:: Vss_sync $*
- * *
- * $Modtime:: 8/29/01 10:24p $*
- * *
- * $Revision:: 11 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * CurrentPos -- Create an instance to parse argv with. *
- * ArgvClass::Free -- Release data allocated. *
- * ArgvClass::Load_File -- Load args from a file. *
- * *ArgvClass::Find_Value -- Find value of argument given prefix. *
- * *ArgvClass::Get_Cur_Value -- Get value of current argugment. *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "argv.h"
- #include <assert.h>
- #include <ctype.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "ffactory.h"
- #include "rawfile.h"
- int ArgvClass::Argc = 0;
- char *ArgvClass::Argv[MAX_ARGC];
- /***********************************************************************************************
- * CurrentPos -- Create an instance to parse argv with. *
- * *
- * INPUT: *
- * bool case_sensitive - Do you want to perform a case sensitive search (stricmp)? *
- * bool exact_size - Do you want string of same lenght (strncmp) ? *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 06/18/1999 SKB : Created. *
- *=============================================================================================*/
- ArgvClass::ArgvClass(bool case_sensitive, bool exact_size):
- Flags(0),
- LastArg(0),
- CurrentPos(-1)
- {
- Case_Sensitive(case_sensitive);
- Exact_Size(exact_size);
- }
- /***********************************************************************************************
- * *ArgvClass::Find_Again -- Search for a string given the flags. *
- * *
- * INPUT: *
- * const char *arg - String to search for. If NULL, LastArg will be used. *
- * *
- * OUTPUT: *
- * const char *string found (null if not found) *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 06/17/1999 SKB : Created. *
- *=============================================================================================*/
- const char *ArgvClass::Find_Again(const char *arg)
- {
- if (arg) {
- LastArg = arg;
- } else {
- arg = LastArg;
- }
- // Make sure user has given us something to work with here.
- assert(LastArg);
- CurrentPos++;
- if (CurrentPos < Argc) {
- if (Is_Case_Sensitive()) {
- if (Is_Exact_Size()) {
- // Case Sensitive, Exact Size.
- for (; CurrentPos < Argc; CurrentPos++) {
- if (!strcmp(arg, Argv[CurrentPos])) {
- return Argv[CurrentPos];
- }
- }
- } else {
- // Case Sensitive, Match first strlen(arg).
- int len = strlen(arg);
- for (; CurrentPos < Argc; CurrentPos++) {
- if (!strncmp(arg, Argv[CurrentPos], len)) {
- return Argv[CurrentPos];
- }
- }
- }
- } else {
- if (Is_Exact_Size()) {
- // Note case sensitive, Exact Size.
- for (; CurrentPos < Argc; CurrentPos++) {
- if (!stricmp(arg, Argv[CurrentPos])) {
- return Argv[CurrentPos];
- }
- }
- } else {
- // Note case sensitive, Match first strlen(arg).
- int len = strlen(arg);
- for (; CurrentPos < Argc; CurrentPos++) {
- if (!strnicmp(arg, Argv[CurrentPos], len)) {
- return Argv[CurrentPos];
- }
- }
- }
- }
- }
- return NULL;
- }
- /***********************************************************************************************
- * ArgvClass::Init -- Setup the command line. *
- * *
- * INPUT: *
- * LPSTR lpCmdLine - A string of white space seperated strings. Quotes force spaces to *
- * be ignored. *
- * char *fileprefix - A prefix on an arguement telling system to load postfix file name *
- * as command line params. *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * This may be called multible times with different strings. *
- * Once Argc reaches MAX_ARGC, no more will be added. *
- * *
- * HISTORY: *
- * 06/17/1999 SKB : Created. *
- * 07/15/2001 SKB : Put file arguements in the correct order they were included. *
- *=============================================================================================*/
- int ArgvClass::Init(char *lpCmdLine, char *fileprefix)
- {
- // Get pointer to command line.
- char *ptr = lpCmdLine;
- if (!ptr || !*ptr) {
- return 0;
- }
- int fp_cmp_len = (fileprefix) ? strlen(fileprefix) : 0;
- // Save original Argc for return.
- int origargc = Argc;
- while (*ptr) {
- char *eos;
- char save;
- // Keep anything within quotes as one string.
- if (*ptr == '"') {
- ptr++;
- eos = ptr;
- // Search for next " or a null.
- while (*eos && (*eos != '"')) {
- eos++;
- }
- } else if (isspace(*ptr)) {
- ptr++;
- continue;
- } else {
- eos = ptr + 1;
- // search for next white space or null.
- while (*eos && !isspace(*eos)) {
- eos++;
- }
- }
- // Null out end of string so string function work.
- // Save the end to restore later.
- save = *eos;
- *eos = 0;
- bool was_file = false;
- // See if we are to load a file with parameters in it.
- if (fp_cmp_len && !strncmp(fileprefix, ptr, fp_cmp_len)) {
- ptr += fp_cmp_len;
- if (*ptr) {
- was_file = Load_File(ptr);
- }
- }
- // If it was not the file or the load failed...then add parameter.
- if (!was_file) {
- // Copy string over and continue.
- Argv[Argc] = strdup(ptr);
- Argc++;
- }
- // If save is null, then we are at the end and we can bail out.
- if (!save) break;
- // resore whitespace.
- *eos = save;
- ptr = eos + 1;
- }
- // Return number of params read in.
- return(Argc - origargc);
- }
- /***********************************************************************************************
- * ArgvClass::Load_File -- Load args from a file. *
- * *
- * INPUT: *
- * const char *fname - file to load. *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 06/18/1999 SKB : Created. *
- *=============================================================================================*/
- bool ArgvClass::Load_File(const char *fname)
- {
- file_auto_ptr fileap(_TheFileFactory, fname);
- FILE *fp = fopen(fileap->File_Name(), "r");
- // [SKB: May 08 2001 @ 8:42pm] :
- // If file factor fails to return a valid name (i.e. can't open the file),
- // then see if user (namely me) specified a full path for the file and see
- // if we can open just fname.
- if (!fp)
- fp = fopen(fname, "r");
- if (fp) {
- while (Argc < MAX_ARGC) {
- const int maxstrlen = 255;
- char string[maxstrlen + 1];
- // Get next line in file.
- if (!fgets(string, maxstrlen - 1, fp)) {
- break;
- }
- // Check for comments.
- if ((*string != '#') && (*string != ';')) {
- // Make sure null terminated.
- string[maxstrlen - 1] = '\0';
- char *ptr = string + (strlen(string) - 1);
- while (*ptr <= ' ') {
- *ptr = 0;
- // Is it just a blank line?
- if (ptr == string) {
- break;
- }
- ptr--;
- }
- // If there is anyting in the string. (NAK: old code used to fail for 1 char options)
- if (strlen(string)) {
- Argv[Argc] = strdup(string);
- Argc++;
- }
- }
- }
- fclose(fp);
- return(true);
- }
- return(false);
- }
- /***********************************************************************************************
- * ArgvClass::Free -- Release data allocated. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 06/18/1999 SKB : Created. *
- *=============================================================================================*/
- void ArgvClass::Free()
- {
- for (int lp = 0; lp < Argc; lp++) {
- free(Argv[lp]);
- Argv[lp] = 0;
- }
- Argc = -1;
- }
-
- /***********************************************************************************************
- * *ArgvClass::Find_Value -- Find value of argument given prefix. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/23/1999 SKB : Created. *
- *=============================================================================================*/
- const char *ArgvClass::Find_Value(const char *arg)
- {
- if (arg && *arg) {
- const char *ptr = Find(arg);
- if (ptr) {
- return(Get_Cur_Value(strlen(arg)));
- }
- }
- return(NULL);
- }
-
- /***********************************************************************************************
- * *ArgvClass::Get_Cur_Value -- Get value of current argugment. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/23/1999 SKB : Created. *
- * 06/25/2001 SKB : add flag user can check to see if value was extracted from next location.*
- *=============================================================================================*/
- const char *ArgvClass::Get_Cur_Value(unsigned prefixlen, bool * val_in_next)
- {
- if (val_in_next) *val_in_next = false;
- if (CurrentPos < 0) {
- return NULL;
- }
- char *ptr = Argv[CurrentPos];
-
- if (strlen(ptr) < prefixlen) {
- return(NULL);
- }
- ptr += prefixlen;
- // Look for non white space (or eol).
- while (*ptr && !isgraph(*ptr)) {
- ptr++;
- }
- if (*ptr) {
- return ptr;
- }
- // Goto next line to handle '-P data' case on command line.
- ptr = Argv[CurrentPos + 1];
- if (!ptr) {
- return NULL;
- }
- while (*ptr) {
- if (isgraph(*ptr)) {
- if (val_in_next) *val_in_next = true;
- return ptr;
- }
- ptr++;
- }
- return (NULL);
- }
- /***********************************************************************************************
- * void ArgvClass::Update_Value -- Add/Replace a value *
- * *
- * INPUT: *
- * attrib = cmd line attrib to add/replace *
- * value = new value for attrib *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: Not Tested! *
- * *
- * HISTORY: *
- * 12/13/1999 NAK : Created. *
- *=============================================================================================*/
- void ArgvClass::Update_Value(const char *attrib, const char *value)
- {
- if ((Find_Value(attrib))!=NULL)
- {
- if (((CurrentPos+1) < Argc) && (Argv[CurrentPos+1][0] != '-')) // update old value
- {
- free(Argv[CurrentPos+1]);
- Argv[CurrentPos+1]=strdup(value);
- }
- else // add new value
- {
- // shift vals down to make room
- memmove(&(Argv[CurrentPos+2]),&(Argv[CurrentPos+1]),sizeof(char *) * (MAX_ARGC-CurrentPos-2));
- Argv[CurrentPos+1]=strdup(value);
- Argc++;
- }
- }
- else // just add the new stuff
- Add_Value(attrib, value);
- }
- /***********************************************************************************************
- * void ArgvClass::Add_Value -- Add a value *
- * *
- * INPUT: *
- * attrib = thing to add *
- * value = new optional value *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 12/13/1999 NAK : Created. *
- *=============================================================================================*/
- void ArgvClass::Add_Value(const char *attrib, const char *value)
- {
- if (attrib)
- {
- Argv[Argc]=strdup(attrib);
- Argc++;
- if (value)
- {
- Argv[Argc]=strdup(value);
- Argc++;
- }
- }
- }
- /***********************************************************************************************
- * bool ArgvClass::Remove_Value -- Remove a value *
- * *
- * INPUT: *
- * attrib = thing to remove *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * THIS CONTAINS A POTENTIAL BUG - I don't want to fix it because it might be a desired *
- * behavior. Given: *
- * Argv[0] = "-i test" "*.txt" as values in Argv, *
- * calling Remove_Value("-i") will remove *.txt as well. *
- * *
- * HISTORY: *
- * 12/13/1999 NAK : Created. *
- * 06/25/2001 SKB : WARNINGS message *
- *=============================================================================================*/
- bool ArgvClass::Remove_Value(const char *attrib)
- {
- int removeCount=1;
- if ((Find_Value(attrib))!=NULL)
- {
- free(Argv[CurrentPos]);
- if (((CurrentPos+1) < Argc)&&(Argv[CurrentPos+1][0]!='-')) // value for this arg
- {
- free(Argv[CurrentPos+1]);
- removeCount=2;
- }
- memmove(&(Argv[CurrentPos]),&(Argv[CurrentPos+removeCount]),sizeof(char *) * (MAX_ARGC-CurrentPos-removeCount));
- Argc-=removeCount;
- return(true);
- }
- return(false);
- }
|