blob: 0ea60eef8c8bb1969535187f1eb4f860fd12a224 [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package macromedia.asc.embedding;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import macromedia.asc.util.Context;
import macromedia.asc.util.ContextStatics;
import macromedia.asc.util.ObjectList;
import macromedia.asc.util.Version;
import static macromedia.asc.embedding.avmplus.Features.*;
public class Main
{
static boolean show_parsetrees = false;
static boolean show_instructions = false;
static boolean show_linenums = false;
static boolean show_bytes = false;
static boolean show_machinecode = false;
static boolean show_flow = false;
static boolean emit_debug_info = false;
static boolean emit_doc_info = false;
static boolean do_test = false;
static boolean do_help = false;
static boolean filespecFound = false; // only default param
static boolean make_movieclip = false;
static boolean lint_mode = false;
static boolean use_static_semantics = false;
static boolean sanity_mode = false;
static boolean emit_metadata = false;
static boolean log = false;
static PrintStream stderr = System.err;
static int earliest_dialect = 7;
static int latest_dialect = 11;
static int default_dialect = 9;
static int default_target = TARGET_AVM2; // Default to FP10
static int dialect = default_dialect;
static int target = default_target;
static int api_version = -1;
static boolean optimize = false;
static ObjectList<String> include_filespecs = new ObjectList<String>();
static ObjectList<String> import_filespecs = new ObjectList<String>();
static ObjectList<String> use_namespaces;
static String swf_options = "";
static String language = "EN";
static String avmplus_exe = null;
static ObjectList<ConfigVar> config_vars = new ObjectList<ConfigVar>();
static ObjectList<ConfigVar> optimizer_configs = null;
public static void main(String[] args) throws Exception
{
String filename = "";
String ext = "";
if (args.length == 0)
{
do_help = true;
}
else
{
for (int i = 0; i < args.length; ++i)
{
String flag = args[i];
if (flag.charAt(0) == '-')
{
if( flag.length() < 2 )
{
do_help = true;
continue;
}
switch (flag.charAt(1))
{
case '!':
use_static_semantics = true;
break;
case 'b':
show_bytes = true;
break;
case 'f':
show_flow = true;
break;
case 'p':
show_parsetrees = true;
break;
case 'i':
if (flag.length() == 3 && flag.charAt(2) == 'n') // -in
// <filespec>
{
++i;
include_filespecs.add(args[i]);
}
else if (flag.length() == 7 && "-import".equals(flag)) // -import
// <filespec>
{
++i;
import_filespecs.add(args[i].trim());
}
else
{
show_instructions = true;
}
break;
case 'm':
if (flag.length() == 10 && "-movieclip".equals(flag))
{
make_movieclip = true;
}
else if (flag.length() == 3 && "-md".equals(flag))
{
emit_metadata = true;
}
else
{
show_instructions = true; // -m implies -i
show_machinecode = true;
}
break;
case 'a':
if (flag.length() == 10 && "-abcfuture".equals(flag))
{
FUTURE_ABC = true;
}
else if ( flag.length() == 10 && "-avmtarget".equals(flag))
{
++i;
try
{
String vm_target = args[i].trim();
int v = Integer.parseInt(vm_target);
switch(v) {
case 1:
target = TARGET_AVM1;
break;
case 2:
target = TARGET_AVM2;
break;
default:
do_help = true;
break;
}
}
catch(Exception e)
{
do_help = true;
}
}
break;
case 'c':
if (flag.length() == 6 && "-coach".equals(flag))
{
lint_mode = true;
}
else if( flag.length() == 7 && "-config".equals(flag))
{
++i;
String temp = args[i];
ConfigVar cv = parseConfigVar(temp);
if( cv != null)
config_vars.push_back(cv);
else
do_help = true;
}
break;
case 'w':
if (flag.length() == 9 && "-warnings".equals(flag))
{
lint_mode = true;
}
break;
case 's':
if (flag.length() == 7)
{
if ("-strict".equals(flag))
{
use_static_semantics = true;
}
else if ("-sanity".equals(flag))
{
sanity_mode = true;
}
}
else if (flag.length() == 4 && "-swf".equals(flag))
{
++i;
swf_options = args[i];
if (swf_options.indexOf("-g") > -1) // -g means make it a debuggable swf
emit_debug_info = true;
}
break;
case 'e':
if (flag.length() == 4)
{
if ("-exe".equals(flag))
{
++i;
avmplus_exe = args[i];
}
}
break;
case 'd':
if (flag.length() == 4 && "-doc".equals(flag))
{
emit_doc_info = true;
}
else
{
emit_debug_info = true;
}
break;
case 'l':
if (flag.length() == 4 && "-log".equals(flag))
{
log = true;
}
else if (flag.length() == 9 && "-language".equals(flag))
{
i++;
language = args[i];
}
else
{
show_linenums = true;
}
break;
case 't':
do_test = true;
break;
case 'h':
do_help = true;
break;
case 'o':
if ( "-O".equalsIgnoreCase(flag))
{
optimize = true;
}
else if (flag.substring(0, 3).equalsIgnoreCase("-O2") )
{
if ( null == optimizer_configs)
{
optimizer_configs = new ObjectList<ConfigVar>();
}
if ( flag.length() > 4)
{
String option_name = flag.substring(4);
String option_value = "";
int eq_pos = option_name.indexOf('=');
if ( eq_pos != -1 )
{
option_value = option_name.substring(eq_pos+1); // Skip the "=" char
option_name = option_name.substring(0, eq_pos);
}
optimizer_configs.add(new ConfigVar("o2", option_name, option_value));
}
}
break;
case 'A':
if (flag.length() == 4 && "-AS3".equalsIgnoreCase(flag))
{
dialect = 10;
}
break;
case 'E':
if (flag.length() == 3 && "-ES".equalsIgnoreCase(flag))
{
dialect = 9;
}
else if (flag.length() == 4 && "-ES4".equalsIgnoreCase(flag))
{
dialect = 11;
}
break;
case 'u':
if (flag.length() == 4 && "-use".equals(flag)) // -use <namespace>
{
++i;
if (use_namespaces == null)
use_namespaces = new ObjectList<String>();
use_namespaces.add(args[i].trim());
}
break;
default:
try
{
if (flag.length() > 1
&& (dialect = -1 * Integer.parseInt(flag)) != 0)
{
if (dialect < earliest_dialect
|| dialect > latest_dialect)
{
do_help = true;
}
// otherwise, we have a valid dialect number
}
}
catch (NumberFormatException nfe)
{
do_help = true;
}
break;
}
}
// assume it's a filename
else
{
filename = new String(args[i].trim());
if (filename.endsWith(".as"))
{
ext = ".as";
}
else if (filename.endsWith(".es"))
{
ext = ".es";
}
else if (filename.endsWith(".js"))
{
ext = ".js";
}
else
{
ext = "";
}
filespecFound = true;
handleFile(filename, ext);
}
}
}
if (!(do_help || filespecFound))
{
Context cx = new Context(new ContextStatics());
System.err.println(cx.errorString(ErrorConstants.kError_MissingFilespec));
System.exit(1);
}
else if (do_help)
{
handleFile("","");
}
}
private static void handleFile(String filename, String ext) throws IOException, FileNotFoundException, Exception
{
String scriptname;
if (do_help)
{
System.out.println("ActionScript 3.0 for AVM+");
System.out.println("version " + Version.getVersion() + " build "+ Version.getBuild());
System.out.println("Copyright 2016 The Apache Software Foundation");
System.out.println("All rights reserved\n");
System.out.println("Usage:");
System.out.println(" asc {-AS3|-ES|-d|-f|-h|-i|-import <filename>|-in <filename>|-m|-p}* filespec");
System.out.println(" -AS3 = use the AS3 class based object model for greater performance and better error reporting");
System.out.println(" -ES = use the ECMAScript edition 3 prototype based object model to allow dynamic overriding of prototype properties");
System.out.println(" -d = emit debug info into the bytecode");
System.out.println(" -f = print the flow graph to standard out");
System.out.println(" -h = print this message");
System.out.println(" -i = write intermediate code to the .il file");
System.out.println(" -import <filename> = make the packages in the");
System.out.println(" specified file available for import");
System.out.println(" -in <filename> = include the specified filename");
System.out.println(" (multiple -in arguments allowed)");
System.out.println(" -m = write the avm+ assembly code to the .il file");
System.out.println(" -p = write parse tree to the .p file");
System.out.println(" -md = emit metadata information into the bytecode");
System.out.println(" -warnings = warn on common actionscript mistakes");
System.out.println(" -strict = treat undeclared variable and method access as errors");
System.out.println(" -sanity = system-independent error/warning output -- appropriate for sanity testing");
System.out.println(" -log = redirect all error output to a logfile");
System.out.println(" -exe <avmplus path> = emit an EXE file (projector)");
System.out.println(" -swf classname,width,height[,fps] = emit a SWF file");
System.out.println(" -language = set the language for output strings {EN|FR|DE|IT|ES|JP|KR|CN|TW}");
System.out.println(" -optimize = produced an optimized abc file");
System.out.println(" -config ns::name=value = define a configuration value in the namespace ns");
System.out.println(" -use <namespace> = automatically use a namespace when compiling this code");
System.out.println(" -avmtarget <vm version number> = emit bytecode for a specific VM version, 1 is AVM1, 2 is AVM2, etc");
System.out.println("");
System.exit(1);
}
if (do_test)
{
if (false) // DEFINE_TEST_DRIVERS
{
// InputBuffer::main(argc,argv);
// InputBuffer::test_getLineText();
// InputBuffer::test_markandcopy();
// InputBuffer.test_retract();
// InputBuffer::test_nextchar();
// Token::main(argc,argv);
// Scanner::main(argc,argv);
// NodeFactory::main(argc,argv);
// Parser::main(argc,argv);
// ConstantEvaluator::main(argc,argv);
// ObjectValue::main(argc,argv);
// CodeGenerator::main(argc,argv);
} // DEFINE_TEST_DRIVER
}
else
{
File f = new File(filename.trim());
if (!f.exists())
{
Context cx = new Context(new ContextStatics());
StringBuilder error_msg = new StringBuilder();
Context.replaceStringArg(error_msg, cx
.errorString(ErrorConstants.kError_UnableToOpenFile),
0, filename);
System.err.println(error_msg.toString());
return;
}
String pathspec;
try
{
pathspec = new File(f.getCanonicalPath()).getParent();
}
catch (IOException ex)
{
pathspec = new File(f.getAbsolutePath()).getParent();
}
scriptname = f.getName().substring(0,
f.getName().length() - ext.length());
BufferedInputStream in = new BufferedInputStream(
new FileInputStream(f));
// Compiler.doCompile(in, pathspec, scriptname, filename,
// include_filespec,
// import_filespec, errorname, null, show_instructions,
// show_machinecode, show_linenums,
// show_parsetrees, show_bytes, show_flow, emit_debug_info);
CompilerPlug plug = new CompilerPlug();
plug.in = in;
plug.pathspec = pathspec;
plug.filename = f.getPath();
; // TODO errorname
plug.scriptname = scriptname;
plug.emit_debug_info = emit_debug_info;
plug.emit_doc_info = emit_doc_info;
plug.make_movieclip = make_movieclip;
plug.import_filespecs = import_filespecs;
plug.use_namespaces = use_namespaces;
plug.lint_mode = lint_mode;
plug.use_static_semantics = use_static_semantics;
plug.emit_metadata = emit_metadata;
plug.swf_options = swf_options;
plug.avmplus_exe = avmplus_exe;
plug.language = language;
plug.dialect = dialect;
plug.target = target;
plug.optimize = optimize;
plug.optimizer_configs = optimizer_configs;
plug.configs = config_vars;
plug.api_version = api_version;
if(sanity_mode)
{
ContextStatics.useSanityStyleErrors = true;
plug.handler = new SanityCompilerHandler();
}
if (log)
{
String logfile = filename.substring(0, filename.length()
- ext.length())
+ ".log";
System.setErr(stderr);
System.err.println("Logging to " + logfile);
System.setErr(new PrintStream(new FileOutputStream(new File(logfile))));
}
if (include_filespecs.size() > 0)
{
plug.includes = new ObjectList<IncludeInfo>();
for (int n = 0; n < include_filespecs.size(); ++n)
{
String filespec = include_filespecs.get(n);
f = new File(filespec);
if (!f.exists())
{
System.err.println("File not found");
return;
}
filespec = f.getPath();
pathspec = new File(f.getCanonicalPath()).getParent();
filename = f.getAbsolutePath();
scriptname = f.getName().substring(0,
f.getName().length() - ext.length());
in = new BufferedInputStream(new FileInputStream(f));
IncludeInfo iinfo = new IncludeInfo();
iinfo.script = in;
if (make_movieclip)
{
iinfo.name = "frame" + n;
}
else
{
iinfo.name = filespec;
}
plug.includes.push_back(iinfo);
}
}
ObjectList<CompilerPlug> plugs = new ObjectList<CompilerPlug>();
Compiler.doCompile(plug, plugs, show_instructions,
show_machinecode, show_linenums, show_parsetrees,
show_bytes, show_flow);
// delete all the input file streams
}
}
public static ConfigVar parseConfigVar(String s)
{
ConfigVar cv = null;
if( s != null )
{
int ns_end = s.indexOf("::");
if( ns_end != -1 )
{
String ns = s.substring(0,ns_end);
int eq_pos = s.indexOf("=", ns_end);
if( eq_pos != -1 )
{
String name = s.substring(ns_end+2, eq_pos);
String value = s.substring(eq_pos+1, s.length());
cv = new ConfigVar(ns, name, value);
}
}
}
return cv;
}
}