Commit 55c01759 authored by Jamie A. Jennings's avatar Jamie A. Jennings

(1) Enhanced ktable to hold string length (no more requiring null...

(1) Enhanced ktable to hold string length (no more requiring null termination).  (2) Introduced new logging flags (at compile time) like BUFDEBUG, FILEDEBUG.  Now, we can enable DEBUG=1 to get all the asserts to run without also getting logging output.  Really we should start using syslog, now that we have lots of different kinds of log messages.
parent 6cc5c0c6
......@@ -98,14 +98,15 @@ static void stackDump (lua_State *L) {
LOGstack(L); \
luaL_error((L), "%s:%d: did not get right type for ktable", __FILE__, __LINE__); \
} \
Ktable *kt = (Ktable *)lua_touserdata((L), (idx)); \
const char *_name = ktable_element(kt, (i)); \
if (_name) lua_pushstring((L), _name); \
Ktable *_kt = (Ktable *)lua_touserdata((L), (idx)); \
size_t _len; \
const char *_name = ktable_element_name(_kt, (i), &_len); \
if (_name) lua_pushlstring((L), _name, _len); \
else { \
LOG("nil ktable value\n"); \
lua_pushnil((L)); } \
} while (0)
#endif
......@@ -227,8 +227,10 @@ void printktable (Ktable *kt) {
n = ktable_len(kt);
printf("[");
for (i = 1; i <= n; i++) {
size_t len;
const char *name = ktable_element_name(kt, i, &len);
printf("%d = ", i);
printf("%s ", ktable_element(kt, i));
printf("%.*s ", (int) len, name);
}
printf("]\n");
}
......
......@@ -92,8 +92,9 @@ static const char *val2str (lua_State *L, int idx) {
*/
static void fixonecall (lua_State *L, int postable, TTree *g, TTree *t, Ktable *kt) {
int n;
const char *rulename = ktable_element(kt, t->key);
lua_pushstring(L, rulename);
size_t len;
const char *rulename = ktable_element_name(kt, t->key, &len);
lua_pushlstring(L, rulename, len);
lua_gettable(L, postable); /* query name in position table */
n = lua_tonumber(L, -1); /* get (absolute) position */
......@@ -132,12 +133,16 @@ static void correctassociativity (TTree *tree) {
#if 0
/* find a duplicate for the ktable element at 'key' */
static int find_ktable_duplicate(Ktable *kt, int key) {
const char *target_element = ktable_element(kt, key);
size_t name_len, target_len;
const char *name;
const char *target_element = ktable_element_name(kt, key, &target_len);
int last = ktable_len(kt);
for (int i = 1; i <= last; i++)
for (int i = 1; i <= last; i++) {
name = ktable_element_name(kt, i, &name_len);
if ((i != key) &&
(strncmp(ktable_element(kt, i), target_element, KTABLE_MAX_ELEMENT_LEN)==0))
(ktable_entry_name_cmp(name, name_len, target_element, target_len)))
return i;
}
return 0; /* no match */
}
#endif
......@@ -252,9 +257,10 @@ static int addtoktable (lua_State *L, int idx) {
else if (!lua_isstring(L, idx))
return luaL_error(L, "(add) ktable entry is not a string: %s", lua_tostring(L, idx));
else {
const char *s = lua_tostring(L, idx); /* element to be added */
size_t len;
const char *s = lua_tolstring(L, idx, &len); /* element to be added */
assert (s);
if (!ktable_add(kt, (const char *)s))
if (!ktable_add(kt, (const char *)s, len))
luaL_error(L, "(add) out of memory");
return n+1; /* index of newly added item */
}
......@@ -1153,7 +1159,9 @@ static void initialrulename (lua_State *L, TTree *grammar, int frule) {
LOGf("initial rule not referenced, and n = %d\n", n);
lua_pushvalue(L, frule); /* rule's name */
assert( lua_isstring(L, -1) );
int actualpos = ktable_add(kt, lua_tostring(L, -1));
size_t name_len;
const char *name = lua_tolstring(L, -1, &name_len);
int actualpos = ktable_add(kt, name, name_len);
if (!actualpos)
luaL_error(L, "(initial rule) out of memory");
lua_pop(L, 1); /* remove rule name (string) */
......@@ -1260,7 +1268,16 @@ static void compact_ktable(lua_State *L, Pattern *p) {
int idx, newidx;
Ktable *ckt = ktable_compact(p->kt);
if (!ckt) luaL_error(L, "%s:%d: could not compact ktable\n", __FILE__, __LINE__);
if (ckt == p->kt) return; /* no action was taken by ktable_compact */
// if (ckt == p->kt) return; /* no action was taken by ktable_compact */
#if 0
/* DEBUGGING */
printf("BEFORE COMPACTING:\n");
ktable_dump(p->kt);
printf("AFTER COMPACTING:\n");
ktable_dump(ckt);
printf("---\n");
#endif
/*
Create mapping from old to new.
Note: alloca fails in an odd way, not returning NULL, when
......@@ -1270,9 +1287,12 @@ static void compact_ktable(lua_State *L, Pattern *p) {
if (!mapping) luaL_error(L, "%s:%d: out of memory (while compacting ktable)\n", __FILE__, __LINE__);
mapping[0] = 0;
for (idx = 1; idx <= ktable_len(p->kt); idx++) { /* 0 is an unused index */
newidx = ktable_compact_search(ckt, ktable_element(p->kt, idx));
size_t len;
const char *name = ktable_element_name(p->kt, idx, &len);
newidx = ktable_compact_search(ckt, name, len);
if (newidx == 0) {
free(mapping);
//printf("incomplete compacted ktable: missing '%.*s'\n", (int) len, name);
luaL_error(L, "%s:%d: incomplete compacted ktable\n", __FILE__, __LINE__);
}
mapping[idx] = newidx;
......
......@@ -29,8 +29,6 @@
#define INT_FMT "%d"
#define r_inttostring(s, i) (snprintf((char *)(s), (MAXNUMBER2STR), (INT_FMT), (i)))
#define getfromktable(cs,v) ktable_element((cs)->kt, (v))
int debug_Close(CapState *cs, Buffer *buf, int count, const char *start);
int debug_Open(CapState *cs, Buffer *buf, int count);
......
......@@ -9,13 +9,19 @@
#if !defined(ktable_h)
#define ktable_h
typedef struct Ktable_element {
int32_t start; /* index into block */
int32_t len; /* length of string in block */
int32_t entrypoint; /* index into code vector, or -1 for none */
} Ktable_element;
typedef struct Ktable {
char *block; /* storage for null-terminated strings */
size_t blocksize; /* size of storage block */
int blocknext; /* next available char is block[blocknext] */
int *elements; /* array of indices into block */
int size; /* size of array */
int next; /* next available ktable entry is elements[next] */
int32_t blocknext; /* next available char is block[blocknext] */
Ktable_element *elements;
int32_t size; /* capacity of elements array */
int32_t next; /* next available ktable entry is elements[next] */
} Ktable;
/* Parameters that can be tuned for performance:
......@@ -43,19 +49,22 @@ static const char __attribute__ ((unused)) *KTABLE_MESSAGES[] = {
#define ktable_messages ((int) ((sizeof KTABLE_MESSAGES) / sizeof (const char *)))
#define blockspace(kt) ( (size_t) (kt)->blocksize - (kt)->blocknext )
#define elementlen(e) (strnlen((e), KTABLE_MAX_ELEMENT_LEN) + 1)
#define elementlen(e) ( (e)->len )
Ktable *ktable_new(int initial_size, size_t initial_blocksize);
void ktable_free(Ktable *kt);
int ktable_concat(Ktable *kt1, Ktable *kt2, int *n);
int ktable_add(Ktable *kt, const char *element);
int ktable_add(Ktable *kt, const char *element, size_t len);
int ktable_len(Ktable *kt);
const char *ktable_element(Ktable *kt, int i);
int *ktable_sorted_index(Ktable *kt);
Ktable_element *ktable_element(Ktable *kt, int i);
const char *ktable_element_name(Ktable *kt, int i, size_t *len);
Ktable_element *ktable_sorted_index(Ktable *kt);
Ktable *ktable_compact(Ktable *orig);
int ktable_compact_search(Ktable *kt, const char *target);
int ktable_compact_search(Ktable *kt, const char *target, size_t len);
int ktable_entry_name_cmp(const char *a, size_t alen, const char *b, size_t blen);
/* debugging */
void ktable_dump(Ktable *kt);
#endif
......@@ -32,8 +32,22 @@ debugger_flag=-O0 -g
ndebug_flag=
endif
COPT = -O2 $(debug_flag) $(ndebug_flag) $(debugger_flag)
FILES = buf.o vm.o ktable.o capture.o file.o json.o rplx.o
# How to set these generically?
ifdef FILEDEBUG
filedebug='-DFILEDEBUG=1'
endif
ifdef VMEBUG
vmdebug='-DVMDEBUG=1'
endif
ifdef BUFDEBUG
bufdebug='-DBUFDEBUG=1'
endif
COPT = -O2 $(debug_flag) $(ndebug_flag) $(debugger_flag) $(filedebug) $(vmdebug) $(bufdebug)
FILES = buf.o vm.o ktable.o capture.o file.o json.o rplx.o
ifeq ($(PLATFORM), macosx)
CC= cc
......
......@@ -25,11 +25,13 @@
#include <string.h>
#include "buf.h"
#ifndef DEBUG
#define DEBUG 0
#ifndef BUFDEBUG
#define BUFDEBUG 0
#else
#define BUFDEBUG 1
#endif
#if DEBUG
#if BUFDEBUG
#define Announce_free(b) do { \
fprintf(stderr, "*** freeing buffer->data %p (capacity was %ld)\n", (void *)(b->data), b->capacity); \
......
......@@ -32,18 +32,21 @@
*/
static void print_capture(CapState *cs) {
size_t len;
Capture *c = cs->cap;
printf(" kind = %s\n", CAPTURE_NAME(capkind(c)));
printf(" pos (1-based) = %lu\n", c->s ? (c->s - cs->s + 1) : 0);
const char *str = getfromktable(cs, capidx(c));
const char *str = ktable_element_name(cs->kt, capidx(c), &len);
if (str) {
printf(" idx = %u\n", capidx(c));
printf(" ktable[idx] = %s\n", str);
printf(" ktable[idx] = %.*s\n", (int) len, str);
}
}
static void print_constant_capture(CapState *cs) {
printf(" constant match: %s\n", getfromktable(cs, capidx(cs->cap)));
size_t len;
const char *str = ktable_element_name(cs->kt, capidx(cs->cap), &len);
printf(" constant match: %.*s\n", (int) len, str);
}
int debug_Close(CapState *cs, Buffer *buf, int count, const char *start) {
......@@ -110,8 +113,11 @@ static void encode_string(const char *str, size_t len,
}
static void encode_ktable_element(CapState *cs, byte negflag, Buffer *buf) {
const char *name = getfromktable(cs, capidx(cs->cap));
encode_string(name, strnlen(name, KTABLE_MAX_ELEMENT_LEN), 1, negflag, buf); /* shortflag is set */
size_t len;
const char *name = ktable_element_name(cs->kt, capidx(cs->cap), &len);
assert( name );
//assert( len > 0 ); //len could be zero?
encode_string(name, len, 1, negflag, buf); /* shortflag is set */
}
int byte_Close(CapState *cs, Buffer *buf, int count, const char *start) {
......
......@@ -10,6 +10,12 @@
#define RPLX_FILE_MIN_VERSION 0 /* min version this code will accept */
#define RPLX_FILE_MAX_VERSION 0 /* max version this code will accept */
#ifndef FILEDEBUG
#define FILEDEBUG 0
#else
#define FILEDEBUG 1
#endif
/* TODO
*
* Add meta-data to binary files, including:
......@@ -125,9 +131,10 @@ static int read_newline(FILE *stream) {
if (written != 1) return FILE_ERR_WRITE; \
}
/* TODO: fclose(out) before returning an error code */
int file_save (const char *filename, Chunk *chunk) {
FILE *out;
size_t written;
size_t bytes, written;
int ok;
out = fopen(filename, "wb");
......@@ -139,35 +146,46 @@ int file_save (const char *filename, Chunk *chunk) {
Ktable *kt = chunk->ktable;
assert( kt );
assert( kt->next > 0 );
assert( kt->block );
assert( kt->blocknext > 0 );
#if DEBUG
assert( kt->elements );
assert( kt->size > 0 );
assert( kt->next > 0 );
#if FILEDEBUG
fprintf(stderr, "file_save: number of ktable entries is %d\n", kt->next - 1);
#endif
ok = write_int(out, kt->next - 1);
if (!ok) return FILE_ERR_WRITE;
#if DEBUG
#if FILEDEBUG
fprintf(stderr, "file_save: size of ktable block is %d\n", kt->blocknext);
#endif
ok = write_int(out, kt->blocknext);
if (!ok) return FILE_ERR_WRITE;
write_newline(out);
bytes = kt->next * sizeof(Ktable_element);
written = fwrite(kt->elements, bytes, 1, out);
if (written != 1) return FILE_ERR_WRITE;
write_newline(out);
written = fwrite(kt->block, kt->blocknext, 1, out);
if (written != 1) return FILE_ERR_WRITE;
write_newline(out);
#if DEBUG
#if FILEDEBUG
fprintf(stderr, "file_save: number of instructions is %zu\n", chunk->codesize);
#endif
ok = write_int(out, chunk->codesize);
#if DEBUG
#if FILEDEBUG
fprintf(stderr, "file_save: saved instruction size %s\n", ok ? "ok" : "ERROR");
#endif
if (!ok) return FILE_ERR_WRITE;
written = fwrite(chunk->code, sizeof(Instruction), chunk->codesize, out);
if (written != chunk->codesize) return FILE_ERR_WRITE;
#if DEBUG
#if FILEDEBUG
fprintf(stderr, "file_save: number of instructions written is %zu\n", written);
#endif
......@@ -181,7 +199,7 @@ int file_save (const char *filename, Chunk *chunk) {
int file_load (const char *filename, Chunk *chunk) {
FILE *in;
size_t len;
int n, ok, ktable_bytes;
int n, ok, blocksize;
size_t bytes;
char magic[sizeof(FILE_MAGIC_NUMBER)];
......@@ -193,46 +211,61 @@ int file_load (const char *filename, Chunk *chunk) {
if (strncmp(magic, FILE_MAGIC_NUMBER, sizeof(FILE_MAGIC_NUMBER)) != 0)
return FILE_ERR_MAGIC_NUMBER;
#if FILEDEBUG
fprintf(stderr, "file_load: magic number ok\n");
#endif
/* TODO: Insert a read of file version here. Check against min, max. */
/* TODO: Insert a read of endianness here. */
/* TODO: Insert a read of rpl major/minor versions here. */
ok = read_int(in, &n);
if (!ok) return FILE_ERR_READ;
if ((n < 0) || (n > MAX_CAPLISTSIZE)) return FILE_ERR_KTABLE_LEN;
ok = read_int(in, &ktable_bytes);
if (!ok) return FILE_ERR_READ;
if ((ktable_bytes < 0) || (ktable_bytes > MAX_INSTLEN_BYTES)) return FILE_ERR_KTABLE_SIZE;
#if FILEDEBUG
fprintf(stderr, "file_load: number of ktable entries is %d\n", n);
#endif
/* FUTURE: Move the code below into ktable.c, into a new function that
* creates a new (nonempty) ktable, given its block.
*/
ok = read_int(in, &blocksize);
if (!ok) return FILE_ERR_READ;
#if FILEDEBUG
fprintf(stderr, "file_load: size of ktable block is %d\n", blocksize);
#endif
if ((blocksize < 0) || (blocksize > MAX_INSTLEN_BYTES)) return FILE_ERR_KTABLE_SIZE;
Ktable *kt = ktable_new(n, ktable_bytes);
kt->next = n + 1;
if (read_newline(in) < 0) return FILE_ERR_READ;
ok = fread(kt->block, kt->blocksize, 1, in);
Ktable *kt = ktable_new(n, blocksize);
kt->blocksize = blocksize;
kt->size = n; /* capacity */
kt->next = n + 1; /* next element requires more capacity */
/* N.B. This is dependent on same endianness of file writer and file reader */
bytes = (n+1) * sizeof(Ktable_element);
ok = fread(kt->elements, bytes, 1, in);
#if FILEDEBUG
fprintf(stderr, "file_load: read of elements %s\n",
(ok != -1) ? "succeeded" : "failed");
#endif
if (ok != 1) return FILE_ERR_READ;
kt->elements[1] = 0;
int next = 2;
for (size_t i = 0; i < kt->blocksize; i++) {
if (next > n) break;
if (kt->block[i] == '\0') {
kt->elements[next] = i + 1;
next++;
}
}
if (read_newline(in) < 0) return FILE_ERR_READ;
assert( next == kt->next );
ok = fread(kt->block, kt->blocksize, 1, in);
#if FILEDEBUG
fprintf(stderr, "file_load: read of block %s\n",
(ok != -1) ? "succeeded" : "failed");
#endif
if (ok != 1) return FILE_ERR_READ;
kt->blocknext = kt->blocksize;
if (read_newline(in) < 0) return FILE_ERR_READ;
ok = read_int(in, &n);
bytes = n * sizeof(Instruction);
#if DEBUG
fprintf(stderr, "n is %d, bytes is %zu\n", n, bytes);
#if FILEDEBUG
fprintf(stderr, "file_load: number of instructions is %d, bytes is %zu\n", n, bytes);
#endif
if ((n < 0) || (bytes > MAX_INSTLEN_BYTES)) return FILE_ERR_INST_LEN;
......@@ -241,7 +274,7 @@ int file_load (const char *filename, Chunk *chunk) {
len = fread((char *)buf, sizeof(Instruction), n, in);
if (len != (size_t) n) return FILE_ERR_READ;
#if DEBUG
#if FILEDEBUG
fprintf(stderr, "file_load: number of instructions read is %d\n", n);
#endif
if (read_newline(in) < 0) return FILE_ERR_READ;
......@@ -249,8 +282,8 @@ int file_load (const char *filename, Chunk *chunk) {
chunk->codesize = (size_t) n;
chunk->code = buf;
chunk->ktable = kt;
chunk->rpl_major = 0; /* TODO */
chunk->rpl_minor = 0; /* TODO */
chunk->rpl_major = 0; /* TODO */
chunk->rpl_minor = 0; /* TODO */
chunk->file_version = 0; /* TODO */
chunk->filename = strndup(filename, MAXPATHLEN);
......
......@@ -95,8 +95,9 @@ static void json_encode_pos(size_t pos, Buffer *buf) {
}
static void json_encode_ktable_element(CapState *cs, Buffer *buf) {
const char *name = getfromktable(cs, capidx(cs->cap));
buf_addstring(buf, name);
size_t len;
const char *name = ktable_element_name(cs->kt, capidx(cs->cap), &len);
buf_addlstring(buf, name, len);
}
int json_Close(CapState *cs, Buffer *buf, int count, const char *start) {
......
This diff is collapsed.
......@@ -51,11 +51,13 @@
/* ----------------------------------------------------------------------------- */
#ifndef DEBUG
#define DEBUG 0
#ifndef STACKDEBUG
#define STACKDEBUG 0
#else
#define STACKDEBUG 1
#endif
#if DEBUG
#if STACKDEBUG
#define Announce_stack_expand(stack) do { \
fprintf(stderr, "*** expanding %s stack (current size is %ld)\n", \
stack->name, STACK_CAPACITY(*(stack))); \
......
......@@ -18,7 +18,13 @@
#include "buf.h"
#include "vm.h"
#if DEBUG
#ifndef VMDEBUG
#define VMDEBUG 0
#else
#define VMDEBUG 1
#endif
#if VMDEBUG
#define Announce_doublecap(oldsize) do { \
fprintf(stderr, "*** doubling current capture array size of %d\n", (oldsize)); \
......@@ -86,7 +92,8 @@ static Capture *doublecap (Capture *cap, Capture *initial_capture, int captop) {
static void BTEntry_stack_print (BTEntry_stack *stack, const char *o, Instruction *op) {
BTEntry *top;
for (top = (stack->next - 1); top >= stack->base; top--)
printf("%ld: pos=%ld, pc %ld: %s, caplevel=%d\n",
fprintf(stderr,
"%ld: pos=%ld, pc %ld: %s, caplevel=%d\n",
top - stack->base,
(top->s == NULL) ? -1 : (top->s - o),
(top->p == &giveup) ? -1 : (top->p - op),
......@@ -244,10 +251,10 @@ static int find_prior_capture(Capture *capture, int captop, int target_idx,
#if 0
#define PRINT_VM_STATE do { \
printf("Next instruction: %ld %s\n", \
fprintf(stderr, "Next instruction: %ld %s\n", \
p - op, \
OPCODE_NAME(p->i.code)); \
printf("Stack: next=%ld, limit=%ld, base==init: %s\n", \
fprintf(stderr, "Stack: next=%ld, limit=%ld, base==init: %s\n", \
stack.next - stack.base, \
STACK_CAPACITY(stack), \
(stack.base == &stack.init[0]) ? "static" : "dynamic"); \
......@@ -539,8 +546,8 @@ static int vm (const char **r,
return MATCH_OK;
}
default: {
if (DEBUG) {
printf("Illegal opcode at %d: %d\n", (int) (pc - op), opcode(pc));
if (VMDEBUG) {
fprintf(stderr, "Illegal opcode at %d: %d\n", (int) (pc - op), opcode(pc));
printcode(op); /* print until IEnd */
}
assert(0);
......@@ -744,7 +751,7 @@ int vm_match (Chunk *chunk, Buffer *input, int start, Encoder encode,
// PASSING KTABLE TO VM ONLY FOR DEBUGGING
err = vm(&r, s, s + i, s + l, chunk->code, &capture, stats, capstats, chunk->ktable);
#if (DEBUG)
#if (VMDEBUG)
printf("vm() completed with err code %d, r as position = %ld\n", err, r ? r - s : 0);
if (stats) printf("vm executed %d instructions\n", stats->insts);
printf("capstats from vm: Close %d, Rosiecap %d\n", capstats[Cclose], capstats[Crosiecap]);
......
......@@ -10,9 +10,9 @@
#include <stdlib.h>
#include <assert.h>
#include "../config.h"
#include "../rplx.h"
#include "../file.h"
#include "config.h"
#include "rplx.h"
#include "file.h"
void error(const char *msg) {
fprintf(stderr, "Error: %s\n", msg);
......
......@@ -9,7 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../ktable.h"
#include "ktable.h"
void *error(const char *msg) {
fprintf(stderr, "%s\n", msg);
......@@ -27,24 +27,24 @@ int main(int argc, char **argv) {
if (!k1) error("failed to create new table");
ktable_dump(k1);
ok = ktable_add(k1, "first");
ok = ktable_add(k1, "first", 5);
if (!ok) error("first add failed");
ktable_dump(k1);
ok = ktable_add(k1, "#2");
ok = ktable_add(k1, "#2", 2);
if (!ok) error("second add failed");
ktable_dump(k1);
ok = ktable_add(k1, "3");
ok = ktable_add(k1, "3", 1);
if (!ok) error("third add failed");
ktable_dump(k1);
ok = ktable_add(k1, "FOUR");
ok = ktable_add(k1, "FOUR", 4);
if (!ok) error("fourth add failed");
ktable_dump(k1);
for (int i = 1; i <= 20; i++) {
ok = ktable_add(k1, "abcdef");
ok = ktable_add(k1, "abcdef", 6);
if (!ok) error("repeated add failed");
ktable_dump(k1);
}
......@@ -58,11 +58,12 @@ int main(int argc, char **argv) {
size_t justright_len = strnlen(justright, 2 * KTABLE_MAX_ELEMENT_LEN);
printf("Length of next string is %zu\n", justright_len);
ok = ktable_add(k1, justright);
ok = ktable_add(k1, justright, justright_len);
if (!ok) error("justright add failed");
ktable_dump(k1);
size_t element_len = strnlen(ktable_element(k1, ok), 2 * KTABLE_MAX_ELEMENT_LEN);
size_t element_len;
const char *element = ktable_element_name(k1, ok, &element_len);
int truncated = (element_len < justright_len);
printf("Length of last element added is %zu and %s truncated... ",
element_len, truncated ? "WAS" : "was not");
......@@ -77,20 +78,21 @@ int main(int argc, char **argv) {
size_t toobig_len = strnlen(toobig, 2 * KTABLE_MAX_ELEMENT_LEN);
printf("Length of next string is %zu\n", toobig_len);
ok = ktable_add(k1, toobig);
ok = ktable_add(k1, toobig, toobig_len);
if (!ok) error("toobig add failed");
ktable_dump(k1);
element_len = strnlen(ktable_element(k1, ok), 2 * KTABLE_MAX_ELEMENT_LEN);
element = ktable_element_name(k1, ok, &element_len);
truncated = (element_len < toobig_len);
printf("Length of last element added is %zu and %s truncated... ",
element_len, truncated ? "WAS" : "was not");
printf(truncated ? "correct.\n" : "ERROR!\n");
printf("Testing indexing into ktable with bad index values:\n");
for (int i = -2; i < ktable_len(k1) + 2; i++)
printf(" index %d is %s\n", i,
(ktable_element(k1, i) == NULL) ? "invalid" : "ok");
for (int i = -2; i < ktable_len(k1) + 2; i++) {
element = ktable_element_name(k1, i, &element_len);
printf(" index %d is %s\n", i, element==NULL ? "invalid" : "ok");
}
/* ---------------------------------------------------------------------------------------- */
printf("\nPart 2: concat two tables\n\n");
......@@ -100,7 +102,8 @@ int main(int argc, char **argv) {
printf("Length of k1 is %d; length of (new) k2 is %d\n", ktable_len(k1), ktable_len(k2));
int n = ktable_concat(k1, k2);
int n;
if (ktable_concat(k1, k2, &n) != KTABLE_OK) error("failed to concat two tables");
printf("moved contents of k1 into k2; amount to correct by is %d\n", n);
if (n != 0) {
......@@ -108,7 +111,7 @@ int main(int argc, char **argv) {
}
ktable_dump(k2);
n = ktable_concat(k1, k2);
if (ktable_concat(k1, k2, &n) != KTABLE_OK) error("failed to concat two tables");
printf("moved contents of k1 into k2; amount to correct by is %d\n", n);
if (n != 26) {
......@@ -118,7 +121,7 @@ int main(int argc, char **argv) {
Ktable *k3 = ktable_new(4, 4*30);
n = ktable_concat(k3, k2);
if (ktable_concat(k3, k2, &n) != KTABLE_OK) error("failed to concat two tables");
printf("moved contents of (empty) k3 into k2; amount to correct by is %d\n", n);
if (n != 0) {
......@@ -126,4 +129,13 @@ int main(int argc, char **argv) {
}
ktable_dump(k2);
/* ---------------------------------------------------------------------------------------- */
printf("\nPart 3: compact a table\n\n");
ktable_free(k3);
k3 = ktable_compact(k2);
if (!k3) error("compact_ktable failed");
printf("length of compacted ktable is %d\n", ktable_len(k3));
ktable_dump(k3);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment