#!/usr/local/bin/bx Main() if args != 1 usage("width") int width = atoi(arg[0]) sched_init() new(r, Reader) new(s, Splitter) new(f, Filler, width) new(w, Writer) sh(cstr, r, s) sh(cstr, s, f) sh(cstr, f, w) start(r) start(s) start(f) start(w) run() proc Reader() port cstr out state cstr s repeat s = Input() wr(out, s) if s == NULL break proc Splitter() port cstr in port cstr out state cstr line state cstr rest state cstr word repeat rd(in, line) if line == NULL break rest = line while *rest == ' ' ++rest if *rest == '\0' wr(out, strdup("")) else while rest != NULL while *rest == ' ' ++rest if *rest == '\0' break word = rest rest = strchr(rest, ' ') if rest == NULL wr(out, strdup(word)) wr(out, strdup("")) break *rest = '\0' ++rest wr(out, strdup(word)) Free(line) wr(out, NULL) # TODO get macros to work within coros # I wanted a macro to write the buffer, like this: # buffer_add_nul(b) # wr(out, strdup(buffer_get_start(b))) # buffer_clear(b) # but couldn't because the symbol "b" needs to be remapped ... # can I use local macros to do that remapping? # TODO some sort of subroutines / states / functions-that-can-yield within coros proc Filler(int width) port cstr in port cstr out state buffer struct__b state buffer *b = &struct__b state cstr word buffer_init(b) repeat rd(in, word) if word == NULL if buffer_get_size(b) buffer_add_nul(b) wr(out, strdup(buffer_get_start(b))) buffer_clear(b) wr(out, NULL) buffer_free(b) stop() eif cstr_is_empty(word) buffer_add_nul(b) wr(out, strdup(buffer_get_start(b))) buffer_clear(b) else int len = strlen(word) if buffer_get_size(b) && (int)buffer_get_size(b) + len >= width buffer_add_nul(b) wr(out, strdup(buffer_get_start(b))) buffer_clear(b) if buffer_get_size(b) buffer_cat_char(b, ' ') buffer_cat_cstr(b, word) proc Writer() port cstr in state cstr s repeat rd(in, s) if s == NULL break Say(s) Free(s) # REMEMBER - if using wr to write a var, that var MUST be state, not a local var # if splitting a string and freeing it, must alloc new strings for the words! use b shuttle(cstr)