1 package org.sentrysoftware.jawk;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.ObjectInputStream;
29 import java.io.ObjectOutputStream;
30 import java.io.PrintStream;
31 import java.lang.reflect.Constructor;
32 import java.lang.reflect.InvocationTargetException;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Set;
40 import java.util.StringTokenizer;
41
42 import org.sentrysoftware.jawk.backend.AVM;
43 import org.sentrysoftware.jawk.ext.JawkExtension;
44 import org.sentrysoftware.jawk.frontend.AwkParser;
45 import org.sentrysoftware.jawk.frontend.AwkSyntaxTree;
46 import org.sentrysoftware.jawk.intermediate.AwkTuples;
47 import org.sentrysoftware.jawk.util.AwkLogger;
48 import org.sentrysoftware.jawk.util.AwkSettings;
49 import org.sentrysoftware.jawk.util.ScriptSource;
50 import org.slf4j.Logger;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 public class Awk {
88
89 private static final String DEFAULT_EXTENSIONS
90 = org.sentrysoftware.jawk.ext.CoreExtension.class.getName()
91 + "#" + org.sentrysoftware.jawk.ext.StdinExtension.class.getName();
92
93 private static final Logger LOG = AwkLogger.getLogger(Awk.class);
94
95
96
97
98 public Awk() {}
99
100
101
102
103
104
105
106
107
108
109
110
111
112 public void invoke(AwkSettings settings)
113 throws IOException, ClassNotFoundException, ExitException
114 {
115 AVM avm = null;
116 try {
117
118 Map<String, JawkExtension> extensions;
119 if (settings.isUserExtensions()) {
120 extensions = getJawkExtensions();
121 LOG.trace("user extensions = {}", extensions.keySet());
122 } else {
123 extensions = Collections.emptyMap();
124 LOG.trace("user extensions not enabled");
125 }
126
127 AwkTuples tuples = new AwkTuples();
128
129
130 List<ScriptSource> notIntermediateScriptSources = new ArrayList<ScriptSource>(settings.getScriptSources().size());
131 for (ScriptSource scriptSource : settings.getScriptSources()) {
132 if (scriptSource.isIntermediate()) {
133
134 tuples = (AwkTuples) readObjectFromInputStream(scriptSource.getInputStream());
135 } else {
136 notIntermediateScriptSources.add(scriptSource);
137 }
138 }
139 if (!notIntermediateScriptSources.isEmpty()) {
140 AwkParser parser = new AwkParser(
141 settings.isAdditionalFunctions(),
142 settings.isAdditionalTypeFunctions(),
143 extensions);
144
145 AwkSyntaxTree ast = parser.parse(notIntermediateScriptSources);
146
147 if (settings.isDumpSyntaxTree()) {
148
149 String filename = settings.getOutputFilename("syntax_tree.lst");
150 LOG.info("writing to '{}'", filename);
151 PrintStream ps = new PrintStream(new FileOutputStream(filename));
152 if (ast != null) {
153 ast.dump(ps);
154 }
155 ps.close();
156 return;
157 }
158
159
160 if (ast != null) {
161
162 ast.semanticAnalysis();
163
164 ast.semanticAnalysis();
165
166 int result = ast.populateTuples(tuples);
167
168 assert result == 0;
169
170
171 tuples.postProcess();
172
173
174
175 parser.populateGlobalVariableNameToOffsetMappings(tuples);
176 }
177 if (settings.isWriteIntermediateFile()) {
178
179 String filename = settings.getOutputFilename("a.ai");
180 LOG.info("writing to '{}'", filename);
181 writeObjectToFile(tuples, filename);
182 return;
183 }
184 }
185 if (settings.isDumpIntermediateCode()) {
186
187 String filename = settings.getOutputFilename("avm.lst");
188 LOG.info("writing to '{}'", filename);
189 PrintStream ps = new PrintStream(new FileOutputStream(filename));
190 tuples.dump(ps);
191 ps.close();
192 return;
193 }
194
195
196 avm = new AVM(settings, extensions);
197 avm.interpret(tuples);
198
199 } finally {
200 if (avm != null) {
201 avm.waitForIO();
202 }
203 }
204 }
205
206 private static Object readObjectFromInputStream(InputStream is)
207 throws IOException, ClassNotFoundException
208 {
209 ObjectInputStream ois = new ObjectInputStream(is);
210 Object retval = ois.readObject();
211 ois.close();
212 return retval;
213 }
214
215 private static void writeObjectToFile(Object object, String filename)
216 throws IOException
217 {
218 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename));
219 oos.writeObject(object);
220 oos.close();
221 }
222
223 private static Map<String, JawkExtension> getJawkExtensions() {
224 String extensionsStr = System.getProperty("jawk.extensions", null);
225 if (extensionsStr == null) {
226
227 extensionsStr = DEFAULT_EXTENSIONS;
228 } else {
229 extensionsStr = DEFAULT_EXTENSIONS + "#" + extensionsStr;
230 }
231
232
233
234 Set<Class<?>> extensionClasses = new HashSet<Class<?>>();
235 Map<String, JawkExtension> retval = new HashMap<String, JawkExtension>();
236
237 StringTokenizer st = new StringTokenizer(extensionsStr, "#");
238 while (st.hasMoreTokens()) {
239 String cls = st.nextToken();
240 LOG.trace("cls = {}", cls);
241 try {
242 Class<?> c = Class.forName(cls);
243
244 if (!JawkExtension.class.isAssignableFrom(c)) {
245 throw new ClassNotFoundException(cls + " does not implement JawkExtension");
246 }
247 if (extensionClasses.contains(c)) {
248 LOG.warn("class {} is multiple times referred in extension class list. Skipping.", cls);
249 continue;
250 } else {
251 extensionClasses.add(c);
252 }
253
254
255
256 try {
257 Constructor<?> constructor = c.getDeclaredConstructor();
258 JawkExtension ji = (JawkExtension) constructor.newInstance();
259 String[] keywords = ji.extensionKeywords();
260 for (String keyword : keywords) {
261 if (retval.get(keyword) != null) {
262 throw new IllegalArgumentException("keyword collision : " + keyword
263 + " for both " + retval.get(keyword).getExtensionName()
264 + " and " + ji.getExtensionName());
265 }
266 retval.put(keyword, ji);
267 }
268 } catch (InstantiationException |
269 IllegalAccessException |
270 NoSuchMethodException |
271 SecurityException |
272 IllegalArgumentException |
273 InvocationTargetException e) {
274 LOG.warn("Cannot instantiate " + c.getName(), e);
275 }
276 } catch (ClassNotFoundException cnfe) {
277 LOG.warn("Cannot classload {} : {}", new Object[] {cls, cnfe});
278 }
279 }
280
281 return retval;
282 }
283 }