void f_destructed_objects (void) { int i; array_t *ret; object_t *ob; ret = allocate_empty_array(tot_dangling_object); ob = obj_list_dangling; for (i = 0; i < tot_dangling_object; i++) { ret->item[i].type = T_ARRAY; ret->item[i].u.arr = allocate_empty_array(2); ret->item[i].u.arr->item[0].type = T_STRING; ret->item[i].u.arr->item[0].subtype = STRING_SHARED; ret->item[i].u.arr->item[0].u.string = make_shared_string(ob->obname); ret->item[i].u.arr->item[1].type = T_NUMBER; ret->item[i].u.arr->item[1].u.number = ob->ref; ob = ob->next_all; } push_refed_array(ret); }
void f_db_exec (void) { int ret = 0; db_t *db; array_t *info; info = allocate_empty_array(1); info->item[0].type = T_STRING; info->item[0].subtype = STRING_MALLOC; info->item[0].u.string = string_copy(sp->u.string, "f_db_exec"); valid_database("exec", info); db = find_db_conn((sp-1)->u.number); if (!db) { error("Attempt to exec on an invalid database handle\n"); } #ifdef PACKAGE_ASYNC if(!db_mut){ db_mut = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); pthread_mutex_init(db_mut, NULL); } pthread_mutex_lock(db_mut); #endif if (db->type->cleanup) { db->type->cleanup(&(db->c)); } if (db->type->execute) { ret = db->type->execute(&(db->c), sp->u.string); } pop_stack(); if (ret == -1) { if (db->type->error) { char *errormsg; errormsg = db->type->error(&(db->c)); put_malloced_string(errormsg); } else { put_constant_string("Unknown error"); } } else { sp->u.number = ret; } #ifdef PACKAGE_ASYNC pthread_mutex_unlock(db_mut); #endif }
void f_named_livings() { int i; int nob; #ifdef F_SET_HIDE int apply_valid_hide, display_hidden = 0; #endif object_t *ob, **obtab; array_t *vec; nob = 0; #ifdef F_SET_HIDE apply_valid_hide = 1; #endif obtab = CALLOCATE(max_array_size, object_t *, TAG_TEMPORARY, "named_livings"); for (i = 0; i < CFG_LIVING_HASH_SIZE; i++) { for (ob = hashed_living[i]; ob; ob = ob->next_hashed_living) { if (!(ob->flags & O_ENABLE_COMMANDS)) continue; #ifdef F_SET_HIDE if (ob->flags & O_HIDDEN) { if (apply_valid_hide) { apply_valid_hide = 0; display_hidden = valid_hide(current_object); } if (!display_hidden) continue; } #endif if (nob == max_array_size) break; obtab[nob++] = ob; } } vec = allocate_empty_array(nob); while (--nob >= 0) { vec->item[nob].type = T_OBJECT; vec->item[nob].u.ob = obtab[nob]; add_ref(obtab[nob], "livings"); } FREE(obtab); push_refed_array(vec); }
static void encode_stat (svalue_t * vp, int flags, char * str, struct stat * st) { if (flags == -1) { array_t *v = allocate_empty_array(3); v->item[0].type = T_STRING; v->item[0].subtype = STRING_MALLOC; v->item[0].u.string = string_copy(str, "encode_stat"); v->item[1].type = T_NUMBER; v->item[1].u.number = ((st->st_mode & S_IFDIR) ? -2 : st->st_size); v->item[2].type = T_NUMBER; v->item[2].u.number = st->st_mtime; vp->type = T_ARRAY; vp->u.arr = v; } else { vp->type = T_STRING; vp->subtype = STRING_MALLOC; vp->u.string = string_copy(str, "encode_stat"); } }
/* * check permission */ int check_valid_socket (const char * const what, int fd, object_t * owner, const char * const addr, int port) { array_t *info; svalue_t *mret; info = allocate_empty_array(4); info->item[0].type = T_NUMBER; info->item[0].u.number = fd; assign_socket_owner(&info->item[1], owner); info->item[2].type = T_STRING; info->item[2].subtype = STRING_SHARED; info->item[2].u.string = make_shared_string(addr); info->item[3].type = T_NUMBER; info->item[3].u.number = port; push_object(current_object); push_constant_string(what); push_refed_array(info); mret = apply_master_ob(APPLY_VALID_SOCKET, 3); return MASTER_APPROVED(mret); }
void f_socket_status (void) { array_t *info; int i; if (st_num_arg) { info = socket_status(sp->u.number); if (!info) { sp->u.number = 0; } else { sp->type = T_ARRAY; sp->u.arr = info; } } else { info = allocate_empty_array(max_lpc_socks); for (i = 0; i < max_lpc_socks; i++) { info->item[i].type = T_ARRAY; info->item[i].u.arr = socket_status(i); } push_refed_array(info); } }
static array_t *pcre_match(array_t *v, svalue_t *pattern, int flag) { pcre_t *run; array_t *ret; svalue_t *sv1, *sv2; char *res; int num_match, size, match = !(flag & 2); if (!(size = v->size)) return &the_null_array; run = CALLOCATE(1, pcre_t, TAG_TEMPORARY, "pcre_match : run"); run->ovector = NULL; run->ovecsize = 0; assign_svalue_no_free(&run->pattern, pattern); run->re = pcre_get_cached_pattern(&pcre_cache, &run->pattern); if (run->re == NULL) { if (pcre_local_compile(run) == NULL) { const char *rerror = run->error; int offset = run->erroffset; pcre_free_memory(run); error("PCRE compilation failed at offset %d: %s\n", offset, rerror); } else pcre_cache_pattern(&pcre_cache, run->re, &run->pattern); } res = (char*)DMALLOC(size, TAG_TEMPORARY, "prcre_match: res"); sv1 = v->item + size; num_match = 0; while (size--) { if ((--sv1)->type != T_STRING) { res[size] = 0; continue; } run->subject = sv1->u.string; run->s_length = SVALUE_STRLEN(sv1); pcre_local_exec(run); if (pcre_query_match(run) != match) //was not checking for match! (woom) { res[size] = 0; continue; } res[size] = 1; num_match++; } flag &= 1; ret = allocate_empty_array(num_match << flag); sv2 = ret->item + (num_match << flag); size = v->size; while (size--) { if (res[size]) { if (flag) { (--sv2)->type = T_NUMBER; sv2->u.number = size + 1; } (--sv2)->type = T_STRING; sv1 = v->item + size; *sv2 = *sv1; if (sv1->subtype & STRING_COUNTED) { INC_COUNTED_REF(sv1->u.string); ADD_STRING(MSTR_SIZE(sv1->u.string)); } if (!--num_match) break; } } FREE(res); pcre_free_memory(run); return ret; }
array_t *get_dir (const char * path, int flags) { array_t *v; int i, count = 0; #ifndef WIN32 DIR *dirp; #endif int namelen, do_match = 0; #ifndef WIN32 #ifdef USE_STRUCT_DIRENT struct dirent *de; #else struct direct *de; #endif #endif struct stat st; char *endtemp; char temppath[MAX_FNAME_SIZE + MAX_PATH_LEN + 2]; char regexppath[MAX_FNAME_SIZE + MAX_PATH_LEN + 2]; char *p; #ifdef WIN32 struct _finddata_t FindBuffer; long FileHandle, FileCount; #endif if (!path) return 0; path = check_valid_path(path, current_object, "stat", 0); if (path == 0) return 0; if (strlen(path) < 2) { temppath[0] = path[0] ? path[0] : '.'; temppath[1] = '\000'; p = temppath; } else { strncpy(temppath, path, MAX_FNAME_SIZE + MAX_PATH_LEN + 1); temppath[MAX_FNAME_SIZE + MAX_PATH_LEN + 1] = '\0'; /* * If path ends with '/' or "/." remove it */ if ((p = strrchr(temppath, '/')) == 0) p = temppath; if (p[0] == '/' && ((p[1] == '.' && p[2] == '\0') || p[1] == '\0')) *p = '\0'; } if (stat(temppath, &st) < 0) { if (*p == '\0') return 0; if (p != temppath) { strcpy(regexppath, p + 1); *p = '\0'; } else { strcpy(regexppath, p); strcpy(temppath, "."); } do_match = 1; } else if (*p != '\0' && strcmp(temppath, ".")) { if (*p == '/' && *(p + 1) != '\0') p++; v = allocate_empty_array(1); encode_stat(&v->item[0], flags, p, &st); return v; } #ifdef WIN32 FileHandle = -1; FileCount = 1; /* strcat(temppath, "\\*"); */ strcat(temppath, "/*"); if ((FileHandle = _findfirst(temppath, &FindBuffer)) == -1) return 0; #else if ((dirp = opendir(temppath)) == 0) return 0; #endif /* * Count files */ #ifdef WIN32 do { if (!do_match && (!strcmp(FindBuffer.name, ".") || !strcmp(FindBuffer.name, ".."))) { continue; } if (do_match && !match_string(regexppath, FindBuffer.name)) { continue; } count++; if (count >= max_array_size) { break; } } while (!_findnext(FileHandle, &FindBuffer)); _findclose(FileHandle); #else for (de = readdir(dirp); de; de = readdir(dirp)) { #ifdef USE_STRUCT_DIRENT namelen = strlen(de->d_name); #else namelen = de->d_namlen; #endif if (!do_match && (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)) continue; if (do_match && !match_string(regexppath, de->d_name)) continue; count++; if (count >= max_array_size) break; } #endif /* * Make array and put files on it. */ v = allocate_empty_array(count); if (count == 0) { /* This is the easy case :-) */ #ifndef WIN32 closedir(dirp); #endif return v; } #ifdef WIN32 FileHandle = -1; if ((FileHandle = _findfirst(temppath, &FindBuffer)) == -1) return 0; endtemp = temppath + strlen(temppath) - 2; *endtemp = 0; /* strcat(endtemp++, "\\"); */ strcat(endtemp++, "/"); i = 0; do { if (!do_match && (!strcmp(FindBuffer.name, ".") || !strcmp(FindBuffer.name, ".."))) continue; if (do_match && !match_string(regexppath, FindBuffer.name)) continue; if (flags == -1) { strcpy(endtemp, FindBuffer.name); stat(temppath, &st); } encode_stat(&v->item[i], flags, FindBuffer.name, &st); i++; } while (!_findnext(FileHandle, &FindBuffer)); _findclose(FileHandle); #else /* WIN32 */ rewinddir(dirp); endtemp = temppath + strlen(temppath); strcat(endtemp++, "/"); for (i = 0, de = readdir(dirp); i < count; de = readdir(dirp)) { #ifdef USE_STRUCT_DIRENT namelen = strlen(de->d_name); #else namelen = de->d_namlen; #endif if (!do_match && (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)) continue; if (do_match && !match_string(regexppath, de->d_name)) continue; de->d_name[namelen] = '\0'; if (flags == -1) { /* * We'll have to .... sigh.... stat() the file to get some add'tl * info. */ strcpy(endtemp, de->d_name); stat(temppath, &st);/* We assume it works. */ } encode_stat(&v->item[i], flags, de->d_name, &st); i++; } closedir(dirp); #endif /* OS2 */ /* Sort the names. */ qsort((void *) v->item, count, sizeof v->item[0], (flags == -1) ? parrcmp : pstrcmp); return v; }
static array_t *msql_fetch (dbconn_t * c, int row) { int i, num_fields; m_row this_row; array_t *v; if (!c->msql.result_set) { return &the_null_array; } if (row < 1 || row > msqlNumRows(c->msql.result_set)) { return &the_null_array; } num_fields = msqlNumFields(c->msql.result_set); if (num_fields < 1) { return &the_null_array; } msqlDataSeek(c->msql.result_set, row - 1); this_row = msqlFetchRow(c->msql.result_set); if (!this_row) { return &the_null_array; } v = allocate_empty_array(num_fields); for (i = 0; i < num_fields; i++) { m_field *field; field = msqlFetchField(c->msql.result_set); if (!field || !this_row[i]) { v->item[i] = const0u; } else { switch (field->type) { case INT_TYPE: case UINT_TYPE: v->item[i].type = T_NUMBER; v->item[i].u.number = atoi(this_row[i]); break; case REAL_TYPE: case MONEY_TYPE: v->item[i].type = T_REAL; v->item[i].u.real = atof(this_row[i]); break; case CHAR_TYPE: case TEXT_TYPE: case DATE_TYPE: case TIME_TYPE: v->item[i].type = T_STRING; v->item[i].subtype = STRING_MALLOC; v->item[i].u.string = string_copy(this_row[i], "msql_fetch"); break; default: v->item[i] = const0u; break; } } } msqlFieldSeek(c->msql.result_set, 0); return v; }
/* This is mostly copy/paste from reg_assoc, some parts are changed * TODO: rewrite with new logic */ static array_t *pcre_assoc(svalue_t *str, array_t *pat, array_t *tok, svalue_t *def) { int i, size; const char *tmp; array_t *ret; if ((size = pat->size) != tok->size) error("Pattern and token array size must be identical.\n"); for (i = 0; i < size; i++) if (pat->item[i].type != T_STRING) error("Non-string found in pattern array.\n"); ret = allocate_empty_array(2); if (size) { pcre_t **rgpp; struct reg_match { int tok_i; const char *begin, *end; struct reg_match *next; } *rmp = (struct reg_match *) 0, *rmph = (struct reg_match *) 0; int num_match = 0, length; svalue_t *sv1, *sv2, *sv; int regindex; pcre_t *tmpreg; int laststart; rgpp = CALLOCATE(size, pcre_t *, TAG_TEMPORARY, "pcre_assoc : rgpp"); for (i = 0; i < size; i++) { rgpp[i] = CALLOCATE(1, pcre_t, TAG_TEMPORARY, "pcre_assoc : rgpp[i]"); rgpp[i]->ovector = NULL; rgpp[i]->ovecsize = 0; assign_svalue_no_free(&rgpp[i]->pattern, &pat->item[i]); rgpp[i]->re = pcre_get_cached_pattern(&pcre_cache, &rgpp[i]->pattern); if (rgpp[i]->re == NULL) { if (pcre_local_compile(rgpp[i]) == NULL) { const char *rerror = rgpp[i]->error; int offset = rgpp[i]->erroffset; while (i--) pcre_free_memory(rgpp[i]); FREE(rgpp); free_empty_array(ret); error("PCRE compilation failed at offset %d: %s\n", offset, rerror); } else pcre_cache_pattern(&pcre_cache, rgpp[i]->re, &rgpp[i]->pattern); } } tmp = str->u.string; int totalsize = SVALUE_STRLEN(str); int used = 0; while (*tmp) { laststart = 0; regindex = -1; for (i = 0; i < size; i++) { rgpp[i]->subject = tmp; rgpp[i]->s_length = totalsize-used; pcre_local_exec(tmpreg = rgpp[i]); if (pcre_query_match(tmpreg)) { char *curr_temp; size_t curr_temp_sz; curr_temp_sz = totalsize - used - tmpreg->ovector[0]; if(!tmpreg->ovector[0]){ regindex = i; break; } if (laststart < curr_temp_sz) { laststart = curr_temp_sz; regindex = i; } } } if (regindex >= 0) { const char *rmpb_tmp, *rmpe_tmp; size_t rmpb_tmp_sz, rmpe_tmp_sz; num_match++; if (rmp) { rmp->next = ALLOCATE(struct reg_match, TAG_TEMPORARY, "pcre_assoc : rmp->next"); rmp = rmp->next; } else rmph = rmp = ALLOCATE(struct reg_match, TAG_TEMPORARY, "pcre_assoc : rmp"); tmpreg = rgpp[regindex]; rmpb_tmp = tmp + tmpreg->ovector[0]; rmpe_tmp = tmp + tmpreg->ovector[1]; rmp->begin = rmpb_tmp; rmp->end = tmp = rmpe_tmp; used+=tmpreg->ovector[1]; rmp->tok_i = regindex; rmp->next = (struct reg_match *) 0; } else break; if (rmp->begin == tmp && (!*++tmp)) break; }
0., 0., 1., 0., 0., 0., 0., 1.}; static void print_matrix PROT((Matrix, char *)); static void print_array PROT((Vector *, char *)); static Vector *normalize_array PROT((Vector *)); static Vector *cross_product PROT((Vector *, Vector *, Vector *)); static Vector *points_to_array PROT((Vector *, Vector *, Vector *)); #ifdef F_ID_MATRIX void f_id_matrix PROT((void)) { array_t *matrix; int i; matrix = allocate_empty_array(16); for (i = 0; i < 16; i++) { matrix->item[i].type = T_REAL; matrix->item[i].u.real = identity[i]; } (++sp)->u.arr = matrix; sp->type = T_ARRAY; } #endif #ifdef F_TRANSLATE void f_translate PROT((void)) { array_t *matrix; double x, y, z; Matrix current_matrix;
static array_t *MySQL_fetch (dbconn_t * c, int row) { array_t *v; MYSQL_ROW target_row; unsigned int i, num_fields; if (!c->mysql.results) { return &the_null_array; } if (row < 0 || row > mysql_num_rows(c->mysql.results)) { return &the_null_array; } num_fields = mysql_num_fields(c->mysql.results); if (num_fields < 1) { return &the_null_array; } if(row>0){ mysql_data_seek(c->mysql.results, row - 1); target_row = mysql_fetch_row(c->mysql.results); if (!target_row) { return &the_null_array; } } v = allocate_empty_array(num_fields); for (i = 0; i < num_fields; i++) { MYSQL_FIELD *field; field = mysql_fetch_field(c->mysql.results); if (row == 0) { if (field == (MYSQL_FIELD *)NULL) { v->item[i] = const0u; } else { v->item[i].type = T_STRING; v->item[i].subtype = STRING_MALLOC; v->item[i].u.string = string_copy(field->name, "f_db_fetch"); } continue; } if (!field || !target_row[i]) { v->item[i] = const0u; } else { switch (field->type) { case FIELD_TYPE_TINY: case FIELD_TYPE_SHORT: case FIELD_TYPE_DECIMAL: case FIELD_TYPE_LONG: case FIELD_TYPE_INT24: case FIELD_TYPE_LONGLONG: v->item[i].type = T_NUMBER; v->item[i].subtype = 0; v->item[i].u.number = atoi(target_row[i]); break; case FIELD_TYPE_FLOAT: case FIELD_TYPE_DOUBLE: v->item[i].type = T_REAL; v->item[i].u.real = atof(target_row[i]); break; case FIELD_TYPE_TINY_BLOB: case FIELD_TYPE_MEDIUM_BLOB: case FIELD_TYPE_LONG_BLOB: case FIELD_TYPE_BLOB: case FIELD_TYPE_STRING: case FIELD_TYPE_VAR_STRING: if (field->flags & BINARY_FLAG) { #ifndef NO_BUFFER_TYPE v->item[i].type = T_BUFFER; v->item[i].u.buf = allocate_buffer(field->max_length); write_buffer(v->item[i].u.buf, 0, target_row[i], field->max_length); #else v->item[i] = const0u; #endif } else { v->item[i].type = T_STRING; if (target_row[i]) { v->item[i].subtype = STRING_MALLOC; v->item[i].u.string = string_copy(target_row[i], "MySQL_fetch"); } else { v->item[i].subtype = STRING_CONSTANT; v->item[i].u.string = ""; } } break; default: v->item[i] = const0u; break; } } } mysql_field_seek(c->mysql.results, 0); return v; }
static array_t *SQLite3_fetch (dbconn_t * c, int row) { int cols, last_row, length, i, r; array_t *v; if (!c->SQLite3.results) { return &the_null_array; } if (c->SQLite3.step_res && c->SQLite3.step_res != SQLITE_ROW) { return &the_null_array; } if (row < 0 || row > c->SQLite3.nrows) { return &the_null_array; } cols = sqlite3_column_count(c->SQLite3.results); if (cols < 1) { return &the_null_array; } /* If the fetch is for row 0 then we don't return a row from the prepared * statement, instead we return an array containing the column names. This * ability is useful in a number of circumstances when the column names are * not known in advance for a query. We do not step the statement nor do we * adjust the last_row index since sqlite provides a method to obtain the * column names at any time. */ if (row == 0) { v = allocate_empty_array(cols); for (i = 0; i< cols; i++) { v->item[i].type = T_STRING; v->item[i].subtype = STRING_MALLOC; v->item[i].u.string = string_copy((char *)sqlite3_column_name(c->SQLite3.results, i), "SQLite3_fetch"); } return v; } /* There is no quick entry to a row in the prepared statement. Thus we have * too loop through till we reach the desired row, but only if the last row * that we fetched is not the previous row... confused? join the club. */ last_row = c->SQLite3.last_row; /* If the requested row is before the last row that was accessed then we * reset the compiled statement before continuing. This is because we can't * just select a row at will using sqlite and we can't rewind a step either. * We could just reset the result statement at the end of this function like * the msql and mysql versions, but that gets expensive next time it's called * if we need to walk through everything again... sigh */ if (row < last_row) { sqlite3_reset(c->SQLite3.results); c->SQLite3.last_row = 0; c->SQLite3.step_res = 0; last_row = 0; } /* If the requested row is the same as the last one, ie: it's been requested * again! we do not need to step forward, so we miss the row location loop * and get straight to the nitty gritty of building the result array. If not * we loop through from the last_row requested to the one requested this time * using sqlite3_step(). As long as the result is SQLITE_ROW we move on, if * not then either an error occured or there are no more rows so we return a * null array. The result is stored in the sqlite structure for later checks * so if fetch is called again on a completed or errornous statement we can * fail out sooner saving time. */ if ((row != last_row) && (last_row < row)) { for (i = last_row; i < row; i++) { c->SQLite3.step_res = sqlite3_step(c->SQLite3.results); if (c->SQLite3.step_res == SQLITE_ROW) break; else return &the_null_array; } } v = allocate_empty_array(cols); for (i = 0; i < cols; i++) { switch (sqlite3_column_type(c->SQLite3.results, i)) { case SQLITE_INTEGER: v->item[i].type = T_NUMBER; v->item[i].u.number = sqlite3_column_int(c->SQLite3.results, i); break; case SQLITE_FLOAT: v->item[i].type = T_REAL; v->item[i].u.real = (double)sqlite3_column_double(c->SQLite3.results, i); break; case SQLITE3_TEXT: v->item[i].type = T_STRING; v->item[i].subtype = STRING_MALLOC; v->item[i].u.string = string_copy((char *)sqlite3_column_text(c->SQLite3.results, i), "SQLite3_fetch"); break; case SQLITE_BLOB: #ifndef NO_BUFFER_TYPE length = sqlite3_column_bytes(c->SQLite3.results, i); v->item[i].type = T_BUFFER; v->item[i].u.buf = allocate_buffer(length); write_buffer(v->item[i].u.buf, 0, (char *)sqlite3_column_blob(c->SQLite3.results, i), length); #else v->item[i] = const0u; #endif break; default: v->item[i] = const0u; break; } } c->SQLite3.last_row = row; return v; }
void f_db_connect (void) { char *errormsg = 0; const char *user = "", *database, *host; db_t *db; array_t *info; svalue_t *mret; int handle, ret = 0, args = 0, type; #ifdef DEFAULT_DB type = DEFAULT_DB; #else type = 0; #endif switch (st_num_arg) { case 4: type = (sp - (args++))->u.number; case 3: user = (sp - (args++))->u.string; case 2: database = (sp - (args++))->u.string; case 1: host = (sp - (args++))->u.string; } info = allocate_empty_array(3); info->item[0].type = info->item[1].type = info->item[2].type = T_STRING; info->item[0].subtype = info->item[1].subtype = info->item[2].subtype = STRING_MALLOC; info->item[0].u.string = string_copy(database, "f_db_connect:1"); if (*host) info->item[1].u.string = string_copy(host, "f_db_connect:2"); else info->item[1] = const0; info->item[2].u.string = string_copy(user, "f_db_connect:3"); mret = valid_database("connect", info); handle = create_db_conn(); if (!handle) { pop_n_elems(args); push_number(0); return; } db = find_db_conn(handle); switch (type) { default: /* fallthrough */ #ifdef USE_MSQL #if USE_MSQL - 0 case USE_MSQL: #endif db->type = &msql; break; #endif #ifdef USE_MYSQL #if USE_MYSQL - 0 case USE_MYSQL: #endif db->type = &mysql; break; #endif #ifdef USE_SQLITE2 #if USE_SQLITE2 - 0 case USE_SQLITE2: #endif db->type = &SQLite2; break; #endif #ifdef USE_SQLITE3 #if USE_SQLITE3 - 0 case USE_SQLITE3: #endif db->type = &SQLite3; break; #endif #ifdef USE_POSTGRES #if USE_POSTGRES - 0 case USE_POSTGRES: #endif db->type = &postgres; break; #endif } if (db->type->connect) { ret = db->type->connect(&(db->c), host, database, user, (mret != (svalue_t *)-1 && mret->type == T_STRING ? mret->u.string : 0)); } pop_n_elems(args); if (!ret) { if (db->type->error) { errormsg = db->type->error(&(db->c)); push_malloced_string(errormsg); } else { push_number(0); } free_db_conn(db); } else { push_number(handle); } }
static array_t *SQLite2_fetch (dbconn_t * c, int row) { int last_row, length, i, l, r; char *p_end; const char *tail; double d; array_t *v; if (!c->SQLite2.vm) { /* We don't have a vm yet because the sql has not been compiled. * This is down to db_exec using sqlite_get_table to execute the sql in the * first instance. This is the reason we saved the sql into the SQLite * structure, compile it now and create a vm. We return a null array only * if the compile fails. */ r = sqlite_compile(c->SQLite2.handle, c->SQLite2.sql, NULL, &c->SQLite2.vm, &c->SQLite2.errormsg); if (r != SQLITE_OK || !c->SQLite2.vm) return &the_null_array; } if (c->SQLite2.step_res && c->SQLite2.step_res != SQLITE_ROW) { return &the_null_array; } if (row < 0 || row > c->SQLite2.nrows) { return &the_null_array; } if (c->SQLite2.ncolumns < 1) { return &the_null_array; } /* If the fetch is for row 0 then we don't return a row containing data values * instead we return the column names. This has proven quite useful in a number * of circumstances when they are unknown ahead of the query. Unlike SQLite3 we * have no means of obtaining them without stepping the virtual machine so we * have no choice. We will have to check the last_row and step_rc later to make * sure we use the values here before we step again. */ if (row == 0) { c->SQLite2.step_res = sqlite_step(c->SQLite2.vm, NULL, &c->SQLite2.values, &c->SQLite2.col_names); if (c->SQLite2.step_res == SQLITE_ROW || c->SQLite2.step_res == SQLITE_DONE) { v = allocate_empty_array(c->SQLite2.ncolumns); for (i = 0; i < c->SQLite2.ncolumns; i++) { v->item[i].type = T_STRING; v->item[i].subtype = STRING_MALLOC; v->item[i].u.string = string_copy((char *)c->SQLite2.col_names[i], "SQLite2_fetch"); } return v; } return &the_null_array; } /* There is no quick entry to a row in the prepared statement. Thus we have * too loop through until we reach the desired row, but only if the last row * that we fetched is not the previous row... confused? join the club. */ last_row = c->SQLite2.last_row; /* If the requested row is before the last row that was accessed then we need * to re-compile the sql and recreate the virtual machine. SQLite3 provides a * facility to reset a vm however SQLite2 does not. This is a downfall of * SQLite in general though, we need to restart everything and walk through * all of the results again until we get to the row we want... sigh */ if (row < last_row) { free(c->SQLite2.errormsg); sqlite_finalize(c->SQLite2.vm, NULL); if (sqlite_compile(c->SQLite2.handle, c->SQLite2.sql, &tail, &c->SQLite2.vm, &c->SQLite2.errormsg) != SQLITE_OK) return 0; c->SQLite2.last_row = 0; c->SQLite2.step_res = 0; last_row = 0; } /* If the requested row is the same as the last one, ie: it's been requested * again! we do not need to step forward, so we miss the row location loop * and get straight to the nitty gritty of building the result array. If not * we loop through from the last_row requested to the one requested this time * using sqlite_step(). As long as the result is SQLITE_ROW we move on, if * not then either an error occured or there are no more rows so we return a * null array. The result is stored in the SQLite structure for later checks * so if fetch is called again on a completed or errornous statement we can * fail out sooner saving time. */ if ((row != last_row) && (last_row < row)) { for (i = last_row; i < row; i++) { c->SQLite2.step_res = sqlite_step(c->SQLite2.vm, NULL, &c->SQLite2.values, &c->SQLite2.col_names); if (c->SQLite2.step_res == SQLITE_ROW) break; else return &the_null_array; } } /* SQLite v2 does not provide any functions for obtaining the values based on * their datatypes like v3 does. It is completely typeless and everything is * returned as a (char *). Thus we need a way of determining if the value is * numeric or a string. I do make some assumptions here, but all in all it * does work for the vast majority of cases. There is no support for blobs * to be returned as LPC buffers with v2. Support for binary data in v2 is * suspect at best and is not recommended anyway, if you need that use v3. * * To determine the datatype, we do the following. Run the value through * strtoul() if it fails then the value could not be converted to a number * so we assume it's a string and return it as such. If it works but also * has trailing data, then it might be a real number or a string. Both * "12.34" and "12 bottles" will cause strtoul() to work returning 12 but * both will also have trailing data. Thus we try converting it to a real * number using strtod() if this fails then we assume its a string that * starts with a number ie: "12 bottles" and return it as a string. If it * works then we return it as a real number (float). * * It's by no means perfect, but it does catch pretty much everything I've * thrown at it and is the best solution, bar walking the embedded datatype * description, if one was set, and working it out from that. */ v = allocate_empty_array(c->SQLite2.ncolumns); for (i = 0; i < c->SQLite2.ncolumns; i++) { /* If we have a NULL value get out now or we'll segfault */ if (c->SQLite2.values[i] == NULL) { v->item[i] = const0u; continue; } errno = 0; l = strtoul(c->SQLite2.values[i], &p_end, 10); if (errno != 0 || c->SQLite2.values[i] == p_end) { /* The conversion failed so assume it's a string */ v->item[i].type = T_STRING; v->item[i].subtype = STRING_MALLOC; v->item[i].u.string = string_copy((char *)c->SQLite2.values[i], "SQLite2_fetch"); } else if (*p_end != 0) { /* The conversion left trailing characters behind, see if its a float */ errno = 0; d = strtod(c->SQLite2.values[i], &p_end); if (errno != 0 || c->SQLite2.values[i] == p_end || *p_end != 0) { /* The conversion to float failed so it must be a string */ v->item[i].type = T_STRING; v->item[i].subtype = STRING_MALLOC; v->item[i].u.string = string_copy((char *)c->SQLite2.values[i], "SQLite2_fetch"); } else { /* It was a floating point number */ v->item[i].type = T_REAL; v->item[i].u.real = (double)d; } } else if (errno == 0) { /* It was an integer */ v->item[i].type = T_NUMBER; v->item[i].u.number = (int)l; } else { /* No idea what it was */ v->item[i] = const0u; } } c->SQLite2.last_row = row; return v; }
rmp->begin = rmpb_tmp; rmp->end = tmp = rmpe_tmp; used+=tmpreg->ovector[1]; rmp->tok_i = regindex; rmp->next = (struct reg_match *) 0; } else break; if (rmp->begin == tmp && (!*++tmp)) break; } sv = ret->item; sv->type = T_ARRAY; sv1 = (sv->u.arr = allocate_empty_array(2*num_match + 1))->item; sv++; sv->type = T_ARRAY; sv2 = (sv->u.arr = allocate_empty_array(2*num_match + 1))->item; rmp = rmph; tmp = str->u.string; while (num_match--){ char *svtmp; length = rmp->begin - tmp; sv1->type = T_STRING; sv1->subtype = STRING_MALLOC;
array_t *explode_string P4(char *, str, int, slen, char *, del, int, len) { char *p, *beg, *lastdel = (char *) NULL; int num, j, limit; array_t *ret; char *buff, *tmp; short sz; if (!slen) return null_array(); /* return an array of length strlen(str) -w- one character per element */ if (len == 0) { sz = 1; if (slen > max_array_size) { slen = max_array_size; } ret = allocate_empty_array(slen); for (j = 0; j < slen; j++) { ret->item[j].type = T_STRING; ret->item[j].subtype = STRING_MALLOC; ret->item[j].u.string = tmp = new_string(1, "explode_string: tmp"); tmp[0] = str[j]; tmp[1] = '\0'; } return ret; } if (len == 1) { char delimeter; delimeter = *del; /* * Skip leading 'del' strings, if any. */ while (*str == delimeter) { str++; slen--; if (str[0] == '\0') { return null_array(); } #ifdef SANE_EXPLODE_STRING break; #endif } /* * Find number of occurences of the delimiter 'del'. */ for (p = str, num = 0; *p;) { if (*p == delimeter) { num++; lastdel = p; } p++; } /* * Compute number of array items. It is either number of delimiters, * or, one more. */ limit = max_array_size; if (lastdel != (str + slen - 1)) { num++; limit--; } if (num > max_array_size) { num = max_array_size; } ret = allocate_empty_array(num); for (p = str, beg = str, num = 0; *p && (num < limit);) { if (*p == delimeter) { DEBUG_CHECK(num >= ret->size, "Index out of bounds in explode!\n"); sz = p - beg; ret->item[num].type = T_STRING; ret->item[num].subtype = STRING_MALLOC; ret->item[num].u.string = buff = new_string(p - beg, "explode_string: buff"); strncpy(buff, beg, p - beg); buff[p - beg] = '\0'; num++; beg = ++p; } else { p++; } } /* Copy last occurence, if there was not a 'del' at the end. */ if (*beg != '\0') { ret->item[num].type = T_STRING; ret->item[num].subtype = STRING_MALLOC; ret->item[num].u.string = string_copy(beg, "explode_string: last, len == 1"); } return ret; } /* len == 1 */ /* * Skip leading 'del' strings, if any. */ while (strncmp(str, del, len) == 0) { str += len; slen -= len; if (str[0] == '\0') { return null_array(); } #ifdef SANE_EXPLODE_STRING break; #endif } /* * Find number of occurences of the delimiter 'del'. */ for (p = str, num = 0; *p;) { if (strncmp(p, del, len) == 0) { num++; lastdel = p; p += len; } else { p++; } } /* * Compute number of array items. It is either number of delimiters, or, * one more. */ if ((slen <= len) || (lastdel != (str + slen - len))) { num++; } if (num > max_array_size) { num = max_array_size; } ret = allocate_empty_array(num); limit = max_array_size - 1; /* extra element can be added after loop */ for (p = str, beg = str, num = 0; *p && (num < limit);) { if (strncmp(p, del, len) == 0) { if (num >= ret->size) fatal("Index out of bounds in explode!\n"); ret->item[num].type = T_STRING; ret->item[num].subtype = STRING_MALLOC; ret->item[num].u.string = buff = new_string(p - beg, "explode_string: buff"); strncpy(buff, beg, p - beg); buff[p - beg] = '\0'; num++; beg = p + len; p = beg; } else { p++; } } /* Copy last occurence, if there was not a 'del' at the end. */ if (*beg != '\0') { ret->item[num].type = T_STRING; ret->item[num].subtype = STRING_MALLOC; ret->item[num].u.string = string_copy(beg, "explode_string: last, len != 1"); } return ret; }
/* FIXME: most of the #ifdefs here should be based on configure checks instead. Same for rusage() */ void f_localtime (void) { struct tm *tm; array_t *vec; time_t lt; #ifdef sequent struct timezone tz; #endif lt = sp->u.number; tm = localtime(<); vec = allocate_empty_array(11); vec->item[LT_SEC].type = T_NUMBER; vec->item[LT_SEC].u.number = tm->tm_sec; vec->item[LT_MIN].type = T_NUMBER; vec->item[LT_MIN].u.number = tm->tm_min; vec->item[LT_HOUR].type = T_NUMBER; vec->item[LT_HOUR].u.number = tm->tm_hour; vec->item[LT_MDAY].type = T_NUMBER; vec->item[LT_MDAY].u.number = tm->tm_mday; vec->item[LT_MON].type = T_NUMBER; vec->item[LT_MON].u.number = tm->tm_mon; vec->item[LT_YEAR].type = T_NUMBER; vec->item[LT_YEAR].u.number = tm->tm_year + 1900; vec->item[LT_WDAY].type = T_NUMBER; vec->item[LT_WDAY].u.number = tm->tm_wday; vec->item[LT_YDAY].type = T_NUMBER; vec->item[LT_YDAY].u.number = tm->tm_yday; vec->item[LT_GMTOFF].type = T_NUMBER; vec->item[LT_ZONE].type = T_STRING; vec->item[LT_ZONE].subtype = STRING_MALLOC; vec->item[LT_ISDST].type = T_NUMBER; #if defined(BSD42) || defined(apollo) || defined(_AUX_SOURCE) \ || defined(OLD_ULTRIX) /* 4.2 BSD doesn't seem to provide any way to get these last three values */ vec->item[LT_GMTOFF].u.number = 0; vec->item[LT_ZONE].type = T_NUMBER; vec->item[LT_ZONE].u.number = 0; vec->item[LT_ISDST].u.number = -1; #else /* BSD42 */ vec->item[LT_ISDST].u.number = tm->tm_isdst; #if defined(sequent) vec->item[LT_GMTOFF].u.number = 0; gettimeofday(NULL, &tz); vec->item[LT_GMTOFF].u.number = tz.tz_minuteswest; vec->item[LT_ZONE].u.string = string_copy(timezone(tz.tz_minuteswest, tm->tm_isdst), "f_localtime"); #else /* sequent */ #if (defined(hpux) || defined(_SEQUENT_) || defined(_AIX) || defined(SunOS_5) \ || defined(SVR4) || defined(sgi) || defined(linux) || defined(cray) \ || defined(LATTICE) || defined(SCO)) if (!tm->tm_isdst) { vec->item[LT_GMTOFF].u.number = timezone; vec->item[LT_ZONE].u.string = string_copy(tzname[0], "f_localtime"); } else { #if (defined(_AIX) || defined(hpux) || defined(linux) || defined(cray) \ || defined(LATTICE)) vec->item[LT_GMTOFF].u.number = timezone; #else vec->item[LT_GMTOFF].u.number = altzone; #endif vec->item[LT_ZONE].u.string = string_copy(tzname[1], "f_localtime"); } #else #ifndef WIN32 vec->item[LT_GMTOFF].u.number = tm->tm_gmtoff; vec->item[LT_ZONE].u.string = string_copy(tm->tm_zone, "f_localtime"); #else vec->item[LT_GMTOFF].u.number = _timezone; vec->item[LT_ZONE].u.string = string_copy(_tzname[_daylight?1:0],"f_localtime"); #endif #endif #endif /* sequent */ #endif /* BSD42 */ put_array(vec); }
void filter_array P2(svalue_t *, arg, int, num_arg) { array_t *vec = arg->u.arr, *r; int size; if ((size = vec->size) < 1) { pop_n_elems(num_arg - 1); return; } else { funptr_t *fp; object_t *ob = 0; char *func; char *flags = new_string(size, "TEMP: filter: flags"); svalue_t *extra, *v; int res = 0, cnt, numex = 0; push_malloced_string(flags); if ((arg+1)->type == T_FUNCTION){ fp = (arg+1)->u.fp; if (num_arg > 2) extra = arg+2, numex = num_arg - 2; } else { func = (arg+1)->u.string; if (num_arg < 3) ob = current_object; else { if ((arg+2)->type == T_OBJECT) ob = (arg+2)->u.ob; else if ((arg+2)->type == T_STRING){ if ((ob = find_object(arg[2].u.string)) && !object_visible(ob)) ob = 0; } if (!ob) bad_argument(arg+2, T_STRING | T_OBJECT, 3, F_FILTER); if (num_arg > 3) extra = arg + 3, numex = num_arg - 3; } } for (cnt = 0; cnt < size; cnt++){ push_svalue(vec->item + cnt); if (numex) push_some_svalues(extra, numex); v = ob ? apply(func, ob, 1 + numex, ORIGIN_EFUN) : call_function_pointer(fp, 1 + numex); if (!IS_ZERO(v)){ flags[cnt] = 1; res++; } else flags[cnt] = 0; } r = allocate_empty_array(res); if (res){ while (cnt--) { if (flags[cnt]) assign_svalue_no_free(&r->item[--res], vec->item+cnt); } } FREE_MSTR(flags); sp--; pop_n_elems(num_arg - 1); free_array(vec); sp->u.arr = r; } }