Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

v0.0.1.9 -- added config file parsing and basic logging facility, as …

…well as corrected significant issues with working directory path detection
  • Loading branch information...
commit fe439582591e19365d7b949a8e8894aecea84a3c 1 parent b03e206
Kyle Simpson authored
18 README.txt
... ... @@ -1,5 +1,5 @@
1 1 BikechainJS Engine
2   -v0.0.1.4 (c) 2010 Kyle Simpson
  2 +v0.0.1.9 (c) 2010 Kyle Simpson
3 3 MIT License
4 4
5 5
@@ -19,12 +19,16 @@ Installation:
19 19
20 20 3. If you created the "static" V8 library, edit the makefile to reference to proper static library file.
21 21
22   -4. Run "make" and then "make clean".
  22 +4. Run "make install" and then "make clean".
23 23
24   -5. You should now have a "engine" executable in the root directory. You can execute a JavaScript file by passing it as a parameter to engine, like this:
  24 +5. You should now have a "engine" executable in the [root]/engine/ directory. You can execute a JavaScript file by passing it as a parameter to engine, like this:
25 25
26 26 ./engine dosomething.js
27 27
  28 +6. You can configure your BikechainJS instance by editing values in the engine.json file, also in the [root]/engine/ directory.
  29 +
  30 +7. Make sure the [root]/logs directory is writeable by the user/process executing bikechain.
  31 +
28 32
29 33 --------------
30 34
@@ -36,14 +40,14 @@ Provided global environment:
36 40
37 41 3. include_once(path-to-file): will ensure an exact file (via path) only gets loaded/parsed once.
38 42
39   -4. alert(), console.log(), console.warn(), and console.error() are all defined and mapped to [system].stdout.print().
  43 +4. alert() maps to [system].stdout.print(). console.info(), console.log(), console.warn(), and console.error() all send messages to the logs.
40 44
41 45 5. exit() to immediately stop execution of any javascript in this instance and flush output.
42 46
43 47
44 48 --------------
45 49
46   -Modules:
  50 +Modules (provided in [root]/modules/):
47 51
48 52 Several modules are available to be loaded into the executing environment by using the global require() function.
49 53
@@ -52,7 +56,7 @@ Several modules are available to be loaded into the executing environment by usi
52 56 * [system].stdout.write(str): writes "str" to the standard output
53 57 * [system].stdout.print(str): writes "str" to the standard output, followed by a new-line
54 58 * [system].stdout.flush(): flushes the output buffer (if necessary)
55   - * [system].stdin.read(): if stdin has any buffered, reads from stdin up until an EOF. Otherwise, read returns empty immediately (non-blocking).
  59 + * [system].stdin.read(nonblocking[=true]): if non-blocking (default), if stdin has any buffered, reads from stdin up until an EOF. Otherwise, read returns empty immediately. If not non-blocking, read() blocks waiting for input.
56 60 * [system].stderr.write(str): same as stdout.write()
57 61 * [system].stderr.print(str): same as stdout.print()
58 62 * [system].stderr.flush(): same as stdout.flush()
@@ -66,7 +70,7 @@ Several modules are available to be loaded into the executing environment by usi
66 70
67 71 3. "os": Operating System (process execution)
68 72
69   - * [os].command(cmd, [..cmds, ..]): execute a command on the local system, specified by "cmd" and "cmds" parameters
  73 + * [os].execute(input, cmd, [..cmds, ..]): execute a command on the local system, specified by "cmd" and "cmds" parameters
70 74 -- returns iopipe:
71 75 [iopipe].stdout.read(): reads the output from the executed command
72 76
45 engine/backchannel.js
... ... @@ -0,0 +1,45 @@
  1 +/*! BikechainJS (backchannel.js)
  2 + v0.0.1.9 (c) Kyle Simpson
  3 + MIT License
  4 +*/
  5 +
  6 +(function(imports){
  7 + var global = this,
  8 + cfg = {},
  9 + default_cfg = {
  10 + logging: false,
  11 + log_format: "common",
  12 + log_level: 1,
  13 + error_log_level: 2,
  14 + file_logging: false,
  15 + file_log_file: "logs/bikechain.json",
  16 + file_log_error_file: "logs/bikechain.error.json",
  17 + system_event_logging: false,
  18 + display_errors: false
  19 + }
  20 + ;
  21 +
  22 + try {
  23 + cfg = JSON.parse(JSON.minify(imports.cfg));
  24 + }
  25 + catch (err) {
  26 + throw new Error("Failed parsing engine configuration");
  27 + }
  28 + try {
  29 + // merge default values for engine configuration
  30 + for (var k in default_cfg) { if (default_cfg.hasOwnProperty(k)) {
  31 + if (!cfg.hasOwnProperty(k)) cfg[k] = default_cfg[k];
  32 + }}
  33 + }
  34 + catch (err) {
  35 + throw new Error("Failed initializing engine configuration");
  36 + }
  37 +
  38 + global.getCfg = function(name) {
  39 + return name ? cfg[name] : cfg;
  40 + };
  41 +
  42 + global.setCfg = function(name,value) {
  43 + cfg[name] = value;
  44 + };
  45 +})
49 engine/engine.js
... ... @@ -1,10 +1,10 @@
1 1 /*! BikechainJS (engine.js)
2   - v0.0.1.4 (c) Kyle Simpson
  2 + v0.0.1.9 (c) Kyle Simpson
3 3 MIT License
4 4 */
5 5
6 6
7   -(function(imports){
  7 +(function(bikechain_root_path, imports){
8 8 var global = this,
9 9 FS,
10 10 SYSTEM,
@@ -25,7 +25,7 @@
25 25 // special function `require` for loading modules
26 26 global.require = function(module_path,forceReload) {
27 27 forceReload = !(!forceReload);
28   - var module_repo_path = "bikechain/modules/",
  28 + var module_repo_path = bikechain_root_path+"modules/",
29 29 source, module_name
30 30 ;
31 31
@@ -43,18 +43,22 @@
43 43 module_name = module_name[1];
44 44 }
45 45 else { // otherwise, bail now
46   - return void 0;
  46 + throw new Error("Failed loading unknown module from path: "+module_path);
47 47 }
48 48
49 49 if (!FS) {
50   - source = imports.__FSRead__(module_repo_path+"fs.js");
  50 + try { source = imports.__FSRead__(module_repo_path+"fs.js"); }
  51 + catch (err) { throw new Error("Failed loading module `fs` from path: "+module_repo_path+"fs.js"); }
  52 +
51 53 loaded_modules["fs"] = FS = Function.apply(global,imports_names.concat([source])).apply(global,imports_funcs);
52 54 }
53 55 if (!forceReload && typeof loaded_modules[module_name] !== "undefined") {
54 56 return loaded_modules[module_name];
55 57 }
56 58 if (module_name != "fs" || forceReload) {
57   - source = FS.read(module_path);
  59 + try { source = FS.read(module_path); }
  60 + catch (err) { throw new Error("Failed loading module `"+module_name+"` from path: "+module_path); }
  61 +
58 62 return (loaded_modules[module_name] = Function.apply(global,imports_names.concat([source])).apply(global,imports_funcs));
59 63 }
60 64 return FS;
@@ -74,24 +78,47 @@
74 78 if (!forceReload && typeof loaded_includes[src] != "undefined") {
75 79 return loaded_includes[src];
76 80 }
77   - loaded_includes[src] = FS.read(src);
  81 + try { loaded_includes[src] = FS.read(src); }
  82 + catch (err) { throw new Error("Failed including file from path: "+src); }
  83 +
78 84 eval.call(this,loaded_includes[src]);
79 85 });
80 86
81 87 // sandbox `include_once` as special core function
82 88 global.include_once = SANDBOX(function(src){
83 89 if (typeof loaded_includes[src] == "undefined") {
84   - global.include.call(this,src);
  90 + try { global.include.call(this,src); }
  91 + catch (err) { throw new Error("Failed including file from path: "+src); }
85 92 }
86 93 });
87 94
88 95 // sandbox alert and console.xxx as special core functions
89 96 global.console = {};
90   - global.alert = global.console.log = global.console.warn = global.console.error = SANDBOX(function(){
  97 + global.alert = SANDBOX(function(){
91 98 for (var i=0, len=arguments.length; i<len; i++) {
92 99 SYSTEM.stdout.print(arguments[i]);
93 100 }
94 101 });
  102 + global.console.info = SANDBOX(function(){
  103 + for (var i=0, len=arguments.length; i<len; i++) {
  104 + imports.__Console__("notice",arguments[i]);
  105 + }
  106 + });
  107 + global.console.log = SANDBOX(function(){
  108 + for (var i=0, len=arguments.length; i<len; i++) {
  109 + imports.__Console__("log",arguments[i]);
  110 + }
  111 + });
  112 + global.console.warn = SANDBOX(function(){
  113 + for (var i=0, len=arguments.length; i<len; i++) {
  114 + imports.__Console__("warn",arguments[i]);
  115 + }
  116 + });
  117 + global.console.error = SANDBOX(function(){
  118 + for (var i=0, len=arguments.length; i<len; i++) {
  119 + imports.__Console__("error",arguments[i]);
  120 + }
  121 + });
95 122
96 123 // sandbox "exit" as special core function
97 124 global.exit = SANDBOX(function(exit_code){
@@ -100,8 +127,8 @@
100 127 });
101 128
102 129 // pull in custom extension JSON.minify() to strip comments from JSON strings read from files
103   - include_once("bikechain/misc/minify.json.js");
  130 + include_once(bikechain_root_path+"misc/minify.json.js");
104 131
105 132 // pull in String.trim() if not defined yet by the JavaScript environment
106   - include_once("bikechain/misc/string.trim.js");
  133 + include_once(bikechain_root_path+"misc/string.trim.js");
107 134 })
25 engine/engine.json
... ... @@ -0,0 +1,25 @@
  1 +/* BikechainJS (engine.json configuration)
  2 + v0.0.1.9 (c) Kyle Simpson
  3 + MIT License
  4 +*/
  5 +
  6 +{
  7 + // controls log/error output
  8 + "logging": true, // default: false
  9 + "log_format": "json", // default: "common"; values: "common", "json"
  10 + "log_level": 1, // default: 1; values: 0(notice), 1(console)
  11 + "error_log_level": 2, // default: 2; values: 0(warning), 1(error), 2(fatal)
  12 +
  13 + // controls log/error output to bikechain log files
  14 + "file_logging": true, // default: false
  15 +
  16 + // NOTE: relative paths will be relative to bikechain's root directory
  17 + "file_log_file": "logs/bikechain.json", // default: "logs/bikechain.json"
  18 + "file_log_error_file": "logs/bikechain.error.json", // default: "logs/bikechain.error.json"
  19 +
  20 + // controls log/error output to standard system event queue
  21 + "system_event_logging": false, // default: false
  22 +
  23 + // dumps errors to stdout as well
  24 + "display_errors": false // default: false
  25 +}
664 engine/src/engine.cpp
... ... @@ -1,29 +1,50 @@
1 1 /* BikechainJS (engine)
2   -v0.0.1.4b (c) Kyle Simpson
3   -MIT License
  2 + v0.0.1.9 (c) Kyle Simpson
  3 + MIT License
4 4 */
5 5
6 6 #include <v8.h>
7 7 #include <fcntl.h>
8 8 #include <string.h>
  9 +#include <vector>
  10 +#include <map>
9 11 #include <stdio.h>
  12 +#include <iostream>
  13 +#include <sstream>
10 14 #include <stdlib.h>
11 15 #include <ctype.h>
12 16 #include <errno.h>
13 17 #include <string>
  18 +#include <time.h>
14 19 #include <cstdlib>
15 20 #include <sys/types.h>
16 21 #include <signal.h>
17 22 #include <sys/wait.h>
18 23 #include <unistd.h>
  24 +#include <sys/stat.h>
19 25
20 26 #ifdef _WIN32
21   -#include <sys/time.h>
  27 + #include <sys/time.h>
  28 + #include <windows.h>
  29 + #include <winevt.h>
  30 +#else
  31 + #include <syslog.h>
22 32 #endif
23 33
24 34 #include <engine.h>
25 35
26 36 int content_type_needed = 0;
  37 +bool backchannel_ready = false;
  38 +
  39 +FILE *file_log_file_handle;
  40 +FILE *file_log_error_file_handle;
  41 +std::string bikechain_root_path_directory;
  42 +v8::Handle<v8::Context> backchannel_context;
  43 +v8::Handle<v8::Context> engine_context;
  44 +v8::Handle<v8::Value> tmpval;
  45 +v8::Handle<v8::Function> jsonstringify_func;
  46 +v8::Handle<v8::Function> getcfg_func;
  47 +v8::Handle<v8::Function> setcfg_func;
27 48
28 49 // From: http://www.gnu.org/s/libc/manual/html_node/Working-Directory.html
29 50 char* gnu_getcwd() {
@@ -46,6 +67,11 @@ const char* ToCString(const v8::String::Utf8Value& value) {
46 67 return *value ? *value : "<string conversion failed>";
47 68 }
48 69
  70 +// converts a v8::Value handle to a std::string
  71 +std::string ToStdString(v8::Handle<v8::Value> value) {
  72 + return std::string(ToCString(v8::String::Utf8Value(value)));
  73 +}
  74 +
49 75 v8::Handle<v8::Value> ioRead(const v8::Arguments& args) {
50 76 v8::String::Utf8Value nonblocking(args[0]);
51 77 return ReadIO((strcmp(ToCString(nonblocking),"true") == 0));
@@ -115,9 +141,27 @@ v8::Handle<v8::Value> sysExit(const v8::Arguments& args) {
115 141
116 142 v8::String::Utf8Value exitStatus(args[0]);
117 143 int status = atoi(ToCString(exitStatus));
  144 + v8::V8::Dispose();
  145 + fclose(file_log_file_handle);
  146 + fclose(file_log_error_file_handle);
118 147 exit(status);
119 148 }
120 149
  150 +v8::Handle<v8::Value> sysConsole(const v8::Arguments& args) {
  151 + if (args.Length() != 2) {
  152 + return v8::ThrowException(v8::String::New("Bad parameters"));
  153 + }
  154 +
  155 + std::string console_type = ToStdString(args[0]);
  156 + std::string console_msg = ToStdString(args[1]);
  157 +
  158 + if (console_type == "notice") return v8::Boolean::New(log_notice(console_msg));
  159 + else if (console_type == "log") return v8::Boolean::New(log_console(console_msg));
  160 + else if (console_type == "warn") return v8::Boolean::New(log_warning(console_msg));
  161 + else if (console_type == "error") return v8::Boolean::New(log_error(console_msg));
  162 + else return v8::Undefined();
  163 +}
  164 +
121 165 v8::Handle<v8::Value> setContentTypeNeeded(const v8::Arguments& args) {
122 166 v8::String::Utf8Value flag(args[0]);
123 167 content_type_needed = atoi(ToCString(flag));
@@ -131,7 +175,10 @@ v8::Handle<v8::Value> isContentTypeNeeded(const v8::Arguments& args) {
131 175 // Reads a file into a v8 string.
132 176 v8::Handle<v8::Value> ReadFile(const char* name) {
133 177 FILE* file = fopen(name, "rb");
134   - if (file == NULL) return v8::ThrowException(v8::String::New((std::string("Error reading from file: ")+std::string(name)).c_str()));
  178 + if (file == NULL) {
  179 + v8::ThrowException(v8::String::New((std::string("Error reading from file: ")+std::string(name)).c_str()));
  180 + return v8::Undefined();
  181 + }
135 182
136 183 fseek(file, 0, SEEK_END);
137 184 int size = ftell(file);
@@ -238,8 +285,7 @@ v8::Handle<v8::Value> executeProcess(const v8::Arguments& args) {
238 285
239 286 // take off args[0], since will be sent into stdin of process
240 287 num_args--;
241   - v8::String::Utf8Value v8_input_data(args[0]);
242   - std::string input_data(ToCString(v8_input_data));
  288 + std::string input_data = ToStdString(args[0]);
243 289
244 290 // copy the args array (starting at index 1) into cmd_args
245 291 cmd_args = (char**)malloc((num_args+1)*sizeof(char*));
@@ -278,7 +324,7 @@ v8::Handle<v8::Value> executeProcess(const v8::Arguments& args) {
278 324 default: // parent process
279 325 close(pipe_to_child[0]);
280 326 close(pipe_from_child[1]);
281   - if (input_data != "") {
  327 + if (!input_data.empty()) {
282 328 write(pipe_to_child[1],input_data.c_str(),strlen(input_data.c_str()));
283 329 }
284 330 close(pipe_to_child[1]);
@@ -323,121 +369,591 @@ v8::Handle<v8::Value> executeProcess(const v8::Arguments& args) {
323 369
324 370 void ReportException(v8::TryCatch* try_catch) {
325 371 v8::HandleScope handle_scope;
326   - v8::String::Utf8Value exception(try_catch->Exception());
327   - const char* exception_string = ToCString(exception);
  372 + std::string exception_string = ToStdString(try_catch->Exception());
328 373 v8::Handle<v8::Message> message = try_catch->Message();
329 374
330 375 if (content_type_needed) {
331 376 printf("Content-type: text/plain\n\n");
  377 + content_type_needed = 0;
332 378 }
333 379
334 380 if (message.IsEmpty()) {
335 381 // V8 didn't provide any extra information about this error; just
336 382 // print the exception.
337   - printf("%s\n", exception_string);
  383 + log_error(exception_string);
338 384 }
339 385 else {
340   - // Print (filename):(line number): (message).
341   - v8::String::Utf8Value filename(message->GetScriptResourceName());
342   - const char* filename_string = ToCString(filename);
  386 + // Print (filename):(line number):(char position) (message).
  387 + std::string filename_string = ToStdString(message->GetScriptResourceName());
343 388 int linenum = message->GetLineNumber();
344   - printf("%s:%i: %s\n", filename_string, linenum, exception_string);
345   - // Print line of source code.
346   - v8::String::Utf8Value sourceline(message->GetSourceLine());
347   - const char* sourceline_string = ToCString(sourceline);
348   - printf("%s\n", sourceline_string);
349   - // Print wavy underline (GetUnderline is deprecated).
350 389 int start = message->GetStartColumn();
351   - for (int i = 0; i < start; i++) {
352   - printf(" ");
353   - }
354   - int end = message->GetEndColumn();
355   - for (int i = start; i < end; i++) {
356   - printf("^");
357   - }
358   - printf("\n");
  390 + std::string sourceline_string = ToStdString(message->GetSourceLine());
  391 +
  392 + log_error(filename_string + ":" + stringify(linenum) + ":" + stringify(start) + " " + exception_string + "\n" + sourceline_string);
359 393 }
360 394 }
361 395
362 396 bool ExecuteString(v8::Handle<v8::String> source, v8::Handle<v8::Value> name) {
363 397 v8::HandleScope handle_scope;
  398 + v8::Handle<v8::Value> result = ExecuteStringValue(source, name);
  399 +
  400 + return !result.IsEmpty();
  401 +}
  402 +
  403 +v8::Handle<v8::Value> ExecuteStringValue(v8::Handle<v8::String> source, v8::Handle<v8::Value> name) {
  404 + v8::HandleScope handle_scope;
364 405 v8::TryCatch try_catch;
365 406 v8::Handle<v8::Script> script = v8::Script::Compile(source, name);
366 407 if (script.IsEmpty()) {
367 408 // Print errors that happened during compilation.
368 409 ReportException(&try_catch);
  410 + return v8::Undefined();
  411 + }
  412 + else {
  413 + return handle_scope.Close(script->Run());
  414 + }
  415 +}
  416 +
  417 +std::vector<std::string> split_path(std::string path) {
  418 + std::vector<std::string> ret(2);
  419 + int pos = path.find_last_of("/");
  420 + ret[0] = path.substr(0,pos) + "/";
  421 + ret[1] = path.substr(pos+1);
  422 + return ret;
  423 +}
  424 +
  425 +std::string get_canonical_path(std::string cwd, std::string path) {
  426 + // if path is relative, prepend cwd
  427 + if (path[0] != '/') {
  428 + path = cwd + ((cwd[(cwd.length()-1)] != '/') ? "/" : "") + path;
  429 + }
  430 +
  431 + // now, remove any null directories (ie, './') from the path string
  432 + int null_dir_pos;
  433 + if (path.substr(0,2) == "./") path = path.substr(2);
  434 + while ((null_dir_pos = path.find("/./")) != std::string::npos) {
  435 + path = path.replace(null_dir_pos,3,"/");
  436 + }
  437 +
  438 + return path;
  439 +}
  440 +
  441 +v8::Handle<v8::Value> getCfgVal(std::string cfg_name) {
  442 + v8::HandleScope handle_scope;
  443 + v8::Context::Scope scope(backchannel_context);
  444 +
  445 + // prepare getCfg() parameter
  446 + v8::Handle<v8::Value> getcfg_args[1] = {v8::String::New(cfg_name.c_str())};
  447 +
  448 + // run getCfg()
  449 + v8::TryCatch try_catch;
  450 + v8::Handle<v8::Value> res = getcfg_func->Call(backchannel_context->Global(), 1, getcfg_args);
  451 + if (!res.IsEmpty()) {
  452 + return handle_scope.Close(res);
  453 + }
  454 + else {
  455 + return v8::Undefined();
  456 + }
  457 +}
  458 +
  459 +v8::Handle<v8::Object> getCfgObj() {
  460 + return v8::Handle<v8::Object>::Cast(getCfgVal(""));
  461 +}
  462 +
  463 +bool setCfgVal(std::string cfg_name, v8::Handle<v8::Value> cfg_val) {
  464 + v8::HandleScope handle_scope;
  465 + v8::Context::Scope scope(backchannel_context);
  466 +
  467 + // prepare setCfg() parameters
  468 + v8::Handle<v8::Value> setcfg_args[2] = {v8::String::New(cfg_name.c_str()), cfg_val};
  469 +
  470 + // run setCfg()
  471 + v8::TryCatch try_catch;
  472 + v8::Handle<v8::Value> res = setcfg_func->Call(backchannel_context->Global(), 2, setcfg_args);
  473 + if (res.IsEmpty()) {
  474 + ReportException(&try_catch); // setCfg() failed
369 475 return false;
370 476 }
  477 + return true;
  478 +}
  479 +
  480 +std::string formatLogMessageBasic(std::vector< std::pair<std::string,std::string> > msg, std::string format) {
  481 + std::string formatted = "";
  482 + std::string log_format;
  483 +
  484 + if (format == "*") {
  485 + log_format = "common";
  486 + }
371 487 else {
372   - v8::Handle<v8::Value> result = script->Run();
373   - if (result.IsEmpty()) {
374   - // Print errors that happened during execution.
375   - ReportException(&try_catch);
376   - return false;
  488 + log_format = format;
  489 + }
  490 +
  491 + for(std::vector< std::pair<std::string,std::string> >::iterator ii=msg.begin(); ii!=msg.end(); ++ii) {
  492 + // default ("common") format: display each value, with space as separator
  493 + formatted += ((!formatted.empty()) ? " " : "") + ii->second;
  494 + }
  495 +
  496 + return formatted;
  497 +}
  498 +
  499 +std::string formatLogMessage(std::vector< std::pair<std::string,std::string> > msg, std::string format) {
  500 + if (!backchannel_ready) {
  501 + return formatLogMessageBasic(msg,format);
  502 + }
  503 +
  504 + v8::HandleScope handle_scope;
  505 + v8::Context::Scope scope(backchannel_context);
  506 +
  507 + std::string formatted = "";
  508 + std::string log_format = "";
  509 + v8::Handle<v8::Object> obj_inject;
  510 +
  511 + if (format == "*") {
  512 + obj_inject = v8::Object::New();
  513 + log_format = ToStdString(getCfgVal(std::string("log_format")));
  514 + }
  515 + else {
  516 + log_format = format;
  517 + }
  518 +
  519 + for(std::vector< std::pair<std::string,std::string> >::iterator ii=msg.begin(); ii!=msg.end(); ++ii) {
  520 + if (log_format == "json") {
  521 + obj_inject->Set(v8::String::New(ii->first.c_str()), v8::String::New(ii->second.c_str()));
  522 + }
  523 + else { // default ("common") format: display each value, with space as separator
  524 + formatted += ((!formatted.empty()) ? " " : "") + ii->second;
  525 + }
  526 + }
  527 +
  528 + if (log_format == "json") {
  529 + v8::Handle<v8::Value> obj_args[1] = {obj_inject};
  530 +
  531 + // run JSON.stringify() on object to format it to JSON
  532 + v8::TryCatch try_catch;
  533 + v8::Handle<v8::Value> res = jsonstringify_func->Call(backchannel_context->Global(), 1, obj_args);
  534 + if (res.IsEmpty()) {
  535 + ReportException(&try_catch); // JSON.stringify() failed to be called
  536 + return "";
  537 + }
  538 +
  539 + formatted = ToStdString(res);
  540 + }
  541 +
  542 + return formatted;
  543 +}
  544 +
  545 +off_t file_size(std::string filename) {
  546 + struct stat fileinfo;
  547 + int res;
  548 +
  549 + res = stat(filename.c_str(),&fileinfo);
  550 + if (res == 0) {
  551 + return fileinfo.st_size;
  552 + }
  553 + else {
  554 + return -1;
  555 + }
  556 +}
  557 +
  558 +bool file_exists(std::string filename) {
  559 + return file_size(filename) >= 0;
  560 +}
  561 +
  562 +void init_log_file(std::string log_format, std::string filename, FILE* fh) {
  563 + if (file_size(filename) == 0) {
  564 + std::vector< std::pair<std::string,std::string> > msg_vec;
  565 + msg_vec.push_back(std::pair<std::string,std::string>("type","Init"));
  566 + msg_vec.push_back(std::pair<std::string,std::string>("timestamp",current_timestamp()));
  567 + std::string msg;
  568 + if (log_format == "json") msg = "[\n " + formatLogMessage(msg_vec) + "\n]\n";
  569 + else msg = formatLogMessage(msg_vec) + "\n";
  570 +
  571 + fwrite(msg.c_str(),sizeof(char),msg.length(),fh);
  572 + fflush(fh);
  573 + }
  574 +}
  575 +
  576 +void write_to_log_file(std::string log_format, std::string str, FILE* fh) {
  577 + if (log_format == "json") {
  578 + fseek(fh, -3, SEEK_END);
  579 + }
  580 + fwrite(str.c_str(),sizeof(char),str.length(),fh);
  581 + fflush(fh);
  582 +}
  583 +
  584 +bool logMessage(std::string message, int msg_type) {
  585 +// msg_type:
  586 +// 0: notice
  587 +// 1: console
  588 +// 2: warning
  589 +// 3: error
  590 +
  591 + if (message.empty()) {
  592 + return false;
  593 + }
  594 +
  595 + std::string write_msg = message;
  596 +
  597 + if (backchannel_ready) {
  598 + v8::HandleScope handle_scope;
  599 + v8::Context::Scope scope(backchannel_context);
  600 +
  601 + v8::Handle<v8::Object> cfg = getCfgObj();
  602 + if (!cfg.IsEmpty() && !cfg->IsUndefined()) {
  603 + std::string log_format = ToStdString(cfg->Get(v8::String::New("log_format")));
  604 + std::string file_log_file = ToStdString(cfg->Get(v8::String::New("file_log_file")));
  605 + std::string file_log_error_file = ToStdString(cfg->Get(v8::String::New("file_log_error_file")));
  606 + int log_level = cfg->Get(v8::String::New("log_level"))->IntegerValue();
  607 + int error_log_level = cfg->Get(v8::String::New("error_log_level"))->IntegerValue();
  608 +
  609 + if (log_format == "json") write_msg = ",\n " + write_msg + "\n]\n";
  610 + else write_msg += "\n";
  611 +
  612 + if (cfg->Get(v8::String::New("logging"))->BooleanValue()) {
  613 + if (cfg->Get(v8::String::New("file_logging"))->BooleanValue()) {
  614 + if ((msg_type == 0 || msg_type == 1) && (log_level <= msg_type)) {
  615 + init_log_file(log_format,file_log_file,file_log_file_handle);
  616 + write_to_log_file(log_format,write_msg,file_log_file_handle);
  617 + }
  618 + else if (msg_type >= 2 && (error_log_level+2) <= msg_type) {
  619 + init_log_file(log_format,file_log_error_file,file_log_error_file_handle);
  620 + write_to_log_file(log_format,write_msg,file_log_error_file_handle);
  621 + }
  622 + }
  623 + if (cfg->Get(v8::String::New("system_event_logging"))->BooleanValue()) {
  624 +
  625 + }
  626 + }
  627 + if (msg_type >= 3 && (!cfg->Get(v8::String::New("logging"))->BooleanValue() || cfg->Get(v8::String::New("display_errors"))->BooleanValue())) {
  628 + if (content_type_needed) {
  629 + printf("Content-type: text/plain\n\n");
  630 + content_type_needed = 0;
  631 + }
  632 + if (cfg->Get(v8::String::New("display_errors"))->BooleanValue()) { // forced display of error
  633 + printf("%s\n",message.c_str());
  634 + }
  635 + else { // error was not logged or displayed to stdout, so at least send to stderr
  636 + fprintf(stderr, "%s\n",message.c_str());
  637 + }
  638 + }
  639 + return true;
  640 + }
  641 + return false;
  642 + }
  643 + else { // logging before backchannel is ready
  644 + // so, only log errors (and above), to stderr
  645 + if (msg_type >= 3) {
  646 + if (content_type_needed) {
  647 + printf("Content-type: text/plain\n\n");
  648 + content_type_needed = 0;
  649 + }
  650 + fprintf(stderr, "%s\n",message.c_str());
377 651 }
378 652 return true;
379 653 }
380 654 }
381 655
  656 +std::string stringify(int num) {
  657 + std::ostringstream o;
  658 + o << num;
  659 + return o.str();
  660 +}
  661 +
  662 +std::string left_pad_str(std::string str, int toLength, char pad) {
  663 + if (toLength < 1 || str.length() >= toLength) return str;
  664 + return std::string(toLength-str.length(), pad) + str;
  665 +}
  666 +
  667 +std::string current_timestamp() {
  668 + std::string dow[7] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
  669 + std::string mon[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
  670 + std::string ts;
  671 + time_t rawtime;
  672 + struct tm* timeinfo;
  673 + std::string tz;
  674 +
  675 + time(&rawtime);
  676 + timeinfo = localtime(&rawtime);
  677 +
  678 + std::string tzoffset = stringify(0-(timezone/36));
  679 + if (tzoffset[0] != '-') tzoffset = "+" + tzoffset;
  680 + tzoffset = "GMT" + tzoffset.substr(0,1) + left_pad_str(tzoffset.substr(1),4,'0');
  681 +
  682 + ts = dow[timeinfo->tm_wday] + " " + mon[timeinfo->tm_mon] + " " + stringify(timeinfo->tm_mday) + " " + stringify(1900+timeinfo->tm_year);
  683 + ts += " " + left_pad_str(stringify(timeinfo->tm_hour),2,'0') + ":" + left_pad_str(stringify(timeinfo->tm_min),2,'0') + ":" + left_pad_str(stringify(timeinfo->tm_sec),2,'0');
  684 + ts += " " + tzoffset + " (" + std::string(*tzname) + ")";
  685 +
  686 + return ts;
  687 +}
  688 +
  689 +bool log(std::string msg, int msg_type=0, int errorNumber) {
  690 +// msg_type:
  691 +// 0: notice
  692 +// 1: console
  693 +// 2: warning
  694 +// 3: error
  695 +
  696 + std::string types[4] = {"Notice", "Console", "Warning", "Error"};
  697 +
  698 + if (!msg.empty()) {
  699 + std::vector< std::pair<std::string,std::string> > msg_vec;
  700 +
  701 + msg_vec.push_back(std::pair<std::string,std::string>("type",types[msg_type]));
  702 + msg_vec.push_back(std::pair<std::string,std::string>("timestamp",current_timestamp()));
  703 + if (msg_type >= 3 && errorNumber > 0) {
  704 + msg_vec.push_back(std::pair<std::string,std::string>("code",stringify(errorNumber)));
  705 + }
  706 + msg_vec.push_back(std::pair<std::string,std::string>("msg",msg));
  707 +
  708 + return logMessage(formatLogMessage(msg_vec),msg_type);
  709 + }
  710 + else {
  711 + return false;
  712 + }
  713 +}
  714 +
  715 +bool log_notice(std::string msg) { return log(msg,0); }
  716 +bool log_console(std::string msg) { return log(msg,1); }
  717 +bool log_warning(std::string msg) { return log(msg,2); }
  718 +bool log_error(std::string msg, int error_number) { return log(msg,3,error_number); }
  719 +bool log_fatal(std::string msg, int error_number) { return log(msg,3,error_number); }
  720 +
  721 +
382 722 int RunMain(int argc, char* argv[]) {
  723 +
  724 + // initialize the timezone info
  725 + tzset();
  726 +
  727 +// ***** SETUP *****
383 728 // get the current working directory and full executable path
384   - char* cwd_str = gnu_getcwd();
385   - std::string path_cwd(cwd_str);
386   - free(cwd_str);
  729 + std::string path_cwd(gnu_getcwd());
387 730 std::string path_exec(argv[0]);
388   - std::string full_path = path_cwd + "/" + path_exec;
  731 +
  732 + // parse path parts
  733 + std::string path_parts_str = get_canonical_path(path_cwd,path_exec);
  734 + std::vector<std::string> path_parts = split_path(path_parts_str);
  735 + std::string exec_path_directory = path_parts[0];
  736 + std::string exec_path_name = path_parts[1];
  737 +
  738 + bikechain_root_path_directory = exec_path_directory.substr(0,exec_path_directory.find_last_of("/",exec_path_directory.length()-2)+1);
  739 +
  740 + log_notice("Starting BikechainJS in " + bikechain_root_path_directory);
389 741
390 742 // start the V8 environment
391 743 v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
392 744 v8::HandleScope handle_scope;
393 745
394   - v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
395   -
396   - v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
397   - v8::Context::Scope context_scope(context);
398   -
399   - v8::Handle<v8::String> source = v8::Handle<v8::String>::Cast(ReadFile((full_path+".js").c_str()));
400   - v8::Handle<v8::Script> compiled_source = v8::Script::Compile(source);
401   - if (compiled_source.IsEmpty()) {
402   - printf("Error reading engine.js\n");
403   - return 1;
404   - }
405   - v8::Handle<v8::Value> enginejs = compiled_source->Run();
406   - v8::Handle<v8::Function> enginejs_func = v8::Handle<v8::Function>::Cast(enginejs);
407   -
408   - v8::Handle<v8::Object> inject = v8::Object::New();
409   - inject->Set(v8::String::New("__IORead__"), v8::FunctionTemplate::New(ioRead)->GetFunction());
410   - inject->Set(v8::String::New("__IOWrite__"), v8::FunctionTemplate::New(ioWrite)->GetFunction());
411   - inject->Set(v8::String::New("__IOFlush__"), v8::FunctionTemplate::New(ioFlush)->GetFunction());
412   - inject->Set(v8::String::New("__FSRead__"), v8::FunctionTemplate::New(fsRead)->GetFunction());
413   - inject->Set(v8::String::New("__FSWrite__"), v8::FunctionTemplate::New(fsWrite)->GetFunction());
414   - inject->Set(v8::String::New("__SysExec__"), v8::FunctionTemplate::New(sysExec)->GetFunction());
415   - inject->Set(v8::String::New("__SysExit__"), v8::FunctionTemplate::New(sysExit)->GetFunction());
416   - inject->Set(v8::String::New("__SetContentTypeNeeded__"), v8::FunctionTemplate::New(setContentTypeNeeded)->GetFunction());
417   - inject->Set(v8::String::New("__IsContentTypeNeeded__"), v8::FunctionTemplate::New(isContentTypeNeeded)->GetFunction());
418   - v8::Handle<v8::Value> args[1] = {inject};
419   -
420   - enginejs_func->Call(context->Global(), 1, args);
421   -
422   - for (int i = 1; i < argc; i++) {
423   - const char* str = argv[i];
424   - // Use all arguments as names of files to load and run.
425   - v8::HandleScope handle_scope;
426   - v8::Handle<v8::String> file_name = v8::String::New(str);
427   - v8::Handle<v8::String> source = v8::Handle<v8::String>::Cast(ReadFile((path_cwd + "/" + std::string(str)).c_str()));
428   - if (source.IsEmpty()) {
429   - printf("Error reading '%s'\n", str);
  746 + v8::Handle<v8::String> bikechain_root_path = v8::String::New(bikechain_root_path_directory.c_str());
  747 +
  748 +// ***** BACKCHANNEL *****
  749 + // set up the backchannel controller (for processing config file and formatting log messages)
  750 + v8::Handle<v8::ObjectTemplate> backchannel_global = v8::ObjectTemplate::New();
  751 + backchannel_context = v8::Context::New(NULL, backchannel_global);
  752 + {
  753 + v8::Context::Scope scope(backchannel_context);
  754 +
  755 + // prepare JSON serializer
  756 + jsonstringify_func = v8::Handle<v8::Function>::Cast(ExecuteStringValue(v8::String::New("(function(j){return JSON.stringify(j);})"),v8::String::New("inline::code")));
  757 + if (jsonstringify_func.IsEmpty() || jsonstringify_func->IsUndefined()) {
  758 + log_fatal("Failed preparing engine backchannel JSON utility");
  759 + return 1;
  760 + }
  761 +
  762 + // load JSON.minify() utility
  763 + tmpval = ReadFile((bikechain_root_path_directory+"misc/minify.json.js").c_str());
  764 + if (tmpval.IsEmpty() || tmpval->IsUndefined()) {
  765 + log_fatal("Failed loading engine backchannel: `minify.json.js`");
  766 + return 1;
  767 + }
  768 + v8::Handle<v8::String> json_minify_source = v8::Handle<v8::String>::Cast(tmpval);
  769 + if (!ExecuteString(json_minify_source, v8::String::New("minify.json.js"))) {
  770 + log_fatal("Failed parsing engine backchannel: `minify.json.js`");
  771 + return 1;
  772 + }
  773 +
  774 + // load String.trim() utility
  775 + tmpval = ReadFile((bikechain_root_path_directory+"misc/string.trim.js").c_str());
  776 + if (tmpval.IsEmpty() || tmpval->IsUndefined()) {
  777 + log_fatal("Failed loading engine backchannel; `string.trim.js`");
  778 + return 1;
  779 + }
  780 + v8::Handle<v8::String> string_trim_source = v8::Handle<v8::String>::Cast(tmpval);
  781 + if (!ExecuteString(string_trim_source, v8::String::New("string.trim.js"))) {
  782 + log_fatal("Failed parsing engine backchannel: `string.trim.js`");
  783 + return 1;
  784 + }
  785 +
  786 + // load/prepare backchannel controller
  787 + tmpval = ReadFile((exec_path_directory+"backchannel.js").c_str());
  788 + if (tmpval.IsEmpty() || tmpval->IsUndefined()) {
  789 + log_fatal("Failed loading engine backchannel: `backchannel.js`");
430 790 return 1;
431 791 }
432   - if (!ExecuteString(source, file_name))
433   - return 1;
  792 + v8::Handle<v8::Function> backchannel_func = v8::Handle<v8::Function>::Cast(ExecuteStringValue(v8::Handle<v8::String>::Cast(tmpval),v8::String::New("backchannel.js")));
  793 + if (backchannel_func.IsEmpty() || backchannel_func->IsUndefined()) {
  794 + log_fatal("Failed parsing engine backchannel: `backchannel.js`");
  795 + return 1;
  796 + }
  797 +
  798 + // read/parse config file
  799 + tmpval = ReadFile((exec_path_directory+exec_path_name+".json").c_str());
  800 + if (tmpval.IsEmpty() || tmpval->IsUndefined()) {
  801 + log_fatal("Failed loading engine configuration: `" + exec_path_name + ".json`");
  802 + return 1;
  803 + }
  804 +
  805 + // prepare backchannel init parameters
  806 + v8::Handle<v8::Object> backchannel_inject = v8::Object::New();
  807 + backchannel_inject->Set(v8::String::New("cfg"), v8::Handle<v8::String>::Cast(tmpval));
  808 + v8::Handle<v8::Value> backchannel_args[1] = {backchannel_inject};
  809 +
  810 + // run backchannel init
  811 + v8::TryCatch try_catch;
  812 + v8::Handle<v8::Value> res = backchannel_func->Call(backchannel_context->Global(), 1, backchannel_args);
  813 + if (res.IsEmpty()) {
  814 + ReportException(&try_catch);
  815 + log_fatal("Failed initializing backchannel");
  816 + return 1;
  817 + }
  818 +
  819 + // store references to backchannel configuration get/set JS functions
  820 + getcfg_func = v8::Handle<v8::Function>::Cast(ExecuteStringValue(v8::String::New("getCfg"),v8::String::New("inline::code")));
  821 + if (getcfg_func.IsEmpty() || getcfg_func->IsUndefined()) {
  822 + log_fatal("Failed preparing engine configuration management");
  823 + return 1;
  824 + }
  825 + v8::TryCatch try_catch2;
  826 + setcfg_func = v8::Handle<v8::Function>::Cast(ExecuteStringValue(v8::String::New("setCfg"),v8::String::New("inline::code")));
  827 + if (setcfg_func.IsEmpty() || setcfg_func->IsUndefined()) {
  828 + ReportException(&try_catch2);
  829 + log_fatal("Failed preparing engine configuration management");
  830 + return 1;
  831 + }
  832 +
  833 + // manage engine configuration
  834 + v8::Handle<v8::Object> tmp_cfg = getCfgObj();
  835 + if (!tmp_cfg.IsEmpty() && !tmp_cfg->IsUndefined()) {
  836 + // canonicalize the `file_log_*` paths from the engine configuration
  837 + std::string file_log_file = get_canonical_path(bikechain_root_path_directory,ToStdString(tmp_cfg->Get(v8::String::New("file_log_file"))));
  838 + std::string file_log_error_file = get_canonical_path(bikechain_root_path_directory,ToStdString(tmp_cfg->Get(v8::String::New("file_log_error_file"))));
  839 +
  840 + // push the updated path values back into the configuration cache
  841 + if (!setCfgVal("file_log_file", v8::String::New(file_log_file.c_str()))) {
  842 + log_fatal("Failed normalizing engine configuration");
  843 + return 1;
  844 + }
  845 + if (!setCfgVal("file_log_error_file", v8::String::New(file_log_error_file.c_str()))) {
  846 + log_fatal("Failed normalizing engine configuration");
  847 + return 1;
  848 + }
  849 +
  850 + // make sure the log files exist and are properly initialized
  851 + if (!file_exists(file_log_file)) file_log_file_handle = fopen(file_log_file.c_str(),"w+t");
  852 + else file_log_file_handle = fopen(file_log_file.c_str(),"r+t");
  853 + if (file_log_file_handle == NULL) {
  854 + log_fatal("Failed opening log file: `" + file_log_file + "`");
  855 + return 1;
  856 + }
  857 + chmod(file_log_file.c_str(),0664);
  858 +
  859 + if (!file_exists(file_log_error_file)) file_log_error_file_handle = fopen(file_log_error_file.c_str(),"w+t");
  860 + else file_log_error_file_handle = fopen(file_log_error_file.c_str(),"r+t");
  861 + if (file_log_error_file_handle == NULL) {
  862 + log_fatal("Failed opening error log file: `" + file_log_error_file + "`");
  863 + return 1;
  864 + }
  865 + chmod(file_log_error_file.c_str(),0664);
  866 + }
  867 + else {
  868 + log_fatal("Failed executing engine configuration management");
  869 + return 1;
  870 + }
  871 +
  872 + backchannel_ready = true;
  873 + }
  874 +
  875 +
  876 +// ***** ENGINE *****
  877 + v8::Handle<v8::ObjectTemplate> engine_global = v8::ObjectTemplate::New();
  878 + engine_context = v8::Context::New(NULL, engine_global);
  879 + {
  880 + v8::Context::Scope scope(engine_context);
  881 +
  882 + // load engine source
  883 + tmpval = ReadFile((exec_path_directory+exec_path_name+".js").c_str());
  884 + if (tmpval.IsEmpty() || tmpval->IsUndefined()) {
  885 + log_fatal("Failed loading engine: `" + exec_path_name + ".js`");
  886 + return 1;
  887 + }
  888 +
  889 + v8::Handle<v8::Function> engine_func = v8::Handle<v8::Function>::Cast(ExecuteStringValue(v8::Handle<v8::String>::Cast(tmpval),v8::String::New(std::string(exec_path_name+".js").c_str())));
  890 + if (engine_func.IsEmpty() || engine_func->IsUndefined()) {
  891 + log_fatal("Failed parsing engine: `" + exec_path_name + ".js`");
  892 + return 1;
  893 + }
  894 +
  895 + // prepare engine init parameters
  896 + v8::Handle<v8::Object> engine_inject = v8::Object::New();
  897 + engine_inject->Set(v8::String::New("__IORead__"), v8::FunctionTemplate::New(ioRead)->GetFunction());
  898 + engine_inject->Set(v8::String::New("__IOWrite__"), v8::FunctionTemplate::New(ioWrite)->GetFunction());
  899 + engine_inject->Set(v8::String::New("__IOFlush__"), v8::FunctionTemplate::New(ioFlush)->GetFunction());
  900 + engine_inject->Set(v8::String::New("__FSRead__"), v8::FunctionTemplate::New(fsRead)->GetFunction());
  901 + engine_inject->Set(v8::String::New("__FSWrite__"), v8::FunctionTemplate::New(fsWrite)->GetFunction());
  902 + engine_inject->Set(v8::String::New("__SysExec__"), v8::FunctionTemplate::New(sysExec)->GetFunction());
  903 + engine_inject->Set(v8::String::New("__SysExit__"), v8::FunctionTemplate::New(sysExit)->GetFunction());
  904 + engine_inject->Set(v8::String::New("__Console__"), v8::FunctionTemplate::New(sysConsole)->GetFunction());
  905 + engine_inject->Set(v8::String::New("__SetContentTypeNeeded__"), v8::FunctionTemplate::New(setContentTypeNeeded)->GetFunction());
  906 + engine_inject->Set(v8::String::New("__IsContentTypeNeeded__"), v8::FunctionTemplate::New(isContentTypeNeeded)->GetFunction());
  907 + v8::Handle<v8::Value> engine_args[2] = {bikechain_root_path,engine_inject};
  908 +
  909 + // run engine
  910 + v8::TryCatch try_catch;
  911 + v8::Handle<v8::Value> res = engine_func->Call(engine_context->Global(), 2, engine_args);
  912 + if (res.IsEmpty()) {
  913 + ReportException(&try_catch); // engine failed to init
  914 + log_fatal("Failed initializing engine");
  915 + return 1;
  916 + }
  917 +
  918 + log_notice("Engine and backchannel ready");
  919 +
  920 +
  921 +// ***** COMMAND-LINE *****
  922 +
  923 + std::string filename_str;
  924 +
  925 + // run parameter .js files
  926 + for (int i = 1; i < argc; i++) {
  927 + v8::HandleScope handle_scope;
  928 + const char* str = argv[i];
  929 +
  930 + // Use all arguments as names of files to load and run.
  931 + filename_str = get_canonical_path(path_cwd,std::string(str));
  932 + v8::Handle<v8::String> file_name = v8::String::New(filename_str.c_str());
  933 +
  934 + log_notice("Loading `" + filename_str + "`");
  935 +
  936 + // load and run file specified
  937 + tmpval = ReadFile(filename_str.c_str());
  938 + if (tmpval.IsEmpty() || tmpval->IsUndefined()) {
  939 + log_fatal("Failed loading file: `" + filename_str + "`");
  940 + return 1;
  941 + }
  942 + if (!ExecuteString(v8::Handle<v8::String>::Cast(tmpval),file_name)) {
  943 + log_fatal("Failed executing file: `" + filename_str + "`");
  944 + return 1;
  945 + }
  946 + }
434 947 }
  948 +
435 949 return 0;
436 950 }
437 951
438 952 int main(int argc, char* argv[]) {
439 953 int result = RunMain(argc, argv);
440 954 v8::V8::Dispose();
  955 + fclose(file_log_file_handle);
  956 + fclose(file_log_error_file_handle);
441 957 return result;
442 958 }
443 959
32 engine/src/engine.h
... ... @@ -1,9 +1,10 @@
1 1 /* BikechainJS (engine)
2   - v0.0.1.4 (c) Kyle Simpson
  2 + v0.0.1.9 (c) Kyle Simpson
3 3 MIT License
4 4 */
5 5
6 6 const char* ToCString(const v8::String::Utf8Value& value);
  7 +std::string ToStdString(v8::Handle<v8::Value> value);
7 8
8 9 v8::Handle<v8::Value> ioRead();
9 10 v8::Handle<v8::Value> ioWrite(const v8::Arguments& args);
@@ -22,4 +23,31 @@ void FlushIO();
22 23 v8::Handle<v8::Value> executeProcess(const v8::Arguments& args);
23 24
24 25 void ReportException(v8::TryCatch* handler);
25   -bool ExecuteString(v8::Handle<v8::String> source, v8::Handle<v8::Value> name, bool print_result, bool report_exceptions);
  26 +bool ExecuteString(v8::Handle<v8::String> source, v8::Handle<v8::Value> name);
  27 +v8::Handle<v8::Value> ExecuteStringValue(v8::Handle<v8::String> source, v8::Handle<v8::Value> name);
  28 +
  29 +std::vector<std::string> split_path(std::string path);
  30 +std::string get_canonical_path(std::string cwd, std::string path);
  31 +
  32 +v8::Handle<v8::Value> getCfgVal(std::string cfg_name);
  33 +v8::Handle<v8::Object> getCfgObj(void);
  34 +bool setCfgVal(std::string cfg_name, v8::Handle<v8::Value> cfg_val);
  35 +std::string formatLogMessageBasic(std::vector< std::pair<std::string,std::string> > msg, std::string format="*");
  36 +std::string formatLogMessage(std::vector< std::pair<std::string,std::string> > msg, std::string format="*");
  37 +bool logMessage(std::string message, int msg_type=0);
  38 +
  39 +off_t file_size(std::string filename);
  40 +bool file_exists(std::string filename);
  41 +void init_log_file(std::string log_format, std::string filename, FILE* fh);
  42 +void write_to_log_file(std::string log_format, std::string str, FILE* fh);
  43 +
  44 +std::string stringify(int num);
  45 +std::string left_pad_str(std::string str, int to_length, char pad=' ');
  46 +std::string current_timestamp();
  47 +
  48 +bool log(std::string msg, int msg_type, int error_number=0);
  49 +bool log_notice(std::string msg);
  50 +bool log_console(std::string msg);
  51 +bool log_warning(std::string msg);
  52 +bool log_error(std::string msg, int error_number=0);
  53 +bool log_fatal(std::string msg, int error_number=0);
12 engine/src/makefile
... ... @@ -1,12 +1,18 @@
1 1 ## BikechainJS (makefile)
2   -## v0.0.1.3 (c) Kyle Simpson
  2 +## v0.0.1.9 (c) Kyle Simpson
3 3 ## MIT License
4 4
  5 +
5 6 engine : engine.o
6   - g++ -o ../engine -lv8 engine.o
  7 + g++ -o engine -lv8 engine.o
7 8
8 9 engine.o : engine.cpp
9 10 g++ -c engine.cpp -I/path/to/V8/include -I./
10 11
  12 +install : engine
  13 + strip ./engine
  14 + cp ./engine ../engine
  15 + chmod 750 ../engine
  16 +
11 17 clean:
12   - rm *.o; strip ../engine
  18 + rm *.o
1  misc/string.trim.js
... ... @@ -1,3 +1,4 @@
  1 +// String.trim() is defined as a static utility function rather than a prototype extension
1 2 if (!String.trim) {
2 3 String.trim = function(str) { // from: http://blog.stevenlevithan.com/archives/faster-trim-javascript
3 4 var str = str.replace(/^\s\s*/, ''),ws = /\s/,i = str.length;

0 comments on commit fe43958

Please sign in to comment.
Something went wrong with that request. Please try again.