/*
 * This file is part of Beastie <https://purl.org/nxg/dist/beastie>
 * SPDX-FileCopyrightText: 2023 Norman Gray <https://nxg.me.uk>
 * SPDX-License-Identifier: BSD-2-Clause
 */

#ifndef UTIL_H
#define UTIL_H 1

#include <stdlib.h>
#include <stdarg.h>

#include "beastie.h"

/* exported to library users, but not documented */
void error_exit(const char* fmt, ...);
s7_pointer prepare_beastie_error(s7_scheme* sc, const char* fmt, ...);
s7_pointer return_beastie_error(s7_scheme* sc, const char* fmt, ...);

s7_pointer scheme_name_to_value(const char* sym);
s7_pointer scheme_eval(const char* fn, ...);
s7_pointer scheme_eval_with_let(s7_pointer let, const char* fnname, ...);
s7_pointer scheme_make_list(s7_pointer v1, ...);
s7_pointer scheme_symbol_value_ci(s7_pointer s);
s7_pointer scheme_trimmed_string(const char* s);
s7_pointer scheme_trimmed_string_with_length(const char* s, int l);

#if 0
// implemented, but unused
const char* scheme_read_expr_from_stdin(void);
const char* scheme_read_expr(int (*read_char)(void));
#endif

void s7w(const char* before, s7_pointer s, const char* after);
void s7w4(const char* before, s7_pointer s, const char* after, int stderr_p);
void scheme_printf(const char* fmt, ...);

struct append_buffer {
    size_t alloc;
    size_t len;
    char* buf;
};
typedef struct append_buffer* StringBuilder;
StringBuilder make_stringbuilder();
StringBuilder make_stringbuilder_with_size(size_t initial_alloc);
//StringBuilder make_stringbuilder_with_content(const char*, size_t);
StringBuilder stringbuilder_append_c(StringBuilder, char);
StringBuilder stringbuilder_append_s(StringBuilder, const char*);
StringBuilder stringbuilder_append_sn(StringBuilder, const char*, size_t);
StringBuilder stringbuilder_append_sb(StringBuilder, StringBuilder);
StringBuilder stringbuilder_printf(StringBuilder buf, const char* fmt, ...);
StringBuilder stringbuilder_terminate(StringBuilder buf);
StringBuilder stringbuilder_reset(StringBuilder buf);
void stringbuilder_free(StringBuilder buf);

// flags for scan_to_matching_char
// (this has shrunk back to being a very short list!):
//
// do we include the matching end-character?
#define SCAN_INCLUDE_LAST 1
s7_pointer scan_to_matching_char(int (*in)(void*), // read a character from a scanner
                                 void* scanner,    // the scanner
                                 int startline,    // the start line, for error reporting
                                 const char* startwith, // to be initially added to the result
                                 const char endwith,
                                 unsigned int flags);
int expand_accented_string(const char* s, size_t slen, char level1only, StringBuilder sb);

#endif /* UTIL_H */
