Release 0.95.1: Tweaked type system and changed "label" to "symbol" in a lot of places.

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@35 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2014-06-07 00:12:10 +00:00
parent d152f60acd
commit 808ccf39a3
28 changed files with 708 additions and 718 deletions

View File

@ -30,7 +30,7 @@ The two exceptions are:
*** 1) Labels are defined too late
*** 1) Symbols are defined too late
If ACME cannot figure out the argument value in the first pass, it
assumes that the command uses 16-bit addressing.
@ -39,7 +39,7 @@ If it later finds out that the argument only needs 8 bits, ACME gives
a warning ("using oversized addressing mode") and continues. However,
if it finds out that the argument needs 24 bits, it gives an error.
These problems can be solved by defining the labels *before* using
These problems can be solved by defining the symbols *before* using
them, so that the value can be figured out in the first pass. If this
is not possible, you can use the postfix method, effectively exactly
defining what addressing mode to use. The postfix method is described
@ -65,16 +65,16 @@ target location using leading zeros. ACME will then use an addressing
mode that is big enough even if the leading zeros would have been
other digits:
label1 = $fb
label2 = $00fd
label3 = $0000ff
symbol1 = $fb
symbol2 = $00fd
symbol3 = $0000ff
lda $fa
sta $00fc
lda $0000fe
sta label1
lda label2
sta label3
sta symbol1
lda symbol2
sta symbol3
will be assembled to
@ -108,17 +108,17 @@ priorities.
Here's an (overly complicated) example:
label1 = $fb
label2 = $fd
label3+3 = $ff ; set Force Bit 3 and store in label's flags
symbol1 = $fb
symbol2 = $fd
symbol3+3 = $ff ; set Force Bit 3 and store in symbol's flags
ldx $fa
ldy+2 $fc ; set Force Bit 2 (16-bit addressing)
lda+3 $fe ; set Force Bit 3 (24-bit addressing)
stx label1
sty+2 label2 ; set Force Bit 2 (16-bit addressing)
sta label3 ; no need to set Force Bit 3 as it is
; already set in "label3".
stx symbol1
sty+2 symbol2 ; set Force Bit 2 (16-bit addressing)
sta symbol3 ; no need to set Force Bit 3 as it is
; already set in "symbol3".
will be assembled to
@ -131,13 +131,13 @@ will be assembled to
Postfixes given directly after the command have higher priority than
those given to the argument. As you can see, you can add the postfix
to the label definition as well (equivalent to leading zeros).
to the symbol definition as well (equivalent to leading zeros).
Applying the byte extraction operators ("<" gives the low byte, ">"
gives the high byte and "^" gives the bank byte of a value) to any
value will clear the argument's Force Bits 2 and 3 and set Force
Bit 1 instead. So "lda <label" will use 8-bit addressing, regardless
of the label's Force Bits. Of course, you can change this by
Bit 1 instead. So "lda <symbol" will use 8-bit addressing, regardless
of the symbol's Force Bits. Of course, you can change this by
postfixing the command again... :)
@ -154,9 +154,9 @@ ACME acts upon it. So postfixes have the highest priority.
Otherwise, ACME checks whether the argument has any Force Bits set
(because of leading zeros or byte extraction operators, for example)
or references to labels that have. If any Force Bit is set, ACME acts
or references symbols that have. If any Force Bit is set, ACME acts
upon it. This is the next priority level: Leading zeros or postfixes
added to the label definition.
added to the symbol definition.
Otherwise, ACME checks whether the argument could be figured out in
the first pass. If it couldn't, ACME tries to use a default addressing

View File

@ -21,16 +21,16 @@ Call: !8 EXPRESSION [, EXPRESSION]*
Purpose: Insert 8-bit values.
Parameters: EXPRESSION: Any formula the value parser accepts.
Aliases: "!08", "!by", "!byte"
Examples: !08 127, label, -128 ; output some values
Examples: !08 127, symbol, -128 ; output some values
!by 14, $3d, %0110, &304, <*, "c"
!byte 3 - 4, label1 XOR label2, 2 ^ tz, (3+4)*7
!byte 3 - 4, symbol1 XOR symbol2, 2 ^ tz, (3+4)*7
Call: !16 EXPRESSION [, EXPRESSION]*
Purpose: Insert 16-bit values.
Parameters: EXPRESSION: Any formula the value parser accepts.
Aliases: "!wo", "!word"
Examples: !16 65535, label, -32768 ; output some values
Examples: !16 65535, symbol, -32768 ; output some values
!wo 14, $4f35, %100101010010110, &36304, *, "c"
!word 3000 - 4, a1 AND a2, 2 ^ tz, (3+4)*70, l1 & .j2
@ -38,7 +38,7 @@ Examples: !16 65535, label, -32768 ; output some values
Call: !24 EXPRESSION [, EXPRESSION]*
Purpose: Insert 24-bit values.
Parameters: EXPRESSION: Any formula the value parser accepts.
Examples: !24 16777215, label, -8388608, 14, $6a4f35
Examples: !24 16777215, symbol, -8388608, 14, $6a4f35
!24 %10010110100101010010110, &47336304, *, "c"
!24 300000 - 4, a1 AND a2, 2 ^ tz, (3+4)*70, l1 & .j2
@ -46,7 +46,7 @@ Examples: !24 16777215, label, -8388608, 14, $6a4f35
Call: !32 EXPRESSION [, EXPRESSION]*
Purpose: Insert 32-bit values.
Parameters: EXPRESSION: Any formula the value parser accepts.
Examples: !32 $7fffffff, label, -$80000000, 14, $46a4f35
Examples: !32 $7fffffff, symbol, -$80000000, 14, $46a4f35
!32 %1001011010010101001011010010, &4733630435, *, "c"
!32 300000 - 4, a AND a2, 2 ^ tz, (3+4)*70, l1 & .j2
@ -247,11 +247,11 @@ Examples: !binary <Own/menudata.b> ; insert library file
----------------------------------------------------------------------
Section: Labels
Section: Symbols
----------------------------------------------------------------------
Call: !zone [TITLE] [ { BLOCK } ]
Purpose: Switch to new zone of local labels. Zones can either
Purpose: Switch to new zone of local symbols. Zones can either
be nested or used sequentially.
Parameters: TITLE: May consist of letters and digits. Its only
purpose is to be displayed in error messages, so it'll
@ -262,9 +262,9 @@ Parameters: TITLE: May consist of letters and digits. Its only
If a block is given, the old zone continues after the
block.
Aliases: "!zn"
Examples: .backgroundcolor = 0 ; some local label
!zone File_IO ; new zone begins here
.backgroundcolor = 1 ; so this is a different label
Examples: .backgroundcolor = 0 ; some local symbol
!zone File_IO ; new zone begins here, so
.backgroundcolor = 1 ; this is a different symbol
!zn LinkedList_Init
.backgroundcolor = 2
!zone LinkedList { ; start of nested zone
@ -279,17 +279,17 @@ Examples: .backgroundcolor = 0 ; some local label
!zone LinkedList_End
; you know what to imagine here...
}
.backgroundcolor = 3 ; => "Label already defined."
.backgroundcolor = 3 ; => "Symbol already defined."
Call: !sl FILENAME
Purpose: Save all the global labels to the given file after the
assembly is finished. This table could be loaded
Purpose: Save all the global symbols to the given file after
the assembly is finished. This table could be loaded
during another assembly session using the "!source"
pseudo opcode.
Parameters: FILENAME: A file name given in "..." quoting.
Examples: !sl "Labels.a" ; produce label dump after assembly
!sl "global" ; produce label dump after assembly
Examples: !sl "Symbols.a" ; produce symbol dump after assembly
!sl "global" ; produce symbol dump after assembly
----------------------------------------------------------------------
@ -305,7 +305,7 @@ Parameters: CONDITION: Any formula the value parser accepts, but
it must be solvable even in the first pass.
BLOCK: A block of assembler statements.
Examples: !text "Black", 0 ; Choose wording according to
!if country = uk { ; content of "country" label.
!if country = uk { ; content of "country" symbol.
!text "Grey"
} else {
!text "Gray"
@ -313,38 +313,38 @@ Examples: !text "Black", 0 ; Choose wording according to
!byte 0
!text "White", 0
; Insert debug commands if label "debug" is not zero:
; Insert debug commands if symbol "debug" is not zero:
!if debug { lda #"z":jsr char_output }
Call: !ifdef LABEL { BLOCK } [ else { BLOCK } ]
or: !ifdef LABEL STATEMENT
Call: !ifndef LABEL { BLOCK } [ else { BLOCK } ]
or: !ifndef LABEL STATEMENT
Purpose: Conditional assembly, depending on whether a label is
Call: !ifdef SYMBOL { BLOCK } [ else { BLOCK } ]
or: !ifdef SYMBOL STATEMENT
Call: !ifndef SYMBOL { BLOCK } [ else { BLOCK } ]
or: !ifndef SYMBOL STATEMENT
Purpose: Conditional assembly, depending on whether a symbol is
already defined or not.
With "ifdef", if the label is defined, the first block
of statements will be parsed; if it isn't, the second
block will be parsed instead (if present).
With "ifndef", it's the other way around: If the label
isn't defined, the first block of statements will be
parsed; if it is defined, the second block will be
parsed instead (if present).
With "ifdef", if the symbol is defined, the first
block of statements will be parsed; if it isn't, the
second block will be parsed instead (if present).
With "ifndef", it's the other way around: If the
symbol isn't defined, the first block of statements
will be parsed; if it is defined, the second block
will be parsed instead (if present).
CAUTION: These opcodes were added to speed up parsing
of library files (see example below). They can be used
to tell passes apart, therefore only use them in your
own files if you're sure you *really* know what you
are doing - using them in the wrong way will result in
loads of error messages.
Parameters: LABEL: Any valid label name.
Parameters: SYMBOL: Any valid symbol name.
BLOCK: A block of assembler statements.
STATEMENT: Any assembler statement.
Examples: ; this was taken from <6502/std.a>:
!ifdef Lib_6502_std_a !eof ; in later passes,
Lib_6502_std_a = 1 ; skip this file.
; During the first pass, the label is not defined,
; During the first pass, the symbol is not defined,
; therefore the file will get parsed. During all
; further passes, the label is already defined,
; further passes, the symbol is already defined,
; therefore the file will be skipped.
; if the following code gets included several times,
@ -358,32 +358,32 @@ Examples: ; this was taken from <6502/std.a>:
}
Call: !for LABEL, START, END { BLOCK }
Call: !for SYMBOL, START, END { BLOCK }
Purpose: Looping assembly. The block of statements will be
parsed a fixed number of times, as specified by the
values of START and END. For a more flexible
possibility, have a look at "!do" below.
Parameters: LABEL: Any valid label name.
Parameters: SYMBOL: Any valid symbol name.
START: Any formula the value parser accepts, but it
must be solvable even in the first pass. LABEL will
must be solvable even in the first pass. SYMBOL will
have this value during the first loop cycle.
END: Any formula the value parser accepts, but it must
be solvable even in the first pass. LABEL will have
be solvable even in the first pass. SYMBOL will have
this value during the last loop cycle.
BLOCK: A block of assembler statements.
If START or END are floats, they will be converted to
integers (never use floats for loop counters). If
START is less than or equal to END, LABEL will get
START is less than or equal to END, SYMBOL will get
incremented at the end of each cycle; if START is
greater than END, LABEL will get decremented at the
end of each cycle. So after leaving the loop, LABEL
greater than END, SYMBOL will get decremented at the
end of each cycle. So after leaving the loop, SYMBOL
will have an "illegal" value (END + 1 if counting up,
END - 1 if counting down).
Please note that it is impossible to change the number
of loop cycles "inside" the loop by fiddling with the
counter using the "!set" pseudo opcode: The "!for"
routine keeps its own copy of the counter value and
only sets the label value, it never reads it back.
only sets the symbol value, it never reads it back.
This was done to eliminate a possibility to hang ACME.
Examples:
int2BCD ; conversion table: integer to BCD
@ -409,7 +409,7 @@ Examples:
sta $0400 + i
}
Miscellaneous: The old syntax ("!for LABEL, END { BLOCK }" where
Miscellaneous: The old syntax ("!for SYMBOL, END { BLOCK }" where
START was always implied to be 1) is still fully
supported, but gives a warning to get people to change
to the new syntax. You can disable this warning using
@ -418,19 +418,19 @@ Miscellaneous: The old syntax ("!for LABEL, END { BLOCK }" where
When migrating your sources, bear in mind that it is
no longer possible to skip the block completely by
specifying a loop count of zero.
Also note that with the new algorithm, LABEL has a
Also note that with the new algorithm, SYMBOL has a
different value after the block than during the last
loop cycle, while the old algorithm kept that last
value.
Call: !set LABEL = VALUE
Purpose: Assign given value to label even if the label already
has a different value. Needed for loop counters when
using "!do", for example. Only use this opcode for
something else if you're sure you *really* know what
you are doing... :)
Parameters: LABEL: Any valid label name.
Call: !set SYMBOL = VALUE
Purpose: Assign given value to symbol even if the symbol
already has a different value. Needed for loop
counters when using "!do", for example. Only use this
opcode for something else if you're sure you *really*
know what you are doing... :)
Parameters: SYMBOL: Any valid symbol name.
VALUE: Any formula the value parser accepts.
Example: see "!do" below
@ -523,20 +523,20 @@ Example: !source "part1.a" ; sets part1_version
Section: Macro usage
----------------------------------------------------------------------
Call: !macro TITLE [[~]LABEL [, [~]LABEL]*] { BLOCK }
Call: !macro TITLE [[~]SYMBOL [, [~]SYMBOL]*] { BLOCK }
Purpose: Define a macro.
Parameters: TITLE: The macro's desired name (same rules as for
label names). If the title's first character is a dot
symbol names). If the title's first character is a dot
("."), the macro will be local (though why anyone
could want this is beyond me).
LABEL: The desired name for the parameter value at
call time. Normally, these parameter labels should be
SYMBOL: The desired name for the parameter value at
call time. Normally, these parameter symbols should be
local (first character a dot), as different macro
calls will almost for sure have different parameter
values.
If you prefix LABEL with a '~' character, it will be
If you prefix SYMBOL with a '~' character, it will be
called by reference, not by value: Changing the value
inside the macro will result in the "outer" label to
inside the macro will result in the "outer" symbol to
be changed as well.
BLOCK: A block of assembler statements.
Examples: ; far branch, as defined in <6502/std.a>
@ -586,10 +586,10 @@ Purpose: Call a macro, using the given parameter values.
Parameters: TITLE: The macro's name as given in its definition.
ARGUMENT: This is either any formula the value parser
accepts, or (new in release 0.86) a '~' character
followed by a label name. The '~'-prefix indicates
followed by a symbol name. The '~'-prefix indicates
call-by-reference semantics, which means that when the
macro changes the label's value, the caller's label's
value will change as well.
macro changes the symbol's value, the caller's
symbol's value will change as well.
Examples: inc label
bne mark ; "near" branch
inc label2
@ -819,15 +819,15 @@ Section: Type system
----------------------------------------------------------------------
Call: !address [ { BLOCK } ]
or: !address LABEL = VALUE
or: !address SYMBOL = VALUE
Purpose: Mark a block or a statement as "explicitly defined
labels are holding addresses".
symbols are holding addresses".
Parameters: BLOCK: A block of assembler statements
Everything inside the block will be parsed as usual,
but labels getting explicitly defined will be marked
as referencing memory.
but explicitly defined symbols will be marked as
referencing memory.
If no block is given, only the current statement will
be affected, which should then be an explicit label
be affected, which should then be an explicit symbol
definition.
Aliases: "!addr"
Examples: !addr k_chrout = $ffd2 ; this is an address

View File

@ -12,6 +12,18 @@ platform used. There should be another help file in this archive
outlining the platform specific changes.
----------------------------------------------------------------------
Section: New in release 0.95.1
----------------------------------------------------------------------
Fixed a bug: Anonymous forward labels were allowed to be redefined.
Tweaked type system: When negating a value, address reference count
will now be negated as well.
When using type system, label dump file will now contain "!addr" to
mark addresses.
Changed "label" to "symbol" in a lot of code, error messages and docs.
----------------------------------------------------------------------
Section: New in release 0.95
----------------------------------------------------------------------

View File

@ -55,6 +55,13 @@ Bug in ACME, code follows
C-style "==" comparison detected.
To check for equality, use a single '=' character instead.
Converted to integer for binary logic operator.
Applying binary logic to float values does not make much sense,
therefore floats will be converted to integer in this case.
"EOR" is deprecated; use "XOR" instead.
This means the operator, not the mnemonic.
Found old "!for" syntax.
Please update your sources to use the new "!for" syntax. See
AllPOs.txt for details.
@ -64,23 +71,23 @@ Found new "!for" syntax.
When using the "-Wno-old-for" switch to disable the warning about
the older syntax, the new syntax will trigger this warning.
Implicit label definition not in leftmost column.
An implicit label definition has blanks before the label name.
Label dump file already chosen.
The "!sl" command was given more than once (or in addition to the
"--labeldump" command line option). Only use it once.
Label name not in leftmost column.
A label definition has blanks before the label name.
Imagine this source code:
lda #00
imx
rts
Obviously, there's a typo in the middle line (imx instead of inx),
but ACME does not recognize this: It looks just like an implicit
label definition! Therefore releases 0.89 and higher warn you when
an implicit label does not start in column 1. Releases 0.94 and
higher support a command line option to switch off this warning
but ACME does not recognize this: It looks just like a label
definition! Therefore releases 0.89 and higher warn you when a
label name does not start in column 1. Releases 0.94 and higher
support a command line option to switch off this warning
("-Wno-label-indent").
Label dump file already chosen.
The "!sl" command was given more than once (or in addition to the
"--labeldump" command line option). Only use it once.
Label name starts with a shift-space character.
The name of a global label starts with a shift-space character. It
is highly likely that this is a typing error, therefore this
@ -122,7 +129,7 @@ Using oversized addressing mode.
the argument's value in the first pass, therefore assuming a 16-
bit addressing mode. If, in a later pass, ACME finds out that the
argument is small enough to fit in 8 bits, then this warning is
shown. If you define all your zeropage labels *before* they are
shown. If you define all your zeropage symbols *before* they are
first used, this shouldn't happen. If you know that a specific
argument fits in 8 bits, you can force ACME to use 8 bits
addressing by postfixing the command with "+1". Example:
@ -202,10 +209,6 @@ Illegal combination of command and postfix.
Illegal postfix.
You used a postfix other than "+1", "+2" or "+3".
Label already defined.
You defined a label that already had a different value. To change
a label's value, use the "!set" pseudo opcode.
Macro already defined.
Macros can only be defined once. If you define a macro twice, ACME
will help you find the definitions by giving a warning for the
@ -219,7 +222,7 @@ Macro not defined (or wrong signature).
formal parameters and the call's actual arguments.
Macro parameter twice.
The same label name is used two (or more) times in the same macro
The same symbol name is used two (or more) times in the same macro
parameter list.
Negative value - cannot choose addressing mode.
@ -244,6 +247,10 @@ Quotes still open at end of line.
Source file contains illegal character.
Your source code file contained a null byte.
Symbol already defined.
You defined a symbol that already had a different value. To change
a symbol's value, use the "!set" pseudo opcode.
Syntax error.
Guess what - there's a syntax error.
@ -263,7 +270,7 @@ There's more than one character.
contained more than a single character.
Too late for postfix.
You can only postfix labels at the start, before they are used for
You can only postfix symbols at the start, before they are used for
the first time.
Too many '('.
@ -291,7 +298,7 @@ Unknown "* =" segment modifier.
You used a modifier keyword ACME does not know.
Value not yet defined.
A value could not be worked out. Maybe you mistyped a label name.
A value could not be worked out. Maybe you mistyped a symbol name.
Whether this is given as a "normal" or as a serious error depends
on the currently parsed pseudo opcode.
@ -346,7 +353,7 @@ Too deeply nested. Recursive "!source"?
64.
Value not yet defined.
A value could not be worked out. Maybe you mistyped a label name.
A value could not be worked out. Maybe you mistyped a symbol name.
Whether this is given as a "normal" or as a serious error depends
on the currently parsed pseudo opcode.

View File

@ -98,8 +98,8 @@ ACME's maths parser has no problems concerning parentheses and
indirect addressing modes.
ACME's maths parser knows a shit load of different operations.
ACME supports both integer and floating point maths operations.
You can dump the global labels into a file.
ACME supports a library of commonly used macros and labels.
You can dump the global symbols into a file.
ACME supports a library of commonly used macros and symbols.
It always takes as many passes as are needed.
ACME exists on several platforms, meaning you can easily exchange your
sources with other people (preferring other OSes).
@ -152,7 +152,7 @@ A minor problem is the different character tables used on different
systems. As all predefined ACME keywords only use 7-bit ASCII, the
assembler will work on any system that uses a superset of this
character table: UTF-8, ANSI, ISO 8859, etc.
Label names can contain top-bit-set characters - these may look
Symbol names can contain top-bit-set characters - these may look
strange if the sources are edited on a different platform, but ACME
will still work.

View File

@ -21,7 +21,7 @@ Section: Example of what an ACME source code file looks like
!to "tiny.o", cbm ; set output file and format
* = $c000 ; set program counter
CLEAR = 147 ; a global label definition
CLEAR = 147 ; a global symbol definition
!addr basout = $ffd2 ; another one, marked as an address
; a string output loop:
@ -49,11 +49,11 @@ Here's the same fragment again, now with some additional info:
* = $c000 ; set program counter
; This can also be done using the command line option "--setpc".
; some global label definitions
; some global symbol definitions
CLEAR = 147 ; this is a simple constant
; Now "CLEAR" is defined as a global label having the value 147.
; Now "CLEAR" is defined as a global symbol having the value 147.
!addr basout = $ffd2 ; this gets marked as an address
; Now "basout" is defined as a global "address" type label having the
; Now "basout" is defined as a global "address" type symbol having the
; value $ffd2.
; The distinction between addresses and non-addresses only
; matters when the type check system gets activated using
@ -65,20 +65,20 @@ Here's the same fragment again, now with some additional info:
ldx #0
beq + ; enter loop
; "+" is an anonymous forward label. Other ones are "++", "+++", etc.
; They can be used like any other label, but they always reference
; They can be used like any other symbol, but they always reference
; their *NEXT* definition. This saves having to think of names for
; unimportant labels. As the label's value is not defined yet, ACME
; will need to perform a second pass.
- jsr basout ; output character
; "-" is an anonymous backward label. Other ones are "--", "---", etc.
; They can be used like any other label, but they always reference
; They can be used like any other symbol, but they always reference
; their *PREVIOUS* definition. This saves having to think of names for
; unimportant labels. In the line above, the value of "-" is set to
; the current program counter.
inx ; advance pointer
+ lda .string,x ; get character
; Here the value of "+" is set to the current program counter.
; ".string" is a local label (because its name starts with a '.'
; ".string" is a local symbol (because its name starts with a '.'
; character), but as its value is not defined yet, ACME will need to
; perform a second pass.
bne - ; check whether last
@ -97,12 +97,12 @@ As you can see, pseudo opcodes are prefixed with an exclamation mark.
That's non-standard, but: Backwards compatibility is the root of all
evil. :)
Summary about labels:
Summary about symbols:
There are global labels (their names starting with a letter or an
There are global symbols (their names starting with a letter or an
underscore character). These can be accessed throughout the whole
assembly.
Then there are local labels (their names starting with a '.'
Then there are local symbols (their names starting with a '.'
character). These can only be accessed from inside the macro or zone
they were defined in (for more about macros and zones, see the file
"AllPOs.txt").
@ -112,7 +112,7 @@ macro/zone), but in addition to that, the "-" labels can only be used
for backward references, while the "+" labels can only be used for
forward references.
In contrast to global and local labels, anonymous labels can not be
defined explicitly (as in LABEL = VALUE).
defined explicitly (as in SYMBOL = VALUE).
Save the given example source code to a file called "tiny.a" and start
acme by typing
@ -144,7 +144,7 @@ found in the file "AllPOs.txt". Here's just a short overview:
...for directly placing values into the output file.
!zone !sl
...for defining the scope of local labels and saving global labels.
...for defining the scope of local symbols and saving global symbols.
!convtab !pet !raw !scr !scrxor !text
...for converting and outputting strings.
@ -171,7 +171,7 @@ found in the file "AllPOs.txt". Here's just a short overview:
...for generating warnings, errors and serious errors.
!addr
...to mark labels as addresses, for the optional type check system.
...to mark symbols as addresses, for the optional type check system.
----------------------------------------------------------------------
@ -231,7 +231,7 @@ Available options are:
In addition to the "-v2" output, ACME will now announce
each source file.
-DLABEL=VALUE define global label
-DSYMBOL=VALUE define global symbol
This option is useful if you build your projects using
Makefiles: "-DSYSTEM=64" could build the C64 version while
"-DSYSTEM=128" could build the C128 version of the software
@ -239,8 +239,8 @@ Available options are:
-W fine-tune amount and type of warnings
-Wno-label-indent
Disables warnings about implicit label definitions not
being in the leftmost column.
Disables warnings about labels not being in the leftmost
column.
-Wno-old-for
Disables warnings about the old "!for" syntax and at the
same time enables warnings about the _new_ "!for" syntax.
@ -269,8 +269,8 @@ shifts, negation, boolean operations and some assembler-specific stuff
like extracting the "low byte", the "high byte" or the "bank byte"
of a value.
Calculations are done using either signed 32-bit integer arithmetic or
floating point arithmetic using the C "double" data type. Label values
are stored the same way.
floating point arithmetic using the C "double" data type. Symbol
values are stored the same way.
This is a list of the operators currently known by ACME:
@ -350,8 +350,8 @@ $d011 hexadecimal values are indicated by either a
'q' quotes. The actual numeric value depends on the
current conversion table (none/petscii/screen),
chosen using the "!ct" pseudo opcode.
poll_joy2 a global label
.fail a local label, indicated by leading dot
poll_joy2 a global symbol
.fail a local symbol, indicated by leading dot
* the current program counter. During offset assembly,
"*" gives the value of the "Pseudo PC". Just to
make sure: The value of the program counter is
@ -376,24 +376,23 @@ optional comment. Statements have to be separated from each other
using colon (":") characters, the comment has to be prefixed with a
semicolon (";") character.
Every statement consists of an optional "implicit label definition"
and an optional "command". These are separated from each other using
any number of SPACE or TAB characters. If an implicit label definition
has blanks before it, a warning is given (to spot typing errors - see
Errors.txt for more info).
Every statement consists of an optional "label" and an optional
"command". These are separated from each other using any number of
SPACE or TAB characters. If a label has blanks before it, a warning is
issued (to spot typing errors - see Errors.txt for more info).
Every label consists of these characters: "a" to "z", "A" to "Z", "0"
to "9", the underscore character "_" and all characters with values
beyond 127. The first character must not be a digit though. But it can
be a dot ("."), making the label a local one. Two other possibilities
for label names are "all-characters-are-minus" (then it's an anonymous
backward label) and "all-characters-are-plus" (then it's an anonymous
forward label).
Every symbol name consists of these characters: "a" to "z", "A" to
"Z", "0" to "9", the underscore character "_" and all characters with
values beyond 127. The first character must not be a digit though. But
it can be a dot ("."), making the symbol a local one. Two other
possibilities for label names are "all-characters-are-minus" (then it
is an anonymous backward label) and "all-characters-are-plus" (then it
is an anonymous forward label).
Every command is one of the following:
An assembler opcode
A pseudo opcode, beginning with a "!" character
An explicit label definition (label=value)
A symbol definition (symbol=value)
A pc definition, beginning with a "*" character
A macro call, beginning with a "+" character
...and the syntax of those things varies. :)
@ -404,5 +403,5 @@ whether you write "LDA" or "lda" or "LdA" does not make a difference.
In earlier releases of ACME, arithmetic operators like MOD, XOR, LSL
had to be written in UPPER CASE. This is no longer needed.
Label names are case sensitive, so "label" and "Label" are two
Symbol names are case sensitive, so "label" and "Label" are two
different things.

View File

@ -8,7 +8,7 @@ RM = rm
PROGS = acme
BINDIR = /usr/local/bin
USERBIN = $(HOME)/bin
OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o
OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o
all: $(PROGS)
@ -17,9 +17,9 @@ acme: $(OBJS)
strip acme
acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h label.h macro.h mnemo.h output.h section.h acme.h acme.c
acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h section.h symbol.h acme.h acme.c
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h label.h section.h tree.h alu.h alu.c
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h section.h symbol.h tree.h alu.h alu.c
cliargs.o: cliargs.h cliargs.c
@ -29,15 +29,13 @@ dynabuf.o: config.h acme.h global.h input.h dynabuf.h dynabuf.c
encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h encoding.h encoding.c
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h macro.h mnemo.h tree.h flow.h flow.c
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h macro.h mnemo.h tree.h symbol.h flow.h flow.c
global.o: config.h platform.h acme.h cpu.h input.h label.h macro.h section.h global.h global.c
global.o: config.h platform.h acme.h cpu.h input.h macro.h section.h symbol.h global.h global.c
input.o: config.h dynabuf.h global.h section.h tree.h input.h input.c
label.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h label.h label.c
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h section.h tree.h macro.h macro.c
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h section.h symbol.h tree.h macro.h macro.c
mnemo.o: config.h alu.h cpu.h dynabuf.h global.h input.h output.h tree.h mnemo.h mnemo.c
@ -47,7 +45,9 @@ platform.o: config.h platform.h platform.c
section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c
tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h symbol.h symbol.c
tree.o: config.h dynabuf.h global.h symbol.h tree.h tree.c
typesystem.o: config.h global.h typesystem.h typesystem.c

View File

@ -8,7 +8,7 @@ RM = rm
PROGS = acme
#BINDIR = /usr/local/bin
#USERBIN = $(HOME)/bin
OBJS = acme.o alu.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o
OBJS = acme.o alu.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o
all: $(PROGS)
@ -18,9 +18,9 @@ acme: $(OBJS)
djp acme.exe
djp acmepmod.exe
acme.o: config.h platform.h acme.h alu.h cpu.h dynabuf.h encoding.h flow.h global.h input.h label.h macro.h mnemo.h output.h section.h acme.h acme.c
acme.o: config.h platform.h acme.h alu.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h section.h symbol.h acme.h acme.c
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h label.h section.h tree.h alu.h alu.c
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h section.h symbol.h tree.h alu.h alu.c
cliargs.o: cliargs.h cliargs.c
@ -30,15 +30,13 @@ dynabuf.o: config.h acme.h global.h input.h dynabuf.h dynabuf.c
encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h encoding.h encoding.c
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h macro.h mnemo.h tree.h flow.h flow.c
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h macro.h mnemo.h symbol.h tree.h flow.h flow.c
global.o: config.h platform.h acme.h cpu.h input.h label.h macro.h section.h global.h global.c
global.o: config.h platform.h acme.h cpu.h input.h macro.h section.h symbol.h global.h global.c
input.o: config.h dynabuf.h global.h section.h tree.h input.h input.c
label.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h label.h label.c
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h section.h tree.h macro.h macro.c
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h section.h symbol.h tree.h macro.h macro.c
mnemo.o: config.h alu.h cpu.h dynabuf.h global.h input.h output.h tree.h mnemo.h mnemo.c
@ -48,7 +46,9 @@ platform.o: config.h platform.h platform.c
section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c
tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h symbol.h symbol.c
tree.o: config.h dynabuf.h global.h symbol.h tree.h tree.c
typesystem.o: config.h global.h typesystem.h typesystem.c

View File

@ -15,15 +15,15 @@ USERBIN = $(HOME)/bin
all: $(PROGS)
acme.exe: acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o_dos.o resource.res
$(CC) $(LIBS) $(CFLAGS) -o acme acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o resource.res
acme.exe: acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o_dos.o resource.res
$(CC) $(LIBS) $(CFLAGS) -o acme acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o resource.res
strip acme.exe
acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h label.h macro.h mnemo.h output.h section.h acme.h _dos.h acme.c
acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h section.h symbol.h acme.h _dos.h acme.c
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h label.h section.h tree.h alu.h alu.c
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h section.h symbol.h tree.h alu.h alu.c
cliargs.o: cliargs.h cliargs.c
@ -33,15 +33,13 @@ dynabuf.o: config.h acme.h global.h input.h dynabuf.h dynabuf.c
encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h encoding.h encoding.c
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h macro.h mnemo.h tree.h flow.h flow.c
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h macro.h mnemo.h symbol.h tree.h flow.h flow.c
global.o: config.h platform.h acme.h cpu.h input.h label.h macro.h section.h global.h global.c
global.o: config.h platform.h acme.h cpu.h input.h macro.h section.h symbol.h global.h global.c
input.o: config.h dynabuf.h global.h section.h tree.h input.h input.c
label.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h label.h label.c
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h section.h tree.h macro.h macro.c
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h section.h symbol.h tree.h macro.h macro.c
mnemo.o: config.h alu.h cpu.h dynabuf.h global.h input.h output.h tree.h mnemo.h mnemo.c
@ -51,7 +49,9 @@ platform.o: config.h platform.h platform.c
section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c
tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h symbol.h symbol.c
tree.o: config.h dynabuf.h global.h symbol.h tree.h tree.c
typesystem.o: config.h global.h typesystem.h typesystem.c

View File

@ -8,7 +8,7 @@ RM = rm
PROGS = acme
#BINDIR = /usr/local/bin
#USERBIN = $(HOME)/bin
OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o
OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o
all: $(PROGS)
@ -16,9 +16,9 @@ acme: $(OBJS)
$(CC) $(CFLAGS) -o !Unsqueezed $(OBJS) $(LIBS)
Squeeze -f -v !Unsqueezed !ACME.!RunImage
acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h label.h macro.h mnemo.h output.h section.h acme.h acme.c
acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h section.h symbol.h acme.h acme.c
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h label.h section.h tree.h alu.h alu.c
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h section.h symbol.h tree.h alu.h alu.c
basics.o: config.h alu.h cpu.h dynabuf.h input.h global.h output.h tree.h basics.h basics.c
@ -30,15 +30,13 @@ dynabuf.o: config.h acme.h global.h input.h dynabuf.h dynabuf.c
encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h encoding.h encoding.c
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h macro.h mnemo.h tree.h flow.h flow.c
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h macro.h mnemo.h symbol.h tree.h flow.h flow.c
global.o: config.h platform.h acme.h cpu.h input.h label.h macro.h output.h section.h tree.h global.h global.c
global.o: config.h platform.h acme.h cpu.h input.h macro.h output.h section.h symbol.h tree.h global.h global.c
input.o: config.h alu.h dynabuf.h global.h section.h tree.h input.h input.c
label.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h section.h tree.h label.h label.c
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h section.h tree.h macro.h macro.c
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h section.h symbol.h tree.h macro.h macro.c
mnemo.o: config.h alu.h cpu.h dynabuf.h global.h input.h output.h tree.h mnemo.h mnemo.c
@ -48,7 +46,9 @@ platform.o: config.h platform.h platform.c
section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c
tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h section.h tree.h symbol.h symbol.c
tree.o: config.h dynabuf.h global.h symbol.h tree.h tree.c
typesystem.o: config.h global.h typesystem.h typesystem.c

View File

@ -15,9 +15,9 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define RELEASE "0.95" // update before release (FIXME)
#define RELEASE "0.95.1" // update before release (FIXME)
#define CODENAME "Fenchurch" // update before release
#define CHANGE_DATE "2 Jun" // update before release
#define CHANGE_DATE "7 Jun" // update before release
#define CHANGE_YEAR "2014" // update before release
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" // FIXME
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
@ -36,12 +36,12 @@
#include "flow.h"
#include "global.h"
#include "input.h"
#include "label.h"
#include "macro.h"
#include "mnemo.h"
#include "output.h"
#include "platform.h"
#include "section.h"
#include "symbol.h"
// constants
@ -75,7 +75,7 @@ static int toplevel_src_count = 0;
static signed long start_address = ILLEGAL_START_ADDRESS;
static signed long fill_value = MEMINIT_USE_DEFAULT;
static const struct cpu_type *default_cpu = NULL;
const char *labeldump_filename = NULL;
const char *symboldump_filename = NULL;
const char *output_filename = NULL;
// maximum recursion depth for macro calls and "!source"
signed long macro_recursions_left = MAX_NESTING;
@ -124,7 +124,7 @@ static void show_help_and_exit(void)
" --" OPTION_MAXERRORS " NUMBER set number of errors before exiting\n"
" --" OPTION_MAXDEPTH " NUMBER set recursion depth for macro calls and !src\n"
" -vDIGIT set verbosity level\n"
" -DLABEL=VALUE define global label\n"
" -DSYMBOL=VALUE define global symbol\n"
// as long as there is only one -W option:
#define OPTIONWNO_LABEL_INDENT "no-label-indent"
" -W" OPTIONWNO_LABEL_INDENT " suppress warnings about indented labels\n"
@ -141,20 +141,20 @@ PLATFORM_OPTION_HELP
// error handling
// tidy up before exiting by saving label dump
// tidy up before exiting by saving symbol dump
int ACME_finalize(int exit_code)
{
FILE *fd;
if (labeldump_filename) {
fd = fopen(labeldump_filename, FILE_WRITETEXT);
if (symboldump_filename) {
fd = fopen(symboldump_filename, FILE_WRITETEXT);
if (fd) {
Label_dump_all(fd);
symbols_dump_all(fd);
fclose(fd);
} else {
fprintf(stderr,
"Error: Cannot open label dump file \"%s\".\n",
labeldump_filename);
symboldump_filename);
exit_code = EXIT_FAILURE;
}
}
@ -344,8 +344,8 @@ static void set_mem_contents(void)
}
// define label
static void define_label(const char definition[])
// define symbol
static void define_symbol(const char definition[])
{
const char *walk = definition;
signed long value;
@ -358,7 +358,7 @@ static void define_label(const char definition[])
could_not_parse(definition);
value = string_to_number(walk + 1);
DynaBuf_append(GlobalDynaBuf, '\0');
Label_define(value);
symbol_define(value);
}
@ -372,7 +372,7 @@ static const char *long_option(const char *string)
else if (strcmp(string, OPTION_OUTFILE) == 0)
output_filename = cliargs_safe_get_next(name_outfile);
else if (strcmp(string, OPTION_LABELDUMP) == 0)
labeldump_filename = cliargs_safe_get_next(name_dumpfile);
symboldump_filename = cliargs_safe_get_next(name_dumpfile);
else if (strcmp(string, OPTION_SETPC) == 0)
set_starting_pc();
else if (strcmp(string, OPTION_CPU) == 0)
@ -402,7 +402,7 @@ static char short_option(const char *argument)
while (*argument) {
switch (*argument) {
case 'D': // "-D" define constants
define_label(argument + 1);
define_symbol(argument + 1);
goto done;
case 'h': // "-h" shows help
show_help_and_exit();
@ -412,8 +412,8 @@ static char short_option(const char *argument)
case 'o': // "-o" selects output filename
output_filename = cliargs_safe_get_next(name_outfile);
break;
case 'l': // "-l" selects label dump filename
labeldump_filename = cliargs_safe_get_next(name_dumpfile);
case 'l': // "-l" selects symbol dump filename
symboldump_filename = cliargs_safe_get_next(name_dumpfile);
break;
case 'v': // "-v" changes verbosity
Process_verbosity++;
@ -465,7 +465,7 @@ int main(int argc, const char *argv[])
PLATFORM_INIT;
// init some keyword trees needed for argument handling
CPUtype_init();
Label_clear_init(); // needed so
symbols_clear_init(); // needed so
Outputfile_init();
// prepare a buffer large enough to hold pointers to "-D" switch values
// cli_defines = safe_malloc(argc * sizeof(*cli_defines));
@ -481,7 +481,7 @@ int main(int argc, const char *argv[])
Encoding_init();
Flow_init();
Input_init();
Label_register_init();
symbols_register_init();
Macro_init();
Mnemo_init();
Output_init(fill_value);

View File

@ -1,5 +1,5 @@
// ACME - a crossassembler for producing 6502/65c02/65816 code.
// Copyright (C) 1998-2009 Marco Baye
// Copyright (C) 1998-2014 Marco Baye
// Have a look at "acme.c" for further info
//
// Main definitions
@ -11,7 +11,7 @@
// Variables
extern const char *labeldump_filename;
extern const char *symboldump_filename;
extern const char *output_filename;
// maximum recursion depth for macro calls and "!source"
extern signed long macro_recursions_left;
@ -20,7 +20,7 @@ extern signed long source_recursions_left;
// Prototypes
// Tidy up before exiting by saving label dump
// tidy up before exiting by saving symbol dump
extern int ACME_finalize(int exit_code);

View File

@ -19,9 +19,9 @@
#include "encoding.h"
#include "global.h"
#include "input.h"
#include "label.h"
#include "output.h"
#include "section.h"
#include "symbol.h"
#include "tree.h"
@ -146,7 +146,7 @@ static struct dynabuf *function_dyna_buf; // dynamic buffer for fn names
static struct operator **operator_stack = NULL;
static int operator_stk_size = HALF_INITIAL_STACK_SIZE;
static int operator_sp; // operator stack pointer
static struct result_t *operand_stack = NULL; // flags and value
static struct result *operand_stack = NULL; // flags and value
static int operand_stk_size = HALF_INITIAL_STACK_SIZE;
static int operand_sp; // value stack pointer
static int indirect_flag; // Flag for indirect addressing
@ -313,21 +313,21 @@ static intval_t my_asr(intval_t left, intval_t right)
}
// Lookup (and create, if necessary) label tree item and return its value.
// DynaBuf holds the label's name and "zone" its zone.
// Lookup (and create, if necessary) symbol tree item and return its value.
// DynaBuf holds the symbol's name and "zone" its zone.
// This function is not allowed to change DynaBuf because that's where the
// label name is stored!
static void get_label_value(zone_t zone)
// symbol name is stored!
static void get_symbol_value(zone_t zone)
{
struct label *label;
struct symbol *symbol;
// if the label gets created now, mark it as unsure
label = Label_find(zone, MVALUE_UNSURE);
// if the symbol gets created now, mark it as unsure
symbol = symbol_find(zone, MVALUE_UNSURE);
// in first pass, count usage
if (pass_count == 0)
label->usage++;
symbol->usage++;
// push operand, regardless of whether int or float
operand_stack[operand_sp] = label->result;
operand_stack[operand_sp] = symbol->result;
operand_stack[operand_sp++].flags |= MVALUE_EXISTS;
}
@ -542,7 +542,7 @@ static void parse_octal_value(void) // Now GotByte = "&"
// Parse program counter ('*')
static void parse_program_counter(void) // Now GotByte = "*"
{
struct result_t pc;
struct result pc;
GetByte();
vcpu_read_pc(&pc);
@ -579,8 +579,8 @@ static void expect_operand_or_monadic_operator(void)
do
DYNABUF_APPEND(GlobalDynaBuf, '+');
while (GetByte() == '+');
Label_fix_forward_name();
get_label_value(Section_now->zone);
symbol_fix_forward_anon_name(FALSE); // FALSE: do not increment counter
get_symbol_value(Section_now->zone);
goto now_expect_dyadic;
case '-': // NEGATION operator or anonymous backward label
@ -594,7 +594,7 @@ static void expect_operand_or_monadic_operator(void)
SKIPSPACE();
if (BYTEFLAGS(GotByte) & FOLLOWS_ANON) {
DynaBuf_append(GlobalDynaBuf, '\0');
get_label_value(Section_now->zone);
get_symbol_value(Section_now->zone);
goto now_expect_dyadic;
}
@ -656,7 +656,7 @@ static void expect_operand_or_monadic_operator(void)
goto now_expect_dyadic;
// FIXME - find a way to tell decimal point and LOCAL_PREFIX apart!
case '.': // Local label or fractional part of float value
case '.': // local symbol or fractional part of float value
GetByte(); // start after '.'
// check for fractional part of float value
if ((GotByte >= '0') && (GotByte <= '9')) {
@ -667,13 +667,13 @@ static void expect_operand_or_monadic_operator(void)
if (Input_read_keyword()) {
// Now GotByte = illegal char
get_label_value(Section_now->zone);
get_symbol_value(Section_now->zone);
goto now_expect_dyadic;
}
alu_state = STATE_ERROR;
break;
// Decimal values and global labels
// decimal values and global symbols
default: // all other characters
if ((GotByte >= '0') && (GotByte <= '9')) {
parse_decimal_value();
@ -698,7 +698,7 @@ static void expect_operand_or_monadic_operator(void)
if (GotByte == '(') {
parse_function_call();
} else {
get_label_value(ZONE_GLOBAL);
get_symbol_value(ZONE_GLOBAL);
goto now_expect_dyadic;
}
@ -1061,6 +1061,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
else
RIGHT_INTVAL = -(RIGHT_INTVAL);
RIGHT_FLAGS &= ~MVALUE_ISBYTE;
RIGHT_ADDRREFS = -RIGHT_ADDRREFS; // negate address ref count as well
goto remove_next_to_last_operator;
case OPHANDLE_LOWBYTEOF:
@ -1346,7 +1347,7 @@ RNTLObutDontTouchIndirectFlag:
// The core of it. Returns number of parentheses left open.
// FIXME - make state machine using function pointers? or too slow?
static int parse_expression(struct result_t *result)
static int parse_expression(struct result *result)
{
int open_parentheses = 0;
@ -1427,31 +1428,13 @@ static int parse_expression(struct result_t *result)
}
// These functions handle numerical expressions.
// There are several different ways to call the core function:
// intval_t ALU_any_int(void);
// returns int value (0 if result was undefined)
// intval_t ALU_defined_int(void);
// returns int value
// if result was undefined, serious error is thrown
// void ALU_int_result(result_int_t*);
// stores int value and flags (floats are transformed to int)
// void ALU_any_result(result_t*);
// stores value and flags (result may be either int or float)
// int ALU_liberal_int(result_int_t*);
// stores int value and flags. allows one '(' too many (for x-
// indirect addressing). returns number of additional '(' (1 or 0).
// int ALU_optional_defined_int(intval_t*);
// stores int value if given. Returns whether stored.
// Throws error if undefined.
// return int value (if result is undefined, returns zero)
// If the result's "exists" flag is clear (=empty expression), it throws an
// error.
// If the result's "defined" flag is clear, result_is_undefined() is called.
intval_t ALU_any_int(void)
{
struct result_t result;
struct result result;
if (parse_expression(&result))
Throw_error(exception_paren_open);
@ -1469,7 +1452,7 @@ intval_t ALU_any_int(void)
// return int value (if result is undefined, serious error is thrown)
intval_t ALU_defined_int(void)
{
struct result_t result;
struct result result;
if (parse_expression(&result))
Throw_error(exception_paren_open);
@ -1489,7 +1472,7 @@ intval_t ALU_defined_int(void)
// throws a serious error and therefore stops assembly.
int ALU_optional_defined_int(intval_t *target)
{
struct result_t result;
struct result result;
if (parse_expression(&result))
Throw_error(exception_paren_open);
@ -1510,7 +1493,7 @@ int ALU_optional_defined_int(intval_t *target)
// It the result's "exists" flag is clear (=empty expression), it throws an
// error.
// If the result's "defined" flag is clear, result_is_undefined() is called.
void ALU_int_result(struct result_t *intresult)
void ALU_int_result(struct result *intresult)
{
if (parse_expression(intresult))
Throw_error(exception_paren_open);
@ -1530,7 +1513,7 @@ void ALU_int_result(struct result_t *intresult)
// This function allows for one '(' too many. Needed when parsing indirect
// addressing modes where internal indices have to be possible. Returns number
// of parentheses still open (either 0 or 1).
int ALU_liberal_int(struct result_t *intresult)
int ALU_liberal_int(struct result *intresult)
{
int parentheses_still_open;
@ -1555,7 +1538,7 @@ int ALU_liberal_int(struct result_t *intresult)
// It the result's "exists" flag is clear (=empty expression), it throws an
// error.
// If the result's "defined" flag is clear, result_is_undefined() is called.
void ALU_any_result(struct result_t *result)
void ALU_any_result(struct result *result)
{
if (parse_expression(result))
Throw_error(exception_paren_open);

View File

@ -12,31 +12,21 @@
// constants
// meaning of bits in "flags" of result_t structure:
#define MVALUE_IS_FP (1u << 8)
// floating point value
#define MVALUE_INDIRECT (1u << 7)
// needless parentheses indicate use of indirect addressing modes
#define MVALUE_EXISTS (1u << 6)
// 0: expression was empty. 1: there was *something* to parse.
#define MVALUE_UNSURE (1u << 5)
// value once was related to undefined expression. Needed for producing
// the same addresses in all passes; because in the first pass there
// will almost for sure be labels that are undefined, you can't simply
// get the addressing mode from looking at the parameter's value.
#define MVALUE_DEFINED (1u << 4)
// 0: undefined expression (value will be zero). 1: known result
#define MVALUE_ISBYTE (1u << 3)
// value is guaranteed to fit in one byte
#define MVALUE_FORCE24 (1u << 2)
// value usage forces 24-bit usage
#define MVALUE_FORCE16 (1u << 1)
// value usage forces 16-bit usage
#define MVALUE_FORCE08 (1u << 0)
// value usage forces 8-bit usage
// meaning of bits in "flags" of struct result:
#define MVALUE_IS_FP (1u << 8) // floating point value
#define MVALUE_INDIRECT (1u << 7) // needless parentheses indicate use of indirect addressing modes
#define MVALUE_EXISTS (1u << 6) // 0: expression was empty. 1: there was *something* to parse.
#define MVALUE_UNSURE (1u << 5) // value once was related to undefined
// expression. Needed for producing the same addresses in all passes; because in
// the first pass there will almost for sure be labels that are undefined, you
// can't simply get the addressing mode from looking at the parameter's value.
#define MVALUE_DEFINED (1u << 4) // 0: undefined expression (value will be zero). 1: known result
#define MVALUE_ISBYTE (1u << 3) // value is guaranteed to fit in one byte
#define MVALUE_FORCE24 (1u << 2) // value usage forces 24-bit usage
#define MVALUE_FORCE16 (1u << 1) // value usage forces 16-bit usage
#define MVALUE_FORCE08 (1u << 0) // value usage forces 8-bit usage
#define MVALUE_FORCEBITS (MVALUE_FORCE08|MVALUE_FORCE16|MVALUE_FORCE24)
#define MVALUE_GIVEN (MVALUE_DEFINED | MVALUE_EXISTS)
// bit mask for fixed values (defined and existing)
#define MVALUE_GIVEN (MVALUE_DEFINED | MVALUE_EXISTS) // bit mask for fixed values (defined and existing)
// create dynamic buffer, operator/function trees and operator/operand stacks
@ -48,13 +38,14 @@ extern intval_t ALU_any_int(void);
// returns int value (if result was undefined, serious error is thrown)
extern intval_t ALU_defined_int(void);
// stores int value if given. Returns whether stored. Throws error if undefined.
extern int ALU_optional_defined_int(intval_t *);
extern int ALU_optional_defined_int(intval_t *target);
// stores int value and flags (floats are transformed to int)
extern void ALU_int_result(struct result_t *);
// stores int value and flags, allowing for one '(' too many (x-indirect addr)
extern int ALU_liberal_int(struct result_t *);
extern void ALU_int_result(struct result *intresult);
// stores int value and flags, allowing for one '(' too many (x-indirect addr).
// returns number of additional '(' (1 or 0).
extern int ALU_liberal_int(struct result *intresult);
// stores value and flags (result may be either int or float)
extern void ALU_any_result(struct result_t *);
extern void ALU_any_result(struct result *result);
#endif

View File

@ -156,7 +156,7 @@ static enum eos PO_addr(void) // Now GotByte = illegal char
// show user-defined message
static enum eos throw_string(const char prefix[], void (*fn)(const char *))
{
struct result_t result;
struct result result;
DYNABUF_CLEAR(user_message);
DynaBuf_add_string(user_message, prefix);

View File

@ -12,7 +12,7 @@ typedef unsigned int zone_t;
typedef signed long intval_t; // at least 32 bits
typedef unsigned long uintval_t; // just for logical shift right
// result structure type definition with support for floating point
struct result_t { // either int or float
struct result { // either int or float
int flags; // expression flags
union {
intval_t intval; // integer value

View File

@ -18,9 +18,9 @@
#include "dynabuf.h"
#include "global.h"
#include "input.h"
#include "label.h"
#include "macro.h"
#include "mnemo.h"
#include "symbol.h"
#include "tree.h"
@ -185,14 +185,14 @@ static enum eos PO_for(void) // Now GotByte = illegal char
{
struct input loop_input,
*outer_input;
struct result_t loop_counter;
struct result loop_counter;
intval_t first_arg,
counter_first,
counter_last,
counter_increment;
int old_algo; // actually bool
char *loop_body; // pointer to loop's body block
struct label *label;
struct symbol *symbol;
zone_t zone;
int force_bit,
loop_start; // line number of "!for" pseudo opcode
@ -201,7 +201,7 @@ static enum eos PO_for(void) // Now GotByte = illegal char
return SKIP_REMAINDER;
// Now GotByte = illegal char
force_bit = Input_get_force_bit(); // skips spaces after
label = Label_find(zone, force_bit);
symbol = symbol_find(zone, force_bit);
if (!Input_accept_comma()) {
Throw_error(exception_syntax);
return SKIP_REMAINDER;
@ -242,14 +242,14 @@ static enum eos PO_for(void) // Now GotByte = illegal char
// init counter
loop_counter.flags = MVALUE_DEFINED | MVALUE_EXISTS;
loop_counter.val.intval = counter_first;
Label_set_value(label, &loop_counter, TRUE);
symbol_set_value(symbol, &loop_counter, TRUE);
if (old_algo) {
// old algo for old syntax:
// if count == 0, skip loop
if (counter_last) {
do {
loop_counter.val.intval += counter_increment;
Label_set_value(label, &loop_counter, TRUE);
symbol_set_value(symbol, &loop_counter, TRUE);
parse_ram_block(loop_start, loop_body);
} while (loop_counter.val.intval < counter_last);
}
@ -258,7 +258,7 @@ static enum eos PO_for(void) // Now GotByte = illegal char
do {
parse_ram_block(loop_start, loop_body);
loop_counter.val.intval += counter_increment;
Label_set_value(label, &loop_counter, TRUE);
symbol_set_value(symbol, &loop_counter, TRUE);
} while (loop_counter.val.intval != (counter_last + counter_increment));
}
// Free memory
@ -337,30 +337,30 @@ static enum eos PO_if(void) // Now GotByte = illegal char
static enum eos ifdef_ifndef(int invert) // Now GotByte = illegal char
{
struct node_ra_t *node;
struct label *label;
struct symbol *symbol;
zone_t zone;
int defined = FALSE;
if (Input_read_zone_and_keyword(&zone) == 0) // skips spaces before
return SKIP_REMAINDER;
Tree_hard_scan(&node, Label_forest, zone, FALSE);
Tree_hard_scan(&node, symbols_forest, zone, FALSE);
if (node) {
label = (struct label *) node->body;
symbol = (struct symbol *) node->body;
// in first pass, count usage
if (pass_count == 0)
label->usage++;
if (label->result.flags & MVALUE_DEFINED)
symbol->usage++;
if (symbol->result.flags & MVALUE_DEFINED)
defined = TRUE;
}
SKIPSPACE();
// if "ifndef", invert condition
if (invert)
defined = !defined;
if (GotByte == CHAR_SOB)
parse_block_else_block(defined);
else
if (GotByte != CHAR_SOB)
return defined ? PARSE_REMAINDER : SKIP_REMAINDER;
parse_block_else_block(defined);
return ENSURE_EOS;
}

View File

@ -13,10 +13,10 @@
#include "dynabuf.h"
#include "global.h"
#include "input.h"
#include "label.h"
#include "macro.h"
#include "output.h"
#include "section.h"
#include "symbol.h"
#include "tree.h"
#include "typesystem.h"
@ -183,8 +183,8 @@ static int first_label_of_statement(int *statement_flags)
}
// Parse global label definition or assembler mnemonic
static void parse_mnemo_or_global_label_def(int *statement_flags)
// Parse global symbol definition or assembler mnemonic
static void parse_mnemo_or_global_symbol_def(int *statement_flags)
{
// It is only a label if it isn't a mnemonic
if ((CPU_state.type->keyword_is_mnemonic(Input_read_keyword()) == FALSE)
@ -195,23 +195,23 @@ static void parse_mnemo_or_global_label_def(int *statement_flags)
if ((*GLOBALDYNABUF_CURRENT == (char) 0xa0)
|| ((GlobalDynaBuf->size >= 2) && (GLOBALDYNABUF_CURRENT[0] == (char) 0xc2) && (GLOBALDYNABUF_CURRENT[1] == (char) 0xa0)))
Throw_first_pass_warning("Label name starts with a shift-space character.");
Label_parse_definition(ZONE_GLOBAL, *statement_flags);
symbol_parse_definition(ZONE_GLOBAL, *statement_flags);
}
}
// Parse local label definition
static void parse_local_label_def(int *statement_flags)
// parse local symbol definition
static void parse_local_symbol_def(int *statement_flags)
{
if (!first_label_of_statement(statement_flags))
return;
GetByte(); // start after '.'
if (Input_read_keyword())
Label_parse_definition(Section_now->zone, *statement_flags);
symbol_parse_definition(Section_now->zone, *statement_flags);
}
// Parse anonymous backward label definition. Called with GotByte == '-'
// parse anonymous backward label definition. Called with GotByte == '-'
static void parse_backward_anon_def(int *statement_flags)
{
if (!first_label_of_statement(statement_flags))
@ -221,15 +221,13 @@ static void parse_backward_anon_def(int *statement_flags)
DYNABUF_APPEND(GlobalDynaBuf, '-');
while (GetByte() == '-');
DynaBuf_append(GlobalDynaBuf, '\0');
Label_implicit_definition(Section_now->zone, *statement_flags, 0, TRUE);
symbol_set_label(Section_now->zone, *statement_flags, 0, TRUE); // this "TRUE" is the whole secret
}
// Parse anonymous forward label definition. Called with GotByte == ?
// parse anonymous forward label definition. called with GotByte == ?
static void parse_forward_anon_def(int *statement_flags)
{
struct label *counter_label;
if (!first_label_of_statement(statement_flags))
return;
DYNABUF_CLEAR(GlobalDynaBuf);
@ -238,10 +236,9 @@ static void parse_forward_anon_def(int *statement_flags)
DYNABUF_APPEND(GlobalDynaBuf, '+');
GetByte();
}
counter_label = Label_fix_forward_name();
counter_label->result.val.intval++;
symbol_fix_forward_anon_name(TRUE); // TRUE: increment counter
DynaBuf_append(GlobalDynaBuf, '\0');
Label_implicit_definition(Section_now->zone, *statement_flags, 0, TRUE);
symbol_set_label(Section_now->zone, *statement_flags, 0, FALSE);
}
@ -294,11 +291,11 @@ void Parse_until_eob_or_eof(void)
parse_pc_def();
break;
case LOCAL_PREFIX:
parse_local_label_def(&statement_flags);
parse_local_symbol_def(&statement_flags);
break;
default:
if (BYTEFLAGS(GotByte) & STARTS_KEYWORD) {
parse_mnemo_or_global_label_def(&statement_flags);
parse_mnemo_or_global_symbol_def(&statement_flags);
} else {
Throw_error(exception_syntax);
Input_skip_remainder();

View File

@ -1,321 +0,0 @@
// ACME - a crossassembler for producing 6502/65c02/65816 code.
// Copyright (C) 1998-2014 Marco Baye
// Have a look at "acme.c" for further info
//
// Label stuff
//
// 22 Nov 2007 "warn on indented labels" is now a CLI switch
// 25 Sep 2011 Fixed bug in !sl (colons in filename could be interpreted as EOS)
#include <stdio.h>
#include "acme.h"
#include "alu.h"
#include "dynabuf.h"
#include "global.h"
#include "input.h"
#include "label.h"
#include "output.h"
#include "platform.h"
#include "section.h"
#include "tree.h"
#include "typesystem.h"
// constants
#define s_sl (s_asl + 1) // Yes, I know I'm sick
// variables
struct node_ra_t *Label_forest[256]; // ... (because of 8-bit hash)
// Dump label value and flags to dump file
static void dump_one_label(struct node_ra_t *node, FILE *fd)
{
struct label *label = node->body;
// output name
fprintf(fd, "%s", node->id_string);
switch (label->result.flags & MVALUE_FORCEBITS) {
case MVALUE_FORCE16:
fprintf(fd, "+2\t= ");
break;
case MVALUE_FORCE16 | MVALUE_FORCE24:
/*FALLTHROUGH*/
case MVALUE_FORCE24:
fprintf(fd, "+3\t= ");
break;
default:
fprintf(fd, "\t= ");
}
if (label->result.flags & MVALUE_DEFINED) {
if (label->result.flags & MVALUE_IS_FP)
fprintf(fd, "%.30f", label->result.val.fpval); //FIXME %g
else
fprintf(fd, "$%x", (unsigned) label->result.val.intval);
} else {
fprintf(fd, " ?");
}
if (label->result.flags & MVALUE_UNSURE)
fprintf(fd, "\t; ?");
if (label->usage == 0)
fprintf(fd, "\t; unused");
fprintf(fd, "\n");
}
// Search for label. Create if nonexistant. If created, give it flags "flags".
// The label name must be held in GlobalDynaBuf.
struct label *Label_find(zone_t zone, int flags)
{
struct node_ra_t *node;
struct label *label;
int node_created,
force_bits = flags & MVALUE_FORCEBITS;
node_created = Tree_hard_scan(&node, Label_forest, zone, TRUE);
// if node has just been created, create label as well
if (node_created) {
// Create new label structure
label = safe_malloc(sizeof(*label));
// Finish empty label item
label->result.flags = flags;
label->result.addr_refs = 0;
if (flags & MVALUE_IS_FP)
label->result.val.fpval = 0;
else
label->result.val.intval = 0;
label->usage = 0; // usage count
label->pass = pass_count;
node->body = label;
} else {
label = node->body;
}
// make sure the force bits don't clash
if ((node_created == FALSE) && force_bits)
if ((label->result.flags & MVALUE_FORCEBITS) != force_bits)
Throw_error("Too late for postfix.");
return label;
}
// Assign value to label. The function acts upon the label's flag bits and
// produces an error if needed.
void Label_set_value(struct label *label, struct result_t *newvalue, int change_allowed)
{
int oldflags = label->result.flags;
// value stuff
if ((oldflags & MVALUE_DEFINED) && (change_allowed == FALSE)) {
// Label is already defined, so compare new and old values
// if different type OR same type but different value, complain
if (((oldflags ^ newvalue->flags) & MVALUE_IS_FP)
|| ((oldflags & MVALUE_IS_FP)
? (label->result.val.fpval != newvalue->val.fpval)
: (label->result.val.intval != newvalue->val.intval)))
Throw_error("Label already defined.");
} else {
// Label is not defined yet OR redefinitions are allowed
label->result = *newvalue;
}
// flags stuff
// Ensure that "unsure" labels without "isByte" state don't get that
if ((oldflags & (MVALUE_UNSURE | MVALUE_ISBYTE)) == MVALUE_UNSURE)
newvalue->flags &= ~MVALUE_ISBYTE;
if (change_allowed) {
oldflags = (oldflags & MVALUE_UNSURE) | newvalue->flags;
} else {
if ((oldflags & MVALUE_FORCEBITS) == 0)
if ((oldflags & (MVALUE_UNSURE | MVALUE_DEFINED)) == 0)
oldflags |= newvalue->flags & MVALUE_FORCEBITS;
oldflags |= newvalue->flags & ~MVALUE_FORCEBITS;
}
label->result.flags = oldflags;
}
// (Re)set label
static enum eos PO_set(void) // Now GotByte = illegal char
{
struct result_t result;
int force_bit;
struct label *label;
zone_t zone;
if (Input_read_zone_and_keyword(&zone) == 0) // skips spaces before
// Now GotByte = illegal char
return SKIP_REMAINDER;
force_bit = Input_get_force_bit(); // skips spaces after
label = Label_find(zone, force_bit);
if (GotByte != '=') {
Throw_error(exception_syntax);
return SKIP_REMAINDER;
}
// label = parsed value
GetByte(); // proceed with next char
ALU_any_result(&result);
// clear label's force bits and set new ones
label->result.flags &= ~(MVALUE_FORCEBITS | MVALUE_ISBYTE);
if (force_bit) {
label->result.flags |= force_bit;
result.flags &= ~(MVALUE_FORCEBITS | MVALUE_ISBYTE);
}
Label_set_value(label, &result, TRUE);
return ENSURE_EOS;
}
// Select dump file
static enum eos PO_sl(void)
{
// bugfix: first read filename, *then* check for first pass.
// if skipping right away, quoted colons might be misinterpreted as EOS
// FIXME - why not just fix the skipping code to handle quotes? :)
// "!to" has been fixed as well
// read filename to global dynamic buffer
// if no file name given, exit (complaining will have been done)
if (Input_read_filename(FALSE))
return SKIP_REMAINDER;
// only process this pseudo opcode in first pass
if (pass_count)
return SKIP_REMAINDER;
// if label dump file already chosen, complain and exit
if (labeldump_filename) {
Throw_warning("Label dump file already chosen.");
return SKIP_REMAINDER;
}
// get malloc'd copy of filename
labeldump_filename = DynaBuf_get_copy(GlobalDynaBuf);
// ensure there's no garbage at end of line
return ENSURE_EOS;
}
// predefined stuff
static struct node_t pseudo_opcodes[] = {
PREDEFNODE("set", PO_set),
PREDEFLAST(s_sl, PO_sl),
// ^^^^ this marks the last element
};
// Parse implicit label definition (can be either global or local).
// GlobalDynaBuf holds the label name.
void Label_implicit_definition(zone_t zone, int stat_flags, int force_bit, int change)
{
struct result_t pc,
result;
struct label *label;
label = Label_find(zone, force_bit);
// implicit label definition (label)
if ((stat_flags & SF_FOUND_BLANK) && warn_on_indented_labels)
Throw_first_pass_warning("Implicit label definition not in leftmost column.");
vcpu_read_pc(&pc);
result.flags = pc.flags & MVALUE_DEFINED;
result.val.intval = pc.val.intval;
result.addr_refs = pc.addr_refs;
Label_set_value(label, &result, change);
}
// parse label definition (can be either global or local).
// GlobalDynaBuf holds the label name.
void Label_parse_definition(zone_t zone, int stat_flags)
{
struct result_t result;
struct label *label;
int force_bit = Input_get_force_bit(); // skips spaces after
// FIXME - force bit is allowed for implicit label defs?!
if (GotByte == '=') {
// explicit label definition (label = <something>)
label = Label_find(zone, force_bit);
// label = parsed value
GetByte(); // skip '='
ALU_any_result(&result);
// if wanted, mark as address reference
if (typesystem_says_address())
result.addr_refs = 1;
Label_set_value(label, &result, FALSE);
Input_ensure_EOS();
} else {
Label_implicit_definition(zone, stat_flags, force_bit, FALSE);
}
}
// set global label to value, no questions asked (for "-D" switch)
// Name must be held in GlobalDynaBuf.
void Label_define(intval_t value)
{
struct result_t result;
struct label *label;
result.flags = MVALUE_GIVEN;
result.val.intval = value;
label = Label_find(ZONE_GLOBAL, 0);
Label_set_value(label, &result, TRUE);
}
// dump global labels to file
void Label_dump_all(FILE *fd)
{
Tree_dump_forest(Label_forest, ZONE_GLOBAL, dump_one_label, fd);
PLATFORM_SETFILETYPE_TEXT(labeldump_filename);
}
// clear label forest (is done early)
void Label_clear_init(void)
{
struct node_ra_t **ptr;
int ii;
// cut down all the trees (clear pointer table)
ptr = Label_forest;
for (ii = 255; ii >= 0; ii--)
*ptr++ = NULL;
}
// register pseudo opcodes (done later)
void Label_register_init(void)
{
Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes);
}
// fix name of anonymous forward label (held in DynaBuf, NOT TERMINATED!) so it
// references the *next* anonymous forward label definition. The tricky bit is,
// each name length would need its own counter. But hey, ACME's real quick in
// finding labels, so I'll just abuse the label system to store those counters.
struct label *Label_fix_forward_name(void)
{
struct label *counter_label;
unsigned long number;
// terminate name, find "counter" label and read value
DynaBuf_append(GlobalDynaBuf, '\0');
counter_label = Label_find(Section_now->zone, 0);
// make sure it gets reset to zero in each new pass
if (counter_label->pass != pass_count) {
counter_label->pass = pass_count;
counter_label->result.val.intval = 0;
}
number = (unsigned long) counter_label->result.val.intval;
// now append to the name to make it unique
GlobalDynaBuf->size--; // forget terminator, we want to append
do {
DYNABUF_APPEND(GlobalDynaBuf, 'a' + (number & 15));
number >>= 4;
} while (number);
DynaBuf_append(GlobalDynaBuf, '\0');
return counter_label;
}

View File

@ -1,51 +0,0 @@
// ACME - a crossassembler for producing 6502/65c02/65816 code.
// Copyright (C) 1998-2014 Marco Baye
// Have a look at "acme.c" for further info
//
// Label stuff
#ifndef label_H
#define label_H
#include <stdio.h>
#include "config.h"
// "label" structure type definition
struct label {
struct result_t result; // Expression flags and value
int usage; // usage count
int pass; // pass of creation (for anon counters)
};
// variables
extern struct node_ra_t *Label_forest[]; // trees (because of 8-bit hash)
// clear label forest (is done early)
extern void Label_clear_init(void);
// register pseudo opcodes (done later)
extern void Label_register_init(void);
// function acts upon the label's flag bits and produces an error if needed.
extern void Label_set_value(struct label *, struct result_t *, int change_allowed);
// Parse implicit label definition (can be either global or local).
// Name must be held in GlobalDynaBuf.
extern void Label_implicit_definition(zone_t zone, int stat_flags, int force_bit, int change);
// Parse label definition (can be either global or local).
// Name must be held in GlobalDynaBuf.
extern void Label_parse_definition(zone_t zone, int stat_flags);
// Search for label. Create if nonexistant. If created, assign flags.
// Name must be held in GlobalDynaBuf.
extern struct label *Label_find(zone_t, int flags);
// set global label to value, no questions asked (for "-D" switch)
// Name must be held in GlobalDynaBuf.
extern void Label_define(intval_t value);
// Dump global labels to file
extern void Label_dump_all(FILE *fd);
// Fix name of anonymous forward label (held in GlobalDynaBuf, NOT TERMINATED!)
// so it references the *next* anonymous forward label definition.
extern struct label *Label_fix_forward_name(void);
#endif

View File

@ -11,8 +11,8 @@
#include "dynabuf.h"
#include "global.h"
#include "input.h"
#include "label.h"
#include "section.h"
#include "symbol.h"
#include "tree.h"
#include "macro.h"
@ -42,8 +42,8 @@ struct macro {
// gives us the possibility to find out which args are call-by-value and
// which ones are call-by-reference.
union macro_arg_t {
struct result_t result; // value and flags (call by value)
struct label *label; // pointer to label struct (call by reference)
struct result result; // value and flags (call by value)
struct symbol *symbol; // pointer to symbol struct (call by reference)
};
@ -187,12 +187,12 @@ void Macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
DynaBuf_append(GlobalDynaBuf, REFERENCE_CHAR);
GetByte();
}
// handle prefix for local labels (LOCAL_PREFIX, normally '.')
// handle prefix for local symbols (LOCAL_PREFIX, normally '.')
if (GotByte == LOCAL_PREFIX) {
DynaBuf_append(GlobalDynaBuf, LOCAL_PREFIX);
GetByte();
}
// handle label name
// handle symbol name
Input_append_keyword_to_global_dynabuf();
} while (pipe_comma());
// ensure CHAR_SOB ('{')
@ -225,16 +225,16 @@ void Macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
{
char local_gotbyte;
struct label *label;
struct symbol *symbol;
struct section new_section,
*outer_section;
struct input new_input,
*outer_input;
struct macro *actual_macro;
struct node_ra_t *macro_node,
*label_node;
*symbol_node;
zone_t macro_zone,
label_zone;
symbol_zone;
int arg_count = 0;
// Enter deeper nesting level
@ -261,10 +261,9 @@ void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
// read call-by-reference arg
DynaBuf_append(internal_name, ARGTYPE_NUM_REF);
GetByte(); // skip '~' character
Input_read_zone_and_keyword(&label_zone);
Input_read_zone_and_keyword(&symbol_zone);
// GotByte = illegal char
arg_table[arg_count].label =
Label_find(label_zone, 0);
arg_table[arg_count].symbol = symbol_find(symbol_zone, 0);
} else {
// read call-by-value arg
DynaBuf_append(internal_name, ARGTYPE_NUM_VAL);
@ -299,8 +298,7 @@ void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
outer_section = Section_now;
// start new section (with new zone)
// FALSE = title mustn't be freed
Section_new_zone(&new_section, "Macro",
actual_macro->original_name, FALSE);
Section_new_zone(&new_section, "Macro", actual_macro->original_name, FALSE);
GetByte(); // fetch first byte of parameter list
// assign arguments
if (GotByte != CHAR_EOS) { // any at all?
@ -312,19 +310,19 @@ void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
if (GotByte == REFERENCE_CHAR) {
// assign call-by-reference arg
GetByte(); // skip '~' character
Input_read_zone_and_keyword(&label_zone);
if ((Tree_hard_scan(&label_node, Label_forest, label_zone, TRUE) == FALSE)
Input_read_zone_and_keyword(&symbol_zone);
if ((Tree_hard_scan(&symbol_node, symbols_forest, symbol_zone, TRUE) == FALSE)
&& (pass_count == 0))
Throw_error("Macro parameter twice.");
label_node->body = arg_table[arg_count].label;
symbol_node->body = arg_table[arg_count].symbol;
} else {
// assign call-by-value arg
Input_read_zone_and_keyword(&label_zone);
label = Label_find(label_zone, 0);
// FIXME - add a possibility to Label_find to make it possible to find out
// whether label was just created. Then check for the same error message here
Input_read_zone_and_keyword(&symbol_zone);
symbol = symbol_find(symbol_zone, 0);
// FIXME - add a possibility to symbol_find to make it possible to find out
// whether symbol was just created. Then check for the same error message here
// as above ("Macro parameter twice.").
label->result = arg_table[arg_count].result;
symbol->result = arg_table[arg_count].result;
}
arg_count++;
} while (Input_accept_comma());

View File

@ -396,9 +396,9 @@ static int get_index(int next)
return addressing_mode;
}
// This function stores the command's argument in the given result_t
// This function stores the command's argument in the given result
// structure (using the valueparser). The addressing mode is returned.
static int get_argument(struct result_t *result)
static int get_argument(struct result *result)
{
int open_paren,
addressing_mode = HAM_ABS;
@ -451,7 +451,7 @@ static int get_argument(struct result_t *result)
// Helper function for calc_arg_size()
// Only call with "size_bit = MVALUE_FORCE16" or "size_bit = MVALUE_FORCE24"
static int check_oversize(int size_bit, struct result_t *argument)
static int check_oversize(int size_bit, struct result *argument)
{
// only check if value is *defined*
if ((argument->flags & MVALUE_DEFINED) == 0)
@ -478,7 +478,7 @@ static int check_oversize(int size_bit, struct result_t *argument)
// argument value and flags of parameter
// addressing_modes adressing modes (8b, 16b, 24b or any combination)
// Return value = force bit for number of parameter bytes to send (0 = error)
static int calc_arg_size(int force_bit, struct result_t *argument, int addressing_modes)
static int calc_arg_size(int force_bit, struct result *argument, int addressing_modes)
{
// if there are no possible addressing modes, complain
if (addressing_modes == MAYBE______) {
@ -588,7 +588,7 @@ static void not_in_bank(intval_t target)
// Mnemonics using only 8bit relative addressing (short branch instructions).
static void group_only_relative8_addressing(int opcode)
{
struct result_t target;
struct result target;
intval_t offset = 0; // dummy value, to not throw more errors than necessary
ALU_int_result(&target);
@ -623,7 +623,7 @@ static void group_only_relative8_addressing(int opcode)
// Mnemonics using only 16bit relative addressing (BRL and PER).
static void group_only_relative16_addressing(int opcode)
{
struct result_t target;
struct result target;
intval_t offset = 0; // dummy value, to not throw more errors than necessary
ALU_int_result(&target);
@ -644,7 +644,7 @@ static void group_only_relative16_addressing(int opcode)
// set addressing mode bits depending on which opcodes exist, then calculate
// argument size and output both opcode and argument
static void make_command(int force_bit, struct result_t *result, unsigned long opcodes)
static void make_command(int force_bit, struct result *result, unsigned long opcodes)
{
int addressing_modes = MAYBE______;
@ -695,7 +695,7 @@ static unsigned int imm_ops(int *force_bit, unsigned char opcode, int imm_flag)
static void group_main(int index, int imm_flag)
{
unsigned long imm_opcodes;
struct result_t result;
struct result result;
int force_bit = Input_get_force_bit(); // skips spaces after
switch (get_argument(&result)) {
@ -744,7 +744,7 @@ static void group_main(int index, int imm_flag)
static void group_misc(int index, int imm_flag)
{
unsigned long imm_opcodes;
struct result_t result;
struct result result;
int force_bit = Input_get_force_bit(); // skips spaces after
switch (get_argument(&result)) {
@ -802,7 +802,7 @@ static void group_move(int opcode)
// The jump instructions.
static void group_jump(int index)
{
struct result_t result;
struct result result;
int force_bit = Input_get_force_bit(); // skips spaces after
switch (get_argument(&result)) {

View File

@ -615,7 +615,7 @@ void PO_setpc(void)
// get program counter
void vcpu_read_pc(struct result_t *target)
void vcpu_read_pc(struct result *target)
{
*target = CPU_state.pc;
}

View File

@ -19,7 +19,7 @@
// FIXME - move struct definition to .c file and change other .c files' accesses to fn calls
struct vcpu {
const struct cpu_type *type; // current CPU type (default 6502) (FIXME - move out of struct again?)
struct result_t pc; // current program counter (pseudo value)
struct result pc; // current program counter (pseudo value)
int add_to_pc; // add to PC after statement
int a_is_long;
int xy_are_long;
@ -65,7 +65,7 @@ extern void Output_end_segment(void);
// set program counter to defined value (FIXME - allow undefined!)
extern void vcpu_set_pc(intval_t new_pc, int flags);
// get program counter
extern void vcpu_read_pc(struct result_t *target);
extern void vcpu_read_pc(struct result *target);
// get size of current statement (until now) - needed for "!bin" verbose output
extern int vcpu_get_statement_size(void);
// adjust program counter (called at end of each statement)

325
src/symbol.c Normal file
View File

@ -0,0 +1,325 @@
// ACME - a crossassembler for producing 6502/65c02/65816 code.
// Copyright (C) 1998-2014 Marco Baye
// Have a look at "acme.c" for further info
//
// symbol stuff
//
// 22 Nov 2007 "warn on indented labels" is now a CLI switch
// 25 Sep 2011 Fixed bug in !sl (colons in filename could be interpreted as EOS)
#include <stdio.h>
#include "acme.h"
#include "alu.h"
#include "dynabuf.h"
#include "global.h"
#include "input.h"
#include "output.h"
#include "platform.h"
#include "section.h"
#include "symbol.h"
#include "tree.h"
#include "typesystem.h"
// constants
#define s_sl (s_asl + 1) // Yes, I know I'm sick
// variables
struct node_ra_t *symbols_forest[256]; // ... (because of 8-bit hash)
// Dump symbol value and flags to dump file
static void dump_one_symbol(struct node_ra_t *node, FILE *fd)
{
struct symbol *symbol = node->body;
// output name
if (warn_on_type_mismatch
&& symbol->result.addr_refs == 1)
fprintf(fd, "!addr\t");
fprintf(fd, "%s", node->id_string);
switch (symbol->result.flags & MVALUE_FORCEBITS) {
case MVALUE_FORCE16:
fprintf(fd, "+2\t= ");
break;
case MVALUE_FORCE16 | MVALUE_FORCE24:
/*FALLTHROUGH*/
case MVALUE_FORCE24:
fprintf(fd, "+3\t= ");
break;
default:
fprintf(fd, "\t= ");
}
if (symbol->result.flags & MVALUE_DEFINED) {
if (symbol->result.flags & MVALUE_IS_FP)
fprintf(fd, "%.30f", symbol->result.val.fpval); //FIXME %g
else
fprintf(fd, "$%x", (unsigned) symbol->result.val.intval);
} else {
fprintf(fd, " ?");
}
if (symbol->result.flags & MVALUE_UNSURE)
fprintf(fd, "\t; ?");
if (symbol->usage == 0)
fprintf(fd, "\t; unused");
fprintf(fd, "\n");
}
// search for symbol. create if nonexistant. if created, give it flags "flags".
// the symbol name must be held in GlobalDynaBuf.
struct symbol *symbol_find(zone_t zone, int flags)
{
struct node_ra_t *node;
struct symbol *symbol;
int node_created,
force_bits = flags & MVALUE_FORCEBITS;
node_created = Tree_hard_scan(&node, symbols_forest, zone, TRUE);
// if node has just been created, create symbol as well
if (node_created) {
// create new symbol structure
symbol = safe_malloc(sizeof(*symbol));
// finish empty symbol item
symbol->result.flags = flags;
symbol->result.addr_refs = 0;
if (flags & MVALUE_IS_FP)
symbol->result.val.fpval = 0;
else
symbol->result.val.intval = 0;
symbol->usage = 0; // usage count
symbol->pass = pass_count;
node->body = symbol;
} else {
symbol = node->body;
}
// make sure the force bits don't clash
if ((node_created == FALSE) && force_bits)
if ((symbol->result.flags & MVALUE_FORCEBITS) != force_bits)
Throw_error("Too late for postfix.");
return symbol;
}
// assign value to symbol. the function acts upon the symbol's flag bits and
// produces an error if needed.
void symbol_set_value(struct symbol *symbol, struct result *new_value, int change_allowed)
{
int oldflags = symbol->result.flags;
// value stuff
if ((oldflags & MVALUE_DEFINED) && (change_allowed == FALSE)) {
// symbol is already defined, so compare new and old values
// if different type OR same type but different value, complain
if (((oldflags ^ new_value->flags) & MVALUE_IS_FP)
|| ((oldflags & MVALUE_IS_FP)
? (symbol->result.val.fpval != new_value->val.fpval)
: (symbol->result.val.intval != new_value->val.intval)))
Throw_error("Symbol already defined.");
} else {
// symbol is not defined yet OR redefinitions are allowed
symbol->result = *new_value;
}
// flags stuff
// Ensure that "unsure" symbols without "isByte" state don't get that
if ((oldflags & (MVALUE_UNSURE | MVALUE_ISBYTE)) == MVALUE_UNSURE)
new_value->flags &= ~MVALUE_ISBYTE;
if (change_allowed) {
oldflags = (oldflags & MVALUE_UNSURE) | new_value->flags;
} else {
if ((oldflags & MVALUE_FORCEBITS) == 0)
if ((oldflags & (MVALUE_UNSURE | MVALUE_DEFINED)) == 0)
oldflags |= new_value->flags & MVALUE_FORCEBITS;
oldflags |= new_value->flags & ~MVALUE_FORCEBITS;
}
symbol->result.flags = oldflags;
}
// (Re)set symbol
static enum eos PO_set(void) // Now GotByte = illegal char
{
struct result result;
int force_bit;
struct symbol *symbol;
zone_t zone;
if (Input_read_zone_and_keyword(&zone) == 0) // skips spaces before
// Now GotByte = illegal char
return SKIP_REMAINDER;
force_bit = Input_get_force_bit(); // skips spaces after
symbol = symbol_find(zone, force_bit);
if (GotByte != '=') {
Throw_error(exception_syntax);
return SKIP_REMAINDER;
}
// symbol = parsed value
GetByte(); // proceed with next char
ALU_any_result(&result);
// clear symbol's force bits and set new ones
symbol->result.flags &= ~(MVALUE_FORCEBITS | MVALUE_ISBYTE);
if (force_bit) {
symbol->result.flags |= force_bit;
result.flags &= ~(MVALUE_FORCEBITS | MVALUE_ISBYTE);
}
symbol_set_value(symbol, &result, TRUE);
return ENSURE_EOS;
}
// Select dump file
static enum eos PO_sl(void)
{
// bugfix: first read filename, *then* check for first pass.
// if skipping right away, quoted colons might be misinterpreted as EOS
// FIXME - why not just fix the skipping code to handle quotes? :)
// "!to" has been fixed as well
// read filename to global dynamic buffer
// if no file name given, exit (complaining will have been done)
if (Input_read_filename(FALSE))
return SKIP_REMAINDER;
// only process this pseudo opcode in first pass
if (pass_count)
return SKIP_REMAINDER;
// if symbol dump file already chosen, complain and exit
if (symboldump_filename) {
Throw_warning("Label dump file already chosen.");
return SKIP_REMAINDER;
}
// get malloc'd copy of filename
symboldump_filename = DynaBuf_get_copy(GlobalDynaBuf);
// ensure there's no garbage at end of line
return ENSURE_EOS;
}
// predefined stuff
static struct node_t pseudo_opcodes[] = {
PREDEFNODE("set", PO_set),
PREDEFLAST(s_sl, PO_sl),
// ^^^^ this marks the last element
};
// parse label definition (can be either global or local).
// name must be held in GlobalDynaBuf.
void symbol_set_label(zone_t zone, int stat_flags, int force_bit, int change_allowed)
{
struct result pc,
result;
struct symbol *symbol;
symbol = symbol_find(zone, force_bit);
// label definition
if ((stat_flags & SF_FOUND_BLANK) && warn_on_indented_labels)
Throw_first_pass_warning("Label name not in leftmost column.");
vcpu_read_pc(&pc);
result.flags = pc.flags & MVALUE_DEFINED;
result.val.intval = pc.val.intval;
result.addr_refs = pc.addr_refs;
symbol_set_value(symbol, &result, change_allowed);
}
// parse symbol definition (can be either global or local, may turn out to be a label).
// name must be held in GlobalDynaBuf.
void symbol_parse_definition(zone_t zone, int stat_flags)
{
struct result result;
struct symbol *symbol;
int force_bit = Input_get_force_bit(); // skips spaces after
// FIXME - force bit is allowed for label definitions?!
if (GotByte == '=') {
// explicit symbol definition (symbol = <something>)
symbol = symbol_find(zone, force_bit);
// symbol = parsed value
GetByte(); // skip '='
ALU_any_result(&result);
// if wanted, mark as address reference
if (typesystem_says_address())
result.addr_refs = 1;
symbol_set_value(symbol, &result, FALSE);
Input_ensure_EOS();
} else {
symbol_set_label(zone, stat_flags, force_bit, FALSE);
}
}
// set global symbol to value, no questions asked (for "-D" switch)
// Name must be held in GlobalDynaBuf.
void symbol_define(intval_t value)
{
struct result result;
struct symbol *symbol;
result.flags = MVALUE_GIVEN;
result.val.intval = value;
symbol = symbol_find(ZONE_GLOBAL, 0);
symbol_set_value(symbol, &result, TRUE);
}
// dump global symbols to file
void symbols_dump_all(FILE *fd)
{
Tree_dump_forest(symbols_forest, ZONE_GLOBAL, dump_one_symbol, fd);
PLATFORM_SETFILETYPE_TEXT(symboldump_filename);
}
// clear symbols forest (is done early)
void symbols_clear_init(void)
{
struct node_ra_t **ptr;
int ii;
// cut down all the trees (clear pointer table)
ptr = symbols_forest;
for (ii = 255; ii >= 0; ii--)
*ptr++ = NULL;
}
// register pseudo opcodes (done later)
void symbols_register_init(void)
{
Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes);
}
// fix name of anonymous forward label (held in DynaBuf, NOT TERMINATED!) so it
// references the *next* anonymous forward label definition. The tricky bit is,
// each name length would need its own counter. But hey, ACME's real quick in
// finding symbols, so I'll just abuse the symbol system to store those counters.
void symbol_fix_forward_anon_name(int increment)
{
struct symbol *counter_symbol;
unsigned long number;
// terminate name, find "counter" symbol and read value
DynaBuf_append(GlobalDynaBuf, '\0');
counter_symbol = symbol_find(Section_now->zone, 0);
// make sure it gets reset to zero in each new pass
if (counter_symbol->pass != pass_count) {
counter_symbol->pass = pass_count;
counter_symbol->result.val.intval = 0;
}
number = (unsigned long) counter_symbol->result.val.intval;
// now append to the name to make it unique
GlobalDynaBuf->size--; // forget terminator, we want to append
do {
DYNABUF_APPEND(GlobalDynaBuf, 'a' + (number & 15));
number >>= 4;
} while (number);
DynaBuf_append(GlobalDynaBuf, '\0');
if (increment)
counter_symbol->result.val.intval++;
}

50
src/symbol.h Normal file
View File

@ -0,0 +1,50 @@
// ACME - a crossassembler for producing 6502/65c02/65816 code.
// Copyright (C) 1998-2014 Marco Baye
// Have a look at "acme.c" for further info
//
// symbol stuff
#ifndef symbol_H
#define symbol_H
#include <stdio.h>
#include "config.h"
struct symbol {
struct result result; // expression flags and value
int usage; // usage count
int pass; // pass of creation (for anon counters)
};
// variables
extern struct node_ra_t *symbols_forest[]; // trees (because of 8-bit hash)
// clear symbol forest (is done early)
extern void symbols_clear_init(void);
// register pseudo opcodes (done later)
extern void symbols_register_init(void);
// function acts upon the symbol's flag bits and produces an error if needed.
extern void symbol_set_value(struct symbol *symbol, struct result *new_value, int change_allowed);
// parse label definition (can be either global or local).
// name must be held in GlobalDynaBuf.
extern void symbol_set_label(zone_t zone, int stat_flags, int force_bit, int change_allowed);
// parse symbol definition (can be either global or local, may turn out to be a label).
// name must be held in GlobalDynaBuf.
extern void symbol_parse_definition(zone_t zone, int stat_flags);
// search for symbol. create if nonexistant. if created, assign flags.
// name must be held in GlobalDynaBuf.
extern struct symbol *symbol_find(zone_t, int flags);
// set global symbol to value, no questions asked (for "-D" switch)
// name must be held in GlobalDynaBuf.
extern void symbol_define(intval_t value);
// dump global symbols to file
extern void symbols_dump_all(FILE *fd);
// fix name of anonymous forward label (held in GlobalDynaBuf, NOT TERMINATED!)
// so it references the *next* anonymous forward label definition.
extern void symbol_fix_forward_anon_name(int increment);
#endif

View File

@ -33,7 +33,7 @@ void typesystem_force_address_statement(int value)
in_address_statement = value;
}
void typesystem_want_imm(struct result_t *result)
void typesystem_want_imm(struct result *result)
{
if (!warn_on_type_mismatch)
return;
@ -42,7 +42,7 @@ void typesystem_want_imm(struct result_t *result)
if (result->addr_refs != 0)
Throw_warning("Wrong type - expected integer.");
}
void typesystem_want_addr(struct result_t *result)
void typesystem_want_addr(struct result *result)
{
if (!warn_on_type_mismatch)
return;

View File

@ -10,16 +10,16 @@
#include "config.h"
// return whether explicit label definitions should force "address" mode
// return whether explicit symbol definitions should force "address" mode
extern int typesystem_says_address(void);
// parse a block while forcing address mode
extern void typesystem_force_address_block(void);
// force address mode on or off for the next statement
extern void typesystem_force_address_statement(int value);
// warn if result is address instead of integer
extern void typesystem_want_imm(struct result_t *result);
// warn if result is integer instead of address
extern void typesystem_want_addr(struct result_t *result);
// warn if result is not integer
extern void typesystem_want_imm(struct result *result);
// warn if result is not address
extern void typesystem_want_addr(struct result *result);
#endif