Compare commits

...
1181 Commits
Author SHA1 Message Date
ISSOtm 76c1995559 Fix CI 2021-04-01 11:38:07 +02:00
Rangi ae84570f04 Revise RGBASM manual 2021-03-31 18:35:09 -04:00
Rangi 094a31ef8c Update RGBASM command-line manual 2021-03-31 18:17:18 -04:00
ISSOtm 291dcf3b6c Update RGBASM manual 2021-04-01 00:11:41 +02:00
Rangi a890bd072b Fix "INCBIN"
Examples: (...s are optional)

ld [b @:...] = "Dockerfile"
ld [b @:...] = "Dockerfile"[451:...]
ld [b @:...] = "Dockerfile"[23:5]
ld [b @:5] = "Dockerfile"[23:...]
2021-03-31 18:06:14 -04:00
Rangi 2f6c808ccb Revise instruction reference 2021-03-31 17:59:12 -04:00
ISSOtm e80907abd0 Update instruction reference 2021-03-31 23:26:57 +02:00
Rangi 25d39155d3 Support ld a, a±c±LOW(bc) as well as ld a, a±c±c 2021-03-30 12:36:11 -04:00
Rangi 77021d229b Support ld [c], a and ld a, [c] 2021-03-30 12:02:29 -04:00
Rangi 1b250b90b2 Implement ds <len> ==> ld [b @:<len>], ? 2021-03-30 11:54:39 -04:00
Rangi e2b4723489 Fix lexing @ 2021-03-30 11:52:25 -04:00
Rangi 2507413162 Fix lexing a., b., etc 2021-03-30 11:41:44 -04:00
Rangi e023a84d04 Allow 'ld a, a±c±<r8>' or 'ld a, a±<r8>±c' for adc/sbc 2021-03-30 11:27:19 -04:00
Rangi 34c127d9c3 Allow ld [b @:<len>] = "file.bin"[<ofs>:...] 2021-03-30 10:51:48 -04:00
Rangi 9a930988c2 Implement db, dw, dl, ds, and INCBIN with ld
To do: let the `b` in `ld [b @]` be optional, and allow
`ld [b @:<len>] = "file.bin"[<ofs>:...]`
2021-03-30 10:47:05 -04:00
Rangi 8c4204c542 Make 'w' and '...' tokens, and make '@' a separate token
Now '@' is valid as a relocexpr_no_str, in 'BANK(@)', and
in 'DEF(@)', but not in general T_ID or T_LABEL contexts

This will make it easier to implement INCBIN with 'ld'
2021-03-30 10:17:09 -04:00
Rangi 663c1930ec Factor out 'ld a, a+c+' and 'ld a, a-c-' prefixes
This fixes all the shift/reduce and reduce/reduce conflicts
2021-03-30 09:57:08 -04:00
Rangi 30ccf43f44 Factor out individual 'ld <r16>,' prefixes 2021-03-30 09:43:34 -04:00
Rangi fdc17adbcb Factor out common ld a, prefix 2021-03-30 09:19:58 -04:00
Rangi cc196954f3 Consolidate some parser rules with reg_ss and reg_r
There are now 5 shift/reduce conflicts and 3 reduce/reduce conflicts
2021-03-29 20:52:24 -04:00
Rangi 55b6cfff84 Prevent GitHub Actions from running any workflows 2021-03-29 19:50:13 -04:00
Rangi 1fc73b04eb Parse ld instructions as discussed
There are 13 shift/reduce conflicts, so some instructions
may need different formats.

This also does not yet implement `db`, `dw`, `dl`, `ds`,
or `INCBIN` using `ld`.

The `lexerState->nextToken` solution to lexing something
like "a.2" as three tokens instead of one identifier
is taken from the first commit in rgbds PR #799.
2021-03-29 19:42:18 -04:00
Rangi d05703c692 Release 0.5.0-rc2 2021-03-28 17:15:44 -04:00
Rangi 5dbfafcc55 Update man page copyrights to 2021 2021-03-28 16:37:15 -04:00
Rangi a265b85d9d Report "1 error", not "1 errors", when assembly is aborted
This matches other such pluralized error messages
2021-03-28 15:55:32 -04:00
Rangi 28abf03c0a Output USED space, not FREE space, in the .map file
Fixes #808
2021-03-28 15:49:44 -04:00
Rangi 7e7f92f18c Assign section locations to all UNIONs/FRAGMENTs
Fixes the test case from #800

The `out.gb` output was corrected, since the two "test"
fragments have a different order in ROM than in SRAM.
It is effectively:

; ROM0[$0000], fragments ordered by size
    jr Label
    dw Label
    db 0

; SRAM[$a000], fragments ordered by .o order
    ds 1  ; db 0
    ds 2  ; jr Label
Label:    ; $a003
    ds 2  ; dw Label
2021-03-28 15:21:17 -04:00
Eldred Habert 7461170956 Add LOAD FRAGMENT pc test (#800)
Reproduces a reported problem, fix pending
2021-03-28 15:11:20 -04:00
Rangi 57d966d6e0 Merge pull request #804 from Rangi42/normal-backslash
Backslash in normal lexer mode must be a line continuation
2021-03-26 13:33:11 -04:00
Rangi 17752d7094 Backslash in normal lexer mode must be a line continuation
Macro args were already handled by `peek`, and character escapes
do not exist outside of string literals.

This only affects the error message printed when a non-whitespace
character comes after the backslash. Instead of "Illegal character
escape '%s'", it will print "Begun line continuation, but
encountered character '%s'".
2021-03-26 13:23:05 -04:00
ISSOtm 4216f0a9b0 Init top-level fstack node line number
It still gets written to the object file, generating Valgrind warnings
about using uninitialized memory. To silence those errors, and make
output more reproducible, init the line no to a dummy (0) value.
2021-03-25 11:26:58 +01:00
ISSOtm e3fde986ad Remove hashmap collision warning
It was only used to check hashmap collision rate in the wild,
but it no longer has a purpose and produces spurious messages
2021-03-23 21:34:08 +01:00
Rangi aa99ed056c Do not evaluate an untaken ELIF's condition
Fixes #764
2021-03-23 16:20:24 +01:00
ISSOtm 46d6652df1 Fix missing .sym/.map symbols in SECTION UNION/FRAGMENTs
Only the first "slice"'s symbols were considered, forgetting some symbols
2021-03-22 23:23:06 +01:00
ISSOtm 5406674cdd Install groff to build PDFs correctly in CI 2021-03-20 02:09:47 +01:00
ISSOtm 5d2e2e2182 Make docs update script also produce PDFs
See rgbds-www#12
2021-03-20 01:53:26 +01:00
ISSOtm a929f36bc5 Replace UTF-8 hyphens with ASCII ones in man pages 2021-03-20 01:25:17 +01:00
ISSOtm bdb84a901f Use sub-sections for the different symbol types
This will make them appear in the ToC, and generate HTML anchors for them
2021-03-19 11:04:22 +01:00
Rangi 093631ca0b Revise rgbasm(5) string symbol documentation
Clarify the differences between EQUS expansion and {interpolation}
2021-03-19 01:48:36 +01:00
Rangi 7e127a4e52 Don't expand string symbols in MACRO and FOR symbol names
Explicit {interpolation} can still achieve this, but
to match DEF, REDEF, and PURGE, these new directives that
define symbols do not expand string EQUS.
2021-03-19 01:48:36 +01:00
Rangi b8093847dc New definition syntax with leading DEF keyword
This will enable fixing #457 later once the old
definition syntax is removed.
2021-03-19 01:48:36 +01:00
Rangi 8d1b56bcf5 rgblink identifies patches' PC sections after reading all sections
Fixes #794
2021-03-18 23:53:54 +01:00
ISSOtm 5fb7fcf461 Fix description of rgbgfx -h
The old description was backwards and mostly confusing.
2021-03-18 15:35:01 +01:00
Rangi ee900ae7a3 Add a missing newline to a verbosePrint 2021-03-17 20:53:25 -04:00
ISSOtm 3ca58e13dc Fix verbose messages claiming non-existent errors
They were confusing when trying to debug other things
2021-03-14 18:52:16 +01:00
ISSOtm aaa4e17454 Add verbose messages for early exit from -MG
Should help debugging Make invocations
2021-03-14 18:28:05 +01:00
daid a81d383f75 Alignment mask was incorrectly checked for 1 instead of 0
This caused an `ALIGN[1]` to be ignored.
2021-03-11 13:24:59 +01:00
ISSOtm 60019cf476 Fix a bunch of Clang warnings
As reported by #789
Should avoid relying on 32-bit int (for implicit conversions)
and account for more extreme uses of RGBDS.
2021-03-10 10:56:57 +01:00
ISSOtm 5a6a44cbc1 Fix master documentation updater
Its path was not synced with a recent change
2021-03-10 01:15:51 +01:00
ISSOtm b61a187b19 Add forgotten __RGBDS_RC__ symbol 2021-03-10 01:09:18 +01:00
ISSOtm 6382f13647 Release 0.5.0-rc1 2021-03-10 01:04:23 +01:00
ISSOtm 714d39c86f Make some INCBIN errors non-fatal 2021-03-10 01:02:45 +01:00
ISSOtm f11241c2ae Add INCBIN tests 2021-03-10 01:02:45 +01:00
daid cb47ac8b97 Change the start position check on INCBIN
Currently INCBIN gives an error if your start position == file size.
This means you cannot include an empty file.
It also means the text of the error message is incorrect
(as the start is not greater, but equal to the length of the file)
2021-03-10 01:02:45 +01:00
ISSOtm 028e7af7d1 Prepare release candidates
We'll use "-rcX" instead of "-pre" to allow multiple ones, jic
Additionally, they will be able to be detected using __RGBDS_RC__
Finally, adapt everything version-related to this new system
2021-03-10 00:06:32 +01:00
ISSOtm e141da1d94 Compute fallback version string at compile time 2021-03-09 23:59:34 +01:00
ISSOtm 35367282e4 Add workflow to auto-prepare a release
Just push a tag beginning with "v" and a number to trigger it
2021-03-09 22:58:42 +01:00
ISSOtm 4c0fa6732e Fix release doc creation workflow 2021-03-09 22:58:42 +01:00
ISSOtm e9d9a44687 Make release doc update also register docs 2021-03-09 22:58:42 +01:00
ISSOtm 611bd46e0b Ignore CRLF vs LF for syntax error test check 2021-03-09 22:58:32 +01:00
ISSOtm e67254093e Delete version test if stale 2021-03-09 22:58:00 +01:00
ISSOtm 3ce3d2f662 Explicitly force tested projects to use tested bins 2021-03-09 22:56:59 +01:00
ISSOtm 3da9d81071 Ignore DLLs too
Since you may want to put them next to the EXEs here
2021-03-09 22:46:17 +01:00
Rangi 88646093ca Swap the Name and Type columns in Predeclared Symbols 2021-03-05 17:00:06 -05:00
Rangi 0a0427afbb windows-xbuild CI uses ubuntu-18.04 for its gcc 7.3.0 (#784)
GitHub's ubuntu-18.04 environment installs gcc 7.3.0.
The latest ubuntu-20.04 environment installs gcc 9.3.0.
Version 9.3.0 is incompatible with building libpng 1.6.37,
as of 2021-03-04.

Fixes #783
2021-03-05 11:27:12 -05:00
Rangi 88048cdcd7 Clarify the character encoding example in rgbasm.5 2021-03-05 10:08:43 -05:00
Rangi c878ff8775 Report slack totals at the end of the .map file (#781)
Fixes #777
2021-03-05 08:53:27 -05:00
dannye a4049a3f1b rgbasm(5): Clarify charmap behavior (#558) 2021-03-05 13:16:49 +01:00
Rangi 8a75cc5051 Test an indented anonymous label 2021-03-03 12:26:35 -05:00
Rangi b674c5fcaa Comment refers to "built-in" symbols 2021-03-03 10:35:47 -05:00
daid a6d3df7ac9 Put all local symbols in object/sym/map files (#774)
* Store all the local symbols in object files, not only the ones that need linker patches.
  This generates better map/sym files, and thus allows for better debugging as well.

* Add comments explaining the ->src and the (void)arg;
2021-03-03 10:59:51 +01:00
Rangi 365484ef18 Factor out handleCRLF()
This logic repeats ten times
2021-03-03 10:03:52 +01:00
Rangi 5e2bd35239 Factor out a 'plain_directive' parser rule similar to the reverted 'last_line'
Also expand on the comment explaining how the EOF-newline hack affects the parser
2021-03-02 20:46:17 -05:00
Rangi 6655e04ef0 Restore the "EOF-newline" lexer hack
This was removed in b3c0db218d
(along with two unrelated changes).

Removing this hack introduced issue #742, whereby INCLUDing
a file without a trailing newline can cause a syntax error.

A more proper fix would involve Bison's tracking locations,
but for now the EOF-newline hack fixes the issue while only
affecting some reported errors (expecting "newline"
instead of "end of file").

Fixes #742
2021-03-02 16:53:56 -08:00
ISSOtm 40c6b840f8 Add tests for certain directives at EOF without a newline 2021-03-02 16:53:56 -08:00
daid 5d6e0677d9 Fix error-related issues (#773)
* Mark `error` as a `format` function, to properly scan its format

* Fix the call to error() from parser.y:
  - Use '%s' to avoid passing an arbitrary format
  - Simplify yyerror overall

* Fix size parameter of %.*s format being an int... bonkers standard.

* Report the number of arguments required and provided on a STRFMT mismatch

* Add an assert to check for a very unlikely bug
2021-03-02 16:34:19 +01:00
Rangi 56071599e7 Allow trailing commas in bare lists
This applies to macro arguments, DB, DW, DL, DS,
PRINT, PRINTLN, EXPORT, PURGE, and OPT.

It also removes support for empty entries in DB/DW/DL.
(Deprecating it would require keeping parser support,
which is ambiguous with trailing commas.)

Fixes #753
2021-03-02 11:48:20 +01:00
Rangi c637447d5d Make the "db/dw/dl directive without data in ROM" warning more specific
Also use uppercase for DB/DW/DL to be consistent
2021-03-02 11:48:20 +01:00
Rangi ac2cefdd87 Refactor some math functions into a shared file for rgbasm and rgblink
Fixes #769

Fixes #770
2021-03-02 11:40:03 +01:00
Rangi 0774f5eb9d Rename math.c/mymath.h to fixpoint.c/.h
This also changes the functions' prefix
from "math_" to "fix_".
2021-03-02 11:40:03 +01:00
Rangi 76d8862900 Refactor part of getSection into createSection
getSection validates its parameters and calls
either mergeSections or createSection.
2021-02-28 16:12:03 -05:00
Rangi 1dafc1c762 Allow empty macro arguments, with a warning
Fixes #739
2021-02-28 10:38:49 -08:00
Rangi 63d15ac8c9 append_yylval_tzString should always evaluate its argument
Fixes #762
2021-02-28 10:38:49 -08:00
Rangi 1f579deaff Trim right whitespace from macro args before warning about length 2021-02-28 10:38:49 -08:00
Rangi fad48326f8 Support /* block comments */ in macro arguments
Fixes #746
2021-02-28 10:38:49 -08:00
Rangi e7d6ddf593 Fix linking tiny overlay files (#755)
* Fix compatibility of rgblink -O and -t

The -t "tiny mode" option makes ROM0 cover 0x8000 bytes,
not 0x4000. The -O "overlay" option fills areas uncovered
by sections with data from an overlay file. These needed
to cooperate so that the calculated uncovered overlay size
does not exceed the actual size of the ROM.

Fixes #754

* Print link test names like asm tests do

* Make the three test.sh scripts more similar
2021-02-24 23:04:51 -05:00
Rangi 953f79c0d9 Support 'MACRO mac' as well as 'mac: MACRO' for defining macros
The new syntax is used in documentation, but
the old syntax is not yet deprecated.
2021-02-25 04:42:35 +01:00
Rangi 3c5e1caa7c Disallow "." as a local label
Fixes #760
2021-02-25 04:40:42 +01:00
Rangi d4028fff10 Prevent ELIF or ELSE after an ELSE
Fixes #749
2021-02-25 04:39:49 +01:00
Rangi dd892d61d8 Correct rgbasm(5) about whitespace before labels
Also rephrase some more label-related documentation
2021-02-23 15:31:29 -05:00
Rangi a09f2d4115 Test an indented macro label 2021-02-23 14:48:27 -05:00
Eldred Habert dafef5a953 Remove column 1 restriction for labels with colons (#635)
Partial fix for #457
2021-02-23 14:42:24 -05:00
dannye 929e2a4490 rgbasm: Report conflicting file/line number for duplicate sections 2021-02-23 20:08:59 +01:00
dannye cc1129093d Add duplicate-section test 2021-02-23 20:08:59 +01:00
ISSOtm 72911ada2d Prevent non-numeric symbol from overriding refs
Fixes #751
2021-02-22 13:00:25 +01:00
Rangi 037bc7abb3 Add an rgblink test case for an $8000-byte ROM0 section with -t 2021-02-21 16:30:02 -05:00
Rangi 5fd636ac4b Implement floored / and divisor-sign % operators (#745)
Fixes #703
2021-02-21 16:14:44 -05:00
Rangi a6d844a9a5 Add more test cases for IF, REPT, and MACRO (#748) 2021-02-19 19:34:21 -05:00
ISSOtm bee62076c6 Allow ENDC at EOF without a newline 2021-02-20 00:51:33 +01:00
ISSOtm cd072d5e6a Add assertion check for potential UAF trigger
It actually currently triggers if an INCLUDE directive is given at EOF,
but #742 will fix that.
2021-02-19 16:53:30 +01:00
ISSOtm 6ef3ee1391 Give void* ptr to %p formatter
Silences a format type mismatch warning
2021-02-19 16:53:26 +01:00
ISSOtm c29b616f93 Fix forgotten initialization of lexerState->isReferenced 2021-02-18 16:33:06 +01:00
Rangi 39c179aa32 Fix missing newline in a dbgPrint 2021-02-17 13:14:02 -05:00
Rangi 5c1ae4ce22 Shorter quine test cases 2021-02-17 11:51:21 -05:00
Rangi efbfeca292 Avoid two peek(1) calls when lexing """multi-line strings""" 2021-02-17 10:36:36 -05:00
Rangi 7dd34f1572 Format INT32_MIN as '-2147483648', not '--2147483648' 2021-02-17 09:48:40 -05:00
Rangi 748e7dd4c7 Fix calculation of 2**30
In exponent(), 'base *= base;' should not run
when base is 65536, since it overflows an int32_t.

This also optimizes exponent() based on
gcc and clang -O3 test cases in godbolt.org.
2021-02-17 09:25:02 -05:00
Rangi d049ffc0f0 Handle string literals within macro arguments (#685)
Fixes #683 and #691

The lexer's raw mode for reading macro args already attempted
to handle semicolons inside string literals, versus outside ones
which start comments. This change reuses the same function for
reading string literals in normal and raw modes, also handling:

- Commas in strings versus between macro args
- Character escapes
- {Interpolations} and \1-\9 args inside vs. outside strings
- Multi-line string literals

Macro args now allow escaping '\', '"', and '\\'.

A consistent model for expanding macro args and interpolations,
within macro args, string literals, and normal context:

- "{S}" should always equal the contents of S
- "\1" should always act like quoting the value of \1
2021-02-16 22:44:25 -05:00
Rangi 8c0275480c Allow ds to take multiple values to repeat for a count (#725)
Fixes #722
2021-02-16 22:01:23 -05:00
Rangi 76d6ef8695 Implement LOAD UNION and LOAD FRAGMENT
Fix #632
2021-02-17 03:42:06 +01:00
Rangi c67a696a87 Use macros to convert between radians and fixed-point 65536ths 2021-02-16 18:07:05 -05:00
Rangi ee20d9010e Make @ relative to the start of a ds even at link time
Fix #737
2021-02-16 22:47:07 +01:00
Rangi 2bc12447e2 Update rgbds(5) object file format documentation (#740) 2021-02-16 16:36:37 -05:00
Rangi cb61da8842 -Wmacro-shift warns about shifting macro arguments too far (#741)
Fixes #735
2021-02-16 16:31:01 -05:00
ISSOtm 122ba6eba5 Update deprecated feature examples
Those have been removed, lol
2021-02-16 22:09:31 +01:00
Rangi dddff0f450 Cannot start a new section that's already on the stack
This is only relevant for FRAGMENT or UNION sections, since
normal ones would fail with "Section already defined previously".

Fixes #730
2021-02-16 21:51:48 +01:00
Antonio Vivace a919f922a1 Add FUNDING.yml to show the Sponsor button on the repository 2021-02-16 21:23:27 +01:00
Rangi 8f20620c16 Allow shifting macro arguments by a negative amount
Fixes #733
2021-02-14 16:21:00 +01:00
Rangi 96bce05be2 Newlines in multi-line strings update the line number
This affects error and warning messages, and dbgPrint
2021-02-14 16:16:52 +01:00
Rangi fc2bf3d11d Prefer sizeof($$) to MAXSTRLEN + 1
This makes `strsubUTF8` similar to `strrpl` and `strfmt`
2021-02-14 16:16:52 +01:00
Rangi 8415ce3ed0 Correct the keywordDict size
The stale keywords XDEF and GLOBAL were removed,
so there can be fewer keyword nodes.
2021-02-14 16:16:52 +01:00
Rangi ebb5aab6db Correct some comments
nPCOffset no longer exists, and the lexer only
returns T_NEWLINE for EOF in raw mode.
2021-02-14 16:16:52 +01:00
Rangi 464a3a4892 Separate extern getopt implementation from the unistd.h one
Fixes #710
2021-02-12 00:29:21 +01:00
ISSOtm 88e1cc7302 Make EOF token name consistent across Bison versions
The "end of file" name apparently only became a default recently
2021-02-11 13:04:43 +01:00
ISSOtm b3c0db218d Remove "EOF-newline" lexer hack
In preparation for an upcoming change
Makes for nicer error messages, complaining about EOF instead of newlines
The hack had to be kept for the lexer raw mode to avoid a bug;
see the relevant code comment for more info.
2021-02-11 12:48:37 +01:00
ISSOtm 76446e6d00 Change behavior of merging FRAGMENTs to constrain each fragment individually
Additionally, remove the deprecated merging of non-fragment SECTIONs
2021-02-10 10:19:16 +01:00
ISSOtm 6623b1dc45 Fix CI on macOS
Apple supplies version 2.3 (from 2006!!), which doesn't support `%empty`.
2021-01-23 13:45:12 +01:00
ISSOtm 70bbb098d3 Remove stale keywords
They were removed from the grammar, but not the lexer
2021-01-23 00:05:56 +01:00
ISSOtm 1926065377 Enable Bison warnings
-Wall should be old enough.
Also use %empty instead of comments
2021-01-23 00:05:56 +01:00
Rangi e3d355d976 Attempt to recover from syntax errors with bison
Fixes #595
2021-01-22 15:54:24 +01:00
ISSOtm a679e02246 Get rid of asm.h and localasm.h
No need to make them global
2021-01-22 13:34:16 +01:00
ISSOtm 592e9b3725 Reorganize and comment better main() 2021-01-22 11:09:27 +01:00
ISSOtm effc58241d Rework defining variables on command-line
Avoids allocating memory
Detects CLI errors even when failing to open file
Reports symbols as defined on command-line instead of input line 0 (!?)
2021-01-22 11:03:43 +01:00
ISSOtm 3697065afc Add asm/opt.c to CMakeLists
Fixes compiling with CMake
2021-01-22 11:01:33 +01:00
ISSOtm fa0fa4d5ac Significantly overhaul OPT code
Simplify the mess that was option setting (2 redundant variables !?)
Move options to a separate file
Have "modules" own their options, and OPT only access them (less redundancy)
Simplify code, respect naming conventions better
2021-01-22 10:41:09 +01:00
ISSOtm 5acc48fa54 Error out when given several input files
Also rename tzMainFile
2021-01-22 09:44:41 +01:00
ISSOtm 1487eebe79 Remove time counter
Nobody uses that, and it requires running extra code for each line
2021-01-22 08:51:57 +01:00
ISSOtm 993c034039 Avoid using EXPAND_AND_STR with external defines
There is no guarantee that they are purely numeric, use the values instead
2021-01-22 08:51:35 +01:00
ISSOtm 09f16bda4a Use putc instead of fputc
Also rename some functions for consistency
2021-01-22 08:32:28 +01:00
ISSOtm 41d544a4eb Rewrite RGBFIX
- Make it work inside pipelines
- Add RGBFIX tests to the suite
- Be more flexible in accepted MBC names
- Add warnings for dangerous or nonsensical input params
- Improve man page
2021-01-20 21:22:55 +01:00
Rangi f28b4abafc Fix a potential buffer overflow in strrpl
This caused an error using clang with -O3 -flto
2021-01-20 10:21:53 +01:00
ISSOtm ca1c934629 Have CMake use specified compiler in CI, not system default
Otherwise it's just GCC on Linux and Clang on macOS...
2021-01-19 16:35:06 +01:00
Rangi d5a00cf634 Comment cites the string hash algorithm (djb2)
"If you just want to have a good hash function,
and cannot wait, djb2 is one of the best string
hash functions I know."
2021-01-19 15:03:22 +01:00
Rangi fb39c3a70e Consistently refer to "directives", not "pseudo-ops"
Some docs and warnings already referred to SECTION and
db/dw/dl "directives", but others used "pseudo-ops".
2021-01-19 15:03:22 +01:00
ISSOtm 15ec6efc28 Fix missing newline in charmap override warning 2021-01-17 20:13:51 +01:00
Rangi 93d83e17dc Don't override bison's internal 'yytnamerr' function
This is not used in all bison versions, which causes a
"defined but not used" warning for the 'rgbasm_yytnamerr'
replacement, treated as an error by 'make develop'.
2021-01-15 11:51:31 +01:00
Rangi df16e64fc6 Handle MACRO and REPT/FOR bodies differently
Fixes #697
2021-01-15 02:16:37 +01:00
Rangi a4ebb87858 Add Rangi to contributors 2021-01-14 18:36:10 +01:00
Rangi 5ef8e0a1f6 Use an IELR parser if available 2021-01-14 18:36:10 +01:00
Rangi eb4952c188 Use more verbose syntax error messages
Fixes #385
2021-01-14 18:36:10 +01:00
ISSOtm 57b734a7df Reinstate RL into the _RS family
Removal of colon-less labels lifted the grammar ambiguity that
prevented `RL` from being usable as a variable declarator.
Thus, reinstate its functionality.
2021-01-11 01:38:03 +01:00
ISSOtm 5be1c0da62 Fix intra-section ALIGN not computing offset correctly 2021-01-09 23:29:08 +01:00
ISSOtm b598911e96 Enable LTO in release builds
Fixes #693
2021-01-09 20:31:15 +01:00
Rangi cab9cb06a3 Store IF depth relative to each fstack context
This disallows starting/ending an IF inside an
INCLUDEd file or a macro expansion
2021-01-09 20:12:14 +01:00
Rangi 62bea23c49 Implement BREAK to exit REPT and FOR loops
Fixes #684
2021-01-08 21:13:23 +01:00
Rangi 7ce5cf1595 Convert floating to fixed point by rounding, not truncation
Fixes #678
2021-01-04 21:23:43 +01:00
Rangi 7e3fc1db03 Fix Actions CI for MSVC
Fixes #616
2021-01-04 02:01:25 +01:00
Rangi 77279984a5 Implement STRRPL
Fixes #660

STRRPL(str, "", new) does nothing
(warn about it with -Wempty-strrpl)
2021-01-04 00:20:35 +01:00
Rangi 669a392fcd Revise the rgbasm(5) docs 2021-01-02 08:29:57 +01:00
ISSOtm 51ce0b038a Remove removed features from documentation 2021-01-02 02:47:13 +01:00
ISSOtm bd244e6865 Remove deprecated features
Trimming off the fat!
- GLOBAL and XDEF keywords
- Colon-less global labels
- *-comments
2021-01-02 02:42:44 +01:00
Rangi a70ecba06f Implement PRINT and PRINTLN (#672)
Fixes #669
Closes #368
Closes #624

Deprecate PRINTT, PRINTV, PRINTI, and PRINTF

Default STRFMT("%f") to 5 fractional digits like "{f:}"
Any use of string formatting will share this default
2021-01-02 02:37:32 +01:00
Rangi 9d2d5cfcfe Implement REDEF to allow redefining EQUS string equates
Fixes #677
2021-01-02 01:49:00 +01:00
ISSOtm 18f3c8ff9a Un-document deprecated _PI 2021-01-02 01:43:49 +01:00
Rangi 895ec5564d Update mathematical functions (#675)
Document the existing `ROUND`, `CEIL`, and `FLOOR` functions
Also update the trig function docs for searchability

Implement `POW` and `LOG`
Addresses part of #675

Implement ** for integer exponents
** has higher precedence than -, like Python, so -3**4 == -(3**4) == 81
2021-01-02 01:39:20 +01:00
Rangi 7bb6f71f0b Change FOREACH to FOR (#680) 2021-01-02 00:46:26 +01:00
Rangi 10e3f1a02b Deprecate built-in _PI
Fixes #670
2021-01-01 19:18:17 +01:00
Rangi 2a9d52871b Make dbgPrint in lexer.c report the correct colNo (#676)
Fixes #656
2021-01-01 18:44:47 +01:00
ISSOtm c4fb5591ee Fix size of unterminated REPT/FOREACH blocks
Do not "uncapture" ENDR if it was not read in the first place
2020-12-30 15:52:24 +01:00
Rangi c0ce1da4c3 Implement STRFMT and more printf-like format specifiers for string interpolation (#646)
Fixes #570
Fixes #178

Use errors for inapplicable format spec flags instead of -Wstring-format
2020-12-29 22:53:15 +01:00
ISSOtm aa27e714d4 Make Bison version detection more portable
- POSIX sh actually does NOT support `+=`,
  but Bash does even in compatibility mode
- `mawk` does not fully support POSIX EREs (regexes),
  so work around its lack of brace support
Fixes building on Debian, apparently.
2020-12-29 22:31:15 +01:00
Rangi 6874f694e5 Implement FOREACH (#658)
This acts like `REPT` with a variable automatically
incremented across a range of values

Fixes #432
2020-12-29 21:30:42 +01:00
Rangi 3690546795 make checkpatch and make checkcodebase check the same files
Only check src and include (not test), and
exclude src/extern and include/extern.
2020-12-29 20:27:00 +01:00
ISSOtm 7bc42d468b Clean up temp test files even if interrupted
Avoids "tmp.*" piling up in /tmp
2020-12-26 14:38:04 +01:00
ISSOtm 097999cad3 Prevent tests from running if RGBDS hasn't been built
Prevents a *lot* of spurious errors due to files not generating
2020-12-26 14:26:50 +01:00
ISSOtm f82edaa7ec Make gbdiff.bash handle CRLF sym files gracefully
Additionally, reduce the amount of lines piped through `cut`,
improving performance
2020-12-26 02:47:04 +01:00
ISSOtm d8e8b796e7 Update tested projects to latest commits
Compatibility fixes, etc.
2020-12-26 02:02:38 +01:00
ISSOtm 900fd8cabc Improve gbdiff script
Use better constructs where possible
- <<< instead of echo|
- Parameter expansions instead of `cut`
- Etc.
Improves performance and reliability somewhat

Also, accept "d" between diff line info parts
2020-12-26 01:44:45 +01:00
ISSOtm c20ac35074 Refactor readString
Much more readable, and avoids `peek(nz)`
2020-12-19 13:02:05 +01:00
Rangi 255b8bf9ba Implement """triple-quoted""" multi-line strings
Fixes #589
2020-12-19 12:34:32 +01:00
Rangi ad6f17cd93 Support SOURCE_DATE_EPOCH for reproducible builds
See https://reproducible-builds.org/docs/source-date-epoch/

Fixes #286
2020-12-19 01:09:45 +01:00
Rangi 063a22ddf9 LOAD blocks cannot create a ROM section
Fixes #576
2020-12-19 00:58:54 +01:00
Rangi 1d9cc01ae1 Macro arguments within a string literal are read into the string, not expanded
Fixes #643
2020-12-15 21:28:15 +01:00
Rangi f31deb5010 Fix STRUPR and STRLWR after 5aabb915ec
Fixes #647
2020-12-15 20:18:45 +01:00
Rangi 0956d300c4 Document \# 2020-12-14 10:48:03 +01:00
ISSOtm 4ef490f3cb Avoid interpreting Liquid in doc pages
They are auto-generated, so they wouldn't normally contain Liquid
(The post-processor may insert some, but it has control over the `raw` tags)
Some code introduced as examples contains `{{` due to nested brace expansions,
which was interpreted as (invalid) Liquid. This fixes such problems.
Additionally, Jekyll generates warnings about excerpts being part of a Liquid
block (the `{% raw %}`). This is fine, since doc pages don't use excerpts.
2020-12-14 10:35:30 +01:00
ISSOtm 8f2a894b88 Add anonymous labels
Fix #497
2020-12-14 10:14:40 +01:00
Rangi 0e40543757 Implement \# to expand to all unshifted macro arguments
Fixes #596
2020-12-14 00:12:36 +01:00
Rangi ce58f6d6be Allow {symbol} interpolation outside of strings
Fixes #629

Closes #631
2020-12-13 23:53:16 +01:00
ISSOtm 5aabb915ec Allow STRCAT to take any number of args
Fixes bullet point 1 of #625
2020-12-12 23:46:32 +01:00
ISSOtm 0d9de01f9d Make charmap-converting a non-UTF8 string non-fatal 2020-12-12 14:16:50 +01:00
ISSOtm f5b0eae9cd Remove custom action code when equivalent to default
Enables Bison to better reason about it, and should improve performance
2020-12-12 12:22:36 +01:00
Rangi e6552064bf Specify rgbfix --mbc-type by name
This supports the names listed in Pan Docs:
https://gbdev.io/pandocs/#_0147-cartridge-type
Spaces may be replaced with underscores.

It also supports "ROM" for "ROM ONLY".
2020-12-12 01:53:42 +01:00
Rangi 861cb552c4 discardBlockComment sets lexerState->disableMacroArgs = true, like discardComment 2020-12-12 01:34:01 +01:00
ISSOtm 417cceb0de Document dw and dl with strings 2020-12-11 11:02:20 +01:00
Rangi 165bd8cb71 Allow 'dw' and 'dl' to apply to characters of strings
Fixes #568

The old behavior of `dw "string"` can be replicated with `dw ("string")`; likewise for dl
2020-12-11 11:02:20 +01:00
ISSOtm e54e02dc77 Correct underscore-in-number documentation
No radix actually allows underscores at the beginning of a literal
2020-12-10 16:01:18 +01:00
ISSOtm 2bf3b08d76 Document underscores in numeric literals 2020-12-10 15:40:59 +01:00
ISSOtm 21b58b08b8 Fix not shifting CRLF at end of raw lines
Fixes line reporting errors on Windows
2020-12-10 15:37:50 +01:00
Rangi af530859f0 Allow underscores in numeric literals
Fixes #539

Changes \@'s output to start with "_u", not "_", so it will be valid within labels but not numerics
2020-12-10 15:34:21 +01:00
Rangi 58739b0bf2 Implement STRRIN, like STRIN but searching from the right 2020-12-10 15:32:17 +01:00
ISSOtm 3e4c2fe712 Avoid error with old Bison versions
`api.token.raw` is only defined starting with Bison 3.5
Since it's not essential, define it on the command-line iff the Bison
version is sufficient.
2020-12-10 15:13:45 +01:00
ISSOtm bdfce25db0 Avoid running version test when git describe fails
Can happen when not enough history has been fetched, notably in our CI
2020-12-10 13:43:22 +01:00
ISSOtm 2b6d9cd1e0 Avoid using yytoken_kind_t
Apparently it was added in a fairly recent Bison version...
2020-12-10 13:32:18 +01:00
ISSOtm bf789dd7b3 Add automated test for version consistency
Automatically check that the version number constants
(__RGBDS_MAJOR__ etc.) match `rgbasm -V`
Should avoid the problem with 0.4.2's release...
2020-12-10 12:22:29 +01:00
ISSOtm 9b6f01047c Enable raw token types
Removes one layer of indirection for the parser, and helps remove all literals from the grammar

The latter preparing the next change
2020-12-09 21:22:05 +01:00
ISSOtm 3fe2fa43bb Switch to GNU Bison as a dependency
First step for #595
2020-12-09 20:30:31 +01:00
ISSOtm ede982b50a Bump patch level appropriately
*HEADDESK*
2020-12-09 20:30:31 +01:00
ISSOtm 319d775c13 Add CI script to create docs on new releases 2020-12-09 16:08:43 +01:00
ISSOtm 44124319a6 Work around old Bison versions not forward-declaring yyparse
Notably, macOS still ships 2.3 (from 2008)...
Should fix #214
2020-12-09 16:00:22 +01:00
ISSOtm 462fd7539c Prohibit nested macros
After discussion (starting there:
https://github.com/gbdev/rgbds/pull/594#issuecomment-706437458
), it was decided that plain nested macros should not be
allowed.
Since #590 is fixed, EQUS can be used as a workaround;
multiline strings (#589) will make that easier on the
user when implemented.
Fixes #588, supersedes and closes #594.
Additionally, closes #388.
2020-12-09 10:44:39 +01:00
ISSOtm f16e34b804 Fix captures beginning in expansions
Fixes #590
2020-12-09 09:54:55 +01:00
ISSOtm c3ccdc548e Remove unnecessary flex dep from Dockerfile 2020-12-09 09:42:19 +01:00
ISSOtm fd721ca480 Document optional RB/RW/RL argument 2020-12-09 09:39:46 +01:00
ISSOtm eac365aef0 Allow argument to rb, rw and rl to be optional
Fixes #617
2020-12-09 09:31:47 +01:00
ISSOtm 4de6266442 Add explanation of how EXPORT works
Fixes #608
2020-12-08 21:07:24 +01:00
ISSOtm 213d985e17 Fix incorrect "sliced" INCBIN causing memory leaks
Oh, how I miss RAII...
2020-11-29 12:47:53 +01:00
ISSOtm de76dcb8fb Fix possible segfault from -MT and -MQ
Happened only if `malloc` failed, so...
2020-11-29 12:47:53 +01:00
Eldred Habert 30fb6bde5e Merge pull request #615 from ISSOtm/find-sym
Create specialized symbol finder functions
2020-11-25 15:17:34 +01:00
ISSOtm 4f842a1248 Create specialized symbol finder functions
The old "find symbol with auto scope" function is now three:
- One finds the exact name passed to it, skipping any checks
  This is useful e.g. if such checks were already performed.
- One checks that the name is not scoped, and calls the first.
  This is useful for names that cannot be scoped, such as checking for EQUS.
  Doing this instead of the third should improve performance somehwat, since
  this specific case is hit by the lexer each time an identifier is read.
- The last one checks if the name should be expanded (`.loc` → `Glob.loc`),
  and that the local part is not scoped. This is essentially the old function.
2020-11-21 01:06:17 +01:00
ISSOtm cc4d455b8a Add test for empty local label component 2020-11-21 00:58:40 +01:00
Eldred Habert 0bb5efebfd Merge pull request #610 from daid/stdin
Allow rgbasm and rgblink to use stdout and stdin as input and output
2020-11-08 01:20:44 +01:00
ISSOtm b6bf7ae620 Fix RGBLINK incorrectly reading file stack nodes
This caused node IDs to mismatch, yielding possibly corrupted file stacks
Worst part is, the docs mentioned the reading order had to be reversed...
2020-11-04 02:52:06 +01:00
ISSOtm dc96cc6d1e Add zsh completion scripts
Can't get bash ones to work, but these do.
2020-11-03 23:29:47 +01:00
daid 642daf1a76 Update main.c 2020-11-03 13:33:57 +01:00
daid 84edfb3d88 Update output.c 2020-11-03 13:33:02 +01:00
Daid 7e620bff81 Allow rgbasm and rgblink to use stdout and stdin as input and output 2020-10-26 20:28:15 +01:00
ISSOtm 0c55703438 Improve helpers.h
Use C11 standard _Noreturn instead of attributes (except, of course, MSVC)
Remove unused helpers
Avoid trapping in release builds, in favor of just unreachability
Improve shim when __builtin_* are not available
2020-10-26 15:19:31 +01:00
ISSOtm 6c57ad2226 Have make clean delete parser artifacts
Forgot to update the names there
2020-10-25 16:26:58 +01:00
ISSOtm 9028fb5391 Fix mistakes in RGBDS man pages
As reported by `mandoc -Wall`
2020-10-23 01:02:59 +02:00
ISSOtm 12dc49b60a Make page processor print usage only after reporting all bad opts 2020-10-23 00:40:05 +02:00
Eldred Habert 7e1d20acdf Merge pull request #607 from anderoonies/inline-comment-#537
handle inline c-like comments in lexer
2020-10-19 19:36:49 +02:00
anderoonies 5230104852 documentation for block comments 2020-10-19 18:05:37 +02:00
anderoonies 55be77be69 discard block comments delimited with /* */ 2020-10-15 12:42:53 -04:00
Eldred Habert 42b3a17356 Merge pull request #602 from NieDzejkob/shiftstorm
Report only one error when invalid shift has argument
2020-10-13 15:48:16 +02:00
Jakub Kądziołka 4e1d79081c Improve error message for negative shift arguments 2020-10-13 15:42:16 +02:00
ISSOtm 4ce4fdec71 Mention setting CMAKE_BUILD_TYPE to Release when using CMake
Not *necessary*, but if you don't know better, you should probably use it.
Fixes rgbds-www#9
2020-10-13 11:37:25 +02:00
Eldred Habert 05256946ac Merge pull request #604 from NieDzejkob/narg-overwrite
Don't overwrite symbol when it's not allowed
2020-10-13 10:47:57 +02:00
Eldred Habert 73396166aa Merge pull request #605 from NieDzejkob/invalid-labels
Don't consider difference of invalid labels constant
2020-10-13 10:42:05 +02:00
Jakub Kądziołka 4c5d5c7085 Don't consider difference of invalid labels constant
If a label is defined outside of a section, avoid trying to obtain its
value.
2020-10-12 23:03:14 +02:00
Jakub Kądziołka 045a9e8b93 Report only one error when invalid shift has argument
Not to mention that incrementing a variable in a loop is kinda dumb.
2020-10-12 22:54:20 +02:00
Jakub Kądziołka 4419f0d54f remove dead function: sym_GetDefinedValue 2020-10-12 13:31:21 +02:00
Jakub Kądziołka b07aa00d5c Don't overwrite symbol when it's not allowed
When a user tried to overwrite a builtin symbol, it would change its
type despite the error, making the second try succeed. This is
problematic, as the location of a builtin symbol cannot be updated.
2020-10-12 12:35:49 +02:00
Eldred Habert e4f5df1306 Merge pull request #603 from NieDzejkob/rpn-realloc
reserveSpace: don't assume one doubling is enough
2020-10-12 12:26:44 +02:00
Jakub Kądziołka dc62d60e9b reserveSpace: don't assume one doubling is enough 2020-10-12 11:57:03 +02:00
ISSOtm 71d8aeb4c2 Add CMake defines to enable tracing lexer and parser 2020-10-12 09:02:21 +02:00
Eldred Habert 0836f67d42 Merge pull request #601 from NieDzejkob/utf8decoder
utf8decoder: Use byte-sized byte argument
2020-10-12 01:49:57 +02:00
Eldred Habert 176a57a1e9 Merge pull request #600 from NieDzejkob/stray-shift
Report error when shifting outside a macro
2020-10-12 01:44:10 +02:00
Eldred Habert 0d02355dbf Merge pull request #599 from NieDzejkob/stray-align
Report error when aligning outside of a section
2020-10-12 01:43:35 +02:00
Jakub Kądziołka 6767d11c23 utf8decoder: Use byte-sized byte argument
This prevents passing a negative value out of a signed char by accident.
Also renders some casts in the code superfluous.
2020-10-12 01:22:09 +02:00
ISSOtm 2dd9015dc6 Remove two stale variables from parser.y
They were made useless with the lexer rewrite
2020-10-12 00:52:12 +02:00
Jakub Kądziołka 217c10ddac Report error when shifting outside a macro 2020-10-12 00:47:01 +02:00
Jakub Kądziołka 822e4e7c44 Report error when aligning outside of a section 2020-10-12 00:27:54 +02:00
ISSOtm 0b1d01792d Indicate cur offset in linkerscript "backwards org" message 2020-10-12 00:04:08 +02:00
ISSOtm 01637768cf Rename asmy to more explicit parser
This should make the purpose of that file clearer to newcomers
2020-10-11 21:03:41 +02:00
ISSOtm 6a8ae643d5 Mention that SHIFT updates _NARG
Fixes #598
2020-10-11 02:13:30 +02:00
ISSOtm fd83d46ba0 Enable master docs update workflow always
There seems to be no way to make the check work, and Actions are disabled
in forks by default anyways.
2020-10-11 02:04:09 +02:00
ISSOtm 914856342c Fix incorrect documentation of accepted sym names
No, they cannot start with a digit!
2020-10-11 01:57:27 +02:00
Eldred Habert 91889fc14a Merge pull request #593 from Rangi42/issue586
Fix #586: Update the `charmaps` hashmap when an existing charmap is resized
2020-10-10 02:15:04 +02:00
Rangi 7c8ec5a5ed Add a test case for charmaps that segfaults prior to this fix 2020-10-09 20:06:02 -04:00
Rangi effc6788eb Fix #586 segfault: Update the charmaps hashmap when an existing charmap is resized 2020-10-07 13:21:13 -04:00
Eldred Habert f9daf27511 Merge pull request #585 from ISSOtm/msvc-ci
Add MSVC in CI
2020-10-06 17:48:13 +02:00
ISSOtm 06f7387466 Avoid using VLA in EQUS dumping
MSVC does not support those...
Also add a `develop` warning about VLAs, to avoid future incidents
2020-10-06 08:55:45 +02:00
ISSOtm 21e50eeff1 Have lexer not require <unistd.h> on MSVC
Required for `open`, `close`, `read`, and `STDIN_FILENO`,
which are defined elsewhere on MSVC.
2020-10-06 08:55:45 +02:00
ISSOtm fd4cec93cd Compile with MSVC as well in CI 2020-10-06 08:55:41 +02:00
ISSOtm 92f2055a6c Fix implicit cast between enums
This caused `make develop` to fail
2020-10-05 01:53:54 +02:00
Eldred Habert be9b1198e9 Merge pull request #584 from Xeyler/master
Add directory summary to README.rst
2020-10-04 20:20:08 +02:00
Brigham Campbell 56bea083f9 Add directory summary to README.rst 2020-10-04 12:04:59 -06:00
Eldred Habert fdfc02ab96 Merge pull request #583 from JL2210/cmake-build-type
Modularize CMake build configuration
2020-10-04 19:45:20 +02:00
Eldred Habert fc7f042ad6 Merge pull request #551 from NieDzejkob/errors-after-unknown-symbol
link: Suppress cascading errors.
2020-10-04 19:43:38 +02:00
James Larrowe 761c775043 Modularize CMake build configuration
Build type no longer defaults to Release (!)
have separate options for extra warning flags and sanitizers

toss DEVELOP macro

Fix sanitizers with CMake while I'm at it :|
2020-10-04 13:28:00 -04:00
Jakub Kądziołka b421c983d6 link: Suppress cascading errors. 2020-10-04 18:14:22 +02:00
Eldred Habert 3036b58598 Merge pull request #557 from ISSOtm/new-lexer-electric-boogaloo
New lexer 2 — Electric Boogaloo
2020-10-04 16:45:47 +02:00
ISSOtm 2eca43cd2d Fix critical oversight in lexer buffer refilling
Since the lexer buffer wraps, the refilling gets handled in two steps:
First, iff the buffer would wrap, the buffer is refilled until its end.
Then, if more characters are requested, that amount is refilled too.

An important detail is that `read()` may not return as many characters as
requested; for this reason, the first step checks if its `read()` was
"full", and skips the second step otherwise.
This is also where a bug lied.

After a *lot* of trying, I eventually managed to reproduce the bug on an
OpenBSD VM, and after adding a couple of `assert`s in `peekInternal`, this
is what happened, starting at line 724:

0. `lexerState->nbChars` is 0, `lexerState->index` is 19;
1. We end up with `target` = 42, and `writeIndex` = 19;
2. 42 + 19 is greater than `LEXER_BUF_SIZE` (= 42), so the `if` is entered;
3. Within the first `readChars`, **`read` only returns 16 bytes**,
   advancing `writeIndex` to 35 and `target` to 26;
4. Within the second `readChars`, a `read(26)` is issued, overflowing the
   buffer.

The bug should be clear now: **the check at line 750 failed to work!** Why?
Because `readChars` modifies `writeIndex`.
The fix is simply to cache the number of characters expected, and use that.
2020-10-04 16:10:32 +02:00
ISSOtm c24694233f Fix incomplete duplication of REPT nodes
"Initialization, sizeof, and the assignment operator ignore the flexible array member."
Oops!
2020-10-04 04:46:01 +02:00
ISSOtm 423a7c4899 Handle \\r better
Translate it to \\n regardless of the lexer mode
2020-10-04 04:46:01 +02:00
ISSOtm ee9e45b3d4 Change assertion condition in __FILE__ buf dumping
Removes a false positive from Clang static analysis
2020-10-04 04:46:01 +02:00
ISSOtm 5a65188ca9 Implement compact file stacks in object files
Gets rid of `open_memstream`, enabling Windows compatibility again
Also fixes #491 as a nice bonus!
2020-10-04 04:46:01 +02:00
ISSOtm 930080f556 Mark not unmapping macro-containing files as okay
There isn't really a better alternative.
Making several mappings instead requires too much bookkeeping.
2020-10-04 04:46:01 +02:00
ISSOtm 8e7afb0ab3 Move some MSVC-specific defines to platform.h 2020-10-04 04:46:01 +02:00
ISSOtm 138523570e Fix possible uninitialized read on Windows 2020-10-04 04:46:01 +02:00
ISSOtm 82469ac0fd Shim around mmap on Windows 2020-10-04 04:46:01 +02:00
ISSOtm 96cb5e10ed Fix range-dependent dead code in recursion depth check 2020-10-04 04:46:01 +02:00
ISSOtm b224cab3e0 Harmonize printing distance 2020-10-04 04:46:01 +02:00
ISSOtm 7381d7b92f Remove unnecessarily nested symbol data union 2020-10-04 04:46:01 +02:00
ISSOtm dbef51ba05 Move isWhitespace to a place where it makes more sense 2020-10-04 04:46:01 +02:00
ISSOtm c952dd8a6e Fix fixed-point constants not working correctly
And added a test to check their behavior
2020-10-04 04:46:01 +02:00
ISSOtm b65ea64a58 Add newlines to all test output
MacOS treats them differently, for some reason.
2020-10-04 04:46:01 +02:00
ISSOtm 542b5d18f1 Fix possible capture buffer size overflow
Attempt to grow it to the max size first.
Seriously, if this triggers, *how*
2020-10-04 04:46:01 +02:00
ISSOtm 71a0a42cfb Fix C2x use of static_assert 2020-10-04 04:46:01 +02:00
ISSOtm ac011fe69f Use common function to discard comments in macro args 2020-10-04 04:46:01 +02:00
ISSOtm 9e3d7a50e6 Handle comments in line continuations 2020-10-04 04:46:00 +02:00
ISSOtm e33c2ad6a2 Fix INCLUDE ignoring -MG 2020-10-04 04:46:00 +02:00
ISSOtm 615f1072d9 Fix readFractionalPart never shifting characters 2020-10-04 04:46:00 +02:00
ISSOtm f7b7a97407 Prevent expanding macro args in comments
Also use a cleaner way, instead of hardcoding to capture
2020-10-04 04:46:00 +02:00
ISSOtm ece6853e0f Implement opt b and opt g 2020-10-04 04:46:00 +02:00
ISSOtm b7b03ee451 Fix "REPT 0" not being a no-op 2020-10-04 04:45:59 +02:00
ISSOtm f9b48c0cad Fix else working incorrectly from macros
Since the "skip ELSE blocks" variable is global, it used to get carried
over from the macro's `if` to the outer's.
2020-10-04 04:45:59 +02:00
ISSOtm aa76603da9 Add line+col trace info to lexer 2020-10-04 04:45:59 +02:00
ISSOtm b83b9825f8 Fix _NARG crashing outside of macros
And add a test for it
2020-10-04 04:45:59 +02:00
ISSOtm d641972cde Fix macro args not being restored when exiting macros 2020-10-04 04:45:59 +02:00
ISSOtm 4d1333e124 Fix incorrect error reporting of INCLUDEd files 2020-10-04 04:45:59 +02:00
ISSOtm 35396e6410 Fix files being unmapped when still referenced by macros 2020-10-04 04:45:59 +02:00
ISSOtm 8d18b39eee Support missing register tokens
Made possible by #491
2020-10-04 04:45:59 +02:00
ISSOtm ae77893021 Fix file name reporting
As noted in the function's code, this is very error-prone, but
will do the job; this needs rewriting due to #491 anyways, so, temporary.
2020-10-04 04:45:59 +02:00
ISSOtm baeb180acd Apply error reporting changes to tests 2020-10-04 04:45:58 +02:00
ISSOtm fd02ffb7bd Implement __FILE__ symbol
Also clean up built-in symbol creation
This is not great, but currently okay.
Should be fixed later, like the rest...
2020-10-04 04:45:58 +02:00
ISSOtm 62ecdce0b0 Fix line-continuation-macro test 2020-10-04 04:45:58 +02:00
ISSOtm e4f2fad215 Support line continuations in main scope 2020-10-04 04:45:58 +02:00
ISSOtm 3f5f9bcaf0 Fix numeric constant overflow checks 2020-10-04 04:45:58 +02:00
ISSOtm 08867b3cec Enable catching invalid macro arg 0 2020-10-04 04:45:55 +02:00
ISSOtm 9081feab51 Reinstate macro arg scan distance
Used to be broken, so it was removed, but doing so prevents escaping them.
So it was instead put back in, but with corrected behavior
2020-10-04 04:39:27 +02:00
ISSOtm cf992164f7 Fix lexer capture sometimes not being reset 2020-10-04 04:39:27 +02:00
ISSOtm b27b821e7f Fix RAW lexer length underflow
Also added an assertion to check against more such overflows
2020-10-04 04:39:26 +02:00
ISSOtm d9ecaabac1 Add debug tracing code to lexer
Hidden behind a #define, like YYDEBUG
2020-10-04 04:39:26 +02:00
ISSOtm cd747d8175 Fix many lexer bugs
More to come...
2020-10-04 04:39:25 +02:00
ISSOtm df75fd2ec2 Fix expansion reporting being incorrect 2020-10-04 04:38:53 +02:00
ISSOtm adcaf4cd46 Fix crash when no macro args are being used 2020-10-04 04:38:53 +02:00
ISSOtm 81a77a9b88 Re-implement block copy to avoid expanding macro args
They were expanded during the capture, and there was no easy way to
avoid expanding them (believe me, after three hours and somehow an OOM, I
gave up trying).
2020-10-04 04:38:53 +02:00
ISSOtm 6e805cd318 Implement macro args
This finally allows running 90% of the test suite, debugging time!
2020-10-04 04:38:53 +02:00
ISSOtm e11f25024e Add test for built-in file symbol
It's currently defined in fstack.c, making it more prone to accidental
dropping. Let's not repeat the 0.3.9 scenario...
2020-10-04 04:38:53 +02:00
ISSOtm 7c895f8a1b Fix diagnostic formatting
Missing colon and space after the file stack
2020-10-04 04:38:53 +02:00
ISSOtm 38bda7e1bb Fix string expansion reporting
More expansions were allowed than the limit specified, and reporting code
did not account for the extra one that caused overflow
2020-10-04 04:38:52 +02:00
ISSOtm 149db9a022 Fix incorrect freeing of expansions
Freeing an expansion should free its children, not its siblings...
Fixes a use-after-free reported by scan-build. Nice catch!
2020-10-04 04:38:52 +02:00
ISSOtm fed252bc49 Fix nested expansions being incorrectly handled
The biggest problem was simply that the length of children expansions was
not accounted for when skipping over the parent... this took a lot of
arduous debugging, but it finally works!
2020-10-04 04:38:52 +02:00
ISSOtm 61b2fd9816 Add string expansion reporting
And fix line counting with expansion-made newlines.
This has the same bug as the old lexer (equs-newline's output does not
print the second warning as being part of the expansion).
Additionally, we regress equs-recursion, as we are no longer able to
catch this specific EQUS recursion. Simply enough, the new expansion
begins **after** the old one ends! I have found no way to handle that.
2020-10-04 04:38:52 +02:00
ISSOtm 5ad7a93750 Add EQUS expansion 2020-10-04 04:38:52 +02:00
ISSOtm 2ec10012b6 Fix mmap read offset not being initialized 2020-10-04 04:38:52 +02:00
ISSOtm e56c6cc291 Fix PC's name not being passed to parser 2020-10-04 04:38:52 +02:00
ISSOtm 4c9a929a14 Implement almost all functionality
Add keywords and identifiers
Add comments
Add number literals
Add strings
Add a lot of new tokens
Add (and clean up) IF etc.
Improve reporting of unexpected chars / garbage bytes
Fix bug with and improved error messages when failing to open file
Add verbose-level messages about how files are opened
Enforce that files finish with a newline
Fix chars returned not being cast to unsigned char (may conflict w/ EOF)
Return null path when no file is open, rather than crash
Unify and improve error printing slightly

Known to be missing: macro expansion, REPT blocks, EQUS expansions
2020-10-04 04:38:50 +02:00
ISSOtm 71f8871702 Implement more functionality
Macro arg detection, first emitted tokens, primitive (bad) column counting
2020-10-04 04:37:58 +02:00
ISSOtm 6dc4ce6599 Implement infrastructure around new lexer
The lexer itself is very much incomplete, but this is intended to be a
safe point to revert to should further implementation go south.
2020-10-04 04:37:58 +02:00
Eldred Habert 3a44cc7722 Merge pull request #582 from ISSOtm/rewrite-charmap
Rewrite charmap system
2020-10-04 04:37:06 +02:00
ISSOtm 4cfed3c98f Rewrite charmap system
Avoid allocating a *ton* of data per charmap
Stop relying on uninitialized data in charmap nodes
Only initialize charmap nodes lazily
2020-10-04 04:31:10 +02:00
Eldred Habert 6af57ff026 Merge pull request #581 from JL2210/cmake-docs
Install manpages with CMake
2020-10-03 22:15:17 +02:00
ISSOtm 2e3db9d56a Clean up label generation
Only check for localness when we already know we have a local
2020-10-03 21:33:30 +02:00
James Larrowe f8d9fa87ed Install manpages with CMake 2020-10-03 12:37:56 -04:00
ISSOtm f53ad359a6 Remove whoami step from Windows CI
A carry-over from testing
2020-10-03 02:17:18 +02:00
ISSOtm 84de86beb5 Enable make develop on Ubuntu 20.04 CI as well 2020-10-03 01:05:09 +02:00
Eldred Habert 04e7af2675 Merge pull request #579 from ISSOtm/cmake-ci
Enable CMake in CI
2020-10-02 23:30:26 +02:00
Eldred Habert 4f13a336b9 Merge pull request #578 from JL2210/cmake-pkgconfig
Use pkg-config to detect libpng
2020-10-02 22:30:30 +02:00
ISSOtm 03508119e5 Use CMake in CI as well 2020-10-02 22:24:02 +02:00
James Larrowe 03e20138d3 Use pkg-config to detect libpng
Only fall back to findpng
2020-10-01 18:58:36 -04:00
Antonio Niño Díaz dfcba36448 test: Update commit of uCity used for testing
This one updates the code to fix all warnings introduced in the last few
months because of updates to RGBDS.
2020-09-27 22:47:56 +01:00
ISSOtm 8e4a9a5c21 Remove assertions from release builds
I believe the CMakeLists already did that, but the Makefile did not.
2020-09-27 17:05:52 +02:00
ISSOtm a1286e6f0e Make newlines explicit in error messages
In preparation for a change a PR is about to make
2020-09-27 10:54:06 +02:00
ISSOtm c0808246e5 Silence the mingw test
Use "quiet" instead of "count"...
2020-09-27 10:51:52 +02:00
ISSOtm ba051e10fb Factor printing assert failures into functions
Saves some code duplication
2020-09-27 09:24:24 +02:00
ISSOtm 9fee0603b1 Fix typo in object file format doc
Thanks @ax6!
2020-09-24 16:43:13 +02:00
ISSOtm be8ebe6db9 Fix master docs update CI script
GitHub documentation about the syntax is unclear, this should be right
according to the examples I saw.
2020-09-24 16:41:23 +02:00
ISSOtm 548e3dc31c Correct previously-introduced test being a no-op
Forgot to invoke the macro due to a copy-paste error
2020-09-24 16:35:45 +02:00
ISSOtm 9440086d77 Add a test for purging a macro while running
This could cause a crash if the macro name is then used for error reporting
2020-09-24 16:14:18 +02:00
ISSOtm ec5a1bc71f Fix incorrect obj file documentation
Bit 7 of section types was actually documented in the symbol type
Bit 6 of section types was not documented at all
2020-09-24 10:26:02 +02:00
ISSOtm 9742fa731c Run the quote in file name except on Windows
This should make the CI function again
2020-09-22 18:13:26 +02:00
ISSOtm 91a3c538d9 Enable running regression tests on PRs as well 2020-09-22 17:27:29 +02:00
ISSOtm e98485da3f Make code style errors fail their CI job
Mimics the behavior of the old Travis script
2020-09-22 02:59:38 +02:00
ISSOtm 6528a955fe Fix checkpatch in CI 2020-09-22 02:44:24 +02:00
ISSOtm 431f77127e Also update master docs when updating script 2020-09-22 01:05:49 +02:00
ISSOtm 2cc58723cb Do not try updating docs if no key is set
This will avoid this randomly failing in forks, unless we want to run it
2020-09-22 00:56:14 +02:00
ISSOtm 268219d74e Avoid warning about /* fallthrough */ comments
We do not have `fallthrough;`, so...
2020-09-21 17:46:44 +02:00
ISSOtm d09ed3e52e Get rid of flex as a dependency in CMakeLists
It will actually not be needed for new lexer
2020-09-20 03:39:53 +02:00
ISSOtm 421d1f5490 Add regression test for #546
Check for quotes in `__FILE__`
2020-09-20 00:44:29 +02:00
ISSOtm 66784b7122 Fix documentation not mentioning SECTION FRAGMENTsyntax 2020-09-20 00:06:51 +02:00
ISSOtm 54f2d99ce7 Apply two minor fixes to rgbasm(5)
Mustn't → must not
Add a comma to INCBIN sentence to mirror INCLUDE's
2020-09-17 20:45:58 +02:00
ISSOtm 557c799ec9 Update README to point to online install instructions 2020-09-17 03:47:55 +02:00
ISSOtm d22a667095 Update help text to redirect to new online docs 2020-09-17 03:10:02 +02:00
ISSOtm 30085a5342 Update documentation link in README 2020-09-16 15:52:36 +02:00
ISSOtm 304e6c4279 Sync redirect page generation with site 2020-09-16 06:25:46 +02:00
ISSOtm 12458aae6f Fix permalinks of index pages 2020-09-16 06:04:38 +02:00
ISSOtm 7e5d9683b1 Use mandoc 1.14.5 in CI
This is the version that added -Otoc
2020-09-15 19:24:25 +02:00
ISSOtm 210a4a957a Get rid of in-repo HTML documentation
The online documentation is now managed by a CI hook
2020-09-15 18:39:22 +02:00
ISSOtm 131ad9b315 Fix GitHub link in BUGS sections 2020-09-15 18:35:04 +02:00
ISSOtm 06b4cf57ab Fix example arguments to -MT appearing as options 2020-09-15 18:32:13 +02:00
ISSOtm dbefdc923a Clean up doc post-processor
Description blurb is already inline from new stylesheet
`Xr` links are already handled by `mandoc` now
Handle spaces between both dashes in long options
Remove `<head>` modifications, as fragments are generated instead
2020-09-15 18:30:40 +02:00
ISSOtm 37e45de9c1 Improve rendering of pages
Make links to other man pages work
Add a table of contents to rgbasm(5)
Make the OS at the bottom of all pages 'Linux'
Apply post-processor that used to be used
2020-09-15 18:27:55 +02:00
ISSOtm 5e63527190 Update repo link at bottom of all man pages 2020-09-15 16:00:17 +02:00
ISSOtm 0cc9026978 Fix docs update action
Make script executable (facepalm)
Fix `run**s**-on` typo
Add key using ssh-agent
Force using SSH for pushing back
2020-09-15 15:57:20 +02:00
ISSOtm bb6a5441ed Update RGBDS history to mention org move 2020-09-15 15:02:26 +02:00
ISSOtm 0ffda1bf29 Add CI Action to update man pages from master 2020-09-15 15:00:07 +02:00
Antonio Vivace 56b5f77dc8 Mention the new website, add notice about the movement to the gbdev org 2020-09-15 14:01:38 +02:00
Antonio Vivace 6eb284f99e Update README.rst 2020-09-15 13:53:22 +02:00
Marco Spataro 34c2288fd0 Fix __FILE__ when filename contains quotes 2020-09-10 12:49:04 +02:00
ISSOtm 304bb9f902 Remove most Hungarian notation in section module
Seriously, it sucks.
2020-09-06 20:43:13 +02:00
ISSOtm 14be01880d Move UNION code inside section.c
Improves organization and locality
2020-09-06 19:18:10 +02:00
ISSOtm 12b7cf3cd4 Move curOffset into section code
Improves organization
2020-09-06 18:50:19 +02:00
ISSOtm 0d7914bff7 Fix asm/charmap.h not including required header 2020-09-06 17:16:49 +02:00
ISSOtm d2285953d7 Fix test missed by last PR
We need to fix CI
2020-09-03 14:28:28 +02:00
Eldred Habert d2801505c3 Merge pull request #562 from Rangi42/strsub-0
Resolve #554: STRSUB("<N-char string>", N, 0) will not warn "Position N is past the end of the string"
2020-09-03 12:12:03 +02:00
ISSOtm 9d62b4b9bb Fix bugs with LOAD section size
LOAD blocks did not properly update their parent's size until after closed
Additionally, section size wasn't correctly sanitized inside LOAD blocks
2020-09-03 12:07:12 +02:00
Rangi b65b723fa6 Resolve #554: STRSUB("<N-char string>", N, 0) will not warn "Position N is past the end of the string" 2020-08-31 15:40:25 -04:00
ISSOtm e05321356b Fix truncation warning when adding charmap mapping
It used to warn when mapping negative values
2020-08-31 21:33:53 +02:00
ISSOtm 0778959e98 Remove arbitrary limits on charmap
They were made irrelevant when switching to a trie
2020-08-31 21:26:21 +02:00
Eldred Habert 76331d1c4a Merge pull request #552 from mattcurrie/incbin-length-optional
Make INCBIN's length argument optional
2020-08-23 00:11:54 +02:00
Eldred Habert 9e378ec5cf Bump license year
I feel like there's a 20xx joke to be made here...
2020-08-20 23:02:25 +02:00
ISSOtm f57d33b17a Update subprojects in test suite
Especially necessary for the "new lexer" branch
2020-08-18 16:40:41 +02:00
Matt Currie c389e8dccb Fix typo
'arugment' => 'argument'
2020-08-17 13:57:58 +12:00
Matt Currie 90c64a94d1 Revert change to rgbasm.5.html
Will be rebuilt upon release
2020-08-17 13:56:29 +12:00
Eldred Habert df27af6d1c Merge pull request #553 from JL2210/cmake-develop
Add DEVELOP option to CMake
2020-08-16 22:12:47 +02:00
James Larrowe c85b48f23e Default to debug when building in develop mode 2020-08-16 13:58:02 -04:00
James Larrowe 5a9f2b7750 Add DEVELOP option to CMake
This requires CMake 3.0 so -Werror won't conflict with link tests.
Remove all version checks to improve simplicity.
2020-08-16 13:23:29 -04:00
ISSOtm fcfecc6e82 Improve description of @ symbol
As requested by someone on GBDev
2020-08-15 15:23:11 +02:00
Matt Currie f863a927c1 Make INCBIN's length argument optional
INCBIN can now be used with just a start position to include everything
from the start position until the end of the file.
2020-08-15 17:24:11 +12:00
Eldred Habert cb4fbdfcd5 Merge pull request #550 from rednex/an/array
Refactor warning array for clarity
2020-08-05 10:53:21 +02:00
Eldred Habert c6eacde55e Merge pull request #544 from ISSOtm/atomic_ind
Split register-indirect tokens
2020-08-05 10:52:18 +02:00
Antonio Niño Díaz daf780c7e6 Refactor warning array for clarity 2020-08-04 22:28:56 +01:00
Eldred Habert 613305d234 Add checkpatch link in README 2020-07-31 16:07:00 +02:00
ISSOtm 656432301d Run as many CI jobs as possible when one fails
The other matrixes should not have this problem, so only touch unix testing
2020-07-27 18:34:32 +02:00
ISSOtm 38a80f2816 Fix test failing on OS-dependent trailing newline 2020-07-27 18:30:12 +02:00
ISSOtm 6563133426 Avoid using echo -e in tests 2020-07-27 18:26:05 +02:00
ISSOtm 762474d3ac Let RGBASM write JR offsets in floating sections
This requires some special-casing for `jr @` because the `jr` opcode has
already been emitted, but not the operand, so PC points to the middle.
Moved the RGBLINK test to RGBASM's folder, and created a new RGBLINK test.
2020-07-27 18:17:29 +02:00
ISSOtm b1adbcc77c Output a non-empty RPN buffer from known expressions
The code expected to never get "known" expressions passed in, as RGBASM
otherwise patches the bytes in by itself; however, JR cannot be patched in
by RGBASM unless the section's base address is known as well!
2020-07-27 17:43:31 +02:00
Eldred Habert dda052da20 Merge pull request #545 from JL2210/consistent-versions
Use versioning consistent with the Makefile in CMake
2020-07-26 19:16:27 +02:00
James Larrowe 2d6bdbc1b1 Use versioning consistent with the Makefile in CMake
This uses git to determine the dirty version and uses a fallback
if that's not available.
2020-07-23 10:47:01 -04:00
ISSOtm 0600856167 Move incbin slice sign check
The grammar's message is pretty generic, so this one is more useful.
2020-07-23 01:06:28 +02:00
ISSOtm ce47b57b03 Document version string fallback in Makefile
For a packager just looking at the Makefile, it's not obvious that there
is one...
2020-07-22 16:21:58 +02:00
ISSOtm f3c916ab96 Allow env vars to override default CFLAGS etc.
Should make the work easier for downstream packagers
2020-07-22 16:21:21 +02:00
ISSOtm ca6fa6d1d7 Split register-indirect tokens
This allows whitespace between the brackets and the register.
This also fixes #531

Note that `$ff00 + c` is still treated as a single token, because trying to
use an expression on the left side causes a shift/reduce conflict.
This isn't great, but most people seem to be either used to it as-is, or
using the new `ldh a, [c]` syntax.
If this causes problems with a lexer rewrite, it'll be deprecated; but for
now, keep it around, as the support is clunky but bearable.
2020-07-22 15:00:39 +02:00
ISSOtm fcd37b52b6 Update pret projects to latest commits
Behind pokecrystal by 123, behind pokered by 172
2020-07-22 00:29:38 +02:00
ISSOtm 8c0adb63a1 Sync release version in CMakeLists 2020-07-21 23:54:36 +02:00
ISSOtm f5b0c701a6 Add install hint to CMakeLists 2020-07-21 23:41:56 +02:00
ISSOtm 874bd92604 Only require libpng 1.2 in CMakeLists
This version is sufficient for rgbgfx to function properly, according to testing.
The security problems are not ours to decide, however!
2020-07-21 23:23:52 +02:00
ISSOtm 69a8c62863 Add install directives to CMakeLists
Otherwise `make install` or `cmake --install` does not work
2020-07-21 23:17:33 +02:00
ISSOtm 5481af5093 Release 0.4.1 2020-07-21 23:11:06 +02:00
ISSOtm 6355d0598b Regenerate docs for 0.4.1 2020-07-21 23:10:14 +02:00
Eldred Habert 1145d10996 Merge pull request #543 from ISSOtm/ubuntu20
Add Ubuntu 20.04 to CI
2020-07-21 22:24:28 +02:00
ISSOtm 32231e3f7e Add Ubuntu 20.04 to CI 2020-07-21 22:15:56 +02:00
Eldred Habert 29314f76f7 Merge pull request #533 from JL2210/platform-fixes
Add platform-specific fixes file (only for MSVC, currently)
2020-07-21 22:11:25 +02:00
ISSOtm 8e92383fa3 Enable -Wobsolete by default
The fact that deprecations were common and quickly acted upon was raised by
some users
2020-07-21 21:06:48 +02:00
James Larrowe e51701acaa Add platform-specific fixes file
Create a new file, platform.h, for platform-specific hacks

for MSVC, this includes defining strncasecmp to _stricmp and
strdup to _strdup, among other things like defining missing
stat macros

Change some things not supported in MSVC, like _Static_assert,
to their counterparts (in this case, static_assert)

Replace usage of VLAs with malloc and free

Update getopt_long and use the getopt implementation from musl
on Windows.

Use comments to show which functions from platform.h are being used
2020-07-21 14:24:22 -04:00
ISSOtm 0793e9effe Fix develop compilation error
This bug slipped by because my pre-commit hook for testing was broken...
2020-07-21 20:10:28 +02:00
ISSOtm c25b0be085 Document that -t and -w convert section types
This is also a fairly overdue doc update
2020-07-21 20:05:26 +02:00
ISSOtm 1f2f797cb9 Add section fragments
Fixes #517, and hopefully enables RGBDS as a SDCC back-end
2020-07-21 19:56:46 +02:00
ISSOtm aca00e4fce Document MP etc. in rgbasm(1)
This is actually kind of overdue...
2020-07-21 15:55:56 +02:00
Eldred Habert cf80293d9b Merge pull request #540 from daid/patch-1
Make the local variables of getopt static.
2020-07-21 13:11:30 +02:00
daid 6d53753c66 Make the local variables of getopt static.
While compiling for empscripten there is a duplicate symbol conflict with these two variables. And as they are only used locally, and do not need a symbol exported they can just be static.
2020-07-21 10:21:33 +02:00
Eldred Habert 79f293c3d7 Merge pull request #529 from JL2210/cmake
Add CMake build system
2020-07-20 16:02:47 +02:00
Eldred Habert 8c765883fb Merge pull request #536 from braydenm303/patch-1
Fix error in documentation about unary not
2020-07-20 15:11:29 +02:00
Brayden Morris 83aa456d05 Fix error in documentation about unary not 2020-07-13 09:32:43 -06:00
James R Larrowe 819c36943e Add CMake build system
This should hopefully work torwards compatibility with more systems.
I've tried to make this as general as possible but some small assumptions
about the compiler are made. I've also tried to recreate the build process
as closely as possible, but I had to change some things slightly to work
with CMake (version strings, mainly).

For now, it doesn't allow in-source builds, as that could overwrite the
Makefile.

This adds:

- Support for more build systems
- Automatic dependency generation
- Performance gains (especially when using i.e. Ninja)

Defaults to Release build.
2020-07-03 15:10:18 -04:00
Eldred Habert 8b60efa149 Merge pull request #530 from JL2210/fix-clang
Fix Clang warning in linkdefs
2020-06-27 22:07:19 +02:00
James Larrowe 240fca0861 Fix Clang warning in linkdefs
This one's really stupid; printing an int with %hhu gives a warning
even though a regular unsigned char is promoted to an int before
printing anyway. Silence it so the build with Clang works.

This is a regression introduced in 5c24de3
2020-06-23 23:29:49 -04:00
Eldred Habert f996186fae Merge pull request #526 from JL2210/fix-bank-index
Fix indexing of banks array, fixes #525
2020-06-21 12:44:17 +02:00
James Larrowe 69a41d8ef9 Fix indexing of banks array
When ROMX bank 1 is given, the banks array is indexed with an index
of 1 rather than an index of zero.
2020-06-17 13:33:48 -04:00
Eldred Habert b958820bce Merge pull request #523 from RandomBananazz/patch-1
Fixed error in POP AF instruction reference
2020-05-27 12:45:44 +02:00
Jason Yuan 7624bd524c Fixed error in POP AF instruction reference
The "imaginary" equivalent instructions put the instructions in the wrong order (inc sp first).
2020-05-26 23:29:06 -04:00
Eldred Habert 663f0ca3b0 Merge pull request #522 from JL2210/djgpp
Fix DJGPP build
2020-05-21 22:37:24 +02:00
James Larrowe f88d9e728d Fix DJGPP build
GCC with the -std=c11 defines __STRICT_ANSI__. DJGPP checks if
__STRICT_ANSI__ is defined and if so doesn't define some things
mandated by POSIX such as struct stat, PATH_MAX, and others.
The -std=gnu11 option does not define this macro, so use it instead.

_DEFAULT_SOURCE isn't needed as no GNU nor BSD-specific functions
are used. Remove it.

Fix the last two occurrences of incorrect format specifiers for standard
fixed-width integer types.
2020-05-19 19:21:16 -04:00
ISSOtm 71fa62c9d1 Fix incorrectly spaced unary ! in RPN documentation 2020-05-13 01:20:34 +02:00
ISSOtm 5c6069dbe9 Add NULL and overflow checks to macro args 2020-05-13 01:17:58 +02:00
ISSOtm d517d2d6b4 Change macro arg allocation to geometric growth array 2020-05-13 00:22:56 +02:00
ISSOtm 80218fa109 Fix array overflow on invalid macro arg evaluation
`macro_GetArg` had not been changed after the previous commit; however,
the old code relied on the `macroArgs->args` array being at least
`MAXMACROARGS` entries large (which was the case until the last commit).
The boundary against which it checked would have better been written as
`sizeof(macroArgs->args)/sizeof(macroArgs->args[0])`, I guess, but what's
done is done.
2020-05-12 16:44:23 +02:00
Eldred Habert fee8a58b77 Merge pull request #521 from aaaaaa123456789/master
Support over 256 macro arguments
2020-05-12 15:46:42 +02:00
aaaaaa123456789 fd52a6f046 Add a test for >256 macro arguments 2020-05-12 07:22:42 -03:00
aaaaaa123456789 89fb372326 Set max macro arguments to 99,999 2020-05-12 06:46:17 -03:00
aaaaaa123456789 a828f82414 Remove fixed-size array for macro arguments 2020-05-12 06:46:07 -03:00
Eldred Habert 4d0d6664d7 Merge pull request #520 from JL2210/inttypes-stdint
Use inttypes for stdint types
2020-05-07 17:31:06 +02:00
James Larrowe 5c24de3dc4 Use inttypes for stdint types
This should help make RGBDS portable to systems with 16-bit integers,
like DOS.

For kicks, use the macros for 16-bit and 8-bit integers.

Fix other miscellaneous things, like #include ordering and other
printf-format related things.

Reduce repitition in math.c while I'm there.
2020-05-07 11:10:20 -04:00
ISSOtm 363458c3bc Fix semi-unused variable in lexer.c 2020-05-06 19:55:37 +02:00
ISSOtm b299f6fb3b Fix uninitialized memory use with -MT and -MQ
This didn't break unless the first uninitialized byte was non-zero,
which happened to be the case on someone's Windows machine.

Would it be worth it setting up Valgrind in CI?
2020-05-06 19:19:10 +02:00
Eldred Habert 645473e336 Merge pull request #518 from JL2210/warn-parameterless-dx
Add empty data directive warning
2020-05-06 16:25:03 +02:00
James Larrowe bdf397bba7 Add empty data directive warning
Fixes #516
2020-05-06 09:50:28 -04:00
ISSOtm 781a65ee49 Fix hashmap collisions sometimes hanging deletion 2020-05-03 19:13:12 +02:00
ISSOtm c135e2c6a0 Fix local sym names not being expanded by PURGE
And an additional bug that broke the attached test
2020-05-03 19:06:48 +02:00
ISSOtm 12693081c9 Use colons for hour symbols 2020-04-28 13:05:06 +02:00
Eldred Habert 7c22954fd5 Merge pull request #513 from JL2210/disable-padding-option
Add option to disable padding in rgblink
2020-04-27 11:05:55 +02:00
ISSOtm 8958e352df Update documentation for new -x option 2020-04-27 11:04:29 +02:00
ISSOtm 573003113b Fix 0-byte sections incorrectly printed in map files
Fixes #515
2020-04-17 11:38:28 +02:00
JL2210 8b1351fc3e Add option to disable padding in rgblink
Fixes #307

RGBFIX can handle padding, so there's no reason why
we can't add an option to disable padding in rgblink.

Signed-off-by: JL2210 <[email protected]>
2020-04-15 09:34:51 -04:00
Eldred Habert 106ef895ee Merge pull request #514 from JL2210/fix-gfx-gb-leak
Add error checking and fix memory leak in gfx/gb.c
2020-04-14 21:31:12 +02:00
JL2210 7f9bd12f76 Add error checking and fix memory leak in gfx/gb.c
It's possible that tile could be leaked, so free it.

Fix sizeof convention and check the result of malloc.

Signed-off-by: JL2210 <[email protected]>
2020-04-13 22:02:24 -04:00
ISSOtm 5fe3a0adb6 Remove non-OPT options from Options struct 2020-04-13 17:15:00 +02:00
Eldred Habert cdb4c5f553 Merge pull request #509 from JL2210/zero-alloc-use-fix-3
Fix use of zero-allocated memory
2020-04-13 02:50:58 +02:00
ISSOtm 57639f3765 Change comment style and use errx instead of err 2020-04-13 02:50:11 +02:00
Eldred Habert 9bec983923 Merge pull request #511 from JL2210/memory-errors
Fix memory errors in makepng
2020-04-13 02:39:17 +02:00
ISSOtm 2220f19fa7 Fix use-after-free with include in linker scripts
Fixes #510, and further proves that you *really* should not entrust memory
ownership management to humans :P
2020-04-13 02:36:19 +02:00
JL2210 2a734ecba2 Fix memory errors
This includes not checking the result of malloc and
using the wrong type in sizeof. Only the latter was
caught by scan-build.

Also use more idiomatic sizeof().

Signed-off-by: JL2210 <[email protected]>
2020-04-12 19:45:37 -04:00
JL2210 d21015e34a Fix use of zero-allocated memory
It's possible that the unsigned integer may overflow to zero,
and then we might use zero-allocated memory.

This is incredibly unlikely, and I would even go so far as to say
that this is a false positive. Fix it anyway, to silence this warning:

src/link/patch.c:92:24: warning: Use of zero-allocated memory
        stack.buf[stack.size] = value;
        ~~~~~~~~~~~~~~~~~~~~~ ^

Deal with overflow, and check for zero to get rid of the warning.

Signed-off-by: JL2210 <[email protected]>
2020-04-12 19:36:47 -04:00
ISSOtm 023a3c037f Properly handle missing symbols
Fixes #512
2020-04-12 22:52:32 +02:00
ISSOtm 828edb7403 Remove spurious error from div by zero test 2020-04-12 01:05:06 +02:00
ISSOtm a034ce0478 Deprecate '*' for comments 2020-04-09 17:57:15 +02:00
Eldred Habert d6cd5823e3 Merge pull request #508 from JL2210/mod-by-zero-fix-2
Fix modulo by zero
2020-04-09 14:52:12 +02:00
JL2210 5dd941b311 Fix modulo by zero
Yet another case caught by scan-build:

src/link/patch.c:188:21: warning: Division by zero
                        value = popRPN() % value;
                                ~~~~~~~~~^~~~~~~

Just copy over the code from the division case, with a few modifications.

Signed-off-by: JL2210 <[email protected]>
2020-04-09 08:50:23 -04:00
ISSOtm f9f27d6f5a Clean up symbol system
Get rid of Hungarian notation
Improve encapsulation (the rest of the world should not touch PC directly)
2020-04-09 10:42:37 +02:00
Eldred Habert 5ea8490e2b Merge pull request #507 from JL2210/null-pointer-fix-1
Fix possible null pointer dereference
2020-04-08 23:35:21 +02:00
JL2210 5863cd10b8 Fix possible null pointer dereference
It's possible that if the FILE passed to yy_create_buffer is at the
end-of file, there may be a null pointer dereference.

This should hopefully fix that.

Found with clang-tools' scan-build:

src/asm/lexer.c:281:25: warning: Array access (via field 'pBuffer')
 results in a null pointer dereference
        pBuffer->pBuffer[size] = 0;
                 ~~~~~~~       ^
1 warning generated.

Signed-off-by: JL2210 <[email protected]>
2020-04-08 17:30:43 -04:00
ISSOtm 40f8e33e6c Fix periods not being accepted as second char of label names 2020-04-08 15:14:07 +02:00
ISSOtm 0157ba63d3 Document whitespace before local labels 2020-04-08 15:08:29 +02:00
ISSOtm 9e3d8b22cb Document new intra-section align
Also sneak in two code style fixes forgotten in last commit
2020-04-08 15:01:36 +02:00
ISSOtm 665412c073 Implement mid-section alignment directive
Fixes #254.
2020-04-08 12:29:00 +02:00
ISSOtm 2b0c34ecb5 Fix a few code style errors 2020-04-08 00:44:41 +02:00
ISSOtm b0ec8468e6 Allow specifying offset in addition to alignment 2020-04-08 00:40:41 +02:00
ISSOtm e82ad21704 Use a single byte for alignment 2020-04-07 21:19:09 +02:00
ISSOtm e098bf47ba Allow references to be overridden by constant symbols
RGBLINK is capable of handling it now.
Though it'd be ideal for RGBASM to directly catch it.

Fixes #496.
2020-04-07 20:57:20 +02:00
ISSOtm 190678107b Prevent RGBLINK from crashing when getting the bank of a constant 2020-04-07 20:41:29 +02:00
ISSOtm 9f82fa4cf7 Fix BANK(@) outside sections causing crashes 2020-04-07 15:51:17 +02:00
Eldred Habert 562835308b Merge pull request #504 from runlevel5/gcc10-fix
Fix multiple definitions for GCC10
2020-04-07 15:18:23 +02:00
ISSOtm 927c65e863 Fix incorrect PC in LOAD blocks at link time 2020-04-07 14:44:51 +02:00
ISSOtm 5b6c1569a4 Make failure to open file a fatal error 2020-04-07 11:36:44 +02:00
Trung Lê 65121e6d5d Fix multiple definitions for GCC10 2020-04-07 14:48:30 +10:00
ISSOtm 82e0e4ffaf Make some RGBLINK errors non-fatal 2020-04-06 00:48:10 +02:00
ISSOtm ffb199a26a Avoid Useless Use of backticks in rgblink testing 2020-04-06 00:44:59 +02:00
ISSOtm 175933d2b1 Remove old scripts for updating references for tests
I much rather prefer correcting everything by hand, and gauging
whether the change is good on a case by case basis
2020-04-06 00:41:37 +02:00
Eldred Habert c86e6fef0a Merge pull request #502 from JL2210/more-conventional-permissions
Use more conventional permissions and man-page directory
2020-04-06 00:25:33 +02:00
JL2210 1e3ce2a36f Use more conventional permissions and man-page directory
As 444 and 555 seem to be used for no apparent reason, use the more
conventional 644 and 755.

/man is typically unused or a symlink to /share/man now, so just use
/share/man.

Signed-off-by: JL2210 <[email protected]>
2020-04-05 17:02:12 -04:00
ISSOtm 153915dc2f Improve portability of new make dist 2020-04-04 14:48:15 +02:00
ISSOtm ced38bc6ee Add new Makefile target for release tarballs 2020-04-04 14:23:28 +02:00
ISSOtm 4e96cf9875 Release 0.4.0 2020-04-03 12:11:50 +02:00
ISSOtm 80170eb6eb Regenerate man page HTML renders 2020-04-03 12:03:59 +02:00
ISSOtm bdad1499fe Merge branch 'release' 2020-04-03 11:58:53 +02:00
Eldred Habert 1f5ca39559 Merge pull request #494 from ISSOtm/docs
Overhaul man pages
2020-04-03 11:56:41 +02:00
ISSOtm 5013b64f55 Update disassemblies to latest commits 2020-04-02 21:26:38 +02:00
ISSOtm 7eb73d766e Make compilation optimized unless debugging
Note: I wanted to enable `-Og` on `develop`, but this generated warnings
(thus, errors) that aren't in `-O0`. Needs further investigation, but
annoyingly some of those are within `extern/` code, thus requiring
different flags, which AFAIK is only possible (sanely) with GNU Make.
2020-04-02 16:56:04 +02:00
ISSOtm bcfeb49d6b Allow labels to be passed to DEF 2020-04-02 16:54:41 +02:00
ISSOtm 702d9e0542 Fix wrong error function used in RGBGFX 2020-03-31 17:28:31 +02:00
ISSOtm c0aff678e9 Improve arg-shift test 2020-03-29 12:34:13 +02:00
ISSOtm a3d8836671 Prevent assertions outside sections from crashing 2020-03-29 12:18:24 +02:00
ISSOtm db1eb8fbcb Revert "Prevent RGBASM from outputting corrupted files"
This reverts commit 06fe27c516.

According to Microsoft's documentation
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/tmpfile?view=vs-2019
`tmpfile` attempts to create the temporary file at the **root** folder
This seems to assume that the user has admin rights; might be a compat
thing, idk, but it breaks on people's computers.
(CI didn't catch it, annoyingly.)

Reverting to make RGBASM usable on most Windows computers.
(Sanely-configured ones, at least.)
Another solution to #446 needs to be figured out, yay...
2020-03-27 23:36:11 +01:00
ISSOtm 95f347dc6a Evaluate assertions after placing sections 2020-03-27 20:00:29 +01:00
ISSOtm 6579120d9e Simplify symbol-writing logic 2020-03-27 12:32:14 +01:00
ISSOtm 84cd9f2db9 Fix segfaults when using PC outside a section 2020-03-27 12:30:09 +01:00
ISSOtm 06fe27c516 Prevent RGBASM from outputting corrupted files
Properly fixes #451
2020-03-27 11:19:02 +01:00
ISSOtm 5039af6af1 Document new "unionized section" feature 2020-03-26 23:50:30 +01:00
ISSOtm 4df74d44ec Improve opcode reference 2020-03-26 23:11:01 +01:00
ISSOtm 9113647d41 Fix incorrect macro used for x-ref 2020-03-26 23:11:01 +01:00
ISSOtm 26af2bff5e Prevent text from bumping sides on mobile devices 2020-03-26 23:11:01 +01:00
ISSOtm 3c304f3acf Override mandoc styling without modifying the stylesheet 2020-03-26 23:11:01 +01:00
ISSOtm e308130e23 Update style overrides for new mandoc.css 2020-03-26 23:11:01 +01:00
ISSOtm 713eef9ef2 Update mandoc style sheet 2020-03-26 23:11:01 +01:00
ISSOtm 7635a2fc74 Reword and give an example of symbol interpolation 2020-03-26 23:11:01 +01:00
ISSOtm 6889334521 Add viewport tag for mobile users 2020-03-26 23:11:01 +01:00
ISSOtm d1e82e50cb Improve style of man page HTML renders
See individual comments within `rgbds.css` for more info
Not too fond of having to modify `mandoc.css`, but I did my best to
modify as little as possible
2020-03-26 23:11:01 +01:00
ISSOtm 7955447ca4 Overhaul man pages 2020-03-26 23:11:01 +01:00
ISSOtm 51e225cd75 Add post-processor for HTML renders
Adds links to argument descriptions in synopsis
Adds links to man pages in the set (not to external ones)
Removes artifact from the way long opts are encoded
Makes description blurb inline, consistently with terminal output
2020-03-26 23:11:01 +01:00
ISSOtm 187f88aa50 Only copy necessary characters for bare labels 2020-03-26 23:10:51 +01:00
ISSOtm caddd61f17 Remove "column 1" restriction for local labels
Because a local symbol is necessarily a label, the disambiguation
is not necessary. This is a first step towards fixing #457.
2020-03-26 22:36:40 +01:00
ISSOtm 29629245a4 Use new hashmap implementation for symbols 2020-03-24 12:50:53 +01:00
ISSOtm 666b9f8f7b Add tests for purging symbols 2020-03-24 10:52:45 +01:00
ISSOtm 7deb8d3e8a Allow purging exported symbols 2020-03-24 10:52:02 +01:00
ISSOtm cb0a882a31 Order warnings alphabetically 2020-03-23 16:03:36 +01:00
ISSOtm df2c0dc2f9 Check for unsatisfiable alignment constraints
Fixes #493
2020-03-22 11:54:57 +01:00
ISSOtm 062fa5392b Still override alignment even if not satisfied 2020-03-22 11:52:31 +01:00
Eldred Habert baeec2315f Merge pull request #495 from ISSOtm/sectunion
Implement unionized sections
2020-03-22 11:21:24 +01:00
ISSOtm 92134d7684 Add testing for assertions inside unionized sections 2020-03-22 11:14:04 +01:00
ISSOtm 4877bb783c Add more tests for unionized sections + fix bugs
Implementing those tests found a few bugs... oops
2020-03-22 11:14:04 +01:00
ISSOtm 275b8e15ff Document modification to object file format 2020-03-22 11:14:04 +01:00
ISSOtm e123b6dec7 Implement unionized sections in RGBLINK 2020-03-22 11:13:39 +01:00
ISSOtm cb52ae0f26 Implement unionized sections in RGBASM
This touched a lot more code than initially expected, for two reasons.

First, this broke a big RGBASM assumption: that sections are always being
written to at their end. This plus other problems required touching
basically the entirety of `section.c`.

Second, I tried different solutions to solve the above problem, and along
the way I cleaned up many things around. (I believe that keeping this to
"cleanup" commits yields subpar results, and since it's boring they get
postponed anyways.)

RGBLINK support still needs to be added, but this will come next.
2020-03-22 11:06:17 +01:00
ISSOtm 46a402f7d7 Prevent passing assertions that RGBASM passed to RGBLINK 2020-03-22 10:46:37 +01:00
ISSOtm e233c5d256 Don't drop RGBLINK output in RGBASM tests 2020-03-22 10:43:06 +01:00
Eldred Habert fe824e0068 Merge pull request #490 from ISSOtm/const
Implement `ISCONST`, reporting compile-time constness
2020-03-21 23:20:01 +01:00
Eldred Habert 66512ed8d2 Merge pull request #488 from rednex/assert
Add assertions
2020-03-21 23:06:44 +01:00
ISSOtm fb58166e5d Add assertions
Closes #292
2020-03-21 23:00:38 +01:00
ISSOtm 0759c98d91 Increase version number to 0.3.10 2020-03-21 21:18:14 +01:00
ISSOtm 402ffbf0c5 Add test for version constants 2020-03-21 21:01:25 +01:00
ISSOtm 8191e5eb27 Define version symbols
Major blunder. That warrants a new release on its own...
2020-03-21 19:26:40 +01:00
ISSOtm 03967bd623 Prevent purging referenced symbols
This is an immediate fix for #492, although #342 is needed to implement the
desired functionality.
2020-03-21 15:42:52 +01:00
ISSOtm eb445271df Remove carryover from RGBASM in RGBLINK tests 2020-03-20 21:50:38 +01:00
ISSOtm af22cf182b Simplify out_PCRelByte by using PC 2020-03-20 20:22:19 +01:00
ISSOtm 5a0fcda4c8 Prevent POPS within LOAD blocks 2020-03-20 18:57:37 +01:00
ISSOtm 29623c4146 Test generating direct bytes in LOAD blocks 2020-03-20 18:29:15 +01:00
ISSOtm ebda8255ff Improve LOAD test to also test patches inside LOAD section 2020-03-20 18:20:20 +01:00
ISSOtm deb91f679d Reset symbol scope on every section change 2020-03-20 17:59:47 +01:00
ISSOtm fb5e768142 Prevent using LOAD blocks outide code sections 2020-03-20 16:37:10 +01:00
ISSOtm ecf44c784c Reject including directories 2020-03-20 01:24:53 +01:00
ISSOtm 5bca1172ff Fix section continuation when only one bank exists 2020-03-19 23:07:07 +01:00
ISSOtm 136446fccb Improve checking of RST and LDH values at assembly time 2020-03-15 15:23:39 +01:00
ISSOtm 49bca8d588 Fix misnamed hashmap function 2020-03-15 15:23:39 +01:00
ISSOtm 7ddbe44b21 Use hashmap system for charmap 2020-03-15 15:23:32 +01:00
ISSOtm af60e7f74a Allow charmap creation even if its base doesn't exist 2020-03-15 00:40:45 +01:00
ISSOtm 2f16e82cf7 Improve PC offset management
Basically make it always point to the instruction's first byte.
This was the behavior all whom I asked to intuitively expected.
2020-03-15 00:18:10 +01:00
ISSOtm 7b54312d97 Deprecate OPT z in favor of OPT p
Fixes #298
2020-03-14 17:09:15 +01:00
ISSOtm 5b98beec8b Use left recursion instead of right
> Any kind of sequence can be defined using either left recursion or right
> recursion, but you should always use left recursion, because it can
> parse a sequence of any number of elements with bounded stack space.
https://www.gnu.org/software/bison/manual/html_node/Recursion.html
2020-03-14 16:22:33 +01:00
ISSOtm 6662c86d5e Define 3-bit value when invalid 2020-03-14 16:17:30 +01:00
ISSOtm 2f466c2939 Revamp macro arg system
This should significantly improve performance: on pokecrystal builds, perf
reported as much CPU time spent on `yyparse` as on `sym_UseNewMacroArgs`
Measurements show ~6 seconds of improvement on that codebase.

This also fixes #321, as a bonus, due to saner management!
2020-03-14 16:13:40 +01:00
ISSOtm 61897d8b52 Fix warning.h not including a required header 2020-03-14 11:33:51 +01:00
ISSOtm a259f53b52 Rename macro functions with proper prefix 2020-03-13 23:20:27 +01:00
ISSOtm ffdb1fbfe5 Split macro arg management into its own file
It has no relation to symbols, and helps a tiny bit deflate `symbol.c`
2020-03-11 02:39:36 +01:00
ISSOtm 4b33b4b387 Remove forward decl of nonexistent function
I can only assume it was for debugging? (No, I'm not looking it
up the history)
2020-03-11 02:21:30 +01:00
ISSOtm 8fcdcb1731 Implement ISCONST, reporting compile-time constness 2020-03-11 02:15:31 +01:00
ISSOtm 55b911654c Get rid of obsoleted function 2020-03-11 01:46:26 +01:00
ISSOtm 7c8eba9fd2 Remove error message causing segfault
This was utterly stupid. The check right above ensured that `sym` was NULL,
ergo that the argument to `yyerror` *would* segfault.

The only two call sites cannot pass a non-NULL pointer anyways, which I'm
betting is why this went unnoticed.
I did what an optimizing compiler would do anyways: remove the dead code.
2020-03-11 00:39:57 +01:00
ISSOtm 23effcc3f0 Fix error messages in sym_GetConstantValue 2020-03-11 00:16:35 +01:00
ISSOtm ea0c5581a5 Prevent deletion of built-in symbols 2020-03-10 23:25:33 +01:00
ISSOtm 2ea329c920 Make symbol creation funcs return ptr to symbol 2020-03-10 16:36:02 +01:00
ISSOtm 3948795d49 Remove deprecated section types 2020-03-10 16:08:09 +01:00
ISSOtm 13e4920122 Get rid of comma token 2020-03-10 16:08:09 +01:00
ISSOtm 88b1121037 Uniformize style in asmy.y 2020-03-10 16:08:02 +01:00
ISSOtm d2a97e934b Remove obsolete instruction forms 2020-03-10 15:50:11 +01:00
ISSOtm cb3997d8c9 Fix org location being undefined when incorrect 2020-03-10 15:37:33 +01:00
ISSOtm c7320a49a9 Deprecate GLOBAL and XDEF
They're basically synonyms for `EXPORT`, and the latter isn't
even documented!
2020-03-10 13:49:55 +01:00
ISSOtm 8d9a896166 Remove deprecated IMPORT symbol
It had a warning that it had no effect for a long while now; removing it so
the name can be re-used
2020-03-10 13:43:15 +01:00
ISSOtm 81a057416f Remove typing for operators that don't need it 2020-03-08 16:26:09 +01:00
ISSOtm 361326e06c Allow inlining of two simple RPN functions 2020-03-07 18:18:57 +01:00
ISSOtm 0d31afaff8 Correct four code style issues 2020-03-07 18:09:00 +01:00
ISSOtm 48ad3973a9 Tell the user about "label"s instead of "relocatable"s
That's the common term, and even the manual uses it.
2020-03-07 18:04:13 +01:00
ISSOtm f6f25296a0 Fix passing constant label to BANK() causing an error 2020-03-07 18:02:06 +01:00
ISSOtm cb62076f8c Use $(MAKE) instead of make in develop 2020-03-06 18:15:32 +01:00
ISSOtm 8034e567f1 Un-silence make checkpatch in CI 2020-03-06 02:32:46 +01:00
ISSOtm 59546c8980 Un-trivialize expression in long RPN expr test 2020-03-05 04:33:43 +01:00
ISSOtm eee0e6adc8 Simplify long-rpn-expression.asm test 2020-02-29 16:39:13 +01:00
ISSOtm fa10ee4356 Deprecate colon-less non-local labels 2020-02-29 16:30:47 +01:00
ISSOtm 5bc8d51a9e Ignore unused arguments in a more standard way 2020-02-29 16:25:54 +01:00
Eldred Habert 361d6cf517 Merge pull request #437 from rednex/locals
Prevent local symbols that are not labels
2020-02-26 02:56:35 +01:00
ISSOtm 6800609fa7 Make RGBLINK check divisions by zero 2020-02-24 17:54:55 +01:00
ISSOtm dac13ba4bb Add string format checking to err.h functions
And fix all problems this detected... oops
2020-02-24 16:58:55 +01:00
ISSOtm 702075eba6 Add forgotten file name argument to err 2020-02-24 16:58:55 +01:00
ISSOtm 3b62bd0bce Bundle GCC runtime in Win32 bin package
After discussing with some Windows user, this actually seems to be
a common thing to do (it seemed weird to me, but I know Windows' handling
of DLLs is weird anyways), so bundle that runtime and reinstate the
full test run for Win32.
2020-02-23 23:14:26 +01:00
ISSOtm 4cc24f4369 Add ds cnt, byte syntax
As suggested by https://github.com/rednex/rgbds/issues/350#issuecomment-498030458
The order `count` then `byte` was decided after some discussion:
- First argument consistent with single-arg syntax
- Intuitive at least to some people other than myself
- Consistent with other assemblers, at least ca65
2020-02-23 22:43:50 +01:00
ISSOtm cfe21876e5 Make writing patches not affect the expression
This also removes one int member from the struct that shouldn't be there
2020-02-23 22:29:01 +01:00
ISSOtm ef2bfe4ea0 Store patch file line in the file name
It's more consistent with how it's stored for all other entries in the stack
2020-02-19 09:51:40 +01:00
ISSOtm 14731c0a1d Use the GitHub-provided base ref for checkpatch testing 2020-02-19 00:56:06 +01:00
ISSOtm 93747af215 Allow overriding the base ref for checkpatch
The default is sane, but not a catch-all.
2020-02-19 00:55:00 +01:00
ISSOtm 76efd26da0 Prevent local symbols that are not labels
Fixes errors brought up in #423
2020-02-19 00:20:58 +01:00
ISSOtm cf2001de5f Allow compiling parser in debug mode with -DYYDEBUG=1 2020-02-19 00:01:51 +01:00
ISSOtm 6d00877231 Prevent infinite loop with line continuations without newlines 2020-02-18 20:58:20 +01:00
ISSOtm 6755a0912b Improve naming of CI build artifacts 2020-02-18 20:23:37 +01:00
ISSOtm b6ac23be3d Remove Travis CI files
Obsoleted by GitHub Actions since #486
2020-02-18 20:12:18 +01:00
ISSOtm e941cafedb Make locals in main scope a non-fatal error 2020-02-18 20:07:44 +01:00
ISSOtm 03fe077b41 Make locals without parent a non-fatal error 2020-02-18 20:07:44 +01:00
Eldred Habert 12ef879860 Merge pull request #486 from ISSOtm/actions
Switch CI to GitHub Actions
2020-02-18 20:04:26 +01:00
ISSOtm 179e047474 Add Windows testing 2020-02-18 02:55:38 +01:00
ISSOtm d497190aa1 Do not zip artifacts ourselves
GitHub does it, this creates zips of zips...
2020-02-17 15:04:14 +01:00
ISSOtm e078c1e793 Use develop in CI when possible 2020-02-17 15:04:14 +01:00
ISSOtm 7471f46a07 Add checkpatch testing 2020-02-17 15:04:14 +01:00
ISSOtm 8cee3c3c3e Upload binaries after compilation 2020-02-17 15:04:14 +01:00
ISSOtm 97bcbf5d84 Add GitHub Actions for regression testing 2020-02-17 15:04:14 +01:00
ISSOtm 3fce9ed9a4 Have Wine shim explicitly require bash
I didn't know the substitution was Bash-only..!
2020-02-17 15:03:46 +01:00
ISSOtm 21ffcc74db Don't use echo -e for creating the Wine shim
Apparently that's not as portable as I expected.
2020-02-17 14:32:35 +01:00
ISSOtm 9e99db9a8e Allow \r in strings
Fixes #484
2020-02-17 13:52:38 +01:00
ISSOtm 5fd38c5f67 Do not try to link libpng statically 2020-02-14 03:07:24 +01:00
ISSOtm 03ed914714 Give reason to why writing the object file fails 2020-02-14 00:29:24 +01:00
ISSOtm 42faffe6f3 Make the Wine shims a separate target 2020-02-13 23:06:05 +01:00
ISSOtm bc80e910ed Fix two code style errors 2020-02-13 20:43:47 +01:00
ISSOtm 30a95d735a Improve testing PC 2020-02-13 20:20:35 +01:00
ISSOtm f01a227470 Fix non-const labels with callbacks having incorrect values when diffed
Basically, this broke PC, which is currently the only label-typed symbol
with a callback.
2020-02-13 20:16:59 +01:00
ISSOtm 91b65c9380 Add include guards and license header to section.h 2020-02-13 15:57:27 +01:00
ISSOtm 18c47843f1 Check if sections referenced in linker script exist 2020-02-12 15:27:07 +01:00
Eldred Habert d5fe377c11 Merge pull request #482 from ISSOtm/conflict
Fix one shift/reduce and one reduce/reduce conflict
2020-02-12 01:39:18 +01:00
ISSOtm ed4a613473 Rename productions to "reloc" when not really constant 2020-02-11 19:04:35 +01:00
ISSOtm 112098514d Fix 1 s/r and 1 r/r conflict
Implements the fix suggested [here](https://github.com/rednex/rgbds/issues/44#issuecomment-69360499), which performed better than expected!
I'm not \*too\* fond of this but this seems like the right way
2020-02-11 18:59:55 +01:00
ISSOtm 31aa1ea474 Improve arg-shift test
New test case courtesy of @aaaaaa123456789
2020-02-11 11:38:57 +01:00
ISSOtm 96b6e4a76e Add forgotten semicolon in grammar 2020-02-11 11:36:50 +01:00
ISSOtm 001b95d12a Add SHIFT with numeric argument
Fixes #442.
2020-02-11 11:25:38 +01:00
ISSOtm 3b2c862320 Make more RGBASM errors print their line number
Fixes #379.
2020-02-11 09:35:19 +01:00
ISSOtm 230f849229 Fix error output slightly broken on Windows
Apparently, `perror` on Windows forces a newline before itself, which is
not the behavior intended. Instead, print the error message inline.
2020-02-11 09:06:38 +01:00
Eldred Habert c37253fe5a Merge pull request #480 from ISSOtm/section
Improve section management
2020-02-11 08:51:00 +01:00
Eldred Habert 0ed8d3859d Merge pull request #481 from rednex/revert-451-atomic_output
Revert "Make RGBASM overwrite output files atomically"
2020-02-11 08:32:27 +01:00
ISSOtm 6963d77f8a Add documentation for LOAD blocks 2020-02-10 09:30:33 +01:00
ISSOtm 02ea52f453 Add test for LOAD 2020-02-10 03:39:09 +01:00
ISSOtm cdabc057a0 Allow unseekable files with INCBIN
Go figure the use case, but the feature is there now
2020-02-10 03:39:09 +01:00
ISSOtm eb0d75711a Implement LOAD/ENDL blocks
Basically implements and closes rednex#274.
2020-02-10 03:39:09 +01:00
ISSOtm f121119283 Use section's offset instead of general one
That's more future-proof and makes more sense
2020-02-10 03:37:44 +01:00
ISSOtm d9c1b66931 Deduplicate value output function code 2020-02-10 03:37:43 +01:00
ISSOtm 2f60e0a59e Use meaningful types for byte output functions 2020-02-10 03:36:51 +01:00
ISSOtm ffe9e92b48 Skip double-checking overflow in byte output 2020-02-10 03:36:51 +01:00
ISSOtm aa90a53f34 Move 1-byte overflow check to out_AbsByte
This check is already performed in bulk by all functions calling it except
`out_AbsByte`, adding extra overhead to those.
2020-02-10 03:36:51 +01:00
ISSOtm 598c923506 Use callback for PC's value
This causes it to auto-update whenever the current section's attributes are
updated, simplifying the code and eliminating redundancy.
This should also overall reduce overhead (one extra function call on each
PC evaluation, but less bookkeeping for each byte output)
2020-02-10 03:36:51 +01:00
ISSOtm 8c4b473d6f Add more checks to section creation in RGBASM
Fixes rednex#471, but also backports a couple more checks from RGBLINK
2020-02-10 03:35:55 +01:00
ISSOtm a4fe274c25 Unify all section declarations 2020-02-10 03:35:55 +01:00
ISSOtm 34597ce6a0 Mark some section functions as const 2020-02-10 03:34:58 +01:00
ISSOtm 4a2af807b2 Remove legacy forward declaration 2020-02-10 03:34:58 +01:00
ISSOtm d0ec35628f Split section management into its own file 2020-02-10 03:34:58 +01:00
ISSOtm bfdbd00092 Do some misc cleanup of output.c 2020-02-10 03:25:03 +01:00
ISSOtm d0278d8663 Invert logic for section max sizes
Prep for the next commit
2020-02-10 03:25:03 +01:00
Eldred Habert 632bc2aaec Merge pull request #476 from ISSOtm/expr_cleanup
Clean up expression evaluation
2020-02-10 03:10:05 +01:00
Eldred Habert 1ca59f25d0 Revert "Make RGBASM overwrite output files atomically" 2020-02-10 03:08:27 +01:00
Eldred Habert 1d0c8fa113 Merge pull request #451 from rednex/atomic_output
Make RGBASM overwrite output files atomically
2020-02-10 03:08:14 +01:00
ISSOtm 1d70c989be Test one more label diff case 2020-02-10 02:55:51 +01:00
ISSOtm 818a0d0296 Test more cases in label-diff test 2020-02-10 02:51:48 +01:00
ISSOtm ab1eb146c9 Print special message when PC is not constant 2020-02-10 02:51:48 +01:00
ISSOtm 63054ae0fd Make more functions ignore the RPN buffer when constant 2020-02-10 02:51:48 +01:00
ISSOtm 155040240d Improve error message when a symbol's value is not constant 2020-02-10 02:51:48 +01:00
ISSOtm d466cab1e8 Init RPN expressions created by binary operators 2020-02-10 02:51:48 +01:00
ISSOtm 4e8b34f42e Improve error message when a symbol is not constant 2020-02-10 02:51:48 +01:00
ISSOtm 5014f55c48 Treat PC as a symbol as well 2020-02-10 02:51:48 +01:00
ISSOtm 1d78cd0f03 Axe the constexpr expression evaluator
This avoids redundancy between them (and also having to port fixes and features)
The error messages have been preserved through a string reporting mechanism
2020-02-10 02:51:48 +01:00
ISSOtm 52d62c6b21 Handle subtractions between labels 2020-02-10 02:47:50 +01:00
ISSOtm b4a73f33ce Avoid undefined behavior when shifting in RPN math 2020-02-10 02:47:50 +01:00
ISSOtm f9c25608e9 Ignore RPN strings when their value is known 2020-02-10 02:47:50 +01:00
ISSOtm 9fb9e63554 Reserve space for RPN expressions in a single call
This should mean less overhead with some commands
2020-02-10 02:47:12 +01:00
ISSOtm 9ce8a9f5f0 Add comments to RPN expr struct 2020-02-10 02:47:12 +01:00
ISSOtm cc59730c5b Cleanup the RPN evaluator somewhat
Make the bool field an actual bool
Rename `iReloc` to a more exact `isKnown` (as was already pointed out by some
comments)
Make the value of `BANK(symbol)` consistent when the argument is invalid
2020-02-10 02:47:12 +01:00
ISSOtm 0a04904b75 Refactor RPN binary expressions into a single func
This mirrors what the constexpr evaluator is doing, and removes a lot of code shared
between all of them
2020-02-10 02:47:12 +01:00
ISSOtm 9ed6e9af65 Make = a separate token from SET
This does break backwards compat, but if anyone complains I'm gonna be mad
2020-02-10 00:49:45 +01:00
ISSOtm c424a9bf5a Only output a single error with charmaps 2020-02-09 22:15:43 +01:00
ISSOtm 9d811e1267 Warn when truncating values in charmap 2020-02-09 22:13:16 +01:00
ISSOtm af6f62701c Remove ambiguous charmap syntax
The syntax was `charmap "anything", "string"`; the second string was
already handled by `const`, but to the same effect... the ambiguous
declaration has been removed, leaving us at "only" two reduce/reduce
conflicts.
2020-02-09 22:03:11 +01:00
ISSOtm 299574221e Truncate shift.out.bin
Too large a size makes diff output (when tests fail) annoying
2020-02-09 19:51:47 +01:00
ISSOtm fe0c269382 Use ++ and -- instead of [+-]= 1
Seriously...
2020-02-09 15:21:08 +01:00
ISSOtm 579a324ce7 Fix diffing bin files in RGBASM tests 2020-02-09 13:58:47 +01:00
ISSOtm 7903c14993 Fix undefined behavior when reading constant in RGBLINK 2020-02-07 14:51:26 +01:00
ISSOtm b42a04c24e Add test for jr @
Fun fact: current build *fails* this test!
2020-02-07 13:19:50 +01:00
ISSOtm ea52e45335 Fix @
The symbol's evaluation by the assembler and linker was very inconsistent
2020-02-07 13:19:50 +01:00
ISSOtm 9687e6e1dd Allow forcing the second byte of STOP
Fixes #433
2020-02-07 10:06:02 +01:00
ISSOtm ee34200e5f Output diffs when binary tests fail 2020-02-06 15:36:15 +01:00
ISSOtm 295fc6c619 Improve coverage of db-@ test 2020-02-05 13:24:50 +01:00
ISSOtm 28473d314a Make implicit truncation a warning 2020-02-05 13:20:51 +01:00
ISSOtm 35f7340dc9 Report failing test names in RGBLINK as well 2020-02-04 01:41:35 +01:00
Eldred Habert b76567e7d1 Merge pull request #470 from ISSOtm/rst
Allow using labels as argument to `rst`
2020-02-04 01:26:06 +01:00
ISSOtm 652db60ad6 Document modifications made to object file format 2020-02-03 21:10:05 +01:00
ISSOtm a7cb0a166a Inline readRGBxObject
This was made separate with the intention of supporting multiple versions,
but after some discussion this was decided against, so better improve
readability instead.
2020-02-03 21:10:05 +01:00
ISSOtm f363541611 Introduce revision number field 2020-02-03 21:10:05 +01:00
ISSOtm fa1fba7fd9 Increase object version to RGB9 2020-02-03 21:07:46 +01:00
ISSOtm d73fa09774 Remove RGB6 parsing 2020-02-03 21:07:12 +01:00
ISSOtm b1cd730db2 Add link-time RST instruction
This allows using a label as the argument to a `rst` instruction
Fixes rednex#448
2020-02-03 21:07:12 +01:00
ISSOtm 359a048b6e Bump object version number
We're about to break the format, so let's do this
2020-02-03 21:07:12 +01:00
ISSOtm f2be601a13 Check "left" boundary as well in isLocationSuitable
"fixed" and "aligned" location checking advanced the target location to places
regardless of the associated free space, potentially breaking the assumption
that the location was always further in memory than the free space's base.

Rather than adding more code to try keeping that assumption true, harden
`isLocationSuitable` and handle that case as well.
2020-02-03 20:57:12 +01:00
ISSOtm 4d2379b3df Merge both "single-side" code paths in placeSection 2020-02-03 20:19:30 +01:00
ISSOtm fd32b2252f Define additional variable when doing make develop 2020-02-03 19:58:02 +01:00
ISSOtm d15915ef14 Simplify bankrangecheck 2020-02-03 15:36:38 +01:00
ISSOtm 877e0e0b91 Get rid of BANK_COUNT_* symbols
They weren't used save for the definitions right below, so Occam's razor applies
2020-02-03 15:19:48 +01:00
ISSOtm da1d9f68c7 Remove and reorder bank counts
Why was this an enum in the first place, anyways?
2020-02-03 15:19:48 +01:00
ISSOtm 24f41ef897 Expose link def arrays to RGBASM 2020-02-03 15:19:48 +01:00
ISSOtm 09dff85d5b Merge common.h into linkdefs.h 2020-02-03 14:50:00 +01:00
Eldred Habert 20e5685c1a Merge pull request #424 from ISSOtm/better_deps
Improve dependency generation
2020-02-03 03:50:09 +01:00
Eldred Habert ac6232bc87 Merge pull request #473 from ISSOtm/shift_ub
Remove undefined behavior from shifts
2020-02-03 03:49:38 +01:00
ISSOtm b16ec83a33 Add gbdiff.bash script
This script allows diffing two Game Boy ROMs using `xxd` and `diff` and
attempts to augment the diff using information pulled from SYM files.
It's not part of RGBDS proper, but can be useful to debug tests (when ROMs fail
to match).
2020-01-30 02:43:31 +01:00
ISSOtm ed72baca2a Make more symbol functions const
Can't hurt to specify those as they are now. Perhaps it'll enable slightly more
compiler optimizations, too?
2020-01-30 02:38:33 +01:00
ISSOtm edb562d2e5 Mark a few symbol functions as static 2020-01-30 02:19:36 +01:00
ISSOtm 6d4b128611 Avoid unnecessary copies in symbol init 2020-01-30 02:15:43 +01:00
ISSOtm e2e01e84fa Fall back from failure in time a bit better 2020-01-30 02:07:55 +01:00
ISSOtm 93ee417567 Fix timestamp symbols on Windows (partially)
Windows does not honor `%F` nor `%T` in `strftime`. These are worked around
by writing the full format they serve as a short for.
However, Windows also treats `%z` and `%Z` identically, where SUS instead
requires `%z` to output a ±XXXX offset.
Since the current information is broken (no information), this isn't *breaking*
anything, but at least provides something a human will probably understand.
`__ISO_8601_UTC__` is unaffected because it hardcodes the timezone character,
only `__ISO_8601_LOCAL__` suffers from this.
2020-01-30 01:47:50 +01:00
ISSOtm 44cdcd12c3 Use tput for formatting escape sequences 2020-01-28 21:04:41 +01:00
ISSOtm ed06981f57 Add test for db X, @
It should behave identically to both of these on separate lines
2020-01-28 21:04:41 +01:00
Eldred Habert ec6c42e9d6 Merge pull request #467 from ISSOtm/report
Report failing file names in comparisons
2020-01-28 18:59:11 +01:00
ISSOtm b11d121c48 Remove undefined behavior from shifts
`asl` and `asr` in `src/link/patch.c` courtesy of @pinobatch, and rearranged in RGBASM
evaluators.
2020-01-28 12:37:38 +01:00
ISSOtm cdf6000618 Report failing file names in comparisons
The files being diffed (especially for  variants) are temp files, so their
names are pretty nondescript. This improve error output, using ANSI escape
sequences to make those lines stand out.
2020-01-28 11:44:50 +01:00
ISSOtm 2e8094b712 Allow RGBASM to overwrite object files on Windows 2020-01-28 11:08:16 +01:00
ISSOtm a9cb4f8245 Make RGBASM overwrite output files atomically
Fixes rednex/#446.
I am not sure this is the best (in cases where the target directory
is not writable but the target file is), but maybe this can be
toggled via a flag, for example.
2020-01-28 11:08:16 +01:00
ISSOtm 1bd41bf79a Don't use diff to compare bin files in tests 2020-01-26 21:10:31 +01:00
ISSOtm 08ab34cf57 Fix a few checkpatch warnings in symbol.h 2020-01-26 18:26:57 +01:00
ISSOtm 7bb55469fe Fix partial paths being output to dep files with -i 2020-01-26 15:33:36 +01:00
ISSOtm a29dd738f2 Reimplement -M variants using long options 2020-01-26 15:33:36 +01:00
ISSOtm 4a98b41d57 Fix -MG always being enabled 2020-01-26 15:33:36 +01:00
ISSOtm 6fc5097278 Allow outputting dep files to stdout using - 2020-01-26 15:33:36 +01:00
ISSOtm 12f2f654dd Add -MG
This option allows for automatic dependency detection and generation:
as soon as a missing file is found, it is output to the dep file, and
assembly immediately aborts. (No .o file is produced, even if `-o` was
speicified.) This doesn't cause an error, either; the point is that once
the file is added to the dep file, the Makefile is re-parsed, and this
time the file will be generated, so the dep list builds up automatically.
This mimicks GCC's option and behavior.
2020-01-26 15:33:36 +01:00
ISSOtm 0649b360fb Allow specifying multiple dependency targets
This is done to match GCC's behavior.
Also, this unifies the code of -MT and -MQ.
2020-01-26 15:32:45 +01:00
ISSOtm f1f314270d Add -MQ
Just like GCC's -MQ, this is basically -MT but the file name is escaped.
2020-01-26 15:32:45 +01:00
ISSOtm 1fb9f90f0f Add -MT option
Allows overriding the output file in dependencies, which also allows
outputting those without also outputting the object file.
This, again, mimicks GCC's option.
2020-01-26 15:32:45 +01:00
ISSOtm bfa8da78a6 Add -MP option
Adds a phony target to every included file, mimicking gcc's
2020-01-26 15:32:45 +01:00
Eldred Habert fb81733b2b Merge pull request #472 from ISSOtm/romx-tiny
Allow ROMX and WRAMX sections in restricted modes
2020-01-26 14:48:32 +01:00
Eldred Habert e7eac583da Merge pull request #477 from ISSOtm/sym_overhaul
Overhaul the symbol system
2020-01-26 14:30:47 +01:00
ISSOtm cd107855e7 Test new working label subtractions 2020-01-24 03:03:18 +01:00
ISSOtm ab9307ac61 Clean up symbol management
Stop using that bitfield for everything, including what can be determined otherwise
It also makes it easier to have a sane state, since some bits were (supposedly)
mutually exclusive
2020-01-24 02:51:48 +01:00
ISSOtm e3ef194b4f Remove local label error checking
This is actually not necessary, because RGBLINK would warn about missing labels.
Besides, through semi-esoteric ways, it is possible to define more labels in this scope,
and there's no reason to prevent that.
2020-01-24 02:51:48 +01:00
ISSOtm ab4ca9ad8c Make symbol ref in patch symbols constant 2020-01-24 02:51:48 +01:00
ISSOtm 3fb5648880 Actually rely on createsymbol never returning NULL
This reduces complexity, basically
2020-01-24 02:51:48 +01:00
ISSOtm a7c0616cd8 Rename export type enum to that
This prevents a conflict in the next commit
2020-01-24 02:51:48 +01:00
ISSOtm 51d5ff0567 Test subtracting labels 2020-01-24 02:50:24 +01:00
ISSOtm 0665146dcd Report line info on empty RPN stack 2020-01-21 03:12:43 +01:00
ISSOtm 1f8422575e Test that all-instructions does not error out 2020-01-21 03:05:22 +01:00
ISSOtm 61c381a62c Systemize RGBLINK testing 2020-01-21 03:01:58 +01:00
ISSOtm 56d5f1588a Do not run .pipe tests if the normal variant fails
They'll most likely fail as well, just adding redundant error output
2020-01-21 00:27:28 +01:00
ISSOtm c05334dfc1 Upgrade testing to latest disasm commits 2020-01-20 14:51:25 +01:00
Eldred Habert 09d6c7a54f Merge pull request #475 from ISSOtm/licensing
Add license headers where missing
2020-01-19 15:45:46 +01:00
ISSOtm 4fe44447a2 Add license headers where missing 2020-01-19 11:11:36 +01:00
ISSOtm 23c600eef5 Remove unnecessary gitignore file
This became unnecessary when the linker script parser was rewritten ad-hoc
2020-01-19 11:02:47 +01:00
ISSOtm 50f091ab7c Fix RGBLINK failing to read args on certain machines
`char` has implementation-defined signedness, and if it's chosen to be unsigned,
then -1 gets converted to 255, which is then promoted back to `int` as... 255,
always failing the loop condition in src/link/main.c:118
`int8_t` has the correct signedness, but considering `musl_getopt_long_only`
returns `int`, better use that so as not to lose any bits
2020-01-18 22:12:25 +01:00
ISSOtm 7437f7eb85 Clarify redefinition error message 2020-01-17 03:53:27 +01:00
ISSOtm d6a99981d6 Fix checkcodebase warnings 2020-01-16 22:31:24 +01:00
ISSOtm 71fe652556 Allow ROMX and WRAMX sections in restricted modes
Closes #462, although with this implementation `BANK("some ROMX section")` would
return 0 instead of 1, which I think is benign anyways
2020-01-16 22:24:05 +01:00
ISSOtm 89917ef688 Put semicolons before labels in test suite 2020-01-16 22:09:31 +01:00
Eldred Habert 097e4c9799 Merge pull request #468 from ISSOtm/include_stem
Enforce trailing slash in include paths
2020-01-16 19:18:00 +01:00
ISSOtm 2c37a1e971 Fix default warning states
They were in the wrong order for some reason, this especially caused user
warnings to be off by default
2020-01-16 19:16:54 +01:00
ISSOtm 2c52364978 Add test for fixed section addresses 2020-01-16 18:12:42 +01:00
ISSOtm 10140f74dc Allow RGBLINK to report multiple sanity check errors 2020-01-16 18:10:35 +01:00
ISSOtm 558e8f46ff Sanity check fixed address of sections in RGBLINK
This could otherwise cause segfaults while reporting errors (!) during placement
2020-01-16 12:41:23 +01:00
ISSOtm 9ccb71205a Remove stale clean line
Those files don't exist in RGBLINK's source anymore
2020-01-14 11:42:07 +01:00
ISSOtm e50bcaa272 Enforce trailing slash in include paths
Fixes rednex#456
2020-01-13 22:48:59 +01:00
ISSOtm 86a28e8201 Provide string arguments to errors in constexpr_BankSection
How the f did it work before
2020-01-13 15:13:19 +01:00
ISSOtm 95cd0c6e53 Add test for BANK() in constant context 2020-01-12 13:09:27 +01:00
ISSOtm 23ab245cec Return a consistent number for const BANK() when erroring out 2020-01-12 13:07:48 +01:00
ISSOtm eb82476591 Make bank of "bank 0" sections known to RGBASM
This allows `BANK("Some ROM0 section")` to be used in a constant expression
2020-01-10 14:57:39 +01:00
ISSOtm f1f70d250a Add test for DEF(@) 2020-01-09 06:10:28 +01:00
ISSOtm 98a221d6b6 Add test for DEF(@) 2020-01-09 02:10:48 +01:00
Eldred Habert fb22d12b0f Merge pull request #463 from ISSOtm/windows_test_suite
Run tests on MinGW versions
2020-01-09 01:15:47 +01:00
ISSOtm 83249ed69f Cap the number of concurrent jobs for testing
This has a serious tendency to just blow up process load (~35 here with the shim)
2020-01-09 01:10:51 +01:00
ISSOtm 1534df0b3c Use minGW's pkg-config 2020-01-09 01:10:51 +01:00
ISSOtm ece9177f5a Produce shims to run the test suite on Windows bins via Wine 2020-01-09 01:10:51 +01:00
ISSOtm 8a90d74340 Ignore line endings in test suite
This removes many false positives with Windows
2020-01-09 01:10:51 +01:00
ISSOtm 5a06fad31e Separate stdout and stderr in tests
POSIX leaves undefined the order of output if stderr is injected into stdout,
and in practice it differs on Windows (Linux buffers both streams separately,
Windows interleaves them as they arrive without buffering).
This should help testing on other platforms
2020-01-09 01:10:51 +01:00
Eldred Habert add07259f4 Merge pull request #465 from ISSOtm/rebuild_version
Always update version
2020-01-09 01:01:11 +01:00
Eldred Habert 36ca18bc7b Merge pull request #466 from AntonioND/an/warning
Fix declaration of constexpr_BankSymbol()
2020-01-09 00:46:47 +01:00
Antonio Niño Díaz 6003be3fae Fix declaration of constexpr_BankSymbol() 2020-01-08 23:33:42 +00:00
ISSOtm 6d9399e3a0 Always update version
Implements https://github.com/rednex/rgbds/pull/378#issuecomment-569836686
2020-01-09 00:27:22 +01:00
Eldred Habert 676800476d Merge pull request #430 from ISSOtm/known_selfbank
Make `BANK(@)` and `BANK("section")` known to RGBASM
2020-01-08 18:56:28 +01:00
Eldred Habert 4dfa3157e5 Merge pull request #454 from ISSOtm/unlocked_windows
Fix mingw build
2020-01-08 13:14:13 +01:00
Eldred Habert f26cfa2d94 Merge pull request #455 from ISSOtm/man
Overhaul RGBDS man pages and help messages
2020-01-07 22:44:58 +01:00
ISSOtm d3328406a2 Improve jr out-of-reach error message 2020-01-02 14:06:40 +01:00
ISSOtm 3564b3f9ea Have jr offset wrap with 16 bits
Overflow with `int16_t` is defined to two's complement so it's OK
This could trigger when jumping from the top of ROM0 to HRAM
2020-01-02 14:03:54 +01:00
ISSOtm b81faeccfa Rename rgbfix long opt verbose to validate
The previous name was probably copy-pasted, it was completely wrong
2019-12-29 17:41:19 +01:00
ISSOtm 1c4cb2cd2d Add warning option to RGBASM man synopsis 2019-12-29 17:38:46 +01:00
ISSOtm 6959b76749 Rework help/usage messages
Trimmed down the option lists as per @bentley's request;
Reinstated the man pages' synopsis
2019-12-29 17:38:08 +01:00
ISSOtm 8a1e920e23 Fix incorrect line counting when running REPT blocks.
Fixes #461
2019-12-12 23:46:16 +01:00
ISSOtm 606519c515 Touch up ds documentation as per rednex#350 2019-12-12 23:22:51 +01:00
ISSOtm 34618e0294 Overhaul RGBDS man pages and help messages 2019-12-12 23:22:51 +01:00
ISSOtm 373762dedc Fix lack of newline when passing no files to RGBLINK 2019-12-10 18:35:40 +01:00
ISSOtm b30dfb166b Fix a line over 80 chars 2019-12-08 00:08:44 +01:00
ISSOtm 36db3257f3 Align fatalerror return code with every other one 2019-12-08 00:07:48 +01:00
ISSOtm cad23465a5 Remove flex from the list of dependencies in the README 2019-12-08 00:04:15 +01:00
ISSOtm d23401316e Improve pc-bank test 2019-12-07 23:44:00 +01:00
ISSOtm b49e025703 Allow BANK() in constexpr expressions 2019-12-07 23:43:02 +01:00
ISSOtm e4f4706508 Add tests for new "known self-bank" 2019-12-07 22:15:07 +01:00
ISSOtm 02fe73d1f3 Make BANK("Section") known at assembling time when possible
If the target section is in the current file and its bank is known,
this means this value is known prior to linking.
2019-12-07 22:15:07 +01:00
ISSOtm 74f43d4e09 Add a way to seek a SECTION by name without creating one 2019-12-07 22:15:07 +01:00
ISSOtm 54ed050ecf Make BANK(@) known at assembling time when possible
If the current section's bank is fixed, this means this value is
known prior to linking.
2019-12-07 22:12:57 +01:00
ISSOtm f262d3b34b Fix undefined behavior in readlong
See the new comment for what caused the UB, and how it was fixed
2019-12-07 21:19:13 +01:00
ISSOtm 32f7860a4e Fix possible 0-length array in RGBLINK 2019-12-07 15:23:52 +01:00
ISSOtm b62832e94d Move empty entries warning to -Wextra
Since the behavior actually kinda makes sense, it's better as extra.
2019-12-07 02:48:06 +01:00
ISSOtm e5820312d4 Document actual behavior of empty entries in db and co 2019-12-07 02:46:59 +01:00
ISSOtm f710f21ad8 Reorder warnings alphabetically 2019-12-06 12:06:21 +01:00
ISSOtm 90fefb468b Remove user warnings from -Wall
It does not make sense to include it there, as it's enabled by default.
2019-12-06 12:06:21 +01:00
ISSOtm 21f4cafef5 Make -Werror= with a meta warning an error
The previous behavior was to just enable the meta warning's warnings.
This is an error now because it doesn't make sense to do that, does it?
2019-12-06 12:06:21 +01:00
ISSOtm b1d4be66e4 Remove deprecated "section charmap" feature 2019-12-04 01:56:06 +01:00
ISSOtm ef43ae0eea Add a verbose print each time a file is included 2019-12-04 01:55:01 +01:00
ISSOtm 9976a139de Update test repos to latest commits
They work, and after an upcoming change the current ones are not
going to anymore!
2019-12-04 01:54:22 +01:00
ISSOtm 5718354500 Get rid of joinexpr()
This macro hid away the arguments to the underlying call, and served
no purpose beyond saving the programmer some typing. This is 2019,
people have IDEs (even Vim!) with autocompletion.
2019-12-04 00:21:57 +01:00
ISSOtm 2d7d9eef9f Fix some make checkcodebase errors
- Reorder checkpatch ignore flags alphabetically
- Fix checkpatch WARNINGs and CHECKs when they make sense
- Add more checkpatch ignores
2019-12-04 00:16:28 +01:00
ISSOtm a290e19f46 Make make checkcodebase ignore extern/
That folder contains external code, and modifying it to conform to our
code style would make applying upstream patches, amongst others,
problematic. Therefore, skip checking it.
Ideally, the folder should also be excluded from `make checkpatch`,
but I haven't figured out a way to do that yet.
2019-12-03 23:09:07 +01:00
ISSOtm 92a2be62fe Remove lex rules from Makefile
Since the RGBLINK rewrite, there have been no .l files in the whole codebase
(RGBASM has the C file directly, for better and for worse)
Since flex isn't used anymore, it's a good idea to remove it from the Makefile
so people don't think it's a dependency.
2019-12-03 23:02:38 +01:00
ISSOtm 5410dba4f4 Do prevent using org in linker scripts to go backwards 2019-11-27 01:37:00 +01:00
ISSOtm d93ad2e650 Rename all functions imported from musl
This is to avoid conflicting with libraries, which occurred in the mingw builds
2019-11-23 23:08:44 +01:00
ISSOtm 68410d35d3 Get rid of unlocked_stdio functions
Those did not provide a significant speedup, and are not provided by mingw
2019-11-23 23:00:44 +01:00
ISSOtm ceae4a44f3 Stop using f(un)?lockfile
Those are only useful for locking file IO across threads, but RGBLINK is
single-threaded anyways, so they don't matter. Plus, they aren't provided by
mingw, so that'll remove part of the problem
2019-11-23 22:21:11 +01:00
ISSOtm ea003487aa Use trap_ instead of abort() for consistency 2019-11-23 21:59:36 +01:00
Eldred Habert 401fd8b56b Merge pull request #452 from ISSOtm/warn
Add support for toggleable warnings
2019-11-18 20:58:21 +01:00
ISSOtm 191ee4ba1f Add support for toggleable warnings 2019-11-18 20:45:21 +01:00
ISSOtm 58556f91f7 Disable chcecking for global initialisers
This is specific to the kernel and does not apply to us
2019-11-18 12:45:38 +01:00
ISSOtm faa7893761 Fix develop error in getopt_long_only
The error was due to casting `const` away for permuting argv
elements, which is necessary for a libc for compatibility with older
systems, but not for us.

Checkpatch will complain about the style not being followed, but this is not
our code, so it can be ignored.
2019-11-09 00:48:00 +01:00
Eldred Habert 648df0dc7d Merge pull request #449 from ISSOtm/better_error_msg
Report overlapping sections whenever possible
2019-11-06 09:00:11 +01:00
ISSOtm 44173dbe8b Improve error messages slightly 2019-11-06 08:48:24 +01:00
ISSOtm 7233f568a7 Report overlapping sections whenever possible 2019-11-06 08:40:13 +01:00
Eldred Habert 197f1e9b7b Merge pull request #444 from ISSOtm/fix_develop
Fix errors in `make develop`
2019-11-06 08:34:37 +01:00
Eldred Habert 7063f66b2d Merge pull request #450 from ISSOtm/labels_in_sections
Prevent creating labels outside of sections
2019-11-06 08:33:25 +01:00
Eldred Habert 6e59bcb60e Merge pull request #447 from ISSOtm/long_opts
Add long options
2019-11-06 02:34:26 +01:00
ISSOtm 0649e6d65f Add long options 2019-11-06 00:48:41 +01:00
ISSOtm 072c965ba5 Add musl's implementation of getopt_long_only
Both `getopt_long` and `getopt_long_only` are GNU-specific, so we'll be
copying musl's implementation for portability.
This was retrieved as of commit 90251cf73dfdd44e7a3f085d236e89a7dff1b00b.

musl is licensed as MIT, which is compatible (being identical...) to RGBDS'.
The file is being copied as-is, without a copyright notice or attribution,
but this is only to have a verbatim copy in the history. Those will be added
in the next commit.
2019-11-06 00:40:55 +01:00
ISSOtm 122f5fe12e Prevent creating labels outside of sections
This doesn't make sense, and causes RGBLINK to misbehave
2019-11-04 08:35:00 +01:00
ISSOtm a40d599cd7 Fix extraneous comma in error message 2019-11-04 01:20:23 +01:00
ISSOtm babf36e96e Don't forget to initialize additional banks when using an overlay 2019-11-04 01:16:08 +01:00
ISSOtm d6a43f6a53 Fix RGBGFX man page
- Add color curve option to synopsis
- Fix ordering of `-d`'d description
2019-11-03 21:21:53 +01:00
Eldred Habert ff8e38fcc6 Merge pull request #441 from ISSOtm/linker_error_stack
Make linker output error stacks instead of their top level
2019-11-03 16:41:09 +01:00
Eldred Habert 192f2de704 Merge pull request #440 from ISSOtm/nested_brackets
Allow nested bracketed symbols
2019-11-03 16:40:34 +01:00
Eldred Habert c568b3a976 Merge pull request #439 from ISSOtm/tests_locale
Run tests under a specific locale
2019-11-03 16:30:38 +01:00
Eldred Habert 9c818ef3e1 Merge pull request #438 from ISSOtm/sub_doc_fix
Fix documentation for `sub`, `sbc` and `cp`
2019-11-03 16:18:09 +01:00
Eldred Habert 5aea30f40d Merge pull request #434 from ISSOtm/rgblink_rewrite
Rewrite RGBLINK entirely
2019-11-03 16:15:37 +01:00
ISSOtm 09c9395ff8 Fix NULL deref when fetching an unknown symbol in RPN expressions
was being overwritten with the result, so
was meaningless. Using a temporary instead is better.
2019-11-02 22:37:10 +01:00
ISSOtm 81047afb4b Rework "overflow" error message 2019-11-02 22:37:10 +01:00
ISSOtm f1441cc962 Make linker script error messages more descriptive
Provide file names when appropriate, print memory locations in hex
2019-11-02 22:37:10 +01:00
ISSOtm 50804d661a Fix linkerscript not updating section categorization 2019-11-02 22:37:10 +01:00
ISSOtm 9b895e8a0a Fix bank-fixed sections going in any bank 2019-11-02 22:37:10 +01:00
ISSOtm 4600f70fef Fix address-fixed sections potentially incorrectly assigned
This happened if all space before their fixed location was taken
2019-11-02 22:37:10 +01:00
ISSOtm 9e33cc998f Implement INCLUDE keyword in linker scripts 2019-11-02 22:37:10 +01:00
ISSOtm 5496c2e76f Make linkerscript errors report file names 2019-11-02 22:37:10 +01:00
ISSOtm bf75971a3a Only open files when necessary 2019-11-02 22:37:10 +01:00
ISSOtm 8a59994c0d Fix false positives in readstr
Reading the byte `EOF & 0xFF` would cause an incorrect termination
2019-11-02 22:37:10 +01:00
ISSOtm f2e1b7d868 Add EOF checking in string reading
Fixes rednex/#422
2019-11-02 22:37:10 +01:00
ISSOtm 8c91b31ae6 Fix typo that led to segfault 2019-11-02 22:37:10 +01:00
ISSOtm 302b210470 Fix error in object file documentation 2019-11-02 22:37:10 +01:00
ISSOtm 5bd0076233 Write some doc comments 2019-11-02 22:37:10 +01:00
ISSOtm 0e24adcafd Rewrite RGBLINK entirely
The goal was to improve readability, but along the way a few things were
gained.
- Sorted sym and map files
- Infrastructure for supporting multiple .o versions
- Valgrind-proof, as far as my testing goes anyways
- Improved verbosity messages
- Added error checking
- Performance improvements, see end of commit message

The readability improvement was spurred while trying to make sense of the
old code while trying to implement features such as sorted sym and map
files.
I also did my best to remove hardcoded logic, such that modifications
should be doable; for example, "RAM loading" sections, which are linked
against a different location than the one they're stored at.

Some work remains to be done, see the "TODO:" and "FIXME:" comments.
Further, while regression tests pass, this new linker should be tested on
different codebases (ideally while instrumented with `make develop` and
under valgrind).
The few errors spotted in the man pages (alignment) need to be corrected.
Finally, documentation comments need to be written, I have written a lot of
them but not all.

This also provides a significant performance boost (benchmarked with a
51994-symbol project):

Current master RGBLINK:
2.02user 0.03system 0:02.06elapsed 99%CPU (0avgtext+0avgdata 84336maxresident)k
0inputs+11584outputs (0major+20729minor)pagefaults 0swaps

Rewritten RGBLINK:
0.19user 0.06system 0:00.63elapsed 40%CPU (0avgtext+0avgdata 32460maxresident)k
23784inputs+11576outputs (0major+7672minor)pagefaults 0swaps
2019-11-02 22:37:10 +01:00
ISSOtm 696feae32e Have RGBDS' err and warn output an error message
The stdlib functions specify the difference between `err` and `errx`
is that the former prints a message obtained with `strerror`.
However, RGBDS' implementation breaks that contract, and `warn`'s puts the
added semicolon in the wrong place.
2019-11-02 22:37:10 +01:00
ISSOtm 323738e7b8 Increase version number to 0.3.9 2019-11-01 17:38:43 +01:00
ISSOtm a1d132cd35 Regenerate wwwman 2019-11-01 17:35:46 +01:00
ISSOtm f7c2665e14 Fix errors in make develop 2019-10-30 13:34:21 +01:00
ISSOtm ae0b95ec6d Make linker output error stacks instead of their top level 2019-10-11 17:12:18 +02:00
ISSOtm cdd8200936 Add test for nested brackets 2019-10-10 15:00:59 +02:00
ISSOtm 694075e840 Allow nested bracketed symbols
Fixes #320
2019-10-10 14:58:17 +02:00
ISSOtm d76f994318 Run tests under a specific locale
Fixes #427
2019-10-10 13:23:36 +02:00
ISSOtm 11b7052f94 Fix flag documentation for sub, sbc and cp 2019-10-10 01:01:21 +02:00
Eldred Habert e93d65d736 Merge pull request #425 from ISSOtm/eexpansion_error
Add info about string expansions in error reports
2019-10-03 10:20:49 +02:00
ISSOtm 0f4d543aeb Have make clean delete all .o files in source directory
This will work better if files are rearranged in the future.
This appears to be POSIX-compliant, so why wasn't it used earlier?
2019-09-25 03:17:36 +02:00
ISSOtm dab5f59ed9 Fix location of all relevant SECTIONs in tests
If section placement is changed such that those are no longer guaranteed to be
placed at zero, tests would break when they shouldn't.
2019-09-23 01:28:48 +02:00
Eldred Habert 22a6a82642 Merge pull request #419 from dbrotz/fix-blackslash-tab-at-eof
Handle tabs after backslash at end of file
2019-09-23 00:05:21 +02:00
Eldred Habert 7b592eff8a Merge pull request #420 from dbrotz/disallow-null-char
Reject input that contains null characters
2019-09-22 02:43:06 +02:00
Eldred Habert 4be81d9ffd Merge pull request #416 from ISSOtm/makefile
Improve Makefile
2019-09-22 01:55:51 +02:00
ISSOtm 55fbecee49 Add info about string expansions in error reports
This is especially useful when an EQUS expands to another one, to help
track them.
This is done separately from the file stack as the EQUS stack is separate
(which is itself because EQUS are managed *way* differently).
2019-09-12 10:02:24 +02:00
dbrotz f36a3d5b2a Fix macro and rept buffer overflows
Macro and rept buffers were not always being terminated with newlines
and/or were vulnerable to the final newline being escaped, allowing
buffer overflows to occur. Now, they are terminated with newlines using
the same mechanism as the file buffer.
2019-09-10 03:03:04 -07:00
dbrotz c5e8e4ff83 Reject input that contains null characters
Null characters in the middle of strings interact badly with the RGBDS
codebase, which assumes null-terminated strings. There is no reason to
support null characters in input source code, so the simplest way to deal
with null characters is to reject them early.
2019-09-09 17:27:56 -07:00
Eldred Habert ccc666c1e4 Merge pull request #417 from ISSOtm/zero_sections
Allow 0-byte SECTIONs to be fixed anywhere
2019-09-09 23:32:30 +02:00
dbrotz 89eda89838 Handle tabs after backslash at end of file
Commit 6fbb25c added support for tabs between a \ and the newline it escapes,
but yy_create_buffer() was not updated to handle tabs.
2019-09-09 12:25:26 -07:00
Eldred Habert 17b9838c8f Merge pull request #418 from dbrotz/fix-symbol-macro-arg-0
Print useful error message when '\0' is used in a symbol name
2019-09-09 19:37:44 +02:00
dbrotz 889dd83798 Print useful error message when '\0' is used in a symbol name
AppendMacroArg() was passing 0 to sym_FindMacroArg(), which caused an assertion
failure. Now, AppendMacroArg() prints an error message instead.
2019-09-09 09:46:18 -07:00
ISSOtm 38a372f25f Allow 0-byte SECTIONs to be fixed anywhere
They do not take any room, so they can only be used to define symbols at
a given location. I ran into trouble with such a SECTION failing to be
placed where specified, which doesn't make sense.
This way, it also makes sense to have such a SECTION in the middle of
another one, but that should be fine, since there's no actual overlap.
2019-09-09 00:00:36 +02:00
ISSOtm 2e6f5ac679 Fix unary NOT being broken
nVal wasn't being set, this made the operator a no-op on constant expressions
2019-09-08 21:42:17 +02:00
ISSOtm 7a45fc68d9 Fix incorrect evaluation of && and ||
f29d768 forgot to switch these two `expr->nVal` to `src1->nVal`
This won't break anything, since this wasn't published yet.
I checked, and didn't see any other missed changes.

Reported by pret, I confirmed that `1 && 1` evaluated to 0.
2019-09-08 21:12:31 +02:00
ISSOtm 1288737c0d Clean up suffix rules
Generate .c files from .l files instead of directly a .o
Improve yacc and lex header generation dependency
2019-09-07 13:19:32 +00:00
ISSOtm 5902306271 Have make clean delete all generated .o files
Especially important if the file structure changes, to avoid
leaving stale object files in non-fresh repos.
2019-09-07 12:53:30 +00:00
ISSOtm 2fe4521a96 Remove locallex.o reference
The file was deleted in 8e88659, finish eliminating it
2019-09-07 12:53:30 +00:00
ISSOtm 74673436a1 Separate LDFLAGS from CFLAGS 2019-09-07 12:53:29 +00:00
ISSOtm 481748c279 Make CI output Makefile commands
This is good for debugging Makefiles on systems I don't have (eg. macOS)
End users will not be affected by this, and CI provides a persistent log
so clobbering isn't much of an issue.
2019-09-07 12:53:29 +00:00
ISSOtm 9faa5c7a9e Update docs on char escapes in macro args
Fixes #415
2019-09-05 15:40:54 +02:00
ISSOtm 6fbb25c0da Clean up lexer.c
Remove some hardcoded character values
Allow tabs to be used for line continuations
2019-09-05 15:22:24 +02:00
ISSOtm 65fc42cce5 Remove -Wchkp from develop target
This option has been removed in GCC 9, and according to GCC 8.2's man page,
only has an implementation on Intel MRX anyways.
2019-09-05 05:56:11 +02:00
Eldred Habert 736b7727b6 Merge pull request #400 from NieDzejkob/out.pipe-substitute
test/asm: Generate .out.pipe files on the fly
2019-09-04 18:43:00 +02:00
Jakub Kądziołka fa920f8449 Remove the no-longer-needed .out.pipe files 2019-09-03 23:25:27 +02:00
Jakub Kądziołka 01aa56606f test/asm: special-case include-recursion 2019-09-03 23:25:15 +02:00
Jakub Kądziołka bddd5bc678 test/asm: Generate .out.pipe files on the fly 2019-09-03 22:46:05 +02:00
Eldred Habert f6b7e39ce7 Merge pull request #405 from ISSOtm/output_errors
Make RGBDS behave identically whether writing a .o
2019-09-03 10:05:19 +02:00
clach04 1363dd8f34 Add url link to releases page to readme (#413) 2019-09-03 01:51:38 +02:00
Eldred Habert 8214f0c09d Merge pull request #412 from clach04/patch-1
Clarify install instructions on Windows
2019-09-03 00:50:43 +02:00
clach04 ff7c46f5a6 Readme windows install instructions, alternative install location 2019-09-02 10:19:22 -07:00
ISSOtm b44f5825a5 Make RGBDS behave identically whether writing a .o
Some errors are only tripped in `out_WriteObject`, which was
basically a stub when `-o` wasn't specified. Now, instead,
errors are checked in a separate function before out_WriteFile
2019-09-02 15:04:46 +02:00
Eldred Habert 631910bd67 Merge pull request #395 from ISSOtm/better_error_stack
Improve error stack
2019-09-02 14:33:06 +02:00
ISSOtm 37089ef940 Improve error stack
The old error stack was fairly obtuse and hard to use for debugging.
This improves it notably by ensuring all line numbers are relative
to the file, and not, say, the macro definition.
This is a breaking change if you were parsing the old stack, but
the change should be painless, and the new stack only brings more info.
The syntax is unchanged for files, macros see their name prefixed
with the file they're defined in and a pair of colors, REPT blocks
simply append a '::REPT~n' to the context they're in, where 'n' is
the number of iterations the REPT has done.
This is especially helpful in macro-heavy code such as rgbds-structs.
2019-09-02 14:18:29 +02:00
Eldred Habert 4ef27a0d23 Merge pull request #411 from ISSOtm/recursion_limit
Add a recursion limit
2019-09-02 02:21:16 +02:00
ISSOtm 476ccc9f6b Fix undefined behavior in yyunputstr
Refer to comment at lexer.c:100 for more info
2019-09-02 02:09:59 +02:00
Eldred Habert 89dc14fcaf Merge pull request #408 from ISSOtm/plumbing
Fix memory leaks with macro args
2019-09-01 22:16:27 +02:00
clach04 1ca2f12d24 Update README.rst
Add Windows path note, in preference from adding exes to system locations
2019-09-01 09:51:47 -07:00
ISSOtm 20b2f5ee2f Fix incorrect line numbers with some IF blocks
If a line ended with a string's closing quote, or a newline escape, then
skipping over that line via IF/ELIF/ELSE would fail to count that line,
offsetting the rest of the file.
I have no idea why but for some reason 9829be1 changed *specifically*
`if_skip_to_else` to have incorrect behavior on string endings. The incorrect
behavior on newline escapes seems to have been here since the beginning.
Also added a test to check for both of those behaviors in both functions.

Honestly, it baffles me that nobody ever noticed. I didn't until I started
working on #395.
2019-09-01 03:59:29 +02:00
ISSOtm 3cc67c48cf Add recursion limit info to man and help 2019-08-31 17:34:54 +02:00
ISSOtm f9a04696f2 Add recursion overflow tests 2019-08-31 17:22:43 +02:00
ISSOtm e0e8170fe6 Add recursion limit for string expansions
Unlike macros, REPTs and INCLUDEs, this recursion depth is independent.
This is intentional, because string expansions work very differently.

While it's easy to know when a string expansion begins, checking where it
ends is much more complicated, since the expansion's contents are simply
injected back into the lex buffer. Therefore, the depth has to be checked
after lexing took place.
Because of this, the placement of the expansion end check is somewhat
haphazard, but I think it's good. While I have no certainty, all tests
ended with all expansions properly ended, and I couldn't find any pitfalls.

Finally, `pCurrentStringExpansion` has been made global so error printing
can use it to tell the user if an error occurred inside of an expansion.
2019-08-31 15:50:08 +02:00
Eldred Habert 9b40663d54 Merge pull request #409 from rednex/dd-head
Use POSIX-compatible dd(1) instead of head -c.
2019-08-31 12:59:18 +02:00
Anthony J. Bentley a517f900e4 Use POSIX-compatible dd(1) instead of head -c. 2019-08-30 23:11:28 -06:00
Eldred Habert 350f40300c Merge pull request #403 from dbrotz/multiple-charmaps
Add support for multiple charmaps
2019-08-31 04:44:58 +02:00
dbrotz d3db5f0d76 Add pushc and popc directives 2019-08-30 19:36:23 -07:00
ISSOtm 7e3af4b3cd Make testing external projects use local RGBDS
Currently, the installed version is used instead, which isn't
consistent with the tests, which use the local version.
2019-08-31 04:17:16 +02:00
ISSOtm dfb3072381 Fix memory leaks with macro args
REPT blocks nested in macros (and possibly other cases) leaked
memory on every call. Unlike most other memory leaks, which would
be freed at the end of program execution if they were done properly,
those piled up the more compilation went on.
I believe memory usage could have started being fairly high on
large projects following the "one master file INCLUDEs all the rest"
so this may have actually been worth it.
2019-08-31 03:52:42 +02:00
ISSOtm 02191135a0 Fix possible unterminated string
sym_SetMacroArgID used a `sprintf` that could write no \0.
In practice this was benign because %u cannot print 256 chars,
but better future-proof this.
2019-08-31 03:00:26 +02:00
ISSOtm dc2c97fe0c Comment and improve ParseSymbol and AppendMacroArg 2019-08-31 02:31:46 +02:00
ISSOtm 6068b565f5 Add recursion limit for INCLUDE and macros
(And REPT.)
Not exactly a *recursion* limit, more like a *stack depth* limit,
but calling it "recursion" conveys its purpose better.
The default of 64 is super overkill: even in a a project with
what I believe to be above-average levels of nesting, the
level only peaked at 6.
Keeping in mind the purpose of this is to catch infinite
recursion, which is still caught quickly (in usual cases, anyways),
this default seems sensible.
And it passes tests. What more do you need?
2019-08-31 02:31:42 +02:00
ISSOtm a21cef7190 Say which macro argument caused an error when one does 2019-08-30 20:57:11 +02:00
dbrotz 461ef6cea5 Don't complain about initializing statics
This error is specific to the way the Linux kernel handles statics.
It does not apply to userspace programs.
2019-08-29 22:48:16 -07:00
dbrotz e05199ca1e Add support for multiple charmaps
This adds two new directives: newcharmap and setcharmap.
newcharmap creates a new charmap and switches to it.
setcharmap switches to an existing charmap.
2019-08-29 21:54:06 -07:00
Eldred Habert 12d82eb768 Remove extra entry in error stack on macro not defined (#394)
While working on #392, I noticed that the macro-@ test (as well
as the line-continuation test, but for that one see #393)
printed an additional '@(-1)' entry which doesn't make sense.
2019-08-30 02:14:21 +02:00
Eldred Habert 05becf3f4b Merge pull request #381 from NieDzejkob/rgbgfx-curve
rgbgfx: Add an option to take the CGB's color profile into account
2019-08-29 22:19:36 +02:00
Eldred Habert 3cc7981c82 Merge pull request #402 from dbrotz/fix-386
Fix nested if statements that don't have following whitespace
2019-08-29 22:06:10 +02:00
dbrotz 8f287eeef9 Fix nested if statements that don't have following whitespace
When trying to skip over nested if statements, if there was no whitespace
after an "if", then that "if" would not be recognized. That's a problem since
"if(" and "if{" are also valid ways to start an if statement. This change
will make it so that they are recognized correctly.
2019-08-29 12:37:59 -07:00
Eldred Habert ce05cb5683 Merge pull request #401 from dbrotz/line-cont-test
Get rid of error in line continuation test
2019-08-29 21:23:00 +02:00
dbrotz 17945a7377 Get rid of error in line continuation test
The purpose of the test is to ensure that rgbasm doesn't segfault in this case.
The "Macro '@' not defined" error is unnecessary.
2019-08-29 11:49:17 -07:00
Eldred Habert 3a1b47129e Merge pull request #397 from NieDzejkob/test-local-without-parent
Add a test for a defining local label without a parent
2019-08-29 20:24:36 +02:00
Eldred Habert 6ffa751090 Merge pull request #390 from ISSOtm/print_types
Add "print types" to bracketed symbols
2019-08-29 20:12:32 +02:00
Eldred Habert c3641321d7 Merge pull request #399 from ISSOtm/allow_dots
Allow periods to continue macro args
2019-08-29 20:09:32 +02:00
Eldred Habert 446173f0cb Merge pull request #387 from ISSOtm/set_doesnt_override_equ
Prevent `SET` from overriding constant symbols
2019-08-29 20:08:08 +02:00
Eldred Habert e27f381842 Merge pull request #361 from ISSOtm/better_section_overflow
Improve section overflow error message
2019-08-29 20:04:48 +02:00
ISSOtm a3ee76dddd Allow periods to continue macro args
c75a953 broke my (previously-working) project that defined, via
macros, 'sizeof_.player'.
A test was added to confirm that those are indeed accepted
outside of macros.
2019-08-29 19:51:47 +02:00
ISSOtm 995265c549 Improve testing bracketed symbols
Also test EQU and _RS constants, as well as that EQUS errors out,
and that labels don't work.
2019-08-29 19:16:28 +02:00
Jakub Kądziołka 03629b74d9 Add a test for a defining local label without a parent 2019-08-29 19:14:02 +02:00
Eldred Habert b069278e98 Merge pull request #384 from dbrotz/fix-local-label-segfault
Check if parent exists for local label reference
2019-08-29 19:05:27 +02:00
Eldred Habert 9738c88f95 Merge pull request #383 from dbrotz/fix-380
Change the precedence of == to match the documentation
2019-08-29 17:14:05 +02:00
ISSOtm a21ea30be0 Add tests for bracketed symbols 2019-08-29 17:08:54 +02:00
ISSOtm 64752da42d Add "print types" to bracketed symbols
Should partially cover #178 and close #270.
This allows printing numbers in different bases and without the dollar prefix
This is especially useful in macros because the dollar isnt a valid character
for symbol names, requiring heavy `STRSUB` usage.
2019-08-29 14:04:58 +02:00
ISSOtm e3e18063c6 Prevent SET from overriding constant symbols
Fixes #341
2019-08-27 21:23:36 +02:00
ISSOtm e400eac42b Improve section overflow error message
When trying to fix a section becoming too large, the size it reached is necessary to know whether to optimize away a few bytes or split it entirely.
This error is also commonly encountered when INCBINing too large a slice of a file, in which case the amount of bytes by which the section is too large is again an useful information
2019-08-20 19:13:01 +02:00
dbrotz a6bf77718c Check if parent exists for local label reference
If an attempt is made to reference a local label before any non-local label
is defined, raise an error instead of segfaulting.
2019-08-20 09:57:53 -07:00
dbrotz c2787a9ea9 Change the precedence of == to match the documentation
The documentation states that == has the same precedence as the other
comparison operators.
2019-08-20 08:50:18 -07:00
Antonio Niño Díaz e33e6e2413 Merge pull request #382 from NieDzejkob/checkpatch-bool-member
checkpatch.conf: Don't complain when bools are used in struct
2019-08-20 14:17:15 +01:00
Jakub Kądziołka 3cb56c5a2e checkpatch.conf: Don't complain when bools are used in struct
In RGBDS's codebase, boolean struct members aren't a problem. See
include/asm/main.h, include/gfx/main.h for examples.
2019-08-20 14:43:31 +02:00
Jakub Kądziołka 91984cb7e7 rgbgfx: Add an option to take the CGB's color profile into account 2019-08-20 14:38:17 +02:00
Antonio Niño Díaz b8d5dd1824 Merge pull request #366 from dbrotz/fix-313
Fix signed integer overflow issues
2019-08-17 16:09:09 +01:00
Antonio Niño Díaz 88b66f2941 Merge pull request #364 from dbrotz/fix-362
Don't append invalid characters to symbol name
2019-08-17 16:08:27 +01:00
Antonio Niño Díaz 3c7e59b9e1 Merge pull request #374 from Ben10do/pushs-outside-of-section
Allow PUSHS to be used before a section
2019-08-17 16:07:28 +01:00
Ben Hetherington c4471e3300 Update CONTRIBUTORS.rst
Updated to reflect my current committer identity.
2019-08-16 13:22:19 +01:00
Ben Hetherington 16111f46ef Allow PUSHS to be used before a section
Previously, a PUSHS before a SECTION directive would cause rgbasm to crash when encountering a subsequent POPS.

This is because the subsequently-called out_setCurrentSection() expected the new section to be non-null, which wasn’t the case in this situation. This has been addressed by allowing the ‘null’ section to be set in this function, and only dereferencing it (to set nPC) if a non-null section is to be set.

In practice, this means that PUSHS/POPS can now be used to push/restore a context without a section.
2019-08-16 13:22:19 +01:00
Antonio Niño Díaz b019b03946 Merge pull request #358 from dbrotz/fix-357
Fix buffer overflow when creating patches with long RPN expressions
2019-07-12 00:49:08 +01:00
Antonio Niño Díaz 605acd24ba Merge pull request #372 from jidoc01/master
Document the feature of input from stdin (resolves #371)
2019-07-12 00:48:25 +01:00
jidoc01 c8630eee95 Document the feature of input from stdin
Since #329, rgbasm can get input from stdin. I updated the manpage
file related to it, which explain the description and usages in
rgbasm.
2019-07-08 23:28:46 +09:00
Antonio Niño Díaz 4040555532 Merge pull request #365 from dbrotz/terminate-bracketed-symbol
Terminate standalone bracketed symbol strings
2019-07-07 11:46:43 +01:00
Antonio Niño Díaz defb221c98 Merge pull request #360 from jidoc01/master
Improve charmap structure with trie.
2019-07-07 11:46:08 +01:00
jidoc01 e7dc094e56 Improve charmap structure with trie
Charmap's previous structure was using brute-force comparison for
converting the strings in source files. It always compared given
strings to all of the strings in charmap, which was very costly
in huge projects.
For its improvement, I changed its structure into trie, which is
being used in many string-processing areas. It's now much faster
than before.
2019-07-06 19:25:44 +09:00
Antonio Niño Díaz dfdb107105 Merge pull request #370 from jidoc01/fix_bug
Fix comment bug
2019-07-06 11:10:17 +01:00
Antonio Niño Díaz 9f598dfdb7 Merge pull request #359 from dbrotz/fix-lexer-out-of-bounds
Fix out of bounds array access in lexer
2019-07-06 11:09:43 +01:00
jidoc01 38110a833d Fix comment bug
There is a bug in processing the comments in source files. It's
related to #326. And this bug comes out when you comment something
with the character ';', and include the quotation mark without its
pair in it.

The lastest version of rgbds compiler has a step to parse the given
source to convert its line endings to a unified one, and it
processes quotation marks even before it processes the comments.

I edited a little bit of the source, and it works fine now.
2019-07-05 13:48:24 +09:00
dbrotz 484d15dbb2 Handle unprintable characters more gracefully
* Skip UTF-8 byte order mark at beginning of file
* Error on other unexpected unprintable characters
2019-07-04 17:14:55 -07:00
dbrotz 1decf5d0d4 Fix out of bounds array access in lexer
If the type char is signed, then in the function
yylex_GetFloatMaskAndFloatLen(), *s can have a negative value and be converted
to a negative int32_t which is then used as an array index. It should be
converted to uint8_t instead to ensure that the value is in the bounds of the
tFloatingFirstChar, tFloatingSecondChar, and tFloatingChars arrays.
2019-07-04 17:01:29 -07:00
dbrotz 74e9de1b71 Check for RPN stack overflow in linker 2019-07-04 16:49:23 -07:00
dbrotz 015d2b0830 Fix buffer overflow when creating patches with long RPN expressions
The createpatch() function was using a fixed-size buffer. I've changed it
to be dynamically allocated. I saw that the RPN format used in patches is
slightly different from the one used internally in the assembler, so I
added a new member to the Expression struct to track the patch size.

I've also limited the RPN expression length to 1MB. I realized that the
patch RPN expression could potentially be longer than the internal RPN
expression, so the internal expression would need a limit smaller than
UINT32_MAX. I thought 1MB would be a reasonable limit.
2019-07-04 16:49:09 -07:00
dbrotz c75a9539ba Don't append invalid characters to symbol name
When a macro arg appears in a symbol name, the contents are appended.
However, the contents of the macro arg were not being validated.
Any character, regardless of whether it was allowed in a symbol name,
would be appended. With this change, the contents of the macro arg
are now validated character by character. The symbol name is considered
to end at the last valid character. The remainder of the macro arg is
treated as though it followed the symbol name in the asm source code.
2019-07-04 16:34:47 -07:00
dbrotz ca6149abcf Fix signed integer overflow issues
It seemed that the consensus in our discussions of signed integer
overflow, which invokes undefined behavior in C, was that integer
arithmetic should be two's complement and there should be no warning for
overflows. I have implemented that by converting values to unsigned types
when appropriate. These changes will mostly preserve existing behavior,
except for a few cases that were being handled incorrectly before.

The case of dividing INT_MIN by -1 previously resulted in a CPU
exception and program termination. Now, that case is detected and results
in a warning and a value of INT_MIN.

Similarly, INT_MIN % -1 would have resulted in a CPU exception. Since this
is a mathematically valid operation with a result of 0, it now simply
gives that result without a warning.

I noticed that in rpn.c, there were attempts in certain operation handlers
to validate the nVal members of the source expressions even when the
expressions may have been relocatable expressions with meaningless numbers
for the nVal member. This could have caused spurious errors/warnings, so I
made those handlers confirm that isReloc is false before validating nVal.

Also, integer constants that are too large now result in a warning. The
post-conversion values have not been changed, in order to preserve
backward compatibility.
2019-07-04 16:27:31 -07:00
dbrotz b3120aea25 Terminate standalone bracketed symbol strings
Standalone bracketed symbols like the following weren't being zero-terminated.

X EQUS {Y}

This doesn't apply to bracketed symbols that aren't standalone, but are
instead found in a string. For example, the following works even without this
fix.

X EQUS "{Y}"
2019-07-04 16:01:57 -07:00
Antonio Niño Díaz 54e5bf0f0c Merge pull request #343 from phs/phs/docker
Have a docker file
2019-07-04 23:07:16 +01:00
Antonio Niño Díaz 847cae5b95 Merge pull request #329 from NieDzejkob/allow-stdin-input
Allow using - to indicate input from stdin (resolves #305)
2019-07-04 23:02:42 +01:00
Jakub Kądziołka df15c97b6e Handle zero-byte files gracefully 2019-07-03 16:38:35 +02:00
Jakub Kądziołka 0d97b58265 Avoid potentially implementation-defined behavior when using a pipe as input 2019-07-03 16:38:00 +02:00
Jakub Kądziołka f7bc61e874 Automatic tests for input from stdin 2019-07-03 16:05:54 +02:00
Jakub Kądziołka 8d5a53f529 Handle non-seekable input correctly 2019-07-03 15:38:14 +02:00
Jakub Kądziołka 20f9492899 Allow using - to indicate input from stdin 2019-07-03 15:38:14 +02:00
Antonio Niño Díaz 3cd1d46a1b Merge pull request #356 from NieDzejkob/add-narg-test
Add a test for the behavior of NARG after SHIFT
2019-06-16 22:35:37 +01:00
Jakub Kądziołka 88eceec257 Add a test for the behavior of NARG after SHIFT 2019-06-09 12:58:32 +02:00
Antonio Niño Díaz d00ec024a2 Merge pull request #351 from dbrotz/fix-strsub-strlen
Use code points instead of bytes for STRSUB/STRLEN
2019-06-07 10:31:11 +01:00
Antonio Niño Díaz 0bcd53778a Merge pull request #346 from qguv/tilemap-mirrored-duplicates
gfx: Add mirrored tile check when generating tilemap
2019-06-07 10:29:15 +01:00
Antonio Niño Díaz 7592eaf42b Merge pull request #354 from NieDzejkob/test-runner-stuff
Various test running fixes
2019-06-05 23:23:57 +01:00
Antonio Niño Díaz 12ed9e044a Merge pull request #353 from qguv/checkpatch-path-override
Clarify how to override checkpatch.pl path
2019-06-05 23:15:10 +01:00
Jakub Kądziołka 0a3af87aee Ignore the .git folder of the test repositories
Before this change, doing `git add test` would also add
pokecrystal and the other test repos, even though they
didn't show up on `git status`.
2019-06-05 20:54:21 +02:00
Jakub Kądziołka 4dee999f68 Clean the test repositories before running tests 2019-06-05 20:53:32 +02:00
Jakub Kądziołka 9a4941c794 Allow running the tests from outside of the test folder 2019-06-05 20:52:35 +02:00
Quint Guvernator 2d0fd71159 Clarify how to override checkpatch.pl path 2019-06-04 15:22:45 +02:00
Quint Guvernator 327582be31 Regenerate wwwman 2019-06-04 13:23:33 +02:00
Quint Guvernator 21aea281bd gfx: Add mirrored tile check when generating tilemap 2019-06-04 13:22:59 +02:00
dbrotz 975f85260d Use code points instead of bytes for STRSUB/STRLEN 2019-06-02 16:10:34 -07:00
dbrotz f29d768989 Set all of expr struct's fields in mergetwoexpressions() 2019-05-31 08:59:50 -07:00
Phil Smith 9bd7ecad4c Have a docker file 2019-05-31 08:26:53 -07:00
Antonio Niño Díaz cc458a9693 Fix a few checkpatch issues 2019-05-31 12:34:14 +01:00
Antonio Niño Díaz d2bd9a2368 Merge pull request #337 from dbrotz/one-pass
Use only one pass
2019-05-31 12:10:46 +01:00
dbrotz b909a5063a Include symbol name in 'symbol too long' error message 2019-05-29 10:56:59 -07:00
Marcus Huderle b2c1f6122e Properly set all 16 characters in ROM header title 2019-05-18 19:43:54 -05:00
Antonio Niño Díaz a761e98e18 Run checkpatch against origin/master
The develop branch has been deleted. Remove references to it.
2019-05-10 00:16:27 +01:00
dbrotz e12e7b2acc Don't assign PC to macro symbols
Macros have nothing to do with the current PC, so this doesn't make any sense.
The value isn't ever used either.
2019-05-09 15:01:06 -07:00
dbrotz f927c41abb Add test for referencing a symbol before setting it 2019-05-09 14:46:11 -07:00
dbrotz 249acace08 Prevent non-reloc symbol from shadowing reloc symbol 2019-05-09 12:48:10 -07:00
Antonio Niño Díaz fa37922ca7 Remove develop branch from contributing guide
This branch was meant to contain changes that were considered too risky
to be in master. However, there is not enough activity in the repository
to justify its presence. Both branches are always pointing at the same
commit.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2019-05-09 18:58:25 +01:00
dbrotz 021990b8e0 Properly check if a symbol's full name is too long 2019-05-05 20:21:55 -07:00
dbrotz 540564694c Add missing space to error message 2019-05-05 18:13:10 -07:00
dbrotz 8da4feb83c Use sym_FindSymbol() where possible 2019-05-05 18:10:05 -07:00
dbrotz 23f5e9dacc Use only one pass 2019-05-05 15:50:56 -07:00
Antonio Niño Díaz 6ff9435e0a Merge pull request #335 from dbrotz/fix-334
Dynamically allocate RPN expression buffer
2019-05-05 23:33:36 +01:00
dbrotz 40006c6152 Make yylex() return int 2019-05-02 19:53:45 -07:00
dbrotz b256e4c2e3 Dynamically allocate RPN expression buffer 2019-05-02 19:31:26 -07:00
Antonio Niño Díaz a37a09c09c Merge pull request #328 from NieDzejkob/better-linker-errors
Print location information in linker errors where viable #328
2019-03-10 23:41:14 +01:00
Antonio Niño Díaz 8ece231d8b Merge pull request #327 from NieDzejkob/symbol-length-check
Fix symbol length checking
2019-03-10 23:40:03 +01:00
Jakub Kądziołka e7de0745ad Improve documentation of the object format 2019-03-04 09:45:14 +01:00
Jakub Kądziołka 7af2d5dfe1 Print location information in linker errors where viable 2019-03-03 22:55:17 +01:00
Jakub Kądziołka 2f2f14bf80 Fix symbol length checking
When the while loop in `ParseSymbol` stops because of the symbol length,
`copied` will have the value of `MAXSYMLEN`, which is obviously not
greater than `MAXSYMLEN`. Changing the condition to `>=` fixes the
issue.

As a bonus, the correct union field will now be used. It shouldn't
matter, but it's technically UB to use a wrong one.
2019-03-02 19:11:53 +01:00
jmle c59cb6a828 Increase version number to 0.3.8 2019-02-20 00:10:02 +01:00
Simon Harms 06aaf5b571 Update README.rst
Add instructions to install on Arch Linux through AUR.
2019-02-14 18:03:28 -05:00
Antonio Niño Díaz 65d7909466 Merge pull request #319 from mid-kid/patch-317
Allow linker script to consider section attributes
2019-01-19 16:15:42 +00:00
Antonio Niño Díaz 861192c332 Merge pull request #318 from mid-kid/patch-316
Update a symbol's filename and line when defined
2019-01-19 16:14:11 +00:00
mid-kid c63af05427 Allow linker script to consider section attributes
The linker script now allows you to assign a section with the same
attributes as in the source.
To do this, I've removed a check from AssignSectionAddressAndBankByName
that would never be triggered, due to that condition being checked
before. Shouldn't this and IsSectionSameTypeBankAndAttrs be condensed
into a single function?
2019-01-18 12:37:23 +01:00
mid-kid d07ba6971b Update a symbol's filename and line when defined
Currently, all symbols are assigned a filename and line when they're
first encountered and added to the internal hash table. This is often
not expected and leads to erroneous error messages.
2019-01-12 12:57:58 +01:00
Antonio Niño Díaz 4b40d63dfd Merge pull request #311 from dbrotz/fix-222
Fix #222 and #255
2018-12-10 23:17:39 +00:00
Antonio Niño Díaz a99b7f6902 Merge pull request #314 from dbrotz/fix-314
Fix #314
2018-12-10 23:09:39 +00:00
Antonio Niño Díaz b3391f699f Merge pull request #310 from dbrotz/fix-302
Fix #302
2018-12-10 23:05:22 +00:00
dbrotz 5a3c12cc6b Add test for file ending with \ 2018-12-06 23:27:41 -08:00
dbrotz a05fd9b818 Print full file path in error messages 2018-12-06 22:59:24 -08:00
dbrotz 6c1ec59a5b Use separate function to append newlines 2018-12-05 01:32:06 -08:00
Antonio Niño Díaz e25a4b0abc Merge pull request #309 from dbrotz/master
Fix #308
2018-12-04 21:07:08 +00:00
dbrotz a060f135b8 Only add newlines to file if necessary 2018-12-02 20:43:20 -08:00
dbrotz f5d3087e9b Check if integer constants only contain radix prefix 2018-12-02 16:16:41 -08:00
dbrotz 2795404cd7 Add myself to contributors 2018-12-02 16:01:08 -08:00
Antonio Niño Díaz 16fac50db4 Fix clone of external repository
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-12-02 23:39:09 +00:00
dbrotz 3806eb3139 Fix ambiguity in const parsing 2018-12-02 13:49:12 -08:00
dbrotz bad66e54fa Fix buffer overflow when file ends with \ 2018-12-01 07:21:25 -08:00
karas 5cb6c4af4b Fix typo in documentation
Signed-off-by: GwanYeong Kim <[email protected]>
2018-08-30 18:53:44 +09:00
Antonio Niño Díaz 69f79f8598 Remove unused str2int()
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-08-18 00:19:48 +01:00
karas 573011a99e Remove dead code
Fixed: #301

Signed-off-by: GwanYeong Kim <[email protected]>
2018-08-17 18:49:19 +09:00
Antonio Niño Díaz d778b8e71c Update HTML documentation 2018-07-31 20:02:06 +01:00
Anthony J. Bentley 432a7574c9 Remove alphabetical list of keywords.
The original list only existed because the documentation was split
across multiple files. When all keywords are described in a single
document, Ctrl+F suffices to find them.
2018-07-28 02:05:52 -06:00
Anthony J. Bentley 4d2598e7bf Fix Bl -column widths: the arguments are strings as wide as the column. 2018-07-28 02:02:47 -06:00
Anthony J. Bentley 2e565bcb4e Escape some operators. 2018-07-28 01:55:38 -06:00
Anthony J. Bentley 62ecb6da0b Mark up #define with Fd. 2018-07-28 01:55:38 -06:00
Anthony J. Bentley 46fcebe2b5 Use .Fn for defining functions. 2018-07-28 01:55:35 -06:00
Anthony J. Bentley ab1901eeac Remove excess tabs in column lists. 2018-07-28 01:55:35 -06:00
Anthony J. Bentley 29d2fc6ebc Cleanup "Sections" section. 2018-07-28 01:55:28 -06:00
Anthony J. Bentley efe4599bd8 New sentence, new line. 2018-07-28 00:46:16 -06:00
Anthony J. Bentley 4fc1e41b16 @, &, $, {, and } don't need to be escaped. 2018-07-28 00:46:16 -06:00
Anthony J. Bentley e771d60ec0 Eliminate \[dq] escapes and superfluous double quotes.
" can be used directly except in macro lines. Also in some situations
wrapping with a Dq or Ql macro can be more appropriate.
2018-07-28 00:45:54 -06:00
yenatch e2de106d71 Use charmaps in const expressions. 2018-07-06 22:58:58 -04:00
Antonio Niño Díaz adea89f3eb Merge pull request #294 from yenatch/utf-8
Fix UTF-8 characters with an even number of bytes.
2018-07-02 23:10:46 +01:00
yenatch 361015497c Remove signoff step from contributing guide. 2018-07-02 16:04:53 -04:00
yenatch 5e9c433a24 checkpatch: Don't expect Signed-off-by lines in commit messages 2018-07-01 00:05:11 -04:00
yenatch 587159448a Test binary output for rgbasm tests 2018-06-30 23:46:17 -04:00
yenatch 64158cf513 Run checkpatch in a separate build. 2018-06-30 21:58:05 -04:00
yenatch a567365d7c unit test for db "é" 2018-06-30 21:57:34 -04:00
yenatch 57bf220e40 Fix formatting of utf8d table. 2018-06-30 20:07:23 -04:00
yenatch e6e3cc474d Fix UTF-8 characters with an even number of bytes. 2018-06-30 19:41:46 -04:00
Antonio Niño Díaz 33c984e456 Merge pull request #287 from Ben10do/remove-dummymem
Two variables, pSection->Data and tSymbols, were previously set to
dummymem, a global variable that was otherwise not used.

As this can potentially cause alignment warnings on Clang, this commit
replaces that mechanism with a plain old NULL pointer, which is more
generally used as a dummy pointer value.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-06-10 22:54:16 +01:00
Antonio Niño Díaz 458f79f44f Fix test projects compilation in OS X
The tool md5sum is required by some of them.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-06-06 22:18:29 +01:00
Antonio Niño Díaz 34e04b0327 Re-enable OS X builds in Travis CI
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-06-06 22:10:21 +01:00
Antonio Niño Díaz cf7bb9e99f Merge pull request #285 from Ben10do/allow-test-repos-to-be-kept
We no longer assume that the test repos don’t exist when we run
run-tests.sh. This allows developers to choose to keep them, to allow
them to run the tests more quickly.

- Add the test repos to the .gitignore.
- Check if the directory for each repo already exists, before trying to
  clone it.
- Do a git pull for each repo, to ensure that existing copies of repos
  are up-to-date.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-06-06 22:06:04 +01:00
Ben10do 1af5343e29 Use specific commits when running tests
This ensures that build breaks to any of the test projects don’t immediately cause rgbds tests to fail.

On clone, I’ve set it up to pull the commits since the day before the desired commit. Sadly, this will clone more recent commits that we’re not testing, but at least it ensures that the desired commit can be checked out. This is hopefully a good enough replacement for —depth=1.

Signed-off-by: Ben10do <[email protected]>
2018-06-06 22:00:45 +01:00
Ben10do a5e3a7cbc9 Replace pointers to ‘dummymem’ with NULL
Two variables, pSection->Data and tSymbols, were previously set to ‘dummymem’, a global variable that was otherwise not used.

As this can potentially cause alignment warnings on Clang, this commit replaces that mechanism with a plain old NULL pointer, which is more generally used as a dummy pointer value.

Signed-off-by: Ben10do <[email protected]>
2018-06-06 21:16:53 +01:00
Antonio Niño Díaz df065dbbcb Update html documentation
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-06-06 19:21:30 +01:00
Eldred Habert fac7247483 Update descriptions of how flags are pushed/popped
Signed-off-by: ISSOtm <[email protected]>
2018-06-06 09:06:07 +02:00
Ben10do 60050af186 Allow test repos to be kept locally
We no longer assume that the test repos don’t exist when we run run-tests.sh. This allows developers to choose to keep them, to allow them to run the tests more quickly.

- Add the test repos to the .gitignore.
- Check if the directory for each repo already exists, before trying to clone it.
- Do a `git pull` for each repo, to ensure that existing copies of repos are up-to-date.

Signed-off-by: Ben10do <[email protected]>
2018-06-03 18:23:19 +01:00
Ben10do 11c47570ce Fix the global checksum calculation in rgbfix
A regression was spotted in rgbfix 0.3.7, where we would accidentally include the first byte of the existing checksum when calculating a global checksum. We now correctly ignore both of the existing checksum bytes.

This was spotted when running rgbfix on the Pokémon Gold/Silver betas, as they have a non-zero global checksum.

Fixes #280.

Signed-off-by: Ben10do <[email protected]>
2018-06-03 10:11:55 +01:00
Antonio Niño Díaz f8b4cc52f6 rgbasm: Allow variations of 'ld [$FF00+c],a'
The following mnemonics are now valid:

    - ld
    - ldh
    - ldio

The following are valid as operands:

    - [$ff00+c]
    - [$ff00 + c]
    - [c]

This is done for consistency with 'ld [$FF00+n],a' and variations of it.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-05-20 21:04:47 +01:00
Antonio Niño Díaz 748943f6fc Increase version number to 0.3.7
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-05-02 20:04:00 +01:00
Antonio Niño Díaz d945c5811c rgbasm: Check the values of operands in bit shifts
The tests are not exhaustive, there are some conditions that aren't
checked. The tests are based in the C standard rules about undefined
behaviour.

This is a compatibility break but, hopefully, all projects are using
sane values. If not, there is no guarantee that the projects will build
in any platform where RGBDS can be compiled, so it would be better to
fix them.

Even though, technically, the left shift of a negative value is always
undefined, some projects rely on its current behaviour. This is the
reason why this doesn't cause a fatal error.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-28 01:59:37 +01:00
Antonio Niño Díaz 6fe2741f2d Enable GCC options to detect undefined behaviour
GCC has an Undefined Behavior Sanitizer (ubsan), which enables run-time
checks of undefined behaviour. It has been enabled for the `develop`
build target.

A small bug detected with it has been fixed.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-28 00:57:25 +01:00
Antonio Niño Díaz 24d7cfe0f9 checkpatch: Ignore warnings about SPDX
The Linux kernel expects the SPDX license tag to be in the first line of
all source code files. The reason is that they have many different
license headers, and this simplifies the work for any tool that has to
determine the license of each file.

In this project, the license headers follow the same pattern, so it
isn't useful.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-27 23:00:29 +01:00
Antonio Niño Díaz 630933b148 rgbfix: Fix checkpatch issues
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-22 21:02:08 +01:00
Antonio Niño Díaz e8a16c6f53 Don't generate output file if overlay isn't found
Previously, the output file was opened before trying to open the
overlay. Because of this, rgblink generated an empty output file if the
overlay couldn't be opened.

Now the overlay is opened (and checked) before the output file, so the
output file is only generated if the overlay is found.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-22 20:54:48 +01:00
Antonio Niño Díaz 2cb50730a1 Document Section ID == -1 in object files
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-22 20:21:45 +01:00
Antonio Niño Díaz efae6c7fd2 Merge pull request #264 from inmemrgbfix
Rewrite rgbfix to perform most actions in memory.

Limit file operations to a small number that can be reasonably checked,
and do the majority of the actual work on a buffered header in memory
where operations won't fail.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-22 20:03:32 +01:00
Anthony J. Bentley 8a559beeb8 Rewrite rgbfix to perform most actions in memory.
Limit file operations to a small number that can be reasonably checked,
and do the majority of the actual work on a buffered header in memory
where operations won't fail.
2018-04-05 00:41:09 -06:00
Antonio Niño Díaz 7149fc1e39 tests: Update references
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-03 23:04:29 +01:00
Antonio Niño Díaz 2e695334c1 rgbfix: Add check to malloc()
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-03 22:41:51 +01:00
Antonio Niño Díaz e2b4554a5c Replace tabs by spaces in fprintf()
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-03 22:41:44 +01:00
Antonio Niño Díaz ef87dd5a6e rgbasm: Fix declaration of fatalerror()
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-03 22:41:37 +01:00
Antonio Niño Díaz 4f126b37d0 Merge pull request #261 from warnings
Enable a lot of GCC warnings and cleanup Makefile and compiler macros

Most of the warnings in the GCC documentation have been enabled. As the
build system was using `-Werror`, this made the new builds very
susceptible to any minor change in the compiler. To fix that, this
option has been removed from the default Makefile target and it is only
used when the code is compiled through `make develop`.

The file `stdnoreturn.h` has been modified to remove support for
compilers that aren't actually tested. It now has defines for
`__attribute__((unused))` and it has been renamed to `helpers.h`.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-03 19:57:04 +01:00
Antonio Niño Díaz 1b4187e51f Cleanup GCC compiler attributes
Added define 'unused_' for '__attribute__((unused))'. The oldest version
of GCC with online docs (GCC 2.95.3, released in March 16, 2001 [1])
already has support for this attribute, so it doesn't make sense to
check the version.

Renamed 'noreturn' to 'noreturn_' for consistency.

[1] https://gcc.gnu.org/onlinedocs/

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-03 19:52:50 +01:00
Antonio Niño Díaz 0daec91683 Check code style as part of the CI tests
If checkpatch.pl detects any ERROR in the new patches, the Travis CI
build will fail.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-03 00:02:17 +01:00
Antonio Niño Díaz cbaaec98ca Simplify helpers.h
`__attribute__((noreturn))` has been supported since GCC 2.5, that was
released October 22, 1993. It doesn't make sense to check if the version
is at least that one, we are compiling for C99, that is more modern. [1]

Also, remove the MSVC check. This code is never compiled with it so
there may be problems that need to be solved to make it compile. All
releases cross-compiled from linux. If there is an actual need to
support MSVC, the compiler definitions can be added again.

Also, if the compiler is not supported, the compiler helpers default to
nothing, so the code can still compile.

[1] https://gcc.gnu.org/onlinedocs/

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-02 22:53:48 +01:00
Antonio Niño Díaz 895d1d5813 Remove check for C11 in helpers.h
The mandatory CFLAGS in the Makefile make the compiler use C99.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-02 22:53:48 +01:00
Antonio Niño Díaz e99a651165 Create makefile target to check all warnings
Remove '-Werror' from the default make target to make it easy for
regular users of RGBDS to compile the source code. Only a few basic
warnings are left in that target.

All the warnings have been moved to a new target called 'develop'. This
target is now the one used in Travis CI to check for problems during
compilation.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-02 22:53:48 +01:00
Antonio Niño Díaz 0ae69b3114 Rename stdnoreturn.h to helpers.h
This file will contain more compiler-specific helpers.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-02 22:53:48 +01:00
Antonio Niño Díaz 95ccc48d0c Enable -Wundef
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-02 22:53:48 +01:00
Antonio Niño Díaz 29253046d5 Remove C++ check in stdnoreturn.h
This isn't a C++ project, only keep checks for C compilers.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-02 22:53:48 +01:00
Antonio Niño Díaz 340362d984 Enable a few warning flags
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-02 22:53:48 +01:00
Antonio Niño Díaz 85ece88268 Add default clauses to switch statements
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-02 22:53:43 +01:00
Antonio Niño Díaz 516e4578ea Enable more optional warnings
-Wformat-truncation is set to 1 instead of 2 because in some cases the
return value of snprintf is used to warn about truncations but GCC still
creates a warning for it, preventing the compilation from continuing.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-01 01:42:55 +01:00
Antonio Niño Díaz 9829be1045 Enable -Wextra
-Wsign-compare has been disabled because flex generates a comparison
that triggers a warning and cannot be fixed in the code.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-01 01:42:55 +01:00
Antonio Niño Díaz b28a16c0da Enable -Wpedantic
Fix a few warnings related needed to build the source with this option.

Add new exception to .checkpatch.conf.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-04-01 00:56:00 +01:00
Antonio Niño Díaz 4d13d57491 Fix behaviour of '@'
When '@' is used as argument of any instruction (LD, JR, JP, etc), the
address it refers to is the address of the first byte of the
instruction. When '@' is used with DB/DW/DL, it refers to the same
address it is being placed at. This means that instructions need an
offset of 1 byte and others need an offset of 0 bytes.

The assembler doesn't evaluate anything related to '@' because it would
only work in sections with a fixed base address. It is left to the
linker. This means that the offset needs to be added to the RPN
expression of the patch that is saved in the linker. It isn't enough by
adding an offset to the final expresion. The following value wouldn't be
calculated correctly (even if it doesn't make sense):

    JP @ * @

The correct patch is `(@ - 1) * (@ - 1)`, not `(@ * @) - 1`.

This patch introduces an offset on 1 byte by default in every line, and
sets it to 0 only if a DB/DW/DL is detected.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-03-31 00:43:25 +01:00
Antonio Niño Díaz be6bc7460b Don't save '@' in map and sym files
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-03-31 00:43:25 +01:00
Antonio Niño Díaz efdd42c6a8 Simplify parsing of variable-length lists
This change removes 2 reduce/reduce conflicts in the parser while
preserving the behaviour of the rules.

Note that now each list with empty elements will only print a warning
per line.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-03-31 00:43:02 +01:00
Antonio Niño Díaz c1a97f6541 Allow to JR to numeric constants
Previously, JR was only allowed to labels (in the same section, or
different sections). When trying to JR to an address specified as a
numeric value, rgbasm would fail to calculate the JR offset (as it
doesn't know the final address of the JR so it can't calculate the
difference).

This patch makes rgblink calculate the offset whenever there is a JR.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-03-29 23:38:54 +01:00
Antonio Niño Díaz ea4276c7ac Increase version number to 0.3.6
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-03-20 20:11:38 +00:00
Antonio Niño Díaz 7bce97f817 Fix crash in rgbgfx with height not multiple of 8
Images are allowed to have any arbitrary height if the width is 8. If
the height is not a multiple of 8, the number of tiles calculated won't
be an exact number and it will be rounded down. This patch increases the
number of tiles allocated in this case to prevent rgbgfx from accessing
memory that hasn't been allocated.

The buffers are now initialized to 0 with calloc instead of being
created with malloc.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-03-19 21:47:19 +00:00
Antonio Niño Díaz 483a63156b Document character maps
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-03-15 21:04:43 +00:00
Anthony J. Bentley 5a4bbe4985 Add a new flag, -f, which allows independently fixing or trashing checksums. 2018-03-10 21:48:23 -07:00
Antonio Niño Díaz f86dbafad0 Fix format in manpage
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-03-07 18:23:44 +00:00
Antonio Niño Díaz 8744d360a3 Fix format of manpage
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-27 19:42:29 +00:00
Antonio Niño Díaz b6bd57a764 Merge pull request #237 from continue-lines
Allow to continue lines

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-26 21:55:19 +00:00
Antonio Niño Díaz f2b55527d5 Update html manpages
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-26 21:49:19 +00:00
Antonio Niño Díaz 84a6899c6c Document line continuation syntax
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-26 21:48:28 +00:00
Antonio Niño Díaz 8cffe22295 Fix style of code sections in manpages
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-26 21:48:26 +00:00
Antonio Niño Díaz 0c85240b97 Allow line continuations in list of macro args
For example:

    PrintMacro : MACRO
        PRINTT \1
    ENDM

        PrintMacro STRCAT(\"Hello\"\,  \
                          \" world\\n\")

It is possible to have spaces after the '\' and before the newline
character. This is needed because Windows line endings "\r\n" are
converted to " \n" before the lexer has a chance to handle them.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-26 21:47:52 +00:00
Antonio Niño Díaz 58ab88da82 Allow to scape " in lists of macro args
For example:

    PrintMacro : MACRO
        PRINTT \1
    ENDM

        PrintMacro STRCAT(\"Hello\"\,  \" world\\n\")

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-26 21:47:52 +00:00
Antonio Niño Díaz 3e219dee36 Allow to continuate lines except inside macros
Lines can be continuated after a newline character ('\n'):

    DB 1, 2, 3, 4 \
       5, 6, 7, 8

This doesn't work for now in lists of arguments of macros.

It is possible to have spaces after the '\' and before the newline
character. This is needed because Windows line endings "\r\n" are
converted to " \n" before the lexer has a chance to handle them.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-26 21:47:52 +00:00
Antonio Niño Díaz 6ad5bd2325 Add flag to rgbasm to disable LD->LDH optimization
rgbasm tries to optimize any loads from/to $FF00-$FFFF and generate
LDH 2-byte opcodes instead of regular LD 3-byte opcodes. This is a bit
inconsistent as it only works for constant values. If a load is trying
to access a label in a HRAM floating section, or a section found in a
different object file, this optimization doesn't work.

This means that a simple refactor or code could allow rgbasm to perform
the optimzation or prevent it from doing so. For certain projects, like
disassemblies, this is a problem.

This patch adds flag -L to rgbasm to disable the optimization, and
doesn't change the behaviour of any other existing code.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-26 21:44:00 +00:00
Antonio Niño Díaz 2a97535e75 Add safeguards against string overflows
Use snprintf instead of other unsafe functions. That way it is possible
to limit the size of the buffer and to ensure that it never overflows.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-25 22:58:29 +00:00
Antonio Niño Díaz 0e0e12a769 Add CSS file for the html documentation
It has been obtained from here:

http://mdocml.bsd.lv/cgi-bin/cvsweb/mandoc.css

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-24 16:40:55 +00:00
Antonio Niño Díaz 3bebedf1f8 Handle newlines and comments correctly
Newlines have to be handled before comments or comments won't be able to
handle line endings that don't include at least one LF character.

Also, document an obscure comment syntax: Anything that follows a '*'
placed at the start of a line is also a comment until the end of the
line.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-23 19:24:18 +00:00
Antonio Niño Díaz 2ed937db2c Allow JR between sections
Previously, JR was only allowed if the destination label was in the same
section as the JR. This patch removes this restriction. The check to see
if the relative value overflows is now done when linking the ROM.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-23 19:21:44 +00:00
Antonio Niño Díaz d243bd04ef Introduce command PRINTI to print integers
PRINTV prints integers in hexadecimal, PRINTI prints them in signed
decimal. For example:

    PRINTT "Error at line "
    PRINTI __LINE__
    PRINTT "\n"

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-23 19:20:52 +00:00
Antonio Niño Díaz 3623638be7 Fix HIGH() and LOW() for constants
HIGH() and LOW() only worked with labels and register pairs.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-22 21:23:25 +00:00
Antonio Niño Díaz 8ea3669a64 Merge pull request #235 from obskyr/rgbgfx-color
Add color support to rgbgfx (again)!

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-20 19:56:39 +00:00
obskyr 8fe5293077 Allow superfluous height for 1-tile-wide images
Currently used here and there for small, icon-like tiles, it seems.

Signed-off-by: obskyr <[email protected]>
2018-02-20 10:06:33 +01:00
obskyr 825fa915ee Fix rgbgfx's code style
Signed-off-by: obskyr <[email protected]>
2018-02-20 10:06:00 +01:00
obskyr 885e8ea24a Add to contributor list
Signed-off-by: obskyr <[email protected]>
2018-02-20 09:35:07 +01:00
obskyr 898f75ce57 Clarify and update rgbgfx documentation
Signed-off-by: obskyr <[email protected]>
2018-02-20 09:35:00 +01:00
obskyr b8af100c63 Handle grayscale images as expected
Signed-off-by: obskyr <[email protected]>
2018-02-20 09:34:48 +01:00
obskyr 3075945367 Add color and transparency support to rgbgfx
In addition, fix various bugs.
Among them are minor memory issues and edge cases with certain inputs.

Signed-off-by: obskyr <[email protected]>
2018-02-20 09:33:53 +01:00
Antonio Niño Díaz d602ebfde5 Fix typo in rgblink manpage
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-02-18 19:57:02 +00:00
Antonio Niño Díaz 305512a2b7 Increase version number to 0.3.5
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-28 13:08:00 +00:00
Antonio Niño Díaz a6b244b12e Move version files out of extern folder
The folder extern is reserved for external contributions, not common
files.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-28 13:07:21 +00:00
Antonio Niño Díaz ceabbeaa2f Fix linkerscript man page
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-27 17:25:21 +00:00
Antonio Niño Díaz 3995852cc5 Fix nit in rgbasm.5 man page
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-27 15:19:18 +00:00
Antonio Niño Díaz 9793bcba6f Fix local execution of run-tests.sh script
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-27 15:04:17 +00:00
Antonio Niño Díaz 0727eb4374 Add test to verify hex codes of all instructions
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-27 14:38:52 +00:00
Antonio Niño Díaz f8f67fcbce Add external projects to Travis CI jobs
Small tests like the ones included in this repository are good to test
individual features, but it is also a good idea to test some real
projects.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-27 11:14:10 +00:00
Anthony J. Bentley abeca2d305 Prefer snprintf to strncpy when outputting C strings
strncpy is designed to output to fixed‐width buffers, not C strings
(hence its weird null termination behavior). In this case it happens to
work correctly due to the length check but, for style reasons, I would
rather use snprintf. Especially in this case, where it shortens the
code a bit.
2018-01-27 01:22:58 +00:00
Antonio Niño Díaz a7dc86001c Add note about the MIT License in CONTRIBUTING.rst
Also, LICENSE.rst doesn't have any special formatting now, so it has
been renamed to LICENSE.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-27 00:47:06 +00:00
Antonio Niño Díaz c071586ae5 Remove dependency of reallocarray()
By removing this dependency, all of the code of this repository is
licensed under the MIT license.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-27 00:30:13 +00:00
Antonio Niño Díaz c6187be210 Remove dependency of strlcpy()
There was only one place where `strlcpy` was still used.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-27 00:02:44 +00:00
Antonio Niño Díaz f9f3bb7761 Remove dependency of strlcat()
There was only one place where `strlcat` was used, and `snprintf`
actually does a better job at what the code was trying to achieve.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-27 00:02:26 +00:00
Antonio Niño Díaz 1a5c423984 Relicense codebase under MIT license
With permission from the main authors [1], most of the code has been
relicensed under the MIT license.

SPDX license identifiers are used so that the license headers in source
code files aren't too large.

Add CONTRIBUTORS.rst file.

[1] https://github.com/rednex/rgbds/issues/128

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-26 22:59:02 +00:00
Antonio Niño Díaz b382dffdec Split src/asm/charmap.c into two files
This way it is easier to identify the license of the code.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-26 22:55:13 +00:00
Antonio Niño Díaz 33e9eb098c Exclude html files from checkpatch
Also, fix 2 nits in the codebase.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-26 18:57:25 +00:00
Antonio Niño Díaz e77ebfe38a Disable OSX builds in Travis CI
Travis seems to be having some problems with OSX builds, so it's better
to disable them temporarily.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-25 22:23:43 +00:00
Antonio Niño Díaz 698ed9d5fc Don't clean html files with make clean
Added a new target to remove html files: `cleanwwwman`.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-25 22:12:31 +00:00
Antonio Niño Díaz b07a8501d6 Fix linkerscript linking errors
The problems were introduced by the following commits:

- 959bfe2a9d

- 975200834e

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-25 22:07:16 +00:00
Antonio Niño Díaz f779e724e2 Fix typo in manpage
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-24 20:29:27 +00:00
Antonio Niño Díaz 494b98e46a Fix html doc file name
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-24 20:29:09 +00:00
Antonio Niño Díaz d1ff057889 Make clean target of Makefile clean html files
The html files generated with `make wwwman` weren't cleaned correctly
with `clean`.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-23 22:54:37 +00:00
Antonio Niño Díaz 292302c6d1 Move documentation to this repository
Modified Makefile wwwman target to output files inside docs/.

Modified .gitignore to allow *.html files.

Update README.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-23 21:28:10 +00:00
Antonio Niño Díaz b55fead749 Fix typo in documentation
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-23 20:37:00 +00:00
Antonio Niño Díaz 844e027a18 Increase version number to 0.3.4
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-23 20:30:47 +00:00
Antonio Niño Díaz 0fb80cd7a9 Fix indentation in asmy.y
Remove extra spaces.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-21 22:51:42 +00:00
Antonio Niño Díaz 311b412f5d Improve error messages
NULL error messages have been given a description.

Messages that weren't descriptive enough now also print the name of the
function that has failed.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-16 22:39:44 +00:00
Antonio Niño Díaz 975200834e Fix WRAMX BANK offset in the right place
ROMX and WRAMX bank numers are stored in an object file as their number
minus one. This means that this offset has to be applied somewhere.

The old code applied the fix for ROMX and WRAMX in two different places.
It looks like the patch that added support for WRAMX didn't set the
offset correctly in 'src/link/assign.c'. When this was fixed, it was
done in the wrong place, in 'src/asm/asm.y'. This patch moves the fix to
'src/link/assign.c'.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-16 22:39:44 +00:00
Antonio Niño Díaz c8fa799883 Output error msg when object file can't be opened
In rgbasm, output a fatal error if the destination object file can't be
opened.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-16 22:39:44 +00:00
Antonio Niño Díaz 7f37eef218 Cleanup BANK related definitions
Simplify comparisons and remove magic numbers.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-16 00:46:29 +00:00
Antonio Niño Díaz 8521e45edc Reduce SRAM bank number to 16 in rgbasm
The limit was already 16 banks in the linker, which made the previous
limit of 511 useless.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-14 16:12:29 +00:00
Antonio Niño Díaz 7bd082563d Add CONTRIBUTING.rst file
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-14 14:07:22 +00:00
Antonio Niño Díaz de32e245c9 PUSHS and POPS also affect the symbol scope
Now, when POPS is executed, it restores the symbol scope of the
corresponding PUSHS. That way, the local symbols previously available
can be used again after the POPS.

This is useful in cases like this one:

```
    SECTION "Section 1", ROMX

BigFunction:

    ...

.loop:

    ...

    PUSHS

    SECTION "Section 2", ROMX

DataForBigFunction:
    DB 1, 2, 3, 4, 5

    POPS

    ld  a,BANK(DataForBigFunction)
    ld  hl,DataForBigFunction

    ...

    jr  .loop
```

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-07 23:05:04 +00:00
Antonio Niño Díaz f5164325d2 Convert Markdown files to reStructuredText
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-07 19:22:38 +00:00
Antonio Niño Díaz 959bfe2a9d Allow to request BANK() of sections and PC
The bank of a section can be requested with `BANK("Section Name")`, and
the bank of the current section with `BANK(@)`. In both cases, the bank
number is resolved by the linker.

New commands have been added to the list of RPN commands of object
files, and the rest has been moved so that new additions don't force a
new change in the number of the enumerations.

Increase object file version, as it is now incompatible with the old
format.

Update manpages to reflect the new ways of using `BANK()` and the new
format of the object files.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-07 02:05:05 +00:00
Antonio Niño Díaz d24cf11ad4 Make list of linker symbols common
That way the definitions of the assembler and the linker are always the
same.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-05 00:32:50 +00:00
Antonio Niño Díaz 8d89ba39d4 Decouple commands in checkpatch Makefile target
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-04 21:54:10 +00:00
Antonio Niño Díaz b04596a32b Move externs to header files
Follow Linux kernel coding style.

Remove exception from checkpatch.pl configuration file.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-04 01:28:23 +00:00
Antonio Niño Díaz 8e8865940a Join list of keywords of locallex.c and globlex.c
It made sense to have them in different files when the toolchain
targeted systems other than the GB. Now, there are no generic and
system-specific keywords because there is only one supported system.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-04 01:28:23 +00:00
Antonio Niño Díaz 3c14f9760f Fix echo command in checkpatch target in Makefile
Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-03 19:46:48 +01:00
Antonio Niño Díaz 3c15b141e0 Add checkpatch.pl config file and Makefile targets
This is used to verify the coding style of patches.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-02 17:09:36 +01:00
Antonio Niño Díaz 72f801283d Cleanup code of rgbasm
Follow Linux kernel coding style.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-02 17:09:36 +01:00
Antonio Niño Díaz 2ffaf72e39 Cleanup code of rgbfix, rgbgfx and external libs
Follow Linux kernel coding style.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-02 13:16:53 +01:00
Antonio Niño Díaz f41c532400 Cleanup code of rbglink
Follow Linux kernel coding style.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2018-01-02 13:16:53 +01:00
Antonio Niño Díaz ec76431c51 Replace C types by stdint.h types
Not all occurrences have been replaced, in some cases they have been
left as they were before (like in rgbgfx and when they are in the
interface of a C standard library function).

Signed-off-by: Antonio Niño Díaz <[email protected]>
2017-12-31 15:46:22 +01:00
Antonio Niño Díaz 71961a88a0 Use M_PI instead of PI
Signed-off-by: Antonio Niño Díaz <[email protected]>
2017-12-31 15:16:08 +01:00
Antonio Niño Díaz ba944527ec Replace ULONG by uint32_t
All affected `printf` have been fixed.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2017-12-31 15:16:08 +01:00
Antonio Niño Díaz 87c9d819a1 Replace SLONG by int32_t
All affected `printf` have been fixed.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2017-12-31 15:16:08 +01:00
Antonio Niño Díaz 13c0684497 Replace 8 and 16 bit custom types by stdint.h types
Signed-off-by: Antonio Niño Díaz <[email protected]>
2017-12-31 15:16:08 +01:00
Antonio Niño Díaz c24cab6d1d Use NOT operator to complement bits instead of XOR
The previous way of doing it relied on the variable being 32-bit wide.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2017-12-31 15:16:08 +01:00
Antonio Niño Díaz 0cbe6abbd5 Increase package version number to 0.3.3
Signed-off-by: Antonio Niño Díaz <[email protected]>
2017-12-31 15:16:08 +01:00
Antonio Niño Díaz fe6e5e445b Remove warning on DB/DW/DL emtpy lists
This warning was added in 781c90b940 as a
way of catching the following cases, which are most likely programmer
mistakes:

    DB 1,, 2
    DB 1, 2,

However, the warning was also triggered in the following case:

    DB

It can be used as a replacement of:

    DS 1

In this case, it shouldn't output a warning.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2017-12-29 12:05:57 +01:00
Antonio Niño Díaz 781c90b940 Add warnings for empty elements in lists of consts
Even though this behaviour is documented (empty elements are treated as
0), it can be misleading. By having a warning, compatibility is
maintained and potential problems in the code can be detected.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2017-12-07 22:37:43 +00:00
Antonio Niño Díaz e7a8bb1140 Fix and document DL keyword
This keyword acts like DB or DW but for 32-bit values.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2017-12-07 22:36:50 +00:00
Antonio Niño Díaz f1c13af703 Fix warning about unused variable
Signed-off-by: Antonio Niño Díaz <[email protected]>
2017-10-27 20:21:03 +01:00
Antonio Niño Díaz 90bc8d9110 Reintroduce EQU __LINE__
It was removed in commit 6198cc185c, but
the documentation wasn't updated back then.

It makes more sense to reintroduce it now than to remove it from the
docs.

Signed-off-by: Antonio Niño Díaz <[email protected]>
2017-10-26 23:23:22 +01:00
1014 changed files with 27684 additions and 12565 deletions
+88
View File
@@ -0,0 +1,88 @@
# Configuration for checkpatch.pl
# ===============================
# Enable more tests
--strict
# Quiet
--quiet
# No per-file summary
--no-summary
# Don't expect the Linux kernel tree
--no-tree
# Show file line, not input line
--showfile
# Don't expect SPDX tag in the first line of a file
--ignore SPDX_LICENSE_TAG
# Don't expect Signed-off-by lines in commit messages
--no-signoff
# List of ignored rules
# ---------------------
# There's no BIT macro
--ignore BIT_MACRO
# Don't complain when bools are used in structs
--ignore BOOL_MEMBER
# Allow CamelCase
--ignore CAMELCASE
# Comparing to NULL explicitly isn't a bad thing
--ignore COMPARISON_TO_NULL
# Causes false positives
--ignore COMPLEX_MACRO
# Don't complain about structs not being const
--ignore CONST_STRUCT
# Don't complain about printing "warning:" without the function name, as warning
# printing is relevant to the code being parsed, not RGBDS' code
--ignore EMBEDDED_FUNCTION_NAME
# Do not check the format of commit messages
--ignore GIT_COMMIT_ID
# Do not check for global initializers (this is specific to the kernel)
--ignore GLOBAL_INITIALISERS
# Don't complain about initializing statics (this is specific to the kernel)
--ignore INITIALISED_STATIC
# We don't have a MAINTAINERS file, don't complain about it.
--ignore FILE_PATH_CHANGES
# Writing the continuation on the start of the line can make it clearer
--ignore LOGICAL_CONTINUATIONS
# Don't complain if a line that contains a string is too long. It's better to
# have a really long line that can be found with grep.
--ignore LONG_LINE_STRING
# Don't complain when files are modified in 'include/asm'
--ignore MODIFIED_INCLUDE_ASM
# Allow new typedefs
--ignore NEW_TYPEDEFS
# We allow lines ending with parentheses for the usage prints
--ignore OPEN_ENDED_LINE
# Prefer stdint.h types over kernel types
--ignore PREFER_KERNEL_TYPES
# Don't ask to replace sscanf by kstrto
--ignore SSCANF_TO_KSTRTO
# Parentheses can make the code clearer
--ignore UNNECESSARY_PARENTHESES
# We don't have `fallthrough;` */
--ignore PREFER_FALLTHROUGH
+7
View File
@@ -0,0 +1,7 @@
# This file is part of RGBDS.
#
# Copyright (c) 2018-2019, Phil Smith and RGBDS contributors.
#
# SPDX-License-Identifier: MIT
.git
docs
+3
View File
@@ -0,0 +1,3 @@
github: avivace
patreon: gbdev01
open_collective: gbdev
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/awk -f
/^\s+<td><b class="Sy">.+<\/b><\/td>$/ {
# Assuming that all cells whose contents are bold are heading cells,
# use the HTML tag for those
sub(/td><b class="Sy"/, "th");
sub(/b><\/td/, "th");
}
# The whole page is being generated, so it's not meant to contain any Liquid
BEGIN {
print "{% raw %}"
}
END {
print "{% endraw %}"
}
BEGIN {
in_synopsis = 0
}
/<table class="Nm">/ {
in_synopsis = 1
}
/<\/table>/ {
# Resets synopsis state even when already reset, but whatever
in_synopsis = 0
}
/<code class="Fl">-[a-zA-Z]/ {
# Add links to arg descr in synopsis section
if (in_synopsis) {
while (match($0, /<code class="Fl">-[a-zA-Z]+/)) {
# 123456789012345678 -> 18 chars
optchars = substr($0, RSTART + 18, RLENGTH - 18)
i = length(optchars)
while (i) {
end = RSTART + 18 + i
i -= 1
len = i ? 1 : 2
$0 = sprintf("%s<a href=\"#%s\">%s</a>%s",
substr($0, 0, end - len - 1),
substr($0, end - 1, 1),
substr($0, end - len, len),
substr($0, end))
}
}
}
}
{
# Make long opts (defined using `Fl Fl`) into a single tag
gsub(/<code class="Fl">-<\/code>\s*<code class="Fl">/, "<code class=\"Fl\">-")
}
{
print
}
+113
View File
@@ -0,0 +1,113 @@
#!/bin/bash
usage() {
cat <<EOF
Usage: $0 [-h] [-r] <rgbds-www> <version>
Copy renders from RGBDS repository to rgbds-www documentation
Execute from the root folder of the RGBDS repo, checked out at the desired tag
<rgbds-www> : Path to the rgbds-www repository
<version> : Version to be copied, such as 'v0.4.1' or 'master'
-h Display this help message
-r Update "latest stable" redirection pages and add a new entry to the index
(use for releases, not master)
EOF
}
is_release=0
bad_usage=0
while getopts ":hr" opt; do
case $opt in
r)
is_release=1
;;
h)
usage
exit 0
;;
\?)
echo "Unknown option '$OPTARG'"
bad_usage=1
;;
esac
done
if [ $bad_usage -ne 0 ]; then
usage
exit 1
fi
shift $(($OPTIND - 1))
declare -A PAGES
PAGES=(
[rgbasm.1.html]=src/asm/rgbasm.1
[rgbasm.5.html]=src/asm/rgbasm.5
[rgblink.1.html]=src/link/rgblink.1
[rgblink.5.html]=src/link/rgblink.5
[rgbfix.1.html]=src/fix/rgbfix.1
[rgbgfx.1.html]=src/gfx/rgbgfx.1
[rgbds.5.html]=src/rgbds.5
[rgbds.7.html]=src/rgbds.7
[gbz80.7.html]=src/gbz80.7
)
WWWPATH="/docs"
mkdir -p "$1/_documentation/$2"
# `mandoc` uses a different format for referring to man pages present in the **current** directory.
# We want that format for RGBDS man pages, and the other one for the rest;
# we thus need to copy all pages to a temporary directory, and process them there.
# Copy all pages to current dir
cp "${PAGES[@]}" .
for page in "${!PAGES[@]}"; do
stem="${page%.html}"
manpage="${stem%.?}(${stem#*.})"
descr="$(awk -v 'FS=.Nd ' '/.Nd/ { print $2; }' "${PAGES[$page]}")"
cat >"$1/_documentation/$2/$page" <<EOF
---
layout: doc
title: $manpage [$2]
description: RGBDS $2 — $descr
---
EOF
options=fragment,man='%N.%S;https://linux.die.net/man/%S/%N'
if [ $stem = rgbasm.5 ]; then
options+=,toc
fi
mandoc -Thtml -I os=Linux -O$options "${PAGES[$page]##*/}" | .github/actions/doc_postproc.awk >> "$1/_documentation/$2/$page"
groff -Tpdf -mdoc -wall "${PAGES[$page]##*/}" >"$1/_documentation/$2/$stem.pdf"
if [ $is_release -ne 0 ]; then
cat - >"$1/_documentation/$page" <<EOF
---
redirect_to: $WWWPATH/$2/${page%.html}
permalink: $WWWPATH/${page%.html}/
title: $manpage [latest stable]
description: RGBDS latest stable — $descr
---
EOF
fi
done
cat - >"$1/_documentation/$2/index.html" <<EOF
---
layout: doc_index
permalink: /docs/$2/
title: RGBDS online manual [$2]
description: RGBDS $2 - Online manual
---
EOF
# If making a release, add a new entry right after `master`
if [ $is_release -ne 0 ]; then
awk '{ print }
/"name": "master"/ { print "\t\t{\"name\": \"'$2'\", \"text\": \"'$2'\" }," }
' "$1/_data/doc.json" >"$1/_data/doc.json.tmp"
mv "$1/_data/doc.json"{.tmp,}
fi
# Clean up
rm "${PAGES[@]##*/}"
+18
View File
@@ -0,0 +1,18 @@
case `echo $1 | cut -d '-' -f 1` in
ubuntu)
sudo apt-get -qq update
sudo apt-get install -yq bison libpng-dev pkg-config
;;
macos)
brew install bison libpng pkg-config md5sha1sum
# For the version check below exclusively, re-do this before building
export PATH="/usr/local/opt/bison/bin:$PATH"
;;
*)
echo "WARNING: Cannot install deps for OS '$1'"
;;
esac
bison --version
make --version
cmake --version
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash
source mingw-env @TRIPLE@
echo LAST IS: $last
# check if last arg is a path to configure, else use parent
for last; do true; done
if test -x "${last}/configure"; then
config_path="$last"
else
config_path=".."
fi
${config_path}/configure \
--host=@TRIPLE@ --target=@TRIPLE@ --build="$CHOST" \
--prefix=/usr/@TRIPLE@ --libdir=/usr/@TRIPLE@/lib --includedir=/usr/@TRIPLE@/include \
--enable-shared --enable-static "$@"
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
_arch=$1
default_mingw_pp_flags="-D_FORTIFY_SOURCE=2"
default_mingw_compiler_flags="$default_mingw_pp_flags -O2 -pipe -fno-plt -fexceptions --param=ssp-buffer-size=4"
default_mingw_linker_flags="-Wl,-O1,--sort-common,--as-needed -fstack-protector"
export CPPFLAGS="${MINGW_CPPFLAGS:-$default_mingw_pp_flags $CPPFLAGS}"
export CFLAGS="${MINGW_CFLAGS:-$default_mingw_compiler_flags $CFLAGS}"
export CXXFLAGS="${MINGW_CXXFLAGS:-$default_mingw_compiler_flags $CXXFLAGS}"
export LDFLAGS="${MINGW_LDFLAGS:-$default_mingw_linker_flags $LDFLAGS}"
mingw_prefix=/usr/${_arch}
export PKG_CONFIG_SYSROOT_DIR="${mingw_prefix}"
export PKG_CONFIG_LIBDIR="${mingw_prefix}/lib/pkgconfig:${mingw_prefix}/share/pkgconfig"
+44
View File
@@ -0,0 +1,44 @@
#!/bin/sh
# This script was written by ISSOtm while looking at Arch Linux's PKGBUILD for
# the corresponding package. (And its dependencies)
# https://aur.archlinux.org/packages/mingw-w64-libpng/
set -e
pngver=1.6.37
_apngver=$pngver
_arch="$1"
## Install mingw-configure and mingw-env (both build dependencies)
install -m 755 .github/actions/mingw-env.sh /usr/bin/mingw-env
sed "s|@TRIPLE@|${_arch}|g" .github/actions/mingw-configure.sh > ${_arch}-configure
install -m 755 ${_arch}-configure /usr/bin/
## Grab sources and check them
wget http://downloads.sourceforge.net/sourceforge/libpng/libpng-$pngver.tar.xz
wget http://downloads.sourceforge.net/project/apng/libpng/libpng16/libpng-$_apngver-apng.patch.gz
sha256sum -c .github/actions/mingw-w64-libpng-dev.sha256sums
## Extract sources
tar -xf libpng-$pngver.tar.xz
gunzip libpng-$_apngver-apng.patch.gz
## Start building!
cd libpng-$pngver
# Patch in apng support
patch -p0 ../libpng-$_apngver-apng.patch
mkdir -p build-${_arch}
cd build-${_arch}
${_arch}-configure LDFLAGS=-static-libgcc
make
make install
@@ -0,0 +1,2 @@
10d9e0cb60e2b387a79b355eb7527c0bee2ed8cbd12cf04417cabc4d6976683c libpng-1.6.37-apng.patch.gz
505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca libpng-1.6.37.tar.xz
+25
View File
@@ -0,0 +1,25 @@
name: "Code style checking"
on: pull_request
jobs:
checkpatch:
runs-on: ubuntu-latest
steps:
- name: Set up repo
run: |
git clone -b "${{ github.event.pull_request.head.ref }}" "${{ github.event.pull_request.head.repo.clone_url }}" rgbds
cd rgbds
git remote add upstream "${{ github.event.pull_request.base.repo.clone_url }}"
git fetch upstream
- name: Set up checkpatch
working-directory: rgbds
run: |
wget 'https://raw.githubusercontent.com/torvalds/linux/master/scripts/checkpatch.pl'
chmod +x checkpatch.pl
wget 'https://raw.githubusercontent.com/torvalds/linux/master/scripts/const_structs.checkpatch'
wget 'https://raw.githubusercontent.com/torvalds/linux/master/scripts/spelling.txt'
- name: Checkpatch
working-directory: rgbds
run: |
make checkpatch CHECKPATCH=./checkpatch.pl "BASE_REF=${{ github.event.pull_request.base.sha }}" Q= | tee log
if grep -q ERROR: log; then exit 1; else exit 0; fi
@@ -0,0 +1,52 @@
name: "Create release docs"
on:
release:
types:
- released # This avoids triggering on pre-releases
jobs:
build:
runs-on: ubuntu-18.04
steps:
- name: Checkout rgbds@release
uses: actions/checkout@v2
with:
path: rgbds
- name: Checkout rgbds-www@master
uses: actions/checkout@v2
with:
repository: ${{ github.repository_owner }}/rgbds-www
path: rgbds-www
# `-O toc` was added in 1.14.5, but the repos only have 1.14.4
- name: Build and install mandoc + install groff
run: |
sudo apt-get -qq update
sudo apt-get install -yq groff zlib1g-dev
wget 'http://mandoc.bsd.lv/snapshots/mandoc-1.14.5.tar.gz'
tar xf mandoc-1.14.5.tar.gz
cd mandoc-1.14.5
./configure
make
sudo make install
- name: Update pages
working-directory: rgbds
run: | # The ref appears to be in the format "refs/tags/<version>", so strip that
./.github/actions/get-pages.sh -r ../rgbds-www ${GITHUB_REF##*/}
- name: Push new pages
working-directory: rgbds-www
run: |
mkdir -p -m 700 ~/.ssh
cat > ~/.ssh/id_ed25519 <<<"${{ secrets.SSH_KEY_SECRET }}"
chmod 0600 ~/.ssh/id_ed25519
eval $(ssh-agent -s)
ssh-add ~/.ssh/id_ed25519
git config --global user.name "GitHub Action"
git config --global user.email "[email protected]"
git add -A
git commit -m "Create RGBDS ${GITHUB_REF##*/} documentation"
if git remote | grep -q origin; then
git remote set-url origin [email protected]:${{ github.repository_owner }}/rgbds-www.git
else
git remote add origin [email protected]:${{ github.repository_owner }}/rgbds-www.git
fi
git push origin master
+200
View File
@@ -0,0 +1,200 @@
name: "Regression testing"
on:
- push
- pull_request
jobs:
unix-testing:
strategy:
matrix:
os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04, macos-10.15]
cc: [gcc, clang]
buildsys: [make, cmake]
include:
- os: ubuntu-18.04
cc: gcc
target: develop
cmakevars: -DSANITIZERS=ON -DMORE_WARNINGS=ON -DCMAKE_BUILD_TYPE=Debug
- os: ubuntu-20.04
cc: gcc
target: develop
cmakevars: -DSANITIZERS=ON -DMORE_WARNINGS=ON -DCMAKE_BUILD_TYPE=Debug
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Install deps
shell: bash
run: |
./.github/actions/install_deps.sh ${{ matrix.os }}
# The `export` lines are to allow working on macOS...
# Apple's base version is severely outdated, not even supporting -Wall,
# but it overrides Homebrew's version nonetheless...
- name: Build & install using Make
run: |
export PATH="/usr/local/opt/bison/bin:$PATH"
make ${{ matrix.target }} -j Q= CC=${{ matrix.cc }}
sudo make install -j Q=
if: matrix.buildsys == 'make'
- name: Build & install using CMake
run: |
export PATH="/usr/local/opt/bison/bin:$PATH"
cmake -S . -B build -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=${{ matrix.cc }} ${{ matrix.cmakevars }}
cmake --build build
cp build/src/rgb{asm,link,fix,gfx} .
sudo cmake --install build
if: matrix.buildsys == 'cmake'
- name: Package binaries
run: |
mkdir bins
cp rgb{asm,link,fix,gfx} bins
- name: Upload binaries
uses: actions/upload-artifact@v1
with:
name: rgbds-canary-${{ matrix.os }}-${{ matrix.cc }}-${{ matrix.buildsys }}
path: bins
- name: Test
shell: bash
run: |
test/run-tests.sh
windows-testing:
strategy:
matrix:
bits: [32, 64]
include:
- bits: 32
arch: x86
platform: Win32
- bits: 64
arch: x86_x64
platform: x64
fail-fast: false
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- name: Get zlib, libpng and bison
run: | # TODO: use an array
$wc = New-Object System.Net.WebClient
$wc.DownloadFile('https://www.zlib.net/zlib1211.zip', 'zlib.zip')
$hash = (Get-FileHash "zlib.zip" -Algorithm SHA256).Hash
if ($hash -ne 'd7510a8ee1918b7d0cad197a089c0a2cd4d6df05fee22389f67f115e738b178d') {
Write-Host "zlib SHA256 mismatch! ($hash)"
exit 1
}
$wc.DownloadFile('https://download.sourceforge.net/libpng/lpng1637.zip', 'libpng.zip')
$hash = (Get-FileHash "libpng.zip" -Algorithm SHA256).Hash
if ($hash -ne '3b4b1cbd0bae6822f749d39b1ccadd6297f05e2b85a83dd2ce6ecd7d09eabdf2') {
Write-Host "libpng SHA256 mismatch! ($hash)"
exit 1
}
$wc.DownloadFile('https://github.com/lexxmark/winflexbison/releases/download/v2.5.23/win_flex_bison-2.5.23.zip', 'winflexbison.zip')
$hash = (Get-FileHash "winflexbison.zip" -Algorithm SHA256).Hash
if ($hash -ne '6AA5C8EA662DA1550020A5804C28BE63FFAA53486DA9F6842E24C379EC422DFC') {
Write-Host "bison SHA256 mismatch! ($hash)"
}
Expand-Archive -DestinationPath . "zlib.zip"
Expand-Archive -DestinationPath . "libpng.zip"
Expand-Archive -DestinationPath install_dir "winflexbison.zip"
Move-Item zlib-1.2.11 zlib
Move-Item lpng1637 libpng
- name: Build zlib
run: | # BUILD_SHARED_LIBS causes the output DLL to be correctly called `zlib1.dll`
cmake -S zlib -B zbuild -A ${{ matrix.platform }} -DCMAKE_INSTALL_PREFIX=install_dir -DBUILD_SHARED_LIBS=ON
cmake --build zbuild --config Release
cmake --install zbuild
- name: Build libpng
run: |
cmake -S libpng -B pngbuild -A ${{ matrix.platform }} -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=ON -DPNG_TESTS=OFF
cmake --build pngbuild --config Release
cmake --install pngbuild
- name: Build Windows binaries
run: |
cmake -S . -B build -A ${{ matrix.platform }} -DCMAKE_INSTALL_PREFIX=install_dir -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release
cmake --install build
- name: Package binaries
shell: bash
run: |
mkdir bins
cp install_dir/bin/{rgbasm.exe,rgblink.exe,rgbfix.exe,rgbgfx.exe,zlib1.dll,libpng16.dll} bins
- name: Upload Windows binaries
uses: actions/upload-artifact@v1
with:
name: rgbds-canary-win${{ matrix.bits }}
path: bins
- name: Test
shell: bash
run: |
cp bins/* .
test/run-tests.sh
windows-xbuild:
strategy:
matrix:
bits: [32, 64]
os: [ubuntu-18.04]
include:
- bits: 32
arch: i686
triplet: i686-w64-mingw32
- bits: 64
arch: x86-64
triplet: x86_64-w64-mingw32
fail-fast: false
runs-on: ${{ matrix.os }}
env:
DIST_DIR: win${{ matrix.bits }}
steps:
- uses: actions/checkout@v2
- name: Install deps
shell: bash
run: |
./.github/actions/install_deps.sh ${{ matrix.os }}
- name: Install MinGW
run: |
sudo apt-get install gcc-mingw-w64-${{ matrix.arch }} mingw-w64-tools libz-mingw-w64-dev
- name: Install libpng dev headers for MinGW
run: |
sudo ./.github/actions/mingw-w64-libpng-dev.sh ${{ matrix.triplet }}
- name: Cross-build Windows binaries
run: |
make mingw${{ matrix.bits }} -j Q=
- name: Package binaries
run: |
mkdir bins
mv rgbasm bins/rgbasm.exe
mv rgblink bins/rgblink.exe
mv rgbfix bins/rgbfix.exe
mv rgbgfx bins/rgbgfx.exe
cp /usr/${{ matrix.triplet }}/lib/zlib1.dll bins
cp /usr/${{ matrix.triplet }}/bin/libpng16-16.dll bins
if [ ${{ matrix.bits }} -eq 32 ]; then cp /usr/lib/gcc/${{ matrix.triplet }}/7.3-win32/libgcc_s_sjlj-1.dll bins; fi
- name: Upload Windows binaries
uses: actions/upload-artifact@v1
with:
name: rgbds-canary-mingw-win${{ matrix.bits }}
path: bins
windows-xtesting:
needs: windows-xbuild
strategy:
matrix:
bits: [32, 64]
fail-fast: false
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- name: Retrieve binaries
uses: actions/download-artifact@v1
with:
name: rgbds-canary-mingw-win${{ matrix.bits }}
path: bins
- name: Extract binaries
shell: bash
run: |
cp bins/* .
- name: Run tests
shell: bash
run: |
test/run-tests.sh
@@ -0,0 +1,65 @@
name: "Update master docs"
on:
push:
branches:
- master
paths:
- .github/actions/get-pages.sh
- src/gbz80.7
- src/rgbds.5
- src/rgbds.7
- src/asm/rgbasm.1
- src/asm/rgbasm.5
- src/link/rgblink.1
- src/link/rgblink.5
- src/fix/rgbfix.1
- src/gfx/rgbgfx.1
jobs:
build:
runs-on: ubuntu-18.04
steps:
- name: Checkout rgbds@master
uses: actions/checkout@v2
with:
repository: gbdev/rgbds
ref: master
path: rgbds
- name: Checkout rgbds-www@master
uses: actions/checkout@v2
with:
repository: gbdev/rgbds-www
ref: master
path: rgbds-www
- name: Build and install mandoc + install groff
run: |
sudo apt-get -qq update
sudo apt-get install -yq groff zlib1g-dev
wget 'http://mandoc.bsd.lv/snapshots/mandoc-1.14.5.tar.gz'
tar xf mandoc-1.14.5.tar.gz
cd mandoc-1.14.5
./configure
make
sudo make install
- name: Update pages
working-directory: rgbds
run: |
./.github/actions/get-pages.sh ../rgbds-www master
- name: Push new pages
working-directory: rgbds-www
run: |
mkdir -p -m 700 ~/.ssh
echo "${{ secrets.SSH_KEY_SECRET }}" > ~/.ssh/id_ed25519
chmod 0600 ~/.ssh/id_ed25519
eval $(ssh-agent -s)
ssh-add ~/.ssh/id_ed25519
git config --global user.name "GitHub Action"
git config --global user.email "[email protected]"
git add .
git commit -m "Update RGBDS master documentation"
if git remote | grep -q origin; then
git remote set-url origin [email protected]:gbdev/rgbds-www.git
else
git remote add origin [email protected]:gbdev/rgbds-www.git
fi
git push origin master
@@ -0,0 +1,96 @@
name: "Create release artifacts"
on:
push:
tags:
- v[0-9]*
jobs:
windows:
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- name: Get version from tag
shell: bash
run: | # Turn "refs/tags/vX.Y.Z" into "X.Y.Z"
VERSION="${{ github.ref }}"
echo "version=${VERSION##*/v}" >> $GITHUB_ENV
- name: Get zlib, libpng and bison
run: | # TODO: use an array
$wc = New-Object System.Net.WebClient
$wc.DownloadFile('https://www.zlib.net/zlib1211.zip', 'zlib.zip')
$hash = (Get-FileHash "zlib.zip" -Algorithm SHA256).Hash
if ($hash -ne 'd7510a8ee1918b7d0cad197a089c0a2cd4d6df05fee22389f67f115e738b178d') {
Write-Host "zlib SHA256 mismatch! ($hash)"
exit 1
}
$wc.DownloadFile('https://download.sourceforge.net/libpng/lpng1637.zip', 'libpng.zip')
$hash = (Get-FileHash "libpng.zip" -Algorithm SHA256).Hash
if ($hash -ne '3b4b1cbd0bae6822f749d39b1ccadd6297f05e2b85a83dd2ce6ecd7d09eabdf2') {
Write-Host "libpng SHA256 mismatch! ($hash)"
exit 1
}
$wc.DownloadFile('https://github.com/lexxmark/winflexbison/releases/download/v2.5.23/win_flex_bison-2.5.23.zip', 'winflexbison.zip')
$hash = (Get-FileHash "winflexbison.zip" -Algorithm SHA256).Hash
if ($hash -ne '6AA5C8EA662DA1550020A5804C28BE63FFAA53486DA9F6842E24C379EC422DFC') {
Write-Host "bison SHA256 mismatch! ($hash)"
}
Expand-Archive -DestinationPath . "zlib.zip"
Expand-Archive -DestinationPath . "libpng.zip"
Expand-Archive -DestinationPath install_dir "winflexbison.zip"
Move-Item zlib-1.2.11 zlib
Move-Item lpng1637 libpng
- name: Build 32-bit zlib
run: | # BUILD_SHARED_LIBS causes the output DLL to be correctly called `zlib1.dll`
cmake -S zlib -B zbuild32 -A Win32 -DCMAKE_INSTALL_PREFIX=install_dir -DBUILD_SHARED_LIBS=ON
cmake --build zbuild32 --config Release
cmake --install zbuild32
- name: Build 32-bit libpng
run: |
cmake -S libpng -B pngbuild32 -A Win32 -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=ON -DPNG_TESTS=OFF
cmake --build pngbuild32 --config Release
cmake --install pngbuild32
- name: Build 32-bit Windows binaries
run: |
cmake -S . -B build32 -A Win32 -DCMAKE_INSTALL_PREFIX=install_dir -DCMAKE_BUILD_TYPE=Release
cmake --build build32 --config Release
cmake --install build32
- name: Package 32-bit binaries
run: |
Compress-Archive -LiteralPath @("install_dir/bin/rgbasm.exe", "install_dir/bin/rgblink.exe", "install_dir/bin/rgbfix.exe", "install_dir/bin/rgbgfx.exe", "install_dir/bin/zlib1.dll", "install_dir/bin/libpng16.dll") "rgbds-${{ env.version }}-win32.zip"
- name: Build 64-bit zlib
run: | # BUILD_SHARED_LIBS causes the output DLL to be correctly called `zlib1.dll`
cmake -S zlib -B zbuild64 -A x64 -DCMAKE_INSTALL_PREFIX=install_dir -DBUILD_SHARED_LIBS=ON
cmake --build zbuild64 --config Release
cmake --install zbuild64
- name: Build 64-bit libpng
run: |
cmake -S libpng -B pngbuild64 -A x64 -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=ON -DPNG_TESTS=OFF
cmake --build pngbuild64 --config Release
cmake --install pngbuild64
- name: Build 64-bit Windows binaries
run: |
cmake -S . -B build64 -A x64 -DCMAKE_INSTALL_PREFIX=install_dir -DCMAKE_BUILD_TYPE=Release
cmake --build build64 --config Release
cmake --install build64
- name: Package 64-bit binaries
run: |
Compress-Archive -LiteralPath @("install_dir/bin/rgbasm.exe", "install_dir/bin/rgblink.exe", "install_dir/bin/rgbfix.exe", "install_dir/bin/rgbgfx.exe", "install_dir/bin/zlib1.dll", "install_dir/bin/libpng16.dll") "rgbds-${{ env.version }}-win64.zip"
- name: Package sources
run: |
make dist
- name: Release
uses: softprops/action-gh-release@v1
with:
body: |
Please ensure that the three assets below work properly.
Once that's done, replace this text with the changelog, un-draft the release, and update the `release` branch.
By the way, if you forgot to update `include/version.h`, RGBASM's version test is gonna fail in the tag's regression testing! (Use `git push --delete origin <tag>` to delete it)
draft: true # Don't publish the release quite yet...
prerelease: ${{ contains(github.ref, '-rc') }}
files: |
rgbds-${{ env.version }}-win32.zip
rgbds-${{ env.version }}-win64.zip
rgbds-${{ env.version }}.tar.gz
fail_on_unmatched_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+10 -1
View File
@@ -2,6 +2,15 @@ rgbasm
rgblink
rgbfix
rgbgfx
rgbshim.sh
*.o
*.exe
*.html
*.dll
.checkpatch-camelcase.*
CMakeCache.txt
CMakeFiles
cmake_install.cmake
test/pokecrystal
test/pokered
test/ucity
-13
View File
@@ -1,13 +0,0 @@
#!/bin/sh
if [ $TRAVIS_OS_NAME = "osx" ]; then
brew update
brew install libpng pkg-config
else # linux
sudo apt-get -qq update
sudo apt-get install -y -q bison flex libpng-dev pkg-config
fi
echo "Dependencies:"
yacc --version
flex --version
-16
View File
@@ -1,16 +0,0 @@
language: c
sudo: required
install:
- ./.travis-deps.sh
os:
- linux
- osx
compiler:
- clang
- gcc
script:
- make
- sudo make install
after_success:
- pushd test/asm/ && ./test.sh && popd
- pushd test/link/ && ./test.sh && popd
+97
View File
@@ -0,0 +1,97 @@
#
# This file is part of RGBDS.
#
# Copyright (c) 2020 RGBDS contributors.
#
# SPDX-License-Identifier: MIT
#
# 3.9 required for LTO checks
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
project(rgbds
LANGUAGES C)
# get real path of source and binary directories
get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH)
get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH)
# reject in-source builds, may conflict with Makefile
if(srcdir STREQUAL bindir)
message("RGBDS should not be built in the source directory.")
message("Instead, create a separate build directory and specify to CMake the path to the source directory.")
message(FATAL_ERROR "Terminating configuration")
endif()
option(SANITIZERS "Build with sanitizers enabled" OFF) # Ignored on MSVC
option(MORE_WARNINGS "Turn on more warnings" OFF) # Ignored on MSVC
option(TRACE_PARSER "Trace parser execution" OFF)
option(TRACE_LEXER "Trace lexer execution" OFF)
if(MSVC)
# MSVC's standard library triggers warning C5105,
# "macro expansion producing 'defined' has undefined behavior"
add_compile_options(/std:c11 /W1 /MP /wd5105)
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
else()
add_compile_options(-Wall -pedantic)
if(SANITIZERS)
set(SAN_FLAGS -fsanitize=shift -fsanitize=integer-divide-by-zero
-fsanitize=unreachable -fsanitize=vla-bound
-fsanitize=signed-integer-overflow -fsanitize=bounds
-fsanitize=object-size -fsanitize=bool -fsanitize=enum
-fsanitize=alignment -fsanitize=null)
add_compile_options(${SAN_FLAGS})
link_libraries(${SAN_FLAGS})
endif()
if(MORE_WARNINGS)
add_compile_options(-Werror -Wextra -Wno-type-limits
-Wno-sign-compare -Wvla -Wformat -Wformat-security -Wformat-overflow=2
-Wformat-truncation=1 -Wformat-y2k -Wswitch-enum -Wunused
-Wuninitialized -Wunknown-pragmas -Wstrict-overflow=5
-Wstringop-overflow=4 -Walloc-zero -Wduplicated-cond
-Wfloat-equal -Wshadow -Wcast-qual -Wcast-align -Wlogical-op
-Wnested-externs -Wno-aggressive-loop-optimizations -Winline
-Wundef -Wstrict-prototypes -Wold-style-definition)
endif()
endif()
# Use versioning consistent with Makefile
# the git revision is used but uses the fallback in an archive
execute_process(COMMAND git describe --tags --dirty --always
OUTPUT_VARIABLE GIT_REV
ERROR_QUIET)
string(STRIP "${GIT_REV}" GIT_REV)
include_directories("${PROJECT_SOURCE_DIR}/include")
add_definitions(-DBUILD_VERSION_STRING="${GIT_REV}")
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED True)
add_subdirectory(src)
# By default, build in Release mode; Debug mode must be explicitly requested
# (You may want to augment it with the options above)
if(CMAKE_BUILD_TYPE STREQUAL "Release")
message(CHECK_START "Checking if LTO is supported")
include(CheckIPOSupported)
check_ipo_supported(RESULT enable_lto)
if(enable_lto)
message(CHECK_PASS "yes")
set_property(TARGET rgbasm rgblink rgbfix rgbgfx PROPERTY INTERPROCEDURAL_OPTIMIZATION ON)
else()
message(CHECK_FAIL "no")
endif()
endif()
if(TRACE_PARSER)
target_compile_definitions(rgbasm PRIVATE -DYYDEBUG)
endif()
if(TRACE_LEXER)
target_compile_definitions(rgbasm PRIVATE -DLEXER_DEBUG)
endif()
+96
View File
@@ -0,0 +1,96 @@
Contributing
============
RGBDS was created in the late 90's and has received contributions from several
developers since then. It wouldn't have been possible to get to this point
without their work and, for that reason, it is always open to the contributions
of other people.
Reporting Bugs
--------------
Bug reports are essential to improve RGBDS and they are always welcome. If you
want to report a bug:
1. Make sure that there isn't a similar issue already reported
`here <https://github.com/rednex/rgbds/issues>`__.
2. Figure out a way of reproducing it reliably.
3. If there is a piece of code that triggers the bug, try to reduce it to the
smallest file you can.
4. Create a new `issue <https://github.com/rednex/rgbds/issues>`__.
Of course, it may not always be possible to give an accurate bug report, but it
always helps to fix it.
Requesting new features
-----------------------
If you come up with a good idea that could be implemented, you can propose it to
be done.
1. Create a new `issue <https://github.com/rednex/rgbds/issues>`__.
2. Try to be as accurate as possible. Describe what you need and why you need
it, maybe with examples.
Please understand that the contributors are doing it in their free time, so
simple requests are more likely to catch the interest of a contributor than
complicated ones. If you really need something to be done, and you think you can
implement it yourself, you can always contribute to RGBDS with your own code.
Contributing code
-----------------
If you want to contribute with your own code, whether it is to fix a current
issue or to add something that nobody had requested, you should first consider
if your change is going to be small (and likely to be accepted as-is) or big
(and will have to go through some rework).
Big changes will most likely require some discussion, so open an
`issue <https://github.com/rednex/rgbds/issues>`__ and explain what you want to
do and how you intend to do it. If you already have a prototype, it's always a
good idea to show it. Tests help, too.
If you are going to work on a specific issue that involves a lot of work, it is
always a good idea to leave a message, just in case someone else is interested
but doesn't know that there's someone working on it.
Note that you must contribute all your changes under the MIT License. If you are
just modifying a file, you don't need to do anything (maybe update the copyright
years). If you are adding new files, you need to use the correct header with the
copyright and the reference to the MIT License.
1. Fork this repository.
2. Checkout the ``master`` branch.
3. Create a new branch to work on. You could still work on ``master``, but it's
easier that way.
4. Compile your changes with ``make develop`` instead of just ``make``. This
target checks for additional warnings. Your patches shouldn't introduce any
new warning (but it may be possible to remove some warning checks if it makes
the code much easier).
5. Follow the Linux kernel coding style, which can be found in the file
``Documentation/process/coding-style.rst`` in the Linux kernel repository.
Note that the coding style isn't written in stone, if there is a good reason
to deviate from it, it should be fine.
6. Download the files ``checkpatch.pl``, ``const_structs.checkpatch`` and
``spelling.txt`` from the folder ``scripts`` in the Linux kernel repository.
7. To use ``checkpatch.pl`` you can use ``make checkpatch``, which will check
the coding style of all patches between the current one and the upstream
code. By default, the Makefile expects the script (and associate files) to be
located in ``../linux/scripts/``, but you can place them anywhere you like as
long as you specify it when executing the command:
``make checkpatch CHECKPATCH=../path/to/folder``.
8. Create a pull request against the branch ``master``.
9. Be prepared to get some comments about your code and to modify it. Tip: Use
``git rebase -i origin/master`` to modify chains of commits.
+53
View File
@@ -0,0 +1,53 @@
Contributors to RGBDS
=====================
Original author
---------------
- Carsten Elton Sørensen <[email protected]>
Main contributors
-----------------
- Justin Lloyd <[email protected]>
- Vegard Nossum <[email protected]>
- Anthony J. Bentley <[email protected]>
- stag019 <[email protected]>
- Antonio Niño Díaz <[email protected]>
Other contributors
------------------
- Ben Hetherington <[email protected]>
- Björn Höhrmann <[email protected]>
- Christophe Staïesse <[email protected]>
- David Brotz <[email protected]>
- Eldred Habert <[email protected]>
- The Musl C library <http://www.musl-libc.org>
- obskyr <[email protected]>
- The OpenBSD Project <http://www.openbsd.org>
- Quint Guvernator <[email protected]>
- Rangi <http://github.com/Rangi42>
- Sanqui <[email protected]>
- YamaArashi <[email protected]>
- yenatch <[email protected]>
- phs <[email protected]>
- jidoc01 <[email protected]>
+24
View File
@@ -0,0 +1,24 @@
# This file is part of RGBDS.
#
# Copyright (c) 2018-2019, Phil Smith and RGBDS contributors.
#
# SPDX-License-Identifier: MIT
# docker build -t rgbds:vX.X.X-alpine
FROM alpine:latest
RUN apk add --update \
build-base \
bison \
libpng-dev
COPY . /rgbds
WORKDIR /rgbds
RUN make Q='' all
FROM alpine:latest
RUN apk add --update \
libpng
COPY --from=0 \
/rgbds/rgbasm \
/rgbds/rgbfix \
/rgbds/rgblink \
/rgbds/rgbgfx \
/bin/
+21
View File
@@ -0,0 +1,21 @@
The MIT License
Copyright (c) 1997-2020, Carsten Sorensen and RGBDS contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
-74
View File
@@ -1,74 +0,0 @@
# Original code
Copyright (C) 1997 Carsten Sorensen <surfsmurf@matilde.demon.co.uk>
The ASMotor package (xAsm, xLink, RGBFix, examples and documentation) is
freeware and distributed as is. The author retains his copyright and right to
modify the specifications and operation of the software without notice.
In other words this means I encourage you to...
- use it for whatever purpose even professional work without me charging you a
penny
- copy it to another person (wholly or in part, though I'm sure he'd appreciate
the whole package) in whatever form you find suitable
- mass-distribute the ASMotor package if it is complete (xAsm, xLink, RGBFix and
documentation).
- contact me if you have any problems
This also means you can't...
- blame me for loss of profit, data, sleep, food or other nasty things through
the use or distribution of ASMotor. If you choose to use ASMotor you do so at
your own risk.
- expect me to be able to help you should you have a problem related or not to
ASMotor.
# Otaku no Zoku's modifications
Copyright (C) 1999 Justin Lloyd <jlloyd@imf.la> (?)
```
DO WHATEVER PUBLIC LICENSE*
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You can do whatever you want to with the work.
1. You cannot stop anybody from doing whatever they want to with the work.
2. You cannot revoke anybody elses DO WHATEVER PUBLIC LICENSE in the work.
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the DO WHATEVER PUBLIC LICENSE
Software originally created by Justin Lloyd @ http://otakunozoku.com/
```
# rgbds-linux
Copyright (C) 2009 Vegard Nossum <vegard.nossum@gmail.com>
# Current
rgbasm and rgblink are derived from Justin Lloyd's RGBDS.
rgbfix was rewritten from scratch by Anthony J. Bentley, and is released
under the ISC license; see the source file for the text of the license.
rgbgfx was written by stag019, and is released under the ISC license.
Some files of rgblink were written by Antonio Niño Díaz, and they are relased
under the ISC license. The affected files have the appropriate license in the
header of the file.
The UTF-8 decoder in src/asm/charmap.c was written by Björn Höhrmann and is
released under the MIT license. The remainder of charmap.c was written by
stag019, and is released under the ISC license.
extern/err.c is derived from the Musl C library, http://www.musl-libc.org,
and is released under the MIT license.
extern/reallocarray.c is derived from the OpenBSD Project,
http://www.openbsd.org, and is released under the ISC license.
extern/strl.c is derived from the OpenBSD Project, http://www.openbsd.org,
and is released under the BSD license.
+144 -79
View File
@@ -1,35 +1,51 @@
#
# This file is part of RGBDS.
#
# Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
#
# SPDX-License-Identifier: MIT
#
.SUFFIXES:
.SUFFIXES: .h .y .c .o
# User-defined variables
Q := @
PREFIX := /usr/local
bindir := ${PREFIX}/bin
mandir := ${PREFIX}/man
mandir := ${PREFIX}/share/man
STRIP := -s
BINMODE := 555
MANMODE := 444
BINMODE := 755
MANMODE := 644
CHECKPATCH := ../linux/scripts/checkpatch.pl
# Other variables
PKG_CONFIG := pkg-config
PNGCFLAGS := `${PKG_CONFIG} --static --cflags libpng`
PNGLDFLAGS := `${PKG_CONFIG} --static --libs-only-L libpng`
PNGLDLIBS := `${PKG_CONFIG} --static --libs-only-l libpng`
PNGCFLAGS := `${PKG_CONFIG} --cflags libpng`
PNGLDFLAGS := `${PKG_CONFIG} --libs-only-L libpng`
PNGLDLIBS := `${PKG_CONFIG} --libs-only-l libpng`
# Note: if this comes up empty, `version.c` will automatically fall back to last release number
VERSION_STRING := `git describe --tags --dirty --always 2>/dev/null`
WARNFLAGS := -Wall -Werror
WARNFLAGS := -Wall
# Overridable CFLAGS
CFLAGS := -g
CFLAGS ?= -O3 -flto -DNDEBUG
# Non-overridable CFLAGS
REALCFLAGS := ${CFLAGS} ${WARNFLAGS} -std=c99 -D_POSIX_C_SOURCE=200809L \
-Iinclude -DBUILD_VERSION_STRING=\"${VERSION_STRING}\"
REALCFLAGS := ${CFLAGS} ${WARNFLAGS} -std=gnu11 -D_POSIX_C_SOURCE=200809L \
-Iinclude
# Overridable LDFLAGS
LDFLAGS ?=
# Non-overridable LDFLAGS
REALLDFLAGS := ${LDFLAGS} ${WARNFLAGS} \
-DBUILD_VERSION_STRING=\"${VERSION_STRING}\"
YFLAGS :=
LFLAGS := --nounistd
YFLAGS ?= -Wall
YACC := yacc
LEX := flex
BISON := bison
RM := rm -rf
# Rules to build the RGBDS binaries
@@ -37,93 +53,106 @@ RM := rm -rf
all: rgbasm rgblink rgbfix rgbgfx
rgbasm_obj := \
src/asm/asmy.o \
src/asm/charmap.o \
src/asm/fixpoint.o \
src/asm/format.o \
src/asm/fstack.o \
src/asm/globlex.o \
src/asm/lexer.o \
src/asm/macro.o \
src/asm/main.o \
src/asm/math.o \
src/asm/parser.o \
src/asm/opt.o \
src/asm/output.o \
src/asm/rpn.o \
src/asm/section.o \
src/asm/symbol.o \
src/asm/locallex.o \
src/asm/util.o \
src/asm/warning.o \
src/extern/err.o \
src/extern/reallocarray.o \
src/extern/strlcpy.o \
src/extern/strlcat.o \
src/extern/version.o
src/extern/getopt.o \
src/extern/utf8decoder.o \
src/hashmap.o \
src/linkdefs.o \
src/opmath.o
src/asm/asmy.h: src/asm/asmy.c
src/asm/locallex.o src/asm/globlex.o src/asm/lexer.o: src/asm/asmy.h
src/asm/lexer.o src/asm/main.o: src/asm/parser.h
rgblink_obj := \
src/link/assign.o \
src/link/lexer.o \
src/link/library.o \
src/link/main.o \
src/link/mapfile.o \
src/link/object.o \
src/link/output.o \
src/link/patch.o \
src/link/parser.o \
src/link/script.o \
src/link/section.o \
src/link/symbol.o \
src/extern/err.o \
src/extern/version.o
src/link/parser.h: src/link/parser.c
src/link/lexer.o: src/link/parser.h
src/extern/getopt.o \
src/hashmap.o \
src/linkdefs.o \
src/opmath.o
rgbfix_obj := \
src/fix/main.o \
src/extern/err.o \
src/extern/version.o
src/extern/getopt.o
rgbgfx_obj := \
src/gfx/gb.o \
src/gfx/main.o \
src/gfx/makepng.o \
src/extern/err.o \
src/extern/version.o
src/extern/getopt.o
rgbasm: ${rgbasm_obj}
$Q${CC} ${REALCFLAGS} -o $@ ${rgbasm_obj} -lm
$Q${CC} ${REALLDFLAGS} -o $@ ${rgbasm_obj} ${REALCFLAGS} src/version.c -lm
rgblink: ${rgblink_obj}
$Q${CC} ${REALCFLAGS} -o $@ ${rgblink_obj}
$Q${CC} ${REALLDFLAGS} -o $@ ${rgblink_obj} ${REALCFLAGS} src/version.c
rgbfix: ${rgbfix_obj}
$Q${CC} ${REALCFLAGS} -o $@ ${rgbfix_obj}
$Q${CC} ${REALLDFLAGS} -o $@ ${rgbfix_obj} ${REALCFLAGS} src/version.c
rgbgfx: ${rgbgfx_obj}
$Q${CC} ${REALCFLAGS} ${PNGLDFLAGS} -o $@ ${rgbgfx_obj} ${PNGLDLIBS}
$Q${CC} ${REALLDFLAGS} ${PNGLDFLAGS} -o $@ ${rgbgfx_obj} ${REALCFLAGS} src/version.c ${PNGLDLIBS}
# Rules to process files
.y.c:
$Q${YACC} -d ${YFLAGS} -o $@ $<
# We want the Bison invocation to pass through our rules, not default ones
.y.o:
.l.o:
$Q${RM} $*.c
$Q${LEX} ${LFLAGS} -o $*.c $<
$Q${CC} ${REALCFLAGS} -c -o $@ $*.c
$Q${RM} $*.c
# Bison-generated C files have an accompanying header
src/asm/parser.h: src/asm/parser.c
$Qtouch $@
src/asm/parser.c: src/asm/parser.y
$QDEFS=; \
add_flag(){ \
if src/check_bison_ver.sh $$1 $$2; then \
DEFS="-D$$3 $$DEFS"; \
fi \
}; \
add_flag 3 5 api.token.raw=true; \
add_flag 3 6 parse.error=detailed; \
add_flag 3 0 parse.error=verbose; \
add_flag 3 0 parse.lac=full; \
add_flag 3 0 lr.type=ielr; \
echo "DEFS=$$DEFS"; \
${BISON} $$DEFS -d ${YFLAGS} -o $@ $<
.c.o:
$Q${CC} ${REALCFLAGS} ${PNGCFLAGS} -c -o $@ $<
# Target used to remove all files generated by other Makefile targets.
# Target used to remove all files generated by other Makefile targets
clean:
$Q${RM} rgbds.7.html gbz80.7.html rgbds.5.html
$Q${RM} rgbasm rgbasm.exe ${rgbasm_obj} rgbasm.1.html rgbasm.5.html
$Q${RM} rgblink rgblink.exe ${rgblink_obj} rgblink.1.html rgblink.5.html
$Q${RM} rgbfix rgbfix.exe ${rgbfix_obj} rgbfix.1.html
$Q${RM} rgbgfx rgbgfx.exe ${rgbgfx_obj} rgbgfx.1.html
$Q${RM} src/asm/asmy.c src/asm/asmy.h
$Q${RM} src/link/lexer.c src/link/parser.c src/link/parser.h
$Q${RM} rgbasm rgbasm.exe
$Q${RM} rgblink rgblink.exe
$Q${RM} rgbfix rgbfix.exe
$Q${RM} rgbgfx rgbgfx.exe
$Qfind src/ -name "*.o" -exec rm {} \;
$Q${RM} rgbshim.sh
$Q${RM} src/asm/parser.c src/asm/parser.h
# Target used to install the binaries and man pages.
@@ -144,21 +173,49 @@ install: all
$Qinstall -m ${MANMODE} src/link/rgblink.5 ${DESTDIR}${mandir}/man5/rgblink.5
$Qinstall -m ${MANMODE} src/gfx/rgbgfx.1 ${DESTDIR}${mandir}/man1/rgbgfx.1
# Target for the project maintainer to easily create web manuals.
# It relies on mandoc: http://mdocml.bsd.lv
# Target used to check the coding style of the whole codebase.
# `extern/` is excluded, as it contains external code that should not be patched
# to meet our coding style, so applying upstream patches is easier.
# `.y` files aren't checked, unfortunately...
MANDOC := -Thtml -Ios=General -Oman=%N.%S.html -Ostyle=manual.css
checkcodebase:
$Qfor file in `git ls-files | grep -E '(\.c|\.h)$$' | grep -Ev '(src|include)/extern/'`; do \
${CHECKPATCH} -f "$$file"; \
done
wwwman:
$Qmandoc ${MANDOC} src/rgbds.7 > rgbds.7.html
$Qmandoc ${MANDOC} src/gbz80.7 > gbz80.7.html
$Qmandoc ${MANDOC} src/rgbds.5 > rgbds.5.html
$Qmandoc ${MANDOC} src/asm/rgbasm.1 > rgbasm.1.html
$Qmandoc ${MANDOC} src/asm/rgbasm.5 > rgbasm.5.html
$Qmandoc ${MANDOC} src/fix/rgbfix.1 > rgbfix.1.html
$Qmandoc ${MANDOC} src/link/rgblink.1 > rgblink.1.html
$Qmandoc ${MANDOC} src/link/rgblink.5 > rgblink.5.html
$Qmandoc ${MANDOC} src/gfx/rgbgfx.1 > rgbgfx.1.html
# Target used to check the coding style of the patches from the upstream branch
# to the HEAD. Runs checkpatch once for each commit between the current HEAD and
# the first common commit between the HEAD and origin/master.
# `.y` files aren't checked, unfortunately...
BASE_REF:= origin/master
checkpatch:
$Qeval COMMON_COMMIT=$$(git merge-base HEAD ${BASE_REF}); \
for commit in `git rev-list $$COMMON_COMMIT..HEAD`; do \
echo "[*] Analyzing commit '$$commit'"; \
git format-patch --stdout "$$commit~..$$commit" \
-- src include '!src/extern' '!include/extern' \
| ${CHECKPATCH} - || true; \
done
# This target is used during development in order to prevent adding new issues
# to the source code. All warnings are treated as errors in order to block the
# compilation and make the continous integration infrastructure return failure.
develop:
$Qenv $(MAKE) -j WARNFLAGS="-Werror -Wall -Wextra -Wpedantic -Wno-type-limits \
-Wno-sign-compare -Wvla -Wformat -Wformat-security -Wformat-overflow=2 \
-Wformat-truncation=1 -Wformat-y2k -Wswitch-enum -Wunused \
-Wuninitialized -Wunknown-pragmas -Wstrict-overflow=4 \
-Wstringop-overflow=4 -Walloc-zero -Wduplicated-cond \
-Wfloat-equal -Wshadow -Wcast-qual -Wcast-align -Wlogical-op \
-Wnested-externs -Wno-aggressive-loop-optimizations -Winline \
-Wundef -Wstrict-prototypes -Wold-style-definition \
-fsanitize=shift -fsanitize=integer-divide-by-zero \
-fsanitize=unreachable -fsanitize=vla-bound \
-fsanitize=signed-integer-overflow -fsanitize=bounds \
-fsanitize=object-size -fsanitize=bool -fsanitize=enum \
-fsanitize=alignment -fsanitize=null" CFLAGS="-ggdb3 -O0"
# Targets for the project maintainer to easily create Windows exes.
# This is not for Windows users!
@@ -166,17 +223,25 @@ wwwman:
# install instructions instead.
mingw32:
$Qenv PKG_CONFIG_PATH=/usr/i686-w64-mingw32/sys-root/mingw/lib/pkgconfig/ \
make CC=i686-w64-mingw32-gcc YACC=bison WARNFLAGS= -j
$Qmv rgbasm rgbasm.exe
$Qmv rgblink rgblink.exe
$Qmv rgbfix rgbfix.exe
$Qmv rgbgfx rgbgfx.exe
$Qmake CC=i686-w64-mingw32-gcc BISON=bison \
PKG_CONFIG=i686-w64-mingw32-pkg-config -j
mingw64:
$Qenv PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/sys-root/mingw/lib/pkgconfig/ \
make CC=x86_64-w64-mingw32-gcc YACC=bison WARNFLAGS= -j
$Qmv rgbasm rgbasm.exe
$Qmv rgblink rgblink.exe
$Qmv rgbfix rgbfix.exe
$Qmv rgbgfx rgbgfx.exe
$Qmake CC=x86_64-w64-mingw32-gcc BISON=bison \
PKG_CONFIG=x86_64-w64-mingw32-pkg-config -j
wine-shim:
$Qecho '#!/bin/bash' > rgbshim.sh
$Qecho 'WINEDEBUG=-all wine $$0.exe "$${@:1}"' >> rgbshim.sh
$Qchmod +x rgbshim.sh
$Qln -s rgbshim.sh rgbasm
$Qln -s rgbshim.sh rgblink
$Qln -s rgbshim.sh rgbfix
$Qln -s rgbshim.sh rgbgfx
# Target for the project maintainer to produce distributable release tarballs
# of the source code.
dist:
$Qgit ls-files | sed s~^~$${PWD##*/}/~ \
| tar -czf rgbds-`git describe --tags | cut -c 2-`.tar.gz -C .. -T -
-157
View File
@@ -1,157 +0,0 @@
# RGBDS
RGBDS (Rednex Game Boy Development System) is a free assembler/linker package
for the Game Boy and Game Boy Color. It consists of:
- rgbasm (assembler)
- rgblink (linker)
- rgbfix (checksum/header fixer)
- rgbgfx (PNGtoGame Boy graphics converter)
This is a fork of the original RGBDS which aims to make the programs more like
other UNIX tools.
This toolchain is maintained on [GitHub](https://github.com/rednex/rgbds), as
well as its [documentation](https://github.com/rednex/rednex.github.io).
The documentation of this toolchain can be viewed online
[here](https://rednex.github.io/), it is generated from the man pages found in
this repository.
## 1. Installing RGBDS
### 1.1 Windows
Windows builds are available in the releases page on GitHub:
https://github.com/rednex/rgbds/releases
Copy the `.exe` files to `C:\Windows\` or similar.
If you require the latest version in development, it should be possible to
compile RGBDS with MinGW or Cygwin by following the instructions to build it
on UNIX systems.
### 1.2 macOS
You can build RGBDS by following the instructions below. However, if you would
prefer not to build RGBDS yourself, you may also install it using
[Homebrew](http://brew.sh/).
To install the latest release, use:
```sh
brew install rgbds
```
To install RGBDS with all of the current changes in development (as seen on the
`master` branch on GitHub), use:
```sh
brew install rgbds --HEAD
```
### 1.3 Other UNIX-like systems
No official binaries of RGBDS are distributed for these systems, you must follow
the simple instructions below to compile and install it.
## 2. Building RGBDS from source
RGBDS can be built in UNIX-like systems by following the instructions below.
### 2.1 Dependencies
RGBDS requires yacc, flex, libpng and pkg-config to be installed.
On macOS, install the latter two with [Homebrew](http://brew.sh/):
```sh
brew install libpng pkg-config
```
On other Unixes, use the built-in package manager. For example, on Debian or
Ubuntu:
```sh
sudo apt-get install byacc flex pkg-config libpng-dev
```
You can test if libpng and pkg-config are installed by running
`pkg-config --cflags libpng`: if the output is a path, then you're good, and if
it outputs an error then you need to install them via a package manager.
### 2.2 Build process
To build the programs, run in your terminal:
```sh
make
```
Then, to install the compiled programs and manual pages, run (with appropriate
privileges, e.g, with `sudo`):
```sh
make install
```
After installation, you can read the manuals with the `man` command. E.g.,
```sh
man 7 rgbds
```
There are some variables in the Makefile that can be redefined by the user. The
variables described below can affect installation behavior when given on the
make command line. For example, to install RGBDS in your home directory instead
of systemwide, run the following:
```sh
make install PREFIX=$HOME
```
To do a verbose build, run:
```sh
make Q=
```
This is the complete list of user-defined variables:
- `PREFIX`: Location where RGBDS will be installed. Defaults to `/usr/local`.
- `bindir`: Location where the binaries will be installed. Defaults to `${PREFIX}/bin`.
- `mandir`: Location where the manpages will be installed. Defaults to `${PREFIX}/man`.
- `DESTDIR`: This is prepended to all paths during the installation. It is
mainly used for packaging.
- `Q`: Whether to quiet the build or not. To make the build more verbose, clear
this variable. Defaults to `@`.
- `STRIP`: Whether to strip the installed binaries of debug symbols or not.
Defaults to `-s`.
- `BINMODE`: Permissions of the installed binaries. Defaults to `555`.
- `MANMODE`: Permissions of the installed manpages. Defaults to `444`.
## 3 History
- Around 1997, Carsten Sorensen (AKA SurfSmurf) writes ASMotor as a
general-purpose assembler/linker system for DOS/Win32
- Around 1999, Justin Lloyd (AKA Otaku no Zoku) adapts ASMotor to read and
produce GBZ80 assembly/machine code, and releases this version as RGBDS.
- 2009, Vegard Nossum adapts the code to be more UNIX-like and releases this
version as rgbds-linux on [GitHub](https://github.com/vegard/rgbds-linux).
- 2010, Anthony J. Bentley forks that repository. The fork becomes the reference
implementation of rgbds.
- 2017, Bentley's repository is moved to a neutral name.
+115
View File
@@ -0,0 +1,115 @@
RGBDS
=====
RGBDS (Rednex Game Boy Development System) is a free assembler/linker package
for the Game Boy and Game Boy Color. It consists of:
- rgbasm (assembler)
- rgblink (linker)
- rgbfix (checksum/header fixer)
- rgbgfx (PNGtoGame Boy graphics converter)
This is a fork of the original RGBDS which aims to make the programs more like
other UNIX tools.
This toolchain is maintained on `GitHub <https://github.com/rednex/rgbds>`__.
The documentation of this toolchain can be viewed online
`here <https://rgbds.gbdev.io/docs/>`__, it is generated from the man pages
found in this repository.
1. Installing RGBDS
-------------------
The `installation procedure <https://rgbds.gbdev.io/install>`__ is available
online for various platforms. `Building from source <https://rgbds.gbdev.io/install/source>`__
is possible using ``make`` or ``cmake``; follow the link for more detailed instructions.
.. code:: sh
make
sudo make install
.. code:: sh
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
cmake --install build
2. RGBDS Folder Organization
----------------------------
The RGBDS source code file structure somewhat resembles the following:
::
.
├── .github/
│   ├── actions/
│   │   └── ...
│   └── workflows/
│      └── ...
├── contrib/
│   ├── zsh_compl/
│   │   └── ...
│   └── ...
├── include/
│   └── ...
├── src/
│   ├── asm/
│   │   └── ...
│   ├── extern/
│   │   └── ...
│   ├── fix/
│   │   └── ...
│   ├── gfx/
│   │   └── ...
│   ├── link/
│   │   └── ...
│   ├── CMakeLists.txt
│   └── ...
├── test/
│   ├── ...
│ └── run-tests.sh
├── CMakeLists.txt
├── Makefile
└── README.rst
- ``.github/`` - files and scripts related to the integration of the RGBDS codebase with
GitHub.
- ``contrib/`` - scripts and other resources which may be useful to users and developers of
RGBDS.
* ``zsh_compl`` contains tab completion scripts for use with zsh. Put them somewhere in your ``fpath``, and they should auto-load.
- ``include/`` - header files for each respective C files in `src`.
- ``src/`` - source code and manual pages for RGBDS.
* Note that the code unique to each RGBDS tool is stored in its respective subdirectory
(rgbasm -> ``src/asm/``, for example). ``src/extern/`` contains code imported from external sources.
- ``test/`` - testing framework used to verify that changes to the code don't break or modify the behavior of RGBDS.
3. History
----------
- Around 1997, Carsten Sørensen (AKA SurfSmurf) writes ASMotor as a
general-purpose assembler/linker system for DOS/Win32
- Around 1999, Justin Lloyd (AKA Otaku no Zoku) adapts ASMotor to read and
produce GBZ80 assembly/machine code, and releases this version as RGBDS.
- 2009, Vegard Nossum adapts the code to be more UNIX-like and releases
this version as rgbds-linux on
`GitHub <https://github.com/vegard/rgbds-linux>`__.
- 2010, Anthony J. Bentley forks that repository. The fork becomes the reference
implementation of rgbds.
- 2017, Bentley's repository is moved to a neutral name.
- 2018, codebase relicensed under the MIT license.
- 2020, repository is moved to the `gbdev <https://github.com/gbdev>`__ organisation. The `rgbds.gbdev.io <https://rgbds.gbdev.io>`__ website serving documentation and downloads is created.
+73
View File
@@ -0,0 +1,73 @@
#!/bin/bash
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2020 Eldred Habert
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
STATE=0
diff <(xxd $1) <(xxd $2) | while read -r LINE; do
if [ $STATE -eq 0 ]; then
# Discard first line (line info)
STATE=1
elif [ "$LINE" = '---' ]; then
# Separator between files switches states
echo $LINE
STATE=3
elif grep -Eq '^[0-9]+(,[0-9]+)?[cd][0-9]+(,[0-9]+)?' <<< "$LINE"; then
# Line info resets the whole thing
STATE=1
elif [ $STATE -eq 1 -o $STATE -eq 3 ]; then
# Compute the GB address from the ROM offset
OFS=$(cut -d ' ' -f 2 <<< "$LINE" | tr -d ':')
BANK=$((0x$OFS / 0x4000))
ADDR=$((0x$OFS % 0x4000 + ($BANK != 0) * 0x4000))
# Try finding the preceding symbol closest to the diff
if [ $STATE -eq 1 ]; then
STATE=2
SYMFILE=${1%.*}.sym
else
STATE=4
SYMFILE=${2%.*}.sym
fi
EXTRA=$(if [ -f "$SYMFILE" ]; then
# Read the sym file for such a symbol
# Ignore comment lines, only pick matching bank
# (The bank regex ignores comments already, make `cut` and `tr` process less lines)
grep -Ei $(printf "^%02x:" $BANK) "$SYMFILE" |
cut -d ';' -f 1 |
tr -d "\r" |
while read -r SYMADDR SYM; do
SYMADDR=$((0x${SYMADDR#*:}))
if [ $SYMADDR -le $ADDR ]; then
printf " (%s+%#x)\n" "$SYM" $(($ADDR - $SYMADDR))
fi
# TODO: assumes sorted sym files
done | tail -n 1
fi)
printf "%02x:%04x %s\n" $BANK $ADDR $EXTRA
fi
if [ $STATE -eq 2 -o $STATE -eq 4 ]; then
OFS=$(cut -d ' ' -f 2 <<< "$LINE" | tr -d ':')
BANK=$((0x$OFS / 0x4000))
ADDR=$((0x$OFS % 0x4000 + ($BANK != 0) * 0x4000))
printf "%s %02x:%04x: %s\n" "${LINE:0:1}" $BANK $ADDR "${LINE#*: }"
fi
done
+49
View File
@@ -0,0 +1,49 @@
#compdef rgbasm
_rgbasm_warnings() {
local warnings=(
'error:Turn all warnings into errors'
'all:Enable most warning messages'
'extra:Enable extra, possibly unwanted, messages'
'everything:Enable literally everything'
'assert:Warn when WARN-type asserts fail'
'builtin-args:Report incorrect args to built-in funcs'
'div:Warn when dividing the smallest int by -1'
'empty-entry:Warn on empty entries in db, dw, dl args'
'large-constant:Warn on constants too large for a signed 32-bit int'
'long-string:Warn on strings too long'
'obsolete:Warn when using deprecated features'
'shift:Warn when shifting negative values'
'shift-amount:Warn when a shift'\''s operand it negative or \> 32'
'truncation:Warn when implicit truncations lose bits'
'user:Warn when executing the WARN built-in'
)
# TODO: handle `no-` and `error=` somehow?
_describe warning warnings
}
local args=(
# Arguments are listed here in the same order as in the manual, except for the version
'(- : * options)'{-V,--version}'[Print version number]'
'(-E --export-all)'{-E,--export-all}'[Export all symbols]'
'(-h --halt-without-nop)'{-h,--halt-without-nop}'[Avoid outputting a `nop` after `halt`]'
'(-L ---preserve-ld)'{-L,--preserve-ld}'[Prevent auto-optimizing `ld` into `ldh`]'
'(-v --verbose)'{-v,--verbose}'[Print additional messages regarding progression]'
-w'[Disable all warnings]'
'(-b --binary-digits)'{-b,--binary-digits}'+[Change chars for binary constants]:digit spec:'
'(-D --define)'{-D,--define}'+[Define a string symbol]:name + value (default 1):'
'(-g --gfx-chars)'{-g,--gfx-chars}'+[Change chars for gfx constants]:chars spec:'
'(-i --include)'{-i,--include}'+[Add an include directory]:include path:_files -/'
'(-M --dependfile)'{-M,--dependfile}"+[List deps in make format]:output file:_files -g '*.{d,mk}"
'(-o --output)'{-o,--output}'+[Output file]:output file:_files'
'(-p --pad-value)'{-p,--pad-value}'+[Set padding byte]:padding byte:'
'(-r --recursion-depth)'{-r,--recursion-depth}'+[Set maximum recursion depth]:depth:'
'(-W --warning)'{-W,--warning}'+[Toggle warning flags]:warning flag:_rgbasm_warnings'
'*'":assembly sources:_files -g '*.asm'"
)
_arguments -s -S : $args
+25
View File
@@ -0,0 +1,25 @@
#compdef rgbfix
local args=(
# Arguments are listed here in the same order as in the manual, except for the version
'(- : * options)'{-V,--version}'[Print version number]'
'(-C --color-only)'{-C,--color-only}'[Mark ROM as GBC-only]'
'(-c --color-compatible)'{-c,--color-compatible}'[Mark ROM as GBC-compatible]'
'(-j --non-japanese)'{-j,--non-japanese}'[Set the non-Japanese region flag]'
'(-s --sgb-compatible)'{-s,--sgb-compatible}'[Set the SGB flag]'
'(-f --fix-spec -v --validate)'{-v,--validate}'[Shorthand for -f lhg]'
'(-f --fix-spec -v --validate)'{-f,--fix-spec}'+[Fix or trash some header values]:fix spec:'
'(-i --game-id)'{-i,--game-id}'+[Set game ID string]:4-char game ID:'
'(-k --new-licensee)'{-k,--new-licensee}'+[Set new licensee string]:2-char licensee ID:'
'(-l --old-licensee)'{-l,--old-licensee}'+[Set old licensee ID]:licensee number:'
'(-m --mbc-type)'{-m,--mbc-type}'+[Set MBC flags]:mbc flags byte:'
'(-n --rom-version)'{-n,--rom-version}'+[Set ROM version]:rom version byte:'
'(-p --pad-value)'{-p,--pad-value}'+[Pad to next valid size using this byte as padding]:padding byte:'
'(-r --ram-size)'{-r,--ram-size}'+[Set RAM size]:ram size byte:'
'(-t --title)'{-t,--title}'+[Set title string]:11-char title string:'
'*'":ROM files:_files -g '*.{gb,sgb,gbc}'"
)
_arguments -s -S : $args
+37
View File
@@ -0,0 +1,37 @@
#compdef rgbgfx
_depths() {
local depths=(
'1:1bpp'
'2:2bpp (native)'
)
_describe 'bit depth' depths
}
local args=(
# Arguments are listed here in the same order as in the manual, except for the version
'(- : * options)'{-V,--version}'[Print version number]'
'(-a --attr-map -A --output-attr-map)'{-A,--output-attr-map}'[Shortcut for -a <file>.attrmap]'
'(-C --color-curve)'{-C,--color-curve}'[Generate palettes using GBC color curve]'
'(-D --debug)'{-D,--debug}'[Enable debug features]'
'(-f --fix -F --fix-and-save)'{-f,--fix}'[Fix input PNG into an indexed image]'
'(-f --fix -F --fix-and-save)'{-F,--fix-and-save}'[Like -f but also save CLI params within the PNG]'
'(-h --horizontal)'{-h,--horizontal}'[Lay out tiles horizontally instead of vertically]'
'(-m --mirror-tiles)'{-m,--mirror-tiles}'[Eliminate mirrored tiles from output]'
'(-p --palette -P --output-palette)'{-P,--output-palette}'[Shortcut for -p <file>.pal]'
'(-t --tilemap -T --output-tilemap)'{-T,--output-tilemap}'[Shortcut for -t <file>.tilemap]'
'(-u --unique-tiles)'{-u,--unique-tiles}'[Eliminate redundant tiles]'
'(-v --verbose)'{-v,--verbose}'[Enable verbose output]'
'(-a --attr-map -A --output-attr-map)'{-a,--attr-map}'+[Generate a map of tile attributes (mirroring)]:attrmap file:_files'
'(-d --depth)'{-d,--depth}'+[Set bit depth]:bit depth:_depths'
'(-o --output)'{-o,--output}'+[Set output file]:output file:_files'
'(-p --palette -P --output-palette)'{-p,--palette}"+[Output the image's palette in little-endian native RGB555 format]:palette file:_files"
'(-t --tilemap -T --output-tilemap)'{-t,--tilemap}'+[Generate a map of tile indices]:tilemap file:_files'
'(-x --trim-end)'{-x,--trim-end}'+[Trim end of output by this many tiles]:tile count:'
'*'":input png files:_files -g '*.png'"
)
_arguments -s -S : $args
+22
View File
@@ -0,0 +1,22 @@
#compdef rgblink
local args=(
# Arguments are listed here in the same order as in the manual, except for the version
'(- : * options)'{-V,--version}'[Print version number]'
'(-d --dmg)'{-d,--dmg}'[Enable DMG mode (-w + no VRAM banking)]'
'(-t --tiny)'{-t,--tiny}'[Enable tiny mode, disabling ROM banking]'
'(-v --verbose)'{-v,--verbose}'[Enable verbose output]'
'(-w --wramx)'{-w,--wramx}'[Disable WRAM banking]'
'(-l --linkerscript)'{-l,--linkerscript}"+[Use a linker script]:linker script:_files -g '*.link'"
'(-m --map)'{-m,--map}"+[Produce a map file]:map file:_files -g '*.map'"
'(-n --sym)'(-n,--sym)"+[Produce a symbol file]:sym file:_files -g '*.sym'"
'(-O --overlay)'{-O,--overlay}'+[Overlay sections over on top of bin file]:base overlay:_files'
'(-o --output)'{-o,--output}"+[Write ROM image to this file]:rom file:_files -g '*.{gb,sgb,gbc}'"
'(-p --pad-value)'{-p,--pad-value}'+[Set padding byte]:padding byte:'
'(-s --smart)'{-s,--smart}'+[!BROKEN! Perform smart linking from this symbol]:symbol name:'
'*'":object files:_files -g '*.o'"
)
_arguments -s -S : $args
-40
View File
@@ -1,40 +0,0 @@
/* asm.h
*
* Contains some assembler-wide defines and externs
*
* Copyright 1997 Carsten Sorensen
*
*/
#ifndef RGBDS_ASM_ASM_H
#define RGBDS_ASM_ASM_H
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "types.h"
#include "asm/symbol.h"
#include "asm/localasm.h"
#define MAXUNIONS 128
#define MAXMACROARGS 256
#define MAXINCPATHS 128
extern SLONG nLineNo;
extern ULONG nTotalLines;
extern ULONG nPC;
extern ULONG nPass;
extern ULONG nIFDepth;
extern bool skipElif;
extern ULONG nUnionDepth;
extern ULONG unionStart[MAXUNIONS];
extern ULONG unionSize[MAXUNIONS];
extern char tzCurrentFileName[_MAX_PATH + 1];
extern struct Section *pCurrentSection;
extern struct sSymbol *tHashedSymbols[HASHSIZE];
extern struct sSymbol *pPCSymbol;
extern bool oDontExpandStrings;
#endif /* // ASM_H */
+17 -13
View File
@@ -1,18 +1,22 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_ASM_CHARMAP_H
#define RGBDS_ASM_CHARMAP_H
#define MAXCHARMAPS 512
#define CHARMAPLENGTH 16
#include <stdint.h>
struct Charmap {
int count;
char input[MAXCHARMAPS][CHARMAPLENGTH + 1];
char output[MAXCHARMAPS];
};
struct Charmap *charmap_New(const char *name, const char *baseName);
void charmap_Delete(struct Charmap *charmap);
void charmap_Set(const char *name);
void charmap_Push(void);
void charmap_Pop(void);
void charmap_Add(char *mapping, uint8_t value);
size_t charmap_Convert(char const *input, uint8_t *output);
int readUTF8Char(char *destination, char *source);
void charmap_Sort();
int charmap_Add(char *input, UBYTE output);
int charmap_Convert(char **input);
#endif
#endif /* RGBDS_ASM_CHARMAP_H */
+31
View File
@@ -0,0 +1,31 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2021, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_ASM_FIXPOINT_H
#define RGBDS_ASM_FIXPOINT_H
#include <stdint.h>
int32_t fix_Callback_PI(void);
void fix_Print(int32_t i);
int32_t fix_Sin(int32_t i);
int32_t fix_Cos(int32_t i);
int32_t fix_Tan(int32_t i);
int32_t fix_ASin(int32_t i);
int32_t fix_ACos(int32_t i);
int32_t fix_ATan(int32_t i);
int32_t fix_ATan2(int32_t i, int32_t j);
int32_t fix_Mul(int32_t i, int32_t j);
int32_t fix_Div(int32_t i, int32_t j);
int32_t fix_Pow(int32_t i, int32_t j);
int32_t fix_Log(int32_t i, int32_t j);
int32_t fix_Round(int32_t i);
int32_t fix_Ceil(int32_t i);
int32_t fix_Floor(int32_t i);
#endif /* RGBDS_ASM_FIXPOINT_H */
+63
View File
@@ -0,0 +1,63 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2020, RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_FORMAT_SPEC_H
#define RGBDS_FORMAT_SPEC_H
#include <stdint.h>
#include <stdbool.h>
enum FormatState {
FORMAT_SIGN, // expects '+' or ' ' (optional)
FORMAT_PREFIX, // expects '#' (optional)
FORMAT_ALIGN, // expects '-' (optional)
FORMAT_WIDTH, // expects '0'-'9', max 255 (optional) (leading '0' indicates pad)
FORMAT_FRAC, // got '.', expects '0'-'9', max 255 (optional)
FORMAT_DONE, // got [duXxbofs] (required)
FORMAT_INVALID, // got unexpected character
};
struct FormatSpec {
enum FormatState state;
int sign;
bool prefix;
bool alignLeft;
bool padZero;
uint8_t width;
bool hasFrac;
uint8_t fracWidth;
int type;
bool valid;
};
struct StrFmtArg {
union {
uint32_t number;
char *string;
};
bool isNumeric;
};
#define INITIAL_STRFMT_ARG_SIZE 4
struct StrFmtArgList {
char *format;
size_t nbArgs;
size_t capacity;
struct StrFmtArg *args;
};
struct FormatSpec fmt_NewSpec(void);
bool fmt_IsEmpty(struct FormatSpec const *fmt);
bool fmt_IsValid(struct FormatSpec const *fmt);
bool fmt_IsFinished(struct FormatSpec const *fmt);
void fmt_UseCharacter(struct FormatSpec *fmt, int c);
void fmt_FinishCharacters(struct FormatSpec *fmt);
void fmt_PrintString(char *buf, size_t bufLen, struct FormatSpec const *fmt, char const *value);
void fmt_PrintNumber(char *buf, size_t bufLen, struct FormatSpec const *fmt, uint32_t value);
#endif /* RGBDS_FORMAT_SPEC_H */
+67 -32
View File
@@ -1,48 +1,83 @@
/* fstack.h
/*
* This file is part of RGBDS.
*
* Contains some assembler-wide defines and externs
*
* Copyright 1997 Carsten Sorensen
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
/*
* Contains some assembler-wide defines and externs
*/
#ifndef RGBDS_ASM_FSTACK_H
#define RGBDS_ASM_FSTACK_H
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "asm/asm.h"
#include "types.h"
#include "asm/lexer.h"
struct sContext {
YY_BUFFER_STATE FlexHandle;
struct sSymbol *pMacro;
struct sContext *pNext;
char tzFileName[_MAX_PATH + 1];
char *tzMacroArgs[MAXMACROARGS + 1];
SLONG nLine;
ULONG nStatus;
FILE *pFile;
char *pREPTBlock;
ULONG nREPTBlockCount;
ULONG nREPTBlockSize;
#include "types.h"
struct FileStackNode {
struct FileStackNode *parent; /* Pointer to parent node, for error reporting */
/* Line at which the parent context was exited; meaningless for the root level */
uint32_t lineNo;
struct FileStackNode *next; /* Next node in the output linked list */
bool referenced; /* If referenced, don't free! */
uint32_t ID; /* Set only if referenced: ID within the object file, -1 if not output yet */
enum {
NODE_REPT,
NODE_FILE,
NODE_MACRO,
} type;
};
void
fstk_RunInclude(char *);
extern void fstk_RunMacroArg(SLONG s);
void
fstk_Init(char *);
extern void fstk_Dump(void);
extern void fstk_AddIncludePath(char *s);
extern ULONG fstk_RunMacro(char *s);
extern void fstk_RunRept(ULONG count);
FILE *
fstk_FindFile(char *);
struct FileStackReptNode { /* NODE_REPT */
struct FileStackNode node;
uint32_t reptDepth;
/* WARNING: if changing this type, change overflow check in `fstk_Init` */
uint32_t iters[]; /* REPT iteration counts since last named node, in reverse depth order */
};
int fstk_GetLine(void);
struct FileStackNamedNode { /* NODE_FILE, NODE_MACRO */
struct FileStackNode node;
char name[]; /* File name for files, file::macro name for macros */
};
extern int yywrap(void);
extern size_t nMaxRecursionDepth;
#endif
struct MacroArgs;
void fstk_Dump(struct FileStackNode const *node, uint32_t lineNo);
void fstk_DumpCurrent(void);
struct FileStackNode *fstk_GetFileStack(void);
/* The lifetime of the returned chars is until reaching the end of that file */
char const *fstk_GetFileName(void);
void fstk_AddIncludePath(char const *s);
/**
* @param path The user-provided file name
* @param fullPath The address of a pointer, which will be made to point at the full path
* The pointer's value must be a valid argument to `realloc`, including NULL
* @param size Current size of the buffer, or 0 if the pointer is NULL
* @return True if the file was found, false if no path worked
*/
bool fstk_FindFile(char const *path, char **fullPath, size_t *size);
bool yywrap(void);
void fstk_RunInclude(char const *path);
void fstk_RunMacro(char const *macroName, struct MacroArgs *args);
void fstk_RunRept(uint32_t count, int32_t nReptLineNo, char *body, size_t size);
void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
int32_t reptLineNo, char *body, size_t size);
void fstk_StopRept(void);
bool fstk_Break(void);
void fstk_Init(char const *mainPath, size_t maxRecursionDepth);
#endif /* RGBDS_ASM_FSTACK_H */
+89 -53
View File
@@ -1,65 +1,101 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_ASM_LEXER_H
#define RGBDS_ASM_LEXER_H
#include <stdio.h>
#include <stdbool.h>
#include "types.h"
#define MAXSTRLEN 255
#define LEXHASHSIZE (1 << 11)
#define MAXSTRLEN 255
struct LexerState;
extern struct LexerState *lexerState;
extern struct LexerState *lexerStateEOL;
struct sLexInitString {
char *tzName;
ULONG nToken;
static inline struct LexerState *lexer_GetState(void)
{
return lexerState;
}
static inline void lexer_SetState(struct LexerState *state)
{
lexerState = state;
}
static inline void lexer_SetStateAtEOL(struct LexerState *state)
{
lexerStateEOL = state;
}
extern char binDigits[2];
extern char gfxDigits[4];
static inline void lexer_SetBinDigits(char const digits[2])
{
binDigits[0] = digits[0];
binDigits[1] = digits[1];
}
static inline void lexer_SetGfxDigits(char const digits[4])
{
gfxDigits[0] = digits[0];
gfxDigits[1] = digits[1];
gfxDigits[2] = digits[2];
gfxDigits[3] = digits[3];
}
/*
* `path` is referenced, but not held onto..!
*/
struct LexerState *lexer_OpenFile(char const *path);
struct LexerState *lexer_OpenFileView(char *buf, size_t size, uint32_t lineNo);
void lexer_RestartRept(uint32_t lineNo);
void lexer_DeleteState(struct LexerState *state);
void lexer_Init(void);
enum LexerMode {
LEXER_NORMAL,
LEXER_RAW,
LEXER_SKIP_TO_ELIF,
LEXER_SKIP_TO_ENDC,
LEXER_SKIP_TO_ENDR
};
struct sLexFloat {
ULONG(*Callback) (char *s, ULONG size);
ULONG nToken;
void lexer_SetMode(enum LexerMode mode);
void lexer_ToggleStringExpansion(bool enable);
uint32_t lexer_GetIFDepth(void);
void lexer_IncIFDepth(void);
void lexer_DecIFDepth(void);
bool lexer_RanIFBlock(void);
bool lexer_ReachedELSEBlock(void);
void lexer_RunIFBlock(void);
void lexer_ReachELSEBlock(void);
struct CaptureBody {
uint32_t lineNo;
char *body;
size_t size;
};
struct yy_buffer_state {
char *pBufferRealStart; // actual starting address
char *pBufferStart; // address where the data is initially written
// after the "safety margin"
char *pBuffer;
ULONG nBufferSize;
ULONG oAtLineStart;
char const *lexer_GetFileName(void);
uint32_t lexer_GetLineNo(void);
uint32_t lexer_GetColNo(void);
void lexer_DumpStringExpansions(void);
int yylex(void);
void lexer_CaptureRept(struct CaptureBody *capture);
void lexer_CaptureMacroBody(struct CaptureBody *capture);
#define INITIAL_DS_ARG_SIZE 2
struct DsArgList {
size_t nbArgs;
size_t capacity;
struct Expression *args;
};
enum eLexerState {
LEX_STATE_NORMAL,
LEX_STATE_MACROARGS
};
#define INITIAL 0
#define macroarg 3
typedef struct yy_buffer_state *YY_BUFFER_STATE;
extern void yy_set_state(enum eLexerState i);
extern YY_BUFFER_STATE yy_create_buffer(FILE * f);
extern YY_BUFFER_STATE yy_scan_bytes(char *mem, ULONG size);
extern void yy_delete_buffer(YY_BUFFER_STATE);
extern void yy_switch_to_buffer(YY_BUFFER_STATE);
extern ULONG lex_FloatAlloc(struct sLexFloat * tok);
extern void lex_FloatAddRange(ULONG id, UWORD start, UWORD end);
extern void lex_FloatDeleteRange(ULONG id, UWORD start, UWORD end);
extern void lex_FloatAddFirstRange(ULONG id, UWORD start, UWORD end);
extern void lex_FloatDeleteFirstRange(ULONG id, UWORD start, UWORD end);
extern void lex_FloatAddSecondRange(ULONG id, UWORD start, UWORD end);
extern void lex_FloatDeleteSecondRange(ULONG id, UWORD start, UWORD end);
extern void lex_Init(void);
extern void lex_AddStrings(struct sLexInitString * lex);
extern void lex_SetBuffer(char *buffer, ULONG len);
extern ULONG yylex(void);
extern void yyunput(char c);
extern void yyunputstr(char *s);
extern void yyskipbytes(ULONG count);
extern void yyunputbytes(ULONG count);
extern YY_BUFFER_STATE pCurrentBuffer;
extern void upperstring(char *s);
extern void lowerstring(char *s);
#endif
#endif /* RGBDS_ASM_LEXER_H */
-132
View File
@@ -1,132 +0,0 @@
/* GB Z80 instruction groups
n3 = 3-bit
n = 8-bit
nn = 16-bit
* ADC A,n : 0xCE
* ADC A,r : 0x88|r
* ADD A,n : 0xC6
* ADD A,r : 0x80|r
* ADD HL,ss : 0x09|(ss<<4)
* ADD SP,n : 0xE8
* AND A,n : 0xE6
* AND A,r : 0xA0|r
* BIT n3,r : 0xCB 0x40|(n3<<3)|r
* CALL cc,nn : 0xC4|(cc<<3)
* CALL nn : 0xCD
* CCF : 0x3F
* CP A,n : 0xFE
* CP A,r : 0xB8|r
* CPL : 0x2F
* DAA : 0x27
* DEC r : 0x05|(r<<3)
* DEC ss : 0x0B|(ss<<4)
* DI : 0xF3
* EI : 0xFB
* HALT : 0x76
* INC r : 0x04|(r<<3)
* INC ss : 0x03|(ss<<4)
* JP HL : 0xE9
* JP cc,nn : 0xC2|(cc<<3)
* JP nn : 0xC3|(cc<<3)
* JR n : 0x18
* JR cc,n : 0x20|(cc<<3)
* LD (nn),SP : 0x08
* LD ($FF00+C),A : 0xE2
* LD ($FF00+n),A : 0xE0
* LD (nn),A : 0xEA
* LD (rr),A : 0x02|(rr<<4) // HL+ and HL- included
* LD A,($FF00+C) : 0xF2
* LD A,($FF00+n) : 0xF0
* LD A,(nn) : 0xFA
* LD A,(rr) : 0x0A|(rr<<4) // HL+ and HL- included
* LD HL,SP+n : 0xF8
* LD SP,HL : 0xF9
* LD r,n : 0x06|(r<<3)
* LD r,r' : 0x40|(r<<3)|r' // NOTE: LD (HL),(HL) not allowed
* LD ss,nn : 0x01|(ss<<4)
* NOP : 0x00
* OR A,n : 0xF6
* OR A,r : 0xB0|r
* POP tt : 0xC1|(tt<<4)
* PUSH tt : 0xC5|(tt<<4)
* RES n3,r : 0xCB 0x80|(n3<<3)|r
* RET : 0xC9
* RET cc : 0xC0|(cc<<3)
* RETI : 0xD9
* RL r : 0xCB 0x10|r
* RLA : 0x17
* RLC r : 0xCB 0x00|r
* RLCA : 0x07
* RR r : 0xCB 0x18|r
* RRA : 0x1F
* RRC r : 0xCB 0x08|r
* RRCA : 0x0F
* RST n : 0xC7|n
* SBC A,n : 0xDE
* SBC A,r : 0x98|r
* SCF : 0x37
* SET n3,r : 0xCB 0xC0|(n8<<3)|r
* SLA r : 0xCB 0x20|r
* SRA r : 0xCB 0x28|r
* SRL r : 0xCB 0x38|r
* STOP : 0x10 0x00
* SUB A,n : 0xD6
* SUB A,r : 0x90|r
* SWAP r : 0xCB 0x30|r
* XOR A,n : 0xEE
* XOR A,r : 0xA8|r
*/
#define NAME_DB "db"
#define NAME_DW "dw"
#define NAME_RB "rb"
#define NAME_RW "rw"
/* "r" defs */
enum {
REG_B = 0,
REG_C,
REG_D,
REG_E,
REG_H,
REG_L,
REG_HL_IND,
REG_A
};
/* "rr" defs */
enum {
REG_BC_IND = 0,
REG_DE_IND,
REG_HL_INDINC,
REG_HL_INDDEC,
};
/* "ss" defs */
enum {
REG_BC = 0,
REG_DE,
REG_HL,
REG_SP
};
/* "tt" defs */
/*
#define REG_BC 0
#define REG_DE 1
#define REG_HL 2
*/
#define REG_AF 3
/* "cc" defs */
enum {
CC_NZ = 0,
CC_Z,
CC_NC,
CC_C
};
+37
View File
@@ -0,0 +1,37 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2020, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_MACRO_H
#define RGBDS_MACRO_H
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "asm/warning.h"
#include "helpers.h"
struct MacroArgs;
struct MacroArgs *macro_GetCurrentArgs(void);
struct MacroArgs *macro_NewArgs(void);
void macro_AppendArg(struct MacroArgs **args, char *s);
void macro_UseNewArgs(struct MacroArgs *args);
void macro_FreeArgs(struct MacroArgs *args);
char const *macro_GetArg(uint32_t i);
char *macro_GetAllArgs(void);
uint32_t macro_GetUniqueID(void);
char const *macro_GetUniqueIDStr(void);
void macro_SetUniqueID(uint32_t id);
uint32_t macro_UseNewUniqueID(void);
void macro_ShiftCurrentArgs(int32_t count);
uint32_t macro_NbArgs(void);
#endif
+27 -47
View File
@@ -1,57 +1,37 @@
#ifndef RGBDS_MAIN_H
#define RGBDS_MAIN_H
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2021, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_MAIN_H
#define RGBDS_MAIN_H
#include <stdbool.h>
#include "extern/stdnoreturn.h"
#include <stdint.h>
#include <stdio.h>
struct sOptions {
char gbgfx[4];
char binary[2];
SLONG fillchar;
bool verbose;
bool haltnop;
bool exportall;
bool warnings; /* true to enable warnings, false to disable them. */
//-1 == random
};
#include "helpers.h"
extern char *tzNewMacro;
extern ULONG ulNewMacroSize;
extern SLONG nGBGfxID;
extern SLONG nBinaryID;
extern bool haltnop;
extern bool optimizeloads;
extern bool verbose;
extern bool warnings; /* True to enable warnings, false to disable them. */
extern struct sOptions DefaultOptions;
extern struct sOptions CurrentOptions;
extern void opt_Push(void);
extern void opt_Pop(void);
extern void opt_Parse(char *s);
extern FILE *dependfile;
extern char *tzTargetFileName;
extern bool oGeneratedMissingIncludes;
extern bool oFailedOnMissingInclude;
extern bool oGeneratePhonyDeps;
/*
* Used for errors that compromise the whole assembly process by affecting the
* folliwing code, potencially making the assembler generate errors caused by
* the first one and unrelated to the code that the assembler complains about.
* It is also used when the assembler goes into an invalid state (for example,
* when it fails to allocate memory).
*/
noreturn void fatalerror(const char *fmt, ...);
/*
* Used for errors that make it impossible to assemble correctly, but don't
* affect the following code. The code will fail to assemble but the user will
* get a list of all errors at the end, making it easier to fix all of them at
* once.
*/
void yyerror(const char *fmt, ...);
/*
* Used to warn the user about problems that don't prevent the generation of
* valid code.
*/
void warning(const char *fmt, ...);
/* TODO: are these really needed? */
#define YY_FATAL_ERROR fatalerror
#define YY_FATAL_ERROR fatalerror
#ifdef YYLMAX
#undef YYLMAX
#ifdef YYLMAX
#undef YYLMAX
#endif
#define YYLMAX 65536
#endif
#endif /* RGBDS_MAIN_H */
-61
View File
@@ -1,61 +0,0 @@
#ifndef RGBDS_ASM_LINK_H
#define RGBDS_ASM_LINK_H
enum {
RPN_ADD = 0,
RPN_SUB,
RPN_MUL,
RPN_DIV,
RPN_MOD,
RPN_UNSUB,
RPN_OR,
RPN_AND,
RPN_XOR,
RPN_UNNOT,
RPN_LOGAND,
RPN_LOGOR,
RPN_LOGUNNOT,
RPN_LOGEQ,
RPN_LOGNE,
RPN_LOGGT,
RPN_LOGLT,
RPN_LOGGE,
RPN_LOGLE,
RPN_SHL,
RPN_SHR,
RPN_BANK,
RPN_HRAM,
RPN_CONST = 0x80,
RPN_SYM = 0x81
};
enum {
SECT_WRAM0 = 0,
SECT_VRAM,
SECT_ROMX,
SECT_ROM0,
SECT_HRAM,
SECT_WRAMX,
SECT_SRAM,
SECT_OAM
};
enum {
SYM_LOCAL = 0,
SYM_IMPORT,
SYM_EXPORT
};
enum {
PATCH_BYTE = 0,
PATCH_WORD_L,
PATCH_LONG_L
};
#endif
-21
View File
@@ -1,21 +0,0 @@
#ifndef RGBDS_ASM_MATH_H
#define RGBDS_ASM_MATH_H
#include "types.h"
void math_DefinePI(void);
void math_Print(SLONG i);
SLONG math_Sin(SLONG i);
SLONG math_Cos(SLONG i);
SLONG math_Tan(SLONG i);
SLONG math_ASin(SLONG i);
SLONG math_ACos(SLONG i);
SLONG math_ATan(SLONG i);
SLONG math_ATan2(SLONG i, SLONG j);
SLONG math_Mul(SLONG i, SLONG j);
SLONG math_Div(SLONG i, SLONG j);
SLONG math_Round(SLONG i);
SLONG math_Ceil(SLONG i);
SLONG math_Floor(SLONG i);
#endif
+22
View File
@@ -0,0 +1,22 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2021, Eldred Habert and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_OPT_H
#define RGBDS_OPT_H
void opt_B(char chars[2]);
void opt_G(char chars[4]);
void opt_P(uint8_t fill);
void opt_Parse(char const *option);
void opt_Push(void);
void opt_Pop(void);
#endif
+22 -32
View File
@@ -1,40 +1,30 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_ASM_OUTPUT_H
#define RGBDS_ASM_OUTPUT_H
#include "asm/rpn.h"
#include "types.h"
#include <stdint.h>
struct Section {
char *pzName;
UBYTE nType;
ULONG nPC;
ULONG nOrg;
ULONG nBank;
ULONG nAlign;
struct Section *pNext;
struct Patch *pPatches;
struct Charmap *charmap;
UBYTE *tData;
};
#include "linkdefs.h"
void out_PrepPass2(void);
struct Expression;
struct FileStackNode;
extern char *tzObjectname;
extern struct Section *pSectionList, *pCurrentSection;
void out_RegisterNode(struct FileStackNode *node);
void out_ReplaceNode(struct FileStackNode *node);
void out_SetFileName(char *s);
void out_NewSection(char *pzName, ULONG secttype);
void out_NewAbsSection(char *pzName, ULONG secttype, SLONG org, SLONG bank);
void out_NewAlignedSection(char *pzName, ULONG secttype, SLONG alignment, SLONG bank);
void out_AbsByte(int b);
void out_AbsByteGroup(char *s, int length);
void out_RelByte(struct Expression * expr);
void out_RelWord(struct Expression * expr);
void out_PCRelByte(struct Expression * expr);
void out_CreatePatch(uint32_t type, struct Expression const *expr, uint32_t ofs, uint32_t pcShift);
bool out_CreateAssert(enum AssertionType type, struct Expression const *expr,
char const *message, uint32_t ofs);
void out_WriteObject(void);
void out_Skip(int skip);
void out_BinaryFile(char *s);
void out_BinaryFileSlice(char *s, SLONG start_pos, SLONG length);
void out_String(char *s);
void out_AbsLong(SLONG b);
void out_RelLong(struct Expression * expr);
void out_PushSection(void);
void out_PopSection(void);
#endif
#endif /* RGBDS_ASM_OUTPUT_H */
+59 -74
View File
@@ -1,81 +1,66 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_ASM_RPN_H
#define RGBDS_ASM_RPN_H
#include <stdint.h>
#include <stdbool.h>
#include "linkdefs.h"
#define MAXRPNLEN 1048576
struct Expression {
SLONG nVal;
UBYTE tRPN[256];
ULONG nRPNLength;
ULONG nRPNOut;
ULONG isReloc;
ULONG isPCRel;
int32_t nVal; // If the expression's value is known, it's here
char *reason; // Why the expression is not known, if it isn't
bool isKnown; // Whether the expression's value is known
bool isSymbol; // Whether the expression represents a symbol
uint8_t *tRPN; // Array of bytes serializing the RPN expression
uint32_t nRPNCapacity; // Size of the `tRPN` buffer
uint32_t nRPNLength; // Used size of the `tRPN` buffer
uint32_t nRPNPatchSize; // Size the expression will take in the obj file
};
ULONG rpn_isReloc(struct Expression * expr);
ULONG rpn_isPCRelative(struct Expression * expr);
void rpn_Symbol(struct Expression * expr, char *tzSym);
void rpn_Number(struct Expression * expr, ULONG i);
void rpn_LOGNOT(struct Expression * expr, struct Expression * src1);
void
rpn_LOGOR(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_LOGAND(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_LOGEQU(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_LOGGT(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_LOGLT(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_LOGGE(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_LOGLE(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_LOGNE(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_ADD(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_SUB(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_XOR(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_OR(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_AND(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_SHL(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_SHR(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_MUL(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_DIV(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
rpn_MOD(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void rpn_HIGH(struct Expression * expr, struct Expression * src);
void rpn_LOW(struct Expression * expr, struct Expression * src);
void rpn_UNNEG(struct Expression * expr, struct Expression * src);
void rpn_UNNOT(struct Expression * expr, struct Expression * src);
UWORD rpn_PopByte(struct Expression * expr);
void rpn_Bank(struct Expression * expr, char *tzSym);
void rpn_Reset(struct Expression * expr);
void rpn_CheckHRAM(struct Expression * expr, struct Expression * src1);
/*
* Determines if an expression is known at assembly time
*/
static inline bool rpn_isKnown(const struct Expression *expr)
{
return expr->isKnown;
}
#endif
/*
* Determines if an expression is a symbol suitable for const diffing
*/
static inline bool rpn_isSymbol(const struct Expression *expr)
{
return expr->isSymbol;
}
void rpn_Symbol(struct Expression *expr, char const *tzSym);
void rpn_Number(struct Expression *expr, uint32_t i);
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src);
struct Symbol const *rpn_SymbolOf(struct Expression const *expr);
bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym);
void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
const struct Expression *src1,
const struct Expression *src2);
void rpn_HIGH(struct Expression *expr, const struct Expression *src);
void rpn_LOW(struct Expression *expr, const struct Expression *src);
void rpn_ISCONST(struct Expression *expr, const struct Expression *src);
void rpn_UNNEG(struct Expression *expr, const struct Expression *src);
void rpn_UNNOT(struct Expression *expr, const struct Expression *src);
void rpn_BankSymbol(struct Expression *expr, char const *tzSym);
void rpn_BankSection(struct Expression *expr, char const *tzSectionName);
void rpn_BankSelf(struct Expression *expr);
void rpn_Free(struct Expression *expr);
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src);
void rpn_CheckRST(struct Expression *expr, const struct Expression *src);
#endif /* RGBDS_ASM_RPN_H */
+79
View File
@@ -0,0 +1,79 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2020, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_SECTION_H
#define RGBDS_SECTION_H
#include <stdint.h>
#include <stdbool.h>
#include "linkdefs.h"
extern uint8_t fillByte;
struct Expression;
struct Section {
char *name;
enum SectionType type;
enum SectionModifier modifier;
struct FileStackNode *src; /* Where the section was defined */
uint32_t fileLine; /* Line where the section was defined */
uint32_t size;
uint32_t org;
uint32_t bank;
uint8_t align;
uint16_t alignOfs;
struct Section *next;
struct Patch *patches;
uint8_t *data;
};
struct SectionSpec {
uint32_t bank;
uint8_t alignment;
uint16_t alignOfs;
};
struct Section *out_FindSectionByName(const char *name);
void out_NewSection(char const *name, uint32_t secttype, uint32_t org,
struct SectionSpec const *attributes,
enum SectionModifier mod);
void out_SetLoadSection(char const *name, uint32_t secttype, uint32_t org,
struct SectionSpec const *attributes,
enum SectionModifier mod);
void out_EndLoadSection(void);
struct Section *sect_GetSymbolSection(void);
uint32_t sect_GetSymbolOffset(void);
uint32_t sect_GetOutputOffset(void);
void sect_AlignPC(uint8_t alignment, uint16_t offset);
void sect_StartUnion(void);
void sect_NextUnionMember(void);
void sect_EndUnion(void);
void sect_CheckUnionClosed(void);
void out_AbsByte(uint8_t b);
void out_AbsByteGroup(uint8_t const *s, int32_t length);
void out_AbsWordGroup(uint8_t const *s, int32_t length);
void out_AbsLongGroup(uint8_t const *s, int32_t length);
void out_Skip(int32_t skip, bool ds);
void out_String(char const *s);
void out_RelByte(struct Expression *expr, uint32_t pcShift);
void out_RelBytes(uint32_t n, struct Expression *exprs, size_t size);
void out_RelWord(struct Expression *expr, uint32_t pcShift);
void out_RelLong(struct Expression *expr, uint32_t pcShift);
void out_PCRelByte(struct Expression *expr, uint32_t pcShift);
void out_BinaryFile(char const *s, int32_t startPos);
void out_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length);
void out_PushSection(void);
void out_PopSection(void);
#endif
+143 -68
View File
@@ -1,77 +1,152 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2020, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_SYMBOL_H
#define RGBDS_SYMBOL_H
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include "asm/section.h"
#include "platform.h" // MIN_NB_ELMS
#include "types.h"
#define HASHSIZE (1 << 16)
#define MAXSYMLEN 256
#define HASHSIZE (1 << 16)
#define MAXSYMLEN 256
struct sSymbol {
char tzName[MAXSYMLEN + 1];
SLONG nValue;
ULONG nType;
struct sSymbol *pScope;
struct sSymbol *pNext;
struct Section *pSection;
ULONG ulMacroSize;
char *pMacro;
SLONG(*Callback) (struct sSymbol *);
char tzFileName[_MAX_PATH + 1]; /* File where the symbol was defined. */
ULONG nFileLine; /* Line where the symbol was defined. */
enum SymbolType {
SYM_LABEL,
SYM_EQU,
SYM_SET,
SYM_MACRO,
SYM_EQUS,
SYM_REF // Forward reference to a label
};
#define SYMF_RELOC 0x001 /* symbol will be reloc'ed during
* linking, it's absolute value is
* unknown */
#define SYMF_EQU 0x002 /* symbol is defined using EQU, will
* not be changed during linking */
#define SYMF_SET 0x004 /* symbol is (re)defined using SET,
* will not be changed during linking */
#define SYMF_EXPORT 0x008 /* symbol should be exported */
#define SYMF_IMPORT 0x010 /* symbol is imported, it's value is
* unknown */
#define SYMF_LOCAL 0x020 /* symbol is a local symbol */
#define SYMF_DEFINED 0x040 /* symbol has been defined, not only
* referenced */
#define SYMF_MACRO 0x080 /* symbol is a macro */
#define SYMF_STRING 0x100 /* symbol is a stringsymbol */
#define SYMF_CONST 0x200 /* symbol has a constant value, will
* not be changed during linking */
ULONG calchash(char *s);
void sym_SetExportAll(BBOOL set);
void sym_PrepPass1(void);
void sym_PrepPass2(void);
void sym_AddLocalReloc(char *tzSym);
void sym_AddReloc(char *tzSym);
void sym_Export(char *tzSym);
void sym_PrintSymbolTable(void);
struct sSymbol *sym_FindMacro(char *s);
void sym_InitNewMacroArgs(void);
void sym_AddNewMacroArg(char *s);
void sym_SaveCurrentMacroArgs(char *save[]);
void sym_RestoreCurrentMacroArgs(char *save[]);
void sym_UseNewMacroArgs(void);
void sym_FreeCurrentMacroArgs(void);
void sym_AddEqu(char *tzSym, SLONG value);
void sym_AddSet(char *tzSym, SLONG value);
void sym_Init(void);
ULONG sym_GetConstantValue(char *s);
ULONG sym_isConstant(char *s);
struct sSymbol *sym_FindSymbol(char *tzName);
void sym_Global(char *tzSym);
char *sym_FindMacroArg(SLONG i);
char *sym_GetStringValue(char *tzSym);
void sym_UseCurrentMacroArgs(void);
void sym_SetMacroArgID(ULONG nMacroCount);
ULONG sym_isString(char *tzSym);
void sym_AddMacro(char *tzSym);
void sym_ShiftCurrentMacroArgs(void);
void sym_AddString(char *tzSym, char *tzValue);
ULONG sym_GetValue(char *s);
ULONG sym_GetDefinedValue(char *s);
ULONG sym_isDefined(char *tzName);
void sym_Purge(char *tzName);
ULONG sym_isConstDefined(char *tzName);
int sym_IsRelocDiffDefined(char *tzSym1, char *tzSym2);
struct Symbol {
char name[MAXSYMLEN + 1];
enum SymbolType type;
bool isExported; /* Whether the symbol is to be exported */
bool isBuiltin; /* Whether the symbol is a built-in */
struct Section *section;
struct FileStackNode *src; /* Where the symbol was defined */
uint32_t fileLine; /* Line where the symbol was defined */
#endif
bool hasCallback;
union {
/* If sym_IsNumeric */
int32_t value;
int32_t (*numCallback)(void);
/* For SYM_MACRO */
struct {
size_t macroSize;
char *macro;
};
/* For SYM_EQUS, TODO: separate "base" fields from SYM_MACRO */
char const *(*strCallback)(void); /* For SYM_EQUS */
};
uint32_t ID; /* ID of the symbol in the object file (-1 if none) */
struct Symbol *next; /* Next object to output in the object file */
};
bool sym_IsPC(struct Symbol const *sym);
static inline bool sym_IsDefined(struct Symbol const *sym)
{
return sym->type != SYM_REF;
}
static inline struct Section *sym_GetSection(struct Symbol const *sym)
{
return sym_IsPC(sym) ? sect_GetSymbolSection() : sym->section;
}
static inline bool sym_IsConstant(struct Symbol const *sym)
{
if (sym->type == SYM_LABEL) {
struct Section const *sect = sym_GetSection(sym);
return sect && sect->org != (uint32_t)-1;
}
return sym->type == SYM_EQU || sym->type == SYM_SET;
}
static inline bool sym_IsNumeric(struct Symbol const *sym)
{
return sym->type == SYM_LABEL || sym->type == SYM_EQU
|| sym->type == SYM_SET;
}
static inline bool sym_IsLabel(struct Symbol const *sym)
{
return sym->type == SYM_LABEL || sym->type == SYM_REF;
}
static inline bool sym_IsLocal(struct Symbol const *sym)
{
return sym_IsLabel(sym) && strchr(sym->name, '.');
}
static inline bool sym_IsExported(struct Symbol const *sym)
{
return sym->isExported;
}
/*
* Get a string equate's value
*/
static inline char const *sym_GetStringValue(struct Symbol const *sym)
{
if (sym->hasCallback)
return sym->strCallback();
return sym->macro;
}
void sym_ForEach(void (*func)(struct Symbol *, void *), void *arg);
int32_t sym_GetValue(struct Symbol const *sym);
void sym_SetExportAll(bool set);
struct Symbol *sym_AddLocalLabel(char const *symName);
struct Symbol *sym_AddLabel(char const *symName);
struct Symbol *sym_AddAnonLabel(void);
void sym_WriteAnonLabelName(char buf[MIN_NB_ELMS(MAXSYMLEN + 1)], uint32_t ofs, bool neg);
void sym_Export(char const *symName);
struct Symbol *sym_AddEqu(char const *symName, int32_t value);
struct Symbol *sym_AddSet(char const *symName, int32_t value);
uint32_t sym_GetPCValue(void);
uint32_t sym_GetConstantSymValue(struct Symbol const *sym);
uint32_t sym_GetConstantValue(char const *s);
/*
* Find a symbol by exact name, bypassing expansion checks
*/
struct Symbol *sym_FindExactSymbol(char const *name);
/*
* Find a symbol by exact name; may not be scoped, produces an error if it is
*/
struct Symbol *sym_FindUnscopedSymbol(char const *name);
/*
* Find a symbol, possibly scoped, by name
*/
struct Symbol *sym_FindScopedSymbol(char const *name);
struct Symbol const *sym_GetPC(void);
struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, size_t size);
struct Symbol *sym_Ref(char const *symName);
struct Symbol *sym_AddString(char const *symName, char const *value);
struct Symbol *sym_RedefString(char const *symName, char const *value);
void sym_Purge(char const *symName);
void sym_Init(time_t now);
/* Functions to save and restore the current symbol scope. */
char const *sym_GetCurrentSymbolScope(void);
void sym_SetCurrentSymbolScope(char const *newScope);
#endif /* RGBDS_SYMBOL_H */
+21
View File
@@ -0,0 +1,21 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2019, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_UTIL_H
#define RGBDS_UTIL_H
#include <stdint.h>
uint32_t calchash(const char *s);
char const *print(int c);
/*
* @return The number of bytes read, or 0 if invalid data was found
*/
size_t readUTF8Char(uint8_t *dest, char const *src);
#endif /* RGBDS_UTIL_H */
+70
View File
@@ -0,0 +1,70 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2019, Eldred Habert and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef WARNING_H
#define WARNING_H
#include "helpers.h"
extern unsigned int nbErrors;
enum WarningID {
WARNING_ASSERT, /* Assertions */
WARNING_BUILTIN_ARG, /* Invalid args to builtins */
WARNING_CHARMAP_REDEF, /* Charmap entry re-definition */
WARNING_DIV, /* Division undefined behavior */
WARNING_EMPTY_DATA_DIRECTIVE, /* `db`, `dw` or `dl` directive without data in ROM */
WARNING_EMPTY_MACRO_ARG, /* Empty macro argument */
WARNING_EMPTY_STRRPL, /* Empty second argument in `STRRPL` */
WARNING_LARGE_CONSTANT, /* Constants too large */
WARNING_LONG_STR, /* String too long for internal buffers */
WARNING_MACRO_SHIFT, /* Shift past available arguments in macro */
WARNING_NESTED_COMMENT, /* Comment-start delimiter in a block comment */
WARNING_OBSOLETE, /* Obsolete things */
WARNING_SHIFT, /* Shifting undefined behavior */
WARNING_SHIFT_AMOUNT, /* Strange shift amount */
WARNING_TRUNCATION, /* Implicit truncation loses some bits */
WARNING_USER, /* User warnings */
NB_WARNINGS,
/* Warnings past this point are "meta" warnings */
WARNING_ALL = NB_WARNINGS,
WARNING_EXTRA,
WARNING_EVERYTHING,
NB_WARNINGS_ALL
#define NB_META_WARNINGS (NB_WARNINGS_ALL - NB_WARNINGS)
};
void processWarningFlag(char const *flag);
/*
* Used to warn the user about problems that don't prevent the generation of
* valid code.
*/
void warning(enum WarningID id, const char *fmt, ...) format_(printf, 2, 3);
/*
* Used for errors that compromise the whole assembly process by affecting the
* following code, potencially making the assembler generate errors caused by
* the first one and unrelated to the code that the assembler complains about.
* It is also used when the assembler goes into an invalid state (for example,
* when it fails to allocate memory).
*/
_Noreturn void fatalerror(const char *fmt, ...) format_(printf, 1, 2);
/*
* Used for errors that make it impossible to assemble correctly, but don't
* affect the following code. The code will fail to assemble but the user will
* get a list of all errors at the end, making it easier to fix all of them at
* once.
*/
void error(const char *fmt, ...) format_(printf, 1, 2);
#endif
-6
View File
@@ -1,6 +0,0 @@
#ifndef RGBDS_COMMON_H
#define RGBDS_COMMON_H
#define RGBDS_OBJECT_VERSION_STRING "RGB5"
#endif /* RGBDS_COMMON_H */
+23 -12
View File
@@ -1,12 +1,23 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef EXTERN_ERR_H
#define EXTERN_ERR_H
#ifdef ERR_IN_LIBC
#include <err.h>
#else
#else /* ERR_IN_LIBC */
#include <stdarg.h>
#include "extern/stdnoreturn.h"
#include "helpers.h"
#define warn rgbds_warn
#define vwarn rgbds_vwarn
@@ -18,16 +29,16 @@
#define errx rgbds_errx
#define verrx rgbds_verrx
void warn(const char *, ...);
void vwarn(const char *, va_list);
void warnx(const char *, ...);
void vwarnx(const char *, va_list);
void warn(const char *fmt, ...) format_(printf, 1, 2);
void vwarn(const char *fmt, va_list ap) format_(printf, 1, 0);
void warnx(const char *fmt, ...) format_(printf, 1, 2);
void vwarnx(const char *fmt, va_list ap) format_(printf, 1, 0);
noreturn void err(int, const char *, ...);
noreturn void verr(int, const char *, va_list);
noreturn void errx(int, const char *, ...);
noreturn void verrx(int, const char *, va_list);
_Noreturn void err(int status, const char *fmt, ...) format_(printf, 2, 3);
_Noreturn void verr(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
_Noreturn void errx(int status, const char *fmt, ...) format_(printf, 2, 3);
_Noreturn void verrx(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
#endif
#endif /* ERR_IN_LIBC */
#endif
#endif /* EXTERN_ERR_H */
+45
View File
@@ -0,0 +1,45 @@
/*
* Copyright © 2005-2020 Rich Felker, et al.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* This implementation was taken from musl and modified for RGBDS */
#ifndef RGBDS_EXTERN_GETOPT_H
#define RGBDS_EXTERN_GETOPT_H
extern char *musl_optarg;
extern int musl_optind, musl_opterr, musl_optopt, musl_optreset;
struct option {
const char *name;
int has_arg;
int *flag;
int val;
};
int musl_getopt_long_only(int, char **, const char *, const struct option *, int *);
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#endif
-14
View File
@@ -1,14 +0,0 @@
#ifndef EXTERN_REALLOCARRAY_H
#define EXTERN_REALLOCARRAY_H
#ifdef REALLOCARRAY_IN_LIBC
#include <stdlib.h>
#else
#define reallocarray rgbds_reallocarray
void *reallocarray(void *, size_t, size_t);
#endif
#endif
-16
View File
@@ -1,16 +0,0 @@
#if __STDC_VERSION__ >= 201112L
/* C11 or newer */
#define noreturn _Noreturn
#elif __cplusplus >= 201103L
/* C++11 or newer */
#define noreturn [[noreturn]]
#elif __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ >= 5))
/* GCC 2.5 or newer */
#define noreturn __attribute__ ((noreturn))
#elif _MSC_VER >= 1310
/* MS Visual Studio 2003/.NET Framework 1.1 or newer */
#define noreturn _declspec( noreturn)
#else
/* unsupported, but no need to throw a fit */
#define noreturn
#endif
-13
View File
@@ -1,13 +0,0 @@
#ifndef STRL_H
#define STRL_H
#ifdef STRL_IN_LIBC
#include <string.h>
#else
#define strlcpy rgbds_strlcpy
#define strlcat rgbds_strlcat
size_t strlcpy(char *, const char *, size_t);
size_t strlcat(char *, const char *, size_t);
#endif
#endif
+14
View File
@@ -0,0 +1,14 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2018, Antonio Nino Diaz and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef EXTERN_UTF8DECODER_H
#define EXTERN_UTF8DECODER_H
uint32_t decode(uint32_t *state, uint32_t *codep, uint8_t byte);
#endif /* EXTERN_UTF8DECODER_H */
-21
View File
@@ -1,21 +0,0 @@
/*
* Copyright (C) 2017 Antonio Nino Diaz <antonio_nd@outlook.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define PACKAGE_VERSION_MAJOR (0)
#define PACKAGE_VERSION_MINOR (3)
#define PACKAGE_VERSION_PATCH (2)
const char * get_package_version_string(void);
+23 -17
View File
@@ -1,17 +1,9 @@
/*
* Copyright © 2013 stag019 <stag019@gmail.com>
* This file is part of RGBDS.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* Copyright (c) 2013-2018, stag019 and RGBDS contributors.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_GFX_GB_H
@@ -20,11 +12,25 @@
#include <stdint.h>
#include "gfx/main.h"
void png_to_gb(struct PNGImage png, struct GBImage *gb);
void output_file(struct Options opts, struct GBImage gb);
int get_tile_index(uint8_t *tile, uint8_t **tiles, int num_tiles, int tile_size);
void create_tilemap(struct Options opts, struct GBImage *gb, struct Tilemap *tilemap);
void output_tilemap_file(struct Options opts, struct Tilemap tilemap);
void output_palette_file(struct Options opts, struct PNGImage png);
#define XFLIP 0x40
#define YFLIP 0x20
void raw_to_gb(const struct RawIndexedImage *raw_image, struct GBImage *gb);
void output_file(const struct Options *opts, const struct GBImage *gb);
int get_tile_index(uint8_t *tile, uint8_t **tiles, int num_tiles,
int tile_size);
uint8_t reverse_bits(uint8_t b);
void xflip(uint8_t *tile, uint8_t *tile_xflip, int tile_size);
void yflip(uint8_t *tile, uint8_t *tile_yflip, int tile_size);
int get_mirrored_tile_index(uint8_t *tile, uint8_t **tiles, int num_tiles,
int tile_size, int *flags);
void create_mapfiles(const struct Options *opts, struct GBImage *gb,
struct Mapfile *tilemap, struct Mapfile *attrmap);
void output_tilemap_file(const struct Options *opts,
const struct Mapfile *tilemap);
void output_attrmap_file(const struct Options *opts,
const struct Mapfile *attrmap);
void output_palette_file(const struct Options *opts,
const struct RawIndexedImage *raw_image);
#endif
+38 -22
View File
@@ -1,17 +1,9 @@
/*
* Copyright © 2013 stag019 <stag019@gmail.com>
* This file is part of RGBDS.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* Copyright (c) 2013-2018, stag019 and RGBDS contributors.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_GFX_MAIN_H
@@ -29,30 +21,54 @@ struct Options {
bool hardfix;
bool fix;
bool horizontal;
bool mirror;
bool unique;
bool colorcurve;
int trim;
char *mapfile;
bool mapout;
char *tilemapfile;
bool tilemapout;
char *attrmapfile;
bool attrmapout;
char *palfile;
bool palout;
char *outfile;
char *infile;
};
struct RGBColor {
uint8_t red;
uint8_t green;
uint8_t blue;
};
struct ImageOptions {
bool horizontal;
int trim;
char *tilemapfile;
bool tilemapout;
char *attrmapfile;
bool attrmapout;
char *palfile;
bool palout;
};
struct PNGImage {
png_struct *png;
png_info *info;
png_byte **data;
int width;
int height;
png_byte depth;
png_byte type;
bool horizontal;
int trim;
char *mapfile;
bool mapout;
char *palfile;
bool palout;
};
struct RawIndexedImage {
uint8_t **data;
struct RGBColor *palette;
int num_colors;
unsigned int width;
unsigned int height;
};
struct GBImage {
@@ -62,14 +78,14 @@ struct GBImage {
int trim;
};
struct Tilemap {
struct Mapfile {
uint8_t *data;
int size;
};
int depth, colors;
extern int depth, colors;
#include "gfx/makepng.h"
#include "gfx/gb.h"
#endif
#endif /* RGBDS_GFX_MAIN_H */
+10 -17
View File
@@ -1,17 +1,9 @@
/*
* Copyright © 2013 stag019 <stag019@gmail.com>
* This file is part of RGBDS.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* Copyright (c) 2013-2018, stag019 and RGBDS contributors.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_GFX_PNG_H
@@ -19,10 +11,11 @@
#include "gfx/main.h"
void input_png_file(struct Options opts, struct PNGImage *img);
void get_text(struct PNGImage *png);
void set_text(struct PNGImage *png);
void output_png_file(struct Options opts, struct PNGImage *png);
void free_png_data(struct PNGImage *png);
struct RawIndexedImage *input_png_file(const struct Options *opts,
struct ImageOptions *png_options);
void output_png_file(const struct Options *opts,
const struct ImageOptions *png_options,
const struct RawIndexedImage *raw_image);
void destroy_raw_image(struct RawIndexedImage **raw_image_ptr_ptr);
#endif
#endif /* RGBDS_GFX_PNG_H */
+79
View File
@@ -0,0 +1,79 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2019, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
/* Generic hashmap implementation (C++ templates are calling...) */
#ifndef RGBDS_LINK_HASHMAP_H
#define RGBDS_LINK_HASHMAP_H
#include <assert.h>
#include <stdbool.h>
#define HASH_NB_BITS 32
#define HALF_HASH_NB_BITS 16
static_assert(HALF_HASH_NB_BITS * 2 == HASH_NB_BITS, "");
#define HASHMAP_NB_BUCKETS (1 << HALF_HASH_NB_BITS)
/* HashMapEntry is internal, please do not attempt to use it */
typedef struct HashMapEntry *HashMap[HASHMAP_NB_BUCKETS];
/**
* Adds an element to a hashmap.
* @warning Adding a new element with an already-present key will not cause an
* error, this must be handled externally.
* @warning Inserting a NULL will make `hash_GetElement`'s return ambiguous!
* @param map The HashMap to add the element to
* @param key The key with which the element will be stored and retrieved
* @param element The element to add
* @return True if a collision occurred (for statistics)
*/
bool hash_AddElement(HashMap map, char const *key, void *element);
/**
* Replaces an element with an already-present key in a hashmap.
* @warning Inserting a NULL will make `hash_GetElement`'s return ambiguous!
* @param map The HashMap to replace the element in
* @param key The key with which the element will be stored and retrieved
* @param element The element to replace
* @return True if the element was found and replaced
*/
bool hash_ReplaceElement(HashMap const map, char const *key, void *element);
/**
* Removes an element from a hashmap.
* @param map The HashMap to remove the element from
* @param key The key to search the element with
* @return True if the element was found and removed
*/
bool hash_RemoveElement(HashMap map, char const *key);
/**
* Finds an element in a hashmap.
* @param map The map to consider the elements of
* @param key The key to search an element for
* @return A pointer to the element, or NULL if not found. (NULL can be returned
* if such an element was added, but that sounds pretty silly.)
*/
void *hash_GetElement(HashMap const map, char const *key);
/**
* Executes a function on each element in a hashmap.
* @param map The map to consider the elements of
* @param func The function to run. The first argument will be the element,
* the second will be `arg`.
* @param arg An argument to be passed to all function calls
*/
void hash_ForEach(HashMap const map, void (*func)(void *, void *), void *arg);
/**
* Cleanly empties a hashmap from its contents.
* This does not `free` the data structure itself!
* @param map The map to empty
*/
void hash_EmptyMap(HashMap map);
#endif /* RGBDS_LINK_HASHMAP_H */
+91
View File
@@ -0,0 +1,91 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2014-2020, RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef HELPERS_H
#define HELPERS_H
// Of course, MSVC does not support C11, so no _Noreturn there...
#ifdef _MSC_VER
#define _Noreturn __declspec(noreturn)
#endif
// Ideally, we'd use `__has_attribute` and `__has_builtin`, but these were only introduced in GCC 9
#ifdef __GNUC__ // GCC or compatible
#define format_(archetype, str_index, first_arg) \
__attribute__ ((format (archetype, str_index, first_arg)))
// In release builds, define "unreachable" as such, but trap in debug builds
#ifdef NDEBUG
#define unreachable_ __builtin_unreachable
#else
#define unreachable_ __builtin_trap
#endif
#else
// Unsupported, but no need to throw a fit
#define format_(archetype, str_index, first_arg)
// This seems to generate similar code to __builtin_unreachable, despite different semantics
// Note that executing this is undefined behavior (declared _Noreturn, but does return)
static inline _Noreturn unreachable_(void) {}
#endif
// Use builtins whenever possible, and shim them otherwise
#ifdef __GNUC__ // GCC or compatible
#define ctz __builtin_ctz
#define clz __builtin_clz
#elif defined(_MSC_VER)
#include <assert.h>
#include <intrin.h>
#pragma intrinsic(_BitScanReverse, _BitScanForward)
static inline int ctz(unsigned int x)
{
unsigned long cnt;
assert(x != 0);
_BitScanForward(&cnt, x);
return cnt;
}
static inline int clz(unsigned int x)
{
unsigned long cnt;
assert(x != 0);
_BitScanReverse(&cnt, x);
return 31 - cnt;
}
#else
// FIXME: these are rarely used, and need testing...
#include <limits.h>
static inline int ctz(unsigned int x)
{
int cnt = 0;
while (!(x & 1)) {
x >>= 1;
cnt++;
}
return cnt;
}
static inline int clz(unsigned int x)
{
int cnt = 0;
while (x <= UINT_MAX / 2) {
x <<= 1;
cnt++;
}
return cnt;
}
#endif
// Macros for stringification
#define STR(x) #x
#define EXPAND_AND_STR(x) STR(x)
#endif /* HELPERS_H */
+20 -43
View File
@@ -1,50 +1,27 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2019, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
/* Assigning all sections a place */
#ifndef RGBDS_LINK_ASSIGN_H
#define RGBDS_LINK_ASSIGN_H
#include "mylink.h"
#include "types.h"
#include <stdint.h>
enum eBankCount {
BANK_COUNT_ROM0 = 1,
BANK_COUNT_ROMX = 511,
BANK_COUNT_WRAM0 = 1,
BANK_COUNT_WRAMX = 7,
BANK_COUNT_VRAM = 2,
BANK_COUNT_OAM = 1,
BANK_COUNT_HRAM = 1,
BANK_COUNT_SRAM = 16
};
extern uint64_t nbSectionsToAssign;
enum eBankDefine {
BANK_ROM0 = 0,
BANK_ROMX = BANK_ROM0 + BANK_COUNT_ROM0,
BANK_WRAM0 = BANK_ROMX + BANK_COUNT_ROMX,
BANK_WRAMX = BANK_WRAM0 + BANK_COUNT_WRAM0,
BANK_VRAM = BANK_WRAMX + BANK_COUNT_WRAMX,
BANK_OAM = BANK_VRAM + BANK_COUNT_VRAM,
BANK_HRAM = BANK_OAM + BANK_COUNT_OAM,
BANK_SRAM = BANK_HRAM + BANK_COUNT_HRAM
};
/**
* Assigns all sections a slice of the address space
*/
void assign_AssignSections(void);
#define MAXBANKS (BANK_COUNT_ROM0 + BANK_COUNT_ROMX + BANK_COUNT_WRAM0 + BANK_COUNT_WRAMX \
+ BANK_COUNT_VRAM + BANK_COUNT_OAM + BANK_COUNT_HRAM + BANK_COUNT_SRAM)
/**
* `free`s all assignment memory that was allocated.
*/
void assign_Cleanup(void);
extern SLONG area_Avail(SLONG bank);
extern void AssignSections(void);
extern void CreateSymbolTable(void);
extern SLONG MaxBankUsed;
extern SLONG MaxAvail[MAXBANKS];
int
IsSectionNameInUse(const char *name);
void
SetLinkerscriptName(char *tzLinkerscriptFile);
int
IsSectionSameTypeBankAndFloating(const char *name, enum eSectionType type, int bank);
unsigned int
AssignSectionAddressAndBankByName(const char *name, unsigned int address, int bank);
#endif
#endif /* RGBDS_LINK_ASSIGN_H */
-6
View File
@@ -1,6 +0,0 @@
#ifndef RGBDS_LINK_LIBRARY_H
#define RGBDS_LINK_LIBRARY_H
extern void AddNeededModules(void);
#endif
+81 -4
View File
@@ -1,9 +1,86 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2019, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
/* Declarations that all modules use, as well as `main` and related */
#ifndef RGBDS_LINK_MAIN_H
#define RGBDS_LINK_MAIN_H
#include "types.h"
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
extern SLONG fillchar;
extern char *smartlinkstartsymbol;
#include "helpers.h"
#endif
/* Variables related to CLI options */
extern bool isDmgMode;
extern char *linkerScriptName;
extern char const *mapFileName;
extern char const *symFileName;
extern char const *overlayFileName;
extern char const *outputFileName;
extern uint8_t padValue;
extern bool is32kMode;
extern bool beVerbose;
extern bool isWRA0Mode;
extern bool disablePadding;
struct FileStackNode {
struct FileStackNode *parent;
/* Line at which the parent context was exited; meaningless for the root level */
uint32_t lineNo;
enum {
NODE_REPT,
NODE_FILE,
NODE_MACRO,
} type;
union {
char *name; /* NODE_FILE, NODE_MACRO */
struct { /* NODE_REPT */
uint32_t reptDepth;
uint32_t *iters;
};
};
};
/* Helper macro for printing verbose-mode messages */
#define verbosePrint(...) do { \
if (beVerbose) \
fprintf(stderr, __VA_ARGS__); \
} while (0)
/**
* Dump a file stack to stderr
* @param node The leaf node to dump the context of
*/
char const *dumpFileStack(struct FileStackNode const *node);
void warning(struct FileStackNode const *where, uint32_t lineNo,
char const *fmt, ...) format_(printf, 3, 4);
void error(struct FileStackNode const *where, uint32_t lineNo,
char const *fmt, ...) format_(printf, 3, 4);
_Noreturn void fatal(struct FileStackNode const *where, uint32_t lineNo,
char const *fmt, ...) format_(printf, 3, 4);
/**
* Opens a file if specified, and aborts on error.
* @param fileName The name of the file to open; if NULL, no file will be opened
* @param mode The mode to open the file with
* @return A pointer to a valid FILE structure, or NULL if fileName was NULL
*/
FILE *openFile(char const *fileName, char const *mode);
#define closeFile(file) do { \
FILE *tmp = file; \
if (tmp) \
fclose(tmp); \
} while (0)
#endif /* RGBDS_LINK_MAIN_H */
-11
View File
@@ -1,11 +0,0 @@
#ifndef RGBDS_LINK_MAPFILE_H
#define RGBDS_LINK_MAPFILE_H
extern void SetMapfileName(char *name);
extern void SetSymfileName(char *name);
extern void CloseMapfile(void);
extern void MapfileWriteSection(struct sSection * pSect);
extern void MapfileInitBank(SLONG bank);
extern void MapfileCloseBank(SLONG slack);
#endif
-117
View File
@@ -1,117 +0,0 @@
#ifndef RGBDS_LINK_LINK_H
#define RGBDS_LINK_LINK_H
#ifndef _MAX_PATH
#define _MAX_PATH 512
#endif
#include "types.h"
extern SLONG options;
#define OPT_TINY 0x01
#define OPT_SMART_C_LINK 0x02
#define OPT_OVERLAY 0x04
#define OPT_CONTWRAM 0x08
#define OPT_DMG_MODE 0x10
enum eRpnData {
RPN_ADD = 0,
RPN_SUB,
RPN_MUL,
RPN_DIV,
RPN_MOD,
RPN_UNSUB,
RPN_OR,
RPN_AND,
RPN_XOR,
RPN_UNNOT,
RPN_LOGAND,
RPN_LOGOR,
RPN_LOGUNNOT,
RPN_LOGEQ,
RPN_LOGNE,
RPN_LOGGT,
RPN_LOGLT,
RPN_LOGGE,
RPN_LOGLE,
RPN_SHL,
RPN_SHR,
RPN_BANK,
RPN_HRAM,
RPN_CONST = 0x80,
RPN_SYM = 0x81
};
enum eSectionType {
SECT_WRAM0,
SECT_VRAM,
SECT_ROMX,
SECT_ROM0,
SECT_HRAM,
SECT_WRAMX,
SECT_SRAM,
SECT_OAM
};
struct sSection {
SLONG nBank;
SLONG nOrg;
SLONG nAlign;
BBOOL oAssigned;
char *pzName;
SLONG nByteSize;
enum eSectionType Type;
UBYTE *pData;
SLONG nNumberOfSymbols;
struct sSymbol **tSymbols;
struct sPatch *pPatches;
struct sSection *pNext;
};
enum eSymbolType {
SYM_LOCAL,
SYM_IMPORT,
SYM_EXPORT
};
struct sSymbol {
char *pzName;
enum eSymbolType Type;
/* the following 3 items only valid when Type!=SYM_IMPORT */
SLONG nSectionID; /* internal to object.c */
struct sSection *pSection;
SLONG nOffset;
char *pzObjFileName; /* Object file where the symbol is located. */
char *pzFileName; /* Source file where the symbol was defined. */
ULONG nFileLine; /* Line where the symbol was defined. */
};
enum ePatchType {
PATCH_BYTE = 0,
PATCH_WORD_L,
PATCH_LONG_L
};
struct sPatch {
char *pzFilename;
SLONG nLineNo;
SLONG nOffset;
enum ePatchType Type;
SLONG nRPNSize;
UBYTE *pRPN;
struct sPatch *pNext;
BBOOL oRelocPatch;
};
extern struct sSection *pSections;
extern struct sSection *pLibSections;
#endif
+40 -4
View File
@@ -1,6 +1,42 @@
#ifndef RGBDS_LINK_OBJECT_H
#define RGBDS_LINK_OBJECT_H
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2019, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
extern void obj_Readfile(char *tzObjectfile);
/* Declarations related to processing of object (.o) files */
#endif
#ifndef RGBDS_LINK_OBJECT_H
#define RGBDS_LINK_OBJECT_H
/**
* Read an object (.o) file, and add its info to the data structures.
* @param fileName A path to the object file to be read
* @param i The ID of the file
*/
void obj_ReadFile(char const *fileName, unsigned int i);
/**
* Perform validation on the object files' contents
*/
void obj_DoSanityChecks(void);
/**
* Evaluate all assertions
*/
void obj_CheckAssertions(void);
/**
* Sets up object file reading
* @param nbFiles The number of object files that will be read
*/
void obj_Setup(unsigned int nbFiles);
/**
* `free`s all object memory that was allocated.
*/
void obj_Cleanup(void);
#endif /* RGBDS_LINK_OBJECT_H */
+33 -6
View File
@@ -1,8 +1,35 @@
#ifndef RGBDS_LINK_OUTPUT_H
#define RGBDS_LINK_OUTPUT_H
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2019, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
void out_Setname(char *tzOutputfile);
void out_SetOverlayname(char *tzOverlayfile);
void Output(void);
/* Outputting the result of linking */
#ifndef RGBDS_LINK_OUTPUT_H
#define RGBDS_LINK_OUTPUT_H
#endif
#include <stdint.h>
#include "link/section.h"
/**
* Registers a section for output.
* @param section The section to add
*/
void out_AddSection(struct Section const *section);
/**
* Finds an assigned section overlapping another one.
* @param section The section that is being overlapped
* @return A section overlapping it
*/
struct Section const *out_OverlappingSection(struct Section const *section);
/**
* Writes all output (bin, sym, map) files.
*/
void out_WriteFiles(void);
#endif /* RGBDS_LINK_OUTPUT_H */
+39 -4
View File
@@ -1,9 +1,44 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2019, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
/* Applying patches to SECTIONs */
#ifndef RGBDS_LINK_PATCH_H
#define RGBDS_LINK_PATCH_H
#include "types.h"
#include <stdbool.h>
#include <stdint.h>
void Patch(void);
extern SLONG nPC;
#include "link/section.h"
#endif
#include "linkdefs.h"
struct Assertion {
struct Patch patch;
// enum AssertionType type; The `patch`'s field is instead re-used
char *message;
/*
* This would be redundant with `.section->fileSymbols`... but
* `section` is sometimes NULL!
*/
struct Symbol **fileSymbols;
struct Assertion *next;
};
/**
* Checks all assertions
* @return true if assertion failed
*/
void patch_CheckAssertions(struct Assertion *assertion);
/**
* Applies all SECTIONs' patches to them
*/
void patch_ApplyPatches(void);
#endif /* RGBDS_LINK_PATCH_H */
+22 -23
View File
@@ -1,37 +1,36 @@
/*
* Copyright (C) 2017 Antonio Nino Diaz <antonio_nd@outlook.com>
* This file is part of RGBDS.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* Copyright (c) 1997-2019, Carsten Sorensen and RGBDS contributors.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* SPDX-License-Identifier: MIT
*/
/* Parsing a linker script */
#ifndef RGBDS_LINK_SCRIPT_H
#define RGBDS_LINK_SCRIPT_H
#include "extern/stdnoreturn.h"
#include <stdint.h>
noreturn void script_fatalerror(const char *fmt, ...);
extern FILE * linkerScript;
void script_Parse(const char *path);
struct SectionPlacement {
struct Section *section;
uint16_t org;
uint32_t bank;
};
void script_IncludeFile(const char *path);
int script_IncludeDepthGet(void);
void script_IncludePop(void);
extern uint64_t script_lineNo;
void script_InitSections(void);
void script_SetCurrentSectionType(const char *type, unsigned int bank);
void script_SetAddress(unsigned int addr);
void script_SetAlignment(unsigned int alignment);
void script_OutputSection(const char *section_name);
/**
* Parses the linker script to return the next section constraint
* @return A pointer to a struct, or NULL on EOF. The pointer shouldn't be freed
*/
struct SectionPlacement *script_NextSection(void);
#endif
/**
* `free`s all assignment memory that was allocated.
*/
void script_Cleanup(void);
#endif /* RGBDS_LINK_SCRIPT_H */
+100
View File
@@ -0,0 +1,100 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2019, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
/* Declarations manipulating symbols */
#ifndef RGBDS_LINK_SECTION_H
#define RGBDS_LINK_SECTION_H
/* GUIDELINE: external code MUST NOT BE AWARE of the data structure used!! */
#include <stdint.h>
#include <stdbool.h>
#include "link/main.h"
#include "linkdefs.h"
struct FileStackNode;
struct Section;
struct AttachedSymbol {
struct Symbol *symbol;
struct AttachedSymbol *next;
};
struct Patch {
struct FileStackNode const *src;
uint32_t lineNo;
uint32_t offset;
uint32_t pcSectionID;
uint32_t pcOffset;
enum PatchType type;
uint32_t rpnSize;
uint8_t *rpnExpression;
struct Section const *pcSection;
};
struct Section {
/* Info contained in the object files */
char *name;
uint16_t size;
uint16_t offset;
enum SectionType type;
enum SectionModifier modifier;
bool isAddressFixed;
uint16_t org;
bool isBankFixed;
uint32_t bank;
bool isAlignFixed;
uint16_t alignMask;
uint16_t alignOfs;
uint8_t *data; /* Array of size `size`*/
uint32_t nbPatches;
struct Patch *patches;
/* Extra info computed during linking */
struct Symbol **fileSymbols;
uint32_t nbSymbols;
struct Symbol const **symbols;
struct Section *nextu; /* The next "component" of this unionized sect */
};
/*
* Execute a callback for each section currently registered.
* This is to avoid exposing the data structure in which sections are stored.
* @param callback The function to call for each structure;
* the first argument will be a pointer to the structure,
* the second argument will be the pointer `arg`.
* @param arg A pointer which will be passed to all calls to `callback`.
*/
void sect_ForEach(void (*callback)(struct Section *, void *), void *arg);
/**
* Registers a section to be processed.
* @param section The section to register.
*/
void sect_AddSection(struct Section *section);
/**
* Finds a section by its name.
* @param name The name of the section to look for
* @return A pointer to the section, or NULL if it wasn't found
*/
struct Section *sect_GetSection(char const *name);
/**
* `free`s all section memory that was allocated.
*/
void sect_CleanupSections(void);
/**
* Checks if all sections meet reasonable criteria, such as max size
*/
void sect_DoSanityChecks(void);
#endif /* RGBDS_LINK_SECTION_H */
+56 -7
View File
@@ -1,12 +1,61 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2019, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
/* Declarations manipulating symbols */
#ifndef RGBDS_LINK_SYMBOL_H
#define RGBDS_LINK_SYMBOL_H
#include "types.h"
/* GUIDELINE: external code MUST NOT BE AWARE of the data structure used!! */
void sym_Init(void);
void sym_CreateSymbol(char *tzName, SLONG nValue, SLONG nBank,
char *tzObjFileName, char *tzFileName, ULONG nFileLine);
SLONG sym_GetValue(char *tzName);
SLONG sym_GetBank(char *tzName);
#include <stdint.h>
#endif
#include "linkdefs.h"
struct FileStackNode;
struct Symbol {
/* Info contained in the object files */
char *name;
enum ExportLevel type;
char const *objFileName;
struct FileStackNode const *src;
int32_t lineNo;
int32_t sectionID;
union {
int32_t offset;
int32_t value;
};
/* Extra info computed during linking */
struct Section *section;
};
/*
* Execute a callback for each symbol currently registered.
* This is done to avoid exposing the data structure in which symbol are stored.
* @param callback The function to call for each symbol;
* the first argument will be a pointer to the symbol,
* the second argument will be the pointer `arg`.
* @param arg A pointer which will be passed to all calls to `callback`.
*/
void sym_ForEach(void (*callback)(struct Symbol *, void *), void *arg);
void sym_AddSymbol(struct Symbol *symbol);
/**
* Finds a symbol in all the defined symbols.
* @param name The name of the symbol to look for
* @return A pointer to the symbol, or NULL if not found.
*/
struct Symbol *sym_GetSymbol(char const *name);
/**
* `free`s all symbol memory that was allocated.
*/
void sym_CleanupSymbols(void);
#endif /* RGBDS_LINK_SYMBOL_H */
+152
View File
@@ -0,0 +1,152 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_LINKDEFS_H
#define RGBDS_LINKDEFS_H
#include <stdbool.h>
#include <stdint.h>
#define RGBDS_OBJECT_VERSION_STRING "RGB%1u"
#define RGBDS_OBJECT_VERSION_NUMBER 9U
#define RGBDS_OBJECT_REV 7U
enum AssertionType {
ASSERT_WARN,
ASSERT_ERROR,
ASSERT_FATAL
};
enum RPNCommand {
RPN_ADD = 0x00,
RPN_SUB = 0x01,
RPN_MUL = 0x02,
RPN_DIV = 0x03,
RPN_MOD = 0x04,
RPN_UNSUB = 0x05,
RPN_EXP = 0x06,
RPN_OR = 0x10,
RPN_AND = 0x11,
RPN_XOR = 0x12,
RPN_UNNOT = 0x13,
RPN_LOGAND = 0x21,
RPN_LOGOR = 0x22,
RPN_LOGUNNOT = 0x23,
RPN_LOGEQ = 0x30,
RPN_LOGNE = 0x31,
RPN_LOGGT = 0x32,
RPN_LOGLT = 0x33,
RPN_LOGGE = 0x34,
RPN_LOGLE = 0x35,
RPN_SHL = 0x40,
RPN_SHR = 0x41,
RPN_BANK_SYM = 0x50,
RPN_BANK_SECT = 0x51,
RPN_BANK_SELF = 0x52,
RPN_HRAM = 0x60,
RPN_RST = 0x61,
RPN_CONST = 0x80,
RPN_SYM = 0x81
};
enum SectionType {
SECTTYPE_WRAM0,
SECTTYPE_VRAM,
SECTTYPE_ROMX,
SECTTYPE_ROM0,
SECTTYPE_HRAM,
SECTTYPE_WRAMX,
SECTTYPE_SRAM,
SECTTYPE_OAM,
SECTTYPE_INVALID
};
enum SectionModifier {
SECTION_NORMAL,
SECTION_UNION,
SECTION_FRAGMENT
};
extern char const * const sectionModNames[];
/**
* Tells whether a section has data in its object file definition,
* depending on type.
* @param type The section's type
* @return `true` if the section's definition includes data
*/
static inline bool sect_HasData(enum SectionType type)
{
return type == SECTTYPE_ROM0 || type == SECTTYPE_ROMX;
}
enum ExportLevel {
SYMTYPE_LOCAL,
SYMTYPE_IMPORT,
SYMTYPE_EXPORT
};
enum PatchType {
PATCHTYPE_BYTE,
PATCHTYPE_WORD,
PATCHTYPE_LONG,
PATCHTYPE_JR,
PATCHTYPE_INVALID
};
#define BANK_MIN_ROM0 0
#define BANK_MAX_ROM0 0
#define BANK_MIN_ROMX 1
#define BANK_MAX_ROMX 511
#define BANK_MIN_VRAM 0
#define BANK_MAX_VRAM 1
#define BANK_MIN_SRAM 0
#define BANK_MAX_SRAM 15
#define BANK_MIN_WRAM0 0
#define BANK_MAX_WRAM0 0
#define BANK_MIN_WRAMX 1
#define BANK_MAX_WRAMX 7
#define BANK_MIN_OAM 0
#define BANK_MAX_OAM 0
#define BANK_MIN_HRAM 0
#define BANK_MAX_HRAM 0
extern uint16_t startaddr[];
extern uint16_t maxsize[];
extern uint32_t bankranges[][2];
/**
* Computes a memory region's end address (last byte), eg. 0x7FFF
* @return The address of the last byte in that memory region
*/
static inline uint16_t endaddr(enum SectionType type)
{
return startaddr[type] + maxsize[type] - 1;
}
/**
* Computes a memory region's number of banks
* @return The number of banks, 1 for regions without banking
*/
static inline uint32_t nbbanks(enum SectionType type)
{
return bankranges[type][1] - bankranges[type][0] + 1;
}
extern char const * const typeNames[SECTTYPE_INVALID];
#endif /* RGBDS_LINKDEFS_H */
+20
View File
@@ -0,0 +1,20 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2021, RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_OP_MATH_H
#define RGBDS_OP_MATH_H
#include <stdint.h>
int32_t op_divide(int32_t dividend, int32_t divisor);
int32_t op_modulo(int32_t dividend, int32_t divisor);
int32_t op_exponent(int32_t base, uint32_t power);
int32_t op_shift_left(int32_t value, int32_t amount);
int32_t op_shift_right(int32_t value, int32_t amount);
#endif /* RGBDS_OP_MATH_H */
+73
View File
@@ -0,0 +1,73 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2020 RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
/* platform-specific hacks */
#ifndef RGBDS_PLATFORM_H
#define RGBDS_PLATFORM_H
/* MSVC doesn't have strncasecmp, use a suitable replacement */
#ifdef _MSC_VER
# include <string.h>
# define strncasecmp _strnicmp
#else
# include <strings.h>
#endif
/* MSVC has deprecated strdup in favor of _strdup */
#ifdef _MSC_VER
# define strdup _strdup
#endif
/* MSVC prefixes the names of S_* macros with underscores,
and doesn't define any S_IS* macros. Define them ourselves */
#ifdef _MSC_VER
# define S_IFMT _S_IFMT
# define S_IFDIR _S_IFDIR
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
/* MSVC doesn't use POSIX types or defines for `read` */
#ifdef _MSC_VER
# include <io.h>
# define STDIN_FILENO 0
# define STDOUT_FILENO 1
# define STDERR_FILENO 2
# define ssize_t int
# define SSIZE_MAX INT_MAX
#else
# include <fcntl.h>
# include <unistd.h>
#endif
/* MSVC doesn't support `[static N]` for array arguments from C99 */
#ifdef _MSC_VER
# define MIN_NB_ELMS(N)
#else
# define MIN_NB_ELMS(N) static (N)
#endif
// MSVC uses a different name for O_RDWR, and needs an additional _O_BINARY flag
#ifdef _MSC_VER
# include <fcntl.h>
# define O_RDWR _O_RDWR
# define S_ISREG(field) ((field) & _S_IFREG)
# define O_BINARY _O_BINARY
#elif !defined(O_BINARY) // Cross-compilers define O_BINARY
# define O_BINARY 0 // POSIX says we shouldn't care!
#endif // _MSC_VER
// Windows has stdin and stdout open as text by default, which we may not want
#if defined(_MSC_VER) || defined(__MINGW32__)
# include <io.h>
# define setmode(fd, mode) _setmode(fd, mode)
#else
# define setmode(fd, mode) ((void)0)
#endif
#endif /* RGBDS_PLATFORM_H */
+10 -10
View File
@@ -1,16 +1,16 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_TYPES_H
#define RGBDS_TYPES_H
#ifndef _MAX_PATH
#define _MAX_PATH 512
#define _MAX_PATH 512
#endif
typedef unsigned char UBYTE;
typedef signed char SBYTE;
typedef unsigned short UWORD;
typedef signed short SWORD;
typedef unsigned long ULONG;
typedef signed long SLONG;
typedef signed char BBOOL;
#endif
#endif /* RGBDS_TYPES_H */
+19
View File
@@ -0,0 +1,19 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2017-2021, Antonio Nino Diaz and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef EXTERN_VERSION_H
#define EXTERN_VERSION_H
#define PACKAGE_VERSION_MAJOR 0
#define PACKAGE_VERSION_MINOR 5
#define PACKAGE_VERSION_PATCH 0
#define PACKAGE_VERSION_RC 2
const char *get_package_version_string(void);
#endif /* EXTERN_VERSION_H */
+128
View File
@@ -0,0 +1,128 @@
#
# This file is part of RGBDS.
#
# Copyright (c) 2020 RGBDS contributors.
#
# SPDX-License-Identifier: MIT
#
set(common_src
"extern/err.c"
"extern/getopt.c"
"version.c"
)
find_package(PkgConfig)
if(MSVC OR NOT PKG_CONFIG_FOUND)
# fallback to find_package
find_package(PNG REQUIRED)
else()
pkg_check_modules(LIBPNG REQUIRED libpng)
endif()
find_package(BISON REQUIRED)
set(BISON_FLAGS "-Wall")
# Set sompe optimization flags on versions that support them
if(BISON_VERSION VERSION_GREATER_EQUAL "3.5")
set(BISON_FLAGS "${BISON_FLAGS} -Dapi.token.raw=true")
endif()
if(BISON_VERSION VERSION_GREATER_EQUAL "3.6")
set(BISON_FLAGS "${BISON_FLAGS} -Dparse.error=detailed")
elseif(BISON_VERSION VERSION_GREATER_EQUAL "3.0")
set(BISON_FLAGS "${BISON_FLAGS} -Dparse.error=verbose")
endif()
if(BISON_VERSION VERSION_GREATER_EQUAL "3.0")
set(BISON_FLAGS "${BISON_FLAGS} -Dparse.lac=full")
set(BISON_FLAGS "${BISON_FLAGS} -Dlr.type=ielr")
endif()
BISON_TARGET(PARSER "asm/parser.y"
"${PROJECT_SOURCE_DIR}/src/asm/parser.c"
COMPILE_FLAGS "${BISON_FLAGS}"
DEFINES_FILE "${PROJECT_SOURCE_DIR}/src/asm/parser.h"
)
set(rgbasm_src
"${BISON_PARSER_OUTPUT_SOURCE}"
"asm/charmap.c"
"asm/fixpoint.c"
"asm/format.c"
"asm/fstack.c"
"asm/lexer.c"
"asm/macro.c"
"asm/main.c"
"asm/opt.c"
"asm/output.c"
"asm/rpn.c"
"asm/section.c"
"asm/symbol.c"
"asm/util.c"
"asm/warning.c"
"extern/utf8decoder.c"
"hashmap.c"
"linkdefs.c"
"opmath.c"
)
set(rgbfix_src
"fix/main.c"
)
set(rgbgfx_src
"gfx/gb.c"
"gfx/main.c"
"gfx/makepng.c"
)
set(rgblink_src
"link/assign.c"
"link/main.c"
"link/object.c"
"link/output.c"
"link/patch.c"
"link/script.c"
"link/section.c"
"link/symbol.c"
"hashmap.c"
"linkdefs.c"
"opmath.c"
)
foreach(PROG "asm" "fix" "gfx" "link")
add_executable(rgb${PROG}
${rgb${PROG}_src}
${common_src}
)
install(TARGETS rgb${PROG} RUNTIME DESTINATION bin)
endforeach()
set(MANDIR "share/man")
set(man1 "asm/rgbasm.1"
"fix/rgbfix.1"
"gfx/rgbgfx.1"
"link/rgblink.1")
set(man5 "asm/rgbasm.5"
"link/rgblink.5"
"rgbds.5")
set(man7 "gbz80.7"
"rgbds.7")
foreach(SECTION "man1" "man5" "man7")
set(DEST "${MANDIR}/${SECTION}")
install(FILES ${${SECTION}} DESTINATION ${DEST})
endforeach()
if(LIBPNG_FOUND) # pkg-config
target_include_directories(rgbgfx PRIVATE ${LIBPNG_INCLUDE_DIRS})
target_link_directories(rgbgfx PRIVATE ${LIBPNG_LIBRARY_DIRS})
target_link_libraries(rgbgfx PRIVATE ${LIBPNG_LIBRARIES})
else()
target_compile_definitions(rgbgfx PRIVATE ${PNG_DEFINITIONS})
target_include_directories(rgbgfx PRIVATE ${PNG_INCLUDE_DIRS})
target_link_libraries(rgbgfx PRIVATE ${PNG_LIBRARIES})
endif()
include(CheckLibraryExists)
check_library_exists("m" "sin" "" HAS_LIBM)
if(HAS_LIBM)
target_link_libraries(rgbasm PRIVATE "m")
endif()
+2 -2
View File
@@ -1,2 +1,2 @@
asmy.c
asmy.h
/parser.c
/parser.h
-1783
View File
File diff suppressed because it is too large Load Diff
+221 -193
View File
@@ -1,218 +1,246 @@
/*
* UTF-8 decoder copyright © 20082009 Björn Höhrmann <bjoern@hoehrmann.de>
* http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
* This file is part of RGBDS.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* Copyright (c) 2013-2018, stag019 and RGBDS contributors.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
* SPDX-License-Identifier: MIT
*/
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
static const uint8_t utf8d[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
};
uint32_t
decode(uint32_t* state, uint32_t* codep, uint32_t byte) {
uint32_t type = utf8d[byte];
*codep = (*state != 0) ?
(byte & 0x3fu) | (*codep << 6) :
(0xff >> type) & (byte);
*state = utf8d[256 + *state*16 + type];
return *state;
}
/*
* Copyright © 2013 stag019 <stag019@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asm/asm.h"
#include "asm/charmap.h"
#include "asm/main.h"
#include "asm/output.h"
#include "asm/util.h"
#include "asm/warning.h"
struct Charmap globalCharmap = {0};
#include "hashmap.h"
extern struct Section *pCurrentSection;
/*
* Charmaps are stored using a structure known as "trie".
* Essentially a tree, where each nodes stores a single character's worth of info:
* whether there exists a mapping that ends at the current character,
*/
struct Charnode {
bool isTerminal; /* Whether there exists a mapping that ends here */
uint8_t value; /* If the above is true, its corresponding value */
/* This MUST be indexes and not pointers, because pointers get invalidated by `realloc`!! */
size_t next[255]; /* Indexes of where to go next, 0 = nowhere */
};
int
readUTF8Char(char *dest, char *src)
{
uint32_t state;
uint32_t codep;
int i;
#define INITIAL_CAPACITY 32
for (i = 0, state = 0;; i++) {
if (decode(&state, &codep, (uint8_t)src[i]) == 1) {
fatalerror("invalid UTF-8 character");
}
struct Charmap {
char *name;
size_t usedNodes; /* How many nodes are being used */
size_t capacity; /* How many nodes have been allocated */
struct Charnode nodes[]; /* first node is reserved for the root node */
};
dest[i] = src[i];
static HashMap charmaps;
i++;
if (state == 0) {
dest[i] = '\0';
return i;
}
dest[i] = src[i];
}
}
int
charmap_Add(char *input, UBYTE output)
{
int i;
size_t input_length;
char temp1i[CHARMAPLENGTH + 1], temp2i[CHARMAPLENGTH + 1], temp1o = 0,
temp2o = 0;
static struct Charmap *currentCharmap;
struct CharmapStackEntry {
struct Charmap *charmap;
struct CharmapStackEntry *next;
};
if (pCurrentSection) {
if (pCurrentSection->charmap) {
charmap = pCurrentSection->charmap;
} else {
if ((charmap = calloc(1, sizeof(struct Charmap))) ==
NULL) {
fatalerror("Not enough memory for charmap");
}
pCurrentSection->charmap = charmap;
}
} else {
charmap = &globalCharmap;
}
struct CharmapStackEntry *charmapStack;
if (nPass == 2) {
return charmap->count;
}
if (charmap->count > MAXCHARMAPS || strlen(input) > CHARMAPLENGTH) {
return -1;
}
input_length = strlen(input);
if (input_length > 1) {
i = 0;
while (i < charmap->count + 1) {
if (input_length > strlen(charmap->input[i])) {
memcpy(temp1i, charmap->input[i],
CHARMAPLENGTH + 1);
memcpy(charmap->input[i], input, input_length);
temp1o = charmap->output[i];
charmap->output[i] = output;
i++;
break;
}
i++;
}
while (i < charmap->count + 1) {
memcpy(temp2i, charmap->input[i], CHARMAPLENGTH + 1);
memcpy(charmap->input[i], temp1i, CHARMAPLENGTH + 1);
memcpy(temp1i, temp2i, CHARMAPLENGTH + 1);
temp2o = charmap->output[i];
charmap->output[i] = temp1o;
temp1o = temp2o;
i++;
}
memcpy(charmap->input[charmap->count + 1], temp1i,
CHARMAPLENGTH + 1);
charmap->output[charmap->count + 1] = temp1o;
} else {
memcpy(charmap->input[charmap->count], input, input_length);
charmap->output[charmap->count] = output;
}
return ++charmap->count;
}
int
charmap_Convert(char **input)
static inline struct Charmap *charmap_Get(const char *name)
{
struct Charmap *charmap;
char outchar[CHARMAPLENGTH + 1];
char *buffer;
int i, j, length;
if (pCurrentSection && pCurrentSection->charmap) {
charmap = pCurrentSection->charmap;
} else {
charmap = &globalCharmap;
}
if ((buffer = malloc(strlen(*input))) == NULL) {
fatalerror("Not enough memory for buffer");
}
length = 0;
while (**input) {
j = 0;
for (i = 0; i < charmap->count; i++) {
j = strlen(charmap->input[i]);
if (memcmp(*input, charmap->input[i], j) == 0) {
outchar[0] = charmap->output[i];
outchar[1] = 0;
break;
}
j = 0;
}
if (!j) {
j = readUTF8Char(outchar, *input);
}
if (!outchar[0]) {
buffer[length++] = 0;
} else {
for (i = 0; outchar[i]; i++) {
buffer[length++] = outchar[i];
}
}
*input += j;
}
*input = buffer;
return length;
return hash_GetElement(charmaps, name);
}
static inline struct Charmap *resizeCharmap(struct Charmap *map, size_t capacity)
{
struct Charmap *new = realloc(map, sizeof(*map) + sizeof(*map->nodes) * capacity);
if (!new)
fatalerror("Failed to %s charmap: %s\n",
map ? "create" : "resize", strerror(errno));
new->capacity = capacity;
return new;
}
static inline void initNode(struct Charnode *node)
{
node->isTerminal = false;
memset(node->next, 0, sizeof(node->next));
}
struct Charmap *charmap_New(const char *name, const char *baseName)
{
struct Charmap *base = NULL;
if (baseName != NULL) {
base = charmap_Get(baseName);
if (base == NULL)
error("Base charmap '%s' doesn't exist\n", baseName);
}
struct Charmap *charmap = charmap_Get(name);
if (charmap) {
error("Charmap '%s' already exists\n", name);
return charmap;
}
/* Init the new charmap's fields */
if (base) {
charmap = resizeCharmap(NULL, base->capacity);
charmap->usedNodes = base->usedNodes;
memcpy(charmap->nodes, base->nodes, sizeof(base->nodes[0]) * charmap->usedNodes);
} else {
charmap = resizeCharmap(NULL, INITIAL_CAPACITY);
charmap->usedNodes = 1;
initNode(&charmap->nodes[0]); /* Init the root node */
}
charmap->name = strdup(name);
hash_AddElement(charmaps, charmap->name, charmap);
currentCharmap = charmap;
return charmap;
}
void charmap_Delete(struct Charmap *charmap)
{
free(charmap->name);
free(charmap);
}
void charmap_Set(const char *name)
{
struct Charmap *charmap = charmap_Get(name);
if (charmap == NULL)
error("Charmap '%s' doesn't exist\n", name);
else
currentCharmap = charmap;
}
void charmap_Push(void)
{
struct CharmapStackEntry *stackEntry;
stackEntry = malloc(sizeof(*stackEntry));
if (stackEntry == NULL)
fatalerror("Failed to alloc charmap stack entry: %s\n", strerror(errno));
stackEntry->charmap = currentCharmap;
stackEntry->next = charmapStack;
charmapStack = stackEntry;
}
void charmap_Pop(void)
{
if (charmapStack == NULL) {
error("No entries in the charmap stack\n");
return;
}
struct CharmapStackEntry *top = charmapStack;
currentCharmap = top->charmap;
charmapStack = top->next;
free(top);
}
void charmap_Add(char *mapping, uint8_t value)
{
struct Charnode *node = &currentCharmap->nodes[0];
for (uint8_t c; *mapping; mapping++) {
c = *mapping - 1;
if (node->next[c]) {
node = &currentCharmap->nodes[node->next[c]];
} else {
/* Register next available node */
node->next[c] = currentCharmap->usedNodes;
/* If no more nodes are available, get new ones */
if (currentCharmap->usedNodes == currentCharmap->capacity) {
currentCharmap->capacity *= 2;
currentCharmap = resizeCharmap(currentCharmap, currentCharmap->capacity);
hash_ReplaceElement(charmaps, currentCharmap->name, currentCharmap);
}
/* Switch to and init new node */
node = &currentCharmap->nodes[currentCharmap->usedNodes++];
initNode(node);
}
}
if (node->isTerminal)
warning(WARNING_CHARMAP_REDEF, "Overriding charmap mapping\n");
node->isTerminal = true;
node->value = value;
}
size_t charmap_Convert(char const *input, uint8_t *output)
{
/*
* The goal is to match the longest mapping possible.
* For that, advance through the trie with each character read.
* If that would lead to a dead end, rewind characters until the last match, and output.
* If no match, read a UTF-8 codepoint and output that.
*/
size_t outputLen = 0;
struct Charnode const *node = &currentCharmap->nodes[0];
struct Charnode const *match = NULL;
size_t rewindDistance = 0;
for (;;) {
/* We still want NULs to reach the `else` path, to give a chance to rewind */
uint8_t c = *input - 1;
if (*input && node->next[c]) {
input++; /* Consume that char */
rewindDistance++;
node = &currentCharmap->nodes[node->next[c]];
if (node->isTerminal) {
match = node;
rewindDistance = 0; /* Rewind from after the match */
}
} else {
input -= rewindDistance; /* Rewind */
rewindDistance = 0;
node = &currentCharmap->nodes[0];
if (match) { /* Arrived at a dead end with a match found */
*output++ = match->value;
outputLen++;
match = NULL; /* Reset match for next round */
} else if (*input) { /* No match found */
size_t codepointLen = readUTF8Char(output, input);
if (codepointLen == 0) {
error("Input string is not valid UTF-8!\n");
break;
}
input += codepointLen; /* OK because UTF-8 has no NUL in multi-byte chars */
output += codepointLen;
outputLen += codepointLen;
}
if (!*input)
break;
}
}
return outputLen;
}
+170
View File
@@ -0,0 +1,170 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2021, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
/*
* Fixed-point math routines
*/
#include <inttypes.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include "asm/fixpoint.h"
#include "asm/symbol.h"
#include "asm/warning.h"
#define fix2double(i) ((double)((i) / 65536.0))
#define double2fix(d) ((int32_t)round((d) * 65536.0))
// pi radians == 32768 fixed-point "degrees"
#define fdeg2rad(f) ((f) * (M_PI / 32768.0))
#define rad2fdeg(r) ((r) * (32768.0 / M_PI))
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
/*
* Return the _PI symbol value
*/
int32_t fix_Callback_PI(void)
{
warning(WARNING_OBSOLETE, "`_PI` is deprecated; use 3.14159\n");
return double2fix(M_PI);
}
/*
* Print a fixed point value
*/
void fix_Print(int32_t i)
{
uint32_t u = i;
const char *sign = "";
if (i < 0) {
u = -u;
sign = "-";
}
printf("%s%" PRIu32 ".%05" PRIu32, sign, u >> 16,
((uint32_t)(fix2double(u) * 100000 + 0.5)) % 100000);
}
/*
* Calculate sine
*/
int32_t fix_Sin(int32_t i)
{
return double2fix(sin(fdeg2rad(fix2double(i))));
}
/*
* Calculate cosine
*/
int32_t fix_Cos(int32_t i)
{
return double2fix(cos(fdeg2rad(fix2double(i))));
}
/*
* Calculate tangent
*/
int32_t fix_Tan(int32_t i)
{
return double2fix(tan(fdeg2rad(fix2double(i))));
}
/*
* Calculate arcsine
*/
int32_t fix_ASin(int32_t i)
{
return double2fix(rad2fdeg(asin(fix2double(i))));
}
/*
* Calculate arccosine
*/
int32_t fix_ACos(int32_t i)
{
return double2fix(rad2fdeg(acos(fix2double(i))));
}
/*
* Calculate arctangent
*/
int32_t fix_ATan(int32_t i)
{
return double2fix(rad2fdeg(atan(fix2double(i))));
}
/*
* Calculate atan2
*/
int32_t fix_ATan2(int32_t i, int32_t j)
{
return double2fix(rad2fdeg(atan2(fix2double(i), fix2double(j))));
}
/*
* Multiplication
*/
int32_t fix_Mul(int32_t i, int32_t j)
{
return double2fix(fix2double(i) * fix2double(j));
}
/*
* Division
*/
int32_t fix_Div(int32_t i, int32_t j)
{
return double2fix(fix2double(i) / fix2double(j));
}
/*
* Power
*/
int32_t fix_Pow(int32_t i, int32_t j)
{
return double2fix(pow(fix2double(i), fix2double(j)));
}
/*
* Logarithm
*/
int32_t fix_Log(int32_t i, int32_t j)
{
return double2fix(log(fix2double(i)) / log(fix2double(j)));
}
/*
* Round
*/
int32_t fix_Round(int32_t i)
{
return double2fix(round(fix2double(i)));
}
/*
* Ceil
*/
int32_t fix_Ceil(int32_t i)
{
return double2fix(ceil(fix2double(i)));
}
/*
* Floor
*/
int32_t fix_Floor(int32_t i)
{
return double2fix(floor(fix2double(i)));
}
+299
View File
@@ -0,0 +1,299 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2020, RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#include <inttypes.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asm/format.h"
#include "asm/warning.h"
struct FormatSpec fmt_NewSpec(void)
{
struct FormatSpec fmt = {0};
return fmt;
}
bool fmt_IsEmpty(struct FormatSpec const *fmt)
{
return !fmt->state;
}
bool fmt_IsValid(struct FormatSpec const *fmt)
{
return fmt->valid || fmt->state == FORMAT_DONE;
}
bool fmt_IsFinished(struct FormatSpec const *fmt)
{
return fmt->state >= FORMAT_DONE;
}
void fmt_UseCharacter(struct FormatSpec *fmt, int c)
{
if (fmt->state == FORMAT_INVALID)
return;
switch (c) {
/* sign */
case ' ':
case '+':
if (fmt->state > FORMAT_SIGN)
goto invalid;
fmt->state = FORMAT_PREFIX;
fmt->sign = c;
break;
/* prefix */
case '#':
if (fmt->state > FORMAT_PREFIX)
goto invalid;
fmt->state = FORMAT_ALIGN;
fmt->prefix = true;
break;
/* align */
case '-':
if (fmt->state > FORMAT_ALIGN)
goto invalid;
fmt->state = FORMAT_WIDTH;
fmt->alignLeft = true;
break;
/* pad and width */
case '0':
if (fmt->state < FORMAT_WIDTH)
fmt->padZero = true;
/* fallthrough */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (fmt->state < FORMAT_WIDTH) {
fmt->state = FORMAT_WIDTH;
fmt->width = c - '0';
} else if (fmt->state == FORMAT_WIDTH) {
fmt->width = fmt->width * 10 + (c - '0');
} else if (fmt->state == FORMAT_FRAC) {
fmt->fracWidth = fmt->fracWidth * 10 + (c - '0');
} else {
goto invalid;
}
break;
case '.':
if (fmt->state > FORMAT_WIDTH)
goto invalid;
fmt->state = FORMAT_FRAC;
fmt->hasFrac = true;
break;
/* type */
case 'd':
case 'u':
case 'X':
case 'x':
case 'b':
case 'o':
case 'f':
case 's':
if (fmt->state >= FORMAT_DONE)
goto invalid;
fmt->state = FORMAT_DONE;
fmt->valid = true;
fmt->type = c;
break;
default:
invalid:
fmt->state = FORMAT_INVALID;
fmt->valid = false;
}
}
void fmt_FinishCharacters(struct FormatSpec *fmt)
{
if (!fmt_IsValid(fmt))
fmt->state = FORMAT_INVALID;
}
void fmt_PrintString(char *buf, size_t bufLen, struct FormatSpec const *fmt, char const *value)
{
if (fmt->sign)
error("Formatting string with sign flag '%c'\n", fmt->sign);
if (fmt->prefix)
error("Formatting string with prefix flag '#'\n");
if (fmt->padZero)
error("Formatting string with padding flag '0'\n");
if (fmt->hasFrac)
error("Formatting string with fractional width\n");
if (fmt->type != 's')
error("Formatting string as type '%c'\n", fmt->type);
size_t len = strlen(value);
size_t totalLen = fmt->width > len ? fmt->width : len;
if (totalLen + 1 > bufLen) /* bufLen includes terminator */
error("Formatted string value too long\n");
size_t padLen = fmt->width > len ? fmt->width - len : 0;
if (fmt->alignLeft) {
strncpy(buf, value, len < bufLen ? len : bufLen);
for (size_t i = 0; i < totalLen && len + i < bufLen; i++)
buf[len + i] = ' ';
} else {
for (size_t i = 0; i < padLen && i < bufLen; i++)
buf[i] = ' ';
if (bufLen > padLen)
strncpy(buf + padLen, value, bufLen - padLen - 1);
}
buf[totalLen] = '\0';
}
void fmt_PrintNumber(char *buf, size_t bufLen, struct FormatSpec const *fmt, uint32_t value)
{
if (fmt->type != 'X' && fmt->type != 'x' && fmt->type != 'b' && fmt->type != 'o'
&& fmt->prefix)
error("Formatting type '%c' with prefix flag '#'\n", fmt->type);
if (fmt->type != 'f' && fmt->hasFrac)
error("Formatting type '%c' with fractional width\n", fmt->type);
if (fmt->type == 's')
error("Formatting number as type 's'\n");
char sign = fmt->sign; /* 0 or ' ' or '+' */
if (fmt->type == 'd' || fmt->type == 'f') {
int32_t v = value;
if (v < 0 && v != INT32_MIN) {
sign = '-';
value = -v;
}
}
char prefix = !fmt->prefix ? 0
: fmt->type == 'X' ? '$'
: fmt->type == 'x' ? '$'
: fmt->type == 'b' ? '%'
: fmt->type == 'o' ? '&'
: 0;
char valueBuf[262]; /* Max 5 digits + decimal + 255 fraction digits + terminator */
if (fmt->type == 'b') {
/* Special case for binary */
char *ptr = valueBuf;
do {
*ptr++ = (value & 1) + '0';
value >>= 1;
} while (value);
*ptr = '\0';
/* Reverse the digits */
size_t valueLen = ptr - valueBuf;
for (size_t i = 0, j = valueLen - 1; i < j; i++, j--) {
char c = valueBuf[i];
valueBuf[i] = valueBuf[j];
valueBuf[j] = c;
}
} else if (fmt->type == 'f') {
/* Special case for fixed-point */
/* Default fractional width (C's is 6 for "%f"; here 5 is enough) */
uint8_t fracWidth = fmt->hasFrac ? fmt->fracWidth : 5;
if (fracWidth) {
char spec[16]; /* Max "%" + 5-char PRIu32 + ".%0255.f" + terminator */
snprintf(spec, sizeof(spec), "%%" PRIu32 ".%%0%d.f", fracWidth);
snprintf(valueBuf, sizeof(valueBuf), spec, value >> 16,
(value % 65536) / 65536.0 * pow(10, fracWidth) + 0.5);
} else {
snprintf(valueBuf, sizeof(valueBuf), "%" PRIu32, value >> 16);
}
} else {
char const *spec = fmt->type == 'd' ? "%" PRId32
: fmt->type == 'u' ? "%" PRIu32
: fmt->type == 'X' ? "%" PRIX32
: fmt->type == 'x' ? "%" PRIx32
: fmt->type == 'o' ? "%" PRIo32
: "%" PRId32;
snprintf(valueBuf, sizeof(valueBuf), spec, value);
}
size_t len = strlen(valueBuf);
size_t numLen = len;
if (sign)
numLen++;
if (prefix)
numLen++;
size_t totalLen = fmt->width > numLen ? fmt->width : numLen;
if (totalLen + 1 > bufLen) /* bufLen includes terminator */
error("Formatted numeric value too long\n");
size_t padLen = fmt->width > numLen ? fmt->width - numLen : 0;
if (fmt->alignLeft) {
size_t pos = 0;
if (sign && pos < bufLen)
buf[pos++] = sign;
if (prefix && pos < bufLen)
buf[pos++] = prefix;
strcpy(buf + pos, valueBuf);
pos += len;
for (size_t i = 0; i < totalLen && pos + i < bufLen; i++)
buf[pos + i] = ' ';
} else {
size_t pos = 0;
if (fmt->padZero) {
/* sign, then prefix, then zero padding */
if (sign && pos < bufLen)
buf[pos++] = sign;
if (prefix && pos < bufLen)
buf[pos++] = prefix;
for (size_t i = 0; i < padLen && pos < bufLen; i++)
buf[pos++] = '0';
} else {
/* space padding, then sign, then prefix */
for (size_t i = 0; i < padLen && pos < bufLen; i++)
buf[pos++] = ' ';
if (sign && pos < bufLen)
buf[pos++] = sign;
if (prefix && pos < bufLen)
buf[pos++] = prefix;
}
if (bufLen > pos)
strcpy(buf + pos, valueBuf);
}
buf[totalLen] = '\0';
}
+511 -343
View File
@@ -1,406 +1,574 @@
/*
* FileStack routines
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#include <sys/stat.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asm/symbol.h"
#include "asm/fstack.h"
#include "types.h"
#include "asm/macro.h"
#include "asm/main.h"
#include "asm/lexer.h"
#include "extern/err.h"
#include "extern/strl.h"
#include "asm/symbol.h"
#include "asm/warning.h"
#include "platform.h" /* S_ISDIR (stat macro) */
#ifndef PATH_MAX
#define PATH_MAX 256
#define MAXINCPATHS 128
#ifdef LEXER_DEBUG
#define dbgPrint(...) fprintf(stderr, "[fstack] " __VA_ARGS__)
#else
#define dbgPrint(...)
#endif
struct sContext *pFileStack;
struct sSymbol *pCurrentMacro;
YY_BUFFER_STATE CurrentFlexHandle;
FILE *pCurrentFile;
ULONG nCurrentStatus;
char tzCurrentFileName[_MAX_PATH + 1];
char IncludePaths[MAXINCPATHS][_MAX_PATH + 1];
SLONG NextIncPath = 0;
ULONG nMacroCount;
struct Context {
struct Context *parent;
struct FileStackNode *fileInfo;
struct LexerState *lexerState;
uint32_t uniqueID;
struct MacroArgs *macroArgs; /* Macro args are *saved* here */
uint32_t nbReptIters;
int32_t forValue;
int32_t forStep;
char *forName;
};
char *pCurrentREPTBlock;
ULONG nCurrentREPTBlockSize;
ULONG nCurrentREPTBlockCount;
static struct Context *contextStack;
static size_t contextDepth = 0;
#define DEFAULT_MAX_DEPTH 64
size_t nMaxRecursionDepth;
ULONG ulMacroReturnValue;
static unsigned int nbIncPaths = 0;
static char const *includePaths[MAXINCPATHS];
extern char *tzObjectname;
extern FILE *dependfile;
/*
* defines for nCurrentStatus
*/
#define STAT_isInclude 0 /* 'Normal' state as well */
#define STAT_isMacro 1
#define STAT_isMacroArg 2
#define STAT_isREPTBlock 3
/*
* Context push and pop
*/
void
pushcontext(void)
static const char *dumpNodeAndParents(struct FileStackNode const *node)
{
struct sContext **ppFileStack;
char const *name;
ppFileStack = &pFileStack;
while (*ppFileStack)
ppFileStack = &((*ppFileStack)->pNext);
if (node->type == NODE_REPT) {
assert(node->parent); /* REPT nodes should always have a parent */
struct FileStackReptNode const *reptInfo = (struct FileStackReptNode const *)node;
if ((*ppFileStack = malloc(sizeof(struct sContext))) != NULL) {
(*ppFileStack)->FlexHandle = CurrentFlexHandle;
(*ppFileStack)->pNext = NULL;
strcpy((char *) (*ppFileStack)->tzFileName,
(char *) tzCurrentFileName);
(*ppFileStack)->nLine = nLineNo;
switch ((*ppFileStack)->nStatus = nCurrentStatus) {
case STAT_isMacroArg:
case STAT_isMacro:
sym_SaveCurrentMacroArgs((*ppFileStack)->tzMacroArgs);
(*ppFileStack)->pMacro = pCurrentMacro;
break;
case STAT_isInclude:
(*ppFileStack)->pFile = pCurrentFile;
break;
case STAT_isREPTBlock:
sym_SaveCurrentMacroArgs((*ppFileStack)->tzMacroArgs);
(*ppFileStack)->pREPTBlock = pCurrentREPTBlock;
(*ppFileStack)->nREPTBlockSize = nCurrentREPTBlockSize;
(*ppFileStack)->nREPTBlockCount =
nCurrentREPTBlockCount;
break;
}
nLineNo = 0;
} else
fatalerror("No memory for context");
}
int
popcontext(void)
{
struct sContext *pLastFile, **ppLastFile;
if (nCurrentStatus == STAT_isREPTBlock) {
if (--nCurrentREPTBlockCount) {
yy_delete_buffer(CurrentFlexHandle);
CurrentFlexHandle =
yy_scan_bytes(pCurrentREPTBlock,
nCurrentREPTBlockSize);
yy_switch_to_buffer(CurrentFlexHandle);
sym_UseCurrentMacroArgs();
sym_SetMacroArgID(nMacroCount++);
sym_UseNewMacroArgs();
return (0);
name = dumpNodeAndParents(node->parent);
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, name);
for (uint32_t i = reptInfo->reptDepth; i--; )
fprintf(stderr, "::REPT~%" PRIu32, reptInfo->iters[i]);
} else {
name = ((struct FileStackNamedNode const *)node)->name;
if (node->parent) {
dumpNodeAndParents(node->parent);
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, name);
} else {
fputs(name, stderr);
}
}
if ((pLastFile = pFileStack) != NULL) {
ppLastFile = &pFileStack;
while (pLastFile->pNext) {
ppLastFile = &(pLastFile->pNext);
pLastFile = *ppLastFile;
}
yy_delete_buffer(CurrentFlexHandle);
nLineNo = pLastFile->nLine;
if (nCurrentStatus == STAT_isInclude)
fclose(pCurrentFile);
if (nCurrentStatus == STAT_isMacro) {
sym_FreeCurrentMacroArgs();
nLineNo += 1;
}
if (nCurrentStatus == STAT_isREPTBlock)
nLineNo += 1;
CurrentFlexHandle = pLastFile->FlexHandle;
strcpy((char *) tzCurrentFileName,
(char *) pLastFile->tzFileName);
switch (nCurrentStatus = pLastFile->nStatus) {
case STAT_isMacroArg:
case STAT_isMacro:
sym_RestoreCurrentMacroArgs(pLastFile->tzMacroArgs);
pCurrentMacro = pLastFile->pMacro;
break;
case STAT_isInclude:
pCurrentFile = pLastFile->pFile;
break;
case STAT_isREPTBlock:
sym_RestoreCurrentMacroArgs(pLastFile->tzMacroArgs);
pCurrentREPTBlock = pLastFile->pREPTBlock;
nCurrentREPTBlockSize = pLastFile->nREPTBlockSize;
nCurrentREPTBlockCount = pLastFile->nREPTBlockCount;
break;
}
free(*ppLastFile);
*ppLastFile = NULL;
yy_switch_to_buffer(CurrentFlexHandle);
return (0);
} else
return (1);
return name;
}
int
fstk_GetLine(void)
void fstk_Dump(struct FileStackNode const *node, uint32_t lineNo)
{
struct sContext *pLastFile, **ppLastFile;
switch (nCurrentStatus) {
case STAT_isInclude:
/* This is the normal mode, also used when including a file. */
return nLineNo;
case STAT_isMacro:
break; /* Peek top file of the stack */
case STAT_isMacroArg:
return nLineNo; /* ??? */
case STAT_isREPTBlock:
break; /* Peek top file of the stack */
}
if ((pLastFile = pFileStack) != NULL) {
ppLastFile = &pFileStack;
while (pLastFile->pNext) {
ppLastFile = &(pLastFile->pNext);
pLastFile = *ppLastFile;
}
return pLastFile->nLine;
}
/* This is only reached if the lexer is in REPT or MACRO mode but there
* are no saved contexts with the origin of said REPT or MACRO. */
fatalerror("fstk_GetLine: Internal error.");
dumpNodeAndParents(node);
fprintf(stderr, "(%" PRIu32 ")", lineNo);
}
int
yywrap(void)
void fstk_DumpCurrent(void)
{
return (popcontext());
}
/*
* Dump the context stack to stderr
*/
void
fstk_Dump(void)
{
struct sContext *pLastFile;
pLastFile = pFileStack;
while (pLastFile) {
fprintf(stderr, "%s(%ld) -> ", pLastFile->tzFileName,
pLastFile->nLine);
pLastFile = pLastFile->pNext;
}
fprintf(stderr, "%s(%ld)", tzCurrentFileName, nLineNo);
}
/*
* Extra includepath stuff
*/
void
fstk_AddIncludePath(char *s)
{
if (NextIncPath == MAXINCPATHS) {
fatalerror("Too many include directories passed from command line");
if (!contextStack) {
fputs("at top level", stderr);
return;
}
fstk_Dump(contextStack->fileInfo, lexer_GetLineNo());
}
if (strlcpy(IncludePaths[NextIncPath++], s, _MAX_PATH) >= _MAX_PATH) {
fatalerror("Include path too long '%s'",s);
struct FileStackNode *fstk_GetFileStack(void)
{
if (!contextStack)
return NULL;
struct FileStackNode *node = contextStack->fileInfo;
/* Mark node and all of its parents as referenced if not already so they don't get freed */
while (node && !node->referenced) {
node->ID = -1;
node->referenced = true;
node = node->parent;
}
return contextStack->fileInfo;
}
char const *fstk_GetFileName(void)
{
/* Iterating via the nodes themselves skips nested REPTs */
struct FileStackNode const *node = contextStack->fileInfo;
while (node->type != NODE_FILE)
node = node->parent;
return ((struct FileStackNamedNode const *)node)->name;
}
void fstk_AddIncludePath(char const *path)
{
if (path[0] == '\0')
return;
if (nbIncPaths >= MAXINCPATHS) {
error("Too many include directories passed from command line\n");
return;
}
size_t len = strlen(path);
size_t allocSize = len + (path[len - 1] != '/') + 1;
char *str = malloc(allocSize);
if (!str) {
/* Attempt to continue without that path */
error("Failed to allocate new include path: %s\n", strerror(errno));
return;
}
memcpy(str, path, len);
char *end = str + len - 1;
if (*end++ != '/')
*end++ = '/';
*end = '\0';
includePaths[nbIncPaths++] = str;
}
static void printDep(char const *path)
{
if (dependfile) {
fprintf(dependfile, "%s: %s\n", tzTargetFileName, path);
if (oGeneratePhonyDeps)
fprintf(dependfile, "%s:\n", path);
}
}
FILE *
fstk_FindFile(char *fname)
static bool isPathValid(char const *path)
{
char path[PATH_MAX];
int i;
FILE *f;
struct stat statbuf;
if ((f = fopen(fname, "rb")) != NULL || errno != ENOENT) {
if (dependfile) {
fprintf(dependfile, "%s: %s\n", tzObjectname, fname);
}
return f;
if (stat(path, &statbuf) != 0)
return false;
/* Reject directories */
return !S_ISDIR(statbuf.st_mode);
}
bool fstk_FindFile(char const *path, char **fullPath, size_t *size)
{
if (!*size) {
*size = 64; /* This is arbitrary, really */
*fullPath = realloc(*fullPath, *size);
if (!*fullPath)
error("realloc error during include path search: %s\n",
strerror(errno));
}
for (i = 0; i < NextIncPath; ++i) {
if (strlcpy(path, IncludePaths[i], sizeof path) >=
sizeof path) {
continue;
}
if (strlcat(path, fname, sizeof path) >= sizeof path) {
continue;
}
if (*fullPath) {
for (size_t i = 0; i <= nbIncPaths; ++i) {
char const *incPath = i ? includePaths[i - 1] : "";
int len = snprintf(*fullPath, *size, "%s%s", incPath, path);
if ((f = fopen(path, "rb")) != NULL || errno != ENOENT) {
if (dependfile) {
fprintf(dependfile, "%s: %s\n", tzObjectname, path);
if (len < 0) {
error("snprintf error during include path search: %s\n",
strerror(errno));
break;
}
/* Oh how I wish `asnprintf` was standard... */
if ((size_t)len >= *size) { /* `len` doesn't include the terminator, `size` does */
*size = len + 1;
*fullPath = realloc(*fullPath, *size);
if (!*fullPath) {
error("realloc error during include path search: %s\n",
strerror(errno));
break;
}
len = sprintf(*fullPath, "%s%s", incPath, path);
}
if (isPathValid(*fullPath)) {
printDep(*fullPath);
return true;
}
return f;
}
}
errno = ENOENT;
return NULL;
if (oGeneratedMissingIncludes)
printDep(path);
return false;
}
bool yywrap(void)
{
uint32_t nIFDepth = lexer_GetIFDepth();
if (nIFDepth != 0)
fatalerror("Ended block with %" PRIu32 " unterminated IF construct%s\n",
nIFDepth, nIFDepth == 1 ? "" : "s");
if (contextStack->fileInfo->type == NODE_REPT) { /* The context is a REPT block, which may loop */
struct FileStackReptNode *fileInfo = (struct FileStackReptNode *)contextStack->fileInfo;
/* If the node is referenced, we can't edit it; duplicate it */
if (contextStack->fileInfo->referenced) {
size_t size = sizeof(*fileInfo) + sizeof(fileInfo->iters[0]) * fileInfo->reptDepth;
struct FileStackReptNode *copy = malloc(size);
if (!copy)
fatalerror("Failed to duplicate REPT file node: %s\n", strerror(errno));
/* Copy all info but the referencing */
memcpy(copy, fileInfo, size);
copy->node.next = NULL;
copy->node.referenced = false;
fileInfo = copy;
contextStack->fileInfo = (struct FileStackNode *)fileInfo;
}
/* If this is a FOR, update the symbol value */
if (contextStack->forName && fileInfo->iters[0] <= contextStack->nbReptIters) {
contextStack->forValue += contextStack->forStep;
struct Symbol *sym = sym_AddSet(contextStack->forName,
contextStack->forValue);
/* This error message will refer to the current iteration */
if (sym->type != SYM_SET)
fatalerror("Failed to update FOR symbol value\n");
}
/* Advance to the next iteration */
fileInfo->iters[0]++;
/* If this wasn't the last iteration, wrap instead of popping */
if (fileInfo->iters[0] <= contextStack->nbReptIters) {
lexer_RestartRept(contextStack->fileInfo->lineNo);
contextStack->uniqueID = macro_UseNewUniqueID();
return false;
}
} else if (!contextStack->parent) {
return true;
}
dbgPrint("Popping context\n");
struct Context *context = contextStack;
contextStack = contextStack->parent;
assert(contextDepth != 0); // This is never supposed to underflow
contextDepth--;
lexer_DeleteState(context->lexerState);
/* Restore args if a macro (not REPT) saved them */
if (context->fileInfo->type == NODE_MACRO) {
dbgPrint("Restoring macro args %p\n", (void *)contextStack->macroArgs);
macro_UseNewArgs(contextStack->macroArgs);
}
/* Free the file stack node */
if (!context->fileInfo->referenced)
free(context->fileInfo);
/* Free the FOR symbol name */
free(context->forName);
/* Free the entry and make its parent the current entry */
free(context);
lexer_SetState(contextStack->lexerState);
macro_SetUniqueID(contextStack->uniqueID);
return false;
}
/*
* Set up an include file for parsing
* Make sure not to switch the lexer state before calling this, so the saved line no is correct
* BE CAREFUL!! This modifies the file stack directly, you should have set up the file info first
* Callers should set contextStack->lexerState after this so it is not NULL
*/
void
fstk_RunInclude(char *tzFileName)
static void newContext(struct FileStackNode *fileInfo)
{
FILE *f;
if (++contextDepth >= nMaxRecursionDepth)
fatalerror("Recursion limit (%zu) exceeded\n", nMaxRecursionDepth);
struct Context *context = malloc(sizeof(*context));
f = fstk_FindFile(tzFileName);
if (!context)
fatalerror("Failed to allocate memory for new context: %s\n", strerror(errno));
fileInfo->parent = contextStack->fileInfo;
fileInfo->lineNo = 0; /* Init to a default value, see struct definition for info */
fileInfo->referenced = false;
fileInfo->lineNo = lexer_GetLineNo();
context->fileInfo = fileInfo;
context->forName = NULL;
/*
* Link new entry to its parent so it's reachable later
* ERRORS SHOULD NOT OCCUR AFTER THIS!!
*/
context->parent = contextStack;
contextStack = context;
}
if (f == NULL) {
err(1, "Unable to open included file '%s'",
tzFileName);
void fstk_RunInclude(char const *path)
{
dbgPrint("Including path \"%s\"\n", path);
char *fullPath = NULL;
size_t size = 0;
if (!fstk_FindFile(path, &fullPath, &size)) {
free(fullPath);
if (oGeneratedMissingIncludes) {
if (verbose)
printf("Aborting (-MG) on INCLUDE file '%s' (%s)\n",
path, strerror(errno));
oFailedOnMissingInclude = true;
} else {
error("Unable to open included file '%s': %s\n", path, strerror(errno));
}
return;
}
dbgPrint("Full path: \"%s\"\n", fullPath);
struct FileStackNamedNode *fileInfo = malloc(sizeof(*fileInfo) + size);
if (!fileInfo) {
error("Failed to alloc file info for INCLUDE: %s\n", strerror(errno));
return;
}
fileInfo->node.type = NODE_FILE;
strcpy(fileInfo->name, fullPath);
free(fullPath);
newContext((struct FileStackNode *)fileInfo);
contextStack->lexerState = lexer_OpenFile(fileInfo->name);
if (!contextStack->lexerState)
fatalerror("Failed to set up lexer for file include\n");
lexer_SetStateAtEOL(contextStack->lexerState);
/* We're back at top-level, so most things are reset */
contextStack->uniqueID = 0;
macro_SetUniqueID(0);
}
void fstk_RunMacro(char const *macroName, struct MacroArgs *args)
{
dbgPrint("Running macro \"%s\"\n", macroName);
struct Symbol *macro = sym_FindExactSymbol(macroName);
if (!macro) {
error("Macro \"%s\" not defined\n", macroName);
return;
}
if (macro->type != SYM_MACRO) {
error("\"%s\" is not a macro\n", macroName);
return;
}
contextStack->macroArgs = macro_GetCurrentArgs();
/* Compute total length of this node's name: <base name>::<macro> */
size_t reptNameLen = 0;
struct FileStackNode const *node = macro->src;
if (node->type == NODE_REPT) {
struct FileStackReptNode const *reptNode = (struct FileStackReptNode const *)node;
/* 4294967295 = 2^32 - 1, aka UINT32_MAX */
reptNameLen += reptNode->reptDepth * strlen("::REPT~4294967295");
/* Look for next named node */
do {
node = node->parent;
} while (node->type == NODE_REPT);
}
struct FileStackNamedNode const *baseNode = (struct FileStackNamedNode const *)node;
size_t baseLen = strlen(baseNode->name);
size_t macroNameLen = strlen(macro->name);
struct FileStackNamedNode *fileInfo = malloc(sizeof(*fileInfo) + baseLen
+ reptNameLen + 2 + macroNameLen + 1);
if (!fileInfo) {
error("Failed to alloc file info for \"%s\": %s\n", macro->name, strerror(errno));
return;
}
fileInfo->node.type = NODE_MACRO;
/* Print the name... */
char *dest = fileInfo->name;
memcpy(dest, baseNode->name, baseLen);
dest += baseLen;
if (node->type == NODE_REPT) {
struct FileStackReptNode const *reptNode = (struct FileStackReptNode const *)node;
for (uint32_t i = reptNode->reptDepth; i--; ) {
int nbChars = sprintf(dest, "::REPT~%" PRIu32, reptNode->iters[i]);
if (nbChars < 0)
fatalerror("Failed to write macro invocation info: %s\n",
strerror(errno));
dest += nbChars;
}
}
*dest++ = ':';
*dest++ = ':';
memcpy(dest, macro->name, macroNameLen + 1);
newContext((struct FileStackNode *)fileInfo);
contextStack->lexerState = lexer_OpenFileView(macro->macro, macro->macroSize,
macro->fileLine);
if (!contextStack->lexerState)
fatalerror("Failed to set up lexer for macro invocation\n");
lexer_SetStateAtEOL(contextStack->lexerState);
contextStack->uniqueID = macro_UseNewUniqueID();
macro_UseNewArgs(args);
}
static bool newReptContext(int32_t reptLineNo, char *body, size_t size)
{
uint32_t reptDepth = contextStack->fileInfo->type == NODE_REPT
? ((struct FileStackReptNode *)contextStack->fileInfo)->reptDepth
: 0;
struct FileStackReptNode *fileInfo = malloc(sizeof(*fileInfo)
+ (reptDepth + 1) * sizeof(fileInfo->iters[0]));
if (!fileInfo) {
error("Failed to alloc file info for REPT: %s\n", strerror(errno));
return false;
}
fileInfo->node.type = NODE_REPT;
fileInfo->reptDepth = reptDepth + 1;
fileInfo->iters[0] = 1;
if (reptDepth)
/* Copy all parent iter counts */
memcpy(&fileInfo->iters[1],
((struct FileStackReptNode *)contextStack->fileInfo)->iters,
reptDepth * sizeof(fileInfo->iters[0]));
newContext((struct FileStackNode *)fileInfo);
/* Correct our line number, which currently points to the `ENDR` line */
contextStack->fileInfo->lineNo = reptLineNo;
contextStack->lexerState = lexer_OpenFileView(body, size, reptLineNo);
if (!contextStack->lexerState)
fatalerror("Failed to set up lexer for REPT block\n");
lexer_SetStateAtEOL(contextStack->lexerState);
contextStack->uniqueID = macro_UseNewUniqueID();
return true;
}
void fstk_RunRept(uint32_t count, int32_t reptLineNo, char *body, size_t size)
{
dbgPrint("Running REPT(%" PRIu32 ")\n", count);
if (count == 0)
return;
if (!newReptContext(reptLineNo, body, size))
return;
contextStack->nbReptIters = count;
contextStack->forName = NULL;
}
void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
int32_t reptLineNo, char *body, size_t size)
{
dbgPrint("Running FOR(\"%s\", %" PRId32 ", %" PRId32 ", %" PRId32 ")\n",
symName, start, stop, step);
struct Symbol *sym = sym_AddSet(symName, start);
if (sym->type != SYM_SET)
return;
uint32_t count = 0;
if (step > 0 && start < stop)
count = (stop - start - 1) / step + 1;
else if (step < 0 && stop < start)
count = (start - stop - 1) / -step + 1;
else if (step == 0)
error("FOR cannot have a step value of 0\n");
if (count == 0)
return;
if (!newReptContext(reptLineNo, body, size))
return;
contextStack->nbReptIters = count;
contextStack->forValue = start;
contextStack->forStep = step;
contextStack->forName = strdup(symName);
if (!contextStack->forName)
fatalerror("Not enough memory for FOR symbol name: %s\n", strerror(errno));
}
void fstk_StopRept(void)
{
/* Prevent more iterations */
contextStack->nbReptIters = 0;
}
bool fstk_Break(void)
{
dbgPrint("Breaking out of REPT/FOR\n");
if (contextStack->fileInfo->type != NODE_REPT) {
error("BREAK can only be used inside a REPT/FOR block\n");
return false;
}
pushcontext();
nLineNo = 1;
nCurrentStatus = STAT_isInclude;
strcpy(tzCurrentFileName, tzFileName);
pCurrentFile = f;
CurrentFlexHandle = yy_create_buffer(pCurrentFile);
yy_switch_to_buffer(CurrentFlexHandle);
//Dirty hack to give the INCLUDE directive a linefeed
yyunput('\n');
nLineNo -= 1;
fstk_StopRept();
return true;
}
/*
* Set up a macro for parsing
*/
ULONG
fstk_RunMacro(char *s)
void fstk_Init(char const *mainPath, size_t maxRecursionDepth)
{
struct sSymbol *sym;
struct LexerState *state = lexer_OpenFile(mainPath);
if ((sym = sym_FindMacro(s)) != NULL) {
pushcontext();
sym_SetMacroArgID(nMacroCount++);
nLineNo = -1;
sym_UseNewMacroArgs();
nCurrentStatus = STAT_isMacro;
strcpy(tzCurrentFileName, s);
if (sym->pMacro == NULL)
return 0;
pCurrentMacro = sym;
CurrentFlexHandle =
yy_scan_bytes(pCurrentMacro->pMacro,
strlen(pCurrentMacro->pMacro));
yy_switch_to_buffer(CurrentFlexHandle);
return (1);
} else
return (0);
}
if (!state)
fatalerror("Failed to open main file!\n");
lexer_SetState(state);
char const *fileName = lexer_GetFileName();
size_t len = strlen(fileName);
struct Context *context = malloc(sizeof(*contextStack));
struct FileStackNamedNode *fileInfo = malloc(sizeof(*fileInfo) + len + 1);
/*
* Set up a macroargument for parsing
*/
void
fstk_RunMacroArg(SLONG s)
{
char *sym;
if (!context)
fatalerror("Failed to allocate memory for main context: %s\n", strerror(errno));
if (!fileInfo)
fatalerror("Failed to allocate memory for main file info: %s\n", strerror(errno));
if (s == '@')
s = -1;
else
s -= '0';
context->fileInfo = (struct FileStackNode *)fileInfo;
/* lineNo and reptIter are unused on the top-level context */
context->fileInfo->parent = NULL;
context->fileInfo->lineNo = 0; // This still gets written to the object file, so init it
context->fileInfo->referenced = false;
context->fileInfo->type = NODE_FILE;
memcpy(fileInfo->name, fileName, len + 1);
if ((sym = sym_FindMacroArg(s)) != NULL) {
pushcontext();
nCurrentStatus = STAT_isMacroArg;
sprintf(tzCurrentFileName, "%c", (UBYTE) s);
CurrentFlexHandle = yy_scan_bytes(sym, strlen(sym));
yy_switch_to_buffer(CurrentFlexHandle);
} else
fatalerror("No such macroargument");
}
context->parent = NULL;
context->lexerState = state;
context->uniqueID = 0;
macro_SetUniqueID(0);
context->nbReptIters = 0;
context->forValue = 0;
context->forStep = 0;
context->forName = NULL;
/*
* Set up a stringequate for parsing
*/
void
fstk_RunString(char *s)
{
struct sSymbol *pSym;
/* Now that it's set up properly, register the context */
contextStack = context;
if ((pSym = sym_FindSymbol(s)) != NULL) {
pushcontext();
nCurrentStatus = STAT_isMacroArg;
strcpy(tzCurrentFileName, s);
CurrentFlexHandle =
yy_scan_bytes(pSym->pMacro, strlen(pSym->pMacro));
yy_switch_to_buffer(CurrentFlexHandle);
} else
yyerror("No such string symbol '%s'", s);
}
/*
* Set up a repeat block for parsing
*/
void
fstk_RunRept(ULONG count)
{
if (count) {
pushcontext();
sym_UseCurrentMacroArgs();
sym_SetMacroArgID(nMacroCount++);
sym_UseNewMacroArgs();
nCurrentREPTBlockCount = count;
nCurrentStatus = STAT_isREPTBlock;
nCurrentREPTBlockSize = ulNewMacroSize;
pCurrentREPTBlock = tzNewMacro;
CurrentFlexHandle =
yy_scan_bytes(pCurrentREPTBlock, nCurrentREPTBlockSize);
yy_switch_to_buffer(CurrentFlexHandle);
/*
* Check that max recursion depth won't allow overflowing node `malloc`s
* This assumes that the rept node is larger
*/
#define DEPTH_LIMIT ((SIZE_MAX - sizeof(struct FileStackReptNode)) / sizeof(uint32_t))
if (maxRecursionDepth > DEPTH_LIMIT) {
error("Recursion depth may not be higher than %zu, defaulting to "
EXPAND_AND_STR(DEFAULT_MAX_DEPTH) "\n", DEPTH_LIMIT);
nMaxRecursionDepth = DEFAULT_MAX_DEPTH;
} else {
nMaxRecursionDepth = maxRecursionDepth;
}
}
/*
* Initialize the filestack routines
*/
void
fstk_Init(char *s)
{
char tzFileName[_MAX_PATH + 1];
char tzSymFileName[_MAX_PATH + 1 + 2];
snprintf(tzSymFileName, sizeof(tzSymFileName), "\"%s\"", s);
sym_AddString("__FILE__", tzSymFileName);
strcpy(tzFileName, s);
pFileStack = NULL;
pCurrentFile = fopen(tzFileName, "rb");
if (pCurrentFile == NULL) {
err(1, "Unable to open file '%s'", tzFileName);
}
nMacroCount = 0;
nCurrentStatus = STAT_isInclude;
strcpy(tzCurrentFileName, tzFileName);
CurrentFlexHandle = yy_create_buffer(pCurrentFile);
yy_switch_to_buffer(CurrentFlexHandle);
nLineNo = 1;
/* Make sure that the default of 64 is OK, though */
assert(DEPTH_LIMIT >= DEFAULT_MAX_DEPTH);
#undef DEPTH_LIMIT
}
-522
View File
@@ -1,522 +0,0 @@
#include "asm/asm.h"
#include "asm/symbol.h"
#include "asm/rpn.h"
#include "asm/symbol.h"
#include "asm/main.h"
#include "asm/lexer.h"
#include "asmy.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
bool oDontExpandStrings = false;
SLONG nGBGfxID = -1;
SLONG nBinaryID = -1;
SLONG
gbgfx2bin(char ch)
{
SLONG i;
for (i = 0; i <= 3; i += 1) {
if (CurrentOptions.gbgfx[i] == ch) {
return (i);
}
}
return (0);
}
SLONG
binary2bin(char ch)
{
SLONG i;
for (i = 0; i <= 1; i += 1) {
if (CurrentOptions.binary[i] == ch) {
return (i);
}
}
return (0);
}
SLONG
char2bin(char ch)
{
if (ch >= 'a' && ch <= 'f')
return (ch - 'a' + 10);
if (ch >= 'A' && ch <= 'F')
return (ch - 'A' + 10);
if (ch >= '0' && ch <= '9')
return (ch - '0');
return (0);
}
typedef SLONG(*x2bin) (char ch);
SLONG
ascii2bin(char *s)
{
SLONG radix = 10;
SLONG result = 0;
x2bin convertfunc = char2bin;
switch (*s) {
case '$':
radix = 16;
s += 1;
convertfunc = char2bin;
break;
case '&':
radix = 8;
s += 1;
convertfunc = char2bin;
break;
case '`':
radix = 4;
s += 1;
convertfunc = gbgfx2bin;
break;
case '%':
radix = 2;
s += 1;
convertfunc = binary2bin;
break;
}
if (radix == 4) {
SLONG c;
while (*s != '\0') {
c = convertfunc(*s++);
result = result * 2 + ((c & 2) << 7) + (c & 1);
}
} else {
while (*s != '\0')
result = result * radix + convertfunc(*s++);
}
return (result);
}
ULONG
ParseFixedPoint(char *s, ULONG size)
{
//char dest[256];
ULONG i = 0, dot = 0;
while (size && dot != 2) {
if (s[i] == '.')
dot += 1;
if (dot < 2) {
//dest[i] = s[i];
size -= 1;
i += 1;
}
}
//dest[i] = 0;
yyunputbytes(size);
yylval.nConstValue = (SLONG) (atof(s) * 65536);
return (1);
}
ULONG
ParseNumber(char *s, ULONG size)
{
char dest[256];
strncpy(dest, s, size);
dest[size] = 0;
yylval.nConstValue = ascii2bin(dest);
return (1);
}
ULONG
ParseSymbol(char *src, ULONG size)
{
char dest[MAXSYMLEN + 1];
int copied = 0, size_backup = size;
while (size && copied < MAXSYMLEN) {
if (*src == '\\') {
char *marg;
src += 1;
size -= 1;
if (*src == '@')
marg = sym_FindMacroArg(-1);
else if (*src >= '0' && *src <= '9')
marg = sym_FindMacroArg(*src - '0');
else {
fatalerror("Malformed ID");
return (0);
}
src += 1;
size -= 1;
if (marg) {
while (*marg)
dest[copied++] = *marg++;
}
} else {
dest[copied++] = *src++;
size -= 1;
}
}
if (copied > MAXSYMLEN)
fatalerror("Symbol too long");
dest[copied] = 0;
if (!oDontExpandStrings && sym_isString(dest)) {
char *s;
yyskipbytes(size_backup);
yyunputstr(s = sym_GetStringValue(dest));
while (*s) {
if (*s++ == '\n') {
nLineNo -= 1;
}
}
return (0);
} else {
strcpy(yylval.tzString, dest);
return (1);
}
}
ULONG
PutMacroArg(char *src, ULONG size)
{
char *s;
yyskipbytes(size);
if ((size == 2 && src[1] >= '1' && src[1] <= '9')) {
if ((s = sym_FindMacroArg(src[1] - '0')) != NULL) {
yyunputstr(s);
} else {
yyerror("Macro argument not defined");
}
} else {
yyerror("Invalid macro argument");
}
return (0);
}
ULONG
PutUniqueArg(char *src, ULONG size)
{
char *s;
yyskipbytes(size);
if ((s = sym_FindMacroArg(-1)) != NULL) {
yyunputstr(s);
} else {
yyerror("Macro unique label string not defined");
}
return (0);
}
enum {
T_LEX_MACROARG = 3000,
T_LEX_MACROUNIQUE
};
extern struct sLexInitString localstrings[];
struct sLexInitString staticstrings[] = {
{"||", T_OP_LOGICOR},
{"&&", T_OP_LOGICAND},
{"==", T_OP_LOGICEQU},
{">", T_OP_LOGICGT},
{"<", T_OP_LOGICLT},
{">=", T_OP_LOGICGE},
{"<=", T_OP_LOGICLE},
{"!=", T_OP_LOGICNE},
{"!", T_OP_LOGICNOT},
{"|", T_OP_OR},
{"^", T_OP_XOR},
{"&", T_OP_AND},
{"<<", T_OP_SHL},
{">>", T_OP_SHR},
{"+", T_OP_ADD},
{"-", T_OP_SUB},
{"*", T_OP_MUL},
{"/", T_OP_DIV},
{"%", T_OP_MOD},
{"~", T_OP_NOT},
{"def", T_OP_DEF},
{"bank", T_OP_BANK},
{"align", T_OP_ALIGN},
{"round", T_OP_ROUND},
{"ceil", T_OP_CEIL},
{"floor", T_OP_FLOOR},
{"div", T_OP_FDIV},
{"mul", T_OP_FMUL},
{"sin", T_OP_SIN},
{"cos", T_OP_COS},
{"tan", T_OP_TAN},
{"asin", T_OP_ASIN},
{"acos", T_OP_ACOS},
{"atan", T_OP_ATAN},
{"atan2", T_OP_ATAN2},
{"high", T_OP_HIGH},
{"low", T_OP_LOW},
{"strcmp", T_OP_STRCMP},
{"strin", T_OP_STRIN},
{"strsub", T_OP_STRSUB},
{"strlen", T_OP_STRLEN},
{"strcat", T_OP_STRCAT},
{"strupr", T_OP_STRUPR},
{"strlwr", T_OP_STRLWR},
{"include", T_POP_INCLUDE},
{"printt", T_POP_PRINTT},
{"printv", T_POP_PRINTV},
{"printf", T_POP_PRINTF},
{"export", T_POP_EXPORT},
{"xdef", T_POP_EXPORT},
{"import", T_POP_IMPORT},
{"xref", T_POP_IMPORT},
{"global", T_POP_GLOBAL},
{"ds", T_POP_DS},
{NAME_DB, T_POP_DB},
{NAME_DW, T_POP_DW},
{"section", T_POP_SECTION},
{"purge", T_POP_PURGE},
{"rsreset", T_POP_RSRESET},
{"rsset", T_POP_RSSET},
{"incbin", T_POP_INCBIN},
{"charmap", T_POP_CHARMAP},
{"fail", T_POP_FAIL},
{"warn", T_POP_WARN},
{"macro", T_POP_MACRO},
/* Not needed but we have it here just to protect the name */
{"endm", T_POP_ENDM},
{"shift", T_POP_SHIFT},
{"rept", T_POP_REPT},
/* Not needed but we have it here just to protect the name */
{"endr", T_POP_ENDR},
{"if", T_POP_IF},
{"else", T_POP_ELSE},
{"elif", T_POP_ELIF},
{"endc", T_POP_ENDC},
{"union", T_POP_UNION},
{"nextu", T_POP_NEXTU},
{"endu", T_POP_ENDU},
{"wram0", T_SECT_WRAM0},
{"vram", T_SECT_VRAM},
{"romx", T_SECT_ROMX},
{"rom0", T_SECT_ROM0},
{"hram", T_SECT_HRAM},
{"wramx", T_SECT_WRAMX},
{"sram", T_SECT_SRAM},
{"oam", T_SECT_OAM},
/* Deprecated section type names */
{"home", T_SECT_HOME},
{"code", T_SECT_CODE},
{"data", T_SECT_DATA},
{"bss", T_SECT_BSS},
{NAME_RB, T_POP_RB},
{NAME_RW, T_POP_RW},
{"equ", T_POP_EQU},
{"equs", T_POP_EQUS},
{"set", T_POP_SET},
{"=", T_POP_SET},
{"pushs", T_POP_PUSHS},
{"pops", T_POP_POPS},
{"pusho", T_POP_PUSHO},
{"popo", T_POP_POPO},
{"opt", T_POP_OPT},
{NULL, 0}
};
struct sLexFloat tNumberToken = {
ParseNumber,
T_NUMBER
};
struct sLexFloat tFixedPointToken = {
ParseFixedPoint,
T_NUMBER
};
struct sLexFloat tIDToken = {
ParseSymbol,
T_ID
};
struct sLexFloat tMacroArgToken = {
PutMacroArg,
T_LEX_MACROARG
};
struct sLexFloat tMacroUniqueToken = {
PutUniqueArg,
T_LEX_MACROUNIQUE
};
void
setuplex(void)
{
ULONG id;
lex_Init();
lex_AddStrings(staticstrings);
lex_AddStrings(localstrings);
//Macro arguments
id = lex_FloatAlloc(&tMacroArgToken);
lex_FloatAddFirstRange(id, '\\', '\\');
lex_FloatAddSecondRange(id, '1', '9');
id = lex_FloatAlloc(&tMacroUniqueToken);
lex_FloatAddFirstRange(id, '\\', '\\');
lex_FloatAddSecondRange(id, '@', '@');
//Decimal constants
id = lex_FloatAlloc(&tNumberToken);
lex_FloatAddFirstRange(id, '0', '9');
lex_FloatAddSecondRange(id, '0', '9');
lex_FloatAddRange(id, '0', '9');
//Binary constants
nBinaryID = id = lex_FloatAlloc(&tNumberToken);
lex_FloatAddFirstRange(id, '%', '%');
lex_FloatAddSecondRange(id, CurrentOptions.binary[0],
CurrentOptions.binary[0]);
lex_FloatAddSecondRange(id, CurrentOptions.binary[1],
CurrentOptions.binary[1]);
lex_FloatAddRange(id, CurrentOptions.binary[0],
CurrentOptions.binary[0]);
lex_FloatAddRange(id, CurrentOptions.binary[1],
CurrentOptions.binary[1]);
//Octal constants
id = lex_FloatAlloc(&tNumberToken);
lex_FloatAddFirstRange(id, '&', '&');
lex_FloatAddSecondRange(id, '0', '7');
lex_FloatAddRange(id, '0', '7');
//Gameboy gfx constants
nGBGfxID = id = lex_FloatAlloc(&tNumberToken);
lex_FloatAddFirstRange(id, '`', '`');
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[0],
CurrentOptions.gbgfx[0]);
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[1],
CurrentOptions.gbgfx[1]);
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[2],
CurrentOptions.gbgfx[2]);
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[3],
CurrentOptions.gbgfx[3]);
lex_FloatAddRange(id, CurrentOptions.gbgfx[0], CurrentOptions.gbgfx[0]);
lex_FloatAddRange(id, CurrentOptions.gbgfx[1], CurrentOptions.gbgfx[1]);
lex_FloatAddRange(id, CurrentOptions.gbgfx[2], CurrentOptions.gbgfx[2]);
lex_FloatAddRange(id, CurrentOptions.gbgfx[3], CurrentOptions.gbgfx[3]);
//Hex constants
id = lex_FloatAlloc(&tNumberToken);
lex_FloatAddFirstRange(id, '$', '$');
lex_FloatAddSecondRange(id, '0', '9');
lex_FloatAddSecondRange(id, 'A', 'F');
lex_FloatAddSecondRange(id, 'a', 'f');
lex_FloatAddRange(id, '0', '9');
lex_FloatAddRange(id, 'A', 'F');
lex_FloatAddRange(id, 'a', 'f');
//ID 's
id = lex_FloatAlloc(&tIDToken);
lex_FloatAddFirstRange(id, 'a', 'z');
lex_FloatAddFirstRange(id, 'A', 'Z');
lex_FloatAddFirstRange(id, '_', '_');
lex_FloatAddSecondRange(id, 'a', 'z');
lex_FloatAddSecondRange(id, 'A', 'Z');
lex_FloatAddSecondRange(id, '0', '9');
lex_FloatAddSecondRange(id, '_', '_');
lex_FloatAddSecondRange(id, '\\', '\\');
lex_FloatAddSecondRange(id, '@', '@');
lex_FloatAddSecondRange(id, '#', '#');
lex_FloatAddRange(id, '.', '.');
lex_FloatAddRange(id, 'a', 'z');
lex_FloatAddRange(id, 'A', 'Z');
lex_FloatAddRange(id, '0', '9');
lex_FloatAddRange(id, '_', '_');
lex_FloatAddRange(id, '\\', '\\');
lex_FloatAddRange(id, '@', '@');
lex_FloatAddRange(id, '#', '#');
//Local ID
id = lex_FloatAlloc(&tIDToken);
lex_FloatAddFirstRange(id, '.', '.');
lex_FloatAddSecondRange(id, 'a', 'z');
lex_FloatAddSecondRange(id, 'A', 'Z');
lex_FloatAddSecondRange(id, '_', '_');
lex_FloatAddRange(id, 'a', 'z');
lex_FloatAddRange(id, 'A', 'Z');
lex_FloatAddRange(id, '0', '9');
lex_FloatAddRange(id, '_', '_');
lex_FloatAddRange(id, '\\', '\\');
lex_FloatAddRange(id, '@', '@');
lex_FloatAddRange(id, '#', '#');
//@ID
id = lex_FloatAlloc(&tIDToken);
lex_FloatAddFirstRange(id, '@', '@');
//Fixed point constants
id = lex_FloatAlloc(&tFixedPointToken);
lex_FloatAddFirstRange(id, '.', '.');
lex_FloatAddFirstRange(id, '0', '9');
lex_FloatAddSecondRange(id, '.', '.');
lex_FloatAddSecondRange(id, '0', '9');
lex_FloatAddRange(id, '.', '.');
lex_FloatAddRange(id, '0', '9');
}
+2595 -671
View File
File diff suppressed because it is too large Load Diff
-89
View File
@@ -1,89 +0,0 @@
#include "asm/symbol.h"
#include "asm/lexer.h"
#include "asm/rpn.h"
#include "asmy.h"
struct sLexInitString localstrings[] = {
{"adc", T_Z80_ADC},
{"add", T_Z80_ADD},
{"and", T_Z80_AND},
{"bit", T_Z80_BIT},
{"call", T_Z80_CALL},
{"ccf", T_Z80_CCF},
{"cpl", T_Z80_CPL},
{"cp", T_Z80_CP},
{"daa", T_Z80_DAA},
{"dec", T_Z80_DEC},
{"di", T_Z80_DI},
{"ei", T_Z80_EI},
{"halt", T_Z80_HALT},
{"inc", T_Z80_INC},
{"jp", T_Z80_JP},
{"jr", T_Z80_JR},
{"ld", T_Z80_LD},
{"ldi", T_Z80_LDI},
{"ldd", T_Z80_LDD},
{"ldio", T_Z80_LDIO},
{"ldh", T_Z80_LDIO},
{"nop", T_Z80_NOP},
{"or", T_Z80_OR},
{"pop", T_Z80_POP},
{"push", T_Z80_PUSH},
{"res", T_Z80_RES},
{"reti", T_Z80_RETI},
{"ret", T_Z80_RET},
{"rlca", T_Z80_RLCA},
{"rlc", T_Z80_RLC},
{"rla", T_Z80_RLA},
{"rl", T_Z80_RL},
{"rrc", T_Z80_RRC},
{"rrca", T_Z80_RRCA},
{"rra", T_Z80_RRA},
{"rr", T_Z80_RR},
{"rst", T_Z80_RST},
{"sbc", T_Z80_SBC},
{"scf", T_Z80_SCF},
/* Handled by globallex.c */
/* { "set", T_POP_SET }, */
{"sla", T_Z80_SLA},
{"sra", T_Z80_SRA},
{"srl", T_Z80_SRL},
{"stop", T_Z80_STOP},
{"sub", T_Z80_SUB},
{"swap", T_Z80_SWAP},
{"xor", T_Z80_XOR},
{"nz", T_CC_NZ},
{"z", T_CC_Z},
{"nc", T_CC_NC},
/* { "c", T_TOKEN_C }, */
{"[bc]", T_MODE_BC_IND},
{"[de]", T_MODE_DE_IND},
{"[hl]", T_MODE_HL_IND},
{"[hl+]", T_MODE_HL_INDINC},
{"[hl-]", T_MODE_HL_INDDEC},
{"[hli]", T_MODE_HL_INDINC},
{"[hld]", T_MODE_HL_INDDEC},
{"[sp]", T_MODE_SP_IND},
{"af", T_MODE_AF},
{"bc", T_MODE_BC},
{"de", T_MODE_DE},
{"hl", T_MODE_HL},
{"sp", T_MODE_SP},
{"[c]", T_MODE_C_IND},
{"[$ff00+c]", T_MODE_C_IND},
{"a", T_TOKEN_A},
{"b", T_TOKEN_B},
{"c", T_TOKEN_C},
{"d", T_TOKEN_D},
{"e", T_TOKEN_E},
{"h", T_TOKEN_H},
{"l", T_TOKEN_L},
{NULL, 0}
};
+190
View File
@@ -0,0 +1,190 @@
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asm/macro.h"
#include "asm/warning.h"
#define MAXMACROARGS 99999
/*
* Your average macro invocation does not go past the tens, but some go further
* This ensures that sane and slightly insane invocations suffer no penalties,
* and the rest is insane and thus will assume responsibility.
* Additionally, ~300 bytes (on x64) of memory per level of nesting has been
* deemed reasonable. (Halve that on x86.)
*/
#define INITIAL_ARG_SIZE 32
struct MacroArgs {
unsigned int nbArgs;
unsigned int shift;
unsigned int capacity;
char *args[];
};
#define SIZEOF_ARGS(nbArgs) (sizeof(struct MacroArgs) + \
sizeof(((struct MacroArgs){0}).args[0]) * (nbArgs))
static struct MacroArgs *macroArgs = NULL;
static uint32_t uniqueID = 0;
static uint32_t maxUniqueID = 0;
/*
* The initialization is somewhat harmful, since it is never used, but it
* guarantees the size of the buffer will be correct. I was unable to find a
* better solution, but if you have one, please feel free!
*/
static char uniqueIDBuf[] = "_u4294967295"; // UINT32_MAX
static char *uniqueIDPtr = NULL;
struct MacroArgs *macro_GetCurrentArgs(void)
{
return macroArgs;
}
struct MacroArgs *macro_NewArgs(void)
{
struct MacroArgs *args = malloc(SIZEOF_ARGS(INITIAL_ARG_SIZE));
if (!args)
fatalerror("Unable to register macro arguments: %s\n", strerror(errno));
args->nbArgs = 0;
args->shift = 0;
args->capacity = INITIAL_ARG_SIZE;
return args;
}
void macro_AppendArg(struct MacroArgs **argPtr, char *s)
{
#define macArgs (*argPtr)
if (s[0] == '\0')
warning(WARNING_EMPTY_MACRO_ARG, "Empty macro argument\n");
if (macArgs->nbArgs == MAXMACROARGS)
error("A maximum of " EXPAND_AND_STR(MAXMACROARGS) " arguments is allowed\n");
if (macArgs->nbArgs >= macArgs->capacity) {
macArgs->capacity *= 2;
/* Check that overflow didn't roll us back */
if (macArgs->capacity <= macArgs->nbArgs)
fatalerror("Failed to add new macro argument: capacity overflow\n");
macArgs = realloc(macArgs, SIZEOF_ARGS(macArgs->capacity));
if (!macArgs)
fatalerror("Error adding new macro argument: %s\n", strerror(errno));
}
macArgs->args[macArgs->nbArgs++] = s;
#undef macArgs
}
void macro_UseNewArgs(struct MacroArgs *args)
{
macroArgs = args;
}
void macro_FreeArgs(struct MacroArgs *args)
{
for (uint32_t i = 0; i < macroArgs->nbArgs; i++)
free(args->args[i]);
}
char const *macro_GetArg(uint32_t i)
{
if (!macroArgs)
return NULL;
uint32_t realIndex = i + macroArgs->shift - 1;
return realIndex >= macroArgs->nbArgs ? NULL
: macroArgs->args[realIndex];
}
char *macro_GetAllArgs(void)
{
if (!macroArgs)
return NULL;
if (macroArgs->shift >= macroArgs->nbArgs)
return "";
size_t len = 0;
for (uint32_t i = macroArgs->shift; i < macroArgs->nbArgs; i++)
len += strlen(macroArgs->args[i]) + 1; /* 1 for comma */
char *str = malloc(len + 1); /* 1 for '\0' */
char *ptr = str;
if (!str)
fatalerror("Failed to allocate memory for expanding '\\#': %s\n", strerror(errno));
for (uint32_t i = macroArgs->shift; i < macroArgs->nbArgs; i++) {
size_t n = strlen(macroArgs->args[i]);
memcpy(ptr, macroArgs->args[i], n);
ptr += n;
/* Commas go between args and after a last empty arg */
if (i < macroArgs->nbArgs - 1 || n == 0)
*ptr++ = ','; /* no space after comma */
}
*ptr = '\0';
return str;
}
uint32_t macro_GetUniqueID(void)
{
return uniqueID;
}
char const *macro_GetUniqueIDStr(void)
{
return uniqueIDPtr;
}
void macro_SetUniqueID(uint32_t id)
{
uniqueID = id;
if (id == 0) {
uniqueIDPtr = NULL;
} else {
if (uniqueID > maxUniqueID)
maxUniqueID = uniqueID;
/* The buffer is guaranteed to be the correct size */
/* This is a valid label fragment, but not a valid numeric */
sprintf(uniqueIDBuf, "_u%" PRIu32, id);
uniqueIDPtr = uniqueIDBuf;
}
}
uint32_t macro_UseNewUniqueID(void)
{
macro_SetUniqueID(++maxUniqueID);
return maxUniqueID;
}
void macro_ShiftCurrentArgs(int32_t count)
{
if (!macroArgs) {
error("Cannot shift macro arguments outside of a macro\n");
} else if (count > 0 && ((uint32_t)count > macroArgs->nbArgs
|| macroArgs->shift > macroArgs->nbArgs - count)) {
warning(WARNING_MACRO_SHIFT,
"Cannot shift macro arguments past their end\n");
macroArgs->shift = macroArgs->nbArgs;
} else if (count < 0 && macroArgs->shift < (uint32_t)-count) {
warning(WARNING_MACRO_SHIFT,
"Cannot shift macro arguments past their beginning\n");
macroArgs->shift = 0;
} else {
macroArgs->shift += count;
}
}
uint32_t macro_NbArgs(void)
{
return macroArgs->nbArgs - macroArgs->shift;
}
+284 -409
View File
@@ -1,492 +1,367 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#include <ctype.h>
#include <errno.h>
#include <float.h>
#include <inttypes.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "asm/symbol.h"
#include "asm/charmap.h"
#include "asm/format.h"
#include "asm/fstack.h"
#include "asm/output.h"
#include "asm/lexer.h"
#include "asm/main.h"
#include "asm/opt.h"
#include "asm/output.h"
#include "asm/rpn.h"
#include "asm/symbol.h"
#include "asm/warning.h"
#include "parser.h"
#include "extern/err.h"
#include "extern/reallocarray.h"
#include "extern/version.h"
#include "extern/getopt.h"
#include "helpers.h"
#include "version.h"
// Old Bison versions (confirmed for 2.3) do not forward-declare `yyparse` in the generated header
// Unfortunately, macOS still ships 2.3, which is from 2008...
int yyparse(void);
void setuplex(void);
int cldefines_index;
int cldefines_size;
char **cldefines;
clock_t nStartClock, nEndClock;
SLONG nLineNo;
ULONG nTotalLines, nPass, nPC, nIFDepth, nUnionDepth, nErrors;
bool skipElif;
ULONG unionStart[128], unionSize[128];
#if defined(YYDEBUG) && YYDEBUG
extern int yydebug;
#endif
FILE *dependfile;
extern char *tzObjectname;
FILE * dependfile;
bool oGeneratedMissingIncludes;
bool oFailedOnMissingInclude;
bool oGeneratePhonyDeps;
char *tzTargetFileName;
bool haltnop;
bool optimizeloads;
bool verbose;
bool warnings; /* True to enable warnings, false to disable them. */
/* Escapes Make-special chars from a string */
static char *make_escape(const char *str)
{
char * const escaped_str = malloc(strlen(str) * 2 + 1);
char *dest = escaped_str;
if (escaped_str == NULL)
err(1, "%s: Failed to allocate memory", __func__);
while (*str) {
/* All dollars needs to be doubled */
if (*str == '$')
*dest++ = '$';
*dest++ = *str++;
}
*dest = '\0';
return escaped_str;
}
/* Short options */
static const char *optstring = "b:D:Eg:hi:LM:o:p:r:VvW:w";
/* Variables for the long-only options */
static int depType; /* Variants of `-M` */
/*
* Option stack
* Equivalent long options
* Please keep in the same order as short opts
*
* Also, make sure long opts don't create ambiguity:
* A long opt's name should start with the same letter as its short opt,
* except if it doesn't create any ambiguity (`verbose` versus `version`).
* This is because long opt matching, even to a single char, is prioritized
* over short opt matching
*/
struct sOptions DefaultOptions;
struct sOptions CurrentOptions;
struct sOptionStackEntry {
struct sOptions Options;
struct sOptionStackEntry *pNext;
static struct option const longopts[] = {
{ "binary-digits", required_argument, NULL, 'b' },
{ "define", required_argument, NULL, 'D' },
{ "export-all", no_argument, NULL, 'E' },
{ "gfx-chars", required_argument, NULL, 'g' },
{ "halt-without-nop", no_argument, NULL, 'h' },
{ "include", required_argument, NULL, 'i' },
{ "preserve-ld", no_argument, NULL, 'L' },
{ "dependfile", required_argument, NULL, 'M' },
{ "MG", no_argument, &depType, 'G' },
{ "MP", no_argument, &depType, 'P' },
{ "MT", required_argument, &depType, 'T' },
{ "MQ", required_argument, &depType, 'Q' },
{ "output", required_argument, NULL, 'o' },
{ "pad-value", required_argument, NULL, 'p' },
{ "recursion-depth", required_argument, NULL, 'r' },
{ "version", no_argument, NULL, 'V' },
{ "verbose", no_argument, NULL, 'v' },
{ "warning", required_argument, NULL, 'W' },
{ NULL, no_argument, NULL, 0 }
};
struct sOptionStackEntry *pOptionStack = NULL;
void
opt_SetCurrentOptions(struct sOptions * pOpt)
static void print_usage(void)
{
if (nGBGfxID != -1) {
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[0],
CurrentOptions.gbgfx[0]);
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[1],
CurrentOptions.gbgfx[1]);
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[2],
CurrentOptions.gbgfx[2]);
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[3],
CurrentOptions.gbgfx[3]);
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[0],
CurrentOptions.gbgfx[0]);
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[1],
CurrentOptions.gbgfx[1]);
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[2],
CurrentOptions.gbgfx[2]);
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[3],
CurrentOptions.gbgfx[3]);
}
if (nBinaryID != -1) {
lex_FloatDeleteRange(nBinaryID, CurrentOptions.binary[0],
CurrentOptions.binary[0]);
lex_FloatDeleteRange(nBinaryID, CurrentOptions.binary[1],
CurrentOptions.binary[1]);
lex_FloatDeleteSecondRange(nBinaryID, CurrentOptions.binary[0],
CurrentOptions.binary[0]);
lex_FloatDeleteSecondRange(nBinaryID, CurrentOptions.binary[1],
CurrentOptions.binary[1]);
}
CurrentOptions = *pOpt;
if (nGBGfxID != -1) {
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[0],
CurrentOptions.gbgfx[0]);
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[1],
CurrentOptions.gbgfx[1]);
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[2],
CurrentOptions.gbgfx[2]);
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[3],
CurrentOptions.gbgfx[3]);
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[0],
CurrentOptions.gbgfx[0]);
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[1],
CurrentOptions.gbgfx[1]);
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[2],
CurrentOptions.gbgfx[2]);
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[3],
CurrentOptions.gbgfx[3]);
}
if (nBinaryID != -1) {
lex_FloatAddRange(nBinaryID, CurrentOptions.binary[0],
CurrentOptions.binary[0]);
lex_FloatAddRange(nBinaryID, CurrentOptions.binary[1],
CurrentOptions.binary[1]);
lex_FloatAddSecondRange(nBinaryID, CurrentOptions.binary[0],
CurrentOptions.binary[0]);
lex_FloatAddSecondRange(nBinaryID, CurrentOptions.binary[1],
CurrentOptions.binary[1]);
}
}
void
opt_Parse(char *s)
{
struct sOptions newopt;
newopt = CurrentOptions;
switch (s[0]) {
case 'g':
if (strlen(&s[1]) == 4) {
newopt.gbgfx[0] = s[1];
newopt.gbgfx[1] = s[2];
newopt.gbgfx[2] = s[3];
newopt.gbgfx[3] = s[4];
} else {
errx(1, "Must specify exactly 4 characters for "
"option 'g'");
}
break;
case 'b':
if (strlen(&s[1]) == 2) {
newopt.binary[0] = s[1];
newopt.binary[1] = s[2];
} else {
errx(1, "Must specify exactly 2 characters for option "
"'b'");
}
break;
case 'z':
if (strlen(&s[1]) <= 2) {
int result;
result = sscanf(&s[1], "%lx", &newopt.fillchar);
if (!((result == EOF) || (result == 1))) {
errx(1, "Invalid argument for option 'z'");
}
} else {
errx(1, "Invalid argument for option 'z'");
exit(1);
}
break;
default:
fatalerror("Unknown option");
break;
}
opt_SetCurrentOptions(&newopt);
}
void
opt_Push(void)
{
struct sOptionStackEntry *pOpt;
if ((pOpt = malloc(sizeof(struct sOptionStackEntry))) != NULL) {
pOpt->Options = CurrentOptions;
pOpt->pNext = pOptionStack;
pOptionStack = pOpt;
} else
fatalerror("No memory for option stack");
}
void
opt_Pop(void)
{
if (pOptionStack) {
struct sOptionStackEntry *pOpt;
pOpt = pOptionStack;
opt_SetCurrentOptions(&(pOpt->Options));
pOptionStack = pOpt->pNext;
free(pOpt);
} else
fatalerror("No entries in the option stack");
}
void
opt_AddDefine(char *s)
{
char *value, *equals;
if(cldefines_index >= cldefines_size)
{
cldefines_size *= 2;
cldefines = reallocarray(cldefines, cldefines_size,
2 * sizeof(void *));
if(!cldefines)
{
fatalerror("No memory for command line defines");
}
}
equals = strchr(s, '=');
if(equals)
{
*equals = '\0';
value = equals + 1;
}
else
{
value = "1";
}
cldefines[cldefines_index++] = s;
cldefines[cldefines_index++] = value;
}
void
opt_ParseDefines()
{
int i;
for(i = 0; i < cldefines_index; i += 2)
{
sym_AddString(cldefines[i], cldefines[i + 1]);
}
}
/*
* Error handling
*/
void
verror(const char *fmt, va_list args)
{
fprintf(stderr, "ERROR: ");
fstk_Dump();
fprintf(stderr, ":\n\t");
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
nErrors += 1;
}
void
yyerror(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
verror(fmt, args);
va_end(args);
}
void
fatalerror(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
verror(fmt, args);
va_end(args);
exit(5);
}
void
warning(const char *fmt, ...)
{
if (!CurrentOptions.warnings)
return;
va_list args;
va_start(args, fmt);
fprintf(stderr, "warning: ");
fstk_Dump();
fprintf(stderr, ":\n\t");
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
}
static void
usage(void)
{
printf(
"Usage: rgbasm [-EhVvw] [-b chars] [-Dname[=value]] [-g chars] [-i path]\n"
" [-M dependfile] [-o outfile] [-p pad_value] file.asm\n");
fputs(
"Usage: rgbasm [-EhLVvw] [-b chars] [-D name[=value]] [-g chars] [-i path]\n"
" [-M depend_file] [-MG] [-MP] [-MT target_file] [-MQ target_file]\n"
" [-o out_file] [-p pad_value] [-r depth] [-W warning] <file>\n"
"Useful options:\n"
" -E, --export-all export all labels\n"
" -M, --dependfile <path> set the output dependency file\n"
" -o, --output <path> set the output object file\n"
" -p, --pad-value <value> set the value to use for `ds'\n"
" -V, --version print RGBASM version and exit\n"
" -W, --warning <warning> enable or disable warnings\n"
"\n"
"For help, use `man rgbasm' or go to https://rgbds.gbdev.io/docs/\n",
stderr);
exit(1);
}
int
main(int argc, char *argv[])
int main(int argc, char *argv[])
{
int ch;
char *ep;
struct sOptions newopt;
time_t now = time(NULL);
char const *sourceDateEpoch = getenv("SOURCE_DATE_EPOCH");
char *tzMainfile;
/*
* Support SOURCE_DATE_EPOCH for reproducible builds
* https://reproducible-builds.org/docs/source-date-epoch/
*/
if (sourceDateEpoch)
now = (time_t)strtoul(sourceDateEpoch, NULL, 0);
dependfile = NULL;
cldefines_size = 32;
cldefines = reallocarray(cldefines, cldefines_size,
2 * sizeof(void *));
if(!cldefines)
{
fatalerror("No memory for command line defines");
}
#if defined(YYDEBUG) && YYDEBUG
yydebug = 1;
#endif
if (argc == 1)
usage();
// Perform some init for below
sym_Init(now);
/* yydebug=1; */
// Set defaults
DefaultOptions.gbgfx[0] = '0';
DefaultOptions.gbgfx[1] = '1';
DefaultOptions.gbgfx[2] = '2';
DefaultOptions.gbgfx[3] = '3';
DefaultOptions.binary[0] = '0';
DefaultOptions.binary[1] = '1';
DefaultOptions.fillchar = 0;
DefaultOptions.verbose = false;
DefaultOptions.haltnop = true;
DefaultOptions.exportall = false;
DefaultOptions.warnings = true;
oGeneratePhonyDeps = false;
oGeneratedMissingIncludes = false;
oFailedOnMissingInclude = false;
tzTargetFileName = NULL;
opt_SetCurrentOptions(&DefaultOptions);
opt_B("01");
opt_G("0123");
opt_P(0);
optimizeloads = true;
haltnop = true;
verbose = false;
warnings = true;
sym_SetExportAll(false);
uint32_t maxRecursionDepth = 64;
size_t nTargetFileNameLen = 0;
newopt = CurrentOptions;
while ((ch = getopt(argc, argv, "b:D:g:hi:M:o:p:EVvw")) != -1) {
while ((ch = musl_getopt_long_only(argc, argv, optstring, longopts, NULL)) != -1) {
switch (ch) {
case 'b':
if (strlen(optarg) == 2) {
newopt.binary[0] = optarg[1];
newopt.binary[1] = optarg[2];
} else {
errx(1, "Must specify exactly 2 characters for "
"option 'b'");
}
if (strlen(musl_optarg) == 2)
opt_B(&musl_optarg[1]);
else
errx(1, "Must specify exactly 2 characters for option 'b'");
break;
char *equals;
case 'D':
opt_AddDefine(optarg);
break;
case 'E':
newopt.exportall = true;
break;
case 'g':
if (strlen(optarg) == 4) {
newopt.gbgfx[0] = optarg[1];
newopt.gbgfx[1] = optarg[2];
newopt.gbgfx[2] = optarg[3];
newopt.gbgfx[3] = optarg[4];
equals = strchr(musl_optarg, '=');
if (equals) {
*equals = '\0';
sym_AddString(musl_optarg, equals + 1);
} else {
errx(1, "Must specify exactly 4 characters for "
"option 'g'");
sym_AddString(musl_optarg, "1");
}
break;
case 'E':
sym_SetExportAll(true);
break;
case 'g':
if (strlen(musl_optarg) == 4)
opt_G(&musl_optarg[1]);
else
errx(1, "Must specify exactly 4 characters for option 'g'");
break;
case 'h':
newopt.haltnop = false;
haltnop = false;
break;
case 'i':
fstk_AddIncludePath(optarg);
fstk_AddIncludePath(musl_optarg);
break;
case 'L':
optimizeloads = false;
break;
case 'M':
if ((dependfile = fopen(optarg, "w")) == NULL) {
err(1, "Could not open dependfile %s", optarg);
}
if (!strcmp("-", musl_optarg))
dependfile = stdout;
else
dependfile = fopen(musl_optarg, "w");
if (dependfile == NULL)
err(1, "Could not open dependfile %s", musl_optarg);
break;
case 'o':
out_SetFileName(optarg);
out_SetFileName(musl_optarg);
break;
unsigned long fill;
case 'p':
newopt.fillchar = strtoul(optarg, &ep, 0);
if (optarg[0] == '\0' || *ep != '\0') {
fill = strtoul(musl_optarg, &ep, 0);
if (musl_optarg[0] == '\0' || *ep != '\0')
errx(1, "Invalid argument for option 'p'");
}
if (newopt.fillchar < 0 || newopt.fillchar > 0xFF) {
errx(1, "Argument for option 'p' must be "
"between 0 and 0xFF");
}
if (fill < 0 || fill > 0xFF)
errx(1, "Argument for option 'p' must be between 0 and 0xFF");
opt_P(fill);
break;
case 'r':
maxRecursionDepth = strtoul(musl_optarg, &ep, 0);
if (musl_optarg[0] == '\0' || *ep != '\0')
errx(1, "Invalid argument for option 'r'");
break;
case 'V':
printf("rgbasm %s\n", get_package_version_string());
exit(0);
case 'v':
newopt.verbose = true;
verbose = true;
break;
case 'W':
processWarningFlag(musl_optarg);
break;
case 'w':
newopt.warnings = false;
warnings = false;
break;
/* Long-only options */
case 0:
switch (depType) {
case 'G':
oGeneratedMissingIncludes = true;
break;
case 'P':
oGeneratePhonyDeps = true;
break;
case 'Q':
case 'T':
if (musl_optind == argc)
errx(1, "-M%c takes a target file name argument", depType);
ep = musl_optarg;
if (depType == 'Q')
ep = make_escape(ep);
nTargetFileNameLen += strlen(ep) + 1;
if (!tzTargetFileName) {
/* On first alloc, make an empty str */
tzTargetFileName = malloc(nTargetFileNameLen + 1);
if (tzTargetFileName)
*tzTargetFileName = '\0';
} else {
tzTargetFileName = realloc(tzTargetFileName,
nTargetFileNameLen + 1);
}
if (tzTargetFileName == NULL)
err(1, "Cannot append new file to target file list");
strcat(tzTargetFileName, ep);
if (depType == 'Q')
free(ep);
char *ptr = tzTargetFileName + strlen(tzTargetFileName);
*ptr++ = ' ';
*ptr = '\0';
break;
}
break;
/* Unrecognized options */
default:
usage();
print_usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
opt_SetCurrentOptions(&newopt);
if (tzTargetFileName == NULL)
tzTargetFileName = tzObjectname;
DefaultOptions = CurrentOptions;
if (argc == 0)
usage();
tzMainfile = argv[argc - 1];
setuplex();
if (CurrentOptions.verbose) {
printf("Assembling %s\n", tzMainfile);
if (argc == musl_optind) {
fputs("FATAL: No input files\n", stderr);
print_usage();
} else if (argc != musl_optind + 1) {
fputs("FATAL: More than one input file given\n", stderr);
print_usage();
}
char const *mainFileName = argv[musl_optind];
if (verbose)
printf("Assembling %s\n", mainFileName);
if (dependfile) {
if (!tzObjectname)
errx(1, "Dependency files can only be created if an output object file is specified.\n");
if (!tzTargetFileName)
errx(1, "Dependency files can only be created if a target file is specified with either -o, -MQ or -MT\n");
fprintf(dependfile, "%s: %s\n", tzObjectname, tzMainfile);
fprintf(dependfile, "%s: %s\n", tzTargetFileName, mainFileName);
}
nStartClock = clock();
charmap_New("main", NULL);
nLineNo = 1;
nTotalLines = 0;
nIFDepth = 0;
skipElif = true;
nUnionDepth = 0;
nPC = 0;
nPass = 1;
nErrors = 0;
sym_PrepPass1();
sym_SetExportAll(CurrentOptions.exportall);
fstk_Init(tzMainfile);
opt_ParseDefines();
// Init lexer and file stack, prodiving file info
lexer_Init();
fstk_Init(mainFileName, maxRecursionDepth);
if (CurrentOptions.verbose) {
printf("Pass 1...\n");
}
// Perform parse (yyparse is auto-generated from `parser.y`)
if (yyparse() != 0 && nbErrors == 0)
nbErrors = 1;
yy_set_state(LEX_STATE_NORMAL);
opt_SetCurrentOptions(&DefaultOptions);
if (dependfile)
fclose(dependfile);
if (yyparse() != 0 || nErrors != 0) {
errx(1, "Assembly aborted in pass 1 (%ld errors)!", nErrors);
}
sect_CheckUnionClosed();
if (nIFDepth != 0) {
errx(1, "Unterminated IF construct (%ld levels)!", nIFDepth);
}
if (nUnionDepth != 0) {
errx(1, "Unterminated UNION construct (%ld levels)!", nUnionDepth);
}
if (nbErrors != 0)
errx(1, "Assembly aborted (%u error%s)!", nbErrors,
nbErrors == 1 ? "" : "s");
nTotalLines = 0;
nLineNo = 1;
nIFDepth = 0;
skipElif = true;
nUnionDepth = 0;
nPC = 0;
nPass = 2;
nErrors = 0;
sym_PrepPass2();
out_PrepPass2();
fstk_Init(tzMainfile);
yy_set_state(LEX_STATE_NORMAL);
opt_SetCurrentOptions(&DefaultOptions);
opt_ParseDefines();
// If parse aborted due to missing an include, and `-MG` was given, exit normally
if (oFailedOnMissingInclude)
return 0;
if (CurrentOptions.verbose) {
printf("Pass 2...\n");
}
if (yyparse() != 0 || nErrors != 0) {
errx(1, "Assembly aborted in pass 2 (%ld errors)!", nErrors);
}
double timespent;
nEndClock = clock();
timespent = ((double)(nEndClock - nStartClock))
/ (double)CLOCKS_PER_SEC;
if (CurrentOptions.verbose) {
printf("Success! %ld lines in %d.%02d seconds ", nTotalLines,
(int) timespent, ((int) (timespent * 100.0)) % 100);
if (timespent == 0)
printf("(INFINITY lines/minute)\n");
else
printf("(%d lines/minute)\n",
(int) (60 / timespent * nTotalLines));
}
out_WriteObject();
/* If no path specified, don't write file */
if (tzObjectname != NULL)
out_WriteObject();
return 0;
}
-148
View File
@@ -1,148 +0,0 @@
/*
* Fixedpoint math routines
*/
#include <math.h>
#include <stdio.h>
#include "types.h"
#include "asm/mymath.h"
#include "asm/symbol.h"
#define fix2double(i) ((double)(i/65536.0))
#define double2fix(d) ((SLONG)(d*65536.0))
#ifndef PI
#define PI (acos(-1))
#endif
/*
* Define the _PI symbol
*/
void
math_DefinePI(void)
{
sym_AddEqu("_PI", double2fix(PI));
}
/*
* Print a fixed point value
*/
void
math_Print(SLONG i)
{
if (i >= 0)
printf("%ld.%05ld", i >> 16,
((SLONG) (fix2double(i) * 100000 + 0.5)) % 100000);
else
printf("-%ld.%05ld", (-i) >> 16,
((SLONG) (fix2double(-i) * 100000 + 0.5)) % 100000);
}
/*
* Calculate sine
*/
SLONG
math_Sin(SLONG i)
{
return (double2fix(sin(fix2double(i) * 2 * PI / 65536)));
}
/*
* Calculate cosine
*/
SLONG
math_Cos(SLONG i)
{
return (double2fix(cos(fix2double(i) * 2 * PI / 65536)));
}
/*
* Calculate tangent
*/
SLONG
math_Tan(SLONG i)
{
return (double2fix(tan(fix2double(i) * 2 * PI / 65536)));
}
/*
* Calculate arcsine
*/
SLONG
math_ASin(SLONG i)
{
return (double2fix(asin(fix2double(i)) / 2 / PI * 65536));
}
/*
* Calculate arccosine
*/
SLONG
math_ACos(SLONG i)
{
return (double2fix(acos(fix2double(i)) / 2 / PI * 65536));
}
/*
* Calculate arctangent
*/
SLONG
math_ATan(SLONG i)
{
return (double2fix(atan(fix2double(i)) / 2 / PI * 65536));
}
/*
* Calculate atan2
*/
SLONG
math_ATan2(SLONG i, SLONG j)
{
return (double2fix
(atan2(fix2double(i), fix2double(j)) / 2 / PI * 65536));
}
/*
* Multiplication
*/
SLONG
math_Mul(SLONG i, SLONG j)
{
return (double2fix(fix2double(i) * fix2double(j)));
}
/*
* Division
*/
SLONG
math_Div(SLONG i, SLONG j)
{
return (double2fix(fix2double(i) / fix2double(j)));
}
/*
* Round
*/
SLONG
math_Round(SLONG i)
{
return double2fix(round(fix2double(i)));
}
/*
* Ceil
*/
SLONG
math_Ceil(SLONG i)
{
return double2fix(ceil(fix2double(i)));
}
/*
* Floor
*/
SLONG
math_Floor(SLONG i)
{
return double2fix(floor(fix2double(i)));
}
+111
View File
@@ -0,0 +1,111 @@
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asm/lexer.h"
#include "asm/section.h"
#include "asm/warning.h"
struct OptStackEntry {
char binary[2];
char gbgfx[4];
int32_t fillByte;
struct OptStackEntry *next;
};
static struct OptStackEntry *stack = NULL;
void opt_B(char chars[2])
{
lexer_SetBinDigits(chars);
}
void opt_G(char chars[4])
{
lexer_SetGfxDigits(chars);
}
void opt_P(uint8_t fill)
{
fillByte = fill;
}
void opt_Parse(char *s)
{
switch (s[0]) {
case 'b':
if (strlen(&s[1]) == 2)
opt_B(&s[1]);
else
error("Must specify exactly 2 characters for option 'b'\n");
break;
case 'g':
if (strlen(&s[1]) == 4)
opt_G(&s[1]);
else
error("Must specify exactly 4 characters for option 'g'\n");
break;
case 'p':
if (strlen(&s[1]) <= 2) {
int result;
unsigned int fillchar;
result = sscanf(&s[1], "%x", &fillchar);
if (result != EOF && result != 1)
error("Invalid argument for option 'p'\n");
else
opt_P(fillchar);
} else {
error("Invalid argument for option 'p'\n");
}
break;
default:
error("Unknown option '%c'\n", s[0]);
break;
}
}
void opt_Push(void)
{
struct OptStackEntry *entry = malloc(sizeof(*entry));
if (entry == NULL)
fatalerror("Failed to alloc option stack entry: %s\n", strerror(errno));
// Both of these pulled from lexer.h
entry->binary[0] = binDigits[0];
entry->binary[1] = binDigits[1];
entry->gbgfx[0] = gfxDigits[0];
entry->gbgfx[1] = gfxDigits[1];
entry->gbgfx[2] = gfxDigits[2];
entry->gbgfx[3] = gfxDigits[3];
entry->fillByte = fillByte; // Pulled from section.h
entry->next = stack;
stack = entry;
}
void opt_Pop(void)
{
if (stack == NULL) {
error("No entries in the option stack\n");
return;
}
struct OptStackEntry *entry = stack;
opt_B(entry->binary);
opt_G(entry->gbgfx);
opt_P(entry->fillByte);
stack = entry->next;
free(entry);
}
+396 -807
View File
File diff suppressed because it is too large Load Diff
+2223
View File
File diff suppressed because it is too large Load Diff
+233 -50
View File
@@ -1,94 +1,278 @@
.\" Copyright © 2010 Anthony J. Bentley <[email protected]>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\" This file is part of RGBDS.
.\"
.\" THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" Copyright (c) 2010-2021, Anthony J. Bentley and RGBDS contributors.
.\"
.Dd April 17, 2017
.\" SPDX-License-Identifier: MIT
.\"
.Dd March 28, 2021
.Dt RGBASM 1
.Os RGBDS Manual
.Os
.Sh NAME
.Nm rgbasm
.Nd Game Boy assembler
.Sh SYNOPSIS
.Nm rgbasm
.Op Fl EhVvw
.Nm
.Op Fl EhLVvw
.Op Fl b Ar chars
.Op Fl D Ar name Ns Op = Ns Ar value
.Op Fl g Ar chars
.Op Fl i Ar path
.Op Fl M Ar dependfile
.Op Fl o Ar outfile
.Op Fl M Ar depend_file
.Op Fl MG
.Op Fl MP
.Op Fl MT Ar target_file
.Op Fl MQ Ar target_file
.Op Fl o Ar out_file
.Op Fl p Ar pad_value
.Ar file
.Op Fl r Ar recursion_depth
.Op Fl W Ar warning
.Ar
.Sh DESCRIPTION
The
.Nm
program creates an object file from an assembly source file.
Its arguments are as follows:
program creates an RGB object file from an assembly source file.
The input
.Ar file
can be a file path, or
.Cm \-
denoting
.Cm stdin .
.Pp
Note that options can be abbreviated as long as the abbreviation is unambiguous:
.Fl Fl verb
is
.Fl Fl verbose ,
but
.Fl Fl ver
is invalid because it could also be
.Fl Fl version .
The arguments are as follows:
.Bl -tag -width Ds
.It Fl b Ar chars
.It Fl b Ar chars , Fl Fl binary-digits Ar chars
Change the two characters used for binary constants.
The defaults are 01.
.It Fl D Ar name Ns Op = Ns Ar value
Add string symbol to the compiled source code. This is equivalent to
.Ar name
.Cm EQUS
.Qq Ar "value"
in code. If a value is not specified, a value of 1 is given.
.It Fl E
.It Fl D Ar name Ns Oo = Ns Ar value Oc , Fl Fl define Ar name Ns Oo = Ns Ar value Oc
Add a string symbol to the compiled source code.
This is equivalent to
.Ql Ar name Ic EQUS \(dq Ns Ar value Ns \(dq
in code, or
.Ql Ar name Ic EQUS \(dq1\(dq
if
.Ar value
is not specified.
.It Fl E , Fl Fl export-all
Export all labels, including unreferenced and local labels.
.It Fl g Ar chars
Change the four characters used for binary constants.
.It Fl g Ar chars , Fl Fl gfx-chars Ar chars
Change the four characters used for gfx constants.
The defaults are 0123.
.It Fl h
.It Fl h , Fl Fl halt-without-nop
By default,
.Nm
inserts a
.Sq nop
.Ic nop
instruction immediately after any
.Sq halt
.Ic halt
instruction.
The
.Fl h
option disables this behavior.
.It Fl i Ar path
.It Fl i Ar path , Fl Fl include Ar path
Add an include path.
.It Fl M Ar dependfile
.It Fl L , Fl Fl preserve-ld
Disable the optimization that turns loads of the form
.Ic LD [$FF00+n8],A
into the opcode
.Ic LD [H $FF00+n8],A
in order to have full control of the result in the final ROM.
.It Fl M Ar depend_file , Fl Fl dependfile Ar depend_file
Print
.Xr make 1
dependencies to
.Ar dependfile .
.It Fl o Ar outfile
.Ar depend_file .
.It Fl MG
To be used in conjunction with
.Fl M .
This makes
.Nm
assume that missing files are auto-generated: when
.Ic INCLUDE
or
.Ic INCBIN
is attempted on a non-existent file, it is added as a dependency, then
.Nm
exits normally instead of erroring out.
This feature is used in automatic updating of makefiles.
.It Fl MP
When enabled, this causes a phony target to be added for each dependency other than the main file.
This prevents
.Xr make 1
from erroring out when dependency files are deleted.
.It Fl MT Ar target_file
Add a target to the rules emitted by
.Fl M .
The exact string provided will be written, including spaces and special characters.
.Dl Fl MT No fileA Fl MT No fileB
is equivalent to
.Dl Fl MT No 'fileA fileB' .
If neither this nor
.Fl MQ
is specified, the output file name is used.
.It Fl MQ Ar target_file
Same as
.Fl MT ,
but additionally escapes any special
.Xr make 1
characters, essentially
.Sq $ .
.It Fl o Ar out_file , Fl Fl output Ar out_file
Write an object file to the given filename.
.It Fl p Ar pad_value
.It Fl p Ar pad_value , Fl Fl pad-value Ar pad_value
When padding an image, pad with this value.
The default is 0x00.
.It Fl V
.It Fl r Ar recursion_depth , Fl Fl recursion-depth Ar recursion_depth
Specifies the recursion depth at which RGBASM will assume being in an infinite loop.
.It Fl V , Fl Fl version
Print the version of the program and exit.
.It Fl v
.It Fl v , Fl Fl verbose
Be verbose.
.It Fl W Ar warning , Fl Fl warning Ar warning
Set warning flag
.Ar warning .
A warning message will be printed if
.Ar warning
is an unknown warning flag.
See the
.Sx DIAGNOSTICS
section for a list of warnings.
.It Fl w
Disable warning output.
Disable all warning output, even when turned into errors.
.El
.Sh DIAGNOSTICS
Warnings are diagnostic messages that indicate possibly erroneous behavior that does not necessarily compromise the assembling process.
The following options alter the way warnings are processed.
.Bl -tag -width Ds
.It Fl Werror
Make all warnings into errors.
.It Fl Werror=
Make the specified warning into an error.
A warning's name is appended
.Pq example: Fl Werror=obsolete ,
and this warning is implicitly enabled and turned into an error.
This is an error if used with a meta warning, such as
.Fl Werror=all .
.El
.Pp
The following warnings are
.Dq meta
warnings, that enable a collection of other warnings.
If a specific warning is toggled via a meta flag and a specific one, the more specific one takes priority.
The position on the command-line acts as a tie breaker, the last one taking effect.
.Bl -tag -width Ds
.It Fl Wall
This enables warnings that are likely to indicate an error or undesired behavior, and that can easily be fixed.
.It Fl Wextra
This enables extra warnings that are less likely to pose a problem, but that may still be wanted.
.It Fl Weverything
Enables literally every warning.
.El
.Pp
The following warnings are actual warning flags; with each description, the corresponding warning flag is included.
Note that each of these flag also has a negation (for example,
.Fl Wcharmap-redef
enables the warning that
.Fl Wno-charmap-redef
disables).
Only the non-default flag is listed here.
Ignoring the
.Dq no-
prefix, entries are listed alphabetically.
.Bl -tag -width Ds
.It Fl Wno-assert
Warns when
.Ic WARN Ns No -type
assertions fail. (See
.Dq Aborting the assembly process
in
.Xr rgbasm 5
for
.Ic ASSERT ) .
.It Fl Wbuiltin-args
Warn about incorrect arguments to built-in functions, such as
.Fn STRSUB
with indexes outside of the string's bounds.
This warning is enabled by
.Fl Wall .
.It Fl Wcharmap-redef
Warn when re-defining a charmap mapping.
This warning is enabled by
.Fl Wall .
.It Fl Wdiv
Warn when dividing the smallest negative integer by -1, which yields itself due to integer overflow.
.It Fl Wempty-macro-arg
Warn when a macro argument is empty.
This warning is enabled by
.Fl Wextra .
.It Fl Wempty-strrpl
Warn when
.Fn STRRPL
is called with an empty string as its second argument (the substring to replace).
This warning is enabled by
.Fl Wall .
.It Fl Wlarge-constant
Warn when a constant too large to fit in a signed 32-bit integer is encountered.
This warning is enabled by
.Fl Wall .
.It Fl Wlong-string
Warn when a string too long to fit in internal buffers is encountered.
This warning is enabled by
.Fl Wall .
.It Fl Wmacro-shift
Warn when shifting macro arguments past their limits.
This warning is enabled by
.Fl Wextra .
.It Fl Wno-obsolete
Warn when obsolete constructs such as the
.Ic _PI
constant or
.Ic PRINTT
directive are encountered.
.It Fl Wshift
Warn when shifting right a negative value.
Use a division by 2^N instead.
.It Fl Wshift-amount
Warn when a shift's operand is negative or greater than 32.
.It Fl Wno-truncation
Warn when an implicit truncation (for example,
.Ic LD [B @] )
loses some bits.
.It Fl Wno-user
Warn when the
.Ic WARN
built-in is executed. (See
.Dq Aborting the assembly process
in
.Xr rgbasm 5
for
.Ic WARN ) .
.El
.Sh EXAMPLES
Assembling a basic source file is simple:
You can assemble a source file in two ways.
.Pp
.D1 $ rgbasm -o bar.o foo.asm
Straightforward way:
.Dl $ rgbasm -o bar.o foo.asm
.Pp
The resulting object file is not yet a usable ROM image \(em it must first be
run through
Pipes way:
.Dl $ cat foo.asm | rgbasm -o bar.o -
.Dl $ rgbasm -o bar.o - < foo.asm
.Pp
The resulting object file is not yet a usable ROM image\(emit must first be run through
.Xr rgblink 1
and
and then
.Xr rgbfix 1 .
.Sh BUGS
Please report bugs on
.Lk https://github.com/gbdev/rgbds/issues GitHub .
.Sh SEE ALSO
.Xr rgbasm 5 ,
.Xr rgbfix 1 ,
@@ -98,7 +282,6 @@ and
.Xr gbz80 7
.Sh HISTORY
.Nm
was originally written by Carsten S\(/orensen as part of the ASMotor package,
and was later packaged in RGBDS by Justin Lloyd. It is now maintained by a
number of contributors at
.Lk https://github.com/rednex/rgbds .
was originally written by Carsten S\(/orensen as part of the ASMotor package, and was later packaged in RGBDS by Justin Lloyd.
It is now maintained by a number of contributors at
.Lk https://github.com/gbdev/rgbds .
+1709 -860
View File
File diff suppressed because it is too large Load Diff
+477 -317
View File
@@ -1,367 +1,527 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
/*
* Controls RPN expressions for objectfiles
*/
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asm/mylink.h"
#include "types.h"
#include "asm/symbol.h"
#include "asm/asm.h"
#include "asm/main.h"
#include "asm/output.h"
#include "asm/rpn.h"
#include "asm/section.h"
#include "asm/symbol.h"
#include "asm/warning.h"
void
mergetwoexpressions(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
#include "opmath.h"
/* Makes an expression "not known", also setting its error message */
#define makeUnknown(expr_, ...) do { \
struct Expression *_expr = expr_; \
_expr->isKnown = false; \
/* If we had `asprintf` this would be great, but alas. */ \
_expr->reason = malloc(128); /* Use an initial reasonable size */ \
if (!_expr->reason) \
fatalerror("Can't allocate err string: %s\n", strerror(errno)); \
int size = snprintf(_expr->reason, 128, __VA_ARGS__); \
if (size >= 128) { /* If this wasn't enough, try again */ \
_expr->reason = realloc(_expr->reason, size + 1); \
sprintf(_expr->reason, __VA_ARGS__); \
} \
} while (0)
static uint8_t *reserveSpace(struct Expression *expr, uint32_t size)
{
*expr = *src1;
memcpy(&(expr->tRPN[expr->nRPNLength]), src2->tRPN, src2->nRPNLength);
/* This assumes the RPN length is always less than the capacity */
if (expr->nRPNCapacity - expr->nRPNLength < size) {
/* If there isn't enough room to reserve the space, realloc */
if (!expr->tRPN)
expr->nRPNCapacity = 256; /* Initial size */
while (expr->nRPNCapacity - expr->nRPNLength < size) {
if (expr->nRPNCapacity >= MAXRPNLEN)
/*
* To avoid generating humongous object files, cap the
* size of RPN expressions
*/
fatalerror("RPN expression cannot grow larger than "
EXPAND_AND_STR(MAXRPNLEN) " bytes\n");
else if (expr->nRPNCapacity > MAXRPNLEN / 2)
expr->nRPNCapacity = MAXRPNLEN;
else
expr->nRPNCapacity *= 2;
}
expr->tRPN = realloc(expr->tRPN, expr->nRPNCapacity);
expr->nRPNLength += src2->nRPNLength;
expr->isReloc |= src2->isReloc;
expr->isPCRel |= src2->isPCRel;
}
#define joinexpr() mergetwoexpressions(expr,src1,src2)
if (!expr->tRPN)
fatalerror("Failed to grow RPN expression: %s\n", strerror(errno));
}
/*
* Add a byte to the RPN expression
*/
void
pushbyte(struct Expression * expr, int b)
{
expr->tRPN[expr->nRPNLength++] = b & 0xFF;
uint8_t *ptr = expr->tRPN + expr->nRPNLength;
expr->nRPNLength += size;
return ptr;
}
/*
* Reset the RPN module
* Init the RPN expression
*/
void
rpn_Reset(struct Expression * expr)
static void rpn_Init(struct Expression *expr)
{
expr->nRPNLength = expr->nRPNOut = expr->isReloc = expr->isPCRel = 0;
expr->reason = NULL;
expr->isKnown = true;
expr->isSymbol = false;
expr->tRPN = NULL;
expr->nRPNCapacity = 0;
expr->nRPNLength = 0;
expr->nRPNPatchSize = 0;
}
/*
* Returns the next rpn byte in expression
* Free the RPN expression
*/
UWORD
rpn_PopByte(struct Expression * expr)
void rpn_Free(struct Expression *expr)
{
if (expr->nRPNOut == expr->nRPNLength) {
return (0xDEAD);
} else
return (expr->tRPN[expr->nRPNOut++]);
}
/*
* Determine if the current expression is relocatable
*/
ULONG
rpn_isReloc(struct Expression * expr)
{
return (expr->isReloc);
}
/*
* Determine if the current expression can be pc-relative
*/
ULONG
rpn_isPCRelative(struct Expression * expr)
{
return (expr->isPCRel);
free(expr->tRPN);
free(expr->reason);
rpn_Init(expr);
}
/*
* Add symbols, constants and operators to expression
*/
void
rpn_Number(struct Expression * expr, ULONG i)
void rpn_Number(struct Expression *expr, uint32_t i)
{
rpn_Reset(expr);
pushbyte(expr, RPN_CONST);
pushbyte(expr, i);
pushbyte(expr, i >> 8);
pushbyte(expr, i >> 16);
pushbyte(expr, i >> 24);
rpn_Init(expr);
expr->nVal = i;
}
void
rpn_Symbol(struct Expression * expr, char *tzSym)
void rpn_Symbol(struct Expression *expr, char const *tzSym)
{
if (!sym_isConstant(tzSym)) {
struct sSymbol *psym;
struct Symbol *sym = sym_FindScopedSymbol(tzSym);
rpn_Reset(expr);
if (sym_IsPC(sym) && !sect_GetSymbolSection()) {
error("PC has no value outside a section\n");
rpn_Number(expr, 0);
} else if (!sym || !sym_IsConstant(sym)) {
rpn_Init(expr);
expr->isSymbol = true;
psym = sym_FindSymbol(tzSym);
makeUnknown(expr, sym_IsPC(sym) ? "PC is not constant at assembly time"
: "'%s' is not constant at assembly time", tzSym);
sym = sym_Ref(tzSym);
expr->nRPNPatchSize += 5; /* 1-byte opcode + 4-byte symbol ID */
if (psym == NULL || psym->pSection == pCurrentSection
|| psym->pSection == NULL)
expr->isPCRel = 1;
expr->isReloc = 1;
pushbyte(expr, RPN_SYM);
while (*tzSym)
pushbyte(expr, *tzSym++);
pushbyte(expr, 0);
} else
size_t nameLen = strlen(sym->name) + 1; /* Don't forget NUL! */
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
*ptr++ = RPN_SYM;
memcpy(ptr, sym->name, nameLen);
} else {
rpn_Number(expr, sym_GetConstantValue(tzSym));
}
void
rpn_Bank(struct Expression * expr, char *tzSym)
{
if (!sym_isConstant(tzSym)) {
rpn_Reset(expr);
/* Check that the symbol exists by evaluating and discarding the value. */
sym_GetValue(tzSym);
expr->isReloc = 1;
pushbyte(expr, RPN_BANK);
while (*tzSym)
pushbyte(expr, *tzSym++);
pushbyte(expr, 0);
} else
yyerror("BANK argument must be a relocatable identifier");
}
void
rpn_CheckHRAM(struct Expression * expr, struct Expression * src)
{
*expr = *src;
pushbyte(expr, RPN_HRAM);
}
void
rpn_LOGNOT(struct Expression * expr, struct Expression * src)
{
*expr = *src;
pushbyte(expr, RPN_LOGUNNOT);
}
void
rpn_LOGOR(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal || src2->nVal);
pushbyte(expr, RPN_LOGOR);
}
void
rpn_LOGAND(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal && src2->nVal);
pushbyte(expr, RPN_LOGAND);
}
void
rpn_HIGH(struct Expression * expr, struct Expression * src)
{
*expr = *src;
expr->nVal = (expr->nVal >> 8) & 0xFF;
pushbyte(expr, RPN_CONST);
pushbyte(expr, 8);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, RPN_SHR);
pushbyte(expr, RPN_CONST);
pushbyte(expr, 0xFF);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, RPN_AND);
}
void
rpn_LOW(struct Expression * expr, struct Expression * src)
{
*expr = *src;
expr->nVal = expr->nVal & 0xFF;
pushbyte(expr, RPN_CONST);
pushbyte(expr, 0xFF);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, RPN_AND);
}
void
rpn_LOGEQU(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal == src2->nVal);
pushbyte(expr, RPN_LOGEQ);
}
void
rpn_LOGGT(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal > src2->nVal);
pushbyte(expr, RPN_LOGGT);
}
void
rpn_LOGLT(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal < src2->nVal);
pushbyte(expr, RPN_LOGLT);
}
void
rpn_LOGGE(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal >= src2->nVal);
pushbyte(expr, RPN_LOGGE);
}
void
rpn_LOGLE(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal <= src2->nVal);
pushbyte(expr, RPN_LOGLE);
}
void
rpn_LOGNE(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal != src2->nVal);
pushbyte(expr, RPN_LOGNE);
}
void
rpn_ADD(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal + src2->nVal);
pushbyte(expr, RPN_ADD);
}
void
rpn_SUB(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal - src2->nVal);
pushbyte(expr, RPN_SUB);
}
void
rpn_XOR(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal ^ src2->nVal);
pushbyte(expr, RPN_XOR);
}
void
rpn_OR(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal | src2->nVal);
pushbyte(expr, RPN_OR);
}
void
rpn_AND(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal & src2->nVal);
pushbyte(expr, RPN_AND);
}
void
rpn_SHL(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal << src2->nVal);
pushbyte(expr, RPN_SHL);
}
void
rpn_SHR(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal >> src2->nVal);
pushbyte(expr, RPN_SHR);
}
void
rpn_MUL(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
expr->nVal = (expr->nVal * src2->nVal);
pushbyte(expr, RPN_MUL);
}
void
rpn_DIV(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
joinexpr();
if (src2->nVal == 0) {
fatalerror("division by zero");
}
expr->nVal = (expr->nVal / src2->nVal);
pushbyte(expr, RPN_DIV);
}
void
rpn_MOD(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
void rpn_BankSelf(struct Expression *expr)
{
joinexpr();
if (src2->nVal == 0) {
fatalerror("division by zero");
rpn_Init(expr);
if (!pCurrentSection) {
error("PC has no bank outside a section\n");
expr->nVal = 1;
} else if (pCurrentSection->bank == (uint32_t)-1) {
makeUnknown(expr, "Current section's bank is not known");
expr->nRPNPatchSize++;
*reserveSpace(expr, 1) = RPN_BANK_SELF;
} else {
expr->nVal = pCurrentSection->bank;
}
expr->nVal = (expr->nVal % src2->nVal);
pushbyte(expr, RPN_MOD);
}
void
rpn_UNNEG(struct Expression * expr, struct Expression * src)
void rpn_BankSymbol(struct Expression *expr, char const *tzSym)
{
*expr = *src;
expr->nVal = -expr->nVal;
pushbyte(expr, RPN_UNSUB);
struct Symbol const *sym = sym_FindScopedSymbol(tzSym);
/* The @ symbol is treated differently. */
if (sym_IsPC(sym)) {
rpn_BankSelf(expr);
return;
}
rpn_Init(expr);
if (sym && !sym_IsLabel(sym)) {
error("BANK argument must be a label\n");
} else {
sym = sym_Ref(tzSym);
assert(sym); // If the symbol didn't exist, it should have been created
if (sym_GetSection(sym) && sym_GetSection(sym)->bank != (uint32_t)-1) {
/* Symbol's section is known and bank is fixed */
expr->nVal = sym_GetSection(sym)->bank;
} else {
makeUnknown(expr, "\"%s\"'s bank is not known", tzSym);
expr->nRPNPatchSize += 5; /* opcode + 4-byte sect ID */
size_t nameLen = strlen(sym->name) + 1; /* Room for NUL! */
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
*ptr++ = RPN_BANK_SYM;
memcpy(ptr, sym->name, nameLen);
}
}
}
void
rpn_UNNOT(struct Expression * expr, struct Expression * src)
void rpn_BankSection(struct Expression *expr, char const *tzSectionName)
{
rpn_Init(expr);
struct Section *pSection = out_FindSectionByName(tzSectionName);
if (pSection && pSection->bank != (uint32_t)-1) {
expr->nVal = pSection->bank;
} else {
makeUnknown(expr, "Section \"%s\"'s bank is not known",
tzSectionName);
size_t nameLen = strlen(tzSectionName) + 1; /* Room for NUL! */
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
expr->nRPNPatchSize += nameLen + 1;
*ptr++ = RPN_BANK_SECT;
memcpy(ptr, tzSectionName, nameLen);
}
}
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src)
{
*expr = *src;
expr->nVal = expr->nVal ^ 0xFFFFFFFF;
pushbyte(expr, RPN_UNNOT);
expr->isSymbol = false;
if (!rpn_isKnown(expr)) {
expr->nRPNPatchSize++;
*reserveSpace(expr, 1) = RPN_HRAM;
} else if (expr->nVal >= 0xFF00 && expr->nVal <= 0xFFFF) {
/* That range is valid, but only keep the lower byte */
expr->nVal &= 0xFF;
} else if (expr->nVal < 0 || expr->nVal > 0xFF) {
error("Source address $%" PRIx32 " not between $FF00 to $FFFF\n", expr->nVal);
}
}
void rpn_CheckRST(struct Expression *expr, const struct Expression *src)
{
*expr = *src;
if (rpn_isKnown(expr)) {
/* A valid RST address must be masked with 0x38 */
if (expr->nVal & ~0x38)
error("Invalid address $%" PRIx32 " for RST\n", expr->nVal);
/* The target is in the "0x38" bits, all other bits are set */
expr->nVal |= 0xC7;
} else {
expr->nRPNPatchSize++;
*reserveSpace(expr, 1) = RPN_RST;
}
}
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src)
{
*expr = *src;
expr->isSymbol = false;
if (rpn_isKnown(expr)) {
expr->nVal = !expr->nVal;
} else {
expr->nRPNPatchSize++;
*reserveSpace(expr, 1) = RPN_LOGUNNOT;
}
}
struct Symbol const *rpn_SymbolOf(struct Expression const *expr)
{
if (!rpn_isSymbol(expr))
return NULL;
return sym_FindScopedSymbol((char *)expr->tRPN + 1);
}
bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym)
{
/* Check if both expressions only refer to a single symbol */
struct Symbol const *sym1 = rpn_SymbolOf(src);
if (!sym1 || !sym || sym1->type != SYM_LABEL || sym->type != SYM_LABEL)
return false;
struct Section const *section1 = sym_GetSection(sym1);
struct Section const *section2 = sym_GetSection(sym);
return section1 && (section1 == section2);
}
static bool isDiffConstant(struct Expression const *src1,
struct Expression const *src2)
{
return rpn_IsDiffConstant(src1, rpn_SymbolOf(src2));
}
void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
const struct Expression *src1, const struct Expression *src2)
{
expr->isSymbol = false;
/* First, check if the expression is known */
expr->isKnown = src1->isKnown && src2->isKnown;
if (expr->isKnown) {
rpn_Init(expr); /* Init the expression to something sane */
/* If both expressions are known, just compute the value */
uint32_t uleft = src1->nVal, uright = src2->nVal;
switch (op) {
case RPN_LOGOR:
expr->nVal = src1->nVal || src2->nVal;
break;
case RPN_LOGAND:
expr->nVal = src1->nVal && src2->nVal;
break;
case RPN_LOGEQ:
expr->nVal = src1->nVal == src2->nVal;
break;
case RPN_LOGGT:
expr->nVal = src1->nVal > src2->nVal;
break;
case RPN_LOGLT:
expr->nVal = src1->nVal < src2->nVal;
break;
case RPN_LOGGE:
expr->nVal = src1->nVal >= src2->nVal;
break;
case RPN_LOGLE:
expr->nVal = src1->nVal <= src2->nVal;
break;
case RPN_LOGNE:
expr->nVal = src1->nVal != src2->nVal;
break;
case RPN_ADD:
expr->nVal = uleft + uright;
break;
case RPN_SUB:
expr->nVal = uleft - uright;
break;
case RPN_XOR:
expr->nVal = src1->nVal ^ src2->nVal;
break;
case RPN_OR:
expr->nVal = src1->nVal | src2->nVal;
break;
case RPN_AND:
expr->nVal = src1->nVal & src2->nVal;
break;
case RPN_SHL:
if (src2->nVal < 0)
warning(WARNING_SHIFT_AMOUNT,
"Shifting left by negative amount %" PRId32 "\n",
src2->nVal);
if (src2->nVal >= 32)
warning(WARNING_SHIFT_AMOUNT,
"Shifting left by large amount %" PRId32 "\n",
src2->nVal);
expr->nVal = op_shift_left(src1->nVal, src2->nVal);
break;
case RPN_SHR:
if (src1->nVal < 0)
warning(WARNING_SHIFT, "Shifting right negative value %"
PRId32 "\n",
src1->nVal);
if (src2->nVal < 0)
warning(WARNING_SHIFT_AMOUNT,
"Shifting right by negative amount %" PRId32 "\n",
src2->nVal);
if (src2->nVal >= 32)
warning(WARNING_SHIFT_AMOUNT,
"Shifting right by large amount %" PRId32 "\n",
src2->nVal);
expr->nVal = op_shift_right(src1->nVal, src2->nVal);
break;
case RPN_MUL:
expr->nVal = uleft * uright;
break;
case RPN_DIV:
if (src2->nVal == 0)
fatalerror("Division by zero\n");
if (src1->nVal == INT32_MIN && src2->nVal == -1) {
warning(WARNING_DIV, "Division of %" PRId32 " by -1 yields %"
PRId32 "\n", INT32_MIN, INT32_MIN);
expr->nVal = INT32_MIN;
} else {
expr->nVal = op_divide(src1->nVal, src2->nVal);
}
break;
case RPN_MOD:
if (src2->nVal == 0)
fatalerror("Modulo by zero\n");
if (src1->nVal == INT32_MIN && src2->nVal == -1)
expr->nVal = 0;
else
expr->nVal = op_modulo(src1->nVal, src2->nVal);
break;
case RPN_EXP:
if (src2->nVal < 0)
fatalerror("Exponentiation by negative power\n");
if (src1->nVal == INT32_MIN && src2->nVal == -1)
expr->nVal = 0;
else
expr->nVal = op_exponent(src1->nVal, src2->nVal);
break;
case RPN_UNSUB:
case RPN_UNNOT:
case RPN_LOGUNNOT:
case RPN_BANK_SYM:
case RPN_BANK_SECT:
case RPN_BANK_SELF:
case RPN_HRAM:
case RPN_RST:
case RPN_CONST:
case RPN_SYM:
fatalerror("%d is not a binary operator\n", op);
}
} else if (op == RPN_SUB && isDiffConstant(src1, src2)) {
struct Symbol const *symbol1 = rpn_SymbolOf(src1);
struct Symbol const *symbol2 = rpn_SymbolOf(src2);
expr->nVal = sym_GetValue(symbol1) - sym_GetValue(symbol2);
expr->isKnown = true;
} else {
/* If it's not known, start computing the RPN expression */
/* Convert the left-hand expression if it's constant */
if (src1->isKnown) {
uint32_t lval = src1->nVal;
uint8_t bytes[] = {RPN_CONST, lval, lval >> 8,
lval >> 16, lval >> 24};
expr->nRPNPatchSize = sizeof(bytes);
expr->tRPN = NULL;
expr->nRPNCapacity = 0;
expr->nRPNLength = 0;
memcpy(reserveSpace(expr, sizeof(bytes)), bytes,
sizeof(bytes));
/* Use the other expression's un-const reason */
expr->reason = src2->reason;
free(src1->reason);
} else {
/* Otherwise just reuse its RPN buffer */
expr->nRPNPatchSize = src1->nRPNPatchSize;
expr->tRPN = src1->tRPN;
expr->nRPNCapacity = src1->nRPNCapacity;
expr->nRPNLength = src1->nRPNLength;
expr->reason = src1->reason;
free(src2->reason);
}
/* Now, merge the right expression into the left one */
uint8_t *ptr = src2->tRPN; /* Pointer to the right RPN */
uint32_t len = src2->nRPNLength; /* Size of the right RPN */
uint32_t patchSize = src2->nRPNPatchSize;
/* If the right expression is constant, merge a shim instead */
uint32_t rval = src2->nVal;
uint8_t bytes[] = {RPN_CONST, rval, rval >> 8, rval >> 16,
rval >> 24};
if (src2->isKnown) {
ptr = bytes;
len = sizeof(bytes);
patchSize = sizeof(bytes);
}
/* Copy the right RPN and append the operator */
uint8_t *buf = reserveSpace(expr, len + 1);
memcpy(buf, ptr, len);
buf[len] = op;
free(src2->tRPN); /* If there was none, this is `free(NULL)` */
expr->nRPNPatchSize += patchSize + 1;
}
}
void rpn_HIGH(struct Expression *expr, const struct Expression *src)
{
*expr = *src;
expr->isSymbol = false;
if (rpn_isKnown(expr)) {
expr->nVal = (uint32_t)expr->nVal >> 8 & 0xFF;
} else {
uint8_t bytes[] = {RPN_CONST, 8, 0, 0, 0, RPN_SHR,
RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
expr->nRPNPatchSize += sizeof(bytes);
memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
}
}
void rpn_LOW(struct Expression *expr, const struct Expression *src)
{
*expr = *src;
expr->isSymbol = false;
if (rpn_isKnown(expr)) {
expr->nVal = expr->nVal & 0xFF;
} else {
uint8_t bytes[] = {RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
expr->nRPNPatchSize += sizeof(bytes);
memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
}
}
void rpn_ISCONST(struct Expression *expr, const struct Expression *src)
{
rpn_Init(expr);
expr->nVal = rpn_isKnown(src);
expr->isKnown = true;
expr->isSymbol = false;
}
void rpn_UNNEG(struct Expression *expr, const struct Expression *src)
{
*expr = *src;
expr->isSymbol = false;
if (rpn_isKnown(expr)) {
expr->nVal = -(uint32_t)expr->nVal;
} else {
expr->nRPNPatchSize++;
*reserveSpace(expr, 1) = RPN_UNSUB;
}
}
void rpn_UNNOT(struct Expression *expr, const struct Expression *src)
{
*expr = *src;
expr->isSymbol = false;
if (rpn_isKnown(expr)) {
expr->nVal = ~expr->nVal;
} else {
expr->nRPNPatchSize++;
*reserveSpace(expr, 1) = RPN_UNNOT;
}
}
+925
View File
@@ -0,0 +1,925 @@
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asm/fstack.h"
#include "asm/main.h"
#include "asm/output.h"
#include "asm/rpn.h"
#include "asm/section.h"
#include "asm/symbol.h"
#include "asm/warning.h"
#include "extern/err.h"
#include "platform.h" // strdup
uint8_t fillByte;
struct SectionStackEntry {
struct Section *section;
char const *scope; /* Section's symbol scope */
uint32_t offset;
struct SectionStackEntry *next;
};
struct SectionStackEntry *sectionStack;
uint32_t curOffset; /* Offset into the current section (see sect_GetSymbolOffset) */
static struct Section *currentLoadSection = NULL;
int32_t loadOffset; /* Offset into the LOAD section's parent (see sect_GetOutputOffset) */
struct UnionStackEntry {
uint32_t start;
uint32_t size;
struct UnionStackEntry *next;
} *unionStack = NULL;
/*
* A quick check to see if we have an initialized section
*/
static inline void checksection(void)
{
if (pCurrentSection == NULL)
fatalerror("Code generation before SECTION directive\n");
}
/*
* A quick check to see if we have an initialized section that can contain
* this much initialized data
*/
static inline void checkcodesection(void)
{
checksection();
if (!sect_HasData(pCurrentSection->type))
fatalerror("Section '%s' cannot contain code or data (not ROM0 or ROMX)\n",
pCurrentSection->name);
}
static inline void checkSectionSize(struct Section const *sect, uint32_t size)
{
uint32_t maxSize = maxsize[sect->type];
if (size > maxSize)
fatalerror("Section '%s' grew too big (max size = 0x%" PRIX32
" bytes, reached 0x%" PRIX32 ").\n", sect->name, maxSize, size);
}
/*
* Check if the section has grown too much.
*/
static inline void reserveSpace(uint32_t delta_size)
{
/*
* This check is here to trap broken code that generates sections that
* are too big and to prevent the assembler from generating huge object
* files or trying to allocate too much memory.
* A check at the linking stage is still necessary.
*/
checkSectionSize(pCurrentSection, curOffset + loadOffset + delta_size);
if (currentLoadSection)
checkSectionSize(currentLoadSection, curOffset + delta_size);
}
struct Section *out_FindSectionByName(const char *name)
{
for (struct Section *sect = pSectionList; sect; sect = sect->next) {
if (strcmp(name, sect->name) == 0)
return sect;
}
return NULL;
}
#define mask(align) ((1U << (align)) - 1)
#define fail(...) \
do { \
error(__VA_ARGS__); \
nbSectErrors++; \
} while (0)
static unsigned int mergeSectUnion(struct Section *sect, enum SectionType type, uint32_t org,
uint8_t alignment, uint16_t alignOffset)
{
assert(alignment < 16); // Should be ensured by the caller
unsigned int nbSectErrors = 0;
/*
* Unionized sections only need "compatible" constraints, and they end up with the strictest
* combination of both.
*/
if (sect_HasData(type))
fail("Cannot declare ROM sections as UNION\n");
if (org != (uint32_t)-1) {
/* If both are fixed, they must be the same */
if (sect->org != (uint32_t)-1 && sect->org != org)
fail("Section already declared as fixed at different address $%04"
PRIx32 "\n", sect->org);
else if (sect->align != 0 && (mask(sect->align) & (org - sect->alignOfs)))
fail("Section already declared as aligned to %u bytes (offset %"
PRIu16 ")\n", 1U << sect->align, sect->alignOfs);
else
/* Otherwise, just override */
sect->org = org;
} else if (alignment != 0) {
/* Make sure any fixed address given is compatible */
if (sect->org != (uint32_t)-1) {
if ((sect->org - alignOffset) & mask(alignment))
fail("Section already declared as fixed at incompatible address $%04"
PRIx32 "\n", sect->org);
/* Check if alignment offsets are compatible */
} else if ((alignOffset & mask(sect->align))
!= (sect->alignOfs & mask(alignment))) {
fail("Section already declared with incompatible %" PRIu8
"-byte alignment (offset %" PRIu16 ")\n",
sect->align, sect->alignOfs);
} else if (alignment > sect->align) {
// If the section is not fixed, its alignment is the largest of both
sect->align = alignment;
sect->alignOfs = alignOffset;
}
}
return nbSectErrors;
}
static unsigned int mergeFragments(struct Section *sect, enum SectionType type, uint32_t org,
uint8_t alignment, uint16_t alignOffset)
{
(void)type;
assert(alignment < 16); // Should be ensured by the caller
unsigned int nbSectErrors = 0;
/*
* Fragments only need "compatible" constraints, and they end up with the strictest
* combination of both.
* The merging is however performed at the *end* of the original section!
*/
if (org != (uint32_t)-1) {
uint16_t curOrg = org - sect->size;
/* If both are fixed, they must be the same */
if (sect->org != (uint32_t)-1 && sect->org != curOrg)
fail("Section already declared as fixed at incompatible address $%04"
PRIx32 " (cur addr = %04" PRIx32 ")\n",
sect->org, sect->org + sect->size);
else if (sect->align != 0 && (mask(sect->align) & (curOrg - sect->alignOfs)))
fail("Section already declared as aligned to %u bytes (offset %"
PRIu16 ")\n", 1U << sect->align, sect->alignOfs);
else
/* Otherwise, just override */
sect->org = curOrg;
} else if (alignment != 0) {
int32_t curOfs = (alignOffset - sect->size) % (1U << alignment);
if (curOfs < 0)
curOfs += 1U << alignment;
/* Make sure any fixed address given is compatible */
if (sect->org != (uint32_t)-1) {
if ((sect->org - curOfs) & mask(alignment))
fail("Section already declared as fixed at incompatible address $%04"
PRIx32 "\n", sect->org);
/* Check if alignment offsets are compatible */
} else if ((curOfs & mask(sect->align)) != (sect->alignOfs & mask(alignment))) {
fail("Section already declared with incompatible %" PRIu8
"-byte alignment (offset %" PRIu16 ")\n",
sect->align, sect->alignOfs);
} else if (alignment > sect->align) {
// If the section is not fixed, its alignment is the largest of both
sect->align = alignment;
sect->alignOfs = curOfs;
}
}
return nbSectErrors;
}
static void mergeSections(struct Section *sect, enum SectionType type, uint32_t org, uint32_t bank,
uint8_t alignment, uint16_t alignOffset, enum SectionModifier mod)
{
unsigned int nbSectErrors = 0;
if (type != sect->type)
fail("Section already exists but with type %s\n", typeNames[sect->type]);
if (sect->modifier != mod) {
fail("Section already declared as %s section\n", sectionModNames[sect->modifier]);
} else {
switch (mod) {
case SECTION_UNION:
case SECTION_FRAGMENT:
nbSectErrors += (mod == SECTION_UNION ? mergeSectUnion : mergeFragments)
(sect, type, org, alignment, alignOffset);
// Common checks
/* If the section's bank is unspecified, override it */
if (sect->bank == (uint32_t)-1)
sect->bank = bank;
/* If both specify a bank, it must be the same one */
else if (bank != (uint32_t)-1 && sect->bank != bank)
fail("Section already declared with different bank %" PRIu32 "\n",
sect->bank);
break;
case SECTION_NORMAL:
fail("Section already defined previously at ");
fstk_Dump(sect->src, sect->fileLine);
putc('\n', stderr);
break;
}
}
if (nbSectErrors)
fatalerror("Cannot create section \"%s\" (%u error%s)\n",
sect->name, nbSectErrors, nbSectErrors == 1 ? "" : "s");
}
#undef fail
/*
* Create a new section, not yet in the list.
*/
static struct Section *createSection(char const *name, enum SectionType type,
uint32_t org, uint32_t bank, uint8_t alignment,
uint16_t alignOffset, enum SectionModifier mod)
{
struct Section *sect = malloc(sizeof(*sect));
if (sect == NULL)
fatalerror("Not enough memory for section: %s\n", strerror(errno));
sect->name = strdup(name);
if (sect->name == NULL)
fatalerror("Not enough memory for section name: %s\n", strerror(errno));
sect->type = type;
sect->modifier = mod;
sect->src = fstk_GetFileStack();
sect->fileLine = lexer_GetLineNo();
sect->size = 0;
sect->org = org;
sect->bank = bank;
sect->align = alignment;
sect->alignOfs = alignOffset;
sect->next = NULL;
sect->patches = NULL;
/* It is only needed to allocate memory for ROM sections. */
if (sect_HasData(type)) {
sect->data = malloc(maxsize[type]);
if (sect->data == NULL)
fatalerror("Not enough memory for section: %s\n", strerror(errno));
} else {
sect->data = NULL;
}
return sect;
}
/*
* Find a section by name and type. If it doesn't exist, create it.
*/
static struct Section *getSection(char const *name, enum SectionType type, uint32_t org,
struct SectionSpec const *attrs, enum SectionModifier mod)
{
uint32_t bank = attrs->bank;
uint8_t alignment = attrs->alignment;
uint16_t alignOffset = attrs->alignOfs;
// First, validate parameters, and normalize them if applicable
if (bank != (uint32_t)-1) {
if (type != SECTTYPE_ROMX && type != SECTTYPE_VRAM
&& type != SECTTYPE_SRAM && type != SECTTYPE_WRAMX)
error("BANK only allowed for ROMX, WRAMX, SRAM, or VRAM sections\n");
else if (bank < bankranges[type][0]
|| bank > bankranges[type][1])
error("%s bank value $%04" PRIx32 " out of range ($%04" PRIx32 " to $%04"
PRIx32 ")\n", typeNames[type], bank,
bankranges[type][0], bankranges[type][1]);
} else if (nbbanks(type) == 1) {
// If the section type only has a single bank, implicitly force it
bank = bankranges[type][0];
}
if (alignOffset >= 1 << alignment) {
error("Alignment offset (%" PRIu16 ") must be smaller than alignment size (%u)\n",
alignOffset, 1U << alignment);
alignOffset = 0;
}
if (org != (uint32_t)-1) {
if (org < startaddr[type] || org > endaddr(type))
error("Section \"%s\"'s fixed address %#" PRIx32
" is outside of range [%#" PRIx16 "; %#" PRIx16 "]\n",
name, org, startaddr[type], endaddr(type));
}
if (alignment != 0) {
if (alignment > 16) {
error("Alignment must be between 0 and 16, not %u\n", alignment);
alignment = 16;
}
/* It doesn't make sense to have both alignment and org set */
uint32_t mask = mask(alignment);
if (org != (uint32_t)-1) {
if ((org - alignOffset) & mask)
error("Section \"%s\"'s fixed address doesn't match its alignment\n",
name);
alignment = 0; /* Ignore it if it's satisfied */
} else if (startaddr[type] & mask) {
error("Section \"%s\"'s alignment cannot be attained in %s\n",
name, typeNames[type]);
} else if (alignment == 16) {
// Treat an alignment of 16 as being fixed at address 0
alignment = 0;
org = 0;
// The address is known to be valid, since the alignment is
}
}
// Check if another section exists with the same name; merge if yes, otherwise create one
struct Section *sect = out_FindSectionByName(name);
if (sect) {
mergeSections(sect, type, org, bank, alignment, alignOffset, mod);
} else {
sect = createSection(name, type, org, bank, alignment, alignOffset, mod);
// Add the new section to the list (order doesn't matter)
sect->next = pSectionList;
pSectionList = sect;
}
return sect;
}
/*
* Set the current section
*/
static void changeSection(void)
{
if (unionStack)
fatalerror("Cannot change the section within a UNION\n");
sym_SetCurrentSymbolScope(NULL);
}
/*
* Set the current section by name and type
*/
void out_NewSection(char const *name, uint32_t type, uint32_t org,
struct SectionSpec const *attribs, enum SectionModifier mod)
{
if (currentLoadSection)
fatalerror("Cannot change the section within a `LOAD` block\n");
for (struct SectionStackEntry *stack = sectionStack; stack; stack = stack->next) {
if (stack->section && !strcmp(name, stack->section->name))
fatalerror("Section '%s' is already on the stack\n", name);
}
struct Section *sect = getSection(name, type, org, attribs, mod);
changeSection();
curOffset = mod == SECTION_UNION ? 0 : sect->size;
pCurrentSection = sect;
}
/*
* Set the current section by name and type
*/
void out_SetLoadSection(char const *name, uint32_t type, uint32_t org,
struct SectionSpec const *attribs,
enum SectionModifier mod)
{
checkcodesection();
if (currentLoadSection)
fatalerror("`LOAD` blocks cannot be nested\n");
if (sect_HasData(type))
error("`LOAD` blocks cannot create a ROM section\n");
struct Section *sect = getSection(name, type, org, attribs, mod);
changeSection();
loadOffset = curOffset - (mod == SECTION_UNION ? 0 : sect->size);
curOffset -= loadOffset;
currentLoadSection = sect;
}
void out_EndLoadSection(void)
{
if (!currentLoadSection)
error("Found `ENDL` outside of a `LOAD` block\n");
changeSection();
curOffset += loadOffset;
loadOffset = 0;
currentLoadSection = NULL;
}
struct Section *sect_GetSymbolSection(void)
{
return currentLoadSection ? currentLoadSection : pCurrentSection;
}
/*
* The offset into the section above
*/
uint32_t sect_GetSymbolOffset(void)
{
return curOffset;
}
uint32_t sect_GetOutputOffset(void)
{
return curOffset + loadOffset;
}
void sect_AlignPC(uint8_t alignment, uint16_t offset)
{
checksection();
struct Section *sect = sect_GetSymbolSection();
uint16_t alignSize = 1 << alignment; // Size of an aligned "block"
if (sect->org != (uint32_t)-1) {
if ((sym_GetPCValue() - offset) % alignSize)
error("Section's fixed address fails required alignment (PC = $%04" PRIx32
")\n", sym_GetPCValue());
} else if (sect->align != 0) {
if ((((sect->alignOfs + curOffset) % (1 << sect->align)) - offset) % alignSize) {
error("Section's alignment fails required alignment (offset from section start = $%04"
PRIx32 ")\n", curOffset);
} else if (alignment > sect->align) {
sect->align = alignment;
sect->alignOfs = (offset - curOffset) % alignSize;
}
} else {
sect->align = alignment;
// We need `(sect->alignOfs + curOffset) % alignSize == offset
sect->alignOfs = (offset - curOffset) % alignSize;
}
}
static inline void growSection(uint32_t growth)
{
curOffset += growth;
if (curOffset + loadOffset > pCurrentSection->size)
pCurrentSection->size = curOffset + loadOffset;
if (currentLoadSection && curOffset > currentLoadSection->size)
currentLoadSection->size = curOffset;
}
static inline void writebyte(uint8_t byte)
{
pCurrentSection->data[sect_GetOutputOffset()] = byte;
growSection(1);
}
static inline void writeword(uint16_t b)
{
writebyte(b & 0xFF);
writebyte(b >> 8);
}
static inline void writelong(uint32_t b)
{
writebyte(b & 0xFF);
writebyte(b >> 8);
writebyte(b >> 16);
writebyte(b >> 24);
}
static inline void createPatch(enum PatchType type, struct Expression const *expr,
uint32_t pcShift)
{
out_CreatePatch(type, expr, sect_GetOutputOffset(), pcShift);
}
void sect_StartUnion(void)
{
if (!pCurrentSection)
fatalerror("UNIONs must be inside a SECTION\n");
if (sect_HasData(pCurrentSection->type))
fatalerror("Cannot use UNION inside of ROM0 or ROMX sections\n");
struct UnionStackEntry *entry = malloc(sizeof(*entry));
if (!entry)
fatalerror("Failed to allocate new union stack entry: %s\n", strerror(errno));
entry->start = curOffset;
entry->size = 0;
entry->next = unionStack;
unionStack = entry;
}
static void endUnionMember(void)
{
uint32_t memberSize = curOffset - unionStack->start;
if (memberSize > unionStack->size)
unionStack->size = memberSize;
curOffset = unionStack->start;
}
void sect_NextUnionMember(void)
{
if (!unionStack)
fatalerror("Found NEXTU outside of a UNION construct\n");
endUnionMember();
}
void sect_EndUnion(void)
{
if (!unionStack)
fatalerror("Found ENDU outside of a UNION construct\n");
endUnionMember();
curOffset += unionStack->size;
struct UnionStackEntry *next = unionStack->next;
free(unionStack);
unionStack = next;
}
void sect_CheckUnionClosed(void)
{
if (unionStack)
error("Unterminated UNION construct!\n");
}
/*
* Output an absolute byte
*/
void out_AbsByte(uint8_t b)
{
checkcodesection();
reserveSpace(1);
writebyte(b);
}
void out_AbsByteGroup(uint8_t const *s, int32_t length)
{
checkcodesection();
reserveSpace(length);
while (length--)
writebyte(*s++);
}
void out_AbsWordGroup(uint8_t const *s, int32_t length)
{
checkcodesection();
reserveSpace(length * 2);
while (length--)
writeword(*s++);
}
void out_AbsLongGroup(uint8_t const *s, int32_t length)
{
checkcodesection();
reserveSpace(length * 4);
while (length--)
writelong(*s++);
}
/*
* Skip this many bytes
*/
void out_Skip(int32_t skip, bool ds)
{
checksection();
reserveSpace(skip);
if (!ds && sect_HasData(pCurrentSection->type))
warning(WARNING_EMPTY_DATA_DIRECTIVE, "%s directive without data in ROM\n",
(skip == 4) ? "DL" : (skip == 2) ? "DW" : "DB");
if (!sect_HasData(pCurrentSection->type)) {
growSection(skip);
} else {
checkcodesection();
while (skip--)
writebyte(fillByte);
}
}
/*
* Output a NULL terminated string (excluding the NULL-character)
*/
void out_String(char const *s)
{
checkcodesection();
reserveSpace(strlen(s));
while (*s)
writebyte(*s++);
}
/*
* Output a relocatable byte. Checking will be done to see if it
* is an absolute value in disguise.
*/
void out_RelByte(struct Expression *expr, uint32_t pcShift)
{
checkcodesection();
reserveSpace(1);
if (!rpn_isKnown(expr)) {
createPatch(PATCHTYPE_BYTE, expr, pcShift);
writebyte(0);
} else {
writebyte(expr->nVal);
}
rpn_Free(expr);
}
/*
* Output several copies of a relocatable byte. Checking will be done to see if
* it is an absolute value in disguise.
*/
void out_RelBytes(uint32_t n, struct Expression *exprs, size_t size)
{
checkcodesection();
reserveSpace(n);
for (uint32_t i = 0; i < n; i++) {
struct Expression *expr = &exprs[i % size];
if (!rpn_isKnown(expr)) {
createPatch(PATCHTYPE_BYTE, expr, i);
writebyte(0);
} else {
writebyte(expr->nVal);
}
}
for (size_t i = 0; i < size; i++)
rpn_Free(&exprs[i]);
}
/*
* Output a relocatable word. Checking will be done to see if
* it's an absolute value in disguise.
*/
void out_RelWord(struct Expression *expr, uint32_t pcShift)
{
checkcodesection();
reserveSpace(2);
if (!rpn_isKnown(expr)) {
createPatch(PATCHTYPE_WORD, expr, pcShift);
writeword(0);
} else {
writeword(expr->nVal);
}
rpn_Free(expr);
}
/*
* Output a relocatable longword. Checking will be done to see if
* is an absolute value in disguise.
*/
void out_RelLong(struct Expression *expr, uint32_t pcShift)
{
checkcodesection();
reserveSpace(2);
if (!rpn_isKnown(expr)) {
createPatch(PATCHTYPE_LONG, expr, pcShift);
writelong(0);
} else {
writelong(expr->nVal);
}
rpn_Free(expr);
}
/*
* Output a PC-relative relocatable byte. Checking will be done to see if it
* is an absolute value in disguise.
*/
void out_PCRelByte(struct Expression *expr, uint32_t pcShift)
{
checkcodesection();
reserveSpace(1);
struct Symbol const *pc = sym_GetPC();
if (!rpn_IsDiffConstant(expr, pc)) {
createPatch(PATCHTYPE_JR, expr, pcShift);
writebyte(0);
} else {
struct Symbol const *sym = rpn_SymbolOf(expr);
/* The offset wraps (jump from ROM to HRAM, for example) */
int16_t offset;
/* Offset is relative to the byte *after* the operand */
if (sym == pc)
offset = -2; /* PC as operand to `jr` is lower than reference PC by 2 */
else
offset = sym_GetValue(sym) - (sym_GetValue(pc) + 1);
if (offset < -128 || offset > 127) {
error("jr target out of reach (expected -129 < %" PRId16 " < 128)\n",
offset);
writebyte(0);
} else {
writebyte(offset);
}
}
rpn_Free(expr);
}
/*
* Output a binary file
*/
void out_BinaryFile(char const *s, int32_t startPos)
{
if (startPos < 0) {
error("Start position cannot be negative (%" PRId32 ")\n", startPos);
startPos = 0;
}
char *fullPath = NULL;
size_t size = 0;
FILE *f = NULL;
if (fstk_FindFile(s, &fullPath, &size))
f = fopen(fullPath, "rb");
free(fullPath);
if (!f) {
if (oGeneratedMissingIncludes) {
if (verbose)
printf("Aborting (-MG) on INCBIN file '%s' (%s)\n", s, strerror(errno));
oFailedOnMissingInclude = true;
return;
}
error("Error opening INCBIN file '%s': %s\n", s, strerror(errno));
return;
}
int32_t fsize = -1;
int byte;
checkcodesection();
if (fseek(f, 0, SEEK_END) != -1) {
fsize = ftell(f);
if (startPos > fsize) {
error("Specified start position is greater than length of file\n");
fclose(f);
return;
}
fseek(f, startPos, SEEK_SET);
reserveSpace(fsize - startPos);
} else {
if (errno != ESPIPE)
error("Error determining size of INCBIN file '%s': %s\n",
s, strerror(errno));
/* The file isn't seekable, so we'll just skip bytes */
while (startPos--)
(void)fgetc(f);
}
while ((byte = fgetc(f)) != EOF) {
if (fsize == -1)
growSection(1);
writebyte(byte);
}
if (ferror(f))
error("Error reading INCBIN file '%s': %s\n", s, strerror(errno));
fclose(f);
}
void out_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length)
{
if (start_pos < 0) {
error("Start position cannot be negative (%" PRId32 ")\n", start_pos);
start_pos = 0;
}
if (length < 0) {
error("Number of bytes to read cannot be negative (%" PRId32 ")\n", length);
length = 0;
}
if (length == 0) /* Don't even bother with 0-byte slices */
return;
char *fullPath = NULL;
size_t size = 0;
FILE *f = NULL;
if (fstk_FindFile(s, &fullPath, &size))
f = fopen(fullPath, "rb");
if (!f) {
free(fullPath);
if (oGeneratedMissingIncludes) {
if (verbose)
printf("Aborting (-MG) on INCBIN file '%s' (%s)\n", s, strerror(errno));
oFailedOnMissingInclude = true;
return;
}
error("Error opening INCBIN file '%s': %s\n", s, strerror(errno));
return;
}
checkcodesection();
reserveSpace(length);
int32_t fsize;
if (fseek(f, 0, SEEK_END) != -1) {
fsize = ftell(f);
if (start_pos > fsize) {
error("Specified start position is greater than length of file\n");
return;
}
if ((start_pos + length) > fsize) {
error("Specified range in INCBIN is out of bounds (%" PRIu32 " + %" PRIu32
" > %" PRIu32 ")\n", start_pos, length, fsize);
return;
}
fseek(f, start_pos, SEEK_SET);
} else {
if (errno != ESPIPE)
error("Error determining size of INCBIN file '%s': %s\n",
s, strerror(errno));
/* The file isn't seekable, so we'll just skip bytes */
while (start_pos--)
(void)fgetc(f);
}
int32_t todo = length;
while (todo--) {
int byte = fgetc(f);
if (byte != EOF) {
writebyte(byte);
} else if (ferror(f)) {
error("Error reading INCBIN file '%s': %s\n", s, strerror(errno));
} else {
error("Premature end of file (%" PRId32 " bytes left to read)\n",
todo + 1);
}
}
fclose(f);
free(fullPath);
}
/*
* Section stack routines
*/
void out_PushSection(void)
{
struct SectionStackEntry *sect = malloc(sizeof(*sect));
if (sect == NULL)
fatalerror("No memory for section stack: %s\n", strerror(errno));
sect->section = pCurrentSection;
sect->scope = sym_GetCurrentSymbolScope();
sect->offset = curOffset;
sect->next = sectionStack;
sectionStack = sect;
/* TODO: maybe set current section to NULL? */
}
void out_PopSection(void)
{
if (!sectionStack)
fatalerror("No entries in the section stack\n");
if (currentLoadSection)
fatalerror("Cannot change the section within a `LOAD` block!\n");
struct SectionStackEntry *sect;
sect = sectionStack;
changeSection();
pCurrentSection = sect->section;
sym_SetCurrentSymbolScope(sect->scope);
curOffset = sect->offset;
sectionStack = sect->next;
free(sect);
}
+587 -753
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More