Board index FlightGear Development Nasal

Compiling Nasal as standalone application

Nasal is the scripting language of FlightGear.

Compiling Nasal as standalone application

Postby xcvb » Thu Jul 27, 2017 8:32 pm

If you want to test your Nasal scripts without starting Flightgear this can be interesting for you. Don't expect too much since access to the property tree is missing.

  1. Get Nasal code from Simgear source folder
  2. Get nasal-bin.c from Nasal Github or use the one below
  3. 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
xcvb
 
Posts: 132
Joined: Sat Mar 14, 2015 3:08 pm
Version: Next
OS: Fedora Kinoite

Re: Compiling Nasal as standalone application

Postby bugman » Thu Jul 27, 2017 10:33 pm

Have you tried compiling the standalone scripting language?

Regards,
Edward
bugman
Moderator
 
Posts: 1808
Joined: Thu Mar 19, 2015 10:01 am
Version: next

Re: Compiling Nasal as standalone application

Postby xcvb » Thu Jul 27, 2017 11:03 pm

Yes, I tried it but the build scripts didn't work for me. Then I saw that there had been some improvements by the Flightgear devs so I used the simgear version.
xcvb
 
Posts: 132
Joined: Sat Mar 14, 2015 3:08 pm
Version: Next
OS: Fedora Kinoite

Re: Compiling Nasal as standalone application

Postby Hooray » Sun Aug 06, 2017 10:46 am

FYI, there is also the Nasal standalone interpreter based on the simgear code (its using cmake), it should also have SGPropertyNode bindings.

https://www.gitorious.org/fg/nasal-core ... one-sg-3.1

The original fgradar repository also included scripting bindings for other useful FG/SG subsystems: https://gitorious.org/fgradar/fgradar?p ... ;a=summary
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU


Return to Nasal

Who is online

Users browsing this forum: No registered users and 1 guest