original_code:
int lx_getsym(struct lexer *lx) {
start:
 if(lx->in[0] == '\0')
  return (lx->sym = 0);
 while(((*__ctype_b_loc ())[(int) ((lx->in[0]))] & (unsigned short int) _ISspace)) {
  if(lx->in[0] == '\n')
   lx->lineno++;
  lx->in++;
 }
 if(lx->in[0] == '#') {
  while(lx->in[0] != '\n' && lx->in[0] != '\0')
   lx->in++;
  goto start;
 }
 if(((*__ctype_b_loc ())[(int) ((lx->in[0]))] & (unsigned short int) _ISalpha) || lx->in[0] == '_') {
  int i = 0;
  lx->sym = 1;
  while(((*__ctype_b_loc ())[(int) ((lx->in[0]))] & (unsigned short int) _ISalnum) || lx->in[0] == '_') {
   lx->text[i++] = *lx->in++;
   if(i == 512 - 1) {
    snprintf(lx->text, 512, "identifier too long");
    return (lx->sym = -1);
   }
  }
  lx->text[i] = '\0';
  if(lx->keywds) {
   int i = 0;
   while(lx->keywds[i].word != ((void *)0)) {
    if(!strcmp(lx->text, lx->keywds[i].word)) {
     lx->sym = lx->keywds[i].value;
     break;
    }
    i++;
   }
  }
 } else if(((*__ctype_b_loc ())[(int) ((lx->in[0]))] & (unsigned short int) _ISdigit)) {
  int i = 0;
  lx->sym = 2;
  while(((*__ctype_b_loc ())[(int) ((lx->in[0]))] & (unsigned short int) _ISdigit)) {
   lx->text[i++] = *lx->in++;
   if(i == 512 - 1) {
    snprintf(lx->text, 512, "number too long");
    return (lx->sym = -1);
   }
  }
  if(lx->in[0] == '.') {
   lx->text[i++] = *lx->in++;
   if(i == 512 - 1) {
    snprintf(lx->text, 512, "number too long");
    return (lx->sym = -1);
   }
   while(((*__ctype_b_loc ())[(int) ((lx->in[0]))] & (unsigned short int) _ISdigit)) {
    lx->text[i++] = *lx->in++;
    if(i == 512 - 1) {
     snprintf(lx->text, 512, "number too long");
     return (lx->sym = -1);
    }
   }
  }
  if(tolower(lx->in[0]) == 'e') {
   lx->text[i++] = *lx->in++;
   if(i == 512 - 1) {
    snprintf(lx->text, 512, "number too long");
    return (lx->sym = -1);
   }
   if(strchr("+-", lx->in[0])) {
    lx->text[i++] = *lx->in++;
    if(i == 512 - 1) {
     snprintf(lx->text, 512, "number too long");
     return (lx->sym = -1);
    }
   }
   while(((*__ctype_b_loc ())[(int) ((lx->in[0]))] & (unsigned short int) _ISdigit)) {
    lx->text[i++] = *lx->in++;
    if(i == 512 - 1) {
     snprintf(lx->text, 512, "number too long");
     return (lx->sym = -1);
    }
   }
  }
  lx->text[i] = '\0';
 } else if(lx->in[0] == '"') {
  int i = 0;
  lx->in++;
  while(lx->in[0] != '"') {
   if(i == 512 - 1) {
    snprintf(lx->text, 512, "string literal too long");
    return (lx->sym = -1);
   }
   switch(lx->in[0]) {
    case '\0' : {
      snprintf(lx->text, 512, "unterminated string literal");
      return (lx->sym = -1);
     }
    case '\\' : {
      lx->in++;
      switch(lx->in[0]) {
       case '\0' : {
         snprintf(lx->text, 512, "unterminated string literal");
         return (lx->sym = -1);
        }
       case '/' : lx->text[i++] = '/'; break;
       case '\\' : lx->text[i++] = '\\'; break;
       case 'b' : lx->text[i++] = '\b'; break;
       case 'f' : lx->text[i++] = '\f'; break;
       case 'n' : lx->text[i++] = '\n'; break;
       case 'r' : lx->text[i++] = '\r'; break;
       case 't' : lx->text[i++] = '\t'; break;
       case '"' : lx->text[i++] = '"'; break;
       default: {
         snprintf(lx->text, 512, "bad escape sequence \\%c", lx->in[0]);
         return (lx->sym = -1);
        }
      }
     } break;
    default : {
      lx->text[i++] = lx->in[0];
      if(lx->in[0] == '\n') {
       lx->lineno++;
      }
     } break;
   }
   lx->in++;
  }
  lx->text[i] = '\0';
  lx->sym = 3;
  lx->in++;
 } else if(strchr(lx->opers, lx->in[0])) {
  return (lx->sym = *lx->in++);
 } else {
  snprintf(lx->text, 512, "Unexpected token '%c'", lx->in[0]);
  return (lx->sym = -1);
 }
 return lx->sym;
}

canonical_original_code:
int lx_getsym(struct lexer *lx) {
start:
 if(lx->in[0] == '\0')
  return (lx->sym = 0);
 while(((*__ctype_b_loc ())[(int) ((lx->in[0]))] & (unsigned short) _ISspace)) {
  if(lx->in[0] == '\n')
   lx->lineno++;
  lx->in++;
 }
 if(lx->in[0] == '#') {
  while(lx->in[0] != '\n' && lx->in[0] != '\0')
   lx->in++;
  goto start;
 }
 if(((*__ctype_b_loc ())[(int) ((lx->in[0]))] & (unsigned short) _ISalpha) || lx->in[0] == '_') {
  int i = 0;
  lx->sym = 1;
  while(((*__ctype_b_loc ())[(int) ((lx->in[0]))] & (unsigned short) _ISalnum) || lx->in[0] == '_') {
   lx->text[i++] = *lx->in++;
   if(i == 512 - 1) {
    snprintf(lx->text, 512, "identifier too long");
    return (lx->sym = -1);
   }
  }
  lx->text[i] = '\0';
  if(lx->keywds) {
   int i = 0;
   while(lx->keywds[i].word != ((void *)0)) {
    if(!strcmp(lx->text, lx->keywds[i].word)) {
     lx->sym = lx->keywds[i].value;
     break;
    }
    i++;
   }
  }
 } else if(((*__ctype_b_loc ())[(int) ((lx->in[0]))] & (unsigned short) _ISdigit)) {
  int i = 0;
  lx->sym = 2;
  while(((*__ctype_b_loc ())[(int) ((lx->in[0]))] & (unsigned short) _ISdigit)) {
   lx->text[i++] = *lx->in++;
   if(i == 512 - 1) {
    snprintf(lx->text, 512, "number too long");
    return (lx->sym = -1);
   }
  }
  if(lx->in[0] == '.') {
   lx->text[i++] = *lx->in++;
   if(i == 512 - 1) {
    snprintf(lx->text, 512, "number too long");
    return (lx->sym = -1);
   }
   while(((*__ctype_b_loc ())[(int) ((lx->in[0]))] & (unsigned short) _ISdigit)) {
    lx->text[i++] = *lx->in++;
    if(i == 512 - 1) {
     snprintf(lx->text, 512, "number too long");
     return (lx->sym = -1);
    }
   }
  }
  if(tolower(lx->in[0]) == 'e') {
   lx->text[i++] = *lx->in++;
   if(i == 512 - 1) {
    snprintf(lx->text, 512, "number too long");
    return (lx->sym = -1);
   }
   if(strchr("+-", lx->in[0])) {
    lx->text[i++] = *lx->in++;
    if(i == 512 - 1) {
     snprintf(lx->text, 512, "number too long");
     return (lx->sym = -1);
    }
   }
   while(((*__ctype_b_loc ())[(int) ((lx->in[0]))] & (unsigned short) _ISdigit)) {
    lx->text[i++] = *lx->in++;
    if(i == 512 - 1) {
     snprintf(lx->text, 512, "number too long");
     return (lx->sym = -1);
    }
   }
  }
  lx->text[i] = '\0';
 } else if(lx->in[0] == '"') {
  int i = 0;
  lx->in++;
  while(lx->in[0] != '"') {
   if(i == 512 - 1) {
    snprintf(lx->text, 512, "string literal too long");
    return (lx->sym = -1);
   }
   switch(lx->in[0]) {
    case '\0' : {
      snprintf(lx->text, 512, "unterminated string literal");
      return (lx->sym = -1);
     }
    case '\\' : {
      lx->in++;
      switch(lx->in[0]) {
       case '\0' : {
         snprintf(lx->text, 512, "unterminated string literal");
         return (lx->sym = -1);
        }
       case '/' : lx->text[i++] = '/'; break;
       case '\\' : lx->text[i++] = '\\'; break;
       case 'b' : lx->text[i++] = '\b'; break;
       case 'f' : lx->text[i++] = '\f'; break;
       case 'n' : lx->text[i++] = '\n'; break;
       case 'r' : lx->text[i++] = '\r'; break;
       case 't' : lx->text[i++] = '\t'; break;
       case '"' : lx->text[i++] = '"'; break;
       default: {
         snprintf(lx->text, 512, "bad escape sequence \\%c", lx->in[0]);
         return (lx->sym = -1);
        }
      }
     } break;
    default : {
      lx->text[i++] = lx->in[0];
      if(lx->in[0] == '\n') {
       lx->lineno++;
      }
     } break;
   }
   lx->in++;
  }
  lx->text[i] = '\0';
  lx->sym = 3;
  lx->in++;
 } else if(strchr(lx->opers, lx->in[0])) {
  return (lx->sym = *lx->in++);
 } else {
  snprintf(lx->text, 512, "Unexpected token '%c'", lx->in[0]);
  return (lx->sym = -1);
 }
 return lx->sym;
}


repo: wernsey/rengine

decompiled_code:
__int64 __fastcall lx_accept(__m128i *a1, int a2)
{
if ( a1->m128i_i32[2] != a2 )
return 0LL;
lx_getsym(a1);
return 1LL;
}

canonical_decompiled_code:
__int64 __fastcall func5(__m128i *a1, int a2)
{
if ( a1->m128i_i32[2] != a2 )
return 0LL;
func4(a1);
return 1LL;
}

original_code:
int lx_accept(struct lexer *lx, int sym) {
 if(lx->sym == sym) {
  lx_getsym(lx);
  return 1;
 }
 return 0;
}

variable_types: struct lexer { char *in; int sym; int lineno; char *opers; struct lx_keywords { char *word; int value; } *keywds; char text[512]; } *

variable_types: sym int

return_type: int

user_defined_types: struct lexer { char *in; int sym; int lineno; char *opers; struct lx_keywords *keywds; char text[512]; }


decompiled_code:
__int64 __fastcall lx_expect(__m128i *a1, int a2)
{
__int64 result; // rax
__m128i v3; // xmm0

result = lx_accept(a1, a2);
if ( (_DWORD)result )
return 1LL;
v3 = _mm_load_si128((const __m128i *)&LC8);
a1[3].m128i_i16[0] = 108;
a1[2] = v3;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func6(__m128i *a1, int a2)
{
__int64 result; // rax
__m128i v3; // xmm0

result = func5(a1, a2);
if ( (_DWORD)result )
return 1LL;
v3 = _mm_load_si128((const __m128i *)&LC8);
a1[3].m128i_i16[0] = 108;
a1[2] = v3;
return result;
}

original_code:
int lx_expect(struct lexer *lx, int sym) {
 if(lx_accept(lx, sym))
  return 1;
 snprintf(lx->text, 512, "unexpected symbol");
 return 0;
}

user_defined_types: struct lx_keywords { char *word; int value; }


decompiled_code:
__int64 __fastcall map_get_cell(__int64 a1, int a2, int a3)
{
return *(_QWORD *)(a1 + 16) + 32LL * (*(_DWORD *)(a1 + 4) * a3 + a2);
}

original_code:
struct map_cell *map_get_cell(struct map *m, int x, int y) {
 return &m->cells[y * m->nc + x];
}

variable_types: struct map { int nr; char dirty; int nl; struct map_cell *cells; struct tile_collection { int tw; struct tileset { struct bitmap { int w; unsigned char *data; unsigned int color; struct bitmap_font { char *type; int (*puts)(struct bitmap *b, int x, int y, char *text); void (*dtor)(struct bitmap_font *font); int (*width)(struct bitmap_font *font); int (*height)(struct bitmap_font *font); void *data; } *font; struct { int x0; int x1; } clip; } *bm; char *name; int border; int nmeta; struct tile_meta { int ti; char *clas; int flags; } *meta; } **tilesets; int ntilesets; } tiles; } *

variable_types: x int

variable_types: y int

return_type: struct map_cell { struct map_tile { short si; short ti; } *tiles; char *id; char *clas; int flags; } *

user_defined_types: struct map { int nr; char dirty; int nl; struct map_cell *cells; struct tile_collection tiles; }

user_defined_types: struct map_cell { struct map_tile *tiles; char *id; char *clas; int flags; }

user_defined_types: struct tile_collection { int tw; struct tileset **tilesets; int ntilesets; }

user_defined_types: struct tileset { struct bitmap *bm; char *name; int border; int nmeta; struct tile_meta *meta; }

user_defined_types: struct bitmap { int w; unsigned char *data; unsigned int color; struct bitmap_font *font; struct { int x0; int x1; } clip; }


original_code:
void map_free(struct map *m) {
 int i;
 if(!m) return;
 for(i = 0; i < m->nr * m->nc; i++) {
  free(m->cells[i].tiles);
  free(m->cells[i].id);
  free(m->cells[i].clas);
 }
 ts_deinit(&m->tiles);
 free(m->cells);
 free(m);
}

variable_types: struct map { int nr; char dirty; int nl; struct map_cell { struct map_tile { short si; short ti; } *tiles; char *id; char *clas; int flags; } *cells; struct tile_collection { int tw; struct tileset { struct bitmap { int w; unsigned char *data; unsigned int color; struct bitmap_font { char *type; int (*puts)(struct bitmap *b, int x, int y, char *text); void (*dtor)(struct bitmap_font *font); int (*width)(struct bitmap_font *font); int (*height)(struct bitmap_font *font); void *data; } *font; struct { int x0; int x1; } clip; } *bm; char *name; int border; int nmeta; struct tile_meta { int ti; char *clas; int flags; } *meta; } **tilesets; int ntilesets; } tiles; } *

variable_types: i int

return_type: void


decompiled_code:
__int64 __fastcall scancode_to_ascii(unsigned int a1, int a2, int a3, int a4)
{
__int64 result; // rax
unsigned int v5; // edi

if ( a1 - 4 > 0x19 )
{
if ( a1 - 89 <= 9 && a4 )
{
result = a1 - 40;
if ( a1 == 98 )
result = 48LL;
}
else
{
switch ( a1 )
{
case 0x1Eu:
result = a2 == 0 ? 49 : 33;
break;
case 0x1Fu:
result = a2 == 0 ? 50 : 64;
break;
case 0x20u:
result = a2 == 0 ? 51 : 35;
break;
case 0x21u:
result = a2 == 0 ? 52 : 36;
break;
case 0x22u:
result = a2 == 0 ? 53 : 37;
break;
case 0x23u:
result = a2 == 0 ? 54 : 94;
break;
case 0x24u:
result = a2 == 0 ? 55 : 38;
break;
case 0x25u:
result = a2 == 0 ? 56 : 42;
break;
case 0x26u:
result = a2 == 0 ? 57 : 40;
break;
case 0x27u:
result = a2 == 0 ? 48 : 41;
break;
case 0x28u:
case 0x58u:
result = 10LL;
break;
case 0x29u:
result = 27LL;
break;
case 0x2Au:
result = 8LL;
break;
case 0x2Bu:
result = 9LL;
break;
case 0x2Cu:
result = 32LL;
break;
case 0x2Du:
result = 95LL;
if ( !a2 )
result = a1;
break;
case 0x2Eu:
result = a2 == 0 ? 61 : 43;
break;
case 0x2Fu:
result = a2 == 0 ? 91 : 123;
break;
case 0x30u:
result = a2 == 0 ? 93 : 125;
break;
case 0x31u:
result = a2 == 0 ? 92 : 124;
break;
case 0x33u:
result = (unsigned int)(a2 == 0) + 58;
break;
case 0x34u:
result = a2 == 0 ? 39 : 34;
break;
case 0x35u:
result = a2 == 0 ? 96 : 126;
break;
case 0x36u:
result = a2 == 0 ? 44 : 60;
break;
case 0x37u:
result = a2 == 0 ? 46 : 62;
break;
case 0x38u:
result = a2 == 0 ? 47 : 63;
break;
case 0x4Cu:
result = 127LL;
break;
case 0x54u:
result = 47LL;
break;
case 0x55u:
result = 42LL;
break;
case 0x56u:
result = 45LL;
break;
case 0x57u:
result = 43LL;
break;
case 0x63u:
result = 46LL;
break;
default:
result = 0LL;
break;
}
}
}
else
{
result = a1 + 61;
v5 = a1 + 93;
if ( a2 == a3 )
result = v5;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func0(unsigned int a1, int a2, int a3, int a4)
{
__int64 result; // rax
unsigned int v5; // edi

if ( a1 - 4 > 0x19 )
{
if ( a1 - 89 <= 9 && a4 )
{
result = a1 - 40;
if ( a1 == 98 )
result = 48LL;
}
else
{
switch ( a1 )
{
case 0x1Eu:
result = a2 == 0 ? 49 : 33;
break;
case 0x1Fu:
result = a2 == 0 ? 50 : 64;
break;
case 0x20u:
result = a2 == 0 ? 51 : 35;
break;
case 0x21u:
result = a2 == 0 ? 52 : 36;
break;
case 0x22u:
result = a2 == 0 ? 53 : 37;
break;
case 0x23u:
result = a2 == 0 ? 54 : 94;
break;
case 0x24u:
result = a2 == 0 ? 55 : 38;
break;
case 0x25u:
result = a2 == 0 ? 56 : 42;
break;
case 0x26u:
result = a2 == 0 ? 57 : 40;
break;
case 0x27u:
result = a2 == 0 ? 48 : 41;
break;
case 0x28u:
case 0x58u:
result = 10LL;
break;
case 0x29u:
result = 27LL;
break;
case 0x2Au:
result = 8LL;
break;
case 0x2Bu:
result = 9LL;
break;
case 0x2Cu:
result = 32LL;
break;
case 0x2Du:
result = 95LL;
if ( !a2 )
result = a1;
break;
case 0x2Eu:
result = a2 == 0 ? 61 : 43;
break;
case 0x2Fu:
result = a2 == 0 ? 91 : 123;
break;
case 0x30u:
result = a2 == 0 ? 93 : 125;
break;
case 0x31u:
result = a2 == 0 ? 92 : 124;
break;
case 0x33u:
result = (unsigned int)(a2 == 0) + 58;
break;
case 0x34u:
result = a2 == 0 ? 39 : 34;
break;
case 0x35u:
result = a2 == 0 ? 96 : 126;
break;
case 0x36u:
result = a2 == 0 ? 44 : 60;
break;
case 0x37u:
result = a2 == 0 ? 46 : 62;
break;
case 0x38u:
result = a2 == 0 ? 47 : 63;
break;
case 0x4Cu:
result = 127LL;
break;
case 0x54u:
result = 47LL;
break;
case 0x55u:
result = 42LL;
break;
case 0x56u:
result = 45LL;
break;
case 0x57u:
result = 43LL;
break;
case 0x63u:
result = 46LL;
break;
default:
result = 0LL;
break;
}
}
}
else
{
result = a1 + 61;
v5 = a1 + 93;
if ( a2 == a3 )
result = v5;
}
return result;
}

original_code:
int scancode_to_ascii(int code, int shift, int caps, int numl) {
 if(code >= SDL_SCANCODE_A && code <= SDL_SCANCODE_Z) {
  if(shift ^ caps)
   return code - SDL_SCANCODE_A + 'A';
  return code - SDL_SCANCODE_A + 'a';
 }
    if(numl && code >= SDL_SCANCODE_KP_1 && code <= SDL_SCANCODE_KP_0) {
        if(code == SDL_SCANCODE_KP_0)
            return '0';
        return code - SDL_SCANCODE_KP_1 + '1';
    }
 switch(code) {
  case SDL_SCANCODE_1 : return shift?'!':'1';
  case SDL_SCANCODE_2 : return shift?'@':'2';
  case SDL_SCANCODE_3 : return shift?'#':'3';
  case SDL_SCANCODE_4 : return shift?'$':'4';
  case SDL_SCANCODE_5 : return shift?'%':'5';
  case SDL_SCANCODE_6 : return shift?'^':'6';
  case SDL_SCANCODE_7 : return shift?'&':'7';
  case SDL_SCANCODE_8 : return shift?'*':'8';
  case SDL_SCANCODE_9 : return shift?'(':'9';
  case SDL_SCANCODE_0 : return shift?')':'0';
  case SDL_SCANCODE_SLASH : return shift?'?':'/';
  case SDL_SCANCODE_SEMICOLON : return shift?':':';';
  case SDL_SCANCODE_LEFTBRACKET : return shift?'{':'[';
  case SDL_SCANCODE_RIGHTBRACKET : return shift?'}':']';
  case SDL_SCANCODE_COMMA : return shift?'<':',';
  case SDL_SCANCODE_PERIOD : return shift?'>':'.';
  case SDL_SCANCODE_MINUS : return shift?'_':'-';
  case SDL_SCANCODE_EQUALS : return shift?'+':'=';
  case SDL_SCANCODE_APOSTROPHE : return shift?'"':'\'';
  case SDL_SCANCODE_BACKSLASH : return shift?'|':'\\';
  case SDL_SCANCODE_GRAVE : return shift?'~':'`';
  case SDL_SCANCODE_SPACE : return ' ';
  case SDL_SCANCODE_RETURN :
  case SDL_SCANCODE_KP_ENTER : return '\n';
  case SDL_SCANCODE_TAB : return '\t';
  case SDL_SCANCODE_BACKSPACE : return '\b';
  case SDL_SCANCODE_DELETE : return 0x7F;
  case SDL_SCANCODE_ESCAPE : return 0x1B;
  case SDL_SCANCODE_KP_PLUS : return '+';
  case SDL_SCANCODE_KP_MINUS : return '-';
  case SDL_SCANCODE_KP_MULTIPLY : return '*';
  case SDL_SCANCODE_KP_DIVIDE : return '/';
  case SDL_SCANCODE_KP_PERIOD : return '.';
  default: return '\0';
 }
}

variable_types: code int

variable_types: shift int

variable_types: caps int

variable_types: numl int


relpath

decompiled_code:
char *__fastcall relpath(const char *a1, const char *a2, char *a3, size_t a4)
{
size_t v4; // rbx
char *v5; // r12
char *v6; // r14
char *v7; // r13
const char *v8; // r15
const char *v9; // rbp
size_t v10; // rdx
__int64 v12; // [rsp+0h] [rbp-48h] BYREF
char v13[64]; // [rsp+8h] [rbp-40h] BYREF

if ( a4 )
{
*a3 = 0;
v4 = a4;
v5 = a3;
v6 = strdup(a1);
v7 = strdup(a2);
v8 = (const char *)my_strtok_r(v6, &unk_170, &v12);
v9 = (const char *)my_strtok_r(v7, &unk_170, v13);
if ( v8 )
{
while ( v9 && !strcmp(v8, v9) )
{
v8 = (const char *)my_strtok_r(0LL, &unk_170, &v12);
v9 = (const char *)my_strtok_r(0LL, &unk_170, v13);
if ( !v8 )
goto LABEL_8;
}
do
{
v10 = v4 - 1;
v4 -= 3LL;
strncat(v5, "../", v10);
}
while ( my_strtok_r(0LL, &unk_170, &v12) );
}
LABEL_8:
while ( v9 )
{
strncat(v5, v9, v4 - 1);
v4 += ~strlen(v9);
strncat(v5, "/", v4);
v9 = (const char *)my_strtok_r(0LL, &unk_170, v13);
}
}
else
{
v7 = 0LL;
v6 = 0LL;
v5 = 0LL;
}
free(v6);
free(v7);
return v5;
}

canonical_decompiled_code:
char *__fastcall func0(const char *a1, const char *a2, char *a3, size_t a4)
{
size_t v4; // rbx
char *v5; // r12
char *v6; // r14
char *v7; // r13
const char *v8; // r15
const char *v9; // rbp
size_t v10; // rdx
__int64 v12; // [rsp+0h] [rbp-48h] BYREF
char v13[64]; // [rsp+8h] [rbp-40h] BYREF

if ( a4 )
{
*a3 = 0;
v4 = a4;
v5 = a3;
v6 = strdup(a1);
v7 = strdup(a2);
v8 = (const char *)my_strtok_r(v6, &unk_170, &v12);
v9 = (const char *)my_strtok_r(v7, &unk_170, v13);
if ( v8 )
{
while ( v9 && !strcmp(v8, v9) )
{
v8 = (const char *)my_strtok_r(0LL, &unk_170, &v12);
v9 = (const char *)my_strtok_r(0LL, &unk_170, v13);
if ( !v8 )
goto LABEL_8;
}
do
{
v10 = v4 - 1;
v4 -= 3LL;
strncat(v5, "../", v10);
}
while ( my_strtok_r(0LL, &unk_170, &v12) );
}
LABEL_8:
while ( v9 )
{
strncat(v5, v9, v4 - 1);
v4 += ~strlen(v9);
strncat(v5, "/", v4);
v9 = (const char *)my_strtok_r(0LL, &unk_170, v13);
}
}
else
{
v7 = 0LL;
v6 = 0LL;
v5 = 0LL;
}
free(v6);
free(v7);
return v5;
}

original_code:
char *relpath(const char *from, const char *to, char *rel, size_t rellen) {
 char *rv = ((void *)0);
 char *from_path = ((void *)0), *to_path = ((void *)0);
 char *from_start = ((void *)0), *to_start = ((void *)0);
 char *from_ptr, *to_ptr;
 if(rellen < 1)
  goto error;
 rel[0] = '\0';
 from_path = strdup(from);
 from_start = from_path;
 to_path = strdup(to);
 to_start = to_path;
 from_path = my_strtok_r(from_path, "\\/", &from_ptr);
 to_path = my_strtok_r(to_path, "\\/", &to_ptr);
 while(from_path && to_path && !strcmp(from_path, to_path)) {
  from_path = my_strtok_r(((void *)0), "\\/", &from_ptr);
  to_path = my_strtok_r(((void *)0), "\\/", &to_ptr);
 }
 while(from_path) {
  strncat(rel, "../", rellen - 1);
  rellen -= 3;
  from_path = my_strtok_r(((void *)0), "\\/", &from_ptr);
 }
 while(to_path) {
  strncat(rel, to_path, rellen - 1);
  rellen -= strlen(to_path);
  strncat(rel, "/", rellen - 1);
  rellen--;
  to_path = my_strtok_r(((void *)0), "\\/", &to_ptr);
 }
 rv = rel;
error:
 free(from_start);
 free(to_start);
 return rv;
}

canonical_original_code:
char *relpath(char *from, char *to, char *rel, unsigned long rellen) {
 char *rv = ((void *)0);
 char *from_path = ((void *)0); char *to_path = ((void *)0);
 char *from_start = ((void *)0); char *to_start = ((void *)0);
 char *from_ptr; char *to_ptr;
 if(rellen < 1)
  goto error;
 rel[0] = '\0';
 from_path = strdup(from);
 from_start = from_path;
 to_path = strdup(to);
 to_start = to_path;
 from_path = my_strtok_r(from_path, "\\/", &from_ptr);
 to_path = my_strtok_r(to_path, "\\/", &to_ptr);
 while(from_path && to_path && !strcmp(from_path, to_path)) {
  from_path = my_strtok_r(((void *)0), "\\/", &from_ptr);
  to_path = my_strtok_r(((void *)0), "\\/", &to_ptr);
 }
 while(from_path) {
  strncat(rel, "../", rellen - 1);
  rellen -= 3;
  from_path = my_strtok_r(((void *)0), "\\/", &from_ptr);
 }
 while(to_path) {
  strncat(rel, to_path, rellen - 1);
  rellen -= strlen(to_path);
  strncat(rel, "/", rellen - 1);
  rellen--;
  to_path = my_strtok_r(((void *)0), "\\/", &to_ptr);
 }
 rv = rel;
error:
 free(from_start);
 free(to_start);
 return rv;
}

variable_types:
from
char *

variable_types:
to
char *

variable_types:
rel
char *

variable_types:
rellen
unsigned long

variable_types:
rv
char *

return_type: char *


repo: wertarbyte/triggerhappy

decompiled_code:
__int64 __fastcall lookup_index(__int64 a1, const char *a2, int a3)
{
__int64 v4; // rbp
__int64 v5; // rbx
const char *v6; // rsi
unsigned int v7; // er13

v4 = a3 + 1;
v5 = 0LL;
while ( 1 )
{
v6 = *(const char **)(a1 + 8 * v5);
v7 = v5;
if ( v6 )
{
if ( !strcmp(a2, v6) )
break;
}
if ( ++v5 == v4 )
return (unsigned int)-1;
}
return v7;
}

canonical_decompiled_code:
__int64 __fastcall func0(__int64 a1, const char *a2, int a3)
{
__int64 v4; // rbp
__int64 v5; // rbx
const char *v6; // rsi
unsigned int v7; // er13

v4 = a3 + 1;
v5 = 0LL;
while ( 1 )
{
v6 = *(const char **)(a1 + 8 * v5);
v7 = v5;
if ( v6 )
{
if ( !strcmp(a2, v6) )
break;
}
if ( ++v5 == v4 )
return (unsigned int)-1;
}
return v7;
}

original_code:
static int lookup_index(const char **map, const char *value, int max) {
 int i = 0;
 while (i <= max) {
  if (map[i] != ((void *)0) &&
      strcmp(value, map[i]) == 0) {
   return i;
  }
  i++;
 }
 return -1;
}

canonical_original_code:
static int lookup_index(char **map, char *value, int max) {
 int i = 0;
 while (i <= max) {
  if (map[i] != ((void *)0) &&
      strcmp(value, map[i]) == 0) {
   return i;
  }
  i++;
 }
 return -1;
}

variable_types:
map
char **

variable_types:
value
char *

variable_types: max int


decompiled_code:
__int64 __fastcall lookup_event_name_i(int a1, int a2)
{
__int64 result; // rax

result = 0LL;
if ( a1 == 3 )
{
if ( a2 <= 63 )
result = ABS_NAME[a2];
}
else if ( a1 > 3 )
{
if ( a1 == 5 && a2 <= 16 )
result = SW_NAME[a2];
}
else if ( a1 == 1 )
{
if ( a2 <= 767 )
result = KEY_NAME[a2];
}
else if ( a1 == 2 && a2 <= 15 )
{
result = REL_NAME[a2];
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func1(int a1, int a2)
{
__int64 result; // rax

result = 0LL;
if ( a1 == 3 )
{
if ( a2 <= 63 )
result = ABS_NAME[a2];
}
else if ( a1 > 3 )
{
if ( a1 == 5 && a2 <= 16 )
result = SW_NAME[a2];
}
else if ( a1 == 1 )
{
if ( a2 <= 767 )
result = KEY_NAME[a2];
}
else if ( a1 == 2 && a2 <= 15 )
{
result = REL_NAME[a2];
}
return result;
}

original_code:
const char *lookup_event_name_i( const int evtype, const int evcode ) {
 switch(evtype) {
  case 0x01:
   return (0x2ff >= evcode ? KEY_NAME[ evcode ] : ((void *)0));
  case 0x05:
   return (0x10 >= evcode ? SW_NAME[ evcode ] : ((void *)0));
  case 0x02:
   return (0x0f >= evcode ? REL_NAME[ evcode ] : ((void *)0));
  case 0x03:
   return (0x3f >= evcode ? ABS_NAME[ evcode ] : ((void *)0));
  default:
   return ((void *)0);
 }
}

canonical_original_code:
char *lookup_event_name_i(int evtype, int evcode) {
 switch(evtype) {
  case 0x01:
   return (0x2ff >= evcode ? KEY_NAME[ evcode ] : ((void *)0));
  case 0x05:
   return (0x10 >= evcode ? SW_NAME[ evcode ] : ((void *)0));
  case 0x02:
   return (0x0f >= evcode ? REL_NAME[ evcode ] : ((void *)0));
  case 0x03:
   return (0x3f >= evcode ? ABS_NAME[ evcode ] : ((void *)0));
  default:
   return ((void *)0);
 }
}

variable_types: evtype int

variable_types: evcode int


decompiled_code:
__int64 __fastcall lookup_type_name_i(int a1)
{
__int64 result; // rax

result = 0LL;
if ( a1 <= 31 )
result = EV_NAME[a1];
return result;
}

canonical_decompiled_code:
__int64 __fastcall func3(int a1)
{
__int64 result; // rax

result = 0LL;
if ( a1 <= 31 )
result = EV_NAME[a1];
return result;
}

original_code:
const char *lookup_type_name_i( const int evtype ) {
 return (0x1f >= evtype ? EV_NAME[ evtype ] : ((void *)0));
}

canonical_original_code:
char *lookup_type_name_i(int evtype) {
 return (0x1f >= evtype ? EV_NAME[ evtype ] : ((void *)0));
}


decompiled_code:
__int64 __fastcall lookup_event_code(const char *a1)
{
__int64 result; // rax

result = lookup_index((__int64)KEY_NAME, a1, 767);
if ( (_DWORD)result == -1 )
{
result = lookup_index((__int64)SW_NAME, a1, 16);
if ( (_DWORD)result == -1 )
{
result = lookup_index((__int64)REL_NAME, a1, 15);
if ( (_DWORD)result == -1 )
result = lookup_index((__int64)ABS_NAME, a1, 63);
}
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func5(const char *a1)
{
__int64 result; // rax

result = func0((__int64)KEY_NAME, a1, 767);
if ( (_DWORD)result == -1 )
{
result = func0((__int64)SW_NAME, a1, 16);
if ( (_DWORD)result == -1 )
{
result = func0((__int64)REL_NAME, a1, 15);
if ( (_DWORD)result == -1 )
result = func0((__int64)ABS_NAME, a1, 63);
}
}
return result;
}

original_code:
int lookup_event_code( const char *eventname ) {
 int res = -1;
 if (res == -1) res = lookup_index(KEY_NAME, eventname, 0x2ff);
 if (res == -1) res = lookup_index(SW_NAME, eventname, 0x10);
 if (res == -1) res = lookup_index(REL_NAME, eventname, 0x0f);
 if (res == -1) res = lookup_index(ABS_NAME, eventname, 0x3f);
 return res;
}

canonical_original_code:
int lookup_event_code(char *eventname) {
 int res = -1;
 if (res == -1) res = lookup_index(KEY_NAME, eventname, 0x2ff);
 if (res == -1) res = lookup_index(SW_NAME, eventname, 0x10);
 if (res == -1) res = lookup_index(REL_NAME, eventname, 0x0f);
 if (res == -1) res = lookup_index(ABS_NAME, eventname, 0x3f);
 return res;
}

variable_types:
eventname
char *

variable_types: res int


decompiled_code:
__int64 __fastcall lookup_event_type(const char *a1)
{
int v1; // er8
__int64 result; // rax
int v3; // er8
int v4; // er8

v1 = lookup_index((__int64)KEY_NAME, a1, 767);
result = 1LL;
if ( v1 == -1 )
{
v3 = lookup_index((__int64)SW_NAME, a1, 16);
result = 5LL;
if ( v3 == -1 )
{
v4 = lookup_index((__int64)REL_NAME, a1, 15);
result = 2LL;
if ( v4 == -1 )
{
result = lookup_index((__int64)ABS_NAME, a1, 63);
if ( (_DWORD)result != -1 )
result = 3LL;
}
}
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func6(const char *a1)
{
int v1; // er8
__int64 result; // rax
int v3; // er8
int v4; // er8

v1 = func0((__int64)KEY_NAME, a1, 767);
result = 1LL;
if ( v1 == -1 )
{
v3 = func0((__int64)SW_NAME, a1, 16);
result = 5LL;
if ( v3 == -1 )
{
v4 = func0((__int64)REL_NAME, a1, 15);
result = 2LL;
if ( v4 == -1 )
{
result = func0((__int64)ABS_NAME, a1, 63);
if ( (_DWORD)result != -1 )
result = 3LL;
}
}
}
return result;
}

original_code:
int lookup_event_type( const char *eventname ) {
 if (lookup_index(KEY_NAME, eventname, 0x2ff) != -1) {
  return 0x01;
 }
 if (lookup_index(SW_NAME, eventname, 0x10) != -1) {
  return 0x05;
 }
 if (lookup_index(REL_NAME, eventname, 0x0f) != -1) {
  return 0x02;
 }
 if (lookup_index(ABS_NAME, eventname, 0x3f) != -1) {
  return 0x03;
 }
 return -1;
}

canonical_original_code:
int lookup_event_type(char *eventname) {
 if (lookup_index(KEY_NAME, eventname, 0x2ff) != -1) {
  return 0x01;
 }
 if (lookup_index(SW_NAME, eventname, 0x10) != -1) {
  return 0x05;
 }
 if (lookup_index(REL_NAME, eventname, 0x0f) != -1) {
  return 0x02;
 }
 if (lookup_index(ABS_NAME, eventname, 0x3f) != -1) {
  return 0x03;
 }
 return -1;
}


decompiled_code:
__int64 __fastcall bind_cmdsocket(char *name)
{
unsigned int v1; // er12
char *v2; // rax
__int64 result; // rax
struct sockaddr v4[7]; // [rsp+0h] [rbp-118h] BYREF
struct stat v5; // [rsp+70h] [rbp-A8h] BYREF

if ( (unsigned int)sd_listen_fds(0LL) == 1 )
{
fwrite("<7>Found socket passed from systemd\n", 1uLL, 0x24uLL, stderr);
result = 3LL;
}
else
{
if ( !stat(name, &v5) && (v5.st_mode & 0xF000) == 49152 )
unlink(name);
v1 = socket(1, 2, 0);
v2 = stpcpy(v4[0].sa_data, name);
v4[0].sa_family = 1;
bind(v1, v4, v2 - v4[0].sa_data + 2);
result = v1;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func0(char *name)
{
unsigned int v1; // er12
char *v2; // rax
__int64 result; // rax
struct sockaddr v4[7]; // [rsp+0h] [rbp-118h] BYREF
struct stat v5; // [rsp+70h] [rbp-A8h] BYREF

if ( (unsigned int)sd_listen_fds(0LL) == 1 )
{
fwrite("<7>Found socket passed from systemd\n", 1uLL, 0x24uLL, stderr);
result = 3LL;
}
else
{
if ( !stat(name, &v5) && (v5.st_mode & 0xF000) == 49152 )
unlink(name);
v1 = socket(1, 2, 0);
v2 = stpcpy(v4[0].sa_data, name);
v4[0].sa_family = 1;
bind(v1, v4, v2 - v4[0].sa_data + 2);
result = v1;
}
return result;
}

original_code:
int bind_cmdsocket( char *name ) {
 int cmd_fd;
 if (sd_listen_fds(0) == 1) {
  fprintf(stderr, "<7>" "Found socket passed from systemd\n");
  return 3 + 0;
 }
 struct sockaddr_un addr;
 struct stat sb;
 int serr = stat(name, &sb);
 if ( !serr && ((((sb.st_mode)) & 0170000) == (0140000))) {
  unlink(name);
 }
 cmd_fd = socket(1, SOCK_DGRAM, 0);
 strcpy(addr.sun_path, name);
 addr.sun_family = 1;
 bind (cmd_fd, (struct sockaddr *) &addr,
  strlen(addr.sun_path) + sizeof (addr.sun_family));
 return cmd_fd;
}

canonical_original_code:
int bind_cmdsocket(char *name) {
 int cmd_fd;
 if (sd_listen_fds(0) == 1) {
  fprintf(stderr, "<7>" "Found socket passed from systemd\n");
  return 3 + 0;
 }
 struct sockaddr_un addr;
 struct stat sb;
 int serr = stat(name, &sb);
 if ( !serr && ((((sb.st_mode)) & 0170000) == (0140000))) {
  unlink(name);
 }
 cmd_fd = socket(1, SOCK_DGRAM, 0);
 strcpy(addr.sun_path, name);
 addr.sun_family = 1;
 bind (cmd_fd, (struct sockaddr *) &addr,
  strlen(addr.sun_path) + sizeof (addr.sun_family));
 return cmd_fd;
}

variable_types:
name
char *

variable_types: struct sockaddr_un { unsigned short sun_family; char sun_path[108]; }

variable_types: struct stat { unsigned long st_dev; unsigned long st_ino; unsigned long st_nlink; unsigned int st_mode; unsigned int st_uid; unsigned int st_gid; int __pad0; unsigned long st_rdev; long st_size; long st_blksize; long st_blocks; struct timespec { long tv_sec; long tv_nsec; } st_atim; struct timespec st_mtim; struct timespec st_ctim; long __glibc_reserved[3]; }

variable_types: serr int

user_defined_types: struct stat { unsigned long st_dev; unsigned long st_ino; unsigned long st_nlink; unsigned int st_mode; unsigned int st_uid; unsigned int st_gid; int __pad0; unsigned long st_rdev; long st_size; long st_blksize; long st_blocks; struct timespec st_atim; struct timespec st_mtim; struct timespec st_ctim; long __glibc_reserved[3]; }

user_defined_types: struct sockaddr { unsigned short sa_family; char sa_data[14]; }


decompiled_code:
__int64 __fastcall connect_cmdsocket(char *src)
{
unsigned int v1; // er12
char *v2; // rax
struct sockaddr v4[8]; // [rsp+0h] [rbp-88h] BYREF

v1 = socket(1, 2, 0);
v2 = stpcpy(v4[0].sa_data, src);
v4[0].sa_family = 1;
connect(v1, v4, v2 - v4[0].sa_data + 2);
return v1;
}

canonical_decompiled_code:
__int64 __fastcall func1(char *src)
{
unsigned int v1; // er12
char *v2; // rax
struct sockaddr v4[8]; // [rsp+0h] [rbp-88h] BYREF

v1 = socket(1, 2, 0);
v2 = stpcpy(v4[0].sa_data, src);
v4[0].sa_family = 1;
connect(v1, v4, v2 - v4[0].sa_data + 2);
return v1;
}

original_code:
int connect_cmdsocket( char *name ) {
 int fd;
 struct sockaddr_un server;
 fd = socket(1, SOCK_DGRAM, 0);
 strcpy(server.sun_path, name);
 server.sun_family = 1;
 connect(fd, (struct sockaddr *) &server,
  strlen(server.sun_path) + sizeof (server.sun_family));
 return fd;
}

canonical_original_code:
int connect_cmdsocket(char *name) {
 int fd;
 struct sockaddr_un server;
 fd = socket(1, SOCK_DGRAM, 0);
 strcpy(server.sun_path, name);
 server.sun_family = 1;
 connect(fd, (struct sockaddr *) &server,
  strlen(server.sun_path) + sizeof (server.sun_family));
 return fd;
}

variable_types: fd int

user_defined_types: struct sockaddr_un { unsigned short sun_family; char sun_path[108]; }


original_code:
int send_command( int cmd_fd, enum command_type type, char *param, int passfd, int exclusive, char *tag ) {
 if (type == CMD_ADD && passfd == 1) {
  type = CMD_PASSFD;
 }
 struct command cmd = {
  .fd = -1,
  .exclusive = exclusive,
  .type = type,
  .param = {0},
  .tag = {0}
 };
 if (param != ((void *)0)) {
  strncpy(cmd.param, param, 256);
  cmd.param[256 -1] = '\0';
 }
 if (tag != ((void *)0)) {
  strncpy(cmd.tag, tag, 256);
  cmd.tag[256 -1] = '\0';
 }
 struct iovec v = {
  .iov_base = &cmd,
  .iov_len = sizeof(cmd)
 };
 struct msghdr m = {
  .msg_iov = &v,
  .msg_iovlen = 1
 };
 int dev_fd[1] = { -1 };
 char buffer[((((sizeof(dev_fd)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)))];
 if (passfd) {
  int fd = open( param, 00 );
  if (fd < 0) {
   perror("open");
   return 1;
  }
  dev_fd[0] = fd ;
  m.msg_control = buffer;
  m.msg_controllen = sizeof(buffer);
  struct cmsghdr *cmessage = ((size_t) (&m)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (&m)->msg_control : (struct cmsghdr *) 0);
  cmessage->cmsg_level = 1;
  cmessage->cmsg_type = SCM_RIGHTS;
  cmessage->cmsg_len = ((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) + (sizeof(dev_fd)));
  m.msg_controllen = cmessage->cmsg_len;
  memcpy(((cmessage)->__cmsg_data), dev_fd, sizeof dev_fd);
 }
 int done = sendmsg( cmd_fd, &m, 0 );
 return (done == -1);
}

canonical_original_code:
int send_command(int cmd_fd, enum command_type type, char *param, int passfd, int exclusive, char *tag) {
 if (type == CMD_ADD && passfd == 1) {
  type = CMD_PASSFD;
 }
 struct command cmd = {
  .fd = -1,
  .exclusive = exclusive,
  .type = type,
  .param = {0},
  .tag = {0}
 };
 if (param != ((void *)0)) {
  strncpy(cmd.param, param, 256);
  cmd.param[256 -1] = '\0';
 }
 if (tag != ((void *)0)) {
  strncpy(cmd.tag, tag, 256);
  cmd.tag[256 -1] = '\0';
 }
 struct iovec v = {
  .iov_base = &cmd,
  .iov_len = sizeof(cmd)
 };
 struct msghdr m = {
  .msg_iov = &v,
  .msg_iovlen = 1
 };
 int dev_fd[1] = { -1 };
 char buffer[-1];
 if (passfd) {
  int fd = open( param, 00 );
  if (fd < 0) {
   perror("open");
   return 1;
  }
  dev_fd[0] = fd ;
  m.msg_control = buffer;
  m.msg_controllen = sizeof(buffer);
  struct cmsghdr *cmessage = ((size_t) (&m)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (&m)->msg_control : (struct cmsghdr *) 0);
  cmessage->cmsg_level = 1;
  cmessage->cmsg_type = SCM_RIGHTS;
  cmessage->cmsg_len = ((((sizeof (struct cmsghdr)) + sizeof (unsigned long) - 1) & (unsigned long) ~(sizeof (unsigned long) - 1)) + (sizeof(dev_fd)));
  m.msg_controllen = cmessage->cmsg_len;
  memcpy(((cmessage)->__cmsg_data), dev_fd, sizeof dev_fd);
 }
 int done = sendmsg( cmd_fd, &m, 0 );
 return (done == -1);
}

variable_types:
param
char *

variable_types: passfd int

variable_types: exclusive int

variable_types:
tag
char *

variable_types: struct command { enum command_type { CMD_NOP=0, CMD_ADD=1, CMD_REMOVE=2, CMD_QUIT=3, CMD_DISABLE=4, CMD_ENABLE=5, CMD_PASSFD=6, CMD_CLEARDEVS=7, CMD_CHANGEMODE=8 } type; char param[256]; int fd; int exclusive; char tag[256]; }

variable_types: struct msghdr { void *msg_name; unsigned int msg_namelen; struct iovec { void *iov_base; unsigned long iov_len; } *msg_iov; unsigned long msg_iovlen; void *msg_control; unsigned long msg_controllen; int msg_flags; }

variable_types:
buffer
char [-1]

variable_types: struct cmsghdr { unsigned long cmsg_len; int cmsg_level; int cmsg_type; unsigned char __cmsg_data[]; } *

variable_types: done int

user_defined_types: struct command { enum command_type type; char param[256]; int fd; int exclusive; char tag[256]; }

user_defined_types: struct msghdr { void *msg_name; unsigned int msg_namelen; struct iovec *msg_iov; unsigned long msg_iovlen; void *msg_control; unsigned long msg_controllen; int msg_flags; }


decompiled_code:
__int64 __fastcall add_device_to_fdset(int *a1)
{
int v1; // ecx
__int64 result; // rax

v1 = *a1;
if ( max_fd < *a1 )
max_fd = *a1;
result = v1 / 64;
rfds.fds_bits[result] |= 1LL << (v1 % 64);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func0(int *a1)
{
int v1; // ecx
__int64 result; // rax

v1 = *a1;
if ( max_fd < *a1 )
max_fd = *a1;
result = v1 / 64;
rfds.fds_bits[result] |= 1LL << (v1 % 64);
return result;
}

original_code:
static void add_device_to_fdset( device *d ) {
 int fd = d->fd;
 if (fd > max_fd) {
  max_fd = fd;
 }
 ((void) (((&rfds)->__fds_bits)[((fd) / (8 * (int) sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((fd) % (8 * (int) sizeof (__fd_mask)))))));
}

canonical_original_code:
static void add_device_to_fdset(struct device *d) {
 int fd = d->fd;
 if (fd > max_fd) {
  max_fd = fd;
 }
 ((void) (((&rfds)->__fds_bits)[((fd) / (8 * (int) sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((fd) % (8 * (int) sizeof (__fd_mask)))))));
}

variable_types: struct device { int fd; char *devname; int exclusive; char tag[256]; struct device *next; } *


decompiled_code:
void __fastcall handle_signal(int a1)
{
if ( a1 == 2 || a1 == 15 )
{
exiting = 1;
}
else if ( a1 == 1 )
{
reload_conf = 1;
}
}

canonical_decompiled_code:
void __fastcall func1(int a1)
{
if ( a1 == 2 || a1 == 15 )
{
exiting = 1;
}
else if ( a1 == 1 )
{
reload_conf = 1;
}
}

original_code:
static void handle_signal(int sig) {
 switch (sig) {
  case 2:
  case 15:
   exiting = 1;
   break;
  case 1:
   reload_conf = 1;
   break;
 }
}

variable_types: sig int


decompiled_code:
__int64 process_devices()
{
return for_each_device(check_device);
}

canonical_decompiled_code:
__int64 func2()
{
return for_each_device(check_device);
}

original_code:
static void process_devices(void) {
 for_each_device( &check_device );
}

canonical_original_code:
static void process_devices() {
 for_each_device( &check_device );
}


decompiled_code:
__int64 reload_triggerfile()
{
clear_triggers();
if ( !triggerfile || !(unsigned int)read_triggers() )
return 0LL;
fprintf(stderr, "Error loading triggerfile '%s'\n", (const char *)triggerfile);
return 1LL;
}

canonical_decompiled_code:
__int64 func3()
{
clear_triggers();
if ( !triggerfile || !(unsigned int)read_triggers() )
return 0LL;
fprintf(stderr, "Error loading triggerfile '%s'\n", (const char *)triggerfile);
return 1LL;
}

original_code:
static int reload_triggerfile(void) {
 clear_triggers();
 if (triggerfile) {
  int err = read_triggers(triggerfile);
  if (err) {
   fprintf(stderr, "Error loading triggerfile '%s'\n", triggerfile);
   return 1;
  }
 }
 return 0;
}

canonical_original_code:
static int reload_triggerfile() {
 clear_triggers();
 if (triggerfile) {
  int err = read_triggers(triggerfile);
  if (err) {
   fprintf(stderr, "Error loading triggerfile '%s'\n", triggerfile);
   return 1;
  }
 }
 return 0;
}

variable_types: err int


decompiled_code:
int process_events()
{
int *v0; // rax
int v1; // edi
int v2; // ebp
void *v3; // rbp
struct timeval v5; // [rsp+0h] [rbp-28h] BYREF

while ( 1 )
{
LODWORD(v0) = count_devices();
if ( (int)v0 <= 0 && cmd_fd == -1 )
break;
memset(&rfds, 0, sizeof(rfds));
max_fd = -1;
for_each_device(add_device_to_fdset);
v1 = cmd_fd;
if ( cmd_fd == -1 )
{
v1 = max_fd;
}
else
{
rfds.fds_bits[cmd_fd / 64] |= 1LL << (cmd_fd % 64);
if ( max_fd >= v1 )
v1 = max_fd;
max_fd = v1;
}
v5.tv_sec = 5LL;
v5.tv_usec = 0LL;
LODWORD(v0) = select(v1 + 1, &rfds, 0LL, 0LL, &v5);
v2 = (int)v0;
if ( (_DWORD)v0 != -1 || (v0 = _errno_location(), *v0 == 4) )
{
if ( exiting )
return (int)v0;
if ( reload_conf )
{
reload_conf = 0;
reload_triggerfile();
}
else if ( v2 )
{
process_devices();
if ( cmd_fd != -1 && (rfds.fds_bits[cmd_fd / 64] & (1LL << (cmd_fd % 64))) != 0 )
{
v3 = (void *)read_command();
obey_command(v3);
free(v3);
}
}
}
else
{
perror("select()");
}
}
return (int)v0;
}

canonical_decompiled_code:
int func4()
{
int *v0; // rax
int v1; // edi
int v2; // ebp
void *v3; // rbp
struct timeval v5; // [rsp+0h] [rbp-28h] BYREF

while ( 1 )
{
LODWORD(v0) = count_devices();
if ( (int)v0 <= 0 && cmd_fd == -1 )
break;
memset(&rfds, 0, sizeof(rfds));
max_fd = -1;
for_each_device(add_device_to_fdset);
v1 = cmd_fd;
if ( cmd_fd == -1 )
{
v1 = max_fd;
}
else
{
rfds.fds_bits[cmd_fd / 64] |= 1LL << (cmd_fd % 64);
if ( max_fd >= v1 )
v1 = max_fd;
max_fd = v1;
}
v5.tv_sec = 5LL;
v5.tv_usec = 0LL;
LODWORD(v0) = select(v1 + 1, &rfds, 0LL, 0LL, &v5);
v2 = (int)v0;
if ( (_DWORD)v0 != -1 || (v0 = _errno_location(), *v0 == 4) )
{
if ( exiting )
return (int)v0;
if ( reload_conf )
{
reload_conf = 0;
func3();
}
else if ( v2 )
{
func2();
if ( cmd_fd != -1 && (rfds.fds_bits[cmd_fd / 64] & (1LL << (cmd_fd % 64))) != 0 )
{
v3 = (void *)read_command();
obey_command(v3);
free(v3);
}
}
}
else
{
perror("select()");
}
}
return (int)v0;
}

original_code:
static void process_events(void) {
 struct timeval tv;
 int retval;
 while ( count_devices() > 0 || cmd_fd != -1 ) {
  do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&rfds)->__fds_bits)[0]) : "memory"); } while (0);
  max_fd = -1;
  for_each_device( &add_device_to_fdset );
  if (cmd_fd != -1) {
   ((void) (((&rfds)->__fds_bits)[((cmd_fd) / (8 * (int) sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((cmd_fd) % (8 * (int) sizeof (__fd_mask)))))));
   max_fd = cmd_fd > max_fd ? cmd_fd : max_fd;
  }
  tv.tv_sec = 5;
  tv.tv_usec = 0;
  retval = select(max_fd+1, &rfds, ((void *)0), ((void *)0), &tv);
  if (retval == -1 && (*__errno_location ()) != 4) {
   perror("select()");
   continue;
  } else if (exiting) {
   break;
  } else if (reload_conf) {
   reload_conf = 0;
   reload_triggerfile();
   continue;
  } else if (retval) {
   process_devices();
   if ( cmd_fd != -1 && ((((&rfds)->__fds_bits)[((cmd_fd) / (8 * (int) sizeof (__fd_mask)))] & ((__fd_mask) (1UL << ((cmd_fd) % (8 * (int) sizeof (__fd_mask)))))) != 0) ) {
    struct command *cmd = read_command( cmd_fd );
    obey_command( cmd );
    free(cmd);
   }
  }
 }
}

canonical_original_code:
static void process_events() {
 struct timeval tv;
 int retval;
 while ( count_devices() > 0 || cmd_fd != -1 ) {
  do { int __d0; int __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&rfds)->__fds_bits)[0]) : "memory"); } while (0);
  max_fd = -1;
  for_each_device( &add_device_to_fdset );
  if (cmd_fd != -1) {
   ((void) (((&rfds)->__fds_bits)[((cmd_fd) / (8 * (int) sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((cmd_fd) % (8 * (int) sizeof (__fd_mask)))))));
   max_fd = cmd_fd > max_fd ? cmd_fd : max_fd;
  }
  tv.tv_sec = 5;
  tv.tv_usec = 0;
  retval = select(max_fd+1, &rfds, ((void *)0), ((void *)0), &tv);
  if (retval == -1 && (*__errno_location ()) != 4) {
   perror("select()");
   continue;
  } else if (exiting) {
   break;
  } else if (reload_conf) {
   reload_conf = 0;
   reload_triggerfile();
   continue;
  } else if (retval) {
   process_devices();
   if ( cmd_fd != -1 && ((((&rfds)->__fds_bits)[((cmd_fd) / (8 * (int) sizeof (__fd_mask)))] & ((__fd_mask) (1UL << ((cmd_fd) % (8 * (int) sizeof (__fd_mask)))))) != 0) ) {
    struct command *cmd = read_command( cmd_fd );
    obey_command( cmd );
    free(cmd);
   }
  }
 }
}

variable_types: struct timeval { long tv_sec; long tv_usec; }

variable_types: retval int

variable_types: struct command { enum command_type { CMD_NOP=0, CMD_ADD=1, CMD_REMOVE=2, CMD_QUIT=3, CMD_DISABLE=4, CMD_ENABLE=5, CMD_PASSFD=6, CMD_CLEARDEVS=7, CMD_CHANGEMODE=8 } type; char param[256]; int fd; int exclusive; char tag[256]; } *


decompiled_code:
__int64 __fastcall check_device(__int64 a1)
{
int v1; // eax
__int64 result; // rax

v1 = *(_DWORD *)a1 + 63;
if ( *(int *)a1 >= 0 )
v1 = *(_DWORD *)a1;
result = v1 >> 6;
if ( (rfds.fds_bits[result] & (1LL << (*(_DWORD *)a1 % 64))) != 0 )
{
result = read_event(a1);
if ( (_DWORD)result )
result = remove_device(*(_QWORD *)(a1 + 8));
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func8(__int64 a1)
{
int v1; // eax
__int64 result; // rax

v1 = *(_DWORD *)a1 + 63;
if ( *(int *)a1 >= 0 )
v1 = *(_DWORD *)a1;
result = v1 >> 6;
if ( (rfds.fds_bits[result] & (1LL << (*(_DWORD *)a1 % 64))) != 0 )
{
result = func7(a1);
if ( (_DWORD)result )
result = remove_device(*(_QWORD *)(a1 + 8));
}
return result;
}

original_code:
static void check_device( device *d ) {
 int fd = d->fd;
 if (((((&rfds)->__fds_bits)[((fd) / (8 * (int) sizeof (__fd_mask)))] & ((__fd_mask) (1UL << ((fd) % (8 * (int) sizeof (__fd_mask)))))) != 0)) {
  if (read_event( d )) {
   remove_device( d->devname );
  }
 }
}

canonical_original_code:
static void check_device(struct device *d) {
 int fd = d->fd;
 if (((((&rfds)->__fds_bits)[((fd) / (8 * (int) sizeof (__fd_mask)))] & ((__fd_mask) (1UL << ((fd) % (8 * (int) sizeof (__fd_mask)))))) != 0)) {
  if (read_event( d )) {
   remove_device( d->devname );
  }
 }
}

user_defined_types: struct device { int fd; char *devname; int exclusive; char tag[256]; struct device *next; }


decompiled_code:
int __fastcall list_event_table(unsigned int a1, int a2)
{
unsigned int v2; // ebx
const char *v3; // rax

v2 = 0;
do
{
v3 = (const char *)lookup_event_name_i(a1, v2);
if ( v3 )
LODWORD(v3) = puts(v3);
++v2;
}
while ( v2 != a2 + 1 );
return (int)v3;
}

canonical_decompiled_code:
int __fastcall func9(unsigned int a1, int a2)
{
unsigned int v2; // ebx
const char *v3; // rax

v2 = 0;
do
{
v3 = (const char *)lookup_event_name_i(a1, v2);
if ( v3 )
LODWORD(v3) = puts(v3);
++v2;
}
while ( v2 != a2 + 1 );
return (int)v3;
}

original_code:
static void list_event_table(int type, int max) {
 int n = 0;
 for (n = 0; n <= max; n++) {
  const char *name = lookup_event_name_i(type, n);
  if (name) {
   printf("%s\n", name);
  }
 }
}

canonical_original_code:
static void list_event_table(int type, int max) {
 int n = 0;
 for (n = 0; n <= max; n++) {
  char *name = lookup_event_name_i(type, n);
  if (name) {
   printf("%s\n", name);
  }
 }
}

variable_types: type int

variable_types: max int

variable_types: n int

variable_types:
name
char *


decompiled_code:
int list_events()
{
list_event_table(1u, 767);
list_event_table(5u, 16);
list_event_table(2u, 15);
return list_event_table(3u, 15);
}

original_code:
static void list_events(void) {
 list_event_table(0x01, 0x2ff);
 list_event_table(0x05, 0x10);
 list_event_table(0x02, 0x0f);
 list_event_table(0x03, 0x0f);
}

canonical_original_code:
static void list_events() {
 list_event_table(0x01, 0x2ff);
 list_event_table(0x05, 0x10);
 list_event_table(0x02, 0x0f);
 list_event_table(0x03, 0x0f);
}


cleanup

decompiled_code:
int cleanup()
{
const char *v0; // rdi
int result; // eax

close_uinput();
v0 = cmd_file;
if ( cmd_file )
{
if ( cmd_fd != -1 )
{
close(cmd_fd);
v0 = cmd_file;
}
unlink(v0);
cmd_fd = -1;
}
result = clear_devices();
if ( pidfile )
result = unlink(pidfile);
return result;
}

canonical_decompiled_code:
int func13()
{
const char *v0; // rdi
int result; // eax

close_uinput();
v0 = cmd_file;
if ( cmd_file )
{
if ( cmd_fd != -1 )
{
close(cmd_fd);
v0 = cmd_file;
}
unlink(v0);
cmd_fd = -1;
}
result = clear_devices();
if ( pidfile )
result = unlink(pidfile);
return result;
}

original_code:
void cleanup(void) {
 close_uinput();
 if (cmd_file) {
  if (cmd_fd != -1) {
   close( cmd_fd );
  }
  unlink(cmd_file);
  cmd_fd = -1;
 }
 clear_devices();
 if (pidfile) {
  unlink(pidfile);
 }
}

canonical_original_code:
void cleanup() {
 close_uinput();
 if (cmd_file) {
  if (cmd_fd != -1) {
   close( cmd_fd );
  }
  unlink(cmd_file);
  cmd_fd = -1;
 }
 clear_devices();
 if (pidfile) {
  unlink(pidfile);
 }
}


decompiled_code:
__int64 __fastcall start_readers(int a1, __int64 a2, int a3, const char *a4)
{
int v6; // eax
unsigned int v7; // er8
__int64 *v8; // rbx
unsigned __int64 v9; // rbp
__int64 v10; // rdi
size_t i; // rbx
char *v12; // rdi
struct passwd *v13; // rax
__gid_t v14; // ebp
__uid_t v15; // er12
__int64 result; // rax
glob_t v17; // [rsp+0h] [rbp-78h] BYREF

if ( a1 - a3 <= 0 && !((unsigned __int64)cmd_file | (unsigned __int64)a4) )
{
fwrite("No input device files or command pipe specified.\n", 1uLL, 0x31uLL, stderr);
return 1;
}
if ( cmd_file )
{
v6 = bind_cmdsocket(cmd_file);
v7 = 1;
cmd_fd = v6;
if ( v6 < 0 )
return v7;
}
if ( a1 > a3 )
{
v8 = (__int64 *)(a2 + 8LL * a3);
v9 = a2 + 8 * (a3 + (unsigned __int64)(unsigned int)(a1 - a3 - 1)) + 8;
do
{
v10 = *v8++;
add_device(v10, 0xFFFFFFFFLL, 0LL, 0LL);
}
while ( (__int64 *)v9 != v8 );
}
if ( a4 )
{
glob(a4, 4, 0LL, &v17);
for ( i = 0LL; v17.gl_pathc > i; ++i )
{
v12 = v17.gl_pathv[i];
add_device(v12, 0xFFFFFFFFLL, 0LL, 0LL);
}
}
if ( run_as_daemon && daemon(0, 0) )
perror("daemon()");
if ( pidfile )
write_pidfile_isra_0(pidfile);
if ( !user )
{
LABEL_18:
sd_notify(0LL, "READY=1");
process_events();
return 0;
}
v13 = getpwnam(user);
if ( v13 )
{
v14 = v13->pw_gid;
v15 = v13->pw_uid;
if ( initgroups(user, v14) )
{
perror("initgroups");
result = 1LL;
}
else
{
if ( !setregid(v14, v14) )
{
if ( setreuid(v15, v15) )
{
perror("setreuid");
return 1;
}
goto LABEL_18;
}
perror("setregid");
result = 1LL;
}
}
else
{
fprintf(stderr, "Unable to lookup user '%s'.\n", user);
result = 1LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func14(int a1, __int64 a2, int a3, const char *a4)
{
int v6; // eax
unsigned int v7; // er8
__int64 *v8; // rbx
unsigned __int64 v9; // rbp
__int64 v10; // rdi
size_t i; // rbx
char *v12; // rdi
struct passwd *v13; // rax
__gid_t v14; // ebp
__uid_t v15; // er12
__int64 result; // rax
glob_t v17; // [rsp+0h] [rbp-78h] BYREF

if ( a1 - a3 <= 0 && !((unsigned __int64)cmd_file | (unsigned __int64)a4) )
{
fwrite("No input device files or command pipe specified.\n", 1uLL, 0x31uLL, stderr);
return 1;
}
if ( cmd_file )
{
v6 = bind_cmdsocket(cmd_file);
v7 = 1;
cmd_fd = v6;
if ( v6 < 0 )
return v7;
}
if ( a1 > a3 )
{
v8 = (__int64 *)(a2 + 8LL * a3);
v9 = a2 + 8 * (a3 + (unsigned __int64)(unsigned int)(a1 - a3 - 1)) + 8;
do
{
v10 = *v8++;
add_device(v10, 0xFFFFFFFFLL, 0LL, 0LL);
}
while ( (__int64 *)v9 != v8 );
}
if ( a4 )
{
glob(a4, 4, 0LL, &v17);
for ( i = 0LL; v17.gl_pathc > i; ++i )
{
v12 = v17.gl_pathv[i];
add_device(v12, 0xFFFFFFFFLL, 0LL, 0LL);
}
}
if ( run_as_daemon && daemon(0, 0) )
perror("daemon()");
if ( pidfile )
func11(pidfile);
if ( !user )
{
LABEL_18:
sd_notify(0LL, "READY=1");
func4();
return 0;
}
v13 = getpwnam(user);
if ( v13 )
{
v14 = v13->pw_gid;
v15 = v13->pw_uid;
if ( initgroups(user, v14) )
{
perror("initgroups");
result = 1LL;
}
else
{
if ( !setregid(v14, v14) )
{
if ( setreuid(v15, v15) )
{
perror("setreuid");
return 1;
}
goto LABEL_18;
}
perror("setregid");
result = 1LL;
}
}
else
{
fprintf(stderr, "Unable to lookup user '%s'.\n", user);
result = 1LL;
}
return result;
}

original_code:
int start_readers(int argc, char *argv[], int start, char *dev_glob) {
 if (argc-start < 1 && cmd_file == ((void *)0) && dev_glob == ((void *)0)) {
  fprintf(stderr, "No input device files or command pipe specified.\n");
  return 1;
 }
 if (cmd_file) {
  cmd_fd = bind_cmdsocket(cmd_file);
  if (cmd_fd < 0) {
   return 1;
  }
 }
 int i;
 for (i=start; i<argc; i++) {
  char *dev = argv[i];
  int grab_dev = 0;
  char *tag_dev = ((void *)0);
  add_device( dev, -1, grab_dev, tag_dev );
 }
 if (dev_glob) {
  glob_t globbuf;
  glob(dev_glob, (1 << 2), ((void *)0), &globbuf);
  for (i=0; i<globbuf.gl_pathc; i++) {
   int grab_dev = 0;
   char *tag_dev = ((void *)0);
   add_device(globbuf.gl_pathv[i], -1, grab_dev, tag_dev);
  }
 }
 if (run_as_daemon) {
  int err = daemon(0,0);
  if (err) {
   perror("daemon()");
  }
 }
 if (pidfile) {
  write_pidfile( pidfile );
 }
 if (user) {
  struct passwd *pw = getpwnam(user);
  if (pw) {
   int uid = pw->pw_uid;
   int gid = pw->pw_gid;
   if ( initgroups(user, gid) ) {
    perror("initgroups");
    return 1;
   }
   if ( setregid( gid, gid ) ) {
    perror("setregid");
    return 1;
   }
   if ( setreuid( uid, uid ) ) {
    perror("setreuid");
    return 1;
   }
  } else {
   fprintf(stderr, "Unable to lookup user '%s'.\n", user);
   return 1;
  }
 }
 sd_notify(0, "READY=1");
 process_events();
 return 0;
}

canonical_original_code:
int start_readers(int argc, char *argv[], int start, char *dev_glob) {
 if (argc-start < 1 && cmd_file == ((void *)0) && dev_glob == ((void *)0)) {
  fprintf(stderr, "No input device files or command pipe specified.\n");
  return 1;
 }
 if (cmd_file) {
  cmd_fd = bind_cmdsocket(cmd_file);
  if (cmd_fd < 0) {
   return 1;
  }
 }
 int i;
 for (i=start; i<argc; i++) {
  char *dev = argv[i];
  int grab_dev = 0;
  char *tag_dev = ((void *)0);
  add_device( dev, -1, grab_dev, tag_dev );
 }
 if (dev_glob) {
  struct glob_t globbuf;
  glob(dev_glob, (1 << 2), ((void *)0), &globbuf);
  for (i=0; i<globbuf.gl_pathc; i++) {
   int grab_dev = 0;
   char *tag_dev = ((void *)0);
   add_device(globbuf.gl_pathv[i], -1, grab_dev, tag_dev);
  }
 }
 if (run_as_daemon) {
  int err = daemon(0,0);
  if (err) {
   perror("daemon()");
  }
 }
 if (pidfile) {
  write_pidfile( pidfile );
 }
 if (user) {
  struct passwd *pw = getpwnam(user);
  if (pw) {
   int uid = pw->pw_uid;
   int gid = pw->pw_gid;
   if ( initgroups(user, gid) ) {
    perror("initgroups");
    return 1;
   }
   if ( setregid( gid, gid ) ) {
    perror("setregid");
    return 1;
   }
   if ( setreuid( uid, uid ) ) {
    perror("setreuid");
    return 1;
   }
  } else {
   fprintf(stderr, "Unable to lookup user '%s'.\n", user);
   return 1;
  }
 }
 sd_notify(0, "READY=1");
 process_events();
 return 0;
}

variable_types: argc int

variable_types:
argv
char *[]

variable_types: start int

variable_types: i int

variable_types:
dev
char *

variable_types: struct glob_t { unsigned long gl_pathc; char **gl_pathv; unsigned long gl_offs; int gl_flags; void (*gl_closedir)(void *); void *(*gl_readdir)(void *); void *(*gl_opendir)(char *); int (*gl_lstat)(char *, void *); int (*gl_stat)(char *, void *); }

variable_types: struct passwd { char *pw_name; char *pw_passwd; unsigned int pw_uid; unsigned int pw_gid; char *pw_gecos; char *pw_dir; char *pw_shell; } *

variable_types: uid int

variable_types: gid int


decompiled_code:
int show_help()
{
puts("Triggerhappy event daemon 0.5.0\n");
puts("Usage:");
puts(" thd [switches] [devices]\n");
puts("Command line switches:");
puts(" --help Display this help message");
puts(" --daemon Run as daemon process");
puts(" --dump Dump events to console");
puts(" --listevents Print a list of all known events");
puts(" --triggers <file> Load trigger definitions from <file>");
puts(" --socket <socket> Read commands from socket");
puts(" --ignore <event> Ignore key events with name <event>");
puts(" --normalize Normalize relative movement events");
puts(" --user <name> Drop privileges to <name> after opening devices");
return puts(" --deviceglob <p> Open device files matching pattern <p>");
}

canonical_decompiled_code:
int func12()
{
puts("Triggerhappy event daemon 0.5.0\n");
puts("Usage:");
puts(" thd [switches] [devices]\n");
puts("Command line switches:");
puts(" --help Display this help message");
puts(" --daemon Run as daemon process");
puts(" --dump Dump events to console");
puts(" --listevents Print a list of all known events");
puts(" --triggers <file> Load trigger definitions from <file>");
puts(" --socket <socket> Read commands from socket");
puts(" --ignore <event> Ignore key events with name <event>");
puts(" --normalize Normalize relative movement events");
puts(" --user <name> Drop privileges to <name> after opening devices");
return puts(" --deviceglob <p> Open device files matching pattern <p>");
}

original_code:
void show_help(void) {
 printf( "Triggerhappy event daemon " "0.5.0" "\n\n" );
 printf( "Usage:\n" );
 printf( "  thd [switches] [devices]\n\n" );
 printf( "Command line switches:\n" );
 printf( "  --help             Display this help message\n" );
 printf( "  --daemon           Run as daemon process\n" );
 printf( "  --dump             Dump events to console\n" );
 printf( "  --listevents       Print a list of all known events\n" );
 printf( "  --triggers <file>  Load trigger definitions from <file>\n" );
 printf( "  --socket <socket>  Read commands from socket\n" );
 printf( "  --ignore <event>   Ignore key events with name <event>\n" );
 printf( "  --normalize        Normalize relative movement events\n" );
 printf( "  --user <name>      Drop privileges to <name> after opening devices\n" );
 printf( "  --deviceglob <p>   Open device files matching pattern <p>\n" );
}

canonical_original_code:
void show_help() {
 printf( "Triggerhappy event daemon " "0.5.0" "\n\n" );
 printf( "Usage:\n" );
 printf( "  thd [switches] [devices]\n\n" );
 printf( "Command line switches:\n" );
 printf( "  --help             Display this help message\n" );
 printf( "  --daemon           Run as daemon process\n" );
 printf( "  --dump             Dump events to console\n" );
 printf( "  --listevents       Print a list of all known events\n" );
 printf( "  --triggers <file>  Load trigger definitions from <file>\n" );
 printf( "  --socket <socket>  Read commands from socket\n" );
 printf( "  --ignore <event>   Ignore key events with name <event>\n" );
 printf( "  --normalize        Normalize relative movement events\n" );
 printf( "  --user <name>      Drop privileges to <name> after opening devices\n" );
 printf( "  --deviceglob <p>   Open device files matching pattern <p>\n" );
}


main

canonical_name: main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
char *v3; // r13
int v4; // eax
int v5; // er14
unsigned int v7; // eax
int longind; // [rsp+Ch] [rbp-CCh] BYREF
struct sigaction v9; // [rsp+10h] [rbp-C8h] BYREF

v3 = 0LL;
signal(17, (__sighandler_t)((char *)add_device_to_fdset + 1));
longind = 0;
while ( 1 )
{
v4 = getopt_long(argc, (char *const *)argv, "t:s:dhpni:u:g:", &long_options, &longind);
if ( v4 == -1 )
break;
if ( v4 )
{
switch ( v4 )
{
case '<':
uinput_dev = (__int64)optarg;
continue;
case 'd':
dump_events = 1;
continue;
case 'g':
v3 = optarg;
continue;
case 'h':
show_help();
v5 = 0;
break;
case 'i':
if ( (unsigned int)lookup_event_type(optarg) == 1 )
{
v7 = lookup_event_code(optarg);
ignore_key(v7, &ignored_keys);
}
continue;
case 'l':
list_events();
v5 = 0;
break;
case 'p':
pidfile = optarg;
continue;
case 's':
cmd_file = optarg;
continue;
case 't':
triggerfile = (__int64)optarg;
continue;
case 'u':
user = optarg;
continue;
default:
v5 = 1;
break;
}
return v5;
}
if ( !*((_QWORD *)&long_options.flag + 4 * longind) )
{
printf("option %s", *(&long_options.name + 4 * longind));
if ( optarg )
printf(" with arg %s", optarg);
putchar(10);
}
}
v5 = 1;
if ( !(unsigned int)reload_triggerfile() )
{
init_keystate_holder(&keystate);
change_trigger_mode(&unk_FAF);
if ( uinput_dev && (unsigned int)open_uinput() == -1 )
{
fwrite("Error setting up uinput support\n", 1uLL, 0x20uLL, stderr);
}
else
{
v9.sa_handler = handle_signal;
sigfillset(&v9.sa_mask);
v9.sa_flags = 0;
sigaction(2, &v9, 0LL);
sigaction(15, &v9, 0LL);
sigaction(1, &v9, 0LL);
v5 = start_readers(argc, (__int64)argv, optind, v3);
cleanup();
}
}
return v5;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
char *v3; // r13
int v4; // eax
int v5; // er14
unsigned int v7; // eax
int longind; // [rsp+Ch] [rbp-CCh] BYREF
struct sigaction v9; // [rsp+10h] [rbp-C8h] BYREF

v3 = 0LL;
signal(17, (__sighandler_t)((char *)add_device_to_fdset + 1));
longind = 0;
while ( 1 )
{
v4 = getopt_long(argc, (char *const *)argv, "t:s:dhpni:u:g:", &long_options, &longind);
if ( v4 == -1 )
break;
if ( v4 )
{
switch ( v4 )
{
case '<':
uinput_dev = (__int64)optarg;
continue;
case 'd':
dump_events = 1;
continue;
case 'g':
v3 = optarg;
continue;
case 'h':
func12();
v5 = 0;
break;
case 'i':
if ( (unsigned int)lookup_event_type(optarg) == 1 )
{
v7 = lookup_event_code(optarg);
ignore_key(v7, &ignored_keys);
}
continue;
case 'l':
func10();
v5 = 0;
break;
case 'p':
pidfile = optarg;
continue;
case 's':
cmd_file = optarg;
continue;
case 't':
triggerfile = (__int64)optarg;
continue;
case 'u':
user = optarg;
continue;
default:
v5 = 1;
break;
}
return v5;
}
if ( !*((_QWORD *)&long_options.flag + 4 * longind) )
{
printf("option %s", *(&long_options.name + 4 * longind));
if ( optarg )
printf(" with arg %s", optarg);
putchar(10);
}
}
v5 = 1;
if ( !(unsigned int)func3() )
{
init_keystate_holder(&keystate);
change_trigger_mode(&unk_FAF);
if ( uinput_dev && (unsigned int)open_uinput() == -1 )
{
fwrite("Error setting up uinput support\n", 1uLL, 0x20uLL, stderr);
}
else
{
v9.sa_handler = handle_signal;
sigfillset(&v9.sa_mask);
v9.sa_flags = 0;
sigaction(2, &v9, 0LL);
sigaction(15, &v9, 0LL);
sigaction(1, &v9, 0LL);
v5 = func14(argc, (__int64)argv, optind, v3);
func13();
}
}
return v5;
}

original_code:
int main(int argc, char *argv[]) {
 signal(17, ((__sighandler_t) 1));
 char *dev_glob = ((void *)0);
 int option_index = 0;
 int c;
 while (1) {
  c = getopt_long (argc, argv, "t:s:dhpni:u:g:", long_options, &option_index);
  if (c == -1) {
   break;
  }
  switch (c) {
   case 0:
    if (long_options[option_index].flag != 0) {
     break;
    }
    printf ("option %s", long_options[option_index].name);
    if (optarg)
     printf (" with arg %s", optarg);
    printf ("\n");
    break;
   case 'd':
    dump_events = 1;
    break;
   case 'p':
    pidfile = optarg;
    break;
   case 't':
    triggerfile = optarg;
    break;
   case 's':
    cmd_file = optarg;
    break;
   case 'i':
    if ( lookup_event_type(optarg) == 0x01 ) {
     ignore_key( lookup_event_code(optarg), &ignored_keys );
    }
    break;
   case 'h':
    show_help();
    return 0;
   case 'l':
    list_events();
    return 0;
   case 'u':
    user = optarg;
    break;
   case '<':
    uinput_dev = optarg;
    break;
   case 'g':
    dev_glob = optarg;
    break;
   case '?':
   default:
    return 1;
  }
 }
 if (reload_triggerfile() != 0) {
  return 1;
 }
 init_keystate_holder(&keystate);
 change_trigger_mode("");
 if (uinput_dev != ((void *)0) && open_uinput(uinput_dev) == -1) {
  fprintf(stderr, "Error setting up uinput support\n");
  return 1;
 }
 struct sigaction handler;
 handler.__sigaction_handler.sa_handler = handle_signal;
 sigfillset(&handler.sa_mask);
 handler.sa_flags=0;
 sigaction(2,&handler,0);
 sigaction(15,&handler,0);
 sigaction(1,&handler,0);
 int status = start_readers(argc, argv, optind, dev_glob);
 cleanup();
 return status;
}

canonical_original_code:
int main(int argc, char *argv[]) {
 signal(17, ((void (*)(int)) 1));
 char *dev_glob = ((void *)0);
 int option_index = 0;
 int c;
 while (1) {
  c = getopt_long (argc, argv, "t:s:dhpni:u:g:", long_options, &option_index);
  if (c == -1) {
   break;
  }
  switch (c) {
   case 0:
    if (long_options[option_index].flag != 0) {
     break;
    }
    printf ("option %s", long_options[option_index].name);
    if (optarg)
     printf (" with arg %s", optarg);
    printf ("\n");
    break;
   case 'd':
    dump_events = 1;
    break;
   case 'p':
    pidfile = optarg;
    break;
   case 't':
    triggerfile = optarg;
    break;
   case 's':
    cmd_file = optarg;
    break;
   case 'i':
    if ( lookup_event_type(optarg) == 0x01 ) {
     ignore_key( lookup_event_code(optarg), &ignored_keys );
    }
    break;
   case 'h':
    show_help();
    return 0;
   case 'l':
    list_events();
    return 0;
   case 'u':
    user = optarg;
    break;
   case '<':
    uinput_dev = optarg;
    break;
   case 'g':
    dev_glob = optarg;
    break;
   case '?':
   default:
    return 1;
  }
 }
 if (reload_triggerfile() != 0) {
  return 1;
 }
 init_keystate_holder(&keystate);
 change_trigger_mode("");
 if (uinput_dev != ((void *)0) && open_uinput(uinput_dev) == -1) {
  fprintf(stderr, "Error setting up uinput support\n");
  return 1;
 }
 struct sigaction handler;
 handler.__sigaction_handler.sa_handler = handle_signal;
 sigfillset(&handler.sa_mask);
 handler.sa_flags=0;
 sigaction(2,&handler,0);
 sigaction(15,&handler,0);
 sigaction(1,&handler,0);
 int status = start_readers(argc, argv, optind, dev_glob);
 cleanup();
 return status;
}

variable_types: c int

variable_types: struct sigaction { union { void (*sa_handler)(int); void (*sa_sigaction)(int, struct siginfo_t { int si_signo; int si_errno; int si_code; int __pad0; union { int _pad[-1]; struct { int si_pid; unsigned int si_uid; } _kill; struct { int si_tid; int si_overrun; union sigval { int sival_int; void *sival_ptr; } si_sigval; } _timer; struct { int si_pid; unsigned int si_uid; union sigval si_sigval; } _rt; struct { int si_pid; unsigned int si_uid; int si_status; long si_utime; long si_stime; } _sigchld; struct { void *si_addr; short si_addr_lsb; union { struct { void *_lower; void *_upper; } _addr_bnd; unsigned int _pkey; } _bounds; } _sigfault; struct { long si_band; int si_fd; } _sigpoll; struct { void *_call_addr; int _syscall; unsigned int _arch; } _sigsys; } _sifields; } *, void *); } __sigaction_handler; struct __sigset_t { unsigned long __val[-1]; } sa_mask; int sa_flags; void (*sa_restorer)(); }

variable_types: status int

user_defined_types: struct sigaction { union { void (*sa_handler)(int); void (*sa_sigaction)(int, struct siginfo_t *, void *); } __sigaction_handler; struct __sigset_t sa_mask; int sa_flags; void (*sa_restorer)(); }

user_defined_types: struct siginfo_t { int si_signo; int si_errno; int si_code; int __pad0; union { int _pad[-1]; struct { int si_pid; unsigned int si_uid; } _kill; struct { int si_tid; int si_overrun; union sigval si_sigval; } _timer; struct { int si_pid; unsigned int si_uid; union sigval si_sigval; } _rt; struct { int si_pid; unsigned int si_uid; int si_status; long si_utime; long si_stime; } _sigchld; struct { void *si_addr; short si_addr_lsb; union { struct { void *_lower; void *_upper; } _addr_bnd; unsigned int _pkey; } _bounds; } _sigfault; struct { long si_band; int si_fd; } _sigpoll; struct { void *_call_addr; int _syscall; unsigned int _arch; } _sigsys; } _sifields; }


original_code:
static int parse_evdef(char *evdef, trigger *t) {
 char *mode = strchr(evdef, '@');
 if (mode) {
  *mode = '\0';
  mode++;
 }
 t->mode = (mode ? strdup(mode) : ((void *)0));
 t->devtag[0] = '\0';
 char *tmp = strchr(evdef, '>');
 if (tmp && evdef[0] == '<') {
  *tmp = '\0';
  strncpy(t->devtag, &evdef[1], 256);
  t->devtag[256 -1] = '\0';
  evdef = tmp+1;
 }
 char *sptr = ((void *)0);
 char *s_trigger = strtok_r(evdef, "+", &sptr);
 int n = 0;
 while (n < 5) {
  char *s_mod = strtok_r(((void *)0), "+", &sptr);
  if (s_mod == ((void *)0)) {
   t->modifiers[n] = -1;
  } else {
   int type = lookup_event_type(s_mod);
   int c = lookup_event_code(s_mod);
   if (type == 0x01 && c >= 0) {
    t->modifiers[n] = c;
   } else {
    return 1;
   }
  }
  n++;
 }
 int type = lookup_event_type( s_trigger );
 int code = lookup_event_code( s_trigger );
 if (type < 0 || code < 0) {
  return 1;
 }
 t->type = type;
 t->code = code;
 return 0;
}

canonical_original_code:
static int parse_evdef(char *evdef, struct trigger *t) {
 char *mode = strchr(evdef, '@');
 if (mode) {
  *mode = '\0';
  mode++;
 }
 t->mode = (mode ? strdup(mode) : ((void *)0));
 t->devtag[0] = '\0';
 char *tmp = strchr(evdef, '>');
 if (tmp && evdef[0] == '<') {
  *tmp = '\0';
  strncpy(t->devtag, &evdef[1], 256);
  t->devtag[256 -1] = '\0';
  evdef = tmp+1;
 }
 char *sptr = ((void *)0);
 char *s_trigger = strtok_r(evdef, "+", &sptr);
 int n = 0;
 while (n < 5) {
  char *s_mod = strtok_r(((void *)0), "+", &sptr);
  if (s_mod == ((void *)0)) {
   t->modifiers[n] = -1;
  } else {
   int type = lookup_event_type(s_mod);
   int c = lookup_event_code(s_mod);
   if (type == 0x01 && c >= 0) {
    t->modifiers[n] = c;
   } else {
    return 1;
   }
  }
  n++;
 }
 int type = lookup_event_type( s_trigger );
 int code = lookup_event_code( s_trigger );
 if (type < 0 || code < 0) {
  return 1;
 }
 t->type = type;
 t->code = code;
 return 0;
}

variable_types:
evdef
char *

variable_types: struct trigger { int type; int code; int value; int modifiers[5]; char *mode; char devtag[256]; char *action; struct trigger *next; } *

variable_types:
mode
char *

variable_types:
tmp
char *

variable_types:
sptr
char *

variable_types: code int


decompiled_code:
void *__fastcall parse_trigger(char *s)
{
char *v1; // rax
char *v2; // r13
char *v3; // r14
char *v4; // rbp
void *v5; // r12
char *v6; // rbx
const unsigned __int16 **i; // rax
__int64 v8; // rdx
char *save_ptr[6]; // [rsp+8h] [rbp-30h] BYREF

v1 = strchr(s, 35);
if ( v1 )
*v1 = 0;
save_ptr[0] = 0LL;
v2 = strtok_r(s, " \t\n", save_ptr);
v3 = strtok_r(0LL, " \t\n", save_ptr);
v4 = strtok_r(0LL, &byte_2FF, save_ptr);
if ( v3 == 0LL || v2 == 0LL || !v4 )
return 0LL;
v5 = calloc(0x138uLL, 1uLL);
if ( !v5 )
{
fwrite("Unable to allocate memory for trigger definition!\n", 1uLL, 0x32uLL, stderr);
return v5;
}
*((_DWORD *)v5 + 2) = atoi(v3);
if ( !(unsigned int)parse_evdef(v2, (__int64)v5) )
{
v6 = &v4[strlen(v4) - 1];
for ( i = _ctype_b_loc(); v4 <= v6; --v6 )
{
v8 = *v6;
if ( ((*i)[v8] & 0x2000) == 0 && (_BYTE)v8 != 10 )
break;
}
v6[1] = 0;
while ( ((*i)[*v4] & 0x2000) != 0 )
++v4;
*((_QWORD *)v5 + 37) = strdup(v4);
return v5;
}
free(*((void **)v5 + 4));
free(*((void **)v5 + 37));
free(v5);
return 0LL;
}

canonical_decompiled_code:
void *__fastcall func1(char *s)
{
char *v1; // rax
char *v2; // r13
char *v3; // r14
char *v4; // rbp
void *v5; // r12
char *v6; // rbx
const unsigned __int16 **i; // rax
__int64 v8; // rdx
char *save_ptr[6]; // [rsp+8h] [rbp-30h] BYREF

v1 = strchr(s, 35);
if ( v1 )
*v1 = 0;
save_ptr[0] = 0LL;
v2 = strtok_r(s, " \t\n", save_ptr);
v3 = strtok_r(0LL, " \t\n", save_ptr);
v4 = strtok_r(0LL, &byte_2FF, save_ptr);
if ( v3 == 0LL || v2 == 0LL || !v4 )
return 0LL;
v5 = calloc(0x138uLL, 1uLL);
if ( !v5 )
{
fwrite("Unable to allocate memory for trigger definition!\n", 1uLL, 0x32uLL, stderr);
return v5;
}
*((_DWORD *)v5 + 2) = atoi(v3);
if ( !(unsigned int)func0(v2, (__int64)v5) )
{
v6 = &v4[strlen(v4) - 1];
for ( i = _ctype_b_loc(); v4 <= v6; --v6 )
{
v8 = *v6;
if ( ((*i)[v8] & 0x2000) == 0 && (_BYTE)v8 != 10 )
break;
}
v6[1] = 0;
while ( ((*i)[*v4] & 0x2000) != 0 )
++v4;
*((_QWORD *)v5 + 37) = strdup(v4);
return v5;
}
free(*((void **)v5 + 4));
free(*((void **)v5 + 37));
free(v5);
return 0LL;
}

original_code:
trigger* parse_trigger(char* line) {
 char *comment = strchr(line, '#');
 if ( comment != ((void *)0) ) {
  *comment = '\0';
 }
 char *delim = " \t\n";
 char *sptr = ((void *)0);
 char *s_evdef = strtok_r(line, delim, &sptr);
 char *s_value = strtok_r(((void *)0), delim, &sptr);
 char *s_action = strtok_r(((void *)0), "", &sptr);
 if (! (s_evdef && s_value && s_action)) {
  return ((void *)0);
 }
 trigger *t = malloc( sizeof(trigger) );
 if (! t) {
  fprintf(stderr, "Unable to allocate memory for trigger definition!\n");
  return ((void *)0);
 }
 memset( t, 0, sizeof(*t) );
 t->next = ((void *)0);
 t->value = atoi(s_value);
 int err = parse_evdef( s_evdef, t );
 if (!err) {
  char *end = s_action + strlen(s_action) - 1;
  while (end >= s_action && (((*__ctype_b_loc ())[(int) ((*end))] & (unsigned short int) _ISspace) || *end == '\n')) {
   end --;
  }
  *(end+1) = '\0';
  while (((*__ctype_b_loc ())[(int) ((*s_action))] & (unsigned short int) _ISspace)) {
   s_action++;
  }
  t->action = strdup(s_action);
 } else {
  free(t->mode);
  free(t->action);
  free(t);
  t = ((void *)0);
 }
 return t;
}

canonical_original_code:
struct trigger *parse_trigger(char *line) {
 char *comment = strchr(line, '#');
 if ( comment != ((void *)0) ) {
  *comment = '\0';
 }
 char *delim = " \t\n";
 char *sptr = ((void *)0);
 char *s_evdef = strtok_r(line, delim, &sptr);
 char *s_value = strtok_r(((void *)0), delim, &sptr);
 char *s_action = strtok_r(((void *)0), "", &sptr);
 if (! (s_evdef && s_value && s_action)) {
  return ((void *)0);
 }
 struct trigger *t = malloc( sizeof(trigger) );
 if (! t) {
  fprintf(stderr, "Unable to allocate memory for trigger definition!\n");
  return ((void *)0);
 }
 memset( t, 0, sizeof(*t) );
 t->next = ((void *)0);
 t->value = atoi(s_value);
 int err = parse_evdef( s_evdef, t );
 if (!err) {
  char *end = s_action + strlen(s_action) - 1;
  while (end >= s_action && (((*__ctype_b_loc ())[(int) ((*end))] & (unsigned short) _ISspace) || *end == '\n')) {
   end --;
  }
  *(end+1) = '\0';
  while (((*__ctype_b_loc ())[(int) ((*s_action))] & (unsigned short) _ISspace)) {
   s_action++;
  }
  t->action = strdup(s_action);
 } else {
  free(t->mode);
  free(t->action);
  free(t);
  t = ((void *)0);
 }
 return t;
}

variable_types:
line
char *

variable_types:
comment
char *

variable_types:
delim
char *

variable_types: err int

variable_types:
end
char *

return_type: struct trigger { int type; int code; int value; int modifiers[5]; char *mode; char devtag[256]; char *action; struct trigger *next; } *


original_code:
static int mods_equal(keystate_holder ksh, trigger_modifier tm, int ignore_key) {
 int n = 0;
 while ( n < 5 ) {
  int code = tm[n];
  if (code < 0) {
   break;
  } else if (ksh[code] <= 0) {
   return 0;
  }
  n++;
 }
 int x;
 for (x=0; x<=0x2ff; x++) {
  if (x != ignore_key && ksh[x] > 0) {
   n--;
  }
 }
 return (n == 0);
}

canonical_original_code:
static int mods_equal(unsigned short ksh[-1], int tm[5], int ignore_key) {
 int n = 0;
 while ( n < 5 ) {
  int code = tm[n];
  if (code < 0) {
   break;
  } else if (ksh[code] <= 0) {
   return 0;
  }
  n++;
 }
 int x;
 for (x=0; x<=0x2ff; x++) {
  if (x != ignore_key && ksh[x] > 0) {
   n--;
  }
 }
 return (n == 0);
}

variable_types:
ksh
unsigned short [-1]

variable_types:
tm
int [5]

variable_types: n int

variable_types: x int


decompiled_code:
_BOOL8 __fastcall accept_triggerfile(const struct dirent *a1)
{
char *v1; // rax
_BOOL8 result; // rax

v1 = strstr(a1->d_name, ".conf");
if ( v1 )
result = v1[5] == 0;
else
result = 0LL;
return result;
}

canonical_decompiled_code:
_BOOL8 __fastcall func1(const struct dirent *a1)
{
char *v1; // rax
_BOOL8 result; // rax

v1 = strstr(a1->d_name, ".conf");
if ( v1 )
result = v1[5] == 0;
else
result = 0LL;
return result;
}

original_code:
static int accept_triggerfile(const struct dirent *entry) {
 const char *suffix = ".conf";
 const char *name = entry->d_name;
 char *end = strstr( name, suffix );
 if ( end && end[ strlen(suffix) ] == '\0' ) {
  return 1;
 } else {
  return 0;
 }
}

canonical_original_code:
static int accept_triggerfile(struct dirent *entry) {
 char *suffix = ".conf";
 char *name = entry->d_name;
 char *end = strstr( name, suffix );
 if ( end && end[ strlen(suffix) ] == '\0' ) {
  return 1;
 } else {
  return 0;
 }
}

variable_types: struct dirent { unsigned long d_ino; long d_off; unsigned short d_reclen; unsigned char d_type; char d_name[256]; } *

variable_types:
suffix
char *

variable_types:
name
char *


decompiled_code:
_BOOL8 __fastcall devtag_equal(char *s2, char *s1)
{
_BOOL8 result; // rax

if ( *s1 )
result = strcmp(s1, s2) == 0;
else
result = 1LL;
return result;
}

canonical_decompiled_code:
_BOOL8 __fastcall func2(char *s2, char *s1)
{
_BOOL8 result; // rax

if ( *s1 )
result = strcmp(s1, s2) == 0;
else
result = 1LL;
return result;
}

original_code:
static int devtag_equal(const char *d_tag, const char *t_tag) {
 if (strlen(t_tag) == 0) {
  return 1;
 }
 if (strcmp(t_tag, d_tag) == 0) {
  return 1;
 }
 return 0;
}

canonical_original_code:
static int devtag_equal(char *d_tag, char *t_tag) {
 if (strlen(t_tag) == 0) {
  return 1;
 }
 if (strcmp(t_tag, d_tag) == 0) {
  return 1;
 }
 return 0;
}


decompiled_code:
void *get_trigger_mode()
{
return trigger_mode;
}

canonical_decompiled_code:
void *func3()
{
return trigger_mode;
}

original_code:
char *get_trigger_mode() {
 return trigger_mode;
}


decompiled_code:
_BOOL8 __fastcall correct_mode(char *s2)
{
const char *v1; // rax

if ( !s2 )
return 1LL;
v1 = (const char *)get_trigger_mode();
return strcmp(v1, s2) == 0;
}

canonical_decompiled_code:
_BOOL8 __fastcall func4(char *s2)
{
const char *v1; // rax

if ( !s2 )
return 1LL;
v1 = (const char *)func3();
return strcmp(v1, s2) == 0;
}

original_code:
static int correct_mode( const char *tmode ) {
 return (tmode == ((void *)0)) || (strcmp( get_trigger_mode(), tmode ) == 0);
}

canonical_original_code:
static int correct_mode(char *tmode) {
 return (tmode == ((void *)0)) || (strcmp( get_trigger_mode(), tmode ) == 0);
}

variable_types:
tmode
char *


decompiled_code:
char *__fastcall change_trigger_mode(char *s)
{
char *result; // rax

if ( trigger_mode )
{
free(trigger_mode);
fprintf(stderr, "Changing trigger mode to <%s>\n", s);
}
result = strdup(s);
trigger_mode = result;
return result;
}

canonical_decompiled_code:
char *__fastcall func5(char *s)
{
char *result; // rax

if ( trigger_mode )
{
free(trigger_mode);
fprintf(stderr, "Changing trigger mode to <%s>\n", s);
}
result = strdup(s);
trigger_mode = result;
return result;
}

original_code:
void change_trigger_mode(const char *mode) {
 if (trigger_mode != ((void *)0)) {
  free(trigger_mode);
  fprintf(stderr, "Changing trigger mode to <%s>\n", mode);
 }
 trigger_mode = strdup(mode);
}

canonical_original_code:
void change_trigger_mode(char *mode) {
 if (trigger_mode != ((void *)0)) {
  free(trigger_mode);
  fprintf(stderr, "Changing trigger mode to <%s>\n", mode);
 }
 trigger_mode = strdup(mode);
}

variable_types:
mode
char *


decompiled_code:
void __fastcall triggers_enabled(int a1)
{
triggers_are_enabled = a1;
}

canonical_decompiled_code:
void __fastcall func6(int a1)
{
triggers_are_enabled = a1;
}

original_code:
void triggers_enabled( int status ) {
 triggers_are_enabled = status;
}

canonical_original_code:
void triggers_enabled(int status) {
 triggers_are_enabled = status;
}

variable_types: status int


decompiled_code:
__int64 __fastcall read_triggers(void *src)
{
int v2; // eax
int v3; // edx
unsigned __int64 v4; // rbx
struct dirent *v5; // rdi
char *v6; // r15
size_t v7; // r14
void *v8; // rsp
__int64 result; // rax
char dest[8]; // [rsp+0h] [rbp-170h] BYREF
char *v11; // [rsp+8h] [rbp-168h]
struct dirent **namelist; // [rsp+18h] [rbp-158h] BYREF
struct stat v13; // [rsp+20h] [rbp-150h] BYREF
struct stat v14; // [rsp+B0h] [rbp-C0h] BYREF

if ( stat((const char *)src, &v13) == -1 )
{
perror("stat");
result = 1LL;
}
else if ( (v13.st_mode & 0xF000) == 0x4000 )
{
v2 = scandir(
(const char *)src,
&namelist,
(int (*)(const struct dirent *))accept_triggerfile,
(int (*)(const struct dirent **, const struct dirent **))&alphasort);
if ( v2 < 0 )
{
perror("scandir");
result = 1LL;
}
else
{
v3 = v2 - 1;
if ( v2 )
{
v4 = 8LL * v3;
*(_QWORD *)dest = 8 * (v2 - (unsigned __int64)(unsigned int)v3) - 16;
do
{
v6 = namelist[v4 / 8]->d_name;
v7 = strlen((const char *)src);
v8 = alloca(v7 + strlen(v6) + 2);
v11 = dest;
memcpy(dest, src, v7);
dest[v7] = 47;
strcpy(&dest[v7 + 1], v6);
if ( stat(dest, &v14) == -1 )
perror("stat");
if ( (v14.st_mode & 0xF000) == 0x8000 )
read_triggerfile(v11);
v5 = namelist[v4 / 8];
v4 -= 8LL;
free(v5);
}
while ( *(_QWORD *)dest != v4 );
}
free(namelist);
result = 0LL;
}
}
else
{
result = read_triggerfile((const char *)src);
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func8(void *src)
{
int v2; // eax
int v3; // edx
unsigned __int64 v4; // rbx
struct dirent *v5; // rdi
char *v6; // r15
size_t v7; // r14
void *v8; // rsp
__int64 result; // rax
char dest[8]; // [rsp+0h] [rbp-170h] BYREF
char *v11; // [rsp+8h] [rbp-168h]
struct dirent **namelist; // [rsp+18h] [rbp-158h] BYREF
struct stat v13; // [rsp+20h] [rbp-150h] BYREF
struct stat v14; // [rsp+B0h] [rbp-C0h] BYREF

if ( stat((const char *)src, &v13) == -1 )
{
perror("stat");
result = 1LL;
}
else if ( (v13.st_mode & 0xF000) == 0x4000 )
{
v2 = scandir(
(const char *)src,
&namelist,
(int (*)(const struct dirent *))accept_triggerfile,
(int (*)(const struct dirent **, const struct dirent **))&alphasort);
if ( v2 < 0 )
{
perror("scandir");
result = 1LL;
}
else
{
v3 = v2 - 1;
if ( v2 )
{
v4 = 8LL * v3;
*(_QWORD *)dest = 8 * (v2 - (unsigned __int64)(unsigned int)v3) - 16;
do
{
v6 = namelist[v4 / 8]->d_name;
v7 = strlen((const char *)src);
v8 = alloca(v7 + strlen(v6) + 2);
v11 = dest;
memcpy(dest, src, v7);
dest[v7] = 47;
strcpy(&dest[v7 + 1], v6);
if ( stat(dest, &v14) == -1 )
perror("stat");
if ( (v14.st_mode & 0xF000) == 0x8000 )
func7(v11);
v5 = namelist[v4 / 8];
v4 -= 8LL;
free(v5);
}
while ( *(_QWORD *)dest != v4 );
}
free(namelist);
result = 0LL;
}
}
else
{
result = func7((const char *)src);
}
return result;
}

original_code:
int read_triggers(const char *path) {
 struct stat sb;
 if (stat(path, &sb) == -1) {
  perror("stat");
  return 1;
 }
 if (((((sb.st_mode)) & 0170000) == (0040000))) {
  struct dirent **namelist;
  int n;
  n = scandir(path, &namelist, accept_triggerfile, alphasort);
  if ( n < 0) {
   perror("scandir");
   return 1;
  } else {
   while (n--) {
    struct stat sf;
    char *file = namelist[n]->d_name;
    char *sep = "/";
    char fpath[strlen(path)+strlen(sep)+strlen(file) + 1];
    strcpy(fpath, path);
    strcat(fpath, sep);
    strcat(fpath, file);
    if (stat(fpath, &sf) == -1) {
     perror("stat");
    }
    if (((((sf.st_mode)) & 0170000) == (0100000))) {
     read_triggerfile(fpath);
    }
    free(namelist[n]);
   }
   free(namelist);
   return 0;
  }
 } else {
  return read_triggerfile( path );
 }
}

canonical_original_code:
int read_triggers(char *path) {
 struct stat sb;
 if (stat(path, &sb) == -1) {
  perror("stat");
  return 1;
 }
 if (((((sb.st_mode)) & 0170000) == (0040000))) {
  struct dirent **namelist;
  int n;
  n = scandir(path, &namelist, accept_triggerfile, alphasort);
  if ( n < 0) {
   perror("scandir");
   return 1;
  } else {
   while (n--) {
    struct stat sf;
    char *file = namelist[n]->d_name;
    char *sep = "/";
    char fpath[-1];
    strcpy(fpath, path);
    strcat(fpath, sep);
    strcat(fpath, file);
    if (stat(fpath, &sf) == -1) {
     perror("stat");
    }
    if (((((sf.st_mode)) & 0170000) == (0100000))) {
     read_triggerfile(fpath);
    }
    free(namelist[n]);
   }
   free(namelist);
   return 0;
  }
 } else {
  return read_triggerfile( path );
 }
}

variable_types:
path
char *

variable_types: struct stat { unsigned long st_dev; unsigned long st_ino; unsigned long st_nlink; unsigned int st_mode; unsigned int st_uid; unsigned int st_gid; int __pad0; unsigned long st_rdev; long st_size; long st_blksize; long st_blocks; struct timespec { long tv_sec; long tv_nsec; } st_atim; struct timespec st_mtim; struct timespec st_ctim; long __glibc_reserved[3]; }

variable_types: struct dirent { unsigned long d_ino; long d_off; unsigned short d_reclen; unsigned char d_type; char d_name[256]; } **

variable_types:
file
char *

variable_types:
sep
char *

variable_types:
fpath
char [-1]


decompiled_code:
int __fastcall run_triggers(int a1, int a2, int a3, __int64 a4, __int64 a5)
{
int result; // eax
unsigned int *v6; // rbx
int v7; // er13
const char *v10; // r13
_BYTE *v11; // rax
_BYTE *v12; // r13
unsigned int v13; // er13
const char *v14; // rax
const char *v15; // rax
char *s2; // [rsp+10h] [rbp-58h]
int v18; // [rsp+18h] [rbp-50h]
unsigned int v19; // [rsp+1Ch] [rbp-4Ch]
char s[64]; // [rsp+28h] [rbp-40h] BYREF

result = triggers_are_enabled;
if ( triggers_are_enabled )
{
v6 = (unsigned int *)trigger_list;
if ( trigger_list )
{
v7 = -1;
result = a5 + 20;
if ( a1 == 1 )
v7 = a2;
s2 = (char *)(a5 + 20);
v18 = v7;
do
{
if ( *v6 == a1 && v6[1] == a2 && v6[2] == a3 )
{
v10 = (const char *)*((_QWORD *)v6 + 37);
if ( v10 )
{
result = correct_mode(*((char **)v6 + 4));
if ( result )
{
result = devtag_equal(s2, (char *)v6 + 40);
if ( result )
{
result = mods_equal(a4, (__int64)(v6 + 3), v18);
if ( result )
{
fprintf(stderr, "Executing trigger action: %s\n", v10);
v11 = (_BYTE *)*((_QWORD *)v6 + 37);
if ( *v11 == 64 )
return (unsigned int)change_trigger_mode(v11 + 1);
if ( *v11 == 60 )
{
v12 = v11 + 1;
fprintf(stderr, "Sending event: %s\n", v11 + 1);
v19 = lookup_event_type(v12);
result = lookup_event_code(v12);
v13 = result;
if ( v19 && result )
{
send_event(v19, (unsigned int)result, 1LL);
send_event(v19, v13, 0LL);
result = send_event(0LL, 0LL, 0LL);
}
}
else
{
result = fork();
if ( !result )
{
setenv("TH_DEVICE", *(const char **)(a5 + 8), 1);
v14 = (const char *)get_keystate(a4);
setenv("TH_KEYSTATE", v14, 1);
v15 = (const char *)lookup_event_name_i(*v6, v6[1]);
setenv("TH_EVENT", v15, 1);
sprintf(s, "%d", v6[2]);
setenv("TH_VALUE", s, 1);
signal(17, 0LL);
system(*((const char **)v6 + 37));
exit(0);
}
if ( result < 0 )
result = fwrite("Unable to fork!\n", 1uLL, 0x10uLL, stderr);
}
}
}
}
}
}
v6 = (unsigned int *)*((_QWORD *)v6 + 38);
}
while ( v6 );
}
}
return result;
}

canonical_decompiled_code:
int __fastcall func9(int a1, int a2, int a3, __int64 a4, __int64 a5)
{
int result; // eax
unsigned int *v6; // rbx
int v7; // er13
const char *v10; // r13
_BYTE *v11; // rax
_BYTE *v12; // r13
unsigned int v13; // er13
const char *v14; // rax
const char *v15; // rax
char *s2; // [rsp+10h] [rbp-58h]
int v18; // [rsp+18h] [rbp-50h]
unsigned int v19; // [rsp+1Ch] [rbp-4Ch]
char s[64]; // [rsp+28h] [rbp-40h] BYREF

result = triggers_are_enabled;
if ( triggers_are_enabled )
{
v6 = (unsigned int *)trigger_list;
if ( trigger_list )
{
v7 = -1;
result = a5 + 20;
if ( a1 == 1 )
v7 = a2;
s2 = (char *)(a5 + 20);
v18 = v7;
do
{
if ( *v6 == a1 && v6[1] == a2 && v6[2] == a3 )
{
v10 = (const char *)*((_QWORD *)v6 + 37);
if ( v10 )
{
result = func4(*((char **)v6 + 4));
if ( result )
{
result = func2(s2, (char *)v6 + 40);
if ( result )
{
result = func0(a4, (__int64)(v6 + 3), v18);
if ( result )
{
fprintf(stderr, "Executing trigger action: %s\n", v10);
v11 = (_BYTE *)*((_QWORD *)v6 + 37);
if ( *v11 == 64 )
return (unsigned int)func5(v11 + 1);
if ( *v11 == 60 )
{
v12 = v11 + 1;
fprintf(stderr, "Sending event: %s\n", v11 + 1);
v19 = lookup_event_type(v12);
result = lookup_event_code(v12);
v13 = result;
if ( v19 && result )
{
send_event(v19, (unsigned int)result, 1LL);
send_event(v19, v13, 0LL);
result = send_event(0LL, 0LL, 0LL);
}
}
else
{
result = fork();
if ( !result )
{
setenv("TH_DEVICE", *(const char **)(a5 + 8), 1);
v14 = (const char *)get_keystate(a4);
setenv("TH_KEYSTATE", v14, 1);
v15 = (const char *)lookup_event_name_i(*v6, v6[1]);
setenv("TH_EVENT", v15, 1);
sprintf(s, "%d", v6[2]);
setenv("TH_VALUE", s, 1);
signal(17, 0LL);
system(*((const char **)v6 + 37));
exit(0);
}
if ( result < 0 )
result = fwrite("Unable to fork!\n", 1uLL, 0x10uLL, stderr);
}
}
}
}
}
}
v6 = (unsigned int *)*((_QWORD *)v6 + 38);
}
while ( v6 );
}
}
return result;
}

original_code:
void run_triggers(int type, int code, int value, keystate_holder ksh, device *dev) {
 if (triggers_are_enabled == 0) {
  return;
 }
 if (dev && dev->tag) {
 }
 trigger *et = trigger_list;
 while (et != ((void *)0)) {
  if ( type == et->type &&
       code == et->code &&
       value == et->value &&
       et->action &&
       correct_mode( et->mode ) &&
       devtag_equal(&(dev->tag[0]), &(et->devtag[0])) &&
       mods_equal(ksh, et->modifiers, (type==0x01?code:-1) )) {
   fprintf(stderr, "Executing trigger action: %s\n", et->action);
   if (et->action[0] == '@') {
    change_trigger_mode( &(et->action)[1] );
    break;
   } else if (et->action[0] == '<' ) {
    char *keyname = &(et->action[1]);
    fprintf(stderr, "Sending event: %s\n", keyname);
    int type = lookup_event_type( keyname );
    int code = lookup_event_code( keyname );
    if (type && code) {
     send_event( type, code, 1 );
     send_event( type, code, 0 );
     send_event( 0x00, 0, 0 );
    }
   } else {
    int pid = fork();
    if (pid == 0 ) {
     setenv( "TH_DEVICE", dev->devname, 1 );
     setenv( "TH_KEYSTATE", get_keystate(ksh), 1 );
     const char *en = lookup_event_name_i( et->type, et->code );
     setenv( "TH_EVENT", en, 1 );
     char ev[8];
     sprintf( &(ev[0]), "%d", et->value );
     setenv( "TH_VALUE", &(ev[0]), 1 );
     signal(17, ((__sighandler_t) 0));
     system(et->action);
     exit(0);
    } else if (pid < 0) {
     fprintf(stderr, "Unable to fork!\n");
    }
   }
  }
  et = et->next;
 }
}

canonical_original_code:
void run_triggers(int type, int code, int value, unsigned short ksh[-1], struct device *dev) {
 if (triggers_are_enabled == 0) {
  return;
 }
 if (dev && dev->tag) {
 }
 struct trigger *et = trigger_list;
 while (et != ((void *)0)) {
  if ( type == et->type &&
       code == et->code &&
       value == et->value &&
       et->action &&
       correct_mode( et->mode ) &&
       devtag_equal(&(dev->tag[0]), &(et->devtag[0])) &&
       mods_equal(ksh, et->modifiers, (type==0x01?code:-1) )) {
   fprintf(stderr, "Executing trigger action: %s\n", et->action);
   if (et->action[0] == '@') {
    change_trigger_mode( &(et->action)[1] );
    break;
   } else if (et->action[0] == '<' ) {
    char *keyname = &(et->action[1]);
    fprintf(stderr, "Sending event: %s\n", keyname);
    int type = lookup_event_type( keyname );
    int code = lookup_event_code( keyname );
    if (type && code) {
     send_event( type, code, 1 );
     send_event( type, code, 0 );
     send_event( 0x00, 0, 0 );
    }
   } else {
    int pid = fork();
    if (pid == 0 ) {
     setenv( "TH_DEVICE", dev->devname, 1 );
     setenv( "TH_KEYSTATE", get_keystate(ksh), 1 );
     char *en = lookup_event_name_i( et->type, et->code );
     setenv( "TH_EVENT", en, 1 );
     char ev[8];
     sprintf( &(ev[0]), "%d", et->value );
     setenv( "TH_VALUE", &(ev[0]), 1 );
     signal(17, ((void (*)(int)) 0));
     system(et->action);
     exit(0);
    } else if (pid < 0) {
     fprintf(stderr, "Unable to fork!\n");
    }
   }
  }
  et = et->next;
 }
}

variable_types: type int

variable_types: code int

variable_types: value int

variable_types: struct device { int fd; char *devname; int exclusive; char tag[256]; struct device *next; } *

variable_types: struct trigger { int type; int code; int value; int modifiers[5]; char *mode; char devtag[256]; char *action; struct trigger *next; } *

variable_types:
keyname
char *

variable_types: pid int

variable_types:
en
char *

variable_types:
ev
char [8]


decompiled_code:
__int64 __fastcall count_triggers(__int64 *a1)
{
__int64 v1; // rax
unsigned int i; // er8

if ( !a1 )
return 0LL;
v1 = *a1;
for ( i = 0; v1; ++i )
v1 = *(_QWORD *)(v1 + 304);
return i;
}

canonical_decompiled_code:
__int64 __fastcall func10(__int64 *a1)
{
__int64 v1; // rax
unsigned int i; // er8

if ( !a1 )
return 0LL;
v1 = *a1;
for ( i = 0; v1; ++i )
v1 = *(_QWORD *)(v1 + 304);
return i;
}

original_code:
int count_triggers( trigger **list ) {
 int n = 0;
 if(!list)
  return 0;
 trigger *p = *list;
 while ( p != ((void *)0) ) {
  n++;
  p = p->next;
 }
 return n;
}

canonical_original_code:
int count_triggers(struct trigger **list) {
 int n = 0;
 if(!list)
  return 0;
 struct trigger *p = *list;
 while ( p != ((void *)0) ) {
  n++;
  p = p->next;
 }
 return n;
}

variable_types: struct trigger { int type; int code; int value; int modifiers[5]; char *mode; char devtag[256]; char *action; struct trigger *next; } **

variable_types: n int


decompiled_code:
void clear_triggers()
{
void **v0; // rbx
void **v1; // rbp

v0 = (void **)trigger_list;
if ( trigger_list )
{
do
{
v1 = v0;
v0 = (void **)v0[38];
free(v1[37]);
free(v1[4]);
free(v1);
}
while ( v0 );
}
trigger_list = 0LL;
}

canonical_decompiled_code:
void func11()
{
void **v0; // rbx
void **v1; // rbp

v0 = (void **)trigger_list;
if ( trigger_list )
{
do
{
v1 = v0;
v0 = (void **)v0[38];
free(v1[37]);
free(v1[4]);
free(v1);
}
while ( v0 );
}
trigger_list = 0LL;
}

original_code:
void clear_triggers() {
 trigger *p = trigger_list;
 while (p != ((void *)0)) {
  trigger *next = p->next;
  free(p->action);
  free(p->mode);
  free(p);
  p = next;
 }
 trigger_list = ((void *)0);
}

canonical_original_code:
void clear_triggers() {
 struct trigger *p = trigger_list;
 while (p != ((void *)0)) {
  struct trigger *next = p->next;
  free(p->action);
  free(p->mode);
  free(p);
  p = next;
 }
 trigger_list = ((void *)0);
}

user_defined_types: struct trigger { int type; int code; int value; int modifiers[5]; char *mode; char devtag[256]; char *action; struct trigger *next; }


decompiled_code:
_BOOL8 __fastcall test_bit(char a1, _DWORD *a2)
{
return (*a2 & (1 << a1)) != 0;
}

canonical_decompiled_code:
_BOOL8 __fastcall func0(char a1, _DWORD *a2)
{
return (*a2 & (1 << a1)) != 0;
}

original_code:
static __inline__ int test_bit(int nr, uint32_t * addr) {
 uint32_t mask;
 addr += nr >> 5;
 mask = 1 << (nr & 0x1f);
 return ((mask & *addr) != 0);
}

canonical_original_code:
static __inline__ int test_bit(int nr, unsigned int *addr) {
 unsigned int mask;
 addr += nr >> 5;
 mask = 1 << (nr & 0x1f);
 return ((mask & *addr) != 0);
}

variable_types: nr int

variable_types:
addr
unsigned int *

variable_types:
mask
unsigned int


original_code:
char *get_device_description(int fd) {
 char descr[256] = "Unknown";
 if(ioctl(fd, (((2U) << (((0 +8)+8)+14)) | (('E') << (0 +8)) | ((0x06) << 0) | ((sizeof(descr)) << ((0 +8)+8))), descr) < 0) {
  perror("evdev ioctl");
 }
 return strdup(descr);
}

variable_types: fd int

variable_types:
descr
char [256]


decompiled_code:
_BOOL8 __fastcall device_is_suitable(int a1)
{
int v1; // er8
_BOOL8 result; // rax
_BOOL4 v3; // er8
_DWORD v4[34]; // [rsp+0h] [rbp-88h] BYREF

v1 = ioctl(a1, 0x80804520uLL, v4);
result = 0LL;
if ( v1 > 0 )
{
v3 = test_bit(1, v4);
result = 1LL;
if ( !v3 )
result = test_bit(5, v4);
}
return result;
}

canonical_decompiled_code:
_BOOL8 __fastcall func2(int a1)
{
int v1; // er8
_BOOL8 result; // rax
_BOOL4 v3; // er8
_DWORD v4[34]; // [rsp+0h] [rbp-88h] BYREF

v1 = ioctl(a1, 0x80804520uLL, v4);
result = 0LL;
if ( v1 > 0 )
{
v3 = func0(1, v4);
result = 1LL;
if ( !v3 )
result = func0(5, v4);
}
return result;
}

variable_types:
bits
unsigned int [32]

variable_types: rc int


decompiled_code:
void __fastcall add_device(char *file, int fd, int a3, const char *a4)
{
int v4; // er14
_QWORD *v7; // rax
_QWORD *v8; // rdx
void **v9; // rbx
void *v10; // rax
void *v11; // r15
char *v12; // rax
int *v13; // rax
char *v14; // rax

v4 = fd;
v7 = device_list;
if ( device_list )
{
do
{
v8 = v7;
v7 = (_QWORD *)v7[35];
}
while ( v7 );
v9 = (void **)(v8 + 35);
}
else
{
v9 = &device_list;
}
if ( fd < 0 )
{
v4 = open(file, 0);
if ( v4 < 0 )
{
v13 = _errno_location();
v14 = strerror(*v13);
fprintf(stderr, "Error opening '%s': %s\n", file, v14);
return;
}
}
if ( !device_is_suitable(v4) )
{
fprintf(stderr, "Device %s not suitable.\n", file);
LABEL_16:
close(v4);
return;
}
if ( a3 && ioctl(v4, 0x40044590uLL, 1LL) == -1 )
{
fprintf(stderr, "Device %s cannot be grabbed exclusively.\n", file);
goto LABEL_16;
}
v10 = malloc(0x120uLL);
*v9 = v10;
if ( v10 && (memset(v10, 0, 0x120uLL), v11 = *v9, v12 = strdup(file), (*((_QWORD *)v11 + 1) = v12) != 0LL) )
{
*(_DWORD *)v11 = v4;
*((_DWORD *)v11 + 4) = a3;
if ( a4 )
{
strncpy((char *)v11 + 20, a4, 0x100uLL);
v11 = *v9;
*((_BYTE *)*v9 + 275) = 0;
}
*((_QWORD *)v11 + 35) = 0LL;
}
else
{
fwrite("Unable to allocate memory for new device!\n", 1uLL, 0x2AuLL, stderr);
if ( *v9 )
free(*((void **)*v9 + 1));
free(*v9);
*v9 = 0LL;
}
}

canonical_decompiled_code:
void __fastcall func3(char *file, int fd, int a3, const char *a4)
{
int v4; // er14
_QWORD *v7; // rax
_QWORD *v8; // rdx
void **v9; // rbx
void *v10; // rax
void *v11; // r15
char *v12; // rax
int *v13; // rax
char *v14; // rax

v4 = fd;
v7 = device_list;
if ( device_list )
{
do
{
v8 = v7;
v7 = (_QWORD *)v7[35];
}
while ( v7 );
v9 = (void **)(v8 + 35);
}
else
{
v9 = &device_list;
}
if ( fd < 0 )
{
v4 = open(file, 0);
if ( v4 < 0 )
{
v13 = _errno_location();
v14 = strerror(*v13);
fprintf(stderr, "Error opening '%s': %s\n", file, v14);
return;
}
}
if ( !func2(v4) )
{
fprintf(stderr, "Device %s not suitable.\n", file);
LABEL_16:
close(v4);
return;
}
if ( a3 && ioctl(v4, 0x40044590uLL, 1LL) == -1 )
{
fprintf(stderr, "Device %s cannot be grabbed exclusively.\n", file);
goto LABEL_16;
}
v10 = malloc(0x120uLL);
*v9 = v10;
if ( v10 && (memset(v10, 0, 0x120uLL), v11 = *v9, v12 = strdup(file), (*((_QWORD *)v11 + 1) = v12) != 0LL) )
{
*(_DWORD *)v11 = v4;
*((_DWORD *)v11 + 4) = a3;
if ( a4 )
{
strncpy((char *)v11 + 20, a4, 0x100uLL);
v11 = *v9;
*((_BYTE *)*v9 + 275) = 0;
}
*((_QWORD *)v11 + 35) = 0LL;
}
else
{
fwrite("Unable to allocate memory for new device!\n", 1uLL, 0x2AuLL, stderr);
if ( *v9 )
free(*((void **)*v9 + 1));
free(*v9);
*v9 = 0LL;
}
}

original_code:
void add_device(char *dev, int fd, int excl, char *tag) {
 device **p = &device_list;
 while (*p != ((void *)0)) {
  p = &( (*p)->next );
 }
 if (fd < 0) {
  fd = open( dev, 00 );
 }
 if (fd >= 0) {
  if (! device_is_suitable(fd) ) {
   fprintf(stderr, "Device %s not suitable.\n", dev);
   close(fd);
   return;
  }
  if (excl) {
   if (ioctl(fd, (((1U) << (((0 +8)+8)+14)) | ((('E')) << (0 +8)) | (((0x90)) << 0) | ((((sizeof(int)))) << ((0 +8)+8))), 1) == -1) {
    fprintf(stderr, "Device %s cannot be grabbed exclusively.\n", dev);
    close(fd);
    return;
   }
  }
  *p = malloc(sizeof(device));
  if (*p == ((void *)0)) goto nomem_cleanup;
  memset(*p, 0, sizeof(device));
  (*p)->devname = strdup(dev);
  if ((*p)->devname == ((void *)0)) goto nomem_cleanup;
  (*p)->fd = fd;
  (*p)->exclusive = excl;
  if (tag) {
   strncpy((*p)->tag, tag, 256);
   (*p)->tag[256 -1] = '\0';
  }
  (*p)->next = ((void *)0);
 } else {
  fprintf( stderr, "Error opening '%s': %s\n", dev, strerror((*__errno_location ())) );
 }
 return;
nomem_cleanup:
 fprintf(stderr, "Unable to allocate memory for new device!\n");
 if (*p) {
  free( (*p)->devname );
 }
 free(*p);
 *p = ((void *)0);
}

canonical_original_code:
void add_device(char *dev, int fd, int excl, char *tag) {
 struct device **p = &device_list;
 while (*p != ((void *)0)) {
  p = &( (*p)->next );
 }
 if (fd < 0) {
  fd = open( dev, 00 );
 }
 if (fd >= 0) {
  if (! device_is_suitable(fd) ) {
   fprintf(stderr, "Device %s not suitable.\n", dev);
   close(fd);
   return;
  }
  if (excl) {
   if (ioctl(fd, (((1U) << (((0 +8)+8)+14)) | ((('E')) << (0 +8)) | (((0x90)) << 0) | ((((sizeof(int)))) << ((0 +8)+8))), 1) == -1) {
    fprintf(stderr, "Device %s cannot be grabbed exclusively.\n", dev);
    close(fd);
    return;
   }
  }
  *p = malloc(sizeof(device));
  if (*p == ((void *)0)) goto nomem_cleanup;
  memset(*p, 0, sizeof(device));
  (*p)->devname = strdup(dev);
  if ((*p)->devname == ((void *)0)) goto nomem_cleanup;
  (*p)->fd = fd;
  (*p)->exclusive = excl;
  if (tag) {
   strncpy((*p)->tag, tag, 256);
   (*p)->tag[256 -1] = '\0';
  }
  (*p)->next = ((void *)0);
 } else {
  fprintf( stderr, "Error opening '%s': %s\n", dev, strerror((*__errno_location ())) );
 }
 return;
nomem_cleanup:
 fprintf(stderr, "Unable to allocate memory for new device!\n");
 if (*p) {
  free( (*p)->devname );
 }
 free(*p);
 *p = ((void *)0);
}

variable_types:
dev
char *

variable_types: excl int

variable_types:
tag
char *

variable_types: struct device { int fd; char *devname; int exclusive; char tag[256]; struct device *next; } **