Check first few chars of argument to ca65 macro?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: Check first few chars of argument to ca65 macro?

Post by thefox »

GradualGames wrote:Not sure I understand all the syntax there, particularly the double %%'s.
Those are there because of the inner sprintf constructs the format string for the outer sprintf. So, for example .sprintf("%%.%ds", 9) would turn into "%.9s" which is used as the format string in the outer sprintf.

(Note that unlike C sprintf, ca65 does not support specifying the field precision as an argument with "*", so nested sprintfs are needed.)
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
GradualGames
Posts: 1106
Joined: Sun Nov 09, 2008 9:18 pm
Location: Pennsylvania, USA
Contact:

Re: Check first few chars of argument to ca65 macro?

Post by GradualGames »

thefox wrote:
GradualGames wrote:Not sure I understand all the syntax there, particularly the double %%'s.
Those are there because of the inner sprintf constructs the format string for the outer sprintf. So, for example .sprintf("%%.%ds", 9) would turn into "%.9s" which is used as the format string in the outer sprintf.

(Note that unlike C sprintf, ca65 does not support specifying the field precision as an argument with "*", so nested sprintfs are needed.)
Ah, %% is an escape for itself then? Gotcha. Cool! There's a couple of other things I don't understand in there, it looks like you're doing a multiply on strlens somewhere, too, what's that for? *edit* I think I understand now that < is returning 0 or 1 so you can prevent it from parameterizing sprintf with a negative number, the trickery you mentioned, I assume. Neat.
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: Check first few chars of argument to ca65 macro?

Post by thefox »

GradualGames wrote:There's a couple of other things I don't understand in there, it looks like you're doing a multiply on strlens somewhere, too, what's that for?
That's the "trickery" I mentioned. (.strlen(ends_with) < .strlen(string)) evaluates to 0 if the ends_with is shorter than string (and 1 otherwise). The multiplication then forces the expression value to 0 to avoid a negative value going into the format string. E.g., "%.-7s" would not be a valid format string.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
GradualGames
Posts: 1106
Joined: Sun Nov 09, 2008 9:18 pm
Location: Pennsylvania, USA
Contact:

Re: Check first few chars of argument to ca65 macro?

Post by GradualGames »

thefox wrote:
GradualGames wrote:There's a couple of other things I don't understand in there, it looks like you're doing a multiply on strlens somewhere, too, what's that for?
That's the "trickery" I mentioned. (.strlen(ends_with) < .strlen(string)) evaluates to 0 if the ends_with is shorter than string (and 1 otherwise). The multiplication then forces the expression value to 0 to avoid a negative value going into the format string. E.g., "%.-7s" would not be a valid format string.
I can't seem to get ca65 to be happy with it. Trying to compile the following:

Wondering if it's a linecont issue. Like if I use .linecont + and then add some \ 's if it'll work.

Code: Select all

.define string_ends_with(string, ends_with) .xmatch(.sprintf(.sprintf("%%.%ds%%s", (.strlen(ends_with) < .strlen(string)) * (.strlen(string) - .strlen(ends_with))), string, ends_with), string)
.if string_ends_with("hello", "llo")
    .out "yes"
.else
    .out "no"
.endif
Last edited by GradualGames on Mon Aug 07, 2017 1:02 pm, edited 1 time in total.
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: Check first few chars of argument to ca65 macro?

Post by thefox »

GradualGames wrote:
thefox wrote:
GradualGames wrote:There's a couple of other things I don't understand in there, it looks like you're doing a multiply on strlens somewhere, too, what's that for?
That's the "trickery" I mentioned. (.strlen(ends_with) < .strlen(string)) evaluates to 0 if the ends_with is shorter than string (and 1 otherwise). The multiplication then forces the expression value to 0 to avoid a negative value going into the format string. E.g., "%.-7s" would not be a valid format string.
I can't seem to get ca65 to be happy with it. Trying to compile the following:

Wondering if it's a linecont issue. Like if I use .linecont + and then add some \ 's if it'll work.

Code: Select all

.define string_ends_with(string, ends_with) .xmatch(.sprintf(.sprintf("%%.%ds%%s", (.strlen(ends_with) < .strlen(string)) * (.strlen(string) - .strlen(ends_with))), string, ends_with), string)
.if string_ends_with("hello", "llo")
    .out "yes"
.else
    .out "no"
.endif
You should not use parens when calling macros. Try:

Code: Select all

.if string_ends_with "hello", "llo"
    .out "yes"
.else
    .out "no"
.endif
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
GradualGames
Posts: 1106
Joined: Sun Nov 09, 2008 9:18 pm
Location: Pennsylvania, USA
Contact:

Re: Check first few chars of argument to ca65 macro?

Post by GradualGames »

thefox wrote: You should not use parens when calling macros. Try:

Code: Select all

.if string_ends_with "hello", "llo"
    .out "yes"
.else
    .out "no"
.endif
Oh! :oops: Probably just force of habit with C style macros... I haven't thus far used any in my ca65 programs, only normal ca65 macros.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Check first few chars of argument to ca65 macro?

Post by tokumaru »

thefox wrote:It works by stripping off .strlen(string) - .strlen(ends_with) characters from the end of string, then appends ends_with to it, and compares to the original string.
Very clever!
Post Reply