示例#1
0
int AMXEXPORT AMXAPI amx_TimeInit(AMX *amx)
{
  #if !defined AMXTIME_NOIDLE
    /* see whether there is a @timer() function */
    if (amx_FindPublic(amx,"@timer",&idxTimer) == AMX_ERR_NONE) {
      if (amx_GetUserData(amx, AMX_USERTAG('I','d','l','e'), (void**)&PrevIdle) != AMX_ERR_NONE)
        PrevIdle = NULL;
      amx_SetUserData(amx, AMX_USERTAG('I','d','l','e'), (void*)amx_TimeIdle);
    } /* if */
  #endif

  return amx_Register(amx, time_Natives, -1);
}
示例#2
0
/* prun_Monitor()
 * A simple debug hook, that allows the user to break out of a program
 * and that monitors stack usage. Note that the stack usage can only be
 * properly monitored when the debug hook is installed from the start
 * of the script to the end.
 */
int AMXAPI prun_Monitor(AMX *amx)
{
  int err;
  STACKINFO *stackinfo;

  /* record the heap and stack usage */
  err = amx_GetUserData(amx, AMX_USERTAG('S','t','c','k'), (void**)&stackinfo);
  if (err == AMX_ERR_NONE) {
    if (amx->stp - amx->stk > stackinfo->maxstack)
      stackinfo->maxstack = amx->stp - amx->stk;
    if (amx->hea - amx->hlw > stackinfo->maxheap)
      stackinfo->maxstack = amx->stp - amx->stk;
  } /* if */

  /* check whether an "abort" was requested */
  return abortflagged ? AMX_ERR_EXIT : AMX_ERR_NONE;
}
示例#3
0
int AMXEXPORT AMXAPI amx_DGramInit(AMX *amx)
{
  dgramBound = 0;
  if (udp_Open()==-1)
    return AMX_ERR_GENERAL;

  /* see whether there is an @receivestring() function */
  if (amx_FindPublic(amx,"@receivestring",&idxReceiveString)==AMX_ERR_NONE
      || amx_FindPublic(amx,"@receivepacket",&idxReceivePacket)==AMX_ERR_NONE)
  {
    if (amx_GetUserData(amx,AMX_USERTAG('I','d','l','e'),(void**)&PrevIdle)!=AMX_ERR_NONE)
      PrevIdle=NULL;
    amx_SetUserData(amx,AMX_USERTAG('I','d','l','e'),amx_DGramIdle);
  } /* if */

  return amx_Register(amx,dgram_Natives,-1);
}
示例#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;
}