Skip to content
Snippets Groups Projects
Select Git revision
  • 56d0bc72cdefaa06deec1030f039f43f967cf603
  • master default protected
  • siv-mode
  • delete-des-compat
  • delete-rsa_blind
  • aes-struct-layout
  • master-updates
  • release-3.4-fixes
  • struct-layout
  • attribute-deprecated
  • rename-data-symbols
  • x86_64-sha_ni-sha256
  • ecc-params-tweak
  • delete-old-aes
  • cmac-support
  • x86_64-sha_ni-sha1
  • gcm-ctr-opt
  • ctr-opt
  • skein
  • api-opaque-fix
  • curve448
  • nettle_3.4.1_release_20181204
  • nettle_3.4.1rc1
  • nettle_3.4_release_20171119
  • nettle_3.4rc2
  • nettle_3.4rc1
  • nettle_3.3_release_20161001
  • nettle_3.2_release_20160128
  • nettle_3.1.1_release_20150424
  • nettle_3.1_release_20150407
  • nettle_3.1rc3
  • nettle_3.1rc2
  • nettle_3.1rc1
  • nettle_3.0_release_20140607
  • nettle_2.7.1_release_20130528
  • nettle_2.7_release_20130424
  • nettle_2.6_release_20130116
  • nettle_2.5_release_20120707
  • converted-master-branch-to-git
  • nettle_2.4_release_20110903
  • nettle_2.3_release_20110902
41 results

buffer.c

Blame
  • Forked from Nettle / nettle
    Source project has a limited visibility.
    • Niels Möller's avatar
      c5c15385
      * Reordered includes in most or all .c-files. All should now include · c5c15385
      Niels Möller authored
      config.h.
      
      Rev: src/nettle/ChangeLog:1.195
      Rev: src/nettle/aes-decrypt-table.c:1.4
      Rev: src/nettle/aes-decrypt.c:1.5
      Rev: src/nettle/aes-encrypt-table.c:1.4
      Rev: src/nettle/aes-encrypt.c:1.5
      Rev: src/nettle/aes-meta.c:1.3
      Rev: src/nettle/aes-set-decrypt-key.c:1.2
      Rev: src/nettle/aes-set-encrypt-key.c:1.2
      Rev: src/nettle/aes.c:1.12
      Rev: src/nettle/aesdata.c:1.2
      Rev: src/nettle/arcfour-meta.c:1.2
      Rev: src/nettle/arcfour.c:1.3
      Rev: src/nettle/base16-decode.c:1.2
      Rev: src/nettle/base16-encode.c:1.2
      Rev: src/nettle/base16-meta.c:1.3
      Rev: src/nettle/base64-decode.c:1.5
      Rev: src/nettle/base64-encode.c:1.3
      Rev: src/nettle/base64-meta.c:1.4
      Rev: src/nettle/bignum-random.c:1.3
      Rev: src/nettle/bignum.c:1.7
      Rev: src/nettle/blowfish.c:1.4
      Rev: src/nettle/buffer-init.c:1.3
      Rev: src/nettle/buffer.c:1.8
      Rev: src/nettle/cast128-meta.c:1.3
      Rev: src/nettle/cast128.c:1.4
      Rev: src/nettle/cbc.c:1.6
      Rev: src/nettle/des-compat.c:1.10
      Rev: src/nettle/des.c:1.7
      Rev: src/nettle/des3.c:1.2
      Rev: src/nettle/dsa-keygen.c:1.6
      Rev: src/nettle/dsa-sign.c:1.7
      Rev: src/nettle/dsa-verify.c:1.4
      Rev: src/nettle/dsa.c:1.5
      Rev: src/nettle/examples/io.c:1.4
      Rev: src/nettle/examples/nettle-benchmark.c:1.8
      Rev: src/nettle/examples/nettle-openssl.c:1.2
      Rev: src/nettle/examples/rsa-keygen.c:1.10
      Rev: src/nettle/examples/rsa-sign.c:1.5
      Rev: src/nettle/examples/rsa-verify.c:1.4
      Rev: src/nettle/hmac-md5.c:1.5
      Rev: src/nettle/hmac-sha1.c:1.2
      Rev: src/nettle/hmac-sha256.c:1.2
      Rev: src/nettle/hmac.c:1.4
      Rev: src/nettle/knuth-lfib.c:1.2
      Rev: src/nettle/md5-compat.c:1.3
      Rev: src/nettle/md5-meta.c:1.2
      Rev: src/nettle/md5.c:1.6
      Rev: src/nettle/memxor.c:1.2
      Rev: src/nettle/nettle-internal.c:1.3
      Rev: src/nettle/pgp-encode.c:1.4
      Rev: src/nettle/pkcs1-rsa-md5.c:1.2
      Rev: src/nettle/pkcs1-rsa-sha1.c:1.2
      Rev: src/nettle/pkcs1.c:1.2
      Rev: src/nettle/realloc.c:1.3
      Rev: src/nettle/rsa-compat.c:1.8
      Rev: src/nettle/rsa-decrypt.c:1.4
      Rev: src/nettle/rsa-encrypt.c:1.5
      Rev: src/nettle/rsa-keygen.c:1.5
      Rev: src/nettle/rsa-md5-sign.c:1.2
      Rev: src/nettle/rsa-md5-verify.c:1.2
      Rev: src/nettle/rsa-sha1-sign.c:1.2
      Rev: src/nettle/rsa-sha1-verify.c:1.2
      Rev: src/nettle/rsa-sign.c:1.3
      Rev: src/nettle/rsa-verify.c:1.2
      Rev: src/nettle/rsa.c:1.12
      Rev: src/nettle/rsa2openpgp.c:1.2
      Rev: src/nettle/rsa2sexp.c:1.7
      Rev: src/nettle/serpent-meta.c:1.2
      Rev: src/nettle/serpent.c:1.4
      Rev: src/nettle/sexp-format.c:1.9
      Rev: src/nettle/sexp-transport-format.c:1.2
      Rev: src/nettle/sexp-transport.c:1.4
      Rev: src/nettle/sexp.c:1.14
      Rev: src/nettle/sexp2bignum.c:1.5
      Rev: src/nettle/sexp2dsa.c:1.4
      Rev: src/nettle/sexp2rsa.c:1.11
      Rev: src/nettle/sha1-meta.c:1.2
      Rev: src/nettle/sha1.c:1.8
      Rev: src/nettle/sha256-meta.c:1.2
      Rev: src/nettle/sha256.c:1.3
      Rev: src/nettle/tools/input.c:1.2
      Rev: src/nettle/tools/misc.c:1.2
      Rev: src/nettle/tools/output.c:1.3
      Rev: src/nettle/tools/parse.c:1.2
      Rev: src/nettle/tools/sexp-conv.c:1.14
      Rev: src/nettle/twofish-meta.c:1.2
      Rev: src/nettle/twofish.c:1.6
      Rev: src/nettle/yarrow256.c:1.17
      Rev: src/nettle/yarrow_key_event.c:1.4
      c5c15385
      History
      * Reordered includes in most or all .c-files. All should now include
      Niels Möller authored
      config.h.
      
      Rev: src/nettle/ChangeLog:1.195
      Rev: src/nettle/aes-decrypt-table.c:1.4
      Rev: src/nettle/aes-decrypt.c:1.5
      Rev: src/nettle/aes-encrypt-table.c:1.4
      Rev: src/nettle/aes-encrypt.c:1.5
      Rev: src/nettle/aes-meta.c:1.3
      Rev: src/nettle/aes-set-decrypt-key.c:1.2
      Rev: src/nettle/aes-set-encrypt-key.c:1.2
      Rev: src/nettle/aes.c:1.12
      Rev: src/nettle/aesdata.c:1.2
      Rev: src/nettle/arcfour-meta.c:1.2
      Rev: src/nettle/arcfour.c:1.3
      Rev: src/nettle/base16-decode.c:1.2
      Rev: src/nettle/base16-encode.c:1.2
      Rev: src/nettle/base16-meta.c:1.3
      Rev: src/nettle/base64-decode.c:1.5
      Rev: src/nettle/base64-encode.c:1.3
      Rev: src/nettle/base64-meta.c:1.4
      Rev: src/nettle/bignum-random.c:1.3
      Rev: src/nettle/bignum.c:1.7
      Rev: src/nettle/blowfish.c:1.4
      Rev: src/nettle/buffer-init.c:1.3
      Rev: src/nettle/buffer.c:1.8
      Rev: src/nettle/cast128-meta.c:1.3
      Rev: src/nettle/cast128.c:1.4
      Rev: src/nettle/cbc.c:1.6
      Rev: src/nettle/des-compat.c:1.10
      Rev: src/nettle/des.c:1.7
      Rev: src/nettle/des3.c:1.2
      Rev: src/nettle/dsa-keygen.c:1.6
      Rev: src/nettle/dsa-sign.c:1.7
      Rev: src/nettle/dsa-verify.c:1.4
      Rev: src/nettle/dsa.c:1.5
      Rev: src/nettle/examples/io.c:1.4
      Rev: src/nettle/examples/nettle-benchmark.c:1.8
      Rev: src/nettle/examples/nettle-openssl.c:1.2
      Rev: src/nettle/examples/rsa-keygen.c:1.10
      Rev: src/nettle/examples/rsa-sign.c:1.5
      Rev: src/nettle/examples/rsa-verify.c:1.4
      Rev: src/nettle/hmac-md5.c:1.5
      Rev: src/nettle/hmac-sha1.c:1.2
      Rev: src/nettle/hmac-sha256.c:1.2
      Rev: src/nettle/hmac.c:1.4
      Rev: src/nettle/knuth-lfib.c:1.2
      Rev: src/nettle/md5-compat.c:1.3
      Rev: src/nettle/md5-meta.c:1.2
      Rev: src/nettle/md5.c:1.6
      Rev: src/nettle/memxor.c:1.2
      Rev: src/nettle/nettle-internal.c:1.3
      Rev: src/nettle/pgp-encode.c:1.4
      Rev: src/nettle/pkcs1-rsa-md5.c:1.2
      Rev: src/nettle/pkcs1-rsa-sha1.c:1.2
      Rev: src/nettle/pkcs1.c:1.2
      Rev: src/nettle/realloc.c:1.3
      Rev: src/nettle/rsa-compat.c:1.8
      Rev: src/nettle/rsa-decrypt.c:1.4
      Rev: src/nettle/rsa-encrypt.c:1.5
      Rev: src/nettle/rsa-keygen.c:1.5
      Rev: src/nettle/rsa-md5-sign.c:1.2
      Rev: src/nettle/rsa-md5-verify.c:1.2
      Rev: src/nettle/rsa-sha1-sign.c:1.2
      Rev: src/nettle/rsa-sha1-verify.c:1.2
      Rev: src/nettle/rsa-sign.c:1.3
      Rev: src/nettle/rsa-verify.c:1.2
      Rev: src/nettle/rsa.c:1.12
      Rev: src/nettle/rsa2openpgp.c:1.2
      Rev: src/nettle/rsa2sexp.c:1.7
      Rev: src/nettle/serpent-meta.c:1.2
      Rev: src/nettle/serpent.c:1.4
      Rev: src/nettle/sexp-format.c:1.9
      Rev: src/nettle/sexp-transport-format.c:1.2
      Rev: src/nettle/sexp-transport.c:1.4
      Rev: src/nettle/sexp.c:1.14
      Rev: src/nettle/sexp2bignum.c:1.5
      Rev: src/nettle/sexp2dsa.c:1.4
      Rev: src/nettle/sexp2rsa.c:1.11
      Rev: src/nettle/sha1-meta.c:1.2
      Rev: src/nettle/sha1.c:1.8
      Rev: src/nettle/sha256-meta.c:1.2
      Rev: src/nettle/sha256.c:1.3
      Rev: src/nettle/tools/input.c:1.2
      Rev: src/nettle/tools/misc.c:1.2
      Rev: src/nettle/tools/output.c:1.3
      Rev: src/nettle/tools/parse.c:1.2
      Rev: src/nettle/tools/sexp-conv.c:1.14
      Rev: src/nettle/twofish-meta.c:1.2
      Rev: src/nettle/twofish.c:1.6
      Rev: src/nettle/yarrow256.c:1.17
      Rev: src/nettle/yarrow_key_event.c:1.4
    array.h 14.45 KiB
    /*
    || 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 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 *merge_array_without_order2(struct array *a, struct array *b,INT32 op);
    PMOD_EXPORT struct array *merge_array_without_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 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);
    /* Prototypes end here */
    
    #define array_get_flags(a) ((a)->flags)
    
    #define visit_array_ref(A, REF_TYPE)					\
      visit_ref (pass_array (A), (REF_TYPE),				\
    	     (visit_thing_fn *) &visit_array, NULL)
    #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((char *) (ITEM(base_sval[-1].u.array) + oldsize__),	\
    	     (char *) 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 */