r4834@macbookpro: aamine | 2009-05-11 03:17:05 +0900

* net/loveruby/cflat/compiler/Compiler.java: objectify assembler.
 * net/loveruby/cflat/compiler/Compiler.java: objectify linker.
 * net/loveruby/cflat/compiler/Options.java: provide #assembler, #asOptions, #linker, #ldOptions.
 * net/loveruby/cflat/sysdep/x86/X86Linux.java -> sysdep/X86Linux.java
 * net/loveruby/cflat/sysdep/Platform.java: provide #assembler, #linker.
 * net/loveruby/cflat/sysdep/X86Linux.java: ditto.
 * net/loveruby/cflat/sysdep/Assembler.java: new interface.
 * net/loveruby/cflat/sysdep/AssemblerOptions.java: new class.
 * net/loveruby/cflat/sysdep/GNUAssembler.java: new Assembler implementation.
 * net/loveruby/cflat/sysdep/Linker.java: new interface.
 * net/loveruby/cflat/sysdep/LinkerOptions.java: new clas.
 * net/loveruby/cflat/sysdep/GNULinker.java: new Linker implementation.
 * net/loveruby/cflat/utils/CommandUtils.java: new class.
 * net/loveruby/cflat/compiler/LdArg.java -> utils/CommandArg.java
 * net/loveruby/cflat/compiler/LdOption.java -> utils/CommandArgStr.java
 * net/loveruby/cflat/compiler/SourceFile.java: implements CommandArg.
 


git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4207 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
Minero Aoki 2009-05-10 18:18:52 +00:00
parent f6c90ab8da
commit c26eb88f2e
18 changed files with 386 additions and 222 deletions

View File

@ -1,3 +1,44 @@
Mon May 11 03:17:32 2009 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/compiler/Compiler.java: objectify assembler.
* net/loveruby/cflat/compiler/Compiler.java: objectify linker.
* net/loveruby/cflat/compiler/Options.java: provide #assembler,
#asOptions, #linker, #ldOptions.
* net/loveruby/cflat/sysdep/x86/X86Linux.java ->
sysdep/X86Linux.java
* net/loveruby/cflat/sysdep/Platform.java: provide #assembler,
#linker.
* net/loveruby/cflat/sysdep/X86Linux.java: ditto.
* net/loveruby/cflat/sysdep/Assembler.java: new interface.
* net/loveruby/cflat/sysdep/AssemblerOptions.java: new class.
* net/loveruby/cflat/sysdep/GNUAssembler.java: new Assembler
implementation.
* net/loveruby/cflat/sysdep/Linker.java: new interface.
* net/loveruby/cflat/sysdep/LinkerOptions.java: new clas.
* net/loveruby/cflat/sysdep/GNULinker.java: new Linker
implementation.
* net/loveruby/cflat/utils/CommandUtils.java: new class.
* net/loveruby/cflat/compiler/LdArg.java -> utils/CommandArg.java
* net/loveruby/cflat/compiler/LdOption.java ->
utils/CommandArgStr.java
* net/loveruby/cflat/compiler/SourceFile.java: implements
CommandArg.
Mon May 11 01:49:29 2009 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/parser/Parser.jj: use JDK_VERSION="1.5" to

View File

@ -19,7 +19,7 @@ public class Compiler {
new Compiler(ProgramName).commandMain(args);
}
protected ErrorHandler errorHandler;
private ErrorHandler errorHandler;
public Compiler(String programName) {
this.errorHandler = new ErrorHandler(programName);
@ -67,7 +67,7 @@ public class Compiler {
System.exit(1);
}
protected boolean isValidSyntax(SourceFile src, Options opts) {
private boolean isValidSyntax(SourceFile src, Options opts) {
try {
parseFile(src, opts);
return true;
@ -82,7 +82,7 @@ public class Compiler {
}
// #@@range/buildTarget{
protected void buildTarget(List<SourceFile> srcs, Options opts)
public void buildTarget(List<SourceFile> srcs, Options opts)
throws CompileException {
for (SourceFile src : srcs) {
compileFile(src, opts);
@ -97,7 +97,7 @@ public class Compiler {
}
// #@@}
protected void compileFile(SourceFile src, Options opts)
public void compileFile(SourceFile src, Options opts)
throws CompileException {
if (src.isCflatSource()) {
AST ast = parseFile(src, opts);
@ -163,7 +163,7 @@ public class Compiler {
return expr;
}
protected AST parseFile(SourceFile src, Options opts)
public AST parseFile(SourceFile src, Options opts)
throws SyntaxException, FileException {
return Parser.parseFile(new File(src.currentName()),
opts.loader(),
@ -171,7 +171,7 @@ public class Compiler {
opts.doesDebugParser());
}
protected void semanticAnalysis(AST ast, Options opts)
public void semanticAnalysis(AST ast, Options opts)
throws SemanticException {
new LocalResolver(errorHandler).resolve(ast);
new TypeResolver(errorHandler).resolve(ast);
@ -184,129 +184,29 @@ public class Compiler {
new TypeChecker(errorHandler).check(ast);
}
protected String generateAssembly(IR ir, Options opts) {
public String generateAssembly(IR ir, Options opts) {
CodeGenerator gen = opts.codeGenerator(errorHandler);
return gen.generate(ir);
}
protected void assemble(String srcPath,
private void assemble(String srcPath,
String destPath,
Options opts) throws IPCException {
List<Object> cmd = new ArrayList<Object>();
cmd.add("as");
cmd.addAll(opts.asOptions());
cmd.add("-o");
cmd.add(destPath);
cmd.add(srcPath);
invoke(cmd, opts.isVerboseMode());
opts.assembler(errorHandler)
.assemble(srcPath, destPath, opts.asOptions());
}
static final protected String DYNAMIC_LINKER = "/lib/ld-linux.so.2";
static final protected String C_RUNTIME_INIT = "/usr/lib/crti.o";
static final protected String C_RUNTIME_START = "/usr/lib/crt1.o";
static final protected String C_RUNTIME_START_PIE = "/usr/lib/Scrt1.o";
static final protected String C_RUNTIME_FINI = "/usr/lib/crtn.o";
protected void generateExecutable(Options opts) throws IPCException {
List<Object> cmd = new ArrayList<Object>();
cmd.add("ld");
cmd.add("-dynamic-linker");
cmd.add(DYNAMIC_LINKER);
if (opts.isGeneratingPIE()) {
cmd.add("-pie");
}
if (! opts.noStartFiles()) {
cmd.add(opts.isGeneratingPIE()
? C_RUNTIME_START_PIE
: C_RUNTIME_START);
cmd.add(C_RUNTIME_INIT);
}
cmd.addAll(opts.ldArgs());
if (! opts.noDefaultLibs()) {
cmd.add("-lc");
cmd.add("-lcbc");
}
if (! opts.noStartFiles()) {
cmd.add(C_RUNTIME_FINI);
}
cmd.add("-o");
cmd.add(opts.exeFileName());
invoke(cmd, opts.isVerboseMode());
private void generateExecutable(Options opts) throws IPCException {
opts.linker(errorHandler)
.generateExecutable(opts.exeFileName(), opts.ldOptions());
}
protected void generateSharedLibrary(Options opts) throws IPCException {
List<Object> cmd = new ArrayList<Object>();
cmd.add("ld");
cmd.add("-shared");
if (! opts.noStartFiles()) {
cmd.add(C_RUNTIME_INIT);
}
cmd.addAll(opts.ldArgs());
if (! opts.noDefaultLibs()) {
cmd.add("-lc");
cmd.add("-lcbc");
}
if (! opts.noStartFiles()) {
cmd.add(C_RUNTIME_FINI);
}
cmd.add("-o");
cmd.add(opts.soFileName());
invoke(cmd, opts.isVerboseMode());
private void generateSharedLibrary(Options opts) throws IPCException {
opts.linker(errorHandler)
.generateSharedLibrary(opts.soFileName(), opts.ldOptions());
}
protected void invoke(List<Object> cmdArgs, boolean debug) throws IPCException {
if (debug) {
dumpCommand(cmdArgs);
}
try {
String[] cmd = getStrings(cmdArgs);
Process proc = Runtime.getRuntime().exec(cmd);
proc.waitFor();
passThrough(proc.getInputStream());
passThrough(proc.getErrorStream());
if (proc.exitValue() != 0) {
errorHandler.error(cmd[0] + " failed."
+ " (status " + proc.exitValue() + ")");
throw new IPCException("compile error");
}
}
catch (InterruptedException ex) {
errorHandler.error("gcc interrupted: " + ex.getMessage());
throw new IPCException("compile error");
}
catch (IOException ex) {
errorHandler.error(ex.getMessage());
throw new IPCException("compile error");
}
}
protected String[] getStrings(List<Object> list) {
String[] a = new String[list.size()];
int idx = 0;
for (Object o : list) {
a[idx++] = o.toString();
}
return a;
}
protected void dumpCommand(List<Object> args) {
String sep = "";
for (Object arg : args) {
System.out.print(sep); sep = " ";
System.out.print(arg.toString());
}
System.out.println("");
}
protected void passThrough(InputStream s) throws IOException {
BufferedReader r = new BufferedReader(new InputStreamReader(s));
String line;
while ((line = r.readLine()) != null) {
System.err.println(line);
}
}
protected void writeFile(String path, String str)
private void writeFile(String path, String str)
throws FileException {
try {
BufferedWriter f = new BufferedWriter(

View File

@ -1,7 +0,0 @@
package net.loveruby.cflat.compiler;
// package private
interface LdArg {
abstract public String toString();
abstract public boolean isSourceFile();
}

View File

@ -1,18 +0,0 @@
package net.loveruby.cflat.compiler;
// package private
class LdOption implements LdArg {
protected String option;
public LdOption(String option) {
this.option = option;
}
public boolean isSourceFile() {
return false;
}
public String toString() {
return this.option;
}
}

View File

@ -3,13 +3,13 @@ import net.loveruby.cflat.parser.LibraryLoader;
import net.loveruby.cflat.type.TypeTable;
import net.loveruby.cflat.asm.*;
import net.loveruby.cflat.sysdep.*;
import net.loveruby.cflat.sysdep.x86.X86Linux;
import net.loveruby.cflat.sysdep.X86Linux;
import net.loveruby.cflat.utils.CommandArg;
import net.loveruby.cflat.utils.ErrorHandler;
import net.loveruby.cflat.exception.*;
import java.util.*;
import java.io.*;
// package scope
class Options {
CompilerMode mode;
LibraryLoader loader = new LibraryLoader();
@ -18,12 +18,8 @@ class Options {
boolean verbose = false;
boolean debugParser = false;
CodeGeneratorOptions genOptions = new CodeGeneratorOptions();
List<String> asOptions = new ArrayList<String>();
boolean generatingSharedLibrary = false;
boolean generatingPIE = false;
List<LdArg> ldArgs = new ArrayList<LdArg>();
boolean noStartFiles = false;
boolean noDefaultLibs = false;
AssemblerOptions asOptions = new AssemblerOptions();
LinkerOptions ldOptions = new LinkerOptions();
CompilerMode mode() {
return mode;
@ -64,7 +60,7 @@ class Options {
private List<SourceFile> sourceFiles() {
List<SourceFile> result = new ArrayList<SourceFile>();
for (LdArg arg : ldArgs) {
for (CommandArg arg : ldOptions.args()) {
if (arg.isSourceFile()) {
result.add((SourceFile)arg);
}
@ -72,22 +68,6 @@ class Options {
return result;
}
Platform platform() {
return platform;
}
TypeTable typeTable() {
return platform.typeTable();
}
CodeGenerator codeGenerator(ErrorHandler errorHandler) {
return platform.codeGenerator(genOptions, errorHandler);
}
LibraryLoader loader() {
return this.loader;
}
String outputFileName() {
return this.outputFileName;
}
@ -100,28 +80,36 @@ class Options {
return this.debugParser;
}
List<String> asOptions() {
return this.asOptions;
LibraryLoader loader() {
return this.loader;
}
TypeTable typeTable() {
return platform.typeTable();
}
CodeGenerator codeGenerator(ErrorHandler h) {
return platform.codeGenerator(genOptions, h);
}
Assembler assembler(ErrorHandler h) {
return platform.assembler(h);
}
AssemblerOptions asOptions() {
return asOptions;
}
Linker linker(ErrorHandler h) {
return platform.linker(h);
}
LinkerOptions ldOptions() {
return ldOptions;
}
boolean isGeneratingSharedLibrary() {
return this.generatingSharedLibrary;
}
boolean isGeneratingPIE() {
return this.generatingPIE;
}
List<LdArg> ldArgs() {
return this.ldArgs;
}
boolean noStartFiles() {
return this.noStartFiles;
}
boolean noDefaultLibs() {
return this.noDefaultLibs;
return ldOptions.generatingSharedLibrary;
}
/** Returns List<SourceFile>. */
@ -170,54 +158,58 @@ class Options {
genOptions.generateVerboseAsm();
}
else if (arg.startsWith("-Wa,")) {
asOptions.addAll(parseCommaSeparatedOptions(arg));
for (String a : parseCommaSeparatedOptions(arg)) {
asOptions.addArg(a);
}
}
else if (arg.equals("-Xassembler")) {
asOptions.add(nextArg(arg, args));
asOptions.addArg(nextArg(arg, args));
}
else if (arg.equals("-static")) {
ldArgs.add(new LdOption(arg));
ldOptions.addArg(arg);
}
else if (arg.equals("-shared")) {
generatingSharedLibrary = true;
ldOptions.generatingSharedLibrary = true;
}
else if (arg.equals("-pie")) {
generatingPIE = true;
ldOptions.generatingPIE = true;
}
else if (arg.equals("--readonly-plt")) {
ldArgs.add(new LdOption("-z"));
ldArgs.add(new LdOption("combreloc"));
ldArgs.add(new LdOption("-z"));
ldArgs.add(new LdOption("now"));
ldArgs.add(new LdOption("-z"));
ldArgs.add(new LdOption("relro"));
ldOptions.addArg("-z");
ldOptions.addArg("combreloc");
ldOptions.addArg("-z");
ldOptions.addArg("now");
ldOptions.addArg("-z");
ldOptions.addArg("relro");
}
else if (arg.startsWith("-L")) {
ldArgs.add(new LdOption("-L" + getOptArg(arg, args)));
ldOptions.addArg("-L" + getOptArg(arg, args));
}
else if (arg.startsWith("-l")) {
ldArgs.add(new LdOption("-l" + getOptArg(arg, args)));
ldOptions.addArg("-l" + getOptArg(arg, args));
}
else if (arg.equals("-nostartfiles")) {
noStartFiles = true;
ldOptions.noStartFiles = true;
}
else if (arg.equals("-nodefaultlibs")) {
noDefaultLibs = true;
ldOptions.noDefaultLibs = true;
}
else if (arg.equals("-nostdlib")) {
noStartFiles = true;
noDefaultLibs = true;
ldOptions.noStartFiles = true;
ldOptions.noDefaultLibs = true;
}
else if (arg.startsWith("-Wl,")) {
for (String opt : parseCommaSeparatedOptions(arg)) {
ldArgs.add(new LdOption(opt));
ldOptions.addArg(opt);
}
}
else if (arg.equals("-Xlinker")) {
ldArgs.add(new LdOption(nextArg(arg, args)));
ldOptions.addArg(nextArg(arg, args));
}
else if (arg.equals("-v")) {
verbose = true;
asOptions.verbose = true;
ldOptions.verbose = true;
}
else if (arg.equals("--version")) {
System.out.printf("%s version %s",
@ -234,12 +226,12 @@ class Options {
}
else {
// source file
addSourceFile(srcs, ldArgs, arg);
addSourceFile(srcs, arg);
}
}
// args has more arguments when "--" is appeared.
while (args.hasNext()) {
addSourceFile(srcs, ldArgs, args.next());
addSourceFile(srcs, args.next());
}
if (srcs.isEmpty()) parseError("no input file");
if (mode == null) {
@ -255,11 +247,11 @@ class Options {
throw new OptionParseError(msg);
}
private void addSourceFile(List<SourceFile> srcs, List<LdArg> ldArgs, String sourceName) {
private void addSourceFile(List<SourceFile> srcs, String sourceName) {
SourceFile src = new SourceFile(sourceName);
srcs.add(src);
// Original argument order does matter when linking.
ldArgs.add(src);
ldOptions.addArg(src);
}
private String getOptArg(String opt, ListIterator<String> args) {

View File

@ -1,10 +1,11 @@
package net.loveruby.cflat.compiler;
import net.loveruby.cflat.utils.CommandArg;
import java.io.File;
// package private
class SourceFile implements LdArg {
protected String originalName;
protected String currentName;
class SourceFile implements CommandArg {
private String originalName;
private String currentName;
public SourceFile(String name) {
this.originalName = name;
@ -63,19 +64,19 @@ class SourceFile implements LdArg {
return or(opts.outputFileName, replaceExt(newExt));
}
protected String or(String x, String y) {
private String or(String x, String y) {
return x != null ? x : y;
}
protected String replaceExt(String ext) {
private String replaceExt(String ext) {
return baseName(originalName, true) + ext;
}
protected String baseName(String path) {
private String baseName(String path) {
return new File(path).getName();
}
protected String baseName(String path, boolean stripExt) {
private String baseName(String path, boolean stripExt) {
if (stripExt) {
return new File(path).getName().replaceFirst("\\.[^.]*$", "");
}
@ -84,7 +85,7 @@ class SourceFile implements LdArg {
}
}
protected String extName(String path) {
private String extName(String path) {
int idx = path.lastIndexOf(".");
if (idx < 0) return "";
return path.substring(idx);

View File

@ -0,0 +1,7 @@
package net.loveruby.cflat.sysdep;
import net.loveruby.cflat.exception.IPCException;
public interface Assembler {
void assemble(String srcPath, String destPath,
AssemblerOptions opts) throws IPCException;
}

View File

@ -0,0 +1,18 @@
package net.loveruby.cflat.sysdep;
import net.loveruby.cflat.utils.CommandArg;
import net.loveruby.cflat.utils.CommandArgStr;
import java.util.List;
import java.util.ArrayList;
public class AssemblerOptions {
public boolean verbose = false;
List<CommandArg> args = new ArrayList<CommandArg>();
public void addArg(String a) {
args.add(new CommandArgStr(a));
}
public void addArg(CommandArg a) {
args.add(a);
}
}

View File

@ -0,0 +1,31 @@
package net.loveruby.cflat.sysdep;
import net.loveruby.cflat.utils.CommandUtils;
import net.loveruby.cflat.utils.CommandArg;
import net.loveruby.cflat.utils.CommandArgStr;
import net.loveruby.cflat.utils.ErrorHandler;
import net.loveruby.cflat.exception.IPCException;
import java.util.List;
import java.util.ArrayList;
class GNUAssembler implements Assembler {
ErrorHandler errorHandler;
GNUAssembler(ErrorHandler h) {
this.errorHandler = h;
}
public void assemble(String srcPath, String destPath,
AssemblerOptions opts) throws IPCException {
List<CommandArg> cmd = new ArrayList<CommandArg>();
cmd.add(arg("as"));
cmd.addAll(opts.args);
cmd.add(arg("-o"));
cmd.add(arg(destPath));
cmd.add(arg(srcPath));
CommandUtils.invoke(cmd, errorHandler, opts.verbose);
}
private CommandArg arg(String a) {
return new CommandArgStr(a);
}
}

View File

@ -0,0 +1,75 @@
package net.loveruby.cflat.sysdep;
import net.loveruby.cflat.utils.CommandUtils;
import net.loveruby.cflat.utils.CommandArg;
import net.loveruby.cflat.utils.CommandArgStr;
import net.loveruby.cflat.utils.ErrorHandler;
import net.loveruby.cflat.exception.IPCException;
import java.util.List;
import java.util.ArrayList;
class GNULinker implements Linker {
static final protected String DYNAMIC_LINKER = "/lib/ld-linux.so.2";
static final protected String C_RUNTIME_INIT = "/usr/lib/crti.o";
static final protected String C_RUNTIME_START = "/usr/lib/crt1.o";
static final protected String C_RUNTIME_START_PIE = "/usr/lib/Scrt1.o";
static final protected String C_RUNTIME_FINI = "/usr/lib/crtn.o";
ErrorHandler errorHandler;
GNULinker(ErrorHandler errorHandler) {
this.errorHandler = errorHandler;
}
public void generateExecutable(
String destPath, LinkerOptions opts) throws IPCException {
List<CommandArg> cmd = new ArrayList<CommandArg>();
cmd.add(arg("ld"));
cmd.add(arg("-dynamic-linker"));
cmd.add(arg(DYNAMIC_LINKER));
if (opts.generatingPIE) {
cmd.add(arg("-pie"));
}
if (! opts.noStartFiles) {
cmd.add(arg(opts.generatingPIE
? C_RUNTIME_START_PIE
: C_RUNTIME_START));
cmd.add(arg(C_RUNTIME_INIT));
}
cmd.addAll(opts.args);
if (! opts.noDefaultLibs) {
cmd.add(arg("-lc"));
cmd.add(arg("-lcbc"));
}
if (! opts.noStartFiles) {
cmd.add(arg(C_RUNTIME_FINI));
}
cmd.add(arg("-o"));
cmd.add(arg(destPath));
CommandUtils.invoke(cmd, errorHandler, opts.verbose);
}
public void generateSharedLibrary(
String destPath, LinkerOptions opts) throws IPCException {
List<CommandArg> cmd = new ArrayList<CommandArg>();
cmd.add(arg("ld"));
cmd.add(arg("-shared"));
if (! opts.noStartFiles) {
cmd.add(arg(C_RUNTIME_INIT));
}
cmd.addAll(opts.args);
if (! opts.noDefaultLibs) {
cmd.add(arg("-lc"));
cmd.add(arg("-lcbc"));
}
if (! opts.noStartFiles) {
cmd.add(arg(C_RUNTIME_FINI));
}
cmd.add(arg("-o"));
cmd.add(arg(destPath));
CommandUtils.invoke(cmd, errorHandler, opts.verbose);
}
private CommandArg arg(String a) {
return new CommandArgStr(a);
}
}

View File

@ -0,0 +1,7 @@
package net.loveruby.cflat.sysdep;
import net.loveruby.cflat.exception.IPCException;
public interface Linker {
void generateExecutable(String destPath, LinkerOptions opts) throws IPCException;
void generateSharedLibrary(String destPath, LinkerOptions opts) throws IPCException;
}

View File

@ -0,0 +1,26 @@
package net.loveruby.cflat.sysdep;
import net.loveruby.cflat.utils.CommandArg;
import net.loveruby.cflat.utils.CommandArgStr;
import java.util.List;
import java.util.ArrayList;
public class LinkerOptions {
public boolean generatingSharedLibrary = false;
public boolean generatingPIE = false;
public boolean noStartFiles = false;
public boolean noDefaultLibs = false;
public boolean verbose = false;
List<CommandArg> args = new ArrayList<CommandArg>();
public void addArg(String a) {
args.add(new CommandArgStr(a));
}
public void addArg(CommandArg a) {
args.add(a);
}
public List<CommandArg> args() {
return this.args;
}
}

View File

@ -5,4 +5,6 @@ import net.loveruby.cflat.utils.ErrorHandler;
public interface Platform {
TypeTable typeTable();
CodeGenerator codeGenerator(CodeGeneratorOptions opts, ErrorHandler h);
Assembler assembler(ErrorHandler h);
Linker linker(ErrorHandler h);
}

View File

@ -1,6 +1,4 @@
package net.loveruby.cflat.sysdep.x86;
import net.loveruby.cflat.sysdep.Platform;
import net.loveruby.cflat.sysdep.CodeGeneratorOptions;
package net.loveruby.cflat.sysdep;
import net.loveruby.cflat.utils.ErrorHandler;
import net.loveruby.cflat.type.TypeTable;
@ -11,6 +9,14 @@ public class X86Linux implements Platform {
public CodeGenerator codeGenerator(
CodeGeneratorOptions opts, ErrorHandler h) {
return new CodeGenerator(opts, h);
return new net.loveruby.cflat.sysdep.x86.CodeGenerator(opts, h);
}
public Assembler assembler(ErrorHandler h) {
return new GNUAssembler(h);
}
public Linker linker(ErrorHandler h) {
return new GNULinker(h);
}
}

View File

@ -8,7 +8,7 @@ import net.loveruby.cflat.utils.AsmUtils;
import net.loveruby.cflat.utils.ErrorHandler;
import java.util.*;
class CodeGenerator
public class CodeGenerator
implements net.loveruby.cflat.sysdep.CodeGenerator,
IRVisitor<Void,Void>,
ELFConstants {

View File

@ -0,0 +1,6 @@
package net.loveruby.cflat.utils;
public interface CommandArg {
public String toString();
public boolean isSourceFile();
}

View File

@ -0,0 +1,17 @@
package net.loveruby.cflat.utils;
public class CommandArgStr implements CommandArg {
private String arg;
public CommandArgStr(String arg) {
this.arg = arg;
}
public boolean isSourceFile() {
return false;
}
public String toString() {
return arg;
}
}

View File

@ -0,0 +1,60 @@
package net.loveruby.cflat.utils;
import net.loveruby.cflat.exception.IPCException;
import java.util.List;
import java.util.ArrayList;
import java.io.*;
abstract public class CommandUtils {
static public void invoke(List<CommandArg> cmdArgs,
ErrorHandler errorHandler, boolean debug) throws IPCException {
if (debug) {
dumpCommand(cmdArgs);
}
try {
String[] cmd = getStrings(cmdArgs);
Process proc = Runtime.getRuntime().exec(cmd);
proc.waitFor();
passThrough(proc.getInputStream());
passThrough(proc.getErrorStream());
if (proc.exitValue() != 0) {
errorHandler.error(cmd[0] + " failed."
+ " (status " + proc.exitValue() + ")");
throw new IPCException("compile error");
}
}
catch (InterruptedException ex) {
errorHandler.error("gcc interrupted: " + ex.getMessage());
throw new IPCException("compile error");
}
catch (IOException ex) {
errorHandler.error(ex.getMessage());
throw new IPCException("compile error");
}
}
static private String[] getStrings(List<CommandArg> list) {
String[] result = new String[list.size()];
int idx = 0;
for (CommandArg arg : list) {
result[idx++] = arg.toString();
}
return result;
}
static private void dumpCommand(List<CommandArg> args) {
String sep = "";
for (CommandArg arg : args) {
System.out.print(sep); sep = " ";
System.out.print(arg.toString());
}
System.out.println("");
}
static private void passThrough(InputStream s) throws IOException {
BufferedReader r = new BufferedReader(new InputStreamReader(s));
String line;
while ((line = r.readLine()) != null) {
System.err.println(line);
}
}
}