static void stack_destroy(WasmAllocator* allocator) {
  WasmStackAllocator* stack_allocator = (WasmStackAllocator*)allocator;
  /* destroy the free chunks */
  WasmStackAllocatorChunk* chunk = stack_allocator->next_free;
  while (chunk) {
    WasmStackAllocatorChunk* next_free = chunk->next_free;
    wasm_free(stack_allocator->fallback, chunk);
    chunk = next_free;
  }

  /* destroy the used chunks */
  chunk = stack_allocator->last;
  while (chunk) {
    WasmStackAllocatorChunk* prev = chunk->prev;
    wasm_free(stack_allocator->fallback, chunk);
    chunk = prev;
  }
}
int main(int argc, char** argv) {
  WasmResult result;
  WasmStackAllocator stack_allocator;
  WasmAllocator* allocator;

  wasm_init_stdio();
  parse_options(argc, argv);

  if (s_use_libc_allocator) {
    allocator = &g_wasm_libc_allocator;
  } else {
    wasm_init_stack_allocator(&stack_allocator, &g_wasm_libc_allocator);
    allocator = &stack_allocator.allocator;
  }

  void* data;
  size_t size;
  result = wasm_read_file(allocator, s_infile, &data, &size);
  if (WASM_SUCCEEDED(result)) {
    WasmModule module;
    WASM_ZERO_MEMORY(module);
    result = wasm_read_binary_ast(allocator, data, size, &s_read_binary_options,
                                  &s_error_handler, &module);
    if (WASM_SUCCEEDED(result)) {
      if (s_generate_names)
        result = wasm_generate_names(allocator, &module);

      if (WASM_SUCCEEDED(result))
        result = wasm_apply_names(allocator, &module);

      if (WASM_SUCCEEDED(result)) {
        WasmFileWriter file_writer;
        if (s_outfile) {
          result = wasm_init_file_writer(&file_writer, s_outfile);
        } else {
          wasm_init_file_writer_existing(&file_writer, stdout);
        }

        if (WASM_SUCCEEDED(result)) {
          result = wasm_write_ast(allocator, &file_writer.base, &module);
          wasm_close_file_writer(&file_writer);
        }
      }
    }

    if (s_use_libc_allocator)
      wasm_destroy_module(allocator, &module);
    wasm_free(allocator, data);
    wasm_print_allocator_stats(allocator);
    wasm_destroy_allocator(allocator);
  }
  return result;
}
static WasmResult run_squirrel_file(WasmAllocator* allocator,
                                    HSQUIRRELVM v,
                                    const char* filename) {
  WasmResult result;
  void* data;
  size_t size;
  result = wasm_read_file(allocator, filename, &data, &size);
  if (WASM_SUCCEEDED(result)) {
    if (SQ_SUCCEEDED(sq_compilebuffer(v, data, size, filename, RAISE_ERROR))) {
      sq_pushroottable(v);
      if (SQ_SUCCEEDED(sq_call(v, 1, WITHOUT_RETVAL, RAISE_ERROR))) {
        /* do some other stuff... */
        result = WASM_OK;
      } else {
        result = WASM_ERROR;
      }
    } else {
      result = WASM_ERROR;
    }
    wasm_free(allocator, data);
  }
  return result;
}
void wasm_destroy_string_slice(WasmAllocator* allocator, WasmStringSlice* str) {
  wasm_free(allocator, (void*)str->start);
}
void wasm_destroy_output_buffer(WasmOutputBuffer* buf) {
  if (buf->allocator)
    wasm_free(buf->allocator, buf->start);
}
void wasm_destroy_ast_lexer(WasmAstLexer* lexer) {
  if (lexer->source.type == WASM_LEXER_SOURCE_TYPE_FILE && lexer->source.file)
    fclose(lexer->source.file);
  wasm_free(lexer->allocator, lexer->buffer);
  wasm_free(lexer->allocator, lexer);
}