57create_esctrie_node(
automaton* a, 
int special){
 
   68  memset(
e, 0, 
sizeof(*
e));
 
   69  e->ntype = NODE_SPECIAL;
 
   70  if((
e->ni.id = special) == 0){
 
   71    const size_t tsize = 
sizeof(*
e->trie) * 0x80;
 
   72    if((
e->trie = malloc(tsize)) == 
NULL){
 
   76    memset(
e->trie, 0, tsize);
 
   78  return esctrie_idx(a, 
e);
 
   84  for(
unsigned i = 0 ; i < a->
poolused ; ++i){
 
 
   94  if(
e->ntype != NODE_SPECIAL){
 
   95    logerror(
"can't make node type %d string", 
e->ntype);
 
   98  for(
unsigned i = 0 ; i < 0x80 ; ++i){
 
  100      e->trie[i] = esctrie_idx(a, term);
 
  101    }
else if(
e->trie[i] == 0){
 
  102      e->trie[i] = esctrie_idx(a, 
e);
 
  110  if(
e->ntype != NODE_SPECIAL){
 
  111    logerror(
"can't make node type %d function", 
e->ntype);
 
  115    logerror(
"can't make followed function");
 
  118  e->ntype = NODE_FUNCTION;
 
  125  if(
e->ntype == NODE_STRING){
 
  129  if(
e->ntype != NODE_SPECIAL){
 
  130    logerror(
"can't make node type %d string", 
e->ntype);
 
  133  for(
int i = 0 ; i < 0x80 ; ++i){
 
  138      logerror(
"can't make %c-followed string", i);
 
  142  esctrie* newe = esctrie_from_idx(a, create_esctrie_node(a, 0));
 
  146  for(
int i = 0 ; i < 0x80 ; ++i){
 
  150    e->trie[i] = esctrie_idx(a, newe);
 
  154  for(
int i = 0 ; i < 0x80 ; ++i){
 
  158    e->
trie[i] = esctrie_idx(a, newe);
 
  161    if((
e->trie[0x1b] = create_esctrie_node(a, 0)) == 0){
 
  164    e = esctrie_from_idx(a, 
e->trie[0x1b]);
 
  166    e->ntype = NODE_SPECIAL;
 
  171    esctrie* term = esctrie_from_idx(a, 
e->trie[0x07]);
 
  172    if((
e->trie[0x1b] = create_esctrie_node(a, 0)) == 0){
 
  175    e = esctrie_from_idx(a, 
e->trie[0x1b]);
 
  176    e->trie[
'\\'] = esctrie_idx(a, term);
 
  178    term->
ntype = NODE_SPECIAL;
 
  181  logdebug(
"made string: %u", esctrie_idx(a, 
e));
 
  187  unsigned eidx = esctrie_idx(a, 
e);
 
  192  unsigned termidx = create_esctrie_node(a, 0);
 
  193  unsigned targidx = create_esctrie_node(a, 0);
 
  194  esctrie* term = esctrie_from_idx(a, termidx);
 
  195  esctrie* targ = esctrie_from_idx(a, targidx);
 
  202  if(esctrie_make_kleene(a, targ, follow, term)){
 
  205  e = esctrie_from_idx(a, eidx);
 
  207  for(
unsigned int i = 0 ; i < 0x80 ; ++i){
 
  210        logerror(
"drain terminator already registered");
 
  213      e->trie[follow] = esctrie_idx(a, term);
 
  214    }
else if(
e->trie[i] == 0){
 
  215      e->trie[i] = esctrie_idx(a, targ);
 
  218  targ->
kleene = esctrie_idx(a, targ);
 
  219  return esctrie_from_idx(a, 
e->trie[follow]);
 
  229  for(
int i = 
'0' ; i <= 
'9' ; ++i){
 
  230    if( (targ = esctrie_from_idx(a, 
e->trie[i])) ){
 
  231      if(targ->
ntype == NODE_NUMERIC){
 
  232        logtrace(
"found existing phi node %u[%c]->%u", esctrie_idx(a, 
e), i, esctrie_idx(a, targ));
 
  244      logerror(
"ten non-phi links from %u", esctrie_idx(a, 
e));
 
  247    if((targ = esctrie_from_idx(a, create_esctrie_node(a, 0))) == 0){
 
  250    targ->
ntype = NODE_NUMERIC;
 
  251    for(
int i = 
'0' ; i <= 
'9' ; ++i){
 
  252      targ->
trie[i] = esctrie_idx(a, targ);
 
  256  return esctrie_idx(a, targ);
 
  262  unsigned phiidx = esctrie_idx(a, phi);
 
  263  unsigned etaidx = phi->
trie[successor];
 
  264  esctrie* eta = esctrie_from_idx(a, etaidx);
 
  267    if((eta = esctrie_from_idx(a, create_esctrie_node(a, 0))) == 
NULL){
 
  270    phi = esctrie_from_idx(a, phiidx);
 
  271    phi->
trie[successor] = esctrie_idx(a, eta);
 
  273  return esctrie_idx(a, eta);
 
  280                      unsigned follow, 
unsigned eta){
 
  282  for(
int i = 
'0' ; i <= 
'9' ; ++i){
 
  283    esctrie* chain = esctrie_from_idx(a, 
e->trie[i]);
 
  287    }
else if(chain->
ntype == NODE_SPECIAL){
 
  289      add_phi_and_eta_chain(a, esctrie_from_idx(a, 
e->trie[i]), phi, follow, eta);
 
  292  if(
e->trie[follow] == 0){
 
  294    e->trie[follow] = eta;
 
  305                        int pfxlen, 
esctrie* phi, 
unsigned follow,
 
  311    add_phi_and_eta_chain(a, 
e, esctrie_idx(a, phi), follow, esctrie_idx(a, eta));
 
  319      logerror(
"illegal wildcard in prefix %c", *prefix);
 
  327    unsigned linked_tri_seen_last = UINT_MAX;
 
  328    for(
int i = 
'0' ; i <= 
'9' ; ++i){
 
  331        e->trie[i] = esctrie_idx(a, phi);
 
  333        if(
e->trie[i] != linked_tri_seen_last){
 
  334            add_phi_and_eta_recurse(a, esctrie_from_idx(a, 
e->trie[i]),
 
  335                                prefix, pfxlen, phi, follow, eta, 1);
 
  336            linked_tri_seen_last = 
e->trie[i];
 
  343      unsigned linked_tri_seen_last = UINT_MAX;
 
  344      for(
int i = 
'0' ; i <= 
'9' ; ++i){
 
  347          e->trie[i] = esctrie_idx(a, phi);
 
  348        }
else if(
e->trie[i] != esctrie_idx(a, 
e) && 
e->trie[i] != linked_tri_seen_last){
 
  349          add_phi_and_eta_recurse(a, esctrie_from_idx(a, 
e->trie[i]),
 
  350                                prefix, pfxlen, phi, follow, eta, 1);
 
  351          linked_tri_seen_last = 
e->trie[i];
 
  355    unsigned char p = *prefix;
 
  357      add_phi_and_eta_recurse(a, esctrie_from_idx(a, 
e->trie[p]),
 
  358                              prefix + 1, pfxlen - 1, phi, follow, eta, 0);
 
  365add_phi_and_eta(
automaton* a, 
const char* prefix, 
size_t pfxlen,
 
  371  add_phi_and_eta_recurse(a, esc, prefix, pfxlen, phi, follow, eta, 0);
 
  388link_numeric(
automaton* a, 
const char* prefix, 
int pfxlen,
 
  390  logdebug(
"adding numeric with follow %c following %*.*s", follow, pfxlen, pfxlen, prefix);
 
  391  unsigned phiidx = get_phi_node(a, 
e);
 
  395  esctrie* phi = esctrie_from_idx(a, phiidx);
 
  397  unsigned etaidx = get_eta_node(a, phi, follow);
 
  401  phi = esctrie_from_idx(a, phiidx);
 
  402  esctrie* eta = esctrie_from_idx(a, etaidx);
 
  403  logtrace(
"phi node: %u->%u", esctrie_idx(a, 
e), esctrie_idx(a, phi));
 
  404  logtrace(
"eta node: %u philink[%c]: %u", esctrie_idx(a, eta), follow, phi->
trie[follow]);
 
  409  add_phi_and_eta(a, prefix, pfxlen, phi, follow, eta);
 
  414insert_path(
automaton* a, 
const char* seq){
 
  416    if((a->
escapes = create_esctrie_node(a, 0)) == 0){
 
  421  bool inescape = 
false;
 
  422  const char* seqstart = seq;
 
  424  while( (
c = *seq++) ){
 
  435          logerror(
"illegal numeric terminator");
 
  439        eptr = link_numeric(a, seqstart, seq - 3 - seqstart, eptr, 
c);
 
  443      }
else if(
c == 
'S' || 
c == 
'R'){
 
  445        if((eptr = esctrie_make_string(a, eptr, 
c == 
'R')) == 
NULL){
 
  452          logerror(
"illegal kleene terminator");
 
  456        eptr = link_kleene(a, eptr, 
c);
 
  466      unsigned eidx = esctrie_idx(a, eptr);
 
  469        unsigned tidx = create_esctrie_node(a, 0);
 
  473        eptr = esctrie_from_idx(a, eidx);
 
  474        eptr->
trie[
c] = tidx;
 
  475      }
else if(esctrie_from_idx(a, eptr->
trie[
c])->
ntype == NODE_NUMERIC){
 
  480        if((newe = esctrie_from_idx(a, create_esctrie_node(a, 0))) == 0){
 
  483        eptr = esctrie_from_idx(a, eidx);
 
  484        for(
int i = 0 ; i < 0x80 ; ++i){
 
  487        eptr->
trie[
c] = esctrie_idx(a, newe);
 
  489      eptr = esctrie_from_idx(a, eidx);
 
  490      eptr = esctrie_from_idx(a, eptr->
trie[
c]);
 
  491      logtrace(
"added fixed 0x%08u %u as %u", 
c, 
c, esctrie_idx(a, eptr));
 
  495    logerror(
"illegal escape at end of line");
 
  503  esctrie* eptr = insert_path(a, seq);
 
  509  return esctrie_make_function(eptr, 
fxn);
 
 
  515  if(esc[0] != 
NCKEY_ESC || strlen(esc) < 2){ 
 
  516    logerror(
"not an escape (0x%x)", special);
 
  519  esctrie* eptr = insert_path(a, esc + 1);
 
  526    if(eptr->
ni.
id != special){
 
  527      logwarn(
"already added escape (got 0x%x, wanted 0x%x)", eptr->
ni.
id, special);
 
  530    eptr->
ni.
id = special;
 
  537    logdebug(
"added 0x%08x to %u", special, esctrie_idx(a, eptr));
 
 
  548  if(candidate >= 0x80){
 
  549    logerror(
"eight-bit char %u in control sequence", candidate);
 
  554  if(candidate == 0x1b && !a->
instring){
 
  563    if(candidate == 0x1b || candidate == 0x07){
 
  564      a->
state = 
e->trie[candidate];
 
  567    e = esctrie_from_idx(a, a->
state);
 
  577  if((a->
state = 
e->trie[candidate]) == 0){
 
  578    if(esctrie_idx(a, 
e) == a->
escapes){
 
  579      memset(
ni, 0, 
sizeof(*
ni));
 
  584    loginfo(
"unexpected transition on %u[%u]",
 
  585            esctrie_idx(a, 
e), candidate);
 
  588  e = esctrie_from_idx(a, a->
state);
 
  598        memcpy(
ni, &
e->ni, 
sizeof(*
ni));
 
 
int walk_automaton(automaton *a, struct inputctx *ictx, unsigned candidate, ncinput *ni)
int inputctx_add_input_escape(automaton *a, const char *esc, uint32_t special, unsigned modifiers)
uint32_t esctrie_id(const esctrie *e)
void input_free_esctrie(automaton *a)
int inputctx_add_cflow(automaton *a, const char *seq, triefunc fxn)
int(* triefunc)(struct inputctx *)
#define logerror(fmt,...)
#define logtrace(fmt,...)
#define logdebug(fmt,...)
struct esctrie * nodepool