/* * This file is a part of Alchemy OS project. * Copyright (C) 2013-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.io.IO; import alchemy.system.Process; import java.io.OutputStream; /** * Compiler environment. * @author Sergey Basalaev */ public final class CompilerEnv { /** Identifiers for optional features. */ public static final String[] OPTION_STRINGS = { "compat", }; /** Option for 2.1 compatibility mode. */ public static final int F_COMPAT21 = 0; /** Identifiers for warning categories. */ public static final String[] WARNING_STRINGS = { "deprecated", "main", "overrides", "empty", "typecast", "cast", "hidden", "divzero", "return", }; /** * Warning category for errors. * Using this constant in {@link #warn(String, int, int, String) warn()} * method increases error counter. */ public static final int W_ERROR = -1; /** Warn about use of deprecated items. */ public static final int W_DEPRECATED = 0; /** Warn about incorrect semantic of main function. */ public static final int W_MAIN = 1; /** Warn about possible problems with overriding methods. */ public static final int W_OVERRIDES = 2; /** Warn about empty body of conditional and loop statements. */ public static final int W_EMPTY = 3; /** Warn about potentially unsafe type casts. */ public static final int W_TYPECAST = 4; /** Warn about unnecessary casts. */ public static final int W_CAST = 5; /** Warn if item hides another item with the same name on the outer level. */ public static final int W_HIDDEN = 6; /** Warn about division by constant integer zero. */ public static final int W_DIVZERO = 7; /** Warn if return statement is not given explicitely. */ public static final int W_RETURN = 8; /** Bit-mask of enabled option flags. */ private final int options; /** Bit-mask of enabled warning flags. */ private int warnings; /** Whether to generate debugging info. */ public final boolean debug; /** Process instance for IO operations. */ public final Process io; private int warncount = 0; private int errcount = 0; public CompilerEnv(Process p, int optionflags, int warningflags, boolean debug) { this.options = optionflags; this.warnings = warningflags; this.debug = debug; this.io = p; } public int getWarningCount() { return warncount; } public int getErrorCount() { return errcount; } public void suppressWarnings() { warnings = 0; } public boolean hasOption(int option) { return (options & (1 << option)) != 0; } /** * Prints warning message on stderr and increases warning count. * Argument <emph>category</emph> is one of W_* constants. * If it is W_ERROR, then error count increases. */ public void warn(String file, int line, int category, String msg) { boolean isError = category == W_ERROR; if (isError || (warnings | (1 << category)) != 0) { if (isError) { errcount++; } else { warncount++; } String output = file + ':' + line + ": [" + ((isError) ? "Error" : "Warning " + WARNING_STRINGS[category]) + "]\n " + msg; IO.println(io.stderr, output); } } /** Returns string of options for debugging messages. */ public String optionString() { StringBuffer buf = new StringBuffer(); if (debug) buf.append(" -g"); for (int i=0; i<OPTION_STRINGS.length; i++) { if ((options & (1 << i)) != 0) buf.append(" -f").append(OPTION_STRINGS[i]); } for (int i=0; i<WARNING_STRINGS.length; i++) { if ((warnings & (1 << i)) != 0) buf.append(" -W").append(WARNING_STRINGS[i]); } return buf.toString(); } public void exceptionHappened(String component, String info, Exception e) { OutputStream err = io.stderr; IO.println(err, "There is a bug in compiler. Please report it with your source code and the following error messages."); IO.println(err, "Component: " + component); IO.println(err, "Compiler options:" + optionString()); IO.println(err, info); IO.println(err, "Exception: " + e); e.printStackTrace(); errcount++; } }