/ini and $ini functionality + source code change

A forum for the general posts relating to MacroQuest. *DEPRECATED: This forum is no longer in public use, but remains here for your reading pleasure. Enjoy

Moderator: MacroQuest Developers

User avatar
BlueSkies
a ghoul
a ghoul
Posts: 132
Joined: Tue Oct 01, 2002 6:22 pm

/ini and $ini functionality + source code change

Post by BlueSkies » Sun Jun 29, 2003 1:55 am

Jalapeno and I have finished our addition to the MacroQuest source -- INI File Manipulation.

Here's how they work:

/ini <filename> <section> <key> <data>
This writes data to an INI file.

$ini(<filename>,<section>,<key>)
and this Reads data from an INI file.

Filename = the INI file you wish to manipulate. This must be a full path+filename, like "c:\macroquest\macros\data\stuff.ini"

Section = the Section of the INI file you wish to manipulate.

Key = the Key (in the specified Section) that you wish to manipulate.

Here's an example of an INI file, for those of you who have no idea what we're talking about:

File: stuff.ini

Code: Select all

[MySection]
Key1=123
Key2=This is cool!
Key3=Wheeee... 15
Let's say we want to get the data for Key3. We can do a /echo for this:
/echo $ini("c:\macroquest\macros\data\stuff.ini","MySection","Key3")
The output from this would be:

Code: Select all

[MacroQuest] Wheeee... 15

Now let's say we want to add some data. We'd use the /ini command for this, like so:

/ini "c:\macroquest\macros\data\stuff.ini" "Section2" "ANewKey" "Some Data!"

When you run this, and open up the stuff.ini file in notepad, it'd look like this:

Code: Select all

[MySection]
Key1=123
Key2=This is cool!
Key3=Wheeee... 15
[Section2]
ANewKey=Some Data!


Let's say you've got an INI file you want to look through, but you don't know what all the section names are. You can simply pass a -1 value for the sectionname and keyname paramaters in $ini and it will return all the section names in one long line, with each section name seperated by a pipe character ( | ). The end of the line will have two pipes ( || ) to let you know that you've reached the end. For example:
/echo $ini("c:\macroquest\macros\data\stuff.ini",-1,-1)

This would return:

Code: Select all

MySection|Section2||
You can do the same thing to retrieve all the key names in a section, like so:
/echo $ini("c:\macroquest\macros\data\stuff.ini","MySection",-1)

would return:

Code: Select all

Key1|Key2|Key3||

In a script, you could use the $instr and $mid functions to parse the output of these two special $ini operations, and then use the data given here to look in the file and retreive the data.

Phew.

That's the nuts and bolts of the /ini command and $ini function.

If you would like to add this functionality to your version of MacroQuest, do the following:

Open the EQLib_Interp.cpp file. Find the _COMMANDORDER struct in the SetCmdList function. Scroll down until you see the following line:
{ NULL, CMD_EQ },
and add this line above it:

Code: Select all

		{ "/ini",		CMD_MQ },
Next, go to the TakeControlOfCommandList function and add the following line to the bottom of the list (but above the entry for NULL, NULL):

Code: Select all

		{"/ini",		"IniOutput"},
Now, open the MQ.h file, and go all the way to the bottom, where you should find a list of commands that look like this: extern "C" EQLIB_API etc etc
Add, to the bottom of this list, the following line:

Code: Select all

extern "C" EQLIB_API VOID  IniOutput	  (PSPAWNINFO, PCHAR);
Now, open the EQLib_Commands.cpp file. Add the following code to the very end of the file:

Code: Select all

// *************************************************************************** 
// Function:	IniOutput
// Description:	Outputs string data to an INI file using
//				WritePrivateProfileString.
// Usage:		/ini 
// *************************************************************************** 
VOID IniOutput(PSPAWNINFO pChar, PCHAR szLine) 
{
	CHAR szArg1[MAX_STRING] = {0};	//Filename
	CHAR szArg2[MAX_STRING] = {0};	//Section
	CHAR szArg3[MAX_STRING] = {0};	//Key
	CHAR szArg4[MAX_STRING] = {0};	//Data to write
	
	CHAR szOutput[MAX_STRING] = {0};  //Success / Error Output
	
	GetArg(szArg1,szLine,1);
	GetArg(szArg2,szLine,2);
	GetArg(szArg3,szLine,3);
	GetArg(szArg4,szLine,4);

	DebugSpew("/ini input -- %s %s %s %s",szArg1,szArg2,szArg3,szArg4);
	if (!WritePrivateProfileString(szArg2,szArg3,szArg4,szArg1)) {
		sprintf(szOutput,"IniOutput ERROR -- during WritePrivateProfileString: %s",szLine);
		DebugSpew(szOutput);
		WriteChatBuffer(szOutput, CONCOLOR_RED);
	} else {
		sprintf(szOutput,"IniOutput Write Successful!");
		DebugSpew("%s: %s",szOutput,szLine);
		WriteChatBuffer(szOutput, CONCOLOR_GREEN);
	}
}
We're almost done. :)
Finally, open the EQLib_MacroParser.cpp file. Go to the very bottom, and add this code just before the line "// $unknown":

Code: Select all

					// $ini(<filename>,<sectionname>,<keyname>)
					// Jalapeno & BlueSkies
					} else if (!strncmp("ini(",szVar,4)) {
						if ((!strstr(szVar,")")) || (!strstr(szVar,",")) || (!strstr(strstr(szVar,",")+1,","))) {
								DebugSpew("PMP - Bad $ini() '%s'",szVar);
								i--;
								szOutput[j] = '@';
								j++;
						} else {
							CHAR szArg1[MAX_STRING] = {0};
							CHAR szArg2[MAX_STRING] = {0};
							CHAR szArg3[MAX_STRING] = {0};
							CHAR szBuffer[MAX_STRING] = {0};
							CHAR szList[MAX_STRING] = {0};
							char* szToken;

							DWORD num = 0;
							DWORD zz = 0;
							DWORD k = 0;

							for (num=0;szVar[num]!=')';num++) {
								if (szVar[num]!='"') {
									szBuffer[zz++] = szVar[num];
								}
							}

							i += (strstr(szVar,")")-szVar);

							strncpy(szArg1,szBuffer+4,strstr(szBuffer,",")-szBuffer-4);
							strncpy(szArg2,szBuffer+4+strlen(szArg1)+1,(strstr(strstr(szBuffer,",")+1,","))-szBuffer-4-strlen(szArg1)-1);
							strcpy(szArg3,strstr(strstr(szBuffer,",")+1,",")+1);

							ZeroMemory(szBuffer,MAX_STRING);

							if (atoi(szArg2)==-1) {
								DebugSpew("INI -- Arg2 was -1.");
								num=GetPrivateProfileString(NULL,NULL,"NOTFOUND",szBuffer,MAX_STRING,szArg1);
							} else if (atoi(szArg3)==-1) {
								DebugSpew("INI -- Arg3 was -1.");
								num=GetPrivateProfileString(szArg2,NULL,"NOTFOUND",szBuffer,MAX_STRING,szArg1);
							} else {
								num=GetPrivateProfileString(szArg2,szArg3,"NOTFOUND",szBuffer,MAX_STRING,szArg1);
							}

							if ((atoi(szArg2)==-1) || (atoi(szArg3)==-1)) {
								DebugSpew("INI -- Testing Null-Delimited String Output");

								for (szToken = szBuffer; *szToken != NULL || k < 1; szToken += strlen(szToken) + 1, k++) {
									strcat(szList,szToken);
									strcat(szList,"|");
								}

								strcat(szList,"|");
								DebugSpew(szList);
								
								strcat(szOutput,szList);
								j+=strlen(szList);
							} else {
								strcat(szOutput,szBuffer);
								j+=strlen(szBuffer);
							}
							DebugSpew("PMP - $ini(%s,%s,%s) returned '%s'",szArg1,szArg2,szArg3,szList);
						}
That should do it. :) Save and compile.

To the people who have access to the CVS (like Rizwank or DKAA) -- if there's anything missing that you guys need before you can add this to the CVS, please let me know.


Oh yeah.
Examples of this functionality in use can be found here:
http://macroquest2.com/phpBB2/viewtopic ... 7056#17056
Live your dreams! Blue Skies everyone

Valerian
a grimling bloodguard
a grimling bloodguard
Posts: 709
Joined: Sun Jul 28, 2002 3:29 am

Post by Valerian » Sun Jun 29, 2003 2:40 am

Got an idea to make this more user friendly...

$ini(<filename>[,<section>[,key]])

section and key are optional, if key is omitted, it will return the list of keys, if section and key are both omitted, it will return the list of sections... will work on your code and tweak it around to do this... can leave your -1 functionality in there as well, and just add this functionality for those of us that don't like messing around with parms that really don't need to be there.

User avatar
BlueSkies
a ghoul
a ghoul
Posts: 132
Joined: Tue Oct 01, 2002 6:22 pm

Post by BlueSkies » Sun Jun 29, 2003 2:45 am

Hehe, good idea. :)

We actually thought about that a while back -- it'd be a great addition if someone were interested in making that change. ;)
Live your dreams! Blue Skies everyone

Jalapeno
orc pawn
orc pawn
Posts: 15
Joined: Sat Jun 28, 2003 9:29 pm
Location: Charleston, SC

Post by Jalapeno » Sun Jun 29, 2003 3:41 am

Thanks for the input Valerian it's always appreciated.
We had thought about adding that in earlier but we were focused on other problems at the time and lost track of it. If no one else gets it we might look into adding the functionality in the future. We have a few other projects were trying to focus on now though.

User avatar
dont_know_at_all
Developer
Developer
Posts: 5450
Joined: Sun Dec 01, 2002 4:15 am
Location: Florida, USA
Contact:

Post by dont_know_at_all » Sun Jun 29, 2003 3:43 am

Can you provide a test script?

I will try to get this in on Sunday or Monday...

Valerian
a grimling bloodguard
a grimling bloodguard
Posts: 709
Joined: Sun Jul 28, 2002 3:29 am

Post by Valerian » Sun Jun 29, 2003 4:33 am

BlueSkies wrote:Oh yeah.
Examples of this functionality in use can be found here:
http://macroquest2.com/phpBB2/viewtopic ... 7056#17056
right there DKAA *grin*

Jalapeno
orc pawn
orc pawn
Posts: 15
Joined: Sat Jun 28, 2003 9:29 pm
Location: Charleston, SC

Post by Jalapeno » Sun Jun 29, 2003 5:10 am

Threw together a complete command and function example script for your enjoyment...

Code: Select all

| INI command and function example
| by Jalapeno
|
| INI command and functionality
| by Jalapeno and BlueSkies


Sub Main

    |You might want to change the drive letter or whatever...
    /varset l0 "c:\newini.ini"

    |/ini <filename> <section> <key> <data> 
    /echo **** Adding 1 section 1 key ****
    /ini $l0 "newsection" "newkey" "newdata"
    
    
    |$ini(<filename>,<sectionname>,<keyname>)
    /echo **** Return value for section: newsection, key: newkey in $l0 >>
    /echo $ini($l0,"newsection","newkey")

    |Add another entry with 3 keys
    /echo **** Adding 1 section 3 keys ****
    /ini $l0 "anothersection" "anotherkey" "moredata"
    /ini $l0 "anothersection" "anotherkey1" "moredata1"
    /ini $l0 "anothersection" "anotherkey2" "moredata2"
    
    |Listing of sections
    /echo **** Listing all sections in $l0 >>
    /echo $ini($l0,-1,-1)
    
    |Listing of keys in a specified section
    /echo **** Listing all keys in section:  anothersection >>
    /echo $ini($l0,"anothersection",-1)

    |Parsing a sections keys
    /echo **** Parsed keys >>
    /varset l1 $ini($l0,"anothersection",-1)
    /varset l2 $left($instr("|",$l1),$l1)
    :repeat
        /echo $l2
        /varcalc l3 $strlen($l1)-$strlen($l2)-1
        /varset l1 $right($l3,$l1)
         /if $l1=="|" {
            /echo End of section keys.
            /return
        }
        /varset l2 $left($instr("|",$l1),$l1)
    /goto :repeat

/return

Valerian
a grimling bloodguard
a grimling bloodguard
Posts: 709
Joined: Sun Jul 28, 2002 3:29 am

Post by Valerian » Sun Jun 29, 2003 6:18 am

Ok, I cleaned up some of your nasty looking code, and got it working... also added more functionality to GetArg()/GetNextArg() to parse Comma Separated Values... one more optional parm at the end of the list of optional parms... may come in handy for future development anyway.

anyway, here's what I have now, cleaned up misc. parts of the PMP code and changed code in Get(Next)Arg()'s...

MQ.h:

Code: Select all

PCHAR		GetNextArg				(PCHAR szLine, DWORD dwNumber = 1, BOOL CSV = FALSE);
PCHAR		GetArg					(PCHAR szDest, PCHAR szSrc, DWORD dwNumber, BOOL LeaveQuotes = FALSE, BOOL ToParen = FALSE, BOOL CSV = FALSE);
EQLib_Utilities.cpp:

Code: Select all

// ***************************************************************************
// Function:    GetNextArg
// Description: Returns a pointer to the next argument
// ***************************************************************************
PCHAR GetNextArg(PCHAR szLine, DWORD dwNumber, BOOL CSV)
{
	PCHAR szNext = szLine;
	BOOL InQuotes = FALSE;
	while ((szNext[0] == ' ') || (szNext[0] == '\t') || ((CSV) && (szNext[0]==','))) szNext++;
	if ((INT)dwNumber < 1) return szNext;
	for (dwNumber;dwNumber>0;dwNumber--) {
		while (((szNext[0] != ' ') && (szNext[0] != '\t') && ((!CSV) || (szNext[0]!=',')) && (szNext[0] != 0)) || (InQuotes)) {
			if ((szNext[0] == 0) && (InQuotes)) {
				DebugSpew("GetNextArg - No matching quote, returning empty string");
				return szNext;
			}
			if (szNext[0] == '"') InQuotes = !InQuotes;
			szNext++;
		}
		while ((szNext[0] == ' ') || (szNext[0] == '\t') || ((CSV) && (szNext[0]==','))) szNext++;
	}
	return szNext;
}

// ***************************************************************************
// Function:    GetArg
// Description: Returns a pointer to the current argument in szDest
// ***************************************************************************
PCHAR GetArg(PCHAR szDest, PCHAR szSrc, DWORD dwNumber, BOOL LeaveQuotes, BOOL ToParen, BOOL CSV)
{
	DWORD i=0;
	DWORD j=0;
	BOOL InQuotes = FALSE;
	PCHAR szTemp = szSrc;
	ZeroMemory(szDest,MAX_STRING);

	szTemp = GetNextArg(szTemp,dwNumber-1, CSV);

	while (((szTemp[i] != ' ') && (szTemp[i] != '\t') && (szTemp[i] != 0) && ((!CSV) || (szTemp[i]!=',')) && ((!ToParen) || (szTemp[i] !=')'))) || (InQuotes)) {
		if ((szTemp[i] == 0) && (InQuotes)) {
			DebugSpew("GetArg - No matching quote, returning entire string");
			DebugSpew("Source = %s",szSrc);
			DebugSpew("Dest = %s",szDest);
			return szDest;
		}
		if (szTemp[i] == '"') {
			InQuotes = !InQuotes;
			if (LeaveQuotes) {
				szDest[j] = szTemp[i];
				j++;
			}
		} else {
			szDest[j] = szTemp[i];
			j++;
		}
		i++;
	}
	if ((ToParen) && (szTemp[i]==')')) szDest[j]=')';
	//DebugSpew("GetArg - Arg%d from '%s' = '%s'",dwNumber,szTemp,szDest);

	return szDest;
}
EQLib_MacroParser.cpp:

Code: Select all

					// $ini(<filename>[,<sectionname>[,<keyname>]]) 
					// Jalapeno & BlueSkies 
					// Additions/Modifications by Valerian
					} else if (!strncmp("ini(",szVar,4)) { 
						if ((!strstr(szVar,")")) || (szVar[4] == ')')) { 
							DebugSpew("PMP - Bad $ini() '%s'",szVar); 
							i--; 
							szOutput[j] = '@'; 
							j++; 
						} else { 
							CHAR szArg1[MAX_STRING] = {0}; 
							CHAR szArg2[MAX_STRING] = {0}; 
							CHAR szArg3[MAX_STRING] = {0}; 
							CHAR szBuffer[MAX_STRING] = {0}; 
							CHAR szList[MAX_STRING] = {0}; 
							char* szToken; 

							DWORD num = 0;
							DWORD zz = 0; 
							DWORD k = 0; 

							i += (strstr(szVar,")")-szVar); 
							strcpy(szBuffer,&szVar[4]);
							szBuffer[strlen(szBuffer)-1]=0;

							GetArg(szArg1,szBuffer,1,FALSE,FALSE,TRUE);
							if (*szArg1) 
								GetArg(szArg2,szBuffer,2,FALSE,FALSE,TRUE);
							if (*szArg2)
								GetArg(szArg3,szBuffer,3,FALSE,FALSE,TRUE);
							ZeroMemory(szBuffer,MAX_STRING);
							//DebugSpew("Arg1: '%s' Arg2: '%s' Arg3: '%s'",szArg1,szArg2,szArg3);

							if ((atoi(szArg2)==-1) || (!*szArg2)) { 
								//DebugSpew("INI -- Arg2 was -1 or missing. Arg1: '%s'",szArg1); 
								num=GetPrivateProfileString(NULL,NULL,"NOTFOUND",szBuffer,MAX_STRING,szArg1); 
							} else if ((atoi(szArg3)==-1) || (!*szArg3)) { 
								//DebugSpew("INI -- Arg3 was -1 or missing. Arg1: '%s'",szArg1); 
								num=GetPrivateProfileString(szArg2,NULL,"NOTFOUND",szBuffer,MAX_STRING,szArg1); 
							} else { 
								//DebugSpew("INI -- File: '%s' Section: '%s' Key: '%s'",szArg1,szArg2,szArg3);
								num=GetPrivateProfileString(szArg2,szArg3,"NOTFOUND",szBuffer,MAX_STRING,szArg1); 
							} 

							if ((atoi(szArg2)==-1) || (atoi(szArg3)==-1) || (!*szArg2) || (!*szArg3)) { 
								DebugSpew("INI -- Testing Null-Delimited String Output"); 

								for (szToken = szBuffer; *szToken != NULL || k < 1; szToken += strlen(szToken) + 1, k++) { 
									strcat(szList,szToken); 
									//strcat(szList," "); // Space Separated list.
									strcat(szList,"|"); 
								} 
								// Remove next line for Space Separated list.
								strcat(szList,"|"); 
								DebugSpew(szList); 
		                         
								strcat(szOutput,szList); 
								strcpy(szBuffer,szList);

								j+=strlen(szList); 
							} else { 
								strcat(szOutput,szBuffer); 
								j+=strlen(szBuffer); 
							} 
							DebugSpew("PMP - $ini(%s,%s,%s) returned '%s'",szArg1,szArg2,szArg3,szBuffer); 
						}
NOTE: I also think it would be much better to have the list returned as a space-separated list, so it could be parsed EASILY with $arg()... I didn't make that change yet, but if implimented it should be done before too many scripts get written to use it... 2 commented lines toward the end there to show how to make this change.

Jalapeno
orc pawn
orc pawn
Posts: 15
Joined: Sat Jun 28, 2003 9:29 pm
Location: Charleston, SC

Post by Jalapeno » Sun Jun 29, 2003 6:37 am

Damn, thats a bit harsh :p You'll have to forgive the strcpy mess that you were obviously referring to (and thanks for cleaning it up). Thats what a total lack of C++ knowledge will do to you. :p We have never programmed in C before this. FYI

When I wrote out that iniexample.mac I was thinking the same thing about the space delimited rather then pipe delimited list. The $arg command that is built into MQ didn't even cross my mind. So it would be good to go ahead and change that over to space delimited.

I definately like your addition to GetArg. Again thanks for the input.

- jala

Valerian
a grimling bloodguard
a grimling bloodguard
Posts: 709
Joined: Sun Jul 28, 2002 3:29 am

Post by Valerian » Sun Jun 29, 2003 7:51 am

Upon further reflection, I realized it would not be wise to use space-delimited lists, since .ini keys and sections can have spaces as well. (duh)

Perhaps a change to $arg for that? *shrug*

Valerian
a grimling bloodguard
a grimling bloodguard
Posts: 709
Joined: Sun Jul 28, 2002 3:29 am

Post by Valerian » Sun Jun 29, 2003 7:59 am

BTW, I'm also currently cleaning up that mess with the whole list parsing thing... sit back and watch guys, you may learn something new about string manipulation in C. *grins*

Valerian
a grimling bloodguard
a grimling bloodguard
Posts: 709
Joined: Sun Jul 28, 2002 3:29 am

Post by Valerian » Sun Jun 29, 2003 8:22 am

Aha! Finally got it working as intended... and managed to cut down your code even more, including a few extra vars that are no longer needed.

Code: Select all

					// $ini(<filename>[,<sectionname>[,<keyname>]]) 
					// Jalapeno & BlueSkies 
					// Additions/Modifications by Valerian
					} else if (!strncmp("ini(",szVar,4)) { 
						if ((!strstr(szVar,")")) || (szVar[4] == ')')) { 
							//DebugSpew("PMP - Bad $ini() '%s'",szVar); 
							i--; 
							szOutput[j] = '@'; 
							j++; 
						} else { 
							CHAR szArg1[MAX_STRING] = {0}; 
							CHAR szArg2[MAX_STRING] = {0}; 
							CHAR szArg3[MAX_STRING] = {0}; 
							CHAR szBuffer[MAX_STRING] = {0}; 

							i += (strstr(szVar,")")-szVar); 
							strcpy(szBuffer,&szVar[4]);
							szBuffer[strlen(szBuffer)-1]=0;

							GetArg(szArg1,szBuffer,1,FALSE,FALSE,TRUE);
							if (*szArg1) 
								GetArg(szArg2,szBuffer,2,FALSE,FALSE,TRUE);
							if (*szArg2)
								GetArg(szArg3,szBuffer,3,FALSE,FALSE,TRUE);
							ZeroMemory(szBuffer,MAX_STRING);

							if ((atoi(szArg2)==-1) || (!*szArg2)) { 
								GetPrivateProfileString(NULL,NULL,"NOTFOUND",szBuffer,MAX_STRING,szArg1); 
							} else if ((atoi(szArg3)==-1) || (!*szArg3)) { 
								GetPrivateProfileString(szArg2,NULL,"NOTFOUND",szBuffer,MAX_STRING,szArg1); 
							} else { 
								GetPrivateProfileString(szArg2,szArg3,"NOTFOUND",szBuffer,MAX_STRING,szArg1); 
							} 

							if ((atoi(szArg2)==-1) || (atoi(szArg3)==-1) || (!*szArg2) || (!*szArg3)) { 
								for (DWORD k = 0;((szBuffer[k] != 0) || (szBuffer[k+1] != 0));k++) 
									if (szBuffer[k]==0) szBuffer[k] = '|';
								strcat(szBuffer,"||");
							}
							strcat(szOutput,szBuffer); 
							j+=strlen(szBuffer); 

							DebugSpew("PMP - $ini(%s,%s,%s) returned '%s'",szArg1,szArg2,szArg3,szBuffer); 
						}
And there ya go... that should work for ya, and do everything yours did originally, but faster and cleaner code. :wink:

BTW, not trying to insult you, you guys are doing GREAT for having very little C knowledge, I remember when I first moved to C from Basic, the learning curve seemed like it was more of a learning cliff. Keep this kind of thing up, and you'll be coding in C and never use VB again. :lol:

EDIT: We could make it return a Comma Separated list, and modify $arg slightly to have another parm to parse a CSV list... I'll do that now with $arg...

EDIT: nope.... that'd mess up your original script (path walking) never mind.... maybe another optional flag on the GetArg...

Valerian
a grimling bloodguard
a grimling bloodguard
Posts: 709
Joined: Sun Jul 28, 2002 3:29 am

Post by Valerian » Sun Jun 29, 2003 9:31 am

OMG I'm hot tonight.

$arg(num,string[,separator])

does not break any current scripts.

separator is ANY single character to use as a delimiter.

Example: $arg(3,"This|is|a|test","|") returns "a"
Example: $arg(2,"eqlive.station.sony.com",".") returns "station"
Example: $arg(4,"I need to get some sleep") returns "get" (old syntax)

Now, I bet a few folks could actually find a use for this... and as an added bonus, I now know about as much as Plasmic about the GetArg() and GetNextArg() funcs... or maybe even more. :lol:

Code: Select all

					// $arg(num,string[,<separator>])
					} else if (!strncmp("arg(",szVar,4)) {
						if ((!strstr(szVar,")")) || (!strstr(szVar,","))) {
							DebugSpew("PMP - Bad $arg() '%s'",szVar);
							i--;
							szOutput[j] = '@';
							j++;
						} else {
							CHAR szArg[MAX_STRING] = {0};
							CHAR szTemp[MAX_STRING] = {0};
							DWORD num = 0;

							GetArg(szArg,szVar,2,FALSE,FALSE,TRUE);
							if (szArg[strlen(szArg)-1]==')') {
								szArg[strlen(szArg)-1]=0;
							} else {
								GetArg(szTemp,szVar,3,FALSE,FALSE,TRUE);
								szTemp[1]=0;
							}
							i += (strstr(szVar,")")-szVar);
							num = atoi(szVar+4);
							DebugSpew("$arg: Number: %d, String: '%s', Separator: '%s'",num,szArg,szTemp);
							GetArg(szTemp,szArg,num,FALSE,FALSE,FALSE,szTemp[0]);
							strcat(szOutput,szTemp);
							j+=strlen(szTemp);
						}
EQLib_Utilities.cpp:

Code: Select all

// ***************************************************************************
// Function:    GetNextArg
// Description: Returns a pointer to the next argument
// ***************************************************************************
PCHAR GetNextArg(PCHAR szLine, DWORD dwNumber, BOOL CSV, CHAR Separator)
{
	PCHAR szNext = szLine;
	BOOL CustomSep = FALSE;
	BOOL InQuotes = FALSE;
	if (Separator!=0) CustomSep=TRUE;

	while ((szNext[0] == ' ') 
		|| (szNext[0] == '\t') 
		|| ((CustomSep) && (szNext[0]==Separator))
		|| ((CSV) && (szNext[0]==','))) szNext++;
	if ((INT)dwNumber < 1) return szNext;
	for (dwNumber;dwNumber>0;dwNumber--) {
		while (((szNext[0] != ' ') 
			&& (szNext[0] != '\t') 
			&& ((!CustomSep) || (szNext[0]!=Separator))
			&& ((!CSV) || (szNext[0]!=',')) 
			&& (szNext[0] != 0)) 
			|| (InQuotes)) {
			if ((szNext[0] == 0) && (InQuotes)) {
				DebugSpew("GetNextArg - No matching quote, returning empty string");
				return szNext;
			}
			if (szNext[0] == '"') InQuotes = !InQuotes;
			szNext++;
		}
		while ((szNext[0] == ' ') 
			|| (szNext[0] == '\t') 
			|| ((CustomSep) && (szNext[0]==Separator))
			|| ((CSV) && (szNext[0]==','))) szNext++;
	}
	return szNext;
}

// ***************************************************************************
// Function:    GetArg
// Description: Returns a pointer to the current argument in szDest
// ***************************************************************************
PCHAR GetArg(PCHAR szDest, PCHAR szSrc, DWORD dwNumber, BOOL LeaveQuotes, BOOL ToParen, BOOL CSV, CHAR Separator)
{
	DWORD i=0;
	DWORD j=0;
	BOOL CustomSep = FALSE;
	BOOL InQuotes = FALSE;
	PCHAR szTemp = szSrc;
	ZeroMemory(szDest,MAX_STRING);
	if (Separator!=0) CustomSep=TRUE;

	szTemp = GetNextArg(szTemp,dwNumber-1, CSV, Separator);

	while (((szTemp[i] != ' ') 
		&& (szTemp[i] != '\t') 
		&& (szTemp[i] != 0) 
		&& ((!CSV) || (szTemp[i]!=',')) 
		&& ((!CustomSep) || (szTemp[i]!=Separator))
		&& ((!ToParen) || (szTemp[i] !=')'))) 
		|| (InQuotes)) {
		if ((szTemp[i] == 0) && (InQuotes)) {
			DebugSpew("GetArg - No matching quote, returning entire string");
			DebugSpew("Source = %s",szSrc);
			DebugSpew("Dest = %s",szDest);
			return szDest;
		}
		if (szTemp[i] == '"') {
			InQuotes = !InQuotes;
			if (LeaveQuotes) {
				szDest[j] = szTemp[i];
				j++;
			}
		} else {
			szDest[j] = szTemp[i];
			j++;
		}
		i++;
	}
	if ((ToParen) && (szTemp[i]==')')) szDest[j]=')';
	//DebugSpew("GetArg - Arg%d from '%s' = '%s'",dwNumber,szTemp,szDest);

	return szDest;
}
MQ.h:

Code: Select all

PCHAR		GetNextArg				(PCHAR szLine, DWORD dwNumber = 1, BOOL CSV = FALSE, CHAR Separator = 0);
PCHAR		GetArg					(PCHAR szDest, PCHAR szSrc, DWORD dwNumber, BOOL LeaveQuotes = FALSE, BOOL ToParen = FALSE, BOOL CSV = FALSE, CHAR Separator = 0);
Enjoy.

BTW, how does one go about becoming a coder for MQ anyway?

User avatar
BlueSkies
a ghoul
a ghoul
Posts: 132
Joined: Tue Oct 01, 2002 6:22 pm

Post by BlueSkies » Sun Jun 29, 2003 1:51 pm

Wow, Valerian, you went off! :P

Thank you SO much for cleaning up our code and adding functionality -- this was really my first attempt at delving into C. :)

And the changes to $arg is simply awesome :)

If DKAA can get this stuff into the CVS, well, that'd just kick ass. :)
Live your dreams! Blue Skies everyone

User avatar
BlueSkies
a ghoul
a ghoul
Posts: 132
Joined: Tue Oct 01, 2002 6:22 pm

Post by BlueSkies » Sun Jun 29, 2003 2:25 pm

Problem with new $arg function, Val:

/echo $arg(1,"This|is|a|test","|")
returns, as expected:
[MacroQuest] This

However:
/echo $arg(1,"This is|a|test","|")
returns
[MacroQuest] This
instead of
[MacroQuest] This is

It's almost like, instead of specifiying the delimiter to use instead of a space, you're adding a delimiter to include with a space... Either way, it's not working, and I don't know enough about the GetArg function to figure it out. :(
Live your dreams! Blue Skies everyone