- Get Nasal code from Simgear source folder
- Get nasal-bin.c from Nasal Github or use the one below
- Compile everything with a standard c-compiler (e.g. gcc or clang)
This is how my slightly adjusted nasal-bin.c looks like:
- Code: Select all
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#include <pthread.h>
#endif
#include "nasal.h"
#include "data.h"
void checkError(naContext ctx)
{
int i;
if(naGetError(ctx)) {
fprintf(stderr, "Runtime error: %s\n at %s, line %d\n",
naGetError(ctx), naStr_data(naGetSourceFile(ctx, 0)),
naGetLine(ctx, 0));
for(i=1; i<naStackDepth(ctx); i++)
fprintf(stderr, " called from: %s, line %d\n",
naStr_data(naGetSourceFile(ctx, i)),
naGetLine(ctx, i));
exit(1);
}
}
// A Nasal extension function (prints its argument list to stdout)
static naRef print(naContext c, naRef me, int argc, naRef* args)
{
int i;
for(i=0; i<argc; i++) {
naRef s = naStringValue(c, args[i]);
if(naIsNil(s)) continue;
fwrite(naStr_data(s), 1, naStr_len(s), stdout);
}
return naNil();
}
#define NASTR(s) naStr_fromdata(naNewString(ctx), (s), strlen((s)))
int main(int argc, char** argv)
{
FILE* f;
struct stat fdat;
char *buf, *script;
struct Context *ctx;
naRef code, namespace, result, *args;
int errLine, i;
if(argc < 2) {
fprintf(stderr, "nasal: must specify a script to run\n");
exit(1);
}
script = argv[1];
// Read the contents of the file into a buffer in memory.
f = fopen(script, "rb");
if(!f) {
fprintf(stderr, "nasal: could not open input file: %s\n", script);
exit(1);
}
stat(script, &fdat);
buf = malloc(fdat.st_size);
if(fread(buf, 1, fdat.st_size, f) != fdat.st_size) {
fprintf(stderr, "nasal: error in fread()\n");
exit(1);
}
// Create an interpreter context
ctx = naNewContext();
// Parse the code in the buffer. The line of a fatal parse error
// is returned via the pointer.
code = naParseCode(ctx, NASTR(script), 1, buf, fdat.st_size, &errLine);
if(naIsNil(code)) {
fprintf(stderr, "Parse error: %s at line %d\n",
naGetError(ctx), errLine);
exit(1);
}
free(buf);
// Make a hash containing the standard library functions. This
// will be the namespace for a new script
namespace = naInit_std(ctx);
// Add application-specific functions (in this case, "print" and
// the math library) to the namespace if desired.
naAddSym(ctx, namespace, "print", naNewFunc(ctx, naNewCCode(ctx, print)));
// Add extra libraries as needed.
naAddSym(ctx, namespace, "utf8", naInit_utf8(ctx));
naAddSym(ctx, namespace, "math", naInit_math(ctx));
naAddSym(ctx, namespace, "bits", naInit_bits(ctx));
naAddSym(ctx, namespace, "io", naInit_io(ctx));
naAddSym(ctx, namespace, "thread", naInit_thread(ctx));
// Bind the "code" object from naParseCode into a "function"
// object. This is optional, really -- we could also just pass
// the namespace hash as the final argument to naCall(). But
// having the global namespace in an outer scope means that we
// won't be polluting it with the local variables of the script.
code = naBindFunction(ctx, code, namespace);
// Build the arg vector
args = malloc(sizeof(naRef) * (argc-2));
for(i=0; i<argc-2; i++)
args[i] = NASTR(argv[i+2]);
// Run it.
result = naCall(ctx, code, argc-2, args, naNil(), naNil());
free(args);
checkError(ctx);
return 0;
}
#undef NASTR