1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-09 08:54:40 +00:00

Added -Dname=body command-line option for defining macros on the command line.

This commit is contained in:
jespergravgaard 2020-05-09 23:17:11 +02:00
parent 8651ee8886
commit 16d19d69a4
10 changed files with 68 additions and 32 deletions

View File

@ -69,6 +69,7 @@
<includes>
<include>**/*.c</include>
<include>**/*.h</include>
<include>**/*.ld</include>
<include>**/*.asm</include>
<include>**/*.sym</include>
<include>**/*.cfg</include>

View File

@ -17,6 +17,7 @@
<includes>
<include>*.c</include>
<include>*.h</include>
<include>*.ld</include>
</includes>
</fileSet>
<fileSet>
@ -25,6 +26,7 @@
<includes>
<include>*.c</include>
<include>*.h</include>
<include>*.ld</include>
</includes>
</fileSet>
<fileSet>

View File

@ -8,18 +8,18 @@ import dk.camelot64.kickc.model.statements.StatementSource;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.values.SymbolRef;
import dk.camelot64.kickc.parser.CParser;
import dk.camelot64.kickc.parser.KickCLexer;
import dk.camelot64.kickc.parser.KickCParser;
import dk.camelot64.kickc.passes.*;
import dk.camelot64.kickc.preprocessor.CPreprocessor;
import org.antlr.v4.runtime.RuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenSource;
import org.antlr.v4.runtime.*;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/**
* Perform KickC compilation and optimizations
@ -148,13 +148,35 @@ public class Compiler {
program.getLibraryPaths().add(path);
}
public void preprocess(List<Path> cFiles) {
Path currentPath = new File(".").toPath();
/**
* Create a CParser and initialize it by adding any command-line defines and loading the files.
*
* @param defines The defined to add
* @param cFiles The files to load
* @param currentPath The current path (used to search for files)
* @return The initialized parser
*/
private CParser initializeParser(Map<String, String> defines, List<Path> cFiles, Path currentPath) {
CParser cParser = new CParser(program);
if(defines != null) {
for(String macroName : defines.keySet()) {
final String macroBodyText = "#define " + macroName + " " + defines.get(macroName) + "\n";
final CodePointCharStream macroCharStream = CharStreams.fromString(macroBodyText);
final KickCLexer macroLexer = cParser.makeLexer(macroCharStream);
cParser.addSourceFirst(macroLexer);
}
}
for(Path cFile : cFiles) {
final TokenSource cFileTokens = cParser.loadCFile(cFile.toString(), currentPath, program.getIncludePaths(), false);
cParser.addSourceLast(cFileTokens);
}
return cParser;
}
public void preprocess(List<Path> cFiles, Map<String, String> defines) {
Path currentPath = new File(".").toPath();
CParser cParser = initializeParser(defines, cFiles, currentPath);
final CPreprocessor preprocessor = cParser.getPreprocessor();
Token token = preprocessor.nextToken();
while(token.getType() != Token.EOF) {
@ -164,7 +186,7 @@ public class Compiler {
System.out.println();
}
public void compile(List<Path> cFiles) {
public void compile(List<Path> cFiles, Map<String, String> defines) {
if(cFiles.size() == 0)
throw new CompileError("Error! You must supply at least one file to compile!");
@ -178,11 +200,7 @@ public class Compiler {
SourceLoader.loadLinkScriptFile(linkScriptFileName, currentPath, program);
}
program.setStatementSequence(new StatementSequence());
CParser cParser = new CParser(program);
for(Path cFile : cFiles) {
final TokenSource cFileTokens = cParser.loadCFile(cFile.toString(), currentPath, program.getIncludePaths(), false);
cParser.addSourceLast(cFileTokens);
}
CParser cParser = initializeParser(defines, cFiles, currentPath);
// Parse the files
KickCParser.FileContext cFileContext = cParser.getParser().file();

View File

@ -18,6 +18,7 @@ import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
@ -40,15 +41,6 @@ public class KickC implements Callable<Void> {
@CommandLine.Parameters(index = "0", arity = "0..n", description = "The C source files to compile.")
private List<Path> cFiles = null;
@CommandLine.Option(names = {"-I", "-includedir"}, description = "Path to an include folder, where the compiler looks for included files. This option can be repeated to add multiple include folders.")
private List<Path> includeDir = null;
@CommandLine.Option(names = {"-L", "-libdir"}, description = "Path to a library folder, where the compiler looks for library files. This option can be repeated to add multiple library folders.")
private List<Path> libDir = null;
@CommandLine.Option(names = {"-F", "-fragmentdir"}, description = "Path to the ASM fragment folder, where the compiler looks for ASM fragments.")
private Path fragmentDir = null;
@CommandLine.Option(names = {"-o", "-output"}, description = "Name of the output file. By default it is the same as the first input file with the proper extension.")
private String outputFileName = null;
@ -67,9 +59,21 @@ public class KickC implements Callable<Void> {
@CommandLine.Option(names = {"-d"}, description = "Debug the assembled prg file using C64Debugger. Implicitly assembles the output.")
private boolean debug = false;
@CommandLine.Option(names = {"-D"}, description = "Define a macro to have a specific value.")
private Map<String, String> defines = null;
@CommandLine.Option(names = {"-E"}, description = "Only run the preprocessor. Output is sent to standard out.")
private boolean preprocess = false;
@CommandLine.Option(names = {"-I", "-includedir"}, description = "Path to an include folder, where the compiler looks for included files. This option can be repeated to add multiple include folders.")
private List<Path> includeDir = null;
@CommandLine.Option(names = {"-L", "-libdir"}, description = "Path to a library folder, where the compiler looks for library files. This option can be repeated to add multiple library folders.")
private List<Path> libDir = null;
@CommandLine.Option(names = {"-F", "-fragmentdir"}, description = "Path to the ASM fragment folder, where the compiler looks for ASM fragments.")
private Path fragmentDir = null;
@CommandLine.Option(names = {"-Ouplift"}, description = "Optimization Option. Number of combinations to test when uplifting variables to registers in a scope. By default 100 combinations are tested.")
private Integer optimizeUpliftCombinations = null;
@ -346,7 +350,7 @@ public class KickC implements Callable<Void> {
if(preprocess) {
System.out.println("Preprocessing " + CFileNames);
try {
compiler.preprocess(cFiles);
compiler.preprocess(cFiles, defines);
} catch(CompileError e) {
// Print the error and exit with compile error
System.err.println(e.getMessage());
@ -358,7 +362,7 @@ public class KickC implements Callable<Void> {
System.out.println("Compiling " + CFileNames);
Program program = compiler.getProgram();
try {
compiler.compile(cFiles);
compiler.compile(cFiles, defines);
} catch(CompileError e) {
// Print the error and exit with compile error
System.err.println(e.getMessage());
@ -396,13 +400,12 @@ public class KickC implements Callable<Void> {
// Find emulator - if set by #pragma
if(emulator == null) {
if(program.getEmulatorCommand() != null)
if(program.getEmulatorCommand() != null && (debug || execute))
emulator = program.getEmulatorCommand();
else if(debug) {
else if(debug)
emulator = "C64Debugger";
} else if(execute) {
else if(execute)
emulator = "x64sc";
}
}
if(assemble || emulator != null) {

View File

@ -27,6 +27,8 @@ struct MOS6581_SID * const SID = 0xd400;
// The VIC-II MOS 6567/6569
struct MOS6569_VICII* const VICII = 0xd000;
// Color Ram
char * const COLORRAM = 0xd800;
// Color Ram
char * const COLS = 0xd800;
// The CIA#1: keyboard matrix, joystick #1/#2

View File

@ -0,0 +1,9 @@
.file [name="%O.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$080d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(%E)
.segment Code

View File

@ -1,7 +1,7 @@
.file [name="%O.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$1001]
.segmentdef Code [start=$1010]
.segmentdef Code [start=$100d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(%E)

View File

@ -23,6 +23,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import static junit.framework.TestCase.fail;
import static org.junit.Assert.assertTrue;
@ -4304,7 +4305,7 @@ public class TestPrograms {
final ArrayList<Path> files = new ArrayList<>();
final Path filePath = Paths.get(fileName);
files.add(filePath);
compiler.compile(files);
compiler.compile(files, null);
Program program = compiler.getProgram();
compileAsm(fileName, program);
boolean success = true;

View File

@ -2,7 +2,7 @@
.file [name="plus4walk.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$1001]
.segmentdef Code [start=$1010]
.segmentdef Code [start=$100d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(__bbegin)

View File

@ -1103,7 +1103,7 @@ Target platform is custom / MOS6502X
.file [name="plus4walk.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$1001]
.segmentdef Code [start=$1010]
.segmentdef Code [start=$100d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(__bbegin)
@ -1746,7 +1746,7 @@ ASSEMBLER BEFORE OPTIMIZATION
.file [name="plus4walk.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$1001]
.segmentdef Code [start=$1010]
.segmentdef Code [start=$100d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(__bbegin)
@ -2448,7 +2448,7 @@ Score: 6721
.file [name="plus4walk.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$1001]
.segmentdef Code [start=$1010]
.segmentdef Code [start=$100d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(__bbegin)