diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..313ed4b --- /dev/null +++ b/.clang-format @@ -0,0 +1,31 @@ +Language: Cpp +BasedOnStyle: LLVM + +AlignAfterOpenBracket: DontAlign +AlignConsecutiveAssignments: None +AllowShortBlocksOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: true +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeBraces: Custom +BreakConstructorInitializers: AfterColon +BraceWrapping: + AfterControlStatement: false + AfterFunction: true + AfterStruct: false + AfterUnion: false + BeforeElse: false +ColumnLimit: 0 +ContinuationIndentWidth: 8 +IncludeBlocks: Preserve +IndentCaseLabels: true +IndentWidth: 8 +KeepEmptyLinesAtTheStartOfBlocks: false +MaxEmptyLinesToKeep: 2 +SortIncludes: true +SpaceAfterCStyleCast: true +SpacesBeforeTrailingComments: 0 +TabWidth: 8 +UseTab: Always +... diff --git a/chan.c b/chan.c index a3d1cc8..cdd149f 100644 --- a/chan.c +++ b/chan.c @@ -27,10 +27,10 @@ chan_init(struct ovni_chan *chan, enum chan_track track, int row, int type, FILE static void mark_dirty(struct ovni_chan *chan, enum chan_dirty dirty) { - if(chan->dirty != CHAN_CLEAN) + if (chan->dirty != CHAN_CLEAN) die("mark_dirty: chan %d already dirty\n", chan->id); - if(dirty == CHAN_CLEAN) + if (dirty == CHAN_CLEAN) die("mark_dirty: cannot use CHAN_CLEAN\n"); dbg("adding dirty chan %d to list\n", chan->id); @@ -40,15 +40,15 @@ mark_dirty(struct ovni_chan *chan, enum chan_dirty dirty) void chan_th_init(struct ovni_ethread *th, - struct ovni_chan **update_list, - enum chan id, - enum chan_track track, - int init_st, - int enabled, - int dirty, - int row, - FILE *prv, - int64_t *clock) + struct ovni_chan **update_list, + enum chan id, + enum chan_track track, + int init_st, + int enabled, + int dirty, + int row, + FILE *prv, + int64_t *clock) { struct ovni_chan *chan; int prvth; @@ -63,21 +63,21 @@ chan_th_init(struct ovni_ethread *th, chan->update_list = update_list; chan->enabled = enabled; chan->stack[chan->n++] = init_st; - if(dirty) + if (dirty) mark_dirty(chan, CHAN_DIRTY_ACTIVE); } void chan_cpu_init(struct ovni_cpu *cpu, - struct ovni_chan **update_list, - enum chan id, - enum chan_track track, - int init_st, - int enabled, - int dirty, - int row, - FILE *prv, - int64_t *clock) + struct ovni_chan **update_list, + enum chan id, + enum chan_track track, + int init_st, + int enabled, + int dirty, + int row, + FILE *prv, + int64_t *clock) { struct ovni_chan *chan; int prvcpu; @@ -92,7 +92,7 @@ chan_cpu_init(struct ovni_cpu *cpu, chan->update_list = update_list; chan->enabled = enabled; chan->stack[chan->n++] = init_st; - if(dirty) + if (dirty) mark_dirty(chan, CHAN_DIRTY_ACTIVE); } @@ -102,9 +102,8 @@ chan_dump_update_list(struct ovni_chan *chan) struct ovni_chan *c; dbg("update list for chan %d at %p:\n", - chan->id, (void *) chan); - for(c = *chan->update_list; c; c = c->next) - { + chan->id, (void *) chan); + for (c = *chan->update_list; c; c = c->next) { dbg(" chan %d at %p\n", c->id, (void *) c); } } @@ -116,8 +115,7 @@ chan_enable(struct ovni_chan *chan, int enabled) dbg("chan_enable chan=%d enabled=%d\n", chan->id, enabled); - if(chan->enabled == enabled) - { + if (chan->enabled == enabled) { err("chan_enable: chan already in enabled=%d\n", enabled); abort(); } @@ -126,14 +124,11 @@ chan_enable(struct ovni_chan *chan, int enabled) chan->t = *chan->clock; /* Only append if not dirty */ - if(!chan->dirty) - { + if (!chan->dirty) { mark_dirty(chan, CHAN_DIRTY_ACTIVE); - } - else - { + } else { dbg("already dirty chan %d: skip update list\n", - chan->id); + chan->id); chan_dump_update_list(chan); } } @@ -157,40 +152,36 @@ chan_set(struct ovni_chan *chan, int st) dbg("chan_set chan %d st=%d\n", chan->id, st); - if(!chan->enabled) + if (!chan->enabled) die("chan_set: chan %d not enabled\n", chan->id); /* Only chan_set can set the 0 state */ - if(st < 0) + if (st < 0) die("chan_set: cannot set a negative state %d\n", st); /* Don't enforce this check if we are dirty because the channel was * just enabled; it may collide with a new state 0 set via chan_set() * used by the tracking channels */ - if(chan->dirty != CHAN_DIRTY_ACTIVE - && chan->lastst >= 0 - && chan->lastst == st) - { + if (chan->dirty != CHAN_DIRTY_ACTIVE + && chan->lastst >= 0 + && chan->lastst == st) { err("chan_set id=%d cannot emit the state %d twice\n", - chan->id, st); + chan->id, st); abort(); } - if(chan->n == 0) + if (chan->n == 0) chan->n = 1; chan->stack[chan->n - 1] = st; chan->t = *chan->clock; /* Only append if not dirty */ - if(!chan->dirty) - { + if (!chan->dirty) { mark_dirty(chan, CHAN_DIRTY_VALUE); - } - else - { + } else { dbg("already dirty chan %d: skip update list\n", - chan->id); + chan->id); chan_dump_update_list(chan); } } @@ -200,28 +191,25 @@ chan_push(struct ovni_chan *chan, int st) { dbg("chan_push chan %d st=%d\n", chan->id, st); - if(!chan->enabled) + if (!chan->enabled) die("chan_push: chan %d not enabled\n", chan->id); - if(st <= 0) - { + if (st <= 0) { err("chan_push: cannot push a non-positive state %d\n", st); abort(); } /* Cannot be dirty */ - if(chan->dirty != CHAN_CLEAN) + if (chan->dirty != CHAN_CLEAN) die("chan_push: chan %d not clean", chan->id); - if(chan->lastst >= 0 && chan->lastst == st) - { + if (chan->lastst >= 0 && chan->lastst == st) { err("chan_push id=%d cannot emit the state %d twice\n", - chan->id, st); + chan->id, st); abort(); } - if(chan->n >= MAX_CHAN_STACK) - { + if (chan->n >= MAX_CHAN_STACK) { err("chan_push: channel stack full\n"); abort(); } @@ -239,25 +227,23 @@ chan_pop(struct ovni_chan *chan, int expected_st) dbg("chan_pop chan %d expected_st=%d\n", chan->id, expected_st); - if(!chan->enabled) + if (!chan->enabled) die("chan_pop: chan %d not enabled\n", chan->id); /* Cannot be dirty */ - if(chan->dirty != CHAN_CLEAN) + if (chan->dirty != CHAN_CLEAN) die("chan_pop: chan %d not clean", chan->id); - if(chan->n <= 0) - { + if (chan->n <= 0) { err("chan_pop: channel empty\n"); abort(); } st = chan->stack[chan->n - 1]; - if(expected_st >= 0 && st != expected_st) - { + if (expected_st >= 0 && st != expected_st) { err("chan_pop: unexpected channel state %d (expected %d)\n", - st, expected_st); + st, expected_st); abort(); } @@ -267,16 +253,14 @@ chan_pop(struct ovni_chan *chan, int expected_st) st = chan_get_st(chan); /* A st == 0 can be obtained when returning to the initial state */ - if(st < 0) - { + if (st < 0) { err("chan_pop: obtained negative state %d from the stack\n", st); abort(); } - if(chan->lastst >= 0 && chan->lastst == st) - { + if (chan->lastst >= 0 && chan->lastst == st) { err("chan_pop id=%d cannot emit the state %d twice\n", - chan->id, st); + chan->id, st); abort(); } @@ -292,19 +276,19 @@ chan_ev(struct ovni_chan *chan, int ev) { dbg("chan_ev chan %d ev=%d\n", chan->id, ev); - if(!chan->enabled) + if (!chan->enabled) die("chan_ev: chan %d not enabled\n", chan->id); /* Cannot be dirty */ - if(chan->dirty != CHAN_CLEAN) + if (chan->dirty != CHAN_CLEAN) die("chan_ev: chan %d is dirty\n", chan->id); - if(ev <= 0) + if (ev <= 0) die("chan_ev: cannot emit non-positive state %d\n", ev); - if(chan->lastst >= 0 && chan->lastst == ev) + if (chan->lastst >= 0 && chan->lastst == ev) die("chan_ev id=%d cannot emit the state %d twice\n", - chan->id, ev); + chan->id, ev); chan->ev = ev; chan->t = *chan->clock; @@ -315,38 +299,36 @@ chan_ev(struct ovni_chan *chan, int ev) int chan_get_st(struct ovni_chan *chan) { - if(chan->enabled == 0) + if (chan->enabled == 0) return chan->badst; - if(chan->n == 0) + if (chan->n == 0) return 0; - if(chan->n < 0) + if (chan->n < 0) die("chan_get_st: chan %d has negative n\n", chan->id); - return chan->stack[chan->n-1]; + return chan->stack[chan->n - 1]; } static void emit(struct ovni_chan *chan, int64_t t, int state) { - if(chan->dirty == CHAN_CLEAN) + if (chan->dirty == CHAN_CLEAN) die("emit: chan %d is not dirty\n", chan->id); /* A channel can only emit the same state as lastst if is dirty because * it has been enabled or disabled. Otherwise is a bug (ie. you have two * consecutive ovni events?) */ - if(chan->lastst != -1 - && chan->dirty == CHAN_DIRTY_VALUE - && chan->lastst == state) - { + if (chan->lastst != -1 + && chan->dirty == CHAN_DIRTY_VALUE + && chan->lastst == state) { /* TODO: Print the raw clock of the offending event */ die("emit: chan %d cannot emit the same state %d twice\n", - chan->id, state); + chan->id, state); } - if(chan->lastst != state) - { + if (chan->lastst != state) { prv_ev(chan->prv, chan->row, t, chan->type, state); chan->lastst = state; @@ -358,16 +340,16 @@ emit_ev(struct ovni_chan *chan) { int new, last; - if(!chan->enabled) + if (!chan->enabled) die("emit_ev: chan %d is not enabled\n", chan->id); - if(chan->ev == -1) + if (chan->ev == -1) die("emit_ev: chan %d cannot emit -1 ev\n", chan->id); new = chan->ev; last = chan_get_st(chan); - emit(chan, chan->t-1, new); + emit(chan, chan->t - 1, new); emit(chan, chan->t, last); chan->ev = -1; @@ -387,16 +369,15 @@ emit_st(struct ovni_chan *chan) void chan_emit(struct ovni_chan *chan) { - if(likely(chan->dirty == 0)) + if (likely(chan->dirty == 0)) return; dbg("chan_emit chan %d\n", chan->id); /* Emit badst if disabled */ - if(chan->enabled == 0) - { + if (chan->enabled == 0) { /* No punctual events allowed when disabled */ - if(chan->ev != -1) + if (chan->ev != -1) die("chan_emit: no punctual event allowed when disabled\n"); emit_st(chan); @@ -404,7 +385,7 @@ chan_emit(struct ovni_chan *chan) } /* Otherwise, emit punctual event if any or the state */ - if(chan->ev != -1) + if (chan->ev != -1) emit_ev(chan); else emit_st(chan); diff --git a/chan.h b/chan.h index 34c848a..ffb0db6 100644 --- a/chan.h +++ b/chan.h @@ -8,27 +8,27 @@ void chan_th_init(struct ovni_ethread *th, - struct ovni_chan **update_list, - enum chan id, - enum chan_track track, - int init_st, - int enabled, - int dirty, - int row, - FILE *prv, - int64_t *clock); + struct ovni_chan **update_list, + enum chan id, + enum chan_track track, + int init_st, + int enabled, + int dirty, + int row, + FILE *prv, + int64_t *clock); void chan_cpu_init(struct ovni_cpu *cpu, - struct ovni_chan **update_list, - enum chan id, - enum chan_track track, - int row, - int init_st, - int enabled, - int dirty, - FILE *prv, - int64_t *clock); + struct ovni_chan **update_list, + enum chan id, + enum chan_track track, + int row, + int init_st, + int enabled, + int dirty, + FILE *prv, + int64_t *clock); void chan_enable(struct ovni_chan *chan, int enabled); diff --git a/compat.h b/compat.h index d669006..3ae7229 100644 --- a/compat.h +++ b/compat.h @@ -11,11 +11,12 @@ /* Define gettid for older glibc versions (below 2.30) */ #if defined(__GLIBC__) #if !__GLIBC_PREREQ(2, 30) -static inline pid_t gettid(void) +static inline pid_t +gettid(void) { - return (pid_t)syscall(SYS_gettid); + return (pid_t) syscall(SYS_gettid); } #endif /* !__GLIBC_PREREQ(2, 30) */ #endif /* defined(__GLIBC__) */ -#endif // COMPAT_H +#endif// COMPAT_H diff --git a/dump.c b/dump.c index 7b57d86..118740d 100644 --- a/dump.c +++ b/dump.c @@ -3,26 +3,26 @@ #define _GNU_SOURCE -#include +#include +#include +#include +#include #include +#include #include #include -#include -#include #include -#include -#include #include +#include "emu.h" #include "ovni.h" #include "trace.h" -#include "emu.h" int filter_tid = -1; char *tracedir; -//static void -//hexdump(uint8_t *buf, size_t size) +// static void +// hexdump(uint8_t *buf, size_t size) //{ // size_t i, j; // @@ -36,7 +36,7 @@ char *tracedir; // } // fprintf(stderr, "\n"); // } -//} +// } static void emit(struct ovni_stream *stream, struct ovni_ev *ev) @@ -44,25 +44,24 @@ emit(struct ovni_stream *stream, struct ovni_ev *ev) uint64_t clock; int i, payloadsize; - //printf("sizeof(*ev) = %d\n", sizeof(*ev)); - //hexdump((uint8_t *) ev, sizeof(*ev)); + // printf("sizeof(*ev) = %d\n", sizeof(*ev)); + // hexdump((uint8_t *) ev, sizeof(*ev)); clock = ovni_ev_get_clock(ev); printf("%s.%d.%d %ld %c%c%c", - stream->loom->hostname, - stream->proc->pid, - stream->thread->tid, - clock, - ev->header.model, - ev->header.category, - ev->header.value); + stream->loom->hostname, + stream->proc->pid, + stream->thread->tid, + clock, + ev->header.model, + ev->header.category, + ev->header.value); payloadsize = ovni_payload_size(ev); - if(payloadsize > 0) - { + if (payloadsize > 0) { printf(" "); - for(i=0; ipayload.u8[i]); } printf("\n"); @@ -81,50 +80,45 @@ dump_events(struct ovni_trace *trace) struct ovni_stream *stream; /* Load events */ - for(i=0; instreams; i++) - { + for (i = 0; i < trace->nstreams; i++) { stream = &trace->stream[i]; /* It can be inactive if it has been disabled by the * thread TID filter */ - if(stream->active) + if (stream->active) ovni_load_next_event(stream); } lastclock = 0; - while(1) - { + while (1) { f = -1; minclock = 0; /* Select next event based on the clock */ - for(i=0; instreams; i++) - { + for (i = 0; i < trace->nstreams; i++) { stream = &trace->stream[i]; - if(!stream->active) + if (!stream->active) continue; ev = stream->cur_ev; - if(f < 0 || ovni_ev_get_clock(ev) < minclock) - { + if (f < 0 || ovni_ev_get_clock(ev) < minclock) { f = i; minclock = ovni_ev_get_clock(ev); } } - //fprintf(stderr, "f=%d minclock=%u\n", f, minclock); + // fprintf(stderr, "f=%d minclock=%u\n", f, minclock); - if(f < 0) + if (f < 0) break; stream = &trace->stream[f]; - if(lastclock > ovni_ev_get_clock(stream->cur_ev)) - { + if (lastclock > ovni_ev_get_clock(stream->cur_ev)) { fprintf(stdout, "warning: backwards jump in time %lu -> %lu\n", - lastclock, ovni_ev_get_clock(stream->cur_ev)); + lastclock, ovni_ev_get_clock(stream->cur_ev)); } /* Emit current event */ @@ -138,7 +132,6 @@ dump_events(struct ovni_trace *trace) /* Unset the index */ f = -1; minclock = 0; - } } @@ -166,10 +159,8 @@ parse_args(int argc, char *argv[]) { int opt; - while((opt = getopt(argc, argv, "t:")) != -1) - { - switch(opt) - { + while ((opt = getopt(argc, argv, "t:")) != -1) { + switch (opt) { case 't': filter_tid = atoi(optarg); break; @@ -178,8 +169,7 @@ parse_args(int argc, char *argv[]) } } - if(optind >= argc) - { + if (optind >= argc) { err("missing tracedir\n"); usage(argc, argv); } @@ -187,25 +177,24 @@ parse_args(int argc, char *argv[]) tracedir = argv[optind]; } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { parse_args(argc, argv); struct ovni_trace *trace = calloc(1, sizeof(struct ovni_trace)); - if(ovni_load_trace(trace, tracedir)) + if (ovni_load_trace(trace, tracedir)) return 1; - if(ovni_load_streams(trace)) + if (ovni_load_streams(trace)) return 1; - if(filter_tid != -1) - { - for(size_t i=0; instreams; i++) - { + if (filter_tid != -1) { + for (size_t i = 0; i < trace->nstreams; i++) { struct ovni_stream *stream; stream = &trace->stream[i]; - if(stream->tid != filter_tid) + if (stream->tid != filter_tid) stream->active = 0; } } diff --git a/emu.c b/emu.c index e6f7fd0..73849ec 100644 --- a/emu.c +++ b/emu.c @@ -3,25 +3,25 @@ #define _POSIX_C_SOURCE 200112L +#include +#include +#include #include -#include +#include #include +#include #include #include -#include -#include #include -#include -#include -#include #include +#include -#include "ovni.h" -#include "trace.h" -#include "emu.h" -#include "prv.h" -#include "pcf.h" #include "chan.h" +#include "emu.h" +#include "ovni.h" +#include "pcf.h" +#include "prv.h" +#include "trace.h" #include "utlist.h" /* Obtains the corrected clock of the given event */ @@ -39,22 +39,21 @@ print_ev(struct ovni_stream *stream, struct ovni_ev *ev) UNUSED(delta); - //dbg("sizeof(*ev) = %d\n", sizeof(*ev)); - //hexdump((uint8_t *) ev, sizeof(*ev)); + // dbg("sizeof(*ev) = %d\n", sizeof(*ev)); + // hexdump((uint8_t *) ev, sizeof(*ev)); clock = evclock(stream, ev); delta = clock - stream->lastclock; dbg(">>> %s.%d.%d %c %c %c % 20ld % 15ld ", - stream->loom->hostname, - stream->proc->pid, - stream->thread->tid, - ev->header.model, ev->header.category, ev->header.value, clock, delta); + stream->loom->hostname, + stream->proc->pid, + stream->thread->tid, + ev->header.model, ev->header.category, ev->header.value, clock, delta); payloadsize = ovni_payload_size(ev); - for(i=0; ipayload.u8[i]); } dbg("\n"); @@ -73,8 +72,7 @@ cpu_update_tracking_chan(struct ovni_chan *cpu_chan, struct ovni_ethread *th) int th_enabled, cpu_enabled, st; struct ovni_chan *th_chan; - switch (cpu_chan->track) - { + switch (cpu_chan->track) { case CHAN_TRACK_TH_RUNNING: cpu_enabled = th->is_running; break; @@ -91,44 +89,36 @@ cpu_update_tracking_chan(struct ovni_chan *cpu_chan, struct ovni_ethread *th) th_enabled = chan_is_enabled(th_chan); /* Enable the cpu channel if needed */ - if(cpu_enabled && !chan_is_enabled(cpu_chan)) + if (cpu_enabled && !chan_is_enabled(cpu_chan)) chan_enable(cpu_chan, cpu_enabled); /* Copy the state from the thread channel if needed */ - if(th_enabled && cpu_enabled) - { + if (th_enabled && cpu_enabled) { /* Both enabled: simply follow the same value */ st = chan_get_st(th_chan); - if(chan_get_st(cpu_chan) != st) + if (chan_get_st(cpu_chan) != st) chan_set(cpu_chan, st); - } - else if(th_enabled && !cpu_enabled) - { + } else if (th_enabled && !cpu_enabled) { /* Only thread enabled: disable CPU */ - if(chan_is_enabled(cpu_chan)) + if (chan_is_enabled(cpu_chan)) chan_disable(cpu_chan); - } - else if(!th_enabled && cpu_enabled) - { + } else if (!th_enabled && cpu_enabled) { /* Only CPU enabled: is this possible? Set to bad */ chan_set(cpu_chan, ST_BAD); err("warning: cpu %s chan %d enabled but tracked thread %d chan disabled\n", - cpu_chan->cpu->name, - cpu_chan->id, - th->tid); - } - else - { + cpu_chan->cpu->name, + cpu_chan->id, + th->tid); + } else { /* Both disabled: disable CPU channel if needed */ - if(chan_is_enabled(cpu_chan)) + if (chan_is_enabled(cpu_chan)) chan_disable(cpu_chan); } dbg("cpu %s chan %d enabled=%d state=%d\n", - cpu_chan->cpu->name, cpu_chan->id, - chan_is_enabled(cpu_chan), - chan_get_st(cpu_chan)); - + cpu_chan->cpu->name, cpu_chan->id, + chan_is_enabled(cpu_chan), + chan_get_st(cpu_chan)); } void @@ -139,8 +129,7 @@ emu_cpu_update_chan(struct ovni_cpu *cpu, struct ovni_chan *cpu_chan) /* Determine the source of tracking */ - switch (cpu_chan->track) - { + switch (cpu_chan->track) { case CHAN_TRACK_TH_RUNNING: count = cpu->nrunning_threads; th = cpu->th_running; @@ -156,32 +145,27 @@ emu_cpu_update_chan(struct ovni_cpu *cpu, struct ovni_chan *cpu_chan) } /* Based on how many threads, determine the state */ - if(count == 0) - { + if (count == 0) { /* The channel can be already disabled (migration of paused * thread) so only disable it if needed. */ - if(chan_is_enabled(cpu_chan)) + if (chan_is_enabled(cpu_chan)) chan_disable(cpu_chan); - } - else if(count == 1) - { - if(th == NULL) + } else if (count == 1) { + if (th == NULL) die("emu_cpu_update_chan: tracking thread is NULL\n"); /* A unique thread found: copy the state */ dbg("cpu_update_chan: unique thread %d found, updating chan %d\n", - th->tid, cpu_chan->id); + th->tid, cpu_chan->id); cpu_update_tracking_chan(cpu_chan, th); - } - else - { + } else { /* More than one thread: enable the channel and set it to a * error value */ - if(!chan_is_enabled(cpu_chan)) + if (!chan_is_enabled(cpu_chan)) chan_enable(cpu_chan, 1); - if(chan_get_st(cpu_chan) != ST_TOO_MANY_TH) + if (chan_get_st(cpu_chan) != ST_TOO_MANY_TH) chan_set(cpu_chan, ST_TOO_MANY_TH); } } @@ -197,13 +181,13 @@ propagate_channels(struct ovni_emu *emu) DL_FOREACH_SAFE(emu->th_chan, th_chan, tmp) { - if(th_chan->thread == NULL) + if (th_chan->thread == NULL) die("propagate_channels: channel thread is NULL\n"); thread = th_chan->thread; /* No CPU in the thread */ - if(thread->cpu == NULL) + if (thread->cpu == NULL) continue; cpu = thread->cpu; @@ -211,7 +195,7 @@ propagate_channels(struct ovni_emu *emu) cpu_chan = &cpu->chan[th_chan->id]; dbg("propagate thread %d chan %d in cpu %s\n", - thread->tid, th_chan->id, cpu->name); + thread->tid, th_chan->id, cpu->name); emu_cpu_update_chan(cpu, cpu_chan); } @@ -266,15 +250,28 @@ hook_end(struct ovni_emu *emu) static void hook_pre(struct ovni_emu *emu) { - switch(emu->cur_ev->header.model) - { - case 'O': hook_pre_ovni(emu); break; - case 'V': hook_pre_nosv(emu); break; - case 'T': hook_pre_tampi(emu); break; - case 'M': hook_pre_openmp(emu); break; - case 'D': hook_pre_nodes(emu); break; - case 'K': hook_pre_kernel(emu); break; - case '6': hook_pre_nanos6(emu); break; + switch (emu->cur_ev->header.model) { + case 'O': + hook_pre_ovni(emu); + break; + case 'V': + hook_pre_nosv(emu); + break; + case 'T': + hook_pre_tampi(emu); + break; + case 'M': + hook_pre_openmp(emu); + break; + case 'D': + hook_pre_nodes(emu); + break; + case 'K': + hook_pre_kernel(emu); + break; + case '6': + hook_pre_nanos6(emu); + break; default: break; } @@ -283,11 +280,10 @@ hook_pre(struct ovni_emu *emu) static void hook_post(struct ovni_emu *emu) { - switch(emu->cur_ev->header.model) - { + switch (emu->cur_ev->header.model) { default: - //dbg("unknown model %c\n", emu->cur_ev->model); - break; + // dbg("unknown model %c\n", emu->cur_ev->model); + break; } } @@ -310,16 +306,17 @@ set_current(struct ovni_emu *emu, struct ovni_stream *stream) * * Invert the comparison function to get a min-heap instead */ -static inline int stream_cmp(heap_node_t *a, heap_node_t *b) +static inline int +stream_cmp(heap_node_t *a, heap_node_t *b) { struct ovni_stream *sa, *sb; sa = heap_elem(a, struct ovni_stream, hh); sb = heap_elem(b, struct ovni_stream, hh); - if(sb->lastclock < sa->lastclock) + if (sb->lastclock < sa->lastclock) return -1; - else if(sb->lastclock > sa->lastclock) + else if (sb->lastclock > sa->lastclock) return +1; else return 0; @@ -330,7 +327,7 @@ get_time(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); - return (double)ts.tv_sec + (double)ts.tv_nsec * 1.0e-9; + return (double) ts.tv_sec + (double) ts.tv_nsec * 1.0e-9; } static void @@ -346,8 +343,7 @@ print_progress(struct ovni_emu *emu) written = cpu_written + th_written; - progress = ((double) emu->global_offset) / - ((double) emu->global_size); + progress = ((double) emu->global_offset) / ((double) emu->global_size); time_now = get_time(); time_elapsed = time_now - emu->start_emulation_time; @@ -361,12 +357,12 @@ print_progress(struct ovni_emu *emu) sec = (int) ((time_left / 60.0 - min) * 60); err("%.1f%% done at %.0f Kev/s, out %.1f GB CPU / %.1f GB TH at %.1f MB/s (%d min %d s left)\n", - 100.0 * progress, - speed_in / 1024.0, - cpu_written / (1024.0 * 1024.0 * 1024.0), - th_written / (1024.0 * 1024.0 * 1024.0), - speed_out / (1024.0 * 1024), - min, sec); + 100.0 * progress, + speed_in / 1024.0, + cpu_written / (1024.0 * 1024.0 * 1024.0), + th_written / (1024.0 * 1024.0 * 1024.0), + speed_out / (1024.0 * 1024), + min, sec); } /* Loads the next event and sets the lastclock in the stream. @@ -374,7 +370,7 @@ print_progress(struct ovni_emu *emu) static int emu_step_stream(struct ovni_emu *emu, struct ovni_stream *stream) { - if(ovni_load_next_event(stream) < 0) + if (ovni_load_next_event(stream) < 0) return -1; stream->lastclock = evclock(stream, stream->cur_ev); @@ -396,19 +392,19 @@ next_event(struct ovni_emu *emu) node = heap_pop_max(&emu->sorted_stream, stream_cmp); /* No more streams */ - if(node == NULL) + if (node == NULL) return -1; stream = heap_elem(node, struct ovni_stream, hh); - if(stream == NULL) + if (stream == NULL) die("next_event: heap_elem returned NULL\n"); set_current(emu, stream); emu->global_offset += ovni_ev_size(stream->cur_ev); - //err("stream %d clock at %ld\n", stream->tid, stream->lastclock); + // err("stream %d clock at %ld\n", stream->tid, stream->lastclock); /* This can happen if two events are not ordered in the stream, but the * emulator picks other events in the middle. Example: @@ -423,19 +419,17 @@ next_event(struct ovni_emu *emu) * 12 * ... * */ - if(emu->lastclock > stream->lastclock) - { + if (emu->lastclock > stream->lastclock) { err("warning: backwards jump in time %lu -> %lu for tid %d\n", - emu->lastclock, stream->lastclock, stream->tid); + emu->lastclock, stream->lastclock, stream->tid); - if(emu->enable_linter) + if (emu->enable_linter) abort(); } emu->lastclock = stream->lastclock; - if(!done_first) - { + if (!done_first) { done_first = 1; emu->firstclock = emu->lastclock; } @@ -459,16 +453,14 @@ emu_load_first_events(struct ovni_emu *emu) /* Load initial streams and events */ trace = &emu->trace; - for(i=0; instreams; i++) - { + for (i = 0; i < trace->nstreams; i++) { stream = &trace->stream[i]; emu->global_size += stream->size; - if(emu_step_stream(emu, stream) < 0) - { + if (emu_step_stream(emu, stream) < 0) { err("warning: empty stream for tid %d\n", stream->tid); - if(emu->enable_linter) + if (emu->enable_linter) abort(); continue; @@ -494,8 +486,7 @@ emulate(struct ovni_emu *emu) emit_channels(emu); /* Then process all events */ - for(i=0; next_event(emu) == 0; i++) - { + for (i = 0; next_event(emu) == 0; i++) { print_cur_ev(emu); hook_pre(emu); @@ -505,8 +496,7 @@ emulate(struct ovni_emu *emu) hook_post(emu); - if(i >= 50000) - { + if (i >= 50000) { print_progress(emu); i = 0; } @@ -527,10 +517,9 @@ emu_get_thread(struct ovni_eproc *proc, int tid) size_t i; struct ovni_ethread *thread; - for(i=0; inthreads; i++) - { + for (i = 0; i < proc->nthreads; i++) { thread = &proc->thread[i]; - if(thread->tid == tid) + if (thread->tid == tid) return thread; } @@ -544,13 +533,13 @@ add_new_cpu(struct ovni_emu *emu, struct ovni_loom *loom, int i, int phyid) cpu = &loom->cpu[i]; - if(i < 0 || i >= (int) loom->ncpus) + if (i < 0 || i >= (int) loom->ncpus) die("CPU with index %d in loom %s is out of bounds\n", - i, loom->hostname); + i, loom->hostname); - if(cpu->state != CPU_ST_UNKNOWN) + if (cpu->state != CPU_ST_UNKNOWN) die("new cpu %d in unexpected state in loom %s\n", - i, loom->hostname); + i, loom->hostname); cpu->state = CPU_ST_READY; cpu->i = i; @@ -563,43 +552,42 @@ add_new_cpu(struct ovni_emu *emu, struct ovni_loom *loom, int i, int phyid) static int proc_load_cpus(struct ovni_emu *emu, struct ovni_loom *loom, - struct ovni_eproc *proc, - struct ovni_eproc *metadata_proc) + struct ovni_eproc *proc, + struct ovni_eproc *metadata_proc) { JSON_Object *meta = json_value_get_object(proc->meta); - if(meta == NULL) + if (meta == NULL) die("json_value_get_object() failed\n"); JSON_Array *cpuarray = json_object_get_array(meta, "cpus"); /* This process doesn't have the cpu list */ - if(cpuarray == NULL) + if (cpuarray == NULL) return -1; - if(metadata_proc) + if (metadata_proc) die("duplicated metadata for proc %d and %d in loom %s\n", - metadata_proc->pid, proc->pid, - loom->hostname); + metadata_proc->pid, proc->pid, + loom->hostname); - if(loom->ncpus != 0) + if (loom->ncpus != 0) die("loom %s already has CPUs\n", loom->hostname); loom->ncpus = json_array_get_count(cpuarray); - if(loom->ncpus == 0) + if (loom->ncpus == 0) die("loom %s proc %d has metadata but no CPUs\n", - loom->hostname, proc->pid); + loom->hostname, proc->pid); loom->cpu = calloc(loom->ncpus, sizeof(struct ovni_cpu)); - if(loom->cpu == NULL) + if (loom->cpu == NULL) die("calloc failed: %s\n", strerror(errno)); - for(size_t i = 0; i < loom->ncpus; i++) - { + for (size_t i = 0; i < loom->ncpus; i++) { JSON_Object *cpu = json_array_get_object(cpuarray, i); - if(cpu == NULL) + if (cpu == NULL) die("proc_load_cpus: json_array_get_object() failed\n"); int index = (int) json_object_get_number(cpu, "index"); @@ -612,9 +600,9 @@ proc_load_cpus(struct ovni_emu *emu, struct ovni_loom *loom, /* Init the vcpu as well */ struct ovni_cpu *vcpu = &loom->vcpu; - if(vcpu->state != CPU_ST_UNKNOWN) + if (vcpu->state != CPU_ST_UNKNOWN) die("unexpected virtual CPU state in loom %s\n", - loom->hostname); + loom->hostname); vcpu->state = CPU_ST_READY; vcpu->i = -1; @@ -638,33 +626,31 @@ load_metadata(struct ovni_emu *emu) trace = &emu->trace; - for(i=0; inlooms; i++) - { + for (i = 0; i < trace->nlooms; i++) { loom = &trace->loom[i]; loom->offset_ncpus = emu->total_ncpus; struct ovni_eproc *metadata_proc = NULL; - for(j=0; jnprocs; j++) - { + for (j = 0; j < loom->nprocs; j++) { proc = &loom->proc[j]; - if(proc_load_cpus(emu, loom, proc, metadata_proc) < 0) + if (proc_load_cpus(emu, loom, proc, metadata_proc) < 0) continue; - if(metadata_proc) + if (metadata_proc) die("duplicated metadata found in pid %d and %d\n", - metadata_proc->pid, - proc->pid); + metadata_proc->pid, + proc->pid); metadata_proc = proc; } /* One of the process must have the list of CPUs */ - if(metadata_proc == NULL) + if (metadata_proc == NULL) die("no metadata found in loom %s\n", loom->hostname); - if(loom->ncpus == 0) + if (loom->ncpus == 0) die("no CPUs found in loom %s\n", loom->hostname); } } @@ -679,14 +665,12 @@ destroy_metadata(struct ovni_emu *emu) trace = &emu->trace; - for(i=0; inlooms; i++) - { + for (i = 0; i < trace->nlooms; i++) { loom = &trace->loom[i]; - for(j=0; jnprocs; j++) - { + for (j = 0; j < loom->nprocs; j++) { proc = &loom->proc[j]; - if(proc->meta == NULL) + if (proc->meta == NULL) die("cannot destroy metadata: is NULL\n"); json_value_free(proc->meta); @@ -707,10 +691,9 @@ open_prvs(struct ovni_emu *emu, char *tracedir) emu->prv_thread = fopen(path, "w"); - if(emu->prv_thread == NULL) - { + if (emu->prv_thread == NULL) { err("error opening thread PRV file %s: %s\n", path, - strerror(errno)); + strerror(errno)); exit(EXIT_FAILURE); } @@ -718,10 +701,9 @@ open_prvs(struct ovni_emu *emu, char *tracedir) emu->prv_cpu = fopen(path, "w"); - if(emu->prv_cpu == NULL) - { + if (emu->prv_cpu == NULL) { err("error opening cpu PRV file %s: %s\n", path, - strerror(errno)); + strerror(errno)); exit(EXIT_FAILURE); } @@ -788,10 +770,8 @@ parse_args(struct ovni_emu *emu, int argc, char *argv[]) { int opt; - while((opt = getopt(argc, argv, "c:l")) != -1) - { - switch(opt) - { + while ((opt = getopt(argc, argv, "c:l")) != -1) { + switch (opt) { case 'c': emu->clock_offset_file = optarg; break; @@ -803,8 +783,7 @@ parse_args(struct ovni_emu *emu, int argc, char *argv[]) } } - if(optind >= argc) - { + if (optind >= argc) { err("missing tracedir\n"); usage(argc, argv); } @@ -817,22 +796,21 @@ set_clock_offsets(struct ovni_emu *emu, const char *host, size_t offset) { size_t matches = 0; - for(size_t i = 0; i < emu->trace.nlooms; i++) - { + for (size_t i = 0; i < emu->trace.nlooms; i++) { struct ovni_loom *loom = &emu->trace.loom[i]; /* Match the hostname exactly */ - if(strcmp(loom->hostname, host) != 0) + if (strcmp(loom->hostname, host) != 0) continue; - if(loom->clock_offset != 0) + if (loom->clock_offset != 0) die("loom %s already has a clock offset\n", loom->dname); loom->clock_offset = offset; matches++; } - if(matches == 0) + if (matches == 0) die("no loom has hostname %s\n", host); } @@ -849,53 +827,44 @@ load_clock_offsets(struct ovni_emu *emu) struct ovni_trace *trace; struct ovni_stream *stream; - if(emu->clock_offset_file != NULL) - { + if (emu->clock_offset_file != NULL) { f = fopen(emu->clock_offset_file, "r"); /* If provided by the user, it must exist */ - if(f == NULL) - { + if (f == NULL) { err("error opening clock offset file %s: %s\n", - emu->clock_offset_file, - strerror(errno)); + emu->clock_offset_file, + strerror(errno)); exit(EXIT_FAILURE); } - } - else - { + } else { char path[PATH_MAX]; - if(snprintf(path, PATH_MAX, "%s/clock-offsets.txt", - emu->tracedir) >= PATH_MAX) - { + if (snprintf(path, PATH_MAX, "%s/clock-offsets.txt", + emu->tracedir) + >= PATH_MAX) { die("clock offset path too long\n"); } f = fopen(path, "r"); - if(f == NULL) - { + if (f == NULL) { /* May not exist, but is fine */ return; } } /* Ignore header line */ - if(fgets(buf, 1024, f) == NULL) - { + if (fgets(buf, 1024, f) == NULL) { perror("fgets failed"); exit(EXIT_FAILURE); } - while(1) - { + while (1) { errno = 0; ret = fscanf(f, "%d %s %lf %lf %lf", &rank, host, &offset, &mean, &std); - if(ret == EOF) - { - if(errno != 0) - { + if (ret == EOF) { + if (errno != 0) { perror("fscanf failed"); exit(EXIT_FAILURE); } @@ -903,10 +872,9 @@ load_clock_offsets(struct ovni_emu *emu) break; } - if(ret != 5) - { + if (ret != 5) { err("fscanf read %d instead of 5 fields in %s\n", - ret, emu->clock_offset_file); + ret, emu->clock_offset_file); exit(EXIT_FAILURE); } @@ -917,8 +885,7 @@ load_clock_offsets(struct ovni_emu *emu) trace = &emu->trace; - for(i=0; instreams; i++) - { + for (i = 0; i < trace->nstreams; i++) { stream = &trace->stream[i]; loom = stream->loom; stream->clock_offset = loom->clock_offset; @@ -941,8 +908,7 @@ write_row_cpu(struct ovni_emu *emu) f = fopen(path, "w"); - if(f == NULL) - { + if (f == NULL) { perror("cannot open row file"); exit(EXIT_FAILURE); } @@ -953,8 +919,7 @@ write_row_cpu(struct ovni_emu *emu) fprintf(f, "LEVEL THREAD SIZE %ld\n", emu->total_ncpus); - for(i=0; itotal_ncpus; i++) - { + for (i = 0; i < emu->total_ncpus; i++) { cpu = emu->global_cpu[i]; fprintf(f, "%s\n", cpu->name); } @@ -974,8 +939,7 @@ write_row_thread(struct ovni_emu *emu) f = fopen(path, "w"); - if(f == NULL) - { + if (f == NULL) { perror("cannot open row file"); exit(EXIT_FAILURE); } @@ -986,8 +950,7 @@ write_row_thread(struct ovni_emu *emu) fprintf(f, "LEVEL THREAD SIZE %ld\n", emu->total_nthreads); - for(i=0; itotal_nthreads; i++) - { + for (i = 0; i < emu->total_nthreads; i++) { th = emu->global_thread[i]; fprintf(f, "THREAD %d.%d\n", th->proc->appid, th->tid); } @@ -1009,15 +972,12 @@ init_threads(struct ovni_emu *emu) trace = &emu->trace; - for(i=0; inlooms; i++) - { + for (i = 0; i < trace->nlooms; i++) { loom = &trace->loom[i]; - for(j=0; jnprocs; j++) - { + for (j = 0; j < loom->nprocs; j++) { proc = &loom->proc[j]; emu->total_nprocs++; - for(k=0; knthreads; k++) - { + for (k = 0; k < proc->nthreads; k++) { thread = &proc->thread[k]; emu->total_nthreads++; } @@ -1025,22 +985,18 @@ init_threads(struct ovni_emu *emu) } emu->global_thread = calloc(emu->total_nthreads, - sizeof(*emu->global_thread)); + sizeof(*emu->global_thread)); - if(emu->global_thread == NULL) - { + if (emu->global_thread == NULL) { perror("calloc failed"); exit(EXIT_FAILURE); } - for(gi=0, i=0; inlooms; i++) - { + for (gi = 0, i = 0; i < trace->nlooms; i++) { loom = &trace->loom[i]; - for(j=0; jnprocs; j++) - { + for (j = 0; j < loom->nprocs; j++) { proc = &loom->proc[j]; - for(k=0; knthreads; k++) - { + for (k = 0; k < proc->nthreads; k++) { thread = &proc->thread[k]; emu->global_thread[gi++] = thread; @@ -1060,25 +1016,22 @@ init_cpus(struct ovni_emu *emu) trace = &emu->trace; emu->global_cpu = calloc(emu->total_ncpus, - sizeof(*emu->global_cpu)); + sizeof(*emu->global_cpu)); - if(emu->global_cpu == NULL) - { + if (emu->global_cpu == NULL) { perror("calloc"); exit(EXIT_FAILURE); } - for(i=0; inlooms; i++) - { + for (i = 0; i < trace->nlooms; i++) { loom = &trace->loom[i]; - for(j=0; jncpus; j++) - { + for (j = 0; j < loom->ncpus; j++) { cpu = &loom->cpu[j]; emu->global_cpu[cpu->gindex] = cpu; - if(snprintf(cpu->name, MAX_CPU_NAME, "CPU %ld.%ld", - i, j) >= MAX_CPU_NAME) - { + if (snprintf(cpu->name, MAX_CPU_NAME, "CPU %ld.%ld", + i, j) + >= MAX_CPU_NAME) { err("error cpu %ld.%ld name too long\n", i, j); exit(EXIT_FAILURE); } @@ -1086,9 +1039,9 @@ init_cpus(struct ovni_emu *emu) } emu->global_cpu[loom->vcpu.gindex] = &loom->vcpu; - if(snprintf(loom->vcpu.name, MAX_CPU_NAME, "CPU %ld.*", - i) >= MAX_CPU_NAME) - { + if (snprintf(loom->vcpu.name, MAX_CPU_NAME, "CPU %ld.*", + i) + >= MAX_CPU_NAME) { err("error cpu %ld.* name too long\n", i); exit(EXIT_FAILURE); } @@ -1104,11 +1057,10 @@ create_pcf_cpus(struct ovni_emu *emu) int prvtype = chan_to_prvtype[CHAN_OVNI_CPU]; struct pcf_type *type = pcf_find_type(pcf, prvtype); - if(type == NULL) + if (type == NULL) die("cannot find PCF type for CHAN_OVNI_CPU\n"); - for(size_t i=0; itotal_ncpus; i++) - { + for (size_t i = 0; i < emu->total_ncpus; i++) { int value = i + 1; char *label = emu->global_cpu[i]->name; @@ -1123,14 +1075,12 @@ emu_init(struct ovni_emu *emu, int argc, char *argv[]) parse_args(emu, argc, argv); - if(ovni_load_trace(&emu->trace, emu->tracedir)) - { + if (ovni_load_trace(&emu->trace, emu->tracedir)) { err("error loading ovni trace\n"); exit(EXIT_FAILURE); } - if(ovni_load_streams(&emu->trace)) - { + if (ovni_load_streams(&emu->trace)) { err("error loading streams\n"); exit(EXIT_FAILURE); } @@ -1151,8 +1101,8 @@ emu_init(struct ovni_emu *emu, int argc, char *argv[]) emu->global_offset = 0; err("loaded %ld cpus and %ld threads\n", - emu->total_ncpus, - emu->total_nthreads); + emu->total_ncpus, + emu->total_nthreads); } static void @@ -1181,41 +1131,41 @@ emu_destroy(struct ovni_emu *emu) } void -edie(struct ovni_emu *emu, const char* fmt, ...) +edie(struct ovni_emu *emu, const char *fmt, ...) { - va_list args; - va_start(args, fmt); + va_list args; + va_start(args, fmt); - fprintf(stderr, "fatal: "); - vfprintf(stderr, fmt, args); - va_end(args); + fprintf(stderr, "fatal: "); + vfprintf(stderr, fmt, args); + va_end(args); - fprintf(stderr, "fatal: while evaluating the event %c%c%c with clock=%ld in thread=%d\n", - emu->cur_ev->header.model, - emu->cur_ev->header.category, - emu->cur_ev->header.value, - emu->cur_ev->header.clock, - emu->cur_thread->tid); + fprintf(stderr, "fatal: while evaluating the event %c%c%c with clock=%ld in thread=%d\n", + emu->cur_ev->header.model, + emu->cur_ev->header.category, + emu->cur_ev->header.value, + emu->cur_ev->header.clock, + emu->cur_thread->tid); - abort(); + abort(); } void -eerr(struct ovni_emu *emu, const char* fmt, ...) +eerr(struct ovni_emu *emu, const char *fmt, ...) { - va_list args; - va_start(args, fmt); + va_list args; + va_start(args, fmt); - fprintf(stderr, "fatal: "); - vfprintf(stderr, fmt, args); - va_end(args); + fprintf(stderr, "fatal: "); + vfprintf(stderr, fmt, args); + va_end(args); - fprintf(stderr, "fatal: while evaluating the event %c%c%c with clock=%ld in thread=%d\n", - emu->cur_ev->header.model, - emu->cur_ev->header.category, - emu->cur_ev->header.value, - emu->cur_ev->header.clock, - emu->cur_thread->tid); + fprintf(stderr, "fatal: while evaluating the event %c%c%c with clock=%ld in thread=%d\n", + emu->cur_ev->header.model, + emu->cur_ev->header.category, + emu->cur_ev->header.value, + emu->cur_ev->header.clock, + emu->cur_thread->tid); } int @@ -1225,8 +1175,7 @@ main(int argc, char *argv[]) emu = malloc(sizeof(struct ovni_emu)); - if(emu == NULL) - { + if (emu == NULL) { perror("malloc"); return 1; } diff --git a/emu.h b/emu.h index a374ad2..ad033d7 100644 --- a/emu.h +++ b/emu.h @@ -7,11 +7,11 @@ #include #include "common.h" -#include "ovni.h" -#include "uthash.h" -#include "parson.h" #include "heap.h" +#include "ovni.h" +#include "parson.h" #include "pcf.h" +#include "uthash.h" /* Emulated thread runtime status */ enum ethread_state { @@ -136,8 +136,8 @@ struct ovni_ethread; struct ovni_eproc; struct task_type { - uint32_t id; /* Per-process task identifier */ - uint32_t gid; /* Global identifier computed from the label */ + uint32_t id; /* Per-process task identifier */ + uint32_t gid; /* Global identifier computed from the label */ char label[MAX_PCF_LABEL]; UT_hash_handle hh; }; @@ -158,17 +158,17 @@ struct task { }; struct task_info { - /* Both hash maps of all known tasks and types */ - struct task_type *types; - struct task *tasks; + /* Both hash maps of all known tasks and types */ + struct task_type *types; + struct task *tasks; }; struct task_stack { - union { - struct task *top; /* Synctactic sugar */ - struct task *tasks; - }; - struct ovni_ethread *thread; + union { + struct task *top; /* Synctactic sugar */ + struct task *tasks; + }; + struct ovni_ethread *thread; }; #define MAX_CHAN_STACK 512 @@ -383,7 +383,7 @@ struct ovni_eproc { /* TODO: Use dynamic allocation */ struct task_info nosv_task_info; - struct task_info nanos6_task_info; + struct task_info nanos6_task_info; }; @@ -445,7 +445,7 @@ struct ovni_loom { size_t nprocs; char hostname[OVNI_MAX_HOSTNAME]; char dname[PATH_MAX]; /* Loom directory name */ - char path[PATH_MAX]; /* Relative to cwd */ + char path[PATH_MAX]; /* Relative to cwd */ size_t max_ncpus; size_t max_phyid; @@ -546,8 +546,8 @@ struct ovni_emu { /* Emulator function declaration */ -void edie(struct ovni_emu *emu, const char* fmt, ...); -void eerr(struct ovni_emu *emu, const char* fmt, ...); +void edie(struct ovni_emu *emu, const char *fmt, ...); +void eerr(struct ovni_emu *emu, const char *fmt, ...); void hook_init_ovni(struct ovni_emu *emu); void hook_pre_ovni(struct ovni_emu *emu); diff --git a/emu_kernel.c b/emu_kernel.c index 199b0ee..52365c7 100644 --- a/emu_kernel.c +++ b/emu_kernel.c @@ -3,11 +3,11 @@ #include "uthash.h" -#include "ovni.h" -#include "trace.h" -#include "emu.h" -#include "prv.h" #include "chan.h" +#include "emu.h" +#include "ovni.h" +#include "prv.h" +#include "trace.h" /* --------------------------- init ------------------------------- */ @@ -27,8 +27,7 @@ hook_init_kernel(struct ovni_emu *emu) prv_cpu = emu->prv_cpu; /* Init the channels in all threads */ - for(i=0; itotal_nthreads; i++) - { + for (i = 0; i < emu->total_nthreads; i++) { th = emu->global_thread[i]; row = th->gindex + 1; uth = &emu->th_chan; @@ -37,8 +36,7 @@ hook_init_kernel(struct ovni_emu *emu) } /* Init the channels in all cpus */ - for(i=0; itotal_ncpus; i++) - { + for (i = 0; i < emu->total_ncpus; i++) { cpu = emu->global_cpu[i]; row = cpu->gindex + 1; ucpu = &emu->cpu_chan; @@ -58,8 +56,7 @@ context_switch(struct ovni_emu *emu) th = emu->cur_thread; chan = &th->chan[CHAN_KERNEL_CS]; - switch(emu->cur_ev->header.value) - { + switch (emu->cur_ev->header.value) { case 'O': chan_push(chan, ST_KERNEL_CSOUT); break; @@ -68,24 +65,23 @@ context_switch(struct ovni_emu *emu) break; default: edie(emu, "unexpected value '%c' (expecting 'O' or 'I')\n", - emu->cur_ev->header.value); + emu->cur_ev->header.value); } } void hook_pre_kernel(struct ovni_emu *emu) { - if(emu->cur_ev->header.model != 'K') + if (emu->cur_ev->header.model != 'K') edie(emu, "hook_pre_kernel: unexpected event with model %c\n", - emu->cur_ev->header.model); + emu->cur_ev->header.model); - switch(emu->cur_ev->header.category) - { + switch (emu->cur_ev->header.category) { case 'C': context_switch(emu); break; default: edie(emu, "hook_pre_kernel: unexpected event with category %c\n", - emu->cur_ev->header.category); + emu->cur_ev->header.category); } } diff --git a/emu_nanos6.c b/emu_nanos6.c index 85557bf..62767b4 100644 --- a/emu_nanos6.c +++ b/emu_nanos6.c @@ -4,11 +4,11 @@ #include "uthash.h" #include "utlist.h" -#include "ovni.h" +#include "chan.h" #include "emu.h" #include "emu_task.h" +#include "ovni.h" #include "prv.h" -#include "chan.h" void hook_init_nanos6(struct ovni_emu *emu) @@ -25,37 +25,34 @@ hook_init_nanos6(struct ovni_emu *emu) prv_cpu = emu->prv_cpu; /* Init the channels in all threads */ - for(size_t i=0; itotal_nthreads; i++) - { + for (size_t i = 0; i < emu->total_nthreads; i++) { th = emu->global_thread[i]; row = th->gindex + 1; uth = &emu->th_chan; - chan_th_init(th, uth, CHAN_NANOS6_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); - chan_th_init(th, uth, CHAN_NANOS6_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); - chan_th_init(th, uth, CHAN_NANOS6_SUBSYSTEM, CHAN_TRACK_TH_ACTIVE, 0, 0, 1, row, prv_th, clock); - chan_th_init(th, uth, CHAN_NANOS6_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); - chan_th_init(th, uth, CHAN_NANOS6_THREAD, CHAN_TRACK_NONE, 0, 1, 1, row, prv_th, clock); + chan_th_init(th, uth, CHAN_NANOS6_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); + chan_th_init(th, uth, CHAN_NANOS6_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); + chan_th_init(th, uth, CHAN_NANOS6_SUBSYSTEM, CHAN_TRACK_TH_ACTIVE, 0, 0, 1, row, prv_th, clock); + chan_th_init(th, uth, CHAN_NANOS6_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); + chan_th_init(th, uth, CHAN_NANOS6_THREAD, CHAN_TRACK_NONE, 0, 1, 1, row, prv_th, clock); } /* Init the Nanos6 channels in all cpus */ - for(size_t i=0; itotal_ncpus; i++) - { + for (size_t i = 0; i < emu->total_ncpus; i++) { cpu = emu->global_cpu[i]; row = cpu->gindex + 1; ucpu = &emu->cpu_chan; - chan_cpu_init(cpu, ucpu, CHAN_NANOS6_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); - chan_cpu_init(cpu, ucpu, CHAN_NANOS6_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); + chan_cpu_init(cpu, ucpu, CHAN_NANOS6_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); + chan_cpu_init(cpu, ucpu, CHAN_NANOS6_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_NANOS6_SUBSYSTEM, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); - chan_cpu_init(cpu, ucpu, CHAN_NANOS6_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); - chan_cpu_init(cpu, ucpu, CHAN_NANOS6_THREAD, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); + chan_cpu_init(cpu, ucpu, CHAN_NANOS6_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); + chan_cpu_init(cpu, ucpu, CHAN_NANOS6_THREAD, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); } /* Init task stack */ - for(size_t i=0; itotal_nthreads; i++) - { + for (size_t i = 0; i < emu->total_nthreads; i++) { th = emu->global_thread[i]; th->nanos6_task_stack.thread = th; } @@ -72,7 +69,7 @@ chan_task_stopped(struct ovni_emu *emu) chan_set(&th->chan[CHAN_NANOS6_TASKID], 0); chan_set(&th->chan[CHAN_NANOS6_TYPE], 0); - if(emu->cur_loom->rank_enabled) + if (emu->cur_loom->rank_enabled) chan_set(&th->chan[CHAN_NANOS6_RANK], 0); } @@ -85,41 +82,41 @@ chan_task_running(struct ovni_emu *emu, struct task *task) th = emu->cur_thread; proc = emu->cur_proc; - if(task->id == 0) + if (task->id == 0) edie(emu, "task id cannot be 0\n"); - if(task->type->gid == 0) + if (task->type->gid == 0) edie(emu, "task type gid cannot be 0\n"); - if(proc->appid <= 0) + if (proc->appid <= 0) edie(emu, "app id must be positive\n"); chan_set(&th->chan[CHAN_NANOS6_TASKID], task->id); chan_set(&th->chan[CHAN_NANOS6_TYPE], task->type->gid); - if(emu->cur_loom->rank_enabled) + if (emu->cur_loom->rank_enabled) chan_set(&th->chan[CHAN_NANOS6_RANK], proc->rank + 1); } static void chan_task_switch(struct ovni_emu *emu, - struct task *prev, struct task *next) + struct task *prev, struct task *next) { struct ovni_ethread *th = emu->cur_thread; - if(!prev || !next) + if (!prev || !next) edie(emu, "cannot switch to or from a NULL task\n"); - if(prev == next) + if (prev == next) edie(emu, "cannot switch to the same task\n"); - if(next->id == 0) + if (next->id == 0) edie(emu, "next task id cannot be 0\n"); - if(next->type->gid == 0) + if (next->type->gid == 0) edie(emu, "next task type id cannot be 0\n"); - if(prev->thread != next->thread) + if (prev->thread != next->thread) edie(emu, "cannot switch to a task of another thread\n"); /* No need to change the rank as we will switch to tasks from @@ -130,14 +127,14 @@ chan_task_switch(struct ovni_emu *emu, * the same type event, to mark the end of the current task. For * now we only emit a new type if we switch to a type with a * different gid. */ - if(prev->type->gid != next->type->gid) + if (prev->type->gid != next->type->gid) chan_set(&th->chan[CHAN_NANOS6_TYPE], next->type->gid); } static void update_task_state(struct ovni_emu *emu) { - if(ovni_payload_size(emu->cur_ev) < 4) + if (ovni_payload_size(emu->cur_ev) < 4) edie(emu, "missing task id in payload\n"); uint32_t task_id = emu->cur_ev->payload.u32[0]; @@ -150,17 +147,24 @@ update_task_state(struct ovni_emu *emu) struct task *task = task_find(info->tasks, task_id); - if(task == NULL) + if (task == NULL) edie(emu, "cannot find task with id %u\n", task_id); - switch(emu->cur_ev->header.value) - { - case 'x': task_execute(emu, stack, task); break; - case 'e': task_end(emu, stack, task); break; - case 'p': task_pause(emu, stack, task); break; - case 'r': task_resume(emu, stack, task); break; + switch (emu->cur_ev->header.value) { + case 'x': + task_execute(emu, stack, task); + break; + case 'e': + task_end(emu, stack, task); + break; + case 'p': + task_pause(emu, stack, task); + break; + case 'r': + task_resume(emu, stack, task); + break; default: - edie(emu, "unexpected Nanos6 task event\n"); + edie(emu, "unexpected Nanos6 task event\n"); } } @@ -170,13 +174,13 @@ expand_transition_value(struct ovni_emu *emu, int was_running, int runs_now) char tr = emu->cur_ev->header.value; /* Ensure we don't clobber the value */ - if(tr == 'X' || tr == 'E') + if (tr == 'X' || tr == 'E') edie(emu, "unexpected event value %c\n", tr); /* Modify the event value to detect nested transitions */ - if(tr == 'x' && was_running) + if (tr == 'x' && was_running) tr = 'X'; /* Execute a new nested task */ - else if(tr == 'e' && runs_now) + else if (tr == 'e' && runs_now) tr = 'E'; /* End a nested task */ return tr; @@ -184,10 +188,9 @@ expand_transition_value(struct ovni_emu *emu, int was_running, int runs_now) static void update_task_channels(struct ovni_emu *emu, - char tr, struct task *prev, struct task *next) + char tr, struct task *prev, struct task *next) { - switch(tr) - { + switch (tr) { case 'x': case 'r': chan_task_running(emu, next); @@ -208,23 +211,22 @@ update_task_channels(struct ovni_emu *emu, static void enforce_task_rules(struct ovni_emu *emu, - char tr, struct task *prev, struct task *next) + char tr, struct task *prev, struct task *next) { UNUSED(prev); /* If a task has just entered the running state, it must show * the running task body subsystem */ - if(tr == 'x' || tr == 'X') - { - if(next->state != TASK_ST_RUNNING) + if (tr == 'x' || tr == 'X') { + if (next->state != TASK_ST_RUNNING) edie(emu, "a Nanos6 task starts running but not in the running state\n"); struct ovni_ethread *th = emu->cur_thread; struct ovni_chan *sschan = &th->chan[CHAN_NANOS6_SUBSYSTEM]; int st = chan_get_st(sschan); - if(st != 0 && st != ST_NANOS6_TASK_BODY) + if (st != 0 && st != ST_NANOS6_TASK_BODY) edie(emu, "a Nanos6 task starts running but not in the \"running body\" subsystem state\n"); } } @@ -255,7 +257,7 @@ update_task(struct ovni_emu *emu) static void create_task(struct ovni_emu *emu) { - if(ovni_payload_size(emu->cur_ev) != 8) + if (ovni_payload_size(emu->cur_ev) != 8) edie(emu, "cannot create task: unexpected payload size\n"); uint32_t task_id = emu->cur_ev->payload.u32[0]; @@ -269,8 +271,7 @@ create_task(struct ovni_emu *emu) static void pre_task(struct ovni_emu *emu) { - switch(emu->cur_ev->header.value) - { + switch (emu->cur_ev->header.value) { case 'c': create_task(emu); break; @@ -290,10 +291,10 @@ pre_type(struct ovni_emu *emu) { uint8_t value = emu->cur_ev->header.value; - if(value != 'c') + if (value != 'c') edie(emu, "unexpected event value %c\n", value); - if((emu->cur_ev->header.flags & OVNI_EV_JUMBO) == 0) + if ((emu->cur_ev->header.flags & OVNI_EV_JUMBO) == 0) edie(emu, "expecting a jumbo event\n"); uint8_t *data = &emu->cur_ev->payload.jumbo.data[0]; @@ -316,12 +317,19 @@ pre_deps(struct ovni_emu *emu) th = emu->cur_thread; chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM]; - switch(emu->cur_ev->header.value) - { - case 'r': chan_push(chan_th, ST_NANOS6_DEP_REG); break; - case 'R': chan_pop (chan_th, ST_NANOS6_DEP_REG); break; - case 'u': chan_push(chan_th, ST_NANOS6_DEP_UNREG); break; - case 'U': chan_pop (chan_th, ST_NANOS6_DEP_UNREG); break; + switch (emu->cur_ev->header.value) { + case 'r': + chan_push(chan_th, ST_NANOS6_DEP_REG); + break; + case 'R': + chan_pop(chan_th, ST_NANOS6_DEP_REG); + break; + case 'u': + chan_push(chan_th, ST_NANOS6_DEP_UNREG); + break; + case 'U': + chan_pop(chan_th, ST_NANOS6_DEP_UNREG); + break; default: edie(emu, "unknown Nanos6 dependency event\n"); } @@ -336,16 +344,31 @@ pre_blocking(struct ovni_emu *emu) th = emu->cur_thread; chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM]; - switch(emu->cur_ev->header.value) - { - case 'b': chan_push(chan_th, ST_NANOS6_BLK_BLOCKING); break; - case 'B': chan_pop (chan_th, ST_NANOS6_BLK_BLOCKING); break; - case 'u': chan_push(chan_th, ST_NANOS6_BLK_UNBLOCKING); break; - case 'U': chan_pop (chan_th, ST_NANOS6_BLK_UNBLOCKING); break; - case 'w': chan_push(chan_th, ST_NANOS6_BLK_TASKWAIT); break; - case 'W': chan_pop (chan_th, ST_NANOS6_BLK_TASKWAIT); break; - case 'f': chan_push(chan_th, ST_NANOS6_BLK_WAITFOR); break; - case 'F': chan_pop (chan_th, ST_NANOS6_BLK_WAITFOR); break; + switch (emu->cur_ev->header.value) { + case 'b': + chan_push(chan_th, ST_NANOS6_BLK_BLOCKING); + break; + case 'B': + chan_pop(chan_th, ST_NANOS6_BLK_BLOCKING); + break; + case 'u': + chan_push(chan_th, ST_NANOS6_BLK_UNBLOCKING); + break; + case 'U': + chan_pop(chan_th, ST_NANOS6_BLK_UNBLOCKING); + break; + case 'w': + chan_push(chan_th, ST_NANOS6_BLK_TASKWAIT); + break; + case 'W': + chan_pop(chan_th, ST_NANOS6_BLK_TASKWAIT); + break; + case 'f': + chan_push(chan_th, ST_NANOS6_BLK_WAITFOR); + break; + case 'F': + chan_pop(chan_th, ST_NANOS6_BLK_WAITFOR); + break; default: edie(emu, "unknown Nanos6 blocking event\n"); } @@ -360,21 +383,46 @@ pre_worker(struct ovni_emu *emu) th = emu->cur_thread; chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM]; - switch(emu->cur_ev->header.value) - { - case '[': chan_push(chan_th, ST_NANOS6_WORKER_LOOP); break; - case ']': chan_pop (chan_th, ST_NANOS6_WORKER_LOOP); break; - case 't': chan_push(chan_th, ST_NANOS6_HANDLING_TASK); break; - case 'T': chan_pop (chan_th, ST_NANOS6_HANDLING_TASK); break; - case 'w': chan_push(chan_th, ST_NANOS6_SWITCH_TO); break; - case 'W': chan_pop (chan_th, ST_NANOS6_SWITCH_TO); break; - case 'm': chan_push(chan_th, ST_NANOS6_MIGRATE); break; - case 'M': chan_pop (chan_th, ST_NANOS6_MIGRATE); break; - case 's': chan_push(chan_th, ST_NANOS6_SUSPEND); break; - case 'S': chan_pop (chan_th, ST_NANOS6_SUSPEND); break; - case 'r': chan_push(chan_th, ST_NANOS6_RESUME); break; - case 'R': chan_pop (chan_th, ST_NANOS6_RESUME); break; - case '*': chan_ev (chan_th, EV_NANOS6_SIGNAL); break; + switch (emu->cur_ev->header.value) { + case '[': + chan_push(chan_th, ST_NANOS6_WORKER_LOOP); + break; + case ']': + chan_pop(chan_th, ST_NANOS6_WORKER_LOOP); + break; + case 't': + chan_push(chan_th, ST_NANOS6_HANDLING_TASK); + break; + case 'T': + chan_pop(chan_th, ST_NANOS6_HANDLING_TASK); + break; + case 'w': + chan_push(chan_th, ST_NANOS6_SWITCH_TO); + break; + case 'W': + chan_pop(chan_th, ST_NANOS6_SWITCH_TO); + break; + case 'm': + chan_push(chan_th, ST_NANOS6_MIGRATE); + break; + case 'M': + chan_pop(chan_th, ST_NANOS6_MIGRATE); + break; + case 's': + chan_push(chan_th, ST_NANOS6_SUSPEND); + break; + case 'S': + chan_pop(chan_th, ST_NANOS6_SUSPEND); + break; + case 'r': + chan_push(chan_th, ST_NANOS6_RESUME); + break; + case 'R': + chan_pop(chan_th, ST_NANOS6_RESUME); + break; + case '*': + chan_ev(chan_th, EV_NANOS6_SIGNAL); + break; default: edie(emu, "unknown Nanos6 worker event\n"); } @@ -389,12 +437,19 @@ pre_memory(struct ovni_emu *emu) th = emu->cur_thread; chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM]; - switch(emu->cur_ev->header.value) - { - case 'a': chan_push(chan_th, ST_NANOS6_ALLOCATING); break; - case 'A': chan_pop (chan_th, ST_NANOS6_ALLOCATING); break; - case 'f': chan_push(chan_th, ST_NANOS6_FREEING); break; - case 'F': chan_pop (chan_th, ST_NANOS6_FREEING); break; + switch (emu->cur_ev->header.value) { + case 'a': + chan_push(chan_th, ST_NANOS6_ALLOCATING); + break; + case 'A': + chan_pop(chan_th, ST_NANOS6_ALLOCATING); + break; + case 'f': + chan_push(chan_th, ST_NANOS6_FREEING); + break; + case 'F': + chan_pop(chan_th, ST_NANOS6_FREEING); + break; default: edie(emu, "unknown Nanos6 memory event\n"); } @@ -409,17 +464,34 @@ pre_sched(struct ovni_emu *emu) th = emu->cur_thread; chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM]; - switch(emu->cur_ev->header.value) - { - case '[': chan_push(chan_th, ST_NANOS6_SCHED_SERVING); break; - case ']': chan_pop (chan_th, ST_NANOS6_SCHED_SERVING); break; - case 'a': chan_push(chan_th, ST_NANOS6_SCHED_ADDING); break; - case 'A': chan_pop (chan_th, ST_NANOS6_SCHED_ADDING); break; - case 'p': chan_push(chan_th, ST_NANOS6_SCHED_PROCESSING); break; - case 'P': chan_pop (chan_th, ST_NANOS6_SCHED_PROCESSING); break; - case '@': chan_ev (chan_th, EV_NANOS6_SCHED_SELF); break; - case 'r': chan_ev (chan_th, EV_NANOS6_SCHED_RECV); break; - case 's': chan_ev (chan_th, EV_NANOS6_SCHED_SEND); break; + switch (emu->cur_ev->header.value) { + case '[': + chan_push(chan_th, ST_NANOS6_SCHED_SERVING); + break; + case ']': + chan_pop(chan_th, ST_NANOS6_SCHED_SERVING); + break; + case 'a': + chan_push(chan_th, ST_NANOS6_SCHED_ADDING); + break; + case 'A': + chan_pop(chan_th, ST_NANOS6_SCHED_ADDING); + break; + case 'p': + chan_push(chan_th, ST_NANOS6_SCHED_PROCESSING); + break; + case 'P': + chan_pop(chan_th, ST_NANOS6_SCHED_PROCESSING); + break; + case '@': + chan_ev(chan_th, EV_NANOS6_SCHED_SELF); + break; + case 'r': + chan_ev(chan_th, EV_NANOS6_SCHED_RECV); + break; + case 's': + chan_ev(chan_th, EV_NANOS6_SCHED_SEND); + break; default: edie(emu, "unknown Nanos6 scheduler event\n"); } @@ -434,16 +506,31 @@ pre_thread(struct ovni_emu *emu) th = emu->cur_thread; chan_th = &th->chan[CHAN_NANOS6_THREAD]; - switch(emu->cur_ev->header.value) - { - case 'e': chan_push(chan_th, ST_NANOS6_TH_EXTERNAL); break; - case 'E': chan_pop (chan_th, ST_NANOS6_TH_EXTERNAL); break; - case 'w': chan_push(chan_th, ST_NANOS6_TH_WORKER); break; - case 'W': chan_pop (chan_th, ST_NANOS6_TH_WORKER); break; - case 'l': chan_push(chan_th, ST_NANOS6_TH_LEADER); break; - case 'L': chan_pop (chan_th, ST_NANOS6_TH_LEADER); break; - case 'm': chan_push(chan_th, ST_NANOS6_TH_MAIN); break; - case 'M': chan_pop (chan_th, ST_NANOS6_TH_MAIN); break; + switch (emu->cur_ev->header.value) { + case 'e': + chan_push(chan_th, ST_NANOS6_TH_EXTERNAL); + break; + case 'E': + chan_pop(chan_th, ST_NANOS6_TH_EXTERNAL); + break; + case 'w': + chan_push(chan_th, ST_NANOS6_TH_WORKER); + break; + case 'W': + chan_pop(chan_th, ST_NANOS6_TH_WORKER); + break; + case 'l': + chan_push(chan_th, ST_NANOS6_TH_LEADER); + break; + case 'L': + chan_pop(chan_th, ST_NANOS6_TH_LEADER); + break; + case 'm': + chan_push(chan_th, ST_NANOS6_TH_MAIN); + break; + case 'M': + chan_pop(chan_th, ST_NANOS6_TH_MAIN); + break; default: edie(emu, "unknown Nanos6 thread type event\n"); } @@ -460,13 +547,16 @@ pre_ss(struct ovni_emu *emu, int st) dbg("pre_ss chan id %d st=%d\n", chan_th->id, st); - switch(emu->cur_ev->header.value) - { - case '[': chan_push(chan_th, st); break; - case ']': chan_pop(chan_th, st); break; + switch (emu->cur_ev->header.value) { + case '[': + chan_push(chan_th, st); + break; + case ']': + chan_pop(chan_th, st); + break; default: edie(emu, "unexpected value '%c' (expecting '[' or ']')\n", - emu->cur_ev->header.value); + emu->cur_ev->header.value); } } @@ -476,16 +566,15 @@ check_affinity(struct ovni_emu *emu) struct ovni_ethread *th = emu->cur_thread; struct ovni_cpu *cpu = th->cpu; - if(!cpu || cpu->virtual) + if (!cpu || cpu->virtual) return; - if(cpu->nrunning_threads > 1) - { + if (cpu->nrunning_threads > 1) { eerr(emu, "cpu %s has more than one thread running\n", cpu->name); /* Only abort in linter mode so we can still see the * trace to find out what was happening */ - if(emu->enable_linter) + if (emu->enable_linter) abort(); } } @@ -493,30 +582,55 @@ check_affinity(struct ovni_emu *emu) void hook_pre_nanos6(struct ovni_emu *emu) { - if(emu->cur_ev->header.model != '6') + if (emu->cur_ev->header.model != '6') edie(emu, "hook_pre_nanos6: unexpected event with model %c\n", - emu->cur_ev->header.model); + emu->cur_ev->header.model); - if(!emu->cur_thread->is_active) { + if (!emu->cur_thread->is_active) { edie(emu, "hook_pre_nanos6: current thread %d not active\n", - emu->cur_thread->tid); + emu->cur_thread->tid); } - switch(emu->cur_ev->header.category) - { - case 'T': pre_task(emu); break; - case 'C': pre_ss(emu, ST_NANOS6_TASK_CREATING); break; - case 'Y': pre_type(emu); break; - case 'S': pre_sched(emu); break; - case 'U': pre_ss(emu, ST_NANOS6_TASK_SUBMIT); break; - case 'F': pre_ss(emu, ST_NANOS6_TASK_SPAWNING); break; - case 'O': pre_ss(emu, ST_NANOS6_TASK_FOR); break; - case 't': pre_ss(emu, ST_NANOS6_TASK_BODY); break; - case 'H': pre_thread(emu); break; - case 'D': pre_deps(emu); break; - case 'B': pre_blocking(emu); break; - case 'W': pre_worker(emu); break; - case 'M': pre_memory(emu); break; + switch (emu->cur_ev->header.category) { + case 'T': + pre_task(emu); + break; + case 'C': + pre_ss(emu, ST_NANOS6_TASK_CREATING); + break; + case 'Y': + pre_type(emu); + break; + case 'S': + pre_sched(emu); + break; + case 'U': + pre_ss(emu, ST_NANOS6_TASK_SUBMIT); + break; + case 'F': + pre_ss(emu, ST_NANOS6_TASK_SPAWNING); + break; + case 'O': + pre_ss(emu, ST_NANOS6_TASK_FOR); + break; + case 't': + pre_ss(emu, ST_NANOS6_TASK_BODY); + break; + case 'H': + pre_thread(emu); + break; + case 'D': + pre_deps(emu); + break; + case 'B': + pre_blocking(emu); + break; + case 'W': + pre_worker(emu); + break; + case 'M': + pre_memory(emu); + break; default: edie(emu, "unknown Nanos6 event category\n"); } @@ -528,27 +642,23 @@ static void end_lint(struct ovni_emu *emu) { /* Ensure we run out of subsystem states */ - for(size_t i = 0; i < emu->total_nthreads; i++) - { + for (size_t i = 0; i < emu->total_nthreads; i++) { struct ovni_ethread *th = emu->global_thread[i]; struct ovni_chan *ch = &th->chan[CHAN_NANOS6_SUBSYSTEM]; - if(ch->n != 1) - { + if (ch->n != 1) { int top = ch->stack[ch->n - 1]; struct pcf_value_label *pv; char *name = "(unknown)"; - for(pv = &nanos6_ss_values[0]; pv->label; pv++) - { - if(pv->value == top) - { + for (pv = &nanos6_ss_values[0]; pv->label; pv++) { + if (pv->value == top) { name = pv->label; break; } } die("thread %d ended with %d extra stacked nanos6 subsystems, top=\"%s\"\n", - th->tid, ch->n - 1, name); + th->tid, ch->n - 1, name); } } } @@ -557,17 +667,14 @@ void hook_end_nanos6(struct ovni_emu *emu) { /* Emit types for all channel types and processes */ - for(enum chan_type ct = 0; ct < CHAN_MAXTYPE; ct++) - { + for (enum chan_type ct = 0; ct < CHAN_MAXTYPE; ct++) { struct pcf_file *pcf = &emu->pcf[ct]; int typeid = chan_to_prvtype[CHAN_NANOS6_TYPE]; struct pcf_type *pcftype = pcf_find_type(pcf, typeid); - for(size_t i = 0; i < emu->trace.nlooms; i++) - { + for (size_t i = 0; i < emu->trace.nlooms; i++) { struct ovni_loom *loom = &emu->trace.loom[i]; - for(size_t j = 0; j < loom->nprocs; j++) - { + for (size_t j = 0; j < loom->nprocs; j++) { struct ovni_eproc *proc = &loom->proc[j]; task_create_pcf_types(pcftype, proc->nanos6_task_info.types); } @@ -575,6 +682,6 @@ hook_end_nanos6(struct ovni_emu *emu) } /* When running in linter mode perform additional checks */ - if(emu->enable_linter) + if (emu->enable_linter) end_lint(emu); } diff --git a/emu_nodes.c b/emu_nodes.c index 21184a1..38dc848 100644 --- a/emu_nodes.c +++ b/emu_nodes.c @@ -3,10 +3,10 @@ #include "uthash.h" -#include "ovni.h" -#include "emu.h" -#include "prv.h" #include "chan.h" +#include "emu.h" +#include "ovni.h" +#include "prv.h" /* --------------------------- init ------------------------------- */ @@ -26,8 +26,7 @@ hook_init_nodes(struct ovni_emu *emu) prv_cpu = emu->prv_cpu; /* Init the channels in all threads */ - for(i=0; itotal_nthreads; i++) - { + for (i = 0; i < emu->total_nthreads; i++) { th = emu->global_thread[i]; row = th->gindex + 1; uth = &emu->th_chan; @@ -36,8 +35,7 @@ hook_init_nodes(struct ovni_emu *emu) } /* Init the channels in all cpus */ - for(i=0; itotal_ncpus; i++) - { + for (i = 0; i < emu->total_ncpus; i++) { cpu = emu->global_cpu[i]; row = cpu->gindex + 1; ucpu = &emu->cpu_chan; @@ -57,8 +55,7 @@ pre_subsystem(struct ovni_emu *emu, int st) th = emu->cur_thread; chan = &th->chan[CHAN_NODES_SUBSYSTEM]; - switch(emu->cur_ev->header.value) - { + switch (emu->cur_ev->header.value) { case '[': chan_push(chan, st); break; @@ -67,31 +64,46 @@ pre_subsystem(struct ovni_emu *emu, int st) break; default: edie(emu, "unexpected value '%c' (expecting '[' or ']')\n", - emu->cur_ev->header.value); + emu->cur_ev->header.value); } } void hook_pre_nodes(struct ovni_emu *emu) { - if(emu->cur_ev->header.model != 'D') + if (emu->cur_ev->header.model != 'D') edie(emu, "hook_pre_nodes: unexpected event with model %c\n", - emu->cur_ev->header.model); + emu->cur_ev->header.model); - if(!emu->cur_thread->is_running) + if (!emu->cur_thread->is_running) edie(emu, "hook_pre_nodes: current thread %d not running\n", - emu->cur_thread->tid); + emu->cur_thread->tid); - switch(emu->cur_ev->header.category) - { - case 'R': pre_subsystem(emu, ST_NODES_REGISTER); break; - case 'U': pre_subsystem(emu, ST_NODES_UNREGISTER); break; - case 'W': pre_subsystem(emu, ST_NODES_IF0_WAIT); break; - case 'I': pre_subsystem(emu, ST_NODES_IF0_INLINE); break; - case 'T': pre_subsystem(emu, ST_NODES_TASKWAIT); break; - case 'C': pre_subsystem(emu, ST_NODES_CREATE); break; - case 'S': pre_subsystem(emu, ST_NODES_SUBMIT); break; - case 'P': pre_subsystem(emu, ST_NODES_SPAWN); break; + switch (emu->cur_ev->header.category) { + case 'R': + pre_subsystem(emu, ST_NODES_REGISTER); + break; + case 'U': + pre_subsystem(emu, ST_NODES_UNREGISTER); + break; + case 'W': + pre_subsystem(emu, ST_NODES_IF0_WAIT); + break; + case 'I': + pre_subsystem(emu, ST_NODES_IF0_INLINE); + break; + case 'T': + pre_subsystem(emu, ST_NODES_TASKWAIT); + break; + case 'C': + pre_subsystem(emu, ST_NODES_CREATE); + break; + case 'S': + pre_subsystem(emu, ST_NODES_SUBMIT); + break; + case 'P': + pre_subsystem(emu, ST_NODES_SPAWN); + break; default: break; } diff --git a/emu_nosv.c b/emu_nosv.c index d70c182..962130c 100644 --- a/emu_nosv.c +++ b/emu_nosv.c @@ -4,11 +4,11 @@ #include "uthash.h" #include "utlist.h" -#include "ovni.h" +#include "chan.h" #include "emu.h" #include "emu_task.h" +#include "ovni.h" #include "prv.h" -#include "chan.h" /* --------------------------- init ------------------------------- */ @@ -28,17 +28,16 @@ hook_init_nosv(struct ovni_emu *emu) prv_cpu = emu->prv_cpu; /* Init the channels in all threads */ - for(i=0; itotal_nthreads; i++) - { + for (i = 0; i < emu->total_nthreads; i++) { th = emu->global_thread[i]; row = th->gindex + 1; uth = &emu->th_chan; chan_th_init(th, uth, CHAN_NOSV_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); - chan_th_init(th, uth, CHAN_NOSV_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); - chan_th_init(th, uth, CHAN_NOSV_APPID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); - chan_th_init(th, uth, CHAN_NOSV_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); + chan_th_init(th, uth, CHAN_NOSV_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); + chan_th_init(th, uth, CHAN_NOSV_APPID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); + chan_th_init(th, uth, CHAN_NOSV_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); /* We allow threads to emit subsystem events in cooling and * warming states as well, as they may be allocating memory. @@ -48,22 +47,20 @@ hook_init_nosv(struct ovni_emu *emu) } /* Init the nosv channels in all cpus */ - for(i=0; itotal_ncpus; i++) - { + for (i = 0; i < emu->total_ncpus; i++) { cpu = emu->global_cpu[i]; row = cpu->gindex + 1; ucpu = &emu->cpu_chan; - chan_cpu_init(cpu, ucpu, CHAN_NOSV_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); - chan_cpu_init(cpu, ucpu, CHAN_NOSV_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); - chan_cpu_init(cpu, ucpu, CHAN_NOSV_APPID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); - chan_cpu_init(cpu, ucpu, CHAN_NOSV_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); + chan_cpu_init(cpu, ucpu, CHAN_NOSV_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); + chan_cpu_init(cpu, ucpu, CHAN_NOSV_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); + chan_cpu_init(cpu, ucpu, CHAN_NOSV_APPID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); + chan_cpu_init(cpu, ucpu, CHAN_NOSV_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_NOSV_SUBSYSTEM, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); } /* Init task stack */ - for(i=0; itotal_nthreads; i++) - { + for (i = 0; i < emu->total_nthreads; i++) { th = emu->global_thread[i]; th->nosv_task_stack.thread = th; } @@ -80,7 +77,7 @@ chan_task_stopped(struct ovni_emu *emu) chan_set(&th->chan[CHAN_NOSV_TYPE], 0); chan_set(&th->chan[CHAN_NOSV_APPID], 0); - if(emu->cur_loom->rank_enabled) + if (emu->cur_loom->rank_enabled) chan_set(&th->chan[CHAN_NOSV_RANK], 0); /* XXX: Do we need this transition? */ @@ -96,20 +93,20 @@ chan_task_running(struct ovni_emu *emu, struct task *task) th = emu->cur_thread; proc = emu->cur_proc; - if(task->id == 0) + if (task->id == 0) edie(emu, "task id cannot be 0\n"); - if(task->type->gid == 0) + if (task->type->gid == 0) edie(emu, "task type gid cannot be 0\n"); - if(proc->appid <= 0) + if (proc->appid <= 0) edie(emu, "app id must be positive\n"); chan_set(&th->chan[CHAN_NOSV_TASKID], task->id); chan_set(&th->chan[CHAN_NOSV_TYPE], task->type->gid); chan_set(&th->chan[CHAN_NOSV_APPID], proc->appid); - if(emu->cur_loom->rank_enabled) + if (emu->cur_loom->rank_enabled) chan_set(&th->chan[CHAN_NOSV_RANK], proc->rank + 1); chan_push(&th->chan[CHAN_NOSV_SUBSYSTEM], ST_NOSV_TASK_RUNNING); @@ -117,23 +114,23 @@ chan_task_running(struct ovni_emu *emu, struct task *task) static void chan_task_switch(struct ovni_emu *emu, - struct task *prev, struct task *next) + struct task *prev, struct task *next) { struct ovni_ethread *th = emu->cur_thread; - if(!prev || !next) + if (!prev || !next) edie(emu, "cannot switch to or from a NULL task\n"); - if(prev == next) + if (prev == next) edie(emu, "cannot switch to the same task\n"); - if(next->id == 0) + if (next->id == 0) edie(emu, "next task id cannot be 0\n"); - if(next->type->gid == 0) + if (next->type->gid == 0) edie(emu, "next task type id cannot be 0\n"); - if(prev->thread != next->thread) + if (prev->thread != next->thread) edie(emu, "cannot switch to a task of another thread\n"); /* No need to change the rank or app ID, as we can only switch @@ -144,14 +141,14 @@ chan_task_switch(struct ovni_emu *emu, * the same type event, to mark the end of the current task. For * now we only emit a new type if we switch to a type with a * different gid. */ - if(prev->type->gid != next->type->gid) + if (prev->type->gid != next->type->gid) chan_set(&th->chan[CHAN_NOSV_TYPE], next->type->gid); } static void update_task_state(struct ovni_emu *emu) { - if(ovni_payload_size(emu->cur_ev) < 4) + if (ovni_payload_size(emu->cur_ev) < 4) edie(emu, "missing task id in payload\n"); uint32_t task_id = emu->cur_ev->payload.u32[0]; @@ -164,18 +161,25 @@ update_task_state(struct ovni_emu *emu) struct task *task = task_find(info->tasks, task_id); - if(task == NULL) + if (task == NULL) edie(emu, "cannot find task with id %u\n", task_id); - switch(emu->cur_ev->header.value) - { - case 'x': task_execute(emu, stack, task); break; - case 'e': task_end(emu, stack, task); break; - case 'p': task_pause(emu, stack, task); break; - case 'r': task_resume(emu, stack, task); break; + switch (emu->cur_ev->header.value) { + case 'x': + task_execute(emu, stack, task); + break; + case 'e': + task_end(emu, stack, task); + break; + case 'p': + task_pause(emu, stack, task); + break; + case 'r': + task_resume(emu, stack, task); + break; default: edie(emu, "unexpected Nanos6 task event value %c\n", - emu->cur_ev->header.value); + emu->cur_ev->header.value); } } @@ -185,13 +189,13 @@ expand_transition_value(struct ovni_emu *emu, int was_running, int runs_now) char tr = emu->cur_ev->header.value; /* Ensure we don't clobber the value */ - if(tr == 'X' || tr == 'E') + if (tr == 'X' || tr == 'E') edie(emu, "unexpected event value %c\n", tr); /* Modify the event value to detect nested transitions */ - if(tr == 'x' && was_running) + if (tr == 'x' && was_running) tr = 'X'; /* Execute a new nested task */ - else if(tr == 'e' && runs_now) + else if (tr == 'e' && runs_now) tr = 'E'; /* End a nested task */ return tr; @@ -199,17 +203,28 @@ expand_transition_value(struct ovni_emu *emu, int was_running, int runs_now) static void update_task_channels(struct ovni_emu *emu, - char tr, struct task *prev, struct task *next) + char tr, struct task *prev, struct task *next) { - switch(tr) - { - case 'x': chan_task_running(emu, next); break; - case 'r': chan_task_running(emu, next); break; - case 'e': chan_task_stopped(emu); break; - case 'p': chan_task_stopped(emu); break; + switch (tr) { + case 'x': + chan_task_running(emu, next); + break; + case 'r': + chan_task_running(emu, next); + break; + case 'e': + chan_task_stopped(emu); + break; + case 'p': + chan_task_stopped(emu); + break; /* Additional nested transitions */ - case 'X': chan_task_switch(emu, prev, next); break; - case 'E': chan_task_switch(emu, prev, next); break; + case 'X': + chan_task_switch(emu, prev, next); + break; + case 'E': + chan_task_switch(emu, prev, next); + break; default: edie(emu, "unexpected transition value %c\n", tr); } @@ -239,7 +254,7 @@ update_task(struct ovni_emu *emu) static void create_task(struct ovni_emu *emu) { - if(ovni_payload_size(emu->cur_ev) != 8) + if (ovni_payload_size(emu->cur_ev) != 8) edie(emu, "cannot create task: unexpected payload size\n"); uint32_t task_id = emu->cur_ev->payload.u32[0]; @@ -253,8 +268,7 @@ create_task(struct ovni_emu *emu) static void pre_task(struct ovni_emu *emu) { - switch(emu->cur_ev->header.value) - { + switch (emu->cur_ev->header.value) { case 'c': create_task(emu); break; @@ -266,18 +280,18 @@ pre_task(struct ovni_emu *emu) break; default: edie(emu, "unexpected task event value %c\n", - emu->cur_ev->header.value); + emu->cur_ev->header.value); } } static void pre_type(struct ovni_emu *emu) { - if(emu->cur_ev->header.value != 'c') + if (emu->cur_ev->header.value != 'c') edie(emu, "unexpected event value %c\n", - emu->cur_ev->header.value); + emu->cur_ev->header.value); - if((emu->cur_ev->header.flags & OVNI_EV_JUMBO) == 0) + if ((emu->cur_ev->header.flags & OVNI_EV_JUMBO) == 0) edie(emu, "expecting a jumbo event\n"); uint8_t *data = &emu->cur_ev->payload.jumbo.data[0]; @@ -300,8 +314,7 @@ pre_sched(struct ovni_emu *emu) th = emu->cur_thread; chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM]; - switch(emu->cur_ev->header.value) - { + switch (emu->cur_ev->header.value) { case 'h': chan_push(chan_th, ST_NOSV_SCHED_HUNGRY); break; @@ -337,19 +350,39 @@ pre_api(struct ovni_emu *emu) th = emu->cur_thread; chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM]; - switch(emu->cur_ev->header.value) - { - case 's': chan_push(chan_th, ST_NOSV_API_SUBMIT); break; - case 'S': chan_pop (chan_th, ST_NOSV_API_SUBMIT); break; - case 'p': chan_push(chan_th, ST_NOSV_API_PAUSE); break; - case 'P': chan_pop (chan_th, ST_NOSV_API_PAUSE); break; - case 'y': chan_push(chan_th, ST_NOSV_API_YIELD); break; - case 'Y': chan_pop (chan_th, ST_NOSV_API_YIELD); break; - case 'w': chan_push(chan_th, ST_NOSV_API_WAITFOR); break; - case 'W': chan_pop (chan_th, ST_NOSV_API_WAITFOR); break; - case 'c': chan_push(chan_th, ST_NOSV_API_SCHEDPOINT); break; - case 'C': chan_pop (chan_th, ST_NOSV_API_SCHEDPOINT); break; - default: break; + switch (emu->cur_ev->header.value) { + case 's': + chan_push(chan_th, ST_NOSV_API_SUBMIT); + break; + case 'S': + chan_pop(chan_th, ST_NOSV_API_SUBMIT); + break; + case 'p': + chan_push(chan_th, ST_NOSV_API_PAUSE); + break; + case 'P': + chan_pop(chan_th, ST_NOSV_API_PAUSE); + break; + case 'y': + chan_push(chan_th, ST_NOSV_API_YIELD); + break; + case 'Y': + chan_pop(chan_th, ST_NOSV_API_YIELD); + break; + case 'w': + chan_push(chan_th, ST_NOSV_API_WAITFOR); + break; + case 'W': + chan_pop(chan_th, ST_NOSV_API_WAITFOR); + break; + case 'c': + chan_push(chan_th, ST_NOSV_API_SCHEDPOINT); + break; + case 'C': + chan_pop(chan_th, ST_NOSV_API_SCHEDPOINT); + break; + default: + break; } } @@ -362,13 +395,21 @@ pre_mem(struct ovni_emu *emu) th = emu->cur_thread; chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM]; - switch(emu->cur_ev->header.value) - { - case 'a': chan_push(chan_th, ST_NOSV_MEM_ALLOCATING); break; - case 'A': chan_pop (chan_th, ST_NOSV_MEM_ALLOCATING); break; - case 'f': chan_push(chan_th, ST_NOSV_MEM_FREEING); break; - case 'F': chan_pop (chan_th, ST_NOSV_MEM_FREEING); break; - default: break; + switch (emu->cur_ev->header.value) { + case 'a': + chan_push(chan_th, ST_NOSV_MEM_ALLOCATING); + break; + case 'A': + chan_pop(chan_th, ST_NOSV_MEM_ALLOCATING); + break; + case 'f': + chan_push(chan_th, ST_NOSV_MEM_FREEING); + break; + case 'F': + chan_pop(chan_th, ST_NOSV_MEM_FREEING); + break; + default: + break; } } @@ -381,15 +422,27 @@ pre_thread_type(struct ovni_emu *emu) th = emu->cur_thread; chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM]; - switch(emu->cur_ev->header.value) - { - case 'a': chan_push(chan_th, ST_NOSV_ATTACH); break; - case 'A': chan_pop (chan_th, ST_NOSV_ATTACH); break; - case 'w': chan_push(chan_th, ST_NOSV_WORKER); break; - case 'W': chan_pop (chan_th, ST_NOSV_WORKER); break; - case 'd': chan_push(chan_th, ST_NOSV_DELEGATE); break; - case 'D': chan_pop (chan_th, ST_NOSV_DELEGATE); break; - default: break; + switch (emu->cur_ev->header.value) { + case 'a': + chan_push(chan_th, ST_NOSV_ATTACH); + break; + case 'A': + chan_pop(chan_th, ST_NOSV_ATTACH); + break; + case 'w': + chan_push(chan_th, ST_NOSV_WORKER); + break; + case 'W': + chan_pop(chan_th, ST_NOSV_WORKER); + break; + case 'd': + chan_push(chan_th, ST_NOSV_DELEGATE); + break; + case 'D': + chan_pop(chan_th, ST_NOSV_DELEGATE); + break; + default: + break; } } @@ -404,8 +457,7 @@ pre_ss(struct ovni_emu *emu, int st) dbg("pre_ss chan id %d st=%d\n", chan_th->id, st); - switch(emu->cur_ev->header.value) - { + switch (emu->cur_ev->header.value) { case '[': chan_push(chan_th, st); break; @@ -414,7 +466,7 @@ pre_ss(struct ovni_emu *emu, int st) break; default: err("unexpected value '%c' (expecting '[' or ']')\n", - emu->cur_ev->header.value); + emu->cur_ev->header.value); abort(); } } @@ -425,44 +477,56 @@ check_affinity(struct ovni_emu *emu) struct ovni_ethread *th = emu->cur_thread; struct ovni_cpu *cpu = th->cpu; - if(!cpu || cpu->virtual) + if (!cpu || cpu->virtual) return; - if(th->state != TH_ST_RUNNING) + if (th->state != TH_ST_RUNNING) return; - if(cpu->nrunning_threads > 1) - { + if (cpu->nrunning_threads > 1) { edie(emu, "cpu %s has more than one thread running\n", - cpu->name); + cpu->name); } } void hook_pre_nosv(struct ovni_emu *emu) { - if(emu->cur_ev->header.model != 'V') + if (emu->cur_ev->header.model != 'V') edie(emu, "hook_pre_nosv: unexpected event with model %c\n", - emu->cur_ev->header.model); + emu->cur_ev->header.model); - if(!emu->cur_thread->is_active) + if (!emu->cur_thread->is_active) edie(emu, "hook_pre_nosv: current thread %d not active\n", - emu->cur_thread->tid); + emu->cur_thread->tid); - switch(emu->cur_ev->header.category) - { - case 'T': pre_task(emu); break; - case 'Y': pre_type(emu); break; - case 'S': pre_sched(emu); break; - case 'U': pre_ss(emu, ST_NOSV_SCHED_SUBMITTING); break; - case 'M': pre_mem(emu); break; - case 'H': pre_thread_type(emu); break; - case 'A': pre_api(emu); break; + switch (emu->cur_ev->header.category) { + case 'T': + pre_task(emu); + break; + case 'Y': + pre_type(emu); + break; + case 'S': + pre_sched(emu); + break; + case 'U': + pre_ss(emu, ST_NOSV_SCHED_SUBMITTING); + break; + case 'M': + pre_mem(emu); + break; + case 'H': + pre_thread_type(emu); + break; + case 'A': + pre_api(emu); + break; default: break; } - if(emu->enable_linter) + if (emu->enable_linter) check_affinity(emu); } @@ -470,17 +534,14 @@ void hook_end_nosv(struct ovni_emu *emu) { /* Emit types for all channel types and processes */ - for(enum chan_type ct = 0; ct < CHAN_MAXTYPE; ct++) - { + for (enum chan_type ct = 0; ct < CHAN_MAXTYPE; ct++) { struct pcf_file *pcf = &emu->pcf[ct]; int typeid = chan_to_prvtype[CHAN_NOSV_TYPE]; struct pcf_type *pcftype = pcf_find_type(pcf, typeid); - for(size_t i = 0; i < emu->trace.nlooms; i++) - { + for (size_t i = 0; i < emu->trace.nlooms; i++) { struct ovni_loom *loom = &emu->trace.loom[i]; - for(size_t j = 0; j < loom->nprocs; j++) - { + for (size_t j = 0; j < loom->nprocs; j++) { struct ovni_eproc *proc = &loom->proc[j]; task_create_pcf_types(pcftype, proc->nosv_task_info.types); } diff --git a/emu_openmp.c b/emu_openmp.c index 043b3eb..1a69f18 100644 --- a/emu_openmp.c +++ b/emu_openmp.c @@ -3,10 +3,10 @@ #include "uthash.h" -#include "ovni.h" -#include "emu.h" -#include "prv.h" #include "chan.h" +#include "emu.h" +#include "ovni.h" +#include "prv.h" /* --------------------------- init ------------------------------- */ @@ -26,8 +26,7 @@ hook_init_openmp(struct ovni_emu *emu) prv_cpu = emu->prv_cpu; /* Init the channels in all threads */ - for(i=0; itotal_nthreads; i++) - { + for (i = 0; i < emu->total_nthreads; i++) { th = emu->global_thread[i]; row = th->gindex + 1; uth = &emu->th_chan; @@ -36,8 +35,7 @@ hook_init_openmp(struct ovni_emu *emu) } /* Init the channels in all cpus */ - for(i=0; itotal_ncpus; i++) - { + for (i = 0; i < emu->total_ncpus; i++) { cpu = emu->global_cpu[i]; row = cpu->gindex + 1; ucpu = &emu->cpu_chan; @@ -57,8 +55,7 @@ pre_mode(struct ovni_emu *emu, int st) th = emu->cur_thread; chan = &th->chan[CHAN_OPENMP_MODE]; - switch(emu->cur_ev->header.value) - { + switch (emu->cur_ev->header.value) { case '[': chan_push(chan, st); break; @@ -67,7 +64,7 @@ pre_mode(struct ovni_emu *emu, int st) break; default: err("unexpected value '%c' (expecting '[' or ']')\n", - emu->cur_ev->header.value); + emu->cur_ev->header.value); abort(); } } @@ -75,18 +72,21 @@ pre_mode(struct ovni_emu *emu, int st) void hook_pre_openmp(struct ovni_emu *emu) { - if(emu->cur_ev->header.model != 'M') + if (emu->cur_ev->header.model != 'M') die("hook_pre_openmp: unexpected event with model %c\n", - emu->cur_ev->header.model); + emu->cur_ev->header.model); - if(!emu->cur_thread->is_active) + if (!emu->cur_thread->is_active) die("hook_pre_openmp: current thread %d not active\n", - emu->cur_thread->tid); + emu->cur_thread->tid); - switch(emu->cur_ev->header.category) - { - case 'T': pre_mode(emu, ST_OPENMP_TASK); break; - case 'P': pre_mode(emu, ST_OPENMP_PARALLEL); break; + switch (emu->cur_ev->header.category) { + case 'T': + pre_mode(emu, ST_OPENMP_TASK); + break; + case 'P': + pre_mode(emu, ST_OPENMP_PARALLEL); + break; default: break; } diff --git a/emu_ovni.c b/emu_ovni.c index 353af88..5031121 100644 --- a/emu_ovni.c +++ b/emu_ovni.c @@ -1,10 +1,10 @@ /* Copyright (c) 2021 Barcelona Supercomputing Center (BSC) * SPDX-License-Identifier: GPL-3.0-or-later */ -#include "ovni.h" -#include "emu.h" -#include "prv.h" #include "chan.h" +#include "emu.h" +#include "ovni.h" +#include "prv.h" #include "utlist.h" /* The emulator ovni module provides the execution model by tracking the thread @@ -28,30 +28,28 @@ hook_init_ovni(struct ovni_emu *emu) prv_cpu = emu->prv_cpu; /* Init the ovni channels in all threads */ - for(i=0; itotal_nthreads; i++) - { + for (i = 0; i < emu->total_nthreads; i++) { th = emu->global_thread[i]; row = th->gindex + 1; uth = &emu->th_chan; - chan_th_init(th, uth, CHAN_OVNI_TID, CHAN_TRACK_TH_RUNNING, th->tid, 0, 1, row, prv_th, clock); - chan_th_init(th, uth, CHAN_OVNI_PID, CHAN_TRACK_TH_RUNNING, th->proc->pid, 0, 1, row, prv_th, clock); - chan_th_init(th, uth, CHAN_OVNI_CPU, CHAN_TRACK_NONE, -1, 0, 1, row, prv_th, clock); - chan_th_init(th, uth, CHAN_OVNI_STATE, CHAN_TRACK_NONE, TH_ST_UNKNOWN, 1, 1, row, prv_th, clock); - chan_th_init(th, uth, CHAN_OVNI_FLUSH, CHAN_TRACK_NONE, ST_NULL, 1, 1, row, prv_th, clock); + chan_th_init(th, uth, CHAN_OVNI_TID, CHAN_TRACK_TH_RUNNING, th->tid, 0, 1, row, prv_th, clock); + chan_th_init(th, uth, CHAN_OVNI_PID, CHAN_TRACK_TH_RUNNING, th->proc->pid, 0, 1, row, prv_th, clock); + chan_th_init(th, uth, CHAN_OVNI_CPU, CHAN_TRACK_NONE, -1, 0, 1, row, prv_th, clock); + chan_th_init(th, uth, CHAN_OVNI_STATE, CHAN_TRACK_NONE, TH_ST_UNKNOWN, 1, 1, row, prv_th, clock); + chan_th_init(th, uth, CHAN_OVNI_FLUSH, CHAN_TRACK_NONE, ST_NULL, 1, 1, row, prv_th, clock); } /* Init the ovni channels in all cpus */ - for(i=0; itotal_ncpus; i++) - { + for (i = 0; i < emu->total_ncpus; i++) { cpu = emu->global_cpu[i]; row = cpu->gindex + 1; ucpu = &emu->cpu_chan; - chan_cpu_init(cpu, ucpu, CHAN_OVNI_TID, CHAN_TRACK_TH_RUNNING, 0, 1, 1, row, prv_cpu, clock); - chan_cpu_init(cpu, ucpu, CHAN_OVNI_PID, CHAN_TRACK_TH_RUNNING, 0, 1, 1, row, prv_cpu, clock); - chan_cpu_init(cpu, ucpu, CHAN_OVNI_NRTHREADS, CHAN_TRACK_NONE, 0, 1, 1, row, prv_cpu, clock); - chan_cpu_init(cpu, ucpu, CHAN_OVNI_FLUSH, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); + chan_cpu_init(cpu, ucpu, CHAN_OVNI_TID, CHAN_TRACK_TH_RUNNING, 0, 1, 1, row, prv_cpu, clock); + chan_cpu_init(cpu, ucpu, CHAN_OVNI_PID, CHAN_TRACK_TH_RUNNING, 0, 1, 1, row, prv_cpu, clock); + chan_cpu_init(cpu, ucpu, CHAN_OVNI_NRTHREADS, CHAN_TRACK_NONE, 0, 1, 1, row, prv_cpu, clock); + chan_cpu_init(cpu, ucpu, CHAN_OVNI_FLUSH, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); } } @@ -63,11 +61,10 @@ chan_tracking_update(struct ovni_chan *chan, struct ovni_ethread *th) { int enabled; - if(th == NULL) + if (th == NULL) die("chan_tracking_update: thread is NULL"); - switch (chan->track) - { + switch (chan->track) { case CHAN_TRACK_TH_RUNNING: enabled = th->is_running; break; @@ -81,11 +78,11 @@ chan_tracking_update(struct ovni_chan *chan, struct ovni_ethread *th) } /* The channel is already in the proper state */ - if(chan_is_enabled(chan) == enabled) + if (chan_is_enabled(chan) == enabled) return; dbg("thread %d changes state to %d: chan %d enabled=%d\n", - th->tid, th->state, chan->id, enabled); + th->tid, th->state, chan->id, enabled); chan_enable(chan, enabled); } @@ -97,25 +94,27 @@ thread_set_state(struct ovni_ethread *th, enum ethread_state state) int i; /* The state must be updated when a cpu is set */ - if(th->cpu == NULL) + if (th->cpu == NULL) die("thread_set_state: thread %d doesn't have a CPU\n", - th->tid); + th->tid); dbg("thread_set_state: setting thread %d state %d\n", - th->tid, state); + th->tid, state); th->state = state; th->is_running = (state == TH_ST_RUNNING) ? 1 : 0; th->is_active = (state == TH_ST_RUNNING - || state == TH_ST_COOLING - || state == TH_ST_WARMING) ? 1 : 0; + || state == TH_ST_COOLING + || state == TH_ST_WARMING) + ? 1 + : 0; chan_set(&th->chan[CHAN_OVNI_STATE], th->state); - + /* Enable or disable the thread channels that track the thread state */ - for(i=0; ichan[i], th); dbg("thread_set_state: done\n"); @@ -129,15 +128,12 @@ cpu_update_th_stats(struct ovni_cpu *cpu) DL_FOREACH(cpu->thread, th) { - if(th->state == TH_ST_RUNNING) - { + if (th->state == TH_ST_RUNNING) { th_running = th; running++; th_active = th; active++; - } - else if(th->state == TH_ST_COOLING || th->state == TH_ST_WARMING) - { + } else if (th->state == TH_ST_COOLING || th->state == TH_ST_WARMING) { th_active = th; active++; } @@ -161,11 +157,11 @@ update_cpu(struct ovni_cpu *cpu) /* From the CPU channels we only need to manually update the number of * threads running in the CPU */ - if(chan_get_st(&cpu->chan[CHAN_OVNI_NRTHREADS]) != (int) cpu->nrunning_threads) + if (chan_get_st(&cpu->chan[CHAN_OVNI_NRTHREADS]) != (int) cpu->nrunning_threads) chan_set(&cpu->chan[CHAN_OVNI_NRTHREADS], (int) cpu->nrunning_threads); /* Update all tracking channels */ - for(i=0; ichan[i]); dbg("updating cpu %s complete!\n", cpu->name); @@ -174,10 +170,10 @@ update_cpu(struct ovni_cpu *cpu) struct ovni_cpu * emu_get_cpu(struct ovni_loom *loom, int cpuid) { - if(cpuid >= (int) loom->ncpus) + if (cpuid >= (int) loom->ncpus) die("emu_get_cpu: CPU index out of bounds\n"); - if(cpuid < 0) + if (cpuid < 0) return &loom->vcpu; return &loom->cpu[cpuid]; @@ -190,7 +186,7 @@ emu_cpu_find_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread) DL_FOREACH(cpu->thread, p) { - if(p == thread) + if (p == thread) return p; } @@ -202,10 +198,9 @@ static void cpu_add_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread) { /* Found, abort */ - if(emu_cpu_find_thread(cpu, thread) != NULL) - { + if (emu_cpu_find_thread(cpu, thread) != NULL) { err("The thread %d is already assigned to %s\n", - thread->tid, cpu->name); + thread->tid, cpu->name); abort(); } @@ -223,10 +218,9 @@ cpu_remove_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread) p = emu_cpu_find_thread(cpu, thread); /* Not found, abort */ - if(p == NULL) - { + if (p == NULL) { err("cannot remove missing thread %d from cpu %s\n", - thread->tid, cpu->name); + thread->tid, cpu->name); abort(); } @@ -238,10 +232,9 @@ cpu_remove_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread) static void cpu_migrate_thread(struct ovni_cpu *cpu, - struct ovni_ethread *thread, - struct ovni_cpu *newcpu) + struct ovni_ethread *thread, + struct ovni_cpu *newcpu) { - cpu_remove_thread(cpu, thread); cpu_add_thread(newcpu, thread); } @@ -251,12 +244,12 @@ cpu_migrate_thread(struct ovni_cpu *cpu, static void thread_set_cpu(struct ovni_ethread *th, struct ovni_cpu *cpu) { - if(th->cpu != NULL) + if (th->cpu != NULL) die("thread_set_cpu: thread %d already has a CPU\n", - th->tid); + th->tid); dbg("thread_set_cpu: setting thread %d cpu to %s\n", - th->tid, cpu->name); + th->tid, cpu->name); th->cpu = cpu; chan_enable(&th->chan[CHAN_OVNI_CPU], 1); @@ -268,9 +261,9 @@ thread_set_cpu(struct ovni_ethread *th, struct ovni_cpu *cpu) static void thread_unset_cpu(struct ovni_ethread *th) { - if(th->cpu == NULL) + if (th->cpu == NULL) die("thread_unset_cpu: thread %d doesn't have a CPU\n", - th->tid); + th->tid); th->cpu = NULL; @@ -282,9 +275,9 @@ thread_unset_cpu(struct ovni_ethread *th) static void thread_migrate_cpu(struct ovni_ethread *th, struct ovni_cpu *cpu) { - if(th->cpu == NULL) + if (th->cpu == NULL) die("thread_migrate_cpu: thread %d doesn't have a CPU\n", - th->tid); + th->tid); th->cpu = cpu; chan_set(&th->chan[CHAN_OVNI_CPU], cpu->gindex + 1); @@ -297,9 +290,9 @@ pre_thread_execute(struct ovni_emu *emu, struct ovni_ethread *th) int cpuid; /* The thread cannot be already running */ - if(th->state == TH_ST_RUNNING) + if (th->state == TH_ST_RUNNING) edie(emu, "pre_thread_execute: thread %d already running\n", - th->tid); + th->tid); cpuid = emu->cur_ev->payload.i32[0]; @@ -320,13 +313,13 @@ pre_thread_execute(struct ovni_emu *emu, struct ovni_ethread *th) static void pre_thread_end(struct ovni_ethread *th) { - if(th->state != TH_ST_RUNNING && th->state != TH_ST_COOLING) + if (th->state != TH_ST_RUNNING && th->state != TH_ST_COOLING) die("pre_thread_end: thread %d not running or cooling\n", - th->tid); + th->tid); - if(th->cpu == NULL) + if (th->cpu == NULL) die("pre_thread_end: thread %d doesn't have a CPU\n", - th->tid); + th->tid); /* First update the thread state */ thread_set_state(th, TH_ST_DEAD); @@ -340,13 +333,13 @@ pre_thread_end(struct ovni_ethread *th) static void pre_thread_pause(struct ovni_ethread *th) { - if(th->state != TH_ST_RUNNING && th->state != TH_ST_COOLING) + if (th->state != TH_ST_RUNNING && th->state != TH_ST_COOLING) die("pre_thread_pause: thread %d not running or cooling\n", - th->tid); + th->tid); - if(th->cpu == NULL) + if (th->cpu == NULL) die("pre_thread_pause: thread %d doesn't have a CPU\n", - th->tid); + th->tid); thread_set_state(th, TH_ST_PAUSED); update_cpu(th->cpu); @@ -355,13 +348,13 @@ pre_thread_pause(struct ovni_ethread *th) static void pre_thread_resume(struct ovni_ethread *th) { - if(th->state != TH_ST_PAUSED && th->state != TH_ST_WARMING) + if (th->state != TH_ST_PAUSED && th->state != TH_ST_WARMING) die("pre_thread_resume: thread %d not paused or warming\n", - th->tid); + th->tid); - if(th->cpu == NULL) + if (th->cpu == NULL) die("pre_thread_resume: thread %d doesn't have a CPU\n", - th->tid); + th->tid); thread_set_state(th, TH_ST_RUNNING); update_cpu(th->cpu); @@ -370,13 +363,13 @@ pre_thread_resume(struct ovni_ethread *th) static void pre_thread_cool(struct ovni_ethread *th) { - if(th->state != TH_ST_RUNNING) + if (th->state != TH_ST_RUNNING) die("pre_thread_cool: thread %d not running\n", - th->tid); + th->tid); - if(th->cpu == NULL) + if (th->cpu == NULL) die("pre_thread_cool: thread %d doesn't have a CPU\n", - th->tid); + th->tid); thread_set_state(th, TH_ST_COOLING); update_cpu(th->cpu); @@ -385,13 +378,13 @@ pre_thread_cool(struct ovni_ethread *th) static void pre_thread_warm(struct ovni_ethread *th) { - if(th->state != TH_ST_PAUSED) + if (th->state != TH_ST_PAUSED) die("pre_thread_warm: thread %d not paused\n", - th->tid); + th->tid); - if(th->cpu == NULL) + if (th->cpu == NULL) die("pre_thread_warm: thread %d doesn't have a CPU\n", - th->tid); + th->tid); thread_set_state(th, TH_ST_WARMING); update_cpu(th->cpu); @@ -403,31 +396,42 @@ pre_thread(struct ovni_emu *emu) struct ovni_ev *ev; struct ovni_ethread *th; - //emu_emit(emu); + // emu_emit(emu); th = emu->cur_thread; ev = emu->cur_ev; - switch(ev->header.value) - { + switch (ev->header.value) { case 'C': /* create */ dbg("thread %d creates a new thread at cpu=%d with args=%x %x\n", - th->tid, - ev->payload.u32[0], - ev->payload.u32[1], - ev->payload.u32[2]); + th->tid, + ev->payload.u32[0], + ev->payload.u32[1], + ev->payload.u32[2]); break; - case 'x': pre_thread_execute(emu, th); break; - case 'e': pre_thread_end(th); break; - case 'p': pre_thread_pause(th); break; - case 'r': pre_thread_resume(th); break; - case 'c': pre_thread_cool(th); break; - case 'w': pre_thread_warm(th); break; + case 'x': + pre_thread_execute(emu, th); + break; + case 'e': + pre_thread_end(th); + break; + case 'p': + pre_thread_pause(th); + break; + case 'r': + pre_thread_resume(th); + break; + case 'c': + pre_thread_cool(th); + break; + case 'w': + pre_thread_warm(th); + break; default: - err("unknown thread event value %c\n", - ev->header.value); - exit(EXIT_FAILURE); + err("unknown thread event value %c\n", + ev->header.value); + exit(EXIT_FAILURE); } } @@ -441,25 +445,25 @@ pre_affinity_set(struct ovni_emu *emu) th = emu->cur_thread; cpuid = emu->cur_ev->payload.i32[0]; - if(th->cpu == NULL) + if (th->cpu == NULL) edie(emu, "pre_affinity_set: thread %d doesn't have a CPU\n", - th->tid); + th->tid); - if(!th->is_active) + if (!th->is_active) edie(emu, "pre_affinity_set: thread %d is not active\n", - th->tid); + th->tid); /* Migrate current cpu to the one at cpuid */ newcpu = emu_get_cpu(emu->cur_loom, cpuid); /* The CPU is already properly set, return */ - if(th->cpu == newcpu) + if (th->cpu == newcpu) return; cpu_migrate_thread(th->cpu, th, newcpu); thread_migrate_cpu(th, newcpu); - //dbg("cpu %d now runs %d\n", cpuid, th->tid); + // dbg("cpu %d now runs %d\n", cpuid, th->tid); } static void @@ -477,47 +481,44 @@ pre_affinity_remote(struct ovni_emu *emu) remote_th = emu_get_thread(emu->cur_proc, tid); - if(remote_th == NULL) - { + if (remote_th == NULL) { /* Search the thread in other processes of the loom if * not found in the current one */ loom = emu->cur_loom; - for(i=0; inprocs; i++) - { + for (i = 0; i < loom->nprocs; i++) { proc = &loom->proc[i]; /* Skip the current process */ - if(proc == emu->cur_proc) + if (proc == emu->cur_proc) continue; remote_th = emu_get_thread(proc, tid); - if(remote_th) + if (remote_th) break; } - if(remote_th == NULL) - { + if (remote_th == NULL) { err("thread tid %d not found: cannot set affinity remotely\n", - tid); + tid); abort(); } } /* The remote_th cannot be in states dead or unknown */ - if(remote_th->state == TH_ST_DEAD) + if (remote_th->state == TH_ST_DEAD) edie(emu, "pre_affinity_remote: remote thread %d in state DEAD\n", - remote_th->tid); + remote_th->tid); - if(remote_th->state == TH_ST_UNKNOWN) + if (remote_th->state == TH_ST_UNKNOWN) edie(emu, "pre_affinity_remote: remote thread %d in state UNKNOWN\n", - remote_th->tid); + remote_th->tid); /* It must have an assigned CPU */ - if(remote_th->cpu == NULL) + if (remote_th->cpu == NULL) edie(emu, "pre_affinity_remote: remote thread %d has no CPU\n", - remote_th->tid); + remote_th->tid); /* Migrate current cpu to the one at cpuid */ newcpu = emu_get_cpu(emu->cur_loom, cpuid); @@ -525,21 +526,24 @@ pre_affinity_remote(struct ovni_emu *emu) cpu_migrate_thread(remote_th->cpu, remote_th, newcpu); thread_migrate_cpu(remote_th, newcpu); - //dbg("remote_th %d switches to cpu %d by remote petition\n", tid, + // dbg("remote_th %d switches to cpu %d by remote petition\n", tid, // cpuid); } static void pre_affinity(struct ovni_emu *emu) { - //emu_emit(emu); - switch(emu->cur_ev->header.value) - { - case 's': pre_affinity_set(emu); break; - case 'r': pre_affinity_remote(emu); break; + // emu_emit(emu); + switch (emu->cur_ev->header.value) { + case 's': + pre_affinity_set(emu); + break; + case 'r': + pre_affinity_remote(emu); + break; default: dbg("unknown affinity event value %c\n", - emu->cur_ev->header.value); + emu->cur_ev->header.value); break; } } @@ -554,17 +558,14 @@ pre_burst(struct ovni_emu *emu) th = emu->cur_thread; - if(th->nbursts >= MAX_BURSTS) - { + if (th->nbursts >= MAX_BURSTS) { err("too many bursts: ignored\n"); return; } th->burst_time[th->nbursts] = emu->delta_time; - if(th->nbursts > 0) - { - dt = th->burst_time[th->nbursts] - - th->burst_time[th->nbursts - 1]; + if (th->nbursts > 0) { + dt = th->burst_time[th->nbursts] - th->burst_time[th->nbursts - 1]; dbg("burst delta time %ld ns\n", dt); } @@ -581,8 +582,7 @@ pre_flush(struct ovni_emu *emu) th = emu->cur_thread; chan_th = &th->chan[CHAN_OVNI_FLUSH]; - switch(emu->cur_ev->header.value) - { + switch (emu->cur_ev->header.value) { case '[': chan_push(chan_th, ST_OVNI_FLUSHING); break; @@ -591,7 +591,7 @@ pre_flush(struct ovni_emu *emu) break; default: err("unexpected value '%c' (expecting '[' or ']')\n", - emu->cur_ev->header.value); + emu->cur_ev->header.value); abort(); } } @@ -599,20 +599,27 @@ pre_flush(struct ovni_emu *emu) void hook_pre_ovni(struct ovni_emu *emu) { - //emu_emit(emu); + // emu_emit(emu); - if(emu->cur_ev->header.model != 'O') + if (emu->cur_ev->header.model != 'O') return; - switch(emu->cur_ev->header.category) - { - case 'H': pre_thread(emu); break; - case 'A': pre_affinity(emu); break; - case 'B': pre_burst(emu); break; - case 'F': pre_flush(emu); break; + switch (emu->cur_ev->header.category) { + case 'H': + pre_thread(emu); + break; + case 'A': + pre_affinity(emu); + break; + case 'B': + pre_burst(emu); + break; + case 'F': + pre_flush(emu); + break; default: dbg("unknown ovni event category %c\n", - emu->cur_ev->header.category); + emu->cur_ev->header.category); break; } } diff --git a/emu_tampi.c b/emu_tampi.c index bd93e6e..4e83fc2 100644 --- a/emu_tampi.c +++ b/emu_tampi.c @@ -3,10 +3,10 @@ #include "uthash.h" -#include "ovni.h" -#include "emu.h" -#include "prv.h" #include "chan.h" +#include "emu.h" +#include "ovni.h" +#include "prv.h" /* --------------------------- init ------------------------------- */ @@ -26,8 +26,7 @@ hook_init_tampi(struct ovni_emu *emu) prv_cpu = emu->prv_cpu; /* Init the channels in all threads */ - for(i=0; itotal_nthreads; i++) - { + for (i = 0; i < emu->total_nthreads; i++) { th = emu->global_thread[i]; row = th->gindex + 1; uth = &emu->th_chan; @@ -36,8 +35,7 @@ hook_init_tampi(struct ovni_emu *emu) } /* Init the channels in all cpus */ - for(i=0; itotal_ncpus; i++) - { + for (i = 0; i < emu->total_ncpus; i++) { cpu = emu->global_cpu[i]; row = cpu->gindex + 1; ucpu = &emu->cpu_chan; @@ -55,8 +53,7 @@ pre_tampi_mode(struct ovni_emu *emu, int state) th = emu->cur_thread; - switch(emu->cur_ev->header.value) - { + switch (emu->cur_ev->header.value) { case '[': chan_push(&th->chan[CHAN_TAMPI_MODE], state); break; @@ -65,25 +62,36 @@ pre_tampi_mode(struct ovni_emu *emu, int state) break; default: edie(emu, "unexpected event value %c for tampi mode\n", - emu->cur_ev->header.value); + emu->cur_ev->header.value); } } void hook_pre_tampi(struct ovni_emu *emu) { - if(emu->cur_ev->header.model != 'T') + if (emu->cur_ev->header.model != 'T') edie(emu, "hook_pre_tampi: unexpected event with model %c\n", - emu->cur_ev->header.model); + emu->cur_ev->header.model); - switch(emu->cur_ev->header.category) - { - case 'S': pre_tampi_mode(emu, ST_TAMPI_SEND); break; - case 'R': pre_tampi_mode(emu, ST_TAMPI_RECV); break; - case 's': pre_tampi_mode(emu, ST_TAMPI_ISEND); break; - case 'r': pre_tampi_mode(emu, ST_TAMPI_IRECV); break; - case 'V': pre_tampi_mode(emu, ST_TAMPI_WAIT); break; - case 'W': pre_tampi_mode(emu, ST_TAMPI_WAITALL); break; + switch (emu->cur_ev->header.category) { + case 'S': + pre_tampi_mode(emu, ST_TAMPI_SEND); + break; + case 'R': + pre_tampi_mode(emu, ST_TAMPI_RECV); + break; + case 's': + pre_tampi_mode(emu, ST_TAMPI_ISEND); + break; + case 'r': + pre_tampi_mode(emu, ST_TAMPI_IRECV); + break; + case 'V': + pre_tampi_mode(emu, ST_TAMPI_WAIT); + break; + case 'W': + pre_tampi_mode(emu, ST_TAMPI_WAITALL); + break; default: break; } diff --git a/emu_task.c b/emu_task.c index 926fa9f..304e0f2 100644 --- a/emu_task.c +++ b/emu_task.c @@ -4,11 +4,11 @@ #include "uthash.h" #include "utlist.h" -#include "ovni.h" +#include "chan.h" #include "emu.h" #include "emu_task.h" +#include "ovni.h" #include "prv.h" -#include "chan.h" struct task * task_find(struct task *tasks, uint32_t task_id) @@ -30,21 +30,21 @@ task_type_find(struct task_type *types, uint32_t type_id) void task_create(struct ovni_emu *emu, struct task_info *info, - uint32_t type_id, uint32_t task_id) + uint32_t type_id, uint32_t task_id) { /* Ensure the task id is new */ - if(task_find(info->tasks, task_id) != NULL) + if (task_find(info->tasks, task_id) != NULL) edie(emu, "cannot create task: task_id %u already exists\n", - task_id); + task_id); /* Ensure the type exists */ struct task_type *type = task_type_find(info->types, type_id); - if(type == NULL) + if (type == NULL) edie(emu, "cannot create task: unknown type id %u\n", type_id); struct task *task = calloc(1, sizeof(struct task)); - if(task == NULL) + if (task == NULL) die("calloc failed\n"); task->id = task_id; @@ -60,24 +60,24 @@ task_create(struct ovni_emu *emu, struct task_info *info, void task_execute(struct ovni_emu *emu, - struct task_stack *stack, struct task *task) + struct task_stack *stack, struct task *task) { - if(task == NULL) + if (task == NULL) edie(emu, "cannot execute: task is NULL\n"); - if(task->state != TASK_ST_CREATED) + if (task->state != TASK_ST_CREATED) edie(emu, "cannot execute task %u: state is not created\n", task->id); - if(task->thread != NULL) + if (task->thread != NULL) edie(emu, "task already has a thread assigned\n"); - if(stack->thread->state != TH_ST_RUNNING) + if (stack->thread->state != TH_ST_RUNNING) edie(emu, "thread state is not running\n"); - if(stack->top == task) + if (stack->top == task) edie(emu, "thread already has assigned task %u\n", task->id); - if(stack->top && stack->top->state != TASK_ST_RUNNING) + if (stack->top && stack->top->state != TASK_ST_RUNNING) edie(emu, "cannot execute a nested task from a non-running task\n"); task->state = TASK_ST_RUNNING; @@ -90,24 +90,24 @@ task_execute(struct ovni_emu *emu, void task_pause(struct ovni_emu *emu, - struct task_stack *stack, struct task *task) + struct task_stack *stack, struct task *task) { - if(task == NULL) + if (task == NULL) edie(emu, "cannot pause: task is NULL\n"); - if(task->state != TASK_ST_RUNNING) + if (task->state != TASK_ST_RUNNING) edie(emu, "cannot pause: task state is not running\n"); - if(task->thread == NULL) + if (task->thread == NULL) edie(emu, "cannot pause: task has no thread assigned\n"); - if(stack->thread->state != TH_ST_RUNNING) + if (stack->thread->state != TH_ST_RUNNING) edie(emu, "cannot pause: thread state is not running\n"); - if(stack->top != task) + if (stack->top != task) edie(emu, "thread has assigned a different task\n"); - if(stack->thread != task->thread) + if (stack->thread != task->thread) edie(emu, "task is assigned to a different thread\n"); task->state = TASK_ST_PAUSED; @@ -117,24 +117,24 @@ task_pause(struct ovni_emu *emu, void task_resume(struct ovni_emu *emu, - struct task_stack *stack, struct task *task) + struct task_stack *stack, struct task *task) { - if(task == NULL) + if (task == NULL) edie(emu, "cannot resume: task is NULL\n"); - if(task->state != TASK_ST_PAUSED) + if (task->state != TASK_ST_PAUSED) edie(emu, "task state is not paused\n"); - if(task->thread == NULL) + if (task->thread == NULL) edie(emu, "cannot resume: task has no thread assigned\n"); - if(stack->thread->state != TH_ST_RUNNING) + if (stack->thread->state != TH_ST_RUNNING) edie(emu, "thread is not running\n"); - if(stack->top != task) + if (stack->top != task) edie(emu, "thread has assigned a different task\n"); - if(stack->thread != task->thread) + if (stack->thread != task->thread) edie(emu, "task is assigned to a different thread\n"); task->state = TASK_ST_RUNNING; @@ -144,24 +144,24 @@ task_resume(struct ovni_emu *emu, void task_end(struct ovni_emu *emu, - struct task_stack *stack, struct task *task) + struct task_stack *stack, struct task *task) { - if(task == NULL) + if (task == NULL) edie(emu, "cannot end: task is NULL\n"); - if(task->state != TASK_ST_RUNNING) + if (task->state != TASK_ST_RUNNING) edie(emu, "task state is not running\n"); - if(task->thread == NULL) + if (task->thread == NULL) edie(emu, "cannot end: task has no thread assigned\n"); - if(stack->thread->state != TH_ST_RUNNING) + if (stack->thread->state != TH_ST_RUNNING) edie(emu, "cannot end task: thread is not running\n"); - if(stack->top != task) + if (stack->top != task) edie(emu, "thread has assigned a different task\n"); - if(stack->thread != task->thread) + if (stack->thread != task->thread) edie(emu, "task is assigned to a different thread\n"); task->state = TASK_ST_DEAD; @@ -187,7 +187,7 @@ get_task_type_gid(const char *label) /* Avoid bad colors for "Unlabeled0" */ gid += 123; - if(gid == 0) + if (gid == 0) gid++; return gid; @@ -200,29 +200,29 @@ task_type_create(struct task_info *info, uint32_t type_id, const char *label) /* Ensure the type id is new */ HASH_FIND_INT(info->types, &type_id, type); - if(type != NULL) + if (type != NULL) die("a task type with id %u already exists\n", type_id); type = calloc(1, sizeof(*type)); - if(type == NULL) + if (type == NULL) die("calloc failed"); type->id = type_id; - if(type->id == 0) + if (type->id == 0) die("invalid task type id %d\n", type->id); type->gid = get_task_type_gid(label); int n = snprintf(type->label, MAX_PCF_LABEL, "%s", label); - if(n >= MAX_PCF_LABEL) + if (n >= MAX_PCF_LABEL) die("task type label too long: %s\n", label); /* Add the new task type to the hash table */ HASH_ADD_INT(info->types, id, type); dbg("new task type created id=%d label=%s\n", type->id, - type->label); + type->label); } void @@ -230,14 +230,12 @@ task_create_pcf_types(struct pcf_type *pcftype, struct task_type *types) { /* Emit types for all task types */ struct task_type *tt; - for(tt = types; tt != NULL; tt = tt->hh.next) - { + for (tt = types; tt != NULL; tt = tt->hh.next) { struct pcf_value *pcfvalue = pcf_find_value(pcftype, tt->gid); - if(pcfvalue != NULL) - { + if (pcfvalue != NULL) { /* Ensure the label is the same, so we know that * no collision occurred */ - if(strcmp(pcfvalue->label, tt->label) != 0) + if (strcmp(pcfvalue->label, tt->label) != 0) die("collision occurred in task type labels\n"); else continue; @@ -251,7 +249,7 @@ struct task * task_get_running(struct task_stack *stack) { struct task *task = stack->top; - if(task && task->state == TASK_ST_RUNNING) + if (task && task->state == TASK_ST_RUNNING) return task; return NULL; diff --git a/heap.h b/heap.h index a8c621f..82aa5f7 100644 --- a/heap.h +++ b/heap.h @@ -7,8 +7,8 @@ #ifndef HEAP_H #define HEAP_H -#include #include "common.h" +#include typedef struct heap_node { struct heap_node *parent; @@ -24,15 +24,19 @@ typedef struct head_head { #define heap_elem(head, type, name) \ ((type *) (((char *) head) - offsetof(type, name))) -#define heap_swap(a, b) \ - do { heap_node_t *aux = (a); (a) = (b); (b) = aux; } while(0) +#define heap_swap(a, b) \ + do { \ + heap_node_t *aux = (a); \ + (a) = (b); \ + (b) = aux; \ + } while (0) /* heap_node_compare_t - comparison function. * The comparison function cmp(a, b) shall return an integer: * > 0 if a > b * < 0 if a < b * = 0 if a == b - * + * * Invert the comparison function to get a min-heap instead */ typedef int (*heap_node_compare_t)(heap_node_t *a, heap_node_t *b); @@ -116,7 +120,7 @@ heap_get_move(size_t *node /*out*/) // Round to previous po2 size_t base = (1ULL) << (sizeof(size_t) * 8 - - __builtin_clzll(aux_node) - 1); + - __builtin_clzll(aux_node) - 1); aux_node -= base / 2; @@ -157,7 +161,7 @@ heap_pop_max(heap_head_t *head, heap_node_compare_t cmp) size_t size = head->size; heap_node_t *change = heap_get(head, size); - if(change == NULL) + if (change == NULL) die("heap_pop_max: heap_get() failed\n"); head->size--; @@ -189,10 +193,10 @@ heap_pop_max(heap_head_t *head, heap_node_compare_t cmp) else change->parent->left = NULL; - if(change->left) + if (change->left) die("heap_pop_max: change->left not NULL\n"); - if(change->right) + if (change->right) die("heap_pop_max: change->right not NULL\n"); change->left = max->left; @@ -230,11 +234,11 @@ heap_insert(heap_head_t *head, heap_node_t *node, heap_node_compare_t cmp) // Right child if (head->size % 2) { - if(parent->right) + if (parent->right) die("heap_insert: parent->right already set\n"); parent->right = node; } else { - if(parent->left) + if (parent->left) die("heap_insert: parent->left already set\n"); parent->left = node; } @@ -286,4 +290,4 @@ heap_insert(heap_head_t *head, heap_node_t *node, heap_node_compare_t cmp) head->root = node; } -#endif // HEAP_H +#endif// HEAP_H diff --git a/ovni.c b/ovni.c index b6a7fb1..0fe7a52 100644 --- a/ovni.c +++ b/ovni.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -14,10 +13,10 @@ #include #include -#include "ovni.h" #include "common.h" -#include "parson.h" #include "compat.h" +#include "ovni.h" +#include "parson.h" /* Data per process */ struct ovni_rproc rproc = {0}; @@ -31,15 +30,15 @@ create_trace_stream(void) char path[PATH_MAX]; int written = snprintf(path, PATH_MAX, "%s/thread.%d", - rproc.procdir, rthread.tid); + rproc.procdir, rthread.tid); - if(written >= PATH_MAX) + if (written >= PATH_MAX) die("thread trace path too long: %s/thread.%d\n", - rproc.procdir, rthread.tid); + rproc.procdir, rthread.tid); rthread.streamfd = open(path, O_WRONLY | O_CREAT, 0644); - if(rthread.streamfd == -1) + if (rthread.streamfd == -1) die("open %s failed: %s\n", path, strerror(errno)); } @@ -48,7 +47,7 @@ proc_metadata_init(struct ovni_rproc *proc) { proc->meta = json_value_init_object(); - if(proc->meta == NULL) + if (proc->meta == NULL) die("failed to create metadata JSON object\n"); } @@ -57,35 +56,35 @@ proc_metadata_store(JSON_Value *meta, const char *procdir) { char path[PATH_MAX]; - if(meta == NULL) + if (meta == NULL) die("process metadata not initialized\n"); - if(snprintf(path, PATH_MAX, "%s/metadata.json", procdir) >= PATH_MAX) + if (snprintf(path, PATH_MAX, "%s/metadata.json", procdir) >= PATH_MAX) die("metadata path too long: %s/metadata.json\n", - procdir); + procdir); - if(json_serialize_to_file_pretty(meta, path) != JSONSuccess) + if (json_serialize_to_file_pretty(meta, path) != JSONSuccess) die("failed to write process metadata\n"); } void ovni_add_cpu(int index, int phyid) { - if(index < 0) + if (index < 0) die("ovni_add_cpu: cannot use negative index %d\n", index); - if(phyid < 0) + if (phyid < 0) die("ovni_add_cpu: cannot use negative CPU id %d\n", phyid); - if(!rproc.ready) + if (!rproc.ready) die("ovni_add_cpu: process not yet initialized\n"); - if(rproc.meta == NULL) + if (rproc.meta == NULL) die("ovni_add_cpu: metadata not initialized\n"); JSON_Object *meta = json_value_get_object(rproc.meta); - if(meta == NULL) + if (meta == NULL) die("ovni_add_cpu: json_value_get_object() failed\n"); int first_time = 0; @@ -93,43 +92,41 @@ ovni_add_cpu(int index, int phyid) /* Find the CPU array and create it if needed */ JSON_Array *cpuarray = json_object_dotget_array(meta, "cpus"); - if(cpuarray == NULL) - { + if (cpuarray == NULL) { JSON_Value *value = json_value_init_array(); - if(value == NULL) + if (value == NULL) die("ovni_add_cpu: json_value_init_array() failed\n"); cpuarray = json_array(value); - if(cpuarray == NULL) + if (cpuarray == NULL) die("ovni_add_cpu: json_array() failed\n"); first_time = 1; } JSON_Value *valcpu = json_value_init_object(); - if(valcpu == NULL) + if (valcpu == NULL) die("ovni_add_cpu: json_value_init_object() failed\n"); JSON_Object *cpu = json_object(valcpu); - if(cpu == NULL) + if (cpu == NULL) die("ovni_add_cpu: json_object() failed\n"); - if(json_object_set_number(cpu, "index", index) != 0) + if (json_object_set_number(cpu, "index", index) != 0) die("ovni_add_cpu: json_object_set_number() failed\n"); - if(json_object_set_number(cpu, "phyid", phyid) != 0) + if (json_object_set_number(cpu, "phyid", phyid) != 0) die("ovni_add_cpu: json_object_set_number() failed\n"); - if(json_array_append_value(cpuarray, valcpu) != 0) + if (json_array_append_value(cpuarray, valcpu) != 0) die("ovni_add_cpu: json_array_append_value() failed\n"); - if(first_time) - { + if (first_time) { JSON_Value *value = json_array_get_wrapping_value(cpuarray); - if(value == NULL) + if (value == NULL) die("ovni_add_cpu: json_array_get_wrapping_value() failed\n"); - if(json_object_set_value(meta, "cpus", value) != 0) + if (json_object_set_value(meta, "cpus", value) != 0) die("ovni_add_cpu: json_object_set_value failed\n"); } } @@ -139,10 +136,10 @@ proc_set_app(int appid) { JSON_Object *meta = json_value_get_object(rproc.meta); - if(meta == NULL) + if (meta == NULL) die("json_value_get_object failed\n"); - if(json_object_set_number(meta, "app_id", appid) != 0) + if (json_object_set_number(meta, "app_id", appid) != 0) die("json_object_set_number for app_id failed\n"); } @@ -151,13 +148,13 @@ proc_set_version(void) { JSON_Object *meta = json_value_get_object(rproc.meta); - if(meta == NULL) + if (meta == NULL) die("json_value_get_object failed\n"); - if(json_object_set_number(meta, "version", OVNI_METADATA_VERSION) != 0) + if (json_object_set_number(meta, "version", OVNI_METADATA_VERSION) != 0) die("json_object_set_number for version failed\n"); - if(json_object_set_string(meta, "model_version", OVNI_MODEL_VERSION) != 0) + if (json_object_set_string(meta, "model_version", OVNI_MODEL_VERSION) != 0) die("json_object_set_string for model_version failed\n"); } @@ -165,18 +162,18 @@ proc_set_version(void) void ovni_proc_set_rank(int rank, int nranks) { - if(!rproc.ready) + if (!rproc.ready) die("ovni_proc_set_rank: process not yet initialized\n"); JSON_Object *meta = json_value_get_object(rproc.meta); - if(meta == NULL) + if (meta == NULL) die("json_value_get_object failed\n"); - if(json_object_set_number(meta, "rank", rank) != 0) + if (json_object_set_number(meta, "rank", rank) != 0) die("json_object_set_number for rank failed\n"); - if(json_object_set_number(meta, "nranks", nranks) != 0) + if (json_object_set_number(meta, "nranks", nranks) != 0) die("json_object_set_number for nranks failed\n"); } @@ -197,7 +194,7 @@ mkdir_proc(char *path, const char *tracedir, const char *loom, int pid) snprintf(path, PATH_MAX, "%s/loom.%s/proc.%d", tracedir, loom, pid); /* But this one shall not fail */ - if(mkdir(path, 0755)) + if (mkdir(path, 0755)) die("mkdir %s failed: %s\n", path, strerror(errno)); } @@ -206,14 +203,11 @@ create_proc_dir(const char *loom, int pid) { char *tmpdir = getenv("OVNI_TMPDIR"); - if(tmpdir != NULL) - { + if (tmpdir != NULL) { rproc.move_to_final = 1; mkdir_proc(rproc.procdir, tmpdir, loom, pid); mkdir_proc(rproc.procdir_final, OVNI_TRACEDIR, loom, pid); - } - else - { + } else { rproc.move_to_final = 0; mkdir_proc(rproc.procdir, OVNI_TRACEDIR, loom, pid); } @@ -222,12 +216,12 @@ create_proc_dir(const char *loom, int pid) void ovni_proc_init(int app, const char *loom, int pid) { - if(rproc.ready) + if (rproc.ready) die("ovni_proc_init: pid %d already initialized\n", pid); memset(&rproc, 0, sizeof(rproc)); - if(strlen(loom) >= OVNI_MAX_HOSTNAME) + if (strlen(loom) >= OVNI_MAX_HOSTNAME) die("ovni_proc_init: loom name too long: %s\n", loom); strcpy(rproc.loom, loom); @@ -253,28 +247,25 @@ move_thread_to_final(const char *src, const char *dst) FILE *infile = fopen(src, "r"); - if(infile == NULL) - { + if (infile == NULL) { err("fopen(%s) failed: %s\n", src, strerror(errno)); return -1; } FILE *outfile = fopen(dst, "w"); - if(outfile == NULL) - { + if (outfile == NULL) { err("fopen(%s) failed: %s\n", src, strerror(errno)); return -1; } - while((bytes = fread(buffer, 1, sizeof(buffer), infile)) > 0) + while ((bytes = fread(buffer, 1, sizeof(buffer), infile)) > 0) fwrite(buffer, 1, bytes, outfile); fclose(outfile); fclose(infile); - if(remove(src) != 0) - { + if (remove(src) != 0) { err("remove(%s) failed: %s\n", src, strerror(errno)); return -1; } @@ -291,71 +282,65 @@ move_procdir_to_final(const char *procdir, const char *procdir_final) char thread_final[PATH_MAX]; int err = 0; - if((dir = opendir(procdir)) == NULL) - { + if ((dir = opendir(procdir)) == NULL) { err("opendir %s failed: %s\n", procdir, strerror(errno)); return; } const char *prefix = "thread."; - while((dirent = readdir(dir)) != NULL) - { + while ((dirent = readdir(dir)) != NULL) { /* It should only contain thread.* directories, skip others */ - if(strncmp(dirent->d_name, prefix, strlen(prefix)) != 0) + if (strncmp(dirent->d_name, prefix, strlen(prefix)) != 0) continue; - if(snprintf(thread, PATH_MAX, "%s/%s", procdir, - dirent->d_name) >= PATH_MAX) - { + if (snprintf(thread, PATH_MAX, "%s/%s", procdir, + dirent->d_name) + >= PATH_MAX) { err("snprintf: path too large: %s/%s\n", procdir, - dirent->d_name); + dirent->d_name); err = 1; continue; } - if(snprintf(thread_final, PATH_MAX, "%s/%s", procdir_final, - dirent->d_name) >= PATH_MAX) - { + if (snprintf(thread_final, PATH_MAX, "%s/%s", procdir_final, + dirent->d_name) + >= PATH_MAX) { err("snprintf: path too large: %s/%s\n", procdir_final, - dirent->d_name); + dirent->d_name); err = 1; continue; } - if(move_thread_to_final(thread, thread_final) != 0) + if (move_thread_to_final(thread, thread_final) != 0) err = 1; } closedir(dir); - if(rmdir(procdir) != 0) - { + if (rmdir(procdir) != 0) { err("rmdir(%s) failed: %s\n", procdir, strerror(errno)); err = 1; } /* Warn the user, but we cannot do much at this point */ - if(err) + if (err) err("errors occurred when moving the trace to %s\n", procdir_final); } void ovni_proc_fini(void) { - if(!rproc.ready) + if (!rproc.ready) die("ovni_proc_fini: process not initialized\n"); /* Mark the process no longer ready */ rproc.ready = 0; - if(rproc.move_to_final) - { + if (rproc.move_to_final) { proc_metadata_store(rproc.meta, rproc.procdir_final); move_procdir_to_final(rproc.procdir, rproc.procdir_final); - } - else - { + } else { proc_metadata_store(rproc.meta, rproc.procdir); } } @@ -363,16 +348,15 @@ ovni_proc_fini(void) static void write_evbuf(uint8_t *buf, size_t size) { - do - { + do { ssize_t written = write(rthread.streamfd, buf, size); - if(written < 0) + if (written < 0) die("failed to write buffer to disk: %s\n", strerror(errno)); size -= written; buf += written; - } while(size > 0); + } while (size > 0); } static void @@ -399,16 +383,15 @@ write_stream_header(void) void ovni_thread_init(pid_t tid) { - if(rthread.ready) - { + if (rthread.ready) { err("warning: thread %d already initialized, ignored\n", tid); return; } - if(tid == 0) + if (tid == 0) die("ovni_thread_init: cannot use tid=%d\n", tid); - if(!rproc.ready) + if (!rproc.ready) die("ovni_thread_init: process not yet initialized\n"); memset(&rthread, 0, sizeof(rthread)); @@ -417,7 +400,7 @@ ovni_thread_init(pid_t tid) rthread.evlen = 0; rthread.evbuf = malloc(OVNI_MAX_EV_BUF); - if(rthread.evbuf == NULL) + if (rthread.evbuf == NULL) die("ovni_thread_init: malloc failed: %s", strerror(errno)); create_trace_stream(); @@ -429,7 +412,7 @@ ovni_thread_init(pid_t tid) void ovni_thread_free(void) { - if(!rthread.ready) + if (!rthread.ready) die("ovni_thread_free: thread not initialized\n"); free(rthread.evbuf); @@ -442,13 +425,14 @@ ovni_thread_isready(void) } #ifdef USE_TSC -static inline -uint64_t clock_tsc_now(void) +static inline uint64_t +clock_tsc_now(void) { uint32_t lo, hi; /* RDTSC copies contents of 64-bit TSC into EDX:EAX */ - __asm__ volatile("rdtsc" : "=a" (lo), "=d" (hi)); + __asm__ volatile("rdtsc" + : "=a"(lo), "=d"(hi)); return (uint64_t) hi << 32 | lo; } #endif @@ -459,7 +443,7 @@ clock_monotonic_now(void) uint64_t ns = 1000ULL * 1000ULL * 1000ULL; struct timespec tp; - if(clock_gettime(rproc.clockid, &tp)) + if (clock_gettime(rproc.clockid, &tp)) die("clock_gettime() failed: %s\n", strerror(errno)); return tp.tv_sec * ns + tp.tv_nsec; @@ -506,12 +490,12 @@ ovni_payload_size(const struct ovni_ev *ev) { int size; - if(ev->header.flags & OVNI_EV_JUMBO) + if (ev->header.flags & OVNI_EV_JUMBO) return get_jumbo_payload_size(ev); size = ev->header.flags & 0x0f; - if(size == 0) + if (size == 0) return 0; /* The minimum size is 2 bytes, so we can encode a length of 16 @@ -524,22 +508,22 @@ ovni_payload_size(const struct ovni_ev *ev) void ovni_payload_add(struct ovni_ev *ev, const uint8_t *buf, int size) { - if(ev->header.flags & OVNI_EV_JUMBO) + if (ev->header.flags & OVNI_EV_JUMBO) die("ovni_payload_add: event is marked as jumbo\n"); - if(size < 2) + if (size < 2) die("ovni_payload_add: payload size %d too small\n", size); size_t payload_size = ovni_payload_size(ev); /* Ensure we have room */ - if(payload_size + size > sizeof(ev->payload)) + if (payload_size + size > sizeof(ev->payload)) die("ovni_payload_add: no space left for %d bytes\n", size); memcpy(&ev->payload.u8[payload_size], buf, size); payload_size += size; - ev->header.flags = (ev->header.flags & 0xf0) | ((payload_size-1) & 0x0f); + ev->header.flags = (ev->header.flags & 0xf0) | ((payload_size - 1) & 0x0f); } int @@ -554,12 +538,12 @@ ovni_ev_add(struct ovni_ev *ev); void ovni_flush(void) { - struct ovni_ev pre={0}, post={0}; + struct ovni_ev pre = {0}, post = {0}; - if(!rthread.ready) + if (!rthread.ready) die("ovni_flush: thread is not initialized\n"); - if(!rproc.ready) + if (!rproc.ready) die("ovni_flush: process is not initialized\n"); ovni_ev_set_clock(&pre, ovni_clock_now()); @@ -578,7 +562,7 @@ ovni_flush(void) static void add_flush_events(uint64_t t0, uint64_t t1) { - struct ovni_ev pre={0}, post={0}; + struct ovni_ev pre = {0}, post = {0}; pre.header.clock = t0; ovni_ev_set_mcv(&pre, "OF["); @@ -597,7 +581,7 @@ ovni_ev_add_jumbo(struct ovni_ev *ev, const uint8_t *buf, uint32_t bufsize) int flushed = 0; uint64_t t0, t1; - if(ovni_payload_size(ev) != 0) + if (ovni_payload_size(ev) != 0) die("ovni_ev_add_jumbo: the event payload must be empty\n"); ovni_payload_add(ev, (uint8_t *) &bufsize, sizeof(bufsize)); @@ -605,12 +589,11 @@ ovni_ev_add_jumbo(struct ovni_ev *ev, const uint8_t *buf, uint32_t bufsize) size_t totalsize = evsize + bufsize; - if(totalsize >= OVNI_MAX_EV_BUF) + if (totalsize >= OVNI_MAX_EV_BUF) die("ovni_ev_add_jumbo: event too large\n"); /* Check if the event fits or flush first otherwise */ - if(rthread.evlen + totalsize >= OVNI_MAX_EV_BUF) - { + if (rthread.evlen + totalsize >= OVNI_MAX_EV_BUF) { /* Measure the flush times */ t0 = ovni_clock_now(); flush_evbuf(); @@ -627,8 +610,7 @@ ovni_ev_add_jumbo(struct ovni_ev *ev, const uint8_t *buf, uint32_t bufsize) memcpy(&rthread.evbuf[rthread.evlen], buf, bufsize); rthread.evlen += bufsize; - if(flushed) - { + if (flushed) { /* Emit the flush events *after* the user event */ add_flush_events(t0, t1); } @@ -643,8 +625,7 @@ ovni_ev_add(struct ovni_ev *ev) int size = ovni_ev_size(ev); /* Check if the event fits or flush first otherwise */ - if(rthread.evlen + size >= OVNI_MAX_EV_BUF) - { + if (rthread.evlen + size >= OVNI_MAX_EV_BUF) { /* Measure the flush times */ t0 = ovni_clock_now(); flush_evbuf(); @@ -655,8 +636,7 @@ ovni_ev_add(struct ovni_ev *ev) memcpy(&rthread.evbuf[rthread.evlen], ev, size); rthread.evlen += size; - if(flushed) - { + if (flushed) { /* Emit the flush events *after* the user event */ add_flush_events(t0, t1); } diff --git a/ovni.h b/ovni.h index c28da86..739ce96 100644 --- a/ovni.h +++ b/ovni.h @@ -8,16 +8,16 @@ extern "C" { #endif -#include +#include +#include #include +#include #include #include -#include #include -#include /* Hardcode the JSON_Value to avoid a dependency with janson */ -typedef struct json_value_t JSON_Value; +typedef struct json_value_t JSON_Value; #define OVNI_METADATA_VERSION 1 @@ -43,7 +43,6 @@ struct __attribute__((__packed__)) ovni_jumbo_payload { }; union __attribute__((__packed__)) ovni_ev_payload { - int8_t i8[16]; int16_t i16[8]; int32_t i32[4]; diff --git a/ovni2prv.c b/ovni2prv.c index bfa044f..4c66c9d 100644 --- a/ovni2prv.c +++ b/ovni2prv.c @@ -1,15 +1,15 @@ /* Copyright (c) 2021 Barcelona Supercomputing Center (BSC) * SPDX-License-Identifier: GPL-3.0-or-later */ -#include +#include +#include +#include +#include #include +#include #include #include -#include -#include #include -#include -#include #include "ovni.h" #include "trace.h" @@ -20,19 +20,19 @@ emit(struct ovni_ev *ev, int row) static uint64_t firstclock = 0; int64_t delta; - if(firstclock == 0) + if (firstclock == 0) firstclock = ovni_ev_get_clock(ev); delta = ovni_ev_get_clock(ev) - firstclock; //#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(00000000000000000008:1) - //2:0:1:1:7:1540663:6400010:1 - //2:0:1:1:7:1540663:6400015:1 - //2:0:1:1:7:1540663:6400017:0 - //2:0:1:1:7:1542091:6400010:1 - //2:0:1:1:7:1542091:6400015:1 - //2:0:1:1:7:1542091:6400025:1 - //2:0:1:1:7:1542091:6400017:0 + // 2:0:1:1:7:1540663:6400010:1 + // 2:0:1:1:7:1540663:6400015:1 + // 2:0:1:1:7:1540663:6400017:0 + // 2:0:1:1:7:1542091:6400010:1 + // 2:0:1:1:7:1542091:6400015:1 + // 2:0:1:1:7:1542091:6400025:1 + // 2:0:1:1:7:1542091:6400017:0 printf("2:0:1:1:%d:%ld:%d:%d\n", row, delta, ev->header.category, ev->header.value); } @@ -47,44 +47,39 @@ dump_events(struct ovni_trace *trace) struct ovni_stream *stream; /* Load events */ - for(i=0; instreams; i++) - { + for (i = 0; i < trace->nstreams; i++) { stream = &trace->stream[i]; ovni_load_next_event(stream); } lastclock = 0; - while(1) - { + while (1) { f = -1; minclock = 0; /* Select next event based on the clock */ - for(i=0; instreams; i++) - { + for (i = 0; i < trace->nstreams; i++) { stream = &trace->stream[i]; - if(!stream->active) + if (!stream->active) continue; ev = stream->cur_ev; - if(f < 0 || ovni_ev_get_clock(ev) < minclock) - { + if (f < 0 || ovni_ev_get_clock(ev) < minclock) { f = i; minclock = ovni_ev_get_clock(ev); } } - //fprintf(stderr, "f=%d minclock=%u\n", f, minclock); + // fprintf(stderr, "f=%d minclock=%u\n", f, minclock); - if(f < 0) + if (f < 0) break; stream = &trace->stream[f]; - if(lastclock >= ovni_ev_get_clock(stream->cur_ev)) - { + if (lastclock >= ovni_ev_get_clock(stream->cur_ev)) { fprintf(stderr, "warning: backwards jump in time\n"); } @@ -100,37 +95,35 @@ dump_events(struct ovni_trace *trace) /* Unset the index */ f = -1; minclock = 0; - } } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { char *tracedir; struct ovni_trace *trace = calloc(1, sizeof(struct ovni_trace)); - if(trace == NULL) - { + if (trace == NULL) { perror("calloc"); exit(EXIT_FAILURE); } - if(argc != 2) - { + if (argc != 2) { fprintf(stderr, "missing tracedir\n"); exit(EXIT_FAILURE); } tracedir = argv[1]; - if(ovni_load_trace(trace, tracedir)) + if (ovni_load_trace(trace, tracedir)) return 1; - if(ovni_load_streams(trace)) + if (ovni_load_streams(trace)) return 1; printf("#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(%ld:1)\n", - trace->nstreams); + trace->nstreams); dump_events(trace); diff --git a/ovnisync.c b/ovnisync.c index a06dc10..056b778 100644 --- a/ovnisync.c +++ b/ovnisync.c @@ -60,18 +60,15 @@ static double get_time(clockid_t clock, int use_ns) { struct timespec tv; - if(clock_gettime(clock, &tv) != 0) - { + if (clock_gettime(clock, &tv) != 0) { perror("clock_gettime failed"); exit(EXIT_FAILURE); } - if(use_ns) - return (double)(tv.tv_sec) * 1.0e9 + - (double)tv.tv_nsec; + if (use_ns) + return (double) (tv.tv_sec) * 1.0e9 + (double) tv.tv_nsec; - return (double)(tv.tv_sec) + - (double)tv.tv_nsec * 1.0e-9; + return (double) (tv.tv_sec) + (double) tv.tv_nsec * 1.0e-9; } static int @@ -82,9 +79,9 @@ cmp_double(const void *pa, const void *pb) a = *(const double *) pa; b = *(const double *) pb; - if(a < b) + if (a < b) return -1; - else if(a > b) + else if (a > b) return 1; else return 0; @@ -96,7 +93,7 @@ usage(void) fprintf(stderr, "%s: clock synchronization utility\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "Usage: %s [-o outfile] [-d ndrift_samples] [-v] [-n nsamples] [-w drift_delay]\n", - progname); + progname); exit(EXIT_FAILURE); } @@ -105,13 +102,10 @@ try_mkdir(const char *path, mode_t mode) { struct stat st; - if(stat(path, &st) != 0) - { + if (stat(path, &st) != 0) { /* Directory does not exist */ return mkdir(path, mode); - } - else if(!S_ISDIR(st.st_mode)) - { + } else if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; return -1; } @@ -183,8 +177,7 @@ parse_options(struct options *options, int argc, char *argv[]) } } - if (optind < argc) - { + if (optind < argc) { fprintf(stderr, "error: unexpected extra arguments\n"); exit(EXIT_FAILURE); } @@ -200,8 +193,7 @@ get_clock_samples(struct offset *offset, int nsamples) offset->nsamples = nsamples; - for(i=0; iclock_sample[i] = get_time(CLOCK_MONOTONIC, 1); } @@ -218,13 +210,12 @@ fill_offset(struct offset *offset, int nsamples) MPI_Comm_rank(MPI_COMM_WORLD, &offset->rank); /* Fill the host name */ - if(gethostname(offset->hostname, OVNI_MAX_HOSTNAME) != 0) - { + if (gethostname(offset->hostname, OVNI_MAX_HOSTNAME) != 0) { perror("gethostname"); exit(EXIT_FAILURE); } - //printf("rank=%d hostname=%s\n", offset->rank, offset->hostname); + // printf("rank=%d hostname=%s\n", offset->rank, offset->hostname); /* Warm up iterations */ warmup_nsamples = nsamples >= 20 ? 20 : nsamples; @@ -241,21 +232,18 @@ offset_compute_delta(struct offset *ref, struct offset *cur, int nsamples, int v delta = malloc(sizeof(double) * nsamples); - if(delta == NULL) - { + if (delta == NULL) { perror("malloc"); exit(EXIT_FAILURE); } - for(i=0; iclock_sample[i] - cur->clock_sample[i]; - if(verbose) - { + if (verbose) { printf("rank=%d sample=%d delta=%f ref=%f cur=%f\n", - cur->rank, i, delta[i], - ref->clock_sample[i], - cur->clock_sample[i]); + cur->rank, i, delta[i], + ref->clock_sample[i], + cur->clock_sample[i]); } } @@ -263,14 +251,13 @@ offset_compute_delta(struct offset *ref, struct offset *cur, int nsamples, int v cur->delta_median = delta[nsamples / 2]; - for(cur->delta_mean=0, i=0; idelta_mean = 0, i = 0; i < nsamples; i++) cur->delta_mean += delta[i]; cur->delta_mean /= nsamples; - for(cur->delta_var=0, i=0; idelta_var += (delta[i] - cur->delta_mean) * - (delta[i] - cur->delta_mean); + for (cur->delta_var = 0, i = 0; i < nsamples; i++) + cur->delta_var += (delta[i] - cur->delta_mean) * (delta[i] - cur->delta_mean); cur->delta_var /= (double) (nsamples - 1); cur->delta_std = sqrt(cur->delta_var); @@ -307,12 +294,10 @@ build_offset_table(int nsamples, int rank, int verbose) void *sendbuf; /* The rank 0 must build the table */ - if(rank == 0) - { + if (rank == 0) { table = malloc(sizeof(*table)); - if(table == NULL) - { + if (table == NULL) { perror("malloc"); exit(EXIT_FAILURE); } @@ -321,33 +306,27 @@ build_offset_table(int nsamples, int rank, int verbose) table->_offset = calloc(table->nprocs, offset_size(nsamples)); - if(table->_offset == NULL) - { + if (table->_offset == NULL) { perror("malloc"); exit(EXIT_FAILURE); } - table->offset = malloc(sizeof(struct offset *) * - table->nprocs); + table->offset = malloc(sizeof(struct offset *) * table->nprocs); - if(table->offset == NULL) - { + if (table->offset == NULL) { perror("malloc"); exit(EXIT_FAILURE); } - for(i=0; inprocs; i++) + for (i = 0; i < table->nprocs; i++) table->offset[i] = table_get_offset(table, i, nsamples); offset = table->offset[0]; - } - else - { + } else { /* Otherwise just allocate one offset */ offset = calloc(1, offset_size(nsamples)); - if(offset == NULL) - { + if (offset == NULL) { perror("malloc"); exit(EXIT_FAILURE); } @@ -362,21 +341,19 @@ build_offset_table(int nsamples, int rank, int verbose) /* Then collect all the offsets into the rank 0 */ MPI_Gather(sendbuf, offset_size(nsamples), MPI_CHAR, - offset, offset_size(nsamples), MPI_CHAR, - 0, MPI_COMM_WORLD); + offset, offset_size(nsamples), MPI_CHAR, + 0, MPI_COMM_WORLD); /* Finish the offsets by computing the deltas on rank 0 */ - if(rank == 0) - { - for(i=0; inprocs; i++) - { + if (rank == 0) { + for (i = 0; i < table->nprocs; i++) { offset_compute_delta(offset, table->offset[i], - nsamples, verbose); + nsamples, verbose); } } /* Cleanup for non-zero ranks */ - if(rank != 0) + if (rank != 0) free(offset); return table; @@ -386,13 +363,12 @@ static void print_drift_header(FILE *out, struct offset_table *table) { int i; - //char buf[64]; + // char buf[64]; fprintf(out, "%-20s", "wallclock"); - for(i=0; inprocs; i++) - { - //sprintf(buf, "rank%d", i); + for (i = 0; i < table->nprocs; i++) { + // sprintf(buf, "rank%d", i); fprintf(out, " %-20s", table->offset[i]->hostname); } @@ -406,7 +382,7 @@ print_drift_row(FILE *out, struct offset_table *table) fprintf(out, "%-20f", table->offset[0]->wall_t1); - for(i=0; inprocs; i++) + for (i = 0; i < table->nprocs; i++) fprintf(out, " %-20ld", table->offset[i]->offset); fprintf(out, "\n"); @@ -419,14 +395,13 @@ print_table_detailed(FILE *out, struct offset_table *table) struct offset *offset; fprintf(out, "%-10s %-20s %-20s %-20s %-20s\n", - "rank", "hostname", "offset_median", "offset_mean", "offset_std"); + "rank", "hostname", "offset_median", "offset_mean", "offset_std"); - for(i=0; inprocs; i++) - { + for (i = 0; i < table->nprocs; i++) { offset = table->offset[i]; fprintf(out, "%-10d %-20s %-20ld %-20f %-20f\n", - i, offset->hostname, offset->offset, - offset->delta_mean, offset->delta_std); + i, offset->hostname, offset->offset, + offset->delta_mean, offset->delta_std); } } @@ -440,39 +415,31 @@ do_work(struct options *options, int rank) drift_mode = options->ndrift_samples > 1 ? 1 : 0; - if(rank == 0) - { - if(mkpath(options->outpath, 0755) != 0) - { + if (rank == 0) { + if (mkpath(options->outpath, 0755) != 0) { fprintf(stderr, "mkpath(%s) failed: %s\n", - options->outpath, strerror(errno)); + options->outpath, strerror(errno)); exit(EXIT_FAILURE); } out = fopen(options->outpath, "w"); - if(out == NULL) - { + if (out == NULL) { fprintf(stderr, "fopen(%s) failed: %s\n", - options->outpath, strerror(errno)); + options->outpath, strerror(errno)); exit(EXIT_FAILURE); } } - for(i=0; indrift_samples; i++) - { + for (i = 0; i < options->ndrift_samples; i++) { table = build_offset_table(options->nsamples, rank, options->verbose); - if(rank == 0) - { - if(drift_mode) - { - if(i == 0) + if (rank == 0) { + if (drift_mode) { + if (i == 0) print_drift_header(out, table); print_drift_row(out, table); - } - else - { + } else { print_table_detailed(out, table); } @@ -481,11 +448,11 @@ do_work(struct options *options, int rank) free(table); } - if(drift_mode) + if (drift_mode) sleep(options->drift_wait); } - if(rank == 0) + if (rank == 0) fclose(out); } diff --git a/parson.c b/parson.c index 65a0e8b..8f4e6ee 100644 --- a/parson.c +++ b/parson.c @@ -30,27 +30,30 @@ #include "parson.h" +#include +#include +#include #include #include #include -#include -#include -#include /* Apparently sscanf is not implemented in some "standard" libraries, so don't use it, if you * don't have to. */ #define sscanf THINK_TWICE_ABOUT_USING_SSCANF #define STARTING_CAPACITY 16 -#define MAX_NESTING 2048 +#define MAX_NESTING 2048 #define FLOAT_FORMAT "%1.17g" /* do not increase precision without incresing NUM_BUF_SIZE */ -#define NUM_BUF_SIZE 64 /* double printed with "%1.17g" shouldn't be longer than 25 bytes so let's be paranoid and use 64 */ +#define NUM_BUF_SIZE 64 /* double printed with "%1.17g" shouldn't be longer than 25 bytes so let's be paranoid and use 64 */ -#define SIZEOF_TOKEN(a) (sizeof(a) - 1) -#define SKIP_CHAR(str) ((*str)++) -#define SKIP_WHITESPACES(str) while (isspace((unsigned char)(**str))) { SKIP_CHAR(str); } -#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define SIZEOF_TOKEN(a) (sizeof(a) - 1) +#define SKIP_CHAR(str) ((*str)++) +#define SKIP_WHITESPACES(str) \ + while (isspace((unsigned char) (**str))) { \ + SKIP_CHAR(str); \ + } +#define MAX(a, b) ((a) > (b) ? (a) : (b)) #undef malloc #undef free @@ -58,7 +61,7 @@ #if defined(isnan) && defined(isinf) #define IS_NUMBER_INVALID(x) (isnan((x)) || isinf((x))) #else -#define IS_NUMBER_INVALID(x) (((x) * 0.0) != 0.0) +#define IS_NUMBER_INVALID(x) (((x) *0.0) != 0.0) #endif static JSON_Malloc_Function parson_malloc = malloc; @@ -66,2114 +69,2499 @@ static JSON_Free_Function parson_free = free; static int parson_escape_slashes = 1; -#define IS_CONT(b) (((unsigned char)(b) & 0xC0) == 0x80) /* is utf-8 continuation byte */ +#define IS_CONT(b) (((unsigned char) (b) &0xC0) == 0x80) /* is utf-8 continuation byte */ typedef struct json_string { - char *chars; - size_t length; + char *chars; + size_t length; } JSON_String; /* Type definitions */ typedef union json_value_value { - JSON_String string; - double number; - JSON_Object *object; - JSON_Array *array; - int boolean; - int null; + JSON_String string; + double number; + JSON_Object *object; + JSON_Array *array; + int boolean; + int null; } JSON_Value_Value; struct json_value_t { - JSON_Value *parent; - JSON_Value_Type type; - JSON_Value_Value value; + JSON_Value *parent; + JSON_Value_Type type; + JSON_Value_Value value; }; struct json_object_t { - JSON_Value *wrapping_value; - char **names; - JSON_Value **values; - size_t count; - size_t capacity; + JSON_Value *wrapping_value; + char **names; + JSON_Value **values; + size_t count; + size_t capacity; }; struct json_array_t { - JSON_Value *wrapping_value; - JSON_Value **items; - size_t count; - size_t capacity; + JSON_Value *wrapping_value; + JSON_Value **items; + size_t count; + size_t capacity; }; /* Various */ -static char * read_file(const char *filename); -static void remove_comments(char *string, const char *start_token, const char *end_token); -static char * parson_strndup(const char *string, size_t n); -static char * parson_strdup(const char *string); -static int hex_char_to_int(char c); -static int parse_utf16_hex(const char *string, unsigned int *result); -static int num_bytes_in_utf8_sequence(unsigned char c); -static int verify_utf8_sequence(const unsigned char *string, int *len); -static int is_valid_utf8(const char *string, size_t string_len); -static int is_decimal(const char *string, size_t length); +static char *read_file(const char *filename); +static void remove_comments(char *string, const char *start_token, const char *end_token); +static char *parson_strndup(const char *string, size_t n); +static char *parson_strdup(const char *string); +static int hex_char_to_int(char c); +static int parse_utf16_hex(const char *string, unsigned int *result); +static int num_bytes_in_utf8_sequence(unsigned char c); +static int verify_utf8_sequence(const unsigned char *string, int *len); +static int is_valid_utf8(const char *string, size_t string_len); +static int is_decimal(const char *string, size_t length); /* JSON Object */ -static JSON_Object * json_object_init(JSON_Value *wrapping_value); -static JSON_Status json_object_add(JSON_Object *object, const char *name, JSON_Value *value); -static JSON_Status json_object_addn(JSON_Object *object, const char *name, size_t name_len, JSON_Value *value); -static JSON_Status json_object_resize(JSON_Object *object, size_t new_capacity); -static JSON_Value * json_object_getn_value(const JSON_Object *object, const char *name, size_t name_len); -static JSON_Status json_object_remove_internal(JSON_Object *object, const char *name, int free_value); -static JSON_Status json_object_dotremove_internal(JSON_Object *object, const char *name, int free_value); -static void json_object_free(JSON_Object *object); +static JSON_Object *json_object_init(JSON_Value *wrapping_value); +static JSON_Status json_object_add(JSON_Object *object, const char *name, JSON_Value *value); +static JSON_Status json_object_addn(JSON_Object *object, const char *name, size_t name_len, JSON_Value *value); +static JSON_Status json_object_resize(JSON_Object *object, size_t new_capacity); +static JSON_Value *json_object_getn_value(const JSON_Object *object, const char *name, size_t name_len); +static JSON_Status json_object_remove_internal(JSON_Object *object, const char *name, int free_value); +static JSON_Status json_object_dotremove_internal(JSON_Object *object, const char *name, int free_value); +static void json_object_free(JSON_Object *object); /* JSON Array */ -static JSON_Array * json_array_init(JSON_Value *wrapping_value); -static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value); -static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity); -static void json_array_free(JSON_Array *array); +static JSON_Array *json_array_init(JSON_Value *wrapping_value); +static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value); +static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity); +static void json_array_free(JSON_Array *array); /* JSON Value */ -static JSON_Value * json_value_init_string_no_copy(char *string, size_t length); -static const JSON_String * json_value_get_string_desc(const JSON_Value *value); +static JSON_Value *json_value_init_string_no_copy(char *string, size_t length); +static const JSON_String *json_value_get_string_desc(const JSON_Value *value); /* Parser */ -static JSON_Status skip_quotes(const char **string); -static int parse_utf16(const char **unprocessed, char **processed); -static char * process_string(const char *input, size_t input_len, size_t *output_len); -static char * get_quoted_string(const char **string, size_t *output_string_len); -static JSON_Value * parse_object_value(const char **string, size_t nesting); -static JSON_Value * parse_array_value(const char **string, size_t nesting); -static JSON_Value * parse_string_value(const char **string); -static JSON_Value * parse_boolean_value(const char **string); -static JSON_Value * parse_number_value(const char **string); -static JSON_Value * parse_null_value(const char **string); -static JSON_Value * parse_value(const char **string, size_t nesting); +static JSON_Status skip_quotes(const char **string); +static int parse_utf16(const char **unprocessed, char **processed); +static char *process_string(const char *input, size_t input_len, size_t *output_len); +static char *get_quoted_string(const char **string, size_t *output_string_len); +static JSON_Value *parse_object_value(const char **string, size_t nesting); +static JSON_Value *parse_array_value(const char **string, size_t nesting); +static JSON_Value *parse_string_value(const char **string); +static JSON_Value *parse_boolean_value(const char **string); +static JSON_Value *parse_number_value(const char **string); +static JSON_Value *parse_null_value(const char **string); +static JSON_Value *parse_value(const char **string, size_t nesting); /* Serialization */ -static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf); -static int json_serialize_string(const char *string, size_t len, char *buf); -static int append_indent(char *buf, int level); -static int append_string(char *buf, const char *string); +static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf); +static int json_serialize_string(const char *string, size_t len, char *buf); +static int append_indent(char *buf, int level); +static int append_string(char *buf, const char *string); /* Various */ -static char * parson_strndup(const char *string, size_t n) { - /* We expect the caller has validated that 'n' fits within the input buffer. */ - char *output_string = (char*)parson_malloc(n + 1); - if (!output_string) { - return NULL; - } - output_string[n] = '\0'; - memcpy(output_string, string, n); - return output_string; +static char * +parson_strndup(const char *string, size_t n) +{ + /* We expect the caller has validated that 'n' fits within the input buffer. */ + char *output_string = (char *) parson_malloc(n + 1); + if (!output_string) { + return NULL; + } + output_string[n] = '\0'; + memcpy(output_string, string, n); + return output_string; } -static char * parson_strdup(const char *string) { - return parson_strndup(string, strlen(string)); +static char * +parson_strdup(const char *string) +{ + return parson_strndup(string, strlen(string)); } -static int hex_char_to_int(char c) { - if (c >= '0' && c <= '9') { - return c - '0'; - } else if (c >= 'a' && c <= 'f') { - return c - 'a' + 10; - } else if (c >= 'A' && c <= 'F') { - return c - 'A' + 10; - } - return -1; +static int +hex_char_to_int(char c) +{ + if (c >= '0' && c <= '9') { + return c - '0'; + } else if (c >= 'a' && c <= 'f') { + return c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + return c - 'A' + 10; + } + return -1; } -static int parse_utf16_hex(const char *s, unsigned int *result) { - int x1, x2, x3, x4; - if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0' || s[3] == '\0') { - return 0; - } - x1 = hex_char_to_int(s[0]); - x2 = hex_char_to_int(s[1]); - x3 = hex_char_to_int(s[2]); - x4 = hex_char_to_int(s[3]); - if (x1 == -1 || x2 == -1 || x3 == -1 || x4 == -1) { - return 0; - } - *result = (unsigned int)((x1 << 12) | (x2 << 8) | (x3 << 4) | x4); - return 1; +static int +parse_utf16_hex(const char *s, unsigned int *result) +{ + int x1, x2, x3, x4; + if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0' || s[3] == '\0') { + return 0; + } + x1 = hex_char_to_int(s[0]); + x2 = hex_char_to_int(s[1]); + x3 = hex_char_to_int(s[2]); + x4 = hex_char_to_int(s[3]); + if (x1 == -1 || x2 == -1 || x3 == -1 || x4 == -1) { + return 0; + } + *result = (unsigned int) ((x1 << 12) | (x2 << 8) | (x3 << 4) | x4); + return 1; } -static int num_bytes_in_utf8_sequence(unsigned char c) { - if (c == 0xC0 || c == 0xC1 || c > 0xF4 || IS_CONT(c)) { - return 0; - } else if ((c & 0x80) == 0) { /* 0xxxxxxx */ - return 1; - } else if ((c & 0xE0) == 0xC0) { /* 110xxxxx */ - return 2; - } else if ((c & 0xF0) == 0xE0) { /* 1110xxxx */ - return 3; - } else if ((c & 0xF8) == 0xF0) { /* 11110xxx */ - return 4; - } - return 0; /* won't happen */ +static int +num_bytes_in_utf8_sequence(unsigned char c) +{ + if (c == 0xC0 || c == 0xC1 || c > 0xF4 || IS_CONT(c)) { + return 0; + } else if ((c & 0x80) == 0) { /* 0xxxxxxx */ + return 1; + } else if ((c & 0xE0) == 0xC0) { /* 110xxxxx */ + return 2; + } else if ((c & 0xF0) == 0xE0) { /* 1110xxxx */ + return 3; + } else if ((c & 0xF8) == 0xF0) { /* 11110xxx */ + return 4; + } + return 0; /* won't happen */ } -static int verify_utf8_sequence(const unsigned char *string, int *len) { - unsigned int cp = 0; - *len = num_bytes_in_utf8_sequence(string[0]); +static int +verify_utf8_sequence(const unsigned char *string, int *len) +{ + unsigned int cp = 0; + *len = num_bytes_in_utf8_sequence(string[0]); - if (*len == 1) { - cp = string[0]; - } else if (*len == 2 && IS_CONT(string[1])) { - cp = string[0] & 0x1F; - cp = (cp << 6) | (string[1] & 0x3F); - } else if (*len == 3 && IS_CONT(string[1]) && IS_CONT(string[2])) { - cp = ((unsigned char)string[0]) & 0xF; - cp = (cp << 6) | (string[1] & 0x3F); - cp = (cp << 6) | (string[2] & 0x3F); - } else if (*len == 4 && IS_CONT(string[1]) && IS_CONT(string[2]) && IS_CONT(string[3])) { - cp = string[0] & 0x7; - cp = (cp << 6) | (string[1] & 0x3F); - cp = (cp << 6) | (string[2] & 0x3F); - cp = (cp << 6) | (string[3] & 0x3F); - } else { - return 0; - } + if (*len == 1) { + cp = string[0]; + } else if (*len == 2 && IS_CONT(string[1])) { + cp = string[0] & 0x1F; + cp = (cp << 6) | (string[1] & 0x3F); + } else if (*len == 3 && IS_CONT(string[1]) && IS_CONT(string[2])) { + cp = ((unsigned char) string[0]) & 0xF; + cp = (cp << 6) | (string[1] & 0x3F); + cp = (cp << 6) | (string[2] & 0x3F); + } else if (*len == 4 && IS_CONT(string[1]) && IS_CONT(string[2]) && IS_CONT(string[3])) { + cp = string[0] & 0x7; + cp = (cp << 6) | (string[1] & 0x3F); + cp = (cp << 6) | (string[2] & 0x3F); + cp = (cp << 6) | (string[3] & 0x3F); + } else { + return 0; + } - /* overlong encodings */ - if ((cp < 0x80 && *len > 1) || - (cp < 0x800 && *len > 2) || - (cp < 0x10000 && *len > 3)) { - return 0; - } + /* overlong encodings */ + if ((cp < 0x80 && *len > 1) || (cp < 0x800 && *len > 2) || (cp < 0x10000 && *len > 3)) { + return 0; + } - /* invalid unicode */ - if (cp > 0x10FFFF) { - return 0; - } + /* invalid unicode */ + if (cp > 0x10FFFF) { + return 0; + } - /* surrogate halves */ - if (cp >= 0xD800 && cp <= 0xDFFF) { - return 0; - } + /* surrogate halves */ + if (cp >= 0xD800 && cp <= 0xDFFF) { + return 0; + } - return 1; + return 1; } -static int is_valid_utf8(const char *string, size_t string_len) { - int len = 0; - const char *string_end = string + string_len; - while (string < string_end) { - if (!verify_utf8_sequence((const unsigned char*)string, &len)) { - return 0; - } - string += len; - } - return 1; +static int +is_valid_utf8(const char *string, size_t string_len) +{ + int len = 0; + const char *string_end = string + string_len; + while (string < string_end) { + if (!verify_utf8_sequence((const unsigned char *) string, &len)) { + return 0; + } + string += len; + } + return 1; } -static int is_decimal(const char *string, size_t length) { - if (length > 1 && string[0] == '0' && string[1] != '.') { - return 0; - } - if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.') { - return 0; - } - while (length--) { - if (strchr("xX", string[length])) { - return 0; - } - } - return 1; +static int +is_decimal(const char *string, size_t length) +{ + if (length > 1 && string[0] == '0' && string[1] != '.') { + return 0; + } + if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.') { + return 0; + } + while (length--) { + if (strchr("xX", string[length])) { + return 0; + } + } + return 1; } -static char * read_file(const char * filename) { - FILE *fp = fopen(filename, "r"); - size_t size_to_read = 0; - size_t size_read = 0; - long pos; - char *file_contents; - if (!fp) { - return NULL; - } - fseek(fp, 0L, SEEK_END); - pos = ftell(fp); - if (pos < 0) { - fclose(fp); - return NULL; - } - size_to_read = pos; - rewind(fp); - file_contents = (char*)parson_malloc(sizeof(char) * (size_to_read + 1)); - if (!file_contents) { - fclose(fp); - return NULL; - } - size_read = fread(file_contents, 1, size_to_read, fp); - if (size_read == 0 || ferror(fp)) { - fclose(fp); - parson_free(file_contents); - return NULL; - } - fclose(fp); - file_contents[size_read] = '\0'; - return file_contents; +static char * +read_file(const char *filename) +{ + FILE *fp = fopen(filename, "r"); + size_t size_to_read = 0; + size_t size_read = 0; + long pos; + char *file_contents; + if (!fp) { + return NULL; + } + fseek(fp, 0L, SEEK_END); + pos = ftell(fp); + if (pos < 0) { + fclose(fp); + return NULL; + } + size_to_read = pos; + rewind(fp); + file_contents = (char *) parson_malloc(sizeof(char) * (size_to_read + 1)); + if (!file_contents) { + fclose(fp); + return NULL; + } + size_read = fread(file_contents, 1, size_to_read, fp); + if (size_read == 0 || ferror(fp)) { + fclose(fp); + parson_free(file_contents); + return NULL; + } + fclose(fp); + file_contents[size_read] = '\0'; + return file_contents; } -static void remove_comments(char *string, const char *start_token, const char *end_token) { - int in_string = 0, escaped = 0; - size_t i; - char *ptr = NULL, current_char; - size_t start_token_len = strlen(start_token); - size_t end_token_len = strlen(end_token); - if (start_token_len == 0 || end_token_len == 0) { - return; - } - while ((current_char = *string) != '\0') { - if (current_char == '\\' && !escaped) { - escaped = 1; - string++; - continue; - } else if (current_char == '\"' && !escaped) { - in_string = !in_string; - } else if (!in_string && strncmp(string, start_token, start_token_len) == 0) { - for(i = 0; i < start_token_len; i++) { - string[i] = ' '; - } - string = string + start_token_len; - ptr = strstr(string, end_token); - if (!ptr) { - return; - } - for (i = 0; i < (ptr - string) + end_token_len; i++) { - string[i] = ' '; - } - string = ptr + end_token_len - 1; - } - escaped = 0; - string++; - } +static void +remove_comments(char *string, const char *start_token, const char *end_token) +{ + int in_string = 0, escaped = 0; + size_t i; + char *ptr = NULL, current_char; + size_t start_token_len = strlen(start_token); + size_t end_token_len = strlen(end_token); + if (start_token_len == 0 || end_token_len == 0) { + return; + } + while ((current_char = *string) != '\0') { + if (current_char == '\\' && !escaped) { + escaped = 1; + string++; + continue; + } else if (current_char == '\"' && !escaped) { + in_string = !in_string; + } else if (!in_string && strncmp(string, start_token, start_token_len) == 0) { + for (i = 0; i < start_token_len; i++) { + string[i] = ' '; + } + string = string + start_token_len; + ptr = strstr(string, end_token); + if (!ptr) { + return; + } + for (i = 0; i < (ptr - string) + end_token_len; i++) { + string[i] = ' '; + } + string = ptr + end_token_len - 1; + } + escaped = 0; + string++; + } } /* JSON Object */ -static JSON_Object * json_object_init(JSON_Value *wrapping_value) { - JSON_Object *new_obj = (JSON_Object*)parson_malloc(sizeof(JSON_Object)); - if (new_obj == NULL) { - return NULL; - } - new_obj->wrapping_value = wrapping_value; - new_obj->names = (char**)NULL; - new_obj->values = (JSON_Value**)NULL; - new_obj->capacity = 0; - new_obj->count = 0; - return new_obj; +static JSON_Object * +json_object_init(JSON_Value *wrapping_value) +{ + JSON_Object *new_obj = (JSON_Object *) parson_malloc(sizeof(JSON_Object)); + if (new_obj == NULL) { + return NULL; + } + new_obj->wrapping_value = wrapping_value; + new_obj->names = (char **) NULL; + new_obj->values = (JSON_Value **) NULL; + new_obj->capacity = 0; + new_obj->count = 0; + return new_obj; } -static JSON_Status json_object_add(JSON_Object *object, const char *name, JSON_Value *value) { - if (name == NULL) { - return JSONFailure; - } - return json_object_addn(object, name, strlen(name), value); +static JSON_Status +json_object_add(JSON_Object *object, const char *name, JSON_Value *value) +{ + if (name == NULL) { + return JSONFailure; + } + return json_object_addn(object, name, strlen(name), value); } -static JSON_Status json_object_addn(JSON_Object *object, const char *name, size_t name_len, JSON_Value *value) { - size_t index = 0; - if (object == NULL || name == NULL || value == NULL) { - return JSONFailure; - } - if (json_object_getn_value(object, name, name_len) != NULL) { - return JSONFailure; - } - if (object->count >= object->capacity) { - size_t new_capacity = MAX(object->capacity * 2, STARTING_CAPACITY); - if (json_object_resize(object, new_capacity) == JSONFailure) { - return JSONFailure; - } - } - index = object->count; - object->names[index] = parson_strndup(name, name_len); - if (object->names[index] == NULL) { - return JSONFailure; - } - value->parent = json_object_get_wrapping_value(object); - object->values[index] = value; - object->count++; - return JSONSuccess; +static JSON_Status +json_object_addn(JSON_Object *object, const char *name, size_t name_len, JSON_Value *value) +{ + size_t index = 0; + if (object == NULL || name == NULL || value == NULL) { + return JSONFailure; + } + if (json_object_getn_value(object, name, name_len) != NULL) { + return JSONFailure; + } + if (object->count >= object->capacity) { + size_t new_capacity = MAX(object->capacity * 2, STARTING_CAPACITY); + if (json_object_resize(object, new_capacity) == JSONFailure) { + return JSONFailure; + } + } + index = object->count; + object->names[index] = parson_strndup(name, name_len); + if (object->names[index] == NULL) { + return JSONFailure; + } + value->parent = json_object_get_wrapping_value(object); + object->values[index] = value; + object->count++; + return JSONSuccess; } -static JSON_Status json_object_resize(JSON_Object *object, size_t new_capacity) { - char **temp_names = NULL; - JSON_Value **temp_values = NULL; +static JSON_Status +json_object_resize(JSON_Object *object, size_t new_capacity) +{ + char **temp_names = NULL; + JSON_Value **temp_values = NULL; - if ((object->names == NULL && object->values != NULL) || - (object->names != NULL && object->values == NULL) || - new_capacity == 0) { - return JSONFailure; /* Shouldn't happen */ - } - temp_names = (char**)parson_malloc(new_capacity * sizeof(char*)); - if (temp_names == NULL) { - return JSONFailure; - } - temp_values = (JSON_Value**)parson_malloc(new_capacity * sizeof(JSON_Value*)); - if (temp_values == NULL) { - parson_free(temp_names); - return JSONFailure; - } - if (object->names != NULL && object->values != NULL && object->count > 0) { - memcpy(temp_names, object->names, object->count * sizeof(char*)); - memcpy(temp_values, object->values, object->count * sizeof(JSON_Value*)); - } - parson_free(object->names); - parson_free(object->values); - object->names = temp_names; - object->values = temp_values; - object->capacity = new_capacity; - return JSONSuccess; + if ((object->names == NULL && object->values != NULL) || (object->names != NULL && object->values == NULL) || new_capacity == 0) { + return JSONFailure; /* Shouldn't happen */ + } + temp_names = (char **) parson_malloc(new_capacity * sizeof(char *)); + if (temp_names == NULL) { + return JSONFailure; + } + temp_values = (JSON_Value **) parson_malloc(new_capacity * sizeof(JSON_Value *)); + if (temp_values == NULL) { + parson_free(temp_names); + return JSONFailure; + } + if (object->names != NULL && object->values != NULL && object->count > 0) { + memcpy(temp_names, object->names, object->count * sizeof(char *)); + memcpy(temp_values, object->values, object->count * sizeof(JSON_Value *)); + } + parson_free(object->names); + parson_free(object->values); + object->names = temp_names; + object->values = temp_values; + object->capacity = new_capacity; + return JSONSuccess; } -static JSON_Value * json_object_getn_value(const JSON_Object *object, const char *name, size_t name_len) { - size_t i, name_length; - for (i = 0; i < json_object_get_count(object); i++) { - name_length = strlen(object->names[i]); - if (name_length != name_len) { - continue; - } - if (strncmp(object->names[i], name, name_len) == 0) { - return object->values[i]; - } - } - return NULL; +static JSON_Value * +json_object_getn_value(const JSON_Object *object, const char *name, size_t name_len) +{ + size_t i, name_length; + for (i = 0; i < json_object_get_count(object); i++) { + name_length = strlen(object->names[i]); + if (name_length != name_len) { + continue; + } + if (strncmp(object->names[i], name, name_len) == 0) { + return object->values[i]; + } + } + return NULL; } -static JSON_Status json_object_remove_internal(JSON_Object *object, const char *name, int free_value) { - size_t i = 0, last_item_index = 0; - if (object == NULL || json_object_get_value(object, name) == NULL) { - return JSONFailure; - } - last_item_index = json_object_get_count(object) - 1; - for (i = 0; i < json_object_get_count(object); i++) { - if (strcmp(object->names[i], name) == 0) { - parson_free(object->names[i]); - if (free_value) { - json_value_free(object->values[i]); - } - if (i != last_item_index) { /* Replace key value pair with one from the end */ - object->names[i] = object->names[last_item_index]; - object->values[i] = object->values[last_item_index]; - } - object->count -= 1; - return JSONSuccess; - } - } - return JSONFailure; /* No execution path should end here */ +static JSON_Status +json_object_remove_internal(JSON_Object *object, const char *name, int free_value) +{ + size_t i = 0, last_item_index = 0; + if (object == NULL || json_object_get_value(object, name) == NULL) { + return JSONFailure; + } + last_item_index = json_object_get_count(object) - 1; + for (i = 0; i < json_object_get_count(object); i++) { + if (strcmp(object->names[i], name) == 0) { + parson_free(object->names[i]); + if (free_value) { + json_value_free(object->values[i]); + } + if (i != last_item_index) { /* Replace key value pair with one from the end */ + object->names[i] = object->names[last_item_index]; + object->values[i] = object->values[last_item_index]; + } + object->count -= 1; + return JSONSuccess; + } + } + return JSONFailure; /* No execution path should end here */ } -static JSON_Status json_object_dotremove_internal(JSON_Object *object, const char *name, int free_value) { - JSON_Value *temp_value = NULL; - JSON_Object *temp_object = NULL; - const char *dot_pos = strchr(name, '.'); - if (dot_pos == NULL) { - return json_object_remove_internal(object, name, free_value); - } - temp_value = json_object_getn_value(object, name, dot_pos - name); - if (json_value_get_type(temp_value) != JSONObject) { - return JSONFailure; - } - temp_object = json_value_get_object(temp_value); - return json_object_dotremove_internal(temp_object, dot_pos + 1, free_value); +static JSON_Status +json_object_dotremove_internal(JSON_Object *object, const char *name, int free_value) +{ + JSON_Value *temp_value = NULL; + JSON_Object *temp_object = NULL; + const char *dot_pos = strchr(name, '.'); + if (dot_pos == NULL) { + return json_object_remove_internal(object, name, free_value); + } + temp_value = json_object_getn_value(object, name, dot_pos - name); + if (json_value_get_type(temp_value) != JSONObject) { + return JSONFailure; + } + temp_object = json_value_get_object(temp_value); + return json_object_dotremove_internal(temp_object, dot_pos + 1, free_value); } -static void json_object_free(JSON_Object *object) { - size_t i; - for (i = 0; i < object->count; i++) { - parson_free(object->names[i]); - json_value_free(object->values[i]); - } - parson_free(object->names); - parson_free(object->values); - parson_free(object); +static void +json_object_free(JSON_Object *object) +{ + size_t i; + for (i = 0; i < object->count; i++) { + parson_free(object->names[i]); + json_value_free(object->values[i]); + } + parson_free(object->names); + parson_free(object->values); + parson_free(object); } /* JSON Array */ -static JSON_Array * json_array_init(JSON_Value *wrapping_value) { - JSON_Array *new_array = (JSON_Array*)parson_malloc(sizeof(JSON_Array)); - if (new_array == NULL) { - return NULL; - } - new_array->wrapping_value = wrapping_value; - new_array->items = (JSON_Value**)NULL; - new_array->capacity = 0; - new_array->count = 0; - return new_array; +static JSON_Array * +json_array_init(JSON_Value *wrapping_value) +{ + JSON_Array *new_array = (JSON_Array *) parson_malloc(sizeof(JSON_Array)); + if (new_array == NULL) { + return NULL; + } + new_array->wrapping_value = wrapping_value; + new_array->items = (JSON_Value **) NULL; + new_array->capacity = 0; + new_array->count = 0; + return new_array; } -static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value) { - if (array->count >= array->capacity) { - size_t new_capacity = MAX(array->capacity * 2, STARTING_CAPACITY); - if (json_array_resize(array, new_capacity) == JSONFailure) { - return JSONFailure; - } - } - value->parent = json_array_get_wrapping_value(array); - array->items[array->count] = value; - array->count++; - return JSONSuccess; +static JSON_Status +json_array_add(JSON_Array *array, JSON_Value *value) +{ + if (array->count >= array->capacity) { + size_t new_capacity = MAX(array->capacity * 2, STARTING_CAPACITY); + if (json_array_resize(array, new_capacity) == JSONFailure) { + return JSONFailure; + } + } + value->parent = json_array_get_wrapping_value(array); + array->items[array->count] = value; + array->count++; + return JSONSuccess; } -static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity) { - JSON_Value **new_items = NULL; - if (new_capacity == 0) { - return JSONFailure; - } - new_items = (JSON_Value**)parson_malloc(new_capacity * sizeof(JSON_Value*)); - if (new_items == NULL) { - return JSONFailure; - } - if (array->items != NULL && array->count > 0) { - memcpy(new_items, array->items, array->count * sizeof(JSON_Value*)); - } - parson_free(array->items); - array->items = new_items; - array->capacity = new_capacity; - return JSONSuccess; +static JSON_Status +json_array_resize(JSON_Array *array, size_t new_capacity) +{ + JSON_Value **new_items = NULL; + if (new_capacity == 0) { + return JSONFailure; + } + new_items = (JSON_Value **) parson_malloc(new_capacity * sizeof(JSON_Value *)); + if (new_items == NULL) { + return JSONFailure; + } + if (array->items != NULL && array->count > 0) { + memcpy(new_items, array->items, array->count * sizeof(JSON_Value *)); + } + parson_free(array->items); + array->items = new_items; + array->capacity = new_capacity; + return JSONSuccess; } -static void json_array_free(JSON_Array *array) { - size_t i; - for (i = 0; i < array->count; i++) { - json_value_free(array->items[i]); - } - parson_free(array->items); - parson_free(array); +static void +json_array_free(JSON_Array *array) +{ + size_t i; + for (i = 0; i < array->count; i++) { + json_value_free(array->items[i]); + } + parson_free(array->items); + parson_free(array); } /* JSON Value */ -static JSON_Value * json_value_init_string_no_copy(char *string, size_t length) { - JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); - if (!new_value) { - return NULL; - } - new_value->parent = NULL; - new_value->type = JSONString; - new_value->value.string.chars = string; - new_value->value.string.length = length; - return new_value; +static JSON_Value * +json_value_init_string_no_copy(char *string, size_t length) +{ + JSON_Value *new_value = (JSON_Value *) parson_malloc(sizeof(JSON_Value)); + if (!new_value) { + return NULL; + } + new_value->parent = NULL; + new_value->type = JSONString; + new_value->value.string.chars = string; + new_value->value.string.length = length; + return new_value; } /* Parser */ -static JSON_Status skip_quotes(const char **string) { - if (**string != '\"') { - return JSONFailure; - } - SKIP_CHAR(string); - while (**string != '\"') { - if (**string == '\0') { - return JSONFailure; - } else if (**string == '\\') { - SKIP_CHAR(string); - if (**string == '\0') { - return JSONFailure; - } - } - SKIP_CHAR(string); - } - SKIP_CHAR(string); - return JSONSuccess; +static JSON_Status +skip_quotes(const char **string) +{ + if (**string != '\"') { + return JSONFailure; + } + SKIP_CHAR(string); + while (**string != '\"') { + if (**string == '\0') { + return JSONFailure; + } else if (**string == '\\') { + SKIP_CHAR(string); + if (**string == '\0') { + return JSONFailure; + } + } + SKIP_CHAR(string); + } + SKIP_CHAR(string); + return JSONSuccess; } -static int parse_utf16(const char **unprocessed, char **processed) { - unsigned int cp, lead, trail; - int parse_succeeded = 0; - char *processed_ptr = *processed; - const char *unprocessed_ptr = *unprocessed; - unprocessed_ptr++; /* skips u */ - parse_succeeded = parse_utf16_hex(unprocessed_ptr, &cp); - if (!parse_succeeded) { - return JSONFailure; - } - if (cp < 0x80) { - processed_ptr[0] = (char)cp; /* 0xxxxxxx */ - } else if (cp < 0x800) { - processed_ptr[0] = ((cp >> 6) & 0x1F) | 0xC0; /* 110xxxxx */ - processed_ptr[1] = ((cp) & 0x3F) | 0x80; /* 10xxxxxx */ - processed_ptr += 1; - } else if (cp < 0xD800 || cp > 0xDFFF) { - processed_ptr[0] = ((cp >> 12) & 0x0F) | 0xE0; /* 1110xxxx */ - processed_ptr[1] = ((cp >> 6) & 0x3F) | 0x80; /* 10xxxxxx */ - processed_ptr[2] = ((cp) & 0x3F) | 0x80; /* 10xxxxxx */ - processed_ptr += 2; - } else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */ - lead = cp; - unprocessed_ptr += 4; /* should always be within the buffer, otherwise previous sscanf would fail */ - if (*unprocessed_ptr++ != '\\' || *unprocessed_ptr++ != 'u') { - return JSONFailure; - } - parse_succeeded = parse_utf16_hex(unprocessed_ptr, &trail); - if (!parse_succeeded || trail < 0xDC00 || trail > 0xDFFF) { /* valid trail surrogate? (0xDC00..0xDFFF) */ - return JSONFailure; - } - cp = ((((lead - 0xD800) & 0x3FF) << 10) | ((trail - 0xDC00) & 0x3FF)) + 0x010000; - processed_ptr[0] = (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */ - processed_ptr[1] = (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */ - processed_ptr[2] = (((cp >> 6) & 0x3F) | 0x80); /* 10xxxxxx */ - processed_ptr[3] = (((cp) & 0x3F) | 0x80); /* 10xxxxxx */ - processed_ptr += 3; - } else { /* trail surrogate before lead surrogate */ - return JSONFailure; - } - unprocessed_ptr += 3; - *processed = processed_ptr; - *unprocessed = unprocessed_ptr; - return JSONSuccess; +static int +parse_utf16(const char **unprocessed, char **processed) +{ + unsigned int cp, lead, trail; + int parse_succeeded = 0; + char *processed_ptr = *processed; + const char *unprocessed_ptr = *unprocessed; + unprocessed_ptr++; /* skips u */ + parse_succeeded = parse_utf16_hex(unprocessed_ptr, &cp); + if (!parse_succeeded) { + return JSONFailure; + } + if (cp < 0x80) { + processed_ptr[0] = (char) cp; /* 0xxxxxxx */ + } else if (cp < 0x800) { + processed_ptr[0] = ((cp >> 6) & 0x1F) | 0xC0; /* 110xxxxx */ + processed_ptr[1] = ((cp) &0x3F) | 0x80; /* 10xxxxxx */ + processed_ptr += 1; + } else if (cp < 0xD800 || cp > 0xDFFF) { + processed_ptr[0] = ((cp >> 12) & 0x0F) | 0xE0; /* 1110xxxx */ + processed_ptr[1] = ((cp >> 6) & 0x3F) | 0x80; /* 10xxxxxx */ + processed_ptr[2] = ((cp) &0x3F) | 0x80; /* 10xxxxxx */ + processed_ptr += 2; + } else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */ + lead = cp; + unprocessed_ptr += 4; /* should always be within the buffer, otherwise previous sscanf would fail */ + if (*unprocessed_ptr++ != '\\' || *unprocessed_ptr++ != 'u') { + return JSONFailure; + } + parse_succeeded = parse_utf16_hex(unprocessed_ptr, &trail); + if (!parse_succeeded || trail < 0xDC00 || trail > 0xDFFF) { /* valid trail surrogate? (0xDC00..0xDFFF) */ + return JSONFailure; + } + cp = ((((lead - 0xD800) & 0x3FF) << 10) | ((trail - 0xDC00) & 0x3FF)) + 0x010000; + processed_ptr[0] = (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */ + processed_ptr[1] = (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */ + processed_ptr[2] = (((cp >> 6) & 0x3F) | 0x80); /* 10xxxxxx */ + processed_ptr[3] = (((cp) &0x3F) | 0x80); /* 10xxxxxx */ + processed_ptr += 3; + } else { /* trail surrogate before lead surrogate */ + return JSONFailure; + } + unprocessed_ptr += 3; + *processed = processed_ptr; + *unprocessed = unprocessed_ptr; + return JSONSuccess; } /* Copies and processes passed string up to supplied length. Example: "\u006Corem ipsum" -> lorem ipsum */ -static char* process_string(const char *input, size_t input_len, size_t *output_len) { - const char *input_ptr = input; - size_t initial_size = (input_len + 1) * sizeof(char); - size_t final_size = 0; - char *output = NULL, *output_ptr = NULL, *resized_output = NULL; - output = (char*)parson_malloc(initial_size); - if (output == NULL) { - goto error; - } - output_ptr = output; - while ((*input_ptr != '\0') && (size_t)(input_ptr - input) < input_len) { - if (*input_ptr == '\\') { - input_ptr++; - switch (*input_ptr) { - case '\"': *output_ptr = '\"'; break; - case '\\': *output_ptr = '\\'; break; - case '/': *output_ptr = '/'; break; - case 'b': *output_ptr = '\b'; break; - case 'f': *output_ptr = '\f'; break; - case 'n': *output_ptr = '\n'; break; - case 'r': *output_ptr = '\r'; break; - case 't': *output_ptr = '\t'; break; - case 'u': - if (parse_utf16(&input_ptr, &output_ptr) == JSONFailure) { - goto error; - } - break; - default: - goto error; - } - } else if ((unsigned char)*input_ptr < 0x20) { - goto error; /* 0x00-0x19 are invalid characters for json string (http://www.ietf.org/rfc/rfc4627.txt) */ - } else { - *output_ptr = *input_ptr; - } - output_ptr++; - input_ptr++; - } - *output_ptr = '\0'; - /* resize to new length */ - final_size = (size_t)(output_ptr-output) + 1; - /* todo: don't resize if final_size == initial_size */ - resized_output = (char*)parson_malloc(final_size); - if (resized_output == NULL) { - goto error; - } - memcpy(resized_output, output, final_size); - *output_len = final_size - 1; - parson_free(output); - return resized_output; +static char * +process_string(const char *input, size_t input_len, size_t *output_len) +{ + const char *input_ptr = input; + size_t initial_size = (input_len + 1) * sizeof(char); + size_t final_size = 0; + char *output = NULL, *output_ptr = NULL, *resized_output = NULL; + output = (char *) parson_malloc(initial_size); + if (output == NULL) { + goto error; + } + output_ptr = output; + while ((*input_ptr != '\0') && (size_t) (input_ptr - input) < input_len) { + if (*input_ptr == '\\') { + input_ptr++; + switch (*input_ptr) { + case '\"': + *output_ptr = '\"'; + break; + case '\\': + *output_ptr = '\\'; + break; + case '/': + *output_ptr = '/'; + break; + case 'b': + *output_ptr = '\b'; + break; + case 'f': + *output_ptr = '\f'; + break; + case 'n': + *output_ptr = '\n'; + break; + case 'r': + *output_ptr = '\r'; + break; + case 't': + *output_ptr = '\t'; + break; + case 'u': + if (parse_utf16(&input_ptr, &output_ptr) == JSONFailure) { + goto error; + } + break; + default: + goto error; + } + } else if ((unsigned char) *input_ptr < 0x20) { + goto error; /* 0x00-0x19 are invalid characters for json string (http://www.ietf.org/rfc/rfc4627.txt) */ + } else { + *output_ptr = *input_ptr; + } + output_ptr++; + input_ptr++; + } + *output_ptr = '\0'; + /* resize to new length */ + final_size = (size_t) (output_ptr - output) + 1; + /* todo: don't resize if final_size == initial_size */ + resized_output = (char *) parson_malloc(final_size); + if (resized_output == NULL) { + goto error; + } + memcpy(resized_output, output, final_size); + *output_len = final_size - 1; + parson_free(output); + return resized_output; error: - parson_free(output); - return NULL; + parson_free(output); + return NULL; } /* Return processed contents of a string between quotes and skips passed argument to a matching quote. */ -static char * get_quoted_string(const char **string, size_t *output_string_len) { - const char *string_start = *string; - size_t input_string_len = 0; - JSON_Status status = skip_quotes(string); - if (status != JSONSuccess) { - return NULL; - } - input_string_len = *string - string_start - 2; /* length without quotes */ - return process_string(string_start + 1, input_string_len, output_string_len); +static char * +get_quoted_string(const char **string, size_t *output_string_len) +{ + const char *string_start = *string; + size_t input_string_len = 0; + JSON_Status status = skip_quotes(string); + if (status != JSONSuccess) { + return NULL; + } + input_string_len = *string - string_start - 2; /* length without quotes */ + return process_string(string_start + 1, input_string_len, output_string_len); } -static JSON_Value * parse_value(const char **string, size_t nesting) { - if (nesting > MAX_NESTING) { - return NULL; - } - SKIP_WHITESPACES(string); - switch (**string) { - case '{': - return parse_object_value(string, nesting + 1); - case '[': - return parse_array_value(string, nesting + 1); - case '\"': - return parse_string_value(string); - case 'f': case 't': - return parse_boolean_value(string); - case '-': - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - return parse_number_value(string); - case 'n': - return parse_null_value(string); - default: - return NULL; - } +static JSON_Value * +parse_value(const char **string, size_t nesting) +{ + if (nesting > MAX_NESTING) { + return NULL; + } + SKIP_WHITESPACES(string); + switch (**string) { + case '{': + return parse_object_value(string, nesting + 1); + case '[': + return parse_array_value(string, nesting + 1); + case '\"': + return parse_string_value(string); + case 'f': + case 't': + return parse_boolean_value(string); + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return parse_number_value(string); + case 'n': + return parse_null_value(string); + default: + return NULL; + } } -static JSON_Value * parse_object_value(const char **string, size_t nesting) { - JSON_Value *output_value = NULL, *new_value = NULL; - JSON_Object *output_object = NULL; - char *new_key = NULL; - output_value = json_value_init_object(); - if (output_value == NULL) { - return NULL; - } - if (**string != '{') { - json_value_free(output_value); - return NULL; - } - output_object = json_value_get_object(output_value); - SKIP_CHAR(string); - SKIP_WHITESPACES(string); - if (**string == '}') { /* empty object */ - SKIP_CHAR(string); - return output_value; - } - while (**string != '\0') { - size_t key_len = 0; - new_key = get_quoted_string(string, &key_len); - /* We do not support key names with embedded \0 chars */ - if (new_key == NULL || key_len != strlen(new_key)) { - if (new_key) { - parson_free(new_key); - } - json_value_free(output_value); - return NULL; - } - SKIP_WHITESPACES(string); - if (**string != ':') { - parson_free(new_key); - json_value_free(output_value); - return NULL; - } - SKIP_CHAR(string); - new_value = parse_value(string, nesting); - if (new_value == NULL) { - parson_free(new_key); - json_value_free(output_value); - return NULL; - } - if (json_object_add(output_object, new_key, new_value) == JSONFailure) { - parson_free(new_key); - json_value_free(new_value); - json_value_free(output_value); - return NULL; - } - parson_free(new_key); - SKIP_WHITESPACES(string); - if (**string != ',') { - break; - } - SKIP_CHAR(string); - SKIP_WHITESPACES(string); - } - SKIP_WHITESPACES(string); - if (**string != '}' || /* Trim object after parsing is over */ - json_object_resize(output_object, json_object_get_count(output_object)) == JSONFailure) { - json_value_free(output_value); - return NULL; - } - SKIP_CHAR(string); - return output_value; +static JSON_Value * +parse_object_value(const char **string, size_t nesting) +{ + JSON_Value *output_value = NULL, *new_value = NULL; + JSON_Object *output_object = NULL; + char *new_key = NULL; + output_value = json_value_init_object(); + if (output_value == NULL) { + return NULL; + } + if (**string != '{') { + json_value_free(output_value); + return NULL; + } + output_object = json_value_get_object(output_value); + SKIP_CHAR(string); + SKIP_WHITESPACES(string); + if (**string == '}') { /* empty object */ + SKIP_CHAR(string); + return output_value; + } + while (**string != '\0') { + size_t key_len = 0; + new_key = get_quoted_string(string, &key_len); + /* We do not support key names with embedded \0 chars */ + if (new_key == NULL || key_len != strlen(new_key)) { + if (new_key) { + parson_free(new_key); + } + json_value_free(output_value); + return NULL; + } + SKIP_WHITESPACES(string); + if (**string != ':') { + parson_free(new_key); + json_value_free(output_value); + return NULL; + } + SKIP_CHAR(string); + new_value = parse_value(string, nesting); + if (new_value == NULL) { + parson_free(new_key); + json_value_free(output_value); + return NULL; + } + if (json_object_add(output_object, new_key, new_value) == JSONFailure) { + parson_free(new_key); + json_value_free(new_value); + json_value_free(output_value); + return NULL; + } + parson_free(new_key); + SKIP_WHITESPACES(string); + if (**string != ',') { + break; + } + SKIP_CHAR(string); + SKIP_WHITESPACES(string); + } + SKIP_WHITESPACES(string); + if (**string != '}' || /* Trim object after parsing is over */ + json_object_resize(output_object, json_object_get_count(output_object)) == JSONFailure) { + json_value_free(output_value); + return NULL; + } + SKIP_CHAR(string); + return output_value; } -static JSON_Value * parse_array_value(const char **string, size_t nesting) { - JSON_Value *output_value = NULL, *new_array_value = NULL; - JSON_Array *output_array = NULL; - output_value = json_value_init_array(); - if (output_value == NULL) { - return NULL; - } - if (**string != '[') { - json_value_free(output_value); - return NULL; - } - output_array = json_value_get_array(output_value); - SKIP_CHAR(string); - SKIP_WHITESPACES(string); - if (**string == ']') { /* empty array */ - SKIP_CHAR(string); - return output_value; - } - while (**string != '\0') { - new_array_value = parse_value(string, nesting); - if (new_array_value == NULL) { - json_value_free(output_value); - return NULL; - } - if (json_array_add(output_array, new_array_value) == JSONFailure) { - json_value_free(new_array_value); - json_value_free(output_value); - return NULL; - } - SKIP_WHITESPACES(string); - if (**string != ',') { - break; - } - SKIP_CHAR(string); - SKIP_WHITESPACES(string); - } - SKIP_WHITESPACES(string); - if (**string != ']' || /* Trim array after parsing is over */ - json_array_resize(output_array, json_array_get_count(output_array)) == JSONFailure) { - json_value_free(output_value); - return NULL; - } - SKIP_CHAR(string); - return output_value; +static JSON_Value * +parse_array_value(const char **string, size_t nesting) +{ + JSON_Value *output_value = NULL, *new_array_value = NULL; + JSON_Array *output_array = NULL; + output_value = json_value_init_array(); + if (output_value == NULL) { + return NULL; + } + if (**string != '[') { + json_value_free(output_value); + return NULL; + } + output_array = json_value_get_array(output_value); + SKIP_CHAR(string); + SKIP_WHITESPACES(string); + if (**string == ']') { /* empty array */ + SKIP_CHAR(string); + return output_value; + } + while (**string != '\0') { + new_array_value = parse_value(string, nesting); + if (new_array_value == NULL) { + json_value_free(output_value); + return NULL; + } + if (json_array_add(output_array, new_array_value) == JSONFailure) { + json_value_free(new_array_value); + json_value_free(output_value); + return NULL; + } + SKIP_WHITESPACES(string); + if (**string != ',') { + break; + } + SKIP_CHAR(string); + SKIP_WHITESPACES(string); + } + SKIP_WHITESPACES(string); + if (**string != ']' || /* Trim array after parsing is over */ + json_array_resize(output_array, json_array_get_count(output_array)) == JSONFailure) { + json_value_free(output_value); + return NULL; + } + SKIP_CHAR(string); + return output_value; } -static JSON_Value * parse_string_value(const char **string) { - JSON_Value *value = NULL; - size_t new_string_len = 0; - char *new_string = get_quoted_string(string, &new_string_len); - if (new_string == NULL) { - return NULL; - } - value = json_value_init_string_no_copy(new_string, new_string_len); - if (value == NULL) { - parson_free(new_string); - return NULL; - } - return value; +static JSON_Value * +parse_string_value(const char **string) +{ + JSON_Value *value = NULL; + size_t new_string_len = 0; + char *new_string = get_quoted_string(string, &new_string_len); + if (new_string == NULL) { + return NULL; + } + value = json_value_init_string_no_copy(new_string, new_string_len); + if (value == NULL) { + parson_free(new_string); + return NULL; + } + return value; } -static JSON_Value * parse_boolean_value(const char **string) { - size_t true_token_size = SIZEOF_TOKEN("true"); - size_t false_token_size = SIZEOF_TOKEN("false"); - if (strncmp("true", *string, true_token_size) == 0) { - *string += true_token_size; - return json_value_init_boolean(1); - } else if (strncmp("false", *string, false_token_size) == 0) { - *string += false_token_size; - return json_value_init_boolean(0); - } - return NULL; +static JSON_Value * +parse_boolean_value(const char **string) +{ + size_t true_token_size = SIZEOF_TOKEN("true"); + size_t false_token_size = SIZEOF_TOKEN("false"); + if (strncmp("true", *string, true_token_size) == 0) { + *string += true_token_size; + return json_value_init_boolean(1); + } else if (strncmp("false", *string, false_token_size) == 0) { + *string += false_token_size; + return json_value_init_boolean(0); + } + return NULL; } -static JSON_Value * parse_number_value(const char **string) { - char *end; - double number = 0; - errno = 0; - number = strtod(*string, &end); - if (errno == ERANGE && (number == -HUGE_VAL || number == HUGE_VAL)) { - return NULL; - } - if ((errno && errno != ERANGE) || !is_decimal(*string, end - *string)) { - return NULL; - } - *string = end; - return json_value_init_number(number); +static JSON_Value * +parse_number_value(const char **string) +{ + char *end; + double number = 0; + errno = 0; + number = strtod(*string, &end); + if (errno == ERANGE && (number == -HUGE_VAL || number == HUGE_VAL)) { + return NULL; + } + if ((errno && errno != ERANGE) || !is_decimal(*string, end - *string)) { + return NULL; + } + *string = end; + return json_value_init_number(number); } -static JSON_Value * parse_null_value(const char **string) { - size_t token_size = SIZEOF_TOKEN("null"); - if (strncmp("null", *string, token_size) == 0) { - *string += token_size; - return json_value_init_null(); - } - return NULL; +static JSON_Value * +parse_null_value(const char **string) +{ + size_t token_size = SIZEOF_TOKEN("null"); + if (strncmp("null", *string, token_size) == 0) { + *string += token_size; + return json_value_init_null(); + } + return NULL; } /* Serialization */ -#define APPEND_STRING(str) do { written = append_string(buf, (str));\ - if (written < 0) { return -1; }\ - if (buf != NULL) { buf += written; }\ - written_total += written; } while(0) +#define APPEND_STRING(str) \ + do { \ + written = append_string(buf, (str)); \ + if (written < 0) { \ + return -1; \ + } \ + if (buf != NULL) { \ + buf += written; \ + } \ + written_total += written; \ + } while (0) -#define APPEND_INDENT(level) do { written = append_indent(buf, (level));\ - if (written < 0) { return -1; }\ - if (buf != NULL) { buf += written; }\ - written_total += written; } while(0) +#define APPEND_INDENT(level) \ + do { \ + written = append_indent(buf, (level)); \ + if (written < 0) { \ + return -1; \ + } \ + if (buf != NULL) { \ + buf += written; \ + } \ + written_total += written; \ + } while (0) -static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf) +static int +json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf) { - const char *key = NULL, *string = NULL; - JSON_Value *temp_value = NULL; - JSON_Array *array = NULL; - JSON_Object *object = NULL; - size_t i = 0, count = 0; - double num = 0.0; - int written = -1, written_total = 0; - size_t len = 0; + const char *key = NULL, *string = NULL; + JSON_Value *temp_value = NULL; + JSON_Array *array = NULL; + JSON_Object *object = NULL; + size_t i = 0, count = 0; + double num = 0.0; + int written = -1, written_total = 0; + size_t len = 0; - switch (json_value_get_type(value)) { - case JSONArray: - array = json_value_get_array(value); - count = json_array_get_count(array); - APPEND_STRING("["); - if (count > 0 && is_pretty) { - APPEND_STRING("\n"); - } - for (i = 0; i < count; i++) { - if (is_pretty) { - APPEND_INDENT(level+1); - } - temp_value = json_array_get_value(array, i); - written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf); - if (written < 0) { - return -1; - } - if (buf != NULL) { - buf += written; - } - written_total += written; - if (i < (count - 1)) { - APPEND_STRING(","); - } - if (is_pretty) { - APPEND_STRING("\n"); - } - } - if (count > 0 && is_pretty) { - APPEND_INDENT(level); - } - APPEND_STRING("]"); - return written_total; - case JSONObject: - object = json_value_get_object(value); - count = json_object_get_count(object); - APPEND_STRING("{"); - if (count > 0 && is_pretty) { - APPEND_STRING("\n"); - } - for (i = 0; i < count; i++) { - key = json_object_get_name(object, i); - if (key == NULL) { - return -1; - } - if (is_pretty) { - APPEND_INDENT(level+1); - } - /* We do not support key names with embedded \0 chars */ - written = json_serialize_string(key, strlen(key), buf); - if (written < 0) { - return -1; - } - if (buf != NULL) { - buf += written; - } - written_total += written; - APPEND_STRING(":"); - if (is_pretty) { - APPEND_STRING(" "); - } - temp_value = json_object_get_value_at(object, i); - written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf); - if (written < 0) { - return -1; - } - if (buf != NULL) { - buf += written; - } - written_total += written; - if (i < (count - 1)) { - APPEND_STRING(","); - } - if (is_pretty) { - APPEND_STRING("\n"); - } - } - if (count > 0 && is_pretty) { - APPEND_INDENT(level); - } - APPEND_STRING("}"); - return written_total; - case JSONString: - string = json_value_get_string(value); - if (string == NULL) { - return -1; - } - len = json_value_get_string_len(value); - written = json_serialize_string(string, len, buf); - if (written < 0) { - return -1; - } - if (buf != NULL) { - buf += written; - } - written_total += written; - return written_total; - case JSONBoolean: - if (json_value_get_boolean(value)) { - APPEND_STRING("true"); - } else { - APPEND_STRING("false"); - } - return written_total; - case JSONNumber: - num = json_value_get_number(value); - if (buf != NULL) { - num_buf = buf; - } - written = sprintf(num_buf, FLOAT_FORMAT, num); - if (written < 0) { - return -1; - } - if (buf != NULL) { - buf += written; - } - written_total += written; - return written_total; - case JSONNull: - APPEND_STRING("null"); - return written_total; - case JSONError: - return -1; - default: - return -1; - } + switch (json_value_get_type(value)) { + case JSONArray: + array = json_value_get_array(value); + count = json_array_get_count(array); + APPEND_STRING("["); + if (count > 0 && is_pretty) { + APPEND_STRING("\n"); + } + for (i = 0; i < count; i++) { + if (is_pretty) { + APPEND_INDENT(level + 1); + } + temp_value = json_array_get_value(array, i); + written = json_serialize_to_buffer_r(temp_value, buf, level + 1, is_pretty, num_buf); + if (written < 0) { + return -1; + } + if (buf != NULL) { + buf += written; + } + written_total += written; + if (i < (count - 1)) { + APPEND_STRING(","); + } + if (is_pretty) { + APPEND_STRING("\n"); + } + } + if (count > 0 && is_pretty) { + APPEND_INDENT(level); + } + APPEND_STRING("]"); + return written_total; + case JSONObject: + object = json_value_get_object(value); + count = json_object_get_count(object); + APPEND_STRING("{"); + if (count > 0 && is_pretty) { + APPEND_STRING("\n"); + } + for (i = 0; i < count; i++) { + key = json_object_get_name(object, i); + if (key == NULL) { + return -1; + } + if (is_pretty) { + APPEND_INDENT(level + 1); + } + /* We do not support key names with embedded \0 chars */ + written = json_serialize_string(key, strlen(key), buf); + if (written < 0) { + return -1; + } + if (buf != NULL) { + buf += written; + } + written_total += written; + APPEND_STRING(":"); + if (is_pretty) { + APPEND_STRING(" "); + } + temp_value = json_object_get_value_at(object, i); + written = json_serialize_to_buffer_r(temp_value, buf, level + 1, is_pretty, num_buf); + if (written < 0) { + return -1; + } + if (buf != NULL) { + buf += written; + } + written_total += written; + if (i < (count - 1)) { + APPEND_STRING(","); + } + if (is_pretty) { + APPEND_STRING("\n"); + } + } + if (count > 0 && is_pretty) { + APPEND_INDENT(level); + } + APPEND_STRING("}"); + return written_total; + case JSONString: + string = json_value_get_string(value); + if (string == NULL) { + return -1; + } + len = json_value_get_string_len(value); + written = json_serialize_string(string, len, buf); + if (written < 0) { + return -1; + } + if (buf != NULL) { + buf += written; + } + written_total += written; + return written_total; + case JSONBoolean: + if (json_value_get_boolean(value)) { + APPEND_STRING("true"); + } else { + APPEND_STRING("false"); + } + return written_total; + case JSONNumber: + num = json_value_get_number(value); + if (buf != NULL) { + num_buf = buf; + } + written = sprintf(num_buf, FLOAT_FORMAT, num); + if (written < 0) { + return -1; + } + if (buf != NULL) { + buf += written; + } + written_total += written; + return written_total; + case JSONNull: + APPEND_STRING("null"); + return written_total; + case JSONError: + return -1; + default: + return -1; + } } -static int json_serialize_string(const char *string, size_t len, char *buf) { - size_t i = 0; - char c = '\0'; - int written = -1, written_total = 0; - APPEND_STRING("\""); - for (i = 0; i < len; i++) { - c = string[i]; - switch (c) { - case '\"': APPEND_STRING("\\\""); break; - case '\\': APPEND_STRING("\\\\"); break; - case '\b': APPEND_STRING("\\b"); break; - case '\f': APPEND_STRING("\\f"); break; - case '\n': APPEND_STRING("\\n"); break; - case '\r': APPEND_STRING("\\r"); break; - case '\t': APPEND_STRING("\\t"); break; - case '\x00': APPEND_STRING("\\u0000"); break; - case '\x01': APPEND_STRING("\\u0001"); break; - case '\x02': APPEND_STRING("\\u0002"); break; - case '\x03': APPEND_STRING("\\u0003"); break; - case '\x04': APPEND_STRING("\\u0004"); break; - case '\x05': APPEND_STRING("\\u0005"); break; - case '\x06': APPEND_STRING("\\u0006"); break; - case '\x07': APPEND_STRING("\\u0007"); break; - /* '\x08' duplicate: '\b' */ - /* '\x09' duplicate: '\t' */ - /* '\x0a' duplicate: '\n' */ - case '\x0b': APPEND_STRING("\\u000b"); break; - /* '\x0c' duplicate: '\f' */ - /* '\x0d' duplicate: '\r' */ - case '\x0e': APPEND_STRING("\\u000e"); break; - case '\x0f': APPEND_STRING("\\u000f"); break; - case '\x10': APPEND_STRING("\\u0010"); break; - case '\x11': APPEND_STRING("\\u0011"); break; - case '\x12': APPEND_STRING("\\u0012"); break; - case '\x13': APPEND_STRING("\\u0013"); break; - case '\x14': APPEND_STRING("\\u0014"); break; - case '\x15': APPEND_STRING("\\u0015"); break; - case '\x16': APPEND_STRING("\\u0016"); break; - case '\x17': APPEND_STRING("\\u0017"); break; - case '\x18': APPEND_STRING("\\u0018"); break; - case '\x19': APPEND_STRING("\\u0019"); break; - case '\x1a': APPEND_STRING("\\u001a"); break; - case '\x1b': APPEND_STRING("\\u001b"); break; - case '\x1c': APPEND_STRING("\\u001c"); break; - case '\x1d': APPEND_STRING("\\u001d"); break; - case '\x1e': APPEND_STRING("\\u001e"); break; - case '\x1f': APPEND_STRING("\\u001f"); break; - case '/': - if (parson_escape_slashes) { - APPEND_STRING("\\/"); /* to make json embeddable in xml\/html */ - } else { - APPEND_STRING("/"); - } - break; - default: - if (buf != NULL) { - buf[0] = c; - buf += 1; - } - written_total += 1; - break; - } - } - APPEND_STRING("\""); - return written_total; +static int +json_serialize_string(const char *string, size_t len, char *buf) +{ + size_t i = 0; + char c = '\0'; + int written = -1, written_total = 0; + APPEND_STRING("\""); + for (i = 0; i < len; i++) { + c = string[i]; + switch (c) { + case '\"': + APPEND_STRING("\\\""); + break; + case '\\': + APPEND_STRING("\\\\"); + break; + case '\b': + APPEND_STRING("\\b"); + break; + case '\f': + APPEND_STRING("\\f"); + break; + case '\n': + APPEND_STRING("\\n"); + break; + case '\r': + APPEND_STRING("\\r"); + break; + case '\t': + APPEND_STRING("\\t"); + break; + case '\x00': + APPEND_STRING("\\u0000"); + break; + case '\x01': + APPEND_STRING("\\u0001"); + break; + case '\x02': + APPEND_STRING("\\u0002"); + break; + case '\x03': + APPEND_STRING("\\u0003"); + break; + case '\x04': + APPEND_STRING("\\u0004"); + break; + case '\x05': + APPEND_STRING("\\u0005"); + break; + case '\x06': + APPEND_STRING("\\u0006"); + break; + case '\x07': + APPEND_STRING("\\u0007"); + break; + /* '\x08' duplicate: '\b' */ + /* '\x09' duplicate: '\t' */ + /* '\x0a' duplicate: '\n' */ + case '\x0b': + APPEND_STRING("\\u000b"); + break; + /* '\x0c' duplicate: '\f' */ + /* '\x0d' duplicate: '\r' */ + case '\x0e': + APPEND_STRING("\\u000e"); + break; + case '\x0f': + APPEND_STRING("\\u000f"); + break; + case '\x10': + APPEND_STRING("\\u0010"); + break; + case '\x11': + APPEND_STRING("\\u0011"); + break; + case '\x12': + APPEND_STRING("\\u0012"); + break; + case '\x13': + APPEND_STRING("\\u0013"); + break; + case '\x14': + APPEND_STRING("\\u0014"); + break; + case '\x15': + APPEND_STRING("\\u0015"); + break; + case '\x16': + APPEND_STRING("\\u0016"); + break; + case '\x17': + APPEND_STRING("\\u0017"); + break; + case '\x18': + APPEND_STRING("\\u0018"); + break; + case '\x19': + APPEND_STRING("\\u0019"); + break; + case '\x1a': + APPEND_STRING("\\u001a"); + break; + case '\x1b': + APPEND_STRING("\\u001b"); + break; + case '\x1c': + APPEND_STRING("\\u001c"); + break; + case '\x1d': + APPEND_STRING("\\u001d"); + break; + case '\x1e': + APPEND_STRING("\\u001e"); + break; + case '\x1f': + APPEND_STRING("\\u001f"); + break; + case '/': + if (parson_escape_slashes) { + APPEND_STRING("\\/"); /* to make json embeddable in xml\/html */ + } else { + APPEND_STRING("/"); + } + break; + default: + if (buf != NULL) { + buf[0] = c; + buf += 1; + } + written_total += 1; + break; + } + } + APPEND_STRING("\""); + return written_total; } -static int append_indent(char *buf, int level) { - int i; - int written = -1, written_total = 0; - for (i = 0; i < level; i++) { - APPEND_STRING(" "); - } - return written_total; +static int +append_indent(char *buf, int level) +{ + int i; + int written = -1, written_total = 0; + for (i = 0; i < level; i++) { + APPEND_STRING(" "); + } + return written_total; } -static int append_string(char *buf, const char *string) { - if (buf == NULL) { - return (int)strlen(string); - } - return sprintf(buf, "%s", string); +static int +append_string(char *buf, const char *string) +{ + if (buf == NULL) { + return (int) strlen(string); + } + return sprintf(buf, "%s", string); } #undef APPEND_STRING #undef APPEND_INDENT /* Parser API */ -JSON_Value * json_parse_file(const char *filename) { - char *file_contents = read_file(filename); - JSON_Value *output_value = NULL; - if (file_contents == NULL) { - return NULL; - } - output_value = json_parse_string(file_contents); - parson_free(file_contents); - return output_value; +JSON_Value * +json_parse_file(const char *filename) +{ + char *file_contents = read_file(filename); + JSON_Value *output_value = NULL; + if (file_contents == NULL) { + return NULL; + } + output_value = json_parse_string(file_contents); + parson_free(file_contents); + return output_value; } -JSON_Value * json_parse_file_with_comments(const char *filename) { - char *file_contents = read_file(filename); - JSON_Value *output_value = NULL; - if (file_contents == NULL) { - return NULL; - } - output_value = json_parse_string_with_comments(file_contents); - parson_free(file_contents); - return output_value; +JSON_Value * +json_parse_file_with_comments(const char *filename) +{ + char *file_contents = read_file(filename); + JSON_Value *output_value = NULL; + if (file_contents == NULL) { + return NULL; + } + output_value = json_parse_string_with_comments(file_contents); + parson_free(file_contents); + return output_value; } -JSON_Value * json_parse_string(const char *string) { - if (string == NULL) { - return NULL; - } - if (string[0] == '\xEF' && string[1] == '\xBB' && string[2] == '\xBF') { - string = string + 3; /* Support for UTF-8 BOM */ - } - return parse_value((const char**)&string, 0); +JSON_Value * +json_parse_string(const char *string) +{ + if (string == NULL) { + return NULL; + } + if (string[0] == '\xEF' && string[1] == '\xBB' && string[2] == '\xBF') { + string = string + 3; /* Support for UTF-8 BOM */ + } + return parse_value((const char **) &string, 0); } -JSON_Value * json_parse_string_with_comments(const char *string) { - JSON_Value *result = NULL; - char *string_mutable_copy = NULL, *string_mutable_copy_ptr = NULL; - string_mutable_copy = parson_strdup(string); - if (string_mutable_copy == NULL) { - return NULL; - } - remove_comments(string_mutable_copy, "/*", "*/"); - remove_comments(string_mutable_copy, "//", "\n"); - string_mutable_copy_ptr = string_mutable_copy; - result = parse_value((const char**)&string_mutable_copy_ptr, 0); - parson_free(string_mutable_copy); - return result; +JSON_Value * +json_parse_string_with_comments(const char *string) +{ + JSON_Value *result = NULL; + char *string_mutable_copy = NULL, *string_mutable_copy_ptr = NULL; + string_mutable_copy = parson_strdup(string); + if (string_mutable_copy == NULL) { + return NULL; + } + remove_comments(string_mutable_copy, "/*", "*/"); + remove_comments(string_mutable_copy, "//", "\n"); + string_mutable_copy_ptr = string_mutable_copy; + result = parse_value((const char **) &string_mutable_copy_ptr, 0); + parson_free(string_mutable_copy); + return result; } /* JSON Object API */ -JSON_Value * json_object_get_value(const JSON_Object *object, const char *name) { - if (object == NULL || name == NULL) { - return NULL; - } - return json_object_getn_value(object, name, strlen(name)); +JSON_Value * +json_object_get_value(const JSON_Object *object, const char *name) +{ + if (object == NULL || name == NULL) { + return NULL; + } + return json_object_getn_value(object, name, strlen(name)); } -const char * json_object_get_string(const JSON_Object *object, const char *name) { - return json_value_get_string(json_object_get_value(object, name)); +const char * +json_object_get_string(const JSON_Object *object, const char *name) +{ + return json_value_get_string(json_object_get_value(object, name)); } -size_t json_object_get_string_len(const JSON_Object *object, const char *name) { - return json_value_get_string_len(json_object_get_value(object, name)); +size_t +json_object_get_string_len(const JSON_Object *object, const char *name) +{ + return json_value_get_string_len(json_object_get_value(object, name)); } -double json_object_get_number(const JSON_Object *object, const char *name) { - return json_value_get_number(json_object_get_value(object, name)); +double +json_object_get_number(const JSON_Object *object, const char *name) +{ + return json_value_get_number(json_object_get_value(object, name)); } -JSON_Object * json_object_get_object(const JSON_Object *object, const char *name) { - return json_value_get_object(json_object_get_value(object, name)); +JSON_Object * +json_object_get_object(const JSON_Object *object, const char *name) +{ + return json_value_get_object(json_object_get_value(object, name)); } -JSON_Array * json_object_get_array(const JSON_Object *object, const char *name) { - return json_value_get_array(json_object_get_value(object, name)); +JSON_Array * +json_object_get_array(const JSON_Object *object, const char *name) +{ + return json_value_get_array(json_object_get_value(object, name)); } -int json_object_get_boolean(const JSON_Object *object, const char *name) { - return json_value_get_boolean(json_object_get_value(object, name)); +int +json_object_get_boolean(const JSON_Object *object, const char *name) +{ + return json_value_get_boolean(json_object_get_value(object, name)); } -JSON_Value * json_object_dotget_value(const JSON_Object *object, const char *name) { - const char *dot_position = strchr(name, '.'); - if (!dot_position) { - return json_object_get_value(object, name); - } - object = json_value_get_object(json_object_getn_value(object, name, dot_position - name)); - return json_object_dotget_value(object, dot_position + 1); +JSON_Value * +json_object_dotget_value(const JSON_Object *object, const char *name) +{ + const char *dot_position = strchr(name, '.'); + if (!dot_position) { + return json_object_get_value(object, name); + } + object = json_value_get_object(json_object_getn_value(object, name, dot_position - name)); + return json_object_dotget_value(object, dot_position + 1); } -const char * json_object_dotget_string(const JSON_Object *object, const char *name) { - return json_value_get_string(json_object_dotget_value(object, name)); +const char * +json_object_dotget_string(const JSON_Object *object, const char *name) +{ + return json_value_get_string(json_object_dotget_value(object, name)); } -size_t json_object_dotget_string_len(const JSON_Object *object, const char *name) { - return json_value_get_string_len(json_object_dotget_value(object, name)); +size_t +json_object_dotget_string_len(const JSON_Object *object, const char *name) +{ + return json_value_get_string_len(json_object_dotget_value(object, name)); } -double json_object_dotget_number(const JSON_Object *object, const char *name) { - return json_value_get_number(json_object_dotget_value(object, name)); +double +json_object_dotget_number(const JSON_Object *object, const char *name) +{ + return json_value_get_number(json_object_dotget_value(object, name)); } -JSON_Object * json_object_dotget_object(const JSON_Object *object, const char *name) { - return json_value_get_object(json_object_dotget_value(object, name)); +JSON_Object * +json_object_dotget_object(const JSON_Object *object, const char *name) +{ + return json_value_get_object(json_object_dotget_value(object, name)); } -JSON_Array * json_object_dotget_array(const JSON_Object *object, const char *name) { - return json_value_get_array(json_object_dotget_value(object, name)); +JSON_Array * +json_object_dotget_array(const JSON_Object *object, const char *name) +{ + return json_value_get_array(json_object_dotget_value(object, name)); } -int json_object_dotget_boolean(const JSON_Object *object, const char *name) { - return json_value_get_boolean(json_object_dotget_value(object, name)); +int +json_object_dotget_boolean(const JSON_Object *object, const char *name) +{ + return json_value_get_boolean(json_object_dotget_value(object, name)); } -size_t json_object_get_count(const JSON_Object *object) { - return object ? object->count : 0; +size_t +json_object_get_count(const JSON_Object *object) +{ + return object ? object->count : 0; } -const char * json_object_get_name(const JSON_Object *object, size_t index) { - if (object == NULL || index >= json_object_get_count(object)) { - return NULL; - } - return object->names[index]; +const char * +json_object_get_name(const JSON_Object *object, size_t index) +{ + if (object == NULL || index >= json_object_get_count(object)) { + return NULL; + } + return object->names[index]; } -JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index) { - if (object == NULL || index >= json_object_get_count(object)) { - return NULL; - } - return object->values[index]; +JSON_Value * +json_object_get_value_at(const JSON_Object *object, size_t index) +{ + if (object == NULL || index >= json_object_get_count(object)) { + return NULL; + } + return object->values[index]; } -JSON_Value *json_object_get_wrapping_value(const JSON_Object *object) { - return object->wrapping_value; +JSON_Value * +json_object_get_wrapping_value(const JSON_Object *object) +{ + return object->wrapping_value; } -int json_object_has_value (const JSON_Object *object, const char *name) { - return json_object_get_value(object, name) != NULL; +int +json_object_has_value(const JSON_Object *object, const char *name) +{ + return json_object_get_value(object, name) != NULL; } -int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) { - JSON_Value *val = json_object_get_value(object, name); - return val != NULL && json_value_get_type(val) == type; +int +json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) +{ + JSON_Value *val = json_object_get_value(object, name); + return val != NULL && json_value_get_type(val) == type; } -int json_object_dothas_value (const JSON_Object *object, const char *name) { - return json_object_dotget_value(object, name) != NULL; +int +json_object_dothas_value(const JSON_Object *object, const char *name) +{ + return json_object_dotget_value(object, name) != NULL; } -int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) { - JSON_Value *val = json_object_dotget_value(object, name); - return val != NULL && json_value_get_type(val) == type; +int +json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) +{ + JSON_Value *val = json_object_dotget_value(object, name); + return val != NULL && json_value_get_type(val) == type; } /* JSON Array API */ -JSON_Value * json_array_get_value(const JSON_Array *array, size_t index) { - if (array == NULL || index >= json_array_get_count(array)) { - return NULL; - } - return array->items[index]; +JSON_Value * +json_array_get_value(const JSON_Array *array, size_t index) +{ + if (array == NULL || index >= json_array_get_count(array)) { + return NULL; + } + return array->items[index]; } -const char * json_array_get_string(const JSON_Array *array, size_t index) { - return json_value_get_string(json_array_get_value(array, index)); +const char * +json_array_get_string(const JSON_Array *array, size_t index) +{ + return json_value_get_string(json_array_get_value(array, index)); } -size_t json_array_get_string_len(const JSON_Array *array, size_t index) { - return json_value_get_string_len(json_array_get_value(array, index)); +size_t +json_array_get_string_len(const JSON_Array *array, size_t index) +{ + return json_value_get_string_len(json_array_get_value(array, index)); } -double json_array_get_number(const JSON_Array *array, size_t index) { - return json_value_get_number(json_array_get_value(array, index)); +double +json_array_get_number(const JSON_Array *array, size_t index) +{ + return json_value_get_number(json_array_get_value(array, index)); } -JSON_Object * json_array_get_object(const JSON_Array *array, size_t index) { - return json_value_get_object(json_array_get_value(array, index)); +JSON_Object * +json_array_get_object(const JSON_Array *array, size_t index) +{ + return json_value_get_object(json_array_get_value(array, index)); } -JSON_Array * json_array_get_array(const JSON_Array *array, size_t index) { - return json_value_get_array(json_array_get_value(array, index)); +JSON_Array * +json_array_get_array(const JSON_Array *array, size_t index) +{ + return json_value_get_array(json_array_get_value(array, index)); } -int json_array_get_boolean(const JSON_Array *array, size_t index) { - return json_value_get_boolean(json_array_get_value(array, index)); +int +json_array_get_boolean(const JSON_Array *array, size_t index) +{ + return json_value_get_boolean(json_array_get_value(array, index)); } -size_t json_array_get_count(const JSON_Array *array) { - return array ? array->count : 0; +size_t +json_array_get_count(const JSON_Array *array) +{ + return array ? array->count : 0; } -JSON_Value * json_array_get_wrapping_value(const JSON_Array *array) { - return array->wrapping_value; +JSON_Value * +json_array_get_wrapping_value(const JSON_Array *array) +{ + return array->wrapping_value; } /* JSON Value API */ -JSON_Value_Type json_value_get_type(const JSON_Value *value) { - return value ? value->type : JSONError; -} - -JSON_Object * json_value_get_object(const JSON_Value *value) { - return json_value_get_type(value) == JSONObject ? value->value.object : NULL; -} - -JSON_Array * json_value_get_array(const JSON_Value *value) { - return json_value_get_type(value) == JSONArray ? value->value.array : NULL; -} - -static const JSON_String * json_value_get_string_desc(const JSON_Value *value) { - return json_value_get_type(value) == JSONString ? &value->value.string : NULL; -} - -const char * json_value_get_string(const JSON_Value *value) { - const JSON_String *str = json_value_get_string_desc(value); - return str ? str->chars : NULL; -} - -size_t json_value_get_string_len(const JSON_Value *value) { - const JSON_String *str = json_value_get_string_desc(value); - return str ? str->length : 0; -} - -double json_value_get_number(const JSON_Value *value) { - return json_value_get_type(value) == JSONNumber ? value->value.number : 0; -} - -int json_value_get_boolean(const JSON_Value *value) { - return json_value_get_type(value) == JSONBoolean ? value->value.boolean : -1; -} - -JSON_Value * json_value_get_parent (const JSON_Value *value) { - return value ? value->parent : NULL; -} - -void json_value_free(JSON_Value *value) { - switch (json_value_get_type(value)) { - case JSONObject: - json_object_free(value->value.object); - break; - case JSONString: - parson_free(value->value.string.chars); - break; - case JSONArray: - json_array_free(value->value.array); - break; - default: - break; - } - parson_free(value); -} - -JSON_Value * json_value_init_object(void) { - JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); - if (!new_value) { - return NULL; - } - new_value->parent = NULL; - new_value->type = JSONObject; - new_value->value.object = json_object_init(new_value); - if (!new_value->value.object) { - parson_free(new_value); - return NULL; - } - return new_value; -} - -JSON_Value * json_value_init_array(void) { - JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); - if (!new_value) { - return NULL; - } - new_value->parent = NULL; - new_value->type = JSONArray; - new_value->value.array = json_array_init(new_value); - if (!new_value->value.array) { - parson_free(new_value); - return NULL; - } - return new_value; -} - -JSON_Value * json_value_init_string(const char *string) { - if (string == NULL) { - return NULL; - } - return json_value_init_string_with_len(string, strlen(string)); -} - -JSON_Value * json_value_init_string_with_len(const char *string, size_t length) { - char *copy = NULL; - JSON_Value *value; - if (string == NULL) { - return NULL; - } - if (!is_valid_utf8(string, length)) { - return NULL; - } - copy = parson_strndup(string, length); - if (copy == NULL) { - return NULL; - } - value = json_value_init_string_no_copy(copy, length); - if (value == NULL) { - parson_free(copy); - } - return value; -} - -JSON_Value * json_value_init_number(double number) { - JSON_Value *new_value = NULL; - if (IS_NUMBER_INVALID(number)) { - return NULL; - } - new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); - if (new_value == NULL) { - return NULL; - } - new_value->parent = NULL; - new_value->type = JSONNumber; - new_value->value.number = number; - return new_value; -} - -JSON_Value * json_value_init_boolean(int boolean) { - JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); - if (!new_value) { - return NULL; - } - new_value->parent = NULL; - new_value->type = JSONBoolean; - new_value->value.boolean = boolean ? 1 : 0; - return new_value; -} - -JSON_Value * json_value_init_null(void) { - JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); - if (!new_value) { - return NULL; - } - new_value->parent = NULL; - new_value->type = JSONNull; - return new_value; -} - -JSON_Value * json_value_deep_copy(const JSON_Value *value) { - size_t i = 0; - JSON_Value *return_value = NULL, *temp_value_copy = NULL, *temp_value = NULL; - const JSON_String *temp_string = NULL; - const char *temp_key = NULL; - char *temp_string_copy = NULL; - JSON_Array *temp_array = NULL, *temp_array_copy = NULL; - JSON_Object *temp_object = NULL, *temp_object_copy = NULL; - - switch (json_value_get_type(value)) { - case JSONArray: - temp_array = json_value_get_array(value); - return_value = json_value_init_array(); - if (return_value == NULL) { - return NULL; - } - temp_array_copy = json_value_get_array(return_value); - for (i = 0; i < json_array_get_count(temp_array); i++) { - temp_value = json_array_get_value(temp_array, i); - temp_value_copy = json_value_deep_copy(temp_value); - if (temp_value_copy == NULL) { - json_value_free(return_value); - return NULL; - } - if (json_array_add(temp_array_copy, temp_value_copy) == JSONFailure) { - json_value_free(return_value); - json_value_free(temp_value_copy); - return NULL; - } - } - return return_value; - case JSONObject: - temp_object = json_value_get_object(value); - return_value = json_value_init_object(); - if (return_value == NULL) { - return NULL; - } - temp_object_copy = json_value_get_object(return_value); - for (i = 0; i < json_object_get_count(temp_object); i++) { - temp_key = json_object_get_name(temp_object, i); - temp_value = json_object_get_value(temp_object, temp_key); - temp_value_copy = json_value_deep_copy(temp_value); - if (temp_value_copy == NULL) { - json_value_free(return_value); - return NULL; - } - if (json_object_add(temp_object_copy, temp_key, temp_value_copy) == JSONFailure) { - json_value_free(return_value); - json_value_free(temp_value_copy); - return NULL; - } - } - return return_value; - case JSONBoolean: - return json_value_init_boolean(json_value_get_boolean(value)); - case JSONNumber: - return json_value_init_number(json_value_get_number(value)); - case JSONString: - temp_string = json_value_get_string_desc(value); - if (temp_string == NULL) { - return NULL; - } - temp_string_copy = parson_strndup(temp_string->chars, temp_string->length); - if (temp_string_copy == NULL) { - return NULL; - } - return_value = json_value_init_string_no_copy(temp_string_copy, temp_string->length); - if (return_value == NULL) { - parson_free(temp_string_copy); - } - return return_value; - case JSONNull: - return json_value_init_null(); - case JSONError: - return NULL; - default: - return NULL; - } -} - -size_t json_serialization_size(const JSON_Value *value) { - char num_buf[NUM_BUF_SIZE]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */ - int res = json_serialize_to_buffer_r(value, NULL, 0, 0, num_buf); - return res < 0 ? 0 : (size_t)(res) + 1; -} - -JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) { - int written = -1; - size_t needed_size_in_bytes = json_serialization_size(value); - if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) { - return JSONFailure; - } - written = json_serialize_to_buffer_r(value, buf, 0, 0, NULL); - if (written < 0) { - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename) { - JSON_Status return_code = JSONSuccess; - FILE *fp = NULL; - char *serialized_string = json_serialize_to_string(value); - if (serialized_string == NULL) { - return JSONFailure; - } - fp = fopen(filename, "w"); - if (fp == NULL) { - json_free_serialized_string(serialized_string); - return JSONFailure; - } - if (fputs(serialized_string, fp) == EOF) { - return_code = JSONFailure; - } - if (fclose(fp) == EOF) { - return_code = JSONFailure; - } - json_free_serialized_string(serialized_string); - return return_code; -} - -char * json_serialize_to_string(const JSON_Value *value) { - JSON_Status serialization_result = JSONFailure; - size_t buf_size_bytes = json_serialization_size(value); - char *buf = NULL; - if (buf_size_bytes == 0) { - return NULL; - } - buf = (char*)parson_malloc(buf_size_bytes); - if (buf == NULL) { - return NULL; - } - serialization_result = json_serialize_to_buffer(value, buf, buf_size_bytes); - if (serialization_result == JSONFailure) { - json_free_serialized_string(buf); - return NULL; - } - return buf; -} - -size_t json_serialization_size_pretty(const JSON_Value *value) { - char num_buf[NUM_BUF_SIZE]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */ - int res = json_serialize_to_buffer_r(value, NULL, 0, 1, num_buf); - return res < 0 ? 0 : (size_t)(res) + 1; -} - -JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) { - int written = -1; - size_t needed_size_in_bytes = json_serialization_size_pretty(value); - if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) { - return JSONFailure; - } - written = json_serialize_to_buffer_r(value, buf, 0, 1, NULL); - if (written < 0) { - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename) { - JSON_Status return_code = JSONSuccess; - FILE *fp = NULL; - char *serialized_string = json_serialize_to_string_pretty(value); - if (serialized_string == NULL) { - return JSONFailure; - } - fp = fopen(filename, "w"); - if (fp == NULL) { - json_free_serialized_string(serialized_string); - return JSONFailure; - } - if (fputs(serialized_string, fp) == EOF) { - return_code = JSONFailure; - } - if (fclose(fp) == EOF) { - return_code = JSONFailure; - } - json_free_serialized_string(serialized_string); - return return_code; -} - -char * json_serialize_to_string_pretty(const JSON_Value *value) { - JSON_Status serialization_result = JSONFailure; - size_t buf_size_bytes = json_serialization_size_pretty(value); - char *buf = NULL; - if (buf_size_bytes == 0) { - return NULL; - } - buf = (char*)parson_malloc(buf_size_bytes); - if (buf == NULL) { - return NULL; - } - serialization_result = json_serialize_to_buffer_pretty(value, buf, buf_size_bytes); - if (serialization_result == JSONFailure) { - json_free_serialized_string(buf); - return NULL; - } - return buf; -} - -void json_free_serialized_string(char *string) { - parson_free(string); -} - -JSON_Status json_array_remove(JSON_Array *array, size_t ix) { - size_t to_move_bytes = 0; - if (array == NULL || ix >= json_array_get_count(array)) { - return JSONFailure; - } - json_value_free(json_array_get_value(array, ix)); - to_move_bytes = (json_array_get_count(array) - 1 - ix) * sizeof(JSON_Value*); - memmove(array->items + ix, array->items + ix + 1, to_move_bytes); - array->count -= 1; - return JSONSuccess; -} - -JSON_Status json_array_replace_value(JSON_Array *array, size_t ix, JSON_Value *value) { - if (array == NULL || value == NULL || value->parent != NULL || ix >= json_array_get_count(array)) { - return JSONFailure; - } - json_value_free(json_array_get_value(array, ix)); - value->parent = json_array_get_wrapping_value(array); - array->items[ix] = value; - return JSONSuccess; -} - -JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string) { - JSON_Value *value = json_value_init_string(string); - if (value == NULL) { - return JSONFailure; - } - if (json_array_replace_value(array, i, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_array_replace_string_with_len(JSON_Array *array, size_t i, const char *string, size_t len) { - JSON_Value *value = json_value_init_string_with_len(string, len); - if (value == NULL) { - return JSONFailure; - } - if (json_array_replace_value(array, i, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number) { - JSON_Value *value = json_value_init_number(number); - if (value == NULL) { - return JSONFailure; - } - if (json_array_replace_value(array, i, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean) { - JSON_Value *value = json_value_init_boolean(boolean); - if (value == NULL) { - return JSONFailure; - } - if (json_array_replace_value(array, i, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_array_replace_null(JSON_Array *array, size_t i) { - JSON_Value *value = json_value_init_null(); - if (value == NULL) { - return JSONFailure; - } - if (json_array_replace_value(array, i, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_array_clear(JSON_Array *array) { - size_t i = 0; - if (array == NULL) { - return JSONFailure; - } - for (i = 0; i < json_array_get_count(array); i++) { - json_value_free(json_array_get_value(array, i)); - } - array->count = 0; - return JSONSuccess; -} - -JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value) { - if (array == NULL || value == NULL || value->parent != NULL) { - return JSONFailure; - } - return json_array_add(array, value); -} - -JSON_Status json_array_append_string(JSON_Array *array, const char *string) { - JSON_Value *value = json_value_init_string(string); - if (value == NULL) { - return JSONFailure; - } - if (json_array_append_value(array, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_array_append_string_with_len(JSON_Array *array, const char *string, size_t len) { - JSON_Value *value = json_value_init_string_with_len(string, len); - if (value == NULL) { - return JSONFailure; - } - if (json_array_append_value(array, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_array_append_number(JSON_Array *array, double number) { - JSON_Value *value = json_value_init_number(number); - if (value == NULL) { - return JSONFailure; - } - if (json_array_append_value(array, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_array_append_boolean(JSON_Array *array, int boolean) { - JSON_Value *value = json_value_init_boolean(boolean); - if (value == NULL) { - return JSONFailure; - } - if (json_array_append_value(array, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_array_append_null(JSON_Array *array) { - JSON_Value *value = json_value_init_null(); - if (value == NULL) { - return JSONFailure; - } - if (json_array_append_value(array, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value) { - size_t i = 0; - JSON_Value *old_value; - if (object == NULL || name == NULL || value == NULL || value->parent != NULL) { - return JSONFailure; - } - old_value = json_object_get_value(object, name); - if (old_value != NULL) { /* free and overwrite old value */ - json_value_free(old_value); - for (i = 0; i < json_object_get_count(object); i++) { - if (strcmp(object->names[i], name) == 0) { - value->parent = json_object_get_wrapping_value(object); - object->values[i] = value; - return JSONSuccess; - } - } - } - /* add new key value pair */ - return json_object_add(object, name, value); -} - -JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string) { - JSON_Value *value = json_value_init_string(string); - JSON_Status status = json_object_set_value(object, name, value); - if (status == JSONFailure) { - json_value_free(value); - } - return status; -} - -JSON_Status json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len) { - JSON_Value *value = json_value_init_string_with_len(string, len); - JSON_Status status = json_object_set_value(object, name, value); - if (status == JSONFailure) { - json_value_free(value); - } - return status; -} - -JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number) { - JSON_Value *value = json_value_init_number(number); - JSON_Status status = json_object_set_value(object, name, value); - if (status == JSONFailure) { - json_value_free(value); - } - return status; -} - -JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean) { - JSON_Value *value = json_value_init_boolean(boolean); - JSON_Status status = json_object_set_value(object, name, value); - if (status == JSONFailure) { - json_value_free(value); - } - return status; -} - -JSON_Status json_object_set_null(JSON_Object *object, const char *name) { - JSON_Value *value = json_value_init_null(); - JSON_Status status = json_object_set_value(object, name, value); - if (status == JSONFailure) { - json_value_free(value); - } - return status; -} - -JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value) { - const char *dot_pos = NULL; - JSON_Value *temp_value = NULL, *new_value = NULL; - JSON_Object *temp_object = NULL, *new_object = NULL; - JSON_Status status = JSONFailure; - size_t name_len = 0; - if (object == NULL || name == NULL || value == NULL) { - return JSONFailure; - } - dot_pos = strchr(name, '.'); - if (dot_pos == NULL) { - return json_object_set_value(object, name, value); - } - name_len = dot_pos - name; - temp_value = json_object_getn_value(object, name, name_len); - if (temp_value) { - /* Don't overwrite existing non-object (unlike json_object_set_value, but it shouldn't be changed at this point) */ - if (json_value_get_type(temp_value) != JSONObject) { - return JSONFailure; - } - temp_object = json_value_get_object(temp_value); - return json_object_dotset_value(temp_object, dot_pos + 1, value); - } - new_value = json_value_init_object(); - if (new_value == NULL) { - return JSONFailure; - } - new_object = json_value_get_object(new_value); - status = json_object_dotset_value(new_object, dot_pos + 1, value); - if (status != JSONSuccess) { - json_value_free(new_value); - return JSONFailure; - } - status = json_object_addn(object, name, name_len, new_value); - if (status != JSONSuccess) { - json_object_dotremove_internal(new_object, dot_pos + 1, 0); - json_value_free(new_value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string) { - JSON_Value *value = json_value_init_string(string); - if (value == NULL) { - return JSONFailure; - } - if (json_object_dotset_value(object, name, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_object_dotset_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len) { - JSON_Value *value = json_value_init_string_with_len(string, len); - if (value == NULL) { - return JSONFailure; - } - if (json_object_dotset_value(object, name, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number) { - JSON_Value *value = json_value_init_number(number); - if (value == NULL) { - return JSONFailure; - } - if (json_object_dotset_value(object, name, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean) { - JSON_Value *value = json_value_init_boolean(boolean); - if (value == NULL) { - return JSONFailure; - } - if (json_object_dotset_value(object, name, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_object_dotset_null(JSON_Object *object, const char *name) { - JSON_Value *value = json_value_init_null(); - if (value == NULL) { - return JSONFailure; - } - if (json_object_dotset_value(object, name, value) == JSONFailure) { - json_value_free(value); - return JSONFailure; - } - return JSONSuccess; -} - -JSON_Status json_object_remove(JSON_Object *object, const char *name) { - return json_object_remove_internal(object, name, 1); -} - -JSON_Status json_object_dotremove(JSON_Object *object, const char *name) { - return json_object_dotremove_internal(object, name, 1); -} - -JSON_Status json_object_clear(JSON_Object *object) { - size_t i = 0; - if (object == NULL) { - return JSONFailure; - } - for (i = 0; i < json_object_get_count(object); i++) { - parson_free(object->names[i]); - json_value_free(object->values[i]); - } - object->count = 0; - return JSONSuccess; -} - -JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value) { - JSON_Value *temp_schema_value = NULL, *temp_value = NULL; - JSON_Array *schema_array = NULL, *value_array = NULL; - JSON_Object *schema_object = NULL, *value_object = NULL; - JSON_Value_Type schema_type = JSONError, value_type = JSONError; - const char *key = NULL; - size_t i = 0, count = 0; - if (schema == NULL || value == NULL) { - return JSONFailure; - } - schema_type = json_value_get_type(schema); - value_type = json_value_get_type(value); - if (schema_type != value_type && schema_type != JSONNull) { /* null represents all values */ - return JSONFailure; - } - switch (schema_type) { - case JSONArray: - schema_array = json_value_get_array(schema); - value_array = json_value_get_array(value); - count = json_array_get_count(schema_array); - if (count == 0) { - return JSONSuccess; /* Empty array allows all types */ - } - /* Get first value from array, rest is ignored */ - temp_schema_value = json_array_get_value(schema_array, 0); - for (i = 0; i < json_array_get_count(value_array); i++) { - temp_value = json_array_get_value(value_array, i); - if (json_validate(temp_schema_value, temp_value) == JSONFailure) { - return JSONFailure; - } - } - return JSONSuccess; - case JSONObject: - schema_object = json_value_get_object(schema); - value_object = json_value_get_object(value); - count = json_object_get_count(schema_object); - if (count == 0) { - return JSONSuccess; /* Empty object allows all objects */ - } else if (json_object_get_count(value_object) < count) { - return JSONFailure; /* Tested object mustn't have less name-value pairs than schema */ - } - for (i = 0; i < count; i++) { - key = json_object_get_name(schema_object, i); - temp_schema_value = json_object_get_value(schema_object, key); - temp_value = json_object_get_value(value_object, key); - if (temp_value == NULL) { - return JSONFailure; - } - if (json_validate(temp_schema_value, temp_value) == JSONFailure) { - return JSONFailure; - } - } - return JSONSuccess; - case JSONString: case JSONNumber: case JSONBoolean: case JSONNull: - return JSONSuccess; /* equality already tested before switch */ - case JSONError: default: - return JSONFailure; - } -} - -int json_value_equals(const JSON_Value *a, const JSON_Value *b) { - JSON_Object *a_object = NULL, *b_object = NULL; - JSON_Array *a_array = NULL, *b_array = NULL; - const JSON_String *a_string = NULL, *b_string = NULL; - const char *key = NULL; - size_t a_count = 0, b_count = 0, i = 0; - JSON_Value_Type a_type, b_type; - a_type = json_value_get_type(a); - b_type = json_value_get_type(b); - if (a_type != b_type) { - return 0; - } - switch (a_type) { - case JSONArray: - a_array = json_value_get_array(a); - b_array = json_value_get_array(b); - a_count = json_array_get_count(a_array); - b_count = json_array_get_count(b_array); - if (a_count != b_count) { - return 0; - } - for (i = 0; i < a_count; i++) { - if (!json_value_equals(json_array_get_value(a_array, i), - json_array_get_value(b_array, i))) { - return 0; - } - } - return 1; - case JSONObject: - a_object = json_value_get_object(a); - b_object = json_value_get_object(b); - a_count = json_object_get_count(a_object); - b_count = json_object_get_count(b_object); - if (a_count != b_count) { - return 0; - } - for (i = 0; i < a_count; i++) { - key = json_object_get_name(a_object, i); - if (!json_value_equals(json_object_get_value(a_object, key), - json_object_get_value(b_object, key))) { - return 0; - } - } - return 1; - case JSONString: - a_string = json_value_get_string_desc(a); - b_string = json_value_get_string_desc(b); - if (a_string == NULL || b_string == NULL) { - return 0; /* shouldn't happen */ - } - return a_string->length == b_string->length && - memcmp(a_string->chars, b_string->chars, a_string->length) == 0; - case JSONBoolean: - return json_value_get_boolean(a) == json_value_get_boolean(b); - case JSONNumber: - return fabs(json_value_get_number(a) - json_value_get_number(b)) < 0.000001; /* EPSILON */ - case JSONError: - return 1; - case JSONNull: - return 1; - default: - return 1; - } -} - -JSON_Value_Type json_type(const JSON_Value *value) { - return json_value_get_type(value); -} - -JSON_Object * json_object (const JSON_Value *value) { - return json_value_get_object(value); -} - -JSON_Array * json_array (const JSON_Value *value) { - return json_value_get_array(value); -} - -const char * json_string (const JSON_Value *value) { - return json_value_get_string(value); -} - -size_t json_string_len(const JSON_Value *value) { - return json_value_get_string_len(value); -} - -double json_number (const JSON_Value *value) { - return json_value_get_number(value); -} - -int json_boolean(const JSON_Value *value) { - return json_value_get_boolean(value); -} - -void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun) { - parson_malloc = malloc_fun; - parson_free = free_fun; -} - -void json_set_escape_slashes(int escape_slashes) { - parson_escape_slashes = escape_slashes; +JSON_Value_Type +json_value_get_type(const JSON_Value *value) +{ + return value ? value->type : JSONError; +} + +JSON_Object * +json_value_get_object(const JSON_Value *value) +{ + return json_value_get_type(value) == JSONObject ? value->value.object : NULL; +} + +JSON_Array * +json_value_get_array(const JSON_Value *value) +{ + return json_value_get_type(value) == JSONArray ? value->value.array : NULL; +} + +static const JSON_String * +json_value_get_string_desc(const JSON_Value *value) +{ + return json_value_get_type(value) == JSONString ? &value->value.string : NULL; +} + +const char * +json_value_get_string(const JSON_Value *value) +{ + const JSON_String *str = json_value_get_string_desc(value); + return str ? str->chars : NULL; +} + +size_t +json_value_get_string_len(const JSON_Value *value) +{ + const JSON_String *str = json_value_get_string_desc(value); + return str ? str->length : 0; +} + +double +json_value_get_number(const JSON_Value *value) +{ + return json_value_get_type(value) == JSONNumber ? value->value.number : 0; +} + +int +json_value_get_boolean(const JSON_Value *value) +{ + return json_value_get_type(value) == JSONBoolean ? value->value.boolean : -1; +} + +JSON_Value * +json_value_get_parent(const JSON_Value *value) +{ + return value ? value->parent : NULL; +} + +void +json_value_free(JSON_Value *value) +{ + switch (json_value_get_type(value)) { + case JSONObject: + json_object_free(value->value.object); + break; + case JSONString: + parson_free(value->value.string.chars); + break; + case JSONArray: + json_array_free(value->value.array); + break; + default: + break; + } + parson_free(value); +} + +JSON_Value * +json_value_init_object(void) +{ + JSON_Value *new_value = (JSON_Value *) parson_malloc(sizeof(JSON_Value)); + if (!new_value) { + return NULL; + } + new_value->parent = NULL; + new_value->type = JSONObject; + new_value->value.object = json_object_init(new_value); + if (!new_value->value.object) { + parson_free(new_value); + return NULL; + } + return new_value; +} + +JSON_Value * +json_value_init_array(void) +{ + JSON_Value *new_value = (JSON_Value *) parson_malloc(sizeof(JSON_Value)); + if (!new_value) { + return NULL; + } + new_value->parent = NULL; + new_value->type = JSONArray; + new_value->value.array = json_array_init(new_value); + if (!new_value->value.array) { + parson_free(new_value); + return NULL; + } + return new_value; +} + +JSON_Value * +json_value_init_string(const char *string) +{ + if (string == NULL) { + return NULL; + } + return json_value_init_string_with_len(string, strlen(string)); +} + +JSON_Value * +json_value_init_string_with_len(const char *string, size_t length) +{ + char *copy = NULL; + JSON_Value *value; + if (string == NULL) { + return NULL; + } + if (!is_valid_utf8(string, length)) { + return NULL; + } + copy = parson_strndup(string, length); + if (copy == NULL) { + return NULL; + } + value = json_value_init_string_no_copy(copy, length); + if (value == NULL) { + parson_free(copy); + } + return value; +} + +JSON_Value * +json_value_init_number(double number) +{ + JSON_Value *new_value = NULL; + if (IS_NUMBER_INVALID(number)) { + return NULL; + } + new_value = (JSON_Value *) parson_malloc(sizeof(JSON_Value)); + if (new_value == NULL) { + return NULL; + } + new_value->parent = NULL; + new_value->type = JSONNumber; + new_value->value.number = number; + return new_value; +} + +JSON_Value * +json_value_init_boolean(int boolean) +{ + JSON_Value *new_value = (JSON_Value *) parson_malloc(sizeof(JSON_Value)); + if (!new_value) { + return NULL; + } + new_value->parent = NULL; + new_value->type = JSONBoolean; + new_value->value.boolean = boolean ? 1 : 0; + return new_value; +} + +JSON_Value * +json_value_init_null(void) +{ + JSON_Value *new_value = (JSON_Value *) parson_malloc(sizeof(JSON_Value)); + if (!new_value) { + return NULL; + } + new_value->parent = NULL; + new_value->type = JSONNull; + return new_value; +} + +JSON_Value * +json_value_deep_copy(const JSON_Value *value) +{ + size_t i = 0; + JSON_Value *return_value = NULL, *temp_value_copy = NULL, *temp_value = NULL; + const JSON_String *temp_string = NULL; + const char *temp_key = NULL; + char *temp_string_copy = NULL; + JSON_Array *temp_array = NULL, *temp_array_copy = NULL; + JSON_Object *temp_object = NULL, *temp_object_copy = NULL; + + switch (json_value_get_type(value)) { + case JSONArray: + temp_array = json_value_get_array(value); + return_value = json_value_init_array(); + if (return_value == NULL) { + return NULL; + } + temp_array_copy = json_value_get_array(return_value); + for (i = 0; i < json_array_get_count(temp_array); i++) { + temp_value = json_array_get_value(temp_array, i); + temp_value_copy = json_value_deep_copy(temp_value); + if (temp_value_copy == NULL) { + json_value_free(return_value); + return NULL; + } + if (json_array_add(temp_array_copy, temp_value_copy) == JSONFailure) { + json_value_free(return_value); + json_value_free(temp_value_copy); + return NULL; + } + } + return return_value; + case JSONObject: + temp_object = json_value_get_object(value); + return_value = json_value_init_object(); + if (return_value == NULL) { + return NULL; + } + temp_object_copy = json_value_get_object(return_value); + for (i = 0; i < json_object_get_count(temp_object); i++) { + temp_key = json_object_get_name(temp_object, i); + temp_value = json_object_get_value(temp_object, temp_key); + temp_value_copy = json_value_deep_copy(temp_value); + if (temp_value_copy == NULL) { + json_value_free(return_value); + return NULL; + } + if (json_object_add(temp_object_copy, temp_key, temp_value_copy) == JSONFailure) { + json_value_free(return_value); + json_value_free(temp_value_copy); + return NULL; + } + } + return return_value; + case JSONBoolean: + return json_value_init_boolean(json_value_get_boolean(value)); + case JSONNumber: + return json_value_init_number(json_value_get_number(value)); + case JSONString: + temp_string = json_value_get_string_desc(value); + if (temp_string == NULL) { + return NULL; + } + temp_string_copy = parson_strndup(temp_string->chars, temp_string->length); + if (temp_string_copy == NULL) { + return NULL; + } + return_value = json_value_init_string_no_copy(temp_string_copy, temp_string->length); + if (return_value == NULL) { + parson_free(temp_string_copy); + } + return return_value; + case JSONNull: + return json_value_init_null(); + case JSONError: + return NULL; + default: + return NULL; + } +} + +size_t +json_serialization_size(const JSON_Value *value) +{ + char num_buf[NUM_BUF_SIZE]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */ + int res = json_serialize_to_buffer_r(value, NULL, 0, 0, num_buf); + return res < 0 ? 0 : (size_t) (res) + 1; +} + +JSON_Status +json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) +{ + int written = -1; + size_t needed_size_in_bytes = json_serialization_size(value); + if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) { + return JSONFailure; + } + written = json_serialize_to_buffer_r(value, buf, 0, 0, NULL); + if (written < 0) { + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_serialize_to_file(const JSON_Value *value, const char *filename) +{ + JSON_Status return_code = JSONSuccess; + FILE *fp = NULL; + char *serialized_string = json_serialize_to_string(value); + if (serialized_string == NULL) { + return JSONFailure; + } + fp = fopen(filename, "w"); + if (fp == NULL) { + json_free_serialized_string(serialized_string); + return JSONFailure; + } + if (fputs(serialized_string, fp) == EOF) { + return_code = JSONFailure; + } + if (fclose(fp) == EOF) { + return_code = JSONFailure; + } + json_free_serialized_string(serialized_string); + return return_code; +} + +char * +json_serialize_to_string(const JSON_Value *value) +{ + JSON_Status serialization_result = JSONFailure; + size_t buf_size_bytes = json_serialization_size(value); + char *buf = NULL; + if (buf_size_bytes == 0) { + return NULL; + } + buf = (char *) parson_malloc(buf_size_bytes); + if (buf == NULL) { + return NULL; + } + serialization_result = json_serialize_to_buffer(value, buf, buf_size_bytes); + if (serialization_result == JSONFailure) { + json_free_serialized_string(buf); + return NULL; + } + return buf; +} + +size_t +json_serialization_size_pretty(const JSON_Value *value) +{ + char num_buf[NUM_BUF_SIZE]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */ + int res = json_serialize_to_buffer_r(value, NULL, 0, 1, num_buf); + return res < 0 ? 0 : (size_t) (res) + 1; +} + +JSON_Status +json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) +{ + int written = -1; + size_t needed_size_in_bytes = json_serialization_size_pretty(value); + if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) { + return JSONFailure; + } + written = json_serialize_to_buffer_r(value, buf, 0, 1, NULL); + if (written < 0) { + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_serialize_to_file_pretty(const JSON_Value *value, const char *filename) +{ + JSON_Status return_code = JSONSuccess; + FILE *fp = NULL; + char *serialized_string = json_serialize_to_string_pretty(value); + if (serialized_string == NULL) { + return JSONFailure; + } + fp = fopen(filename, "w"); + if (fp == NULL) { + json_free_serialized_string(serialized_string); + return JSONFailure; + } + if (fputs(serialized_string, fp) == EOF) { + return_code = JSONFailure; + } + if (fclose(fp) == EOF) { + return_code = JSONFailure; + } + json_free_serialized_string(serialized_string); + return return_code; +} + +char * +json_serialize_to_string_pretty(const JSON_Value *value) +{ + JSON_Status serialization_result = JSONFailure; + size_t buf_size_bytes = json_serialization_size_pretty(value); + char *buf = NULL; + if (buf_size_bytes == 0) { + return NULL; + } + buf = (char *) parson_malloc(buf_size_bytes); + if (buf == NULL) { + return NULL; + } + serialization_result = json_serialize_to_buffer_pretty(value, buf, buf_size_bytes); + if (serialization_result == JSONFailure) { + json_free_serialized_string(buf); + return NULL; + } + return buf; +} + +void +json_free_serialized_string(char *string) +{ + parson_free(string); +} + +JSON_Status +json_array_remove(JSON_Array *array, size_t ix) +{ + size_t to_move_bytes = 0; + if (array == NULL || ix >= json_array_get_count(array)) { + return JSONFailure; + } + json_value_free(json_array_get_value(array, ix)); + to_move_bytes = (json_array_get_count(array) - 1 - ix) * sizeof(JSON_Value *); + memmove(array->items + ix, array->items + ix + 1, to_move_bytes); + array->count -= 1; + return JSONSuccess; +} + +JSON_Status +json_array_replace_value(JSON_Array *array, size_t ix, JSON_Value *value) +{ + if (array == NULL || value == NULL || value->parent != NULL || ix >= json_array_get_count(array)) { + return JSONFailure; + } + json_value_free(json_array_get_value(array, ix)); + value->parent = json_array_get_wrapping_value(array); + array->items[ix] = value; + return JSONSuccess; +} + +JSON_Status +json_array_replace_string(JSON_Array *array, size_t i, const char *string) +{ + JSON_Value *value = json_value_init_string(string); + if (value == NULL) { + return JSONFailure; + } + if (json_array_replace_value(array, i, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_array_replace_string_with_len(JSON_Array *array, size_t i, const char *string, size_t len) +{ + JSON_Value *value = json_value_init_string_with_len(string, len); + if (value == NULL) { + return JSONFailure; + } + if (json_array_replace_value(array, i, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_array_replace_number(JSON_Array *array, size_t i, double number) +{ + JSON_Value *value = json_value_init_number(number); + if (value == NULL) { + return JSONFailure; + } + if (json_array_replace_value(array, i, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_array_replace_boolean(JSON_Array *array, size_t i, int boolean) +{ + JSON_Value *value = json_value_init_boolean(boolean); + if (value == NULL) { + return JSONFailure; + } + if (json_array_replace_value(array, i, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_array_replace_null(JSON_Array *array, size_t i) +{ + JSON_Value *value = json_value_init_null(); + if (value == NULL) { + return JSONFailure; + } + if (json_array_replace_value(array, i, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_array_clear(JSON_Array *array) +{ + size_t i = 0; + if (array == NULL) { + return JSONFailure; + } + for (i = 0; i < json_array_get_count(array); i++) { + json_value_free(json_array_get_value(array, i)); + } + array->count = 0; + return JSONSuccess; +} + +JSON_Status +json_array_append_value(JSON_Array *array, JSON_Value *value) +{ + if (array == NULL || value == NULL || value->parent != NULL) { + return JSONFailure; + } + return json_array_add(array, value); +} + +JSON_Status +json_array_append_string(JSON_Array *array, const char *string) +{ + JSON_Value *value = json_value_init_string(string); + if (value == NULL) { + return JSONFailure; + } + if (json_array_append_value(array, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_array_append_string_with_len(JSON_Array *array, const char *string, size_t len) +{ + JSON_Value *value = json_value_init_string_with_len(string, len); + if (value == NULL) { + return JSONFailure; + } + if (json_array_append_value(array, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_array_append_number(JSON_Array *array, double number) +{ + JSON_Value *value = json_value_init_number(number); + if (value == NULL) { + return JSONFailure; + } + if (json_array_append_value(array, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_array_append_boolean(JSON_Array *array, int boolean) +{ + JSON_Value *value = json_value_init_boolean(boolean); + if (value == NULL) { + return JSONFailure; + } + if (json_array_append_value(array, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_array_append_null(JSON_Array *array) +{ + JSON_Value *value = json_value_init_null(); + if (value == NULL) { + return JSONFailure; + } + if (json_array_append_value(array, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value) +{ + size_t i = 0; + JSON_Value *old_value; + if (object == NULL || name == NULL || value == NULL || value->parent != NULL) { + return JSONFailure; + } + old_value = json_object_get_value(object, name); + if (old_value != NULL) { /* free and overwrite old value */ + json_value_free(old_value); + for (i = 0; i < json_object_get_count(object); i++) { + if (strcmp(object->names[i], name) == 0) { + value->parent = json_object_get_wrapping_value(object); + object->values[i] = value; + return JSONSuccess; + } + } + } + /* add new key value pair */ + return json_object_add(object, name, value); +} + +JSON_Status +json_object_set_string(JSON_Object *object, const char *name, const char *string) +{ + JSON_Value *value = json_value_init_string(string); + JSON_Status status = json_object_set_value(object, name, value); + if (status == JSONFailure) { + json_value_free(value); + } + return status; +} + +JSON_Status +json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len) +{ + JSON_Value *value = json_value_init_string_with_len(string, len); + JSON_Status status = json_object_set_value(object, name, value); + if (status == JSONFailure) { + json_value_free(value); + } + return status; +} + +JSON_Status +json_object_set_number(JSON_Object *object, const char *name, double number) +{ + JSON_Value *value = json_value_init_number(number); + JSON_Status status = json_object_set_value(object, name, value); + if (status == JSONFailure) { + json_value_free(value); + } + return status; +} + +JSON_Status +json_object_set_boolean(JSON_Object *object, const char *name, int boolean) +{ + JSON_Value *value = json_value_init_boolean(boolean); + JSON_Status status = json_object_set_value(object, name, value); + if (status == JSONFailure) { + json_value_free(value); + } + return status; +} + +JSON_Status +json_object_set_null(JSON_Object *object, const char *name) +{ + JSON_Value *value = json_value_init_null(); + JSON_Status status = json_object_set_value(object, name, value); + if (status == JSONFailure) { + json_value_free(value); + } + return status; +} + +JSON_Status +json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value) +{ + const char *dot_pos = NULL; + JSON_Value *temp_value = NULL, *new_value = NULL; + JSON_Object *temp_object = NULL, *new_object = NULL; + JSON_Status status = JSONFailure; + size_t name_len = 0; + if (object == NULL || name == NULL || value == NULL) { + return JSONFailure; + } + dot_pos = strchr(name, '.'); + if (dot_pos == NULL) { + return json_object_set_value(object, name, value); + } + name_len = dot_pos - name; + temp_value = json_object_getn_value(object, name, name_len); + if (temp_value) { + /* Don't overwrite existing non-object (unlike json_object_set_value, but it shouldn't be changed at this point) */ + if (json_value_get_type(temp_value) != JSONObject) { + return JSONFailure; + } + temp_object = json_value_get_object(temp_value); + return json_object_dotset_value(temp_object, dot_pos + 1, value); + } + new_value = json_value_init_object(); + if (new_value == NULL) { + return JSONFailure; + } + new_object = json_value_get_object(new_value); + status = json_object_dotset_value(new_object, dot_pos + 1, value); + if (status != JSONSuccess) { + json_value_free(new_value); + return JSONFailure; + } + status = json_object_addn(object, name, name_len, new_value); + if (status != JSONSuccess) { + json_object_dotremove_internal(new_object, dot_pos + 1, 0); + json_value_free(new_value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_object_dotset_string(JSON_Object *object, const char *name, const char *string) +{ + JSON_Value *value = json_value_init_string(string); + if (value == NULL) { + return JSONFailure; + } + if (json_object_dotset_value(object, name, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_object_dotset_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len) +{ + JSON_Value *value = json_value_init_string_with_len(string, len); + if (value == NULL) { + return JSONFailure; + } + if (json_object_dotset_value(object, name, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_object_dotset_number(JSON_Object *object, const char *name, double number) +{ + JSON_Value *value = json_value_init_number(number); + if (value == NULL) { + return JSONFailure; + } + if (json_object_dotset_value(object, name, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean) +{ + JSON_Value *value = json_value_init_boolean(boolean); + if (value == NULL) { + return JSONFailure; + } + if (json_object_dotset_value(object, name, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_object_dotset_null(JSON_Object *object, const char *name) +{ + JSON_Value *value = json_value_init_null(); + if (value == NULL) { + return JSONFailure; + } + if (json_object_dotset_value(object, name, value) == JSONFailure) { + json_value_free(value); + return JSONFailure; + } + return JSONSuccess; +} + +JSON_Status +json_object_remove(JSON_Object *object, const char *name) +{ + return json_object_remove_internal(object, name, 1); +} + +JSON_Status +json_object_dotremove(JSON_Object *object, const char *name) +{ + return json_object_dotremove_internal(object, name, 1); +} + +JSON_Status +json_object_clear(JSON_Object *object) +{ + size_t i = 0; + if (object == NULL) { + return JSONFailure; + } + for (i = 0; i < json_object_get_count(object); i++) { + parson_free(object->names[i]); + json_value_free(object->values[i]); + } + object->count = 0; + return JSONSuccess; +} + +JSON_Status +json_validate(const JSON_Value *schema, const JSON_Value *value) +{ + JSON_Value *temp_schema_value = NULL, *temp_value = NULL; + JSON_Array *schema_array = NULL, *value_array = NULL; + JSON_Object *schema_object = NULL, *value_object = NULL; + JSON_Value_Type schema_type = JSONError, value_type = JSONError; + const char *key = NULL; + size_t i = 0, count = 0; + if (schema == NULL || value == NULL) { + return JSONFailure; + } + schema_type = json_value_get_type(schema); + value_type = json_value_get_type(value); + if (schema_type != value_type && schema_type != JSONNull) { /* null represents all values */ + return JSONFailure; + } + switch (schema_type) { + case JSONArray: + schema_array = json_value_get_array(schema); + value_array = json_value_get_array(value); + count = json_array_get_count(schema_array); + if (count == 0) { + return JSONSuccess; /* Empty array allows all types */ + } + /* Get first value from array, rest is ignored */ + temp_schema_value = json_array_get_value(schema_array, 0); + for (i = 0; i < json_array_get_count(value_array); i++) { + temp_value = json_array_get_value(value_array, i); + if (json_validate(temp_schema_value, temp_value) == JSONFailure) { + return JSONFailure; + } + } + return JSONSuccess; + case JSONObject: + schema_object = json_value_get_object(schema); + value_object = json_value_get_object(value); + count = json_object_get_count(schema_object); + if (count == 0) { + return JSONSuccess; /* Empty object allows all objects */ + } else if (json_object_get_count(value_object) < count) { + return JSONFailure; /* Tested object mustn't have less name-value pairs than schema */ + } + for (i = 0; i < count; i++) { + key = json_object_get_name(schema_object, i); + temp_schema_value = json_object_get_value(schema_object, key); + temp_value = json_object_get_value(value_object, key); + if (temp_value == NULL) { + return JSONFailure; + } + if (json_validate(temp_schema_value, temp_value) == JSONFailure) { + return JSONFailure; + } + } + return JSONSuccess; + case JSONString: + case JSONNumber: + case JSONBoolean: + case JSONNull: + return JSONSuccess; /* equality already tested before switch */ + case JSONError: + default: + return JSONFailure; + } +} + +int +json_value_equals(const JSON_Value *a, const JSON_Value *b) +{ + JSON_Object *a_object = NULL, *b_object = NULL; + JSON_Array *a_array = NULL, *b_array = NULL; + const JSON_String *a_string = NULL, *b_string = NULL; + const char *key = NULL; + size_t a_count = 0, b_count = 0, i = 0; + JSON_Value_Type a_type, b_type; + a_type = json_value_get_type(a); + b_type = json_value_get_type(b); + if (a_type != b_type) { + return 0; + } + switch (a_type) { + case JSONArray: + a_array = json_value_get_array(a); + b_array = json_value_get_array(b); + a_count = json_array_get_count(a_array); + b_count = json_array_get_count(b_array); + if (a_count != b_count) { + return 0; + } + for (i = 0; i < a_count; i++) { + if (!json_value_equals(json_array_get_value(a_array, i), + json_array_get_value(b_array, i))) { + return 0; + } + } + return 1; + case JSONObject: + a_object = json_value_get_object(a); + b_object = json_value_get_object(b); + a_count = json_object_get_count(a_object); + b_count = json_object_get_count(b_object); + if (a_count != b_count) { + return 0; + } + for (i = 0; i < a_count; i++) { + key = json_object_get_name(a_object, i); + if (!json_value_equals(json_object_get_value(a_object, key), + json_object_get_value(b_object, key))) { + return 0; + } + } + return 1; + case JSONString: + a_string = json_value_get_string_desc(a); + b_string = json_value_get_string_desc(b); + if (a_string == NULL || b_string == NULL) { + return 0; /* shouldn't happen */ + } + return a_string->length == b_string->length && memcmp(a_string->chars, b_string->chars, a_string->length) == 0; + case JSONBoolean: + return json_value_get_boolean(a) == json_value_get_boolean(b); + case JSONNumber: + return fabs(json_value_get_number(a) - json_value_get_number(b)) < 0.000001; /* EPSILON */ + case JSONError: + return 1; + case JSONNull: + return 1; + default: + return 1; + } +} + +JSON_Value_Type +json_type(const JSON_Value *value) +{ + return json_value_get_type(value); +} + +JSON_Object * +json_object(const JSON_Value *value) +{ + return json_value_get_object(value); +} + +JSON_Array * +json_array(const JSON_Value *value) +{ + return json_value_get_array(value); +} + +const char * +json_string(const JSON_Value *value) +{ + return json_value_get_string(value); +} + +size_t +json_string_len(const JSON_Value *value) +{ + return json_value_get_string_len(value); +} + +double +json_number(const JSON_Value *value) +{ + return json_value_get_number(value); +} + +int +json_boolean(const JSON_Value *value) +{ + return json_value_get_boolean(value); +} + +void +json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun) +{ + parson_malloc = malloc_fun; + parson_free = free_fun; +} + +void +json_set_escape_slashes(int escape_slashes) +{ + parson_escape_slashes = escape_slashes; } diff --git a/parson.h b/parson.h index 2caac18..354d083 100644 --- a/parson.h +++ b/parson.h @@ -27,36 +27,35 @@ #define parson_parson_h #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif -#include /* size_t */ +#include /* size_t */ /* Types and enums */ typedef struct json_object_t JSON_Object; -typedef struct json_array_t JSON_Array; -typedef struct json_value_t JSON_Value; +typedef struct json_array_t JSON_Array; +typedef struct json_value_t JSON_Value; enum json_value_type { - JSONError = -1, - JSONNull = 1, - JSONString = 2, - JSONNumber = 3, - JSONObject = 4, - JSONArray = 5, - JSONBoolean = 6 + JSONError = -1, + JSONNull = 1, + JSONString = 2, + JSONNumber = 3, + JSONObject = 4, + JSONArray = 5, + JSONBoolean = 6 }; typedef int JSON_Value_Type; enum json_result_t { - JSONSuccess = 0, - JSONFailure = -1 + JSONSuccess = 0, + JSONFailure = -1 }; typedef int JSON_Status; -typedef void * (*JSON_Malloc_Function)(size_t); -typedef void (*JSON_Free_Function)(void *); +typedef void *(*JSON_Malloc_Function)(size_t); +typedef void (*JSON_Free_Function)(void *); /* Call only once, before calling any other function from parson API. If not called, malloc and free from stdlib will be used for all allocations */ @@ -67,35 +66,35 @@ void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Fu void json_set_escape_slashes(int escape_slashes); /* Parses first JSON value in a file, returns NULL in case of error */ -JSON_Value * json_parse_file(const char *filename); +JSON_Value *json_parse_file(const char *filename); /* Parses first JSON value in a file and ignores comments (/ * * / and //), returns NULL in case of error */ -JSON_Value * json_parse_file_with_comments(const char *filename); +JSON_Value *json_parse_file_with_comments(const char *filename); /* Parses first JSON value in a string, returns NULL in case of error */ -JSON_Value * json_parse_string(const char *string); +JSON_Value *json_parse_string(const char *string); /* Parses first JSON value in a string and ignores comments (/ * * / and //), returns NULL in case of error */ -JSON_Value * json_parse_string_with_comments(const char *string); +JSON_Value *json_parse_string_with_comments(const char *string); /* Serialization */ -size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */ +size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */ JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes); JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename); -char * json_serialize_to_string(const JSON_Value *value); +char *json_serialize_to_string(const JSON_Value *value); /* Pretty serialization */ -size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */ +size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */ JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes); JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename); -char * json_serialize_to_string_pretty(const JSON_Value *value); +char *json_serialize_to_string_pretty(const JSON_Value *value); -void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */ +void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */ /* Comparing */ -int json_value_equals(const JSON_Value *a, const JSON_Value *b); +int json_value_equals(const JSON_Value *a, const JSON_Value *b); /* Validation This is *NOT* JSON Schema. It validates json by checking if object have identically @@ -112,45 +111,45 @@ JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value); /* * JSON Object */ -JSON_Value * json_object_get_value (const JSON_Object *object, const char *name); -const char * json_object_get_string (const JSON_Object *object, const char *name); -size_t json_object_get_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */ -JSON_Object * json_object_get_object (const JSON_Object *object, const char *name); -JSON_Array * json_object_get_array (const JSON_Object *object, const char *name); -double json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */ -int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ +JSON_Value *json_object_get_value(const JSON_Object *object, const char *name); +const char *json_object_get_string(const JSON_Object *object, const char *name); +size_t json_object_get_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */ +JSON_Object *json_object_get_object(const JSON_Object *object, const char *name); +JSON_Array *json_object_get_array(const JSON_Object *object, const char *name); +double json_object_get_number(const JSON_Object *object, const char *name); /* returns 0 on fail */ +int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ /* dotget functions enable addressing values with dot notation in nested objects, just like in structs or c++/java/c# objects (e.g. objectA.objectB.value). Because valid names in JSON can contain dots, some values may be inaccessible this way. */ -JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name); -const char * json_object_dotget_string (const JSON_Object *object, const char *name); -size_t json_object_dotget_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */ -JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name); -JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name); -double json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */ -int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ +JSON_Value *json_object_dotget_value(const JSON_Object *object, const char *name); +const char *json_object_dotget_string(const JSON_Object *object, const char *name); +size_t json_object_dotget_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */ +JSON_Object *json_object_dotget_object(const JSON_Object *object, const char *name); +JSON_Array *json_object_dotget_array(const JSON_Object *object, const char *name); +double json_object_dotget_number(const JSON_Object *object, const char *name); /* returns 0 on fail */ +int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ /* Functions to get available names */ -size_t json_object_get_count (const JSON_Object *object); -const char * json_object_get_name (const JSON_Object *object, size_t index); -JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index); -JSON_Value * json_object_get_wrapping_value(const JSON_Object *object); +size_t json_object_get_count(const JSON_Object *object); +const char *json_object_get_name(const JSON_Object *object, size_t index); +JSON_Value *json_object_get_value_at(const JSON_Object *object, size_t index); +JSON_Value *json_object_get_wrapping_value(const JSON_Object *object); /* Functions to check if object has a value with a specific name. Returned value is 1 if object has * a value and 0 if it doesn't. dothas functions behave exactly like dotget functions. */ -int json_object_has_value (const JSON_Object *object, const char *name); +int json_object_has_value(const JSON_Object *object, const char *name); int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type); -int json_object_dothas_value (const JSON_Object *object, const char *name); +int json_object_dothas_value(const JSON_Object *object, const char *name); int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type); /* Creates new name-value pair or frees and replaces old value with a new one. * json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */ JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value); JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string); -JSON_Status json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len); /* length shouldn't include last null character */ +JSON_Status json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len); /* length shouldn't include last null character */ JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number); JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean); JSON_Status json_object_set_null(JSON_Object *object, const char *name); @@ -176,15 +175,15 @@ JSON_Status json_object_clear(JSON_Object *object); /* *JSON Array */ -JSON_Value * json_array_get_value (const JSON_Array *array, size_t index); -const char * json_array_get_string (const JSON_Array *array, size_t index); -size_t json_array_get_string_len(const JSON_Array *array, size_t index); /* doesn't account for last null character */ -JSON_Object * json_array_get_object (const JSON_Array *array, size_t index); -JSON_Array * json_array_get_array (const JSON_Array *array, size_t index); -double json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */ -int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */ -size_t json_array_get_count (const JSON_Array *array); -JSON_Value * json_array_get_wrapping_value(const JSON_Array *array); +JSON_Value *json_array_get_value(const JSON_Array *array, size_t index); +const char *json_array_get_string(const JSON_Array *array, size_t index); +size_t json_array_get_string_len(const JSON_Array *array, size_t index); /* doesn't account for last null character */ +JSON_Object *json_array_get_object(const JSON_Array *array, size_t index); +JSON_Array *json_array_get_array(const JSON_Array *array, size_t index); +double json_array_get_number(const JSON_Array *array, size_t index); /* returns 0 on fail */ +int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */ +size_t json_array_get_count(const JSON_Array *array); +JSON_Value *json_array_get_wrapping_value(const JSON_Array *array); /* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist. * Order of values in array may change during execution. */ @@ -194,7 +193,7 @@ JSON_Status json_array_remove(JSON_Array *array, size_t i); * Does nothing and returns JSONFailure if index doesn't exist. * json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */ JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value); -JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string); +JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char *string); JSON_Status json_array_replace_string_with_len(JSON_Array *array, size_t i, const char *string, size_t len); /* length shouldn't include last null character */ JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number); JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean); @@ -215,33 +214,33 @@ JSON_Status json_array_append_null(JSON_Array *array); /* *JSON Value */ -JSON_Value * json_value_init_object (void); -JSON_Value * json_value_init_array (void); -JSON_Value * json_value_init_string (const char *string); /* copies passed string */ -JSON_Value * json_value_init_string_with_len(const char *string, size_t length); /* copies passed string, length shouldn't include last null character */ -JSON_Value * json_value_init_number (double number); -JSON_Value * json_value_init_boolean(int boolean); -JSON_Value * json_value_init_null (void); -JSON_Value * json_value_deep_copy (const JSON_Value *value); -void json_value_free (JSON_Value *value); +JSON_Value *json_value_init_object(void); +JSON_Value *json_value_init_array(void); +JSON_Value *json_value_init_string(const char *string); /* copies passed string */ +JSON_Value *json_value_init_string_with_len(const char *string, size_t length); /* copies passed string, length shouldn't include last null character */ +JSON_Value *json_value_init_number(double number); +JSON_Value *json_value_init_boolean(int boolean); +JSON_Value *json_value_init_null(void); +JSON_Value *json_value_deep_copy(const JSON_Value *value); +void json_value_free(JSON_Value *value); -JSON_Value_Type json_value_get_type (const JSON_Value *value); -JSON_Object * json_value_get_object (const JSON_Value *value); -JSON_Array * json_value_get_array (const JSON_Value *value); -const char * json_value_get_string (const JSON_Value *value); -size_t json_value_get_string_len(const JSON_Value *value); /* doesn't account for last null character */ -double json_value_get_number (const JSON_Value *value); -int json_value_get_boolean(const JSON_Value *value); -JSON_Value * json_value_get_parent (const JSON_Value *value); +JSON_Value_Type json_value_get_type(const JSON_Value *value); +JSON_Object *json_value_get_object(const JSON_Value *value); +JSON_Array *json_value_get_array(const JSON_Value *value); +const char *json_value_get_string(const JSON_Value *value); +size_t json_value_get_string_len(const JSON_Value *value); /* doesn't account for last null character */ +double json_value_get_number(const JSON_Value *value); +int json_value_get_boolean(const JSON_Value *value); +JSON_Value *json_value_get_parent(const JSON_Value *value); /* Same as above, but shorter */ -JSON_Value_Type json_type (const JSON_Value *value); -JSON_Object * json_object (const JSON_Value *value); -JSON_Array * json_array (const JSON_Value *value); -const char * json_string (const JSON_Value *value); -size_t json_string_len(const JSON_Value *value); /* doesn't account for last null character */ -double json_number (const JSON_Value *value); -int json_boolean(const JSON_Value *value); +JSON_Value_Type json_type(const JSON_Value *value); +JSON_Object *json_object(const JSON_Value *value); +JSON_Array *json_array(const JSON_Value *value); +const char *json_string(const JSON_Value *value); +size_t json_string_len(const JSON_Value *value); /* doesn't account for last null character */ +double json_number(const JSON_Value *value); +int json_boolean(const JSON_Value *value); #ifdef __cplusplus } diff --git a/pcf.c b/pcf.c index c9dae9c..816c694 100644 --- a/pcf.c +++ b/pcf.c @@ -2,12 +2,12 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ #include "pcf.h" -#include "prv.h" #include "emu.h" +#include "prv.h" -#include -#include #include +#include +#include const char *pcf_def_header = "DEFAULT_OPTIONS\n" @@ -25,44 +25,43 @@ const char *pcf_def_header = "\n" "THREAD_FUNC State As Is\n"; -#define RGB(r, g, b) (r<<16 | g<<8 | b) -#define ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0])) +#define RGB(r, g, b) (r << 16 | g << 8 | b) +#define ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0])) /* Define colors for the trace */ -#define DEEPBLUE RGB( 0, 0, 255) +#define DEEPBLUE RGB(0, 0, 255) #define LIGHTGREY RGB(217, 217, 217) -#define RED RGB(230, 25, 75) -#define GREEN RGB(60, 180, 75) -#define YELLOW RGB(255, 225, 25) -#define ORANGE RGB(245, 130, 48) -#define PURPLE RGB(145, 30, 180) -#define CYAN RGB( 70, 240, 240) -#define MAGENTA RGB(240, 50, 230) -#define LIME RGB(210, 245, 60) -#define PINK RGB(250, 190, 212) -#define TEAL RGB( 0, 128, 128) -#define LAVENDER RGB(220, 190, 255) -#define BROWN RGB(170, 110, 40) -#define BEIGE RGB(255, 250, 200) -#define MAROON RGB(128, 0, 0) -#define MINT RGB(170, 255, 195) -#define OLIVE RGB(128, 128, 0) -#define APRICOT RGB(255, 215, 180) -#define NAVY RGB( 0, 0, 128) -#define BLUE RGB( 0, 130, 200) -#define GREY RGB(128, 128, 128) -#define BLACK RGB( 0, 0, 0) +#define RED RGB(230, 25, 75) +#define GREEN RGB(60, 180, 75) +#define YELLOW RGB(255, 225, 25) +#define ORANGE RGB(245, 130, 48) +#define PURPLE RGB(145, 30, 180) +#define CYAN RGB(70, 240, 240) +#define MAGENTA RGB(240, 50, 230) +#define LIME RGB(210, 245, 60) +#define PINK RGB(250, 190, 212) +#define TEAL RGB(0, 128, 128) +#define LAVENDER RGB(220, 190, 255) +#define BROWN RGB(170, 110, 40) +#define BEIGE RGB(255, 250, 200) +#define MAROON RGB(128, 0, 0) +#define MINT RGB(170, 255, 195) +#define OLIVE RGB(128, 128, 0) +#define APRICOT RGB(255, 215, 180) +#define NAVY RGB(0, 0, 128) +#define BLUE RGB(0, 130, 200) +#define GREY RGB(128, 128, 128) +#define BLACK RGB(0, 0, 0) const uint32_t pcf_def_palette[] = { - BLACK, /* (never shown anyways) */ - BLUE, /* runtime */ - LIGHTGREY, /* busy wait */ - RED, /* task */ + BLACK, /* (never shown anyways) */ + BLUE, /* runtime */ + LIGHTGREY, /* busy wait */ + RED, /* task */ GREEN, YELLOW, ORANGE, PURPLE, CYAN, MAGENTA, LIME, PINK, TEAL, GREY, LAVENDER, BROWN, BEIGE, MAROON, MINT, - OLIVE, APRICOT, NAVY, DEEPBLUE -}; + OLIVE, APRICOT, NAVY, DEEPBLUE}; const uint32_t *pcf_palette = pcf_def_palette; const int pcf_palette_len = ARRAY_LEN(pcf_def_palette); @@ -70,197 +69,201 @@ const int pcf_palette_len = ARRAY_LEN(pcf_def_palette); /* ------------------ Value labels --------------------- */ struct pcf_value_label default_values[] = { - { ST_TOO_MANY_TH, "Unknown: Multiple threads running" }, - { -1, NULL }, + {ST_TOO_MANY_TH, "Unknown: Multiple threads running"}, + {-1, NULL}, }; struct pcf_value_label ovni_state_values[] = { - { TH_ST_UNKNOWN, "Unknown" }, - { TH_ST_RUNNING, "Running" }, - { TH_ST_PAUSED, "Paused" }, - { TH_ST_DEAD, "Dead" }, - { TH_ST_COOLING, "Cooling" }, - { TH_ST_WARMING, "Warming" }, - { -1, NULL }, + {TH_ST_UNKNOWN, "Unknown"}, + {TH_ST_RUNNING, "Running"}, + {TH_ST_PAUSED, "Paused"}, + {TH_ST_DEAD, "Dead"}, + {TH_ST_COOLING, "Cooling"}, + {TH_ST_WARMING, "Warming"}, + {-1, NULL}, }; struct pcf_value_label ovni_flush_values[] = { - { 0, "None" }, - { ST_OVNI_FLUSHING, "Flushing" }, - { ST_TOO_MANY_TH, "Unknown flushing state: Multiple threads running" }, - { -1, NULL }, + {0, "None"}, + {ST_OVNI_FLUSHING, "Flushing"}, + {ST_TOO_MANY_TH, "Unknown flushing state: Multiple threads running"}, + {-1, NULL}, }; struct pcf_value_label nosv_ss_values[] = { /* Errors */ - { ST_BAD, "Unknown: bad happened (report bug)" }, - { ST_TOO_MANY_TH, "Unknown: multiple threads running" }, + {ST_BAD, "Unknown: bad happened (report bug)"}, + {ST_TOO_MANY_TH, "Unknown: multiple threads running"}, /* Good values */ - { ST_NULL, "No subsystem" }, - { ST_NOSV_SCHED_HUNGRY, "Scheduler: Hungry" }, - { ST_NOSV_SCHED_SERVING, "Scheduler: Serving" }, - { ST_NOSV_SCHED_SUBMITTING, "Scheduler: Submitting" }, - { ST_NOSV_MEM_ALLOCATING, "Memory: Allocating" }, - { ST_NOSV_MEM_FREEING, "Memory: Freeing" }, - { ST_NOSV_TASK_RUNNING, "Task: Running" }, - { ST_NOSV_API_SUBMIT, "API: Submit" }, - { ST_NOSV_API_PAUSE, "API: Pause" }, - { ST_NOSV_API_YIELD, "API: Yield" }, - { ST_NOSV_API_WAITFOR, "API: Waitfor" }, - { ST_NOSV_API_SCHEDPOINT, "API: Scheduling point" }, - { ST_NOSV_ATTACH, "Thread: Attached" }, - { ST_NOSV_WORKER, "Thread: Worker" }, - { ST_NOSV_DELEGATE, "Thread: Delegate" }, - { EV_NOSV_SCHED_SEND, "EV Scheduler: Send task" }, - { EV_NOSV_SCHED_RECV, "EV Scheduler: Recv task" }, - { EV_NOSV_SCHED_SELF, "EV Scheduler: Self-assign task" }, - { -1, NULL }, + {ST_NULL, "No subsystem"}, + {ST_NOSV_SCHED_HUNGRY, "Scheduler: Hungry"}, + {ST_NOSV_SCHED_SERVING, "Scheduler: Serving"}, + {ST_NOSV_SCHED_SUBMITTING, "Scheduler: Submitting"}, + {ST_NOSV_MEM_ALLOCATING, "Memory: Allocating"}, + {ST_NOSV_MEM_FREEING, "Memory: Freeing"}, + {ST_NOSV_TASK_RUNNING, "Task: Running"}, + {ST_NOSV_API_SUBMIT, "API: Submit"}, + {ST_NOSV_API_PAUSE, "API: Pause"}, + {ST_NOSV_API_YIELD, "API: Yield"}, + {ST_NOSV_API_WAITFOR, "API: Waitfor"}, + {ST_NOSV_API_SCHEDPOINT, "API: Scheduling point"}, + {ST_NOSV_ATTACH, "Thread: Attached"}, + {ST_NOSV_WORKER, "Thread: Worker"}, + {ST_NOSV_DELEGATE, "Thread: Delegate"}, + {EV_NOSV_SCHED_SEND, "EV Scheduler: Send task"}, + {EV_NOSV_SCHED_RECV, "EV Scheduler: Recv task"}, + {EV_NOSV_SCHED_SELF, "EV Scheduler: Self-assign task"}, + {-1, NULL}, }; struct pcf_value_label tampi_mode_values[] = { - { ST_NULL, "NULL" }, - { ST_TOO_MANY_TH, "TAMPI: Unknown, multiple threads running" }, - { ST_TAMPI_SEND, "TAMPI: Send" }, - { ST_TAMPI_RECV, "TAMPI: Recv" }, - { ST_TAMPI_ISEND, "TAMPI: Isend" }, - { ST_TAMPI_IRECV, "TAMPI: Irecv" }, - { ST_TAMPI_WAIT, "TAMPI: Wait" }, - { ST_TAMPI_WAITALL, "TAMPI: Waitall" }, - { -1, NULL }, + {ST_NULL, "NULL"}, + {ST_TOO_MANY_TH, "TAMPI: Unknown, multiple threads running"}, + {ST_TAMPI_SEND, "TAMPI: Send"}, + {ST_TAMPI_RECV, "TAMPI: Recv"}, + {ST_TAMPI_ISEND, "TAMPI: Isend"}, + {ST_TAMPI_IRECV, "TAMPI: Irecv"}, + {ST_TAMPI_WAIT, "TAMPI: Wait"}, + {ST_TAMPI_WAITALL, "TAMPI: Waitall"}, + {-1, NULL}, }; struct pcf_value_label openmp_mode_values[] = { - { ST_NULL, "NULL" }, - { ST_TOO_MANY_TH, "OpenMP: Unknown, multiple threads running" }, - { ST_OPENMP_TASK, "OpenMP: Task" }, - { ST_OPENMP_PARALLEL, "OpenMP: Parallel" }, - { -1, NULL }, + {ST_NULL, "NULL"}, + {ST_TOO_MANY_TH, "OpenMP: Unknown, multiple threads running"}, + {ST_OPENMP_TASK, "OpenMP: Task"}, + {ST_OPENMP_PARALLEL, "OpenMP: Parallel"}, + {-1, NULL}, }; struct pcf_value_label nodes_mode_values[] = { - { ST_NULL, "NULL" }, - { ST_TOO_MANY_TH, "NODES: Multiple threads running" }, - { ST_NODES_REGISTER, "Dependencies: Registering task accesses" }, - { ST_NODES_UNREGISTER, "Dependencies: Unregistering task accesses" }, - { ST_NODES_IF0_WAIT, "If0: Waiting for an If0 task" }, - { ST_NODES_IF0_INLINE, "If0: Executing an If0 task inline" }, - { ST_NODES_TASKWAIT, "Taskwait: Taskwait" }, - { ST_NODES_CREATE, "Add Task: Creating a task" }, - { ST_NODES_SUBMIT, "Add Task: Submitting a task" }, - { ST_NODES_SPAWN, "Spawn Function: Spawning a function" }, - { -1, NULL }, + {ST_NULL, "NULL"}, + {ST_TOO_MANY_TH, "NODES: Multiple threads running"}, + {ST_NODES_REGISTER, "Dependencies: Registering task accesses"}, + {ST_NODES_UNREGISTER, "Dependencies: Unregistering task accesses"}, + {ST_NODES_IF0_WAIT, "If0: Waiting for an If0 task"}, + {ST_NODES_IF0_INLINE, "If0: Executing an If0 task inline"}, + {ST_NODES_TASKWAIT, "Taskwait: Taskwait"}, + {ST_NODES_CREATE, "Add Task: Creating a task"}, + {ST_NODES_SUBMIT, "Add Task: Submitting a task"}, + {ST_NODES_SPAWN, "Spawn Function: Spawning a function"}, + {-1, NULL}, }; struct pcf_value_label kernel_cs_values[] = { - { ST_NULL, "NULL" }, - { ST_TOO_MANY_TH, "Unknown: multiple threads running" }, - { ST_KERNEL_CSOUT, "Context switch: Out of the CPU" }, - { -1, NULL }, + {ST_NULL, "NULL"}, + {ST_TOO_MANY_TH, "Unknown: multiple threads running"}, + {ST_KERNEL_CSOUT, "Context switch: Out of the CPU"}, + {-1, NULL}, }; struct pcf_value_label nanos6_ss_values[] = { - { ST_NULL, "No subsystem" }, - { ST_TOO_MANY_TH, "Unknown: multiple threads running" }, - { ST_NANOS6_TASK_BODY, "Task: Running body" }, - { ST_NANOS6_TASK_CREATING, "Task: Creating" }, - { ST_NANOS6_TASK_SUBMIT, "Task: Submitting" }, - { ST_NANOS6_TASK_SPAWNING, "Task: Spawning function" }, - { ST_NANOS6_TASK_FOR, "Task: Running task for" }, - { ST_NANOS6_SCHED_SERVING, "Scheduler: Serving tasks" }, - { ST_NANOS6_SCHED_ADDING, "Scheduler: Adding ready tasks" }, - { ST_NANOS6_SCHED_PROCESSING, "Scheduler: Processing ready tasks" }, - { ST_NANOS6_DEP_REG, "Dependency: Registering" }, - { ST_NANOS6_DEP_UNREG, "Dependency: Unregistering" }, - { ST_NANOS6_BLK_TASKWAIT, "Blocking: Taskwait" }, - { ST_NANOS6_BLK_BLOCKING, "Blocking: Blocking current task" }, - { ST_NANOS6_BLK_UNBLOCKING, "Blocking: Unblocking remote task" }, - { ST_NANOS6_BLK_WAITFOR, "Blocking: Wait for deadline" }, - { ST_NANOS6_HANDLING_TASK, "Worker: Handling task" }, - { ST_NANOS6_WORKER_LOOP, "Worker: Looking for work" }, - { ST_NANOS6_SWITCH_TO, "Worker: Switching to another thread" }, - { ST_NANOS6_MIGRATE, "Worker: Migrating CPU" }, - { ST_NANOS6_SUSPEND, "Worker: Suspending thread" }, - { ST_NANOS6_RESUME, "Worker: Resuming another thread" }, - { ST_NANOS6_ALLOCATING, "Memory: Allocating" }, - { ST_NANOS6_FREEING, "Memory: Freeing" }, - { EV_NANOS6_SCHED_SEND, "EV Scheduler: Send task" }, - { EV_NANOS6_SCHED_RECV, "EV Scheduler: Recv task" }, - { EV_NANOS6_SCHED_SELF, "EV Scheduler: Self-assign task" }, - { EV_NANOS6_CPU_IDLE, "EV CPU: Becomes idle" }, - { EV_NANOS6_CPU_ACTIVE, "EV CPU: Becomes active" }, - { EV_NANOS6_SIGNAL, "EV Worker: Wakening another thread" }, - { -1, NULL }, + {ST_NULL, "No subsystem"}, + {ST_TOO_MANY_TH, "Unknown: multiple threads running"}, + {ST_NANOS6_TASK_BODY, "Task: Running body"}, + {ST_NANOS6_TASK_CREATING, "Task: Creating"}, + {ST_NANOS6_TASK_SUBMIT, "Task: Submitting"}, + {ST_NANOS6_TASK_SPAWNING, "Task: Spawning function"}, + {ST_NANOS6_TASK_FOR, "Task: Running task for"}, + {ST_NANOS6_SCHED_SERVING, "Scheduler: Serving tasks"}, + {ST_NANOS6_SCHED_ADDING, "Scheduler: Adding ready tasks"}, + {ST_NANOS6_SCHED_PROCESSING, "Scheduler: Processing ready tasks"}, + {ST_NANOS6_DEP_REG, "Dependency: Registering"}, + {ST_NANOS6_DEP_UNREG, "Dependency: Unregistering"}, + {ST_NANOS6_BLK_TASKWAIT, "Blocking: Taskwait"}, + {ST_NANOS6_BLK_BLOCKING, "Blocking: Blocking current task"}, + {ST_NANOS6_BLK_UNBLOCKING, "Blocking: Unblocking remote task"}, + {ST_NANOS6_BLK_WAITFOR, "Blocking: Wait for deadline"}, + {ST_NANOS6_HANDLING_TASK, "Worker: Handling task"}, + {ST_NANOS6_WORKER_LOOP, "Worker: Looking for work"}, + {ST_NANOS6_SWITCH_TO, "Worker: Switching to another thread"}, + {ST_NANOS6_MIGRATE, "Worker: Migrating CPU"}, + {ST_NANOS6_SUSPEND, "Worker: Suspending thread"}, + {ST_NANOS6_RESUME, "Worker: Resuming another thread"}, + {ST_NANOS6_ALLOCATING, "Memory: Allocating"}, + {ST_NANOS6_FREEING, "Memory: Freeing"}, + {EV_NANOS6_SCHED_SEND, "EV Scheduler: Send task"}, + {EV_NANOS6_SCHED_RECV, "EV Scheduler: Recv task"}, + {EV_NANOS6_SCHED_SELF, "EV Scheduler: Self-assign task"}, + {EV_NANOS6_CPU_IDLE, "EV CPU: Becomes idle"}, + {EV_NANOS6_CPU_ACTIVE, "EV CPU: Becomes active"}, + {EV_NANOS6_SIGNAL, "EV Worker: Wakening another thread"}, + {-1, NULL}, }; struct pcf_value_label nanos6_thread_type[] = { - { ST_NULL, "No type" }, - { ST_TOO_MANY_TH, "Unknown: multiple threads running" }, - { ST_NANOS6_TH_EXTERNAL, "External" }, - { ST_NANOS6_TH_WORKER, "Worker" }, - { ST_NANOS6_TH_LEADER, "Leader" }, - { ST_NANOS6_TH_MAIN, "Main" }, - { -1, NULL }, + {ST_NULL, "No type"}, + {ST_TOO_MANY_TH, "Unknown: multiple threads running"}, + {ST_NANOS6_TH_EXTERNAL, "External"}, + {ST_NANOS6_TH_WORKER, "Worker"}, + {ST_NANOS6_TH_LEADER, "Leader"}, + {ST_NANOS6_TH_MAIN, "Main"}, + {-1, NULL}, }; struct pcf_value_label (*pcf_chan_value_labels[CHAN_MAX])[] = { - [CHAN_OVNI_PID] = &default_values, - [CHAN_OVNI_TID] = &default_values, - [CHAN_OVNI_NRTHREADS] = &default_values, - [CHAN_OVNI_STATE] = &ovni_state_values, - [CHAN_OVNI_APPID] = &default_values, - [CHAN_OVNI_CPU] = &default_values, - [CHAN_OVNI_FLUSH] = &ovni_flush_values, + [CHAN_OVNI_PID] = &default_values, + [CHAN_OVNI_TID] = &default_values, + [CHAN_OVNI_NRTHREADS] = &default_values, + [CHAN_OVNI_STATE] = &ovni_state_values, + [CHAN_OVNI_APPID] = &default_values, + [CHAN_OVNI_CPU] = &default_values, + [CHAN_OVNI_FLUSH] = &ovni_flush_values, - [CHAN_NOSV_TASKID] = &default_values, - [CHAN_NOSV_TYPE] = &default_values, - [CHAN_NOSV_APPID] = &default_values, - [CHAN_NOSV_SUBSYSTEM] = &nosv_ss_values, - [CHAN_NOSV_RANK] = &default_values, + [CHAN_NOSV_TASKID] = &default_values, + [CHAN_NOSV_TYPE] = &default_values, + [CHAN_NOSV_APPID] = &default_values, + [CHAN_NOSV_SUBSYSTEM] = &nosv_ss_values, + [CHAN_NOSV_RANK] = &default_values, - [CHAN_TAMPI_MODE] = &tampi_mode_values, - [CHAN_OPENMP_MODE] = &openmp_mode_values, - [CHAN_NODES_SUBSYSTEM] = &nodes_mode_values, + [CHAN_TAMPI_MODE] = &tampi_mode_values, + [CHAN_OPENMP_MODE] = &openmp_mode_values, + [CHAN_NODES_SUBSYSTEM] = &nodes_mode_values, - [CHAN_NANOS6_TASKID] = &default_values, - [CHAN_NANOS6_TYPE] = &default_values, + [CHAN_NANOS6_TASKID] = &default_values, + [CHAN_NANOS6_TYPE] = &default_values, [CHAN_NANOS6_SUBSYSTEM] = &nanos6_ss_values, - [CHAN_NANOS6_RANK] = &default_values, - [CHAN_NANOS6_THREAD] = &nanos6_thread_type, + [CHAN_NANOS6_RANK] = &default_values, + [CHAN_NANOS6_THREAD] = &nanos6_thread_type, - [CHAN_KERNEL_CS] = &kernel_cs_values, + [CHAN_KERNEL_CS] = &kernel_cs_values, }; /* ------------------ Type labels --------------------- */ char *pcf_chan_name[CHAN_MAX] = { - [CHAN_OVNI_PID] = "PID", - [CHAN_OVNI_TID] = "TID", - [CHAN_OVNI_NRTHREADS] = "Number of RUNNING threads", - [CHAN_OVNI_STATE] = "Execution state", - [CHAN_OVNI_APPID] = "AppID", - [CHAN_OVNI_CPU] = "CPU affinity", - [CHAN_OVNI_FLUSH] = "Flushing state", + [CHAN_OVNI_PID] = "PID", + [CHAN_OVNI_TID] = "TID", + [CHAN_OVNI_NRTHREADS] = "Number of RUNNING threads", + [CHAN_OVNI_STATE] = "Execution state", + [CHAN_OVNI_APPID] = "AppID", + [CHAN_OVNI_CPU] = "CPU affinity", + [CHAN_OVNI_FLUSH] = "Flushing state", - [CHAN_NOSV_TASKID] = "nOS-V TaskID", - [CHAN_NOSV_TYPE] = "nOS-V task type", - [CHAN_NOSV_APPID] = "nOS-V task AppID", - [CHAN_NOSV_SUBSYSTEM] = "nOS-V subsystem", - [CHAN_NOSV_RANK] = "nOS-V task MPI rank", + [CHAN_NOSV_TASKID] = "nOS-V TaskID", + [CHAN_NOSV_TYPE] = "nOS-V task type", + [CHAN_NOSV_APPID] = "nOS-V task AppID", + [CHAN_NOSV_SUBSYSTEM] = "nOS-V subsystem", + [CHAN_NOSV_RANK] = "nOS-V task MPI rank", - [CHAN_TAMPI_MODE] = "TAMPI mode", - [CHAN_OPENMP_MODE] = "OpenMP mode", - [CHAN_NODES_SUBSYSTEM] = "NODES subsystem", + [CHAN_TAMPI_MODE] = "TAMPI mode", + [CHAN_OPENMP_MODE] = "OpenMP mode", + [CHAN_NODES_SUBSYSTEM] = "NODES subsystem", - [CHAN_NANOS6_TASKID] = "Nanos6 task ID", - [CHAN_NANOS6_TYPE] = "Nanos6 task type", + [CHAN_NANOS6_TASKID] = "Nanos6 task ID", + [CHAN_NANOS6_TYPE] = "Nanos6 task type", [CHAN_NANOS6_SUBSYSTEM] = "Nanos6 subsystem", - [CHAN_NANOS6_RANK] = "Nanos6 task MPI rank", - [CHAN_NANOS6_THREAD] = "Nanos6 thread type", + [CHAN_NANOS6_RANK] = "Nanos6 task MPI rank", + [CHAN_NANOS6_THREAD] = "Nanos6 thread type", - [CHAN_KERNEL_CS] = "Context switches", + [CHAN_KERNEL_CS] = "Context switches", }; -enum pcf_suffix { NONE = 0, CUR_TH, RUN_TH, ACT_TH, SUFFIX_MAX }; +enum pcf_suffix { NONE = 0, + CUR_TH, + RUN_TH, + ACT_TH, + SUFFIX_MAX }; char *pcf_suffix_name[SUFFIX_MAX] = { [NONE] = "", @@ -270,32 +273,32 @@ char *pcf_suffix_name[SUFFIX_MAX] = { }; int pcf_chan_suffix[CHAN_MAX][CHAN_MAXTYPE] = { - /* Thread CPU */ - [CHAN_OVNI_PID] = { CUR_TH, CUR_TH }, - [CHAN_OVNI_TID] = { CUR_TH, CUR_TH }, - [CHAN_OVNI_NRTHREADS] = { NONE, NONE }, - [CHAN_OVNI_STATE] = { CUR_TH, NONE }, - [CHAN_OVNI_APPID] = { NONE, RUN_TH }, - [CHAN_OVNI_CPU] = { CUR_TH, NONE }, - [CHAN_OVNI_FLUSH] = { CUR_TH, RUN_TH }, + /* Thread CPU */ + [CHAN_OVNI_PID] = {CUR_TH, CUR_TH}, + [CHAN_OVNI_TID] = {CUR_TH, CUR_TH}, + [CHAN_OVNI_NRTHREADS] = {NONE, NONE}, + [CHAN_OVNI_STATE] = {CUR_TH, NONE}, + [CHAN_OVNI_APPID] = {NONE, RUN_TH}, + [CHAN_OVNI_CPU] = {CUR_TH, NONE}, + [CHAN_OVNI_FLUSH] = {CUR_TH, RUN_TH}, - [CHAN_NOSV_TASKID] = { RUN_TH, RUN_TH }, - [CHAN_NOSV_TYPE] = { RUN_TH, RUN_TH }, - [CHAN_NOSV_APPID] = { RUN_TH, RUN_TH }, - [CHAN_NOSV_SUBSYSTEM] = { ACT_TH, RUN_TH }, - [CHAN_NOSV_RANK] = { RUN_TH, RUN_TH }, + [CHAN_NOSV_TASKID] = {RUN_TH, RUN_TH}, + [CHAN_NOSV_TYPE] = {RUN_TH, RUN_TH}, + [CHAN_NOSV_APPID] = {RUN_TH, RUN_TH}, + [CHAN_NOSV_SUBSYSTEM] = {ACT_TH, RUN_TH}, + [CHAN_NOSV_RANK] = {RUN_TH, RUN_TH}, - [CHAN_TAMPI_MODE] = { RUN_TH, RUN_TH }, - [CHAN_OPENMP_MODE] = { RUN_TH, RUN_TH }, - [CHAN_NODES_SUBSYSTEM] = { RUN_TH, RUN_TH }, + [CHAN_TAMPI_MODE] = {RUN_TH, RUN_TH}, + [CHAN_OPENMP_MODE] = {RUN_TH, RUN_TH}, + [CHAN_NODES_SUBSYSTEM] = {RUN_TH, RUN_TH}, - [CHAN_NANOS6_TASKID] = { RUN_TH, RUN_TH }, - [CHAN_NANOS6_TYPE] = { RUN_TH, RUN_TH }, - [CHAN_NANOS6_SUBSYSTEM] = { ACT_TH, RUN_TH }, - [CHAN_NANOS6_RANK] = { RUN_TH, RUN_TH }, - [CHAN_NANOS6_THREAD] = { ACT_TH, NONE }, + [CHAN_NANOS6_TASKID] = {RUN_TH, RUN_TH}, + [CHAN_NANOS6_TYPE] = {RUN_TH, RUN_TH}, + [CHAN_NANOS6_SUBSYSTEM] = {ACT_TH, RUN_TH}, + [CHAN_NANOS6_RANK] = {RUN_TH, RUN_TH}, + [CHAN_NANOS6_THREAD] = {ACT_TH, NONE}, - [CHAN_KERNEL_CS] = { RUN_TH, ACT_TH }, + [CHAN_KERNEL_CS] = {RUN_TH, ACT_TH}, }; /* ----------------------------------------------- */ @@ -303,9 +306,9 @@ int pcf_chan_suffix[CHAN_MAX][CHAN_MAXTYPE] = { static void decompose_rgb(uint32_t col, uint8_t *r, uint8_t *g, uint8_t *b) { - *r = (col>>16) & 0xff; - *g = (col>>8) & 0xff; - *b = (col>>0) & 0xff; + *r = (col >> 16) & 0xff; + *g = (col >> 8) & 0xff; + *b = (col >> 0) & 0xff; } static void @@ -323,8 +326,7 @@ write_colors(FILE *f, const uint32_t *palette, int n) fprintf(f, "\n\n"); fprintf(f, "STATES_COLOR\n"); - for(i=0; iid, type->label); fprintf(f, "VALUES\n"); - for(struct pcf_value *v = type->values; v != NULL; v = v->hh.next) + for (struct pcf_value *v = type->values; v != NULL; v = v->hh.next) fprintf(f, "%-4d %s\n", v->value, v->label); } @@ -347,19 +349,19 @@ write_types(struct pcf_file *pcf) { struct pcf_type *t; - for(t = pcf->types; t != NULL; t = t->hh.next) + for (t = pcf->types; t != NULL; t = t->hh.next) write_type(pcf->f, t); } static void create_values(struct pcf_type *t, enum chan c) { - struct pcf_value_label (*q)[] = pcf_chan_value_labels[c]; + struct pcf_value_label(*q)[] = pcf_chan_value_labels[c]; - if(q == NULL) + if (q == NULL) return; - for(struct pcf_value_label *p = *q; p->label != NULL; p++) + for (struct pcf_value_label *p = *q; p->label != NULL; p++) pcf_add_value(t, p->value, p->label); } @@ -370,7 +372,7 @@ create_type(struct pcf_file *pcf, enum chan c) enum chan_type ct = pcf->chantype; int prv_type = chan_to_prvtype[c]; - if(prv_type == -1) + if (prv_type == -1) return; /* Compute the label by joining the two parts */ @@ -379,9 +381,9 @@ create_type(struct pcf_file *pcf, enum chan c) char *suffix = pcf_suffix_name[isuffix]; int ret = snprintf(label, MAX_PCF_LABEL, "%s %s", - prefix, suffix); + prefix, suffix); - if(ret >= MAX_PCF_LABEL) + if (ret >= MAX_PCF_LABEL) die("computed type label too long\n"); struct pcf_type *t = pcf_add_type(pcf, prv_type, label); @@ -398,14 +400,13 @@ pcf_open(struct pcf_file *pcf, char *path, int chantype) pcf->f = fopen(path, "w"); pcf->chantype = chantype; - if(pcf->f == NULL) - { + if (pcf->f == NULL) { die("cannot open PCF file '%s': %s\n", - path, strerror(errno)); + path, strerror(errno)); } /* Create default types and values */ - for(enum chan c = 0; c < CHAN_MAX; c++) + for (enum chan c = 0; c < CHAN_MAX; c++) create_type(pcf, c); } @@ -431,11 +432,11 @@ pcf_add_type(struct pcf_file *pcf, int type_id, const char *label) pcftype = pcf_find_type(pcf, type_id); - if(pcftype != NULL) + if (pcftype != NULL) die("PCF type %d already defined\n", type_id); pcftype = calloc(1, sizeof(struct pcf_type)); - if(pcftype == NULL) + if (pcftype == NULL) die("calloc failed: %s\n", strerror(errno)); pcftype->id = type_id; @@ -443,7 +444,7 @@ pcf_add_type(struct pcf_file *pcf, int type_id, const char *label) pcftype->nvalues = 0; int len = snprintf(pcftype->label, MAX_PCF_LABEL, "%s", label); - if(len >= MAX_PCF_LABEL) + if (len >= MAX_PCF_LABEL) die("PCF type label too long\n"); HASH_ADD_INT(pcf->types, id, pcftype); @@ -471,17 +472,17 @@ pcf_add_value(struct pcf_type *type, int value, const char *label) { struct pcf_value *pcfvalue = pcf_find_value(type, value); - if(pcfvalue != NULL) + if (pcfvalue != NULL) die("PCF value %d already in type %d\n", value, type->id); pcfvalue = calloc(1, sizeof(struct pcf_value)); - if(pcfvalue == NULL) + if (pcfvalue == NULL) die("calloc failed: %s\n", strerror(errno)); pcfvalue->value = value; int len = snprintf(pcfvalue->label, MAX_PCF_LABEL, "%s", label); - if(len >= MAX_PCF_LABEL) + if (len >= MAX_PCF_LABEL) die("PCF value label too long\n"); HASH_ADD_INT(type->values, value, pcfvalue); diff --git a/pcf.h b/pcf.h index 4361c2b..3fe08b7 100644 --- a/pcf.h +++ b/pcf.h @@ -4,8 +4,8 @@ #ifndef OVNI_PCF_H #define OVNI_PCF_H -#include #include "uthash.h" +#include #define MAX_PCF_LABEL 512 @@ -53,10 +53,10 @@ void pcf_close(struct pcf_file *pcf); struct pcf_type *pcf_find_type(struct pcf_file *pcf, int type_id); struct pcf_type *pcf_add_type(struct pcf_file *pcf, int type_id, - const char *label); + const char *label); struct pcf_value *pcf_add_value(struct pcf_type *type, int value, - const char *label); + const char *label); struct pcf_value *pcf_find_value(struct pcf_type *type, int value); diff --git a/prv.c b/prv.c index 51afbe6..dad8062 100644 --- a/prv.c +++ b/prv.c @@ -3,8 +3,8 @@ #include -#include "ovni.h" #include "emu.h" +#include "ovni.h" #include "prv.h" void @@ -41,16 +41,16 @@ prv_ev_cpu(struct ovni_emu *emu, int row, int type, int val) void prv_ev_autocpu_raw(struct ovni_emu *emu, int64_t time, int type, int val) { - if(emu->cur_thread == NULL) + if (emu->cur_thread == NULL) die("prv_ev_autocpu_raw: current thread is NULL\n"); struct ovni_cpu *cpu = emu->cur_thread->cpu; - if(cpu == NULL) + if (cpu == NULL) die("prv_ev_autocpu_raw: current thread CPU is NULL\n"); /* FIXME: Use the global index of the CPUs */ - if(cpu->i < 0) + if (cpu->i < 0) die("prv_ev_autocpu_raw: CPU index is negative\n"); /* Begin at 1 */ diff --git a/prv.h b/prv.h index b420eb8..149611e 100644 --- a/prv.h +++ b/prv.h @@ -4,9 +4,9 @@ #ifndef OVNI_PRV_H #define OVNI_PRV_H -#include -#include "ovni.h" #include "emu.h" +#include "ovni.h" +#include void prv_ev(FILE *f, int row, int64_t time, int type, int val); diff --git a/sort.c b/sort.c index 605115c..70801de 100644 --- a/sort.c +++ b/sort.c @@ -27,9 +27,9 @@ #include #include +#include "emu.h" #include "ovni.h" #include "trace.h" -#include "emu.h" struct ring { ssize_t head; @@ -54,7 +54,8 @@ struct sortplan { int fd; }; -enum operation_mode { SORT, CHECK }; +enum operation_mode { SORT, + CHECK }; static char *tracedir = NULL; static enum operation_mode operation_mode = SORT; @@ -72,13 +73,13 @@ ring_add(struct ring *r, struct ovni_ev *ev) r->ev[r->tail] = ev; r->tail++; - if(r->tail >= r->size) + if (r->tail >= r->size) r->tail = 0; - if(r->head == r->tail) + if (r->head == r->tail) r->head = r->tail + 1; - if(r->head >= r->size) + if (r->head >= r->size) r->head = 0; } @@ -92,12 +93,10 @@ find_destination(struct ring *r, uint64_t clock) start = r->tail - 1 >= 0 ? r->tail - 1 : r->size - 1; end = r->head - 1 >= 0 ? r->head - 1 : r->size - 1; - for(i=start; i != end; i = i-1 < 0 ? r->size - 1: i-1) - { - if(r->ev[i]->header.clock < clock) - { + for (i = start; i != end; i = i - 1 < 0 ? r->size - 1 : i - 1) { + if (r->ev[i]->header.clock < clock) { dbg("found suitable position %ld events backwards\n", - nback); + nback); return i; } nback++; @@ -111,17 +110,13 @@ find_destination(struct ring *r, uint64_t clock) static int starts_unsorted_region(struct ovni_ev *ev) { - return ev->header.model == 'O' && - ev->header.category == 'U' && - ev->header.value == '['; + return ev->header.model == 'O' && ev->header.category == 'U' && ev->header.value == '['; } static int ends_unsorted_region(struct ovni_ev *ev) { - return ev->header.model == 'O' && - ev->header.category == 'U' && - ev->header.value == ']'; + return ev->header.model == 'O' && ev->header.category == 'U' && ev->header.value == ']'; } #if 0 @@ -168,7 +163,7 @@ hexdump(uint8_t *buf, size_t size) static void sort_buf(uint8_t *src, uint8_t *buf, int64_t bufsize, - uint8_t *srcbad, uint8_t *srcnext) + uint8_t *srcbad, uint8_t *srcnext) { uint8_t *p, *q; int64_t evsize, injected = 0; @@ -179,31 +174,27 @@ sort_buf(uint8_t *src, uint8_t *buf, int64_t bufsize, p = src; q = srcbad; - while(1) - { + while (1) { ep = (struct ovni_ev *) p; eq = (struct ovni_ev *) q; - if(p < srcbad && ep->header.clock < eq->header.clock) - { + if (p < srcbad && ep->header.clock < eq->header.clock) { ev = ep; evsize = ovni_ev_size(ev); p += evsize; - } - else - { + } else { ev = eq; evsize = ovni_ev_size(ev); q += evsize; } - if((uint8_t *) ev == srcnext) + if ((uint8_t *) ev == srcnext) break; - if((uint8_t *) ev > srcnext) + if ((uint8_t *) ev > srcnext) die("exceeded srcnext while sorting\n"); - if(bufsize < evsize) + if (bufsize < evsize) die("no space left in the sort buffer\n"); memcpy(buf, ev, evsize); @@ -218,11 +209,11 @@ sort_buf(uint8_t *src, uint8_t *buf, int64_t bufsize, static void write_stream(int fd, void *base, void *dst, const void *src, size_t size) { - while(size > 0) { + while (size > 0) { off_t offset = (off_t) ((int64_t) dst - (int64_t) base); ssize_t written = pwrite(fd, src, size, offset); - if(written < 0) + if (written < 0) die("pwrite failed: %s\n", strerror(errno)); size -= written; @@ -243,10 +234,9 @@ execute_sort_plan(struct sortplan *sp) dbg("attempt to sort: start clock %ld\n", sp->bad0->header.clock); /* Cannot sort in one pass; just fail for now */ - if((i0 = find_destination(sp->r, sp->bad0->header.clock)) < 0) - { + if ((i0 = find_destination(sp->r, sp->bad0->header.clock)) < 0) { err("cannot find destination for region starting at clock %ld\n", - sp->bad0->header.clock); + sp->bad0->header.clock); return -1; } @@ -257,15 +247,15 @@ execute_sort_plan(struct sortplan *sp) /* Allocate a working buffer */ bufsize = ((int64_t) sp->next) - ((int64_t) first); - if(bufsize <= 0) + if (bufsize <= 0) die("bufsize is non-positive\n"); buf = malloc(bufsize); - if(!buf) + if (!buf) die("malloc failed: %s\n", strerror(errno)); sort_buf((uint8_t *) first, buf, bufsize, - (uint8_t *) sp->bad0, (uint8_t *) sp->next); + (uint8_t *) sp->bad0, (uint8_t *) sp->next); /* Copy the sorted events back into the stream buffer */ memcpy(first, buf, bufsize); @@ -282,13 +272,13 @@ stream_winsort(struct ovni_stream *stream, struct ring *r) { struct ovni_ev *ev; struct sortplan sp = {0}; - //uint64_t lastclock = 0; + // uint64_t lastclock = 0; char st = 'S'; char *fn = stream->thread->tracefile; int fd = open(fn, O_WRONLY); - if(fd < 0) + if (fd < 0) die("open %s failed: %s\n", fn, strerror(errno)); ring_reset(r); @@ -299,41 +289,30 @@ stream_winsort(struct ovni_stream *stream, struct ring *r) size_t empty_regions = 0; size_t updated = 0; - while(stream->active) - { + while (stream->active) { ovni_load_next_event(stream); ev = stream->cur_ev; - if(st == 'S' && starts_unsorted_region(ev)) - { + if (st == 'S' && starts_unsorted_region(ev)) { st = 'U'; - } - else if(st == 'U') - { + } else if (st == 'U') { /* Ensure that we have at least one unsorted * event inside the section */ - if(ends_unsorted_region(ev)) - { + if (ends_unsorted_region(ev)) { empty_regions++; st = 'S'; - } - else - { + } else { st = 'X'; sp.bad0 = ev; } - } - else if(st == 'X') - { - if(ends_unsorted_region(ev)) - { + } else if (st == 'X') { + if (ends_unsorted_region(ev)) { updated = 1; sp.next = ev; dbg("executing sort plan for stream tid=%d\n", stream->tid); - if(execute_sort_plan(&sp) < 0) - { + if (execute_sort_plan(&sp) < 0) { err("sort failed for stream tid=%d\n", - stream->tid); + stream->tid); return -1; } @@ -348,14 +327,14 @@ stream_winsort(struct ovni_stream *stream, struct ring *r) ring_add(r, ev); } - if(empty_regions > 0) + if (empty_regions > 0) err("warning: stream %d contains %ld empty sort regions\n", - stream->tid, empty_regions); + stream->tid, empty_regions); - if(updated && fdatasync(fd) < 0) + if (updated && fdatasync(fd) < 0) die("fdatasync %s failed: %s\n", fn, strerror(errno)); - if(close(fd) < 0) + if (close(fd) < 0) die("close %s failed: %s\n", fn, strerror(errno)); return 0; @@ -370,16 +349,14 @@ stream_check(struct ovni_stream *stream) uint64_t last_clock = ev->header.clock; int ret = 0; - while(stream->active) - { + while (stream->active) { ovni_load_next_event(stream); ev = stream->cur_ev; uint64_t cur_clock = ovni_ev_get_clock(ev); - if(cur_clock < last_clock) - { + if (cur_clock < last_clock) { err("backwards jump in time %ld -> %ld for stream tid=%d\n", - last_clock, cur_clock, stream->tid); + last_clock, cur_clock, stream->tid); ret = -1; } @@ -400,27 +377,21 @@ process_trace(struct ovni_trace *trace) ring.size = max_look_back; ring.ev = malloc(ring.size * sizeof(struct ovni_ev *)); - if(ring.ev == NULL) + if (ring.ev == NULL) die("malloc failed: %s\n", strerror(errno)); - for(i=0; instreams; i++) - { + for (i = 0; i < trace->nstreams; i++) { stream = &trace->stream[i]; - if(operation_mode == SORT) - { + if (operation_mode == SORT) { dbg("sorting stream tid=%d\n", stream->tid); - if(stream_winsort(stream, &ring) != 0) - { + if (stream_winsort(stream, &ring) != 0) { err("sort stream tid=%d failed\n", stream->tid); /* When sorting, return at the first * attempt */ return -1; } - } - else - { - if(stream_check(stream) != 0) - { + } else { + if (stream_check(stream) != 0) { err("stream tid=%d is not sorted\n", stream->tid); /* When checking, report all errors and * then fail */ @@ -431,14 +402,10 @@ process_trace(struct ovni_trace *trace) free(ring.ev); - if(operation_mode == CHECK) - { - if(ret == 0) - { + if (operation_mode == CHECK) { + if (ret == 0) { err("all streams sorted\n"); - } - else - { + } else { err("streams NOT sorted\n"); } } @@ -458,7 +425,7 @@ usage(int argc, char *argv[]) err("tracedir, so they are suitable for the emulator ovniemu.\n"); err("Only the events enclosed by OU[ OU] are sorted. At most a\n"); err("total of %ld events are looked back to insert the unsorted\n", - max_look_back); + max_look_back); err("events, so the sort procedure can fail with an error.\n"); err("\n"); err("Options:\n"); @@ -476,10 +443,8 @@ parse_args(int argc, char *argv[]) { int opt; - while((opt = getopt(argc, argv, "c")) != -1) - { - switch(opt) - { + while ((opt = getopt(argc, argv, "c")) != -1) { + switch (opt) { case 'c': operation_mode = CHECK; break; @@ -488,8 +453,7 @@ parse_args(int argc, char *argv[]) } } - if(optind >= argc) - { + if (optind >= argc) { err("missing tracedir\n"); usage(argc, argv); } @@ -497,7 +461,8 @@ parse_args(int argc, char *argv[]) tracedir = argv[optind]; } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { int ret = 0; struct ovni_trace *trace; @@ -506,19 +471,18 @@ int main(int argc, char *argv[]) trace = calloc(1, sizeof(struct ovni_trace)); - if(trace == NULL) - { + if (trace == NULL) { perror("calloc"); exit(EXIT_FAILURE); } - if(ovni_load_trace(trace, tracedir)) + if (ovni_load_trace(trace, tracedir)) return 1; - if(ovni_load_streams(trace)) + if (ovni_load_streams(trace)) return 1; - if(process_trace(trace)) + if (process_trace(trace)) ret = 1; ovni_free_streams(trace); diff --git a/test/emu/instr.h b/test/emu/instr.h index 3b22e98..fc0ab71 100644 --- a/test/emu/instr.h +++ b/test/emu/instr.h @@ -18,46 +18,46 @@ #include #include -#define INSTR_0ARG(name, mcv) \ - static inline void name(void) \ - { \ - struct ovni_ev ev = {0}; \ +#define INSTR_0ARG(name, mcv) \ + static inline void name(void) \ + { \ + struct ovni_ev ev = {0}; \ ovni_ev_set_clock(&ev, ovni_clock_now()); \ - ovni_ev_set_mcv(&ev, mcv); \ - ovni_ev_emit(&ev); \ + ovni_ev_set_mcv(&ev, mcv); \ + ovni_ev_emit(&ev); \ } -#define INSTR_1ARG(name, mcv, ta, a) \ - static inline void name(ta a) \ - { \ - struct ovni_ev ev = {0}; \ - ovni_ev_set_clock(&ev, ovni_clock_now()); \ - ovni_ev_set_mcv(&ev, mcv); \ +#define INSTR_1ARG(name, mcv, ta, a) \ + static inline void name(ta a) \ + { \ + struct ovni_ev ev = {0}; \ + ovni_ev_set_clock(&ev, ovni_clock_now()); \ + ovni_ev_set_mcv(&ev, mcv); \ ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \ - ovni_ev_emit(&ev); \ + ovni_ev_emit(&ev); \ } -#define INSTR_2ARG(name, mcv, ta, a, tb, b) \ - static inline void name(ta a, tb b) \ - { \ - struct ovni_ev ev = {0}; \ - ovni_ev_set_clock(&ev, ovni_clock_now()); \ - ovni_ev_set_mcv(&ev, mcv); \ +#define INSTR_2ARG(name, mcv, ta, a, tb, b) \ + static inline void name(ta a, tb b) \ + { \ + struct ovni_ev ev = {0}; \ + ovni_ev_set_clock(&ev, ovni_clock_now()); \ + ovni_ev_set_mcv(&ev, mcv); \ ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \ ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \ - ovni_ev_emit(&ev); \ + ovni_ev_emit(&ev); \ } -#define INSTR_3ARG(name, mcv, ta, a, tb, b, tc, c) \ - static inline void name(ta a, tb b, tc c) \ - { \ - struct ovni_ev ev = {0}; \ - ovni_ev_set_mcv(&ev, mcv); \ - ovni_ev_set_clock(&ev, ovni_clock_now()); \ +#define INSTR_3ARG(name, mcv, ta, a, tb, b, tc, c) \ + static inline void name(ta a, tb b, tc c) \ + { \ + struct ovni_ev ev = {0}; \ + ovni_ev_set_mcv(&ev, mcv); \ + ovni_ev_set_clock(&ev, ovni_clock_now()); \ ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \ ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \ ovni_payload_add(&ev, (uint8_t *) &c, sizeof(c)); \ - ovni_ev_emit(&ev); \ + ovni_ev_emit(&ev); \ } INSTR_3ARG(instr_thread_execute, "OHx", int32_t, cpu, int32_t, creator_tid, uint64_t, tag) @@ -81,7 +81,7 @@ instr_start(int rank, int nranks) char hostname[OVNI_MAX_HOSTNAME]; char rankname[OVNI_MAX_HOSTNAME + 64]; - if(gethostname(hostname, HOST_NAME_MAX) != 0) + if (gethostname(hostname, HOST_NAME_MAX) != 0) die("gethostname failed"); sprintf(rankname, "%s.%d", hostname, rank); @@ -91,13 +91,13 @@ instr_start(int rank, int nranks) ovni_thread_init(gettid()); /* All ranks inform CPUs */ - for(int i=0; i < nranks; i++) + for (int i = 0; i < nranks; i++) ovni_add_cpu(i, i); int curcpu = rank; dbg("thread %d has cpu %d (ncpus=%d)\n", - gettid(), curcpu, nranks); + gettid(), curcpu, nranks); instr_thread_execute(curcpu, -1, 0); } diff --git a/test/emu/nanos6/instr_nanos6.h b/test/emu/nanos6/instr_nanos6.h index 9c09b81..48ac859 100644 --- a/test/emu/nanos6/instr_nanos6.h +++ b/test/emu/nanos6/instr_nanos6.h @@ -34,72 +34,72 @@ INSTR_1ARG(instr_nanos6_task_pause, "6Tp", int32_t, id) INSTR_1ARG(instr_nanos6_task_resume, "6Tr", int32_t, id) INSTR_1ARG(instr_nanos6_task_end, "6Te", int32_t, id) -INSTR_0ARG(instr_nanos6_task_create_begin, "6C[") -INSTR_0ARG(instr_nanos6_task_create_end, "6C]") +INSTR_0ARG(instr_nanos6_task_create_begin, "6C[") +INSTR_0ARG(instr_nanos6_task_create_end, "6C]") -INSTR_0ARG(instr_nanos6_sched_server_enter, "6S[") -INSTR_0ARG(instr_nanos6_sched_server_exit, "6S]") -INSTR_0ARG(instr_nanos6_add_ready_enter, "6Sa") -INSTR_0ARG(instr_nanos6_add_ready_exit, "6SA") -INSTR_0ARG(instr_nanos6_process_ready_enter, "6Sp") -INSTR_0ARG(instr_nanos6_process_ready_exit, "6SP") -INSTR_0ARG(instr_nanos6_sched_receive, "6Sr") -INSTR_0ARG(instr_nanos6_sched_assign, "6Ss") -INSTR_0ARG(instr_nanos6_sched_self_assign, "6S@") +INSTR_0ARG(instr_nanos6_sched_server_enter, "6S[") +INSTR_0ARG(instr_nanos6_sched_server_exit, "6S]") +INSTR_0ARG(instr_nanos6_add_ready_enter, "6Sa") +INSTR_0ARG(instr_nanos6_add_ready_exit, "6SA") +INSTR_0ARG(instr_nanos6_process_ready_enter, "6Sp") +INSTR_0ARG(instr_nanos6_process_ready_exit, "6SP") +INSTR_0ARG(instr_nanos6_sched_receive, "6Sr") +INSTR_0ARG(instr_nanos6_sched_assign, "6Ss") +INSTR_0ARG(instr_nanos6_sched_self_assign, "6S@") -INSTR_0ARG(instr_nanos6_worker_loop_enter, "6W[") -INSTR_0ARG(instr_nanos6_worker_loop_exit, "6W]") -INSTR_0ARG(instr_nanos6_handle_task_enter, "6Wt") -INSTR_0ARG(instr_nanos6_handle_task_exit, "6WT") -INSTR_0ARG(instr_nanos6_switch_to_enter, "6Ww") -INSTR_0ARG(instr_nanos6_switch_to_exit, "6WW") -INSTR_0ARG(instr_nanos6_migrate_enter, "6Wm") -INSTR_0ARG(instr_nanos6_migrate_exit, "6WM") -INSTR_0ARG(instr_nanos6_suspend_enter, "6Ws") -INSTR_0ARG(instr_nanos6_suspend_exit, "6WS") -INSTR_0ARG(instr_nanos6_resume_enter, "6Wr") -INSTR_0ARG(instr_nanos6_resume_exit, "6WR") -INSTR_0ARG(instr_nanos6_signal, "6W*") +INSTR_0ARG(instr_nanos6_worker_loop_enter, "6W[") +INSTR_0ARG(instr_nanos6_worker_loop_exit, "6W]") +INSTR_0ARG(instr_nanos6_handle_task_enter, "6Wt") +INSTR_0ARG(instr_nanos6_handle_task_exit, "6WT") +INSTR_0ARG(instr_nanos6_switch_to_enter, "6Ww") +INSTR_0ARG(instr_nanos6_switch_to_exit, "6WW") +INSTR_0ARG(instr_nanos6_migrate_enter, "6Wm") +INSTR_0ARG(instr_nanos6_migrate_exit, "6WM") +INSTR_0ARG(instr_nanos6_suspend_enter, "6Ws") +INSTR_0ARG(instr_nanos6_suspend_exit, "6WS") +INSTR_0ARG(instr_nanos6_resume_enter, "6Wr") +INSTR_0ARG(instr_nanos6_resume_exit, "6WR") +INSTR_0ARG(instr_nanos6_signal, "6W*") -INSTR_0ARG(instr_nanos6_submit_task_enter, "6U[") -INSTR_0ARG(instr_nanos6_submit_task_exit, "6U]") +INSTR_0ARG(instr_nanos6_submit_task_enter, "6U[") +INSTR_0ARG(instr_nanos6_submit_task_exit, "6U]") -INSTR_0ARG(instr_nanos6_spawn_function_enter, "6F[") -INSTR_0ARG(instr_nanos6_spawn_function_exit, "6F]") +INSTR_0ARG(instr_nanos6_spawn_function_enter, "6F[") +INSTR_0ARG(instr_nanos6_spawn_function_exit, "6F]") -INSTR_0ARG(instr_nanos6_taskfor_start, "6O[") -INSTR_0ARG(instr_nanos6_taskfor_stop, "6O]") +INSTR_0ARG(instr_nanos6_taskfor_start, "6O[") +INSTR_0ARG(instr_nanos6_taskfor_stop, "6O]") -INSTR_0ARG(instr_nanos6_task_body_enter, "6t[") -INSTR_0ARG(instr_nanos6_task_body_exit, "6t]") +INSTR_0ARG(instr_nanos6_task_body_enter, "6t[") +INSTR_0ARG(instr_nanos6_task_body_exit, "6t]") -INSTR_0ARG(instr_nanos6_register_enter, "6Dr") -INSTR_0ARG(instr_nanos6_register_exit, "6DR") -INSTR_0ARG(instr_nanos6_unregister_enter, "6Du") -INSTR_0ARG(instr_nanos6_unregister_exit, "6DU") +INSTR_0ARG(instr_nanos6_register_enter, "6Dr") +INSTR_0ARG(instr_nanos6_register_exit, "6DR") +INSTR_0ARG(instr_nanos6_unregister_enter, "6Du") +INSTR_0ARG(instr_nanos6_unregister_exit, "6DU") -INSTR_0ARG(instr_nanos6_block_enter, "6Bb") -INSTR_0ARG(instr_nanos6_block_exit, "6BB") -INSTR_0ARG(instr_nanos6_unblock_enter, "6Bb") -INSTR_0ARG(instr_nanos6_unblock_exit, "6BB") -INSTR_0ARG(instr_nanos6_taskwait_enter, "6Bw") -INSTR_0ARG(instr_nanos6_taskwait_exit, "6BW") -INSTR_0ARG(instr_nanos6_waitfor_enter, "6Bf") -INSTR_0ARG(instr_nanos6_waitfor_exit, "6BF") +INSTR_0ARG(instr_nanos6_block_enter, "6Bb") +INSTR_0ARG(instr_nanos6_block_exit, "6BB") +INSTR_0ARG(instr_nanos6_unblock_enter, "6Bb") +INSTR_0ARG(instr_nanos6_unblock_exit, "6BB") +INSTR_0ARG(instr_nanos6_taskwait_enter, "6Bw") +INSTR_0ARG(instr_nanos6_taskwait_exit, "6BW") +INSTR_0ARG(instr_nanos6_waitfor_enter, "6Bf") +INSTR_0ARG(instr_nanos6_waitfor_exit, "6BF") -INSTR_0ARG(instr_nanos6_external_set, "6He") -INSTR_0ARG(instr_nanos6_external_unset, "6HE") -INSTR_0ARG(instr_nanos6_worker_set, "6Hw") -INSTR_0ARG(instr_nanos6_worker_unset, "6HW") -INSTR_0ARG(instr_nanos6_leader_set, "6Hl") -INSTR_0ARG(instr_nanos6_leader_unset, "6HL") -INSTR_0ARG(instr_nanos6_main_set, "6Hm") -INSTR_0ARG(instr_nanos6_main_unset, "6HM") +INSTR_0ARG(instr_nanos6_external_set, "6He") +INSTR_0ARG(instr_nanos6_external_unset, "6HE") +INSTR_0ARG(instr_nanos6_worker_set, "6Hw") +INSTR_0ARG(instr_nanos6_worker_unset, "6HW") +INSTR_0ARG(instr_nanos6_leader_set, "6Hl") +INSTR_0ARG(instr_nanos6_leader_unset, "6HL") +INSTR_0ARG(instr_nanos6_main_set, "6Hm") +INSTR_0ARG(instr_nanos6_main_unset, "6HM") -INSTR_0ARG(instr_nanos6_alloc_enter, "6Ma") -INSTR_0ARG(instr_nanos6_alloc_exit, "6MA") -INSTR_0ARG(instr_nanos6_free_enter, "6Mf") -INSTR_0ARG(instr_nanos6_free_exit, "6MF") +INSTR_0ARG(instr_nanos6_alloc_enter, "6Ma") +INSTR_0ARG(instr_nanos6_alloc_exit, "6MA") +INSTR_0ARG(instr_nanos6_free_enter, "6Mf") +INSTR_0ARG(instr_nanos6_free_exit, "6MF") static inline void instr_nanos6_task_create_and_execute(int32_t id, uint32_t typeid) diff --git a/test/emu/nanos6/nested-tasks.c b/test/emu/nanos6/nested-tasks.c index 020254b..e07de27 100644 --- a/test/emu/nanos6/nested-tasks.c +++ b/test/emu/nanos6/nested-tasks.c @@ -14,16 +14,14 @@ main(void) instr_nanos6_type_create(typeid); /* Create and run the tasks, one nested into another */ - for(int i = 0; i < ntasks; i++) - { + for (int i = 0; i < ntasks; i++) { instr_nanos6_handle_task_enter(); instr_nanos6_task_create_and_execute(i + 1, typeid); usleep(500); } /* End the tasks in the opposite order */ - for(int i = ntasks - 1; i >= 0; i--) - { + for (int i = ntasks - 1; i >= 0; i--) { instr_nanos6_task_end(i + 1); instr_nanos6_task_body_exit(); instr_nanos6_handle_task_exit(); diff --git a/test/emu/nanos6/task-types.c b/test/emu/nanos6/task-types.c index 319e1aa..b9a813e 100644 --- a/test/emu/nanos6/task-types.c +++ b/test/emu/nanos6/task-types.c @@ -14,11 +14,10 @@ main(void) int ntasks = 100; int ntypes = 10; - for(int i = 0; i < ntypes; i++) + for (int i = 0; i < ntypes; i++) instr_nanos6_type_create(i + 1); - for(int i = 0; i < ntasks; i++) - { + for (int i = 0; i < ntasks; i++) { instr_nanos6_task_create_and_execute(i + 1, (i % ntypes) + 1); usleep(500); instr_nanos6_task_end(i + 1); diff --git a/test/emu/nosv/nested-tasks.c b/test/emu/nosv/nested-tasks.c index 3624c10..4fdbbab 100644 --- a/test/emu/nosv/nested-tasks.c +++ b/test/emu/nosv/nested-tasks.c @@ -22,15 +22,14 @@ main(void) instr_nosv_type_create(typeid); /* Create and run the tasks, one nested into another */ - for(int i = 0; i < ntasks; i++) + for (int i = 0; i < ntasks; i++) create_and_run(i + 1, typeid, 500); /* End the tasks in the opposite order */ - for(int i = ntasks - 1; i >= 0; i--) + for (int i = ntasks - 1; i >= 0; i--) instr_nosv_task_end(i + 1); instr_end(); return 0; } - diff --git a/test/emu/nosv/pause.c b/test/emu/nosv/pause.c index 95ee1d1..0847986 100644 --- a/test/emu/nosv/pause.c +++ b/test/emu/nosv/pause.c @@ -27,4 +27,3 @@ main(void) return 0; } - diff --git a/test/emu/nosv/task-types.c b/test/emu/nosv/task-types.c index 31b7476..1555f2f 100644 --- a/test/emu/nosv/task-types.c +++ b/test/emu/nosv/task-types.c @@ -14,11 +14,10 @@ main(void) int ntasks = 100; int ntypes = 10; - for(int i=0; i +#include +#include #include +#include #include -#include #include #include -#include -#include +#include -#include "ovni.h" #include "compat.h" +#include "ovni.h" static inline void init(void) { char hostname[HOST_NAME_MAX]; - if(gethostname(hostname, HOST_NAME_MAX) != 0) - { + if (gethostname(hostname, HOST_NAME_MAX) != 0) { perror("gethostname failed"); exit(EXIT_FAILURE); } @@ -32,7 +31,8 @@ init(void) ovni_add_cpu(0, 0); } -static void emit(uint8_t *buf, size_t size) +static void +emit(uint8_t *buf, size_t size) { struct ovni_ev ev = {0}; ovni_ev_set_mcv(&ev, "O$$"); @@ -42,13 +42,13 @@ static void emit(uint8_t *buf, size_t size) #define NRUNS 50 -int main(void) +int +main(void) { size_t payload_size; uint8_t *payload_buf; - if(setenv("OVNI_TMPDIR", "/dev/shm/ovni-flush-overhead", 1) != 0) - { + if (setenv("OVNI_TMPDIR", "/dev/shm/ovni-flush-overhead", 1) != 0) { perror("setenv failed"); exit(EXIT_FAILURE); } @@ -59,21 +59,18 @@ int main(void) payload_size = 1024 * 1024; payload_buf = calloc(1, payload_size); - if(!payload_buf) - { + if (!payload_buf) { perror("calloc failed"); exit(EXIT_FAILURE); } double *times = calloc(sizeof(double), NRUNS); - if(times == NULL) - { + if (times == NULL) { perror("calloc failed"); exit(EXIT_FAILURE); } - for(int i=0; i < NRUNS; i++) - { + for (int i = 0; i < NRUNS; i++) { emit(payload_buf, payload_size); double t0 = (double) ovni_clock_now(); ovni_flush(); @@ -83,10 +80,10 @@ int main(void) } double mean = 0.0; - for(int i=0; i < NRUNS; i++) + for (int i = 0; i < NRUNS; i++) mean += times[i]; mean /= (double) NRUNS; - + fprintf(stderr, "mean %f ms\n", mean); /* It should be able to write 1 MiB in less than 1 ms */ @@ -94,8 +91,8 @@ int main(void) fprintf(stderr, "took too much time to flush: %f ms\n", mean); fprintf(stderr, "times (in ms):\n"); - for(int i=0; i < NRUNS; i++) - fprintf(stderr, " %4d %f\n", i, times[i]); + for (int i = 0; i < NRUNS; i++) + fprintf(stderr, " %4d %f\n", i, times[i]); exit(EXIT_FAILURE); } diff --git a/test/emu/ovni/flush.c b/test/emu/ovni/flush.c index 6f46d0e..49a142a 100644 --- a/test/emu/ovni/flush.c +++ b/test/emu/ovni/flush.c @@ -4,25 +4,24 @@ #define _POSIX_C_SOURCE 200112L #define _GNU_SOURCE -#include +#include +#include #include +#include #include -#include #include #include -#include -#include +#include -#include "ovni.h" #include "compat.h" +#include "ovni.h" static inline void init(void) { char hostname[HOST_NAME_MAX]; - if(gethostname(hostname, HOST_NAME_MAX) != 0) - { + if (gethostname(hostname, HOST_NAME_MAX) != 0) { perror("gethostname failed"); exit(EXIT_FAILURE); } @@ -32,7 +31,8 @@ init(void) ovni_add_cpu(0, 0); } -static void emit(uint8_t *buf, size_t size) +static void +emit(uint8_t *buf, size_t size) { struct ovni_ev ev = {0}; ovni_ev_set_mcv(&ev, "O$$"); @@ -40,7 +40,8 @@ static void emit(uint8_t *buf, size_t size) ovni_ev_jumbo_emit(&ev, buf, size); } -int main(void) +int +main(void) { size_t payload_size; uint8_t *payload_buf; @@ -50,8 +51,7 @@ int main(void) payload_size = (size_t) (0.9 * (double) OVNI_MAX_EV_BUF); payload_buf = calloc(1, payload_size); - if(!payload_buf) - { + if (!payload_buf) { perror("calloc failed"); exit(EXIT_FAILURE); } diff --git a/test/emu/ovni/mp-rank.c b/test/emu/ovni/mp-rank.c index fa2f619..e20ab05 100644 --- a/test/emu/ovni/mp-rank.c +++ b/test/emu/ovni/mp-rank.c @@ -3,8 +3,8 @@ #define _GNU_SOURCE -#include "ovni.h" #include "compat.h" +#include "ovni.h" #include #include @@ -15,27 +15,29 @@ #include #include -static void fail(const char *msg) +static void +fail(const char *msg) { fprintf(stderr, "%s\n", msg); abort(); } -#define INSTR_3ARG(name, mcv, ta, a, tb, b, tc, c) \ - static inline void name(ta a, tb b, tc c) \ - { \ - struct ovni_ev ev = {0}; \ - ovni_ev_set_mcv(&ev, mcv); \ - ovni_ev_set_clock(&ev, ovni_clock_now()); \ - ovni_payload_add(&ev, (uint8_t *)&a, sizeof(a)); \ - ovni_payload_add(&ev, (uint8_t *)&b, sizeof(b)); \ - ovni_payload_add(&ev, (uint8_t *)&c, sizeof(c)); \ - ovni_ev_emit(&ev); \ +#define INSTR_3ARG(name, mcv, ta, a, tb, b, tc, c) \ + static inline void name(ta a, tb b, tc c) \ + { \ + struct ovni_ev ev = {0}; \ + ovni_ev_set_mcv(&ev, mcv); \ + ovni_ev_set_clock(&ev, ovni_clock_now()); \ + ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \ + ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \ + ovni_payload_add(&ev, (uint8_t *) &c, sizeof(c)); \ + ovni_ev_emit(&ev); \ } INSTR_3ARG(instr_thread_execute, "OHx", int32_t, cpu, int32_t, creator_tid, uint64_t, tag) -static inline void instr_thread_end(void) +static inline void +instr_thread_end(void) { struct ovni_ev ev = {0}; @@ -47,36 +49,37 @@ static inline void instr_thread_end(void) ovni_flush(); } -static inline void instr_start(int rank, int nranks) +static inline void +instr_start(int rank, int nranks) { char hostname[HOST_NAME_MAX]; - if(gethostname(hostname, HOST_NAME_MAX) != 0) + if (gethostname(hostname, HOST_NAME_MAX) != 0) fail("gethostname failed"); ovni_proc_init(1, hostname, getpid()); - + ovni_proc_set_rank(rank, nranks); ovni_thread_init(gettid()); /* Only the rank 0 inform about all CPUs */ - if(rank == 0) - { + if (rank == 0) { /* Fake nranks cpus */ - for(int i=0; i < nranks; i++) + for (int i = 0; i < nranks; i++) ovni_add_cpu(i, i); } int curcpu = rank; fprintf(stderr, "thread %d has cpu %d (ncpus=%d)\n", - gettid(), curcpu, nranks); + gettid(), curcpu, nranks); instr_thread_execute(curcpu, -1, 0); } -static inline void instr_end(void) +static inline void +instr_end(void) { instr_thread_end(); ovni_thread_free(); @@ -132,7 +135,8 @@ task(int32_t id, uint32_t typeid, int us) ovni_ev_emit(&ev); } -int main(void) +int +main(void) { int rank = atoi(getenv("OVNI_RANK")); int nranks = atoi(getenv("OVNI_NRANKS")); @@ -143,11 +147,10 @@ int main(void) type_create(typeid); /* Create some fake nosv tasks */ - for(int i=0; i<10; i++) + for (int i = 0; i < 10; i++) task(i + 1, typeid, 5000); instr_end(); return 0; } - diff --git a/test/emu/ovni/mp-simple.c b/test/emu/ovni/mp-simple.c index 44d690e..cb6d532 100644 --- a/test/emu/ovni/mp-simple.c +++ b/test/emu/ovni/mp-simple.c @@ -3,8 +3,8 @@ #define _GNU_SOURCE -#include "ovni.h" #include "compat.h" +#include "ovni.h" #include #include @@ -16,27 +16,29 @@ #include #include -static void fail(const char *msg) +static void +fail(const char *msg) { fprintf(stderr, "%s\n", msg); abort(); } -#define INSTR_3ARG(name, mcv, ta, a, tb, b, tc, c) \ - static inline void name(ta a, tb b, tc c) \ - { \ - struct ovni_ev ev = {0}; \ - ovni_ev_set_mcv(&ev, mcv); \ - ovni_ev_set_clock(&ev, ovni_clock_now()); \ - ovni_payload_add(&ev, (uint8_t *)&a, sizeof(a)); \ - ovni_payload_add(&ev, (uint8_t *)&b, sizeof(b)); \ - ovni_payload_add(&ev, (uint8_t *)&c, sizeof(c)); \ - ovni_ev_emit(&ev); \ +#define INSTR_3ARG(name, mcv, ta, a, tb, b, tc, c) \ + static inline void name(ta a, tb b, tc c) \ + { \ + struct ovni_ev ev = {0}; \ + ovni_ev_set_mcv(&ev, mcv); \ + ovni_ev_set_clock(&ev, ovni_clock_now()); \ + ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \ + ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \ + ovni_payload_add(&ev, (uint8_t *) &c, sizeof(c)); \ + ovni_ev_emit(&ev); \ } INSTR_3ARG(instr_thread_execute, "OHx", int32_t, cpu, int32_t, creator_tid, uint64_t, tag) -static inline void instr_thread_end(void) +static inline void +instr_thread_end(void) { struct ovni_ev ev = {0}; @@ -48,29 +50,27 @@ static inline void instr_thread_end(void) ovni_flush(); } -static inline void instr_start(int rank) +static inline void +instr_start(int rank) { cpu_set_t mask; char hostname[HOST_NAME_MAX]; int i, j = 0, curcpu = -1; int last_phy; - if(gethostname(hostname, HOST_NAME_MAX) != 0) + if (gethostname(hostname, HOST_NAME_MAX) != 0) fail("gethostname failed"); - if(sched_getaffinity(0, sizeof(mask), &mask) < 0) + if (sched_getaffinity(0, sizeof(mask), &mask) < 0) fail("sched_getaffinity failed"); ovni_proc_init(1, hostname, getpid()); ovni_thread_init(gettid()); /* Only the rank 0 inform about all CPUs */ - if(rank == 0) - { - for(i=0; i < CPU_SETSIZE; i++) - { - if(CPU_ISSET(i, &mask)) - { + if (rank == 0) { + for (i = 0; i < CPU_SETSIZE; i++) { + if (CPU_ISSET(i, &mask)) { last_phy = i; if (rank == 0) @@ -79,28 +79,30 @@ static inline void instr_start(int rank) } } - if(CPU_COUNT(&mask) == 1) + if (CPU_COUNT(&mask) == 1) curcpu = last_phy; else curcpu = -1; fprintf(stderr, "thread %d has cpu %d (ncpus=%d)\n", - gettid(), curcpu, CPU_COUNT(&mask)); + gettid(), curcpu, CPU_COUNT(&mask)); instr_thread_execute(curcpu, -1, 0); } -static inline void instr_end(void) +static inline void +instr_end(void) { instr_thread_end(); ovni_thread_free(); ovni_proc_fini(); } -int main(void) +int +main(void) { int rank = atoi(getenv("OVNI_RANK")); - //int nranks = atoi(getenv("OVNI_NRANKS")); + // int nranks = atoi(getenv("OVNI_NRANKS")); instr_start(rank); @@ -110,4 +112,3 @@ int main(void) return 0; } - diff --git a/test/rt/nanos6/if0.c b/test/rt/nanos6/if0.c index fff4bc8..cdfafc3 100644 --- a/test/rt/nanos6/if0.c +++ b/test/rt/nanos6/if0.c @@ -4,9 +4,10 @@ #define _GNU_SOURCE #include -int main(void) +int +main(void) { - #pragma oss task if(0) +#pragma oss task if (0) { usleep(1000); } diff --git a/test/rt/nanos6/nested-task.c b/test/rt/nanos6/nested-task.c index 63a9e5d..ffe43bd 100644 --- a/test/rt/nanos6/nested-task.c +++ b/test/rt/nanos6/nested-task.c @@ -1,14 +1,15 @@ /* Copyright (c) 2022 Barcelona Supercomputing Center (BSC) * SPDX-License-Identifier: GPL-3.0-or-later */ -int main(void) +int +main(void) { - #pragma oss task +#pragma oss task { - #pragma oss task - { - } - #pragma oss taskwait +#pragma oss task + { + } +#pragma oss taskwait } return 0; } diff --git a/test/rt/nanos6/sched-add.c b/test/rt/nanos6/sched-add.c index 7a508b0..4efeab6 100644 --- a/test/rt/nanos6/sched-add.c +++ b/test/rt/nanos6/sched-add.c @@ -36,25 +36,26 @@ do_run(void) memset(handle, 0, ntasks * sizeof(void *)); atomic_store(&nhandles, 0); - for(int t = 0; t < ntasks; t++) + for (int t = 0; t < ntasks; t++) do_task(t); /* Wait for all tasks to fill the handle */ - while (atomic_load(&nhandles) < ntasks); + while (atomic_load(&nhandles) < ntasks) + ; /* Is ok if we call unblock before the block happens */ - for(int t = 0; t < ntasks; t++) - { + for (int t = 0; t < ntasks; t++) { if (handle[t] == NULL) abort(); nanos6_unblock_task(handle[t]); } - #pragma oss taskwait +#pragma oss taskwait } -static int get_ncpus(void) +static int +get_ncpus(void) { return (int) nanos6_get_num_cpus(); } @@ -66,13 +67,12 @@ main(void) handle = calloc(ntasks, sizeof(void *)); - if(handle == NULL) - { + if (handle == NULL) { perror("calloc failed"); return -1; } - for(int run = 0; run < nruns; run++) + for (int run = 0; run < nruns; run++) do_run(); return 0; diff --git a/test/rt/nanos6/several-tasks.c b/test/rt/nanos6/several-tasks.c index b73881e..5fc020c 100644 --- a/test/rt/nanos6/several-tasks.c +++ b/test/rt/nanos6/several-tasks.c @@ -1,17 +1,16 @@ /* Copyright (c) 2022 Barcelona Supercomputing Center (BSC) * SPDX-License-Identifier: GPL-3.0-or-later */ -int main(void) +int +main(void) { - for(int i = 0; i < 5000; i++) - { - #pragma oss task + for (int i = 0; i < 5000; i++) { +#pragma oss task { - for(volatile long j = 0; j < 10000L; j++) - { + for (volatile long j = 0; j < 10000L; j++) { } } } - #pragma oss taskwait +#pragma oss taskwait return 0; } diff --git a/test/rt/nanos6/simple-task.c b/test/rt/nanos6/simple-task.c index 0299899..f983275 100644 --- a/test/rt/nanos6/simple-task.c +++ b/test/rt/nanos6/simple-task.c @@ -1,9 +1,10 @@ /* Copyright (c) 2022 Barcelona Supercomputing Center (BSC) * SPDX-License-Identifier: GPL-3.0-or-later */ -int main(void) +int +main(void) { - #pragma oss task +#pragma oss task { } return 0; diff --git a/test/rt/nanos6/taskfor.c b/test/rt/nanos6/taskfor.c index e9297d5..95bf6ce 100644 --- a/test/rt/nanos6/taskfor.c +++ b/test/rt/nanos6/taskfor.c @@ -4,10 +4,11 @@ #define _GNU_SOURCE #include -int main(void) +int +main(void) { - #pragma oss task for - for(int i = 0; i < 1024; i++) +#pragma oss task for + for (int i = 0; i < 1024; i++) usleep(1000); return 0; diff --git a/test/rt/nosv/attach.c b/test/rt/nosv/attach.c index 9d5d22b..0e508e5 100644 --- a/test/rt/nosv/attach.c +++ b/test/rt/nosv/attach.c @@ -3,33 +3,35 @@ #define _DEFAULT_SOURCE -#include #include +#include #include "common.h" -int main(void) +int +main(void) { nosv_init(); nosv_task_type_t type; - if(nosv_type_init(&type, NULL, NULL, NULL, "adopted", NULL, - NULL, NOSV_TYPE_INIT_EXTERNAL) != 0) + if (nosv_type_init(&type, NULL, NULL, NULL, "adopted", NULL, + NULL, NOSV_TYPE_INIT_EXTERNAL) + != 0) die("nosv_type_init failed\n"); nosv_task_t task; - if(nosv_attach(&task, type, 0, NULL, 0) != 0) + if (nosv_attach(&task, type, 0, NULL, 0) != 0) die("nosv_attach failed\n"); usleep(100); - if(nosv_detach(0) != 0) + if (nosv_detach(0) != 0) die("nosv_detach failed\n"); - if(nosv_type_destroy(type, 0) != 0) + if (nosv_type_destroy(type, 0) != 0) die("nosv_type_destroy failed\n"); - if(nosv_shutdown() != 0) + if (nosv_shutdown() != 0) die("nosv_shutdown failed\n"); return 0; diff --git a/trace.c b/trace.c index a024b2c..1ce3d6c 100644 --- a/trace.c +++ b/trace.c @@ -6,20 +6,19 @@ #define _GNU_SOURCE #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include static int find_dir_prefix_str(const char *dirname, const char *prefix, const char **str) @@ -29,18 +28,18 @@ find_dir_prefix_str(const char *dirname, const char *prefix, const char **str) p = dirname; /* Check the prefix */ - if(strncmp(p, prefix, strlen(prefix)) != 0) + if (strncmp(p, prefix, strlen(prefix)) != 0) return -1; p += strlen(prefix); /* Find the dot */ - if(*p != '.') + if (*p != '.') return -1; p++; - if(str) + if (str) *str = p; return 0; @@ -51,7 +50,7 @@ find_dir_prefix_int(const char *dirname, const char *prefix, int *num) { const char *p; - if(find_dir_prefix_str(dirname, prefix, &p) != 0) + if (find_dir_prefix_str(dirname, prefix, &p) != 0) return -1; /* Convert the suffix string to a number */ @@ -66,9 +65,8 @@ count_dir_prefix(DIR *dir, const char *prefix) struct dirent *dirent; size_t n = 0; - while((dirent = readdir(dir)) != NULL) - { - if(find_dir_prefix_str(dirent->d_name, prefix, NULL) != 0) + while ((dirent = readdir(dir)) != NULL) { + if (find_dir_prefix_str(dirent->d_name, prefix, NULL) != 0) continue; n++; @@ -88,8 +86,7 @@ load_thread(struct ovni_ethread *thread, struct ovni_eproc *proc, int index, int thread->state = TH_ST_UNKNOWN; thread->proc = proc; - if(strlen(filepath) >= PATH_MAX) - { + if (strlen(filepath) >= PATH_MAX) { err("filepath too large: %s\n", filepath); return -1; } @@ -105,24 +102,21 @@ load_proc_metadata(struct ovni_eproc *proc, int *rank_enabled) JSON_Object *meta; meta = json_value_get_object(proc->meta); - if(meta == NULL) + if (meta == NULL) die("load_proc_metadata: json_value_get_object() failed\n"); JSON_Value *appid_val = json_object_get_value(meta, "app_id"); - if(appid_val == NULL) + if (appid_val == NULL) die("process %d is missing app_id in metadata\n", proc->pid); proc->appid = (int) json_number(appid_val); JSON_Value *rank_val = json_object_get_value(meta, "rank"); - if(rank_val != NULL) - { + if (rank_val != NULL) { proc->rank = (int) json_number(rank_val); *rank_enabled = 1; - } - else - { + } else { proc->rank = -1; } } @@ -131,40 +125,35 @@ static void check_metadata_version(struct ovni_eproc *proc) { JSON_Object *meta = json_value_get_object(proc->meta); - if(meta == NULL) + if (meta == NULL) die("check_metadata_version: json_value_get_object() failed\n"); JSON_Value *version_val = json_object_get_value(meta, "version"); - if(version_val == NULL) - { + if (version_val == NULL) { die("process %d is missing attribute \"version\" in metadata\n", - proc->pid); + proc->pid); } int version = (int) json_number(version_val); - if(version != OVNI_METADATA_VERSION) - { + if (version != OVNI_METADATA_VERSION) { die("pid %d: metadata version mismatch %d (expected %d)\n", - proc->pid, version, - OVNI_METADATA_VERSION); + proc->pid, version, + OVNI_METADATA_VERSION); } JSON_Value *mversion_val = json_object_get_value(meta, "model_version"); - if(mversion_val == NULL) - { + if (mversion_val == NULL) { die("process %d is missing attribute \"model_version\" in metadata\n", - proc->pid); + proc->pid); } const char *mversion = json_string(mversion_val); - if(strcmp(mversion, OVNI_MODEL_VERSION) != 0) - { + if (strcmp(mversion, OVNI_MODEL_VERSION) != 0) { die("pid %d: metadata model version mismatch '%s' (expected '%s')\n", - proc->pid, mversion, - OVNI_MODEL_VERSION); - + proc->pid, mversion, + OVNI_MODEL_VERSION); } } @@ -174,9 +163,9 @@ compare_int(const void *a, const void *b) int aa = *(const int *) a; int bb = *(const int *) b; - if(aa < bb) + if (aa < bb) return -1; - else if(aa > bb) + else if (aa > bb) return +1; else return 0; @@ -197,16 +186,13 @@ load_proc(struct ovni_eproc *proc, struct ovni_loom *loom, int index, int pid, c proc->gindex = total_procs++; proc->loom = loom; - if(snprintf(path, PATH_MAX, "%s/%s", procdir, "metadata.json") >= - PATH_MAX) - { + if (snprintf(path, PATH_MAX, "%s/%s", procdir, "metadata.json") >= PATH_MAX) { err("snprintf: path too large: %s\n", procdir); abort(); } proc->meta = json_parse_file_with_comments(path); - if(proc->meta == NULL) - { + if (proc->meta == NULL) { err("error loading metadata from %s\n", path); return -1; } @@ -216,51 +202,45 @@ load_proc(struct ovni_eproc *proc, struct ovni_loom *loom, int index, int pid, c /* The appid is populated from the metadata */ load_proc_metadata(proc, &loom->rank_enabled); - if((dir = opendir(procdir)) == NULL) - { + if ((dir = opendir(procdir)) == NULL) { fprintf(stderr, "opendir %s failed: %s\n", - procdir, strerror(errno)); + procdir, strerror(errno)); return -1; } proc->nthreads = count_dir_prefix(dir, "thread"); - if(proc->nthreads <= 0) - { + if (proc->nthreads <= 0) { err("cannot find any thread for process %d\n", - proc->pid); + proc->pid); return -1; } proc->thread = calloc(proc->nthreads, sizeof(struct ovni_ethread)); - if(proc->thread == NULL) - { + if (proc->thread == NULL) { perror("calloc failed"); return -1; } int *tids; - if((tids = calloc(proc->nthreads, sizeof(int))) == NULL) - { + if ((tids = calloc(proc->nthreads, sizeof(int))) == NULL) { perror("calloc failed\n"); return -1; } rewinddir(dir); - for(size_t i = 0; i < proc->nthreads; ) - { + for (size_t i = 0; i < proc->nthreads;) { dirent = readdir(dir); - if(dirent == NULL) - { + if (dirent == NULL) { err("inconsistent: readdir returned NULL\n"); return -1; } - if(find_dir_prefix_int(dirent->d_name, "thread", &tids[i]) != 0) + if (find_dir_prefix_int(dirent->d_name, "thread", &tids[i]) != 0) continue; i++; @@ -271,20 +251,17 @@ load_proc(struct ovni_eproc *proc, struct ovni_loom *loom, int index, int pid, c /* Sort threads by ascending TID */ qsort(tids, proc->nthreads, sizeof(int), compare_int); - for(size_t i = 0; i < proc->nthreads; i++) - { + for (size_t i = 0; i < proc->nthreads; i++) { int tid = tids[i]; - if(snprintf(path, PATH_MAX, "%s/thread.%d", procdir, tid) >= - PATH_MAX) - { + if (snprintf(path, PATH_MAX, "%s/thread.%d", procdir, tid) >= PATH_MAX) { err("snprintf: path too large: %s\n", procdir); abort(); } thread = &proc->thread[i]; - if(load_thread(thread, proc, i, tid, path) != 0) + if (load_thread(thread, proc, i, tid, path) != 0) return -1; } @@ -302,27 +279,24 @@ load_loom(struct ovni_loom *loom, char *loomdir) DIR *dir; struct dirent *dirent; - if((dir = opendir(loomdir)) == NULL) - { + if ((dir = opendir(loomdir)) == NULL) { fprintf(stderr, "opendir %s failed: %s\n", - loomdir, strerror(errno)); + loomdir, strerror(errno)); return -1; } loom->rank_enabled = 0; loom->nprocs = count_dir_prefix(dir, "proc"); - if(loom->nprocs <= 0) - { + if (loom->nprocs <= 0) { err("cannot find any process directory in loom %s\n", - loom->hostname); + loom->hostname); return -1; } loom->proc = calloc(loom->nprocs, sizeof(struct ovni_eproc)); - if(loom->proc == NULL) - { + if (loom->proc == NULL) { perror("calloc failed"); return -1; } @@ -330,28 +304,24 @@ load_loom(struct ovni_loom *loom, char *loomdir) rewinddir(dir); i = 0; - while((dirent = readdir(dir)) != NULL) - { - if(find_dir_prefix_int(dirent->d_name, "proc", &pid) != 0) + while ((dirent = readdir(dir)) != NULL) { + if (find_dir_prefix_int(dirent->d_name, "proc", &pid) != 0) continue; sprintf(path, "%s/%s", loomdir, dirent->d_name); - if(i >= loom->nprocs) - { + if (i >= loom->nprocs) { err("more process than expected\n"); abort(); } - if(load_proc(&loom->proc[i], loom, i, pid, path) != 0) + if (load_proc(&loom->proc[i], loom, i, pid, path) != 0) return -1; i++; - } - if(i != loom->nprocs) - { + if (i != loom->nprocs) { err("unexpected number of processes\n"); abort(); } @@ -359,15 +329,12 @@ load_loom(struct ovni_loom *loom, char *loomdir) closedir(dir); /* Ensure all process have the rank, if enabled in any */ - if(loom->rank_enabled) - { - for(i = 0; i < loom->nprocs; i++) - { + if (loom->rank_enabled) { + for (i = 0; i < loom->nprocs; i++) { struct ovni_eproc *proc = &loom->proc[i]; - if(proc->rank < 0) - { + if (proc->rank < 0) { die("process %d is missing the rank\n", - proc->pid); + proc->pid); } } } @@ -388,16 +355,15 @@ loom_to_host(const char *loom_name, char *host, int n) { int i; - for(i = 0; i < n; i++) - { + for (i = 0; i < n; i++) { /* Copy until dot or end */ - if(loom_name[i] != '.' && loom_name[i] != '\0') + if (loom_name[i] != '.' && loom_name[i] != '\0') host[i] = loom_name[i]; else break; } - if(i == n) + if (i == n) die("loom host name %s too long\n", loom_name); host[i] = '\0'; @@ -408,24 +374,21 @@ ovni_load_trace(struct ovni_trace *trace, char *tracedir) { DIR *dir; - if((dir = opendir(tracedir)) == NULL) - { + if ((dir = opendir(tracedir)) == NULL) { err("opendir %s failed: %s\n", tracedir, strerror(errno)); return -1; } trace->nlooms = count_dir_prefix(dir, "loom"); - if(trace->nlooms == 0) - { + if (trace->nlooms == 0) { err("cannot find any loom in %s\n", tracedir); return -1; } trace->loom = calloc(trace->nlooms, sizeof(struct ovni_loom)); - if(trace->loom == NULL) - { + if (trace->loom == NULL) { perror("calloc failed\n"); return -1; } @@ -435,25 +398,21 @@ ovni_load_trace(struct ovni_trace *trace, char *tracedir) size_t l = 0; struct dirent *dirent; - while((dirent = readdir(dir)) != NULL) - { + while ((dirent = readdir(dir)) != NULL) { struct ovni_loom *loom = &trace->loom[l]; const char *loom_name; - if(find_dir_prefix_str(dirent->d_name, "loom", &loom_name) != 0) - { + if (find_dir_prefix_str(dirent->d_name, "loom", &loom_name) != 0) { /* Ignore other files in tracedir */ continue; } - if(l >= trace->nlooms) - { + if (l >= trace->nlooms) { err("extra loom detected\n"); return -1; } /* Copy the complete loom directory name to looms */ - if(snprintf(loom->dname, PATH_MAX, "%s", dirent->d_name) >= PATH_MAX) - { + if (snprintf(loom->dname, PATH_MAX, "%s", dirent->d_name) >= PATH_MAX) { err("error: loom name %s too long\n", dirent->d_name); return -1; } @@ -465,30 +424,28 @@ ovni_load_trace(struct ovni_trace *trace, char *tracedir) /* Sort the looms, so we get the hostnames in alphanumeric order */ qsort(trace->loom, trace->nlooms, sizeof(struct ovni_loom), - compare_looms); + compare_looms); - for(size_t i = 0; i < trace->nlooms; i++) - { + for (size_t i = 0; i < trace->nlooms; i++) { struct ovni_loom *loom = &trace->loom[i]; const char *name = NULL; - if(find_dir_prefix_str(loom->dname, "loom", &name) != 0) - { + if (find_dir_prefix_str(loom->dname, "loom", &name) != 0) { err("error: mismatch for loom %s\n", loom->dname); return -1; } loom_to_host(name, loom->hostname, sizeof(loom->hostname)); - if(snprintf(loom->path, PATH_MAX, "%s/%s", - tracedir, loom->dname) >= PATH_MAX) - { + if (snprintf(loom->path, PATH_MAX, "%s/%s", + tracedir, loom->dname) + >= PATH_MAX) { err("error: loom path %s/%s too long\n", - tracedir, loom->dname); + tracedir, loom->dname); return -1; } - if(load_loom(loom, loom->path) != 0) + if (load_loom(loom, loom->path) != 0) return -1; } @@ -500,30 +457,27 @@ check_stream_header(struct ovni_stream *stream) { int ret = 0; - if(stream->size < sizeof(struct ovni_stream_header)) - { + if (stream->size < sizeof(struct ovni_stream_header)) { err("stream %d: incomplete stream header\n", - stream->tid); + stream->tid); return -1; } struct ovni_stream_header *h = (struct ovni_stream_header *) stream->buf; - if(memcmp(h->magic, OVNI_STREAM_MAGIC, 4) != 0) - { + if (memcmp(h->magic, OVNI_STREAM_MAGIC, 4) != 0) { char magic[5]; memcpy(magic, h->magic, 4); magic[4] = '\0'; err("stream %d: wrong stream magic '%s' (expected '%s')\n", - stream->tid, magic, OVNI_STREAM_MAGIC); + stream->tid, magic, OVNI_STREAM_MAGIC); ret = -1; } - if(h->version != OVNI_STREAM_VERSION) - { + if (h->version != OVNI_STREAM_VERSION) { err("stream %d: stream version mismatch %u (expected %u)\n", - stream->tid, h->version, OVNI_STREAM_VERSION); + stream->tid, h->version, OVNI_STREAM_VERSION); ret = -1; } @@ -534,15 +488,13 @@ static int load_stream_fd(struct ovni_stream *stream, int fd) { struct stat st; - if(fstat(fd, &st) < 0) - { + if (fstat(fd, &st) < 0) { perror("fstat failed"); return -1; } /* Error because it doesn't have the header */ - if(st.st_size == 0) - { + if (st.st_size == 0) { err("stream %d is empty\n", stream->tid); return -1; } @@ -550,8 +502,7 @@ load_stream_fd(struct ovni_stream *stream, int fd) int prot = PROT_READ | PROT_WRITE; stream->buf = mmap(NULL, st.st_size, prot, MAP_PRIVATE, fd, 0); - if(stream->buf == MAP_FAILED) - { + if (stream->buf == MAP_FAILED) { perror("mmap failed"); return -1; } @@ -566,31 +517,28 @@ load_stream_buf(struct ovni_stream *stream, struct ovni_ethread *thread) { int fd; - if((fd = open(thread->tracefile, O_RDWR)) == -1) - { + if ((fd = open(thread->tracefile, O_RDWR)) == -1) { perror("open failed"); return -1; } - if(load_stream_fd(stream, fd) != 0) + if (load_stream_fd(stream, fd) != 0) return -1; - if(check_stream_header(stream) != 0) - { + if (check_stream_header(stream) != 0) { err("stream %d: bad header\n", stream->tid); return -1; } stream->offset = sizeof(struct ovni_stream_header); - if(stream->offset == stream->size) + if (stream->offset == stream->size) stream->active = 0; else stream->active = 1; /* No need to keep the fd open */ - if(close(fd)) - { + if (close(fd)) { perror("close failed"); return -1; } @@ -610,14 +558,11 @@ ovni_load_streams(struct ovni_trace *trace) trace->nstreams = 0; - for(i=0; inlooms; i++) - { + for (i = 0; i < trace->nlooms; i++) { loom = &trace->loom[i]; - for(j=0; jnprocs; j++) - { + for (j = 0; j < loom->nprocs; j++) { proc = &loom->proc[j]; - for(k=0; knthreads; k++) - { + for (k = 0; k < proc->nthreads; k++) { trace->nstreams++; } } @@ -625,22 +570,18 @@ ovni_load_streams(struct ovni_trace *trace) trace->stream = calloc(trace->nstreams, sizeof(struct ovni_stream)); - if(trace->stream == NULL) - { + if (trace->stream == NULL) { perror("calloc failed"); return -1; } err("loaded %ld streams\n", trace->nstreams); - for(s=0, i=0; inlooms; i++) - { + for (s = 0, i = 0; i < trace->nlooms; i++) { loom = &trace->loom[i]; - for(j=0; jnprocs; j++) - { + for (j = 0; j < loom->nprocs; j++) { proc = &loom->proc[j]; - for(k=0; knthreads; k++) - { + for (k = 0; k < proc->nthreads; k++) { thread = &proc->thread[k]; stream = &trace->stream[s++]; @@ -652,12 +593,10 @@ ovni_load_streams(struct ovni_trace *trace) stream->offset = 0; stream->cur_ev = NULL; - if(load_stream_buf(stream, thread) != 0) - { + if (load_stream_buf(stream, thread) != 0) { err("load_stream_buf failed\n"); return -1; } - } } } @@ -668,10 +607,9 @@ ovni_load_streams(struct ovni_trace *trace) void ovni_free_streams(struct ovni_trace *trace) { - for(size_t i = 0; i < trace->nstreams; i++) - { + for (size_t i = 0; i < trace->nstreams; i++) { struct ovni_stream *stream = &trace->stream[i]; - if(munmap(stream->buf, stream->size) != 0) + if (munmap(stream->buf, stream->size) != 0) die("munmap stream failed: %s\n", strerror(errno)); } @@ -683,10 +621,8 @@ ovni_free_trace(struct ovni_trace *trace) { size_t i, j; - for(i=0; inlooms; i++) - { - for(j=0; jloom[i].nprocs; j++) - { + for (i = 0; i < trace->nlooms; i++) { + for (j = 0; j < trace->loom[i].nprocs; j++) { free(trace->loom[i].proc[j].thread); } @@ -699,23 +635,21 @@ ovni_free_trace(struct ovni_trace *trace) int ovni_load_next_event(struct ovni_stream *stream) { - if(stream->active == 0) - { + if (stream->active == 0) { dbg("stream is inactive, cannot load more events\n"); return -1; } /* Only step the offset if we have load an event */ - if(stream->cur_ev != NULL) + if (stream->cur_ev != NULL) stream->offset += ovni_ev_size(stream->cur_ev); /* It cannot overflow, otherwise we are reading garbage */ - if(stream->offset > stream->size) + if (stream->offset > stream->size) die("ovni_load_next_event: stream offset exceeds size\n"); /* We have reached the end */ - if(stream->offset == stream->size) - { + if (stream->offset == stream->size) { stream->active = 0; stream->cur_ev = NULL; dbg("stream %d runs out of events\n", stream->tid); diff --git a/trace.h b/trace.h index 575e2c8..998a77f 100644 --- a/trace.h +++ b/trace.h @@ -4,8 +4,8 @@ #ifndef OVNI_TRACE_H #define OVNI_TRACE_H -#include "ovni.h" #include "emu.h" +#include "ovni.h" int ovni_load_next_event(struct ovni_stream *stream); diff --git a/uthash.h b/uthash.h index 76bdca6..a29deb8 100644 --- a/uthash.h +++ b/uthash.h @@ -26,40 +26,40 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define UTHASH_VERSION 2.1.0 -#include /* memcmp, memset, strlen */ -#include /* ptrdiff_t */ -#include /* exit */ +#include /* ptrdiff_t */ +#include /* exit */ +#include /* memcmp, memset, strlen */ /* These macros use decltype or the earlier __typeof GNU extension. As decltype is only available in newer compilers (VS2010 or gcc 4.3+ when compiling c++ source) this code uses whatever method is needed or, for VS2008 where neither is available, uses casting workarounds. */ #if !defined(DECLTYPE) && !defined(NO_DECLTYPE) -#if defined(_MSC_VER) /* MS compiler */ -#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ #define DECLTYPE(x) (decltype(x)) -#else /* VS2008 or older (or VS2010 in C mode) */ +#else /* VS2008 or older (or VS2010 in C mode) */ #define NO_DECLTYPE #endif #elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) #define NO_DECLTYPE -#else /* GNU, Sun and other compilers */ +#else /* GNU, Sun and other compilers */ #define DECLTYPE(x) (__typeof(x)) #endif #endif #ifdef NO_DECLTYPE #define DECLTYPE(x) -#define DECLTYPE_ASSIGN(dst,src) \ -do { \ - char **_da_dst = (char**)(&(dst)); \ - *_da_dst = (char*)(src); \ -} while (0) +#define DECLTYPE_ASSIGN(dst, src) \ + do { \ + char **_da_dst = (char **) (&(dst)); \ + *_da_dst = (char *) (src); \ + } while (0) #else -#define DECLTYPE_ASSIGN(dst,src) \ -do { \ - (dst) = DECLTYPE(dst)(src); \ -} while (0) +#define DECLTYPE_ASSIGN(dst, src) \ + do { \ + (dst) = DECLTYPE(dst)(src); \ + } while (0) #endif /* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */ @@ -80,13 +80,13 @@ typedef unsigned char uint8_t; #endif #ifndef uthash_malloc -#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ +#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ #endif #ifndef uthash_free -#define uthash_free(ptr,sz) free(ptr) /* free fcn */ +#define uthash_free(ptr, sz) free(ptr) /* free fcn */ #endif #ifndef uthash_bzero -#define uthash_bzero(a,n) memset(a,'\0',n) +#define uthash_bzero(a, n) memset(a, '\0', n) #endif #ifndef uthash_strlen #define uthash_strlen(s) strlen(s) @@ -96,18 +96,18 @@ typedef unsigned char uint8_t; /* This warning will not catch programs that define uthash_memcmp AFTER including uthash.h. */ #warning "uthash_memcmp is deprecated; please use HASH_KEYCMP instead" #else -#define uthash_memcmp(a,b,n) memcmp(a,b,n) +#define uthash_memcmp(a, b, n) memcmp(a, b, n) #endif #ifndef HASH_KEYCMP -#define HASH_KEYCMP(a,b,n) uthash_memcmp(a,b,n) +#define HASH_KEYCMP(a, b, n) uthash_memcmp(a, b, n) #endif #ifndef uthash_noexpand_fyi -#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ +#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ #endif #ifndef uthash_expand_fyi -#define uthash_expand_fyi(tbl) /* can be defined to log expands */ +#define uthash_expand_fyi(tbl) /* can be defined to log expands */ #endif #ifndef HASH_NONFATAL_OOM @@ -118,17 +118,22 @@ typedef unsigned char uint8_t; /* malloc failures can be recovered from */ #ifndef uthash_nonfatal_oom -#define uthash_nonfatal_oom(obj) do {} while (0) /* non-fatal OOM error */ +#define uthash_nonfatal_oom(obj) \ + do { \ + } while (0) /* non-fatal OOM error */ #endif -#define HASH_RECORD_OOM(oomed) do { (oomed) = 1; } while (0) +#define HASH_RECORD_OOM(oomed) \ + do { \ + (oomed) = 1; \ + } while (0) #define IF_HASH_NONFATAL_OOM(x) x #else /* malloc failures result in lost memory, hash tables are unusable */ #ifndef uthash_fatal -#define uthash_fatal(msg) exit(-1) /* fatal OOM error */ +#define uthash_fatal(msg) exit(-1) /* fatal OOM error */ #endif #define HASH_RECORD_OOM(oomed) uthash_fatal("out of memory") @@ -137,308 +142,307 @@ typedef unsigned char uint8_t; #endif /* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ #define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */ -#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ +#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ /* calculate the element whose hash handle address is hhp */ -#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) +#define ELMT_FROM_HH(tbl, hhp) ((void *) (((char *) (hhp)) - ((tbl)->hho))) /* calculate the hash handle from element address elp */ -#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle *)(((char*)(elp)) + ((tbl)->hho))) +#define HH_FROM_ELMT(tbl, elp) ((UT_hash_handle *) (((char *) (elp)) + ((tbl)->hho))) -#define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \ -do { \ - struct UT_hash_handle *_hd_hh_item = (itemptrhh); \ - unsigned _hd_bkt; \ - HASH_TO_BKT(_hd_hh_item->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ - (head)->hh.tbl->buckets[_hd_bkt].count++; \ - _hd_hh_item->hh_next = NULL; \ - _hd_hh_item->hh_prev = NULL; \ -} while (0) +#define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \ + do { \ + struct UT_hash_handle *_hd_hh_item = (itemptrhh); \ + unsigned _hd_bkt; \ + HASH_TO_BKT(_hd_hh_item->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + (head)->hh.tbl->buckets[_hd_bkt].count++; \ + _hd_hh_item->hh_next = NULL; \ + _hd_hh_item->hh_prev = NULL; \ + } while (0) -#define HASH_VALUE(keyptr,keylen,hashv) \ -do { \ - HASH_FCN(keyptr, keylen, hashv); \ -} while (0) +#define HASH_VALUE(keyptr, keylen, hashv) \ + do { \ + HASH_FCN(keyptr, keylen, hashv); \ + } while (0) -#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \ -do { \ - (out) = NULL; \ - if (head) { \ - unsigned _hf_bkt; \ - HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ - if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \ - HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \ - } \ - } \ -} while (0) +#define HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, hashval, out) \ + do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_bkt; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ + if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \ + HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[_hf_bkt], keyptr, keylen, hashval, out); \ + } \ + } \ + } while (0) -#define HASH_FIND(hh,head,keyptr,keylen,out) \ -do { \ - unsigned _hf_hashv; \ - HASH_VALUE(keyptr, keylen, _hf_hashv); \ - HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ -} while (0) +#define HASH_FIND(hh, head, keyptr, keylen, out) \ + do { \ + unsigned _hf_hashv; \ + HASH_VALUE(keyptr, keylen, _hf_hashv); \ + HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ + } while (0) #ifdef HASH_BLOOM #define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) -#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL) -#define HASH_BLOOM_MAKE(tbl,oomed) \ -do { \ - (tbl)->bloom_nbits = HASH_BLOOM; \ - (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ - if (!(tbl)->bloom_bv) { \ - HASH_RECORD_OOM(oomed); \ - } else { \ - uthash_bzero((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ - (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ - } \ -} while (0) +#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN / 8UL) + (((HASH_BLOOM_BITLEN % 8UL) != 0UL) ? 1UL : 0UL) +#define HASH_BLOOM_MAKE(tbl, oomed) \ + do { \ + (tbl)->bloom_nbits = HASH_BLOOM; \ + (tbl)->bloom_bv = (uint8_t *) uthash_malloc(HASH_BLOOM_BYTELEN); \ + if (!(tbl)->bloom_bv) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ + (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ + } \ + } while (0) -#define HASH_BLOOM_FREE(tbl) \ -do { \ - uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ -} while (0) +#define HASH_BLOOM_FREE(tbl) \ + do { \ + uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ + } while (0) -#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U))) -#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U))) +#define HASH_BLOOM_BITSET(bv, idx) (bv[(idx) / 8U] |= (1U << ((idx) % 8U))) +#define HASH_BLOOM_BITTEST(bv, idx) (bv[(idx) / 8U] & (1U << ((idx) % 8U))) -#define HASH_BLOOM_ADD(tbl,hashv) \ - HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) +#define HASH_BLOOM_ADD(tbl, hashv) \ + HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t) ((1UL << (tbl)->bloom_nbits) - 1U))) -#define HASH_BLOOM_TEST(tbl,hashv) \ - HASH_BLOOM_BITTEST((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) +#define HASH_BLOOM_TEST(tbl, hashv) \ + HASH_BLOOM_BITTEST((tbl)->bloom_bv, ((hashv) & (uint32_t) ((1UL << (tbl)->bloom_nbits) - 1U))) #else -#define HASH_BLOOM_MAKE(tbl,oomed) +#define HASH_BLOOM_MAKE(tbl, oomed) #define HASH_BLOOM_FREE(tbl) -#define HASH_BLOOM_ADD(tbl,hashv) -#define HASH_BLOOM_TEST(tbl,hashv) (1) +#define HASH_BLOOM_ADD(tbl, hashv) +#define HASH_BLOOM_TEST(tbl, hashv) (1) #define HASH_BLOOM_BYTELEN 0U #endif -#define HASH_MAKE_TABLE(hh,head,oomed) \ -do { \ - (head)->hh.tbl = (UT_hash_table*)uthash_malloc(sizeof(UT_hash_table)); \ - if (!(head)->hh.tbl) { \ - HASH_RECORD_OOM(oomed); \ - } else { \ - uthash_bzero((head)->hh.tbl, sizeof(UT_hash_table)); \ - (head)->hh.tbl->tail = &((head)->hh); \ - (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ - (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ - (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ - (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ - HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ - (head)->hh.tbl->signature = HASH_SIGNATURE; \ - if (!(head)->hh.tbl->buckets) { \ - HASH_RECORD_OOM(oomed); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - } else { \ - uthash_bzero((head)->hh.tbl->buckets, \ - HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ - HASH_BLOOM_MAKE((head)->hh.tbl, oomed); \ - IF_HASH_NONFATAL_OOM( \ - if (oomed) { \ - uthash_free((head)->hh.tbl->buckets, \ - HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - } \ - ) \ - } \ - } \ -} while (0) +#define HASH_MAKE_TABLE(hh, head, oomed) \ + do { \ + (head)->hh.tbl = (UT_hash_table *) uthash_malloc(sizeof(UT_hash_table)); \ + if (!(head)->hh.tbl) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head)->hh.tbl->tail = &((head)->hh); \ + (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ + (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ + (head)->hh.tbl->hho = (char *) (&(head)->hh) - (char *) (head); \ + (head)->hh.tbl->buckets = (UT_hash_bucket *) uthash_malloc( \ + HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + (head)->hh.tbl->signature = HASH_SIGNATURE; \ + if (!(head)->hh.tbl->buckets) { \ + HASH_RECORD_OOM(oomed); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + } else { \ + uthash_bzero((head)->hh.tbl->buckets, \ + HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_MAKE((head)->hh.tbl, oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (oomed) { \ + uthash_free((head)->hh.tbl->buckets, \ + HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + }) \ + } \ + } \ + } while (0) -#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \ -do { \ - (replaced) = NULL; \ - HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ - if (replaced) { \ - HASH_DELETE(hh, head, replaced); \ - } \ - HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ -} while (0) +#define HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, hashval, add, replaced, cmpfcn) \ + do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ + } while (0) -#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \ -do { \ - (replaced) = NULL; \ - HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ - if (replaced) { \ - HASH_DELETE(hh, head, replaced); \ - } \ - HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ -} while (0) +#define HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, hashval, add, replaced) \ + do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ + } while (0) -#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ -do { \ - unsigned _hr_hashv; \ - HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ - HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ -} while (0) +#define HASH_REPLACE(hh, head, fieldname, keylen_in, add, replaced) \ + do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ + } while (0) -#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \ -do { \ - unsigned _hr_hashv; \ - HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ - HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ -} while (0) +#define HASH_REPLACE_INORDER(hh, head, fieldname, keylen_in, add, replaced, cmpfcn) \ + do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ + } while (0) -#define HASH_APPEND_LIST(hh, head, add) \ -do { \ - (add)->hh.next = NULL; \ - (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ - (head)->hh.tbl->tail->next = (add); \ - (head)->hh.tbl->tail = &((add)->hh); \ -} while (0) +#define HASH_APPEND_LIST(hh, head, add) \ + do { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ + (head)->hh.tbl->tail->next = (add); \ + (head)->hh.tbl->tail = &((add)->hh); \ + } while (0) -#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ -do { \ - do { \ - if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) { \ - break; \ - } \ - } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ -} while (0) +#define HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn) \ + do { \ + do { \ + if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) { \ + break; \ + } \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ + } while (0) #ifdef NO_DECLTYPE #undef HASH_AKBI_INNER_LOOP -#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ -do { \ - char *_hs_saved_head = (char*)(head); \ - do { \ - DECLTYPE_ASSIGN(head, _hs_iter); \ - if (cmpfcn(head, add) > 0) { \ - DECLTYPE_ASSIGN(head, _hs_saved_head); \ - break; \ - } \ - DECLTYPE_ASSIGN(head, _hs_saved_head); \ - } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ -} while (0) +#define HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn) \ + do { \ + char *_hs_saved_head = (char *) (head); \ + do { \ + DECLTYPE_ASSIGN(head, _hs_iter); \ + if (cmpfcn(head, add) > 0) { \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + break; \ + } \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ + } while (0) #endif #if HASH_NONFATAL_OOM -#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ -do { \ - if (!(oomed)) { \ - unsigned _ha_bkt; \ - (head)->hh.tbl->num_items++; \ - HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ - HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ - if (oomed) { \ - HASH_ROLLBACK_BKT(hh, head, &(add)->hh); \ - HASH_DELETE_HH(hh, head, &(add)->hh); \ - (add)->hh.tbl = NULL; \ - uthash_nonfatal_oom(add); \ - } else { \ - HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ - HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ - } \ - } else { \ - (add)->hh.tbl = NULL; \ - uthash_nonfatal_oom(add); \ - } \ -} while (0) +#define HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, oomed) \ + do { \ + if (!(oomed)) { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + if (oomed) { \ + HASH_ROLLBACK_BKT(hh, head, &(add)->hh); \ + HASH_DELETE_HH(hh, head, &(add)->hh); \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } else { \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + } \ + } else { \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } \ + } while (0) #else -#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ -do { \ - unsigned _ha_bkt; \ - (head)->hh.tbl->num_items++; \ - HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ - HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ - HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ - HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ -} while (0) +#define HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, oomed) \ + do { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + } while (0) #endif -#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \ -do { \ - IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ - (add)->hh.hashv = (hashval); \ - (add)->hh.key = (char*) (keyptr); \ - (add)->hh.keylen = (unsigned) (keylen_in); \ - if (!(head)) { \ - (add)->hh.next = NULL; \ - (add)->hh.prev = NULL; \ - HASH_MAKE_TABLE(hh, add, _ha_oomed); \ - IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ +#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, hashval, add, cmpfcn) \ + do { \ + IF_HASH_NONFATAL_OOM(int _ha_oomed = 0;) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char *) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ + IF_HASH_NONFATAL_OOM(if (!_ha_oomed) { ) \ (head) = (add); \ - IF_HASH_NONFATAL_OOM( } ) \ - } else { \ - void *_hs_iter = (head); \ - (add)->hh.tbl = (head)->hh.tbl; \ - HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn); \ - if (_hs_iter) { \ - (add)->hh.next = _hs_iter; \ - if (((add)->hh.prev = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) { \ - HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = (add); \ - } else { \ - (head) = (add); \ - } \ - HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add); \ - } else { \ - HASH_APPEND_LIST(hh, head, add); \ - } \ - } \ - HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ - HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE_INORDER"); \ -} while (0) + IF_HASH_NONFATAL_OOM( }) \ + } else { \ + void *_hs_iter = (head); \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn); \ + if (_hs_iter) { \ + (add)->hh.next = _hs_iter; \ + if (((add)->hh.prev = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) { \ + HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = (add); \ + } else { \ + (head) = (add); \ + } \ + HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add); \ + } else { \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE_INORDER"); \ + } while (0) -#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \ -do { \ - unsigned _hs_hashv; \ - HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ - HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ -} while (0) +#define HASH_ADD_KEYPTR_INORDER(hh, head, keyptr, keylen_in, add, cmpfcn) \ + do { \ + unsigned _hs_hashv; \ + HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ + } while (0) -#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \ - HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) +#define HASH_ADD_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, hashval, add, cmpfcn) \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) -#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \ - HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) +#define HASH_ADD_INORDER(hh, head, fieldname, keylen_in, add, cmpfcn) \ + HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) -#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \ -do { \ - IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ - (add)->hh.hashv = (hashval); \ - (add)->hh.key = (char*) (keyptr); \ - (add)->hh.keylen = (unsigned) (keylen_in); \ - if (!(head)) { \ - (add)->hh.next = NULL; \ - (add)->hh.prev = NULL; \ - HASH_MAKE_TABLE(hh, add, _ha_oomed); \ - IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ +#define HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, hashval, add) \ + do { \ + IF_HASH_NONFATAL_OOM(int _ha_oomed = 0;) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char *) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ + IF_HASH_NONFATAL_OOM(if (!_ha_oomed) { ) \ (head) = (add); \ - IF_HASH_NONFATAL_OOM( } ) \ - } else { \ - (add)->hh.tbl = (head)->hh.tbl; \ - HASH_APPEND_LIST(hh, head, add); \ - } \ - HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ - HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE"); \ -} while (0) + IF_HASH_NONFATAL_OOM( }) \ + } else { \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE"); \ + } while (0) -#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ -do { \ - unsigned _ha_hashv; \ - HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ - HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ -} while (0) +#define HASH_ADD_KEYPTR(hh, head, keyptr, keylen_in, add) \ + do { \ + unsigned _ha_hashv; \ + HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ + } while (0) -#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \ - HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) +#define HASH_ADD_BYHASHVALUE(hh, head, fieldname, keylen_in, hashval, add) \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) -#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ - HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) +#define HASH_ADD(hh, head, fieldname, keylen_in, add) \ + HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) -#define HASH_TO_BKT(hashv,num_bkts,bkt) \ -do { \ - bkt = ((hashv) & ((num_bkts) - 1U)); \ -} while (0) +#define HASH_TO_BKT(hashv, num_bkts, bkt) \ + do { \ + bkt = ((hashv) & ((num_bkts) -1U)); \ + } while (0) /* delete "delptr" from the hash table. * "the usual" patch-up process for the app-order doubly-linked-list. @@ -452,138 +456,142 @@ do { * copy the deletee pointer, then the latter references are via that * scratch pointer rather than through the repointed (users) symbol. */ -#define HASH_DELETE(hh,head,delptr) \ - HASH_DELETE_HH(hh, head, &(delptr)->hh) +#define HASH_DELETE(hh, head, delptr) \ + HASH_DELETE_HH(hh, head, &(delptr)->hh) -#define HASH_DELETE_HH(hh,head,delptrhh) \ -do { \ - struct UT_hash_handle *_hd_hh_del = (delptrhh); \ - if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - (head) = NULL; \ - } else { \ - unsigned _hd_bkt; \ - if (_hd_hh_del == (head)->hh.tbl->tail) { \ - (head)->hh.tbl->tail = HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev); \ - } \ - if (_hd_hh_del->prev != NULL) { \ - HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = _hd_hh_del->next; \ - } else { \ - DECLTYPE_ASSIGN(head, _hd_hh_del->next); \ - } \ - if (_hd_hh_del->next != NULL) { \ - HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = _hd_hh_del->prev; \ - } \ - HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ - HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ - (head)->hh.tbl->num_items--; \ - } \ - HASH_FSCK(hh, head, "HASH_DELETE_HH"); \ -} while (0) +#define HASH_DELETE_HH(hh, head, delptrhh) \ + do { \ + struct UT_hash_handle *_hd_hh_del = (delptrhh); \ + if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } else { \ + unsigned _hd_bkt; \ + if (_hd_hh_del == (head)->hh.tbl->tail) { \ + (head)->hh.tbl->tail = HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev); \ + } \ + if (_hd_hh_del->prev != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = _hd_hh_del->next; \ + } else { \ + DECLTYPE_ASSIGN(head, _hd_hh_del->next); \ + } \ + if (_hd_hh_del->next != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = _hd_hh_del->prev; \ + } \ + HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ + (head)->hh.tbl->num_items--; \ + } \ + HASH_FSCK(hh, head, "HASH_DELETE_HH"); \ + } while (0) /* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ -#define HASH_FIND_STR(head,findstr,out) \ -do { \ - unsigned _uthash_hfstr_keylen = (unsigned)uthash_strlen(findstr); \ - HASH_FIND(hh, head, findstr, _uthash_hfstr_keylen, out); \ -} while (0) -#define HASH_ADD_STR(head,strfield,add) \ -do { \ - unsigned _uthash_hastr_keylen = (unsigned)uthash_strlen((add)->strfield); \ - HASH_ADD(hh, head, strfield[0], _uthash_hastr_keylen, add); \ -} while (0) -#define HASH_REPLACE_STR(head,strfield,add,replaced) \ -do { \ - unsigned _uthash_hrstr_keylen = (unsigned)uthash_strlen((add)->strfield); \ - HASH_REPLACE(hh, head, strfield[0], _uthash_hrstr_keylen, add, replaced); \ -} while (0) -#define HASH_FIND_INT(head,findint,out) \ - HASH_FIND(hh,head,findint,sizeof(int),out) -#define HASH_ADD_INT(head,intfield,add) \ - HASH_ADD(hh,head,intfield,sizeof(int),add) -#define HASH_REPLACE_INT(head,intfield,add,replaced) \ - HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) -#define HASH_FIND_PTR(head,findptr,out) \ - HASH_FIND(hh,head,findptr,sizeof(void *),out) -#define HASH_ADD_PTR(head,ptrfield,add) \ - HASH_ADD(hh,head,ptrfield,sizeof(void *),add) -#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ - HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) -#define HASH_DEL(head,delptr) \ - HASH_DELETE(hh,head,delptr) +#define HASH_FIND_STR(head, findstr, out) \ + do { \ + unsigned _uthash_hfstr_keylen = (unsigned) uthash_strlen(findstr); \ + HASH_FIND(hh, head, findstr, _uthash_hfstr_keylen, out); \ + } while (0) +#define HASH_ADD_STR(head, strfield, add) \ + do { \ + unsigned _uthash_hastr_keylen = (unsigned) uthash_strlen((add)->strfield); \ + HASH_ADD(hh, head, strfield[0], _uthash_hastr_keylen, add); \ + } while (0) +#define HASH_REPLACE_STR(head, strfield, add, replaced) \ + do { \ + unsigned _uthash_hrstr_keylen = (unsigned) uthash_strlen((add)->strfield); \ + HASH_REPLACE(hh, head, strfield[0], _uthash_hrstr_keylen, add, replaced); \ + } while (0) +#define HASH_FIND_INT(head, findint, out) \ + HASH_FIND(hh, head, findint, sizeof(int), out) +#define HASH_ADD_INT(head, intfield, add) \ + HASH_ADD(hh, head, intfield, sizeof(int), add) +#define HASH_REPLACE_INT(head, intfield, add, replaced) \ + HASH_REPLACE(hh, head, intfield, sizeof(int), add, replaced) +#define HASH_FIND_PTR(head, findptr, out) \ + HASH_FIND(hh, head, findptr, sizeof(void *), out) +#define HASH_ADD_PTR(head, ptrfield, add) \ + HASH_ADD(hh, head, ptrfield, sizeof(void *), add) +#define HASH_REPLACE_PTR(head, ptrfield, add, replaced) \ + HASH_REPLACE(hh, head, ptrfield, sizeof(void *), add, replaced) +#define HASH_DEL(head, delptr) \ + HASH_DELETE(hh, head, delptr) /* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. */ #ifdef HASH_DEBUG -#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) -#define HASH_FSCK(hh,head,where) \ -do { \ - struct UT_hash_handle *_thh; \ - if (head) { \ - unsigned _bkt_i; \ - unsigned _count = 0; \ - char *_prev; \ - for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) { \ - unsigned _bkt_count = 0; \ - _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ - _prev = NULL; \ - while (_thh) { \ - if (_prev != (char*)(_thh->hh_prev)) { \ - HASH_OOPS("%s: invalid hh_prev %p, actual %p\n", \ - (where), (void*)_thh->hh_prev, (void*)_prev); \ - } \ - _bkt_count++; \ - _prev = (char*)(_thh); \ - _thh = _thh->hh_next; \ - } \ - _count += _bkt_count; \ - if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ - HASH_OOPS("%s: invalid bucket count %u, actual %u\n", \ - (where), (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ - } \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("%s: invalid hh item count %u, actual %u\n", \ - (where), (head)->hh.tbl->num_items, _count); \ - } \ - _count = 0; \ - _prev = NULL; \ - _thh = &(head)->hh; \ - while (_thh) { \ - _count++; \ - if (_prev != (char*)_thh->prev) { \ - HASH_OOPS("%s: invalid prev %p, actual %p\n", \ - (where), (void*)_thh->prev, (void*)_prev); \ - } \ - _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ - _thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) : NULL); \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("%s: invalid app item count %u, actual %u\n", \ - (where), (head)->hh.tbl->num_items, _count); \ - } \ - } \ -} while (0) +#define HASH_OOPS(...) \ + do { \ + fprintf(stderr, __VA_ARGS__); \ + exit(-1); \ + } while (0) +#define HASH_FSCK(hh, head, where) \ + do { \ + struct UT_hash_handle *_thh; \ + if (head) { \ + unsigned _bkt_i; \ + unsigned _count = 0; \ + char *_prev; \ + for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) { \ + unsigned _bkt_count = 0; \ + _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ + _prev = NULL; \ + while (_thh) { \ + if (_prev != (char *) (_thh->hh_prev)) { \ + HASH_OOPS("%s: invalid hh_prev %p, actual %p\n", \ + (where), (void *) _thh->hh_prev, (void *) _prev); \ + } \ + _bkt_count++; \ + _prev = (char *) (_thh); \ + _thh = _thh->hh_next; \ + } \ + _count += _bkt_count; \ + if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ + HASH_OOPS("%s: invalid bucket count %u, actual %u\n", \ + (where), (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ + } \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid hh item count %u, actual %u\n", \ + (where), (head)->hh.tbl->num_items, _count); \ + } \ + _count = 0; \ + _prev = NULL; \ + _thh = &(head)->hh; \ + while (_thh) { \ + _count++; \ + if (_prev != (char *) _thh->prev) { \ + HASH_OOPS("%s: invalid prev %p, actual %p\n", \ + (where), (void *) _thh->prev, (void *) _prev); \ + } \ + _prev = (char *) ELMT_FROM_HH((head)->hh.tbl, _thh); \ + _thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) : NULL); \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid app item count %u, actual %u\n", \ + (where), (head)->hh.tbl->num_items, _count); \ + } \ + } \ + } while (0) #else -#define HASH_FSCK(hh,head,where) +#define HASH_FSCK(hh, head, where) #endif /* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to * the descriptor to which this macro is defined for tuning the hash function. * The app can #include to get the prototype for write(2). */ #ifdef HASH_EMIT_KEYS -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ -do { \ - unsigned _klen = fieldlen; \ - write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ - write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ -} while (0) +#define HASH_EMIT_KEY(hh, head, keyptr, fieldlen) \ + do { \ + unsigned _klen = fieldlen; \ + write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ + write(HASH_EMIT_KEYS, keyptr, (unsigned long) fieldlen); \ + } while (0) #else -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) +#define HASH_EMIT_KEY(hh, head, keyptr, fieldlen) #endif /* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ @@ -594,161 +602,193 @@ do { #endif /* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ -#define HASH_BER(key,keylen,hashv) \ -do { \ - unsigned _hb_keylen = (unsigned)keylen; \ - const unsigned char *_hb_key = (const unsigned char*)(key); \ - (hashv) = 0; \ - while (_hb_keylen-- != 0U) { \ - (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ - } \ -} while (0) +#define HASH_BER(key, keylen, hashv) \ + do { \ + unsigned _hb_keylen = (unsigned) keylen; \ + const unsigned char *_hb_key = (const unsigned char *) (key); \ + (hashv) = 0; \ + while (_hb_keylen-- != 0U) { \ + (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ + } \ + } while (0) /* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ -#define HASH_SAX(key,keylen,hashv) \ -do { \ - unsigned _sx_i; \ - const unsigned char *_hs_key = (const unsigned char*)(key); \ - hashv = 0; \ - for (_sx_i=0; _sx_i < keylen; _sx_i++) { \ - hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ - } \ -} while (0) +#define HASH_SAX(key, keylen, hashv) \ + do { \ + unsigned _sx_i; \ + const unsigned char *_hs_key = (const unsigned char *) (key); \ + hashv = 0; \ + for (_sx_i = 0; _sx_i < keylen; _sx_i++) { \ + hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ + } \ + } while (0) /* FNV-1a variation */ -#define HASH_FNV(key,keylen,hashv) \ -do { \ - unsigned _fn_i; \ - const unsigned char *_hf_key = (const unsigned char*)(key); \ - (hashv) = 2166136261U; \ - for (_fn_i=0; _fn_i < keylen; _fn_i++) { \ - hashv = hashv ^ _hf_key[_fn_i]; \ - hashv = hashv * 16777619U; \ - } \ -} while (0) +#define HASH_FNV(key, keylen, hashv) \ + do { \ + unsigned _fn_i; \ + const unsigned char *_hf_key = (const unsigned char *) (key); \ + (hashv) = 2166136261U; \ + for (_fn_i = 0; _fn_i < keylen; _fn_i++) { \ + hashv = hashv ^ _hf_key[_fn_i]; \ + hashv = hashv * 16777619U; \ + } \ + } while (0) -#define HASH_OAT(key,keylen,hashv) \ -do { \ - unsigned _ho_i; \ - const unsigned char *_ho_key=(const unsigned char*)(key); \ - hashv = 0; \ - for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ - hashv += _ho_key[_ho_i]; \ - hashv += (hashv << 10); \ - hashv ^= (hashv >> 6); \ - } \ - hashv += (hashv << 3); \ - hashv ^= (hashv >> 11); \ - hashv += (hashv << 15); \ -} while (0) +#define HASH_OAT(key, keylen, hashv) \ + do { \ + unsigned _ho_i; \ + const unsigned char *_ho_key = (const unsigned char *) (key); \ + hashv = 0; \ + for (_ho_i = 0; _ho_i < keylen; _ho_i++) { \ + hashv += _ho_key[_ho_i]; \ + hashv += (hashv << 10); \ + hashv ^= (hashv >> 6); \ + } \ + hashv += (hashv << 3); \ + hashv ^= (hashv >> 11); \ + hashv += (hashv << 15); \ + } while (0) -#define HASH_JEN_MIX(a,b,c) \ -do { \ - a -= b; a -= c; a ^= ( c >> 13 ); \ - b -= c; b -= a; b ^= ( a << 8 ); \ - c -= a; c -= b; c ^= ( b >> 13 ); \ - a -= b; a -= c; a ^= ( c >> 12 ); \ - b -= c; b -= a; b ^= ( a << 16 ); \ - c -= a; c -= b; c ^= ( b >> 5 ); \ - a -= b; a -= c; a ^= ( c >> 3 ); \ - b -= c; b -= a; b ^= ( a << 10 ); \ - c -= a; c -= b; c ^= ( b >> 15 ); \ -} while (0) +#define HASH_JEN_MIX(a, b, c) \ + do { \ + a -= b; \ + a -= c; \ + a ^= (c >> 13); \ + b -= c; \ + b -= a; \ + b ^= (a << 8); \ + c -= a; \ + c -= b; \ + c ^= (b >> 13); \ + a -= b; \ + a -= c; \ + a ^= (c >> 12); \ + b -= c; \ + b -= a; \ + b ^= (a << 16); \ + c -= a; \ + c -= b; \ + c ^= (b >> 5); \ + a -= b; \ + a -= c; \ + a ^= (c >> 3); \ + b -= c; \ + b -= a; \ + b ^= (a << 10); \ + c -= a; \ + c -= b; \ + c ^= (b >> 15); \ + } while (0) -#define HASH_JEN(key,keylen,hashv) \ -do { \ - unsigned _hj_i,_hj_j,_hj_k; \ - unsigned const char *_hj_key=(unsigned const char*)(key); \ - hashv = 0xfeedbeefu; \ - _hj_i = _hj_j = 0x9e3779b9u; \ - _hj_k = (unsigned)(keylen); \ - while (_hj_k >= 12U) { \ - _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ - + ( (unsigned)_hj_key[2] << 16 ) \ - + ( (unsigned)_hj_key[3] << 24 ) ); \ - _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ - + ( (unsigned)_hj_key[6] << 16 ) \ - + ( (unsigned)_hj_key[7] << 24 ) ); \ - hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ - + ( (unsigned)_hj_key[10] << 16 ) \ - + ( (unsigned)_hj_key[11] << 24 ) ); \ - \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - \ - _hj_key += 12; \ - _hj_k -= 12U; \ - } \ - hashv += (unsigned)(keylen); \ - switch ( _hj_k ) { \ - case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ - case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ - case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ - case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ - case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ - case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ - case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ - case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ - case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ - case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ - case 1: _hj_i += _hj_key[0]; \ - } \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ -} while (0) +#define HASH_JEN(key, keylen, hashv) \ + do { \ + unsigned _hj_i, _hj_j, _hj_k; \ + unsigned const char *_hj_key = (unsigned const char *) (key); \ + hashv = 0xfeedbeefu; \ + _hj_i = _hj_j = 0x9e3779b9u; \ + _hj_k = (unsigned) (keylen); \ + while (_hj_k >= 12U) { \ + _hj_i += (_hj_key[0] + ((unsigned) _hj_key[1] << 8) \ + + ((unsigned) _hj_key[2] << 16) \ + + ((unsigned) _hj_key[3] << 24)); \ + _hj_j += (_hj_key[4] + ((unsigned) _hj_key[5] << 8) \ + + ((unsigned) _hj_key[6] << 16) \ + + ((unsigned) _hj_key[7] << 24)); \ + hashv += (_hj_key[8] + ((unsigned) _hj_key[9] << 8) \ + + ((unsigned) _hj_key[10] << 16) \ + + ((unsigned) _hj_key[11] << 24)); \ + \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + \ + _hj_key += 12; \ + _hj_k -= 12U; \ + } \ + hashv += (unsigned) (keylen); \ + switch (_hj_k) { \ + case 11: \ + hashv += ((unsigned) _hj_key[10] << 24); /* FALLTHROUGH */ \ + case 10: \ + hashv += ((unsigned) _hj_key[9] << 16); /* FALLTHROUGH */ \ + case 9: \ + hashv += ((unsigned) _hj_key[8] << 8); /* FALLTHROUGH */ \ + case 8: \ + _hj_j += ((unsigned) _hj_key[7] << 24); /* FALLTHROUGH */ \ + case 7: \ + _hj_j += ((unsigned) _hj_key[6] << 16); /* FALLTHROUGH */ \ + case 6: \ + _hj_j += ((unsigned) _hj_key[5] << 8); /* FALLTHROUGH */ \ + case 5: \ + _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ + case 4: \ + _hj_i += ((unsigned) _hj_key[3] << 24); /* FALLTHROUGH */ \ + case 3: \ + _hj_i += ((unsigned) _hj_key[2] << 16); /* FALLTHROUGH */ \ + case 2: \ + _hj_i += ((unsigned) _hj_key[1] << 8); /* FALLTHROUGH */ \ + case 1: \ + _hj_i += _hj_key[0]; \ + } \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + } while (0) /* The Paul Hsieh hash function */ #undef get16bits -#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ - || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined(__BORLANDC__) || defined(__TURBOC__) #define get16bits(d) (*((const uint16_t *) (d))) #endif -#if !defined (get16bits) -#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ - +(uint32_t)(((const uint8_t *)(d))[0]) ) +#if !defined(get16bits) +#define get16bits(d) ((((uint32_t) (((const uint8_t *) (d))[1])) << 8) \ + + (uint32_t) (((const uint8_t *) (d))[0])) #endif -#define HASH_SFH(key,keylen,hashv) \ -do { \ - unsigned const char *_sfh_key=(unsigned const char*)(key); \ - uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ - \ - unsigned _sfh_rem = _sfh_len & 3U; \ - _sfh_len >>= 2; \ - hashv = 0xcafebabeu; \ - \ - /* Main loop */ \ - for (;_sfh_len > 0U; _sfh_len--) { \ - hashv += get16bits (_sfh_key); \ - _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \ - hashv = (hashv << 16) ^ _sfh_tmp; \ - _sfh_key += 2U*sizeof (uint16_t); \ - hashv += hashv >> 11; \ - } \ - \ - /* Handle end cases */ \ - switch (_sfh_rem) { \ - case 3: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 16; \ - hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \ - hashv += hashv >> 11; \ - break; \ - case 2: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 11; \ - hashv += hashv >> 17; \ - break; \ - case 1: hashv += *_sfh_key; \ - hashv ^= hashv << 10; \ - hashv += hashv >> 1; \ - } \ - \ - /* Force "avalanching" of final 127 bits */ \ - hashv ^= hashv << 3; \ - hashv += hashv >> 5; \ - hashv ^= hashv << 4; \ - hashv += hashv >> 17; \ - hashv ^= hashv << 25; \ - hashv += hashv >> 6; \ -} while (0) +#define HASH_SFH(key, keylen, hashv) \ + do { \ + unsigned const char *_sfh_key = (unsigned const char *) (key); \ + uint32_t _sfh_tmp, _sfh_len = (uint32_t) keylen; \ + \ + unsigned _sfh_rem = _sfh_len & 3U; \ + _sfh_len >>= 2; \ + hashv = 0xcafebabeu; \ + \ + /* Main loop */ \ + for (; _sfh_len > 0U; _sfh_len--) { \ + hashv += get16bits(_sfh_key); \ + _sfh_tmp = ((uint32_t) (get16bits(_sfh_key + 2)) << 11) ^ hashv; \ + hashv = (hashv << 16) ^ _sfh_tmp; \ + _sfh_key += 2U * sizeof(uint16_t); \ + hashv += hashv >> 11; \ + } \ + \ + /* Handle end cases */ \ + switch (_sfh_rem) { \ + case 3: \ + hashv += get16bits(_sfh_key); \ + hashv ^= hashv << 16; \ + hashv ^= (uint32_t) (_sfh_key[sizeof(uint16_t)]) << 18; \ + hashv += hashv >> 11; \ + break; \ + case 2: \ + hashv += get16bits(_sfh_key); \ + hashv ^= hashv << 11; \ + hashv += hashv >> 17; \ + break; \ + case 1: \ + hashv += *_sfh_key; \ + hashv ^= hashv << 10; \ + hashv += hashv >> 1; \ + } \ + \ + /* Force "avalanching" of final 127 bits */ \ + hashv ^= hashv << 3; \ + hashv += hashv >> 5; \ + hashv ^= hashv << 4; \ + hashv += hashv >> 17; \ + hashv ^= hashv << 25; \ + hashv += hashv >> 6; \ + } while (0) #ifdef HASH_USING_NO_STRICT_ALIASING /* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. @@ -760,136 +800,136 @@ do { * gcc -m64 -dM -E - < /dev/null (on gcc) * cc -## a.c (where a.c is a simple test file) (Sun Studio) */ -#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) -#define MUR_GETBLOCK(p,i) p[i] +#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) +#define MUR_GETBLOCK(p, i) p[i] #else /* non intel */ -#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL) -#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL) -#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL) -#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL) -#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) +#define MUR_PLUS0_ALIGNED(p) (((unsigned long) p & 3UL) == 0UL) +#define MUR_PLUS1_ALIGNED(p) (((unsigned long) p & 3UL) == 1UL) +#define MUR_PLUS2_ALIGNED(p) (((unsigned long) p & 3UL) == 2UL) +#define MUR_PLUS3_ALIGNED(p) (((unsigned long) p & 3UL) == 3UL) +#define WP(p) ((uint32_t *) ((unsigned long) (p) & ~3UL)) #if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) -#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) -#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) -#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) +#define MUR_THREE_ONE(p) ((((*WP(p)) & 0x00ffffff) << 8) | (((*(WP(p) + 1)) & 0xff000000) >> 24)) +#define MUR_TWO_TWO(p) ((((*WP(p)) & 0x0000ffff) << 16) | (((*(WP(p) + 1)) & 0xffff0000) >> 16)) +#define MUR_ONE_THREE(p) ((((*WP(p)) & 0x000000ff) << 24) | (((*(WP(p) + 1)) & 0xffffff00) >> 8)) #else /* assume little endian non-intel */ -#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) -#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) -#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) +#define MUR_THREE_ONE(p) ((((*WP(p)) & 0xffffff00) >> 8) | (((*(WP(p) + 1)) & 0x000000ff) << 24)) +#define MUR_TWO_TWO(p) ((((*WP(p)) & 0xffff0000) >> 16) | (((*(WP(p) + 1)) & 0x0000ffff) << 16)) +#define MUR_ONE_THREE(p) ((((*WP(p)) & 0xff000000) >> 24) | (((*(WP(p) + 1)) & 0x00ffffff) << 8)) #endif -#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ - (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ - (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ - MUR_ONE_THREE(p)))) +#define MUR_GETBLOCK(p, i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : MUR_ONE_THREE(p)))) #endif -#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) -#define MUR_FMIX(_h) \ -do { \ - _h ^= _h >> 16; \ - _h *= 0x85ebca6bu; \ - _h ^= _h >> 13; \ - _h *= 0xc2b2ae35u; \ - _h ^= _h >> 16; \ -} while (0) +#define MUR_ROTL32(x, r) (((x) << (r)) | ((x) >> (32 - (r)))) +#define MUR_FMIX(_h) \ + do { \ + _h ^= _h >> 16; \ + _h *= 0x85ebca6bu; \ + _h ^= _h >> 13; \ + _h *= 0xc2b2ae35u; \ + _h ^= _h >> 16; \ + } while (0) -#define HASH_MUR(key,keylen,hashv) \ -do { \ - const uint8_t *_mur_data = (const uint8_t*)(key); \ - const int _mur_nblocks = (int)(keylen) / 4; \ - uint32_t _mur_h1 = 0xf88D5353u; \ - uint32_t _mur_c1 = 0xcc9e2d51u; \ - uint32_t _mur_c2 = 0x1b873593u; \ - uint32_t _mur_k1 = 0; \ - const uint8_t *_mur_tail; \ - const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \ - int _mur_i; \ - for (_mur_i = -_mur_nblocks; _mur_i != 0; _mur_i++) { \ - _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ - _mur_k1 *= _mur_c1; \ - _mur_k1 = MUR_ROTL32(_mur_k1,15); \ - _mur_k1 *= _mur_c2; \ - \ - _mur_h1 ^= _mur_k1; \ - _mur_h1 = MUR_ROTL32(_mur_h1,13); \ - _mur_h1 = (_mur_h1*5U) + 0xe6546b64u; \ - } \ - _mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4)); \ - _mur_k1=0; \ - switch ((keylen) & 3U) { \ - case 0: break; \ - case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \ - case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8; /* FALLTHROUGH */ \ - case 1: _mur_k1 ^= (uint32_t)_mur_tail[0]; \ - _mur_k1 *= _mur_c1; \ - _mur_k1 = MUR_ROTL32(_mur_k1,15); \ - _mur_k1 *= _mur_c2; \ - _mur_h1 ^= _mur_k1; \ - } \ - _mur_h1 ^= (uint32_t)(keylen); \ - MUR_FMIX(_mur_h1); \ - hashv = _mur_h1; \ -} while (0) -#endif /* HASH_USING_NO_STRICT_ALIASING */ +#define HASH_MUR(key, keylen, hashv) \ + do { \ + const uint8_t *_mur_data = (const uint8_t *) (key); \ + const int _mur_nblocks = (int) (keylen) / 4; \ + uint32_t _mur_h1 = 0xf88D5353u; \ + uint32_t _mur_c1 = 0xcc9e2d51u; \ + uint32_t _mur_c2 = 0x1b873593u; \ + uint32_t _mur_k1 = 0; \ + const uint8_t *_mur_tail; \ + const uint32_t *_mur_blocks = (const uint32_t *) (_mur_data + (_mur_nblocks * 4)); \ + int _mur_i; \ + for (_mur_i = -_mur_nblocks; _mur_i != 0; _mur_i++) { \ + _mur_k1 = MUR_GETBLOCK(_mur_blocks, _mur_i); \ + _mur_k1 *= _mur_c1; \ + _mur_k1 = MUR_ROTL32(_mur_k1, 15); \ + _mur_k1 *= _mur_c2; \ + \ + _mur_h1 ^= _mur_k1; \ + _mur_h1 = MUR_ROTL32(_mur_h1, 13); \ + _mur_h1 = (_mur_h1 * 5U) + 0xe6546b64u; \ + } \ + _mur_tail = (const uint8_t *) (_mur_data + (_mur_nblocks * 4)); \ + _mur_k1 = 0; \ + switch ((keylen) &3U) { \ + case 0: \ + break; \ + case 3: \ + _mur_k1 ^= (uint32_t) _mur_tail[2] << 16; /* FALLTHROUGH */ \ + case 2: \ + _mur_k1 ^= (uint32_t) _mur_tail[1] << 8; /* FALLTHROUGH */ \ + case 1: \ + _mur_k1 ^= (uint32_t) _mur_tail[0]; \ + _mur_k1 *= _mur_c1; \ + _mur_k1 = MUR_ROTL32(_mur_k1, 15); \ + _mur_k1 *= _mur_c2; \ + _mur_h1 ^= _mur_k1; \ + } \ + _mur_h1 ^= (uint32_t) (keylen); \ + MUR_FMIX(_mur_h1); \ + hashv = _mur_h1; \ + } while (0) +#endif /* HASH_USING_NO_STRICT_ALIASING */ /* iterate over items in a known bucket to find desired item */ -#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \ -do { \ - if ((head).hh_head != NULL) { \ - DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ - } else { \ - (out) = NULL; \ - } \ - while ((out) != NULL) { \ - if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ - if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \ - break; \ - } \ - } \ - if ((out)->hh.hh_next != NULL) { \ - DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ - } else { \ - (out) = NULL; \ - } \ - } \ -} while (0) +#define HASH_FIND_IN_BKT(tbl, hh, head, keyptr, keylen_in, hashval, out) \ + do { \ + if ((head).hh_head != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ + } else { \ + (out) = NULL; \ + } \ + while ((out) != NULL) { \ + if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ + if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \ + break; \ + } \ + } \ + if ((out)->hh.hh_next != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ + } else { \ + (out) = NULL; \ + } \ + } \ + } while (0) /* add an item to a bucket */ -#define HASH_ADD_TO_BKT(head,hh,addhh,oomed) \ -do { \ - UT_hash_bucket *_ha_head = &(head); \ - _ha_head->count++; \ - (addhh)->hh_next = _ha_head->hh_head; \ - (addhh)->hh_prev = NULL; \ - if (_ha_head->hh_head != NULL) { \ - _ha_head->hh_head->hh_prev = (addhh); \ - } \ - _ha_head->hh_head = (addhh); \ - if ((_ha_head->count >= ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) \ - && !(addhh)->tbl->noexpand) { \ - HASH_EXPAND_BUCKETS(addhh,(addhh)->tbl, oomed); \ - IF_HASH_NONFATAL_OOM( \ - if (oomed) { \ - HASH_DEL_IN_BKT(head,addhh); \ - } \ - ) \ - } \ -} while (0) +#define HASH_ADD_TO_BKT(head, hh, addhh, oomed) \ + do { \ + UT_hash_bucket *_ha_head = &(head); \ + _ha_head->count++; \ + (addhh)->hh_next = _ha_head->hh_head; \ + (addhh)->hh_prev = NULL; \ + if (_ha_head->hh_head != NULL) { \ + _ha_head->hh_head->hh_prev = (addhh); \ + } \ + _ha_head->hh_head = (addhh); \ + if ((_ha_head->count >= ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) \ + && !(addhh)->tbl->noexpand) { \ + HASH_EXPAND_BUCKETS(addhh, (addhh)->tbl, oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (oomed) { \ + HASH_DEL_IN_BKT(head, addhh); \ + }) \ + } \ + } while (0) /* remove an item from a given bucket */ -#define HASH_DEL_IN_BKT(head,delhh) \ -do { \ - UT_hash_bucket *_hd_head = &(head); \ - _hd_head->count--; \ - if (_hd_head->hh_head == (delhh)) { \ - _hd_head->hh_head = (delhh)->hh_next; \ - } \ - if ((delhh)->hh_prev) { \ - (delhh)->hh_prev->hh_next = (delhh)->hh_next; \ - } \ - if ((delhh)->hh_next) { \ - (delhh)->hh_next->hh_prev = (delhh)->hh_prev; \ - } \ -} while (0) +#define HASH_DEL_IN_BKT(head, delhh) \ + do { \ + UT_hash_bucket *_hd_head = &(head); \ + _hd_head->count--; \ + if (_hd_head->hh_head == (delhh)) { \ + _hd_head->hh_head = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_prev) { \ + (delhh)->hh_prev->hh_next = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_next) { \ + (delhh)->hh_next->hh_prev = (delhh)->hh_prev; \ + } \ + } while (0) /* Bucket expansion has the effect of doubling the number of buckets * and redistributing the items into the new buckets. Ideally the @@ -920,259 +960,246 @@ do { * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) * */ -#define HASH_EXPAND_BUCKETS(hh,tbl,oomed) \ -do { \ - unsigned _he_bkt; \ - unsigned _he_bkt_i; \ - struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ - UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ - _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ - 2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ - if (!_he_new_buckets) { \ - HASH_RECORD_OOM(oomed); \ - } else { \ - uthash_bzero(_he_new_buckets, \ - 2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ - (tbl)->ideal_chain_maxlen = \ - ((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \ - ((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \ - (tbl)->nonideal_items = 0; \ - for (_he_bkt_i = 0; _he_bkt_i < (tbl)->num_buckets; _he_bkt_i++) { \ - _he_thh = (tbl)->buckets[ _he_bkt_i ].hh_head; \ - while (_he_thh != NULL) { \ - _he_hh_nxt = _he_thh->hh_next; \ - HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, _he_bkt); \ - _he_newbkt = &(_he_new_buckets[_he_bkt]); \ - if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) { \ - (tbl)->nonideal_items++; \ - if (_he_newbkt->count > _he_newbkt->expand_mult * (tbl)->ideal_chain_maxlen) { \ - _he_newbkt->expand_mult++; \ - } \ - } \ - _he_thh->hh_prev = NULL; \ - _he_thh->hh_next = _he_newbkt->hh_head; \ - if (_he_newbkt->hh_head != NULL) { \ - _he_newbkt->hh_head->hh_prev = _he_thh; \ - } \ - _he_newbkt->hh_head = _he_thh; \ - _he_thh = _he_hh_nxt; \ - } \ - } \ - uthash_free((tbl)->buckets, (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ - (tbl)->num_buckets *= 2U; \ - (tbl)->log2_num_buckets++; \ - (tbl)->buckets = _he_new_buckets; \ - (tbl)->ineff_expands = ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) ? \ - ((tbl)->ineff_expands+1U) : 0U; \ - if ((tbl)->ineff_expands > 1U) { \ - (tbl)->noexpand = 1; \ - uthash_noexpand_fyi(tbl); \ - } \ - uthash_expand_fyi(tbl); \ - } \ -} while (0) +#define HASH_EXPAND_BUCKETS(hh, tbl, oomed) \ + do { \ + unsigned _he_bkt; \ + unsigned _he_bkt_i; \ + struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ + UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ + _he_new_buckets = (UT_hash_bucket *) uthash_malloc( \ + 2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ + if (!_he_new_buckets) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero(_he_new_buckets, \ + 2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ + (tbl)->ideal_chain_maxlen = \ + ((tbl)->num_items >> ((tbl)->log2_num_buckets + 1U)) + ((((tbl)->num_items & (((tbl)->num_buckets * 2U) - 1U)) != 0U) ? 1U : 0U); \ + (tbl)->nonideal_items = 0; \ + for (_he_bkt_i = 0; _he_bkt_i < (tbl)->num_buckets; _he_bkt_i++) { \ + _he_thh = (tbl)->buckets[_he_bkt_i].hh_head; \ + while (_he_thh != NULL) { \ + _he_hh_nxt = _he_thh->hh_next; \ + HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, _he_bkt); \ + _he_newbkt = &(_he_new_buckets[_he_bkt]); \ + if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) { \ + (tbl)->nonideal_items++; \ + if (_he_newbkt->count > _he_newbkt->expand_mult * (tbl)->ideal_chain_maxlen) { \ + _he_newbkt->expand_mult++; \ + } \ + } \ + _he_thh->hh_prev = NULL; \ + _he_thh->hh_next = _he_newbkt->hh_head; \ + if (_he_newbkt->hh_head != NULL) { \ + _he_newbkt->hh_head->hh_prev = _he_thh; \ + } \ + _he_newbkt->hh_head = _he_thh; \ + _he_thh = _he_hh_nxt; \ + } \ + } \ + uthash_free((tbl)->buckets, (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ + (tbl)->num_buckets *= 2U; \ + (tbl)->log2_num_buckets++; \ + (tbl)->buckets = _he_new_buckets; \ + (tbl)->ineff_expands = ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) ? ((tbl)->ineff_expands + 1U) : 0U; \ + if ((tbl)->ineff_expands > 1U) { \ + (tbl)->noexpand = 1; \ + uthash_noexpand_fyi(tbl); \ + } \ + uthash_expand_fyi(tbl); \ + } \ + } while (0) /* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ /* Note that HASH_SORT assumes the hash handle name to be hh. * HASH_SRT was added to allow the hash handle name to be passed in. */ -#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) -#define HASH_SRT(hh,head,cmpfcn) \ -do { \ - unsigned _hs_i; \ - unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ - struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ - if (head != NULL) { \ - _hs_insize = 1; \ - _hs_looping = 1; \ - _hs_list = &((head)->hh); \ - while (_hs_looping != 0U) { \ - _hs_p = _hs_list; \ - _hs_list = NULL; \ - _hs_tail = NULL; \ - _hs_nmerges = 0; \ - while (_hs_p != NULL) { \ - _hs_nmerges++; \ - _hs_q = _hs_p; \ - _hs_psize = 0; \ - for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) { \ - _hs_psize++; \ - _hs_q = ((_hs_q->next != NULL) ? \ - HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ - if (_hs_q == NULL) { \ - break; \ - } \ - } \ - _hs_qsize = _hs_insize; \ - while ((_hs_psize != 0U) || ((_hs_qsize != 0U) && (_hs_q != NULL))) { \ - if (_hs_psize == 0U) { \ - _hs_e = _hs_q; \ - _hs_q = ((_hs_q->next != NULL) ? \ - HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ - _hs_qsize--; \ - } else if ((_hs_qsize == 0U) || (_hs_q == NULL)) { \ - _hs_e = _hs_p; \ - if (_hs_p != NULL) { \ - _hs_p = ((_hs_p->next != NULL) ? \ - HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ - } \ - _hs_psize--; \ - } else if ((cmpfcn( \ - DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_p)), \ - DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_q)) \ - )) <= 0) { \ - _hs_e = _hs_p; \ - if (_hs_p != NULL) { \ - _hs_p = ((_hs_p->next != NULL) ? \ - HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ - } \ - _hs_psize--; \ - } else { \ - _hs_e = _hs_q; \ - _hs_q = ((_hs_q->next != NULL) ? \ - HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ - _hs_qsize--; \ - } \ - if ( _hs_tail != NULL ) { \ - _hs_tail->next = ((_hs_e != NULL) ? \ - ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL); \ - } else { \ - _hs_list = _hs_e; \ - } \ - if (_hs_e != NULL) { \ - _hs_e->prev = ((_hs_tail != NULL) ? \ - ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL); \ - } \ - _hs_tail = _hs_e; \ - } \ - _hs_p = _hs_q; \ - } \ - if (_hs_tail != NULL) { \ - _hs_tail->next = NULL; \ - } \ - if (_hs_nmerges <= 1U) { \ - _hs_looping = 0; \ - (head)->hh.tbl->tail = _hs_tail; \ - DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ - } \ - _hs_insize *= 2U; \ - } \ - HASH_FSCK(hh, head, "HASH_SRT"); \ - } \ -} while (0) +#define HASH_SORT(head, cmpfcn) HASH_SRT(hh, head, cmpfcn) +#define HASH_SRT(hh, head, cmpfcn) \ + do { \ + unsigned _hs_i; \ + unsigned _hs_looping, _hs_nmerges, _hs_insize, _hs_psize, _hs_qsize; \ + struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ + if (head != NULL) { \ + _hs_insize = 1; \ + _hs_looping = 1; \ + _hs_list = &((head)->hh); \ + while (_hs_looping != 0U) { \ + _hs_p = _hs_list; \ + _hs_list = NULL; \ + _hs_tail = NULL; \ + _hs_nmerges = 0; \ + while (_hs_p != NULL) { \ + _hs_nmerges++; \ + _hs_q = _hs_p; \ + _hs_psize = 0; \ + for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) { \ + _hs_psize++; \ + _hs_q = ((_hs_q->next != NULL) ? HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + if (_hs_q == NULL) { \ + break; \ + } \ + } \ + _hs_qsize = _hs_insize; \ + while ((_hs_psize != 0U) || ((_hs_qsize != 0U) && (_hs_q != NULL))) { \ + if (_hs_psize == 0U) { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } else if ((_hs_qsize == 0U) || (_hs_q == NULL)) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else if ((cmpfcn( \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_p)), \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_q)))) \ + <= 0) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } \ + if (_hs_tail != NULL) { \ + _hs_tail->next = ((_hs_e != NULL) ? ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL); \ + } else { \ + _hs_list = _hs_e; \ + } \ + if (_hs_e != NULL) { \ + _hs_e->prev = ((_hs_tail != NULL) ? ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL); \ + } \ + _hs_tail = _hs_e; \ + } \ + _hs_p = _hs_q; \ + } \ + if (_hs_tail != NULL) { \ + _hs_tail->next = NULL; \ + } \ + if (_hs_nmerges <= 1U) { \ + _hs_looping = 0; \ + (head)->hh.tbl->tail = _hs_tail; \ + DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ + } \ + _hs_insize *= 2U; \ + } \ + HASH_FSCK(hh, head, "HASH_SRT"); \ + } \ + } while (0) /* This function selects items from one hash into another hash. * The end result is that the selected items have dual presence * in both hashes. There is no copy of the items made; rather * they are added into the new hash through a secondary hash * hash handle that must be present in the structure. */ -#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ -do { \ - unsigned _src_bkt, _dst_bkt; \ - void *_last_elt = NULL, *_elt; \ - UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ - ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ - if ((src) != NULL) { \ - for (_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ - for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ - _src_hh != NULL; \ - _src_hh = _src_hh->hh_next) { \ - _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ - if (cond(_elt)) { \ - IF_HASH_NONFATAL_OOM( int _hs_oomed = 0; ) \ - _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ - _dst_hh->key = _src_hh->key; \ - _dst_hh->keylen = _src_hh->keylen; \ - _dst_hh->hashv = _src_hh->hashv; \ - _dst_hh->prev = _last_elt; \ - _dst_hh->next = NULL; \ - if (_last_elt_hh != NULL) { \ - _last_elt_hh->next = _elt; \ - } \ - if ((dst) == NULL) { \ - DECLTYPE_ASSIGN(dst, _elt); \ - HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed); \ - IF_HASH_NONFATAL_OOM( \ - if (_hs_oomed) { \ - uthash_nonfatal_oom(_elt); \ - (dst) = NULL; \ - continue; \ - } \ - ) \ - } else { \ - _dst_hh->tbl = (dst)->hh_dst.tbl; \ - } \ - HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ - HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], hh_dst, _dst_hh, _hs_oomed); \ - (dst)->hh_dst.tbl->num_items++; \ - IF_HASH_NONFATAL_OOM( \ - if (_hs_oomed) { \ - HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh); \ - HASH_DELETE_HH(hh_dst, dst, _dst_hh); \ - _dst_hh->tbl = NULL; \ - uthash_nonfatal_oom(_elt); \ - continue; \ - } \ - ) \ - HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv); \ - _last_elt = _elt; \ - _last_elt_hh = _dst_hh; \ - } \ - } \ - } \ - } \ - HASH_FSCK(hh_dst, dst, "HASH_SELECT"); \ -} while (0) +#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ + do { \ + unsigned _src_bkt, _dst_bkt; \ + void *_last_elt = NULL, *_elt; \ + UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh = NULL; \ + ptrdiff_t _dst_hho = ((char *) (&(dst)->hh_dst) - (char *) (dst)); \ + if ((src) != NULL) { \ + for (_src_bkt = 0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ + for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ + _src_hh != NULL; \ + _src_hh = _src_hh->hh_next) { \ + _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ + if (cond(_elt)) { \ + IF_HASH_NONFATAL_OOM(int _hs_oomed = 0;) \ + _dst_hh = (UT_hash_handle *) (((char *) _elt) + _dst_hho); \ + _dst_hh->key = _src_hh->key; \ + _dst_hh->keylen = _src_hh->keylen; \ + _dst_hh->hashv = _src_hh->hashv; \ + _dst_hh->prev = _last_elt; \ + _dst_hh->next = NULL; \ + if (_last_elt_hh != NULL) { \ + _last_elt_hh->next = _elt; \ + } \ + if ((dst) == NULL) { \ + DECLTYPE_ASSIGN(dst, _elt); \ + HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (_hs_oomed) { \ + uthash_nonfatal_oom(_elt); \ + (dst) = NULL; \ + continue; \ + }) \ + } else { \ + _dst_hh->tbl = (dst)->hh_dst.tbl; \ + } \ + HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ + HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], hh_dst, _dst_hh, _hs_oomed); \ + (dst)->hh_dst.tbl->num_items++; \ + IF_HASH_NONFATAL_OOM( \ + if (_hs_oomed) { \ + HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh); \ + HASH_DELETE_HH(hh_dst, dst, _dst_hh); \ + _dst_hh->tbl = NULL; \ + uthash_nonfatal_oom(_elt); \ + continue; \ + }) \ + HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv); \ + _last_elt = _elt; \ + _last_elt_hh = _dst_hh; \ + } \ + } \ + } \ + } \ + HASH_FSCK(hh_dst, dst, "HASH_SELECT"); \ + } while (0) -#define HASH_CLEAR(hh,head) \ -do { \ - if ((head) != NULL) { \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - (head) = NULL; \ - } \ -} while (0) +#define HASH_CLEAR(hh, head) \ + do { \ + if ((head) != NULL) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } \ + } while (0) -#define HASH_OVERHEAD(hh,head) \ - (((head) != NULL) ? ( \ - (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ - ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ - sizeof(UT_hash_table) + \ - (HASH_BLOOM_BYTELEN))) : 0U) +#define HASH_OVERHEAD(hh, head) \ + (((head) != NULL) ? ( \ + (size_t) (((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + sizeof(UT_hash_table) + (HASH_BLOOM_BYTELEN))) \ + : 0U) #ifdef NO_DECLTYPE -#define HASH_ITER(hh,head,el,tmp) \ -for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \ - (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#define HASH_ITER(hh, head, el, tmp) \ + for (((el) = (head)), ((*(char **) (&(tmp))) = (char *) ((head != NULL) ? (head)->hh.next : NULL)); \ + (el) != NULL; ((el) = (tmp)), ((*(char **) (&(tmp))) = (char *) ((tmp != NULL) ? (tmp)->hh.next : NULL))) #else -#define HASH_ITER(hh,head,el,tmp) \ -for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \ - (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#define HASH_ITER(hh, head, el, tmp) \ + for (((el) = (head)), ((tmp) = DECLTYPE(el)((head != NULL) ? (head)->hh.next : NULL)); \ + (el) != NULL; ((el) = (tmp)), ((tmp) = DECLTYPE(el)((tmp != NULL) ? (tmp)->hh.next : NULL))) #endif /* obtain a count of items in the hash */ -#define HASH_COUNT(head) HASH_CNT(hh,head) -#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U) +#define HASH_COUNT(head) HASH_CNT(hh, head) +#define HASH_CNT(hh, head) ((head != NULL) ? ((head)->hh.tbl->num_items) : 0U) typedef struct UT_hash_bucket { - struct UT_hash_handle *hh_head; - unsigned count; + struct UT_hash_handle *hh_head; + unsigned count; - /* expand_mult is normally set to 0. In this situation, the max chain length - * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If - * the bucket's chain exceeds this length, bucket expansion is triggered). - * However, setting expand_mult to a non-zero value delays bucket expansion - * (that would be triggered by additions to this particular bucket) - * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. - * (The multiplier is simply expand_mult+1). The whole idea of this - * multiplier is to reduce bucket expansions, since they are expensive, in - * situations where we know that a particular bucket tends to be overused. - * It is better to let its chain length grow to a longer yet-still-bounded - * value, than to do an O(n) bucket expansion too often. - */ - unsigned expand_mult; + /* expand_mult is normally set to 0. In this situation, the max chain length + * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If + * the bucket's chain exceeds this length, bucket expansion is triggered). + * However, setting expand_mult to a non-zero value delays bucket expansion + * (that would be triggered by additions to this particular bucket) + * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. + * (The multiplier is simply expand_mult+1). The whole idea of this + * multiplier is to reduce bucket expansions, since they are expensive, in + * situations where we know that a particular bucket tends to be overused. + * It is better to let its chain length grow to a longer yet-still-bounded + * value, than to do an O(n) bucket expansion too often. + */ + unsigned expand_mult; } UT_hash_bucket; @@ -1181,47 +1208,47 @@ typedef struct UT_hash_bucket { #define HASH_BLOOM_SIGNATURE 0xb12220f2u typedef struct UT_hash_table { - UT_hash_bucket *buckets; - unsigned num_buckets, log2_num_buckets; - unsigned num_items; - struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ - ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ + UT_hash_bucket *buckets; + unsigned num_buckets, log2_num_buckets; + unsigned num_items; + struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ + ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ - /* in an ideal situation (all buckets used equally), no bucket would have - * more than ceil(#items/#buckets) items. that's the ideal chain length. */ - unsigned ideal_chain_maxlen; + /* in an ideal situation (all buckets used equally), no bucket would have + * more than ceil(#items/#buckets) items. that's the ideal chain length. */ + unsigned ideal_chain_maxlen; - /* nonideal_items is the number of items in the hash whose chain position - * exceeds the ideal chain maxlen. these items pay the penalty for an uneven - * hash distribution; reaching them in a chain traversal takes >ideal steps */ - unsigned nonideal_items; + /* nonideal_items is the number of items in the hash whose chain position + * exceeds the ideal chain maxlen. these items pay the penalty for an uneven + * hash distribution; reaching them in a chain traversal takes >ideal steps */ + unsigned nonideal_items; - /* ineffective expands occur when a bucket doubling was performed, but - * afterward, more than half the items in the hash had nonideal chain - * positions. If this happens on two consecutive expansions we inhibit any - * further expansion, as it's not helping; this happens when the hash - * function isn't a good fit for the key domain. When expansion is inhibited - * the hash will still work, albeit no longer in constant time. */ - unsigned ineff_expands, noexpand; + /* ineffective expands occur when a bucket doubling was performed, but + * afterward, more than half the items in the hash had nonideal chain + * positions. If this happens on two consecutive expansions we inhibit any + * further expansion, as it's not helping; this happens when the hash + * function isn't a good fit for the key domain. When expansion is inhibited + * the hash will still work, albeit no longer in constant time. */ + unsigned ineff_expands, noexpand; - uint32_t signature; /* used only to find hash tables in external analysis */ + uint32_t signature; /* used only to find hash tables in external analysis */ #ifdef HASH_BLOOM - uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ - uint8_t *bloom_bv; - uint8_t bloom_nbits; + uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ + uint8_t *bloom_bv; + uint8_t bloom_nbits; #endif } UT_hash_table; typedef struct UT_hash_handle { - struct UT_hash_table *tbl; - void *prev; /* prev element in app order */ - void *next; /* next element in app order */ - struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ - struct UT_hash_handle *hh_next; /* next hh in bucket order */ - void *key; /* ptr to enclosing struct's key */ - unsigned keylen; /* enclosing struct's key len */ - unsigned hashv; /* result of hash-fcn(key) */ + struct UT_hash_table *tbl; + void *prev; /* prev element in app order */ + void *next; /* next element in app order */ + struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ + struct UT_hash_handle *hh_next; /* next hh in bucket order */ + void *key; /* ptr to enclosing struct's key */ + unsigned keylen; /* enclosing struct's key len */ + unsigned hashv; /* result of hash-fcn(key) */ } UT_hash_handle; #endif /* UTHASH_H */ diff --git a/utlist.h b/utlist.h index e48ff36..d814000 100644 --- a/utlist.h +++ b/utlist.h @@ -62,15 +62,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. when compiling c++ source) this code uses whatever method is needed or, for VS2008 where neither is available, uses casting workarounds. */ #if !defined(LDECLTYPE) && !defined(NO_DECLTYPE) -#if defined(_MSC_VER) /* MS compiler */ -#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ #define LDECLTYPE(x) decltype(x) -#else /* VS2008 or older (or VS2010 in C mode) */ +#else /* VS2008 or older (or VS2010 in C mode) */ #define NO_DECLTYPE #endif #elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) #define NO_DECLTYPE -#else /* GNU, Sun and other compilers */ +#else /* GNU, Sun and other compilers */ #define LDECLTYPE(x) __typeof(x) #endif #endif @@ -80,653 +80,793 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * to dereference its prev/next pointers, and save/restore the real head.*/ #ifdef NO_DECLTYPE #define IF_NO_DECLTYPE(x) x -#define LDECLTYPE(x) char* -#define UTLIST_SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } -#define UTLIST_NEXT(elt,list,next) ((char*)((list)->next)) -#define UTLIST_NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } +#define LDECLTYPE(x) char * +#define UTLIST_SV(elt, list) \ + _tmp = (char *) (list); \ + { \ + char **_alias = (char **) &(list); \ + *_alias = (elt); \ + } +#define UTLIST_NEXT(elt, list, next) ((char *) ((list)->next)) +#define UTLIST_NEXTASGN(elt, list, to, next) \ + { \ + char **_alias = (char **) &((list)->next); \ + *_alias = (char *) (to); \ + } /* #define UTLIST_PREV(elt,list,prev) ((char*)((list)->prev)) */ -#define UTLIST_PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } -#define UTLIST_RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } -#define UTLIST_CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } +#define UTLIST_PREVASGN(elt, list, to, prev) \ + { \ + char **_alias = (char **) &((list)->prev); \ + *_alias = (char *) (to); \ + } +#define UTLIST_RS(list) \ + { \ + char **_alias = (char **) &(list); \ + *_alias = _tmp; \ + } +#define UTLIST_CASTASGN(a, b) \ + { \ + char **_alias = (char **) &(a); \ + *_alias = (char *) (b); \ + } #else #define IF_NO_DECLTYPE(x) -#define UTLIST_SV(elt,list) -#define UTLIST_NEXT(elt,list,next) ((elt)->next) -#define UTLIST_NEXTASGN(elt,list,to,next) ((elt)->next)=(to) +#define UTLIST_SV(elt, list) +#define UTLIST_NEXT(elt, list, next) ((elt)->next) +#define UTLIST_NEXTASGN(elt, list, to, next) ((elt)->next) = (to) /* #define UTLIST_PREV(elt,list,prev) ((elt)->prev) */ -#define UTLIST_PREVASGN(elt,list,to,prev) ((elt)->prev)=(to) +#define UTLIST_PREVASGN(elt, list, to, prev) ((elt)->prev) = (to) #define UTLIST_RS(list) -#define UTLIST_CASTASGN(a,b) (a)=(b) +#define UTLIST_CASTASGN(a, b) (a) = (b) #endif /****************************************************************************** * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort * * Unwieldy variable names used here to avoid shadowing passed-in variables. * *****************************************************************************/ -#define LL_SORT(list, cmp) \ - LL_SORT2(list, cmp, next) +#define LL_SORT(list, cmp) \ + LL_SORT2(list, cmp, next) -#define LL_SORT2(list, cmp, next) \ -do { \ - LDECLTYPE(list) _ls_p; \ - LDECLTYPE(list) _ls_q; \ - LDECLTYPE(list) _ls_e; \ - LDECLTYPE(list) _ls_tail; \ - IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ - int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ - if (list) { \ - _ls_insize = 1; \ - _ls_looping = 1; \ - while (_ls_looping) { \ - UTLIST_CASTASGN(_ls_p,list); \ - (list) = NULL; \ - _ls_tail = NULL; \ - _ls_nmerges = 0; \ - while (_ls_p) { \ - _ls_nmerges++; \ - _ls_q = _ls_p; \ - _ls_psize = 0; \ - for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ - _ls_psize++; \ - UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ - if (!_ls_q) break; \ - } \ - _ls_qsize = _ls_insize; \ - while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ - if (_ls_psize == 0) { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - } else if (_ls_qsize == 0 || !_ls_q) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - } else if (cmp(_ls_p,_ls_q) <= 0) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - } else { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - } \ - if (_ls_tail) { \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ - } else { \ - UTLIST_CASTASGN(list,_ls_e); \ - } \ - _ls_tail = _ls_e; \ - } \ - _ls_p = _ls_q; \ - } \ - if (_ls_tail) { \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ - } \ - if (_ls_nmerges <= 1) { \ - _ls_looping=0; \ - } \ - _ls_insize *= 2; \ - } \ - } \ -} while (0) +#define LL_SORT2(list, cmp, next) \ + do { \ + LDECLTYPE(list) \ + _ls_p; \ + LDECLTYPE(list) \ + _ls_q; \ + LDECLTYPE(list) \ + _ls_e; \ + LDECLTYPE(list) \ + _ls_tail; \ + IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p, list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q, list); \ + _ls_q = UTLIST_NEXT(_ls_q, list, next); \ + UTLIST_RS(list); \ + if (!_ls_q) \ + break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; \ + UTLIST_SV(_ls_q, list); \ + _ls_q = \ + UTLIST_NEXT(_ls_q, list, next); \ + UTLIST_RS(list); \ + _ls_qsize--; \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; \ + UTLIST_SV(_ls_p, list); \ + _ls_p = \ + UTLIST_NEXT(_ls_p, list, next); \ + UTLIST_RS(list); \ + _ls_psize--; \ + } else if (cmp(_ls_p, _ls_q) <= 0) { \ + _ls_e = _ls_p; \ + UTLIST_SV(_ls_p, list); \ + _ls_p = \ + UTLIST_NEXT(_ls_p, list, next); \ + UTLIST_RS(list); \ + _ls_psize--; \ + } else { \ + _ls_e = _ls_q; \ + UTLIST_SV(_ls_q, list); \ + _ls_q = \ + UTLIST_NEXT(_ls_q, list, next); \ + UTLIST_RS(list); \ + _ls_qsize--; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail, list); \ + UTLIST_NEXTASGN(_ls_tail, list, _ls_e, next); \ + UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list, _ls_e); \ + } \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail, list); \ + UTLIST_NEXTASGN(_ls_tail, list, NULL, next); \ + UTLIST_RS(list); \ + } \ + if (_ls_nmerges <= 1) { \ + _ls_looping = 0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ + } while (0) -#define DL_SORT(list, cmp) \ - DL_SORT2(list, cmp, prev, next) +#define DL_SORT(list, cmp) \ + DL_SORT2(list, cmp, prev, next) -#define DL_SORT2(list, cmp, prev, next) \ -do { \ - LDECLTYPE(list) _ls_p; \ - LDECLTYPE(list) _ls_q; \ - LDECLTYPE(list) _ls_e; \ - LDECLTYPE(list) _ls_tail; \ - IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ - int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ - if (list) { \ - _ls_insize = 1; \ - _ls_looping = 1; \ - while (_ls_looping) { \ - UTLIST_CASTASGN(_ls_p,list); \ - (list) = NULL; \ - _ls_tail = NULL; \ - _ls_nmerges = 0; \ - while (_ls_p) { \ - _ls_nmerges++; \ - _ls_q = _ls_p; \ - _ls_psize = 0; \ - for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ - _ls_psize++; \ - UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ - if (!_ls_q) break; \ - } \ - _ls_qsize = _ls_insize; \ - while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) { \ - if (_ls_psize == 0) { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - } else if ((_ls_qsize == 0) || (!_ls_q)) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - } else if (cmp(_ls_p,_ls_q) <= 0) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - } else { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - } \ - if (_ls_tail) { \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ - } else { \ - UTLIST_CASTASGN(list,_ls_e); \ - } \ - UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ - _ls_tail = _ls_e; \ - } \ - _ls_p = _ls_q; \ - } \ - UTLIST_CASTASGN((list)->prev, _ls_tail); \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ - if (_ls_nmerges <= 1) { \ - _ls_looping=0; \ - } \ - _ls_insize *= 2; \ - } \ - } \ -} while (0) +#define DL_SORT2(list, cmp, prev, next) \ + do { \ + LDECLTYPE(list) \ + _ls_p; \ + LDECLTYPE(list) \ + _ls_q; \ + LDECLTYPE(list) \ + _ls_e; \ + LDECLTYPE(list) \ + _ls_tail; \ + IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p, list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q, list); \ + _ls_q = UTLIST_NEXT(_ls_q, list, next); \ + UTLIST_RS(list); \ + if (!_ls_q) \ + break; \ + } \ + _ls_qsize = _ls_insize; \ + while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; \ + UTLIST_SV(_ls_q, list); \ + _ls_q = \ + UTLIST_NEXT(_ls_q, list, next); \ + UTLIST_RS(list); \ + _ls_qsize--; \ + } else if ((_ls_qsize == 0) || (!_ls_q)) { \ + _ls_e = _ls_p; \ + UTLIST_SV(_ls_p, list); \ + _ls_p = \ + UTLIST_NEXT(_ls_p, list, next); \ + UTLIST_RS(list); \ + _ls_psize--; \ + } else if (cmp(_ls_p, _ls_q) <= 0) { \ + _ls_e = _ls_p; \ + UTLIST_SV(_ls_p, list); \ + _ls_p = \ + UTLIST_NEXT(_ls_p, list, next); \ + UTLIST_RS(list); \ + _ls_psize--; \ + } else { \ + _ls_e = _ls_q; \ + UTLIST_SV(_ls_q, list); \ + _ls_q = \ + UTLIST_NEXT(_ls_q, list, next); \ + UTLIST_RS(list); \ + _ls_qsize--; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail, list); \ + UTLIST_NEXTASGN(_ls_tail, list, _ls_e, next); \ + UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list, _ls_e); \ + } \ + UTLIST_SV(_ls_e, list); \ + UTLIST_PREVASGN(_ls_e, list, _ls_tail, prev); \ + UTLIST_RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + UTLIST_CASTASGN((list)->prev, _ls_tail); \ + UTLIST_SV(_ls_tail, list); \ + UTLIST_NEXTASGN(_ls_tail, list, NULL, next); \ + UTLIST_RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping = 0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ + } while (0) -#define CDL_SORT(list, cmp) \ - CDL_SORT2(list, cmp, prev, next) +#define CDL_SORT(list, cmp) \ + CDL_SORT2(list, cmp, prev, next) -#define CDL_SORT2(list, cmp, prev, next) \ -do { \ - LDECLTYPE(list) _ls_p; \ - LDECLTYPE(list) _ls_q; \ - LDECLTYPE(list) _ls_e; \ - LDECLTYPE(list) _ls_tail; \ - LDECLTYPE(list) _ls_oldhead; \ - LDECLTYPE(list) _tmp; \ - int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ - if (list) { \ - _ls_insize = 1; \ - _ls_looping = 1; \ - while (_ls_looping) { \ - UTLIST_CASTASGN(_ls_p,list); \ - UTLIST_CASTASGN(_ls_oldhead,list); \ - (list) = NULL; \ - _ls_tail = NULL; \ - _ls_nmerges = 0; \ - while (_ls_p) { \ - _ls_nmerges++; \ - _ls_q = _ls_p; \ - _ls_psize = 0; \ - for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ - _ls_psize++; \ - UTLIST_SV(_ls_q,list); \ - if (UTLIST_NEXT(_ls_q,list,next) == _ls_oldhead) { \ - _ls_q = NULL; \ - } else { \ - _ls_q = UTLIST_NEXT(_ls_q,list,next); \ - } \ - UTLIST_RS(list); \ - if (!_ls_q) break; \ - } \ - _ls_qsize = _ls_insize; \ - while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ - if (_ls_psize == 0) { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ - } else if (_ls_qsize == 0 || !_ls_q) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ - } else if (cmp(_ls_p,_ls_q) <= 0) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ - } else { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ - } \ - if (_ls_tail) { \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ - } else { \ - UTLIST_CASTASGN(list,_ls_e); \ - } \ - UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ - _ls_tail = _ls_e; \ - } \ - _ls_p = _ls_q; \ - } \ - UTLIST_CASTASGN((list)->prev,_ls_tail); \ - UTLIST_CASTASGN(_tmp,list); \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_tmp,next); UTLIST_RS(list); \ - if (_ls_nmerges <= 1) { \ - _ls_looping=0; \ - } \ - _ls_insize *= 2; \ - } \ - } \ -} while (0) +#define CDL_SORT2(list, cmp, prev, next) \ + do { \ + LDECLTYPE(list) \ + _ls_p; \ + LDECLTYPE(list) \ + _ls_q; \ + LDECLTYPE(list) \ + _ls_e; \ + LDECLTYPE(list) \ + _ls_tail; \ + LDECLTYPE(list) \ + _ls_oldhead; \ + LDECLTYPE(list) \ + _tmp; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p, list); \ + UTLIST_CASTASGN(_ls_oldhead, list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q, list); \ + if (UTLIST_NEXT(_ls_q, list, next) == _ls_oldhead) { \ + _ls_q = NULL; \ + } else { \ + _ls_q = UTLIST_NEXT(_ls_q, list, next); \ + } \ + UTLIST_RS(list); \ + if (!_ls_q) \ + break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; \ + UTLIST_SV(_ls_q, list); \ + _ls_q = \ + UTLIST_NEXT(_ls_q, list, next); \ + UTLIST_RS(list); \ + _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { \ + _ls_q = NULL; \ + } \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; \ + UTLIST_SV(_ls_p, list); \ + _ls_p = \ + UTLIST_NEXT(_ls_p, list, next); \ + UTLIST_RS(list); \ + _ls_psize--; \ + if (_ls_p == _ls_oldhead) { \ + _ls_p = NULL; \ + } \ + } else if (cmp(_ls_p, _ls_q) <= 0) { \ + _ls_e = _ls_p; \ + UTLIST_SV(_ls_p, list); \ + _ls_p = \ + UTLIST_NEXT(_ls_p, list, next); \ + UTLIST_RS(list); \ + _ls_psize--; \ + if (_ls_p == _ls_oldhead) { \ + _ls_p = NULL; \ + } \ + } else { \ + _ls_e = _ls_q; \ + UTLIST_SV(_ls_q, list); \ + _ls_q = \ + UTLIST_NEXT(_ls_q, list, next); \ + UTLIST_RS(list); \ + _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { \ + _ls_q = NULL; \ + } \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail, list); \ + UTLIST_NEXTASGN(_ls_tail, list, _ls_e, next); \ + UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list, _ls_e); \ + } \ + UTLIST_SV(_ls_e, list); \ + UTLIST_PREVASGN(_ls_e, list, _ls_tail, prev); \ + UTLIST_RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + UTLIST_CASTASGN((list)->prev, _ls_tail); \ + UTLIST_CASTASGN(_tmp, list); \ + UTLIST_SV(_ls_tail, list); \ + UTLIST_NEXTASGN(_ls_tail, list, _tmp, next); \ + UTLIST_RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping = 0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ + } while (0) /****************************************************************************** * singly linked list macros (non-circular) * *****************************************************************************/ -#define LL_PREPEND(head,add) \ - LL_PREPEND2(head,add,next) +#define LL_PREPEND(head, add) \ + LL_PREPEND2(head, add, next) -#define LL_PREPEND2(head,add,next) \ -do { \ - (add)->next = (head); \ - (head) = (add); \ -} while (0) +#define LL_PREPEND2(head, add, next) \ + do { \ + (add)->next = (head); \ + (head) = (add); \ + } while (0) -#define LL_CONCAT(head1,head2) \ - LL_CONCAT2(head1,head2,next) +#define LL_CONCAT(head1, head2) \ + LL_CONCAT2(head1, head2, next) -#define LL_CONCAT2(head1,head2,next) \ -do { \ - LDECLTYPE(head1) _tmp; \ - if (head1) { \ - _tmp = (head1); \ - while (_tmp->next) { _tmp = _tmp->next; } \ - _tmp->next=(head2); \ - } else { \ - (head1)=(head2); \ - } \ -} while (0) +#define LL_CONCAT2(head1, head2, next) \ + do { \ + LDECLTYPE(head1) \ + _tmp; \ + if (head1) { \ + _tmp = (head1); \ + while (_tmp->next) { \ + _tmp = _tmp->next; \ + } \ + _tmp->next = (head2); \ + } else { \ + (head1) = (head2); \ + } \ + } while (0) -#define LL_APPEND(head,add) \ - LL_APPEND2(head,add,next) +#define LL_APPEND(head, add) \ + LL_APPEND2(head, add, next) -#define LL_APPEND2(head,add,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - (add)->next=NULL; \ - if (head) { \ - _tmp = (head); \ - while (_tmp->next) { _tmp = _tmp->next; } \ - _tmp->next=(add); \ - } else { \ - (head)=(add); \ - } \ -} while (0) +#define LL_APPEND2(head, add, next) \ + do { \ + LDECLTYPE(head) \ + _tmp; \ + (add)->next = NULL; \ + if (head) { \ + _tmp = (head); \ + while (_tmp->next) { \ + _tmp = _tmp->next; \ + } \ + _tmp->next = (add); \ + } else { \ + (head) = (add); \ + } \ + } while (0) -#define LL_INSERT_INORDER(head,add,cmp) \ - LL_INSERT_INORDER2(head,add,cmp,next) +#define LL_INSERT_INORDER(head, add, cmp) \ + LL_INSERT_INORDER2(head, add, cmp, next) -#define LL_INSERT_INORDER2(head,add,cmp,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - if (head) { \ - LL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ - LL_APPEND_ELEM2(head, _tmp, add, next); \ - } else { \ - (head) = (add); \ - (head)->next = NULL; \ - } \ -} while (0) +#define LL_INSERT_INORDER2(head, add, cmp, next) \ + do { \ + LDECLTYPE(head) \ + _tmp; \ + if (head) { \ + LL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + LL_APPEND_ELEM2(head, _tmp, add, next); \ + } else { \ + (head) = (add); \ + (head)->next = NULL; \ + } \ + } while (0) -#define LL_LOWER_BOUND(head,elt,like,cmp) \ - LL_LOWER_BOUND2(head,elt,like,cmp,next) +#define LL_LOWER_BOUND(head, elt, like, cmp) \ + LL_LOWER_BOUND2(head, elt, like, cmp, next) -#define LL_LOWER_BOUND2(head,elt,like,cmp,next) \ - do { \ - if ((head) == NULL || (cmp(head, like)) >= 0) { \ - (elt) = NULL; \ - } else { \ - for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ - if (cmp((elt)->next, like) >= 0) { \ - break; \ - } \ - } \ - } \ - } while (0) +#define LL_LOWER_BOUND2(head, elt, like, cmp, next) \ + do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ + if (cmp((elt)->next, like) >= 0) { \ + break; \ + } \ + } \ + } \ + } while (0) -#define LL_DELETE(head,del) \ - LL_DELETE2(head,del,next) +#define LL_DELETE(head, del) \ + LL_DELETE2(head, del, next) -#define LL_DELETE2(head,del,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - if ((head) == (del)) { \ - (head)=(head)->next; \ - } else { \ - _tmp = (head); \ - while (_tmp->next && (_tmp->next != (del))) { \ - _tmp = _tmp->next; \ - } \ - if (_tmp->next) { \ - _tmp->next = (del)->next; \ - } \ - } \ -} while (0) +#define LL_DELETE2(head, del, next) \ + do { \ + LDECLTYPE(head) \ + _tmp; \ + if ((head) == (del)) { \ + (head) = (head)->next; \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (del))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (del)->next; \ + } \ + } \ + } while (0) -#define LL_COUNT(head,el,counter) \ - LL_COUNT2(head,el,counter,next) \ +#define LL_COUNT(head, el, counter) \ + LL_COUNT2(head, el, counter, next) -#define LL_COUNT2(head,el,counter,next) \ -do { \ - (counter) = 0; \ - LL_FOREACH2(head,el,next) { ++(counter); } \ -} while (0) +#define LL_COUNT2(head, el, counter, next) \ + do { \ + (counter) = 0; \ + LL_FOREACH2(head, el, next) \ + { \ + ++(counter); \ + } \ + } while (0) -#define LL_FOREACH(head,el) \ - LL_FOREACH2(head,el,next) +#define LL_FOREACH(head, el) \ + LL_FOREACH2(head, el, next) -#define LL_FOREACH2(head,el,next) \ - for ((el) = (head); el; (el) = (el)->next) +#define LL_FOREACH2(head, el, next) \ + for ((el) = (head); el; (el) = (el)->next) -#define LL_FOREACH_SAFE(head,el,tmp) \ - LL_FOREACH_SAFE2(head,el,tmp,next) +#define LL_FOREACH_SAFE(head, el, tmp) \ + LL_FOREACH_SAFE2(head, el, tmp, next) -#define LL_FOREACH_SAFE2(head,el,tmp,next) \ - for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) +#define LL_FOREACH_SAFE2(head, el, tmp, next) \ + for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) -#define LL_SEARCH_SCALAR(head,out,field,val) \ - LL_SEARCH_SCALAR2(head,out,field,val,next) +#define LL_SEARCH_SCALAR(head, out, field, val) \ + LL_SEARCH_SCALAR2(head, out, field, val, next) -#define LL_SEARCH_SCALAR2(head,out,field,val,next) \ -do { \ - LL_FOREACH2(head,out,next) { \ - if ((out)->field == (val)) break; \ - } \ -} while (0) +#define LL_SEARCH_SCALAR2(head, out, field, val, next) \ + do { \ + LL_FOREACH2(head, out, next) \ + { \ + if ((out)->field == (val)) \ + break; \ + } \ + } while (0) -#define LL_SEARCH(head,out,elt,cmp) \ - LL_SEARCH2(head,out,elt,cmp,next) +#define LL_SEARCH(head, out, elt, cmp) \ + LL_SEARCH2(head, out, elt, cmp, next) -#define LL_SEARCH2(head,out,elt,cmp,next) \ -do { \ - LL_FOREACH2(head,out,next) { \ - if ((cmp(out,elt))==0) break; \ - } \ -} while (0) +#define LL_SEARCH2(head, out, elt, cmp, next) \ + do { \ + LL_FOREACH2(head, out, next) \ + { \ + if ((cmp(out, elt)) == 0) \ + break; \ + } \ + } while (0) -#define LL_REPLACE_ELEM2(head, el, add, next) \ -do { \ - LDECLTYPE(head) _tmp; \ - (add)->next = (el)->next; \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - _tmp = (head); \ - while (_tmp->next && (_tmp->next != (el))) { \ - _tmp = _tmp->next; \ - } \ - if (_tmp->next) { \ - _tmp->next = (add); \ - } \ - } \ -} while (0) +#define LL_REPLACE_ELEM2(head, el, add, next) \ + do { \ + LDECLTYPE(head) \ + _tmp; \ + (add)->next = (el)->next; \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ + } while (0) -#define LL_REPLACE_ELEM(head, el, add) \ - LL_REPLACE_ELEM2(head, el, add, next) +#define LL_REPLACE_ELEM(head, el, add) \ + LL_REPLACE_ELEM2(head, el, add, next) -#define LL_PREPEND_ELEM2(head, el, add, next) \ -do { \ - if (el) { \ - LDECLTYPE(head) _tmp; \ - (add)->next = (el); \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - _tmp = (head); \ - while (_tmp->next && (_tmp->next != (el))) { \ - _tmp = _tmp->next; \ - } \ - if (_tmp->next) { \ - _tmp->next = (add); \ - } \ - } \ - } else { \ - LL_APPEND2(head, add, next); \ - } \ -} while (0) \ +#define LL_PREPEND_ELEM2(head, el, add, next) \ + do { \ + if (el) { \ + LDECLTYPE(head) \ + _tmp; \ + (add)->next = (el); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ + } else { \ + LL_APPEND2(head, add, next); \ + } \ + } while (0) -#define LL_PREPEND_ELEM(head, el, add) \ - LL_PREPEND_ELEM2(head, el, add, next) +#define LL_PREPEND_ELEM(head, el, add) \ + LL_PREPEND_ELEM2(head, el, add, next) -#define LL_APPEND_ELEM2(head, el, add, next) \ -do { \ - if (el) { \ - (add)->next = (el)->next; \ - (el)->next = (add); \ - } else { \ - LL_PREPEND2(head, add, next); \ - } \ -} while (0) \ +#define LL_APPEND_ELEM2(head, el, add, next) \ + do { \ + if (el) { \ + (add)->next = (el)->next; \ + (el)->next = (add); \ + } else { \ + LL_PREPEND2(head, add, next); \ + } \ + } while (0) -#define LL_APPEND_ELEM(head, el, add) \ - LL_APPEND_ELEM2(head, el, add, next) +#define LL_APPEND_ELEM(head, el, add) \ + LL_APPEND_ELEM2(head, el, add, next) #ifdef NO_DECLTYPE /* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ #undef LL_CONCAT2 -#define LL_CONCAT2(head1,head2,next) \ -do { \ - char *_tmp; \ - if (head1) { \ - _tmp = (char*)(head1); \ - while ((head1)->next) { (head1) = (head1)->next; } \ - (head1)->next = (head2); \ - UTLIST_RS(head1); \ - } else { \ - (head1)=(head2); \ - } \ -} while (0) +#define LL_CONCAT2(head1, head2, next) \ + do { \ + char *_tmp; \ + if (head1) { \ + _tmp = (char *) (head1); \ + while ((head1)->next) { \ + (head1) = (head1)->next; \ + } \ + (head1)->next = (head2); \ + UTLIST_RS(head1); \ + } else { \ + (head1) = (head2); \ + } \ + } while (0) #undef LL_APPEND2 -#define LL_APPEND2(head,add,next) \ -do { \ - if (head) { \ - (add)->next = head; /* use add->next as a temp variable */ \ - while ((add)->next->next) { (add)->next = (add)->next->next; } \ - (add)->next->next=(add); \ - } else { \ - (head)=(add); \ - } \ - (add)->next=NULL; \ -} while (0) +#define LL_APPEND2(head, add, next) \ + do { \ + if (head) { \ + (add)->next = head; /* use add->next as a temp variable */ \ + while ((add)->next->next) { \ + (add)->next = (add)->next->next; \ + } \ + (add)->next->next = (add); \ + } else { \ + (head) = (add); \ + } \ + (add)->next = NULL; \ + } while (0) #undef LL_INSERT_INORDER2 -#define LL_INSERT_INORDER2(head,add,cmp,next) \ -do { \ - if ((head) == NULL || (cmp(head, add)) >= 0) { \ - (add)->next = (head); \ - (head) = (add); \ - } else { \ - char *_tmp = (char*)(head); \ - while ((head)->next != NULL && (cmp((head)->next, add)) < 0) { \ - (head) = (head)->next; \ - } \ - (add)->next = (head)->next; \ - (head)->next = (add); \ - UTLIST_RS(head); \ - } \ -} while (0) +#define LL_INSERT_INORDER2(head, add, cmp, next) \ + do { \ + if ((head) == NULL || (cmp(head, add)) >= 0) { \ + (add)->next = (head); \ + (head) = (add); \ + } else { \ + char *_tmp = (char *) (head); \ + while ((head)->next != NULL && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->next = (head)->next; \ + (head)->next = (add); \ + UTLIST_RS(head); \ + } \ + } while (0) #undef LL_DELETE2 -#define LL_DELETE2(head,del,next) \ -do { \ - if ((head) == (del)) { \ - (head)=(head)->next; \ - } else { \ - char *_tmp = (char*)(head); \ - while ((head)->next && ((head)->next != (del))) { \ - (head) = (head)->next; \ - } \ - if ((head)->next) { \ - (head)->next = ((del)->next); \ - } \ - UTLIST_RS(head); \ - } \ -} while (0) +#define LL_DELETE2(head, del, next) \ + do { \ + if ((head) == (del)) { \ + (head) = (head)->next; \ + } else { \ + char *_tmp = (char *) (head); \ + while ((head)->next && ((head)->next != (del))) { \ + (head) = (head)->next; \ + } \ + if ((head)->next) { \ + (head)->next = ((del)->next); \ + } \ + UTLIST_RS(head); \ + } \ + } while (0) #undef LL_REPLACE_ELEM2 -#define LL_REPLACE_ELEM2(head, el, add, next) \ -do { \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - (add)->next = head; \ - while ((add)->next->next && ((add)->next->next != (el))) { \ - (add)->next = (add)->next->next; \ - } \ - if ((add)->next->next) { \ - (add)->next->next = (add); \ - } \ - } \ - (add)->next = (el)->next; \ -} while (0) +#define LL_REPLACE_ELEM2(head, el, add, next) \ + do { \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->next = head; \ + while ((add)->next->next && ((add)->next->next != (el))) { \ + (add)->next = (add)->next->next; \ + } \ + if ((add)->next->next) { \ + (add)->next->next = (add); \ + } \ + } \ + (add)->next = (el)->next; \ + } while (0) #undef LL_PREPEND_ELEM2 -#define LL_PREPEND_ELEM2(head, el, add, next) \ -do { \ - if (el) { \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - (add)->next = (head); \ - while ((add)->next->next && ((add)->next->next != (el))) { \ - (add)->next = (add)->next->next; \ - } \ - if ((add)->next->next) { \ - (add)->next->next = (add); \ - } \ - } \ - (add)->next = (el); \ - } else { \ - LL_APPEND2(head, add, next); \ - } \ -} while (0) \ +#define LL_PREPEND_ELEM2(head, el, add, next) \ + do { \ + if (el) { \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->next = (head); \ + while ((add)->next->next && ((add)->next->next != (el))) { \ + (add)->next = (add)->next->next; \ + } \ + if ((add)->next->next) { \ + (add)->next->next = (add); \ + } \ + } \ + (add)->next = (el); \ + } else { \ + LL_APPEND2(head, add, next); \ + } \ + } while (0) #endif /* NO_DECLTYPE */ /****************************************************************************** * doubly linked list macros (non-circular) * *****************************************************************************/ -#define DL_PREPEND(head,add) \ - DL_PREPEND2(head,add,prev,next) +#define DL_PREPEND(head, add) \ + DL_PREPEND2(head, add, prev, next) -#define DL_PREPEND2(head,add,prev,next) \ -do { \ - (add)->next = (head); \ - if (head) { \ - (add)->prev = (head)->prev; \ - (head)->prev = (add); \ - } else { \ - (add)->prev = (add); \ - } \ - (head) = (add); \ -} while (0) +#define DL_PREPEND2(head, add, prev, next) \ + do { \ + (add)->next = (head); \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev = (add); \ + } else { \ + (add)->prev = (add); \ + } \ + (head) = (add); \ + } while (0) -#define DL_APPEND(head,add) \ - DL_APPEND2(head,add,prev,next) +#define DL_APPEND(head, add) \ + DL_APPEND2(head, add, prev, next) -#define DL_APPEND2(head,add,prev,next) \ -do { \ - if (head) { \ - (add)->prev = (head)->prev; \ - (head)->prev->next = (add); \ - (head)->prev = (add); \ - (add)->next = NULL; \ - } else { \ - (head)=(add); \ - (head)->prev = (head); \ - (head)->next = NULL; \ - } \ -} while (0) +#define DL_APPEND2(head, add, prev, next) \ + do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev->next = (add); \ + (head)->prev = (add); \ + (add)->next = NULL; \ + } else { \ + (head) = (add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ + } while (0) -#define DL_INSERT_INORDER(head,add,cmp) \ - DL_INSERT_INORDER2(head,add,cmp,prev,next) +#define DL_INSERT_INORDER(head, add, cmp) \ + DL_INSERT_INORDER2(head, add, cmp, prev, next) -#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - if (head) { \ - DL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ - DL_APPEND_ELEM2(head, _tmp, add, prev, next); \ - } else { \ - (head) = (add); \ - (head)->prev = (head); \ - (head)->next = NULL; \ - } \ -} while (0) +#define DL_INSERT_INORDER2(head, add, cmp, prev, next) \ + do { \ + LDECLTYPE(head) \ + _tmp; \ + if (head) { \ + DL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + DL_APPEND_ELEM2(head, _tmp, add, prev, next); \ + } else { \ + (head) = (add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ + } while (0) -#define DL_LOWER_BOUND(head,elt,like,cmp) \ - DL_LOWER_BOUND2(head,elt,like,cmp,next) +#define DL_LOWER_BOUND(head, elt, like, cmp) \ + DL_LOWER_BOUND2(head, elt, like, cmp, next) -#define DL_LOWER_BOUND2(head,elt,like,cmp,next) \ -do { \ - if ((head) == NULL || (cmp(head, like)) >= 0) { \ - (elt) = NULL; \ - } else { \ - for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ - if ((cmp((elt)->next, like)) >= 0) { \ - break; \ - } \ - } \ - } \ -} while (0) +#define DL_LOWER_BOUND2(head, elt, like, cmp, next) \ + do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ + if ((cmp((elt)->next, like)) >= 0) { \ + break; \ + } \ + } \ + } \ + } while (0) -#define DL_CONCAT(head1,head2) \ - DL_CONCAT2(head1,head2,prev,next) +#define DL_CONCAT(head1, head2) \ + DL_CONCAT2(head1, head2, prev, next) -#define DL_CONCAT2(head1,head2,prev,next) \ -do { \ - LDECLTYPE(head1) _tmp; \ - if (head2) { \ - if (head1) { \ - UTLIST_CASTASGN(_tmp, (head2)->prev); \ - (head2)->prev = (head1)->prev; \ - (head1)->prev->next = (head2); \ - UTLIST_CASTASGN((head1)->prev, _tmp); \ - } else { \ - (head1)=(head2); \ - } \ - } \ -} while (0) +#define DL_CONCAT2(head1, head2, prev, next) \ + do { \ + LDECLTYPE(head1) \ + _tmp; \ + if (head2) { \ + if (head1) { \ + UTLIST_CASTASGN(_tmp, (head2)->prev); \ + (head2)->prev = (head1)->prev; \ + (head1)->prev->next = (head2); \ + UTLIST_CASTASGN((head1)->prev, _tmp); \ + } else { \ + (head1) = (head2); \ + } \ + } \ + } while (0) -#define DL_DELETE(head,del) \ - DL_DELETE2(head,del,prev,next) +#define DL_DELETE(head, del) \ + DL_DELETE2(head, del, prev, next) -#define DL_DELETE2(head,del,prev,next) \ -do { \ - if ((del)->prev == (del)) { \ - (head)=NULL; \ - } else if ((del)==(head)) { \ - (del)->next->prev = (del)->prev; \ - (head) = (del)->next; \ - } else { \ - (del)->prev->next = (del)->next; \ - if ((del)->next) { \ - (del)->next->prev = (del)->prev; \ - } else { \ - (head)->prev = (del)->prev; \ - } \ - } \ -} while (0) +#define DL_DELETE2(head, del, prev, next) \ + do { \ + if ((del)->prev == (del)) { \ + (head) = NULL; \ + } else if ((del) == (head)) { \ + (del)->next->prev = (del)->prev; \ + (head) = (del)->next; \ + } else { \ + (del)->prev->next = (del)->next; \ + if ((del)->next) { \ + (del)->next->prev = (del)->prev; \ + } else { \ + (head)->prev = (del)->prev; \ + } \ + } \ + } while (0) -#define DL_COUNT(head,el,counter) \ - DL_COUNT2(head,el,counter,next) \ +#define DL_COUNT(head, el, counter) \ + DL_COUNT2(head, el, counter, next) -#define DL_COUNT2(head,el,counter,next) \ -do { \ - (counter) = 0; \ - DL_FOREACH2(head,el,next) { ++(counter); } \ -} while (0) +#define DL_COUNT2(head, el, counter, next) \ + do { \ + (counter) = 0; \ + DL_FOREACH2(head, el, next) \ + { \ + ++(counter); \ + } \ + } while (0) -#define DL_FOREACH(head,el) \ - DL_FOREACH2(head,el,next) +#define DL_FOREACH(head, el) \ + DL_FOREACH2(head, el, next) -#define DL_FOREACH2(head,el,next) \ - for ((el) = (head); el; (el) = (el)->next) +#define DL_FOREACH2(head, el, next) \ + for ((el) = (head); el; (el) = (el)->next) /* this version is safe for deleting the elements during iteration */ -#define DL_FOREACH_SAFE(head,el,tmp) \ - DL_FOREACH_SAFE2(head,el,tmp,next) +#define DL_FOREACH_SAFE(head, el, tmp) \ + DL_FOREACH_SAFE2(head, el, tmp, next) -#define DL_FOREACH_SAFE2(head,el,tmp,next) \ - for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) +#define DL_FOREACH_SAFE2(head, el, tmp, next) \ + for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) /* these are identical to their singly-linked list counterparts */ #define DL_SEARCH_SCALAR LL_SEARCH_SCALAR @@ -734,310 +874,319 @@ do { #define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2 #define DL_SEARCH2 LL_SEARCH2 -#define DL_REPLACE_ELEM2(head, el, add, prev, next) \ -do { \ - if ((head) == (el)) { \ - (head) = (add); \ - (add)->next = (el)->next; \ - if ((el)->next == NULL) { \ - (add)->prev = (add); \ - } else { \ - (add)->prev = (el)->prev; \ - (add)->next->prev = (add); \ - } \ - } else { \ - (add)->next = (el)->next; \ - (add)->prev = (el)->prev; \ - (add)->prev->next = (add); \ - if ((el)->next == NULL) { \ - (head)->prev = (add); \ - } else { \ - (add)->next->prev = (add); \ - } \ - } \ -} while (0) +#define DL_REPLACE_ELEM2(head, el, add, prev, next) \ + do { \ + if ((head) == (el)) { \ + (head) = (add); \ + (add)->next = (el)->next; \ + if ((el)->next == NULL) { \ + (add)->prev = (add); \ + } else { \ + (add)->prev = (el)->prev; \ + (add)->next->prev = (add); \ + } \ + } else { \ + (add)->next = (el)->next; \ + (add)->prev = (el)->prev; \ + (add)->prev->next = (add); \ + if ((el)->next == NULL) { \ + (head)->prev = (add); \ + } else { \ + (add)->next->prev = (add); \ + } \ + } \ + } while (0) -#define DL_REPLACE_ELEM(head, el, add) \ - DL_REPLACE_ELEM2(head, el, add, prev, next) +#define DL_REPLACE_ELEM(head, el, add) \ + DL_REPLACE_ELEM2(head, el, add, prev, next) -#define DL_PREPEND_ELEM2(head, el, add, prev, next) \ -do { \ - if (el) { \ - (add)->next = (el); \ - (add)->prev = (el)->prev; \ - (el)->prev = (add); \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - (add)->prev->next = (add); \ - } \ - } else { \ - DL_APPEND2(head, add, prev, next); \ - } \ -} while (0) \ +#define DL_PREPEND_ELEM2(head, el, add, prev, next) \ + do { \ + if (el) { \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->prev->next = (add); \ + } \ + } else { \ + DL_APPEND2(head, add, prev, next); \ + } \ + } while (0) -#define DL_PREPEND_ELEM(head, el, add) \ - DL_PREPEND_ELEM2(head, el, add, prev, next) +#define DL_PREPEND_ELEM(head, el, add) \ + DL_PREPEND_ELEM2(head, el, add, prev, next) -#define DL_APPEND_ELEM2(head, el, add, prev, next) \ -do { \ - if (el) { \ - (add)->next = (el)->next; \ - (add)->prev = (el); \ - (el)->next = (add); \ - if ((add)->next) { \ - (add)->next->prev = (add); \ - } else { \ - (head)->prev = (add); \ - } \ - } else { \ - DL_PREPEND2(head, add, prev, next); \ - } \ -} while (0) \ +#define DL_APPEND_ELEM2(head, el, add, prev, next) \ + do { \ + if (el) { \ + (add)->next = (el)->next; \ + (add)->prev = (el); \ + (el)->next = (add); \ + if ((add)->next) { \ + (add)->next->prev = (add); \ + } else { \ + (head)->prev = (add); \ + } \ + } else { \ + DL_PREPEND2(head, add, prev, next); \ + } \ + } while (0) -#define DL_APPEND_ELEM(head, el, add) \ - DL_APPEND_ELEM2(head, el, add, prev, next) +#define DL_APPEND_ELEM(head, el, add) \ + DL_APPEND_ELEM2(head, el, add, prev, next) #ifdef NO_DECLTYPE /* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ #undef DL_INSERT_INORDER2 -#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ -do { \ - if ((head) == NULL) { \ - (add)->prev = (add); \ - (add)->next = NULL; \ - (head) = (add); \ - } else if ((cmp(head, add)) >= 0) { \ - (add)->prev = (head)->prev; \ - (add)->next = (head); \ - (head)->prev = (add); \ - (head) = (add); \ - } else { \ - char *_tmp = (char*)(head); \ - while ((head)->next && (cmp((head)->next, add)) < 0) { \ - (head) = (head)->next; \ - } \ - (add)->prev = (head); \ - (add)->next = (head)->next; \ - (head)->next = (add); \ - UTLIST_RS(head); \ - if ((add)->next) { \ - (add)->next->prev = (add); \ - } else { \ - (head)->prev = (add); \ - } \ - } \ -} while (0) +#define DL_INSERT_INORDER2(head, add, cmp, prev, next) \ + do { \ + if ((head) == NULL) { \ + (add)->prev = (add); \ + (add)->next = NULL; \ + (head) = (add); \ + } else if ((cmp(head, add)) >= 0) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (head) = (add); \ + } else { \ + char *_tmp = (char *) (head); \ + while ((head)->next && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->prev = (head); \ + (add)->next = (head)->next; \ + (head)->next = (add); \ + UTLIST_RS(head); \ + if ((add)->next) { \ + (add)->next->prev = (add); \ + } else { \ + (head)->prev = (add); \ + } \ + } \ + } while (0) #endif /* NO_DECLTYPE */ /****************************************************************************** * circular doubly linked list macros * *****************************************************************************/ -#define CDL_APPEND(head,add) \ - CDL_APPEND2(head,add,prev,next) +#define CDL_APPEND(head, add) \ + CDL_APPEND2(head, add, prev, next) -#define CDL_APPEND2(head,add,prev,next) \ -do { \ - if (head) { \ - (add)->prev = (head)->prev; \ - (add)->next = (head); \ - (head)->prev = (add); \ - (add)->prev->next = (add); \ - } else { \ - (add)->prev = (add); \ - (add)->next = (add); \ - (head) = (add); \ - } \ -} while (0) +#define CDL_APPEND2(head, add, prev, next) \ + do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + (head) = (add); \ + } \ + } while (0) -#define CDL_PREPEND(head,add) \ - CDL_PREPEND2(head,add,prev,next) +#define CDL_PREPEND(head, add) \ + CDL_PREPEND2(head, add, prev, next) -#define CDL_PREPEND2(head,add,prev,next) \ -do { \ - if (head) { \ - (add)->prev = (head)->prev; \ - (add)->next = (head); \ - (head)->prev = (add); \ - (add)->prev->next = (add); \ - } else { \ - (add)->prev = (add); \ - (add)->next = (add); \ - } \ - (head) = (add); \ -} while (0) +#define CDL_PREPEND2(head, add, prev, next) \ + do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + } \ + (head) = (add); \ + } while (0) -#define CDL_INSERT_INORDER(head,add,cmp) \ - CDL_INSERT_INORDER2(head,add,cmp,prev,next) +#define CDL_INSERT_INORDER(head, add, cmp) \ + CDL_INSERT_INORDER2(head, add, cmp, prev, next) -#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - if (head) { \ - CDL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ - CDL_APPEND_ELEM2(head, _tmp, add, prev, next); \ - } else { \ - (head) = (add); \ - (head)->next = (head); \ - (head)->prev = (head); \ - } \ -} while (0) +#define CDL_INSERT_INORDER2(head, add, cmp, prev, next) \ + do { \ + LDECLTYPE(head) \ + _tmp; \ + if (head) { \ + CDL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + CDL_APPEND_ELEM2(head, _tmp, add, prev, next); \ + } else { \ + (head) = (add); \ + (head)->next = (head); \ + (head)->prev = (head); \ + } \ + } while (0) -#define CDL_LOWER_BOUND(head,elt,like,cmp) \ - CDL_LOWER_BOUND2(head,elt,like,cmp,next) +#define CDL_LOWER_BOUND(head, elt, like, cmp) \ + CDL_LOWER_BOUND2(head, elt, like, cmp, next) -#define CDL_LOWER_BOUND2(head,elt,like,cmp,next) \ -do { \ - if ((head) == NULL || (cmp(head, like)) >= 0) { \ - (elt) = NULL; \ - } else { \ - for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) { \ - if ((cmp((elt)->next, like)) >= 0) { \ - break; \ - } \ - } \ - } \ -} while (0) +#define CDL_LOWER_BOUND2(head, elt, like, cmp, next) \ + do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) { \ + if ((cmp((elt)->next, like)) >= 0) { \ + break; \ + } \ + } \ + } \ + } while (0) -#define CDL_DELETE(head,del) \ - CDL_DELETE2(head,del,prev,next) +#define CDL_DELETE(head, del) \ + CDL_DELETE2(head, del, prev, next) -#define CDL_DELETE2(head,del,prev,next) \ -do { \ - if (((head)==(del)) && ((head)->next == (head))) { \ - (head) = NULL; \ - } else { \ - (del)->next->prev = (del)->prev; \ - (del)->prev->next = (del)->next; \ - if ((del) == (head)) (head)=(del)->next; \ - } \ -} while (0) +#define CDL_DELETE2(head, del, prev, next) \ + do { \ + if (((head) == (del)) && ((head)->next == (head))) { \ + (head) = NULL; \ + } else { \ + (del)->next->prev = (del)->prev; \ + (del)->prev->next = (del)->next; \ + if ((del) == (head)) \ + (head) = (del)->next; \ + } \ + } while (0) -#define CDL_COUNT(head,el,counter) \ - CDL_COUNT2(head,el,counter,next) \ +#define CDL_COUNT(head, el, counter) \ + CDL_COUNT2(head, el, counter, next) -#define CDL_COUNT2(head, el, counter,next) \ -do { \ - (counter) = 0; \ - CDL_FOREACH2(head,el,next) { ++(counter); } \ -} while (0) +#define CDL_COUNT2(head, el, counter, next) \ + do { \ + (counter) = 0; \ + CDL_FOREACH2(head, el, next) \ + { \ + ++(counter); \ + } \ + } while (0) -#define CDL_FOREACH(head,el) \ - CDL_FOREACH2(head,el,next) +#define CDL_FOREACH(head, el) \ + CDL_FOREACH2(head, el, next) -#define CDL_FOREACH2(head,el,next) \ - for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next)) +#define CDL_FOREACH2(head, el, next) \ + for ((el) = (head); el; (el) = (((el)->next == (head)) ? NULL : (el)->next)) -#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ - CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) +#define CDL_FOREACH_SAFE(head, el, tmp1, tmp2) \ + CDL_FOREACH_SAFE2(head, el, tmp1, tmp2, prev, next) -#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \ - for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL; \ - (el) && ((tmp2) = (el)->next, 1); \ - (el) = ((el) == (tmp1) ? NULL : (tmp2))) +#define CDL_FOREACH_SAFE2(head, el, tmp1, tmp2, prev, next) \ + for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL; \ + (el) && ((tmp2) = (el)->next, 1); \ + (el) = ((el) == (tmp1) ? NULL : (tmp2))) -#define CDL_SEARCH_SCALAR(head,out,field,val) \ - CDL_SEARCH_SCALAR2(head,out,field,val,next) +#define CDL_SEARCH_SCALAR(head, out, field, val) \ + CDL_SEARCH_SCALAR2(head, out, field, val, next) -#define CDL_SEARCH_SCALAR2(head,out,field,val,next) \ -do { \ - CDL_FOREACH2(head,out,next) { \ - if ((out)->field == (val)) break; \ - } \ -} while (0) +#define CDL_SEARCH_SCALAR2(head, out, field, val, next) \ + do { \ + CDL_FOREACH2(head, out, next) \ + { \ + if ((out)->field == (val)) \ + break; \ + } \ + } while (0) -#define CDL_SEARCH(head,out,elt,cmp) \ - CDL_SEARCH2(head,out,elt,cmp,next) +#define CDL_SEARCH(head, out, elt, cmp) \ + CDL_SEARCH2(head, out, elt, cmp, next) -#define CDL_SEARCH2(head,out,elt,cmp,next) \ -do { \ - CDL_FOREACH2(head,out,next) { \ - if ((cmp(out,elt))==0) break; \ - } \ -} while (0) +#define CDL_SEARCH2(head, out, elt, cmp, next) \ + do { \ + CDL_FOREACH2(head, out, next) \ + { \ + if ((cmp(out, elt)) == 0) \ + break; \ + } \ + } while (0) -#define CDL_REPLACE_ELEM2(head, el, add, prev, next) \ -do { \ - if ((el)->next == (el)) { \ - (add)->next = (add); \ - (add)->prev = (add); \ - (head) = (add); \ - } else { \ - (add)->next = (el)->next; \ - (add)->prev = (el)->prev; \ - (add)->next->prev = (add); \ - (add)->prev->next = (add); \ - if ((head) == (el)) { \ - (head) = (add); \ - } \ - } \ -} while (0) +#define CDL_REPLACE_ELEM2(head, el, add, prev, next) \ + do { \ + if ((el)->next == (el)) { \ + (add)->next = (add); \ + (add)->prev = (add); \ + (head) = (add); \ + } else { \ + (add)->next = (el)->next; \ + (add)->prev = (el)->prev; \ + (add)->next->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ + } \ + } while (0) -#define CDL_REPLACE_ELEM(head, el, add) \ - CDL_REPLACE_ELEM2(head, el, add, prev, next) +#define CDL_REPLACE_ELEM(head, el, add) \ + CDL_REPLACE_ELEM2(head, el, add, prev, next) -#define CDL_PREPEND_ELEM2(head, el, add, prev, next) \ -do { \ - if (el) { \ - (add)->next = (el); \ - (add)->prev = (el)->prev; \ - (el)->prev = (add); \ - (add)->prev->next = (add); \ - if ((head) == (el)) { \ - (head) = (add); \ - } \ - } else { \ - CDL_APPEND2(head, add, prev, next); \ - } \ -} while (0) +#define CDL_PREPEND_ELEM2(head, el, add, prev, next) \ + do { \ + if (el) { \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ + } else { \ + CDL_APPEND2(head, add, prev, next); \ + } \ + } while (0) -#define CDL_PREPEND_ELEM(head, el, add) \ - CDL_PREPEND_ELEM2(head, el, add, prev, next) +#define CDL_PREPEND_ELEM(head, el, add) \ + CDL_PREPEND_ELEM2(head, el, add, prev, next) -#define CDL_APPEND_ELEM2(head, el, add, prev, next) \ -do { \ - if (el) { \ - (add)->next = (el)->next; \ - (add)->prev = (el); \ - (el)->next = (add); \ - (add)->next->prev = (add); \ - } else { \ - CDL_PREPEND2(head, add, prev, next); \ - } \ -} while (0) +#define CDL_APPEND_ELEM2(head, el, add, prev, next) \ + do { \ + if (el) { \ + (add)->next = (el)->next; \ + (add)->prev = (el); \ + (el)->next = (add); \ + (add)->next->prev = (add); \ + } else { \ + CDL_PREPEND2(head, add, prev, next); \ + } \ + } while (0) -#define CDL_APPEND_ELEM(head, el, add) \ - CDL_APPEND_ELEM2(head, el, add, prev, next) +#define CDL_APPEND_ELEM(head, el, add) \ + CDL_APPEND_ELEM2(head, el, add, prev, next) #ifdef NO_DECLTYPE /* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ #undef CDL_INSERT_INORDER2 -#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ -do { \ - if ((head) == NULL) { \ - (add)->prev = (add); \ - (add)->next = (add); \ - (head) = (add); \ - } else if ((cmp(head, add)) >= 0) { \ - (add)->prev = (head)->prev; \ - (add)->next = (head); \ - (add)->prev->next = (add); \ - (head)->prev = (add); \ - (head) = (add); \ - } else { \ - char *_tmp = (char*)(head); \ - while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) { \ - (head) = (head)->next; \ - } \ - (add)->prev = (head); \ - (add)->next = (head)->next; \ - (add)->next->prev = (add); \ - (head)->next = (add); \ - UTLIST_RS(head); \ - } \ -} while (0) +#define CDL_INSERT_INORDER2(head, add, cmp, prev, next) \ + do { \ + if ((head) == NULL) { \ + (add)->prev = (add); \ + (add)->next = (add); \ + (head) = (add); \ + } else if ((cmp(head, add)) >= 0) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (add)->prev->next = (add); \ + (head)->prev = (add); \ + (head) = (add); \ + } else { \ + char *_tmp = (char *) (head); \ + while ((char *) (head)->next != _tmp && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->prev = (head); \ + (add)->next = (head)->next; \ + (add)->next->prev = (add); \ + (head)->next = (add); \ + UTLIST_RS(head); \ + } \ + } while (0) #endif /* NO_DECLTYPE */ #endif /* UTLIST_H */