#!/bin/sh
set -e -u

_line_number=1
_column_number=0
_last_tok_line_number=1
_last_tok_column_number=0
# IncludeStack struct member declarations
readonly __fp=0
readonly __next=1
readonly __filename=2
readonly __line_number=3
readonly __column_number=4
readonly __sizeof__IncludeStack=5
_include_stack=0
_include_stack2=0
_fp=0
# Enum declaration
readonly _AUTO_KW=300
readonly _BREAK_KW=301
readonly _CASE_KW=302
readonly _CHAR_KW=303
readonly _CONST_KW=304
readonly _CONTINUE_KW=305
readonly _DEFAULT_KW=306
readonly _DO_KW=307
readonly _DOUBLE_KW=308
readonly _ELSE_KW=309
readonly _ENUM_KW=310
readonly _ERROR_KW=311
readonly _EXTERN_KW=312
readonly _FLOAT_KW=313
readonly _FOR_KW=314
readonly _GOTO_KW=315
readonly _IF_KW=316
readonly _IFNDEF_KW=317
readonly _INCLUDE_KW=318
readonly _INT_KW=319
readonly _LONG_KW=320
readonly _REGISTER_KW=321
readonly _RETURN_KW=322
readonly _SHORT_KW=323
readonly _SIGNED_KW=324
readonly _SIZEOF_KW=325
readonly _STATIC_KW=326
readonly _STRUCT_KW=327
readonly _SWITCH_KW=328
readonly _TYPEDEF_KW=329
readonly _UNION_KW=330
readonly _UNSIGNED_KW=331
readonly _VOID_KW=332
readonly _VOLATILE_KW=333
readonly _WHILE_KW=334
readonly _VAR_DECL=335
readonly _VAR_DECLS=336
readonly _FUN_DECL=337
readonly _CAST=338
readonly _INTEGER=401
readonly _CHARACTER=402
readonly _STRING=403
readonly _AMP_AMP=404
readonly _AMP_EQ=405
readonly _ARROW=406
readonly _BAR_BAR=407
readonly _BAR_EQ=408
readonly _CARET_EQ=409
readonly _EQ_EQ=410
readonly _GT_EQ=411
readonly _LSHIFT_EQ=412
readonly _LSHIFT=413
readonly _LT_EQ=414
readonly _MINUS_EQ=415
readonly _MINUS_MINUS=416
readonly _EXCL_EQ=417
readonly _PERCENT_EQ=418
readonly _PLUS_EQ=419
readonly _PLUS_PLUS=420
readonly _RSHIFT_EQ=421
readonly _RSHIFT=422
readonly _SLASH_EQ=423
readonly _STAR_EQ=424
readonly _HASH_HASH=425
readonly _PLUS_PLUS_PRE=426
readonly _MINUS_MINUS_PRE=427
readonly _PLUS_PLUS_POST=428
readonly _MINUS_MINUS_POST=429
readonly _MACRO_ARG=499
readonly _IDENTIFIER=500
readonly _TYPE=501
readonly _MACRO=502
: $((str = 0))
_putstr() { let str $2
  while [ $((_$str)) != 0 ] ; do
    printf \\$(((_$str)/64))$(((_$str)/8%8))$(((_$str)%8))
    : $((str += 1))
  done
  endlet $1 str
}

: $((n = 0))
_putint_aux() { let n $2
  if [ $n -le -10 ] ; then
    _putint_aux __ $((n / 10))
  fi
  printf \\$(((__0__ - (n % 10))/64))$(((__0__ - (n % 10))/8%8))$(((__0__ - (n % 10))%8))
  endlet $1 n
}

: $((n = 0))
_putint() { let n $2
  if [ $n -lt 0 ] ; then
    printf \\$(((__MINUS__)/64))$(((__MINUS__)/8%8))$(((__MINUS__)%8))
    _putint_aux __ $n
  else
    _putint_aux __ $((-(n)))
  fi
  endlet $1 n
}

: $((n = 0))
_putintneg() { let n $2
  if [ $n -gt 0 ] ; then
    printf \\$(((__MINUS__)/64))$(((__MINUS__)/8%8))$(((__MINUS__)%8))
    _putint_aux __ $((-(n)))
  else
    _putint_aux __ $n
  fi
  endlet $1 n
}

: $((msg = 0))
_fatal_error() { let msg $2
  _putstr __ $msg
  printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
  exit 1
  endlet $1 msg
}

: $((msg = 0))
_syntax_error() { let msg $2
  _putstr __ $((_$((_include_stack + __filename))))
  printf \\$(((__COLON__)/64))$(((__COLON__)/8%8))$(((__COLON__)%8))
  _putint __ $_last_tok_line_number
  printf \\$(((__COLON__)/64))$(((__COLON__)/8%8))$(((__COLON__)%8))
  _putint __ $_last_tok_column_number
  printf "  syntax error: "
  _putstr __ $msg
  printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
  exit 1
  endlet $1 msg
}

: $((msg = 0))
_missing_feature_error() { let msg $2
  printf "not yet implemented: "
  _putstr __ $msg
  exit 1
  endlet $1 msg
}

: $((n = 0))
_print_dec() { let n $2
  if [ $n -lt 0 ] ; then
    printf \\$(((__MINUS__)/64))$(((__MINUS__)/8%8))$(((__MINUS__)%8))
    _print_dec __ $((-(n)))
  else
    if [ $n -gt 9 ] ; then
      _print_dec __ $((n / 10))
    fi
    printf \\$(((__0__ + (n % 10))/64))$(((__0__ + (n % 10))/8%8))$(((__0__ + (n % 10))%8))
  fi
  endlet $1 n
}

: $((n = 0))
_print_hex() { let n $2
  if [ $n -lt 0 ] ; then
    printf \\$(((__MINUS__)/64))$(((__MINUS__)/8%8))$(((__MINUS__)%8))
    _print_hex __ $((-(n)))
  else
    if [ $n -gt 15 ] ; then
      _print_hex __ $((n >> 4))
    fi
    defstr __str_0 "0123456789abcdef"
    printf \\$(((_$((__str_0 + (n & 15))))/64))$(((_$((__str_0 + (n & 15))))/8%8))$(((_$((__str_0 + (n & 15))))%8))
  fi
  endlet $1 n
}

_ch=0
_tok=0
_val=0
__ALLOC=1 # Starting heap at 1 because 0 is the null pointer.

_malloc() { # $2 = object size
  : $((_$__ALLOC = $2)) # Track object size
  : $(($1 = $__ALLOC + 1))
  : $((__ALLOC += $2 + 1))
}

defarr() { _malloc $1 $2; }

defarr _string_pool 50000
_string_pool_alloc=0
_string_start=0
_hash=0
defarr _heap 200000
_heap_alloc=107
_alloc_result=0
: $((size = 0))
_alloc_obj() { let size $2
  _alloc_result=$_heap_alloc
  : $((_heap_alloc += size))
  if [ $_heap_alloc -gt 200000 ] ; then
    defstr __str_1 "heap overflow"
    _fatal_error __ $__str_1
  fi
  : $(($1 = _alloc_result))
  endlet $1 size
}

: $((result = child1 = child0 = 0))
_cons() { let child0 $2; let child1 $3
  let result
  _alloc_obj result 2
  : $((_$((_heap + result)) = child0))
  : $((_$((_heap + result + 1)) = child1))
  : $(($1 = result))
  endlet $1 result child1 child0
}

: $((pair = 0))
_car() { let pair $2
  : $(($1 = _$((_heap + pair))))
  endlet $1 pair
}

: $((pair = 0))
_cdr() { let pair $2
  : $(($1 = _$((_heap + pair + 1))))
  endlet $1 pair
}

: $((value = pair = 0))
_set_car() { let pair $2; let value $3
  : $((_$((_heap + pair)) = value))
  : $(($1 = value))
  endlet $1 value pair
}

: $((value = pair = 0))
_set_cdr() { let pair $2; let value $3
  : $((_$((_heap + pair + 1)) = value))
  : $(($1 = value))
  endlet $1 value pair
}

_begin_string() {
  _string_start=$_string_pool_alloc
  _hash=0
}

_accum_string() {
  _hash=$(((_ch + (_hash ^ 2764)) % 107))
  : $((_$((_string_pool + _string_pool_alloc)) = _ch))
  : $((_string_pool_alloc += 1))
  if [ $_string_pool_alloc -ge 50000 ] ; then
    defstr __str_2 "string pool overflow"
    _fatal_error __ $__str_2
  fi
}

: $((c = 0))
_accum_string_char() { let c $2
  _hash=$(((c + (_hash ^ 2764)) % 107))
  : $((_$((_string_pool + _string_pool_alloc)) = c))
  : $((_string_pool_alloc += 1))
  if [ $_string_pool_alloc -ge 50000 ] ; then
    defstr __str_3 "string pool overflow"
    _fatal_error __ $__str_3
  fi
  endlet $1 c
}

: $((i = s = 0))
_accum_string_string() { let s $2
  let i
  i=0
  while [ $((_$((_string_pool + s + i)))) != 0 ] ; do
    _accum_string_char __ $((_$((_string_pool + s + i))))
    : $((i += 1))
  done
  endlet $1 i s
}

: $((n = 0))
_accum_string_integer() { let n $2
  if [ $n -lt 0 ] ; then
    _accum_string_char __ $__MINUS__
    _accum_string_integer __ $((-(n)))
  else
    if [ $n -gt 9 ] ; then
      _accum_string_integer __ $((n / 10))
    fi
    _accum_string_char __ $((__0__ + (n % 10)))
  fi
  endlet $1 n
}

_probe=0
_probe_start=0
_c1=0
_c2=0
_end_ident_i=0
_end_ident() {
  : $((_$((_string_pool + _string_pool_alloc)) = 0))
  : $((_string_pool_alloc += 1))
  _probe=$((_$((_heap + _hash))))
  while [ $_probe != 0 ] ; do
    _probe_start=$((_$((_heap + _probe + 1))))
    _end_ident_i=0
    _c1=$((_$((_string_pool + _string_start + _end_ident_i))))
    _c2=$((_$((_string_pool + _probe_start + _end_ident_i))))
    while [ $_c1 = $_c2 ] ; do
      if [ $_c1 = 0 ] ; then
        _string_pool_alloc=$_string_start
        : $(($1 = _probe))
        return
      fi
      : $((_end_ident_i += 1))
      _c1=$((_$((_string_pool + _string_start + _end_ident_i))))
      _c2=$((_$((_string_pool + _probe_start + _end_ident_i))))
    done
    _hash=$_probe
    _probe=$((_$((_heap + _probe))))
  done
  _alloc_obj _probe 4
  : $((_$((_heap + _hash)) = _probe))
  : $((_$((_heap + _probe)) = 0))
  : $((_$((_heap + _probe + 1)) = _string_start))
  : $((_$((_heap + _probe + 2)) = _IDENTIFIER))
  : $((_$((_heap + _probe + 3)) = 0))
  : $(($1 = _probe))
}

defarr _ifdef_stack 20
_ifdef_stack_ix=0
_ifdef_mask=1
_ifdef_nest_level=0
_expand_macro=1
_expand_macro_arg=1
defarr _macro_stack 100
_macro_stack_ix=0
_macro_tok_lst=0
_macro_args=0
_macro_args_count=0
_paste_last_token=0
_flip_ifdef_mask() {
  _ifdef_mask=$((!_ifdef_mask))
}

: $((new_mask = 0))
_push_ifdef_mask() { let new_mask $2
  if [ $_ifdef_stack_ix -ge 20 ] ; then
    defstr __str_4 "Too many nested #ifdef/#ifndef directives. Maximum supported is 20."
    _syntax_error __ $__str_4
  fi
  : $((_$((_ifdef_stack + _ifdef_stack_ix)) = _ifdef_mask))
  : $((_ifdef_stack_ix += 1))
  _ifdef_mask=$new_mask
  endlet $1 new_mask
}

_pop_ifdef_mask() {
  if [ $_ifdef_stack_ix = 0 ] ; then
    defstr __str_5 "Unbalanced #ifdef/#ifndef/#else/#endif directives."
    _syntax_error __ $__str_5
  fi
  : $((_ifdef_stack_ix -= 1))
  _ifdef_mask=$((_$((_ifdef_stack + _ifdef_stack_ix))))
}

_get_ch() {
  _fgetc _ch $_fp
  if [ $_ch = -1 ] ; then
    if [ $((_$((_include_stack + __next)))) != 0 ] ; then
      _fclose __ $((_$((_include_stack + __fp))))
      _include_stack2=$_include_stack
      _include_stack=$((_$((_include_stack + __next))))
      _fp=$((_$((_include_stack + __fp))))
      _line_number=$((_$((_include_stack + __line_number))))
      _column_number=$((_$((_include_stack + __column_number))))
      _free __ $_include_stack2
      _get_ch __ 
    fi
  elif [ $_ch = $__NEWLINE__ ] ; then
    : $((_line_number += 1))
    _column_number=0
  else
    : $((_column_number += 1))
  fi
}

: $((file_name = 0))
_include_file() { let file_name $2
  defstr __str_6 "r"
  _fopen _fp $file_name $__str_6
  _malloc _include_stack2 $((__sizeof__IncludeStack))
  : $((_$((_include_stack2 + __next)) = _include_stack))
  : $((_$((_include_stack2 + __fp)) = _fp))
  : $((_$((_include_stack2 + __filename)) = file_name))
  : $((_$((_include_stack2 + __line_number)) = 1))
  : $((_$((_include_stack2 + __column_number)) = 0))
  if [ $_include_stack != 0 ] ; then
    : $((_$((_include_stack + __line_number)) = _line_number))
    : $((_$((_include_stack + __column_number)) = _column_number))
  fi
  _line_number=1
  _column_number=1
  _include_stack=$_include_stack2
  endlet $1 file_name
}

_IFDEF_ID=0
_IFNDEF_ID=0
_ENDIF_ID=0
_DEFINE_ID=0
_UNDEF_ID=0
_INCLUDE_ID=0
_INCLUDE_SHELL_ID=0
_NOT_SUPPORTED_ID=0
_ARGV__ID=0
_ARGV_ID=0
_IFS_ID=0
_MAIN_ID=0
_PUTCHAR_ID=0
_GETCHAR_ID=0
_EXIT_ID=0
_MALLOC_ID=0
_FREE_ID=0
_PRINTF_ID=0
_FOPEN_ID=0
_FCLOSE_ID=0
_FGETC_ID=0
_PUTSTR_ID=0
_PUTS_ID=0
_READ_ID=0
_WRITE_ID=0
_OPEN_ID=0
_CLOSE_ID=0
_get_tok_macro() {
  _expand_macro=0
  _get_tok __ 
  _expand_macro=1
}

: $((__t1 = ix = val = tok = args = 0))
_lookup_macro_token() { let args $2; let tok $3; let val $4
  let ix; let __t1
  ix=0
  if [ $tok -lt $_IDENTIFIER ] ; then
    _cons $1 $tok $val
    endlet $1 __t1 ix val tok args
    return
  fi
  while [ $args != 0 ] ; do
    if _car __t1 $args; [ $__t1 = $val ] ; then
      break
    fi
    _cdr args $args
    : $((ix += 1))
  done
  if [ $args = 0 ] ; then
    _cons $1 $tok $val
  else
    _cons $1 $_MACRO_ARG $ix
  fi
  endlet $1 __t1 ix val tok args
}

: $((__t3 = __t2 = __t1 = tail = toks = args = 0))
_read_macro_tokens() { let args $2
  let toks; let tail; let __t1; let __t2; let __t3
  toks=0
  if [ $_ch != $__NEWLINE__ ] && [ $_ch != -1 ] ; then
    _get_tok_macro __ 
    _lookup_macro_token __t1 $args $_tok $_val
    _cons toks $__t1 0
    tail=$toks
    while [ $_ch != $__NEWLINE__ ] && [ $_ch != -1 ] ; do
      _get_tok_macro __ 
      _lookup_macro_token __t1 $args $_tok $_val
      _cons _$((_heap + tail + 1)) $__t1 0
      _cdr tail $tail
    done
    if { _car __t2 $toks; _car __t1 $__t2; [ $__t1 = $_HASH_HASH ]; } || { _car __t3 $tail; _car __t2 $__t3; [ $__t2 = $_HASH_HASH ]; } ; then
      defstr __str_7 "'##' cannot appear at either end of a macro expansion"
      _syntax_error __ $__str_7
    fi
  fi
  : $(($1 = toks))
  endlet $1 __t3 __t2 __t1 tail toks args
}

: $((__t1 = args_count = args = macro = 0))
_handle_define() {
  let macro; let args; let args_count; let __t1
  args=0
  args_count=-1
  _get_tok_macro __ 
  if [ $_tok = $_IDENTIFIER ] || [ $_tok = $_MACRO ] ; then
    : $((_$((_heap + _val + 2)) = _MACRO))
    macro=$_val
  else
    printf "tok="
    _putint __ $_tok
    printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
    defstr __str_8 "#define directive can only be followed by a identifier"
    _syntax_error __ $__str_8
  fi
  if [ $_ch = $__LPAREN__ ] ; then
    args_count=0
    _get_ch __ 
    while [ $_ch != $__NEWLINE__ ] && [ $_ch != -1 ] ; do
      if [ $_ch = $__COMMA__ ] ; then
        _get_ch __ 
        continue
      elif [ $_ch = $__RPAREN__ ] ; then
        _get_ch __ 
        break
      fi
      _get_tok_macro __ 
      _cons args $_val $args
      : $((args_count += 1))
    done
  fi
  while [ $_ch != $__NEWLINE__ ] && [ $_ch != -1 ] && [ $_ch -le $__SPACE__ ] ; do
    _get_ch __ 
  done
  if [ $_ch = $__NEWLINE__ ] || [ $_ch = -1 ] ; then
    _cons _$((_heap + macro + 3)) 0 $args_count
  else
    _read_macro_tokens __t1 $args
    _cons _$((_heap + macro + 3)) $__t1 $args_count
  fi
  endlet $1 __t1 args_count args macro
}

_handle_include() {
  _get_tok __ 
  if [ $_tok = $_STRING ] ; then
    _include_file __ $((_string_pool + _val))
  elif [ $_tok = $__LT__ ] ; then
    _get_tok __ 
    while [ $_tok != $__GT__ ] ; do
      _get_tok __ 
    done
  else
    printf "tok="
    _putint __ $_tok
    printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
    defstr __str_9 "expected string to #include directive"
    _syntax_error __ $__str_9
  fi
}

: $((prev_ifdef_mask = 0))
_handle_preprocessor_directive() {
  let prev_ifdef_mask
  prev_ifdef_mask=$_ifdef_mask
  _get_ch __ 
  _ifdef_mask=1
  _get_tok __ 
  _ifdef_mask=$prev_ifdef_mask
  if [ $_tok = $_IDENTIFIER ] && [ $_val = $_IFDEF_ID ] ; then
    _ifdef_mask=1
    _get_tok_macro __ 
    _ifdef_mask=$prev_ifdef_mask
    if [ $_ifdef_mask != 0 ] ; then
      _push_ifdef_mask __ $((_tok == _MACRO))
    else
      : $((_ifdef_nest_level += 1))
    fi
  elif [ $_tok = $_IDENTIFIER ] && [ $_val = $_IFNDEF_ID ] ; then
    _ifdef_mask=1
    _get_tok_macro __ 
    _ifdef_mask=$prev_ifdef_mask
    if [ $_ifdef_mask != 0 ] ; then
      _push_ifdef_mask __ $((_tok != _MACRO))
    else
      : $((_ifdef_nest_level += 1))
    fi
  elif [ $_tok = $_ELSE_KW ] ; then
    if [ $_ifdef_mask != 0 ] || [ $_ifdef_nest_level = 0 ] ; then
      _flip_ifdef_mask __ 
    fi
  elif [ $_tok = $_IDENTIFIER ] && [ $_val = $_ENDIF_ID ] ; then
    if [ $_ifdef_mask != 0 ] || [ $_ifdef_nest_level = 0 ] ; then
      _pop_ifdef_mask __ 
    else
      : $((_ifdef_nest_level -= 1))
    fi
  elif [ $_ifdef_mask != 0 ] ; then
    if [ $_tok = $_IDENTIFIER ] && [ $_val = $_INCLUDE_ID ] ; then
      _handle_include __ 
    elif [ $_tok = $_IDENTIFIER ] && [ $_val = $_INCLUDE_SHELL_ID ] ; then
      _handle_shell_include __ 
    elif [ $_tok = $_IDENTIFIER ] && [ $_val = $_UNDEF_ID ] ; then
      _get_tok_macro __ 
      if [ $_tok = $_MACRO ] ; then
        : $((_$((_heap + _val + 2)) = _IDENTIFIER))
      else
        printf "tok="
        _putint __ $_tok
        printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
        defstr __str_10 "#undef directive can only be followed by a identifier"
        _syntax_error __ $__str_10
      fi
    elif [ $_tok = $_IDENTIFIER ] && [ $_val = $_DEFINE_ID ] ; then
      _handle_define __ 
    else
      printf "tok="
      _putint __ $_tok
      printf ": "
      _putstr __ $((_string_pool + _$((_heap + _val + 1))))
      printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
      defstr __str_11 "unsupported preprocessor directive"
      _syntax_error __ $__str_11
    fi
  else
    while [ $_ch != $__NEWLINE__ ] && [ $_ch != -1 ] ; do
      _get_ch __ 
    done
  fi
  if [ $_ch != $__NEWLINE__ ] && [ $_ch != -1 ] ; then
    printf "ch="
    _putint __ $_ch
    printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
    defstr __str_12 "preprocessor expected end of line"
    _syntax_error __ $__str_12
  fi
  endlet $1 prev_ifdef_mask
}

_get_ident() {
  _begin_string __ 
  while { [ $__A__ -le $_ch ] && [ $_ch -le $__Z__ ]; } || { [ $__a__ -le $_ch ] && [ $_ch -le $__z__ ]; } || { [ $__0__ -le $_ch ] && [ $_ch -le $__9__ ]; } || [ $_ch = $__UNDERSCORE__ ] ; do
    _accum_string __ 
    _get_ch __ 
  done
  _end_ident _val 
  _tok=$((_$((_heap + _val + 2))))
}

: $((prev_ch = i = name = tok = 0))
_init_ident() { let tok $2; let name $3
  let i; let prev_ch
  i=0
  prev_ch=$_ch
  _begin_string __ 
  while [ $((_$((name + i)))) != 0 ] ; do
    _ch=$((_$((name + i))))
    _accum_string __ 
    : $((i += 1))
  done
  _end_ident i 
  : $((_$((_heap + i + 2)) = tok))
  _ch=$prev_ch
  : $(($1 = i))
  endlet $1 prev_ch i name tok
}

: $((i = 0))
_init_ident_table() {
  let i
  i=0
  while [ $i -lt 107 ] ; do
    : $((_$((_heap + i)) = 0))
    : $((i += 1))
  done
  defstr __str_13 "auto"
  _init_ident __ $_AUTO_KW $__str_13
  defstr __str_14 "break"
  _init_ident __ $_BREAK_KW $__str_14
  defstr __str_15 "case"
  _init_ident __ $_CASE_KW $__str_15
  defstr __str_16 "char"
  _init_ident __ $_CHAR_KW $__str_16
  defstr __str_17 "const"
  _init_ident __ $_CONST_KW $__str_17
  defstr __str_18 "continue"
  _init_ident __ $_CONTINUE_KW $__str_18
  defstr __str_19 "default"
  _init_ident __ $_DEFAULT_KW $__str_19
  defstr __str_20 "do"
  _init_ident __ $_DO_KW $__str_20
  defstr __str_21 "double"
  _init_ident __ $_DOUBLE_KW $__str_21
  defstr __str_22 "else"
  _init_ident __ $_ELSE_KW $__str_22
  defstr __str_23 "enum"
  _init_ident __ $_ENUM_KW $__str_23
  defstr __str_24 "error"
  _init_ident __ $_ERROR_KW $__str_24
  defstr __str_25 "extern"
  _init_ident __ $_EXTERN_KW $__str_25
  defstr __str_26 "float"
  _init_ident __ $_FLOAT_KW $__str_26
  defstr __str_27 "for"
  _init_ident __ $_FOR_KW $__str_27
  defstr __str_28 "goto"
  _init_ident __ $_GOTO_KW $__str_28
  defstr __str_29 "if"
  _init_ident __ $_IF_KW $__str_29
  defstr __str_30 "int"
  _init_ident __ $_INT_KW $__str_30
  defstr __str_31 "long"
  _init_ident __ $_LONG_KW $__str_31
  defstr __str_32 "register"
  _init_ident __ $_REGISTER_KW $__str_32
  defstr __str_33 "return"
  _init_ident __ $_RETURN_KW $__str_33
  defstr __str_34 "short"
  _init_ident __ $_SHORT_KW $__str_34
  defstr __str_35 "signed"
  _init_ident __ $_SIGNED_KW $__str_35
  defstr __str_36 "sizeof"
  _init_ident __ $_SIZEOF_KW $__str_36
  defstr __str_37 "static"
  _init_ident __ $_STATIC_KW $__str_37
  defstr __str_38 "struct"
  _init_ident __ $_STRUCT_KW $__str_38
  defstr __str_39 "switch"
  _init_ident __ $_SWITCH_KW $__str_39
  defstr __str_40 "typedef"
  _init_ident __ $_TYPEDEF_KW $__str_40
  defstr __str_41 "union"
  _init_ident __ $_UNION_KW $__str_41
  defstr __str_42 "unsigned"
  _init_ident __ $_UNSIGNED_KW $__str_42
  defstr __str_43 "void"
  _init_ident __ $_VOID_KW $__str_43
  defstr __str_44 "volatile"
  _init_ident __ $_VOLATILE_KW $__str_44
  defstr __str_45 "while"
  _init_ident __ $_WHILE_KW $__str_45
  defstr __str_46 "ifdef"
  _init_ident _IFDEF_ID $_IDENTIFIER $__str_46
  defstr __str_47 "ifndef"
  _init_ident _IFNDEF_ID $_IDENTIFIER $__str_47
  defstr __str_48 "endif"
  _init_ident _ENDIF_ID $_IDENTIFIER $__str_48
  defstr __str_49 "define"
  _init_ident _DEFINE_ID $_IDENTIFIER $__str_49
  defstr __str_50 "undef"
  _init_ident _UNDEF_ID $_IDENTIFIER $__str_50
  defstr __str_51 "include"
  _init_ident _INCLUDE_ID $_IDENTIFIER $__str_51
  defstr __str_52 "include_shell"
  _init_ident _INCLUDE_SHELL_ID $_IDENTIFIER $__str_52
  defstr __str_53 "argv"
  _init_ident _ARGV_ID $_IDENTIFIER $__str_53
  defstr __str_54 "argv_"
  _init_ident _ARGV__ID $_IDENTIFIER $__str_54
  defstr __str_55 "IFS"
  _init_ident _IFS_ID $_IDENTIFIER $__str_55
  defstr __str_56 "main"
  _init_ident _MAIN_ID $_IDENTIFIER $__str_56
  defstr __str_57 "putchar"
  _init_ident _PUTCHAR_ID $_IDENTIFIER $__str_57
  defstr __str_58 "getchar"
  _init_ident _GETCHAR_ID $_IDENTIFIER $__str_58
  defstr __str_59 "exit"
  _init_ident _EXIT_ID $_IDENTIFIER $__str_59
  defstr __str_60 "malloc"
  _init_ident _MALLOC_ID $_IDENTIFIER $__str_60
  defstr __str_61 "free"
  _init_ident _FREE_ID $_IDENTIFIER $__str_61
  defstr __str_62 "printf"
  _init_ident _PRINTF_ID $_IDENTIFIER $__str_62
  defstr __str_63 "fopen"
  _init_ident _FOPEN_ID $_IDENTIFIER $__str_63
  defstr __str_64 "fclose"
  _init_ident _FCLOSE_ID $_IDENTIFIER $__str_64
  defstr __str_65 "fgetc"
  _init_ident _FGETC_ID $_IDENTIFIER $__str_65
  defstr __str_66 "putstr"
  _init_ident _PUTSTR_ID $_IDENTIFIER $__str_66
  defstr __str_67 "puts"
  _init_ident _PUTS_ID $_IDENTIFIER $__str_67
  defstr __str_68 "read"
  _init_ident _READ_ID $_IDENTIFIER $__str_68
  defstr __str_69 "write"
  _init_ident _WRITE_ID $_IDENTIFIER $__str_69
  defstr __str_70 "open"
  _init_ident _OPEN_ID $_IDENTIFIER $__str_70
  defstr __str_71 "close"
  _init_ident _CLOSE_ID $_IDENTIFIER $__str_71
  defstr __str_72 "NOT_SUPPORTED"
  _init_ident _NOT_SUPPORTED_ID $_IDENTIFIER $__str_72
  endlet $1 i
}

_init_pnut_macros() {
  defstr __str_73 "PNUT_CC"
  _init_ident __ $_MACRO $__str_73
}

: $((digit = base = 0))
_accum_digit() { let base $2
  let digit
  digit=99
  if [ $__0__ -le $_ch ] && [ $_ch -le $__9__ ] ; then
    digit=$((_ch - __0__))
  elif [ $__A__ -le $_ch ] && [ $_ch -le $__Z__ ] ; then
    digit=$(((_ch - __A__) + 10))
  elif [ $__a__ -le $_ch ] && [ $_ch -le $__z__ ] ; then
    digit=$(((_ch - __a__) + 10))
  fi
  if [ $digit -ge $base ] ; then
    : $(($1 = 0))
  else
    _val=$(((_val * base) - digit))
    _get_ch __ 
    : $(($1 = 1))
  fi
  endlet $1 digit base
}

: $((__t1 = 0))
_get_string_char() {
  let __t1
  _val=$_ch
  _get_ch __ 
  if [ $_val = $__BACKSLASH__ ] ; then
    if [ $__0__ -le $_ch ] && [ $_ch -le $__7__ ] ; then
      _val=0
      _accum_digit __ 8
      _accum_digit __ 8
      _accum_digit __ 8
      _val=$((-((_val % 256))))
    elif [ $_ch = $__x__ ] || [ $_ch = $__X__ ] ; then
      _get_ch __ 
      _val=0
      if _accum_digit __t1 16; [ $__t1 != 0 ] ; then
        _accum_digit __ 16
      else
        defstr __str_74 "invalid hex escape -- it must have at least one digit"
        _syntax_error __ $__str_74
      fi
      _val=$((-((_val % 256))))
    else
      if [ $_ch = $__a__ ] ; then
        _val=7
      elif [ $_ch = $__b__ ] ; then
        _val=8
      elif [ $_ch = $__f__ ] ; then
        _val=12
      elif [ $_ch = $__n__ ] ; then
        _val=10
      elif [ $_ch = $__r__ ] ; then
        _val=13
      elif [ $_ch = $__t__ ] ; then
        _val=9
      elif [ $_ch = $__v__ ] ; then
        _val=11
      elif [ $_ch = $__BACKSLASH__ ] || [ $_ch = $__QUOTE__ ] || [ $_ch = $__DQUOTE__ ] ; then
        _val=$_ch
      else
        defstr __str_75 "unimplemented string character escape"
        _syntax_error __ $__str_75
      fi
      _get_ch __ 
    fi
  fi
  endlet $1 __t1
}

: $((__t1 = tail = parens_depth = arg_tokens = 0))
_macro_parse_argument() {
  let arg_tokens; let parens_depth; let tail; let __t1
  arg_tokens=0
  parens_depth=0
  while { [ $parens_depth -gt 0 ] || { [ $_tok != $__COMMA__ ] && [ $_tok != $__RPAREN__ ]; }; } && [ $_tok != -1 ] ; do
    if [ $_tok = $__LPAREN__ ] ; then
      : $((parens_depth += 1))
    fi
    if [ $_tok = $__RPAREN__ ] ; then
      : $((parens_depth -= 1))
    fi
    if [ $arg_tokens = 0 ] ; then
      _cons __t1 $_tok $_val
      _cons arg_tokens $__t1 0
      tail=$arg_tokens
    else
      _cons __t1 $_tok $_val
      _cons _$((_heap + tail + 1)) $__t1 0
      _cdr tail $tail
    fi
    _get_tok_macro __ 
  done
  : $(($1 = arg_tokens))
  endlet $1 __t1 tail parens_depth arg_tokens
}

: $((expected_argc = macro_args_count = 0))
_check_macro_arity() { let macro_args_count $2; let expected_argc $3
  if [ $macro_args_count != $expected_argc ] ; then
    printf "expected_argc="
    _putint __ $expected_argc
    printf " != macro_args_count="
    _putint __ $macro_args_count
    printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
    defstr __str_76 "macro argument count mismatch"
    _syntax_error __ $__str_76
  fi
  endlet $1 expected_argc macro_args_count
}

: $((__t1 = macro_args_count = args = expected_argc = 0))
_get_macro_args_toks() { let expected_argc $2
  let args; let macro_args_count; let __t1
  args=0
  macro_args_count=0
  _get_tok_macro __ 
  if [ $_tok != $__LPAREN__ ] ; then
    _check_macro_arity __ $macro_args_count $expected_argc
    : $(($1 = -1))
    endlet $1 __t1 macro_args_count args expected_argc
    return
  fi
  _get_tok_macro __ 
  while [ $_tok != $__RPAREN__ ] && [ $_tok != -1 ] ; do
    if [ $_tok = $__COMMA__ ] ; then
      _get_tok_macro __ 
      continue
    fi
    _macro_parse_argument __t1 
    _cons args $__t1 $args
    : $((macro_args_count += 1))
  done
  _expect_tok __ $__RPAREN__
  _check_macro_arity __ $macro_args_count $expected_argc
  : $(($1 = args))
  endlet $1 __t1 macro_args_count args expected_argc
}

: $((arg = ix = 0))
_get_macro_arg() { let ix $2
  let arg
  arg=$_macro_args
  while [ $ix -gt 0 ] ; do
    if [ $arg = 0 ] ; then
      defstr __str_77 "too few arguments to macro"
      _syntax_error __ $__str_77
    fi
    _cdr arg $arg
    : $((ix -= 1))
  done
  _car $1 $arg
  endlet $1 arg ix
}

: $((args = tokens = 0))
_push_macro() { let tokens $2; let args $3
  if [ $tokens != 0 ] ; then
    if [ $_macro_tok_lst != 0 ] ; then
      if [ $((_macro_stack_ix + 2)) -ge 100 ] ; then
        defstr __str_78 "Macro recursion depth exceeded."
        _syntax_error __ $__str_78
      fi
      : $((_$((_macro_stack + _macro_stack_ix)) = _macro_tok_lst))
      : $((_$((_macro_stack + _macro_stack_ix + 1)) = _macro_args))
      : $((_macro_stack_ix += 2))
    fi
    _macro_tok_lst=$tokens
    _macro_args=$args
  fi
  endlet $1 args tokens
}

: $((tokens = 0))
_push_tokens() { let tokens $2
  _push_macro __ $tokens 0
  endlet $1 tokens
}

: $((__t2 = __t1 = new_macro_args = macro = 0))
_attempt_macro_expansion() { let macro $2
  let new_macro_args; let __t1; let __t2
  macro=$_val
  if _cdr __t1 $((_$((_heap + macro + 3)))); [ $__t1 = -1 ] ; then
    _car __t1 $((_$((_heap + macro + 3))))
    _push_macro __ $__t1 0
    : $(($1 = 1))
  else
    _cdr __t1 $((_$((_heap + macro + 3))))
    _get_macro_args_toks new_macro_args $__t1
    _cons __t2 $_tok $_val
    _cons __t1 $__t2 0
    _push_macro __ $__t1 $new_macro_args
    if [ $new_macro_args = -1 ] ; then
      _tok=$_IDENTIFIER
      _val=$macro
      : $(($1 = 0))
    else
      _car __t1 $((_$((_heap + macro + 3))))
      _push_macro __ $__t1 $new_macro_args
      : $(($1 = 1))
    fi
  fi
  endlet $1 __t2 __t1 new_macro_args macro
}

: $((__t2 = __t1 = arg = 0))
_stringify() {
  let arg; let __t1; let __t2
  _expand_macro_arg=0
  _get_tok_macro __ 
  _expand_macro_arg=1
  if [ $_tok != $_MACRO_ARG ] ; then
    printf "tok="
    _putint __ $_tok
    printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
    defstr __str_79 "expected macro argument after #"
    _syntax_error __ $__str_79
  fi
  _get_macro_arg arg $_val
  _tok=$_STRING
  if { _car __t2 $arg; _car __t1 $__t2; [ $__t1 = $_IDENTIFIER ]; } && { _cdr __t2 $arg; [ $__t2 = 0 ]; } ; then
    _car __t2 $arg
    _cdr __t1 $__t2
    _val=$((_$((_heap + __t1 + 1))))
  else
    _val=$((_$((_heap + _NOT_SUPPORTED_ID + 1))))
  fi
  endlet $1 __t2 __t1 arg
}

: $((right_digits = result = right_val = left_val = 0))
_paste_integers() { let left_val $2; let right_val $3
  let result; let right_digits
  result=$left_val
  right_digits=$right_val
  while [ $right_digits -gt 0 ] ; do
    : $((result *= 10))
    : $((right_digits /= 10))
  done
  : $(($1 = result + right_val))
  endlet $1 right_digits result right_val left_val
}

: $((__t1 = right_val = right_tok = left_val = left_tok = 0))
_paste_tokens() { let left_tok $2; let left_val $3
  let right_tok; let right_val; let __t1
  _get_tok_macro __ 
  right_tok=$_tok
  right_val=$_val
  if [ $left_tok = $_IDENTIFIER ] || [ $left_tok = $_MACRO ] ; then
    _begin_string __ 
    _accum_string_string __ $((_$((_heap + left_val + 1))))
    if [ $right_tok = $_IDENTIFIER ] || [ $right_tok = $_MACRO ] ; then
      _accum_string_string __ $((_$((_heap + right_val + 1))))
    elif [ $right_tok = $_INTEGER ] ; then
      _accum_string_integer __ $((-(right_val)))
    else
      printf "left_tok="
      _putint __ $left_tok
      printf ", right_tok="
      _putint __ $right_tok
      printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
      defstr __str_80 "cannot paste an identifier with a non-identifier or non-negative integer"
      _syntax_error __ $__str_80
    fi
    _end_ident _val 
    _tok=$((_$((_heap + _val + 2))))
  elif [ $left_tok = $_INTEGER ] ; then
    if [ $right_tok = $_INTEGER ] ; then
      _paste_integers __t1 $((-(left_val))) $((-(right_val)))
      _val=$((-(__t1)))
    else
      printf "left_tok="
      _putint __ $left_tok
      printf ", right_tok="
      _putint __ $right_tok
      printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
      defstr __str_81 "cannot paste an integer with a non-integer"
      _syntax_error __ $__str_81
    fi
  else
    printf "left_tok="
    _putint __ $left_tok
    printf ", right_tok="
    _putint __ $right_tok
    printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
    defstr __str_82 "cannot paste a non-identifier or non-integer"
    _syntax_error __ $__str_82
  fi
  endlet $1 __t1 right_val right_tok left_val left_tok
}

: $((__t2 = __t1 = prev_tok_column_number = prev_tok_line_number = first_time = 0))
_get_tok() {
  let first_time; let prev_tok_line_number; let prev_tok_column_number; let __t1; let __t2
  first_time=1
  prev_tok_line_number=$_line_number
  prev_tok_column_number=$_column_number
  while [ $first_time != 0 ] || [ $((!_ifdef_mask)) != 0 ] ; do
    first_time=0
    while [ 1 != 0 ] ; do
      if [ $_macro_tok_lst != 0 ] ; then
        _car __t1 $_macro_tok_lst
        _car _tok $__t1
        _car __t1 $_macro_tok_lst
        _cdr _val $__t1
        _cdr _macro_tok_lst $_macro_tok_lst
        if [ $_tok -ge $_IDENTIFIER ] ; then
          _tok=$((_$((_heap + _val + 2))))
        fi
        if [ $_macro_tok_lst != 0 ] && { _car __t2 $_macro_tok_lst; _car __t1 $__t2; [ $__t1 = $_HASH_HASH ]; } ; then
          if [ $_tok = $_MACRO ] || [ $_tok = $_MACRO_ARG ] ; then
            _cdr _macro_tok_lst $_macro_tok_lst
            _paste_last_token=1
          else
            _cdr _macro_tok_lst $_macro_tok_lst
            _paste_tokens __ $_tok $_val
            break
          fi
        elif [ $_macro_tok_lst = 0 ] && [ $_paste_last_token != 0 ] ; then
          if [ $_macro_stack_ix = 0 ] ; then
            defstr __str_83 "## cannot appear at the end of a macro expansion"
            _syntax_error __ $__str_83
          fi
          : $((_macro_stack_ix -= 2))
          _macro_tok_lst=$((_$((_macro_stack + _macro_stack_ix))))
          _macro_args=$((_$((_macro_stack + _macro_stack_ix + 1))))
          _paste_last_token=0
          _paste_tokens __ $_tok $_val
        fi
        if [ $_tok = $_MACRO ] ; then
          if _attempt_macro_expansion __t1 $_val; [ $__t1 != 0 ] ; then
            continue
          fi
          break
        elif [ $_tok = $_MACRO_ARG ] && [ $_expand_macro_arg != 0 ] ; then
          _get_macro_arg __t1 $_val
          _push_macro __ $__t1 0
          continue
        elif [ $_tok = $__SHARP__ ] ; then
          _stringify __ 
          break
        fi
        break
      elif [ $_macro_stack_ix != 0 ] ; then
        : $((_macro_stack_ix -= 2))
        _macro_tok_lst=$((_$((_macro_stack + _macro_stack_ix))))
        _macro_args=$((_$((_macro_stack + _macro_stack_ix + 1))))
        continue
      elif [ $_ch -le $__SPACE__ ] ; then
        if [ $_ch = -1 ] ; then
          _tok=-1
          break
        fi
        if [ $_ch = $__NEWLINE__ ] ; then
          _tok=$_ch
        fi
        _get_ch __ 
        while [ 0 -le $_ch ] && [ $_ch -le $__SPACE__ ] ; do
          if [ $_ch = $__NEWLINE__ ] ; then
            _tok=$_ch
          fi
          _get_ch __ 
        done
        if [ $_tok = $__NEWLINE__ ] && [ $_ch = $__SHARP__ ] ; then
          _handle_preprocessor_directive __ 
        fi
      elif { [ $__a__ -le $_ch ] && [ $_ch -le $__z__ ]; } || { [ $__A__ -le $_ch ] && [ $_ch -le $__Z__ ]; } || [ $_ch = $__UNDERSCORE__ ] ; then
        _get_ident __ 
        if [ $_tok = $_MACRO ] ; then
          if [ $_ifdef_mask != 0 ] && [ $_expand_macro != 0 ] ; then
            if _attempt_macro_expansion __t1 $_val; [ $__t1 != 0 ] ; then
              continue
            fi
            break
          fi
        fi
        break
      elif [ $__0__ -le $_ch ] && [ $_ch -le $__9__ ] ; then
        _val=$((__0__ - _ch))
        _get_ch __ 
        if [ $_val = 0 ] ; then
          if [ $_ch = $__x__ ] || [ $_ch = $__X__ ] ; then
            _get_ch __ 
            _val=0
            if _accum_digit __t1 16; [ $__t1 != 0 ] ; then
              while _accum_digit __t1 16; [ $__t1 != 0 ] ; do
                :
              done
            else
              defstr __str_84 "invalid hex integer -- it must have at least one digit"
              _syntax_error __ $__str_84
            fi
          else
            while _accum_digit __t1 8; [ $__t1 != 0 ] ; do
              :
            done
          fi
        else
          while _accum_digit __t1 10; [ $__t1 != 0 ] ; do
            :
          done
        fi
        _tok=$_INTEGER
        break
      elif [ $_ch = $__QUOTE__ ] ; then
        _get_ch __ 
        _get_string_char __ 
        if [ $_ch != $__QUOTE__ ] ; then
          defstr __str_85 "unterminated character literal"
          _syntax_error __ $__str_85
        fi
        _get_ch __ 
        _tok=$_CHARACTER
        break
      elif [ $_ch = $__DQUOTE__ ] ; then
        _get_ch __ 
        _begin_string __ 
        while [ $_ch != $__DQUOTE__ ] && [ $_ch != -1 ] ; do
          _get_string_char __ 
          _tok=$_ch
          _ch=$_val
          _accum_string __ 
          _ch=$_tok
        done
        if [ $_ch != $__DQUOTE__ ] ; then
          defstr __str_86 "unterminated string literal"
          _syntax_error __ $__str_86
        fi
        _ch=0
        _accum_string __ 
        _get_ch __ 
        _val=$_string_start
        _tok=$_STRING
        break
      else
        _tok=$_ch
        if [ $_ch = $__SLASH__ ] ; then
          _get_ch __ 
          if [ $_ch = $__STAR__ ] ; then
            _get_ch __ 
            _tok=$_ch
            while { [ $_tok != $__STAR__ ] || [ $_ch != $__SLASH__ ]; } && [ $_ch != -1 ] ; do
              _tok=$_ch
              _get_ch __ 
            done
            if [ $_ch = -1 ] ; then
              defstr __str_87 "unterminated comment"
              _syntax_error __ $__str_87
            fi
            _get_ch __ 
          elif [ $_ch = $__SLASH__ ] ; then
            while [ $_ch != $__NEWLINE__ ] && [ $_ch != -1 ] ; do
              _get_ch __ 
            done
          else
            if [ $_ch = $__EQ__ ] ; then
              _get_ch __ 
              _tok=$_SLASH_EQ
            fi
            break
          fi
        elif [ $_ch = $__AMP__ ] ; then
          _get_ch __ 
          if [ $_ch = $__AMP__ ] ; then
            _get_ch __ 
            _tok=$_AMP_AMP
          elif [ $_ch = $__EQ__ ] ; then
            _get_ch __ 
            _tok=$_AMP_EQ
          fi
          break
        elif [ $_ch = $__BAR__ ] ; then
          _get_ch __ 
          if [ $_ch = $__BAR__ ] ; then
            _get_ch __ 
            _tok=$_BAR_BAR
          elif [ $_ch = $__EQ__ ] ; then
            _get_ch __ 
            _tok=$_BAR_EQ
          fi
          break
        elif [ $_ch = $__LT__ ] ; then
          _get_ch __ 
          if [ $_ch = $__EQ__ ] ; then
            _get_ch __ 
            _tok=$_LT_EQ
          elif [ $_ch = $__LT__ ] ; then
            _get_ch __ 
            if [ $_ch = $__EQ__ ] ; then
              _get_ch __ 
              _tok=$_LSHIFT_EQ
            else
              _tok=$_LSHIFT
            fi
          fi
          break
        elif [ $_ch = $__GT__ ] ; then
          _get_ch __ 
          if [ $_ch = $__EQ__ ] ; then
            _get_ch __ 
            _tok=$_GT_EQ
          elif [ $_ch = $__GT__ ] ; then
            _get_ch __ 
            if [ $_ch = $__EQ__ ] ; then
              _get_ch __ 
              _tok=$_RSHIFT_EQ
            else
              _tok=$_RSHIFT
            fi
          fi
          break
        elif [ $_ch = $__EQ__ ] ; then
          _get_ch __ 
          if [ $_ch = $__EQ__ ] ; then
            _get_ch __ 
            _tok=$_EQ_EQ
          fi
          break
        elif [ $_ch = $__EXCL__ ] ; then
          _get_ch __ 
          if [ $_ch = $__EQ__ ] ; then
            _get_ch __ 
            _tok=$_EXCL_EQ
          fi
          break
        elif [ $_ch = $__PLUS__ ] ; then
          _get_ch __ 
          if [ $_ch = $__EQ__ ] ; then
            _get_ch __ 
            _tok=$_PLUS_EQ
          elif [ $_ch = $__PLUS__ ] ; then
            _get_ch __ 
            _tok=$_PLUS_PLUS
          fi
          break
        elif [ $_ch = $__MINUS__ ] ; then
          _get_ch __ 
          if [ $_ch = $__EQ__ ] ; then
            _get_ch __ 
            _tok=$_MINUS_EQ
          elif [ $_ch = $__GT__ ] ; then
            _get_ch __ 
            _tok=$_ARROW
          elif [ $_ch = $__MINUS__ ] ; then
            _get_ch __ 
            _tok=$_MINUS_MINUS
          fi
          break
        elif [ $_ch = $__STAR__ ] ; then
          _get_ch __ 
          if [ $_ch = $__EQ__ ] ; then
            _get_ch __ 
            _tok=$_STAR_EQ
          fi
          break
        elif [ $_ch = $__PERCENT__ ] ; then
          _get_ch __ 
          if [ $_ch = $__EQ__ ] ; then
            _get_ch __ 
            _tok=$_PERCENT_EQ
          fi
          break
        elif [ $_ch = $__CARET__ ] ; then
          _get_ch __ 
          if [ $_ch = $__EQ__ ] ; then
            _get_ch __ 
            _tok=$_CARET_EQ
          fi
          break
        elif [ $_ch = $__SHARP__ ] ; then
          _get_ch __ 
          if [ $_ch = $__SHARP__ ] ; then
            _get_ch __ 
            _tok=$_HASH_HASH
          fi
          break
        elif [ $_ch = $__TILDE__ ] || [ $_ch = $__PERIOD__ ] || [ $_ch = $__QUESTION__ ] || [ $_ch = $__COMMA__ ] || [ $_ch = $__COLON__ ] || [ $_ch = $__SEMICOLON__ ] || [ $_ch = $__LPAREN__ ] || [ $_ch = $__RPAREN__ ] || [ $_ch = $__LBRACK__ ] || [ $_ch = $__RBRACK__ ] || [ $_ch = $__LBRACE__ ] || [ $_ch = $__RBRACE__ ] ; then
          _tok=$_ch
          _get_ch __ 
          break
        elif [ $_ch = $__BACKSLASH__ ] ; then
          _get_ch __ 
          if [ $_ch = $__NEWLINE__ ] ; then
            _get_ch __ 
          else
            printf "ch="
            _putint __ $_ch
            printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
            defstr __str_88 "unexpected character after backslash"
            _syntax_error __ $__str_88
          fi
        else
          printf "ch="
          _putint __ $_ch
          printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
          defstr __str_89 "invalid token"
          _syntax_error __ $__str_89
        fi
      fi
    done
  done
  _last_tok_line_number=$prev_tok_line_number
  _last_tok_column_number=$prev_tok_column_number
  endlet $1 __t2 __t1 prev_tok_column_number prev_tok_line_number first_time
}

: $((node = 0))
_get_op() { let node $2
  : $(($1 = _$((_heap + node)) & 1023))
  endlet $1 node
}

: $((node = 0))
_get_nb_children() { let node $2
  : $(($1 = _$((_heap + node)) >> 10))
  endlet $1 node
}

: $((node = 0))
_get_val() { let node $2
  : $(($1 = _$((_heap + node + 1))))
  endlet $1 node
}

: $((val = node = 0))
_set_val() { let node $2; let val $3
  : $((_$((_heap + node + 1)) = val))
  endlet $1 val node
}

: $((i = node = 0))
_get_child() { let node $2; let i $3
  : $(($1 = _$((_heap + node + i + 1))))
  endlet $1 i node
}

: $((child = i = node = 0))
_set_child() { let node $2; let i $3; let child $4
  : $((_$((_heap + node + i + 1)) = child))
  endlet $1 child i node
}

_ast_result=0
: $((val = op = 0))
_new_ast0() { let op $2; let val $3
  _alloc_obj _ast_result 2
  : $((_$((_heap + _ast_result)) = op))
  _set_val __ $_ast_result $val
  : $(($1 = _ast_result))
  endlet $1 val op
}

: $((child0 = op = 0))
_new_ast1() { let op $2; let child0 $3
  _alloc_obj _ast_result 2
  : $((_$((_heap + _ast_result)) = op + 1024))
  _set_child __ $_ast_result 0 $child0
  : $(($1 = _ast_result))
  endlet $1 child0 op
}

: $((child1 = child0 = op = 0))
_new_ast2() { let op $2; let child0 $3; let child1 $4
  _alloc_obj _ast_result 3
  : $((_$((_heap + _ast_result)) = op + 2048))
  _set_child __ $_ast_result 0 $child0
  _set_child __ $_ast_result 1 $child1
  : $(($1 = _ast_result))
  endlet $1 child1 child0 op
}

: $((child2 = child1 = child0 = op = 0))
_new_ast3() { let op $2; let child0 $3; let child1 $4; let child2 $5
  _alloc_obj _ast_result 4
  : $((_$((_heap + _ast_result)) = op + 3072))
  _set_child __ $_ast_result 0 $child0
  _set_child __ $_ast_result 1 $child1
  _set_child __ $_ast_result 2 $child2
  : $(($1 = _ast_result))
  endlet $1 child2 child1 child0 op
}

: $((child3 = child2 = child1 = child0 = op = 0))
_new_ast4() { let op $2; let child0 $3; let child1 $4; let child2 $5; let child3 $6
  _alloc_obj _ast_result 5
  : $((_$((_heap + _ast_result)) = op + 4096))
  _set_child __ $_ast_result 0 $child0
  _set_child __ $_ast_result 1 $child1
  _set_child __ $_ast_result 2 $child2
  _set_child __ $_ast_result 3 $child3
  : $(($1 = _ast_result))
  endlet $1 child3 child2 child1 child0 op
}

: $((__t1 = i = nb_children = orig = 0))
_clone_ast() { let orig $2
  let nb_children; let i; let __t1
  _get_nb_children nb_children $orig
  if [ $nb_children = 0 ] ; then
    nb_children=1
  fi
  _alloc_obj _ast_result $((nb_children + 1))
  : $((_$((_heap + _ast_result)) = _$((_heap + orig))))
  i=0
  while [ $i -lt $nb_children ] ; do
    _get_child __t1 $orig $i
    _set_child __ $_ast_result $i $__t1
    : $((i += 1))
  done
  : $(($1 = _ast_result))
  endlet $1 __t1 i nb_children orig
}

: $((i = val = tok = 0))
_print_tok() { let tok $2; let val $3
  let i
  if [ $tok = $_AUTO_KW ] ; then
    printf "auto"
  elif [ $tok = $_BREAK_KW ] ; then
    printf "break"
  elif [ $tok = $_CASE_KW ] ; then
    printf "case"
  elif [ $tok = $_CHAR_KW ] ; then
    printf "char"
  elif [ $tok = $_CONST_KW ] ; then
    printf "const"
  elif [ $tok = $_CONTINUE_KW ] ; then
    printf "continue"
  elif [ $tok = $_DEFAULT_KW ] ; then
    printf "default"
  elif [ $tok = $_DO_KW ] ; then
    printf "do"
  elif [ $tok = $_DOUBLE_KW ] ; then
    printf "double"
  elif [ $tok = $_ELSE_KW ] ; then
    printf "else"
  elif [ $tok = $_ENUM_KW ] ; then
    printf "enum"
  elif [ $tok = $_ERROR_KW ] ; then
    printf "error"
  elif [ $tok = $_EXTERN_KW ] ; then
    printf "extern"
  elif [ $tok = $_FLOAT_KW ] ; then
    printf "float"
  elif [ $tok = $_FOR_KW ] ; then
    printf "for"
  elif [ $tok = $_GOTO_KW ] ; then
    printf "goto"
  elif [ $tok = $_IF_KW ] ; then
    printf "if"
  elif [ $tok = $_INT_KW ] ; then
    printf "int"
  elif [ $tok = $_LONG_KW ] ; then
    printf "long"
  elif [ $tok = $_REGISTER_KW ] ; then
    printf "register"
  elif [ $tok = $_RETURN_KW ] ; then
    printf "return"
  elif [ $tok = $_SHORT_KW ] ; then
    printf "short"
  elif [ $tok = $_SIGNED_KW ] ; then
    printf "signed"
  elif [ $tok = $_SIZEOF_KW ] ; then
    printf "sizeof"
  elif [ $tok = $_STATIC_KW ] ; then
    printf "static"
  elif [ $tok = $_STRUCT_KW ] ; then
    printf "struct"
  elif [ $tok = $_SWITCH_KW ] ; then
    printf "switch"
  elif [ $tok = $_TYPEDEF_KW ] ; then
    printf "typedef"
  elif [ $tok = $_UNION_KW ] ; then
    printf "union"
  elif [ $tok = $_UNSIGNED_KW ] ; then
    printf "unsigned"
  elif [ $tok = $_VOID_KW ] ; then
    printf "void"
  elif [ $tok = $_VOLATILE_KW ] ; then
    printf "volatile"
  elif [ $tok = $_WHILE_KW ] ; then
    printf "while"
  elif [ $tok = $_AMP_AMP ] ; then
    printf "&&"
  elif [ $tok = $_AMP_EQ ] ; then
    printf "&="
  elif [ $tok = $_BAR_BAR ] ; then
    printf "||"
  elif [ $tok = $_BAR_EQ ] ; then
    printf "|="
  elif [ $tok = $_CARET_EQ ] ; then
    printf "^="
  elif [ $tok = $_EQ_EQ ] ; then
    printf "=="
  elif [ $tok = $_GT_EQ ] ; then
    printf ">="
  elif [ $tok = $_LSHIFT_EQ ] ; then
    printf "<<="
  elif [ $tok = $_LSHIFT ] ; then
    printf "<<"
  elif [ $tok = $_LT_EQ ] ; then
    printf "<="
  elif [ $tok = $_MINUS_EQ ] ; then
    printf " -= "
  elif [ $tok = $_MINUS_MINUS ] ; then
    printf "--"
  elif [ $tok = $_EXCL_EQ ] ; then
    printf "!="
  elif [ $tok = $_PERCENT_EQ ] ; then
    printf "%%="
  elif [ $tok = $_PLUS_EQ ] ; then
    printf "+="
  elif [ $tok = $_RSHIFT_EQ ] ; then
    printf ">>="
  elif [ $tok = $_RSHIFT ] ; then
    printf ">>"
  elif [ $tok = $_SLASH_EQ ] ; then
    printf "/="
  elif [ $tok = $_STAR_EQ ] ; then
    printf "*="
  elif [ $tok = $_HASH_HASH ] ; then
    printf "##"
  elif [ $tok = $_PLUS_PLUS_PRE ] ; then
    printf "++"
  elif [ $tok = $_MINUS_MINUS_PRE ] ; then
    printf " -- "
  elif [ $tok = $_PLUS_PLUS_POST ] ; then
    printf "++"
  elif [ $tok = $_MINUS_MINUS_POST ] ; then
    printf " -- "
  elif [ $tok = $_IDENTIFIER ] ; then
    _putstr __ $((_string_pool + _$((_heap + val + 1))))
  elif [ $tok = $_MACRO ] ; then
    printf \\$(((__LBRACK__)/64))$(((__LBRACK__)/8%8))$(((__LBRACK__)%8))
    _putstr __ $((_string_pool + _$((_heap + val + 1))))
    printf \\$(((__RBRACK__)/64))$(((__RBRACK__)/8%8))$(((__RBRACK__)%8))
  elif [ $tok = $_INTEGER ] ; then
    _putintneg __ $val
  elif [ $tok = $_CHARACTER ] ; then
    printf \\$(((__QUOTE__)/64))$(((__QUOTE__)/8%8))$(((__QUOTE__)%8))
    _print_string_char __ $val
    printf \\$(((__QUOTE__)/64))$(((__QUOTE__)/8%8))$(((__QUOTE__)%8))
  elif [ $tok = $_STRING ] ; then
    printf \\$(((__DQUOTE__)/64))$(((__DQUOTE__)/8%8))$(((__DQUOTE__)%8))
    i=0
    while [ $((_$((_string_pool + val + i)))) != 0 ] ; do
      _print_string_char __ $((_$((_string_pool + val + i))))
      : $((i += 1))
    done
    printf \\$(((__DQUOTE__)/64))$(((__DQUOTE__)/8%8))$(((__DQUOTE__)%8))
  elif [ $tok = $_MACRO_ARG ] ; then
    printf "ARG["
    _putint __ $val
    printf "]"
  else
    printf \\$((tok/64))$((tok/8%8))$((tok%8))
  fi
  if [ $tok = $__SEMICOLON__ ] ; then
    printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
  else
    printf \\$(((__SPACE__)/64))$(((__SPACE__)/8%8))$(((__SPACE__)%8))
  fi
  endlet $1 i val tok
}

: $((tok = 0))
_print_tok_type() { let tok $2
  if [ $tok = $_AUTO_KW ] ; then
    printf "auto"
  elif [ $tok = $_BREAK_KW ] ; then
    printf "break"
  elif [ $tok = $_CASE_KW ] ; then
    printf "case"
  elif [ $tok = $_CHAR_KW ] ; then
    printf "char"
  elif [ $tok = $_CONST_KW ] ; then
    printf "const"
  elif [ $tok = $_CONTINUE_KW ] ; then
    printf "continue"
  elif [ $tok = $_DEFAULT_KW ] ; then
    printf "default"
  elif [ $tok = $_DO_KW ] ; then
    printf "do"
  elif [ $tok = $_DOUBLE_KW ] ; then
    printf "double"
  elif [ $tok = $_ELSE_KW ] ; then
    printf "else"
  elif [ $tok = $_ENUM_KW ] ; then
    printf "enum"
  elif [ $tok = $_ERROR_KW ] ; then
    printf "error"
  elif [ $tok = $_EXTERN_KW ] ; then
    printf "extern"
  elif [ $tok = $_FLOAT_KW ] ; then
    printf "float"
  elif [ $tok = $_FOR_KW ] ; then
    printf "for"
  elif [ $tok = $_GOTO_KW ] ; then
    printf "goto"
  elif [ $tok = $_IF_KW ] ; then
    printf "if"
  elif [ $tok = $_INT_KW ] ; then
    printf "int"
  elif [ $tok = $_LONG_KW ] ; then
    printf "long"
  elif [ $tok = $_REGISTER_KW ] ; then
    printf "register"
  elif [ $tok = $_RETURN_KW ] ; then
    printf "return"
  elif [ $tok = $_SHORT_KW ] ; then
    printf "short"
  elif [ $tok = $_SIGNED_KW ] ; then
    printf "signed"
  elif [ $tok = $_SIZEOF_KW ] ; then
    printf "sizeof"
  elif [ $tok = $_STATIC_KW ] ; then
    printf "static"
  elif [ $tok = $_STRUCT_KW ] ; then
    printf "struct"
  elif [ $tok = $_SWITCH_KW ] ; then
    printf "switch"
  elif [ $tok = $_TYPEDEF_KW ] ; then
    printf "typedef"
  elif [ $tok = $_UNION_KW ] ; then
    printf "union"
  elif [ $tok = $_UNSIGNED_KW ] ; then
    printf "unsigned"
  elif [ $tok = $_VOID_KW ] ; then
    printf "void"
  elif [ $tok = $_VOLATILE_KW ] ; then
    printf "volatile"
  elif [ $tok = $_WHILE_KW ] ; then
    printf "while"
  elif [ $tok = $_AMP_AMP ] ; then
    printf "&&"
  elif [ $tok = $_AMP_EQ ] ; then
    printf "&="
  elif [ $tok = $_BAR_BAR ] ; then
    printf "||"
  elif [ $tok = $_BAR_EQ ] ; then
    printf "|="
  elif [ $tok = $_CARET_EQ ] ; then
    printf "^="
  elif [ $tok = $_EQ_EQ ] ; then
    printf "=="
  elif [ $tok = $_GT_EQ ] ; then
    printf ">="
  elif [ $tok = $_LSHIFT_EQ ] ; then
    printf "<<="
  elif [ $tok = $_LSHIFT ] ; then
    printf "<<"
  elif [ $tok = $_LT_EQ ] ; then
    printf "<="
  elif [ $tok = $_MINUS_EQ ] ; then
    printf " -= "
  elif [ $tok = $_MINUS_MINUS ] ; then
    printf "--"
  elif [ $tok = $_EXCL_EQ ] ; then
    printf "!="
  elif [ $tok = $_PERCENT_EQ ] ; then
    printf "%%="
  elif [ $tok = $_PLUS_EQ ] ; then
    printf "+="
  elif [ $tok = $_RSHIFT_EQ ] ; then
    printf ">>="
  elif [ $tok = $_RSHIFT ] ; then
    printf ">>"
  elif [ $tok = $_SLASH_EQ ] ; then
    printf "/="
  elif [ $tok = $_STAR_EQ ] ; then
    printf "*="
  elif [ $tok = $_HASH_HASH ] ; then
    printf "##"
  elif [ $tok = $_PLUS_PLUS_PRE ] ; then
    printf "++"
  elif [ $tok = $_MINUS_MINUS_PRE ] ; then
    printf " -- "
  elif [ $tok = $_PLUS_PLUS_POST ] ; then
    printf "++"
  elif [ $tok = $_MINUS_MINUS_POST ] ; then
    printf " -- "
  elif [ $tok = $_IDENTIFIER ] ; then
    printf "identifier"
  elif [ $tok = $_INTEGER ] ; then
    printf "integer"
  elif [ $tok = $_CHARACTER ] ; then
    printf "character"
  elif [ $tok = $_STRING ] ; then
    printf "string"
  elif [ $tok = $_MACRO ] ; then
    printf "macro"
  elif [ $tok = $_MACRO_ARG ] ; then
    printf "macro argument"
  elif [ $tok = -1 ] ; then
    printf "end of file"
  else
    printf \\$(((__QUOTE__)/64))$(((__QUOTE__)/8%8))$(((__QUOTE__)%8))
    printf \\$((tok/64))$((tok/8%8))$((tok%8))
    printf \\$(((__QUOTE__)/64))$(((__QUOTE__)/8%8))$(((__QUOTE__)%8))
  fi
  endlet $1 tok
}

: $((nb_children = i = obj = name = 0))
_show_ast() { let name $2; let obj $3
  let i; let nb_children
  _get_nb_children nb_children $obj
  if [ $nb_children = 0 ] ; then
    nb_children=1
  fi
  i=0
  while [ $i -lt $((nb_children + 1)) ] ; do
    _put_pstr __ $name
    printf "[%d] = %d\n" $i $((_$((_heap + obj + i))))
    : $(((i += 1) - 1))
  done
  endlet $1 nb_children i obj name
}

: $((expected_tok = 0))
_expect_tok() { let expected_tok $2
  if [ $_tok != $expected_tok ] ; then
    printf "expected tok="
    _print_tok_type __ $expected_tok
    printf "\ncurrent tok="
    _print_tok_type __ $_tok
    printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
    defstr __str_90 "unexpected token"
    _syntax_error __ $__str_90
  fi
  _get_tok __ 
  endlet $1 expected_tok
}

: $((type_kw = 0))
_parse_type() {
  let type_kw
  type_kw=0
  while [ 1 != 0 ] ; do
    if [ $_tok = $_INT_KW ] || [ $_tok = $_SHORT_KW ] || [ $_tok = $_LONG_KW ] || [ $_tok = $_SIGNED_KW ] ; then
      if [ $type_kw != 0 ] && [ $type_kw != $_INT_KW ] ; then
        defstr __str_91 "inconsistent type"
        _syntax_error __ $__str_91
      fi
      type_kw=$_INT_KW
      _get_tok __ 
    elif [ $_tok = $_CHAR_KW ] ; then
      if [ $type_kw != 0 ] ; then
        defstr __str_92 "inconsistent type"
        _syntax_error __ $__str_92
      fi
      type_kw=$_CHAR_KW
      _get_tok __ 
    elif [ $_tok = $_UNSIGNED_KW ] || [ $_tok = $_FLOAT_KW ] || [ $_tok = $_DOUBLE_KW ] ; then
      defstr __str_93 "unsupported type"
      _syntax_error __ $__str_93
    elif [ $_tok = $_VOID_KW ] ; then
      if [ $type_kw != 0 ] ; then
        defstr __str_94 "inconsistent type"
        _syntax_error __ $__str_94
      fi
      type_kw=$_VOID_KW
      _get_tok __ 
    elif [ $_tok = $_CONST_KW ] ; then
      _get_tok __ 
    elif [ $_tok = $_ENUM_KW ] ; then
      if [ $type_kw != 0 ] ; then
        defstr __str_95 "inconsistent type"
        _syntax_error __ $__str_95
      fi
      _parse_enum $1 
      endlet $1 type_kw
      return
    elif [ $_tok = $_STRUCT_KW ] ; then
      if [ $type_kw != 0 ] ; then
        defstr __str_96 "inconsistent type"
        _syntax_error __ $__str_96
      fi
      _parse_struct $1 
      endlet $1 type_kw
      return
    elif [ $_tok = $_UNION_KW ] ; then
      if [ $type_kw != 0 ] ; then
        defstr __str_97 "inconsistent type"
        _syntax_error __ $__str_97
      fi
      _parse_union $1 
      endlet $1 type_kw
      return
    elif [ $_tok = $_TYPE ] ; then
      type_kw=$((_$((_heap + _val + 3))))
      _get_tok __ 
      : $(($1 = type_kw))
      endlet $1 type_kw
      return
    else
      break
    fi
  done
  if [ $type_kw = 0 ] ; then
    defstr __str_98 "type expected"
    _syntax_error __ $__str_98
  fi
  _new_ast0 $1 $type_kw 0
  endlet $1 type_kw
}

: $((stars = 0))
_parse_stars() {
  let stars
  stars=0
  while [ $_tok = $__STAR__ ] ; do
    : $((stars += 1))
    _get_tok __ 
  done
  : $(($1 = stars))
  endlet $1 stars
}

: $((stars = type = 0))
_parse_stars_for_type() { let type $2
  let stars
  _parse_stars stars 
  if [ $stars != 0 ] ; then
    _clone_ast type $type
    _set_val __ $type $stars
  fi
  : $(($1 = type))
  endlet $1 stars type
}

: $((__t1 = 0))
_parse_type_with_stars() {
  let __t1
  _parse_type __t1 
  _parse_stars_for_type $1 $__t1
  endlet $1 __t1
}

: $((tok = 0))
_is_type_starter() { let tok $2
  : $(($1 = (tok == _INT_KW) || (tok == _CHAR_KW) || (tok == _SHORT_KW) || (tok == _LONG_KW) || (tok == _SIGNED_KW) || (tok == _UNSIGNED_KW) || (tok == _FLOAT_KW) || (tok == _DOUBLE_KW) || (tok == _VOID_KW) || (tok == _TYPE) || (tok == _CONST_KW) || (tok == _ENUM_KW) || (tok == _STRUCT_KW) || (tok == _UNION_KW)))
  endlet $1 tok
}

: $((__t1 = next_value = value = tail = result = ident = name = 0))
_parse_enum() {
  let name; let ident; let result; let tail; let value; let next_value; let __t1
  result=0
  value=0
  next_value=0
  _expect_tok __ $_ENUM_KW
  if [ $_tok = $_IDENTIFIER ] ; then
    _new_ast0 name $_IDENTIFIER $_val
    _get_tok __ 
  elif [ $_tok = $_TYPE ] ; then
    result=$((_$((_heap + _val + 3))))
    if _get_op __t1 $result; [ $__t1 != $_ENUM_KW ] ; then
      defstr __str_99 "enum type expected"
      _syntax_error __ $__str_99
    fi
    _get_tok __ 
    if [ $_tok = $__LBRACE__ ] ; then
      defstr __str_100 "enum type cannot be redefined"
      _syntax_error __ $__str_100
    fi
    : $(($1 = result))
    endlet $1 __t1 next_value value tail result ident name
    return
  else
    name=0
  fi
  if [ $_tok = $__LBRACE__ ] ; then
    _get_tok __ 
    while [ $_tok != $__RBRACE__ ] ; do
      if [ $_tok != $_IDENTIFIER ] ; then
        defstr __str_101 "identifier expected"
        _syntax_error __ $__str_101
      fi
      _new_ast0 ident $_IDENTIFIER $_val
      _get_tok __ 
      if [ $_tok = $__EQ__ ] ; then
        _get_tok __ 
        if [ $_tok != $_INTEGER ] ; then
          defstr __str_102 "integer expected"
          _syntax_error __ $__str_102
        fi
        _new_ast0 value $_INTEGER $_val
        next_value=$((_val - 1))
        _get_tok __ 
      else
        _new_ast0 value $_INTEGER $next_value
        : $((next_value -= 1))
      fi
      if [ $result = 0 ] ; then
        _new_ast3 result $__COMMA__ $ident $value 0
        tail=$result
      else
        _new_ast3 __t1 $__COMMA__ $ident $value 0
        _set_child __ $tail 2 $__t1
        _get_child tail $tail 2
      fi
      if [ $_tok = $__COMMA__ ] ; then
        _get_tok __ 
      else
        break
      fi
    done
    _expect_tok __ $__RBRACE__
  fi
  _new_ast3 $1 $_ENUM_KW 0 $name $result
  endlet $1 __t1 next_value value tail result ident name
}

: $((__t2 = __t1 = tail = result = type = ident = name = 0))
_parse_struct() {
  let name; let ident; let type; let result; let tail; let __t1; let __t2
  result=0
  _expect_tok __ $_STRUCT_KW
  if [ $_tok = $_IDENTIFIER ] ; then
    _new_ast0 name $_IDENTIFIER $_val
    _get_tok __ 
  elif [ $_tok = $_TYPE ] ; then
    result=$((_$((_heap + _val + 3))))
    if _get_op __t1 $result; [ $__t1 != $_STRUCT_KW ] ; then
      defstr __str_103 "struct type expected"
      _syntax_error __ $__str_103
    fi
    _get_tok __ 
    if [ $_tok = $__LBRACE__ ] ; then
      defstr __str_104 "struct type cannot be redefined"
      _syntax_error __ $__str_104
    fi
    : $(($1 = result))
    endlet $1 __t2 __t1 tail result type ident name
    return
  else
    name=0
  fi
  if [ $_tok = $__LBRACE__ ] ; then
    _get_tok __ 
    while [ $_tok != $__RBRACE__ ] ; do
      if _is_type_starter __t1 $_tok; [ $((!__t1)) != 0 ] ; then
        defstr __str_105 "type expected in struct declaration"
        _syntax_error __ $__str_105
      fi
      _parse_type_with_stars type 
      if { _get_val __t1 $type; [ $__t1 = 0 ]; } && { _get_op __t2 $type; [ $__t2 = $_VOID_KW ]; } ; then
        defstr __str_106 "variable with void type"
        _syntax_error __ $__str_106
      fi
      if [ $_tok != $_IDENTIFIER ] ; then
        defstr __str_107 "identifier expected"
        _syntax_error __ $__str_107
      fi
      _new_ast0 ident $_IDENTIFIER $_val
      _get_tok __ 
      if [ $_tok = $__LBRACK__ ] ; then
        _get_tok __ 
        if [ $_tok != $_INTEGER ] ; then
          defstr __str_108 "array size must be an integer constant"
          _syntax_error __ $__str_108
        fi
        _new_ast0 __t1 $_INTEGER $((-(_val)))
        _new_ast2 type $__LBRACK__ $__t1 $type
        _get_tok __ 
        _expect_tok __ $__RBRACK__
      fi
      _expect_tok __ $__SEMICOLON__
      if [ $result = 0 ] ; then
        _new_ast3 result $__COMMA__ $ident $type 0
        tail=$result
      else
        _new_ast3 __t1 $__COMMA__ $ident $type 0
        _set_child __ $tail 2 $__t1
        _get_child tail $tail 2
      fi
    done
    _expect_tok __ $__RBRACE__
  fi
  _new_ast3 $1 $_STRUCT_KW 0 $name $result
  endlet $1 __t2 __t1 tail result type ident name
}

_parse_union() {
  defstr __str_109 "union not supported"
  _syntax_error __ $__str_109
}

: $((__t2 = __t1 = result = name = type = 0))
_parse_declaration() {
  let type; let name; let result; let __t1; let __t2
  result=0
  if _is_type_starter __t1 $_tok; [ $__t1 != 0 ] ; then
    _parse_type_with_stars type 
    name=$_val
    _expect_tok __ $_IDENTIFIER
    if { _get_val __t1 $type; [ $__t1 = 0 ]; } && { _get_op __t2 $type; [ $__t2 = $_VOID_KW ]; } ; then
      defstr __str_110 "variable with void type"
      _syntax_error __ $__str_110
    fi
    _new_ast3 result $_VAR_DECL $name $type 0
  elif [ $_tok = $_IDENTIFIER ] ; then
    name=$_val
    _expect_tok __ $_IDENTIFIER
    _new_ast0 type $_INT_KW 0
    _new_ast3 result $_VAR_DECL $name $type 0
  fi
  : $(($1 = result))
  endlet $1 __t2 __t1 result name type
}

: $((tail = result = decl = 0))
_parse_declaration_list() {
  let decl; let result; let tail
  _parse_declaration decl 
  result=0
  if [ $decl != 0 ] ; then
    _new_ast2 result $__COMMA__ $decl 0
    tail=$result
    while [ $_tok = $__COMMA__ ] ; do
      _get_tok __ 
      _parse_declaration decl 
      if [ $decl = 0 ] ; then
        break
      fi
      _new_ast2 decl $__COMMA__ $decl 0
      _set_child __ $tail 1 $decl
      tail=$decl
    done
  fi
  : $(($1 = result))
  endlet $1 tail result decl
}

: $((__t3 = __t2 = __t1 = current_declaration = tail = result = this_type = body = params = name = init = type = local = 0))
_parse_definition() { let local $2
  let type; let init; let name; let params; let body; let this_type; let result; let tail; let current_declaration; let __t1; let __t2; let __t3
  result=0
  tail=0
  if _is_type_starter __t1 $_tok; [ $__t1 != 0 ] ; then
    _parse_type type 
    if [ $_tok = $__SEMICOLON__ ] ; then
      if { _get_op __t1 $type; [ $__t1 != $_ENUM_KW ]; } && { _get_op __t2 $type; [ $__t2 != $_STRUCT_KW ]; } && { _get_op __t3 $type; [ $__t3 != $_UNION_KW ]; } ; then
        defstr __str_111 "enum/struct/union declaration expected"
        _syntax_error __ $__str_111
      fi
      _get_tok __ 
      : $(($1 = type))
      endlet $1 __t3 __t2 __t1 current_declaration tail result this_type body params name init type local
      return
    fi
    while [ 1 != 0 ] ; do
      _parse_stars_for_type this_type $type
      name=$_val
      _expect_tok __ $_IDENTIFIER
      if [ $_tok = $__LPAREN__ ] ; then
        if [ $local != 0 ] ; then
          defstr __str_112 "function declaration only allowed at global level"
          _syntax_error __ $__str_112
        fi
        _get_tok __ 
        _parse_declaration_list params 
        _expect_tok __ $__RPAREN__
        if [ $_tok = $__SEMICOLON__ ] ; then
          body=-1
          _get_tok __ 
        else
          _parse_compound_statement body 
        fi
        _new_ast4 $1 $_FUN_DECL $name $this_type $params $body
        endlet $1 __t3 __t2 __t1 current_declaration tail result this_type body params name init type local
        return
      else
        if { _get_val __t1 $this_type; [ $__t1 = 0 ]; } && { _get_op __t2 $this_type; [ $__t2 = $_VOID_KW ]; } ; then
          defstr __str_113 "variable with void type"
          _syntax_error __ $__str_113
        fi
        if [ $_tok = $__LBRACK__ ] ; then
          _get_tok __ 
          if [ $_tok = $_INTEGER ] ; then
            _new_ast0 __t1 $_INTEGER $((-(_val)))
            _new_ast2 this_type $__LBRACK__ $__t1 $this_type
            _get_tok __ 
          else
            defstr __str_114 "array size must be an integer constant"
            _syntax_error __ $__str_114
          fi
          _expect_tok __ $__RBRACK__
        fi
        init=0
        if [ $_tok = $__EQ__ ] ; then
          _get_tok __ 
          _parse_conditional_expression init 
        fi
        _new_ast3 current_declaration $_VAR_DECL $name $this_type $init
        if [ $result = 0 ] ; then
          _new_ast2 result $__COMMA__ $current_declaration 0
          tail=$result
        else
          _new_ast2 __t1 $__COMMA__ $current_declaration 0
          _set_child __ $tail 1 $__t1
          _get_child tail $tail 1
        fi
        if [ $_tok = $__SEMICOLON__ ] ; then
          _get_tok __ 
          break
        elif [ $_tok = $__COMMA__ ] ; then
          _get_tok __ 
          continue
        else
          defstr __str_115 "';' or ',' expected"
          _syntax_error __ $__str_115
        fi
      fi
    done
    _new_ast1 $1 $_VAR_DECLS $result
  elif [ $_tok = $_TYPEDEF_KW ] ; then
    _get_tok __ 
    _parse_type_with_stars type 
    if [ $_tok != $_IDENTIFIER ] ; then
      defstr __str_116 "identifier expected"
      _syntax_error __ $__str_116
    fi
    if { _get_op __t1 $type; [ $__t1 = $_STRUCT_KW ]; } || { _get_op __t2 $type; [ $__t2 = $_UNION_KW ]; } || { _get_op __t3 $type; [ $__t3 = $_ENUM_KW ]; } ; then
      if { _get_child __t1 $type 1; [ $__t1 != 0 ]; } && { _get_child __t3 $type 1; _get_val __t2 $__t3; [ $__t2 != $_val ]; } ; then
        defstr __str_117 "typedef name must match struct/union/enum name"
        _syntax_error __ $__str_117
      fi
      _new_ast0 __t1 $_IDENTIFIER $_val
      _set_child __ $type 1 $__t1
    fi
    : $((_$((_heap + _val + 2)) = _TYPE))
    : $((_$((_heap + _val + 3)) = type))
    _new_ast2 result $_TYPEDEF_KW $_val $type
    _get_tok __ 
    _expect_tok __ $__SEMICOLON__
    : $(($1 = result))
  else
    : $(($1 = result))
  fi
  endlet $1 __t3 __t2 __t1 current_declaration tail result this_type body params name init type local
}

: $((result = 0))
_parse_parenthesized_expression() {
  let result
  _expect_tok __ $__LPAREN__
  _parse_comma_expression result 
  _expect_tok __ $__RPAREN__
  : $(($1 = result))
  endlet $1 result
}

: $((__t2 = __t1 = tail = result = 0))
_parse_primary_expression() {
  let result; let tail; let __t1; let __t2
  if [ $_tok = $_IDENTIFIER ] ; then
    _new_ast0 result $_IDENTIFIER $_val
    _get_tok __ 
  elif [ $_tok = $_INTEGER ] ; then
    _new_ast0 result $_INTEGER $_val
    _get_tok __ 
  elif [ $_tok = $_CHARACTER ] ; then
    _new_ast0 result $_CHARACTER $_val
    _get_tok __ 
  elif [ $_tok = $_STRING ] ; then
    _new_ast0 result $_STRING $_val
    _get_tok __ 
    if [ $_tok = $_STRING ] ; then
      _cons result $result 0
      tail=$result
      while [ $_tok = $_STRING ] ; do
        _new_ast0 __t2 $_STRING $_val
        _cons __t1 $__t2 0
        _set_cdr __ $tail $__t1
        _cdr tail $tail
        _get_tok __ 
      done
      _begin_string __ 
      while [ $result != 0 ] ; do
        _car __t2 $result
        _get_val __t1 $__t2
        _accum_string_string __ $__t1
        _cdr result $result
      done
      _accum_string_char __ 0
      _new_ast0 result $_STRING $_string_start
    fi
  elif [ $_tok = $__LPAREN__ ] ; then
    _parse_parenthesized_expression result 
  else
    defstr __str_118 "identifier, literal, or '(' expected"
    _syntax_error __ $__str_118
  fi
  : $(($1 = result))
  endlet $1 __t2 __t1 tail result
}

: $((__t1 = child = result = 0))
_parse_postfix_expression() {
  let result; let child; let __t1
  _parse_primary_expression result 
  while [ 1 != 0 ] ; do
    if [ $_tok = $__LBRACK__ ] ; then
      _get_tok __ 
      _parse_comma_expression child 
      _new_ast2 result $__LBRACK__ $result $child
      _expect_tok __ $__RBRACK__
    elif [ $_tok = $__LPAREN__ ] ; then
      _get_tok __ 
      if [ $_tok = $__RPAREN__ ] ; then
        child=0
      else
        _parse_comma_expression child 
      fi
      _new_ast2 result $__LPAREN__ $result $child
      _expect_tok __ $__RPAREN__
    elif [ $_tok = $__PERIOD__ ] ; then
      _get_tok __ 
      if [ $_tok != $_IDENTIFIER ] ; then
        defstr __str_119 "identifier expected"
        _syntax_error __ $__str_119
      fi
      _new_ast0 __t1 $_IDENTIFIER $_val
      _new_ast2 result $__PERIOD__ $result $__t1
      _get_tok __ 
    elif [ $_tok = $_ARROW ] ; then
      _get_tok __ 
      if [ $_tok != $_IDENTIFIER ] ; then
        defstr __str_120 "identifier expected"
        _syntax_error __ $__str_120
      fi
      _new_ast0 __t1 $_IDENTIFIER $_val
      _new_ast2 result $_ARROW $result $__t1
      _get_tok __ 
    elif [ $_tok = $_PLUS_PLUS ] ; then
      _get_tok __ 
      _new_ast1 result $_PLUS_PLUS_POST $result
    elif [ $_tok = $_MINUS_MINUS ] ; then
      _get_tok __ 
      _new_ast1 result $_MINUS_MINUS_POST $result
    else
      break
    fi
  done
  : $(($1 = result))
  endlet $1 __t1 child result
}

: $((op = result = 0))
_parse_unary_expression() {
  let result; let op
  if [ $_tok = $_PLUS_PLUS ] ; then
    _get_tok __ 
    _parse_unary_expression result 
    _new_ast1 result $_PLUS_PLUS_PRE $result
  elif [ $_tok = $_MINUS_MINUS ] ; then
    _get_tok __ 
    _parse_unary_expression result 
    _new_ast1 result $_MINUS_MINUS_PRE $result
  elif [ $_tok = $__AMP__ ] || [ $_tok = $__STAR__ ] || [ $_tok = $__PLUS__ ] || [ $_tok = $__MINUS__ ] || [ $_tok = $__TILDE__ ] || [ $_tok = $__EXCL__ ] ; then
    op=$_tok
    _get_tok __ 
    _parse_cast_expression result 
    _new_ast1 result $op $result
  elif [ $_tok = $_SIZEOF_KW ] ; then
    _get_tok __ 
    if [ $_tok = $__LPAREN__ ] ; then
      _get_tok __ 
      _parse_type_with_stars result 
      _expect_tok __ $__RPAREN__
    else
      _parse_unary_expression result 
    fi
    _new_ast1 result $_SIZEOF_KW $result
  else
    _parse_postfix_expression result 
  fi
  : $(($1 = result))
  endlet $1 op result
}

: $((__t2 = __t1 = type = result = tokens = 0))
_parse_cast_expression() {
  let tokens; let result; let type; let __t1; let __t2
  tokens=0
  if [ $_tok = $__LPAREN__ ] ; then
    _get_tok __ 
    if _is_type_starter __t1 $_tok; [ $__t1 != 0 ] ; then
      _parse_type_with_stars type 
      if { _get_val __t1 $type; [ $__t1 = 0 ]; } && { _get_op __t2 $type; [ $__t2 = $_VOID_KW ]; } ; then
        defstr __str_121 "variable with void type"
        _syntax_error __ $__str_121
      fi
      _expect_tok __ $__RPAREN__
      _parse_cast_expression __t1 
      _new_ast2 result $_CAST $type $__t1
      : $(($1 = result))
      endlet $1 __t2 __t1 type result tokens
      return
    else
      _cons __t1 $_tok $_val
      _cons tokens $__t1 0
      _push_tokens __ $tokens
      _tok=$__LPAREN__
      _val=0
    fi
  fi
  _parse_unary_expression $1 
  endlet $1 __t2 __t1 type result tokens
}

: $((op = child = result = 0))
_parse_multiplicative_expression() {
  let result; let child; let op
  _parse_cast_expression result 
  while [ $_tok = $__STAR__ ] || [ $_tok = $__SLASH__ ] || [ $_tok = $__PERCENT__ ] ; do
    op=$_tok
    _get_tok __ 
    _parse_cast_expression child 
    _new_ast2 result $op $result $child
  done
  : $(($1 = result))
  endlet $1 op child result
}

: $((op = child = result = 0))
_parse_additive_expression() {
  let result; let child; let op
  _parse_multiplicative_expression result 
  while [ $_tok = $__PLUS__ ] || [ $_tok = $__MINUS__ ] ; do
    op=$_tok
    _get_tok __ 
    _parse_multiplicative_expression child 
    _new_ast2 result $op $result $child
  done
  : $(($1 = result))
  endlet $1 op child result
}

: $((op = child = result = 0))
_parse_shift_expression() {
  let result; let child; let op
  _parse_additive_expression result 
  while [ $_tok = $_LSHIFT ] || [ $_tok = $_RSHIFT ] ; do
    op=$_tok
    _get_tok __ 
    _parse_additive_expression child 
    _new_ast2 result $op $result $child
  done
  : $(($1 = result))
  endlet $1 op child result
}

: $((op = child = result = 0))
_parse_relational_expression() {
  let result; let child; let op
  _parse_shift_expression result 
  while [ $_tok = $__LT__ ] || [ $_tok = $__GT__ ] || [ $_tok = $_LT_EQ ] || [ $_tok = $_GT_EQ ] ; do
    op=$_tok
    _get_tok __ 
    _parse_shift_expression child 
    _new_ast2 result $op $result $child
  done
  : $(($1 = result))
  endlet $1 op child result
}

: $((op = child = result = 0))
_parse_equality_expression() {
  let result; let child; let op
  _parse_relational_expression result 
  while [ $_tok = $_EQ_EQ ] || [ $_tok = $_EXCL_EQ ] ; do
    op=$_tok
    _get_tok __ 
    _parse_relational_expression child 
    _new_ast2 result $op $result $child
  done
  : $(($1 = result))
  endlet $1 op child result
}

: $((child = result = 0))
_parse_AND_expression() {
  let result; let child
  _parse_equality_expression result 
  while [ $_tok = $__AMP__ ] ; do
    _get_tok __ 
    _parse_equality_expression child 
    _new_ast2 result $__AMP__ $result $child
  done
  : $(($1 = result))
  endlet $1 child result
}

: $((child = result = 0))
_parse_exclusive_OR_expression() {
  let result; let child
  _parse_AND_expression result 
  while [ $_tok = $__CARET__ ] ; do
    _get_tok __ 
    _parse_AND_expression child 
    _new_ast2 result $__CARET__ $result $child
  done
  : $(($1 = result))
  endlet $1 child result
}

: $((child = result = 0))
_parse_inclusive_OR_expression() {
  let result; let child
  _parse_exclusive_OR_expression result 
  while [ $_tok = $__BAR__ ] ; do
    _get_tok __ 
    _parse_exclusive_OR_expression child 
    _new_ast2 result $__BAR__ $result $child
  done
  : $(($1 = result))
  endlet $1 child result
}

: $((child = result = 0))
_parse_logical_AND_expression() {
  let result; let child
  _parse_inclusive_OR_expression result 
  while [ $_tok = $_AMP_AMP ] ; do
    _get_tok __ 
    _parse_inclusive_OR_expression child 
    _new_ast2 result $_AMP_AMP $result $child
  done
  : $(($1 = result))
  endlet $1 child result
}

: $((child = result = 0))
_parse_logical_OR_expression() {
  let result; let child
  _parse_logical_AND_expression result 
  while [ $_tok = $_BAR_BAR ] ; do
    _get_tok __ 
    _parse_logical_AND_expression child 
    _new_ast2 result $_BAR_BAR $result $child
  done
  : $(($1 = result))
  endlet $1 child result
}

: $((child2 = child1 = result = 0))
_parse_conditional_expression() {
  let result; let child1; let child2
  _parse_logical_OR_expression result 
  if [ $_tok = $__QUESTION__ ] ; then
    _get_tok __ 
    _parse_comma_expression child1 
    _expect_tok __ $__COLON__
    _parse_conditional_expression child2 
    _new_ast3 result $__QUESTION__ $result $child1 $child2
  fi
  : $(($1 = result))
  endlet $1 child2 child1 result
}

: $((op = child = result = 0))
_parse_assignment_expression() {
  let result; let child; let op
  _parse_conditional_expression result 
  if [ $_tok = $__EQ__ ] || [ $_tok = $_PLUS_EQ ] || [ $_tok = $_MINUS_EQ ] || [ $_tok = $_STAR_EQ ] || [ $_tok = $_SLASH_EQ ] || [ $_tok = $_PERCENT_EQ ] || [ $_tok = $_LSHIFT_EQ ] || [ $_tok = $_RSHIFT_EQ ] || [ $_tok = $_AMP_EQ ] || [ $_tok = $_CARET_EQ ] || [ $_tok = $_BAR_EQ ] ; then
    op=$_tok
    _get_tok __ 
    _parse_assignment_expression child 
    _new_ast2 result $op $result $child
  fi
  : $(($1 = result))
  endlet $1 op child result
}

: $((tail = child = result = 0))
_parse_comma_expression() {
  let result; let child; let tail
  _parse_assignment_expression result 
  if [ $_tok = $__COMMA__ ] ; then
    _new_ast2 result $__COMMA__ $result 0
    tail=$result
    while [ $_tok = $__COMMA__ ] ; do
      _get_tok __ 
      _parse_assignment_expression child 
      _new_ast2 child $__COMMA__ $child 0
      _set_child __ $tail 1 $child
      tail=$child
    done
  fi
  : $(($1 = result))
  endlet $1 tail child result
}

: $((result = 0))
_parse_comma_expression_opt() {
  let result
  if [ $_tok = $__COLON__ ] || [ $_tok = $__SEMICOLON__ ] || [ $_tok = $__RPAREN__ ] ; then
    result=0
  else
    _parse_comma_expression result 
  fi
  : $(($1 = result))
  endlet $1 result
}

_parse_expression() {
  _parse_comma_expression $1 
}

_parse_constant_expression() {
  _parse_expression $1 
}

: $((__t1 = start_tok = child3 = child2 = child1 = result = 0))
_parse_statement() {
  let result; let child1; let child2; let child3; let start_tok; let __t1
  if [ $_tok = $_IF_KW ] ; then
    _get_tok __ 
    _parse_parenthesized_expression result 
    _parse_statement child1 
    if [ $_tok = $_ELSE_KW ] ; then
      _get_tok __ 
      _parse_statement child2 
    else
      child2=0
    fi
    _new_ast3 result $_IF_KW $result $child1 $child2
  elif [ $_tok = $_SWITCH_KW ] ; then
    _get_tok __ 
    _parse_parenthesized_expression result 
    _parse_statement child1 
    _new_ast2 result $_SWITCH_KW $result $child1
  elif [ $_tok = $_CASE_KW ] ; then
    _get_tok __ 
    _parse_constant_expression result 
    _expect_tok __ $__COLON__
    _parse_statement child1 
    _new_ast2 result $_CASE_KW $result $child1
  elif [ $_tok = $_DEFAULT_KW ] ; then
    _get_tok __ 
    _expect_tok __ $__COLON__
    _parse_statement result 
    _new_ast1 result $_DEFAULT_KW $result
  elif [ $_tok = $_WHILE_KW ] ; then
    _get_tok __ 
    _parse_parenthesized_expression result 
    _parse_statement child1 
    _new_ast2 result $_WHILE_KW $result $child1
  elif [ $_tok = $_DO_KW ] ; then
    _get_tok __ 
    _parse_statement result 
    _expect_tok __ $_WHILE_KW
    _parse_parenthesized_expression child1 
    _expect_tok __ $__SEMICOLON__
    _new_ast2 result $_DO_KW $result $child1
  elif [ $_tok = $_FOR_KW ] ; then
    _get_tok __ 
    _expect_tok __ $__LPAREN__
    _parse_comma_expression_opt result 
    _expect_tok __ $__SEMICOLON__
    _parse_comma_expression_opt child1 
    _expect_tok __ $__SEMICOLON__
    _parse_comma_expression_opt child2 
    _expect_tok __ $__RPAREN__
    _parse_statement child3 
    _new_ast4 result $_FOR_KW $result $child1 $child2 $child3
  elif [ $_tok = $_GOTO_KW ] ; then
    _get_tok __ 
    _expect_tok __ $_IDENTIFIER
    _new_ast0 result $_GOTO_KW $_val
    _expect_tok __ $__SEMICOLON__
  elif [ $_tok = $_CONTINUE_KW ] ; then
    _get_tok __ 
    _expect_tok __ $__SEMICOLON__
    _new_ast0 result $_CONTINUE_KW 0
  elif [ $_tok = $_BREAK_KW ] ; then
    _get_tok __ 
    _expect_tok __ $__SEMICOLON__
    _new_ast0 result $_BREAK_KW 0
  elif [ $_tok = $_RETURN_KW ] ; then
    _get_tok __ 
    _parse_comma_expression_opt result 
    _expect_tok __ $__SEMICOLON__
    _new_ast1 result $_RETURN_KW $result
  elif [ $_tok = $__LBRACE__ ] ; then
    _parse_compound_statement result 
  else
    start_tok=$_tok
    _parse_comma_expression_opt result 
    if [ $_tok = $__COLON__ ] && [ $start_tok != $__LPAREN__ ] && { _get_op __t1 $result; [ $__t1 = $_IDENTIFIER ]; } ; then
      _get_tok __ 
      _parse_statement child1 
      _new_ast2 result $__COLON__ $result $child1
    else
      _expect_tok __ $__SEMICOLON__
    fi
  fi
  : $(($1 = result))
  endlet $1 __t1 start_tok child3 child2 child1 result
}

: $((__t1 = tail = child1 = result = 0))
_parse_compound_statement() {
  let result; let child1; let tail; let __t1
  result=0
  _expect_tok __ $__LBRACE__
  if [ $_tok != $__RBRACE__ ] && [ $_tok != -1 ] ; then
    if _is_type_starter __t1 $_tok; [ $__t1 != 0 ] ; then
      _parse_definition child1 1
    else
      _parse_statement child1 
    fi
    _new_ast2 result $__LBRACE__ $child1 0
    tail=$result
    while [ $_tok != $__RBRACE__ ] && [ $_tok != -1 ] ; do
      if _is_type_starter __t1 $_tok; [ $__t1 != 0 ] ; then
        _parse_definition child1 1
      else
        _parse_statement child1 
      fi
      _new_ast2 child1 $__LBRACE__ $child1 0
      _set_child __ $tail 1 $child1
      tail=$child1
    done
  fi
  _expect_tok __ $__RBRACE__
  : $(($1 = result))
  endlet $1 __t1 tail child1 result
}

_runtime_use_local_vars=0
_runtime_local_vars_defined=0
_runtime_local_vars() {
  if [ $_runtime_local_vars_defined != 0 ] ; then
    return
  fi
  _runtime_local_vars_defined=1
  printf "# Local variables\n"
  printf "__=0\n"
  printf "__SP=0\n"
  printf "let() { # \$1: variable name, \$2: value (optional) \n"
  printf "  : \$((__SP += 1)) \$((__\$__SP=\$1)) # Push\n"
  printf "  : \$((\$1=\${2-0}))                 # Init\n"
  printf "}\n"
  printf "endlet() { # \$1: return variable\n"
  printf "           # \$2...: function local variables\n"
  printf "  __ret=\$1 # Don't overwrite return value\n"
  printf "  : \$((__tmp = \$__ret))\n"
  printf "  while [ \$# -ge 2 ]; do\n"
  printf "    : \$((\$2 = __\$__SP)) \$((__SP -= 1)); # Pop\n"
  printf "    shift;\n"
  printf "  done\n"
  printf "  : \$((\$__ret=__tmp))   # Restore return value\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_int_to_char=0
_runtime_int_to_char_defined=0
_runtime_int_to_char() {
  if [ $_runtime_int_to_char_defined != 0 ] ; then
    return
  fi
  _runtime_int_to_char_defined=1
  printf "int_to_char() {\n"
  printf "  case \$1 in\n"
  printf "    48|49|50|51|52|53|54|55|56|57) __char=\$((\$1 - 48)) ;;\n"
  printf "    97)  __char=\"a\" ;;\n"
  printf "    98)  __char=\"b\" ;;\n"
  printf "    99)  __char=\"c\" ;;\n"
  printf "    100) __char=\"d\" ;;\n"
  printf "    101) __char=\"e\" ;;\n"
  printf "    102) __char=\"f\" ;;\n"
  printf "    103) __char=\"g\" ;;\n"
  printf "    104) __char=\"h\" ;;\n"
  printf "    105) __char=\"i\" ;;\n"
  printf "    106) __char=\"j\" ;;\n"
  printf "    107) __char=\"k\" ;;\n"
  printf "    108) __char=\"l\" ;;\n"
  printf "    109) __char=\"m\" ;;\n"
  printf "    110) __char=\"n\" ;;\n"
  printf "    111) __char=\"o\" ;;\n"
  printf "    112) __char=\"p\" ;;\n"
  printf "    113) __char=\"q\" ;;\n"
  printf "    114) __char=\"r\" ;;\n"
  printf "    115) __char=\"s\" ;;\n"
  printf "    116) __char=\"t\" ;;\n"
  printf "    117) __char=\"u\" ;;\n"
  printf "    118) __char=\"v\" ;;\n"
  printf "    119) __char=\"w\" ;;\n"
  printf "    120) __char=\"x\" ;;\n"
  printf "    121) __char=\"y\" ;;\n"
  printf "    122) __char=\"z\" ;;\n"
  printf "    65)  __char=\"A\" ;;\n"
  printf "    66)  __char=\"B\" ;;\n"
  printf "    67)  __char=\"C\" ;;\n"
  printf "    68)  __char=\"D\" ;;\n"
  printf "    69)  __char=\"E\" ;;\n"
  printf "    70)  __char=\"F\" ;;\n"
  printf "    71)  __char=\"G\" ;;\n"
  printf "    72)  __char=\"H\" ;;\n"
  printf "    73)  __char=\"I\" ;;\n"
  printf "    74)  __char=\"J\" ;;\n"
  printf "    75)  __char=\"K\" ;;\n"
  printf "    76)  __char=\"L\" ;;\n"
  printf "    77)  __char=\"M\" ;;\n"
  printf "    78)  __char=\"N\" ;;\n"
  printf "    79)  __char=\"O\" ;;\n"
  printf "    80)  __char=\"P\" ;;\n"
  printf "    81)  __char=\"Q\" ;;\n"
  printf "    82)  __char=\"R\" ;;\n"
  printf "    83)  __char=\"S\" ;;\n"
  printf "    84)  __char=\"T\" ;;\n"
  printf "    85)  __char=\"U\" ;;\n"
  printf "    86)  __char=\"V\" ;;\n"
  printf "    87)  __char=\"W\" ;;\n"
  printf "    88)  __char=\"X\" ;;\n"
  printf "    89)  __char=\"Y\" ;;\n"
  printf "    90)  __char=\"Z\" ;;\n"
  printf "    32)  __char=\" \" ;;\n"
  printf "    33)  __char=\"!\" ;;\n"
  printf "    34)  __char=\"\\\\\"\" ;;\n"
  printf "    35)  __char=\"#\" ;;\n"
  printf "    36)  __char=\"\$\" ;;\n"
  printf "    37)  __char=\"%%\" ;;\n"
  printf "    38)  __char=\"&\" ;;\n"
  printf "    39)  __char=\"'\" ;;\n"
  printf "    40)  __char=\"(\" ;;\n"
  printf "    41)  __char=\")\" ;;\n"
  printf "    42)  __char=\"*\" ;;\n"
  printf "    43)  __char=\"+\" ;;\n"
  printf "    44)  __char=\",\" ;;\n"
  printf "    45)  __char=\"-\" ;;\n"
  printf "    46)  __char=\".\" ;;\n"
  printf "    47)  __char=\"/\" ;;\n"
  printf "    58)  __char=\":\" ;;\n"
  printf "    59)  __char=\";\" ;;\n"
  printf "    60)  __char=\"<\" ;;\n"
  printf "    61)  __char=\"=\" ;;\n"
  printf "    62)  __char=\">\" ;;\n"
  printf "    63)  __char=\"?\" ;;\n"
  printf "    64)  __char=\"@\" ;;\n"
  printf "    91)  __char=\"[\" ;;\n"
  printf "    92)  __char=\"\\\\\\\\\" ;;\n"
  printf "    93)  __char=\"]\" ;;\n"
  printf "    94)  __char=\"^\" ;;\n"
  printf "    95)  __char=\"_\" ;;\n"
  printf "    96)  __char=\"\\\\\`\" ;;\n"
  printf "    123) __char=\"{\" ;;\n"
  printf "    124) __char=\"|\" ;;\n"
  printf "    125) __char=\"}\" ;;\n"
  printf "    126) __char=\"~\" ;;\n"
  printf "    10)  __char=\"\\\\n\" ;;\n"
  printf "    *)\n"
  printf "      echo \"Invalid character code: \$1\" ; exit 1\n"
  printf "      __char=\$(printf \"\\\\\\\\\$(printf \"%%o\" \"\$1\")\") ;;\n"
  printf "  esac\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_char_to_int=0
_runtime_char_to_int_defined=0
_runtime_char_to_int() {
  if [ $_runtime_char_to_int_defined != 0 ] ; then
    return
  fi
  _runtime_char_to_int_defined=1
  printf "__c2i_0=48\n"
  printf "__c2i_1=49\n"
  printf "__c2i_2=50\n"
  printf "__c2i_3=51\n"
  printf "__c2i_4=52\n"
  printf "__c2i_5=53\n"
  printf "__c2i_6=54\n"
  printf "__c2i_7=55\n"
  printf "__c2i_8=56\n"
  printf "__c2i_9=57\n"
  printf "__c2i_a=97\n"
  printf "__c2i_b=98\n"
  printf "__c2i_c=99\n"
  printf "__c2i_d=100\n"
  printf "__c2i_e=101\n"
  printf "__c2i_f=102\n"
  printf "__c2i_g=103\n"
  printf "__c2i_h=104\n"
  printf "__c2i_i=105\n"
  printf "__c2i_j=106\n"
  printf "__c2i_k=107\n"
  printf "__c2i_l=108\n"
  printf "__c2i_m=109\n"
  printf "__c2i_n=110\n"
  printf "__c2i_o=111\n"
  printf "__c2i_p=112\n"
  printf "__c2i_q=113\n"
  printf "__c2i_r=114\n"
  printf "__c2i_s=115\n"
  printf "__c2i_t=116\n"
  printf "__c2i_u=117\n"
  printf "__c2i_v=118\n"
  printf "__c2i_w=119\n"
  printf "__c2i_x=120\n"
  printf "__c2i_y=121\n"
  printf "__c2i_z=122\n"
  printf "__c2i_A=65\n"
  printf "__c2i_B=66\n"
  printf "__c2i_C=67\n"
  printf "__c2i_D=68\n"
  printf "__c2i_E=69\n"
  printf "__c2i_F=70\n"
  printf "__c2i_G=71\n"
  printf "__c2i_H=72\n"
  printf "__c2i_I=73\n"
  printf "__c2i_J=74\n"
  printf "__c2i_K=75\n"
  printf "__c2i_L=76\n"
  printf "__c2i_M=77\n"
  printf "__c2i_N=78\n"
  printf "__c2i_O=79\n"
  printf "__c2i_P=80\n"
  printf "__c2i_Q=81\n"
  printf "__c2i_R=82\n"
  printf "__c2i_S=83\n"
  printf "__c2i_T=84\n"
  printf "__c2i_U=85\n"
  printf "__c2i_V=86\n"
  printf "__c2i_W=87\n"
  printf "__c2i_X=88\n"
  printf "__c2i_Y=89\n"
  printf "__c2i_Z=90\n"
  printf "char_to_int() {\n"
  printf "  case \$1 in\n"
  printf "    [a-zA-Z0-9]) __c=\$((__c2i_\$1)) ;;\n"
  printf "    ' ') __c=32 ;;\n"
  printf "    '!') __c=33 ;;\n"
  printf "    '\"') __c=34 ;;\n"
  printf "    '#') __c=35 ;;\n"
  printf "    '\$') __c=36 ;;\n"
  printf "    '%%') __c=37 ;;\n"
  printf "    '&') __c=38 ;;\n"
  printf "    \"'\") __c=39 ;;\n"
  printf "    '(') __c=40 ;;\n"
  printf "    ')') __c=41 ;;\n"
  printf "    '*') __c=42 ;;\n"
  printf "    '+') __c=43 ;;\n"
  printf "    ',') __c=44 ;;\n"
  printf "    '-') __c=45 ;;\n"
  printf "    '.') __c=46 ;;\n"
  printf "    '/') __c=47 ;;\n"
  printf "    ':') __c=58 ;;\n"
  printf "    ';') __c=59 ;;\n"
  printf "    '<') __c=60 ;;\n"
  printf "    '=') __c=61 ;;\n"
  printf "    '>') __c=62 ;;\n"
  printf "    '?') __c=63 ;;\n"
  printf "    '@') __c=64 ;;\n"
  printf "    '[') __c=91 ;;\n"
  printf "    '\\\\') __c=92 ;;\n"
  printf "    ']') __c=93 ;;\n"
  printf "    '^') __c=94 ;;\n"
  printf "    '_') __c=95 ;;\n"
  printf "    '\`') __c=96 ;;\n"
  printf "    '{') __c=123 ;;\n"
  printf "    '|') __c=124 ;;\n"
  printf "    '}') __c=125 ;;\n"
  printf "    '~') __c=126 ;;\n"
  printf "    *)\n"
  printf "      __c=\$(LC_CTYPE=C printf \"%%d\" \"'\$1\")\n"
  printf "  esac\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_malloc=0
_runtime_malloc_defined=0
_runtime_malloc() {
  if [ $_runtime_malloc_defined != 0 ] ; then
    return
  fi
  _runtime_malloc_defined=1
  printf "__ALLOC=1 # Starting heap at 1 because 0 is the null pointer.\n\n"
  printf "_malloc() { # \$2 = object size\n"
  printf "  : \$((_\$__ALLOC = \$2)) # Track object size\n"
  printf "  : \$((\$1 = \$__ALLOC + 1))\n"
  printf "  : \$((__ALLOC += \$2 + 1))\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_initialize_memory=0
_runtime_initialize_memory_defined=0
_runtime_initialize_memory() {
  if [ $_runtime_initialize_memory_defined != 0 ] ; then
    return
  fi
  _runtime_initialize_memory_defined=1
  printf "# Initialize the memory to 0\n"
  printf "initialize_memory() { # \$1 = address, \$2 = length\n"
  printf "  __ix=\$1\n"
  printf "  __last=\$((\$1 + \$2))\n"
  printf "  while [ \$__ix -lt \$__last ]; do\n"
  printf "    : \$((_\$__ix=0))\n"
  printf "    : \$((__ix += 1))\n"
  printf "  done\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_defarr=0
_runtime_defarr_defined=0
_runtime_defarr() {
  if [ $_runtime_defarr_defined != 0 ] ; then
    return
  fi
  _runtime_defarr_defined=1
  _runtime_malloc __ 
  printf "defarr() { _malloc \$1 \$2; }\n"
  printf "\n"
}

_runtime_use_free=0
_runtime_free_defined=0
_runtime_free() {
  if [ $_runtime_free_defined != 0 ] ; then
    return
  fi
  _runtime_free_defined=1
  printf "_free() { # \$2 = object to free\n"
  printf "  __ptr=\$((\$2 - 1))          # Start of object\n"
  printf "  __end=\$((__ptr + _\$__ptr)) # End of object\n"
  printf "  while [ \$__ptr -lt \$__end ]; do\n"
  printf "    unset \"_\$__ptr\"\n"
  printf "    : \$((__ptr += 1))\n"
  printf "  done\n"
  printf "  : \$((\$1 = 0))              # Return 0\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_unpack_string=0
_runtime_unpack_string_defined=0
_runtime_unpack_string() {
  if [ $_runtime_unpack_string_defined != 0 ] ; then
    return
  fi
  _runtime_unpack_string_defined=1
  _runtime_malloc __ 
  _runtime_char_to_int __ 
  printf "# Convert a Shell string to a C string\n"
  printf "unpack_string() {\n"
  printf "  __str=\"\$2\"\n"
  printf "  _malloc \$1 \$((\${#__str} + 1))\n"
  printf "  __ptr=\$((\$1))\n"
  printf "  __us_buf16=\n"
  printf "  __us_buf256=\n"
  printf "  while [ ! -z \"\$__str\" ] || [ ! -z \"\$__us_buf256\" ] ; do\n"
  printf "  if [ -z \"\$__us_buf256\" ]; then\n"
  printf "    if [ \${#__str} -ge 256 ]; then\n"
  printf "      __temp=\"\${__str#????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????}\"\n"
  printf "      __us_buf256=\"\${__str%%\"\$__temp\"}\"\n"
  printf "      __str=\"\$__temp\"\n"
  printf "    else\n"
  printf "      __us_buf256=\"\$__str\"\n"
  printf "      __str=\n"
  printf ""
  printf "    fi\n"
  printf "  fi\n"
  printf "  if [ -z \"\$__us_buf16\" ]; then\n"
  printf "    if [ \${#__us_buf256} -ge 16 ]; then\n"
  printf "      __temp=\"\${__us_buf256#????????????????}\"\n"
  printf "      __us_buf16=\"\${__us_buf256%%\"\$__temp\"}\"\n"
  printf "      __us_buf256=\"\$__temp\"\n"
  printf "    else\n"
  printf "      __us_buf16=\"\$__us_buf256\"\n"
  printf "      __us_buf256=\n"
  printf ""
  printf "    fi\n"
  printf "  fi\n"
  printf "    while [ ! -z \"\$__us_buf16\" ]; do\n"
  printf "      case \"\$__us_buf16\" in\n"
  printf "        \" \"*) : \$((_\$__ptr = 32))  ;;\n"
  printf "        \"e\"*) : \$((_\$__ptr = 101)) ;;\n"
  printf "        \"=\"*) : \$((_\$__ptr = 61))  ;;\n"
  printf "        \"t\"*) : \$((_\$__ptr = 116)) ;;\n"
  printf "        \";\"*) : \$((_\$__ptr = 59))  ;;\n"
  printf "        \"i\"*) : \$((_\$__ptr = 105)) ;;\n"
  printf "        \")\"*) : \$((_\$__ptr = 41))  ;;\n"
  printf "        \"(\"*) : \$((_\$__ptr = 40))  ;;\n"
  printf "        \"n\"*) : \$((_\$__ptr = 110)) ;;\n"
  printf "        \"s\"*) : \$((_\$__ptr = 115)) ;;\n"
  printf "        \"l\"*) : \$((_\$__ptr = 108)) ;;\n"
  printf "        \"+\"*) : \$((_\$__ptr = 43))  ;;\n"
  printf "        \"p\"*) : \$((_\$__ptr = 112)) ;;\n"
  printf "        \"a\"*) : \$((_\$__ptr = 97))  ;;\n"
  printf "        \"r\"*) : \$((_\$__ptr = 114)) ;;\n"
  printf "        \"f\"*) : \$((_\$__ptr = 102)) ;;\n"
  printf "        \"d\"*) : \$((_\$__ptr = 100)) ;;\n"
  printf "        \"*\"*) : \$((_\$__ptr = 42))  ;;\n"
  printf "        *)\n"
  printf "          char_to_int \"\${__us_buf16%%\"\${__us_buf16#?}\"}\"\n"
  printf "          : \$((_\$__ptr = __c))\n"
  printf "          ;;\n"
  printf "      esac\n"
  printf "      __us_buf16=\${__us_buf16#?}  # Remove the first character\n"
  printf "      : \$((__ptr += 1))           # Move to the next buffer position\n"
  printf "    done\n"
  printf "  done\n"
  printf "  : \$((_\$__ptr = 0))\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_make_argv=0
_runtime_make_argv_defined=0
_runtime_make_argv() {
  if [ $_runtime_make_argv_defined != 0 ] ; then
    return
  fi
  _runtime_make_argv_defined=1
  _runtime_malloc __ 
  _runtime_unpack_string __ 
  printf "make_argv() {\n"
  printf "  __argc=\$1; shift;\n"
  printf "  _malloc __argv \$__argc # Allocate enough space for all elements. No need to initialize.\n"
  printf "  __argv_ptr=\$__argv\n"
  printf "\n"
  printf "  while [ \$# -ge 1 ]; do\n"
  printf "    unpack_string _\$__argv_ptr \"\$1\"\n"
  printf "    : \$((__argv_ptr += 1))\n"
  printf "    shift\n"
  printf "  done\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_unpack_escaped_string=0
_runtime_unpack_escaped_string_defined=0
_runtime_unpack_escaped_string() {
  if [ $_runtime_unpack_escaped_string_defined != 0 ] ; then
    return
  fi
  _runtime_unpack_escaped_string_defined=1
  _runtime_malloc __ 
  _runtime_char_to_int __ 
  printf "unpack_escaped_string() {\n"
  printf "  __buf=\"\$1\"\n"
  printf "  # Allocates enough space for all characters, assuming that no character is escaped\n"
  printf "  _malloc __addr \$((\${#__buf} + 1))\n"
  printf "  __ptr=\$__addr\n"
  printf "  __us_buf16=\n"
  printf "  __us_buf256=\n"
  printf "  while [ ! -z \"\$__buf\" ] || [ ! -z \"\$__us_buf256\" ] ; do\n"
  printf "    if [ -z \"\$__us_buf256\" ]; then\n"
  printf "      if [ \${#__buf} -ge 256 ]; then\n"
  printf "        __temp=\"\${__buf#????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????}\"\n"
  printf "        __us_buf256=\"\${__buf%%\"\$__temp\"}\"\n"
  printf "        __buf=\"\$__temp\"\n"
  printf "      else\n"
  printf "        __us_buf256=\"\$__buf\"\n"
  printf "        __buf=\n"
  printf ""
  printf "      fi\n"
  printf "    fi\n"
  printf "    if [ -z \"\$__us_buf16\" ]; then\n"
  printf "      if [ \${#__us_buf256} -ge 16 ]; then\n"
  printf "        __temp=\"\${__us_buf256#????????????????}\"\n"
  printf "        __us_buf16=\"\${__us_buf256%%\"\$__temp\"}\"\n"
  printf "        __us_buf256=\"\$__temp\"\n"
  printf "      else\n"
  printf "        __us_buf16=\"\$__us_buf256\"\n"
  printf "        __us_buf256=\n"
  printf ""
  printf "      fi\n"
  printf "    fi\n"
  printf "    while [ ! -z \"\$__us_buf16\" ]; do\n"
  printf "      case \"\$__us_buf16\" in\n"
  printf "        '\\\\'*)\n"
  printf "          __us_buf16=\"\${__us_buf16#?}\" # Remove the current char from \$__us_buf16\n"
  printf "          case \"\$__us_buf16\" in\n"
  printf "            'a'*) __c=7 ;;\n"
  printf "            'b'*) __c=8 ;;\n"
  printf "            'f'*) __c=12 ;;\n"
  printf "            'n'*) __c=10 ;;\n"
  printf "            'r'*) __c=13 ;;\n"
  printf "            't'*) __c=9 ;;\n"
  printf "            'v'*) __c=11 ;;\n"
  printf "            '\\\\'*) __c=92 ;;\n"
  printf "            '\"'*) __c=34 ;;\n"
  printf "            \"'\"*) __c=39 ;;\n"
  printf "            '?'*) __c=63 ;;\n"
  printf "            '\$'*) __c=36 ;; # Not in C, used to escape variable expansion between double quotes\n"
  printf "            *) echo \"invalid escape in string: \$__us_buf16\"; exit 1 ;;\n"
  printf "          esac\n"
  printf "          __us_buf16=\"\${__us_buf16#?}\" # Remove the current char from \$__us_buf16\n"
  printf "          ;;\n"
  printf "        *)\n"
  printf "          char_to_int \"\${__us_buf16%%\"\${__us_buf16#?}\"}\"\n"
  printf "          __us_buf16=\"\${__us_buf16#?}\" # Remove the current char from \$__us_buf16\n"
  printf "          ;;\n"
  printf "      esac\n"
  printf "    : \$((_\$__ptr = __c))\n"
  printf "    : \$((__ptr += 1))\n"
  printf "    done\n"
  printf "  done\n"
  printf "  : \$((_\$__ptr = 0))\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_pack_string=0
_runtime_pack_string_defined=0
_runtime_pack_string() {
  if [ $_runtime_pack_string_defined != 0 ] ; then
    return
  fi
  _runtime_pack_string_defined=1
  _runtime_int_to_char __ 
  printf "# Convert a pointer to a C string to a Shell string.\n"
  printf "# \$__res is set to the result, and \$__len is set to the length of the string.\n"
  printf "pack_string() { # \$1 = string address, \$2 = end of string delimiter (default to null), \$3 = max length (default to 100000000) \n"
  printf "  __addr=\$1; \n"
  printf "  __max_len=100000000\n"
  printf "  __delim=0\n"
  printf "  __len=0\n"
  printf "  __res=\"\"\n"
  printf "  if [ \$# -ge 2 ] ; then __delim=\$2   ; fi # Optional end of string delimiter\n"
  printf "  if [ \$# -ge 3 ] ; then __max_len=\$3 ; fi # Optional max length\n"
  printf "  while [ \$((_\$__addr)) != \$__delim ] && [ \$__max_len -gt \$__len ] ; do\n"
  printf "    __char=\$((_\$__addr))\n"
  printf "    __addr=\$((__addr + 1))\n"
  printf "    __len=\$((__len + 1))\n"
  printf "    case \$__char in\n"
  printf "      10) __res=\"\$__res\\\\n\" ;; # 10 == '\\\\n'\n"
  printf "      *)"
  printf "        int_to_char \"\$__char\"\n"
  printf "        __res=\"\$__res\$__char\" ;;\n"
  printf "    esac\n"
  printf "  done\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_defstr=0
_runtime_defstr_defined=0
_runtime_defstr() {
  if [ $_runtime_defstr_defined != 0 ] ; then
    return
  fi
  _runtime_defstr_defined=1
  _runtime_unpack_escaped_string __ 
  printf "# Define a string, and return a reference to it in the varible taken as argument.\n"
  printf "# If the variable is already defined, this function does nothing.\n"
  printf "# Note that it's up to the caller to ensure that no 2 strings share the same variable.\n"
  printf "defstr() { # \$1 = variable name, \$2 = string\n"
  printf "  set +u # Necessary to allow the variable to be empty\n"
  printf "  if [ \$((\$1)) -eq 0 ]; then\n"
  printf "    unpack_escaped_string \"\$2\"\n"
  printf "    : \$((\$1 = __addr))\n"
  printf "  fi\n"
  printf "  set -u\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_exit=0
_runtime_exit_defined=0
_runtime_exit() {
  if [ $_runtime_exit_defined != 0 ] ; then
    return
  fi
  _runtime_exit_defined=1
  printf "_exit() { # \$2: exit status\n"
  printf "  exit \$2\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_putchar=0
_runtime_putchar_defined=0
_runtime_putchar() {
  if [ $_runtime_putchar_defined != 0 ] ; then
    return
  fi
  _runtime_putchar_defined=1
  printf "_putchar() {\n"
  printf "  : \$((\$1 = 0)); shift # Return 0\n"
  printf "  printf \\\\\\\\\$((\$1/64))\$((\$1/8%%8))\$((\$1%%8))\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_getchar=0
_runtime_getchar_defined=0
_runtime_getchar() {
  if [ $_runtime_getchar_defined != 0 ] ; then
    return
  fi
  _runtime_getchar_defined=1
  _runtime_char_to_int __ 
  printf "__stdin_buf=\n"
  printf "__stdin_line_ending=0 # Line ending, either -1 (EOF) or 10 ('\\\\n')\n"
  printf "__stdin_buf16=\n"
  printf "__stdin_buf256=\n"
  printf "__stdin_end=1\n"
  printf "_getchar() {\n"
  printf "  if [ -z \"\$__stdin_buf16\" ] && [ \$__stdin_end -eq 1 ] ; then          # need to get next line when buffer empty\n"
  printf "    if [ \$__stdin_line_ending != 0 ]; then  # Line is empty, return line ending\n"
  printf "      : \$((\$1 = __stdin_line_ending))\n"
  printf "      __stdin_line_ending=0                  # Reset line ending for next getchar call\n"
  printf "      return\n"
  printf "    fi\n"
  printf "    __stdin_end=0\n"
  printf "    IFS=                                            # don't split input\n"
  printf "    if read -r __stdin_buf ; then                   # read next line into \$__stdin_buf\n"
  printf "      if [ -z \"\$__stdin_buf\" ] ; then               # an empty line implies a newline character\n"
  printf "        : \$((\$1 = 10))                              # next getchar call will read next line\n"
  printf "        return\n"
  printf "      fi\n"
  printf "      __stdin_line_ending=10\n"
  printf "    else\n"
  printf "      if [ -z \"\$__stdin_buf\" ] ; then               # EOF reached when read fails\n"
  printf "        : \$((\$1 = -1))\n"
  printf "        return\n"
  printf "      else\n"
  printf "        __stdin_line_ending=-1\n"
  printf "      fi\n"
  printf "    fi\n"
  printf "  fi\n"
  printf "  if [ -z \"\$__stdin_buf256\" ]; then\n"
  printf "    if [ \${#__stdin_buf} -ge 256 ]; then\n"
  printf "      __temp=\"\${__stdin_buf#????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????}\"\n"
  printf "      __stdin_buf256=\"\${__stdin_buf%%\"\$__temp\"}\"\n"
  printf "      __stdin_buf=\"\$__temp\"\n"
  printf "    else\n"
  printf "      __stdin_buf256=\"\$__stdin_buf\"\n"
  printf "      __stdin_buf=\n"
  printf ""
  printf "    fi\n"
  printf "  fi\n"
  printf "  if [ -z \"\$__stdin_buf16\" ]; then\n"
  printf "    if [ \${#__stdin_buf256} -ge 16 ]; then\n"
  printf "      __temp=\"\${__stdin_buf256#????????????????}\"\n"
  printf "      __stdin_buf16=\"\${__stdin_buf256%%\"\$__temp\"}\"\n"
  printf "      __stdin_buf256=\"\$__temp\"\n"
  printf "    else\n"
  printf "      __stdin_buf16=\"\$__stdin_buf256\"\n"
  printf "      __stdin_buf256=\n"
  printf "      __stdin_end=1\n"
  printf "    fi\n"
  printf "  fi\n"
  printf "  case \"\$__stdin_buf16\" in\n"
  printf "    \" \"*) : \$((\$1 = 32))  ;;\n"
  printf "    \"e\"*) : \$((\$1 = 101)) ;;\n"
  printf "    \"=\"*) : \$((\$1 = 61))  ;;\n"
  printf "    \"t\"*) : \$((\$1 = 116)) ;;\n"
  printf "    \";\"*) : \$((\$1 = 59))  ;;\n"
  printf "    \"i\"*) : \$((\$1 = 105)) ;;\n"
  printf "    \")\"*) : \$((\$1 = 41))  ;;\n"
  printf "    \"(\"*) : \$((\$1 = 40))  ;;\n"
  printf "    \"n\"*) : \$((\$1 = 110)) ;;\n"
  printf "    \"s\"*) : \$((\$1 = 115)) ;;\n"
  printf "    \"l\"*) : \$((\$1 = 108)) ;;\n"
  printf "    \"+\"*) : \$((\$1 = 43))  ;;\n"
  printf "    \"p\"*) : \$((\$1 = 112)) ;;\n"
  printf "    \"a\"*) : \$((\$1 = 97))  ;;\n"
  printf "    \"r\"*) : \$((\$1 = 114)) ;;\n"
  printf "    \"f\"*) : \$((\$1 = 102)) ;;\n"
  printf "    \"d\"*) : \$((\$1 = 100)) ;;\n"
  printf "    \"*\"*) : \$((\$1 = 42))  ;;\n"
  printf "    *)\n"
  printf "      char_to_int \"\${__stdin_buf16%%\"\${__stdin_buf16#?}\"}\"\n"
  printf "      : \$((\$1 = __c))\n"
  printf "      ;;\n"
  printf "  esac\n"
  printf "  __stdin_buf16=\${__stdin_buf16#?}  # Remove the first character\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_put_pstr=0
_runtime_put_pstr_defined=0
_runtime_put_pstr() {
  if [ $_runtime_put_pstr_defined != 0 ] ; then
    return
  fi
  _runtime_put_pstr_defined=1
  printf "_put_pstr() {\n"
  printf "  : \$((\$1 = 0)); shift # Return 0\n"
  printf "  __addr=\$1; shift\n"
  printf "  while [ \$((_\$__addr)) != 0 ]; do\n"
  printf "    printf \\\\\\\\\$((_\$__addr/64))\$((_\$__addr/8%%8))\$((_\$__addr%%8))\n"
  printf "    : \$((__addr += 1))\n"
  printf "  done\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_print_string=0
_runtime_print_string_defined=0
_runtime_print_string() {
  if [ $_runtime_print_string_defined != 0 ] ; then
    return
  fi
  _runtime_print_string_defined=1
  _runtime_int_to_char __ 
  printf "# Emit a C-string line by line so that whitespace isn't mangled\n"
  printf "print_string() {\n"
  printf "  __addr=\$1; shift\n"
  printf "  __max_len=100000000\n"
  printf "  __delim=0\n"
  printf "  __len=0\n"
  printf "  __acc=\"\"\n"
  printf "  if [ \$# -ge 1 ] ; then __delim=\$1   ; shift ; fi # Optional end of string delimiter\n"
  printf "  if [ \$# -ge 1 ] ; then __max_len=\$1 ; shift ; fi # Optional max length\n"
  printf "  while [ \$((_\$__addr)) != \$__delim ] && [ \$__max_len -gt \$__len ] ; do\n"
  printf "    __char=\$((_\$__addr))\n"
  printf "    __addr=\$((__addr + 1))\n"
  printf "    __len=\$((__len + 1))\n"
  printf "    case \$__char in\n"
  printf "      10) # 10 == '\\\\n'\n"
  printf "        printf \"%%s\\\\n\" \"\$__acc\"\n"
  printf "        __acc=\"\" ;;\n"
  printf "      *)\n"
  printf "        int_to_char \"\$__char\"\n"
  printf "        __acc=\"\$__acc\$__char\" ;;\n"
  printf "    esac\n"
  printf "  done\n"
  printf "  printf \"%%s\" \"\$__acc\"\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_printf=0
_runtime_printf_defined=0
_runtime_printf() {
  if [ $_runtime_printf_defined != 0 ] ; then
    return
  fi
  _runtime_printf_defined=1
  _runtime_print_string __ 
  _runtime_pack_string __ 
  _runtime_int_to_char __ 
  printf "_printf() { # \$1 = printf format string, \$2... = printf args\n"
  printf "  : \$((\$1 = 0)); shift # Return 0\n"
  printf "  __fmt_ptr=\$1; shift\n"
  printf "  __mod=0\n"
  printf "  while [ \"\$((_\$__fmt_ptr))\" != 0 ] ; do\n"
  printf "    __head=\$((_\$__fmt_ptr))\n"
  printf "    __fmt_ptr=\$((__fmt_ptr + 1))\n"
  printf "    if [ \$__mod -eq 1 ] ; then\n"
  printf "      int_to_char \"\$__head\"\n"
  printf "      __head_char=\$__char\n"
  printf "      case \$__head_char in\n"
  printf "        'd') # 100 = 'd' Decimal integer\n"
  printf "          printf \"%%d\" \$1\n"
  printf "          shift\n"
  printf "          ;;\n"
  printf "        'c') # 99 = 'c' Character\n"
  printf "          # Don't need to handle non-printable characters the only use of %%c is for printable characters\n"
  printf "          printf \\\\\\\\\$((\$1/64))\$((\$1/8%%8))\$((\$1%%8))\n"
  printf "          shift\n"
  printf "          ;;\n"
  printf "        'x') # 120 = 'x' Hexadecimal integer\n"
  printf "          printf \"%%x\" \$1\n"
  printf "          shift\n"
  printf "          ;;\n"
  printf "        's') # 115 = 's' String\n"
  printf "          print_string \$1\n"
  printf "          shift\n"
  printf "          ;;\n"
  printf "        '.') # String with length. %%.*s will print the first 4 characters of the string\n"
  printf "          pack_string \$__fmt_ptr 0 2 # Read next 2 characters\n"
  printf "          __fmt_ptr=\$((__fmt_ptr + 2))\n"
  printf "          if [ \"\$__res\" = \"*s\" ]; then\n"
  printf "            print_string \$2 0 \$1\n"
  printf "            shift 2\n"
  printf "          else\n"
  printf "            echo \"Unknown format specifier: %%.\$__res\" ; exit 1\n"
  printf "          fi\n"
  printf "          ;;\n"
  printf "        [0-9])                         # parse integer\n"
  printf "          # Get max length (with padding)\n"
  printf "          pack_string \$__fmt_ptr 46 # Read until '.' or end of string\n"
  printf "          __fmt_ptr=\$((__fmt_ptr + __len + 1))\n"
  printf "          __min_len=\"\$__head_char\$__res\" # Don't forget the first digit we've already read\n"
  printf "          # Get string length\n"
  printf "          pack_string \$__fmt_ptr 115 # Read until 's' or end of string\n"
  printf "          __fmt_ptr=\$((__fmt_ptr + __len))\n"
  printf "          __str_len=\$__res\n"
  printf "          __head=\$((_\$__fmt_ptr))\n"
  printf "          int_to_char \"\$__head\"\n"
  printf "          __head_char=\$__char\n"
  printf "          __fmt_ptr=\$((__fmt_ptr + 1))\n"
  printf "          if [ \"\$__head_char\" = 's' ]; then\n"
  printf "            __str_ref=\$1; shift\n"
  printf "            # Count length of string with pack_string but don't use packed string\n"
  printf "            pack_string \$__str_ref 0 \$__str_len\n"
  printf "            __pad=\"\"\n"
  printf "            __padlen=\$((__min_len - __len)) # Pad string so it has at least \$__min_len characters\n"
  printf "            while [ \$__padlen -gt 0 ]; do\n"
  printf "              __pad=\" \$__pad\"\n"
  printf "              : \$((__padlen -= 1))\n"
  printf "              done\n"
  printf "            printf \"%%s\" \"\$__pad\" # Pad string\n"
  printf "            print_string \$__str_ref 0 \$__str_len # Print string\n"
  printf "          else\n"
  printf "            echo \"Unknown format specifier: '%%\$__min_len.\$__str_len\$__head_char'\" ; exit 1;\n"
  printf "          fi\n"
  printf "          ;;\n"
  printf "        *)\n"
  printf "          echo \"Unknown format specifier %%\$__head_char\"; exit 1\n"
  printf "      esac\n"
  printf "      __mod=0\n"
  printf "    else\n"
  printf "      case \$__head in\n"
  printf "        10) printf \"\\\\n\" ;;  # 10 == '\\\\n'\n"
  printf "        37) __mod=1 ;; # 37 == '%%'\n"
  printf "        *) printf \\\\\\\\\$((\$__head/64))\$((\$__head/8%%8))\$((\$__head%%8)) ;;\n"
  printf "      esac\n"
  printf "    fi\n"
  printf "  done\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_open=0
_runtime_open_defined=0
_runtime_open() {
  if [ $_runtime_open_defined != 0 ] ; then
    return
  fi
  _runtime_open_defined=1
  _runtime_malloc __ 
  _runtime_pack_string __ 
  printf "__state_fd0=0;\n"
  printf "_malloc __buffer_fd0 1000   # Allocate buffer\n"
  printf ": \$((_\$__buffer_fd0 = 0))   # Init buffer to \"\"\n"
  printf ": \$((__cursor_fd0 = 0))     # Make buffer empty\n"
  printf ": \$((__buflen_fd0 = 1000))  # Init buffer length\n"
  printf "__state_fd1=1\n"
  printf "__state_fd2=1\n"
  printf "__state_fd3=-1\n"
  printf "__state_fd4=-1\n"
  printf "__state_fd5=-1\n"
  printf "__state_fd6=-1\n"
  printf "__state_fd7=-1\n"
  printf "__state_fd8=-1\n"
  printf "__state_fd9=-1\n"
  printf "\n"
  printf "_open() { # \$2: filename, \$3: flags, \$4: mode\n"
  printf "  # Get available fd\n"
  printf "  __fd=0\n"
  printf "  while [ \$__fd -lt 10 ]; do\n"
  printf "    if [ \$((__state_fd\$__fd)) -lt 0 ]; then\n"
  printf "      break\n"
  printf "    fi\n"
  printf "    : \$((__fd += 1))\n"
  printf "  done\n"
  printf "  if [ \$__fd -gt 9 ] ; then\n"
  printf "    # Some shells don't support fd > 9\n"
  printf "    echo \"No more file descriptors available\" ; exit 1\n"
  printf "  else\n"
  printf "    # Because the file must be read line-by-line, and string\n"
  printf "    # values can't be assigned to dynamic variables, each line\n"
  printf "    # is read and then unpacked in the buffer.\n"
  printf "    _malloc __addr 1000                   # Allocate buffer\n"
  printf "    : \$((_\$__addr = 0))                 # Init buffer to \"\"\n"
  printf "    : \$((__buffer_fd\$__fd = __addr))    # Save buffer address\n"
  printf "    : \$((__cursor_fd\$__fd = 0))         # Make buffer empty\n"
  printf "    : \$((__buflen_fd\$__fd = 1000))      # Init buffer length\n"
  printf "    : \$((__state_fd\$__fd = \$3))         # Mark the fd as opened\n"
  printf "    pack_string \$2\n"
  printf "    if [ \$3 = 0 ] ; then\n"
  printf "      case \$__fd in\n"
  printf "        0) exec 0< \$__res ;; 1) exec 1< \$__res ;; 2) exec 2< \$__res ;;\n"
  printf "        3) exec 3< \$__res ;; 4) exec 4< \$__res ;; 5) exec 5< \$__res ;;\n"
  printf "        6) exec 6< \$__res ;; 7) exec 7< \$__res ;; 8) exec 8< \$__res ;;\n"
  printf "        9) exec 9< \$__res ;;\n"
  printf "      esac\n"
  printf "    elif [ \$3 = 1 ] ; then\n"
  printf "      case \$__fd in\n"
  printf "        0) exec 0> \$__res ;; 1) exec 1> \$__res ;; 2) exec 2> \$__res ;;\n"
  printf "        3) exec 3> \$__res ;; 4) exec 4> \$__res ;; 5) exec 5> \$__res ;;\n"
  printf "        6) exec 6> \$__res ;; 7) exec 7> \$__res ;; 8) exec 8> \$__res ;;\n"
  printf "        9) exec 9> \$__res ;;\n"
  printf "      esac\n"
  printf "    elif [ \$3 = 2 ] ; then\n"
  printf "      case \$__fd in\n"
  printf "        0) exec 0>> \$__res ;; 1) exec 1>> \$__res ;; 2) exec 2>> \$__res ;;\n"
  printf "        3) exec 3>> \$__res ;; 4) exec 4>> \$__res ;; 5) exec 5>> \$__res ;;\n"
  printf "        6) exec 6>> \$__res ;; 7) exec 7>> \$__res ;; 8) exec 8>> \$__res ;;\n"
  printf "        9) exec 9>> \$__res ;;\n"
  printf "      esac\n"
  printf "    else\n"
  printf "      echo \"Unknow file mode\" ; exit 1\n"
  printf "    fi\n"
  printf "  fi\n"
  printf "  : \$((\$1 = __fd))\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_read_byte=0
_runtime_read_byte_defined=0
_runtime_read_byte() {
  if [ $_runtime_read_byte_defined != 0 ] ; then
    return
  fi
  _runtime_read_byte_defined=1
  _runtime_malloc __ 
  _runtime_free __ 
  _runtime_char_to_int __ 
  printf "# Unpack a Shell string into an appropriately sized buffer\n"
  printf "unpack_line() { # \$1: Shell string, \$2: Buffer, \$3: Ends with EOF?\n"
  printf "  __fgetc_buf=\$1\n"
  printf "  __buffer=\$2\n"
  printf "  __ends_with_eof=\$3\n"
  printf "  __fgetc_buf16=\n"
  printf "  __stdin_buf256=\n"
  printf "  __continue=1\n"
  printf "  while [ \$__continue != 0 ] ; do\n"
  printf "    if [ -z \"\$__stdin_buf256\" ]; then\n"
  printf "      if [ \${#__fgetc_buf} -ge 256 ]; then\n"
  printf "        __temp=\"\${__fgetc_buf#????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????}\"\n"
  printf "        __stdin_buf256=\"\${__fgetc_buf%%\"\$__temp\"}\"\n"
  printf "        __fgetc_buf=\"\$__temp\"\n"
  printf "      else\n"
  printf "        __stdin_buf256=\"\$__fgetc_buf\"\n"
  printf "        __fgetc_buf=\n"
  printf ""
  printf "      fi\n"
  printf "    fi\n"
  printf "    if [ -z \"\$__fgetc_buf16\" ]; then\n"
  printf "      if [ \${#__stdin_buf256} -ge 16 ]; then\n"
  printf "        __temp=\"\${__stdin_buf256#????????????????}\"\n"
  printf "        __fgetc_buf16=\"\${__stdin_buf256%%\"\$__temp\"}\"\n"
  printf "        __stdin_buf256=\"\$__temp\"\n"
  printf "      else\n"
  printf "        __fgetc_buf16=\"\$__stdin_buf256\"\n"
  printf "        __stdin_buf256=\n"
  printf "        __continue=0\n"
  printf "      fi\n"
  printf "    fi\n"
  printf "    while [ ! -z \"\$__fgetc_buf16\" ]; do\n"
  printf "      case \"\$__fgetc_buf16\" in\n"
  printf "        \" \"*) : \$((_\$__buffer = 32))  ;;\n"
  printf "        \"e\"*) : \$((_\$__buffer = 101)) ;;\n"
  printf "        \"=\"*) : \$((_\$__buffer = 61))  ;;\n"
  printf "        \"t\"*) : \$((_\$__buffer = 116)) ;;\n"
  printf "        \";\"*) : \$((_\$__buffer = 59))  ;;\n"
  printf "        \"i\"*) : \$((_\$__buffer = 105)) ;;\n"
  printf "        \")\"*) : \$((_\$__buffer = 41))  ;;\n"
  printf "        \"(\"*) : \$((_\$__buffer = 40))  ;;\n"
  printf "        \"n\"*) : \$((_\$__buffer = 110)) ;;\n"
  printf "        \"s\"*) : \$((_\$__buffer = 115)) ;;\n"
  printf "        \"l\"*) : \$((_\$__buffer = 108)) ;;\n"
  printf "        \"+\"*) : \$((_\$__buffer = 43))  ;;\n"
  printf "        \"p\"*) : \$((_\$__buffer = 112)) ;;\n"
  printf "        \"a\"*) : \$((_\$__buffer = 97))  ;;\n"
  printf "        \"r\"*) : \$((_\$__buffer = 114)) ;;\n"
  printf "        \"f\"*) : \$((_\$__buffer = 102)) ;;\n"
  printf "        \"d\"*) : \$((_\$__buffer = 100)) ;;\n"
  printf "        \"*\"*) : \$((_\$__buffer = 42))  ;;\n"
  printf "        *)\n"
  printf "          char_to_int \"\${__fgetc_buf16%%\"\${__fgetc_buf16#?}\"}\"\n"
  printf "          : \$((_\$__buffer = __c))\n"
  printf "          ;;\n"
  printf "      esac\n"
  printf "      __fgetc_buf16=\${__fgetc_buf16#?}  # Remove the first character\n"
  printf "      : \$((__buffer += 1))              # Move to the next buffer position\n"
  printf "    done\n"
  printf "  done\n"
  printf "\n"
  printf "  if [ \$__ends_with_eof -eq 0 ]; then # Ends with newline and not EOF?\n"
  printf "    : \$((_\$__buffer = 10))            # Line ends with newline\n"
  printf "    : \$((__buffer += 1))\n"
  printf "  fi\n"
  printf "  : \$((_\$__buffer = 0))               # Then \\\\0\n"
  printf "}\n"
  printf "\n"
  printf "refill_buffer() { # \$1: fd\n"
  printf "  __fd=\$1\n"
  printf "  __buffer=\$((__buffer_fd\$__fd))\n"
  printf "\n"
  printf "  IFS=\n"
  printf "  if read -r __temp_buf <&\$__fd ; then  # read next line into \$__temp_buf\n"
  printf "    __ends_with_eof=0\n"
  printf "  else\n"
  printf "    __ends_with_eof=1\n"
  printf "  fi\n"
  printf "\n"
  printf "  # Check that the buffer is large enough to unpack the line\n"
  printf "  __buflen=\$((__buflen_fd\$__fd - 2)) # Minus 2 to account for newline and \\\\0\n"
  printf "  __len=\${#__temp_buf}\n"
  printf "  if [ \$__len -gt \$__buflen ]; then\n"
  printf "    # Free buffer and reallocate a new one double the line size\n"
  printf "    __buflen=\$((__len * 2))\n"
  printf "    _free __ \$__buffer\n"
  printf "    _malloc __buffer \$__buflen\n"
  printf "    : \$((__buffer_fd\$__fd = __buffer))\n"
  printf "    : \$((__buflen_fd\$__fd = __buflen))\n"
  printf "  fi\n"
  printf "  unpack_line \"\$__temp_buf\" \$__buffer \$__ends_with_eof\n"
  printf "}\n"
  printf "\n"
  printf "read_byte() { # \$2: fd\n"
  printf "  __fd=\$2\n"
  printf "  : \$((__buffer=__buffer_fd\$__fd))\n"
  printf "  : \$((__cursor=__cursor_fd\$__fd))\n"
  printf "  # The cursor is at the end of the buffer, we need to read the next line\n"
  printf "  if [ \$((_\$((__buffer + __cursor)))) -eq 0 ]; then\n"
  printf "    # Buffer has been read completely, read next line\n"
  printf "    refill_buffer \$__fd\n"
  printf "    __cursor=0 # Reset cursor and reload buffer\n"
  printf "    : \$((__buffer=__buffer_fd\$__fd))\n"
  printf "    if [ \$((_\$((__buffer + __cursor)))) -eq 0 ]; then\n"
  printf "      : \$((\$1 = -1)) # EOF\n"
  printf "      return\n"
  printf "    fi\n"
  printf "  fi\n"
  printf "  : \$((\$1 = _\$((__buffer + __cursor))))\n"
  printf "  : \$((__cursor_fd\$__fd = __cursor + 1))  # Increment cursor\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_read=0
_runtime_read_defined=0
_runtime_read() {
  if [ $_runtime_read_defined != 0 ] ; then
    return
  fi
  _runtime_read_defined=1
  _runtime_read_byte __ 
  _runtime_open __ 
  printf "_read() { : \$((__fd = \$2)) \$((__buf = \$3)) \$((__count = \$4))\n"
  printf "  : \$((__i = 0))\n"
  printf "  while [ \$__i -lt \$__count ] ; do\n"
  printf "    read_byte __byte \$__fd\n"
  printf "    if [ \$__byte -lt 0 ] ; then\n"
  printf "      break\n"
  printf "    fi\n"
  printf "    : \$((_\$((__buf + __i)) = __byte))\n"
  printf "    : \$((__i += 1))\n"
  printf "  done\n"
  printf "  : \$((\$1 = __i))\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_write=0
_runtime_write_defined=0
_runtime_write() {
  if [ $_runtime_write_defined != 0 ] ; then
    return
  fi
  _runtime_write_defined=1
  _runtime_open __ 
  printf "_write() { : \$((__fd = \$2)) \$((__buf = \$3)) \$((__count = \$4))\n"
  printf "  : \$((__i = 0))\n"
  printf "  while [ \$__i -lt \$__count ] ; do\n"
  printf "    : \$((__byte = _\$((__buf+__i))))\n"
  printf "    printf \\\\\\\\\$((\$__byte/64))\$((\$__byte/8%%8))\$((\$__byte%%8)) >&\$__fd\n"
  printf "    : \$((__i += 1))\n"
  printf "  done\n"
  printf "  : \$((\$1 = __count))\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_fopen=0
_runtime_fopen_defined=0
_runtime_fopen() {
  if [ $_runtime_fopen_defined != 0 ] ; then
    return
  fi
  _runtime_fopen_defined=1
  _runtime_malloc __ 
  _runtime_open __ 
  printf "# Open the file and return a FILE* for the file.\n"
  printf "# The FILE structure contains the file descriptor.\n"
  printf "_fopen() { # \$2: File name, \$3: Mode\n"
  printf "  _open __fd \$2 \$((_\$3 == 119)) 511\n"
  printf "  _malloc __file 1        # Allocate FILE structure\n"
  printf "  : \$((_\$__file = __fd))  # Save fd\n"
  printf "  : \$((\$1 = __file))\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_close=0
_runtime_close_defined=0
_runtime_close() {
  if [ $_runtime_close_defined != 0 ] ; then
    return
  fi
  _runtime_close_defined=1
  _runtime_open __ 
  _runtime_free __ 
  printf "_close() { # \$2: fd\n"
  printf "  __fd=\$2\n"
  printf "  __buf=\$((__buffer_fd\$__fd))  # Get buffer\n"
  printf "  _free __ \$__buf              # Release buffer\n"
  printf "  : \$((__state_fd\$__fd = -1))  # Mark the fd as closed\n"
  printf "  case \$__fd in\n"
  printf "    0) exec 0<&- ;; 1) exec 1<&- ;; 2) exec 2<&- ;;\n"
  printf "    3) exec 3<&- ;; 4) exec 4<&- ;; 5) exec 5<&- ;;\n"
  printf "    6) exec 6<&- ;; 7) exec 7<&- ;; 8) exec 8<&- ;;\n"
  printf "    9) exec 9<&- ;;\n"
  printf "  esac\n"
  printf "  : \$((\$1 = 0))\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_fclose=0
_runtime_fclose_defined=0
_runtime_fclose() {
  if [ $_runtime_fclose_defined != 0 ] ; then
    return
  fi
  _runtime_fclose_defined=1
  _runtime_free __ 
  _runtime_close __ 
  printf "_fclose() { # \$2: file\n"
  printf "  __file=\$2\n"
  printf "  __fd=\$((_\$__file))  # Get fd\n"
  printf "  _free __ \$__file    # Release FILE structure\n"
  printf "  _close \$1 \$__fd\n"
  printf "}\n"
  printf "\n"
}

_runtime_use_fgetc=0
_runtime_fgetc_defined=0
_runtime_fgetc() {
  if [ $_runtime_fgetc_defined != 0 ] ; then
    return
  fi
  _runtime_fgetc_defined=1
  _runtime_read_byte __ 
  printf "_fgetc() { # \$2: file\n"
  printf "  __file=\$2\n"
  printf "  __fd=\$((_\$__file))\n"
  printf "  read_byte \$1 \$__fd\n"
  printf "}\n"
  printf "\n"
}

_produce_runtime() {
  if [ $_runtime_use_defstr != 0 ] ; then
    _runtime_defstr __ 
  fi
  if [ $_runtime_use_putchar != 0 ] ; then
    _runtime_putchar __ 
  fi
  if [ $_runtime_use_getchar != 0 ] ; then
    _runtime_getchar __ 
  fi
  if [ $_runtime_use_exit != 0 ] ; then
    _runtime_exit __ 
  fi
  if [ $_runtime_use_malloc != 0 ] ; then
    _runtime_malloc __ 
  fi
  if [ $_runtime_use_free != 0 ] ; then
    _runtime_free __ 
  fi
  if [ $_runtime_use_put_pstr != 0 ] ; then
    _runtime_put_pstr __ 
  fi
  if [ $_runtime_use_printf != 0 ] ; then
    _runtime_printf __ 
  fi
  if [ $_runtime_use_fopen != 0 ] ; then
    _runtime_fopen __ 
  fi
  if [ $_runtime_use_fclose != 0 ] ; then
    _runtime_fclose __ 
  fi
  if [ $_runtime_use_fgetc != 0 ] ; then
    _runtime_fgetc __ 
  fi
  if [ $_runtime_use_read != 0 ] ; then
    _runtime_read __ 
  fi
  if [ $_runtime_use_write != 0 ] ; then
    _runtime_write __ 
  fi
  if [ $_runtime_use_open != 0 ] ; then
    _runtime_open __ 
  fi
  if [ $_runtime_use_close != 0 ] ; then
    _runtime_close __ 
  fi
  if [ $_runtime_use_make_argv != 0 ] ; then
    _runtime_make_argv __ 
  fi
  if [ $_runtime_use_local_vars != 0 ] ; then
    _runtime_local_vars __ 
  fi
  if [ $_runtime_use_pack_string != 0 ] ; then
    _runtime_pack_string __ 
  fi
  if [ $_runtime_use_unpack_string != 0 ] ; then
    _runtime_unpack_string __ 
  fi
}

: $((__t1 = c = shell_include_fp = 0))
_handle_shell_include() {
  let shell_include_fp; let c; let __t1
  _get_tok __ 
  if [ $_tok = $_STRING ] ; then
    defstr __str_122 "r"
    _fopen shell_include_fp $((_string_pool + _val)) $__str_122
    _runtime_use_pack_string=1
    _runtime_use_unpack_string=1
    while _fgetc __t1 $shell_include_fp; [ $((c = __t1)) != -1 ] ; do
      printf \\$((c/64))$((c/8%8))$((c%8))
    done
    printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
    _fclose __ $shell_include_fp
  else
    printf "tok="
    _putint __ $_tok
    printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
    defstr __str_123 "expected string to #include_shell directive"
    _syntax_error __ $__str_123
  fi
  endlet $1 __t1 c shell_include_fp
}

: $((c = 0))
_print_string_char() { let c $2
  if [ $c = 7 ] ; then
    printf "\\\\a"
  elif [ $c = 8 ] ; then
    printf "\\\\b"
  elif [ $c = 12 ] ; then
    printf "\\\\f"
  elif [ $c = 10 ] ; then
    printf "\\\\n"
  elif [ $c = 13 ] ; then
    printf "\\\\r"
  elif [ $c = 9 ] ; then
    printf "\\\\t"
  elif [ $c = 11 ] ; then
    printf "\\\\v"
  elif [ $c = $__BACKSLASH__ ] || [ $c = $__QUOTE__ ] || [ $c = $__DQUOTE__ ] ; then
    printf "\\\\"
    printf \\$((c/64))$((c/8%8))$((c%8))
  elif [ $c -lt 32 ] || [ $c -gt 126 ] ; then
    printf "\\\\"
    _putint __ $((c >> 6))
    _putint __ $(((c >> 3) & 7))
    _putint __ $((c & 7))
  else
    printf \\$((c/64))$((c/8%8))$((c%8))
  fi
  endlet $1 c
}

defarr _text_pool 1000000
_text_alloc=1
# TEXT_NODES enum declaration
readonly _TEXT_TREE=0
readonly _TEXT_INTEGER=1
readonly _TEXT_FROM_POOL=2
readonly _TEXT_ESCAPED=3
: $((i = 0))
_wrap_int() { let i $2
  if [ $((_text_alloc + 3)) -ge 1000000 ] ; then
    defstr __str_124 "string tree pool overflow"
    _fatal_error __ $__str_124
  fi
  : $((_$((_text_pool + _text_alloc)) = _TEXT_INTEGER))
  : $((_$((_text_pool + _text_alloc + 1)) = i))
  : $(($1 = (_text_alloc += 2) - 2))
  endlet $1 i
}

: $((for_printf = t = 0))
_escape_text() { let t $2; let for_printf $3
  if [ $((_text_alloc + 3)) -ge 1000000 ] ; then
    defstr __str_125 "string tree pool overflow"
    _fatal_error __ $__str_125
  fi
  : $((_$((_text_pool + _text_alloc)) = _TEXT_ESCAPED))
  : $((_$((_text_pool + _text_alloc + 1)) = t))
  : $((_$((_text_pool + _text_alloc + 2)) = for_printf))
  : $(($1 = (_text_alloc += 3) - 3))
  endlet $1 for_printf t
}

: $((t2 = t1 = 0))
_string_concat() { let t1 $2; let t2 $3
  if [ $((_text_alloc + 4)) -ge 1000000 ] ; then
    defstr __str_126 "string tree pool overflow"
    _fatal_error __ $__str_126
  fi
  : $((_$((_text_pool + _text_alloc)) = _TEXT_TREE))
  : $((_$((_text_pool + _text_alloc + 1)) = 2))
  : $((_$((_text_pool + _text_alloc + 2)) = t1))
  : $((_$((_text_pool + _text_alloc + 3)) = t2))
  : $(($1 = (_text_alloc += 4) - 4))
  endlet $1 t2 t1
}

: $((t3 = t2 = t1 = 0))
_string_concat3() { let t1 $2; let t2 $3; let t3 $4
  if [ $((_text_alloc + 5)) -ge 1000000 ] ; then
    defstr __str_127 "string tree pool overflow"
    _fatal_error __ $__str_127
  fi
  : $((_$((_text_pool + _text_alloc)) = _TEXT_TREE))
  : $((_$((_text_pool + _text_alloc + 1)) = 3))
  : $((_$((_text_pool + _text_alloc + 2)) = t1))
  : $((_$((_text_pool + _text_alloc + 3)) = t2))
  : $((_$((_text_pool + _text_alloc + 4)) = t3))
  : $(($1 = (_text_alloc += 5) - 5))
  endlet $1 t3 t2 t1
}

: $((t4 = t3 = t2 = t1 = 0))
_string_concat4() { let t1 $2; let t2 $3; let t3 $4; let t4 $5
  if [ $((_text_alloc + 6)) -ge 1000000 ] ; then
    defstr __str_128 "string tree pool overflow"
    _fatal_error __ $__str_128
  fi
  : $((_$((_text_pool + _text_alloc)) = _TEXT_TREE))
  : $((_$((_text_pool + _text_alloc + 1)) = 4))
  : $((_$((_text_pool + _text_alloc + 2)) = t1))
  : $((_$((_text_pool + _text_alloc + 3)) = t2))
  : $((_$((_text_pool + _text_alloc + 4)) = t3))
  : $((_$((_text_pool + _text_alloc + 5)) = t4))
  : $(($1 = (_text_alloc += 6) - 6))
  endlet $1 t4 t3 t2 t1
}

: $((t5 = t4 = t3 = t2 = t1 = 0))
_string_concat5() { let t1 $2; let t2 $3; let t3 $4; let t4 $5; let t5 $6
  if [ $((_text_alloc + 7)) -ge 1000000 ] ; then
    defstr __str_129 "string tree pool overflow"
    _fatal_error __ $__str_129
  fi
  : $((_$((_text_pool + _text_alloc)) = _TEXT_TREE))
  : $((_$((_text_pool + _text_alloc + 1)) = 5))
  : $((_$((_text_pool + _text_alloc + 2)) = t1))
  : $((_$((_text_pool + _text_alloc + 3)) = t2))
  : $((_$((_text_pool + _text_alloc + 4)) = t3))
  : $((_$((_text_pool + _text_alloc + 5)) = t4))
  : $((_$((_text_pool + _text_alloc + 6)) = t5))
  : $(($1 = (_text_alloc += 7) - 7))
  endlet $1 t5 t4 t3 t2 t1
}

: $((result = i = s = 0))
_wrap_str() { let s $2
  let i; let result
  i=0
  result=$_text_alloc
  : $((_$((_text_pool + result)) = _TEXT_TREE))
  : $((_text_alloc += 2))
  while [ $((_$((s + i)))) != 0 ] ; do
    : $((_$((_text_pool + _text_alloc)) = -(_$((s + i)))))
    : $((_text_alloc += 1))
    : $((i += 1))
  done
  : $((_$((_text_pool + result + 1)) = i))
  : $(($1 = result))
  endlet $1 result i s
}

: $((s = 0))
_wrap_str_pool() { let s $2
  if [ $((_text_alloc + 3)) -ge 1000000 ] ; then
    defstr __str_130 "string tree pool overflow"
    _fatal_error __ $__str_130
  fi
  : $((_$((_text_pool + _text_alloc)) = _TEXT_FROM_POOL))
  : $((_$((_text_pool + _text_alloc + 1)) = s))
  : $(($1 = (_text_alloc += 2) - 2))
  endlet $1 s
}

: $((sep = t2 = t1 = 0))
_concatenate_strings_with() { let t1 $2; let t2 $3; let sep $4
  if [ $t1 = 0 ] ; then
    : $(($1 = t2))
    endlet $1 sep t2 t1
    return
  fi
  if [ $t2 = 0 ] ; then
    : $(($1 = t1))
    endlet $1 sep t2 t1
    return
  fi
  _string_concat3 $1 $t1 $sep $t2
  endlet $1 sep t2 t1
}

: $((for_printf = c = 0))
_print_escaped_char() { let c $2; let for_printf $3
  if [ $c = $__ALARM__ ] ; then
    printf \\$(((__BACKSLASH__)/64))$(((__BACKSLASH__)/8%8))$(((__BACKSLASH__)%8))
    printf \\$(((__a__)/64))$(((__a__)/8%8))$(((__a__)%8))
  elif [ $c = $__BACKSPACE__ ] ; then
    printf \\$(((__BACKSLASH__)/64))$(((__BACKSLASH__)/8%8))$(((__BACKSLASH__)%8))
    printf \\$(((__b__)/64))$(((__b__)/8%8))$(((__b__)%8))
  elif [ $c = $__PAGE__ ] ; then
    printf \\$(((__BACKSLASH__)/64))$(((__BACKSLASH__)/8%8))$(((__BACKSLASH__)%8))
    printf \\$(((__f__)/64))$(((__f__)/8%8))$(((__f__)%8))
  elif [ $c = $__NEWLINE__ ] ; then
    printf \\$(((__BACKSLASH__)/64))$(((__BACKSLASH__)/8%8))$(((__BACKSLASH__)%8))
    printf \\$(((__n__)/64))$(((__n__)/8%8))$(((__n__)%8))
  elif [ $c = $__RET__ ] ; then
    printf \\$(((__BACKSLASH__)/64))$(((__BACKSLASH__)/8%8))$(((__BACKSLASH__)%8))
    printf \\$(((__r__)/64))$(((__r__)/8%8))$(((__r__)%8))
  elif [ $c = $__TAB__ ] ; then
    printf \\$(((__BACKSLASH__)/64))$(((__BACKSLASH__)/8%8))$(((__BACKSLASH__)%8))
    printf \\$(((__t__)/64))$(((__t__)/8%8))$(((__t__)%8))
  elif [ $c = $__VTAB__ ] ; then
    printf \\$(((__BACKSLASH__)/64))$(((__BACKSLASH__)/8%8))$(((__BACKSLASH__)%8))
    printf \\$(((__v__)/64))$(((__v__)/8%8))$(((__v__)%8))
  elif [ $c = $__BACKSLASH__ ] ; then
    printf \\$(((__BACKSLASH__)/64))$(((__BACKSLASH__)/8%8))$(((__BACKSLASH__)%8))
    printf \\$(((__BACKSLASH__)/64))$(((__BACKSLASH__)/8%8))$(((__BACKSLASH__)%8))
    printf \\$(((__BACKSLASH__)/64))$(((__BACKSLASH__)/8%8))$(((__BACKSLASH__)%8))
    printf \\$(((__BACKSLASH__)/64))$(((__BACKSLASH__)/8%8))$(((__BACKSLASH__)%8))
  elif [ $c = $__DOLLAR__ ] ; then
    printf \\$(((__BACKSLASH__)/64))$(((__BACKSLASH__)/8%8))$(((__BACKSLASH__)%8))
    printf \\$(((__DOLLAR__)/64))$(((__DOLLAR__)/8%8))$(((__DOLLAR__)%8))
  elif [ $c = $__BACKTICK__ ] ; then
    printf \\$(((__BACKSLASH__)/64))$(((__BACKSLASH__)/8%8))$(((__BACKSLASH__)%8))
    printf \\$(((__BACKTICK__)/64))$(((__BACKTICK__)/8%8))$(((__BACKTICK__)%8))
  elif [ $c = $__DQUOTE__ ] ; then
    printf \\$(((__BACKSLASH__)/64))$(((__BACKSLASH__)/8%8))$(((__BACKSLASH__)%8))
    printf \\$(((__DQUOTE__)/64))$(((__DQUOTE__)/8%8))$(((__DQUOTE__)%8))
  elif [ $c = $__PERCENT__ ] && [ $for_printf != 0 ] ; then
    printf \\$(((__PERCENT__)/64))$(((__PERCENT__)/8%8))$(((__PERCENT__)%8))
    printf \\$(((__PERCENT__)/64))$(((__PERCENT__)/8%8))$(((__PERCENT__)%8))
  else
    printf \\$((c/64))$((c/8%8))$((c%8))
  fi
  endlet $1 for_printf c
}

: $((i = for_printf = s = 0))
_print_escaped_string() { let s $2; let for_printf $3
  let i
  i=0
  while [ $((_$((s + i)))) != 0 ] ; do
    _print_escaped_char __ $((_$((s + i)))) $for_printf
    : $((i += 1))
  done
  endlet $1 i for_printf s
}

: $((i = for_printf = t = 0))
_print_escaped_text() { let t $2; let for_printf $3
  let i
  if [ $t = 0 ] ; then
    endlet $1 i for_printf t
    return
  fi
  if [ $t -lt 0 ] ; then
    _print_escaped_char __ $((-(t))) $for_printf
  elif [ $((_$((_text_pool + t)))) = $_TEXT_TREE ] ; then
    i=0
    while [ $i -lt $((_$((_text_pool + t + 1)))) ] ; do
      if [ $((_$((_text_pool + t + i + 2)))) -lt 0 ] ; then
        _print_escaped_char __ $((-(_$((_text_pool + t + i + 2))))) $for_printf
      else
        _print_escaped_text __ $((_$((_text_pool + t + i + 2)))) $for_printf
      fi
      : $((i += 1))
    done
  elif [ $((_$((_text_pool + t)))) = $_TEXT_INTEGER ] ; then
    _putint __ $((_$((_text_pool + t + 1))))
  elif [ $((_$((_text_pool + t)))) = $_TEXT_FROM_POOL ] ; then
    _print_escaped_string __ $((_string_pool + _$((_text_pool + t + 1)))) $for_printf
  elif [ $((_$((_text_pool + t)))) = $_TEXT_ESCAPED ] ; then
    defstr __str_131 "Cannot escape a string that is already escaped"
    _fatal_error __ $__str_131
  else
    printf "\nt=%d %d\n" $t $((_$((_text_pool + t))))
    defstr __str_132 "print_escaped_text: unexpected string tree node"
    _fatal_error __ $__str_132
  fi
  endlet $1 i for_printf t
}

: $((i = t = 0))
_print_text() { let t $2
  let i
  if [ $t = 0 ] ; then
    endlet $1 i t
    return
  fi
  if [ $t -lt 0 ] ; then
    printf \\$(((-(t))/64))$(((-(t))/8%8))$(((-(t))%8))
  elif [ $((_$((_text_pool + t)))) = $_TEXT_TREE ] ; then
    i=0
    while [ $i -lt $((_$((_text_pool + t + 1)))) ] ; do
      if [ $((_$((_text_pool + t + i + 2)))) -lt 0 ] ; then
        printf \\$(((-(_$((_text_pool + t + i + 2))))/64))$(((-(_$((_text_pool + t + i + 2))))/8%8))$(((-(_$((_text_pool + t + i + 2))))%8))
      else
        _print_text __ $((_$((_text_pool + t + i + 2))))
      fi
      : $((i += 1))
    done
  elif [ $((_$((_text_pool + t)))) = $_TEXT_INTEGER ] ; then
    _putint __ $((_$((_text_pool + t + 1))))
  elif [ $((_$((_text_pool + t)))) = $_TEXT_FROM_POOL ] ; then
    _putstr __ $((_string_pool + _$((_text_pool + t + 1))))
  elif [ $((_$((_text_pool + t)))) = $_TEXT_ESCAPED ] ; then
    _print_escaped_text __ $((_$((_text_pool + t + 1)))) $((_$((_text_pool + t + 2))))
  else
    printf "\nt=%d %d\n" $t $((_$((_text_pool + t))))
    defstr __str_133 "print_text: unexpected string tree node"
    _fatal_error __ $__str_133
  fi
  endlet $1 i t
}

defarr _glo_decls 100000
_glo_decl_ix=0
_nest_level=0
_in_tail_position=0
_in_block_head_position=0
_loop_nesting_level=0
_loop_end_actions_start=0
_loop_end_actions_end=0
_local_env=0
_local_env_size=0
_gensym_ix=0
_fun_gensym_ix=0
_max_gensym_ix=0
_string_counter=0
defarr _characters_useds 16
_any_character_used=0
_rest_loc_var_fixups=0
_main_defined=0
_main_returns=0
_top_level_stmt=1
_IDENTIFIER_INTERNAL=600
_IDENTIFIER_STRING=601
_IDENTIFIER_DOLLAR=602
_IDENTIFIER_EMPTY=603
_LOCAL_VAR=0
_KIND_LOCAL=0
_KIND_PARAM=1
: $((i = 0))
_init_comp_context() {
  let i
  i=0
  while [ $i -lt 16 ] ; do
    : $((_$((_characters_useds + i)) = 0))
    : $((i += 1))
  done
  endlet $1 i
}

: $((decl = 0))
_append_glo_decl() { let decl $2
  : $((_$((_glo_decls + _glo_decl_ix)) = _nest_level))
  : $((_$((_glo_decls + _glo_decl_ix + 1)) = 1))
  : $((_$((_glo_decls + _glo_decl_ix + 2)) = decl))
  : $((_glo_decl_ix += 3))
  endlet $1 decl
}

_append_glo_decl_fixup() {
  : $((_$((_glo_decls + _glo_decl_ix)) = _nest_level))
  : $((_$((_glo_decls + _glo_decl_ix + 1)) = 1))
  : $((_$((_glo_decls + _glo_decl_ix + 2)) = -1))
  : $((_glo_decl_ix += 3))
  : $(($1 = _glo_decl_ix - 3))
}

: $((decl = fixup_ix = 0))
_fixup_glo_decl() { let fixup_ix $2; let decl $3
  if [ $((_$((_glo_decls + fixup_ix + 2)))) != -1 ] ; then
    defstr __str_134 "fixup_glo_decl: invalid fixup"
    _fatal_error __ $__str_134
  fi
  : $((_$((_glo_decls + fixup_ix + 2)) = decl))
  endlet $1 decl fixup_ix
}

: $((start = 0))
_undo_glo_decls() { let start $2
  while [ $start -lt $_glo_decl_ix ] ; do
    : $((_$((_glo_decls + start + 1)) -= 1))
    : $((start += 3))
  done
  endlet $1 start
}

: $((reindent = end = start = 0))
_replay_glo_decls() { let start $2; let end $3; let reindent $4
  while [ $start -lt $end ] ; do
    if [ $((_$((_glo_decls + start + 1)))) = 0 ] ; then
      _append_glo_decl __ $((_$((_glo_decls + start + 2))))
      if [ $((!reindent)) != 0 ] ; then
        : $((_$((_glo_decls + _glo_decl_ix - 3)) = _$((_glo_decls + start))))
      fi
    fi
    : $((start += 3))
  done
  endlet $1 reindent end start
}

: $((__t1 = res = end = start = 0))
_replay_glo_decls_inline() { let start $2; let end $3
  let res; let __t1
  res=0
  while [ $start -lt $end ] ; do
    if [ $((_$((_glo_decls + start + 1)))) = 0 ] ; then
      defstr __str_135 "; "
      _wrap_str __t1 $__str_135
      _concatenate_strings_with res $res $((_$((_glo_decls + start + 2)))) $__t1
    fi
    : $((start += 3))
  done
  if [ $res != 0 ] ; then
    defstr __str_136 "; "
    _wrap_str __t1 $__str_136
    _string_concat res $res $__t1
  fi
  : $(($1 = res))
  endlet $1 __t1 res end start
}

: $((level = i = 0))
_print_glo_decls() {
  let i; let level
  i=0
  while [ $i -lt $_glo_decl_ix ] ; do
    if [ $((_$((_glo_decls + i + 1)))) = 1 ] ; then
      if [ $((_$((_glo_decls + i + 2)))) != 0 ] ; then
        level=$((_$((_glo_decls + i))))
        while [ $level -gt 0 ] ; do
          printf \\$(((__SPACE__)/64))$(((__SPACE__)/8%8))$(((__SPACE__)%8))
          printf \\$(((__SPACE__)/64))$(((__SPACE__)/8%8))$(((__SPACE__)%8))
          : $((level -= 1))
        done
        _print_text __ $((_$((_glo_decls + i + 2))))
        printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
      fi
    fi
    : $((i += 3))
  done
  endlet $1 level i
}

: $((__t1 = var = env = ident_tok = 0))
_find_var_in_local_env() { let ident_tok $2
  let env; let var; let __t1
  env=$_local_env
  while [ $env != 0 ] ; do
    _get_child var $env 0
    if _get_child __t1 $var 0; [ $__t1 = $ident_tok ] ; then
      : $(($1 = var))
      endlet $1 __t1 var env ident_tok
      return
    fi
    _get_child env $env 1
  done
  : $(($1 = -1))
  endlet $1 __t1 var env ident_tok
}

: $((__t3 = __t2 = __t1 = op = prefixed_with_dollar = ident = 0))
_format_special_var() { let ident $2; let prefixed_with_dollar $3
  let op; let __t1; let __t2; let __t3
  _get_op op $ident
  if [ $op = $_IDENTIFIER_INTERNAL ] ; then
    defstr __str_137 "__t"
    _wrap_str __t1 $__str_137
    _get_val __t2 $ident
    _string_concat $1 $__t1 $__t2
  elif [ $op = $_IDENTIFIER_STRING ] ; then
    defstr __str_138 "__str_"
    _wrap_str __t1 $__str_138
    _get_val __t2 $ident
    _string_concat $1 $__t1 $__t2
  elif [ $op = $_IDENTIFIER_DOLLAR ] ; then
    if [ $prefixed_with_dollar != 0 ] ; then
      if _get_val __t1 $ident; [ $__t1 -le 9 ] ; then
        _get_val __t1 $ident
        _wrap_int $1 $__t1
      else
        _get_val __t2 $ident
        _wrap_int __t1 $__t2
        _string_concat3 $1 $((-(__LBRACE__))) $__t1 $((-(__RBRACE__)))
      fi
    else
      if _get_val __t1 $ident; [ $__t1 -le 9 ] ; then
        _get_val __t2 $ident
        _wrap_int __t1 $__t2
        _string_concat $1 $((-(__DOLLAR__))) $__t1
      else
        defstr __str_139 "\${"
        _wrap_str __t1 $__str_139
        _get_val __t3 $ident
        _wrap_int __t2 $__t3
        _string_concat3 $1 $__t1 $__t2 $((-(__RBRACE__)))
      fi
    fi
  elif [ $op = $_IDENTIFIER_EMPTY ] ; then
    defstr __str_140 "__"
    _wrap_str $1 $__str_140
  else
    printf "op=%d " $op
    printf \\$((op/64))$((op/8%8))$((op%8))
    defstr __str_141 "format_special_var: unknown identifier type"
    _fatal_error __ $__str_141
    : $(($1 = 0))
  fi
  endlet $1 __t3 __t2 __t1 op prefixed_with_dollar ident
}

: $((__t4 = __t3 = __t2 = __t1 = member_name_ident = 0))
_struct_member_var() { let member_name_ident $2
  let __t1; let __t2; let __t3; let __t4
  defstr __str_142 "__"
  _wrap_str __t1 $__str_142
  _get_val __t4 $member_name_ident
  _get_val __t3 $__t4
  _wrap_str_pool __t2 $__t3
  _string_concat $1 $__t1 $__t2
  endlet $1 __t4 __t3 __t2 __t1 member_name_ident
}

: $((__t4 = __t3 = __t2 = __t1 = struct_name_ident = 0))
_struct_sizeof_var() { let struct_name_ident $2
  let __t1; let __t2; let __t3; let __t4
  defstr __str_143 "__sizeof__"
  _wrap_str __t1 $__str_143
  _get_val __t4 $struct_name_ident
  _get_val __t3 $__t4
  _wrap_str_pool __t2 $__t3
  _string_concat $1 $__t1 $__t2
  endlet $1 __t4 __t3 __t2 __t1 struct_name_ident
}

: $((__t2 = __t1 = ident_tok = 0))
_global_var() { let ident_tok $2
  let __t1; let __t2
  _get_val __t2 $ident_tok
  _wrap_str_pool __t1 $__t2
  _string_concat $1 $((-(__UNDERSCORE__))) $__t1
  endlet $1 __t2 __t1 ident_tok
}

: $((__t2 = __t1 = res = var = prefixed_with_dollar = ident = 0))
_env_var_with_prefix() { let ident $2; let prefixed_with_dollar $3
  let var; let res; let __t1; let __t2
  if _get_op __t1 $ident; [ $__t1 = $_IDENTIFIER ] ; then
    _get_val __t1 $ident
    _find_var_in_local_env var $__t1
    if [ $var != -1 ] ; then
      if { _get_child __t1 $var 2; [ $__t1 = $_KIND_PARAM ]; } && { _get_child __t2 $var 3; [ $__t2 != 0 ]; } ; then
        _get_child __t1 $var 1
        _wrap_int res $__t1
        if [ $((!prefixed_with_dollar)) != 0 ] ; then
          _string_concat res $((-(__DOLLAR__))) $res
        fi
      else
        if _get_val __t1 $ident; [ $__t1 = $_ARGV_ID ] ; then
          defstr __str_144 "argv_"
          _wrap_str res $__str_144
        else
          _get_val __t2 $ident
          _get_val __t1 $__t2
          _wrap_str_pool res $__t1
        fi
      fi
    else
      _get_val __t1 $ident
      _global_var res $__t1
    fi
  else
    _format_special_var res $ident $prefixed_with_dollar
  fi
  : $(($1 = res))
  endlet $1 __t2 __t1 res var prefixed_with_dollar ident
}

: $((ident = 0))
_env_var() { let ident $2
  _env_var_with_prefix $1 $ident 0
  endlet $1 ident
}

: $((__t2 = __t1 = ident_tok = 0))
_function_name() { let ident_tok $2
  let __t1; let __t2
  _get_val __t2 $ident_tok
  _wrap_str_pool __t1 $__t2
  _string_concat $1 $((-(__UNDERSCORE__))) $__t1
  endlet $1 __t2 __t1 ident_tok
}

: $((__t1 = 0))
_fresh_ident() {
  let __t1
  : $((_gensym_ix += 1))
  if [ $_gensym_ix -gt $_fun_gensym_ix ] ; then
    _fun_gensym_ix=$_gensym_ix
  fi
  if [ $_gensym_ix -gt $_max_gensym_ix ] ; then
    _max_gensym_ix=$_gensym_ix
  fi
  _wrap_int __t1 $_gensym_ix
  _new_ast0 $1 $_IDENTIFIER_INTERNAL $__t1
  endlet $1 __t1
}

: $((__t1 = 0))
_fresh_string_ident() {
  let __t1
  : $((_string_counter += 1))
  _wrap_int __t1 $((_string_counter - 1))
  _new_ast0 $1 $_IDENTIFIER_STRING $__t1
  endlet $1 __t1
}

: $((__t1 = var = kind = position = ident_tok = 0))
_add_var_to_local_env() { let ident_tok $2; let position $3; let kind $4
  let var; let __t1
  if _find_var_in_local_env __t1 $ident_tok; [ $__t1 != -1 ] ; then
    defstr __str_145 "add_var_to_local_env: variable already in local environment"
    _fatal_error __ $__str_145
  fi
  _new_ast4 var $_LOCAL_VAR $ident_tok $position $kind 0
  _new_ast2 _local_env $__COMMA__ $var $_local_env
  : $((_local_env_size += 1))
  endlet $1 __t1 var kind position ident_tok
}

: $((__t1 = variable = variables = decls = kind = position = lst = 0))
_add_vars_to_local_env() { let lst $2; let position $3; let kind $4
  let decls; let variables; let variable; let __t1
  while [ $lst != 0 ] ; do
    _get_child decls $lst 0
    _get_child variables $decls 0
    while [ $variables != 0 ] ; do
      _get_child variable $variables 0
      _get_child __t1 $variable 0
      _add_var_to_local_env __ $__t1 $position $kind
      _get_child variables $variables 1
      : $((position += 1))
    done
    _get_child lst $lst 1
  done
  endlet $1 __t1 variable variables decls kind position lst
}

: $((__t1 = decl = kind = position = lst = 0))
_add_fun_params_to_local_env() { let lst $2; let position $3; let kind $4
  let decl; let __t1
  while [ $lst != 0 ] ; do
    _get_child decl $lst 0
    _get_child __t1 $decl 0
    _add_var_to_local_env __ $__t1 $position $kind
    _get_child lst $lst 1
    : $((position += 1))
  done
  endlet $1 __t1 decl kind position lst
}

: $((__t1 = var = ident = 0))
_mark_variable_as_mutable() { let ident $2
  let var; let __t1
  if _get_op __t1 $ident; [ $__t1 = $_IDENTIFIER ] ; then
    _get_val __t1 $ident
    _find_var_in_local_env var $__t1
    if [ $var != -1 ] ; then
      _set_child __ $var 3 0
    fi
  fi
  endlet $1 __t1 var ident
}

: $((__t2 = __t1 = local_var = 0))
_variable_is_constant_param() { let local_var $2
  let __t1; let __t2
  if [ $local_var != -1 ] && { _get_child __t1 $local_var 2; [ $__t1 = $_KIND_PARAM ]; } && { _get_child __t2 $local_var 3; [ $__t2 != 0 ]; } ; then
    : $(($1 = 1))
    endlet $1 __t2 __t1 local_var
    return
  fi
  : $(($1 = 0))
  endlet $1 __t2 __t1 local_var
}

: $((__t3 = __t2 = __t1 = type = name = ident_tok = local = variable = 0))
_assert_var_decl_is_safe() { let variable $2; let local $3
  let ident_tok; let name; let type; let __t1; let __t2; let __t3
  _get_child ident_tok $variable 0
  _get_val __t1 $ident_tok
  name=$((_string_pool + __t1))
  _get_child type $variable 1
  if [ $((_$((name + 0)))) = $__UNDERSCORE__ ] || { [ $((_$((name + 0)))) != $__NUL__ ] && [ $((_$((name + 1)))) = $__UNDERSCORE__ ] && [ $((_$((name + 2)))) = $__NUL__ ]; } ; then
    _put_pstr __ $name
    printf " " 
    defstr __str_146 "variable name is invalid. It can't start or end with '_'."
    _fatal_error __ $__str_146
  fi
  if [ $local != 0 ] && { [ $ident_tok = $_ARGV__ID ] || [ $ident_tok = $_IFS_ID ]; } ; then
    _put_pstr __ $name
    printf " " 
    defstr __str_147 "variable name is invalid. It can't be 'IFS' or 'argv_'."
    _fatal_error __ $__str_147
  fi
  if [ $local != 0 ] && { { _get_op __t1 $type; [ $__t1 = $__LBRACK__ ]; } || { { _get_op __t2 $type; [ $__t2 = $_STRUCT_KW ]; } && { _get_val __t3 $type; [ $__t3 = 0 ]; }; }; } ; then
    _put_pstr __ $name
    printf " " 
    defstr __str_148 "array/struct value type is not supported for shell backend. Use a reference type instead."
    _fatal_error __ $__str_148
  fi
  endlet $1 __t3 __t2 __t1 type name ident_tok local variable
}

: $((__t2 = __t1 = variable = variables = decls = local = lst = 0))
_assert_vars_are_safe() { let lst $2; let local $3
  let decls; let variables; let variable; let __t1; let __t2
  while [ $lst != 0 ] ; do
    if _get_child __t2 $lst 0; _get_op __t1 $__t2; [ $__t1 = $_VAR_DECLS ] ; then
      _get_child decls $lst 0
      _get_child variables $decls 0
      while [ $variables != 0 ] ; do
        _get_child variable $variables 0
        _assert_var_decl_is_safe __ $variable $local
        _get_child variables $variables 1
      done
    else
      _get_child __t1 $lst 0
      _assert_var_decl_is_safe __ $__t1 $local
    fi
    _get_child lst $lst 1
  done
  endlet $1 __t2 __t1 variable variables decls local lst
}

: $((__t2 = __t1 = counter = env = 0))
_num_vars_to_save() {
  let env; let counter; let __t1; let __t2
  env=$_local_env
  counter=$_fun_gensym_ix
  while [ $env != 0 ] ; do
    if _get_child __t2 $env 0; _variable_is_constant_param __t1 $__t2; [ $((!__t1)) != 0 ] ; then
      : $((counter += 1))
    fi
    _get_child env $env 1
  done
  : $(($1 = counter))
  endlet $1 __t2 __t1 counter env
}

: $((__t5 = __t4 = __t3 = __t2 = __t1 = params_ix = res = local_var = ident = params = 0))
_let_params() { let params $2
  let ident; let local_var; let res; let params_ix; let __t1; let __t2; let __t3; let __t4; let __t5
  res=0
  params_ix=2
  if _num_vars_to_save __t1 ; [ $__t1 = 0 ] ; then
    : $(($1 = 0))
    endlet $1 __t5 __t4 __t3 __t2 __t1 params_ix res local_var ident params
    return
  fi
  _runtime_use_local_vars=1
  while [ $params != 0 ] ; do
    _get_child __t2 $params 0
    _get_child __t1 $__t2 0
    _find_var_in_local_env local_var $__t1
    if _variable_is_constant_param __t1 $local_var; [ $((!__t1)) != 0 ] ; then
      _get_child __t2 $params 0
      _get_child __t1 $__t2 0
      _new_ast0 ident $_IDENTIFIER $__t1
      defstr __str_149 "let "
      _wrap_str __t2 $__str_149
      _env_var_with_prefix __t3 $ident 0
      _new_ast0 __t5 $_IDENTIFIER_DOLLAR $params_ix
      _format_special_var __t4 $__t5 0
      _string_concat4 __t1 $__t2 $__t3 $((-(__SPACE__))) $__t4
      defstr __str_150 "; "
      _wrap_str __t2 $__str_150
      _concatenate_strings_with res $res $__t1 $__t2
    fi
    _get_child params $params 1
    : $((params_ix += 1))
  done
  : $(($1 = res))
  endlet $1 __t5 __t4 __t3 __t2 __t1 params_ix res local_var ident params
}

: $((__t3 = __t2 = __t1 = counter = res = ident = local_var = env = params_count = 0))
_save_local_vars() { let params_count $2
  let env; let local_var; let ident; let res; let counter; let __t1; let __t2; let __t3
  env=$_local_env
  res=0
  counter=$_fun_gensym_ix
  if _num_vars_to_save __t1 ; [ $__t1 = 0 ] ; then
    : $(($1 = 0))
    endlet $1 __t3 __t2 __t1 counter res ident local_var env params_count
    return
  fi
  _runtime_use_local_vars=1
  while [ $counter -gt 0 ] ; do
    _wrap_int __t1 $counter
    _new_ast0 ident $_IDENTIFIER_INTERNAL $__t1
    defstr __str_151 "let "
    _wrap_str __t2 $__str_151
    _format_special_var __t3 $ident 1
    _string_concat __t1 $__t2 $__t3
    defstr __str_152 "; "
    _wrap_str __t2 $__str_152
    _concatenate_strings_with res $__t1 $res $__t2
    : $((counter -= 1))
  done
  while [ $env != 0 ] ; do
    _get_child local_var $env 0
    if [ $local_var != -1 ] && { _get_child __t1 $local_var 2; [ $__t1 != $_KIND_PARAM ]; } ; then
      _get_child __t1 $local_var 0
      _new_ast0 ident $_IDENTIFIER $__t1
      defstr __str_153 "let "
      _wrap_str __t2 $__str_153
      _env_var_with_prefix __t3 $ident 1
      _string_concat __t1 $__t2 $__t3
      defstr __str_154 "; "
      _wrap_str __t2 $__str_154
      _concatenate_strings_with res $__t1 $res $__t2
    fi
    _get_child env $env 1
  done
  : $(($1 = res))
  endlet $1 __t3 __t2 __t1 counter res ident local_var env params_count
}

: $((__t1 = counter = res = ident = local_var = env = params_count = 0))
_restore_local_vars() { let params_count $2
  let env; let local_var; let ident; let res; let counter; let __t1
  env=$_local_env
  res=0
  counter=$_fun_gensym_ix
  if _num_vars_to_save __t1 ; [ $__t1 = 0 ] ; then
    : $(($1 = 0))
    endlet $1 __t1 counter res ident local_var env params_count
    return
  fi
  _runtime_use_local_vars=1
  while [ $counter -gt 0 ] ; do
    _wrap_int __t1 $counter
    _new_ast0 ident $_IDENTIFIER_INTERNAL $__t1
    _format_special_var __t1 $ident 0
    _concatenate_strings_with res $res $__t1 $((-(__SPACE__)))
    : $((counter -= 1))
  done
  while [ $env != 0 ] ; do
    _get_child local_var $env 0
    if _variable_is_constant_param __t1 $local_var; [ $((!__t1)) != 0 ] ; then
      _get_child __t1 $local_var 0
      _new_ast0 ident $_IDENTIFIER $__t1
      _env_var __t1 $ident
      _concatenate_strings_with res $res $__t1 $((-(__SPACE__)))
    fi
    _get_child env $env 1
  done
  defstr __str_155 "endlet \$1 "
  _wrap_str __t1 $__str_155
  _string_concat $1 $__t1 $res
  endlet $1 __t1 counter res ident local_var env params_count
}

: $((op = 0))
_op_to_str() { let op $2
  if [ $op -lt 256 ] ; then
    _string_concat3 $1 $((-(__SPACE__))) $((-(op))) $((-(__SPACE__)))
  elif [ $op = $_AMP_AMP ] ; then
    defstr __str_156 " && "
    _wrap_str $1 $__str_156
  elif [ $op = $_AMP_EQ ] ; then
    defstr __str_157 " &= "
    _wrap_str $1 $__str_157
  elif [ $op = $_BAR_BAR ] ; then
    defstr __str_158 " || "
    _wrap_str $1 $__str_158
  elif [ $op = $_BAR_EQ ] ; then
    defstr __str_159 " |= "
    _wrap_str $1 $__str_159
  elif [ $op = $_CARET_EQ ] ; then
    defstr __str_160 " ^= "
    _wrap_str $1 $__str_160
  elif [ $op = $_EQ_EQ ] ; then
    defstr __str_161 " == "
    _wrap_str $1 $__str_161
  elif [ $op = $_GT_EQ ] ; then
    defstr __str_162 " >= "
    _wrap_str $1 $__str_162
  elif [ $op = $_LSHIFT_EQ ] ; then
    defstr __str_163 " <<= "
    _wrap_str $1 $__str_163
  elif [ $op = $_LT_EQ ] ; then
    defstr __str_164 " <= "
    _wrap_str $1 $__str_164
  elif [ $op = $_LSHIFT ] ; then
    defstr __str_165 " << "
    _wrap_str $1 $__str_165
  elif [ $op = $_MINUS_EQ ] ; then
    defstr __str_166 " -= "
    _wrap_str $1 $__str_166
  elif [ $op = $_EXCL_EQ ] ; then
    defstr __str_167 " != "
    _wrap_str $1 $__str_167
  elif [ $op = $_PERCENT_EQ ] ; then
    defstr __str_168 " %= "
    _wrap_str $1 $__str_168
  elif [ $op = $_PLUS_EQ ] ; then
    defstr __str_169 " += "
    _wrap_str $1 $__str_169
  elif [ $op = $_RSHIFT_EQ ] ; then
    defstr __str_170 " >>= "
    _wrap_str $1 $__str_170
  elif [ $op = $_RSHIFT ] ; then
    defstr __str_171 " >> "
    _wrap_str $1 $__str_171
  elif [ $op = $_SLASH_EQ ] ; then
    defstr __str_172 " /= "
    _wrap_str $1 $__str_172
  elif [ $op = $_STAR_EQ ] ; then
    defstr __str_173 " *= "
    _wrap_str $1 $__str_173
  else
    printf "op=%d " $op
    printf \\$((op/64))$((op/8%8))$((op%8))
    printf "\n" 
    defstr __str_174 "op_to_str: unexpected operator"
    _fatal_error __ $__str_174
    : $(($1 = 0))
  fi
  endlet $1 op
}

: $((op = 0))
_test_op_to_str() { let op $2
  if [ $op = $_EQ_EQ ] ; then
    defstr __str_175 " = "
    _wrap_str $1 $__str_175
  elif [ $op = $_EXCL_EQ ] ; then
    defstr __str_176 " != "
    _wrap_str $1 $__str_176
  elif [ $op = $__LT__ ] ; then
    defstr __str_177 " -lt "
    _wrap_str $1 $__str_177
  elif [ $op = $__GT__ ] ; then
    defstr __str_178 " -gt "
    _wrap_str $1 $__str_178
  elif [ $op = $_LT_EQ ] ; then
    defstr __str_179 " -le "
    _wrap_str $1 $__str_179
  elif [ $op = $_GT_EQ ] ; then
    defstr __str_180 " -ge "
    _wrap_str $1 $__str_180
  else
    printf "op=%d " $op
    printf \\$((op/64))$((op/8%8))$((op%8))
    printf "\n" 
    defstr __str_181 "test_op_to_str: unexpected operator"
    _fatal_error __ $__str_181
    : $(($1 = 0))
  fi
  endlet $1 op
}

: $((c = 0))
_character_ident() { let c $2
  : $((_$((_characters_useds + c / 16)) |= (1 << (c % 16))))
  _any_character_used=1
  if { [ $__A__ -le $c ] && [ $c -le $__Z__ ]; } || { [ $__a__ -le $c ] && [ $c -le $__z__ ]; } || { [ $__0__ -le $c ] && [ $c -le $__9__ ]; } ; then
    _string_concat5 $1 $((-(__UNDERSCORE__))) $((-(__UNDERSCORE__))) $((-(c))) $((-(__UNDERSCORE__))) $((-(__UNDERSCORE__)))
  else
    if [ $c = $__NUL__ ] ; then
      defstr __str_182 "__NUL__"
      _wrap_str $1 $__str_182
    elif [ $c = $__NEWLINE__ ] ; then
      defstr __str_183 "__NEWLINE__"
      _wrap_str $1 $__str_183
    elif [ $c = $__SPACE__ ] ; then
      defstr __str_184 "__SPACE__"
      _wrap_str $1 $__str_184
    elif [ $c = $__EXCL__ ] ; then
      defstr __str_185 "__EXCL__"
      _wrap_str $1 $__str_185
    elif [ $c = $__DQUOTE__ ] ; then
      defstr __str_186 "__DQUOTE__"
      _wrap_str $1 $__str_186
    elif [ $c = $__SHARP__ ] ; then
      defstr __str_187 "__SHARP__"
      _wrap_str $1 $__str_187
    elif [ $c = $__DOLLAR__ ] ; then
      defstr __str_188 "__DOLLAR__"
      _wrap_str $1 $__str_188
    elif [ $c = $__PERCENT__ ] ; then
      defstr __str_189 "__PERCENT__"
      _wrap_str $1 $__str_189
    elif [ $c = $__AMP__ ] ; then
      defstr __str_190 "__AMP__"
      _wrap_str $1 $__str_190
    elif [ $c = $__QUOTE__ ] ; then
      defstr __str_191 "__QUOTE__"
      _wrap_str $1 $__str_191
    elif [ $c = $__LPAREN__ ] ; then
      defstr __str_192 "__LPAREN__"
      _wrap_str $1 $__str_192
    elif [ $c = $__RPAREN__ ] ; then
      defstr __str_193 "__RPAREN__"
      _wrap_str $1 $__str_193
    elif [ $c = $__STAR__ ] ; then
      defstr __str_194 "__STAR__"
      _wrap_str $1 $__str_194
    elif [ $c = $__PLUS__ ] ; then
      defstr __str_195 "__PLUS__"
      _wrap_str $1 $__str_195
    elif [ $c = $__COMMA__ ] ; then
      defstr __str_196 "__COMMA__"
      _wrap_str $1 $__str_196
    elif [ $c = $__MINUS__ ] ; then
      defstr __str_197 "__MINUS__"
      _wrap_str $1 $__str_197
    elif [ $c = $__PERIOD__ ] ; then
      defstr __str_198 "__PERIOD__"
      _wrap_str $1 $__str_198
    elif [ $c = $__SLASH__ ] ; then
      defstr __str_199 "__SLASH__"
      _wrap_str $1 $__str_199
    elif [ $c = $__COLON__ ] ; then
      defstr __str_200 "__COLON__"
      _wrap_str $1 $__str_200
    elif [ $c = $__SEMICOLON__ ] ; then
      defstr __str_201 "__SEMICOLON__"
      _wrap_str $1 $__str_201
    elif [ $c = $__LT__ ] ; then
      defstr __str_202 "__LT__"
      _wrap_str $1 $__str_202
    elif [ $c = $__EQ__ ] ; then
      defstr __str_203 "__EQ__"
      _wrap_str $1 $__str_203
    elif [ $c = $__GT__ ] ; then
      defstr __str_204 "__GT__"
      _wrap_str $1 $__str_204
    elif [ $c = $__QUESTION__ ] ; then
      defstr __str_205 "__QUESTION__"
      _wrap_str $1 $__str_205
    elif [ $c = $__AT__ ] ; then
      defstr __str_206 "__AT__"
      _wrap_str $1 $__str_206
    elif [ $c = $__CARET__ ] ; then
      defstr __str_207 "__CARET__"
      _wrap_str $1 $__str_207
    elif [ $c = $__LBRACK__ ] ; then
      defstr __str_208 "__LBRACK__"
      _wrap_str $1 $__str_208
    elif [ $c = $__BACKSLASH__ ] ; then
      defstr __str_209 "__BACKSLASH__"
      _wrap_str $1 $__str_209
    elif [ $c = $__RBRACK__ ] ; then
      defstr __str_210 "__RBRACK__"
      _wrap_str $1 $__str_210
    elif [ $c = $__UNDERSCORE__ ] ; then
      defstr __str_211 "__UNDERSCORE__"
      _wrap_str $1 $__str_211
    elif [ $c = $__BACKTICK__ ] ; then
      defstr __str_212 "__BACKTICK__"
      _wrap_str $1 $__str_212
    elif [ $c = $__LBRACE__ ] ; then
      defstr __str_213 "__LBRACE__"
      _wrap_str $1 $__str_213
    elif [ $c = $__BAR__ ] ; then
      defstr __str_214 "__BAR__"
      _wrap_str $1 $__str_214
    elif [ $c = $__RBRACE__ ] ; then
      defstr __str_215 "__RBRACE__"
      _wrap_str $1 $__str_215
    elif [ $c = $__TILDE__ ] ; then
      defstr __str_216 "__TILDE__"
      _wrap_str $1 $__str_216
    elif [ $c = $__ALARM__ ] ; then
      defstr __str_217 "__ALARM__"
      _wrap_str $1 $__str_217
    elif [ $c = $__BACKSPACE__ ] ; then
      defstr __str_218 "__BACKSPACE__"
      _wrap_str $1 $__str_218
    elif [ $c = $__PAGE__ ] ; then
      defstr __str_219 "__PAGE__"
      _wrap_str $1 $__str_219
    elif [ $c = $__RET__ ] ; then
      defstr __str_220 "__RET__"
      _wrap_str $1 $__str_220
    elif [ $c = $__TAB__ ] ; then
      defstr __str_221 "__TAB__"
      _wrap_str $1 $__str_221
    elif [ $c = $__VTAB__ ] ; then
      defstr __str_222 "__VTAB__"
      _wrap_str $1 $__str_222
    else
      defstr __str_223 "Unknown character"
      _fatal_error __ $__str_223
      : $(($1 = 0))
    fi
  fi
  endlet $1 c
}

_replaced_fun_calls=0
_replaced_fun_calls_tail=0
_conditional_fun_calls=0
_conditional_fun_calls_tail=0
_literals_inits=0
_executes_conditionally=0
_contains_side_effects=0
: $((__t3 = __t2 = __t1 = new_tail = right_conditional_fun_calls = left_conditional_fun_calls = previous_conditional_fun_calls = sub2 = sub1 = start_gensym_ix = nb_children = op = executes_conditionally = node = 0))
_handle_side_effects_go() { let node $2; let executes_conditionally $3
  let op; let nb_children; let start_gensym_ix; let sub1; let sub2; let previous_conditional_fun_calls; let left_conditional_fun_calls; let right_conditional_fun_calls; let new_tail; let __t1; let __t2; let __t3
  _get_op op $node
  _get_nb_children nb_children $node
  if [ $nb_children = 0 ] ; then
    if [ $op = $_IDENTIFIER ] || [ $op = $_IDENTIFIER_INTERNAL ] || [ $op = $_IDENTIFIER_STRING ] || [ $op = $_IDENTIFIER_DOLLAR ] || [ $op = $_INTEGER ] || [ $op = $_CHARACTER ] ; then
      : $(($1 = node))
    elif [ $op = $_STRING ] ; then
      _fresh_string_ident sub1 
      _get_val __t2 $node
      _new_ast2 __t1 $__COMMA__ $sub1 $__t2
      _new_ast2 _literals_inits $__COMMA__ $__t1 $_literals_inits
      : $(($1 = sub1))
    else
      printf "handle_side_effects_go: op=%d " $op
      printf \\$((op/64))$((op/8%8))$((op%8))
      defstr __str_224 "unexpected operator"
      _fatal_error __ $__str_224
      : $(($1 = 0))
    fi
  elif [ $nb_children = 1 ] ; then
    if [ $op = $__AMP__ ] || [ $op = $__STAR__ ] || [ $op = $__PLUS__ ] || [ $op = $__MINUS__ ] || [ $op = $__TILDE__ ] || [ $op = $__EXCL__ ] ; then
      _get_child __t2 $node 0
      _handle_side_effects_go __t1 $__t2 $executes_conditionally
      _new_ast1 $1 $op $__t1
    elif [ $op = $_PLUS_PLUS_PRE ] || [ $op = $_MINUS_MINUS_PRE ] || [ $op = $_PLUS_PLUS_POST ] || [ $op = $_MINUS_MINUS_POST ] ; then
      _contains_side_effects=1
      _get_child __t2 $node 0
      _handle_side_effects_go __t1 $__t2 $executes_conditionally
      _new_ast1 $1 $op $__t1
    elif [ $op = $_SIZEOF_KW ] ; then
      : $(($1 = node))
    else
      printf "1: op=%d " $op
      printf \\$((op/64))$((op/8%8))$((op%8))
      defstr __str_225 "unexpected operator"
      _fatal_error __ $__str_225
      : $(($1 = 0))
    fi
  elif [ $nb_children = 2 ] ; then
    if [ $op = $__LPAREN__ ] ; then
      _fresh_ident sub1 
      start_gensym_ix=$_gensym_ix
      _get_child sub2 $node 1
      if [ $sub2 != 0 ] ; then
        if _get_op __t1 $sub2; [ $__t1 = $__COMMA__ ] ; then
          while _get_op __t1 $sub2; [ $__t1 = $__COMMA__ ] ; do
            _get_child __t2 $sub2 0
            _handle_side_effects_go __t1 $__t2 $executes_conditionally
            _set_child __ $sub2 0 $__t1
            _get_child sub2 $sub2 1
          done
        else
          _handle_side_effects_go sub2 $sub2 $executes_conditionally
          _set_child __ $node 1 $sub2
        fi
      fi
      _gensym_ix=$start_gensym_ix
      _new_ast2 new_tail $__COMMA__ $sub1 $node
      _new_ast2 new_tail $__COMMA__ $new_tail 0
      if [ $executes_conditionally != 0 ] ; then
        if [ $_conditional_fun_calls = 0 ] ; then
          _conditional_fun_calls=$new_tail
        else
          _set_child __ $_conditional_fun_calls_tail 1 $new_tail
        fi
        _conditional_fun_calls_tail=$new_tail
      else
        if [ $_replaced_fun_calls = 0 ] ; then
          _replaced_fun_calls=$new_tail
        else
          _set_child __ $_replaced_fun_calls_tail 1 $new_tail
        fi
        _replaced_fun_calls_tail=$new_tail
      fi
      : $(($1 = sub1))
    elif [ $op = $__AMP__ ] || [ $op = $__BAR__ ] || [ $op = $__LT__ ] || [ $op = $__GT__ ] || [ $op = $__PLUS__ ] || [ $op = $__MINUS__ ] || [ $op = $__STAR__ ] || [ $op = $__SLASH__ ] || [ $op = $__PERCENT__ ] || [ $op = $__CARET__ ] || [ $op = $__COMMA__ ] || [ $op = $_EQ_EQ ] || [ $op = $_EXCL_EQ ] || [ $op = $_LT_EQ ] || [ $op = $_GT_EQ ] || [ $op = $_LSHIFT ] || [ $op = $_RSHIFT ] || [ $op = $__EQ__ ] || [ $op = $__LBRACK__ ] || [ $op = $__PERIOD__ ] || [ $op = $_ARROW ] ; then
      _get_child __t1 $node 0
      _handle_side_effects_go sub1 $__t1 $executes_conditionally
      _get_child __t1 $node 1
      _handle_side_effects_go sub2 $__t1 $executes_conditionally
      _new_ast2 $1 $op $sub1 $sub2
    elif [ $op = $_AMP_EQ ] || [ $op = $_BAR_EQ ] || [ $op = $_CARET_EQ ] || [ $op = $_LSHIFT_EQ ] || [ $op = $_MINUS_EQ ] || [ $op = $_PERCENT_EQ ] || [ $op = $_PLUS_EQ ] || [ $op = $_RSHIFT_EQ ] || [ $op = $_SLASH_EQ ] || [ $op = $_STAR_EQ ] ; then
      _contains_side_effects=1
      _get_child __t1 $node 0
      _handle_side_effects_go sub1 $__t1 $executes_conditionally
      _get_child __t1 $node 1
      _handle_side_effects_go sub2 $__t1 $executes_conditionally
      _new_ast2 $1 $op $sub1 $sub2
    elif [ $op = $_AMP_AMP ] || [ $op = $_BAR_BAR ] ; then
      previous_conditional_fun_calls=$_conditional_fun_calls
      _conditional_fun_calls=0
      _get_child __t1 $node 0
      _handle_side_effects_go sub1 $__t1 1
      left_conditional_fun_calls=$_conditional_fun_calls
      _conditional_fun_calls=0
      _get_child __t1 $node 1
      _handle_side_effects_go sub2 $__t1 1
      right_conditional_fun_calls=$_conditional_fun_calls
      _conditional_fun_calls=$previous_conditional_fun_calls
      _new_ast4 $1 $op $sub1 $sub2 $left_conditional_fun_calls $right_conditional_fun_calls
    elif [ $op = $_CAST ] ; then
      _get_child __t1 $node 0
      _get_child __t3 $node 1
      _handle_side_effects_go __t2 $__t3 $executes_conditionally
      _new_ast2 $1 $_CAST $__t1 $__t2
    else
      printf "2: op=%d " $op
      printf \\$((op/64))$((op/8%8))$((op%8))
      defstr __str_226 "unexpected operator"
      _fatal_error __ $__str_226
      : $(($1 = 0))
    fi
  elif [ $nb_children = 3 ] ; then
    if [ $op = $__QUESTION__ ] ; then
      previous_conditional_fun_calls=$_conditional_fun_calls
      _conditional_fun_calls=0
      _get_child __t1 $node 1
      _handle_side_effects_go sub1 $__t1 1
      left_conditional_fun_calls=$_conditional_fun_calls
      _conditional_fun_calls=0
      _get_child __t1 $node 2
      _handle_side_effects_go sub2 $__t1 1
      right_conditional_fun_calls=$_conditional_fun_calls
      if [ $left_conditional_fun_calls != 0 ] || [ $right_conditional_fun_calls != 0 ] ; then
        defstr __str_227 "Conditional function calls in ternary operator not allowed"
        _fatal_error __ $__str_227
      fi
      _get_child __t2 $node 0
      _handle_side_effects_go __t1 $__t2 $executes_conditionally
      _new_ast3 $1 $__QUESTION__ $__t1 $sub1 $sub2
    else
      printf "3: op=%d " $op
      printf \\$((op/64))$((op/8%8))$((op%8))
      printf "\n" 
      defstr __str_228 "unexpected operator"
      _fatal_error __ $__str_228
      : $(($1 = 0))
    fi
  elif [ $nb_children = 4 ] ; then
    printf "4: op=%d " $op
    printf \\$((op/64))$((op/8%8))$((op%8))
    printf "\n" 
    defstr __str_229 "unexpected operator"
    _fatal_error __ $__str_229
    : $(($1 = 0))
  else
    printf "5: op=%d " $op
    printf \\$((op/64))$((op/8%8))$((op%8))
    _get_nb_children __t1 $node
    printf " with %d children\n" $__t1
    defstr __str_230 "unexpected operator"
    _fatal_error __ $__str_230
    : $(($1 = 0))
  fi
  endlet $1 __t3 __t2 __t1 new_tail right_conditional_fun_calls left_conditional_fun_calls previous_conditional_fun_calls sub2 sub1 start_gensym_ix nb_children op executes_conditionally node
}

: $((node = 0))
_handle_side_effects() { let node $2
  _replaced_fun_calls=0
  _conditional_fun_calls=0
  _literals_inits=0
  _contains_side_effects=0
  _handle_side_effects_go $1 $node 0
  endlet $1 node
}

: $((__t6 = __t5 = __t4 = __t3 = __t2 = __t1 = string_pool_str = ident = 0))
_comp_defstr() { let ident $2; let string_pool_str $3
  let __t1; let __t2; let __t3; let __t4; let __t5; let __t6
  if [ $_top_level_stmt != 0 ] ; then
    _runtime_defstr __ 
  else
    _runtime_use_defstr=1
  fi
  defstr __str_232 " \""
  defstr __str_231 "defstr "
  _wrap_str __t2 $__str_231
  _format_special_var __t3 $ident 0
  _wrap_str __t4 $__str_232
  _wrap_str_pool __t6 $string_pool_str
  _escape_text __t5 $__t6 0
  _string_concat5 __t1 $__t2 $__t3 $__t4 $__t5 $((-(__DQUOTE__)))
  _append_glo_decl __ $__t1
  endlet $1 __t6 __t5 __t4 __t3 __t2 __t1 string_pool_str ident
}

_RVALUE_CTX_BASE=0
_RVALUE_CTX_ARITH_EXPANSION=1
_RVALUE_CTX_TEST=2
_RVALUE_CTX_TEST_ELSEIF=3
: $((__t4 = __t3 = __t2 = __t1 = test_side_effects_code = code = test_side_effects = 0))
_with_prefixed_side_effects() { let test_side_effects $2; let code $3
  let test_side_effects_code; let __t1; let __t2; let __t3; let __t4
  test_side_effects_code=0
  while [ $test_side_effects != 0 ] ; do
    _get_child __t3 $test_side_effects 0
    _get_child __t2 $__t3 1
    _get_child __t4 $test_side_effects 0
    _get_child __t3 $__t4 0
    _comp_fun_call_code __t1 $__t2 $__t3
    defstr __str_233 "; "
    _wrap_str __t2 $__str_233
    _string_concat3 test_side_effects_code $test_side_effects_code $__t1 $__t2
    _get_child test_side_effects $test_side_effects 1
  done
  if [ $test_side_effects_code != 0 ] ; then
    defstr __str_234 "{ "
    _wrap_str __t1 $__str_234
    defstr __str_235 "; }"
    _wrap_str __t2 $__str_235
    _string_concat4 $1 $__t1 $test_side_effects_code $code $__t2
  else
    : $(($1 = code))
  fi
  endlet $1 __t4 __t3 __t2 __t1 test_side_effects_code code test_side_effects
}

: $((op = 0))
_is_associative_operator() { let op $2
  : $(($1 = (op == __PLUS__) | (op == __STAR__) | (op == __AMP__) | (op == __BAR__) | (op == __CARET__) | (op == _EQ_EQ) | (op == _AMP_AMP) | (op == _BAR_BAR)))
  endlet $1 op
}

: $((__t3 = __t2 = __t1 = inner_op = outer_op = code = test_side_effects = context = parens_otherwise = 0))
_wrap_if_needed() { let parens_otherwise $2; let context $3; let test_side_effects $4; let code $5; let outer_op $6; let inner_op $7
  let __t1; let __t2; let __t3
  if [ $context = $_RVALUE_CTX_ARITH_EXPANSION ] ; then
    if [ $parens_otherwise != 0 ] && [ $outer_op != 0 ] && [ $outer_op != $__EQ__ ] && { { _is_associative_operator __t1 $inner_op; [ $((!__t1)) != 0 ]; } || [ $inner_op != $outer_op ]; } ; then
      _string_concat3 $1 $((-(__LPAREN__))) $code $((-(__RPAREN__)))
    else
      : $(($1 = code))
    fi
  elif [ $context = $_RVALUE_CTX_TEST ] ; then
    defstr __str_237 ")) != 0 ]"
    defstr __str_236 "[ \$(("
    _wrap_str __t2 $__str_236
    _wrap_str __t3 $__str_237
    _string_concat3 __t1 $__t2 $code $__t3
    _with_prefixed_side_effects $1 $test_side_effects $__t1
  else
    defstr __str_238 "\$(("
    _wrap_str __t1 $__str_238
    defstr __str_239 "))"
    _wrap_str __t2 $__str_239
    _string_concat3 $1 $__t1 $code $__t2
  fi
  endlet $1 __t3 __t2 __t1 inner_op outer_op code test_side_effects context parens_otherwise
}

: $((__t3 = __t2 = __t1 = code = test_side_effects = context = 0))
_wrap_in_condition_if_needed() { let context $2; let test_side_effects $3; let code $4
  let __t1; let __t2; let __t3
  if [ $context = $_RVALUE_CTX_TEST ] ; then
    defstr __str_241 " != 0 ]"
    defstr __str_240 "[ "
    _wrap_str __t2 $__str_240
    _wrap_str __t3 $__str_241
    _string_concat3 __t1 $__t2 $code $__t3
    _with_prefixed_side_effects $1 $test_side_effects $__t1
  else
    : $(($1 = code))
  fi
  endlet $1 __t3 __t2 __t1 code test_side_effects context
}

: $((__t8 = __t7 = __t6 = __t5 = __t4 = __t3 = __t2 = __t1 = sub3 = sub2 = sub1 = nb_children = op = outer_op = test_side_effects = context = node = 0))
_comp_rvalue_go() { let node $2; let context $3; let test_side_effects $4; let outer_op $5
  let op; let nb_children; let sub1; let sub2; let sub3; let __t1; let __t2; let __t3; let __t4; let __t5; let __t6; let __t7; let __t8
  _get_op op $node
  _get_nb_children nb_children $node
  if [ $nb_children = 0 ] ; then
    if [ $op = $_INTEGER ] ; then
      _get_val __t2 $node
      _wrap_int __t1 $((-(__t2)))
      _wrap_in_condition_if_needed $1 $context $test_side_effects $__t1
    elif [ $op = $_CHARACTER ] ; then
      if [ $context = $_RVALUE_CTX_ARITH_EXPANSION ] ; then
        _get_val __t1 $node
        _character_ident $1 $__t1
      else
        _get_val __t3 $node
        _character_ident __t2 $__t3
        _string_concat __t1 $((-(__DOLLAR__))) $__t2
        _wrap_in_condition_if_needed $1 $context $test_side_effects $__t1
      fi
    elif [ $op = $_IDENTIFIER ] || [ $op = $_IDENTIFIER_INTERNAL ] || [ $op = $_IDENTIFIER_STRING ] || [ $op = $_IDENTIFIER_DOLLAR ] ; then
      if [ $context = $_RVALUE_CTX_ARITH_EXPANSION ] ; then
        _env_var_with_prefix $1 $node 0
      else
        _env_var_with_prefix __t2 $node 1
        _string_concat __t1 $((-(__DOLLAR__))) $__t2
        _wrap_in_condition_if_needed $1 $context $test_side_effects $__t1
      fi
    elif [ $op = $_STRING ] ; then
      defstr __str_242 "comp_rvalue_go: string should have been removed by handle_side_effects"
      _fatal_error __ $__str_242
      : $(($1 = 0))
    else
      printf "op=%d " $op
      printf \\$((op/64))$((op/8%8))$((op%8))
      defstr __str_243 "comp_rvalue_go: unknown rvalue with nb_children == 0"
      _fatal_error __ $__str_243
      : $(($1 = 0))
    fi
  elif [ $nb_children = 1 ] ; then
    if [ $op = $__STAR__ ] ; then
      _get_child __t1 $node 0
      _comp_rvalue_go sub1 $__t1 $_RVALUE_CTX_BASE 0 $op
      _string_concat __t1 $((-(__UNDERSCORE__))) $sub1
      _wrap_if_needed $1 0 $context $test_side_effects $__t1 $outer_op $op
    elif [ $op = $__PLUS__ ] ; then
      _get_child __t1 $node 0
      _comp_rvalue_go $1 $__t1 $context $test_side_effects $op
    elif [ $op = $__MINUS__ ] ; then
      if _get_child __t2 $node 0; _get_op __t1 $__t2; [ $__t1 = $_INTEGER ] ; then
        _get_child __t3 $node 0
        _get_val __t2 $__t3
        _wrap_int __t1 $__t2
        _wrap_in_condition_if_needed $1 $context $test_side_effects $__t1
      else
        _get_child __t1 $node 0
        _comp_rvalue_go sub1 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $op
        defstr __str_244 "-("
        _wrap_str __t2 $__str_244
        _string_concat3 __t1 $__t2 $sub1 $((-(__RPAREN__)))
        _wrap_if_needed $1 0 $context $test_side_effects $__t1 $outer_op $op
      fi
    elif [ $op = $__TILDE__ ] ; then
      _get_child __t1 $node 0
      _comp_rvalue_go sub1 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $op
      defstr __str_245 "~("
      _wrap_str __t2 $__str_245
      _string_concat3 __t1 $__t2 $sub1 $((-(__RPAREN__)))
      _wrap_if_needed $1 0 $context $test_side_effects $__t1 $outer_op $op
    elif [ $op = $__EXCL__ ] ; then
      _get_child __t1 $node 0
      _comp_rvalue_go sub1 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $op
      _string_concat __t1 $((-(__EXCL__))) $sub1
      _wrap_if_needed $1 1 $context $test_side_effects $__t1 $outer_op $op
    elif [ $op = $_MINUS_MINUS_PRE ] ; then
      _get_child __t1 $node 0
      _comp_lvalue sub1 $__t1
      defstr __str_246 " -= 1"
      _wrap_str __t2 $__str_246
      _string_concat __t1 $sub1 $__t2
      _wrap_if_needed $1 1 $context $test_side_effects $__t1 $outer_op $op
    elif [ $op = $_PLUS_PLUS_PRE ] ; then
      _get_child __t1 $node 0
      _comp_lvalue sub1 $__t1
      defstr __str_247 " += 1"
      _wrap_str __t2 $__str_247
      _string_concat __t1 $sub1 $__t2
      _wrap_if_needed $1 1 $context $test_side_effects $__t1 $outer_op $op
    elif [ $op = $_MINUS_MINUS_POST ] ; then
      _get_child __t1 $node 0
      _comp_lvalue sub1 $__t1
      defstr __str_250 " + 1"
      defstr __str_249 " -= 1)"
      defstr __str_248 "("
      _wrap_str __t2 $__str_248
      _wrap_str __t3 $__str_249
      _wrap_str __t4 $__str_250
      _string_concat4 __t1 $__t2 $sub1 $__t3 $__t4
      _wrap_if_needed $1 0 $context $test_side_effects $__t1 $outer_op $__PLUS__
    elif [ $op = $_PLUS_PLUS_POST ] ; then
      _get_child __t1 $node 0
      _comp_lvalue sub1 $__t1
      defstr __str_253 " - 1"
      defstr __str_252 " += 1)"
      defstr __str_251 "("
      _wrap_str __t2 $__str_251
      _wrap_str __t3 $__str_252
      _wrap_str __t4 $__str_253
      _string_concat4 __t1 $__t2 $sub1 $__t3 $__t4
      _wrap_if_needed $1 0 $context $test_side_effects $__t1 $outer_op $__MINUS__
    elif [ $op = $_SIZEOF_KW ] ; then
      if { _get_child __t2 $node 0; _get_op __t1 $__t2; [ $__t1 = $_INT_KW ]; } || { _get_child __t3 $node 0; _get_op __t2 $__t3; [ $__t2 = $_CHAR_KW ]; } || { _get_child __t4 $node 0; _get_op __t3 $__t4; [ $__t3 = $_VOID_KW ]; } || { _get_child __t5 $node 0; _get_op __t4 $__t5; [ $__t4 = $_ENUM_KW ]; } || { { { _get_child __t6 $node 0; _get_op __t5 $__t6; [ $__t5 = $_STRUCT_KW ]; } || { _get_child __t7 $node 0; _get_op __t6 $__t7; [ $__t6 = $_UNION_KW ]; }; } && { _get_child __t8 $node 0; _get_child __t7 $__t8 0; [ $__t7 -ge 1 ]; }; } ; then
        _wrap_int __t1 1
        _wrap_in_condition_if_needed $1 $context $test_side_effects $__t1
      elif _get_child __t2 $node 0; _get_op __t1 $__t2; [ $__t1 = $_STRUCT_KW ] ; then
        _get_child __t3 $node 0
        _get_child __t2 $__t3 1
        _struct_sizeof_var __t1 $__t2
        _wrap_if_needed $1 0 $context $test_side_effects $__t1 $outer_op $op
      else
        defstr __str_254 "comp_rvalue_go: sizeof is not supported for this type or expression"
        _fatal_error __ $__str_254
      fi
    elif [ $op = $__AMP__ ] ; then
      _get_child __t2 $node 0
      _comp_lvalue_address __t1 $__t2
      _wrap_if_needed $1 0 $context $test_side_effects $__t1 $outer_op $op
    else
      printf "1: op=%d " $op
      printf \\$((op/64))$((op/8%8))$((op%8))
      defstr __str_255 "comp_rvalue_go: unexpected operator"
      _fatal_error __ $__str_255
      : $(($1 = 0))
    fi
  elif [ $nb_children = 2 ] ; then
    if [ $op = $__PLUS__ ] || [ $op = $__MINUS__ ] || [ $op = $__STAR__ ] || [ $op = $__SLASH__ ] || [ $op = $__PERCENT__ ] || [ $op = $__AMP__ ] || [ $op = $__BAR__ ] || [ $op = $__CARET__ ] || [ $op = $_LSHIFT ] || [ $op = $_RSHIFT ] ; then
      _get_child __t1 $node 0
      _comp_rvalue_go sub1 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $op
      _get_child __t1 $node 1
      _comp_rvalue_go sub2 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $op
      _op_to_str __t2 $op
      _string_concat3 __t1 $sub1 $__t2 $sub2
      _wrap_if_needed $1 1 $context $test_side_effects $__t1 $outer_op $op
    elif [ $op = $__EQ__ ] || [ $op = $_AMP_EQ ] || [ $op = $_BAR_EQ ] || [ $op = $_CARET_EQ ] || [ $op = $_LSHIFT_EQ ] || [ $op = $_MINUS_EQ ] || [ $op = $_PERCENT_EQ ] || [ $op = $_PLUS_EQ ] || [ $op = $_RSHIFT_EQ ] || [ $op = $_SLASH_EQ ] || [ $op = $_STAR_EQ ] ; then
      _get_child __t1 $node 0
      _comp_lvalue sub1 $__t1
      _get_child __t1 $node 1
      _comp_rvalue_go sub2 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $op
      _op_to_str __t2 $op
      _string_concat3 __t1 $sub1 $__t2 $sub2
      _wrap_if_needed $1 1 $context $test_side_effects $__t1 $outer_op $op
    elif [ $op = $__LBRACK__ ] ; then
      _get_child __t1 $node 0
      _comp_rvalue_go sub1 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $__PLUS__
      _get_child __t1 $node 1
      _comp_rvalue_go sub2 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $__PLUS__
      defstr __str_258 "))"
      defstr __str_257 " + "
      defstr __str_256 "_\$(("
      _wrap_str __t2 $__str_256
      _wrap_str __t3 $__str_257
      _wrap_str __t4 $__str_258
      _string_concat5 __t1 $__t2 $sub1 $__t3 $sub2 $__t4
      _wrap_if_needed $1 0 $context $test_side_effects $__t1 $outer_op $op
    elif [ $op = $_ARROW ] ; then
      _get_child __t1 $node 0
      _comp_rvalue_go sub1 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $op
      _get_child __t1 $node 1
      _struct_member_var sub2 $__t1
      defstr __str_261 "))"
      defstr __str_260 " + "
      defstr __str_259 "_\$(("
      _wrap_str __t2 $__str_259
      _wrap_str __t3 $__str_260
      _wrap_str __t4 $__str_261
      _string_concat5 __t1 $__t2 $sub1 $__t3 $sub2 $__t4
      _wrap_if_needed $1 0 $context $test_side_effects $__t1 $outer_op $op
    elif [ $op = $_EQ_EQ ] || [ $op = $_EXCL_EQ ] || [ $op = $_LT_EQ ] || [ $op = $_GT_EQ ] || [ $op = $__LT__ ] || [ $op = $__GT__ ] ; then
      if [ $context = $_RVALUE_CTX_TEST ] ; then
        _get_child __t1 $node 0
        _comp_rvalue_go sub1 $__t1 $_RVALUE_CTX_BASE 0 $op
        _get_child __t1 $node 1
        _comp_rvalue_go sub2 $__t1 $_RVALUE_CTX_BASE 0 $op
        defstr __str_263 " ]"
        defstr __str_262 "[ "
        _wrap_str __t2 $__str_262
        _test_op_to_str __t3 $op
        _wrap_str __t4 $__str_263
        _string_concat5 __t1 $__t2 $sub1 $__t3 $sub2 $__t4
        _with_prefixed_side_effects $1 $test_side_effects $__t1
      else
        _get_child __t1 $node 0
        _comp_rvalue_go sub1 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $op
        _get_child __t1 $node 1
        _comp_rvalue_go sub2 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $op
        _op_to_str __t2 $op
        _string_concat3 __t1 $sub1 $__t2 $sub2
        _wrap_if_needed $1 1 $context $test_side_effects $__t1 $outer_op $op
      fi
    elif [ $op = $_CAST ] ; then
      _get_child __t1 $node 1
      _comp_rvalue_go $1 $__t1 $context 0 $op
    elif [ $op = $_AMP_AMP ] || [ $op = $_BAR_BAR ] ; then
      defstr __str_264 "comp_rvalue_go: && and || should have 4 children by that point"
      _fatal_error __ $__str_264
      : $(($1 = 0))
    else
      defstr __str_265 "comp_rvalue_go: unknown rvalue with 2 children"
      _fatal_error __ $__str_265
      : $(($1 = 0))
    fi
  elif [ $nb_children = 3 ] ; then
    if [ $op = $__QUESTION__ ] ; then
      _get_child __t1 $node 0
      _comp_rvalue_go sub1 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $op
      _get_child __t1 $node 1
      _comp_rvalue_go sub2 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $op
      _get_child __t1 $node 2
      _comp_rvalue_go sub3 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $op
      defstr __str_266 ": "
      _op_to_str __t2 $op
      _wrap_str __t3 $__str_266
      _string_concat5 __t1 $sub1 $__t2 $sub2 $__t3 $sub3
      _wrap_if_needed $1 1 $context $test_side_effects $__t1 $outer_op $op
      endlet $1 __t8 __t7 __t6 __t5 __t4 __t3 __t2 __t1 sub3 sub2 sub1 nb_children op outer_op test_side_effects context node
      return
      : $(($1 = 0))
    else
      printf "op=%d " $op
      printf \\$((op/64))$((op/8%8))$((op%8))
      printf "\n" 
      defstr __str_267 "comp_rvalue_go: unknown rvalue with 3 children"
      _fatal_error __ $__str_267
      : $(($1 = 0))
    fi
  elif [ $nb_children = 4 ] ; then
    if [ $op = $_AMP_AMP ] || [ $op = $_BAR_BAR ] ; then
      if [ $context = $_RVALUE_CTX_TEST ] ; then
        _get_child __t1 $node 0
        _get_child __t2 $node 2
        _comp_rvalue_go sub1 $__t1 $_RVALUE_CTX_TEST $__t2 $op
        _get_child __t1 $node 1
        _get_child __t2 $node 3
        _comp_rvalue_go sub2 $__t1 $_RVALUE_CTX_TEST $__t2 $op
        if { { _get_child __t2 $node 0; _get_op __t1 $__t2; [ $__t1 = $_AMP_AMP ]; } || { _get_child __t3 $node 0; _get_op __t2 $__t3; [ $__t2 = $_BAR_BAR ]; }; } && { _get_child __t4 $node 0; _get_op __t3 $__t4; [ $__t3 != $op ]; } ; then
          defstr __str_268 "{ "
          _wrap_str __t1 $__str_268
          defstr __str_269 "; }"
          _wrap_str __t2 $__str_269
          _string_concat3 sub1 $__t1 $sub1 $__t2
        fi
        if { { _get_child __t2 $node 1; _get_op __t1 $__t2; [ $__t1 = $_AMP_AMP ]; } || { _get_child __t3 $node 1; _get_op __t2 $__t3; [ $__t2 = $_BAR_BAR ]; }; } && { _get_child __t4 $node 1; _get_op __t3 $__t4; [ $__t3 != $op ]; } ; then
          defstr __str_270 "{ "
          _wrap_str __t1 $__str_270
          defstr __str_271 "; }"
          _wrap_str __t2 $__str_271
          _string_concat3 sub2 $__t1 $sub2 $__t2
        fi
        _op_to_str __t1 $op
        _string_concat3 $1 $sub1 $__t1 $sub2
      else
        if [ $test_side_effects != 0 ] || { _get_child __t1 $node 2; [ $__t1 != 0 ]; } || { _get_child __t2 $node 3; [ $__t2 != 0 ]; } ; then
          defstr __str_272 "comp_rvalue_go: && and || with function calls can only be used in tests"
          _fatal_error __ $__str_272
        fi
        _get_child __t1 $node 0
        _comp_rvalue_go sub1 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $op
        _get_child __t1 $node 1
        _comp_rvalue_go sub2 $__t1 $_RVALUE_CTX_ARITH_EXPANSION 0 $op
        _op_to_str __t2 $op
        _string_concat3 __t1 $sub1 $__t2 $sub2
        _wrap_if_needed $1 1 $context $test_side_effects $__t1 $outer_op $op
      fi
    else
      printf "op=%d " $op
      printf \\$((op/64))$((op/8%8))$((op%8))
      printf "\n" 
      defstr __str_273 "comp_rvalue_go: unknown rvalue with 4 children"
      _fatal_error __ $__str_273
      : $(($1 = 0))
    fi
  else
    printf "op=%d " $op
    printf \\$((op/64))$((op/8%8))$((op%8))
    printf "\n" 
    defstr __str_274 "comp_rvalue_go: unknown rvalue with >4 children"
    _fatal_error __ $__str_274
    : $(($1 = 0))
  fi
  endlet $1 __t8 __t7 __t6 __t5 __t4 __t3 __t2 __t1 sub3 sub2 sub1 nb_children op outer_op test_side_effects context node
}

: $((__t3 = __t2 = __t1 = result = fun_call_decl_start = contains_side_effects2 = replaced_fun_calls2 = simple_ast = context = node = 0))
_comp_rvalue() { let node $2; let context $3
  let simple_ast; let replaced_fun_calls2; let contains_side_effects2; let fun_call_decl_start; let result; let __t1; let __t2; let __t3
  _handle_side_effects simple_ast $node
  replaced_fun_calls2=$_replaced_fun_calls
  contains_side_effects2=$_contains_side_effects
  fun_call_decl_start=$_glo_decl_ix
  while [ $_literals_inits != 0 ] ; do
    _get_child __t2 $_literals_inits 0
    _get_child __t1 $__t2 0
    _get_child __t3 $_literals_inits 0
    _get_child __t2 $__t3 1
    _comp_defstr __ $__t1 $__t2
    _get_child _literals_inits $_literals_inits 1
  done
  if [ $context != $_RVALUE_CTX_TEST_ELSEIF ] ; then
    fun_call_decl_start=$_glo_decl_ix
  fi
  while [ $replaced_fun_calls2 != 0 ] ; do
    _get_child __t2 $replaced_fun_calls2 0
    _get_child __t1 $__t2 1
    _get_child __t3 $replaced_fun_calls2 0
    _get_child __t2 $__t3 0
    _comp_fun_call __ $__t1 $__t2
    _get_child replaced_fun_calls2 $replaced_fun_calls2 1
  done
  if [ $context = $_RVALUE_CTX_TEST ] || [ $context = $_RVALUE_CTX_TEST_ELSEIF ] ; then
    _undo_glo_decls __ $fun_call_decl_start
    _replay_glo_decls_inline result $fun_call_decl_start $_glo_decl_ix
    _comp_rvalue_go __t1 $simple_ast $_RVALUE_CTX_TEST 0 0
    _string_concat result $result $__t1
  else
    _comp_rvalue_go result $simple_ast $context 0 0
  fi
  : $((_contains_side_effects |= contains_side_effects2))
  : $(($1 = result))
  endlet $1 __t3 __t2 __t1 result fun_call_decl_start contains_side_effects2 replaced_fun_calls2 simple_ast context node
}

: $((__t3 = __t2 = __t1 = sub2 = sub1 = op = node = 0))
_comp_lvalue_address() { let node $2
  let op; let sub1; let sub2; let __t1; let __t2; let __t3
  _get_op op $node
  if [ $op = $_IDENTIFIER ] ; then
    defstr __str_275 "comp_rvalue_go: can't take the address of a local variable"
    _fatal_error __ $__str_275
  elif [ $op = $__LBRACK__ ] ; then
    _get_child __t1 $node 0
    _comp_rvalue sub1 $__t1 $_RVALUE_CTX_ARITH_EXPANSION
    _get_child __t1 $node 1
    _comp_rvalue sub2 $__t1 $_RVALUE_CTX_ARITH_EXPANSION
    defstr __str_276 " + "
    _wrap_str __t1 $__str_276
    _string_concat3 $1 $sub1 $__t1 $sub2
  elif [ $op = $__STAR__ ] ; then
    _get_child __t1 $node 0
    _comp_rvalue $1 $__t1 $_RVALUE_CTX_BASE
  elif [ $op = $_ARROW ] ; then
    _get_child __t1 $node 0
    _comp_rvalue sub1 $__t1 $_RVALUE_CTX_ARITH_EXPANSION
    _get_child __t1 $node 1
    _struct_member_var sub2 $__t1
    defstr __str_277 " + "
    _wrap_str __t1 $__str_277
    _string_concat3 $1 $sub1 $__t1 $sub2
    endlet $1 __t3 __t2 __t1 sub2 sub1 op node
    return
    defstr __str_278 "_\$(("
    _wrap_str __t1 $__str_278
    defstr __str_279 " + "
    _wrap_str __t2 $__str_279
    defstr __str_280 "))"
    _wrap_str __t3 $__str_280
    _string_concat5 $1 $__t1 $sub1 $__t2 $sub2 $__t3
  elif [ $op = $_CAST ] ; then
    _get_child __t1 $node 1
    _comp_lvalue_address $1 $__t1
  else
    printf "op=%d " $op
    printf \\$((op/64))$((op/8%8))$((op%8))
    printf "\n" 
    defstr __str_281 "comp_lvalue_address: unknown lvalue"
    _fatal_error __ $__str_281
    : $(($1 = 0))
  fi
  endlet $1 __t3 __t2 __t1 sub2 sub1 op node
}

: $((__t3 = __t2 = __t1 = sub2 = sub1 = op = node = 0))
_comp_lvalue() { let node $2
  let op; let sub1; let sub2; let __t1; let __t2; let __t3
  _get_op op $node
  if [ $op = $_IDENTIFIER ] || [ $op = $_IDENTIFIER_INTERNAL ] || [ $op = $_IDENTIFIER_STRING ] || [ $op = $_IDENTIFIER_EMPTY ] || [ $op = $_IDENTIFIER_DOLLAR ] ; then
    _env_var $1 $node
  elif [ $op = $__LBRACK__ ] ; then
    _get_child __t1 $node 0
    _comp_rvalue sub1 $__t1 $_RVALUE_CTX_ARITH_EXPANSION
    _get_child __t1 $node 1
    _comp_rvalue sub2 $__t1 $_RVALUE_CTX_ARITH_EXPANSION
    defstr __str_282 "_\$(("
    _wrap_str __t1 $__str_282
    defstr __str_283 " + "
    _wrap_str __t2 $__str_283
    defstr __str_284 "))"
    _wrap_str __t3 $__str_284
    _string_concat5 $1 $__t1 $sub1 $__t2 $sub2 $__t3
  elif [ $op = $__STAR__ ] ; then
    _get_child __t1 $node 0
    _comp_rvalue sub1 $__t1 $_RVALUE_CTX_BASE
    _string_concat $1 $((-(__UNDERSCORE__))) $sub1
  elif [ $op = $_ARROW ] ; then
    _get_child __t1 $node 0
    _comp_rvalue sub1 $__t1 $_RVALUE_CTX_ARITH_EXPANSION
    _get_child __t1 $node 1
    _struct_member_var sub2 $__t1
    defstr __str_285 "_\$(("
    _wrap_str __t1 $__str_285
    defstr __str_286 " + "
    _wrap_str __t2 $__str_286
    defstr __str_287 "))"
    _wrap_str __t3 $__str_287
    _string_concat5 $1 $__t1 $sub1 $__t2 $sub2 $__t3
    endlet $1 __t3 __t2 __t1 sub2 sub1 op node
    return
    defstr __str_288 "_\$(("
    _wrap_str __t1 $__str_288
    defstr __str_289 "))"
    _wrap_str __t2 $__str_289
    _string_concat3 $1 $__t1 $sub1 $__t2
  elif [ $op = $_CAST ] ; then
    _get_child __t1 $node 1
    _comp_lvalue $1 $__t1
  else
    printf "op=%d " $op
    printf \\$((op/64))$((op/8%8))$((op%8))
    printf "\n" 
    defstr __str_290 "comp_lvalue: unknown lvalue"
    _fatal_error __ $__str_290
    : $(($1 = 0))
  fi
  endlet $1 __t3 __t2 __t1 sub2 sub1 op node
}

: $((__t1 = code_params = param = count = params = 0))
_fun_call_params() { let params $2; let count $3
  let param; let code_params; let __t1
  code_params=0
  if [ $params != 0 ] && [ $count -gt 0 ] ; then
    if _get_op __t1 $params; [ $__t1 = $__COMMA__ ] ; then
      while { _get_op __t1 $params; [ $__t1 = $__COMMA__ ]; } && [ $count -gt 0 ] ; do
        _get_child __t1 $params 0
        _comp_rvalue param $__t1 $_RVALUE_CTX_BASE
        _concatenate_strings_with code_params $code_params $param $((-(__SPACE__)))
        _get_child params $params 1
        : $((count -= 1))
      done
    else
      _comp_rvalue code_params $params $_RVALUE_CTX_BASE
    fi
  fi
  : $(($1 = code_params))
  endlet $1 __t1 code_params param count params
}

: $((__t5 = __t4 = __t3 = __t2 = __t1 = ident = res = param = 0))
_comp_putchar_inline() { let param $2
  let res; let ident; let __t1; let __t2; let __t3; let __t4; let __t5
  _comp_rvalue res $param $_RVALUE_CTX_ARITH_EXPANSION
  if [ $_contains_side_effects != 0 ] ; then
    _fresh_ident ident 
    _comp_lvalue __t2 $ident
    _string_concat3 __t1 $__t2 $((-(__EQ__))) $res
    _append_glo_decl __ $__t1
    _comp_lvalue res $ident
  elif _get_op __t1 $param; [ $__t1 != $_IDENTIFIER ] ; then
    _string_concat3 res $((-(__LPAREN__))) $res $((-(__RPAREN__)))
  fi
  defstr __str_292 "/64))"
  defstr __str_291 "\$(("
  _wrap_str __t2 $__str_291
  _wrap_str __t3 $__str_292
  _string_concat3 __t1 $__t2 $res $__t3
  defstr __str_294 "/8%8))"
  defstr __str_293 "\$(("
  _wrap_str __t3 $__str_293
  _wrap_str __t4 $__str_294
  _string_concat3 __t2 $__t3 $res $__t4
  defstr __str_296 "%8))"
  defstr __str_295 "\$(("
  _wrap_str __t4 $__str_295
  _wrap_str __t5 $__str_296
  _string_concat3 __t3 $__t4 $res $__t5
  _string_concat3 res $__t1 $__t2 $__t3
  defstr __str_297 "printf \\\\\\\\"
  _wrap_str __t1 $__str_297
  _string_concat $1 $__t1 $res
  endlet $1 __t5 __t4 __t3 __t2 __t1 ident res param
}

: $((a = 0))
_printf_uses_shell_format_specifiers() { let a $2
  while [ $((_$a)) != $__NUL__ ] ; do
    if [ $((_$a)) = $__PERCENT__ ] ; then
      : $((a += 1))
      if [ $((_$a)) != $__d__ ] && [ $((_$a)) != $__c__ ] && [ $((_$a)) != $__x__ ] && [ $((_$a)) != $__PERCENT__ ] && [ $((_$a)) != $__s__ ] ; then
        : $(($1 = 0))
        endlet $1 a
        return
      fi
    fi
    : $((a += 1))
  done
  : $(($1 = 1))
  endlet $1 a
}

: $((__t5 = __t4 = __t3 = __t2 = __t1 = params_start = params_count = format_start = params = format_str = 0))
_handle_printf_call() { let format_str $2; let params $3
  let format_start; let params_count; let params_start; let __t1; let __t2; let __t3; let __t4; let __t5
  format_start=$format_str
  params_count=0
  params_start=$params
  while [ $((_$format_str)) != $__NUL__ ] ; do
    if [ $((_$format_str)) = $__PERCENT__ ] ; then
      : $((format_str += 1))
      if [ $((_$format_str)) = $__d__ ] || [ $((_$format_str)) = $__x__ ] ; then
        if [ $params = 0 ] ; then
          defstr __str_298 "Not enough parameters for printf"
          _fatal_error __ $__str_298
        fi
        : $((params_count += 1))
        _get_child params $params 1
      elif [ $((_$format_str)) = $__s__ ] || [ $((_$format_str)) = $__c__ ] ; then
        if [ $format_start != $((format_str - 1)) ] ; then
          : $((_$((format_str - 1)) = __NUL__))
          defstr __str_300 "\" "
          defstr __str_299 "printf \""
          _wrap_str __t2 $__str_299
          _wrap_str __t4 $format_start
          _escape_text __t3 $__t4 0
          _wrap_str __t4 $__str_300
          _fun_call_params __t5 $params_start $params_count
          _string_concat4 __t1 $__t2 $__t3 $__t4 $__t5
          _append_glo_decl __ $__t1
          : $((_$((format_str - 1)) = __PERCENT__))
        fi
        if [ $((_$format_str)) = $__s__ ] ; then
          _runtime_use_put_pstr=1
          defstr __str_301 "_put_pstr __ "
          _wrap_str __t2 $__str_301
          _get_child __t4 $params 0
          _comp_rvalue __t3 $__t4 $_RVALUE_CTX_BASE
          _string_concat __t1 $__t2 $__t3
          _append_glo_decl __ $__t1
        else
          _get_child __t2 $params 0
          _comp_putchar_inline __t1 $__t2
          _append_glo_decl __ $__t1
        fi
        _gensym_ix=0
        format_start=$((format_str + 1))
        _get_child params $params 1
        params_start=$params
      elif [ $((_$format_str)) != $__PERCENT__ ] ; then
        defstr __str_302 "Unsupported format specifier"
        _fatal_error __ $__str_302
      fi
    fi
    : $((format_str += 1))
  done
  if [ $format_start != $format_str ] ; then
    defstr __str_304 "\" "
    defstr __str_303 "printf \""
    _wrap_str __t2 $__str_303
    _wrap_str __t4 $format_start
    _escape_text __t3 $__t4 0
    _wrap_str __t4 $__str_304
    _fun_call_params __t5 $params_start 1000
    _string_concat4 __t1 $__t2 $__t3 $__t4 $__t5
    _append_glo_decl __ $__t1
  fi
  endlet $1 __t5 __t4 __t3 __t2 __t1 params_start params_count format_start params format_str
}

: $((__t4 = __t3 = __t2 = __t1 = res = name_id = params = name = assign_to = node = 0))
_comp_fun_call_code() { let node $2; let assign_to $3
  let name; let params; let name_id; let res; let __t1; let __t2; let __t3; let __t4
  _get_child name $node 0
  _get_child params $node 1
  _get_val name_id $name
  if _get_op __t1 $assign_to; [ $__t1 = $_IDENTIFIER_EMPTY ] ; then
    if { { [ $name_id = $_PUTSTR_ID ] || [ $name_id = $_PUTS_ID ]; } && [ $params != 0 ] && { _get_op __t1 $params; [ $__t1 = $_STRING ]; }; } || { [ $name_id = $_PRINTF_ID ] && [ $params != 0 ] && { _get_op __t2 $params; [ $__t2 = $_STRING ]; }; } ; then
      defstr __str_305 "printf \""
      _wrap_str __t1 $__str_305
      _get_val __t4 $params
      _wrap_str_pool __t3 $__t4
      _escape_text __t2 $__t3 1
      defstr __str_306 "\""
      _wrap_str __t3 $__str_306
      _string_concat3 $1 $__t1 $__t2 $__t3
      endlet $1 __t4 __t3 __t2 __t1 res name_id params name assign_to node
      return
    elif [ $name_id = $_PRINTF_ID ] && [ $params != 0 ] && { _get_op __t1 $params; [ $__t1 = $__COMMA__ ]; } ; then
      if _get_child __t3 $params 0; _get_val __t2 $__t3; _printf_uses_shell_format_specifiers __t1 $((_string_pool + __t2)); [ $__t1 != 0 ] ; then
        _get_child __t2 $params 0
        _get_val __t1 $__t2
        _get_child __t2 $params 1
        _handle_printf_call __ $((_string_pool + __t1)) $__t2
        : $(($1 = 0))
        endlet $1 __t4 __t3 __t2 __t1 res name_id params name assign_to node
        return
      fi
    elif [ $name_id = $_PUTCHAR_ID ] && [ $params != 0 ] && { _get_op __t1 $params; [ $__t1 != $__COMMA__ ]; } ; then
      _comp_putchar_inline $1 $params
      endlet $1 __t4 __t3 __t2 __t1 res name_id params name assign_to node
      return
    elif [ $name_id = $_EXIT_ID ] && [ $params != 0 ] && { _get_op __t1 $params; [ $__t1 != $__COMMA__ ]; } ; then
      _comp_rvalue res $params $_RVALUE_CTX_BASE
      defstr __str_307 "exit "
      _wrap_str __t1 $__str_307
      _string_concat $1 $__t1 $res
      endlet $1 __t4 __t3 __t2 __t1 res name_id params name assign_to node
      return
    fi
  fi
  if [ $name_id = $_PUTCHAR_ID ] ; then
    _runtime_use_putchar=1
  elif [ $name_id = $_GETCHAR_ID ] ; then
    _runtime_use_getchar=1
  elif [ $name_id = $_EXIT_ID ] ; then
    _runtime_use_exit=1
  elif [ $name_id = $_MALLOC_ID ] ; then
    _runtime_use_malloc=1
  elif [ $name_id = $_FREE_ID ] ; then
    _runtime_use_free=1
  elif [ $name_id = $_PRINTF_ID ] ; then
    _runtime_use_printf=1
  elif [ $name_id = $_FOPEN_ID ] ; then
    _runtime_use_fopen=1
  elif [ $name_id = $_FCLOSE_ID ] ; then
    _runtime_use_fclose=1
  elif [ $name_id = $_FGETC_ID ] ; then
    _runtime_use_fgetc=1
  elif [ $name_id = $_READ_ID ] ; then
    _runtime_use_read=1
  elif [ $name_id = $_WRITE_ID ] ; then
    _runtime_use_write=1
  elif [ $name_id = $_OPEN_ID ] ; then
    _runtime_use_open=1
  elif [ $name_id = $_CLOSE_ID ] ; then
    _runtime_use_close=1
  fi
  _get_val __t2 $name
  _function_name __t1 $__t2
  _comp_lvalue __t2 $assign_to
  _fun_call_params __t3 $params 1000
  _string_concat5 $1 $__t1 $((-(__SPACE__))) $__t2 $((-(__SPACE__))) $__t3
  endlet $1 __t4 __t3 __t2 __t1 res name_id params name assign_to node
}

: $((res = assign_to = node = 0))
_comp_fun_call() { let node $2; let assign_to $3
  let res
  _comp_fun_call_code res $node $assign_to
  if [ $res != 0 ] ; then
    _append_glo_decl __ $res
  fi
  endlet $1 res assign_to node
}

: $((__t6 = __t5 = __t4 = __t3 = __t2 = __t1 = lhs_op = rhs = lhs = 0))
_comp_assignment() { let lhs $2; let rhs $3
  let lhs_op; let __t1; let __t2; let __t3; let __t4; let __t5; let __t6
  _get_op lhs_op $lhs
  if [ $lhs_op = $_IDENTIFIER ] || [ $lhs_op = $__LBRACK__ ] || [ $lhs_op = $__STAR__ ] || [ $lhs_op = $_ARROW ] ; then
    if _get_op __t1 $rhs; [ $__t1 = $__LPAREN__ ] ; then
      _comp_fun_call __ $rhs $lhs
    else
      if [ $lhs_op = $_IDENTIFIER ] ; then
        _comp_lvalue __t2 $lhs
        _comp_rvalue __t3 $rhs $_RVALUE_CTX_BASE
        _string_concat3 __t1 $__t2 $((-(__EQ__))) $__t3
        _append_glo_decl __ $__t1
      else
        defstr __str_310 "))"
        defstr __str_309 " = "
        defstr __str_308 ": \$(("
        _wrap_str __t2 $__str_308
        _comp_lvalue __t3 $lhs
        _wrap_str __t4 $__str_309
        _comp_rvalue __t5 $rhs $_RVALUE_CTX_ARITH_EXPANSION
        _wrap_str __t6 $__str_310
        _string_concat5 __t1 $__t2 $__t3 $__t4 $__t5 $__t6
        _append_glo_decl __ $__t1
      fi
    fi
  else
    printf "lhs_op=%d " $lhs_op
    printf \\$((lhs_op/64))$((lhs_op/8%8))$((lhs_op%8))
    printf "\n" 
    defstr __str_311 "unknown lhs"
    _fatal_error __ $__str_311
  fi
  endlet $1 __t6 __t5 __t4 __t3 __t2 __t1 lhs_op rhs lhs
}

: $((__t2 = __t1 = start_in_tail_position = node = 0))
_comp_body() { let node $2
  let start_in_tail_position; let __t1; let __t2
  start_in_tail_position=$_in_tail_position
  _in_tail_position=0
  _in_block_head_position=1
  if [ $node != 0 ] ; then
    while _get_op __t1 $node; [ $__t1 = $__LBRACE__ ] ; do
      if _get_child __t2 $node 1; _get_op __t1 $__t2; [ $__t1 != $__LBRACE__ ] ; then
        _in_tail_position=$start_in_tail_position
      fi
      _get_child __t1 $node 0
      _comp_statement __ $__t1 0
      _get_child node $node 1
      _in_block_head_position=0
    done
  fi
  endlet $1 __t2 __t1 start_in_tail_position node
}

: $((__t2 = __t1 = start_in_tail_position = node = 0))
_comp_switch_block_statement() { let node $2; let start_in_tail_position $3
  let __t1; let __t2
  if _get_op __t1 $node; [ $__t1 = $_BREAK_KW ] ; then
    : $(($1 = 1))
  elif _get_op __t1 $node; [ $__t1 = $_RETURN_KW ] ; then
    _in_tail_position=$start_in_tail_position
    _comp_statement __ $node 0
    : $(($1 = 1))
  elif { _get_op __t1 $node; [ $__t1 = $_CASE_KW ]; } || { _get_op __t2 $node; [ $__t2 = $_DEFAULT_KW ]; } ; then
    defstr __str_312 "comp_statement: case must be at the beginning of a switch block, and each block must end with a break or return statement"
    _fatal_error __ $__str_312
  else
    _comp_statement __ $node 0
    : $(($1 = 0))
  fi
  endlet $1 __t2 __t1 start_in_tail_position node
}

: $((__t4 = __t3 = __t2 = __t1 = str = statement = start_in_tail_position = node = 0))
_comp_switch() { let node $2
  let start_in_tail_position; let statement; let str; let __t1; let __t2; let __t3; let __t4
  start_in_tail_position=$_in_tail_position
  defstr __str_314 " in"
  defstr __str_313 "case "
  _wrap_str __t2 $__str_313
  _get_child __t4 $node 0
  _comp_rvalue __t3 $__t4 $_RVALUE_CTX_BASE
  _wrap_str __t4 $__str_314
  _string_concat3 __t1 $__t2 $__t3 $__t4
  _append_glo_decl __ $__t1
  : $((_nest_level += 1))
  _get_child node $node 1
  if [ $node = 0 ] || { _get_op __t1 $node; [ $__t1 != $__LBRACE__ ]; } ; then
    defstr __str_315 "comp_statement: switch without body"
    _fatal_error __ $__str_315
  fi
  while _get_op __t1 $node; [ $__t1 = $__LBRACE__ ] ; do
    _get_child statement $node 0
    _get_child node $node 1
    if { _get_op __t1 $statement; [ $__t1 != $_CASE_KW ]; } && { _get_op __t2 $statement; [ $__t2 != $_DEFAULT_KW ]; } ; then
      defstr __str_316 "comp_statement: switch body without case"
      _fatal_error __ $__str_316
    fi
    if _get_op __t1 $statement; [ $__t1 = $_CASE_KW ] ; then
      str=0
      while _get_op __t1 $statement; [ $__t1 = $_CASE_KW ] ; do
        _get_child __t2 $statement 0
        _comp_rvalue __t1 $__t2 $_RVALUE_CTX_BASE
        _concatenate_strings_with str $str $__t1 $((-(__BAR__)))
        _get_child statement $statement 1
      done
    else
      defstr __str_317 "*"
      _wrap_str str $__str_317
      _get_child statement $statement 0
    fi
    defstr __str_318 ")"
    _wrap_str __t2 $__str_318
    _string_concat __t1 $str $__t2
    _append_glo_decl __ $__t1
    : $((_nest_level += 1))
    _in_tail_position=0
    _new_ast2 node $__LBRACE__ $statement $node
    while _get_op __t1 $node; [ $__t1 = $__LBRACE__ ] ; do
      _get_child statement $node 0
      _get_child node $node 1
      if _comp_switch_block_statement __t1 $statement $start_in_tail_position; [ $__t1 != 0 ] ; then
        break
      fi
    done
    : $((_nest_level -= 1))
    defstr __str_319 ";;"
    _wrap_str __t1 $__str_319
    _append_glo_decl __ $__t1
  done
  : $((_nest_level -= 1))
  defstr __str_320 "esac"
  _wrap_str __t1 $__str_320
  _append_glo_decl __ $__t1
  endlet $1 __t4 __t3 __t2 __t1 str statement start_in_tail_position node
}

: $((__t6 = __t5 = __t4 = __t3 = __t2 = __t1 = start_loop_end_actions_end = start_loop_end_actions_start = str = op = else_if = node = 0))
_comp_statement() { let node $2; let else_if $3
  let op; let str; let start_loop_end_actions_start; let start_loop_end_actions_end; let __t1; let __t2; let __t3; let __t4; let __t5; let __t6
  _get_op op $node
  _gensym_ix=0
  if [ $op = $_IF_KW ] ; then
    defstr __str_323 " ; then"
    defstr __str_322 "if "
    defstr __str_321 "elif "
    _wrap_str __t2 $((else_if ? __str_321: __str_322))
    _get_child __t4 $node 0
    _comp_rvalue __t3 $__t4 $((else_if ? _RVALUE_CTX_TEST_ELSEIF: _RVALUE_CTX_TEST))
    _wrap_str __t4 $__str_323
    _string_concat3 __t1 $__t2 $__t3 $__t4
    _append_glo_decl __ $__t1
    : $((_nest_level += 1))
    if _get_child __t1 $node 1; [ $__t1 != 0 ] ; then
      _get_child __t1 $node 1
      _comp_statement __ $__t1 0
    else
      _append_glo_decl __ $((-(__COLON__)))
    fi
    : $((_nest_level -= 1))
    if _get_child __t1 $node 2; [ $__t1 != 0 ] ; then
      if _get_child __t2 $node 2; _get_op __t1 $__t2; [ $__t1 = $_IF_KW ] ; then
        _get_child __t1 $node 2
        _comp_statement __ $__t1 1
      else
        defstr __str_324 "else"
        _wrap_str __t1 $__str_324
        _append_glo_decl __ $__t1
        : $((_nest_level += 1))
        _get_child __t1 $node 2
        _comp_statement __ $__t1 0
        : $((_nest_level -= 1))
      fi
    fi
    if [ $((!else_if)) != 0 ] ; then
      defstr __str_325 "fi"
      _wrap_str __t1 $__str_325
      _append_glo_decl __ $__t1
    fi
  elif [ $op = $_WHILE_KW ] ; then
    defstr __str_327 " ; do"
    defstr __str_326 "while "
    _wrap_str __t2 $__str_326
    _get_child __t4 $node 0
    _comp_rvalue __t3 $__t4 $_RVALUE_CTX_TEST
    _wrap_str __t4 $__str_327
    _string_concat3 __t1 $__t2 $__t3 $__t4
    _append_glo_decl __ $__t1
    : $((_loop_nesting_level += 1))
    : $((_nest_level += 1))
    if _get_child __t1 $node 1; [ $__t1 != 0 ] ; then
      _get_child __t1 $node 1
      _comp_statement __ $__t1 0
    else
      _append_glo_decl __ $((-(__COLON__)))
    fi
    : $((_nest_level -= 1))
    : $((_loop_nesting_level -= 1))
    defstr __str_328 "done"
    _wrap_str __t1 $__str_328
    _append_glo_decl __ $__t1
  elif [ $op = $_FOR_KW ] ; then
    start_loop_end_actions_start=$_loop_end_actions_start
    start_loop_end_actions_end=$_loop_end_actions_end
    if _get_child __t1 $node 0; [ $__t1 != 0 ] ; then
      _get_child __t1 $node 0
      _comp_statement __ $__t1 0
    fi
    str=$((-(__COLON__)))
    if _get_child __t1 $node 1; [ $__t1 != 0 ] ; then
      _get_child __t1 $node 1
      _comp_rvalue str $__t1 $_RVALUE_CTX_TEST
    fi
    defstr __str_330 " ; do"
    defstr __str_329 "while "
    _wrap_str __t2 $__str_329
    _wrap_str __t3 $__str_330
    _string_concat3 __t1 $__t2 $str $__t3
    _append_glo_decl __ $__t1
    _loop_end_actions_start=$_glo_decl_ix
    if _get_child __t1 $node 2; [ $__t1 != 0 ] ; then
      _get_child __t1 $node 2
      _comp_statement __ $__t1 0
    fi
    _undo_glo_decls __ $_loop_end_actions_start
    _loop_end_actions_end=$_glo_decl_ix
    : $((_loop_nesting_level += 1))
    : $((_nest_level += 1))
    if _get_child __t1 $node 3; [ $__t1 != 0 ] ; then
      _get_child __t1 $node 3
      _comp_statement __ $__t1 0
    elif _get_child __t1 $node 2; [ $__t1 = 0 ] ; then
      _append_glo_decl __ $((-(__COLON__)))
    fi
    _replay_glo_decls __ $_loop_end_actions_start $_loop_end_actions_end 1
    : $((_nest_level -= 1))
    : $((_loop_nesting_level -= 1))
    _loop_end_actions_start=$start_loop_end_actions_start
    _loop_end_actions_end=$start_loop_end_actions_end
    defstr __str_331 "done"
    _wrap_str __t1 $__str_331
    _append_glo_decl __ $__t1
  elif [ $op = $_SWITCH_KW ] ; then
    _comp_switch __ $node
  elif [ $op = $_BREAK_KW ] ; then
    if [ $_loop_nesting_level = 0 ] ; then
      defstr __str_332 "comp_statement: break not in loop"
      _fatal_error __ $__str_332
    fi
    defstr __str_333 "break"
    _wrap_str __t1 $__str_333
    _append_glo_decl __ $__t1
  elif [ $op = $_CONTINUE_KW ] ; then
    if [ $_loop_nesting_level = 0 ] ; then
      defstr __str_334 "comp_statement: continue not in loop"
      _fatal_error __ $__str_334
    fi
    _replay_glo_decls __ $_loop_end_actions_start $_loop_end_actions_end 1
    defstr __str_335 "continue"
    _wrap_str __t1 $__str_335
    _append_glo_decl __ $__t1
  elif [ $op = $_RETURN_KW ] ; then
    if _get_child __t1 $node 0; [ $__t1 != 0 ] ; then
      if _get_child __t2 $node 0; _get_op __t1 $__t2; [ $__t1 = $__LPAREN__ ] ; then
        _get_child __t1 $node 0
        _new_ast0 __t2 $_IDENTIFIER_DOLLAR 1
        _comp_fun_call __ $__t1 $__t2
      else
        defstr __str_337 "))"
        defstr __str_336 ": \$((\$1 = "
        _wrap_str __t2 $__str_336
        _get_child __t4 $node 0
        _comp_rvalue __t3 $__t4 $_RVALUE_CTX_ARITH_EXPANSION
        _wrap_str __t4 $__str_337
        _string_concat3 __t1 $__t2 $__t3 $__t4
        _append_glo_decl __ $__t1
      fi
    fi
    if [ $_in_tail_position != 0 ] && [ $_loop_nesting_level = 1 ] ; then
      defstr __str_338 "break"
      _wrap_str __t1 $__str_338
      _append_glo_decl __ $__t1
    elif [ $_in_tail_position != 0 ] && [ $_in_block_head_position != 0 ] && { _get_child __t1 $node 0; [ $__t1 = 0 ]; } ; then
      defstr __str_339 ":"
      _wrap_str __t1 $__str_339
      _append_glo_decl __ $__t1
    elif [ $((!_in_tail_position)) != 0 ] || [ $_loop_nesting_level != 0 ] ; then
      _append_glo_decl_fixup __t1 
      _new_ast2 _rest_loc_var_fixups $__COMMA__ $__t1 $_rest_loc_var_fixups
      defstr __str_340 "return"
      _wrap_str __t1 $__str_340
      _append_glo_decl __ $__t1
    fi
  elif [ $op = $__LPAREN__ ] ; then
    _new_ast0 __t1 $_IDENTIFIER_EMPTY 0
    _comp_fun_call __ $node $__t1
  elif [ $op = $__LBRACE__ ] ; then
    _comp_body __ $node
  elif [ $op = $__EQ__ ] ; then
    _get_child __t1 $node 0
    _get_child __t2 $node 1
    _comp_assignment __ $__t1 $__t2
  elif [ $op = $__COLON__ ] ; then
    defstr __str_341 "# "
    _wrap_str __t2 $__str_341
    _get_child __t6 $node 0
    _get_val __t5 $__t6
    _get_val __t4 $__t5
    _wrap_str_pool __t3 $__t4
    _string_concat3 __t1 $__t2 $__t3 $((-(__COLON__)))
    _append_glo_decl __ $__t1
    _get_child __t1 $node 1
    _comp_statement __ $__t1 0
  elif [ $op = $_GOTO_KW ] ; then
    defstr __str_342 "goto statements not supported"
    _fatal_error __ $__str_342
  elif [ $op = $_VAR_DECLS ] ; then
    defstr __str_343 "variable declaration must be at the beginning of a function"
    _fatal_error __ $__str_343
  else
    _comp_rvalue str $node $_RVALUE_CTX_BASE
    if [ $_contains_side_effects != 0 ] ; then
      defstr __str_344 ": "
      _wrap_str __t2 $__str_344
      _string_concat __t1 $__t2 $str
      _append_glo_decl __ $__t1
    elif [ $_in_block_head_position != 0 ] && [ $_in_tail_position != 0 ] ; then
      defstr __str_345 ":"
      _wrap_str __t1 $__str_345
      _append_glo_decl __ $__t1
    fi
  fi
  endlet $1 __t6 __t5 __t4 __t3 __t2 __t1 start_loop_end_actions_end start_loop_end_actions_start str op else_if node
}

: $((__t1 = new_tail = tail = local_var = result = node = 0))
_get_leading_var_declarations() { let node $2
  let result; let local_var; let tail; let new_tail; let __t1
  result=0
  if _get_op __t1 $node; [ $__t1 = $__LBRACE__ ] ; then
    while _get_op __t1 $node; [ $__t1 = $__LBRACE__ ] ; do
      _get_child local_var $node 0
      if _get_op __t1 $local_var; [ $__t1 != $_VAR_DECLS ] ; then
        break
      fi
      _new_ast2 new_tail $__COMMA__ $local_var 0
      if [ $result = 0 ] ; then
        result=$new_tail
      else
        _set_child __ $tail 1 $new_tail
      fi
      tail=$new_tail
      _get_child node $node 1
    done
  fi
  _new_ast2 $1 $__COMMA__ $result $node
  endlet $1 __t1 new_tail tail local_var result node
}

: $((__t4 = __t3 = __t2 = __t1 = save_loc_vars_fixup = var = vars = decls = params_ix = trailing_txt = local_vars = local_vars_and_body = body = params = fun_type = name = node = 0))
_comp_glo_fun_decl() { let node $2
  let name; let fun_type; let params; let body; let local_vars_and_body; let local_vars; let trailing_txt; let params_ix; let decls; let vars; let var; let save_loc_vars_fixup; let __t1; let __t2; let __t3; let __t4
  _get_child name $node 0
  _get_child fun_type $node 1
  _get_child params $node 2
  _get_child body $node 3
  trailing_txt=0
  if [ $body = -1 ] ; then
    endlet $1 __t4 __t3 __t2 __t1 save_loc_vars_fixup var vars decls params_ix trailing_txt local_vars local_vars_and_body body params fun_type name node
    return
  fi
  _get_child __t1 $node 3
  _get_leading_var_declarations local_vars_and_body $__t1
  _get_child local_vars $local_vars_and_body 0
  _get_child body $local_vars_and_body 1
  _top_level_stmt=0
  _assert_vars_are_safe __ $params 1
  _assert_vars_are_safe __ $local_vars 1
  if [ $name = $_MAIN_ID ] ; then
    _main_defined=1
    if [ $params != 0 ] ; then
      _runtime_use_make_argv=1
    fi
    if _get_op __t1 $fun_type; [ $__t1 != $_VOID_KW ] ; then
      _main_returns=1
    fi
  fi
  _add_fun_params_to_local_env __ $params 2 $_KIND_PARAM
  _add_vars_to_local_env __ $local_vars $((_local_env_size + 2)) $_KIND_LOCAL
  _let_params trailing_txt $params
  if [ $trailing_txt != 0 ] ; then
    _string_concat trailing_txt $((-(__SPACE__))) $trailing_txt
  fi
  if [ $trailing_txt = 0 ] ; then
    params_ix=2
    while [ $params != 0 ] ; do
      _get_child var $params 0
      defstr __str_346 ": \$"
      _get_val __t4 $var
      _get_val __t3 $__t4
      _wrap_str_pool __t2 $__t3
      _wrap_str __t3 $__str_346
      _wrap_int __t4 $params_ix
      _string_concat3 __t1 $__t2 $__t3 $__t4
      defstr __str_347 ", "
      _wrap_str __t2 $__str_347
      _concatenate_strings_with trailing_txt $trailing_txt $__t1 $__t2
      _get_child params $params 1
      : $((params_ix += 1))
    done
    if [ $trailing_txt != 0 ] ; then
      defstr __str_348 " # "
      _wrap_str __t1 $__str_348
      _string_concat trailing_txt $__t1 $trailing_txt
    fi
  fi
  defstr __str_349 "() {"
  _function_name __t2 $name
  _wrap_str __t3 $__str_349
  _string_concat3 __t1 $__t2 $__t3 $trailing_txt
  _append_glo_decl __ $__t1
  _in_tail_position=1
  : $((_nest_level += 1))
  _append_glo_decl_fixup save_loc_vars_fixup 
  while [ $local_vars != 0 ] ; do
    _get_child decls $local_vars 0
    _get_child vars $decls 0
    while [ $vars != 0 ] ; do
      _get_child var $vars 0
      if _get_child __t1 $var 2; [ $__t1 != 0 ] ; then
        _get_child __t2 $var 0
        _new_ast0 __t1 $_IDENTIFIER $__t2
        _get_child __t2 $var 2
        _comp_assignment __ $__t1 $__t2
      fi
      _get_child vars $vars 1
    done
    _get_child local_vars $local_vars 1
  done
  if [ $body = 0 ] ; then
    defstr __str_350 ":"
    _wrap_str __t1 $__str_350
    _append_glo_decl __ $__t1
  else
    _comp_body __ $body
  fi
  _restore_local_vars __t1 $((params_ix - 1))
  _append_glo_decl __ $__t1
  _save_local_vars __t1 $((params_ix - 1))
  _fixup_glo_decl __ $save_loc_vars_fixup $__t1
  while [ $_rest_loc_var_fixups != 0 ] ; do
    _get_child __t1 $_rest_loc_var_fixups 0
    _restore_local_vars __t2 $((params_ix - 1))
    _fixup_glo_decl __ $__t1 $__t2
    _get_child _rest_loc_var_fixups $_rest_loc_var_fixups 1
  done
  : $((_nest_level -= 1))
  defstr __str_351 "}\n"
  _wrap_str __t1 $__str_351
  _append_glo_decl __ $__t1
  endlet $1 __t4 __t3 __t2 __t1 save_loc_vars_fixup var vars decls params_ix trailing_txt local_vars local_vars_and_body body params fun_type name node
}

: $((__t2 = __t1 = new_ident = op = node = 0))
_comp_constant() { let node $2
  let op; let new_ident; let __t1; let __t2
  _get_op op $node
  if [ $op = $_INTEGER ] ; then
    _get_val __t1 $node
    _wrap_int $1 $((-(__t1)))
  elif [ $op = $_CHARACTER ] ; then
    _get_val __t2 $node
    _character_ident __t1 $__t2
    _string_concat $1 $((-(__DOLLAR__))) $__t1
  elif [ $op = $_STRING ] ; then
    _runtime_use_defstr=1
    _fresh_string_ident new_ident 
    _get_val __t1 $node
    _comp_defstr __ $new_ident $__t1
    _format_special_var $1 $new_ident 0
  elif [ $op = $__MINUS__ ] && { _get_nb_children __t1 $node; [ $__t1 = 1 ]; } ; then
    _get_child __t2 $node 0
    _comp_constant __t1 $__t2
    _string_concat $1 $((-(__MINUS__))) $__t1
  else
    defstr __str_352 "comp_constant: unknown constant"
    _fatal_error __ $__str_352
    : $(($1 = 0))
  fi
  endlet $1 __t2 __t1 new_ident op node
}

: $((__t6 = __t5 = __t4 = __t3 = __t2 = __t1 = init = type = name = node = 0))
_comp_glo_var_decl() { let node $2
  let name; let type; let init; let __t1; let __t2; let __t3; let __t4; let __t5; let __t6
  _get_child name $node 0
  _get_child type $node 1
  _get_child init $node 2
  if [ $init = 0 ] ; then
    _new_ast0 init $_INTEGER 0
  fi
  _assert_var_decl_is_safe __ $node 0
  if { { _get_op __t1 $type; [ $__t1 = $__LBRACK__ ]; } && { _get_child __t3 $type 1; _get_op __t2 $__t3; [ $__t2 = $_STRUCT_KW ]; } && { _get_child __t4 $type 1; _get_val __t3 $__t4; [ $__t3 = 0 ]; }; } || { { _get_op __t4 $type; [ $__t4 = $_STRUCT_KW ]; } && { _get_val __t5 $type; [ $__t5 = 0 ]; }; } ; then
    _get_val __t1 $name
    _put_pstr __ $((_string_pool + __t1))
    printf " " 
    defstr __str_353 "array of struct and struct value type are not supported in shell backend. Use a reference type instead."
    _fatal_error __ $__str_353
  fi
  if _get_op __t1 $type; [ $__t1 = $__LBRACK__ ] ; then
    _runtime_defarr __ 
    defstr __str_354 "defarr "
    _wrap_str __t2 $__str_354
    _new_ast0 __t4 $_IDENTIFIER $name
    _env_var __t3 $__t4
    _get_child __t6 $type 0
    _get_val __t5 $__t6
    _wrap_int __t4 $__t5
    _string_concat4 __t1 $__t2 $__t3 $((-(__SPACE__))) $__t4
    _append_glo_decl __ $__t1
  else
    _new_ast0 __t1 $_IDENTIFIER $name
    _comp_assignment __ $__t1 $init
  fi
  endlet $1 __t6 __t5 __t4 __t3 __t2 __t1 init type name node
}

: $((__t3 = __t2 = __t1 = rhs = constant_name = 0))
_comp_assignment_constant() { let constant_name $2; let rhs $3
  let __t1; let __t2; let __t3
  defstr __str_355 "readonly "
  _wrap_str __t2 $__str_355
  _comp_rvalue __t3 $rhs $_RVALUE_CTX_BASE
  _string_concat4 __t1 $__t2 $constant_name $((-(__EQ__))) $__t3
  _append_glo_decl __ $__t1
  endlet $1 __t3 __t2 __t1 rhs constant_name
}

: $((__t5 = __t4 = __t3 = __t2 = __t1 = cases = ident = 0))
_comp_enum_cases() { let ident $2; let cases $3
  let __t1; let __t2; let __t3; let __t4; let __t5
  if [ $ident != 0 ] ; then
    defstr __str_357 " enum declaration"
    defstr __str_356 "# "
    _wrap_str __t2 $__str_356
    _get_val __t5 $ident
    _get_val __t4 $__t5
    _wrap_str_pool __t3 $__t4
    _wrap_str __t4 $__str_357
    _string_concat3 __t1 $__t2 $__t3 $__t4
    _append_glo_decl __ $__t1
  else
    defstr __str_358 "# Enum declaration"
    _wrap_str __t1 $__str_358
    _append_glo_decl __ $__t1
  fi
  while _get_op __t1 $cases; [ $__t1 = $__COMMA__ ] ; do
    _get_child __t2 $cases 0
    _env_var __t1 $__t2
    _get_child __t2 $cases 1
    _comp_assignment_constant __ $__t1 $__t2
    _get_child cases $cases 2
  done
  endlet $1 __t5 __t4 __t3 __t2 __t1 cases ident
}

: $((__t5 = __t4 = __t3 = __t2 = __t1 = field_type = offset = members = ident = 0))
_comp_struct() { let ident $2; let members $3
  let offset; let field_type; let __t1; let __t2; let __t3; let __t4; let __t5
  _new_ast0 offset $_INTEGER 0
  if [ $ident != 0 ] ; then
    defstr __str_360 " struct member declarations"
    defstr __str_359 "# "
    _wrap_str __t2 $__str_359
    _get_val __t5 $ident
    _get_val __t4 $__t5
    _wrap_str_pool __t3 $__t4
    _wrap_str __t4 $__str_360
    _string_concat3 __t1 $__t2 $__t3 $__t4
    _append_glo_decl __ $__t1
  else
    defstr __str_361 "# Struct member declarations"
    _wrap_str __t1 $__str_361
    _append_glo_decl __ $__t1
  fi
  while _get_op __t1 $members; [ $__t1 = $__COMMA__ ] ; do
    _get_child field_type $members 1
    _get_child __t2 $members 0
    _struct_member_var __t1 $__t2
    _comp_assignment_constant __ $__t1 $offset
    _get_child members $members 2
    if { _get_op __t1 $field_type; [ $__t1 = $__LBRACK__ ]; } || { { _get_op __t2 $field_type; [ $__t2 = $_STRUCT_KW ]; } && { _get_val __t3 $field_type; [ $__t3 = 0 ]; }; } ; then
      defstr __str_362 "Nested structures not supported by shell backend. Use a reference type instead."
      _fatal_error __ $__str_362
    else
      _get_val __t1 $offset
      _set_val __ $offset $((__t1 - 1))
    fi
  done
  if [ $ident != 0 ] ; then
    _struct_sizeof_var __t1 $ident
    _comp_assignment_constant __ $__t1 $offset
  fi
  _append_glo_decl __ 0
  endlet $1 __t5 __t4 __t3 __t2 __t1 field_type offset members ident
}

: $((__t2 = __t1 = type = 0))
_handle_enum_struct_union_type_decl() { let type $2
  let __t1; let __t2
  if _get_op __t1 $type; [ $__t1 = $_ENUM_KW ] ; then
    _get_child __t1 $type 1
    _get_child __t2 $type 2
    _comp_enum_cases __ $__t1 $__t2
  elif _get_op __t1 $type; [ $__t1 = $_STRUCT_KW ] ; then
    _get_child __t1 $type 1
    _get_child __t2 $type 2
    _comp_struct __ $__t1 $__t2
  elif _get_op __t1 $type; [ $__t1 = $_UNION_KW ] ; then
    defstr __str_363 "handle_enum_struct_union_type_decl: union not supported"
    _fatal_error __ $__str_363
  fi
  endlet $1 __t2 __t1 type
}

: $((__t2 = __t1 = op = variable = declarations = node = 0))
_comp_glo_decl() { let node $2
  let declarations; let variable; let op; let __t1; let __t2
  _get_op op $node
  _fun_gensym_ix=0
  _top_level_stmt=1
  if [ $op = $__EQ__ ] ; then
    _get_child __t1 $node 0
    _get_child __t2 $node 1
    _comp_assignment __ $__t1 $__t2
  elif [ $op = $_VAR_DECLS ] ; then
    _get_child declarations $node 0
    while [ $declarations != 0 ] ; do
      _get_child variable $declarations 0
      _comp_glo_var_decl __ $variable
      _get_child declarations $declarations 1
    done
  elif [ $op = $_FUN_DECL ] ; then
    _comp_glo_fun_decl __ $node
  elif [ $op = $_TYPEDEF_KW ] ; then
    _get_child __t1 $node 1
    _handle_enum_struct_union_type_decl __ $__t1
  elif [ $op = $_ENUM_KW ] || [ $op = $_STRUCT_KW ] || [ $op = $_UNION_KW ] ; then
    _handle_enum_struct_union_type_decl __ $node
  else
    printf "op=%d " $op
    printf \\$((op/64))$((op/8%8))$((op%8))
    _get_nb_children __t1 $node
    printf " with %d children\n" $__t1
    defstr __str_364 "comp_glo_decl: unexpected declaration"
    _fatal_error __ $__str_364
  fi
  endlet $1 __t2 __t1 op variable declarations node
}

_prologue() {
  printf "#!/bin/sh\n"
  printf "set -e -u\n\n"
}

: $((__t3 = __t2 = __t1 = main_args = c = 0))
_epilogue() {
  let c; let main_args; let __t1; let __t2; let __t3
  main_args=0
  if [ $_any_character_used != 0 ] ; then
    printf "# Character constants\n"
    c=0
    while [ $c -lt 256 ] ; do
      if [ $((_$((_characters_useds + (c / 16))) & (1 << (c % 16)))) != 0 ] ; then
        printf "readonly "
        _character_ident __t1 $c
        _print_text __ $__t1
        printf \\$(((__EQ__)/64))$(((__EQ__)/8%8))$(((__EQ__)%8))
        _putint __ $c
        printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
      fi
      : $((c += 1))
    done
  fi
  printf "# Runtime library\n"
  _produce_runtime __ 
  if [ $_main_defined != 0 ] ; then
    if [ $_runtime_use_make_argv != 0 ] ; then
      printf "# Setup argc, argv\n"
      printf "__argc_for_main=\$((\$# + 1))\n"
      printf "make_argv \$__argc_for_main \"\$0\" \$@; __argv_for_main=\$__argv\n"
      defstr __str_365 " \$__argc_for_main \$__argv_for_main"
      _wrap_str main_args $__str_365
    fi
    if [ $_main_returns != 0 ] ; then
      printf "__code=0; # Success exit code\n"
      defstr __str_367 "; exit \$__code\n"
      defstr __str_366 "_main __code"
      _wrap_str __t2 $__str_366
      _wrap_str __t3 $__str_367
      _string_concat3 __t1 $__t2 $main_args $__t3
      _print_text __ $__t1
    else
      defstr __str_368 "_main __"
      _wrap_str __t2 $__str_368
      _string_concat3 __t1 $__t2 $main_args $((-(__NEWLINE__)))
      _print_text __ $__t1
    fi
  fi
  endlet $1 __t3 __t2 __t1 main_args c
}

: $((__t2 = __t1 = counter = res = ident = local_var = env = 0))
_initialize_function_variables() {
  let env; let local_var; let ident; let res; let counter; let __t1; let __t2
  env=$_local_env
  res=0
  counter=$_fun_gensym_ix
  while [ $counter -gt 0 ] ; do
    _wrap_int __t1 $counter
    _new_ast0 ident $_IDENTIFIER_INTERNAL $__t1
    _format_special_var __t1 $ident 0
    defstr __str_369 " = "
    _wrap_str __t2 $__str_369
    _concatenate_strings_with res $res $__t1 $__t2
    : $((counter -= 1))
  done
  while [ $env != 0 ] ; do
    _get_child local_var $env 0
    _get_child __t1 $local_var 0
    _new_ast0 ident $_IDENTIFIER $__t1
    if _variable_is_constant_param __t1 $local_var; [ $((!__t1)) != 0 ] ; then
      _env_var __t1 $ident
      defstr __str_370 " = "
      _wrap_str __t2 $__str_370
      _concatenate_strings_with res $res $__t1 $__t2
    fi
    _get_child env $env 1
  done
  if [ $res != 0 ] ; then
    defstr __str_371 ": \$(("
    _wrap_str __t1 $__str_371
    defstr __str_372 " = 0))"
    _wrap_str __t2 $__str_372
    _string_concat3 res $__t1 $res $__t2
    _print_text __ $res
    printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
  fi
  endlet $1 __t2 __t1 counter res ident local_var env
}

_codegen_begin() {
  _init_comp_context __ 
  _prologue __ 
}

_max_text_alloc=0
_cumul_text_alloc=0
: $((decl = 0))
_codegen_glo_decl() { let decl $2
  _comp_glo_decl __ $decl
  _initialize_function_variables __ 
  _print_glo_decls __ 
  _glo_decl_ix=0
  _local_env_size=0
  _local_env=0
  _max_text_alloc=$(((_max_text_alloc > _text_alloc) ? _max_text_alloc: _text_alloc))
  : $((_cumul_text_alloc += _text_alloc))
  _text_alloc=1
  endlet $1 decl
}

_codegen_end() {
  _epilogue __ 
}

: $((decl = i = argv_ = argc = 0))
_main() { let argc $2; let argv_ $3
  let i; let decl
  _init_ident_table __ 
  _init_pnut_macros __ 
  i=1
  while [ $i -lt $argc ] ; do
    if [ $((_$((_$((argv_ + i)) + 0)))) = $__MINUS__ ] ; then
      if [ $((_$((_$((argv_ + i)) + 1)))) = $__D__ ] ; then
        _init_ident __ $_MACRO $((_$((argv_ + i)) + 2))
      else
        printf "Option "
        _putstr __ $((_$((argv_ + i))))
        printf \\$(((__NEWLINE__)/64))$(((__NEWLINE__)/8%8))$(((__NEWLINE__)%8))
        defstr __str_373 "unknown option"
        _fatal_error __ $__str_373
      fi
    else
      _include_file __ $((_$((argv_ + i))))
    fi
    : $((i += 1))
  done
  if [ $_fp = 0 ] ; then
    printf "Usage: "
    _putstr __ $((_$((argv_ + 0))))
    printf " <filename>\n"
    defstr __str_374 "no input file"
    _fatal_error __ $__str_374
  fi
  _codegen_begin __ 
  _ch=$__NEWLINE__
  _get_tok __ 
  while [ $_tok != -1 ] ; do
    _parse_definition decl 0
    _codegen_glo_decl __ $decl
  done
  _codegen_end __ 
  : $(($1 = 0))
  endlet $1 decl i argv_ argc
}

# Character constants
readonly __NUL__=0
readonly __ALARM__=7
readonly __BACKSPACE__=8
readonly __TAB__=9
readonly __NEWLINE__=10
readonly __VTAB__=11
readonly __PAGE__=12
readonly __RET__=13
readonly __SPACE__=32
readonly __EXCL__=33
readonly __DQUOTE__=34
readonly __SHARP__=35
readonly __DOLLAR__=36
readonly __PERCENT__=37
readonly __AMP__=38
readonly __QUOTE__=39
readonly __LPAREN__=40
readonly __RPAREN__=41
readonly __STAR__=42
readonly __PLUS__=43
readonly __COMMA__=44
readonly __MINUS__=45
readonly __PERIOD__=46
readonly __SLASH__=47
readonly __0__=48
readonly __7__=55
readonly __9__=57
readonly __COLON__=58
readonly __SEMICOLON__=59
readonly __LT__=60
readonly __EQ__=61
readonly __GT__=62
readonly __QUESTION__=63
readonly __AT__=64
readonly __A__=65
readonly __D__=68
readonly __X__=88
readonly __Z__=90
readonly __LBRACK__=91
readonly __BACKSLASH__=92
readonly __RBRACK__=93
readonly __CARET__=94
readonly __UNDERSCORE__=95
readonly __BACKTICK__=96
readonly __a__=97
readonly __b__=98
readonly __c__=99
readonly __d__=100
readonly __f__=102
readonly __n__=110
readonly __r__=114
readonly __s__=115
readonly __t__=116
readonly __v__=118
readonly __x__=120
readonly __z__=122
readonly __LBRACE__=123
readonly __BAR__=124
readonly __RBRACE__=125
readonly __TILDE__=126
# Runtime library
__c2i_0=48
__c2i_1=49
__c2i_2=50
__c2i_3=51
__c2i_4=52
__c2i_5=53
__c2i_6=54
__c2i_7=55
__c2i_8=56
__c2i_9=57
__c2i_a=97
__c2i_b=98
__c2i_c=99
__c2i_d=100
__c2i_e=101
__c2i_f=102
__c2i_g=103
__c2i_h=104
__c2i_i=105
__c2i_j=106
__c2i_k=107
__c2i_l=108
__c2i_m=109
__c2i_n=110
__c2i_o=111
__c2i_p=112
__c2i_q=113
__c2i_r=114
__c2i_s=115
__c2i_t=116
__c2i_u=117
__c2i_v=118
__c2i_w=119
__c2i_x=120
__c2i_y=121
__c2i_z=122
__c2i_A=65
__c2i_B=66
__c2i_C=67
__c2i_D=68
__c2i_E=69
__c2i_F=70
__c2i_G=71
__c2i_H=72
__c2i_I=73
__c2i_J=74
__c2i_K=75
__c2i_L=76
__c2i_M=77
__c2i_N=78
__c2i_O=79
__c2i_P=80
__c2i_Q=81
__c2i_R=82
__c2i_S=83
__c2i_T=84
__c2i_U=85
__c2i_V=86
__c2i_W=87
__c2i_X=88
__c2i_Y=89
__c2i_Z=90
char_to_int() {
  case $1 in
    [a-zA-Z0-9]) __c=$((__c2i_$1)) ;;
    ' ') __c=32 ;;
    '!') __c=33 ;;
    '"') __c=34 ;;
    '#') __c=35 ;;
    '$') __c=36 ;;
    '%') __c=37 ;;
    '&') __c=38 ;;
    "'") __c=39 ;;
    '(') __c=40 ;;
    ')') __c=41 ;;
    '*') __c=42 ;;
    '+') __c=43 ;;
    ',') __c=44 ;;
    '-') __c=45 ;;
    '.') __c=46 ;;
    '/') __c=47 ;;
    ':') __c=58 ;;
    ';') __c=59 ;;
    '<') __c=60 ;;
    '=') __c=61 ;;
    '>') __c=62 ;;
    '?') __c=63 ;;
    '@') __c=64 ;;
    '[') __c=91 ;;
    '\') __c=92 ;;
    ']') __c=93 ;;
    '^') __c=94 ;;
    '_') __c=95 ;;
    '`') __c=96 ;;
    '{') __c=123 ;;
    '|') __c=124 ;;
    '}') __c=125 ;;
    '~') __c=126 ;;
    *)
      __c=$(LC_CTYPE=C printf "%d" "'$1")
  esac
}

unpack_escaped_string() {
  __buf="$1"
  # Allocates enough space for all characters, assuming that no character is escaped
  _malloc __addr $((${#__buf} + 1))
  __ptr=$__addr
  __us_buf16=
  __us_buf256=
  while [ ! -z "$__buf" ] || [ ! -z "$__us_buf256" ] ; do
    if [ -z "$__us_buf256" ]; then
      if [ ${#__buf} -ge 256 ]; then
        __temp="${__buf#????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????}"
        __us_buf256="${__buf%"$__temp"}"
        __buf="$__temp"
      else
        __us_buf256="$__buf"
        __buf=
      fi
    fi
    if [ -z "$__us_buf16" ]; then
      if [ ${#__us_buf256} -ge 16 ]; then
        __temp="${__us_buf256#????????????????}"
        __us_buf16="${__us_buf256%"$__temp"}"
        __us_buf256="$__temp"
      else
        __us_buf16="$__us_buf256"
        __us_buf256=
      fi
    fi
    while [ ! -z "$__us_buf16" ]; do
      case "$__us_buf16" in
        '\'*)
          __us_buf16="${__us_buf16#?}" # Remove the current char from $__us_buf16
          case "$__us_buf16" in
            'a'*) __c=7 ;;
            'b'*) __c=8 ;;
            'f'*) __c=12 ;;
            'n'*) __c=10 ;;
            'r'*) __c=13 ;;
            't'*) __c=9 ;;
            'v'*) __c=11 ;;
            '\'*) __c=92 ;;
            '"'*) __c=34 ;;
            "'"*) __c=39 ;;
            '?'*) __c=63 ;;
            '$'*) __c=36 ;; # Not in C, used to escape variable expansion between double quotes
            *) echo "invalid escape in string: $__us_buf16"; exit 1 ;;
          esac
          __us_buf16="${__us_buf16#?}" # Remove the current char from $__us_buf16
          ;;
        *)
          char_to_int "${__us_buf16%"${__us_buf16#?}"}"
          __us_buf16="${__us_buf16#?}" # Remove the current char from $__us_buf16
          ;;
      esac
    : $((_$__ptr = __c))
    : $((__ptr += 1))
    done
  done
  : $((_$__ptr = 0))
}

# Define a string, and return a reference to it in the varible taken as argument.
# If the variable is already defined, this function does nothing.
# Note that it's up to the caller to ensure that no 2 strings share the same variable.
defstr() { # $1 = variable name, $2 = string
  set +u # Necessary to allow the variable to be empty
  if [ $(($1)) -eq 0 ]; then
    unpack_escaped_string "$2"
    : $(($1 = __addr))
  fi
  set -u
}

_free() { # $2 = object to free
  __ptr=$(($2 - 1))          # Start of object
  __end=$((__ptr + _$__ptr)) # End of object
  while [ $__ptr -lt $__end ]; do
    unset "_$__ptr"
    : $((__ptr += 1))
  done
  : $(($1 = 0))              # Return 0
}

_put_pstr() {
  : $(($1 = 0)); shift # Return 0
  __addr=$1; shift
  while [ $((_$__addr)) != 0 ]; do
    printf \\$((_$__addr/64))$((_$__addr/8%8))$((_$__addr%8))
    : $((__addr += 1))
  done
}

int_to_char() {
  case $1 in
    48|49|50|51|52|53|54|55|56|57) __char=$(($1 - 48)) ;;
    97)  __char="a" ;;
    98)  __char="b" ;;
    99)  __char="c" ;;
    100) __char="d" ;;
    101) __char="e" ;;
    102) __char="f" ;;
    103) __char="g" ;;
    104) __char="h" ;;
    105) __char="i" ;;
    106) __char="j" ;;
    107) __char="k" ;;
    108) __char="l" ;;
    109) __char="m" ;;
    110) __char="n" ;;
    111) __char="o" ;;
    112) __char="p" ;;
    113) __char="q" ;;
    114) __char="r" ;;
    115) __char="s" ;;
    116) __char="t" ;;
    117) __char="u" ;;
    118) __char="v" ;;
    119) __char="w" ;;
    120) __char="x" ;;
    121) __char="y" ;;
    122) __char="z" ;;
    65)  __char="A" ;;
    66)  __char="B" ;;
    67)  __char="C" ;;
    68)  __char="D" ;;
    69)  __char="E" ;;
    70)  __char="F" ;;
    71)  __char="G" ;;
    72)  __char="H" ;;
    73)  __char="I" ;;
    74)  __char="J" ;;
    75)  __char="K" ;;
    76)  __char="L" ;;
    77)  __char="M" ;;
    78)  __char="N" ;;
    79)  __char="O" ;;
    80)  __char="P" ;;
    81)  __char="Q" ;;
    82)  __char="R" ;;
    83)  __char="S" ;;
    84)  __char="T" ;;
    85)  __char="U" ;;
    86)  __char="V" ;;
    87)  __char="W" ;;
    88)  __char="X" ;;
    89)  __char="Y" ;;
    90)  __char="Z" ;;
    32)  __char=" " ;;
    33)  __char="!" ;;
    34)  __char="\"" ;;
    35)  __char="#" ;;
    36)  __char="$" ;;
    37)  __char="%" ;;
    38)  __char="&" ;;
    39)  __char="'" ;;
    40)  __char="(" ;;
    41)  __char=")" ;;
    42)  __char="*" ;;
    43)  __char="+" ;;
    44)  __char="," ;;
    45)  __char="-" ;;
    46)  __char="." ;;
    47)  __char="/" ;;
    58)  __char=":" ;;
    59)  __char=";" ;;
    60)  __char="<" ;;
    61)  __char="=" ;;
    62)  __char=">" ;;
    63)  __char="?" ;;
    64)  __char="@" ;;
    91)  __char="[" ;;
    92)  __char="\\" ;;
    93)  __char="]" ;;
    94)  __char="^" ;;
    95)  __char="_" ;;
    96)  __char="\`" ;;
    123) __char="{" ;;
    124) __char="|" ;;
    125) __char="}" ;;
    126) __char="~" ;;
    10)  __char="\n" ;;
    *)
      echo "Invalid character code: $1" ; exit 1
      __char=$(printf "\\$(printf "%o" "$1")") ;;
  esac
}

# Convert a pointer to a C string to a Shell string.
# $__res is set to the result, and $__len is set to the length of the string.
pack_string() { # $1 = string address, $2 = end of string delimiter (default to null), $3 = max length (default to 100000000) 
  __addr=$1; 
  __max_len=100000000
  __delim=0
  __len=0
  __res=""
  if [ $# -ge 2 ] ; then __delim=$2   ; fi # Optional end of string delimiter
  if [ $# -ge 3 ] ; then __max_len=$3 ; fi # Optional max length
  while [ $((_$__addr)) != $__delim ] && [ $__max_len -gt $__len ] ; do
    __char=$((_$__addr))
    __addr=$((__addr + 1))
    __len=$((__len + 1))
    case $__char in
      10) __res="$__res\n" ;; # 10 == '\n'
      *)        int_to_char "$__char"
        __res="$__res$__char" ;;
    esac
  done
}

__state_fd0=0;
_malloc __buffer_fd0 1000   # Allocate buffer
: $((_$__buffer_fd0 = 0))   # Init buffer to ""
: $((__cursor_fd0 = 0))     # Make buffer empty
: $((__buflen_fd0 = 1000))  # Init buffer length
__state_fd1=1
__state_fd2=1
__state_fd3=-1
__state_fd4=-1
__state_fd5=-1
__state_fd6=-1
__state_fd7=-1
__state_fd8=-1
__state_fd9=-1

_open() { # $2: filename, $3: flags, $4: mode
  # Get available fd
  __fd=0
  while [ $__fd -lt 10 ]; do
    if [ $((__state_fd$__fd)) -lt 0 ]; then
      break
    fi
    : $((__fd += 1))
  done
  if [ $__fd -gt 9 ] ; then
    # Some shells don't support fd > 9
    echo "No more file descriptors available" ; exit 1
  else
    # Because the file must be read line-by-line, and string
    # values can't be assigned to dynamic variables, each line
    # is read and then unpacked in the buffer.
    _malloc __addr 1000                   # Allocate buffer
    : $((_$__addr = 0))                 # Init buffer to ""
    : $((__buffer_fd$__fd = __addr))    # Save buffer address
    : $((__cursor_fd$__fd = 0))         # Make buffer empty
    : $((__buflen_fd$__fd = 1000))      # Init buffer length
    : $((__state_fd$__fd = $3))         # Mark the fd as opened
    pack_string $2
    if [ $3 = 0 ] ; then
      case $__fd in
        0) exec 0< $__res ;; 1) exec 1< $__res ;; 2) exec 2< $__res ;;
        3) exec 3< $__res ;; 4) exec 4< $__res ;; 5) exec 5< $__res ;;
        6) exec 6< $__res ;; 7) exec 7< $__res ;; 8) exec 8< $__res ;;
        9) exec 9< $__res ;;
      esac
    elif [ $3 = 1 ] ; then
      case $__fd in
        0) exec 0> $__res ;; 1) exec 1> $__res ;; 2) exec 2> $__res ;;
        3) exec 3> $__res ;; 4) exec 4> $__res ;; 5) exec 5> $__res ;;
        6) exec 6> $__res ;; 7) exec 7> $__res ;; 8) exec 8> $__res ;;
        9) exec 9> $__res ;;
      esac
    elif [ $3 = 2 ] ; then
      case $__fd in
        0) exec 0>> $__res ;; 1) exec 1>> $__res ;; 2) exec 2>> $__res ;;
        3) exec 3>> $__res ;; 4) exec 4>> $__res ;; 5) exec 5>> $__res ;;
        6) exec 6>> $__res ;; 7) exec 7>> $__res ;; 8) exec 8>> $__res ;;
        9) exec 9>> $__res ;;
      esac
    else
      echo "Unknow file mode" ; exit 1
    fi
  fi
  : $(($1 = __fd))
}

# Open the file and return a FILE* for the file.
# The FILE structure contains the file descriptor.
_fopen() { # $2: File name, $3: Mode
  _open __fd $2 $((_$3 == 119)) 511
  _malloc __file 1        # Allocate FILE structure
  : $((_$__file = __fd))  # Save fd
  : $(($1 = __file))
}

_close() { # $2: fd
  __fd=$2
  __buf=$((__buffer_fd$__fd))  # Get buffer
  _free __ $__buf              # Release buffer
  : $((__state_fd$__fd = -1))  # Mark the fd as closed
  case $__fd in
    0) exec 0<&- ;; 1) exec 1<&- ;; 2) exec 2<&- ;;
    3) exec 3<&- ;; 4) exec 4<&- ;; 5) exec 5<&- ;;
    6) exec 6<&- ;; 7) exec 7<&- ;; 8) exec 8<&- ;;
    9) exec 9<&- ;;
  esac
  : $(($1 = 0))
}

_fclose() { # $2: file
  __file=$2
  __fd=$((_$__file))  # Get fd
  _free __ $__file    # Release FILE structure
  _close $1 $__fd
}

# Unpack a Shell string into an appropriately sized buffer
unpack_line() { # $1: Shell string, $2: Buffer, $3: Ends with EOF?
  __fgetc_buf=$1
  __buffer=$2
  __ends_with_eof=$3
  __fgetc_buf16=
  __stdin_buf256=
  __continue=1
  while [ $__continue != 0 ] ; do
    if [ -z "$__stdin_buf256" ]; then
      if [ ${#__fgetc_buf} -ge 256 ]; then
        __temp="${__fgetc_buf#????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????}"
        __stdin_buf256="${__fgetc_buf%"$__temp"}"
        __fgetc_buf="$__temp"
      else
        __stdin_buf256="$__fgetc_buf"
        __fgetc_buf=
      fi
    fi
    if [ -z "$__fgetc_buf16" ]; then
      if [ ${#__stdin_buf256} -ge 16 ]; then
        __temp="${__stdin_buf256#????????????????}"
        __fgetc_buf16="${__stdin_buf256%"$__temp"}"
        __stdin_buf256="$__temp"
      else
        __fgetc_buf16="$__stdin_buf256"
        __stdin_buf256=
        __continue=0
      fi
    fi
    while [ ! -z "$__fgetc_buf16" ]; do
      case "$__fgetc_buf16" in
        " "*) : $((_$__buffer = 32))  ;;
        "e"*) : $((_$__buffer = 101)) ;;
        "="*) : $((_$__buffer = 61))  ;;
        "t"*) : $((_$__buffer = 116)) ;;
        ";"*) : $((_$__buffer = 59))  ;;
        "i"*) : $((_$__buffer = 105)) ;;
        ")"*) : $((_$__buffer = 41))  ;;
        "("*) : $((_$__buffer = 40))  ;;
        "n"*) : $((_$__buffer = 110)) ;;
        "s"*) : $((_$__buffer = 115)) ;;
        "l"*) : $((_$__buffer = 108)) ;;
        "+"*) : $((_$__buffer = 43))  ;;
        "p"*) : $((_$__buffer = 112)) ;;
        "a"*) : $((_$__buffer = 97))  ;;
        "r"*) : $((_$__buffer = 114)) ;;
        "f"*) : $((_$__buffer = 102)) ;;
        "d"*) : $((_$__buffer = 100)) ;;
        "*"*) : $((_$__buffer = 42))  ;;
        *)
          char_to_int "${__fgetc_buf16%"${__fgetc_buf16#?}"}"
          : $((_$__buffer = __c))
          ;;
      esac
      __fgetc_buf16=${__fgetc_buf16#?}  # Remove the first character
      : $((__buffer += 1))              # Move to the next buffer position
    done
  done

  if [ $__ends_with_eof -eq 0 ]; then # Ends with newline and not EOF?
    : $((_$__buffer = 10))            # Line ends with newline
    : $((__buffer += 1))
  fi
  : $((_$__buffer = 0))               # Then \0
}

refill_buffer() { # $1: fd
  __fd=$1
  __buffer=$((__buffer_fd$__fd))

  IFS=
  if read -r __temp_buf <&$__fd ; then  # read next line into $__temp_buf
    __ends_with_eof=0
  else
    __ends_with_eof=1
  fi

  # Check that the buffer is large enough to unpack the line
  __buflen=$((__buflen_fd$__fd - 2)) # Minus 2 to account for newline and \0
  __len=${#__temp_buf}
  if [ $__len -gt $__buflen ]; then
    # Free buffer and reallocate a new one double the line size
    __buflen=$((__len * 2))
    _free __ $__buffer
    _malloc __buffer $__buflen
    : $((__buffer_fd$__fd = __buffer))
    : $((__buflen_fd$__fd = __buflen))
  fi
  unpack_line "$__temp_buf" $__buffer $__ends_with_eof
}

read_byte() { # $2: fd
  __fd=$2
  : $((__buffer=__buffer_fd$__fd))
  : $((__cursor=__cursor_fd$__fd))
  # The cursor is at the end of the buffer, we need to read the next line
  if [ $((_$((__buffer + __cursor)))) -eq 0 ]; then
    # Buffer has been read completely, read next line
    refill_buffer $__fd
    __cursor=0 # Reset cursor and reload buffer
    : $((__buffer=__buffer_fd$__fd))
    if [ $((_$((__buffer + __cursor)))) -eq 0 ]; then
      : $(($1 = -1)) # EOF
      return
    fi
  fi
  : $(($1 = _$((__buffer + __cursor))))
  : $((__cursor_fd$__fd = __cursor + 1))  # Increment cursor
}

_fgetc() { # $2: file
  __file=$2
  __fd=$((_$__file))
  read_byte $1 $__fd
}

# Convert a Shell string to a C string
unpack_string() {
  __str="$2"
  _malloc $1 $((${#__str} + 1))
  __ptr=$(($1))
  __us_buf16=
  __us_buf256=
  while [ ! -z "$__str" ] || [ ! -z "$__us_buf256" ] ; do
  if [ -z "$__us_buf256" ]; then
    if [ ${#__str} -ge 256 ]; then
      __temp="${__str#????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????}"
      __us_buf256="${__str%"$__temp"}"
      __str="$__temp"
    else
      __us_buf256="$__str"
      __str=
    fi
  fi
  if [ -z "$__us_buf16" ]; then
    if [ ${#__us_buf256} -ge 16 ]; then
      __temp="${__us_buf256#????????????????}"
      __us_buf16="${__us_buf256%"$__temp"}"
      __us_buf256="$__temp"
    else
      __us_buf16="$__us_buf256"
      __us_buf256=
    fi
  fi
    while [ ! -z "$__us_buf16" ]; do
      case "$__us_buf16" in
        " "*) : $((_$__ptr = 32))  ;;
        "e"*) : $((_$__ptr = 101)) ;;
        "="*) : $((_$__ptr = 61))  ;;
        "t"*) : $((_$__ptr = 116)) ;;
        ";"*) : $((_$__ptr = 59))  ;;
        "i"*) : $((_$__ptr = 105)) ;;
        ")"*) : $((_$__ptr = 41))  ;;
        "("*) : $((_$__ptr = 40))  ;;
        "n"*) : $((_$__ptr = 110)) ;;
        "s"*) : $((_$__ptr = 115)) ;;
        "l"*) : $((_$__ptr = 108)) ;;
        "+"*) : $((_$__ptr = 43))  ;;
        "p"*) : $((_$__ptr = 112)) ;;
        "a"*) : $((_$__ptr = 97))  ;;
        "r"*) : $((_$__ptr = 114)) ;;
        "f"*) : $((_$__ptr = 102)) ;;
        "d"*) : $((_$__ptr = 100)) ;;
        "*"*) : $((_$__ptr = 42))  ;;
        *)
          char_to_int "${__us_buf16%"${__us_buf16#?}"}"
          : $((_$__ptr = __c))
          ;;
      esac
      __us_buf16=${__us_buf16#?}  # Remove the first character
      : $((__ptr += 1))           # Move to the next buffer position
    done
  done
  : $((_$__ptr = 0))
}

make_argv() {
  __argc=$1; shift;
  _malloc __argv $__argc # Allocate enough space for all elements. No need to initialize.
  __argv_ptr=$__argv

  while [ $# -ge 1 ]; do
    unpack_string _$__argv_ptr "$1"
    : $((__argv_ptr += 1))
    shift
  done
}

# Local variables
__=0
__SP=0
let() { # $1: variable name, $2: value (optional) 
  : $((__SP += 1)) $((__$__SP=$1)) # Push
  : $(($1=${2-0}))                 # Init
}
endlet() { # $1: return variable
           # $2...: function local variables
  __ret=$1 # Don't overwrite return value
  : $((__tmp = $__ret))
  while [ $# -ge 2 ]; do
    : $(($2 = __$__SP)) $((__SP -= 1)); # Pop
    shift;
  done
  : $(($__ret=__tmp))   # Restore return value
}

# Setup argc, argv
__argc_for_main=$(($# + 1))
make_argv $__argc_for_main "$0" $@; __argv_for_main=$__argv
__code=0; # Success exit code
_main __code $__argc_for_main $__argv_for_main; exit $__code
