aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@mozilla.com>2011-01-16 13:52:25 -0800
committerAlon Zakai <azakai@mozilla.com>2011-01-16 13:52:25 -0800
commit6a6e842688afe7e15f6a957d4179da982c0f940b (patch)
tree9f31de60b019df0c8c6b0ca23d0ba963e2b1ed76 /src
parent9d209878f9819ffd1aa92c7306123392609db845 (diff)
initial emulation for stdio file reading, and other preparations for poppler
Diffstat (limited to 'src')
-rw-r--r--src/jsifier.js77
-rw-r--r--src/library.js164
-rw-r--r--src/parseTools.js2
-rw-r--r--src/preamble.js2
4 files changed, 194 insertions, 51 deletions
diff --git a/src/jsifier.js b/src/jsifier.js
index a88429a0..847b198d 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -278,56 +278,83 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria
return ret;
} else {
item.JS = 'var ' + item.ident + ';';
- var constant = item.external ?
- makePointer(JSON.stringify(makeEmptyStruct(item.type)) + ' /* external value? */', null, 'ALLOC_STATIC')
- :
- parseConst(item.value, item.type, item.ident);
- if (typeof constant === 'object') {
- // This is a flattened object. We need to find its idents, so they can be assigned to later
- constant.forEach(function(value, i) {
- if (value[0] in set('_', '(') || value.substr(0, 14) === 'CHECK_OVERFLOW') { // ident, or expression containing an ident
- ret.push({
- intertype: 'GlobalVariablePostSet',
- JS: 'IHEAP[' + item.ident + '+' + i + '] = ' + value + ';',
- });
- constant[i] = '0';
- }
+ var constant = null;
+ if (item.external) {
+ return ret;
+ } else {
+ constant = parseConst(item.value, item.type, item.ident);
+ if (typeof constant === 'object') {
+ // This is a flattened object. We need to find its idents, so they can be assigned to later
+ constant.forEach(function(value, i) {
+ if (value[0] in set('_', '(') || value.substr(0, 14) === 'CHECK_OVERFLOW') { // ident, or expression containing an ident
+ ret.push({
+ intertype: 'GlobalVariablePostSet',
+ JS: 'IHEAP[' + item.ident + '+' + i + '] = ' + value + ';'
+ });
+ constant[i] = '0';
+ }
+ });
+ constant = '[' + constant.join(', ') + ']';
+ }
+ constant = makePointer(constant, null, 'ALLOC_STATIC', item.type);
+
+ return ret.concat({
+ intertype: 'GlobalVariable',
+ JS: item.ident + ' = ' + constant + ';',
});
- constant = '[' + constant.join(', ') + ']';
}
- constant = makePointer(constant, null, 'ALLOC_STATIC', item.type);
- return ret.concat({
- intertype: 'GlobalVariable',
- JS: item.ident + ' = ' + constant + ';',
- });
}
}
});
+ var addedLibraryItems = {};
+
// functionStub
substrate.addActor('FunctionStub', {
processItem: function(item) {
+ var ret = [item];
var shortident = item.ident.substr(1);
if (shortident in Library) {
function addFromLibrary(ident) {
var me = arguments.callee;
- if (!me.added) me.added = {};
- if (ident in me.added) return '';
- me.added[ident] = true;
+ if (ident in addedLibraryItems) return '';
+ addedLibraryItems[ident] = true;
var snippet = Library[ident];
if (typeof snippet === 'string') {
if (Library[snippet]) {
snippet = Library[snippet]; // redirection for aliases
}
+ } else if (typeof snippet === 'object') {
+ // JSON.stringify removes functions, so we need to make sure they are added
+ var funcs = [];
+ for (var x in snippet) {
+ if (typeof snippet[x] === 'function') {
+ funcs.push(x + ': ' + snippet[x].toString());
+ }
+ }
+ snippet = JSON.stringify(snippet).replace(/}$/, ', ' + funcs.join(', ') + ' }');
+ } else if (typeof snippet === 'function') {
+ snippet = snippet.toString();
+ }
+
+ var postsetId = ident + '__postset';
+ var postset = Library[postsetId];
+ if (postset && !addedLibraryItems[postsetId]) {
+ addedLibraryItems[postsetId] = true;
+ ret.push({
+ intertype: 'GlobalVariablePostSet',
+ JS: postset
+ });
}
+
var deps = Library[ident + '__deps'];
- return '_' + ident + ' = ' + snippet.toString() + (deps ? '\n' + deps.map(addFromLibrary).join('\n') : '');
+ return '_' + ident + ' = ' + snippet + (deps ? '\n' + deps.map(addFromLibrary).join('\n') : '');
}
item.JS = addFromLibrary(shortident);
} else {
item.JS = '// stub for ' + item.ident;
}
- return [item];
+ return ret;
}
});
diff --git a/src/library.js b/src/library.js
index 495229c3..8bc35ac0 100644
--- a/src/library.js
+++ b/src/library.js
@@ -6,7 +6,8 @@
// entry in the Library is a function, we insert it. If it is a string, we
// do another lookup in the library (a simple way to write a function once,
// if it can be called by different names). We also allow dependencies,
-// using __deps.
+// using __deps. Initialization code to be run after allocating all
+// global constants can be defined by __postset.
//
// Note that the full function name will be '_' + the name in the Library
// object. For convenience, the short name appears here. Note that if you add a
@@ -15,6 +16,7 @@
var Library = {
// stdio.h
+ _formatString__deps: ['STDIO'],
_formatString: function() {
function isFloatArg(type) {
return String.fromCharCode(type) in Runtime.set('f', 'e', 'g');
@@ -142,6 +144,14 @@ var Library = {
_strcpy(str, __formatString.apply(null, args)); // not terribly efficient
},
+ snprintf__deps: ['strncpy', '_formatString'],
+ snprintf: function() {
+ var str = arguments[0];
+ var num = arguments[1];
+ var args = Array.prototype.slice.call(arguments, 2);
+ _strncpy(str, __formatString.apply(null, args), num); // not terribly efficient
+ },
+
fflush: function(file) {
__print__(null);
},
@@ -163,11 +173,6 @@ var Library = {
},
_ZNSo3putEc: 'putchar',
- fopen: function(filename, mode) {
- return 1; // TODO
- },
- __01fopen64_: 'fopen',
-
getc: function(file) {
return -1; // EOF
},
@@ -178,23 +183,6 @@ var Library = {
return chr;
},
- feof: function(stream) {
- return 1;
- },
-
- ferror: function(stream) {
- return 0;
- },
-
- fwrite: function(ptr, size, count, stream) {
- __print__(intArrayToString(Array_copy(ptr, count)));
- return count;
- },
-
- fclose: function(stream) {
- return 0;
- },
-
_ZNSo5flushEv: function() {
__print__('\n');
},
@@ -226,6 +214,115 @@ var Library = {
funlockfile: function(file) {
},
+ // stdio.h - file functions
+
+ STDIO__postset: 'this._STDIO.init()',
+ STDIO: {
+ streams: {},
+ filenames: {},
+ counter: 1,
+ SEEK_SET: 0, /* Beginning of file. */
+ SEEK_CUR: 1, /* Current position. */
+ SEEK_END: 2, /* End of file. */
+ init: function() {
+ _stdin = Pointer_make([0], null, ALLOC_STATIC);
+ IHEAP[_stdin] = this.prepare('<<stdin>>');
+ _stdout = Pointer_make([0], null, ALLOC_STATIC);
+ IHEAP[_stdout] = this.prepare('<<stdout>>');
+ _stderr = Pointer_make([0], null, ALLOC_STATIC);
+ IHEAP[_stderr] = this.prepare('<<stderr>>');
+ },
+ prepare: function(filename, data) {
+ var stream = this.counter++;
+ this.streams[stream] = {
+ filename: filename,
+ data: data,
+ position: 0,
+ eof: 0,
+ error: 0,
+ print: 1 // true for stdout and stderr - we print when receiving data for them
+ };
+ this.filenames[filename] = stream;
+ return stream;
+ }
+ },
+
+ fopen__deps: ['STDIO'],
+ fopen: function(filename, mode) {
+ var str = Pointer_stringify(filename);
+ //assert(str in this._STDIO.filenames, 'No information for file: ' + str);
+ return this._STDIO.filenames[str];
+ },
+ __01fopen64_: 'fopen',
+
+ rewind__deps: ['STDIO'],
+ rewind: function(stream) {
+ var info = this._STDIO.streams[stream];
+ info.position = 0;
+ info.error = 0;
+ },
+
+ fseek__deps: ['STDIO'],
+ fseek: function(stream, offset, whence) {
+ var info = this._STDIO.streams[stream];
+ if (whence === this._STDIO.SEEK_CUR) {
+ offset += info.position;
+ } else if (whence === this._STDIO.SEEK_END) {
+ offset += info.data.length;
+ }
+ info.position = offset;
+ info.eof = 0;
+ return 0;
+ },
+ __01fseeko64_: 'fseek',
+
+ ftell__deps: ['STDIO'],
+ ftell: function(stream) {
+ return this._STDIO.streams[stream].position;
+ },
+ __01ftello64_: 'ftell',
+
+ fread__deps: ['STDIO'],
+ fread: function(ptr, size, count, stream) {
+ var info = this._STDIO.streams[stream];
+ for (var i = 0; i < count; i++) {
+ if (info.position + size > info.data.length) {
+ info.eof = 1;
+ return i;
+ }
+ for (var j = 0; j < size; j++) {
+ {{{ makeSetValue('ptr', '0', 'info.data[info.position]', 'null') }}}
+ info.position++;
+ ptr++;
+ }
+ }
+ return count;
+ },
+
+ fwrite__deps: ['STDIO'],
+ fwrite: function(ptr, size, count, stream) {
+ var info = this._STDIO.streams[stream];
+ if (info.print) {
+ __print__(intArrayToString(Array_copy(ptr, count*size)));
+ } // XXX
+ return count;
+ },
+
+ fclose__deps: ['STDIO'],
+ fclose: function(stream) {
+ return 0;
+ },
+
+ feof__deps: ['STDIO'],
+ feof: function(stream) {
+ return this._STDIO.streams[stream].eof;
+ },
+
+ ferror__deps: ['STDIO'],
+ ferror: function(stream) {
+ return this._STDIO.streams[stream].error;
+ },
+
// stdlib.h
abs: 'Math.abs',
@@ -796,6 +893,14 @@ var Library = {
return -1;
},
+ getuid: function() {
+ return 100;
+ },
+
+ getpwuid: function(uid) {
+ return 0; // NULL
+ },
+
// time.h
time: function(ptr) {
@@ -882,6 +987,19 @@ var Library = {
me.ret = Pointer_make([0], 0, ALLOC_STATIC);
}
return me.ret;
+ },
+
+ // pthread.h (stubs for mutexes only - no thread support yet!)
+
+ pthread_mutex_init: function() {},
+ pthread_mutex_destroy: function() {},
+ pthread_mutex_lock: function() {},
+ pthread_mutex_unlock: function() {},
+
+ // dirent.h
+
+ opendir: function(pname) {
+ return 0;
}
};
diff --git a/src/parseTools.js b/src/parseTools.js
index 12b531ea..52afcfe7 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -57,7 +57,7 @@ function toNiceIdent(ident) {
assert(ident);
if (parseFloat(ident) == ident) return ident;
if (ident == 'null') return '0'; // see parseNumerical
- return ident.replace('%', '$').replace(/["\\ \.@:<>,\*\[\]-]/g, '_');
+ return ident.replace('%', '$').replace(/["&\\ \.@:<>,\*\[\]-]/g, '_');
}
// Kind of a hack. In some cases we have strings that we do not want
diff --git a/src/preamble.js b/src/preamble.js
index ad7ea12a..e375b90a 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -268,8 +268,6 @@ function __shutdownRuntime__() {
}
}
-// stdio.h
-
// Copies a list of num items on the HEAP into a
// a normal JavaScript array of numbers