struct vector * set_manipulate_array(struct vector *arr1, struct vector *arr2, int op) { struct mapping *m; struct vector *r; struct svalue tmp, *v; char *flags; int cnt, res; if (arr1->size < 1 || arr2->size < 1) { switch (op) { case SETARR_SUBTRACT: INCREF(arr1->ref); return arr1; case SETARR_INTERSECT: return allocate_array(0); } } m = make_mapping(arr2, 0); tmp.type = T_NUMBER; tmp.u.number = 1; assign_svalue_no_free(get_map_lvalue(m, &arr2->item[0], 1), &tmp); res = 0; flags = alloca((size_t)arr1->size + 1); for (cnt = 0; cnt < arr1->size; cnt++) { flags[cnt] = 0; v = get_map_lvalue(m, &(arr1->item[cnt]), 0); if (op == SETARR_INTERSECT && v != &const0) { flags[cnt] = 1; res++; } else if (op == SETARR_SUBTRACT && v == &const0) { flags[cnt] = 1; res++; } } r = allocate_array(res); if (res) { for (cnt = res = 0; cnt < arr1->size; cnt++) { if (flags[cnt]) assign_svalue_no_free(&r->item[res++], &arr1->item[cnt]); } } free_mapping(m); return r; }
INLINE struct vector * union_array(struct vector *arr1, struct vector *arr2) { int i, size; struct mapping *mp; struct vector *arr3; char *set; if (arr1->size == 0) { INCREF(arr2->ref); return arr2; } if (arr2->size == 0) { INCREF(arr1->ref); return arr1; } mp = allocate_map(arr1->size); for (i = 0; i < arr1->size; i++) assign_svalue(get_map_lvalue(mp, &arr1->item[i], 1), &const1); set = alloca((size_t)arr2->size); for (i = size = 0; i < arr2->size; i++) { if (get_map_lvalue(mp, &arr2->item[i], 0) == &const0) set[i] = 1, size++; else set[i] = 0; } free_mapping(mp); arr3 = allocate_array(arr1->size + size); for (i = 0; i < arr1->size; i++) assign_svalue_no_free(&arr3->item[i], &arr1->item[i]); size = arr1->size; for (i = 0; i < arr2->size; i++) if (set[i]) assign_svalue_no_free(&arr3->item[size++], &arr2->item[i]); return arr3; }
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 ); }
struct svalue * json_to_mapping(json_object *ob) { static struct svalue ret; ret.type = T_MAPPING; ret.u.map = allocate_map(10); json_object_object_foreach(ob, name, val) { struct svalue key = {}; key.type = T_STRING; key.string_type = STRING_MSTRING; key.u.string = make_mstring(name); assign_svalue_no_free(get_map_lvalue(ret.u.map, &key, 1), json_to_value(val)); } return &ret; }
static struct mapping * restore_mapping(char **str) { struct mapping *m; m = allocate_map(0); for(;;) { if (**str == ']') { if (*++*str == ')') { ++*str; return m; } else break; } else { struct svalue arg, *val; arg = const0; if (!restore_one(&arg, str)) break; if (*(*str)++ != ':') { free_svalue(&arg); break; } val = get_map_lvalue(m, &arg, 1); free_svalue(&arg); if (!restore_one(val, str) || *(*str)++ != ',') break; } } free_mapping(m); return 0; }
/* * Save an object to a mapping. */ struct mapping * m_save_object(struct object *ob) { int i, j; struct mapping *ret; struct svalue s = const0; if (ob->flags & O_DESTRUCTED) return allocate_map(0); /* XXX is this right /LA */ ret = allocate_map((short)(ob->prog->num_variables + ob->prog->inherit[ob->prog->num_inherited - 1]. variable_index_offset)); for (j = 0; j < (int)ob->prog->num_inherited; j++) { struct program *prog = ob->prog->inherit[j].prog; if (ob->prog->inherit[j].type & TYPE_MOD_SECOND || prog->num_variables == 0) continue; for (i = 0; i < (int)prog->num_variables; i++) { struct svalue *v = &ob->variables[i + ob->prog->inherit[j]. variable_index_offset]; if (prog->variable_names[i].type & TYPE_MOD_STATIC) continue; free_svalue(&s); s.type = T_STRING; s.string_type = STRING_MSTRING; s.u.string = make_mstring(prog->variable_names[i].name); assign_svalue(get_map_lvalue(ret, &s, 1), v); } } free_svalue(&s); return ret; }
void restore_map(struct object *ob, struct mapping *map, char *file) { char *name, *buff, *space; size_t len; FILE *f; struct object *save = current_object; struct stat st; if (current_object != ob) fatal("Bad argument to restore_map()\n"); if (ob->flags & O_DESTRUCTED) return; file = check_valid_path(file, ob, "restore_map", 0); if (file == 0) error("Illegal use of restore_map()\n"); len = strlen(file); name = alloca(len + 2 + 1); (void)strcpy(name, file); if (name[len-2] == '.' && name[len-1] == 'c') name[len-1] = 'o'; else (void)strcat(name, ".o"); f = fopen(name, "r"); if (s_flag) num_fileread++; if (!f || fstat(fileno(f), &st) == -1) { if (f) (void)fclose(f); return; } if (st.st_size == 0) { (void)fclose(f); return; } buff = xalloc((size_t)st.st_size + 1); for (;;) { struct svalue v; v.type = T_STRING; v.string_type = STRING_MSTRING; if (fgets(buff, (int)st.st_size + 1, f) == 0) break; /* Remember that we have a newline at end of buff ! */ space = strchr(buff, ' '); if (space == 0) { (void)fclose(f); free(buff); error("Illegal format when restoring %s.\n", file); } *space++ = '\0'; v.u.string = make_mstring(buff); if (!restore_one(get_map_lvalue(map,&v,1), &space)) { (void)fclose(f); free(buff); free_svalue(&v); error("Illegal format when restoring %s.\n", file); } free_svalue(&v); } current_object = save; free(buff); (void)fclose(f); }
/************************************************************************* * 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 ); }
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 */