Skip to content

Commit

Permalink
[automaton] close loop on functionals #2183
Browse files Browse the repository at this point in the history
  • Loading branch information
dankamongmen committed Sep 23, 2021
1 parent e620fc4 commit defeb0e
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 23 deletions.
37 changes: 30 additions & 7 deletions src/lib/automaton.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ typedef struct esctrie {
NODE_FUNCTION, // invokes a function
} ntype;
ncinput ni; // composed key terminating here
uint32_t number; // accumulated number; reset to 0 on entry
int number; // accumulated number; reset to 0 on entry
char* str; // accumulated string; reset to NULL on entry
triefunc fxn; // function to call on match
} esctrie;
Expand All @@ -27,6 +27,13 @@ esctrie** esctrie_trie(esctrie* e){
return e->trie;
}

int esctrie_numeric(const esctrie* e){
if(e->ntype != NODE_NUMERIC){
return -1;
}
return e->number;
}

static inline esctrie*
create_esctrie_node(int special){
esctrie* e = malloc(sizeof(*e));
Expand All @@ -52,9 +59,16 @@ free_trienode(esctrie** eptr){
if(e->trie){
int z;
for(z = 0 ; z < 0x80 ; ++z){
if(e->trie[z]){
// don't recurse down a link to ourselves
if(e->trie[z] && e->trie[z] != e){
free_trienode(&e->trie[z]);
}
// if it's a numeric path, only recurse once
if(z == '0'){
if(e->trie['1'] == e->trie[z]){
z = '9';
}
}
}
free(e->str);
free(e->trie);
Expand Down Expand Up @@ -83,6 +97,7 @@ esctrie_make_numeric(esctrie* e){
for(int i = '0' ; i < '9' ; ++i){
e->trie[i] = e;
}
logdebug("made numeric: %p\n", e);
return 0;
}

Expand All @@ -108,6 +123,7 @@ esctrie_make_string(esctrie* e){
}
e->trie[i] = e;
}
logdebug("made string: %p\n", e);
return 0;
}

Expand All @@ -123,6 +139,7 @@ esctrie_make_function(esctrie* e, triefunc fxn){
}
e->ntype = NODE_FUNCTION;
e->fxn = fxn;
logdebug("made function %p: %p\n", fxn, e);
return 0;
}

Expand All @@ -134,7 +151,7 @@ link_numeric(esctrie* e){
esctrie* targ = e->trie['0'];
for(int i = '1' ; i <= '9' ; ++i){
if(e->trie[i] != targ){
logerror("can't transition to a non-numeric %p != %p\n", e->trie[i], targ);
logerror("can't transition %p to a non-numeric %p != %p\n", e, e->trie[i], targ);
return NULL;
}
}
Expand Down Expand Up @@ -165,12 +182,14 @@ int inputctx_add_cflow(automaton* a, const char* csi, triefunc fxn){
}
}
esctrie* eptr = a->escapes;
if(eptr->trie[']'] == NULL){
if((eptr->trie[']'] = create_esctrie_node(0)) == NULL){
logdebug("ESCAPE START: %p\n", eptr);
if(eptr->trie['['] == NULL){
if((eptr->trie['['] = create_esctrie_node(0)) == NULL){
return -1;
}
}
eptr = eptr->trie[']'];
eptr = eptr->trie['['];
logdebug("CSI START: %p\n", eptr);
bool inescape = false;
unsigned char c;
while( (c = *csi++) ){
Expand Down Expand Up @@ -282,6 +301,7 @@ int walk_automaton(automaton* a, struct inputctx* ictx, unsigned candidate,
return -1;
}
esctrie* e = a->state;
logdebug("state: %p candidate: %c %u type: %d\n", e, candidate, candidate, e->ntype);
// we ought not have been called for an escape with any state!
if(candidate == 0x1b){
assert(NULL == e);
Expand All @@ -290,6 +310,7 @@ int walk_automaton(automaton* a, struct inputctx* ictx, unsigned candidate,
}
if(e->ntype == NODE_NUMERIC){
if(isdigit(candidate)){
// FIXME check for overflow
e->number = e->number * 10 + (candidate - '0');
return 0;
}
Expand Down Expand Up @@ -330,8 +351,10 @@ int walk_automaton(automaton* a, struct inputctx* ictx, unsigned candidate,
}
break;
case NODE_FUNCTION:
e->fxn(ictx);
a->state = NULL; // FIXME?
if(e->fxn(ictx)){
return -1;
}
return 1;
}
return 0;
Expand Down
3 changes: 2 additions & 1 deletion src/lib/automaton.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct ncinput;
struct esctrie;
struct inputctx;

typedef void(*triefunc)(struct inputctx*);
typedef int (*triefunc)(struct inputctx*);

// the state necessary for matching input against our automaton of control
// sequences. we *do not* match the bulk UTF-8 input. we match online (i.e.
Expand Down Expand Up @@ -40,6 +40,7 @@ int walk_automaton(automaton* a, struct inputctx* ictx, unsigned candidate,
uint32_t esctrie_id(const struct esctrie* e);
// returns 128-way array of esctrie pointers
struct esctrie** esctrie_trie(struct esctrie* e);
int esctrie_numeric(const struct esctrie* e);

#ifdef __cplusplus
}
Expand Down
87 changes: 72 additions & 15 deletions src/lib/in.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ inc_input_errors(inputctx* ictx){
// load all known special keys from terminfo, and build the input sequence trie
static int
prep_special_keys(inputctx* ictx){
/*
#ifndef __MINGW64__
static const struct {
const char* tinfo;
Expand Down Expand Up @@ -344,24 +345,74 @@ prep_special_keys(inputctx* ictx){
}
#endif
(void)ictx;
*/
return 0;
}

static void
static int
mouse_press_cb(inputctx* ictx){
return 0;
}

static void
static int
mouse_release_cb(inputctx* ictx){
return 0;
}

static void
static int
cursor_location_cb(inputctx* ictx){
// FIXME figure out a better way than this
struct esctrie* e = ictx->amata.escapes;
e = esctrie_trie(e)['['];
e = esctrie_trie(e)['0'];
int y = esctrie_numeric(e) - 1;
e = esctrie_trie(e)[';'];
e = esctrie_trie(e)['0'];
int x = esctrie_numeric(e) - 1;
pthread_mutex_lock(&ictx->clock);
if(ictx->cvalid == ictx->csize){
pthread_mutex_unlock(&ictx->clock);
logwarn("dropping cursor location report %d/%d\n", y, x);
inc_input_errors(ictx);
}else{
cursorloc* cloc = &ictx->csrs[ictx->cwrite];
if(++ictx->cwrite == ictx->csize){
ictx->cwrite = 0;
}
cloc->y = y;
cloc->x = x;
++ictx->cvalid;
pthread_mutex_unlock(&ictx->clock);
pthread_cond_broadcast(&ictx->ccond);
loginfo("cursor location: %d/%d\n", y, x);
}
return 0;
}

static void
static int
geom_cb(inputctx* ictx){
// FIXME verify first numeric is "4" for pixel, "8" for cell
// FIXME figure out a better way than this
struct esctrie* e = ictx->amata.escapes;
e = esctrie_trie(e)['['];
e = esctrie_trie(e)['0'];
int kind = esctrie_numeric(e) - 1;
e = esctrie_trie(e)[';'];
e = esctrie_trie(e)['0'];
int y = esctrie_numeric(e) - 1;
e = esctrie_trie(e)[';'];
e = esctrie_trie(e)['0'];
int x = esctrie_numeric(e) - 1;
loginfo("geom report type %d %d/%d\n", kind, y, x);
if(kind == 4){
// FIXME pixel
}else if(kind == 8){
// FIXME cell
}else{
logerror("invalid geometry type: %d\n", kind);
return -1;
}
return 0;
}

static int
Expand Down Expand Up @@ -1503,24 +1554,29 @@ process_escape(inputctx* ictx, const unsigned char* buf, int buflen){
}
ictx->state = STATE_NULL;
while(ictx->amata.used < buflen){
logdebug("state now: %p\n", ictx->amata.state);
unsigned char candidate = buf[ictx->amata.used++];
unsigned used = ictx->amata.used;
if(candidate >= 0x80){
ictx->amata.used = 0;
return -(used - 1);
}
int r = pump_control_read(ictx, candidate);
loginfo("pump_control_read: %d used: %d\n", r, ictx->amata.used);
if(r == 2){
ictx->amata.used = 0;
return used;
}
if(r == 1){ // received DA1, ending initial responses
// safe to call even if initdata == NULL
handoff_initial_responses(ictx);
ictx->amata.used = 0;
return used;
// FIXME this goes away
if(ictx->initdata){
int r = pump_control_read(ictx, candidate);
loginfo("pump_control_read: %d used: %d\n", r, ictx->amata.used);
if(r == 2){
ictx->amata.used = 0;
return used;
}
if(r == 1){ // received DA1, ending initial responses
// safe to call even if initdata == NULL
handoff_initial_responses(ictx);
ictx->amata.used = 0;
return used;
}
}
// FIXME this goes away
if(ictx->initdata){
continue; // FIXME drops any Alt+chars entwined within initial responses
}
Expand All @@ -1540,6 +1596,7 @@ process_escape(inputctx* ictx, const unsigned char* buf, int buflen){
logtrace("triepos: %p in: %u special: 0x%08x\n", ictx->amata.state,
candidate, esctrie_id(ictx->amata.state));
int w = walk_automaton(&ictx->amata, ictx, candidate, &ni);
logdebug("walk result on %u (%c): %d %p\n", candidate, candidate, w, ictx->amata.state);
if(w > 0){
if(ni.id){
special_key(ictx, &ni);
Expand Down

0 comments on commit defeb0e

Please sign in to comment.