/usr/include/pike8.0/pike/array.h is in pike8.0-dev 8.0.498-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | /*
|| This file is part of Pike. For copyright information see COPYRIGHT.
|| Pike is distributed under GPL, LGPL and MPL. See the file COPYING
|| for more information.
*/
#ifndef ARRAY_H
#define ARRAY_H
#include "svalue.h"
#include "dmalloc.h"
/* This debug tool writes out messages whenever arrays with unfinished
* type fields are encountered. */
/* #define TRACE_UNFINISHED_TYPE_FIELDS */
/**
* A Pike array is represented as a 'struct array' with all the
* needed svalues malloced in the same block.
*
* @see type_field
*/
struct array
{
PIKE_MEMORY_OBJECT_MEMBERS;
struct array *next; /**< we need to keep track of all arrays */
struct array *prev; /**< Another pointer, so we don't have to search
* when freeing arrays */
INT32 size; /**< number of svalues in this array */
INT32 malloced_size; /**< number of svalues that can fit in this array */
TYPE_FIELD type_field;/**< A bitfield with one bit for each type of
* data in this array.
Bits can be set that don't exist in the array. type_field is
* initialized to BIT_MIXED|BIT_UNFINISHED for newly allocated
* arrays so that they can be modified without having to update
* this. It should be set accurately when that's done, though. */
INT16 flags; /**< ARRAY_* flags */
struct svalue *item; /**< the array of svalues */
struct svalue real_item[1];
};
#define ARRAY_WEAK_FLAG 1
#define ARRAY_CYCLIC 2
#define ARRAY_LVALUE 4
PMOD_EXPORT extern struct array empty_array, weak_empty_array;
extern struct array *first_array;
extern struct array *gc_internal_array;
#if defined(DEBUG_MALLOC) && defined(PIKE_DEBUG)
#define ITEM(X) (((struct array *)(debug_malloc_pass((X))))->item)
#else
#define ITEM(X) ((X)->item)
#endif
/* These are arguments for the function 'merge' which merges two sorted
* set stored in arrays in the way you specify
*/
#define PIKE_ARRAY_OP_A 1
#define PIKE_ARRAY_OP_SKIP_A 2
#define PIKE_ARRAY_OP_TAKE_A 3
#define PIKE_ARRAY_OP_B 4
#define PIKE_ARRAY_OP_SKIP_B 8
#define PIKE_ARRAY_OP_TAKE_B 12
#define PIKE_MINTERM(X,Y,Z) (((X)<<8)+((Y)<<4)+(Z))
#define PIKE_ARRAY_OP_AND PIKE_MINTERM(PIKE_ARRAY_OP_SKIP_A,PIKE_ARRAY_OP_SKIP_A | PIKE_ARRAY_OP_TAKE_B,PIKE_ARRAY_OP_SKIP_B)
#define PIKE_ARRAY_OP_AND_LEFT PIKE_MINTERM(PIKE_ARRAY_OP_SKIP_A,PIKE_ARRAY_OP_SKIP_B | PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_SKIP_B)
#define PIKE_ARRAY_OP_OR PIKE_MINTERM(PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_SKIP_A | PIKE_ARRAY_OP_TAKE_B,PIKE_ARRAY_OP_TAKE_B)
#define PIKE_ARRAY_OP_OR_LEFT PIKE_MINTERM(PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_SKIP_B | PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_TAKE_B)
#define PIKE_ARRAY_OP_XOR PIKE_MINTERM(PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_SKIP_A | PIKE_ARRAY_OP_SKIP_B,PIKE_ARRAY_OP_TAKE_B)
#define PIKE_ARRAY_OP_ADD PIKE_MINTERM(PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_TAKE_A | PIKE_ARRAY_OP_TAKE_B ,PIKE_ARRAY_OP_TAKE_B)
#define PIKE_ARRAY_OP_SUB PIKE_MINTERM(PIKE_ARRAY_OP_TAKE_A,PIKE_ARRAY_OP_SKIP_A ,PIKE_ARRAY_OP_SKIP_B)
/**
* This macro frees one reference to the array V. If the reference
* is the last reference to the array, it will free the memory used
* by the array V.
* @param V an array struct to be freed.
*/
#define free_array(V) do{ \
struct array *v_=(V); \
debug_malloc_touch(v_); \
DO_IF_DEBUG ( \
DO_IF_PIKE_CLEANUP ( \
if (gc_external_refs_zapped) \
gc_check_zapped (v_, PIKE_T_ARRAY, __FILE__, __LINE__))); \
if(!sub_ref(v_)) \
really_free_array(v_); \
}while(0)
#define allocate_array(X) low_allocate_array((X),0)
#define allocate_array_no_init(X,Y) low_allocate_array((X),(Y))
/* Special value used for cmpfuns to signify that two values aren't
* equal and have no order relation, i.e. one is neither greater nor
* less than the other. It consists of the largest bit (under the sign
* bit) set. */
#define CMPFUN_UNORDERED (INT_MAX - (INT_MAX >> 1))
typedef int (*cmpfun)(const struct svalue *, const struct svalue *);
typedef int (*short_cmpfun)(union anything *, union anything *);
typedef short_cmpfun (*cmpfun_getter)(TYPE_T);
#define low_allocate_array(size, extra_space) \
dmalloc_touch (struct array *, \
real_allocate_array ((size), (extra_space)))
/* Prototypes begin here */
PMOD_EXPORT struct array *real_allocate_array(ptrdiff_t size, ptrdiff_t extra_space);
PMOD_EXPORT void really_free_array(struct array *v);
PMOD_EXPORT void do_free_array(struct array *a);
PMOD_EXPORT void clear_array(struct array *a);
PMOD_EXPORT struct array *array_set_flags(struct array *a, int flags);
PMOD_EXPORT void array_index(struct svalue *s,struct array *v,INT32 ind);
PMOD_EXPORT struct array *array_column (struct array *data, struct svalue *index,
int destructive);
PMOD_EXPORT void simple_array_index_no_free(struct svalue *s,
struct array *a,struct svalue *ind);
PMOD_EXPORT void array_free_index(struct array *v,INT32 ind);
PMOD_EXPORT void simple_set_index(struct array *a,struct svalue *ind,struct svalue *s);
PMOD_EXPORT struct array *array_insert(struct array *v,struct svalue *s,INT32 ind);
void o_append_array(INT32 args);
PMOD_EXPORT struct array *resize_array(struct array *a, INT32 size);
PMOD_EXPORT struct array *array_shrink(struct array *v, ptrdiff_t size);
PMOD_EXPORT struct array *array_remove(struct array *v,INT32 ind);
PMOD_EXPORT ptrdiff_t array_search(struct array *v, struct svalue *s,
ptrdiff_t start);
PMOD_EXPORT struct array *slice_array(struct array *v, ptrdiff_t start,
ptrdiff_t end);
PMOD_EXPORT struct array *friendly_slice_array(struct array *v,
ptrdiff_t start,
ptrdiff_t end);
PMOD_EXPORT struct array *copy_array(struct array *v);
PMOD_EXPORT void check_array_for_destruct(struct array *v);
PMOD_EXPORT INT32 array_find_destructed_object(struct array *v);
INT32 *get_order(struct array *v, cmpfun fun);
int set_svalue_cmpfun(const struct svalue *a, const struct svalue *b);
int alpha_svalue_cmpfun(const struct svalue *a, const struct svalue *b);
PMOD_EXPORT void sort_array_destructively(struct array *v);
PMOD_EXPORT INT32 *stable_sort_array_destructively(struct array *v);
PMOD_EXPORT INT32 *get_set_order(struct array *a);
PMOD_EXPORT INT32 *get_switch_order(struct array *a);
PMOD_EXPORT INT32 *get_alpha_order(struct array *a);
INT32 set_lookup(struct array *a, struct svalue *s);
INT32 switch_lookup(struct array *a, struct svalue *s);
PMOD_EXPORT struct array *order_array(struct array *v, INT32 *order);
PMOD_EXPORT struct array *reorder_and_copy_array(struct array *v, INT32 *order);
PMOD_EXPORT TYPE_FIELD array_fix_type_field(struct array *v);
#ifdef PIKE_DEBUG
PMOD_EXPORT void array_check_type_field(struct array *v);
#endif
PMOD_EXPORT union anything *low_array_get_item_ptr(struct array *a,
INT32 ind,
TYPE_T t);
PMOD_EXPORT union anything *array_get_item_ptr(struct array *a,
struct svalue *ind,
TYPE_T t);
INT32 * merge(struct array *a,struct array *b,INT32 opcode);
PMOD_EXPORT struct array *array_zip(struct array *a, struct array *b,INT32 *zipper);
PMOD_EXPORT struct array *add_arrays(struct svalue *argp, INT32 args);
PMOD_EXPORT int array_equal_p(struct array *a, struct array *b, struct processing *p);
PMOD_EXPORT struct array *merge_array_with_order(struct array *a,
struct array *b, INT32 op);
PMOD_EXPORT struct array *subtract_arrays(struct array *a, struct array *b);
PMOD_EXPORT struct array *and_arrays(struct array *a, struct array *b);
int array_is_constant(struct array *a,
struct processing *p);
node *make_node_from_array(struct array *a);
PMOD_EXPORT void push_array_items(struct array *a);
void describe_array_low(struct array *a, struct processing *p, int indent);
#ifdef PIKE_DEBUG
void simple_describe_array(struct array *a);
void describe_index(struct array *a,
int e,
struct processing *p,
int indent);
#endif
void describe_array(struct array *a,struct processing *p,int indent);
PMOD_EXPORT struct array *aggregate_array(INT32 args);
PMOD_EXPORT struct array *append_array(struct array *a, struct svalue *s);
PMOD_EXPORT struct array *explode(struct pike_string *str,
struct pike_string *del);
PMOD_EXPORT struct pike_string *implode(struct array *a,struct pike_string *del);
PMOD_EXPORT struct array *copy_array_recursively(struct array *a,
struct mapping *p);
PMOD_EXPORT void apply_array(struct array *a, INT32 args, int flags);
PMOD_EXPORT struct array *reverse_array(struct array *a, int start, int end);
void array_replace(struct array *a,
struct svalue *from,
struct svalue *to);
#ifdef PIKE_DEBUG
PMOD_EXPORT void check_array(struct array *a);
void check_all_arrays(void);
#endif
PMOD_EXPORT void visit_array (struct array *a, int action, void *extra);
void gc_mark_array_as_referenced(struct array *a);
void real_gc_cycle_check_array(struct array *a, int weak);
unsigned gc_touch_all_arrays(void);
void gc_check_all_arrays(void);
void gc_mark_all_arrays(void);
void gc_cycle_check_all_arrays(void);
void gc_zap_ext_weak_refs_in_arrays(void);
size_t gc_free_all_unreferenced_arrays(void);
#ifdef PIKE_DEBUG
void debug_dump_type_field(TYPE_FIELD t);
void debug_dump_array(struct array *a);
#endif
void count_memory_in_arrays(size_t *num_, size_t *size_);
PMOD_EXPORT struct array *explode_array(struct array *a, struct array *b);
PMOD_EXPORT struct array *implode_array(struct array *a, struct array *b);
/* Automap internals. */
void assign_array_level_value( struct array *a, struct svalue *b, int level );
void assign_array_level( struct array *a, struct array *b, int level );
/* Prototypes end here */
#define array_get_flags(a) ((a)->flags)
#define visit_array_ref(A, REF_TYPE, EXTRA) \
visit_ref (pass_array (A), (REF_TYPE), \
(visit_thing_fn *) &visit_array, (EXTRA))
#define gc_cycle_check_array(X, WEAK) \
gc_cycle_enqueue((gc_cycle_check_cb *) real_gc_cycle_check_array, (X), (WEAK))
/** Macros for aggregating results built on the stack into an array,
* while maintaining a bound on stack consumption. Use like this:
*
* check_stack(120);
* BEGIN_AGGREGATE_ARRAY(estimated_size_of_final_array) {
* for (...) {
* ... stuff that produces a value on the stack ...
* DO_AGGREGATE_ARRAY(120);
* ...
* }
* } END_AGGREGATE_ARRAY;
*
* The array is left on top of the stack.
*/
#define AGGR_ARR_PROLOGUE(base_sval, estimated_size) do { \
push_array(allocate_array_no_init(0, (estimated_size))); \
base_sval = Pike_sp; \
if (base_sval[-1].u.array->malloced_size) \
base_sval[-1].u.array->type_field = (BIT_MIXED | BIT_UNFINISHED); \
} while (0)
#define AGGR_ARR_CHECK(base_sval, max_keep_on_stack) \
do { \
ptrdiff_t diff__ = Pike_sp - base_sval; \
if (diff__ > (max_keep_on_stack)) { \
INT32 oldsize__ = base_sval[-1].u.array->size; \
ACCEPT_UNFINISHED_TYPE_FIELDS { \
base_sval[-1].u.array = \
resize_array(base_sval[-1].u.array, oldsize__ + diff__); \
} END_ACCEPT_UNFINISHED_TYPE_FIELDS; \
/* Unless the user does something, the type field will contain */ \
/* BIT_MIXED|BIT_UNFINISHED from the allocation above. */ \
memcpy(ITEM(base_sval[-1].u.array) + oldsize__, \
base_sval, diff__ * sizeof(struct svalue)); \
Pike_sp = base_sval; \
} \
} while (0)
#define AGGR_ARR_EPILOGUE(base_sval) do { \
ptrdiff_t diff__ = Pike_sp - base_sval; \
if (!diff__) { \
if (!base_sval[-1].u.array->size) { \
free_array (base_sval[-1].u.array); \
add_ref (base_sval[-1].u.array = &empty_array); \
} \
} \
else \
AGGR_ARR_CHECK (base_sval, 0); \
if (base_sval[-1].u.array->type_field & BIT_UNFINISHED) \
array_fix_type_field(Pike_sp[-1].u.array); \
DO_IF_DEBUG(if (TYPEOF(Pike_sp[-1]) != T_ARRAY) { \
Pike_fatal("Lost track of aggregated array.\n"); \
}); \
} while (0)
#define BEGIN_AGGREGATE_ARRAY(estimated_size) do { \
struct svalue *base__; \
AGGR_ARR_PROLOGUE (base__, estimated_size);
#define DO_AGGREGATE_ARRAY(max_keep_on_stack) \
AGGR_ARR_CHECK (base__, max_keep_on_stack)
#define END_AGGREGATE_ARRAY \
AGGR_ARR_EPILOGUE (base__); \
} while (0)
/**
* Extract an svalue from an array
*/
#define array_index_no_free(S,A,I) do { \
INT32 ind_=(I); \
struct array *v_=(A); \
DO_IF_DEBUG( \
if(ind_<0 || ind_>=v_->size) \
Pike_fatal("Illegal index in low level index routine.\n"); \
) \
\
assign_svalue_no_free((S), ITEM(v_) + ind_); \
}while(0)
/**
* Sets an index in an array.
*
* @param V the array to modify
* @param I the index of the array to set
* @param S the svalue to set
*/
#define array_set_index_no_free(V,I,S) do { \
struct array *v_=(V); \
INT32 index_=(I); \
struct svalue *s_=(S); \
\
DO_IF_DEBUG( \
if(index_<0 || index_>v_->size) \
Pike_fatal("Illegal index in low level array set routine.\n"); \
) \
\
check_destructed(s_); \
\
v_->type_field |= 1 << TYPEOF(*s_); \
assign_svalue_no_free( ITEM(v_) + index_, s_); \
}while(0)
#define array_set_index(V,I,S) do { \
struct array *v_=(V); \
INT32 index_=(I); \
struct svalue *s_=(S); \
\
DO_IF_DEBUG( \
if(index_<0 || index_>v_->size) \
Pike_fatal("Illegal index in low level array set routine.\n"); \
) \
\
check_destructed(s_); \
\
v_->type_field |= 1 << TYPEOF(*s_); \
assign_svalue( ITEM(v_) + index_, s_); \
}while(0)
#define array_fix_unfinished_type_field(A) do { \
struct array *a_ = (A); \
if (a_->type_field & BIT_UNFINISHED) { \
DO_IF_DEBUG (array_check_type_field (a_)); \
array_fix_type_field (a_); \
} \
} while (0)
#ifdef TRACE_UNFINISHED_TYPE_FIELDS
/* Note: These macros don't support thread switches. */
extern PMOD_EXPORT int accept_unfinished_type_fields;
PMOD_EXPORT void dont_accept_unfinished_type_fields (void *orig);
#define ACCEPT_UNFINISHED_TYPE_FIELDS do { \
ONERROR autf_uwp_; \
int orig_autf_ = accept_unfinished_type_fields; \
accept_unfinished_type_fields++; \
SET_ONERROR (autf_uwp_, dont_accept_unfinished_type_fields, \
(void *) orig_autf_); \
do
#define END_ACCEPT_UNFINISHED_TYPE_FIELDS \
while (0); \
accept_unfinished_type_fields = orig_autf_; \
UNSET_ONERROR (autf_uwp_); \
} while (0)
#else
#define ACCEPT_UNFINISHED_TYPE_FIELDS do
#define END_ACCEPT_UNFINISHED_TYPE_FIELDS while (0)
#endif
#endif /* ARRAY_H */
|