void gendesc_table(compile_t* c) { uint32_t len = c->reach->next_type_id; size_t size = len * sizeof(LLVMValueRef); LLVMValueRef* args = (LLVMValueRef*)ponyint_pool_alloc_size(size); reach_type_t* t; size_t i = HASHMAP_BEGIN; while((t = reach_types_next(&c->reach->types, &i)) != NULL) { LLVMValueRef desc; if(t->desc != NULL) desc = LLVMBuildBitCast(c->builder, t->desc, c->descriptor_ptr, ""); else desc = LLVMConstNull(c->descriptor_ptr); args[t->type_id] = desc; } LLVMTypeRef type = LLVMArrayType(c->descriptor_ptr, len); LLVMValueRef table = LLVMAddGlobal(c->module, type, "__DescTable"); LLVMValueRef value = LLVMConstArray(c->descriptor_ptr, args, len); LLVMSetInitializer(table, value); LLVMSetGlobalConstant(table, true); LLVMValueRef table_size = LLVMAddGlobal(c->module, c->intptr, "__DescTableSize"); LLVMSetInitializer(table_size, LLVMConstInt(c->intptr, len, false)); LLVMSetGlobalConstant(table_size, true); ponyint_pool_free_size(size, args); }
void pony_serialise(pony_ctx_t* ctx, void* p, void* out) { // This can raise an error. assert(ctx->stack == NULL); ctx->trace_object = ponyint_serialise_object; ctx->trace_actor = ponyint_serialise_actor; ctx->serialise_size = 0; pony_traceunknown(ctx, p, PONY_TRACE_MUTABLE); ponyint_gc_handlestack(ctx); ponyint_array_t* r = (ponyint_array_t*)out; r->size = ctx->serialise_size; r->alloc = r->size; r->ptr = (char*)ponyint_pool_alloc_size(r->size); size_t i = HASHMAP_BEGIN; serialise_t* s; while((s = ponyint_serialise_next(&ctx->serialise, &i)) != NULL) { if(s->t != NULL) s->t->serialise(ctx, (void*)s->key, r->ptr, s->value, s->mutability); } serialise_cleanup(ctx); }
pony_ctx_t* ponyint_sched_init(uint32_t threads, bool noyield, bool nopin, bool pinasio) { use_yield = !noyield; // If no thread count is specified, use the available physical core count. if(threads == 0) threads = ponyint_cpu_count(); scheduler_count = threads; scheduler = (scheduler_t*)ponyint_pool_alloc_size( scheduler_count * sizeof(scheduler_t)); memset(scheduler, 0, scheduler_count * sizeof(scheduler_t)); uint32_t asio_cpu = ponyint_cpu_assign(scheduler_count, scheduler, nopin, pinasio); for(uint32_t i = 0; i < scheduler_count; i++) { scheduler[i].ctx.scheduler = &scheduler[i]; scheduler[i].last_victim = &scheduler[i]; ponyint_messageq_init(&scheduler[i].mq); ponyint_mpmcq_init(&scheduler[i].q); } this_scheduler = &scheduler[0]; ponyint_mpmcq_init(&inject); ponyint_asio_init(asio_cpu); return &scheduler[0].ctx; }
static void add_rmethod_to_subtype(reach_t* r, reach_type_t* t, reach_method_name_t* n, reach_method_t* m, pass_opt_t* opt) { // Add the method to the type if it isn't already there. reach_method_name_t* n2 = add_method_name(t, n->name); add_rmethod(r, t, n2, m->cap, m->typeargs, opt); // Add this mangling to the type if it isn't already there. reach_method_t* mangled = reach_mangled_get(&n2->r_mangled, m); if(mangled != NULL) return; mangled = POOL_ALLOC(reach_method_t); memset(mangled, 0, sizeof(reach_method_t)); mangled->name = m->name; mangled->mangled_name = m->mangled_name; mangled->full_name = make_full_name(t, mangled); mangled->cap = m->cap; mangled->r_fun = ast_dup(m->r_fun); mangled->typeargs = ast_dup(m->typeargs); mangled->forwarding = true; mangled->param_count = m->param_count; mangled->params = (reach_param_t*)ponyint_pool_alloc_size( mangled->param_count * sizeof(reach_param_t)); memcpy(mangled->params, m->params, m->param_count * sizeof(reach_param_t)); mangled->result = m->result; // Add to the mangled table only. reach_mangled_put(&n2->r_mangled, mangled); }
// https://stackoverflow.com/questions/2736753/how-to-remove-extension-from-file-name // remove_ext: removes the "extension" from a file spec. // path is the string to process. // dot is the extension separator. // sep is the path separator (0 means to ignore). // Returns an allocated string identical to the original but // with the extension removed. It must be freed when you're // finished with it. // If you pass in NULL or the new string can't be allocated, // it returns NULL. char* remove_ext(const char* path, char dot, char sep, size_t* allocated_size) { char *retstr, *lastdot, *lastsep; // Error checks and allocate string. if (path == NULL) return NULL; *allocated_size = strlen(path) + 1; retstr = (char*) ponyint_pool_alloc_size(*allocated_size); // Make a copy and find the relevant characters. strcpy(retstr, path); lastdot = strrchr(retstr, dot); lastsep = (sep == 0) ? NULL : strrchr(retstr, sep); // If it has an extension separator. if (lastdot != NULL) { // and it's before the extension separator. if (lastsep != NULL) { if (lastsep < lastdot) { // then remove it. *lastdot = '\0'; } } else { // Has extension separator with no path separator. *lastdot = '\0'; } } // Return the modified string. return retstr; }
static void set_method_types(reach_t* r, reach_method_t* m, pass_opt_t* opt) { AST_GET_CHILDREN(m->r_fun, cap, id, typeparams, params, result, can_error, body); m->param_count = ast_childcount(params); m->params = (reach_param_t*)ponyint_pool_alloc_size( m->param_count * sizeof(reach_param_t)); ast_t* param = ast_child(params); size_t i = 0; while(param != NULL) { AST_GET_CHILDREN(param, p_id, p_type); m->params[i].type = add_type(r, p_type, opt); if(ast_id(p_type) != TK_NOMINAL && ast_id(p_type) != TK_TYPEPARAMREF) m->params[i].cap = TK_REF; else m->params[i].cap = ast_id(cap_fetch(p_type)); ++i; param = ast_sibling(param); } m->result = add_type(r, result, opt); }
static void handle_stack(reachable_method_stack_t* s, reachable_types_t* r, uint32_t* next_type_id) { while(s != NULL) { reachable_method_t* m; s = reachable_method_stack_pop(s, &m); AST_GET_CHILDREN(m->r_fun, cap, id, typeparams, params, result, can_error, body); m->param_count = ast_childcount(params); m->params = (reachable_type_t**)ponyint_pool_alloc_size( m->param_count * sizeof(reachable_type_t*)); ast_t* param = ast_child(params); size_t i = 0; while(param != NULL) { AST_GET_CHILDREN(param, p_id, p_type); m->params[i++] = add_type(&s, r, next_type_id, p_type); param = ast_sibling(param); } m->result = add_type(&s, r, next_type_id, result); reachable_expr(&s, r, next_type_id, body); } }
static LLVMValueRef make_trait_list(compile_t* c, reach_type_t* t, uint32_t* final_count) { // The list is an array of integers. uint32_t* tid; size_t tid_size; uint32_t count = trait_count(t, &tid, &tid_size); // If we have no traits, return a null pointer to a list. if(count == 0) return LLVMConstNull(LLVMPointerType(LLVMArrayType(c->i32, 0), 0)); // Create a constant array of trait identifiers. size_t list_size = count * sizeof(LLVMValueRef); LLVMValueRef* list = (LLVMValueRef*)ponyint_pool_alloc_size(list_size); for(uint32_t i = 0; i < count; i++) list[i] = LLVMConstInt(c->i32, tid[i], false); LLVMValueRef trait_array = LLVMConstArray(c->i32, list, count); // Create a global to hold the array. const char* name = genname_traitlist(t->name); LLVMTypeRef list_type = LLVMArrayType(c->i32, count); LLVMValueRef global = LLVMAddGlobal(c->module, list_type, name); LLVMSetGlobalConstant(global, true); LLVMSetLinkage(global, LLVMPrivateLinkage); LLVMSetInitializer(global, trait_array); ponyint_pool_free_size(tid_size, tid); ponyint_pool_free_size(list_size, list); *final_count = count; return global; }
// Cat together the given strings into a newly allocated buffer. // Any unneeded strings should be passed as "", not NULL. // The returned buffer must be freed with ponyint_pool_free_size() when // no longer needed. // The out_buf_size parameter returns the size of the buffer (which is needed // for freeing), not the length of the string. static char* doc_cat(const char* a, const char* b, const char* c, const char* d, const char* e, size_t* out_buf_size) { assert(a != NULL); assert(b != NULL); assert(c != NULL); assert(d != NULL); assert(e != NULL); assert(out_buf_size != NULL); size_t a_len = strlen(a); size_t b_len = strlen(b); size_t c_len = strlen(c); size_t d_len = strlen(d); size_t e_len = strlen(e); size_t buf_len = a_len + b_len + c_len + d_len + e_len + 1; char* buffer = (char*)ponyint_pool_alloc_size(buf_len); char *p = buffer; if(a_len > 0) { memcpy(p, a, a_len); p += a_len; } if(b_len > 0) { memcpy(p, b, b_len); p += b_len; } if(c_len > 0) { memcpy(p, c, c_len); p += c_len; } if(d_len > 0) { memcpy(p, d, d_len); p += d_len; } if(e_len > 0) { memcpy(p, e, e_len); p += e_len; } *(p++) = '\0'; assert(p == (buffer + buf_len)); *out_buf_size = buf_len; return buffer; }
static void print_params(compile_t* c, printbuf_t* buf, ast_t* params) { ast_t* param = ast_child(params); while(param != NULL) { AST_GET_CHILDREN(param, id, ptype); // Print the parameter. printbuf(buf, ", "); print_type_name(c, buf, ptype); // Smash trailing primes to underscores. const char* name = ast_name(id); size_t len = strlen(name) + 1; size_t buf_size = len; char* buffer = (char*)ponyint_pool_alloc_size(buf_size); memcpy(buffer, name, len); len--; while(buffer[--len] == '\'') buffer[len] = '_'; printbuf(buf, " %s", buffer); param = ast_sibling(param); ponyint_pool_free_size(buf_size, buffer); } }
LLVMValueRef gen_numeric_size_table(compile_t* c) { uint32_t len = c->reach->numeric_type_count; if(len == 0) return NULL; size_t size = len * sizeof(LLVMValueRef); LLVMValueRef* args = (LLVMValueRef*)ponyint_pool_alloc_size(size); uint32_t count = 0; reach_type_t* t; size_t i = HASHMAP_BEGIN; while(count < len) { t = reach_types_next(&c->reach->types, &i); pony_assert(t != NULL); if(t->is_trait || (t->underlying == TK_STRUCT)) continue; uint32_t type_id = t->type_id; if((type_id % 4) == 0) { size_t type_size = (size_t)LLVMABISizeOfType(c->target_data, t->use_type); args[type_id >> 2] = LLVMConstInt(c->i32, type_size, false); count++; } }
static const char* symbol_suffix(const char* symbol, size_t suffix) { size_t len = strlen(symbol); size_t buf_size = len + 32; char* buf = (char*)ponyint_pool_alloc_size(buf_size); snprintf(buf, buf_size, "%s" __zu, symbol, suffix); return stringtab_consume(buf, buf_size); }
LLVMValueRef gen_tuple(compile_t* c, ast_t* ast) { ast_t* child = ast_child(ast); if(ast_sibling(child) == NULL) return gen_expr(c, child); deferred_reification_t* reify = c->frame->reify; ast_t* type = deferred_reify(reify, ast_type(ast), c->opt); // If we contain '_', we have no usable value. if(contains_dontcare(type)) { ast_free_unattached(type); return GEN_NOTNEEDED; } reach_type_t* t = reach_type(c->reach, type); compile_type_t* c_t = (compile_type_t*)t->c_type; int count = LLVMCountStructElementTypes(c_t->primitive); size_t buf_size = count * sizeof(LLVMTypeRef); LLVMTypeRef* elements = (LLVMTypeRef*)ponyint_pool_alloc_size(buf_size); LLVMGetStructElementTypes(c_t->primitive, elements); LLVMValueRef tuple = LLVMGetUndef(c_t->primitive); int i = 0; while(child != NULL) { LLVMValueRef value = gen_expr(c, child); if(value == NULL) { ponyint_pool_free_size(buf_size, elements); return NULL; } // We'll have an undefined element if one of our source elements is a // variable declaration. This is ok, since the tuple value will never be // used. if(value == GEN_NOVALUE || value == GEN_NOTNEEDED) { ponyint_pool_free_size(buf_size, elements); return value; } ast_t* child_type = deferred_reify(reify, ast_type(child), c->opt); value = gen_assign_cast(c, elements[i], value, child_type); ast_free_unattached(child_type); tuple = LLVMBuildInsertValue(c->builder, tuple, value, i++, ""); child = ast_sibling(child); } ponyint_pool_free_size(buf_size, elements); return tuple; }
printbuf_t* printbuf_new() { printbuf_t* buf = POOL_ALLOC(printbuf_t); buf->m = (char*)ponyint_pool_alloc_size(32); buf->m[0] = '\0'; buf->size = 32; buf->offset = 0; return buf; }
source_t* source_open_string(const char* source_code) { source_t* source = POOL_ALLOC(source_t); source->file = NULL; source->len = strlen(source_code); source->m = (char*)ponyint_pool_alloc_size(source->len); memcpy(source->m, source_code, source->len); return source; }
// Convert the given ID to a hygenic string. The resulting string should not be // deleted and is valid indefinitely. static const char* id_to_string(const char* prefix, size_t id) { if(prefix == NULL) prefix = ""; size_t len = strlen(prefix); size_t buf_size = len + 32; char* buffer = (char*)ponyint_pool_alloc_size(buf_size); snprintf(buffer, buf_size, "%s$" __zu, prefix, id); return stringtab_consume(buffer, buf_size); }
static void tuple_indices_push(call_tuple_indices_t* ti, size_t idx) { if(ti->count == ti->alloc) { size_t* tmp_data = (size_t*)ponyint_pool_alloc_size(2 * ti->alloc * sizeof(size_t)); memcpy(tmp_data, ti->data, ti->count * sizeof(size_t)); ponyint_pool_free_size(ti->alloc * sizeof(size_t), ti->data); ti->alloc *= 2; ti->data = tmp_data; } ti->data[ti->count++] = idx; }
static LLVMValueRef make_field_list(compile_t* c, reach_type_t* t) { // The list is an array of field descriptors. uint32_t count; if(t->underlying == TK_TUPLETYPE) count = t->field_count; else count = 0; LLVMTypeRef field_type = LLVMArrayType(c->field_descriptor, count); // If we aren't a tuple, return a null pointer to a list. if(count == 0) return LLVMConstNull(LLVMPointerType(field_type, 0)); // Create a constant array of field descriptors. size_t buf_size = count * sizeof(LLVMValueRef); LLVMValueRef* list = (LLVMValueRef*)ponyint_pool_alloc_size(buf_size); for(uint32_t i = 0; i < count; i++) { LLVMValueRef fdesc[2]; fdesc[0] = LLVMConstInt(c->i32, LLVMOffsetOfElement(c->target_data, t->primitive, i), false); if(t->fields[i].type->desc != NULL) { // We are a concrete type. fdesc[1] = LLVMConstBitCast(t->fields[i].type->desc, c->descriptor_ptr); } else { // We aren't a concrete type. fdesc[1] = LLVMConstNull(c->descriptor_ptr); } list[i] = LLVMConstStructInContext(c->context, fdesc, 2, false); } LLVMValueRef field_array = LLVMConstArray(c->field_descriptor, list, count); // Create a global to hold the array. const char* name = genname_fieldlist(t->name); LLVMValueRef global = LLVMAddGlobal(c->module, field_type, name); LLVMSetGlobalConstant(global, true); LLVMSetLinkage(global, LLVMPrivateLinkage); LLVMSetInitializer(global, field_array); ponyint_pool_free_size(buf_size, list); return global; }
static const char* name_without_case(const char* name) { size_t len = strlen(name) + 1; char* buf = (char*)ponyint_pool_alloc_size(len); if(is_name_type(name)) { for(size_t i = 0; i < len; i++) buf[i] = (char)toupper(name[i]); } else { for(size_t i = 0; i < len; i++) buf[i] = (char)tolower(name[i]); } return stringtab_consume(buf, len); }
const char* buildflagset_print(buildflagset_t* set) { assert(set != NULL); assert(set->flags != NULL); char* p = set->text_buffer; // First the mutually exclusive flags. if(set->have_os_flags) print_flag(_os_flags[set->enum_os_flags], true, set, &p); if(set->have_arch_flags) print_flag(_arch_flags[set->enum_arch_flags], true, set, &p); if(set->have_size_flags) print_flag(_size_flags[set->enum_size_flags], true, set, &p); // Next the normal flags, in any order. size_t i = HASHMAP_BEGIN; flag_t* flag; while((flag = flagtab_next(set->flags, &i)) != NULL) print_flag(flag->name, flag->value, set, &p); if(p == set->text_buffer) // No flags, all configs match. print_str("all configs", set, &p); // Check buffer was big enough for it all. size_t size_needed = (p - set->text_buffer) + 1; // +1 for terminator. if(size_needed > set->buffer_size) { // Buffer we have isn't big enough, make it bigger then go round again. if(set->buffer_size > 0) ponyint_pool_free_size(set->buffer_size, set->text_buffer); set->text_buffer = (char*)ponyint_pool_alloc_size(size_needed); set->buffer_size = size_needed; set->text_buffer[0] = '\0'; buildflagset_print(set); } // Add terminator. assert(set->text_buffer != NULL); set->text_buffer[size_needed - 1] = '\0'; return set->text_buffer; }
static const char* suggest_alt_name(ast_t* ast, const char* name) { assert(ast != NULL); assert(name != NULL); size_t name_len = strlen(name); if(is_name_private(name)) { // Try without leading underscore const char* try_name = stringtab(name + 1); if(ast_get(ast, try_name, NULL) != NULL) return try_name; } else { // Try with a leading underscore char* buf = (char*)ponyint_pool_alloc_size(name_len + 2); buf[0] = '_'; strncpy(buf + 1, name, name_len + 1); const char* try_name = stringtab_consume(buf, name_len + 2); if(ast_get(ast, try_name, NULL) != NULL) return try_name; } // Try with a different case (without crossing type/value boundary) ast_t* case_ast = ast_get_case(ast, name, NULL); if(case_ast != NULL) { ast_t* id = case_ast; if(ast_id(id) != TK_ID) id = ast_child(id); assert(ast_id(id) == TK_ID); const char* try_name = ast_name(id); if(ast_get(ast, try_name, NULL) != NULL) return try_name; } // Give up return NULL; }
static void make_debug_fields(compile_t* c, reach_type_t* t) { LLVMMetadataRef fields = NULL; if(t->field_count > 0) { size_t buf_size = t->field_count * sizeof(LLVMMetadataRef); LLVMMetadataRef* data = (LLVMMetadataRef*)ponyint_pool_alloc_size( buf_size); for(uint32_t i = 0; i < t->field_count; i++) data[i] = make_debug_field(c, t, i); fields = LLVMDIBuilderGetOrCreateArray(c->di, data, t->field_count); ponyint_pool_free_size(buf_size, data); } LLVMTypeRef type; if(t->underlying != TK_TUPLETYPE) type = t->structure; else type = t->primitive; uint64_t size = 0; uint64_t align = 0; if(type != NULL) { size = LLVMABISizeOfType(c->target_data, type); align = LLVMABIAlignmentOfType(c->target_data, type); } LLVMMetadataRef di_type = LLVMDIBuilderCreateStructType(c->di, c->di_unit, t->name, t->di_file, (unsigned) ast_line(t->ast), 8 * size, 8 * align, fields); if(t->underlying != TK_TUPLETYPE) { LLVMMetadataReplaceAllUsesWith(t->di_type_embed, di_type); t->di_type_embed = di_type; } else { LLVMMetadataReplaceAllUsesWith(t->di_type, di_type); t->di_type = di_type; } }
// Append the given character to the current token text static void append_to_token(lexer_t* lexer, char c) { if(lexer->buflen >= lexer->alloc) { size_t new_len = (lexer->alloc > 0) ? lexer->alloc << 1 : 64; char* new_buf = (char*)ponyint_pool_alloc_size(new_len); memcpy(new_buf, lexer->buffer, lexer->alloc); if(lexer->alloc > 0) ponyint_pool_free_size(lexer->alloc, lexer->buffer); lexer->buffer = new_buf; lexer->alloc = new_len; } lexer->buffer[lexer->buflen] = c; lexer->buflen++; }
static uint32_t trait_count(reach_type_t* t, uint32_t** list, size_t* list_size) { switch(t->underlying) { case TK_PRIMITIVE: case TK_CLASS: case TK_ACTOR: { uint32_t count = (uint32_t)reach_type_cache_size(&t->subtypes); if(count == 0) return 0; // Sort the trait identifiers. size_t tid_size = count * sizeof(uint32_t); uint32_t* tid = (uint32_t*)ponyint_pool_alloc_size(tid_size); size_t i = HASHMAP_BEGIN; size_t index = 0; reach_type_t* provide; while((provide = reach_type_cache_next(&t->subtypes, &i)) != NULL) tid[index++] = provide->type_id; qsort(tid, index, sizeof(uint32_t), cmp_uint32); count = (uint32_t)unique_uint32(tid, index); if(list != NULL) { *list = tid; *list_size = tid_size; } else { ponyint_pool_free_size(tid_size, tid); } return count; } default: {} } return 0; }
const char* suffix_filename(compile_t* c, const char* dir, const char* prefix, const char* file, const char* extension) { // Copy to a string with space for a suffix. size_t len = strlen(dir) + strlen(prefix) + strlen(file) + strlen(extension) + 4; char* filename = (char*)ponyint_pool_alloc_size(len); // Start with no suffix. #ifdef PLATFORM_IS_WINDOWS snprintf(filename, len, "%s\\%s%s%s", dir, prefix, file, extension); #else snprintf(filename, len, "%s/%s%s%s", dir, prefix, file, extension); #endif int suffix = 0; while(suffix < 100) { // Overwrite files but not directories. struct stat s; int err = stat(filename, &s); if((err == -1) || !S_ISDIR(s.st_mode)) break; #ifdef PLATFORM_IS_WINDOWS snprintf(filename, len, "%s\\%s%s%d%s", dir, prefix, file, ++suffix, extension); #else snprintf(filename, len, "%s/%s%s%d%s", dir, prefix, file, ++suffix, extension); #endif } if(suffix >= 100) { errorf(c->opt->check.errors, NULL, "couldn't pick an unused file name"); ponyint_pool_free_size(len, filename); return NULL; } return stringtab_consume(filename, len); }
static bool query_registry(HKEY key, bool query_subkeys, query_callback_fn fn, search_t* p) { DWORD sub_keys; DWORD largest_subkey; // Processing a leaf node in the registry, give it to the callback. if(!query_subkeys) { fn(key, NULL, p); return true; } get_child_count(key, &sub_keys, &largest_subkey); if(sub_keys == 0) return false; largest_subkey += 1; HKEY node; DWORD size = largest_subkey; char* name = (char*)ponyint_pool_alloc_size(largest_subkey); bool r = true; for(DWORD i = 0; i < sub_keys; ++i) { if(RegEnumKeyEx(key, i, name, &size, NULL, NULL, NULL, NULL) != ERROR_SUCCESS || RegOpenKeyEx(key, name, 0, KEY_QUERY_VALUE, &node) != ERROR_SUCCESS) { r = false; break; } fn(node, name, p); RegCloseKey(node); size = largest_subkey; } ponyint_pool_free_size(largest_subkey, name); return true; }
void* ponyint_heap_alloc_large(pony_actor_t* actor, heap_t* heap, size_t size) { size = ponyint_pool_adjust_size(size); chunk_t* chunk = (chunk_t*) POOL_ALLOC(chunk_t); chunk->actor = actor; chunk->size = size; chunk->m = (char*) ponyint_pool_alloc_size(size); chunk->slots = 0; chunk->shallow = 0; large_pagemap(chunk->m, size, chunk); chunk->next = heap->large; heap->large = chunk; heap->used += chunk->size; return chunk->m; }
source_t* source_open(const char* file, const char** error_msgp) { FILE* fp = fopen(file, "rb"); if(fp == NULL) { *error_msgp = "can't open file"; return NULL; } fseek(fp, 0, SEEK_END); ssize_t size = ftell(fp); if(size < 0) { *error_msgp = "can't determine length of file"; fclose(fp); return NULL; } fseek(fp, 0, SEEK_SET); source_t* source = POOL_ALLOC(source_t); source->file = stringtab(file); source->m = (char*)ponyint_pool_alloc_size(size + 1); source->len = size + 1; ssize_t read = fread(source->m, sizeof(char), size, fp); source->m[size] = '\0'; if(read < size) { *error_msgp = "failed to read entire file"; ponyint_pool_free_size(source->len, source->m); POOL_FREE(source_t, source); fclose(fp); return NULL; } fclose(fp); return source; }
static const char* quoted_locator(ast_t* use, const char* locator) { assert(locator != NULL); if(strpbrk(locator, "\t\r\n\"'`;$|&<>%*?[]{}()") != NULL) { if(use != NULL) ast_error(use, "use URI contains invalid characters"); return NULL; } size_t len = strlen(locator); char* quoted = (char*)ponyint_pool_alloc_size(len + 3); quoted[0] = '"'; memcpy(quoted + 1, locator, len); quoted[len + 1] = '"'; quoted[len + 2] = '\0'; return stringtab_consume(quoted, len + 3); }
// Append the given text to the program's lib args, handling reallocs. static void append_to_args(program_t* program, const char* text) { pony_assert(program != NULL); pony_assert(text != NULL); size_t text_len = strlen(text); size_t new_len = program->lib_args_size + text_len + 1; // +1 for terminator if(new_len > program->lib_args_alloced) { size_t new_alloc = 2 * new_len; // 2* so there's spare space for next arg char* new_args = (char*)ponyint_pool_alloc_size(new_alloc); memcpy(new_args, program->lib_args, program->lib_args_size + 1); ponyint_pool_free_size(program->lib_args_alloced, program->lib_args); program->lib_args = new_args; program->lib_args_alloced = new_alloc; } strcat(program->lib_args, text); program->lib_args_size = new_len - 1; // Don't add terminator to length }