Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

442 lines (409 sloc) 12.277 kb
#! winxed
// Winxed compiler driver.
// Parses command line options, calls the compiler backend
// and eventually runs the generated program.
$load "Getopt/Obj.pbc";
$include_const "iglobals.pasm";
$include_const "libpaths.pasm";
$include_const "except_severity.pasm";
function extname(string filename, string ext)
{
// Strip a possible .winxed extension from filename,
// add ext, and return the result.
int l = length(filename);
return (l > 7 && substr(filename, -7) == ".winxed") ?
substr(filename, 0, l - 7) + ext :
filename + ext;
}
// Use the OS pmc for file operations.
function getOS()
{
var os;
try {
loadlib("os");
os = new ["OS"];
}
catch() { }
return os;
}
class WinxedDriverOptions : ["Getopt", "Obj"]
{
var name;
var options;
var opts;
function WinxedDriverOptions(var argv, int unused)
{
var options = [
[ "stage=s", "Compiler stage to use" ],
[ "c", "Compile only. Same as --target=pir" ],
[ "e=s", "Evaluate" ],
[ "o=s", "Object name" ],
[ "L=s", "Add to parrot library search path" ],
[ "I=s", "Add to parrot include search path" ],
[ "X=s", "Add to parrot dynext search path" ],
[ "debug", "Set debug mode" ],
[ "noan", "No code annotations" ],
[ "nowarn", "No warnings" ],
[ "target=s", "Set target type: pir, pbc or run. Default is run." ],
[ "help", "Show this help" ],
[ "version", "Show version and exit" ]
];
self.options = options;
for (var o in options)
self.push_string(o[0]);
self.notOptStop(1);
self.name = argv.shift();
self.opts = self.get_options(argv);
}
function getbool(string option)
{
var opts = self.opts;
var value = opts[option];
return value != null;
}
function getstring(string option, string default[optional])
{
var opts = self.opts;
var value = opts[option];
return value != null ? string(value) : default;
}
function showhelp()
{
say("Usage: ", self.name, " [options] [program] [args]");
say(" Available options:");
int l= 0;
int i;
var o;
for (o in self.options) {
i = length(o[0]);
if (i > l)
l = i;
}
l = l + 4;
string filler = " ";
for (o in self.options) {
string s= o[0];
if (length(s) > 1 && substr(s, 1, 1) != "=")
s = "--" + s;
else
s = "-" + s;
say(" ", s, substr(filler, 0, l - length(s)), "-> ", o[1]);
}
}
}
function driver_main(var argv)
{
const int
DEFAULT_STAGE = 3,
CUSTOM_STAGE = -1;
var options = new WinxedDriverOptions(argv, 0);
int help = options.getbool("help");
int version = options.getbool("version");
string opt_stage = options.getstring("stage");
int compileonly = options.getbool("c");
int debug = options.getbool("debug");
int noan = options.getbool("noan");
int nowarn = options.getbool("nowarn");
string eval = options.getstring("e");
string libs = options.getstring("L");
string incs = options.getstring("I");
string dyns = options.getstring("X");
string obj = options.getstring("o", "");
string target = options.getstring("target");
if (help) {
options.showhelp();
return;
}
var env = new [ "Env" ];
// Path for stage pbc files
string winxedpath = env["WINXED_PATH"];
int stage = DEFAULT_STAGE;
if (opt_stage == null) {
string envstage = env["WINXED_STAGE"];
if (envstage != "")
opt_stage = envstage;
}
if (opt_stage != null) {
if (opt_stage.is_integer(opt_stage))
stage = opt_stage;
else
stage = CUSTOM_STAGE;
}
if (version && (stage == 0 || stage == 1)) {
cry("--version not available in stages 0 and 1");
exit(1);
}
const int
TargetDefault = 0,
TargetRun = 1,
TargetPir = 2,
TargetPbc = 3,
TargetConst = 4;
int targettype = TargetDefault;
if (target != null) {
switch (target) {
case "pir":
targettype = TargetPir;
break;
case "pbc":
targettype = TargetPbc;
break;
case "run":
targettype = TargetRun;
break;
case "include":
targettype = TargetConst;
break;
default:
throw "Invalid target: " + target;
}
}
if (compileonly) {
if (targettype != TargetDefault)
throw "Conflicting options";
targettype = TargetPir;
}
if (targettype == TargetDefault)
targettype = TargetRun;
string srcfile;
if (eval == null && ! version) {
int argc= argv;
if (argc < 1) {
say("ERROR: No program specified");
options.showhelp();
return;
}
srcfile = argv.shift();
}
string pirfile;
if (obj != "" && targettype == TargetPir || targettype == TargetConst)
pirfile = obj;
else {
if (eval != null)
pirfile = "__eval__.pir";
else
pirfile = extname(srcfile, ".pir");
}
var os = getOS();
// Call backend compiler
string winxedbin;
switch (stage) {
case 0:
winxedbin = "winxedst0";
break;
case 1:
winxedbin = "winxedst1";
break;
case 2:
winxedbin = "winxedst2";
break;
case 3:
winxedbin = "winxedst3";
break;
case CUSTOM_STAGE:
winxedbin = opt_stage;
break;
default:
throw "Invalid stage " + stage + ". Must be 0, 1, 2 or 3 .";
}
int retval = 0;
int use_pbc = stage > 1 || stage == CUSTOM_STAGE;
if (use_pbc) {
// Set the -I value now so the $include directive can use it.
if (incs != null) {
var interp = getinterp();
var lpaths = interp[IGLOBALS_LIB_PATHS];
var pathlib = lpaths[PARROT_LIB_PATH_INCLUDE];
pathlib.push(string(incs));
}
try {
load_bytecode(winxedbin + ".pbc");
} catch () { }
var compiler = compreg("winxed");
if (compiler == null) {
if (winxedpath != null && winxedpath != "") {
winxedbin = winxedpath + "/" + winxedbin;
try {
load_bytecode(winxedbin + ".pbc");
}
catch (e) {
if (__DEBUG__)
cry("Cannot load ", winxedbin, ": ", e["message"]);
}
compiler = compreg("winxed");
}
if (compiler == null)
throw "Cannot load stage " + winxedbin;
}
if (version) {
var ver = compiler.version_string();
if (ver == null)
ver = "CANNOT GET VERSION";
say(ver);
exit(0);
}
string ctarget = targettype == TargetConst ? "include" : "pir";
var opts = {
"target": ctarget,
"debug": debug,
"noan": noan,
"nowarn": nowarn
};
string pircode;
if (eval == null) {
var output;
var file;
if (pirfile == "-" &&
(targettype == TargetPir || targettype == TargetConst))
output = getstdout();
else {
file = open(pirfile, "w");
output = file;
}
opts["output"] = output;
compiler.compile_from_file(srcfile, opts:[named,flat]);
if (file != null)
file.close();
}
else {
eval = "function main[main](var argv){" + eval + ";}";
pircode = compiler.compile(eval, opts:[named,flat]);
if (pirfile == "-" &&
(targettype == TargetPir || targettype == TargetConst))
print(pircode);
else {
var file = open(pirfile, "w");
file.print(pircode);
file.close();
}
}
}
else {
string cmd[]; // Command to execute
if (stage == 1) {
cmd.push("parrot");
cmd.push("winxedst1.pbc");
}
else {
// First look in WINXED_PATH.
// If not, simple heuristic: if the compiler is in the current
// directory and has no extension, use it.
// If not, assume it's in the PATH or we are on Windows.
var check = null;
if (winxedpath != null && winxedpath != "" &&os != null) {
string checkbin = winxedpath + "/" + winxedbin;
check = os.stat(checkbin);
if (check == null) {
checkbin = winxedpath + "\\" + winxedbin + ".exe";
check = os.stat(checkbin);
}
if (check != null)
winxedbin = checkbin;
}
if (check == null) {
if (os != null)
check = os.stat(winxedbin);
if (check != null)
winxedbin = "./" + winxedbin;
}
cmd.push(winxedbin);
}
if (targettype == TargetConst)
throw "target include unavailable in stage 0";
if (debug)
cmd.push("--debug");
if (noan)
cmd.push("--noan");
if (nowarn && stage != 0)
cmd.push("--nowarn");
if (eval != null) {
cmd.push("-e");
cmd.push(eval);
}
cmd.push("-o");
cmd.push(pirfile);
if (eval == null)
cmd.push(srcfile);
retval = spawnw(cmd);
retval = (retval >> 8) & 0xFF;
}
if (retval)
exit(retval);
string runit[] = [ "parrot" ];
switch (targettype) {
case TargetRun:
// Execute result
if (libs != null) {
runit.push("-L");
runit.push(libs);
}
if (incs != null) {
runit.push("-I");
runit.push(incs);
}
if (dyns != null) {
runit.push("-X");
runit.push(dyns);
}
runit.push(pirfile);
for (string a in argv)
runit.push(a);
retval = spawnw(runit);
// Delete the generated pir file.
try {
os.rm(pirfile);
}
catch (e)
{
cry("WARNING: cannot delete temporary PIR file: ", e["message"]);
}
break;
case TargetPbc:
// Call parrot to ceate the pbc
string objfile;
if (obj != "")
objfile = obj;
else
objfile = extname(srcfile, ".pbc");
runit.push("-o");
runit.push(objfile);
runit.push(pirfile);
retval = spawnw(runit);
// Delete the generated pir file.
try {
os.rm(pirfile);
}
catch (e)
{
cry("WARNING: cannot delete temporary PIR file: ", e["message"]);
}
break;
default:
; // Otherwise, nothing to do.
}
retval = (retval >> 8) & 0xFF;
exit(retval);
}
function main [main] (var argv)
{
int r;
try {
driver_main(argv);
}
catch (e) {
int severity = e["severity"];
if (severity == EXCEPT_EXIT) {
int exit_code = e["exit_code"];
exit(exit_code);
}
int type = e["type"];
var payload = e["payload"];
if (type == __WINXED_ERROR__ && payload != null)
cry(payload.filename, ":", payload.line, ": ", payload.message);
else
cry(e["message"]);
r = 1;
}
exit(r);
}
// End
Jump to Line
Something went wrong with that request. Please try again.