1 /*
  2  * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 package org.openjdk.asmtools.jcoder;
 24 
 25 import org.openjdk.asmtools.common.Tool;
 26 import org.openjdk.asmtools.util.I18NResourceBundle;
 27 import org.openjdk.asmtools.util.ProductInfo;
 28 
 29 import java.io.*;
 30 import java.util.ArrayList;
 31 import java.util.HashMap;
 32 
 33 /**
 34  *
 35  *
 36  */
 37 public class Main extends Tool {
 38 
 39     public static final I18NResourceBundle i18n
 40             = I18NResourceBundle.getBundleForClass(Main.class);
 41 
 42     public Main(PrintWriter out, String programName) {
 43         super(out, programName);
 44         printCannotReadMsg = (fname) -> error(i18n.getString("jcoder.error.cannot_read", fname));
 45     }
 46 
 47     public Main(PrintStream out, String program) {
 48         this(new PrintWriter(out), program);
 49     }
 50 
 51     @Override
 52     public void usage() {
 53         println(i18n.getString("jcoder.usage"));
 54         println(i18n.getString("jcoder.opt.nowrite"));
 55         println(i18n.getString("jcoder.opt.ignore"));
 56         println(i18n.getString("jcoder.opt.d"));
 57         println(i18n.getString("jcoder.opt.version"));
 58     }
 59 
 60     /**
 61      * Run the compiler
 62      */
 63     public synchronized boolean compile(String argv[]) {
 64         File destDir = null;
 65         boolean traceFlag = false;
 66         DebugFlag = () -> false;
 67         long tm = System.currentTimeMillis();
 68         ArrayList<String> v = new ArrayList<>();
 69         boolean nowrite = false;
 70         boolean ignore  = false;
 71         int nwarnings = 0;
 72         HashMap<String, String> macros = new HashMap<>();
 73         macros.put("VERSION", "3;45");
 74 
 75         // Parse arguments
 76         for (int i = 0; i < argv.length; i++) {
 77             String arg = argv[i];
 78             if (!arg.startsWith("-")) {
 79                 v.add(arg);
 80             } else if (arg.startsWith("-D")) {
 81                 int argLength = arg.length();
 82                 if (argLength == 2) {
 83                     error(i18n.getString("jcoder.error.D_needs_macro"));
 84                     return false;
 85                 }
 86                 int index = arg.indexOf('=');
 87                 if (index == -1) {
 88                     error(i18n.getString("jcoder.error.D_needs_macro"));
 89                     return false;
 90                 }
 91                 String macroId = arg.substring(2, index);
 92                 index++;
 93                 if (argLength == index) {
 94                     error(i18n.getString("jcoder.error.D_needs_macro"));
 95                     return false;
 96                 }
 97                 String macro;
 98                 if (arg.charAt(index) == '"') {
 99                     index++;
100                     if (argLength == index || arg.charAt(argLength - 1) != '"') {
101                         error(i18n.getString("jcoder.error.no_closing_quota"));
102                         return false;
103                     }
104                     macro = arg.substring(index, argLength - 1);
105                 } else {
106                     macro = arg.substring(index, argLength);
107                 }
108                 macros.put(macroId, macro);
109             } else if (arg.equals("-vv")) {
110                 DebugFlag = () -> true;
111                 traceFlag = true;
112             } else if (arg.equals("-v")) {
113                 traceFlag = true;
114             } else if (arg.equals("-nowrite")) {
115                 nowrite = true;
116             } else if (arg.equals("-ignore")) {
117                 ignore = true;
118             } else if (arg.equals("-d")) {
119                 if ((i + 1) == argv.length) {
120                     error(i18n.getString("jcoder.error.d_requires_argument"));
121                     usage();
122                     return false;
123                 }
124                 destDir = new File(argv[++i]);
125                 if (!destDir.exists()) {
126                     error(i18n.getString("jcoder.error.does_not_exist", destDir));
127                     return false;
128                 }
129             } else if (arg.equals("-version")) {
130                 println(ProductInfo.FULL_VERSION);
131             } else {
132                 error(i18n.getString("jcoder.error.invalid_option", arg));
133                 usage();
134                 return false;
135             }
136         }
137         if (v.isEmpty()) {
138             usage();
139             return false;
140         }
141         // compile all input files
142         try {
143             for (String inpname : v) {
144                 SourceFile env;
145                 Jcoder p;
146 
147                 DataInputStream dataInputStream = getDataInputStream(inpname);
148                 if( dataInputStream == null ) {
149                     nerrors++;
150                     continue;
151                 }
152                 env = new SourceFile(this, dataInputStream, inpname, out);
153                 env.traceFlag = traceFlag;
154                 env.debugInfoFlag = DebugFlag.getAsBoolean();
155                 p = new Jcoder(env, macros);
156                 p.parseFile();
157                 env.traceln("END PARSER");
158                 env.closeInp();
159 
160                 nerrors += env.nerrors;
161                 nwarnings += env.nwarnings;
162                 if (nowrite || (nerrors > 0 & !ignore)) {
163                     continue;
164                 }
165                 try {
166                     env.traceln("WRITE");
167                     p.write(destDir);
168                 } catch (FileNotFoundException ex) {
169                     error(i18n.getString("jcoder.error.cannot_write", ex.getMessage()));
170                 }
171             }
172         } catch (Error ee) {
173             ee.printStackTrace();
174             error(i18n.getString("jcoder.error.fatal_error"));
175         } catch (Exception ee) {
176             ee.printStackTrace();
177             error(i18n.getString("jcoder.error.fatal_exception"));
178         }
179 
180         boolean errs = nerrors > 0;
181         boolean warns = nwarnings > 0;
182         if (!errs && !warns) {
183             return true;
184         }
185         println(errs ? (nerrors > 1 ? (nerrors + " errors") : "1 error")
186                 : "" + ((errs && warns) ? ", " : "") + (warns ? (nwarnings > 1 ? (nwarnings + " warnings") : "1 warning") : ""));
187         return !errs;
188     }
189 
190     /**
191      * main program
192      */
193     public static void main(String[] argv) {
194         Main compiler = new Main(new PrintWriter(System.out), "jcoder");
195         System.exit(compiler.compile(argv) ? 0 : 1);
196     }
197 }