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"
[M]="dependfile:glob-*.mk *.d"
[o]="output:glob-*.o"
[P]="preinclude:glob-*.asm *.inc"
[p]="pad-value:unk"
[Q]="q-precision: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}'"
'*'-MQ"+[Add a target to the rules]:target:_files -g '*.{d,mk,o}'"
'(-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:'
'(-Q --q-precision)'{-Q,--q-precision}'+[Set fixed-point precision]:precision:'
'(-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);
void fstk_AddIncludePath(char const *s);
void fstk_SetPreIncludeFile(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

View File

@@ -24,21 +24,21 @@
.Op Fl MT Ar target_file
.Op Fl MQ Ar target_file
.Op Fl o Ar out_file
.Op Fl P Ar include_file
.Op Fl p Ar pad_value
.Op Fl Q Ar fix_precision
.Op Fl r Ar recursion_depth
.Op Fl W Ar warning
.Ar
.Ar asmfile
.Sh DESCRIPTION
The
.Nm
program creates an RGB object file from an assembly source file.
The input
.Ar file
can be a file path, or
.Ar asmfile
can be a path to a file, or
.Cm \-
denoting
.Cm stdin .
to read from standard input.
.Pp
Note that options can be abbreviated as long as the abbreviation is unambiguous:
.Fl Fl verb
@@ -87,7 +87,19 @@ instruction immediately after any
.Ic halt
instruction.
.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
By default,
.Nm
@@ -116,6 +128,7 @@ This makes
.Nm
assume that missing files are auto-generated: when
.Ic INCLUDE
.Pq including the implicit one from Fl P
or
.Ic INCBIN
is attempted on a non-existent file, it is added as a dependency, then
@@ -146,6 +159,12 @@ 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 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
When padding an image, pad with this value.
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
INCLUDE "irq.inc"
.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
The four commands
.Ic IF , ELIF , ELSE ,

View File

@@ -42,6 +42,8 @@ size_t maxRecursionDepth;
static unsigned int nbIncPaths = 0;
static char const *includePaths[MAXINCPATHS];
static const char *preIncludeName;
static const char *dumpNodeAndParents(struct FileStackNode const *node)
{
char const *name;
@@ -133,6 +135,11 @@ void fstk_AddIncludePath(char const *path)
includePaths[nbIncPaths++] = str;
}
void fstk_SetPreIncludeFile(char const *path)
{
preIncludeName = path;
}
static void printDep(char const *path)
{
if (dependfile) {
@@ -274,6 +281,7 @@ bool yywrap(void)
lexer_SetState(contextStack->lexerState);
macro_SetUniqueID(contextStack->uniqueID);
return false;
}
@@ -342,6 +350,41 @@ void fstk_RunInclude(char const *path)
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)
{
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
assert(DEPTH_LIMIT >= DEFAULT_MAX_DEPTH);
#undef DEPTH_LIMIT
runPreIncludeFile();
}

View File

@@ -87,7 +87,7 @@ static char *make_escape(char const *str)
}
// 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
static int depType; // Variants of `-M`
@@ -116,6 +116,7 @@ static struct option const longopts[] = {
{ "MT", required_argument, &depType, 'T' },
{ "MQ", required_argument, &depType, 'Q' },
{ "output", required_argument, NULL, 'o' },
{ "preinclude", required_argument, NULL, 'P' },
{ "pad-value", required_argument, NULL, 'p' },
{ "q-precision", required_argument, NULL, 'Q' },
{ "recursion-depth", required_argument, NULL, 'r' },
@@ -130,8 +131,8 @@ static void print_usage(void)
fputs(
"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"
" [-o out_file] [-p pad_value] [-Q precision] [-r depth]\n"
" [-W warning] <file>\n"
" [-o out_file] [-P include_file] [-p pad_value] [-Q precision]\n"
" [-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"
@@ -254,6 +255,10 @@ int main(int argc, char *argv[])
out_SetFileName(musl_optarg);
break;
case 'P':
fstk_SetPreIncludeFile(musl_optarg);
break;
unsigned long padByte;
case 'p':
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
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
echo "${bold}${green}${i%.asm}${variant}...${rescolors}${resbold}"
desired_errname=${i%.asm}.err
@@ -83,7 +88,7 @@ for i in *.asm; do
desired_errname=${i%.asm}.simple.err
fi
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_errput=$desired_errname
else
@@ -97,7 +102,7 @@ for i in *.asm; do
# stdin redirection makes the input an unseekable pipe - a scenario
# that's harder to deal with and was broken when the feature was
# 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
desired_output=$input