diff --git a/docs/AddrModes.txt b/docs/AddrModes.txt index 40e8fc7..192c748 100644 --- a/docs/AddrModes.txt +++ b/docs/AddrModes.txt @@ -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 ; 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 diff --git a/docs/Changes.txt b/docs/Changes.txt index 5323811..9066f35 100644 --- a/docs/Changes.txt +++ b/docs/Changes.txt @@ -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 ---------------------------------------------------------------------- diff --git a/docs/Errors.txt b/docs/Errors.txt index d722ccb..f6ce454 100644 --- a/docs/Errors.txt +++ b/docs/Errors.txt @@ -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. diff --git a/docs/Help.txt b/docs/Help.txt index ef614e8..7f517d5 100644 --- a/docs/Help.txt +++ b/docs/Help.txt @@ -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. diff --git a/docs/QuickRef.txt b/docs/QuickRef.txt index fe4b4bb..a30e585 100644 --- a/docs/QuickRef.txt +++ b/docs/QuickRef.txt @@ -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. diff --git a/src/Makefile b/src/Makefile index 3d3eeb0..7205242 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 diff --git a/src/Makefile.dos b/src/Makefile.dos index fae0ca1..d0f8b9f 100644 --- a/src/Makefile.dos +++ b/src/Makefile.dos @@ -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 diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 408db4e..6a8c867 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -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 diff --git a/src/Makefile.riscos b/src/Makefile.riscos index 118b99d..0d6347b 100644 --- a/src/Makefile.riscos +++ b/src/Makefile.riscos @@ -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 diff --git a/src/acme.c b/src/acme.c index a7ce737..3550d82 100644 --- a/src/acme.c +++ b/src/acme.c @@ -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); diff --git a/src/acme.h b/src/acme.h index 094932b..ca59abf 100644 --- a/src/acme.h +++ b/src/acme.h @@ -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); diff --git a/src/alu.c b/src/alu.c index 07b2cfa..b33cc84 100644 --- a/src/alu.c +++ b/src/alu.c @@ -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); diff --git a/src/alu.h b/src/alu.h index 5129092..bd0ce5d 100644 --- a/src/alu.h +++ b/src/alu.h @@ -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 diff --git a/src/basics.c b/src/basics.c index c59b306..206fb35 100644 --- a/src/basics.c +++ b/src/basics.c @@ -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); diff --git a/src/config.h b/src/config.h index 354307c..c9dd91d 100644 --- a/src/config.h +++ b/src/config.h @@ -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 diff --git a/src/flow.c b/src/flow.c index 4da58f4..1b71194 100644 --- a/src/flow.c +++ b/src/flow.c @@ -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; } diff --git a/src/global.c b/src/global.c index 8f70d47..30d7b6c 100644 --- a/src/global.c +++ b/src/global.c @@ -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(); diff --git a/src/label.c b/src/label.c deleted file mode 100644 index 4e45447..0000000 --- a/src/label.c +++ /dev/null @@ -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 -#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 = ) - 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; -} diff --git a/src/label.h b/src/label.h deleted file mode 100644 index 185ff85..0000000 --- a/src/label.h +++ /dev/null @@ -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 -#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 diff --git a/src/macro.c b/src/macro.c index e61c355..c731b13 100644 --- a/src/macro.c +++ b/src/macro.c @@ -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()); diff --git a/src/mnemo.c b/src/mnemo.c index 1a963ea..ad9a145 100644 --- a/src/mnemo.c +++ b/src/mnemo.c @@ -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)) { diff --git a/src/output.c b/src/output.c index 1df3ef8..889212f 100644 --- a/src/output.c +++ b/src/output.c @@ -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; } diff --git a/src/output.h b/src/output.h index d016da7..9591dfd 100644 --- a/src/output.h +++ b/src/output.h @@ -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) diff --git a/src/symbol.c b/src/symbol.c new file mode 100644 index 0000000..99cd0e4 --- /dev/null +++ b/src/symbol.c @@ -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 +#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 = ) + 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++; +} diff --git a/src/symbol.h b/src/symbol.h new file mode 100644 index 0000000..67c90e6 --- /dev/null +++ b/src/symbol.h @@ -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 +#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 diff --git a/src/typesystem.c b/src/typesystem.c index 56df22b..182f7f8 100644 --- a/src/typesystem.c +++ b/src/typesystem.c @@ -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; diff --git a/src/typesystem.h b/src/typesystem.h index 4333fc5..590fd5a 100644 --- a/src/typesystem.h +++ b/src/typesystem.h @@ -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