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.

Moderator: Moderators

User avatar
thefox
Posts: 3141
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

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

Post by thefox » Mon Aug 07, 2017 12:37 pm

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: 1107
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 » Mon Aug 07, 2017 12:39 pm

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: 3141
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

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

Post by thefox » Mon Aug 07, 2017 12:43 pm

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: 1107
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 » Mon Aug 07, 2017 12:49 pm

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: 3141
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

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

Post by thefox » Mon Aug 07, 2017 12:55 pm

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: 1107
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 » Mon Aug 07, 2017 12:57 pm

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: 11699
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 » Tue Aug 08, 2017 12:59 am

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