int main(int argc,char *argv[])
{
  extern int amx_ConsoleInit(AMX *amx);
  extern int amx_ConsoleCleanup(AMX *amx);
  extern int amx_CoreInit(AMX *amx);
  extern int amx_CoredCleanp(AMX *amx);

  size_t memsize;
  void *program;
  AMX amx;
  int index, err;
  cell amx_addr, *phys_addr;
  char output[128];

  if (argc != 4)
    PrintUsage(argv[0]);
  if ((memsize = aux_ProgramSize(argv[1])) == 0)
    PrintUsage(argv[0]);

  program = malloc(memsize);
  if (program == NULL)
    ErrorExit(NULL, AMX_ERR_MEMORY);

  err = aux_LoadProgram(&amx, argv[1], program);
  if (err)
    ErrorExit(&amx, err);

  amx_ConsoleInit(amx);
  err = amx_CoreInit(amx);
  if (err)
    ErrorExit(&amx, err);

  err = amx_FindPublic(&amx, argv[2], &index);
  if (err)
    ErrorExit(&amx, err);

  err = amx_Allot(&amx, strlen(argv[3]) + 1, &amx_addr, &phys_addr);
  if (err)
    ErrorExit(&amx, err);
  amx_SetString(phys_addr, argv[3], 0);

  err = amx_Exec(&amx, NULL, index, 1, amx_addr);
  if (err)
    ErrorExit(&amx, err);

  amx_GetString(output, phys_addr);
  amx_Release(&amx, amx_addr);
  printf("%s returns %s\n", argv[1], output);

  amx_ConsoleCleanup(&amx);
  amx_CoreCleanup(&amx);
  amx_Cleanup(&amx);
  free(program);
  return 0;
}
Example #2
0
int initialize_pawn_machine (pawn_machine *machine, const char* fname)
{
	int err;
	size_t memsize;
	void* buffer;

	machine->initialized = 0;

	memsize = aux_ProgramSize (fname);
	if (memsize == 0)
	{
		log_error ("Unable to determine memory size for Pawn file %s", fname);
		return 0;
	}

	buffer = malloc (memsize);
	if (buffer == NULL)
	{
		log_error ("unable to allocate memory for Pawn file %s", fname);
		return 0;
	}

	err = aux_LoadProgram (&(machine->amx), fname, buffer);
	if (err != AMX_ERR_NONE)
	{
		free (buffer);
		log_error ("unable to load Pawn file %s", fname);
		return 0;
	}

	// The amx_*Init functions return an error when not all natives
	// used in the amx script are defined, so we only need to check
	// the last Init (when we have defined our entire library).
	amx_ConsoleInit (&(machine->amx));
	amx_FloatInit (&(machine->amx));
	amx_StringInit (&(machine->amx));
	err = amx_ElInit (&(machine->amx));
	if (err != AMX_ERR_NONE)
	{
		free (buffer);
		log_error ("Unable to initialize all native functions for Pawn file %s", fname);
		return 0;
	}

	machine->buf_size = memsize;
	machine->buffer = buffer;
	machine->initialized = 1;

	return 1;
}
Example #3
0
int main(int argc,char *argv[])
{
  AMX amx;
  cell ret = 0;
  int err;
  clock_t start,end;

  if (argc != 2)
    PrintUsage(argv[0]);        /* function "usage" aborts the program */

  if ((err = aux_LoadProgram(&amx, argv[1])) == AMX_ERR_NOTFOUND) {
    /* try adding an extension */
    char filename[_MAX_PATH];
    strcpy(filename, argv[1]);
    strcat(filename, ".amx");
    err = aux_LoadProgram(&amx, filename);
  } /* if */
  ExitOnError(&amx, err);

  amx_ConsoleInit(&amx);
  err = amx_CoreInit(&amx);
  ExitOnError(&amx, err);

  start=clock();
  err = amx_Exec(&amx, &ret, AMX_EXEC_MAIN);
  while (err == AMX_ERR_SLEEP)
    err = amx_Exec(&amx, &ret, AMX_EXEC_CONT);
  end=clock();
  ExitOnError(&amx, err);

  aux_FreeProgram(&amx);

  if (ret!=0)
    printf("\nReturn value: %ld\n", (long)ret);

  printf("\nRun time:     %.2f seconds\n",(double)(end-start)/CLOCKS_PER_SEC);

  return 0;
}
Example #4
0
int main(int argc,char *argv[])
{
  AMX amx;
  cell ret = 0;
  int err, i;
  clock_t start,end;
  STACKINFO stackinfo = { 0 };
  AMX_IDLE idlefunc;

  if (argc < 2)
    PrintUsage(argv[0]);        /* function "usage" aborts the program */

  #if !defined AMX_NODYNALOAD && defined ENABLE_BINRELOC && (defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__)
    /* see www.autopackage.org for the BinReloc module */
    if (br_init(NULL)) {
      char *libroot=br_find_exe_dir("");
      setenv("AMXLIB",libroot,0);
      free(libroot);
    } /* if */
  #endif

  /* Load the program and initialize the abstract machine. */
  err = aux_LoadProgram(&amx, argv[1]);
  if (err != AMX_ERR_NONE) {
    /* try adding an extension */
    char filename[_MAX_PATH];
    strcpy(filename, argv[1]);
    strcat(filename, ".amx");
    err = aux_LoadProgram(&amx, filename);
    if (err != AMX_ERR_NONE)
      PrintUsage(argv[0]);
  } /* if */

  /* To install the debug hook "just-in-time", the signal function needs
   * a pointer to the abstract machine(s) to abort. There are various ways
   * to implement this; here I have done so with a simple global variable.
   */
  global_amx = &amx;
  signal(SIGINT, sigabort);

  /* Initialize two core extension modules (more extension modules may be
   * loaded & initialized automatically as DLLs or shared libraries.
   */
  amx_ConsoleInit(&amx);
  err = amx_CoreInit(&amx);
  ExitOnError(&amx, err);

  /* save the idle function, if set by any of the extension modules */
  if (amx_GetUserData(&amx, AMX_USERTAG('I','d','l','e'), (void**)&idlefunc) != AMX_ERR_NONE)
    idlefunc = NULL;

  for (i = 2; i < argc; i++) {
    if (strcmp(argv[i],"-stack") == 0) {
      uint16_t flags;
      amx_Flags(&amx, &flags);
      if ((flags & AMX_FLAG_NOCHECKS) != 0)
        printf("This script was compiled with debug information removed.\n"
               "Stack monitoring is disfunctional\n\n");
      /* Set "user data" with which the debug monitor can monitor stack usage
       * per abstract machine (in this example, though, there is only one abstract
       * machine, so a global variable would have sufficed).
       */
      memset(&stackinfo, 0, sizeof stackinfo);
      err = amx_SetUserData(&amx, AMX_USERTAG('S','t','c','k'), &stackinfo);
      ExitOnError(&amx, err);
      /* Install the debug hook, so that we can start monitoring the stack/heap
       * usage right from the beginning of the script.
       */
      amx_SetDebugHook(&amx, prun_Monitor);
    } /* if */
  } /* for */

  start=clock();

  /* Run the compiled script and time it. The "sleep" instruction causes the
   * abstract machine to return in a "restartable" state (it restarts from
   * the point that it stopped. This allows for a kind of light-weight
   * cooperative multi-tasking. As native functions (or the debug hook) can
   * also force an abstract machine to "sleep", you can also use it to create
   * "latent functions": functions that allow the host application to continue
   * processing, and/or other abstract machines to run, while they wait for
   * some resource.
   */
  err = amx_Exec(&amx, &ret, AMX_EXEC_MAIN);
  while (err == AMX_ERR_SLEEP) {
    if (idlefunc != NULL) {
      /* If the abstract machine was put to sleep, we can handle events during
       * that time. To save the "restart point", we must make a copy of the AMX
       * (keeping the stack, frame, instruction pointer and other vital
       * registers), but without cloning the entire abstract machine.
       * There should be some criterion on when the abstract machine must be
       * "woken up". In this example run-time, the parameter of the sleep
       * instruction is taken to be a delay in milliseconds. In your own host
       * application, you can choose to wait on a resource/semaphore or other.
       */
      AMX nested_amx = amx;
      clock_t stamp = clock();
      while (((clock() - stamp)*1000)/CLOCKS_PER_SEC < amx.pri
             && (err = idlefunc(&nested_amx,amx_Exec)) == AMX_ERR_NONE)
        /* nothing */;
      ExitOnError(&nested_amx, err);
    } /* if */
    err = amx_Exec(&amx, &ret, AMX_EXEC_CONT);
  } /* while */
  if (idlefunc == NULL || err != AMX_ERR_INDEX)
    ExitOnError(&amx, err);     /* event-driven programs may not have main() */

  /* For event-driven programs, we also need to loop over the idle/monitor
   * function that some extension module installed (this could be the console
   * module, for example). We did this if the main program was put to "sleep",
   * but we do that here too.
   */
  if (idlefunc != NULL) {
    while ((err = idlefunc(&amx,amx_Exec)) == AMX_ERR_NONE)
      /* nothing */;
    ExitOnError(&amx, err);
  } /* if */

  end=clock();

  /* Free the compiled script and resources. This also unloads and DLLs or
   * shared libraries that were registered automatically by amx_Init().
   */
  aux_FreeProgram(&amx);

  /* Print the return code of the compiled script (often not very useful),
   * its run time, and its stack usage.
   */
  if (ret!=0)
    printf("\nReturn value: %ld\n", (long)ret);

  printf("\nRun time:     %.2f seconds\n",(double)(end-start)/CLOCKS_PER_SEC);
  if (stackinfo.maxstack != 0 || stackinfo.maxheap != 0) {
    printf("Stack usage:  %ld cells (%ld bytes)\n",
           stackinfo.maxstack / sizeof(cell), stackinfo.maxstack);
    printf("Heap usage:   %ld cells (%ld bytes)\n",
           stackinfo.maxheap / sizeof(cell), stackinfo.maxheap);
  } /* if */

  #if defined AMX_TERMINAL
    /* This is likely a graphical terminal, which should not be closed
     * automatically
     */
    {
      extern int amx_termctl(int,int);
      while (amx_termctl(4,0))
        /* nothing */;
    }
  #endif

  return 0;
}
Example #5
0
int main(int argc,char *argv[])
{
  AMX amx;
  cell ret = 0;
  int err;

  if (argc != 2)
    PrintUsage(argv[0]);        /* function "usage" aborts the program */

  /* Load the program and initialize the abstract machine. */
  err = aux_LoadProgram(&amx, argv[1], NULL, srun_Monitor);
  if (err != AMX_ERR_NONE) {
    /* try adding an extension */
    char filename[_MAX_PATH];
    strcpy(filename, argv[1]);
    strcat(filename, ".amx");
    err = aux_LoadProgram(&amx, filename, NULL, srun_Monitor);
    if (err != AMX_ERR_NONE)
      PrintUsage(argv[0]);
  } /* if */

  /* Initialize two core extension modules (more extension modules may be
   * loaded & initialized automatically as DLLs or shared libraries.
   */
  amx_ConsoleInit(&amx);
  amx_CoreInit(&amx);
  /* register functions for the bstring library */
  err = amx_Register(&amx, bstring_Natives, -1);
  ExitOnError(&amx, err);

  /* Initialize the garbage collector, start with a small table. */
  gc_setcallback((GC_FREE)bdestroy);
  err = gc_settable(7, GC_AUTOGROW);
  ExitOnError(&amx, err);

  /* Run the compiled script and time it. The "sleep" instruction causes the
   * abstract machine to return in a "restartable" state (it restarts from
   * the point that it stopped. This enables for a kind of light-weight
   * cooperative multi-tasking. As native functions (or the debug hook) can
   * also force an abstract machine to "sleep", you can also use it to create
   * "latent functions": functions that allow the host application to continue
   * processing, and/or other abstract machines to run, while they wait for
   * some resource.
   * In this example, there are no other abstract machines (there is just one)
   * and this "host" program has nothing else to do than run the abstract
   * machine. So if it detects a "sleep" it just restarts the abstract machine
   * immediately.
   */
  err = amx_Exec(&amx, &ret, AMX_EXEC_MAIN, 0);
  while (err == AMX_ERR_SLEEP)
    err = amx_Exec(&amx, &ret, AMX_EXEC_CONT, 0);
  ExitOnError(&amx, err);

  /* Free the compiled script and resources. This also unloads and DLLs or
   * shared libraries that were registered automatically by amx_Init().
   */
  aux_FreeProgram(&amx);

  /* Free the garbarge collector data and tables. */
  gc_settable(0);

  /* Print the return code of the compiled script (often not very useful). */
  if (ret!=0)
    printf("\nReturn value: %ld\n", (long)ret);

  #if defined AMX_TERMINAL
    /* This is likely a graphical terminal, which should not be closed
     * automatically
     */
    {
      extern int amx_termctl(int,int);
      while (amx_termctl(4,0))
        /* nothing */;
    }
  #endif

  return 0;
}