/
Sapphire/bin/
Sapphire/db/
Sapphire/db/OLC_rooms/
Sapphire/db/abi/
Sapphire/db/em_src/
Sapphire/db/helps/
Sapphire/db/helps/emman/ifunc/
Sapphire/db/npcs/Tatt/
Sapphire/db/objects/Tatt/
Sapphire/db/q_data/
Sapphire/db/rooms/Tatt/
Sapphire/doc/
Sapphire/doc/em/
Sapphire/etc/
Sapphire/src/abic/
Sapphire/src/areacon/
Sapphire/src/client/
Sapphire/src/embc/
Sapphire/src/emi/
Sapphire/src/emi/test/
Sapphire/src/include/
Sapphire/src/sapphire/em/
Sapphire/src/tcon/
/*
 * Copyright (C) 1995-1997 Christopher D. Granz
 *
 * This header may not be removed.
 *
 * Refer to the file "License" included in this package for further
 * information and before using any of the following.
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>

#include "emi.h"


/*
 * Globals
 */
extern EM_VALUE *                                                pStack;
extern EM_VALUE *                                             pStackEnd;
extern EM_VALUE *                                       pInterpStackPos;
extern EM_VALUE *                                        pVarStackBegin;
extern EM_VALUE *                                          pVarStackPos;


/*
 * Tables
 */
const struct em_extern_func_type                      emefCFuncTable[] =
{
#if 0
    { _lalloc,                  "lalloc",
      2,  { TYPE_INT, TYPE_INT },
      1,  { TYPE_ARRAY }                                   },
#endif
    { _lnullobj,                "lnullobj",
      1,  { TYPE_OBJECT },
      1,  { TYPE_INT }                                     },

    { _lobjtype,                "lobjtype",
      1,  { TYPE_OBJECT },
      1,  { TYPE_INT }                                     },

    { _lvstacksize,             "lvstacksize",
      0,  { },
      1,  { TYPE_INT }                                     },

    { _listacksize,             "listacksize",
      0,  { },
      1,  { TYPE_INT }                                     },

    { _lnumbfuncargs,           "lnumbfuncargs",
      1,  { TYPE_INT },
      1,  { TYPE_INT }                                     },

    { _lnumfuncargs,            "lnumfuncargs",
      1,  { TYPE_INT },
      1,  { TYPE_INT }                                     },

    { _lcoredump,               "lcoredump",
      0,  { },
      1,  { TYPE_INT }                                     },

    { _lopentfile,              "lopentfile",
      1,  { TYPE_STRING },
      1,  { TYPE_OBJECT }                                  },

    { _lclosefile,              "lclosefile",
      1,  { TYPE_OBJECT },
      1,  { TYPE_INT }                                     },

    { _lout,                    "out",
      1,  { TYPE_STRING },
      0,  { }                                              },

    { NULL,                     NULL,
      0,  { },
      0,  { }                                              }
};


/*
 * Functions
 */

/*
 * Utility used by almost all the builtin functions.  Gets a number of
 * values off the interpreter stack.
 */
#define p                                        ( pInterpStackPos - i )

void em_get_values( long lArgC, ... )
{
    va_list vlArgs;
    int i;

    VA_START( vlArgs, lArgC );

    for ( i = 1; i <= lArgC; i++ )
    {
        switch ( VA_ARG( vlArgs, long ) )
        {
          case 0          :
              *VA_ARG( vlArgs, EM_VALUE ** )  = p;
              break;

          case TYPE_INT   :
              *VA_ARG( vlArgs, long * )       = p->u.lInt;
              break;

          case TYPE_FLOAT :
              *VA_ARG( vlArgs, double * )     = p->u.dFloat;
              break;

          case TYPE_STRING:
              *VA_ARG( vlArgs, char ** )      = p->u.pString->pString;
              break;

          case TYPE_OBJECT:
              *VA_ARG( vlArgs, EM_OBJECT ** ) = p->u.pObject;
              break;
        }
    }

    interp_stack_pop( lArgC );
    VA_END( vlArgs );
}

#undef p


/*
 * int lnullobj( object o );
 *
 * Standard langauge function.
 *
 *
 * Returns 1 the object o is null, otherwise 0 is returned.
 */
void _lnullobj( void )
{
    EM_VALUE v;
    EM_OBJECT *pParam1;

    em_get_values( 1, TYPE_OBJECT, &pParam1 );
    v.iType       = TYPE_INT;
    v.u.lInt      = ( pParam1->pRealObject == NULL ? 1L : 0L );
    interp_stack_push( &v );
}


/*
 * int lobjtype( object o );
 *
 * Standard langauge function.
 *
 *
 * Returns the type of the object o, as an integer.  Will return 0 if
 * o is null.
 */
void _lobjtype( void )
{
    EM_VALUE v;
    EM_OBJECT *pParam1;

    em_get_values( 1, TYPE_OBJECT, &pParam1 );
    v.iType      = TYPE_INT;

    if ( pParam1->pRealObject == NULL )
        v.u.lInt = 0L;
    else
        v.u.lInt = pParam1->iObjectType;

    interp_stack_push( &v );
}


/*
 * int lvstacksize( );
 *
 * Standard langauge function.
 *
 *
 * Returns the maximum possible size of the variable stack.
 */
void _lvstacksize( void )
{
    EM_VALUE v;

    v.iType  = TYPE_INT;
    v.u.lInt = iVarStackSize;
    interp_stack_push( &v );
}


/*
 * int listacksize( );
 *
 * Standard langauge function.
 *
 *
 * Returns the maximum possible size of the interpreter stack.
 */
void _listacksize( void )
{
    EM_VALUE v;

    v.iType  = TYPE_INT;
    v.u.lInt = iInterpStackSize;
    interp_stack_push( &v );
}


/*
 * int lnumbfuncargs( int i );
 *
 * Standard langauge function.
 *
 *
 * Returns the number of arguments the builtin function referenced
 * by i expects.
 */
void _lnumbfuncargs( void )
{
    EM_VALUE v;
    int i;
    long lParam1;

    em_get_values( 1, TYPE_INT, &lParam1 );
    v.iType      = TYPE_INT;

    for ( i = 0; emefCFuncTable[i].pName != NULL; i++ );

    if ( lParam1 < 0 || lParam1 >= i )
        v.u.lInt = -1L;
    else
        v.u.lInt = emefCFuncTable[lParam1].iNumArgs;

    interp_stack_push( &v );
}


/*
 * int lnumfuncargs( int i );
 *
 * Standard langauge function.
 *
 *
 * Returns the number of arguments the user function referenced by
 * i expects.
 */
void _lnumfuncargs( void )
{
    EM_VALUE v;
    long lParam1;

    em_get_values( 1, TYPE_INT, &lParam1 );
    v.iType      = TYPE_INT;

    if ( lParam1 < 0 || lParam1 > siTopFuncIndex )
        v.u.lInt = -1L;
    else
        v.u.lInt = ppFuncs[lParam1]->iNumArgs;

    interp_stack_push( &v );
}


/*
 * int lcoredump( );
 *
 * Standard langauge function.
 *
 *
 * Attemps to create a core image from the current process.  Returns
 * 1 if successful, otherwise 0 is returned.
 */
void _lcoredump( void )
{
    EM_VALUE v;
    pid_t pPid;
    int iError = 1;

    if ( ( pPid = fork( ) ) < 0 )
    {
        iError = 0;
        goto end;
    }

    if ( pPid == 0 )
        abort( );

end:
    v.iType    = TYPE_INT;
    v.u.lInt   = iError;
    interp_stack_push( &v );
}


/*
 * object lopentfile( string sFilename );
 *
 * Standard langauge function.
 *
 *
 * Attemps to open the file sFilename in text mode.  Returns a file
 * object if successful, otherwise a null object is returned.
 */
void _lopentfile( void )
{
    EM_VALUE v;
    char *pParam1;

    em_get_values( 1, TYPE_STRING, &pParam1 );
    v.iType                  = TYPE_OBJECT;
    init_value( &v );
    v.u.pObject->iObjectType = OBJ_TYPE_FILE;
    v.u.pObject->pRealObject = fopen( pParam1, "a+" );
    interp_stack_push( &v );
}


/*
 * int lclosefile( object oFile );
 *
 * Standard langauge function.
 *
 *
 * Closes a file opened by lopentfile() or lopenbfile().  Returns 0 if
 * successful, otherwise -1 is returned.
 */
void _lclosefile( void )
{
    EM_VALUE v;
    EM_OBJECT *pParam1;

    em_get_values( 1, TYPE_OBJECT, &pParam1 );
    v.iType      = TYPE_INT;

    if ( pParam1->iObjectType != OBJ_TYPE_FILE
      || pParam1->pRealObject == NULL )
        v.u.lInt = -1;
    else
        v.u.lInt = ( fclose( pParam1->pRealObject ) < 0 ? -1 : 0 );

    interp_stack_push( &v );
}


/*
 * Temp.
 */
void _lout( void )
{
    char *pParam1;

    em_get_values( 1, TYPE_STRING, &pParam1 );
    printf( "%s", pParam1 );
}


/*
 * End of builtin.c
 */