XPT_NewArena(uint32_t block_size, size_t alignment, const char* name) { XPTArena *arena = calloc(1, sizeof(XPTArena)); if (arena) { XPT_ASSERT(alignment); if (alignment > sizeof(double)) alignment = sizeof(double); arena->alignment = alignment; if (block_size < XPT_MIN_BLOCK_SIZE) block_size = XPT_MIN_BLOCK_SIZE; arena->block_size = ALIGN_RND(block_size, alignment); /* must have room for at least one item! */ XPT_ASSERT(arena->block_size >= ALIGN_RND(sizeof(BLK_HDR), alignment) + ALIGN_RND(1, alignment)); if (name) { arena->name = XPT_STRDUP(arena, name); #ifdef XPT_ARENA_LOGGING /* fudge the stats since we are using space in the arena */ arena->LOG_MallocCallCount = 0; arena->LOG_MallocTotalBytesRequested = 0; arena->LOG_MallocTotalBytesUsed = 0; #endif /* XPT_ARENA_LOGGING */ } } return arena; }
static gboolean find_arg_with_name(TreeState *state, const char *name, int16 *argnum) { int16 count; IDL_tree params; XPT_ASSERT(state); XPT_ASSERT(name); XPT_ASSERT(argnum); params = IDL_OP_DCL(IDL_NODE_UP(IDL_NODE_UP(state->tree))).parameter_dcls; for (count = 0; params != NULL && IDL_LIST(params).data != NULL; params = IDL_LIST(params).next, count++) { const char *cur_name = IDL_IDENT( IDL_PARAM_DCL(IDL_LIST(params).data).simple_declarator).str; if (!strcmp(cur_name, name)) { /* XXX ought to verify that this is the right type here */ /* XXX for iid_is this must be an iid */ /* XXX for size_is and length_is this must be a uint32 */ *argnum = count; return TRUE; } } return FALSE; }
/* if 'exact' is set use that, else grow by the next chunk but * be sure to grow no less that 'at_least' so that we can't get * behind on required space. */ static PRBool GrowPool(XPTArena *arena, XPTDatapool *pool, uint32_t old_size, uint32_t exact, uint32_t at_least) { uint32_t total_size; char *newdata; if (exact) { XPT_ASSERT(exact > pool->allocated); total_size = exact; } else { total_size = pool->allocated + XPT_GROW_CHUNK; if (at_least > total_size) total_size = at_least; } newdata = (char*)XPT_MALLOC(arena, total_size); if (!newdata) return PR_FALSE; if (pool->data) { if (old_size) memcpy(newdata, pool->data, old_size); XPT_FREE(arena, pool->data); } pool->data = newdata; pool->allocated = total_size; return PR_TRUE; }
/* * The bulk of the generation happens here. */ gboolean xpidl_process_node(TreeState *state) { gint type; nodeHandler *dispatch, handler; XPT_ASSERT(state->tree); type = IDL_NODE_TYPE(state->tree); if ((dispatch = state->dispatch) && (handler = dispatch[type])) return handler(state); return TRUE; }
static bool CHECK_COUNT(NotNull<XPTCursor*> cursor, uint32_t space) { // Fail if we're in the data area and about to exceed the allocation. // XXX Also fail if we're in the data area and !state->data_offset if (cursor->pool == XPT_DATA && (CURS_POOL_OFFSET(cursor) + space > (cursor)->state->pool_allocated)) { XPT_ASSERT(0); fprintf(stderr, "FATAL: no room for %d in cursor\n", space); return false; } return true; }
/* fill the interface_directory IDE table from the interface_map */ static gboolean fill_ide_table(gpointer key, gpointer value, gpointer user_data) { TreeState *state = user_data; NewInterfaceHolder *holder = (NewInterfaceHolder *) value; struct nsID id; XPTInterfaceDirectoryEntry *ide; XPT_ASSERT(holder); #ifdef DEBUG_shaver_ifaces fprintf(stderr, "filling %s\n", holder->full_name); #endif if (holder->iid) { if (strlen(holder->iid) != 36) { IDL_tree_error(state->tree, "IID %s is the wrong length\n", holder->iid); return FALSE; } if (!xpidl_parse_iid(&id, holder->iid)) { IDL_tree_error(state->tree, "cannot parse IID %s\n", holder->iid); return FALSE; } } else { memset(&id, 0, sizeof(id)); } ide = &(HEADER(state)->interface_directory[IFACES(state)]); if (!XPT_FillInterfaceDirectoryEntry(ARENA(state), ide, &id, holder->name, holder->name_space, NULL)) { IDL_tree_error(state->tree, "INTERNAL: XPT_FillIDE failed for %s\n", holder->full_name); return FALSE; } IFACES(state)++; DeleteNewInterfaceHolder(holder); return TRUE; }
/* * Parse a uuid string into an nsID struct. We cannot link against libxpcom, * so we re-implement nsID::Parse here. */ gboolean xpidl_parse_iid(nsID *id, const char *str) { PRInt32 count = 0; PRInt32 n1, n2, n3[8]; PRInt32 n0, i; XPT_ASSERT(str != NULL); if (strlen(str) != 36) { return FALSE; } #ifdef DEBUG_shaver_iid fprintf(stderr, "parsing iid %s\n", str); #endif count = sscanf(str, nsIDFmt2, &n0, &n1, &n2, &n3[0],&n3[1],&n3[2],&n3[3], &n3[4],&n3[5],&n3[6],&n3[7]); id->m0 = (PRInt32) n0; id->m1 = (PRInt16) n1; id->m2 = (PRInt16) n2; for (i = 0; i < 8; i++) { id->m3[i] = (PRInt8) n3[i]; } #ifdef DEBUG_shaver_iid if (count == 11) { fprintf(stderr, "IID parsed to "); print_IID(id, stderr); fputs("\n", stderr); } #endif return (gboolean)(count == 11); }
XPT_DoCString(XPTArena *arena, NotNull<XPTCursor*> cursor, char **identp, bool ignore) { uint32_t offset = 0; if (!XPT_Do32(cursor, &offset)) return false; if (!offset) { *identp = NULL; return true; } XPTCursor my_cursor; my_cursor.pool = XPT_DATA; my_cursor.offset = offset; my_cursor.state = cursor->state; char* start = &CURS_POINT(&my_cursor); char* end = strchr(start, 0); /* find the end of the string */ if (!end) { fprintf(stderr, "didn't find end of string on decode!\n"); return false; } int len = end - start; XPT_ASSERT(len > 0); if (!ignore) { char *ident = (char*)XPT_CALLOC1(arena, len + 1u); if (!ident) return false; memcpy(ident, start, (size_t)len); ident[len] = 0; *identp = ident; } return true; }
static gboolean fill_td_from_type(TreeState *state, XPTTypeDescriptor *td, IDL_tree type) { IDL_tree up; int16 size_is_argnum; int16 length_is_argnum; gboolean has_size_is; gboolean has_length_is; gboolean is_array = FALSE; if (type) { /* deal with array */ if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) { IDL_tree sd = IDL_PARAM_DCL(state->tree).simple_declarator; if (IDL_tree_property_get(sd, "array")) { is_array = TRUE; /* size_is is required! */ if (!get_size_and_length(state, type, &size_is_argnum, &length_is_argnum, &has_size_is, &has_length_is)) { /* error was reported by helper function */ return FALSE; } if (!has_size_is) { IDL_tree_error(state->tree, "[array] requires [size_is()]\n"); return FALSE; } td->prefix.flags = TD_ARRAY | XPT_TDP_POINTER; td->argnum = size_is_argnum; if (has_length_is) td->argnum2 = length_is_argnum; else td->argnum2 = size_is_argnum; /* * XXX - NOTE - this will be broken for multidimensional * arrays because of the realloc XPT_InterfaceDescriptorAddTypes * uses. The underlying 'td' can change as we recurse in to get * additional dimensions. Luckily, we don't yet support more * than on dimension in the arrays */ /* setup the additional_type */ if (!XPT_InterfaceDescriptorAddTypes(ARENA(state), CURRENT(state), 1)) { g_error("out of memory\n"); return FALSE; } td->type.additional_type = NEXT_TYPE(state); td = &CURRENT(state)->additional_types[NEXT_TYPE(state)]; NEXT_TYPE(state)++ ; } } handle_typedef: switch (IDL_NODE_TYPE(type)) { case IDLN_TYPE_INTEGER: { gboolean sign = IDL_TYPE_INTEGER(type).f_signed; switch(IDL_TYPE_INTEGER(type).f_type) { case IDL_INTEGER_TYPE_SHORT: td->prefix.flags = sign ? TD_INT16 : TD_UINT16; break; case IDL_INTEGER_TYPE_LONG: td->prefix.flags = sign ? TD_INT32 : TD_UINT32; break; case IDL_INTEGER_TYPE_LONGLONG: td->prefix.flags = sign ? TD_INT64 : TD_UINT64; break; } break; } case IDLN_TYPE_CHAR: td->prefix.flags = TD_CHAR; break; case IDLN_TYPE_WIDE_CHAR: td->prefix.flags = TD_WCHAR; break; case IDLN_TYPE_STRING: if (is_array) { td->prefix.flags = TD_PSTRING | XPT_TDP_POINTER; } else { if (!get_size_and_length(state, type, &size_is_argnum, &length_is_argnum, &has_size_is, &has_length_is)) { /* error was reported by helper function */ return FALSE; } if (has_size_is) { td->prefix.flags = TD_PSTRING_SIZE_IS | XPT_TDP_POINTER; td->argnum = size_is_argnum; if (has_length_is) td->argnum2 = length_is_argnum; else td->argnum2 = size_is_argnum; } else { td->prefix.flags = TD_PSTRING | XPT_TDP_POINTER; } } break; case IDLN_TYPE_WIDE_STRING: if (is_array) { td->prefix.flags = TD_PWSTRING | XPT_TDP_POINTER; } else { if (!get_size_and_length(state, type, &size_is_argnum, &length_is_argnum, &has_size_is, &has_length_is)) { /* error was reported by helper function */ return FALSE; } if (has_size_is) { td->prefix.flags = TD_PWSTRING_SIZE_IS | XPT_TDP_POINTER; td->argnum = size_is_argnum; if (has_length_is) td->argnum2 = length_is_argnum; else td->argnum2 = size_is_argnum; } else { td->prefix.flags = TD_PWSTRING | XPT_TDP_POINTER; } } break; case IDLN_TYPE_BOOLEAN: td->prefix.flags = TD_BOOL; break; case IDLN_TYPE_OCTET: td->prefix.flags = TD_UINT8; break; case IDLN_TYPE_FLOAT: switch (IDL_TYPE_FLOAT (type).f_type) { case IDL_FLOAT_TYPE_FLOAT: td->prefix.flags = TD_FLOAT; break; case IDL_FLOAT_TYPE_DOUBLE: td->prefix.flags = TD_DOUBLE; break; /* XXX 'long double' just ignored, or what? */ default: break; } break; case IDLN_IDENT: if (!(up = IDL_NODE_UP(type))) { IDL_tree_error(state->tree, "ERROR: orphan ident %s in param list\n", IDL_IDENT(type).str); return FALSE; } switch (IDL_NODE_TYPE(up)) { /* This whole section is abominably ugly */ case IDLN_FORWARD_DCL: case IDLN_INTERFACE: { XPTInterfaceDirectoryEntry *ide, *ides; uint16 num_ifaces; char *className; const char *iid_is; handle_iid_is: ides = HEADER(state)->interface_directory; num_ifaces = HEADER(state)->num_interfaces; /* might get here via the goto, so re-check type */ if (IDL_NODE_TYPE(up) == IDLN_INTERFACE) className = IDL_IDENT(IDL_INTERFACE(up).ident).str; else if (IDL_NODE_TYPE(up) == IDLN_FORWARD_DCL) className = IDL_IDENT(IDL_FORWARD_DCL(up).ident).str; else className = IDL_IDENT(IDL_NATIVE(up).ident).str; iid_is = NULL; if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) { iid_is = IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator, "iid_is"); } if (iid_is) { int16 argnum; if (!find_arg_with_name(state, iid_is, &argnum)) { IDL_tree_error(state->tree, "can't find matching argument for " "[iid_is(%s)]\n", iid_is); return FALSE; } td->prefix.flags = TD_INTERFACE_IS_TYPE | XPT_TDP_POINTER; td->argnum = argnum; } else { td->prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER; ide = FindInterfaceByName(ides, num_ifaces, className); if (!ide || ide < ides || ide > ides + num_ifaces) { IDL_tree_error(state->tree, "unknown iface %s in param\n", className); return FALSE; } td->type.iface = ide - ides + 1; #ifdef DEBUG_shaver_index fprintf(stderr, "DBG: index %d for %s\n", td->type.iface, className); #endif } break; } case IDLN_NATIVE: { char *ident; /* jband - adding goto for iid_is when type is native */ if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL && IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator, "iid_is")) goto handle_iid_is; ident = IDL_IDENT(type).str; if (IDL_tree_property_get(type, "nsid")) { td->prefix.flags = TD_PNSIID; if (IDL_tree_property_get(type, "ref")) td->prefix.flags |= XPT_TDP_POINTER | XPT_TDP_REFERENCE; else if (IDL_tree_property_get(type,"ptr")) td->prefix.flags |= XPT_TDP_POINTER; } else if (IDL_tree_property_get(type, "domstring")) { td->prefix.flags = TD_DOMSTRING | XPT_TDP_POINTER; if (IDL_tree_property_get(type, "ref")) td->prefix.flags |= XPT_TDP_REFERENCE; } else if (IDL_tree_property_get(type, "astring")) { td->prefix.flags = TD_ASTRING | XPT_TDP_POINTER; if (IDL_tree_property_get(type, "ref")) td->prefix.flags |= XPT_TDP_REFERENCE; } else if (IDL_tree_property_get(type, "utf8string")) { td->prefix.flags = TD_UTF8STRING | XPT_TDP_POINTER; if (IDL_tree_property_get(type, "ref")) td->prefix.flags |= XPT_TDP_REFERENCE; } else if (IDL_tree_property_get(type, "cstring")) { td->prefix.flags = TD_CSTRING | XPT_TDP_POINTER; if (IDL_tree_property_get(type, "ref")) td->prefix.flags |= XPT_TDP_REFERENCE; } else if (IDL_tree_property_get(type, "jsval")) { td->prefix.flags = TD_JSVAL; if (IDL_tree_property_get(type, "ptr")) td->prefix.flags |= XPT_TDP_POINTER; } else { td->prefix.flags = TD_VOID | XPT_TDP_POINTER; } break; } default: if (IDL_NODE_TYPE(IDL_NODE_UP(up)) == IDLN_TYPE_DCL) { /* restart with the underlying type */ IDL_tree new_type; new_type = IDL_TYPE_DCL(IDL_NODE_UP(up)).type_spec; #ifdef DEBUG_shaver_misc fprintf(stderr, "following %s typedef to %s\n", IDL_IDENT(type).str, IDL_NODE_TYPE_NAME(new_type)); #endif /* * Do a nice messy goto rather than recursion so that * we can avoid screwing up the *array* information. */ /* return fill_td_from_type(state, td, new_type); */ if (new_type) { type = new_type; goto handle_typedef; } else { /* do what we would do in recursion if !type */ td->prefix.flags = TD_VOID; return TRUE; } } IDL_tree_error(state->tree, "can't handle %s ident in param list\n", #ifdef DEBUG_shaver /* XXX is this safe to use on Win now? */ IDL_NODE_TYPE_NAME(IDL_NODE_UP(type)) #else "that type of" #endif ); #ifdef DEBUG_shaver XPT_ASSERT(0); #endif return FALSE; } break; default: IDL_tree_error(state->tree, "can't handle %s in param list\n", #ifdef DEBUG_shaver /* XXX is this safe to use on Win now? */ IDL_NODE_TYPE_NAME(IDL_NODE_UP(type)) #else "that type" #endif ); return FALSE; } } else { td->prefix.flags = TD_VOID; } return TRUE; }
static int NextIsInclude(input_callback_state *callback_state, char **startp, int *lenp) { input_data *data = callback_state->input_stack; input_data *new_data; char *filename, *end; const char *scratch; /* process the #include that we're in now */ if (strncmp(data->point, "#include \"", 10)) { return 0; } filename = data->point + 10; /* skip #include " */ XPT_ASSERT(filename < data->max); end = filename; while (end < data->max) { if (*end == '\"' || *end == '\n' || *end == '\r') break; end++; } if (*end != '\"') { /* * Didn't find end of include file. Scan 'til next whitespace to find * some reasonable approximation of the filename, and use it to report * an error. */ end = filename; while (end < data->max) { if (*end == ' ' || *end == '\n' || *end == '\r' || *end == '\t') break; end++; } *end = '\0'; /* make sure we have accurate line info */ IDL_file_get(&scratch, (int *)&data->lineno); fprintf(stderr, "%s:%d: didn't find end of quoted include name \"%s\n", scratch, data->lineno, filename); return -1; } *end = '\0'; *startp = end + 1; if (data->next == NULL) { /* * If we're in the initial file, add this filename to the list * of filenames to be turned into #include "filename.h" * directives in xpidl_header.c. We do it here rather than in the * block below so it still gets added to the list even if it's * already been recursively included from some other file. */ char *filename_cp = xpidl_strdup(filename); /* note that g_slist_append accepts and likes null as list-start. */ callback_state->base_includes = g_slist_append(callback_state->base_includes, filename_cp); } /* store offset for when we pop, or if we skip this one */ data->point = *startp; if (!g_hash_table_lookup(callback_state->already_included, filename)) { filename = xpidl_strdup(filename); g_hash_table_insert(callback_state->already_included, filename, (void *)TRUE); new_data = new_input_data(filename, callback_state->include_path); if (!new_data) { char *error_message; IDL_file_get(&scratch, (int *)&data->lineno); error_message = g_strdup_printf("can't open included file %s for reading\n", filename); msg_callback(IDL_ERROR, 0, data->lineno, scratch, error_message); g_free(error_message); return -1; } new_data->next = data; /* tell libIDL to exclude this IDL from the toplevel tree */ IDL_inhibit_push(); IDL_file_get(&scratch, (int *)&data->lineno); callback_state->input_stack = new_data; IDL_file_set(new_data->filename, (int)new_data->lineno); } *lenp = 0; /* this is magic, see the comment below */ return 1; }
XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **identp) { XPTCursor my_cursor; char *ident = *identp; uint32_t offset = 0; XPTMode mode = cursor->state->mode; if (mode == XPT_DECODE) { char *start, *end; int len; if (!XPT_Do32(cursor, &offset)) return PR_FALSE; if (!offset) { *identp = NULL; return PR_TRUE; } my_cursor.pool = XPT_DATA; my_cursor.offset = offset; my_cursor.state = cursor->state; start = &CURS_POINT(&my_cursor); end = strchr(start, 0); /* find the end of the string */ if (!end) { fprintf(stderr, "didn't find end of string on decode!\n"); return PR_FALSE; } len = end - start; XPT_ASSERT(len > 0); ident = (char*)XPT_MALLOC(arena, len + 1u); if (!ident) return PR_FALSE; memcpy(ident, start, (size_t)len); ident[len] = 0; *identp = ident; } else { if (!ident) { offset = 0; if (!XPT_Do32(cursor, &offset)) return PR_FALSE; return PR_TRUE; } if (!XPT_MakeCursor(cursor->state, XPT_DATA, strlen(ident) + 1, &my_cursor) || !XPT_Do32(cursor, &my_cursor.offset)) return PR_FALSE; while(*ident) if (!XPT_Do8(&my_cursor, (uint8_t *)ident++)) return PR_FALSE; if (!XPT_Do8(&my_cursor, (uint8_t *)ident)) /* write trailing zero */ return PR_FALSE; } return PR_TRUE; }
/* * Check that parameters referred to by attributes such as size_is exist and * refer to parameters of the appropriate type. */ static gboolean check_param_attribute(IDL_tree method_tree, IDL_tree param, ParamAttrType whattocheck) { const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str; const char *referred_name = NULL; IDL_tree param_type = IDL_PARAM_DCL(param).param_type_spec; IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator; const char *param_name = IDL_IDENT(simple_decl).str; const char *attr_name; const char *needed_type; if (whattocheck == IID_IS) { attr_name = "iid_is"; needed_type = "IID"; } else if (whattocheck == LENGTH_IS) { attr_name = "length_is"; needed_type = "unsigned long (or PRUint32)"; } else if (whattocheck == SIZE_IS) { attr_name = "size_is"; needed_type = "unsigned long (or PRUint32)"; } else { XPT_ASSERT("asked to check an unknown attribute type!"); return TRUE; } referred_name = IDL_tree_property_get(simple_decl, attr_name); if (referred_name != NULL) { IDL_tree referred_param = find_named_parameter(method_tree, referred_name); IDL_tree referred_param_type; if (referred_param == NULL) { IDL_tree_error(method_tree, "attribute [%s(%s)] refers to missing " "parameter \"%s\"", attr_name, referred_name, referred_name); return FALSE; } if (referred_param == param) { IDL_tree_error(method_tree, "attribute [%s(%s)] refers to it's own parameter", attr_name, referred_name); return FALSE; } referred_param_type = IDL_PARAM_DCL(referred_param).param_type_spec; if (whattocheck == IID_IS) { /* require IID type */ if (IDL_tree_property_get(referred_param_type, "nsid") == NULL) { IDL_tree_error(method_tree, "target \"%s\" of [%s(%s)] attribute " "must be of %s type", referred_name, attr_name, referred_name, needed_type); return FALSE; } } else if (whattocheck == LENGTH_IS || whattocheck == SIZE_IS) { /* require PRUint32 type */ IDL_tree real_type; /* Could be a typedef; try to map it to the real type. */ real_type = find_underlying_type(referred_param_type); real_type = real_type ? real_type : referred_param_type; if (IDL_NODE_TYPE(real_type) != IDLN_TYPE_INTEGER || IDL_TYPE_INTEGER(real_type).f_signed != FALSE || IDL_TYPE_INTEGER(real_type).f_type != IDL_INTEGER_TYPE_LONG) { IDL_tree_error(method_tree, "target \"%s\" of [%s(%s)] attribute " "must be of %s type", referred_name, attr_name, referred_name, needed_type); return FALSE; } } } return TRUE; }
XPT_ArenaMalloc(XPTArena *arena, size_t size) { uint8_t *cur; size_t bytes; if (!size) return NULL; if (!arena) { XPT_ASSERT(0); return NULL; } bytes = ALIGN_RND(size, arena->alignment); LOG_MALLOC(arena, size, bytes); if (bytes > arena->space) { BLK_HDR* new_block; size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), arena->alignment); size_t new_space = arena->block_size; while (bytes > new_space - block_header_size) new_space += arena->block_size; new_block = (BLK_HDR*) calloc(new_space/arena->alignment, arena->alignment); if (!new_block) { arena->next = NULL; arena->space = 0; return NULL; } LOG_REAL_MALLOC(arena, new_space); /* link block into the list of blocks for use when we destroy */ new_block->next = arena->first; arena->first = new_block; /* save other block header info */ new_block->size = new_space; /* set info for current block */ arena->next = ((uint8_t*)new_block) + block_header_size; arena->space = new_space - block_header_size; #ifdef DEBUG /* mark block for corruption check */ memset(arena->next, 0xcd, arena->space); #endif } #ifdef DEBUG { /* do corruption check */ size_t i; for (i = 0; i < bytes; ++i) { XPT_ASSERT(arena->next[i] == 0xcd); } /* we guarantee that the block will be filled with zeros */ memset(arena->next, 0, bytes); } #endif cur = arena->next; arena->next += bytes; arena->space -= bytes; return cur; }
XPT_ArenaCalloc(XPTArena *arena, size_t size, size_t alignment) { if (!size) return NULL; if (!arena) { XPT_ASSERT(0); return NULL; } XPTSubArena *subarena; if (alignment == 8) { subarena = &arena->subarena8; } else if (alignment == 1) { subarena = &arena->subarena1; } else { XPT_ASSERT(0); return NULL; } size_t bytes = ALIGN_RND(size, alignment); if (bytes > subarena->space) { BLK_HDR* new_block; size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), alignment); size_t new_space = subarena->block_size; while (bytes > new_space - block_header_size) new_space += subarena->block_size; new_block = static_cast<BLK_HDR*>(calloc(new_space / alignment, alignment)); if (!new_block) { subarena->next = NULL; subarena->space = 0; return NULL; } /* link block into the list of blocks for use when we destroy */ new_block->next = subarena->first; subarena->first = new_block; /* set info for current block */ subarena->next = reinterpret_cast<uint8_t*>(new_block) + block_header_size; subarena->space = new_space - block_header_size; #ifdef DEBUG /* mark block for corruption check */ memset(subarena->next, 0xcd, subarena->space); #endif } #ifdef DEBUG { /* do corruption check */ size_t i; for (i = 0; i < bytes; ++i) { XPT_ASSERT(subarena->next[i] == 0xcd); } /* we guarantee that the block will be filled with zeros */ memset(subarena->next, 0, bytes); } #endif uint8_t* p = subarena->next; subarena->next += bytes; subarena->space -= bytes; return p; }