/* * This file is a part of Alchemy OS project. * Copyright (C) 2011-2014, Sergey Basalaev <sbasalaev@gmail.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package alchemy.nec; import alchemy.fs.Filesystem; import alchemy.io.IO; import alchemy.nec.opt.ConstOptimizer; import alchemy.nec.syntax.Unit; import alchemy.system.NativeApp; import alchemy.system.Process; import java.io.IOException; import java.io.OutputStream; /** * Native Ether compiler. * @author Sergey Basalaev */ public class NEC extends NativeApp { static private final String VERSION = "Native Ether Compiler version 2.2"; static private final String HELP = "Usage: ec [options] <input> \n" + "Options:\n" + "-o <output>\n write to this file\n" + "-O<level>\n choose optimization level\n" + "-I<path>\n add path to includes\n" + "-W<cat> -Wno-<cat>\n Turns on/off category of warnings\n" + "-g\n turn on debugging info\n" + "-f<opt> -fno-<opt>\n Turns on/off option\n" + "-h\n print this help and exit\n" + "-v\n print version and exit"; /** * Constructor without arguments. * Needed to be loaded through the native interface. */ public NEC() { } public int main(Process p, String[] args) { //parsing arguments String outname = null; String fname = null; boolean wait_outname = false; int optlevel = 1; boolean dbginfo = false; int warnmask = -1; // all warnings int optmask = 0; for (int i=0; i<args.length; i++) { String arg = args[i]; if (arg.equals("-h")) { IO.println(p.stdout, HELP); return 0; } else if (arg.equals("-v")) { IO.println(p.stdout, VERSION); return 0; } else if (arg.equals("-o")) { wait_outname = true; } else if (arg.startsWith("-O")) { try { optlevel = Integer.parseInt(arg.substring(2)); } catch (Exception e) { optlevel = 1; } } else if (arg.equals("-g")) { dbginfo = true; } else if (arg.startsWith("-fno-")) { String nooption = arg.substring(5); for (int j=0; j < CompilerEnv.OPTION_STRINGS.length; j++) { if (nooption.equals(CompilerEnv.OPTION_STRINGS[j])) optmask &= ~(1 << j); } } else if (arg.startsWith("-f")) { String option = arg.substring(2); for (int j=0; j < CompilerEnv.OPTION_STRINGS.length; j++) { if (option.equals(CompilerEnv.OPTION_STRINGS[j])) optmask |= (1 << j); } } else if (arg.startsWith("-Wno-")) { String nowarn = arg.substring(5); if (nowarn.equals("all")) warnmask = 0; else for (int j=0; j < CompilerEnv.WARNING_STRINGS.length; j++) { if (nowarn.equals(CompilerEnv.WARNING_STRINGS[j])) warnmask &= ~(1 << j); } } else if (arg.startsWith("-W")) { String warn = arg.substring(2); if (warn.equals("all")) warnmask = 0xffffffff; else for (int j=0; j < CompilerEnv.WARNING_STRINGS.length; j++) { if (warn.equals(CompilerEnv.WARNING_STRINGS[j])) warnmask |= (1 << j); } } else if (arg.startsWith("-I") && arg.length() > 2) { p.setEnv("INCPATH", arg.substring(2) + ':' + p.getEnv("INCPATH")); } else if (arg.charAt(0) == '-') { IO.println(p.stderr, "Unknown argument: "+arg); IO.println(p.stderr, HELP); return 1; } else if (wait_outname) { outname = arg; wait_outname = false; } else { if (fname != null) { IO.println(p.stderr, "Excess parameter: "+fname); IO.println(p.stderr, HELP); return 1; } fname = arg; } } if (fname == null) { IO.println(p.stderr, "No input files."); return 1; } if (outname == null) { outname = fname + ".o"; } // parsing source CompilerEnv env = new CompilerEnv(p, optmask, warnmask, dbginfo); Parser parser = new Parser(env); Unit unit = null; unit = parser.parseUnit(p.toFile(fname)); if (env.getErrorCount() > 0) return 1; // optimizing if (optlevel > 0) { new ConstOptimizer(env).visitUnit(unit); } if (env.getErrorCount() > 0) return 1; // writing binary code try { EAsmWriter wr = new EAsmWriter(env); OutputStream out = Filesystem.write(p.toFile(outname)); wr.writeTo(unit, out); out.flush(); out.close(); } catch (IOException ioe) { IO.println(p.stderr, "I/O error while writing " + outname + '\n' + ioe.getMessage()); return 1; } return 0; } }