/* * xtc - The eXTensible Compiler * Copyright (C) 2009-2012 New York University * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * 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, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ package xtc.lang.cpp; import java.io.FileWriter; import java.io.BufferedWriter; import java.util.HashSet; /** * This tool captures gcc command-line arguments for use by SuperC. * It only captures arguments related to header paths, macro * (un)definitions, and the filename. * * @author Paul Gazzillo * @version $Revision: 1.6 $ */ public class GCCShunt { /** * Determines whether a macro definition should be included when * doing configuration-preserving preprocessing. Some Kbuild macros * need to be defined for SuperC in for use in stringification. * * @param The name of the macro defintion. * @param true if the macro definition is part of the Kbuild macros. */ static boolean isKbuildName(String definition) { return definition.startsWith("KBUILD_STR") || definition.startsWith("KBUILD_BASENAME") || definition.startsWith("KBUILD_MODNAME"); } public static void main(String args[]) { if (args.length < 1) { System.err.println( "USAGE: java GCCShunt [options] gcc-options file\n" + "\n" + "Intercept gcc command-line arguments for header paths and macro\n" + "(un)definitions.\n" + "\n" + "\n" + "OPTIONS\n" + " --shunt-filename file\n" + "\n" + " Verify that the filename passed with gcc flags is the right one.\n" + " If the filenames don't match, do nothing.\n" + "\n" + " --shunt-verbose\n" + "\n" + " Verbose error message mode.\n" + "\n" + " --shunt-config filename\n" + "\n" + " Write the configuration-related arguments to a given file.\n" + "\n" + " --shunt-superc filename\n" + "\n" + " Write only the path-related arguments to a given file.\n" + "\n" + " --shunt-kbuild\n" + "\n" + " Include the kbuild-related arguments, Write only the path-related arguments to a given file.\n" + "\n" + " --emit-exceptions\n" + "\n" + " Emit defines and undefines as a list in -configureExceptions.\n" + "\n" + // "ERROR CODES\n" + // " 1 - no arguments given\n" + // " 2 - no gcc filename was given\n" + // " 3 - gcc filename doesn't match --shunt-filename\n" + // " 4 - could not write file\n" + ""); System.exit(0); // System.exit(1); } String configs = ""; String superc = ""; boolean KBUILD = false; boolean INTENDED_FILENAME = false; String intendedFilename = null; boolean VERBOSE = false; String configsFile = null; String supercFile = null; boolean EMIT_EXCEPTIONS = false; String exceptions = ""; boolean nostdinc = false; for (int i = 0; i < args.length; i++) { String arg = args[i]; if (arg.equals("-nostdinc")) { if (! nostdinc) { // Linux build puts -nostdinc twice which causes xtc's // command-line collector to fail. superc += " " + arg; nostdinc = true; } } else if (arg.equals("-I") || arg.equals("-isystem") || arg.equals("-iquote")) { if (i > args.length - 3) { System.err.println("(shunt) no filename was given."); System.exit(0); // System.exit(2); } String header = " " + arg + " " + args[i+1]; superc += header; configs += header; i++; } else if (arg.startsWith("-I")) { // Single-letter arguments need no space. String header = " " + arg.substring(0, 2) + " " + arg.substring(2); superc += header; configs += header; } else if (arg.equals("-D") || arg.equals("-U") || arg.equals("-include")) { if (i > args.length - 3) { System.err.println("(shunt) no filename was given."); System.exit(0); // System.exit(2); } configs += " " + arg + " " + args[i+1]; if (KBUILD && isKbuildName(args[i+1])) { superc += " " + arg + " " + args[i+1]; } if (EMIT_EXCEPTIONS) { String config_string = args[i+1]; // String config_string = arg.substring(0, 2); String[] config_split = config_string.split("="); String config_var = config_split[0]; String config_def = config_split.length > 1 ? config_split[1] : null; String exception = ""; if (arg.equals("-D")) { exception = config_var + "=" + ((config_def != null) ? config_def : "y"); } else if (arg.equals("-U")) { exception = "# " + config_var + " is not set"; } exceptions += exception + ","; } i++; } else if (arg.startsWith("-D") || arg.startsWith("-U")) { // Single-letter arguments need no space. configs += " " + arg.substring(0, 2) + " " + arg.substring(2); if (KBUILD && isKbuildName(arg.substring(2))) { superc += " " + arg.substring(0, 2) + " " + arg.substring(2); } if (EMIT_EXCEPTIONS) { } } else if (arg.equals("--shunt-filename")) { INTENDED_FILENAME = true; intendedFilename = args[i+1]; } else if (arg.equals("--shunt-verbose")) { VERBOSE = true; } else if (arg.equals("--shunt-config")) { configsFile = args[i+1]; } else if (arg.equals("--shunt-superc")) { supercFile = args[i+1]; } else if (arg.equals("--shunt-kbuild")) { KBUILD = true; } else if (arg.equals("--emit-exceptions")) { EMIT_EXCEPTIONS = true; } } if (INTENDED_FILENAME) { String filename = args[args.length - 1]; if (! filename.equals(intendedFilename)) { if (VERBOSE) { System.err.println("(shunt) filename doesn't match: " + filename); } System.exit(0); // System.exit(3); } } if (null != supercFile) { try { FileWriter fstream = new FileWriter(supercFile); BufferedWriter out = new BufferedWriter(fstream); out.write(superc); out.close(); } catch (Exception e) { System.err.println("(shunt) " + e.getMessage()); System.exit(0); // System.exit(4); } } if (VERBOSE) { System.out.println(superc); } if (null != configsFile) { try { FileWriter fstream = new FileWriter(configsFile); BufferedWriter out = new BufferedWriter(fstream); out.write(configs); out.close(); } catch (Exception e) { System.err.println("(shunt) " + e.getMessage()); System.exit(0); // System.exit(4); } } if (VERBOSE) { System.out.println(configs); } if (EMIT_EXCEPTIONS) { System.out.println(exceptions); } } }