diff --git a/Code/Dqn.h b/Code/Dqn.h index 4214b30..11eae74 100644 --- a/Code/Dqn.h +++ b/Code/Dqn.h @@ -599,7 +599,7 @@ enum struct Dqn_Allocator_Type XHeap, // Malloc realloc, free, crash on failure Arena, Custom, - NullAllocator, + Null, }; #define DQN_ALLOCATOR_ALLOCATE_PROC(name) void *name(Dqn_usize size) @@ -667,8 +667,8 @@ struct Dqn_MemArenaScopedRegion #define DQN_DEBUG_PARAMS #endif -#define DQN_MEM_ARENA_INIT_WITH_ALLOCATOR(arena, allocator, size) Dqn_MemArena_InitWithAllocator(arena, allocator, size DQN_DEBUG_PARAMS) -#define DQN_MEM_ARENA_INIT_MEMORY(arena, src, size) Dqn_MemArena_InitMemory(arena, src, size DQN_DEBUG_PARAMS) +#define DQN_MEM_ARENA_INIT_WITH_ALLOCATOR(allocator, size) Dqn_MemArena_InitWithAllocator(allocator, size DQN_DEBUG_PARAMS) +#define DQN_MEM_ARENA_INIT_MEMORY(src, size) Dqn_MemArena_InitMemory(src, size DQN_DEBUG_PARAMS) #define DQN_MEM_ARENA_ALLOC(arena, size) Dqn_MemArena_Alloc(arena, size DQN_DEBUG_PARAMS) #define DQN_MEM_ARENA_ALLOC_ARRAY(arena, T, num) (T *)Dqn_MemArena_Alloc(arena, sizeof(T) * num DQN_DEBUG_PARAMS) #define DQN_MEM_ARENA_ALLOC_STRUCT(arena, T) (T *)Dqn_MemArena_Alloc(arena, sizeof(T) DQN_DEBUG_PARAMS) @@ -681,28 +681,28 @@ DQN_HEADER_COPY_END // @ NOTE: Dqn_Allocator // @ // @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_NullAllocator()) +DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_Null()) { Dqn_Allocator result = {}; - result.type = Dqn_Allocator_Type::NullAllocator; + result.type = Dqn_Allocator_Type::Null; return result; } -DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_HeapAllocator()) +DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_Heap()) { Dqn_Allocator result = {}; result.type = Dqn_Allocator_Type::Heap; return result; } -DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_XHeapAllocator()) +DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_XHeap()) { Dqn_Allocator result = {}; result.type = Dqn_Allocator_Type::XHeap; return result; } -DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_ArenaAllocator(Dqn_MemArena *arena)) +DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_Arena(Dqn_MemArena *arena)) { Dqn_Allocator result = {}; result.type = Dqn_Allocator_Type::Arena; @@ -710,6 +710,24 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_ArenaAllocator(Dqn return result; } +// @ ------------------------------------------------------------------------------------------------- +// @ +// @ NOTE: String +// @ +// @ ------------------------------------------------------------------------------------------------- +DQN_HEADER_COPY_BEGIN +struct Dqn_String +{ + char *str; + Dqn_isize len; + char const *begin() const { return str; } + char const *end () const { return str + len; } + char *begin() { return str; } + char *end () { return str + len; } +}; +#define DQN_STRING_LITERAL(string) {string, Dqn_CharCountI(string)} +DQN_HEADER_COPY_END + // @ ------------------------------------------------------------------------------------------------- // @ // @ NOTE: String Builder @@ -833,22 +851,19 @@ DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_StringBuilder_BuildIn Dqn_StringBuilder__BuildOutput(builder, dest, dest_size); } -DQN_HEADER_COPY_PROTOTYPE(template char *, Dqn_StringBuilder_BuildFromMalloc(Dqn_StringBuilder *builder, Dqn_isize *len = nullptr)) +DQN_HEADER_COPY_PROTOTYPE(template char *, Dqn_StringBuilder_Build(Dqn_StringBuilder *builder, Dqn_Allocator *allocator, Dqn_isize *len = nullptr)) { Dqn_isize len_w_null_terminator = Dqn_StringBuilder_BuildLen(builder); - auto *result = static_cast(malloc(len_w_null_terminator)); - if (len) *len = len_w_null_terminator; + auto *result = DQN_CAST(char *)Dqn_Allocator_Allocate(allocator, sizeof(char) * len_w_null_terminator); + if (len) *len = len_w_null_terminator; Dqn_StringBuilder__BuildOutput(builder, result, len_w_null_terminator); return result; } -void *Dqn_MemArena_Alloc(Dqn_MemArena *arena, Dqn_usize size DQN_DEBUG_ARGS); -DQN_HEADER_COPY_PROTOTYPE(template char *, Dqn_StringBuilder_BuildFromArena(Dqn_StringBuilder *builder, Dqn_MemArena *arena, Dqn_isize *len = nullptr)) +DQN_HEADER_COPY_PROTOTYPE(template Dqn_String, Dqn_StringBuilder_BuildString(Dqn_StringBuilder *builder, Dqn_Allocator *allocator)) { - Dqn_isize len_w_null_terminator = Dqn_StringBuilder_BuildLen(builder); - char *result = DQN_MEM_ARENA_ALLOC_ARRAY(arena, char, len_w_null_terminator); - if (len) *len = len_w_null_terminator; - Dqn_StringBuilder__BuildOutput(builder, result, len_w_null_terminator); + Dqn_String result = {}; + result.str = Dqn_StringBuilder_Build(builder, allocator, &result.len); return result; } @@ -912,22 +927,18 @@ DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_StringBuilder_Free(Dq template struct Dqn_Slice { - union { T *data; T *buf; T *str; }; - union { Dqn_isize size; Dqn_isize len; }; - - Dqn_Slice() = default; - Dqn_Slice(T *str, Dqn_isize len) { this->str = str; this->len = len; } + T *data; + Dqn_isize len; T const &operator[] (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; } T &operator[] (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; } - T const *begin () const { return data; } - T const *end () const { return data + len; } - T *begin () { return data; } - T *end () { return data + len; } + T const *begin () const { return data; } + T const *end () const { return data + len; } + T *begin () { return data; } + T *end () { return data + len; } T const *operator+ (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data + i; } T *operator+ (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data + i; } }; -#define SLICE_LITERAL(string) Dqn_Slice(DQN_STR_AND_LEN(string)) DQN_HEADER_COPY_PROTOTYPE(template inline Dqn_Slice, Dqn_Slice_CopyNullTerminated(Dqn_MemArena *arena, T const *src, Dqn_isize len)) { @@ -968,51 +979,6 @@ DQN_HEADER_COPY_PROTOTYPE(template inline bool, Dqn_Slice_Equals(Dq return result; } - -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_Asprintf (Allocate Sprintf) -// @ -// @ ------------------------------------------------------------------------------------------------- -int Dqn_Safe_TruncateISizeToInt(Dqn_isize val); -DQN_HEADER_COPY_PROTOTYPE(template Dqn_Slice, Dqn_AsprintfSlice(T *arena, char const *fmt, va_list va)) -{ - Dqn_Slice result = {}; - result.len = stbsp_vsnprintf(nullptr, 0, fmt, va) + 1; - result.buf = DQN_MEM_ARENA_ALLOC_ARRAY(arena, char, result.len); - stbsp_vsnprintf(result.buf, Dqn_Safe_TruncateISizeToInt(result.len), fmt, va); - result.buf[result.len - 1] = 0; - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(template Dqn_Slice, Dqn_AsprintfSlice(T *arena, char const *fmt, ...)) -{ - va_list va; - va_start(va, fmt); - Dqn_Slice result = Dqn_AsprintfSlice(arena, fmt, va); - va_end(va); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(template char *, Dqn_Asprintf(T *arena, int *len, char const *fmt, ...)) -{ - va_list va; - va_start(va, fmt); - Dqn_Slice result = Dqn_AsprintfSlice(arena, fmt, va); - va_end(va); - if (len) *len = result.len; - return result.str; -} - -DQN_HEADER_COPY_PROTOTYPE(template char *, Dqn_Asprintf(T *arena, char const *fmt, ...)) -{ - va_list va; - va_start(va, fmt); - Dqn_Slice result = Dqn_AsprintfSlice(arena, fmt, va); - va_end(va); - return result.str; -} - // @ ------------------------------------------------------------------------------------------------- // @ // @ NOTE: Dqn_FixedArray @@ -1181,7 +1147,7 @@ DQN_HEADER_COPY_END DQN_HEADER_COPY_PROTOTYPE(template Dqn_Array, Dqn_Array_InitMemory(T *memory, Dqn_isize max, Dqn_isize len = 0)) { Dqn_Array result = {}; - result.allocator = Dqn_Allocator_NullAllocator(); + result.allocator = Dqn_Allocator_Null(); result.data = memory; result.len = len; result.max = max; @@ -1457,18 +1423,20 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Log(Dqn_LogType type, char const *file, D return true; } +void * Dqn_MemArena_Alloc(Dqn_MemArena *arena, Dqn_usize size DQN_DEBUG_ARGS); +Dqn_b32 Dqn_MemArena_Reserve(Dqn_MemArena *arena, Dqn_usize size DQN_DEBUG_ARGS); DQN_HEADER_COPY_PROTOTYPE(void *, Dqn_Allocator_Allocate(Dqn_Allocator *allocator, Dqn_usize size)) { void *result = nullptr; switch (allocator->type) { - case Dqn_Allocator_Type::NullAllocator: + case Dqn_Allocator_Type::Null: default: break; case Dqn_Allocator_Type::Heap: case Dqn_Allocator_Type::XHeap: { - result = malloc(size); + result = calloc(1, size); if (!result && allocator->type == Dqn_Allocator_Type::XHeap) { DQN_ASSERT(result); @@ -1494,7 +1462,6 @@ DQN_HEADER_COPY_PROTOTYPE(void *, Dqn_Allocator_Allocate(Dqn_Allocator *allocato return result; } -Dqn_b32 Dqn_MemArena_Reserve(Dqn_MemArena *arena, Dqn_usize size DQN_DEBUG_ARGS); DQN_HEADER_COPY_PROTOTYPE(void *, Dqn_Allocator_Realloc(Dqn_Allocator *allocator, void *old_ptr, Dqn_isize old_size, Dqn_isize new_size)) { DQN_IF_ASSERT(old_size >= 0) old_size = 0; @@ -1503,7 +1470,7 @@ DQN_HEADER_COPY_PROTOTYPE(void *, Dqn_Allocator_Realloc(Dqn_Allocator *allocator void *result = nullptr; switch (allocator->type) { - case Dqn_Allocator_Type::NullAllocator: + case Dqn_Allocator_Type::Null: default: break; case Dqn_Allocator_Type::Heap: @@ -1543,7 +1510,7 @@ DQN_HEADER_COPY_PROTOTYPE(void, Dqn_Allocator_Free(Dqn_Allocator *allocator, voi { switch (allocator->type) { - case Dqn_Allocator_Type::NullAllocator: + case Dqn_Allocator_Type::Null: default: break; case Dqn_Allocator_Type::Heap: @@ -1681,31 +1648,33 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_MemArena_Reserve(Dqn_MemArena *arena, Dqn return true; } -DQN_HEADER_COPY_PROTOTYPE(void, Dqn_MemArena_InitWithAllocator(Dqn_MemArena *arena, Dqn_Allocator allocator, Dqn_usize size DQN_DEBUG_ARGS)) +DQN_HEADER_COPY_PROTOTYPE(Dqn_MemArena, Dqn_MemArena_InitWithAllocator(Dqn_Allocator allocator, Dqn_usize size DQN_DEBUG_ARGS)) { #if defined(DQN_DEBUG_DQN_MEM_ARENA_LOGGING) (void)file; (void)file_len; (void)func; (void)func_len; (void)line; #endif - DQN_ASSERT_MSG(size >= sizeof(*arena->curr_mem_block), "(%zu >= %zu) There needs to be enough space to encode the Dqn_MemBlock struct into the memory buffer", size, sizeof(*arena->curr_mem_block)); - *arena = {}; - arena->allocator = allocator; - Dqn_MemBlock *mem_block = Dqn_MemArena__AllocateBlock(arena, size); - Dqn_MemArena__AttachBlock(arena, mem_block); + Dqn_MemArena result = {}; + DQN_ASSERT_MSG(size >= sizeof(*result.curr_mem_block), "(%zu >= %zu) There needs to be enough space to encode the Dqn_MemBlock struct into the memory buffer", size, sizeof(*result.curr_mem_block)); + result.allocator = allocator; + Dqn_MemBlock *mem_block = Dqn_MemArena__AllocateBlock(&result, size); + Dqn_MemArena__AttachBlock(&result, mem_block); + return result; } -DQN_HEADER_COPY_PROTOTYPE(void, Dqn_MemArena_InitMemory(Dqn_MemArena *arena, void *memory, Dqn_usize size DQN_DEBUG_ARGS)) +DQN_HEADER_COPY_PROTOTYPE(Dqn_MemArena, Dqn_MemArena_InitMemory(void *memory, Dqn_usize size DQN_DEBUG_ARGS)) { #if defined(DQN_DEBUG_DQN_MEM_ARENA_LOGGING) (void)file; (void)file_len; (void)func; (void)func_len; (void)line; #endif - DQN_ASSERT_MSG(size >= sizeof(*arena->curr_mem_block), "(%zu >= %zu) There needs to be enough space to encode the Dqn_MemBlock struct into the memory buffer", size, sizeof(*arena->curr_mem_block)); - *arena = {}; - arena->allocator = Dqn_Allocator_NullAllocator(); - auto *mem_block = DQN_CAST(Dqn_MemBlock *)memory; - *mem_block = {}; - mem_block->memory = DQN_CAST(Dqn_u8 *)memory + sizeof(*mem_block); - mem_block->size = size - sizeof(*mem_block); - Dqn_MemArena__AttachBlock(arena, mem_block); + Dqn_MemArena result = {}; + DQN_ASSERT_MSG(size >= sizeof(*result.curr_mem_block), "(%zu >= %zu) There needs to be enough space to encode the Dqn_MemBlock struct into the memory buffer", size, sizeof(*result.curr_mem_block)); + result.allocator = Dqn_Allocator_Null(); + auto *mem_block = DQN_CAST(Dqn_MemBlock *) memory; + *mem_block = {}; + mem_block->memory = DQN_CAST(Dqn_u8 *) memory + sizeof(*mem_block); + mem_block->size = size - sizeof(*mem_block); + Dqn_MemArena__AttachBlock(&result, mem_block); + return result; } DQN_HEADER_COPY_PROTOTYPE(void, Dqn_MemArena_ResetUsage(Dqn_MemArena *arena, Dqn_ZeroMem zero_mem)) @@ -1749,6 +1718,31 @@ Dqn_MemArenaScopedRegion::~Dqn_MemArenaScopedRegion() this->arena->curr_mem_block->used = this->curr_mem_block_used; } +// @ ------------------------------------------------------------------------------------------------- +// @ +// @ NOTE: Dqn_Asprintf (Allocate Sprintf) +// @ +// @ ------------------------------------------------------------------------------------------------- +int Dqn_Safe_TruncateISizeToInt(Dqn_isize val); +DQN_HEADER_COPY_PROTOTYPE(Dqn_String, Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, va_list va)) +{ + Dqn_String result = {}; + result.len = stbsp_vsnprintf(nullptr, 0, fmt, va) + 1; + result.str = DQN_CAST(char *)Dqn_Allocator_Allocate(allocator, sizeof(char) * result.len); + stbsp_vsnprintf(result.str, Dqn_Safe_TruncateISizeToInt(result.len), fmt, va); + result.str[result.len - 1] = 0; + return result; +} + +DQN_HEADER_COPY_PROTOTYPE(Dqn_String, Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, ...)) +{ + va_list va; + va_start(va, fmt); + Dqn_String result = Dqn_Asprintf(allocator, fmt, va); + va_end(va); + return result; +} + // @ ------------------------------------------------------------------------------------------------- // @ // @ NOTE: Vectors @@ -2124,7 +2118,7 @@ DQN_HEADER_COPY_PROTOTYPE(int, Dqn_Safe_TruncateUSizeToInt(Dqn_usize val)) DQN_HEADER_COPY_PROTOTYPE(Dqn_isize, Dqn_Safe_TruncateUSizeToISize(Dqn_usize val)) { - DQN_ASSERT_MSG(val <= CAST(Dqn_usize)ISIZE_MAX, "%zu <= %zu", val, CAST(Dqn_usize)ISIZE_MAX); + DQN_ASSERT_MSG(val <= DQN_CAST(Dqn_usize)DQN_ISIZE_MAX, "%zu <= %zu", val, DQN_CAST(Dqn_usize)DQN_ISIZE_MAX); auto result = DQN_CAST(Dqn_isize)val; return result; } @@ -2141,7 +2135,6 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Char_IsAlpha(char ch)) return result; } - DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Char_IsDigit(char ch)) { Dqn_b32 result = (ch >= '0' && ch <= '9'); @@ -2162,6 +2155,14 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Char_IsWhitespace(char ch)) return result; } +DQN_HEADER_COPY_PROTOTYPE(char, Dqn_Char_ToLower(char ch)) +{ + char result = ch; + if (result >= 'A' && result <= 'Z') + result = 'a' - 'A'; + return result; +} + // @ ------------------------------------------------------------------------------------------------- // @ // @ NOTE: String Helpers @@ -2382,6 +2383,39 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_i64, Dqn_Str_ToI64(char const *buf, int len = -1)) return result; } +// @ ------------------------------------------------------------------------------------------------- +// @ +// @ NOTE: Dqn_String +// @ +// @ ------------------------------------------------------------------------------------------------- +DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_String_Compare(Dqn_String const lhs, Dqn_String const rhs)) +{ + Dqn_b32 result = false; + if (lhs.len == rhs.len) + result = (memcmp(lhs.str, rhs.str, lhs.len) == 0); + return result; +} + +DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_String_CompareCaseInsensitive(Dqn_String const lhs, Dqn_String const rhs)) +{ + Dqn_b32 result = (lhs.len == rhs.len); + if (result) + { + for (Dqn_isize index = 0; index < lhs.len && result; index++) + result = (Dqn_Char_ToLower(lhs.str[index]) == Dqn_Char_ToLower(rhs.str[index])); + } + return result; +} + +DQN_HEADER_COPY_PROTOTYPE(Dqn_String, Dqn_String_Copy(Dqn_Allocator *allocator, Dqn_String const src)) +{ + Dqn_String result = src; + result.str = DQN_CAST(decltype(result.str))Dqn_Allocator_Allocate(allocator, sizeof(*result.str) * result.len); + memcpy(result.str, src.str, result.len); + return result; +} + + // @ ------------------------------------------------------------------------------------------------- // @ // @ NOTE: File diff --git a/Code/DqnHeader.h b/Code/DqnHeader.h index fd796e1..6da3a36 100644 --- a/Code/DqnHeader.h +++ b/Code/DqnHeader.h @@ -146,12 +146,12 @@ struct HeaderEntry { struct { - Dqn_Slice return_val; - Dqn_Slice name_and_args; + Dqn_String return_val; + Dqn_String name_and_args; } function_decl; - Dqn_Slice comment; - Dqn_Slice copy_range; + Dqn_String comment; + Dqn_String copy_range; }; }; @@ -229,8 +229,9 @@ int main(int argc, char *argv[]) isize func_name_len = 0; char const *func_name = ParseFunctionNameAndParameters(ptr, &func_name_len); - entry->function_decl.return_val = Dqn_AsprintfSlice(&arena, "%.*s", func_type_len, func_type); - entry->function_decl.name_and_args = Dqn_AsprintfSlice(&arena, "%.*s", func_name_len, func_name); + Dqn_Allocator allocator = Dqn_Allocator_Arena(&arena); + entry->function_decl.return_val = Dqn_Asprintf(&allocator, "%.*s", func_type_len, func_type); + entry->function_decl.name_and_args = Dqn_Asprintf(&allocator, "%.*s", func_name_len, func_name); ptr = func_name + func_name_len + 1; // Ptr is at macro closing paren, skip the paren max_prototype_return_val = DQN_MAX(max_prototype_return_val, func_type_len); @@ -243,7 +244,7 @@ int main(int argc, char *argv[]) ptr++; isize comment_len = ptr - comment_start; - entry->comment.buf = DQN_MEM_ARENA_ALLOC_ARRAY(&arena, char, comment_len); + entry->comment.str = DQN_MEM_ARENA_ALLOC_ARRAY(&arena, char, comment_len); DQN_FOR_EACH(comment_index, comment_len) { // NOTE: We capture "// @", and we want to skip the @ symbol, its ugly which is at the index 3 @@ -251,10 +252,10 @@ int main(int argc, char *argv[]) char ch = comment_start[comment_index]; if (comment_index == 3 && ch == '@') continue; if (comment_index == 4 && ch == ' ') continue; - entry->comment.buf[entry->comment.len++] = ch; + entry->comment.str[entry->comment.len++] = ch; } - while (entry->comment.len > 0 && Dqn_Char_IsWhitespace(entry->comment.buf[entry->comment.len - 1])) + while (entry->comment.len > 0 && Dqn_Char_IsWhitespace(entry->comment.str[entry->comment.len - 1])) entry->comment.len--; ptr = comment_start + comment_len; } @@ -271,12 +272,12 @@ int main(int argc, char *argv[]) } isize copy_len = copy_end - copy_start; - entry->copy_range.buf = (char *)DQN_MEM_ARENA_ALLOC(&arena, copy_len); + entry->copy_range.str = (char *)DQN_MEM_ARENA_ALLOC(&arena, copy_len); DQN_FOR_EACH(copy_index, copy_len) { char ch = copy_start[copy_index]; if (ch == '\r') continue; - entry->copy_range.buf[entry->copy_range.len++] = ch; + entry->copy_range.str[entry->copy_range.len++] = ch; } ptr = copy_end; } @@ -301,13 +302,13 @@ int main(int argc, char *argv[]) case HeaderEntryType::Comment: { - fprintf(stdout, "%.*s\n", (int)entry->comment.len, entry->comment.buf); + fprintf(stdout, "%.*s\n", (int)entry->comment.len, entry->comment.str); } break; case HeaderEntryType::CopyBegin: { - fprintf(stdout, "%.*s\n", (int)entry->copy_range.len, entry->copy_range.buf); + fprintf(stdout, "%.*s\n", (int)entry->copy_range.len, entry->copy_range.str); } break; }