📄 jswrap.js
字号:
/*
* Process the jswrap input files and generate output.
* Copyright (c) 1998 New Generation Software (NGS) Oy
*
* Author: Markku Rossi <mtr@ngs.fi>
*/
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA
*/
/*
* $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/jswrap/jswrap.js,v $
* $Id: jswrap.js 21681 2006-04-21 15:00:24Z peterw $
*/
/*
* Constants and definitions.
*/
/* Tokens. */
tEOF = 1000;
tFUNCTION = 1001;
tIDENTIFIER = 1002;
tCSTRING = 2001;
tDOUBLE = 2002;
tINT = 2003;
tSTRING = 2004;
tVOID = 2005;
tIN = 2010;
tOUT = 2011;
tINOUT = 2012;
tSTATIC = 2020;
function is_type_token (token)
{
return (token == tCSTRING || token == tDOUBLE || token == tINT
|| token == tSTRING || token == tVOID);
}
function is_copy_type_token (token)
{
return (token == tIN || token == tOUT || token == tINOUT);
}
function typename (token)
{
if (token == tCSTRING)
return "cstring";
else if (token == tDOUBLE)
return "double";
else if (token == tINT)
return "int";
else if (token == tSTRING)
return "string";
else if (token == tVOID)
return "void";
else if (token == tIN)
return "in";
else if (token == tOUT)
return "out";
else if (token == tINOUT)
return "inout";
else
return "";
}
function c_typename (token)
{
if (token == tCSTRING)
return "char *";
else if (token == tDOUBLE)
return "double ";
else if (token == tINT)
return "long ";
else if (token == tVOID)
return "void ";
else if (token == tOUT || token == tINOUT)
return "*";
else
return "";
}
function jsint_typename (token)
{
if (token == tCSTRING)
return "JS_STRING";
else if (token == tDOUBLE)
return "JS_FLOAT";
else if (token == tINT)
return "JS_INTEGER";
else if (token == tSTRING)
return "JS_STRING";
else
return "";
}
valid_c_identifier_re = new RegExp ("^[A-Za-z_][A-Za-z_0-9]*$");
end_brace_re = new RegExp ("^}[ \t]*$");
/*
* Variables.
*/
/* The input file line number. */
linenum = 1;
token_linenum = 1;
token_value = null;
/*
* Functions.
*/
function process ()
{
if (false)
System.print (program, ": processing file `", input_file,
"', header=`", header_file,
"', output=`", output_file,
"', reentrant=", opt_reentrant, "\n");
linenum = 1;
/* Open input file. */
ifp = new File (input_file);
if (!ifp.open ("r"))
{
System.error (program, ": couldn't open input file `", input_file,
"': ", System.strerror (System.errno), "\n");
System.exit (1);
}
/* Create output files. */
ofp_c = new File (output_file);
if (!ofp_c.open ("w"))
{
System.error (program, ": couldn't create output file `", output_file,
"': ", System.strerror (System.errno), "\n");
System.exit (1);
}
ofp_h = new File (header_file);
if (!ofp_h.open ("w"))
{
ofp_c.close ();
File.remove (output_file);
System.error (program, ": couldn't create header file `", header_file,
"': ", System.strerror (System.errno), "\n");
System.exit (1);
}
if (false)
{
ofp_js = new File (js_file);
if (!ofp_js.open ("w"))
{
ofp_c.close ();
ofp_h.close ();
File.remove (output_file);
File.remove (header_file);
System.error (program, ": couldn't create JS file `", js_file,
"': ", System.strerror (System.errno), "\n");
System.exit (1);
}
}
/* Parse the input. */
parse ();
/* Cleanup. */
ofp_c.close ();
ofp_h.close ();
}
/*
* The Func class to hold function definitions.
*/
function Func ()
{
}
new Func ();
function Func$generate_js ()
{
this.code = new String ("function " + this.name + " (");
var i;
for (i = 0; i < this.args.length; i++)
{
this.code.append (this.args[i].name);
if (i + 1 < this.args.length)
this.code.append (", ");
}
this.code.append (")\n{");
this.code.append (this.body);
this.code.append ("}\n");
}
Func.prototype.generate_js = Func$generate_js;
function Func$print_js (stream)
{
stream.write (this.code);
}
Func.prototype.print_js = Func$print_js;
function Func$print_h (stream, header)
{
stream.write ("\n");
stream.write (c_typename (this.return_type) + this.name + " (");
if (opt_reentrant)
{
/* The first argument is the interpreter handle. */
stream.write ("\n\tJSInterpPtr interp");
if (this.args.length > 0)
stream.write (",");
}
var i;
for (i = 0; i < this.args.length; i++)
{
stream.write ("\n\t");
if (this.args[i].type == tSTRING)
{
stream.write ("unsigned char *"
+ c_typename (this.args[i].copy_type)
+ this.args[i].name + ",\n\t"
+ "unsigned int "
+ c_typename (this.args[i].copy_type)
+ this.args[i].name + "_len");
}
else
{
stream.write (c_typename (this.args[i].type)
+ c_typename (this.args[i].copy_type));
stream.write (this.args[i].name);
}
if (i + 1 < this.args.length)
stream.write (", ");
}
stream.write ("\n\t)");
if (header)
stream.write (";");
stream.write ("\n");
}
Func.prototype.print_h = Func$print_h;
function Func$print_c (stream)
{
this.compile ();
this.dump_bc (stream);
this.print_h (stream, false);
stream.write ("{\n");
if (!opt_reentrant)
stream.write (" JSInterpPtr interp = jswrap_interp;\n");
stream.write (" JSVirtualMachine *vm = interp->vm;\n");
stream.write (" JSNode argv["
+ (this.args.length + 1).toString ()
+ "];\n");
stream.write (" int result;\n");
if (this.return_type == tCSTRING)
stream.write (" char *cp;\n");
stream.write ("\n");
/* Argument count. */
stream.write (" argv[0].type = JS_INTEGER;\n");
stream.write (" argv[0].u.vinteger = "
+ this.args.length.toString ()
+ ";\n");
/* Arguments. */
/* Construct the argv array. */
for (i = 0; i < this.args.length; i++)
{
var arg = this.args[i];
var cspec = "";
stream.write ("\n");
var argnum = (i + 1).toString ();
if (arg.copy_type == tOUT)
{
stream.write (" argv[" + argnum + "].type = JS_UNDEFINED;\n");
}
else
{
if (arg.copy_type == tINOUT)
cspec = "*";
if (arg.type == tCSTRING)
{
stream.write (" js_vm_make"
+ (arg.staticp ? "_static" : "")
+ "_string (vm, &argv["
+ argnum + "], "
+ cspec + arg.name + ", strlen ("
+ cspec + arg.name + "));\n");
}
else if (arg.type == tDOUBLE)
{
stream.write (" argv[" + argnum + "].type = JS_FLOAT;\n");
stream.write (" argv[" + argnum + "].u.vfloat = "
+ cspec + arg.name + ";\n");
}
else if (arg.type == tINT)
{
stream.write (" argv[" + argnum + "].type = JS_INTEGER;\n");
stream.write (" argv[" + argnum + "].u.vinteger = "
+ cspec + arg.name + ";\n");
}
else if (arg.type == tSTRING)
{
stream.write (" js_vm_make_static_string (vm, &argv["
+ argnum + "], "
+ cspec + arg.name + ", "
+ cspec + arg.name + "_len);\n");
}
else
VM.stackTrace ();
}
}
/* Call the function. */
stream.write ("\
retry:
result = js_vm_apply (vm, \"" + this.name + "\", NULL, "
+ (i + 1).toString () + ", argv);
if (result == 0)
{
JSNode *n = &vm->globals[js_vm_intern (vm, \"" + this.name + "\")];
if (n->type != JS_FUNC)
{
JSByteCode *bc = js_bc_read_data (" + this.name + "_bc,
sizeof (" + this.name + "_bc));
result = js_vm_execute (vm, bc);
js_bc_free (bc);
if (result == 0)
jswrap_error (interp, \"initialization of function`"
+ this.name + "' failed\");
goto retry;
}
jswrap_error (interp, \"execution of function `"
+ this.name + "' failed\");
}
");
/* Handle out and inout parameters. */
for (i = 0; i < this.args.length; i++)
{
var arg = this.args[i];
if (arg.copy_type == tIN)
continue;
var spos = (this.args.length - i).toString ();
/* Check that we have there a correct type. */
stream.write ("
if ((vm->sp - " + spos + ")->type != " + jsint_typename (arg.type) + ")
jswrap_error (interp,
\"wrong return type for argument `"
+ arg.name + "' of function `" + this.name + "'\");
");
/* Handle the different types. */
if (arg.type == tCSTRING)
{
stream.write ("\
*" + arg.name + " = (char *) js_vm_alloc (vm, (vm->sp - "
+ spos + ")->u.vstring->len + 1);
memcpy (*" + arg.name + ", (vm->sp - " + spos + ")->u.vstring->data,
(vm->sp - " + spos + ")->u.vstring->len);
" + arg.name + "[(vm->sp - " + spos + ")->u.vstring->len] = '\\0';
");
}
else if (arg.type == tDOUBLE)
{
stream.write ("\
*" + arg.name + " = (vm->sp - " + spos + ")->u.vfloat;\n");
}
else if (arg.type == tINT)
{
stream.write ("\
*" + arg.name + " = (vm->sp - " + spos + ")->u.vinteger;\n");
}
else if (arg.type == tSTRING)
{
stream.write ("\
*" + arg.name + " = (vm->sp - " + spos + ")->u.vstring->data;
*" + arg.name + "_len = (vm->sp - " + spos + ")->u.vstring->len;
");
}
}
/* Handle the function return value. */
if (this.return_type != tVOID)
{
/* Check that the code returned correct type. */
stream.write ("
if (vm->exec_result.type != " + jsint_typename (this.return_type) + ")
jswrap_error (interp, \"return type mismatch in function `"
+ this.name + "'\");
");
/* Handle the different types. */
if (this.return_type == tCSTRING)
{
stream.write ("\
cp = (char *) js_vm_alloc (vm, vm->exec_result.u.vstring->len + 1);
memcpy (cp, vm->exec_result.u.vstring->data, vm->exec_result.u.vstring->len);
cp[vm->exec_result.u.vstring->len] = '\\0';
return cp;
");
}
else if (this.return_type == tDOUBLE)
stream.write (" return vm->exec_result.u.vfloat;\n");
else if (this.return_type == tINT)
stream.write (" return vm->exec_result.u.vinteger;\n");
}
stream.write ("}\n");
}
Func.prototype.print_c = Func$print_c;
function Func$compile ()
{
/* Create the byte-code for this function. */
var flags = 0;
if (false)
flags |= JSC$FLAG_VERBOSE;
if (opt_debug)
flags |= JSC$FLAG_GENERATE_DEBUG_INFO;
flags |= (JSC$FLAG_OPTIMIZE_PEEPHOLE
| JSC$FLAG_OPTIMIZE_JUMPS
| JSC$FLAG_OPTIMIZE_BC_SIZE);
flags |= JSC$FLAG_WARN_MASK;
try
{
this.bc = JSC$compile_string (this.code, flags, null, null);
}
catch (error)
{
System.error (error, "\n");
System.exit (1);
}
}
Func.prototype.compile = Func$compile;
function Func$dump_bc (stream)
{
stream.write ("\nstatic unsigned char " + this.name + "_bc[] = {");
var i;
for (i = 0; i < this.bc.length; i++)
{
if ((i % 12) == 0)
stream.write ("\n ");
var item = this.bc[i].toString (16);
if (item.length == 1)
item = "0" + item;
stream.write (" 0x" + item + ",");
}
stream.write ("\n};\n");
}
Func.prototype.dump_bc = Func$dump_bc;
/*
* The Argument class to hold function argument definitions.
*/
function Argument ()
{
this.type = false;
this.copy_type = tIN;
this.staticp = false;
}
new Argument ();
function Argument$print ()
{
System.print (typename (this.copy_type), " ", typename (this.type),
" ", this.name);
}
Argument.prototype.print = Argument$print;
/*
* The .jsw file parsing.
*/
function parse ()
{
var token;
var func;
headers ();
while ((token = get_token ()) != tEOF)
{
if (token != tFUNCTION)
syntax_error ();
func = new Func ();
/* Possible return type. */
token = get_token ();
if (is_type_token (token))
{
if (token == tSTRING)
{
System.error (input_file, ":", linenum,
": the function return value can't be `string'\n");
System.exit (1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -