Support -P/--preinclude to pre-INCLUDE a file (#1043)

Fixes #1041

Co-authored-by: ISSOtm <eldredhabert0@gmail.com>
This commit is contained in:
Rangi
2022-09-24 12:37:16 -04:00
committed by GitHub
parent 02923a67f3
commit b8385a50e3
13 changed files with 121 additions and 11 deletions

View File

@@ -38,6 +38,7 @@ _rgbasm_completions() {
[i]="include:dir" [i]="include:dir"
[M]="dependfile:glob-*.mk *.d" [M]="dependfile:glob-*.mk *.d"
[o]="output:glob-*.o" [o]="output:glob-*.o"
[P]="preinclude:glob-*.asm *.inc"
[p]="pad-value:unk" [p]="pad-value:unk"
[Q]="q-precision:unk" [Q]="q-precision:unk"
[r]="recursion-depth:unk" [r]="recursion-depth:unk"

View File

@@ -55,6 +55,7 @@ local args=(
'*'-MT"+[Add a target to the rules]:target:_files -g '*.{d,mk,o}'" '*'-MT"+[Add a target to the rules]:target:_files -g '*.{d,mk,o}'"
'*'-MQ"+[Add a target to the rules]:target:_files -g '*.{d,mk,o}'" '*'-MQ"+[Add a target to the rules]:target:_files -g '*.{d,mk,o}'"
'(-o --output)'{-o,--output}'+[Output file]:output file:_files' '(-o --output)'{-o,--output}'+[Output file]:output file:_files'
'(-P --preinclude)'{-P,--preinclude}"+[Pre-include a file]:include file:_files -g '*.{asm,inc}'"
'(-p --pad-value)'{-p,--pad-value}'+[Set padding byte]:padding byte:' '(-p --pad-value)'{-p,--pad-value}'+[Set padding byte]:padding byte:'
'(-Q --q-precision)'{-Q,--q-precision}'+[Set fixed-point precision]:precision:' '(-Q --q-precision)'{-Q,--q-precision}'+[Set fixed-point precision]:precision:'
'(-r --recursion-depth)'{-r,--recursion-depth}'+[Set maximum recursion depth]:depth:' '(-r --recursion-depth)'{-r,--recursion-depth}'+[Set maximum recursion depth]:depth:'

View File

@@ -58,6 +58,7 @@ struct FileStackNode *fstk_GetFileStack(void);
char const *fstk_GetFileName(void); char const *fstk_GetFileName(void);
void fstk_AddIncludePath(char const *s); void fstk_AddIncludePath(char const *s);
void fstk_SetPreIncludeFile(char const *s);
/* /*
* @param path The user-provided file name * @param path The user-provided file name
* @param fullPath The address of a pointer, which will be made to point at the full path * @param fullPath The address of a pointer, which will be made to point at the full path

View File

@@ -24,21 +24,21 @@
.Op Fl MT Ar target_file .Op Fl MT Ar target_file
.Op Fl MQ Ar target_file .Op Fl MQ Ar target_file
.Op Fl o Ar out_file .Op Fl o Ar out_file
.Op Fl P Ar include_file
.Op Fl p Ar pad_value .Op Fl p Ar pad_value
.Op Fl Q Ar fix_precision .Op Fl Q Ar fix_precision
.Op Fl r Ar recursion_depth .Op Fl r Ar recursion_depth
.Op Fl W Ar warning .Op Fl W Ar warning
.Ar .Ar asmfile
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Nm .Nm
program creates an RGB object file from an assembly source file. program creates an RGB object file from an assembly source file.
The input The input
.Ar file .Ar asmfile
can be a file path, or can be a path to a file, or
.Cm \- .Cm \-
denoting to read from standard input.
.Cm stdin .
.Pp .Pp
Note that options can be abbreviated as long as the abbreviation is unambiguous: Note that options can be abbreviated as long as the abbreviation is unambiguous:
.Fl Fl verb .Fl Fl verb
@@ -87,7 +87,19 @@ instruction immediately after any
.Ic halt .Ic halt
instruction. instruction.
.It Fl i Ar path , Fl Fl include Ar path .It Fl i Ar path , Fl Fl include Ar path
Add an include path. Add a new
.Dq include path ; Ar path
must point to a directory.
When a
.Ic INCLUDE
.Pq including the implicit one from Fl P
or
.Ic INCBIN
is attempted,
.Nm
first looks up the provided path from its working directory; if this fails, it tries again from each of the
.Dq include path
directories, in the order they were provided.
.It Fl L , Fl Fl preserve-ld .It Fl L , Fl Fl preserve-ld
By default, By default,
.Nm .Nm
@@ -116,6 +128,7 @@ This makes
.Nm .Nm
assume that missing files are auto-generated: when assume that missing files are auto-generated: when
.Ic INCLUDE .Ic INCLUDE
.Pq including the implicit one from Fl P
or or
.Ic INCBIN .Ic INCBIN
is attempted on a non-existent file, it is added as a dependency, then is attempted on a non-existent file, it is added as a dependency, then
@@ -146,6 +159,12 @@ characters, essentially
.Sq $ . .Sq $ .
.It Fl o Ar out_file , Fl Fl output Ar out_file .It Fl o Ar out_file , Fl Fl output Ar out_file
Write an object file to the given filename. Write an object file to the given filename.
.It Fl P Ar include_file , Fl Fl preinclude Ar include_file
Pre-include a file.
This acts as if a
.Ql Ic INCLUDE Qq Ar include_file
was read before the input
.Ar asmfile .
.It Fl p Ar pad_value , Fl Fl pad-value Ar pad_value .It Fl p Ar pad_value , Fl Fl pad-value Ar pad_value
When padding an image, pad with this value. When padding an image, pad with this value.
The default is 0x00. The default is 0x00.

View File

@@ -1972,6 +1972,13 @@ calls infinitely (or until you run out of memory, whichever comes first).
.Bd -literal -offset indent .Bd -literal -offset indent
INCLUDE "irq.inc" INCLUDE "irq.inc"
.Ed .Ed
.Pp
You may also implicitly
.Ic INCLUDE
a file before the source file with the
.Fl P
option of
.Xr rgbasm 1 .
.Ss Conditional assembling .Ss Conditional assembling
The four commands The four commands
.Ic IF , ELIF , ELSE , .Ic IF , ELIF , ELSE ,

View File

@@ -42,6 +42,8 @@ size_t maxRecursionDepth;
static unsigned int nbIncPaths = 0; static unsigned int nbIncPaths = 0;
static char const *includePaths[MAXINCPATHS]; static char const *includePaths[MAXINCPATHS];
static const char *preIncludeName;
static const char *dumpNodeAndParents(struct FileStackNode const *node) static const char *dumpNodeAndParents(struct FileStackNode const *node)
{ {
char const *name; char const *name;
@@ -133,6 +135,11 @@ void fstk_AddIncludePath(char const *path)
includePaths[nbIncPaths++] = str; includePaths[nbIncPaths++] = str;
} }
void fstk_SetPreIncludeFile(char const *path)
{
preIncludeName = path;
}
static void printDep(char const *path) static void printDep(char const *path)
{ {
if (dependfile) { if (dependfile) {
@@ -274,6 +281,7 @@ bool yywrap(void)
lexer_SetState(contextStack->lexerState); lexer_SetState(contextStack->lexerState);
macro_SetUniqueID(contextStack->uniqueID); macro_SetUniqueID(contextStack->uniqueID);
return false; return false;
} }
@@ -342,6 +350,41 @@ void fstk_RunInclude(char const *path)
contextStack->uniqueID = macro_UndefUniqueID(); contextStack->uniqueID = macro_UndefUniqueID();
} }
// Similar to `fstk_RunInclude`, but not subject to `-MG`, and
// calling `lexer_SetState` instead of `lexer_SetStateAtEOL`.
static void runPreIncludeFile(void)
{
if (!preIncludeName)
return;
char *fullPath = NULL;
size_t size = 0;
if (!fstk_FindFile(preIncludeName, &fullPath, &size)) {
free(fullPath);
error("Unable to open included file '%s': %s\n", preIncludeName, strerror(errno));
return;
}
struct FileStackNamedNode *fileInfo = malloc(sizeof(*fileInfo) + size);
if (!fileInfo) {
error("Failed to alloc file info for pre-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_SetState(contextStack->lexerState);
// We're back at top-level, so most things are reset
contextStack->uniqueID = macro_UndefUniqueID();
}
void fstk_RunMacro(char const *macroName, struct MacroArgs *args) void fstk_RunMacro(char const *macroName, struct MacroArgs *args)
{ {
struct Symbol *macro = sym_FindExactSymbol(macroName); struct Symbol *macro = sym_FindExactSymbol(macroName);
@@ -563,4 +606,6 @@ void fstk_Init(char const *mainPath, size_t maxDepth)
// Make sure that the default of 64 is OK, though // Make sure that the default of 64 is OK, though
assert(DEPTH_LIMIT >= DEFAULT_MAX_DEPTH); assert(DEPTH_LIMIT >= DEFAULT_MAX_DEPTH);
#undef DEPTH_LIMIT #undef DEPTH_LIMIT
runPreIncludeFile();
} }

View File

@@ -87,7 +87,7 @@ static char *make_escape(char const *str)
} }
// Short options // Short options
static const char *optstring = "b:D:Eg:Hhi:LlM:o:p:Q:r:VvW:w"; static const char *optstring = "b:D:Eg:Hhi:LlM:o:P:p:Q:r:VvW:w";
// Variables for the long-only options // Variables for the long-only options
static int depType; // Variants of `-M` static int depType; // Variants of `-M`
@@ -116,6 +116,7 @@ static struct option const longopts[] = {
{ "MT", required_argument, &depType, 'T' }, { "MT", required_argument, &depType, 'T' },
{ "MQ", required_argument, &depType, 'Q' }, { "MQ", required_argument, &depType, 'Q' },
{ "output", required_argument, NULL, 'o' }, { "output", required_argument, NULL, 'o' },
{ "preinclude", required_argument, NULL, 'P' },
{ "pad-value", required_argument, NULL, 'p' }, { "pad-value", required_argument, NULL, 'p' },
{ "q-precision", required_argument, NULL, 'Q' }, { "q-precision", required_argument, NULL, 'Q' },
{ "recursion-depth", required_argument, NULL, 'r' }, { "recursion-depth", required_argument, NULL, 'r' },
@@ -130,8 +131,8 @@ static void print_usage(void)
fputs( fputs(
"Usage: rgbasm [-EHhLlVvw] [-b chars] [-D name[=value]] [-g chars] [-i path]\n" "Usage: rgbasm [-EHhLlVvw] [-b chars] [-D name[=value]] [-g chars] [-i path]\n"
" [-M depend_file] [-MG] [-MP] [-MT target_file] [-MQ target_file]\n" " [-M depend_file] [-MG] [-MP] [-MT target_file] [-MQ target_file]\n"
" [-o out_file] [-p pad_value] [-Q precision] [-r depth]\n" " [-o out_file] [-P include_file] [-p pad_value] [-Q precision]\n"
" [-W warning] <file>\n" " [-r depth] [-W warning] <file>\n"
"Useful options:\n" "Useful options:\n"
" -E, --export-all export all labels\n" " -E, --export-all export all labels\n"
" -M, --dependfile <path> set the output dependency file\n" " -M, --dependfile <path> set the output dependency file\n"
@@ -254,6 +255,10 @@ int main(int argc, char *argv[])
out_SetFileName(musl_optarg); out_SetFileName(musl_optarg);
break; break;
case 'P':
fstk_SetPreIncludeFile(musl_optarg);
break;
unsigned long padByte; unsigned long padByte;
case 'p': case 'p':
padByte = strtoul(musl_optarg, &ep, 0); padByte = strtoul(musl_optarg, &ep, 0);

3
test/asm/preinclude.asm Normal file
View File

@@ -0,0 +1,3 @@
warn "main {__FILE__}"
def v3 = v1 + v2
println "{d:v1} + {d:v2} = {d:v3}"

4
test/asm/preinclude.err Normal file
View File

@@ -0,0 +1,4 @@
warning: preinclude.asm(0) -> preinclude.inc(1): [-Wuser]
pre-include "preinclude.inc"
warning: preinclude.asm(1): [-Wuser]
main "preinclude.asm"

View File

@@ -0,0 +1 @@
-Weverything -P preinclude.inc

11
test/asm/preinclude.inc Normal file
View File

@@ -0,0 +1,11 @@
warn "pre-include {__FILE__}"
def v1 = 12
rept 3
println "rept 3"
endr
def v2 = 34
for i, 3
println "for {d:i}/3"
endr

7
test/asm/preinclude.out Normal file
View File

@@ -0,0 +1,7 @@
rept 3
rept 3
rept 3
for 0/3
for 1/3
for 2/3
12 + 34 = 46

View File

@@ -76,6 +76,11 @@ if ! diff --strip-trailing-cr syntax-error.err $errput; then
fi fi
for i in *.asm; do for i in *.asm; do
flags=${i%.asm}.flags
RGBASMFLAGS=-Weverything
if [ -f $flags ]; then
RGBASMFLAGS="$(head -n 1 "$flags")" # Allow other lines to serve as comments
fi
for variant in '' '.pipe'; do for variant in '' '.pipe'; do
echo "${bold}${green}${i%.asm}${variant}...${rescolors}${resbold}" echo "${bold}${green}${i%.asm}${variant}...${rescolors}${resbold}"
desired_errname=${i%.asm}.err desired_errname=${i%.asm}.err
@@ -83,7 +88,7 @@ for i in *.asm; do
desired_errname=${i%.asm}.simple.err desired_errname=${i%.asm}.simple.err
fi fi
if [ -z "$variant" ]; then if [ -z "$variant" ]; then
$RGBASM -Weverything -o $o $i > $output 2> $errput $RGBASM $RGBASMFLAGS -o $o $i > $output 2> $errput
desired_output=${i%.asm}.out desired_output=${i%.asm}.out
desired_errput=$desired_errname desired_errput=$desired_errname
else else
@@ -97,7 +102,7 @@ for i in *.asm; do
# stdin redirection makes the input an unseekable pipe - a scenario # stdin redirection makes the input an unseekable pipe - a scenario
# that's harder to deal with and was broken when the feature was # that's harder to deal with and was broken when the feature was
# first implemented. # first implemented.
cat $i | $RGBASM -Weverything -o $o - > $output 2> $errput cat $i | $RGBASM $RGBASMFLAGS -o $o - > $output 2> $errput
# Use two otherwise unused files for temp storage # Use two otherwise unused files for temp storage
desired_output=$input desired_output=$input