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 }