예제 #1
0
파일: pkg-odbc.c 프로젝트: Fuchur/ldmud
/************************************************************************* 
 * allocate_db_connection( ) . allocates a hDBC struct with the given ID                      
 * push_db_connection( ) ..... adds an allocated hDBC struct to the DB
 *                             connections 
 * pop_db_connection( ) ...... removes an allocated hDBC struct from  
 *                             the DB connections
 * get_db_connection_by_id( )  returns the requested handle and moves it on    
 *                             top of hODBCEnv->hDBCons                               
 * dispose_db_connection( ) .. disposes the passed connection         
 *************************************************************************/
static hDBC *
allocate_db_connection( int ID )
{
   hDBC      * handle;

   if ( !ID )
      return( NULL );

   handle = pxalloc( sizeof( hDBC ) );
   MEM_CHECK( handle );
   
   handle->ID = ID;
   
   handle->name    = NULL;
   
   handle->prev    = NULL;
   handle->next    = NULL;

   handle->hDBCon  = NULL;
   handle->hStmt   = NULL;

   handle->colcnt  = 0;
   handle->rowcnt  = 0;
   handle->columns = NULL;

   return( handle );
}
예제 #2
0
파일: pkg-odbc.c 프로젝트: Fuchur/ldmud
/*************************************************************************
 * extracts the dignosticinfo of an handle.
 *************************************************************************/
static char *
extract_diagnostics_info( SQLSMALLINT type, SQLHANDLE handle )
{
   char       ** tmp;
   char       * ret;
   int        i,
              j = 0;

   SQLINTEGER recnum;
   
   SQLGetDiagField( type, handle, 0, SQL_DIAG_NUMBER, &recnum, SQL_IS_INTEGER, 0 );

   if ( !recnum )
      return( NULL );

   tmp = pxalloc( recnum * sizeof( tmp ) );

   SQLCHAR     state[ 7 ];
   SQLINTEGER  native;
   SQLCHAR     text[1000],
               buffer[1000];
   SQLSMALLINT len;

  for ( i = 0; i < recnum; i++ ) {
      SQLGetDiagRec( type, handle, i+1, state, &native, text, sizeof( text ), &len );
      sprintf( buffer, "[%5s]%s\n", state, text );
      tmp[ i ] = string_copy( buffer );
      j += strlen( tmp[ i ] );
   }
   
   ret = pxalloc( (j + 1) * sizeof( char ) );
   for ( i = 0; i < recnum; i++ ) {
      if( i ) {
         strcat( ret, tmp[ i ] );
      } else {
         strcpy( ret, tmp[ i ] );
      }
      pfree( tmp[ i ] );
   }
   
   pfree( tmp );

   return( ret );
}
예제 #3
0
파일: pkg-odbc.c 프로젝트: Fuchur/ldmud
static mapping_t * 
fetch_into_mapping( hDBC * handle )
{
   int       i;

   mapping_t  * map;   
   svalue_t  * key,
             * value;

   STORE_DOUBLE_USED;

   map = allocate_mapping( handle->colcnt, 1 );
   MEM_CHECK( map );
         
   for( i = 0; i < handle->colcnt; ++i ) {
      if ( !handle->columns[ i ] ) continue;

      //printf( " fetch_into_mapping[%2d] ", i );
      
      key = pxalloc( sizeof( svalue_t ) ); 
      MEM_CHECK( key );
         
      put_malloced_string( key, string_copy( handle->columns[ i ]->name ) );
         
      value = get_map_lvalue( map, key );
      MEM_CHECK( value );

      switch( handle->columns[ i ]->type ){
         case T_FLOAT:
            //printf( "float=%f\n",  handle->columns[ i ]->data.double_v );
            STORE_DOUBLE( value, *handle->columns[ i ]->data.double_v );

            value->type = T_FLOAT;
            break; 

         case T_NUMBER:
            //printf( "number=%d\n",  *handle->columns[ i ]->data.number_v );
            put_number( value, *handle->columns[ i ]->data.number_v );
            break;

         case T_STRING: 
         default      :
            //printf( "string=%s\n",  handle->columns[ i ]->data.string_v );
            put_malloced_string( value, string_copy(  handle->columns[ i ]->data.string_v ) );
            break;
      }
   }

   return( map );
}
예제 #4
0
파일: pkg-odbc.c 프로젝트: Fuchur/ldmud
/************************************************************************* 
 * allocate_column_meta_data( ) . allocates a COL_META_DATA struct          
 * dispose_column_meta_data( ) .. disposes a COL_META_DATA struct           
 *************************************************************************/
static COL_META_DATA *
allocate_column_meta_data( void )
{
   COL_META_DATA * column;

   column = pxalloc( sizeof( COL_META_DATA ) );
   MEM_CHECK( column ); 
 
   column->nr            = 0;
   column->name          = NULL;

   column->type          = 0;

   column->data.number_v = NULL;
   column->data.double_v = NULL;
   column->data.string_v = NULL;
   
   return( column );
}
예제 #5
0
파일: pkg-odbc.c 프로젝트: Fuchur/ldmud
static char *
init_odbc_environment( void )
{
#if ODBC_DEBUG & DEBUG_FUNC
   printf( "call init_odbc_environment( )\n" );
#endif
   SQLRETURN ret;
   
   if ( hODBCEnv ) // already initialized 
      return( NULL );

   hODBCEnv = pxalloc( sizeof( hODBCENV ) );
   MEM_CHECK( hODBCEnv );

   ret = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(hODBCEnv->hODBCEnv) );
   if ( !SQL_SUCCEEDED( ret ) ) {
      
      destruct_odbc_environment();
      
      return( "Allocation of ODBC Environment failed.\n" );
   }

   ret = SQLSetEnvAttr( hODBCEnv->hODBCEnv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0 );
   if ( !SQL_SUCCEEDED( ret ) ) {
      
      destruct_odbc_environment();
      
      return( "Could not set ODBC Environment Attributes.\n" );
   }

   
   hODBCEnv->next_hDBCon_ID = 1;
   hODBCEnv->hDBCons        = NULL;
   
#if ODBC_DEBUG & DEBUG_FUNC
   printf( "return init_odbc_environment( )\n" );
#endif
   return( NULL );
}
예제 #6
0
파일: pkg-sqlite.c 프로젝트: Fuchur/ldmud
/*-------------------------------------------------------------------------*/
static sqlite_dbs_t *
new_db()

/* Create a new database entry, link it into the global list, and return it.
 * On out of memory, return NULL.
 */

{
    sqlite_dbs_t *tmp;
    tmp = pxalloc (sizeof (*tmp));
    if (!tmp)
        return NULL;
   
    tmp->db = NULL;
    tmp->obj = NULL;
    tmp->next = NULL;
    tmp->prev = head;
    if (head)
        head->next=tmp;
    head=tmp;
   
    return tmp;
} /* new_db() */
예제 #7
0
파일: pkg-odbc.c 프로젝트: Fuchur/ldmud
/************************************************************************* 
 * f_sql_exec( int handle, string statement )
 *
 * executes an SQL statement
 *************************************************************************/
svalue_t *
f_sql_exec( svalue_t * argv, int argc )
{
#if ODBC_DEBUG & DEBUG_FUNC
   printf( "call f_sql_exec( )\n" );
#endif

   int         id, i;
   SQLCHAR     * statement;
   hDBC        * handle;

   //SQLSMALLINT cols;
   SQLRETURN   ret;

   TYPE_TEST2( argv, T_STRING );
   statement = string_copy( argv->u.string );
   free_string_svalue( argv );
   argv--;
   
   TYPE_TEST1( argv, T_NUMBER );
   id = argv->u.number;
   free_svalue( argv );

   if ( !(handle = get_db_connection_by_id( id )) ) {
      pfree( statement );
      errorf( "Illegal handle for database.\n" );
      return( NULL );
   }

   if ( handle->hStmt ) {
      //printf( "freeing statement\n" );
      ret = SQLFreeStmt( handle->hStmt, SQL_UNBIND );
      if ( !SQL_SUCCEEDED( ret ) ) {
          //printf( "SQLFreeStmt( handle->hStmt, SQL_UNBIND ) = %d\n", ret );
          pfree( statement );
          errorf( extract_diagnostics_info( SQL_HANDLE_STMT, handle->hStmt ) );
          return( NULL );
      }
      ret = SQLFreeHandle( SQL_HANDLE_STMT, handle->hStmt );
      if ( !SQL_SUCCEEDED( ret ) ) {
          //printf( "SQLFreeHandle( SQL_HANDLE_STMT, handle->hStmt ) = %d\n", ret );
          pfree( statement );
          errorf( extract_diagnostics_info( SQL_HANDLE_STMT, handle->hStmt ) );
          return( NULL );
      }
   }
   
   if ( handle->columns ) {
      for ( i = 0; i < handle->colcnt; ++i ) {
         dispose_column_meta_data( handle->columns[ i ] );
      }

      pfree( handle->columns );
      handle->columns = NULL;
   }

   //printf( "allocating statement \n" );
   ret = SQLAllocHandle( SQL_HANDLE_STMT, handle->hDBCon, &handle->hStmt );
   if ( !SQL_SUCCEEDED( ret ) ) {
      pfree( statement );
      errorf( extract_diagnostics_info( SQL_HANDLE_DBC, handle->hDBCon ) );

      return( NULL );
   }

   handle->colcnt = 0;
   handle->rowcnt = 0;
   
//   printf( "executing\n" );
   ret = SQLExecDirect( handle->hStmt, statement, SQL_NTS );
   pfree( statement );
   if ( !SQL_SUCCEEDED( ret ) ) {
      //printf( "XXX: %s\n", extract_diagnostics_info( SQL_HANDLE_STMT, handle->hStmt ) );
      put_number( argv, 0 );
      return( argv );
   }
/* getting number of columns. */
   //ret = SQLNumResultCols( handle->hStmt, &cols );
   ret = SQLNumResultCols( handle->hStmt, &handle->colcnt );
   if ( !SQL_SUCCEEDED( ret ) ) {
      put_number( argv, 0 );
      return( argv );
   }
  
   ret = SQLRowCount( handle->hStmt, &handle->rowcnt ); 
   if ( !SQL_SUCCEEDED( ret ) ) {
      put_number( argv, 0 );
      return( argv );
   }
   
   //handle->colcnt  = cols;
   if ( handle->colcnt ) {
      handle->columns = pxalloc( handle->colcnt * sizeof( COL_META_DATA* ) );
      MEM_CHECK( handle->columns );
   }

/* fetching meta data */
   COL_META_DATA * tmp;
   SQLCHAR       dColname[ 100 ];
   SQLSMALLINT   dColnameLen;
   SQLSMALLINT   dType;
   SQLSMALLINT   dDDigits;
   SQLSMALLINT   dNullable;
   SQLUINTEGER   dColSize;
   
   for ( i = 1; i <= handle->colcnt; ++i ) {
      ret = SQLDescribeCol( handle->hStmt, i, dColname, sizeof( dColname ), &dColnameLen, &dType, &dColSize, &dDDigits, &dNullable );
      if ( !SQL_SUCCEEDED( ret ) ) {
         put_number( argv, 0 );
         return( argv );
      }

      tmp = allocate_column_meta_data();
      MEM_CHECK( tmp );

      tmp->nr = i;
      tmp->name = string_copy( dColname );
      tmp->type = map_column_type( dType, dDDigits );

     // printf( "[%s] dColSize=%d dDDigits=%d\n", dColname, dColSize, dDDigits );

      SQLLEN len;
      switch( tmp->type ) {
         case T_NUMBER: 
            tmp->data.number_v = pxalloc( sizeof( SQL_C_LONG ) );
            *tmp->data.number_v = 0;
            SQLBindCol( handle->hStmt, i, SQL_C_LONG, tmp->data.number_v, 100, &len );
            break;

         case T_FLOAT:
            tmp->data.double_v = pxalloc( sizeof( SQL_C_DOUBLE ) );
            *tmp->data.double_v = 0;
            SQLBindCol( handle->hStmt, i, SQL_C_DOUBLE, tmp->data.double_v, 100, &len );
            break;

         default:
            tmp->data.string_v = pxalloc( (dColSize + 1) * sizeof( SQLCHAR ) );
            SQLBindCol( handle->hStmt, i, SQL_C_CHAR, tmp->data.string_v, (dColSize + 1), &len );
      }

      handle->columns[ i-1 ] = tmp;
   }
   
   put_number( argv, id );
#if ODBC_DEBUG & DEBUG_FUNC
   printf( "ret f_sql_exec( )\n" );
#endif
   return( argv );
}
예제 #8
0
파일: pkg-odbc.c 프로젝트: Fuchur/ldmud
/*************************************************************************
 * f_sql_odbc_datasources( void )
 *
 * returns a mapping of all defined datasources.
 * ([ name : description ])
 *************************************************************************/
svalue_t *
f_sql_odbc_datasources( svalue_t * argv, int argc )
{
#if ODBC_DEBUG & DEBUG_FUNC
   printf( "call f_sql_odbc_datasources( )\n" );
#endif
   SQLRETURN   ret;
   
   char        * err;
   
   char        dsName[ 256 ],
               dsDescription[ 256 ];
   SQLSMALLINT dsNameLen,
               dsDescriptionLen;
   
   mapping_t   * map;
   svalue_t    * key;
   svalue_t    * value;

   argv++;

   err = init_odbc_environment();
   if ( err ) {
      errorf( err );
      return( NULL );
   }
   
   map = allocate_mapping( 0, 1 );
   MEM_CHECK( map );
   
   do {
      ret = SQLDataSources( hODBCEnv->hODBCEnv, SQL_FETCH_NEXT, dsName, 256, &dsNameLen,
                                                                dsDescription, 256, &dsDescriptionLen );
      if ( SQL_SUCCEEDED( ret ) ) {
         key = pxalloc( sizeof( svalue_t ) );
         put_malloced_string( key, string_copy( dsName ) );

         value = get_map_lvalue( map, key ); 
         MEM_CHECK( value );

         put_malloced_string( value, string_copy( dsDescription ) );
      }
      
   } while( SQL_SUCCEEDED( ret ) );

   if ( ret != SQL_NO_DATA ) {
      char * err;
      err = extract_diagnostics_info( SQL_HANDLE_ENV, hODBCEnv->hODBCEnv );

      free_mapping( map );

      errorf( (err?err:"Failed to fetch datasource information.\n") );
      return( NULL );
   }

   put_mapping( argv, map );
   
#if ODBC_DEBUG & DEBUG_FUNC
   printf( "ret f_sql_odbc_datasources( )\n" );
#endif
   return( argv );
}
예제 #9
0
파일: pkg-sqlite.c 프로젝트: Fuchur/ldmud
/*-------------------------------------------------------------------------*/
svalue_t * 
v_sl_exec (svalue_t * sp, int num_arg) 

/* EFUN sl_exec()
 *
 *   mixed* sl_exec(string statement, ...)
 *
 * Executes the SQL statement <statement> for the current
 * SQLite database. The SQL statement may contain wildcards like
 * '?' and '?nnn', where 'nnn' is an integer. These wildcards
 * can be given as further parameters to sl_exec. With '?nnn'
 * the number of a specific parameter can be given, the first
 * parameter has number 1.
 * 
 * If the statement returns data, sl_exec returns an array
 * with each row (which is itself an array of columns) as 
 * an element.
 */

{
    svalue_t *argp;
    sqlite_dbs_t *db;
    sqlite3_stmt *stmt;
    const char* tail;
    int err, rows, cols, num;
    struct sl_exec_cleanup_s * rec_data;
    vector_t * result;

    argp = sp - num_arg + 1; /* First argument: the SQL query */
    
    db = find_db (current_object);
    if (!db)
        errorf("The current object doesn't have a database open.\n");
    
    err = sqlite3_prepare(db->db, get_txt(argp->u.str), mstrsize(argp->u.str),
        &stmt, &tail);
    if(err)
    {
        const char* msg = sqlite3_errmsg(db->db);
        if(stmt)
            sqlite3_finalize(stmt);
        errorf("sl_exec: %s\n", msg);
        /* NOTREACHED */
    }
    
    /* Now bind all parameters. */
    for(argp++, num=1; argp <= sp; argp++, num++)
    {
        switch(argp->type)
        {
        default:
            sqlite3_finalize(stmt);
            errorf("Bad argument %d to sl_exec(): type %s\n",
                num+1, typename(argp->type));
            break; /* NOTREACHED */

        case T_FLOAT:
            sqlite3_bind_double(stmt, num, READ_DOUBLE(argp));
            break;

        case T_NUMBER:
            if (sizeof(argp->u.number) > 4)
                sqlite3_bind_int64(stmt, num, argp->u.number);
            else
                sqlite3_bind_int(stmt, num, argp->u.number);
            break;
    
        case T_STRING:
            sqlite3_bind_text(stmt, num, get_txt(argp->u.str),
                mstrsize(argp->u.str), SQLITE_STATIC);
            break;
        }
    }
    
    rows = 0;
    cols = sqlite3_column_count(stmt);

    rec_data = xalloc(sizeof(*rec_data));
    if(!rec_data)
    {
        sqlite3_finalize(stmt);
        errorf("(sl_exec) Out of memory: (%lu bytes) for cleanup structure\n",
            (unsigned long) sizeof(*rec_data));
    }
    rec_data->rows = NULL;
    rec_data->stmt = stmt;
    
    sp = push_error_handler(sl_exec_cleanup, &(rec_data->head));
    
    while((err = sqlite3_step(stmt)) == SQLITE_ROW)
    {
        int col;
        sqlite_rows_t *this_row;

        rows++;
        this_row = pxalloc(sizeof(*this_row));
        if(!this_row)
            errorf("(sl_exec) Out of memory: (%lu bytes)\n",
                (unsigned long) sizeof(*this_row));

        this_row->last = rec_data->rows;
        rec_data->rows = this_row;
        this_row->row = NULL; /* Because allocate_array may throw an error. */

        this_row->row = allocate_array(cols);
        if(!this_row->row)
            errorf("(sl_exec) Out of memory: row vector\n");
    
        for(col = 0; col < cols; col++)
        {
            svalue_t * entry;
            STORE_DOUBLE_USED;

            entry = this_row->row->item + col;

            switch(sqlite3_column_type(stmt, col))
            {
            default:
                errorf( "sl_exec: Unknown type %d.\n"
                      , sqlite3_column_type(stmt, col));
                break;

            case SQLITE_BLOB:
                errorf("sl_exec: Blob columns are not supported.\n");
                break;

            case SQLITE_INTEGER:
                if (sizeof(entry->u.number) >= 8)
                    put_number(entry, sqlite3_column_int64(stmt, col));
                else
                    put_number(entry, sqlite3_column_int(stmt, col));
                break;

           case SQLITE_FLOAT:
                entry->type = T_FLOAT;
                STORE_DOUBLE(entry, sqlite3_column_double(stmt, col));
                break;

            case SQLITE_TEXT:
                put_c_n_string( entry
                              , (char *)sqlite3_column_text(stmt, col)
                              , sqlite3_column_bytes(stmt, col));
                break;

            case SQLITE_NULL:
                /* All elements from this_row->row are initialized to 0. */
                break;
            }
        }
    }

    sqlite3_finalize(stmt);
    rec_data->stmt = NULL;
    
    switch(err)
    {
    default:
        errorf("sl_exec: Unknown return code from sqlite3_step: %d.\n", err);
        break;

    case SQLITE_BUSY:
        errorf("sl_exec: Database is locked.\n");
        break;

    case SQLITE_ERROR:
        errorf("sl_exec: %s\n", sqlite3_errmsg(db->db));
        break;

    case SQLITE_MISUSE:
        errorf("sl_exec: sqlite3_step was called inappropriately.\n");
        break;

    case SQLITE_DONE:
        break;
    }

    if(rows)
    {
        sqlite_rows_t *this_row;

        result = allocate_array(rows);
        if(!result)
            errorf("(sl_exec) Out of memory: result vector\n");

        this_row = rec_data->rows;
        while(rows--)
        {
            put_array(result->item + rows, this_row->row);
            this_row->row = NULL;
            this_row = this_row->last;
        }
    }
    else
        result = NULL;

    // Pop arguments and our error handler.
    // Our error handler gets called and cleans the row stuff.
    sp = pop_n_elems(num_arg + 1, sp) + 1; 
 
    if(rows)
        put_array(sp,result);
    else
        put_number(sp, 0);

    return sp;
} /* v_sl_exec() */
예제 #10
0
파일: POOL.C 프로젝트: daveoman/DCRabbit_10
int main()
{
	void * r;
   long   x;
	void * r0;
   long   x0;
   int i;
   int do_xtra;

   do_xtra = 1;

	// Allocate the xmem pool data area
   xmem_data = xalloc(XMEM_POOL_SIZE * XMEM_ELS);
   xmem_data_xtra = xalloc(XMEM_POOL_SIZE * XMEM_ELS_XTRA);

   // Init the pools
   pool_init(&root_pool, root_data, ROOT_ELS, ROOT_POOL_SIZE);
   pool_xinit(&xmem_pool, xmem_data, XMEM_ELS, XMEM_POOL_SIZE);

   // Turn linking on, so we can easily iterate through allocated elements
   pool_link(&root_pool, 1);
   pool_link(&xmem_pool, 1);

_again:

   printf("Available in root pool: %u\n", pavail(&root_pool));
   printf("Available in xmem pool: %u\n", pavail(&xmem_pool));
   printf("Elements in root pool: %u\n", pnel(&root_pool));
   printf("Elements in xmem pool: %u\n", pnel(&xmem_pool));

   for (i = 0; i < 10; ++i) {
		r = palloc(&root_pool);
      if (r)
      	printf("Got root element at %04X\n", r);
      if (!i)
      	r0 = r;
		x = pxalloc(&xmem_pool);
      if (x)
      	printf("Got xmem element at %08lX\n", x);
      if (!i)
      	x0 = x;
   }

   printf("Available in root pool: %u\n", pavail(&root_pool));
   printf("Available in xmem pool: %u\n", pavail(&xmem_pool));

   // Now free the first elements we remembered
	printf("Freeing up %04X and %08lX...\n", r0, x0);
   pfree(&root_pool, r0);
   pxfree(&xmem_pool, x0);

   printf("Available in root pool: %u\n", pavail(&root_pool));
   printf("Available in xmem pool: %u\n", pavail(&xmem_pool));

   printf("Maximum used in root pool: %u\n", phwm(&root_pool));
   printf("Maximum used in xmem pool: %u\n", phwm(&xmem_pool));

   printf("Deleting everything...\n");
   for (r = pfirst(&root_pool); r; r = r0) {
   	r0 = pnext(&root_pool, r);
      pfree(&root_pool, r);
   }

   for (x = pxfirst(&xmem_pool); x; x = x0) {
   	x0 = pxnext(&xmem_pool, x);
      pxfree(&xmem_pool, x);
   }

   if (do_xtra) {
   	do_xtra = 0;
      printf("Doing it all again, with appended data areas...\n");
      pool_append(&root_pool, root_data_xtra, ROOT_ELS_XTRA);
   	pool_xappend(&xmem_pool, xmem_data_xtra, XMEM_ELS_XTRA);
      goto _again;
   }

	return 0;
}
예제 #11
0
파일: structs.c 프로젝트: Shea690901/ldmud
/*-------------------------------------------------------------------------*/
static bool
add_struct_name (struct_name_t * pSName)

/* Add the struct name <pSName> to the hash table.
 * The <pSName>->hash must already been computed.
 * Returns false on error.
 */

{
     size_t ix;

#ifdef DEBUG
     if (find_by_struct_name(pSName))
         fatal("struct type %s (%s) already in table.\n"
              , get_txt(pSName->name)
              , get_txt(pSName->prog_name)
              );
#endif

     if (!table)
     {
         table = pxalloc(sizeof(*table));
         if (table == NULL)
             return false;

         table_size = 1;
         table[0] = pSName;
         pSName->next = NULL;
         num_types = 1;
         return true;
     }

     ix = pSName->hash & (table_size-1);
     pSName->next = table[ix];
     table[ix] = pSName;

     num_types++;

     /* If chain lengths grow too much (more than 2 entries per bucket
      * on average), increase the table size
      */
     if (num_types > 2 * table_size && table_size * 2 < MAX_HASH32)
     {
         size_t new_size = 2 * table_size;
         struct_name_t ** table2;

         table2 = pxalloc(new_size * sizeof(*table2));
         if (table2)
         {
             memset(table2, 0, new_size * sizeof(*table2));

             /* Rehash all existing entries */
             for (ix = 0; ix < table_size; ix++)
             {
                 struct_name_t * this;

                 while (NULL != (this = table[ix]))
                 {
                     size_t ix2;

                     table[ix] = this->next;
                     ix2 = this->hash & (new_size-1);

                     this->next = table2[ix2];
                     table2[ix2] = this;
                 }
             } /* for() */

             pfree(table);
             table = table2;
             table_size = new_size;
         } /* if (table2) */
         else
             return false;
     } /* if (check for rehash condition) */

     return true;
} /* add_struct_name() */
예제 #12
0
파일: pkg-psyc.c 프로젝트: jomat/ldmud
void
fill_header_from_mapping (svalue_t *key, svalue_t *val, void *extra) {
    psyc_modifier_t *m = extra;
    char oper = 0;
    char *name, *value;
    size_t namelen, valuelen, i;
    uint8_t type;
    svalue_t vsp, *lval;

    psycList list;
    psycString *elems = NULL;

    if (key->type != T_STRING) {
	errorf("fill_header_from_mapping: key type %d not supported\n", key->type);
	return; // not reached
    }

    name = get_txt(key->u.str);
    namelen = mstrsize(key->u.str);
    type = psyc_getVarType2(name, namelen);

    if (m->num_values > 1)
	oper = val[1].u.number;
    if (!oper)
	oper = C_GLYPH_OPERATOR_SET;

    switch (val->type) {
	case T_STRING:
	    value = get_txt(val->u.str);
	    valuelen = mstrsize(val->u.str);
	    break;

	case T_NUMBER:
	case T_OBJECT:
	    vsp.type = val->type;
	    switch (val->type) {
		case T_NUMBER:
		    if (type == PSYC_TYPE_DATE)
			vsp.u.number = val->u.number - PSYC_EPOCH;
		    else
			vsp.u.number = val->u.number;
		    break;
		case T_OBJECT:
		    vsp.u.ob = val->u.ob;
		    break;
	    }

	    f_to_string(&vsp);	// generates an mstring
	    value = get_txt(vsp.u.str);
	    valuelen = mstrsize(vsp.u.str);
	    break;

	case T_POINTER:
	    if (VEC_SIZE(val->u.vec)) {
		elems = pxalloc(sizeof(psycString) * VEC_SIZE(val->u.vec));
		if (!elems) {
		    errorf("Out of memory in fill_header_from_mapping for elems\n");
		    return; // not reached
		}

		for (i = 0; i < VEC_SIZE(val->u.vec); i++) {
		    lval = &(val->u.vec->item[i]);
		    switch (lval->type) {
			case T_STRING:
			    elems[i] = (psycString){mstrsize(lval->u.str), get_txt(lval->u.str)};
			    break;
			case T_NUMBER:
			case T_OBJECT:
			    vsp.type = lval->type;
			    switch (lval->type) {
				case T_NUMBER:
				    vsp.u.number = lval->u.number;
				    break;
				case T_OBJECT:
				    vsp.u.ob = lval->u.ob;
				    break;
			    }

			    f_to_string(&vsp);
			    elems[i] = (psycString){mstrsize(vsp.u.str), get_txt(vsp.u.str)};
			    break;
			default:
			    errorf("fill_header_from_mapping: list value type %d not supported\n", lval->type);
			    return; // not reached
		    }
		}
	    }

	    list = psyc_newList(elems, VEC_SIZE(val->u.vec), PSYC_LIST_CHECK_LENGTH);
	    valuelen = list.length;
	    value = pxalloc(valuelen);
	    if (!value) {
		errorf("Out of memory in fill_header_from_mapping for list value\n");
		return; // not reached
	    }

	    psyc_renderList(&list, value, valuelen);
	    break;

	default:
	    errorf("fill_header_from_mapping: value type %d not supported\n", val->type);
	    return; // not reached
    }

    m->header->modifiers[m->header->lines++] =
	psyc_newModifier2(oper, name, namelen, value, valuelen, m->flag);
}
예제 #13
0
파일: pkg-psyc.c 프로젝트: jomat/ldmud
svalue_t *
f_psyc_parse (svalue_t *sp) {
    char *buffer = NULL;
    svalue_t *sv;
    vector_t *v, *list;
    mapping_t *map;
    char oper = 0;
    psycString name = {0,0}, value = {0,0}, elems[MAX_LIST_SIZE], elem;
    psycParseListState listState;
    int ret, retl, type = -1, error = 0;
    size_t size, i;
    ssize_t n;
    time_t timmy;

    if (!psyc_dispatch_callback)
      psyc_dispatch_callback = new_tabled("psyc_dispatch");

    if (!psyc_error_callback)
      psyc_error_callback = new_tabled("psyc_error");

    assert_shadow_sent(current_object);
    psyc_state_t *state = O_GET_PSYC_STATE(current_object);
    if (!state) {
	state = pxalloc(sizeof(psyc_state_t));
	if (!state) {
	    errorf("Out of memory for psyc state struct.\n");
	    return sp; // not reached
	}
	O_GET_PSYC_STATE(current_object) = state;
	memset(state, 0, sizeof(psyc_state_t));

	state->parser = pxalloc(sizeof(psycParseState));
	if (!state->parser) {
	    errorf("Out of memory for psyc parse state struct.\n");
	    return sp; // not reached
	}
	psyc_initParseState(state->parser);
    }
    v = state->packet;

    if (sp->type == T_POINTER) {
	errorf("\npsyc_parse got %ld int* bytes... not supported yet\n",
	       VEC_SIZE(sp->u.vec));
	return sp; // not reached
    } else if (sp->type == T_STRING) {
#ifdef DEBUG
	printf("\npsyc_parse got a %ld bytes long string...\n", mstrsize(sp->u.str));
#endif
	if (state->remaining) {
	    // there are remaining bytes from the previous call to psyc_parse,
	    // copy them together with the newly arrived data
	    buffer = pxalloc(state->remaining_len + mstrsize(sp->u.str));
	    if (!buffer) {
		errorf("Out of memory for psyc_parse buffer.\n");
		return sp; // not reached
	    }
	    memcpy(buffer, state->remaining, state->remaining_len);
	    memcpy(buffer + state->remaining_len, get_txt(sp->u.str),
		   mstrsize(sp->u.str));
	    psyc_setParseBuffer2(state->parser, buffer,
				 state->remaining_len + mstrsize(sp->u.str));
	    pfree(state->remaining);
	    state->remaining = NULL;
	    state->remaining_len = 0;
	} else {
	    psyc_setParseBuffer2(state->parser, get_txt(sp->u.str),
				 mstrsize(sp->u.str));
	}
    } else {
	errorf("\npsyc_parse got type %d, not supported\n", sp->type);
	return sp; // not reached
    }

    do {
	ret = psyc_parse(state->parser, &oper, &name, &value);
#ifdef DEBUG
	printf("#%2d %c%.*s = %.*s\n", ret, oper ? oper : ' ',
	       (int)name.length, name.ptr, (int)value.length, value.ptr);
#endif
	if (!state->packet) {
	    state->packet = allocate_array(4);
	    if (!state->packet) {
		errorf("Out of memory for psyc_parse array.\n");
		return sp; // not reached
	    }
	    v = state->packet;

	    map = allocate_mapping(0, 2);	// empty mapping
	    if (!map) {
		errorf("Out of memory for psyc_parse routing header.\n");
		return sp; // not reached
	    }
	    put_mapping(&v->item[PACKET_ROUTING], map);
	    map = allocate_mapping(0, 2);	// empty mapping
	    if (!map) {
		errorf("Out of memory for psyc_parse entity header.\n");
		return sp; // not reached
	    }
	    put_mapping(&v->item[PACKET_ENTITY], map);
	}

	switch (ret) {
	    case PSYC_PARSE_ENTITY_START: case PSYC_PARSE_BODY_START:
		// save oper, name & value in state at the start of
		// incomplete entity or body
		state->oper = oper;
		state->name = mstring_alloc_string(name.length);
		memcpy(get_txt(state->name), name.ptr, name.length);
		if (!state->name) {
		    errorf("Out of memory for name.\n");
		    return sp; // not reached
		}

		// allocate memory for the total length of the value
		state->value_len = 0;
		state->value = mstring_alloc_string(psyc_getParseValueLength(state->parser));
		if (!state->value) {
		    errorf("Out of memory for value.\n");
		    return sp; // not reached
		}

		// fall thru
	    case PSYC_PARSE_ENTITY_CONT:  case PSYC_PARSE_BODY_CONT:
	    case PSYC_PARSE_ENTITY_END:   case PSYC_PARSE_BODY_END:
		// append value to tmp buffer in state
		memcpy(get_txt(state->value) + state->value_len, value.ptr, value.length);
		state->value_len += value.length;
	}

	if (ret == PSYC_PARSE_ENTITY_END || ret == PSYC_PARSE_BODY_END) {
	    // incomplete entity or body parsing done,
	    // set oper/name/value to the ones saved in state
	    oper = state->oper;
	    name.ptr = get_txt(state->name);
	    name.length = mstrsize(state->name);
	    value.ptr = get_txt(state->value);
	    value.length = mstrsize(state->value);
	}

	switch (ret) {
	    case PSYC_PARSE_ROUTING:
		sv = pxalloc(sizeof(svalue_t));

		// new_n_tabled fetches a reference of a probably existing
		// shared string
		put_string(sv, new_n_tabled(name.ptr, name.length));
		sv = get_map_lvalue(v->item[PACKET_ROUTING].u.map, sv);
		put_number(&sv[1], oper);
		// strings are capable of containing 0 so we can do this
		// for binary data too. let's use a tabled string even
		// for values of routing variables as they repeat a lot
		put_string(sv, new_n_tabled(value.ptr, value.length));
		break;

	    case PSYC_PARSE_ENTITY_START:
	    case PSYC_PARSE_ENTITY_CONT:
		break;

	    case PSYC_PARSE_ENTITY_END:
	    case PSYC_PARSE_ENTITY:
		sv = pxalloc(sizeof(svalue_t));

		if (ret == PSYC_PARSE_ENTITY)
		    put_string(sv, new_n_tabled(name.ptr, name.length));
		else // PSYC_PARSE_ENTITY_END
		    put_string(sv, make_tabled(state->name));

		sv = get_map_lvalue(v->item[PACKET_ENTITY].u.map, sv);
		put_number(&sv[1], oper);

		type = psyc_getVarType(&name);

		switch (type) {
		    case PSYC_TYPE_DATE: // number + PSYC_EPOCH
			if (psyc_parseDate(&value, &timmy))
			    put_number(sv, timmy);
			else
			    error = PSYC_PARSE_ERROR_DATE;
			break;
		    case PSYC_TYPE_TIME: // number
			if (psyc_parseTime(&value, &timmy))
			    put_number(sv, timmy);
			else
			    error = PSYC_PARSE_ERROR_TIME;
			break;
		    case PSYC_TYPE_AMOUNT: // number
			if (psyc_parseNumber(&value, &n))
			    put_number(sv, n);
			else
			    error = PSYC_PARSE_ERROR_AMOUNT;
			break;
		    case PSYC_TYPE_DEGREE: // first digit
			if (value.length && value.ptr[0] >= '0' && value.ptr[0] <= '9')
			    put_number(sv, value.ptr[0] - '0');
			else
			    error = PSYC_PARSE_ERROR_DEGREE;
			break;
		    case PSYC_TYPE_FLAG: // 0 or 1
			if (value.length && value.ptr[0] >= '0' && value.ptr[0] <= '1')
			    put_number(sv, value.ptr[0] - '0');
			else
			    error = PSYC_PARSE_ERROR_FLAG;
			break;
		    case PSYC_TYPE_LIST: // array
			size = 0;
			if (value.length) {
			    psyc_initParseListState(&listState);
			    psyc_setParseListBuffer(&listState, value);
			    elem = (psycString){0, 0};
			    do {
				retl = psyc_parseList(&listState, &elem);
				switch (retl) {
				    case PSYC_PARSE_LIST_END:
					retl = 0;
				    case PSYC_PARSE_LIST_ELEM:
					if (size >= MAX_LIST_SIZE) {
					    error = PSYC_PARSE_ERROR_LIST_TOO_LARGE;
					    break;
					}
					elems[size++] = elem;
					break;
				    default:
					error = PSYC_PARSE_ERROR_LIST;
				}
			    } while (retl > 0 && !error);
			}
			if (error) break;

			list = allocate_array(size);
			for (i = 0; i < size; i++)
			    put_string(&list->item[i], new_n_tabled(elems[i].ptr,
			                                            elems[i].length));

			put_array(sv, list);
			break;
		    default: // string
			if (ret == PSYC_PARSE_ENTITY)
			    // is it good to put entity variable values into the
			    // shared string table? probably yes.. but it's a guess
			    //t_string(sv, new_n_mstring(value.ptr, value.length));
			    put_string(sv, new_n_tabled(value.ptr, value.length));
			else // PSYC_PARSE_ENTITY_END
			    put_string(sv, state->value);
		}
		break;

	    case PSYC_PARSE_BODY_START:
	    case PSYC_PARSE_BODY_CONT:
		break;

	    case PSYC_PARSE_BODY_END:
		put_string(&v->item[PACKET_METHOD], make_tabled(state->name));
		put_string(&v->item[PACKET_BODY], state->value);
		break;

	    case PSYC_PARSE_BODY:
		// new_n_tabled gets the shared string for the method
		put_string(&v->item[PACKET_METHOD],
			   new_n_tabled(name.ptr, name.length));

		// allocate an untabled string for the packet body
		put_string(&v->item[PACKET_BODY],
			   new_n_mstring(value.ptr, value.length));
		break;

	    case PSYC_PARSE_COMPLETE:
		put_array(inter_sp, v);
		sapply(psyc_dispatch_callback, current_object, 1);
		state->packet = NULL;
		break;

	    case PSYC_PARSE_INSUFFICIENT:
		// insufficient data, save remaining bytes
		state->remaining_len = psyc_getParseRemainingLength(state->parser);
		if (state->remaining_len) {
		    state->remaining = pxalloc(state->remaining_len);
		    memcpy(state->remaining,
			   psyc_getParseRemainingBuffer(state->parser),
			   state->remaining_len);
		} else
		    state->remaining = NULL;

		ret = 0;
		break;

	    default:
		error = ret;
	}

	switch (ret) {
	    case PSYC_PARSE_BODY_END:
	    case PSYC_PARSE_ENTITY_END:
		// reset tmp buffers in state when incomplete
		// entity or body parsing is finished
		state->oper = 0;
		state->name = NULL;
		state->value = NULL;
	}
    } while (ret && !error);

    if (buffer)
	pfree(buffer);

    free_svalue(sp);
    put_number(sp, error);
    return sp;
} /* f_psyc_parse */