FlightGear next
nasal-bin.cxx
Go to the documentation of this file.
1
2#include <cstdio>
3#include <cstring>
4#include <cstdlib>
5#include <sys/types.h>
6#include <sys/stat.h>
7
8#ifdef _WIN32
9#include <windows.h>
10#else
11#include <unistd.h>
12#include <pthread.h>
13#endif
14
15#include <simgear/nasal/nasal.h>
16#include <simgear/io/sg_mmap.hxx>
17#include <simgear/misc/sg_path.hxx>
18
19#define HAVE_SQLITE 1
20
21using namespace std;
22
23void checkError(naContext ctx)
24{
25 int i;
26 if(naGetError(ctx)) {
27 fprintf(stderr, "Runtime error: %s\n at %s, line %d\n",
28 naGetError(ctx), naStr_data(naGetSourceFile(ctx, 0)),
29 naGetLine(ctx, 0));
30
31 for(i=1; i<naStackDepth(ctx); i++)
32 fprintf(stderr, " called from: %s, line %d\n",
33 naStr_data(naGetSourceFile(ctx, i)),
34 naGetLine(ctx, i));
35 exit(1);
36 }
37}
38
39// A Nasal extension function (prints its argument list to stdout)
40static naRef print(naContext c, naRef me, int argc, naRef* args)
41{
42 int i;
43 for(i=0; i<argc; i++) {
44 naRef s = naStringValue(c, args[i]);
45 if(naIsNil(s)) continue;
46 fwrite(naStr_data(s), 1, naStr_len(s), stdout);
47 }
48 return naNil();
49}
50
51static void initAllowedPaths()
52{
53 SGPath::clearListOfAllowedPaths(false); // clear list of read-allowed paths
54 SGPath::clearListOfAllowedPaths(true); // clear list of write-allowed paths
55
56 // Allow reading and writing anywhere
57 SGPath::addAllowedPathPattern("*", false); // read operations
58 SGPath::addAllowedPathPattern("*", true); // write operations
59}
60
61#define NASTR(s) naStr_fromdata(naNewString(ctx), (s), strlen((s)))
62int main(int argc, char** argv)
63{
64 naRef *args, code, nasal, result;
65 struct Context *ctx;
66 int fsize, errLine, i;
67 char *buf;
68
69 if(argc < 2) {
70 fprintf(stderr, "nasal: must specify a script to run\n");
71 exit(1);
72 }
73
74 initAllowedPaths(); // for SGPath::validate()
75
76 // MMap the contents of the file.
77 SGPath script(argv[1]);
78 SGMMapFile f(script);
79 f.open(SG_IO_IN);
80 buf = (char*)f.get();
81 fsize= f.get_size();
82
83 // Create an interpreter context
84 ctx = naNewContext();
85
86 // Parse the code in the buffer. The line of a fatal parse error
87 // is returned via the pointer.
88 code = naParseCode(ctx, NASTR(script.c_str()), 1, buf, fsize, &errLine);
89 if(naIsNil(code)) {
90 fprintf(stderr, "Parse error: %s at line %d\n",
91 naGetError(ctx), errLine);
92 exit(1);
93 }
94 f.close();
95
96 // Make a hash containing the standard library functions. This
97 // will be the namespace for a new script
98 nasal = naInit_std(ctx);
99
100 // Add application-specific functions (in this case, "print" and
101 // the math library) to the nasal if desired.
102 naAddSym(ctx, nasal, (char*)"print", naNewFunc(ctx, naNewCCode(ctx, print)));
103
104 // Add extra libraries as needed.
105 naAddSym(ctx, nasal, (char*)"utf8", naInit_utf8(ctx));
106 naAddSym(ctx, nasal, (char*)"math", naInit_math(ctx));
107 naAddSym(ctx, nasal, (char*)"bits", naInit_bits(ctx));
108 naAddSym(ctx, nasal, (char*)"io", naInit_io(ctx));
109#ifndef _WIN32
110 naAddSym(ctx, nasal, (char*)"unix", naInit_unix(ctx));
111#endif
112 naAddSym(ctx, nasal, (char*)"thread", naInit_thread(ctx));
113#ifdef HAVE_PCRE
114 naAddSym(ctx, nasal, (char*)"regex", naInit_regex(ctx));
115#endif
116#ifdef HAVE_SQLITE
117 naAddSym(ctx, nasal, (char*)"sqlite", naInit_sqlite(ctx));
118#endif
119#ifdef HAVE_READLINE
120 naAddSym(ctx, nasal, (char*)"readline", naInit_readline(ctx));
121#endif
122#ifdef HAVE_GTK
123 // Gtk goes in as "_gtk" -- there is a higher level wrapper module
124 naAddSym(ctx, nasal, (char*)"_gtk", naInit_gtk(ctx));
125 naAddSym(ctx, nasal, (char*)"cairo", naInit_cairo(ctx));
126#endif
127
128 // Bind the "code" object from naParseCode into a "function"
129 // object. This is optional, really -- we could also just pass
130 // the nasal hash as the final argument to naCall(). But
131 // having the global nasal in an outer scope means that we
132 // won't be polluting it with the local variables of the script.
133 code = naBindFunction(ctx, code, nasal);
134
135 // Build the arg vector
136 args = (naRef*)malloc(sizeof(naRef) * (argc-2));
137 for(i=0; i<argc-2; i++)
138 args[i] = NASTR(argv[i+2]);
139
140 // Run it.
141 result = naCall(ctx, code, argc-2, args, naNil(), naNil());
142 (void)result; // surpeess a compiler waring;
143 free(args);
144
145#if 0
146 // Test for naContinue() feature. Keep trying until it reports
147 // success.
148 while(naGetError(ctx)) {
149 printf("Err: \"%s\", calling naContinue()...\n", naGetError(ctx));
150 naContinue(ctx);
151 }
152#endif
153
154 checkError(ctx);
155 return 0;
156}
157#undef NASTR
#define i(x)
int main()
#define NASTR(s)
Definition nasal-bin.cxx:61
static void initAllowedPaths()
Definition nasal-bin.cxx:51
static naRef print(naContext c, naRef me, int argc, naRef *args)
Definition nasal-bin.cxx:40
void checkError(naContext ctx)
Definition nasal-bin.cxx:23
naRef naInit_sqlite(naContext c)