diff --git a/js/dos/compat.js b/js/dos/compat.js new file mode 100644 index 0000000..c6be80c --- /dev/null +++ b/js/dos/compat.js @@ -0,0 +1,818 @@ +/** + ** ================================== + ** OOOO OOOO OOOO O O OOOO + ** O O O O O O O O O + ** O O O O O O O O O + ** OOOO OOOO OOOO O OOO OOOO + ** O O O O O O O O O + ** O O O O O O O O O + ** OOOO OOOO OOOO OOOO O O OOOO + ** ================================== + ** BSSLAB, Dr. Stefan Bosse http://www.bsslab.de + ** + ** COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED + ** BY THE AUTHOR. + ** THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED, + ** MODIFIED, OR OTHERWISE USED IN A CONTEXT + ** OUTSIDE OF THE SOFTWARE SYSTEM. + ** + ** $AUTHORS: Stefan Bosse + ** $INITIAL: (C) 2015 BSSLAB + ** $CREATED: 3/30/15. + ** $VERSION: 1.1.3 + ** + ** $INFO: + ** + ** JavaScript-OCaML Compatibility Module + ** + ** $ENDOFINFO + */ +"use strict"; +var Io = require('./io'); +var Path = require('./ext/path'); + +/** + * + * @param {boolean|string} condmsg conditional message (cond)||(msg) + */ +var assert = function(condmsg) { + if (condmsg != true) { + Io.out('** Assertion failed: '+condmsg+' **'); + Io.stacktrace(); + throw Error(condmsg); + } +}; + +/** OBJ + * + * @type {{isArray: Function, isFunction: Function, isString: Function, isNumber: Function}} + */ +var obj = { + isArray:function (o) { + return typeof o == "array" || (typeof o == "object" && o.constructor === Array); + }, + isFunction: function (o) { + return typeof o == "function"; + }, + isString: function (o) { + return typeof o == "string" || (typeof o == "object" && o.constructor === String); + }, + isNumber: function (o) { + return typeof o == "number" || (typeof o == "object" && o.constructor === Number); + } +}; + +/** ARRAY + * + * @type {{append: Function, check: Function, concat: Function, copy: Function, create: Function, create_matrix: Function, empty: Function, find: Function, filter: Function, flatten: Function, head: Function, init: Function, iter: Function, iter_rev: Function, length: Function, map: Function, match: Function, member: Function, merge: Function, pop: Function, push: Function, range: Function, tail: Function, print: Function, sort: Function}} + */ +var array = { + /** Append one element at the end of the array. + * + * @param {* []} array + * @param {*} element + */ + append : function(array,element) { + array.push(element); + }, + /** Check for an elenment in the array by using a check function. + * + * @param array + * @param fun + * @returns {boolean} + */ + check: function(array,fun) { + var i,exist; + exist=false; + loop: for(i in array) { + var element=array[i]; + if (fun(element,i)) { + exist=true; + break loop; + } + } + return exist; + }, + /** Append array2 at the end of array. + * + * @param array + * @param array2 + */ + concat : function(array,array2) { + for(var i in array2) { + array.push(array2[i]); + } + }, + copy: function(array) { + return array.slice(); + }, + create : function(length,init) { + var arr = [], i = length; + while (i--) { + arr[i] = init; + } + return arr; + }, + create_matrix : function(rows,cols,init) { + var m = []; + var r = []; + var i,j; + for (i = 0; i < rows; i++) { + r=[]; + for(j=0;j=0;i--) { + var element=array[i]; + fun(element,i) + } + }, + length : function(array) { + return array.length; + }, + /** + * + * @param {* []} array + * @param {function(*,number)} fun + * @returns {* []} + */ + map: function(array,fun) { + var i=0; + var len=array.length; + var res=[]; + for(i=0;i1) { + var hd = this.head(array); + var tl = this.tail(array); + fun_hdtl(hd,tl); + } else fun_hdtl(this.head(array),[]); + }, + /** Check for an element in the array. + * + * @param {(number|string|boolean) []} array + * @param {number|string|boolean} element + * @returns {boolean} + */ + member: function(array,element) { + var i,exist; + var len=array.length; + exist=false; + loop: for(i=0;i>4) & 0xf).toString(16))+ + ((n&0xf).toString(16)); + case 4: return (((n>>12) & 0xf).toString(16)+ + ((n>>8) & 0xf).toString(16)+ + ((n>>4) & 0xf).toString(16)+ + (n&0xf).toString(16)); + case 6: return (((n>>20) & 0xf).toString(16)+ + ((n>>16) & 0xf).toString(16)+ + ((n>>12) & 0xf).toString(16)+ + ((n>>8) & 0xf).toString(16)+ + ((n>>4) & 0xf).toString(16)+ + (n&0xf).toString(16)); + case 8: return (((n>>28) & 0xf).toString(16)+ + ((n>>24) & 0xf).toString(16)+ + ((n>>20) & 0xf).toString(16)+ + ((n>>16) & 0xf).toString(16)+ + ((n>>12) & 0xf).toString(16)+ + ((n>>8) & 0xf).toString(16)+ + ((n>>4) & 0xf).toString(16)+ + (n&0xf).toString(16)); + default: return 'format_hex??'; + } + }, + /** + * + * @param {string} str + * @param {number} index + * @returns {string} + */ + get: function (str,index) { + assert((str != undefined && index < str.length && index >= 0)||('string.get ('+str.length+')')); + return str.charAt(index); + }, + /** + * + * @param {string} str + * @param {function(string,number)} fun + */ + iter: function(str,fun) { + var i; + var len=str.length; + for (i = 0; i < len; i++) { + var c = str.charAt(i); + fun(c,i); + } + }, + /** + * + * @param str + * @returns {*} + */ + length: function(str) { + if (str!=undefined) return str.length; + else return 0; + }, + /** + * + * @param {number} size + * @param {string} init + * @returns {string} + */ + make: function(size,init) + { + var i; + var s=''; + for(i=0;i1) { + cex=cas[0]; + if (!obj.isArray(cex)) { + if (this.equal(str,cex)) { + cas[1](); + return; + } + } else { + for(j in cex) { + cv=cex[j]; + if (this.equal(str,cv)) { + cas[1](); + return; + } + } + } + } else if (obj.isArray(cas) && cas.length==1) { + cas[0](); + return; + } else if (obj.isFunction(cas)) { + cas(str); + return; + } + } + }, + /** + * + * @param str + * @param pos + * @param len + * @returns {Number} + */ + parse_hex: function (str,pos,len) { + // parse a hexadecimal number in string 'str' starting at position 'pos' with 'len' figures. + return parseInt(this.sub(str,pos,len),16); + }, + /** + * + * @param str + * @param index + * @param char + * @returns {string} + */ + set: function (str,index,char) { + assert((str != undefined && index < str.length && index >= 0)||'string.get'); + return str.substr(0, index) + char + str.substr(index+1) + }, + /** + * + * @param delim + * @param str + * @returns {*|Array} + */ + split: function (delim,str) { + return str.split(delim); + }, + /** + * + * @param str + * @param off + * @param len + * @returns {string} + */ + sub: function (str,off,len) { + return str.substr(off,len); + }, + /** Remove leading and trailing characters from string + * + * @param str + * @param start + * @param end + * @returns {*} + */ + trim: function (str,start,end) { + if (str.length==0 || + start>str.length || + end>str.length || + (start==0 && end==0) + ) return str; + return str.substr(start,str.length-start-end); + } +}; + +/** RANDOM + * + * @type {{int: Function}} + */ +var random = { + int: function(max) { + return Math.floor(Math.random()*max+0) + } +}; + +/** PRINTF + * + * @type {{sprintf: Function}} + */ +var printf = { + /** Formatted printer + * + * @param {* []} args (['%format',arg]|string) [] format=%s,%d,%f,%c,%x,%#d,%#s,.. + * @returns {string} + */ + sprintf: function(args) { + var str=''; + array.iter(args,function(fmtarg) { + var len, n,fs; + if (obj.isArray(fmtarg)) { + if (fmtarg.length==2) { + var fmt=fmtarg[0]; + var arg=fmtarg[1]; + var fc=''; + var fn=0; + string.iter(fmt,function(c) { + if (c=='s' || c=='d' || c=='f' || c=='x') { + fc=c; + } else if (c!='%') { + fn=fn*10; + n=parseInt(c); + if (!isNaN(n)) fn=fn+n; + } + }); + if (fc=='s' && obj.isString(arg)) { + str=str+arg; + if (fn!=0) { + len=arg.length; + if (len 0 && path[0] == '/'); + }, + join: function (pathl,absolute) { + var path=(absolute?'/':''); + array.iter(pathl,function (name,index) { + if (index>1) { + path=path+'/'+name; + } + else { + path=path+name; + } + }); + return path; + }, + path_absolute: function (path) { + if (this.is_relative(path)) { + var workdir = Io.workdir(); + return this.path_normalize(workdir + '/' + path); + } else this.path_normalize(path); + }, + path_normalize: function (path) { + var i; + if (string.equal(path, '')) path = '/'; + var relpath = !(string.get(path, 0) == '/'); + var pathlist = path.split('/'); + var pathlist2 = pathlist.filter(function (s) { + return (!string.equal(s, '') && !string.equal(s, '.')) + }); + var pathlist3 = []; + array.iter(pathlist2, function (pe) { + if (!string.equal(pe, '..')) { + array.push(pathlist3, pe) + } else { + if (pathlist3.length == 0) return ''; + else + pathlist3 = array.tail(pathlist3); + } + }); + var path2 = ''; + i = 0; + array.iter(pathlist3, function (pe) { + var sep; + if (i == 0) sep = ''; else sep = '/'; + path2 = pe + sep + path2; + i++; + }); + if (relpath) return path2; else return '/' + path2; + } +}; + +/** PERVASIVES + * + * @type {{char_of_int: Function, div: Function, failwith: Function, int_of_char: Function, int_of_float: Function, int_of_string: Function, mtime: Function, min: Function, max: Function, string_of_int: Function, time: Function}} + */ +var pervasives = { + char_of_int: function (i) {return String.fromCharCode(i)}, + div: function(a,b) {return a/b|0;}, + failwith: function(msg) {Io.err(msg);}, + int_of_char: function(c) {return c.charCodeAt()}, + int_of_float: function(f) {return f|0;}, + int_of_string: function(s) {return parseInt(s)}, + mtime: function () {var time = new Date(); return time.getTime();}, + min: function(a,b) { return (ab)?a:b}, + string_of_int: function(i) {return i.toString()}, + time: function () {var time = new Date(); return (time.getTime()/1000)|0;} +}; + +/** BIT + * + * @type {{get: Function, isSet: Function, set: Function}} + */ +var bit = { + get: function (v,b) {return (v >> b) && 1;}, + isSet: function (v,b) {return ((v >> b) && 1)==1;}, + set: function (v,b) {return v & (1 << b);} +}; + +/** ARGS + * + * @type {{parse: Function}} + */ +var args = { + /** Parse process or command line arguments (array agv) + * + * @param {string []} argv + * @param {*[]} map [,,]|[] [] + */ + parse: function(argv,map) { + var shift=undefined; + var in_shift=0; + var shift_args=[]; + var names; + var mapfun; + var numarg; + + argv.forEach(function (val, index) { + if(index>1) { + if (in_shift==0) { + array.check(map,function (onemap) { + if (onemap.length==3) { + names = onemap[0]; + numarg = onemap[1]; + mapfun = onemap[2]; + if (!obj.isArray(names)) names=[names]; + var found = array.check(names,function (name) { + return string.equal(val, name); + }); + if (found) { + if (numarg==0) mapfun(); + else { + in_shift=numarg; + shift_args=[]; + shift=mapfun; + } + return true; + } + } else if (onemap.length==1) { + mapfun = onemap[0]; + mapfun(val); + return true; + } + return false; + }); + } else { + shift_args.push(val); + in_shift--; + if (in_shift==0 && shift!=undefined) { + numarg=shift_args.length; + switch (numarg) { + case 0: shift(val);break; + case 1: shift(shift_args[0],val); break; + case 2: shift(shift_args[0],shift_args[1],val); break; + default: break; + } + shift=undefined; + } + } + } + }); + } + +}; + +/** HASHTBL + * + * @type {{add: Function, create: Function, find: Function, invalidate: Function, iter: Function, remove: Function}} + */ +var hashtbl = { + add: function(hash,key,data) { + hash[key]=data; + }, + create: function(initial) { + return []; + }, + find: function(hash,key) { + return hash[key]; + }, + invalidate: function(hash,key) { + hash[key]=undefined; + }, + iter: function(hash,fun) { + for (var key in hash) { + if (hash[key]!=undefined) fun(key,hash[key]); + } + }, + remove: function(hash,key) { + // TODO: check, its wrong! + if (!hash.hasOwnProperty(key)) + return; + if (isNaN(parseInt(key)) || !(hash instanceof Array)) + delete hash[key]; + else + hash.splice(key, 1) + } +}; + +module.exports = { + args:args, + assert: assert, + array:array, + bit:bit, + div:pervasives.div, + filename:filename, + hashtbl:hashtbl, + isNodeJS: function () { + return (typeof global !== "undefined" && + {}.toString.call(global) == '[object global]'); + }, + obj:obj, + pervasives:pervasives, + printf:printf, + random:random, + string:string, + isArray: obj.isArray, + isString: obj.isString, + isNumber: obj.isNumber +};