I have stupid preprocessor and include guard questions about ca65

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

Post Reply
spaceharrier
Posts: 40
Joined: Wed Jan 19, 2022 9:52 am

I have stupid preprocessor and include guard questions about ca65

Post by spaceharrier »

This is a different issue I am running into than just having an include guard in a header or include file to prevent circular dependencies or redundance.


So, basically, I want to have a single include file per source. The issue I am running into is when it comes to having import statements (as my source file will also export symbols.) My workaround I am thinking of is to include a define in the source file. Bear in mind the syntax is wrong. I am still wrangling to understand the way ca65's preprocessor does things:

In Source.s

Code: Select all


.define SOURCE_S

.include "source.inc"

.export foo
.export bar

And then in source.inc

Code: Select all


; standard include guard
.ifndef SOURCE_INC
.define SOURCE_INC

.ifndef SOURCE_S

.import foo
.import bar

.endif

; Structs and other preprocessor stuffs

blah
blah
blah
blah

.endif	; ifndef SOURCE_INC

Is there a better, more standard way of doing this? Does the ca65 preprocessor already intrinsically define anything based on the name of the source file being processed?

I am also running a small misunderstanding of the syntax used for the .ifdef preprocessor directive. Currently, I am having to declare something in the following manner:

Code: Select all

_APPCONFIG_INC_ = 1
rather than just something like

Code: Select all

.define _APPCONFIG_INC_
User avatar
Movax12
Posts: 541
Joined: Sun Jan 02, 2011 11:50 am

Re: I have stupid preprocessor and include guard questions about ca65

Post by Movax12 »

spaceharrier wrote: Sun Nov 20, 2022 7:53 am Currently, I am having to declare something in the following manner:

Code: Select all

_APPCONFIG_INC_ = 1
A symbol created with .define will always be replaced by what it was defined as except when using .undefine.
So if you .define foo with nothing following, foo will always be replaced with nothing. Therefore, creating an identifier of any value will work instead, like in the last part of your post.

Consider as well, something like .define foo 1 will also not work, as .ifdef 1 won't work as intended.

If you .include a file, it is part of the same module, the text from the file is just included as if it was part of the same file, and .import and .export aren't needed in the way you are using them here.

Import and export work with separate modules. Example: a file that is library code, included only once in the segment you want it to be in, that also has exports to access its variables or functions, and another file that has only imports to those that can be included in other modules.
Last edited by Movax12 on Sun Nov 20, 2022 4:18 pm, edited 1 time in total.
spaceharrier
Posts: 40
Joined: Wed Jan 19, 2022 9:52 am

Re: I have stupid preprocessor and include guard questions about ca65

Post by spaceharrier »

So then is

Code: Select all

THINGY = 1
equivalent to

Code: Select all

.define THINGY 1
?
User avatar
Movax12
Posts: 541
Joined: Sun Jan 02, 2011 11:50 am

Re: I have stupid preprocessor and include guard questions about ca65

Post by Movax12 »

No.
THINGY = 1 Results in the creation of a symbol/identifier named THINGY that evaluates to 1 when used in an expression. .ifdef THINGY or .defined(THINGY) will return true (which in CA65 is an integer value of 1- but this is unrelated the discussion).

.define THINGY 1 Results in a define that will be replaced with the text 1 when referenced before anything else on the line is evaluated by the assembler. It copies the tokens from the define at a low level, then the line is evaluated normally. Using .ifdef THINGY would be exactly the same as typing .ifdef 1

But, if you really want to, you could:

Code: Select all

TRUE = 1
.ifndef INCLUDE_GUARD
.define INCLUDE_GUARD TRUE
; ..etc
This would work because INCLUDE_GUARD will become TRUE which is a valid identifier in the example.
Post Reply