/*
 * © Copyright 1996-2017 ECMWF.
 *
 * This software is licensed under the terms of the Apache Licence Version 2.0
 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 * In applying this licence, ECMWF does not waive the privileges and immunities
 * granted to it by virtue of its status as an intergovernmental organisation nor
 * does it submit to any jurisdiction.
 */

#include "mars_client_config.h"

#include "hash.h"


/* tcp.c */

void socket_buffers(int s);

int writetcp(void* p, void* buf, int len);
int readtcp(void* p, void* buf, int len);

boolean tcp_read_ready(int soc);
boolean is_hostname(const char* host);
void traceroute(struct sockaddr_in* from);
int call_server(const char* host, int port, int retries);
int socket_close(int s);
int socket_file_close(FILE* f);

/* server.c */
struct sockaddr_in* addr_of(int soc);
int tcp_server(int port);
const char* host_of(struct sockaddr_in* from);
int port_of(struct sockaddr_in* from);
void print_address(const char* name, struct sockaddr_in* from);
void server_run(int port, taskproc task, void* data);
int server_mode(int* port, char* address);

/* udp.c */
int readudp(void* p, void* buf, int len);
int writeudp(void* p, void* buf, int len);
int udp_socket(int port);
udpinfo* udp_server(int port);
udpinfo* udp_call(const char* host, int port);
void udp_free(udpinfo* info);

/* service.c */
#if mars_client_HAVE_RPC
err encode_request(const request* r, XDR* x);
request* decode_request(XDR* x);
#endif /* mars_client_HAVE_RPC */
void destroy_service(svc* s);
err svc_connect(svc* s);
svc* create_service(const char* name);
void set_svc_err(svcid* id, err e);
err get_svc_err(svcid* id);
void set_svc_ref(svcid* id, long r);
long get_svc_ref(svcid* id);
const char* get_svc_target(svcid* id);
const char* get_svc_source(svcid* id);
const char* get_svc_msg(svcid* id, int n);
void set_svc_msg(svcid* id, const char* fmt, ...);
err send_drop_info(svc* s, char* target, request* r, long ref);
err send_message(svc* s, request* r);
err send_progress(svcid* id, const char* msg, request* r);
int fork_service(svcid* id);
err send_reply(svcid* id, request* r);
err send_later(svcid* id);
err send_number_reply(svcid* id, double d);
err send_string_reply(svcid* id, char* p);
err call_switchboard(svc* s, request* r);
err call_service(svc* s, const char* target, const request* r, long ref);
request* wait_service(svc* s, char* target, request* r, err* e);
err call_function(svc* s, const char* target, const request* r, long ref);
void keep_alive(svc* s, int alive);
void stop_all(svc* s, const char* p, int code);
void set_maximum(svc* s, int max);
void exit_timeout(svc* s, int timeout);
void add_progress_callback(svc* s, const char* name, svcproc p, void* data);
void add_reply_callback(svc* s, const char* name, svcproc p, void* data);
void add_drop_callback(svc* s, const char* name, svcproc p, void* data);
void add_message_callback(svc* s, const char* name, svcproc p, void* data);
void add_function_callback(svc* s, const char* name, svcproc p, const char* cmt, argdef* args, void* data);
void add_input_callback(svc* s, FILE* f, inputproc p, void* data);
void add_service_callback(svc* s, const char* name, svcproc p, void* data);
boolean service_ready(svc* s);
err re_dispatch(svcid* id, request* r);
err process_service(svc* s);
int service_sync(svc* s);
void service_run(svc* s);
request* pool_fetch(svc* s, const char* name, const char* clss);
void pool_store(svc* s, const char* name, const char* clss, const request* r);
void pool_link(svc* s, const char* name1, const char* name2);
void pool_link_objects(svc* s, request* r);
void recording(svc* s, boolean on);
void support_recording(svc* s);
void record_request(svc* s, char* name, request* r);
void record_function(svc* s, const char* name, argdef* args, va_list list);
void record_line(svc* s, const char* fmt, ...);
void show_help_page(svc* s, const char* page, char* topic);
void show_help_text(svc* s, const char* page, const char* topic, const char* fmt, ...);
void show_help_file(svc* s, const char* page, const char* topic, const char* file);
request* get_preferences(svc* s, const char* name);
void set_preferences(svc* s, request* r, const char* name);

/* queue.c */
#if mars_client_HAVE_RPC
err encode_netblk(XDR* x, netblk* blk);
err decode_netblk(XDR* x, netblk* blk);
void free_netblk(netblk* blk);
#endif
err qmonitor(char* fmt, ...);
err qenter(request* r);
err qleave(void);
err qslave(int port);
err qsync(void);
err qflush(int code);

/* request.c */
void str2range(const char* l, stepRange* r);
void patch_steprange(request* r);
boolean eq_range(const char* l, const char* r);
void paramtable(const char* p, long* param, long* table, boolean paramIdMode);
boolean eq_param(const char* l, const char* r);
boolean eq_string(const char* l, const char* r);
boolean eq_integer(const char* l, const char* r);
boolean eq_real(const char* l, const char* r);
boolean eq_coord(const char* l, const char* r);
boolean eq_null(const char* l, const char* r);
boolean eq_date(const char* l, const char* r);
boolean eq_time(const char* l, const char* r);
boolean eq_default(const char* l, const char* r);
char** mars_order(void);
int mars_order_count(void);
namecmp compare_parameters(const char* name);
boolean parsetime(const char* name, int* h, int* m, int* s);
boolean parsedate(const char* name, long* julian, long* second, boolean* isjul);
boolean isdate(const char* name);
boolean istime(const char* name);
boolean is_integer(const char* name);
boolean is_number(const char* name);
boolean isrange(const char* name);
long mars_julian_to_date(long jdate, boolean century);
long today(void);
long mars_date_to_julian(long ddate);
void check_for_to_by_list(parameter* p);
long get_julian_from_request(const request* req, int i);
boolean fetch(const request* r);
boolean observation(const request* r);
boolean image(const request* r);
boolean simulated_image(const request* r);
boolean gridded_observations(const request* r);
boolean feedback(const request* r);
boolean bias(const request* r);
boolean track(const request* r);
boolean is_bufr(const request* r);
boolean is_odb(const request* r);
boolean is_ocean_netcdf(const request* r);
boolean is_grib(const request* r);
boolean wave2d(const request* r);
parameter* find_parameter(const request* r, const char* parname);
parameter* find_case_parameter(const request* r, const char* parname);
boolean value_exist(const request* r, const char* param, const char* val);
int count_values(const request* r, const char* parname);
const char* get_value(const request* r, const char* parname, int nth);
const char* case_get_param(const request* r, const char* parname);
const char* case_get_value(const request* r, const char* parname, int nth);
int case_count_values(const request* r, const char* parname, int nth);
const char* get_operator(const request* r, const char* parname, int nth);
void unset_value(request* r, const char* parname);
void set_value(request* r, const char* parname, const char* fmt, ...);
void set_value_int(request* r, const char* p, long64 v);
void add_value_int(request* r, const char* p, long64 v);
void set_list(request* r, const char* parname, const char* plist);
void add_unique_value(request* r, const char* parname, const char* fmt, ...);
void add_ordered_value(request* r, const char* parname, const char* fmt, ...);
void add_unique_ordered_value(request* r, const char* parname, const char* fmt, ...);
void add_value(request* r, const char* parname, const char* fmt, ...);
void set_value_long64(request* r, const char* parname, long64 l);
void add_value_long64(request* r, const char* parname, long64 l);
const char* request_verb(const request* r);
void values_loop(const request* r, int count, char* parnames[], loopproc callback, void* data);
request* new_request(char* name, parameter* p);
request* empty_request(const char* name);
parameter* new_parameter(char* name, value* v);
value* new_value(char* name);
value* new_expansion(value* val);
value* new_reference(const char* refname, char* name);
void save_one_request(FILE* f, const request* r);
void save_all_requests(FILE* f, const request* r);
void print_one_request(const request* r);
void print_all_requests(const request* r);
const char* copy_stdin_to_tmpfile();
const char* save_request_file_to_log(const char* fname);
request* read_request_file(const char* fname);
request* unwind_one_request(const request* r);
request* custom_unwind_one_request(const request* r, int cnt, char* names[]);
void names_loop(const request* r, loopproc proc, void* data);
boolean all_is_used(const request* r);
int count_fields(request* r);
int count_fields_in_request(request* r);
int reqcmp(const request* a, const request* b, boolean verbose);
int field_order(const request* r, const request* u);
void valcpy(request* a, request* b, char* aname, char* bname);
void reqcpy(request* a, const request* b);
void reqmerge(request* a, const request* b);
void unset_param_value(request* r, const char* param, const char* par_val);
request* string2request(const char* p);
void value2string(value* r, char* buf);
void parameter2string(parameter* r, char* buf);
char* request2string(const request* r);
request* mars_language(void);
rule* mars_rules(void);
request* build_mars_request(request* r);
request* read_mars_request(const char* fname);
err handle_default(request* r, void* data);
void add_subrequest(request* r, const char* name, const request* s);
void set_subrequest(request* r, const char* name, const request* s);
request* get_subrequest(const request* r, const char* name, int n);
void notify_missing_field(const request* r, const char* name);
void sort_request(const request* r, int count, char* names[], char* vals[], void* data);
int count_requests(const request* r);
void reqcpy_no_underscores(request* a, const request* b);

/* expand.c */
void free_one_value(value* p);
void free_all_values(value* p);
void free_one_parameter(parameter* p);
void free_all_parameters(parameter* p);
void free_one_request(request* r);
void free_all_requests(request* p);
value* clone_one_value(const value* p);
value* clone_all_values(const value* p);
parameter* clone_one_parameter(const parameter* p);
parameter* clone_all_parameters(const parameter* p);
request* clone_one_request(const request* r);
request* clone_all_requests(const request* p);
void update_step_list(int p, int n, int by, value* v);
void check_for_date(parameter* p, value* r);
void check_for_time(parameter* p, value* r);
request* read_language_file(const char* name);
long expand_flags(long flags);
request* expand_all_requests(request* lang, rule* test, const request* r);
void reset_language(request* lang);
request* closest_verb(request* lang, const char* name);
parameter* closest_parameter(request* lang, const char* name);
void loopuk_language(request* lang, const char* v, const char* p, lookupproc c, void* d);
request* trim_all_requests(request* lang, request* r);
request* expand_mars_request(const request* r);
request* mars_language_from_request(const request* r);
void copy_to_ibm_values(request* r, const char* name);
void move_to_ibm_values(request* source, request* dest, const char* name);

/* calc.c */
func* mars_functions(void);
void print_math(math* m);
math* clone_math(math* m);
math* compmath(const char* formula);
void free_math(math* m);
err calculate(math* c, const char* f, void* data);
err handle_compute(request* r, void* data);

/* hidden.c */
request* un_first_guess(const request* r);
request* un_first_guess_all(const request* r);
void ensemble_to_number(request* r);
err add_hidden_parameters(request* r);
void patch_ranges(request* r);

/* environ.c */
void add_groups(const char* u, request* r);
boolean user_in_ABC_account(const char* user, const char* account, const request* env);
request* get_environ(void);
void set_environ(request* e);
void new_user(const char* u);

/* check.c */
void print_conditions(condition* c);
boolean old_expver_func(request* r, char* n, char* a);
boolean call_func(request* c, char* f, char* a);
boolean condition_check(request* c, condition* t);
rule* read_check_file(const char* fname);
void print_actions(action* a);
void print_rules(rule* r);
boolean doaction(rule* c, request* r, action* a);
boolean check_one_request(rule* c, request* r);
rule* new_rule(condition* c, action* a);
condition* new_condition(testop op, condition* l, condition* r);
action* new_action(actop op, void* parm);
condition* clone_condition(condition* c);
void free_action(action* a);
void free_condition(condition* c);
void free_rule(rule* r);

/* hypercube.c */
int axisindex(const char* name);
namecmp comparator(const char* name);
void print_hypercube_index(const hypercube* h);
int cube_order(const hypercube* h, const request* r);
int _cube_position(const hypercube* h, const request* r, boolean remove_holes);
boolean cube_contains(const hypercube* h, const request* r);
void cube_indexes(const hypercube* h, request* r, int* indexes, int size);
hypercube* new_hypercube(const request* r);
int add_field_to_hypercube(hypercube* h, request* r);
int remove_field_from_hypercube(hypercube* h, request* r, int n);
void remove_name_from_hypercube(hypercube* h, const char* ignore);
void print_hypercube(const hypercube* h);
void free_hypercube(hypercube* h);
request* _get_cubelet(hypercube* h, int index);
request* get_cubelet(hypercube* h, int index);
request* next_cubelet(hypercube* h, int* from, int* last);
hypercube* merge_cube(const hypercube* a, const hypercube* b, int init, int va, int vb);
hypercube* new_hypercube_from_mars_request(const request* r);
hypercube* new_simple_hypercube_from_mars_request(const request* r);
hypercube* new_hypercube_from_fieldset_cb(fieldset* fs, void (*callback)(request*, void*), void* data);
hypercube* new_hypercube_from_fieldset(fieldset* fs);
hypercube* new_hypercube_from_file(const char* path);
hypercube* add_cube(const hypercube* a, const hypercube* b);
hypercube* remove_cube(const hypercube* a, const hypercube* b);
int hypercube_field_count(const hypercube* a);
int hypercube_cube_size(const hypercube* a);
int hypercube_compare(const hypercube* a, const hypercube* b);

/* memory.c */
int getpagesize(void);
void mem_exit_on_failure(boolean n);
void* re_alloc(void* p, long64 size);
char* new_string(const char* p);
void* get_mem(long64 size);
void* get_mem_clear(long64 size);
void* free_mem(void* x);
void* fast_new(long64 s, mempool* pool);
void* fast_realloc(void* p, long64 s, mempool* pool);
void fast_delete(void* p, mempool* pool);
void* reserve_mem(long64 s);
void release_mem(void* p);
void memory_info(void);
void* fast_new(long64 s, mempool* pool);
void* fast_realloc(void* p, long64 s, mempool* pool);
void fast_delete(void* p, mempool* pool);
void fast_memory_info(const char* title, mempool* pool);
void memory_info(void);
void release_mem(void* p);
int purge_mem(void);
void install_memory_proc(memproc proc, void* data);
void remove_memory_proc(memproc proc, void* data);

/* tools.c */
boolean init_process(void);
long64 proc_mem(void);
long64 proc_mem(void);
long64 proc_mem(void);
double proc_cpu(void);
const char* user(const char* s);
err mars_compress(void* in, void* out, long inlen, long* outlen);
err mars_uncompress(void* in, void* out, long inlen, long* outlen);
const char* no_quotes(const char* in);
int casecompare(const char* a, const char* b);
void start_timer(void);
char* timename(double t);
double stop_timer(char* text);
clock_t timer_cpu(void);
const char* bytename(double bytes);
int mkdirp(const char* path, int mode);
const char* makepath(const char* dname, const char* fname);
const char* mbasename(const char* fname);
const char* mdirname(const char* fname);
int deletefile(const char* name);
int movefile(const char* from, const char* to);
int copylink(const char* from, const char* to);
int copydata(const char* from, const char* to);
int copydir(const char* from, const char* to);
int mars_copyfile(const char* from, const char* to);
const char* relpath(const char* from, const char* to);
void dumpenv(void);
int faccess(const char* fname, int flags);
const char* lowcase(const char* p);
const char* upcase(const char* p);
void print_environment(FILE* f);
FILE* mail_open(const char* to, char* fmt, ...);
void notify_user(const char* what, const request* r);
FILE* mail_once(const char* mark, const char* to, char* fmt, ...);
void mail_msg(FILE* f, char* fmt, ...);
void mail_request(FILE* f, const char* msg, const request* r);
void mail_close(FILE* f);
const char* real_name(const char* fname);
void nfs_lookup(const char* fname, char* host, char* path);
boolean if_check(const char* host);
boolean if_check(const char* p);
void check_nfs_target(const char* path);
long grib_length(const char* buffer, long length);
void mars_grib_api_init(void);
void mars_fdb5_init(int* argc, char** argv);
void mars_eckit_init(int* argc, char** argv);
long _readany(FILE* f, char* b, long* l);
long _readgrib(FILE* f, char* b, long* l);
long _readbufr(FILE* f, char* b, long* l);
void touch(const char* path);
time_t age(const char* path);
long preferred_IO_blocksize(const char* path, long base);
double round_decimal(double f);
long64 atoll(const char* str);
void print_memory_usage(char* s);

/* list.c */
boolean in_list(marslist* l, const char* name, void* data);
void add_to_list(marslist** l, const char* name, void* data);

/* timer.c */
timer* get_timer(const char* name, const char* statname, boolean elapsed);
int timer_start(timer* t);
int timer_stop(timer* t, long64 total);
double timer_value(timer* t);
void timer_print_to_file(timer* t, FILE* f);
void timer_print(timer* t);
void timer_partial_rate(timer* t, double start, long64 total);
void print_all_timers(void);
void reset_all_timers(void);
int timed_fread(char* buffer, int n, int length, FILE* f, timer* t);
int timed_wind_next(wind* w, FILE* f, char* buffer, long* length, timer* t);
int timed_fwrite(char* buffer, int n, int length, FILE* f, timer* t);
int timed_fclose(FILE* f, timer* t);
int timed_writetcp(void* data, char* buffer, int n, timer* t);
int timed_readtcp(void* data, char* buffer, int n, timer* t);
int timed_readany(FILE* f, char* buffer, long* length, timer* t);

/* logfile.c */
void marsdebug(boolean on);
FILE* marslogfile(FILE* f);
void mars_grib_api_log(const grib_context* c, int level, const char* msg);
void marslog(int level, const char* fmt, ...);
void log_errors(void);
void install_exit_proc(exitproc p, void* data);
void remove_exit_proc(exitproc p, void* data);
void _marsexit(void);
void marsexit(int code);
void dumpmem(void);

/* options.c */
void get_options(const char* clss, const char* name, void* addr, int count, option opts[]);
char* progname(void);
void trap_all_signals(void);
void marsinit(int* argc, char** argv, void* addr, int count, option opts[]);
const char* config_file(const char* p);

/* files.c */
char* marstmp(void);

/* stream.c */
void stream_write_char(mstream* s, char c);
void stream_write_uchar(mstream* s, unsigned char c);
void stream_write_int(mstream* s, int c);
void stream_write_uint(mstream* s, unsigned int c);
void stream_write_long(mstream* s, long c);
void stream_write_ulong(mstream* s, unsigned long c);
void stream_write_longlong(mstream* s, long64 n);
void stream_write_ulonglong(mstream* s, ulong64 n);
void stream_write_double(mstream* s, double x);
void stream_write_short(mstream* s, short c);
void stream_write_ushort(mstream* s, unsigned short c);
void stream_write_string(mstream* s, const char* p);
void stream_write_blob(mstream* s, const void* d, long len);
void stream_write_start(mstream* s, const char* p);
void stream_write_end(mstream* s);
char stream_read_char(mstream* s);
unsigned char stream_read_uchar(mstream* s);
int stream_read_int(mstream* s);
unsigned int stream_read_uint(mstream* s);
long stream_read_long(mstream* s);
unsigned long stream_read_ulong(mstream* s);
short stream_read_short(mstream* s);
unsigned short stream_read_ushort(mstream* s);
const char* stream_read_string(mstream* s);
const void* stream_read_blob(mstream* s, long* size);
long64 stream_read_longlong(mstream* s);
ulong64 stream_read_ulonglong(mstream* s);
const char* stream_read_start(mstream* s);
void stream_read_end(mstream* s);
void make_socket_stream(mstream* s, int* soc);
void make_file_stream(mstream* s, FILE* f);

/* cos.c */
COSFILE* cos_open(const char* fname);
int cos_read(COSFILE* cf, char* buf, long* len);
int cos_write(COSFILE* cf, char* buf, long len);
int cos_close(COSFILE* cf);
void COSOPEN(COSFILE** filedesc, char* fname, long* e);
void COSCLOSE(COSFILE** filedesc, long* e);
void COSREAD(COSFILE** filedesc, char* buffer, long* len, long* e);

/* time.c */
datetime date_time_2_datetime(long julian_date, long hour, long min, long sec);
datetime key_2_datetime(const packed_key* keyptr);
void init_time_interval(time_interval* t, datetime begin, long range);

/* guess.c */
char* guess_class(const char* file);

/* statistics.c */
err locked_write(const char* fname, char* str, long len);
void init_statistics(const request* r, const request* e);
void log_statistics(const char* name, const char* fmt, ...);
void log_statistics_unique(const char* name, const char* fmt, ...);
void flush_statistics(const request* r, const request* env);
void test_statistics(void);

/* udp_statistics.cc */
void send_udp_statistics(const request* stats, const request* env, const request* r);

/* metadata.c */
request* read_request(mstream* s);

/* free.c */
err encode_free_format(void* buffer, long* length, const request* r, const void* blob, long bloblen);
request* decode_free_format_request(void* buffer, long length);
long decode_free_format_blob(void* buffer, long length, void* blob, long max);
err encode_free_format_grib(unsigned char* bin, unsigned char* bout, fortint* length, fortint maxlen, request* r, int marsclass, int type, int stream, char* expver);
err decode_free_format_grib(unsigned char* bin, unsigned char* bout, fortint* length, fortint maxlen, request* r);
err original_grib(char* bin, fortint* length);

/* index.c */
void mars_field_index_add(mars_field_index* idx, const char* name, boolean s_ok, const char* s, boolean l_ok, long l, boolean d_ok, double d);
mars_field_index* mars_field_index_new(off_t offset, long length);
err mars_field_index_send(mars_field_index* idx, mstream* s);
void mars_field_index_free(mars_field_index* idx);
void mars_field_index_print(mars_field_index* idx);

/* api.c */
void ecmwf_api_set_msg_callback(ecmwf_api* api, messageproc msgcb, void* data);
void ecmwf_wait_for_data(ecmwf_api* api, size_t size);
size_t ecmwf_api_transfer_read(ecmwf_api* api, void* ptr, size_t size);
const json_value* _ecmwf_api_call(ecmwf_api* api, const char* method, const char* url, const char* json);
const char* ecmwf_api_must_retry(ecmwf_api* api);
const json_value* ecmwf_api_call(ecmwf_api* api, const char* method, const char* url, const char* json);
ecmwf_api* ecmwf_api_create(const char* url, const char* key, const char* email);
void ecmwf_api_add_message_callback(ecmwf_api* api, void (*cb)(const char*));
void ecmwf_api_destroy(ecmwf_api* api);
int ecmwf_api_in_progress(ecmwf_api* api);
int ecmwf_api_transfer_ready(ecmwf_api* api);
void ecmwf_api_in_wait(ecmwf_api* api);
const char* ecmwf_api_location(ecmwf_api* api);
const char* ecmwf_api_content_type(ecmwf_api* api);
int ecmwf_api_error(ecmwf_api* api);
void ecmwf_api_verbose(ecmwf_api* api, int v);
long long ecmwf_api_transfer_start(ecmwf_api* api, const char* url, typeproc typecb, void* typecb_data);
int ecmwf_api_transfer_end(ecmwf_api* api);

/* json.c */
void json_free(json_value* v);
const char* json_get_string(const json_value* v);
long long json_get_integer(json_value* v);
const char* json_encode_string(const char* s, char* out);
void json_save(const json_value* v, FILE* f);
void json_print(const json_value* v);
void json_dump(const json_value* v);
void json_println(const json_value* v);
json_value* json_new_string(const char* s);
json_value* json_new_array(void);
json_value* json_new_object(void);
void json_object_set_item(json_value* object, const char* key, json_value* value);
void json_array_push_item(json_value* object, json_value* k);
json_value* json_parse_string(const char* str, size_t len);
void json_array_each(json_value* a, void (*proc)(int, json_value*, void*), void* data);
void json_object_each(json_value* a, void (*proc)(const char*, json_value*, void*), void* data);
json_value* json_object_find(const json_value* a, const char* key);
json_value* json_read_file(const char* path);

/* base.c */
base_class* base_class_by_name(const char* name);
database* database_of(void* data);
const char* database_name(void* data);
err database_validate(base_class* driver, const char* name, request* r, request* e, int mode);
database* database_open(base_class* driver, const char* name, const request* r, const request* e, int mode);
err database_read(database* b, request* r, void* buffer, long* length);
err database_write(database* b, request* r, void* buffer, long* length);
err database_control(database* b, int code, void* param, int size);
err database_archive(database* b, request* r);
boolean database_check(database* b, request* r);
err database_close(database* b);
void database_admin(base_class* driver);

/* netbase.c */
void basetask(int soc, int count, void* data);

/* nullbase.c */

/* handler.c */
err handle_request(request* r, void* data);
err handle_end(request* r, void* data);

/* nfdbbase.c */
boolean windgust(request* s);
void request_to_fdb(int ref, request* r, int y2k);

/* msbase.c */

/* gribbase.c */

/* filebase.c */

/* dhsbase.c */
int find_long(long* p, int count, long search);

/* flatfilebase.c */

/* target.c */
char* target_open_mode(const char* target);
err send_remote_targets(void);

/* feedtask.c */
void feedtask(int soc, int count, void* data);

/* rdb.c */

/* multibase.c */

/* odbbase.c */

/* apibase.c */
json_value* request2json(const request* r);

/* archive.c */
err feed(database* bout, request* r);
err handle_archive(request* r, void* data);

/* retrieve.c */
boolean enough(request* r, int count);
const request* findbase(const char* name, const request* req);
database* openbase(const request* s, request* r, const char** name, request** cache, int mode);
void mars_task(void);
err handle_retrieve(request* r, void* data);

/* control.c */
err handle_control(request* r, void* data);

/* remove.c */
err handle_remove(request* r, void* data);

/* grib.c */
err handle_to_request(request* r, grib_handle* g, mars_field_index* idx);
err grib_to_request_index(request* r, char* buffer, long length, mars_field_index* idx);
err grib_to_request(request* r, char* buffer, long length);

/* pproc.c */
err ppstyle(const request* r);
err pprotation(const request* r);
err pparea(request* r);
err makeuv(char* vo, char* d, long inlen, char* u, char* v, long* outlen);
long ppestimate(void);
err ppinit(const request* r, postproc* proc);
err ppdone(void);
err ppcount(int* in, int* out);
fieldset* pp_fieldset(const char* file, request* filter);

/* wind.c */
wind* wind_new(request* r, long64* total, boolean active);
void wind_free(wind* w);
boolean is_wind(long param);
err wind_next(wind* w, FILE* f, char* buffer, long* length, timer* t);

/* bufr.c */
unsigned long getbits(unsigned char* p, int skip, int len);
unsigned long key_length(const char* buffer, const packed_key* k);
void set_key_length(packed_key* key, unsigned long keylength);
boolean get_packed_key(char* buffer, packed_key* k);
boolean get_packed_section_1(char* buffer, packed_section_1* section);
int subset_count(char* buffer);
int bufr_sat_id(char* buffer, packed_key* k);
void set_bufr_sat_id(char* buffer, int id, packed_key* k);
boolean replace_key(char* buffer, packed_key* key);
boolean patch_key_date(char* buffer, int y, int m, int d, int H, int M, int S);
boolean patch_key_ident(char* buffer, int ident);
boolean patch_key_length(char* buffer, unsigned int new_value);
boolean shift_packed_key_ident(char* buffer);
void set_bufr_mars_type(request* r, const packed_key* key);
err bufr_to_request(request* r, char* buffer, long length);
boolean verify_bufr_key(const char* buffer, long length, const packed_key* key);
void print_key_date(const packed_key* keyptr, char* s);
void print_key_time(const packed_key* keyptr, char* s);
int build_packed_key(char* buffer, fortint length, packed_key* k);
void print_packed_key(char* buffer, packed_key* k);

/* field.c */
gribfile* new_gribfile(const char* name);
FILE* open_gribfile(gribfile* g, const char* mode);
void close_gribfile(gribfile* g);
void free_gribfile(gribfile* g);
field_request* new_field_request(request* r);
void free_field_request(field_request* g);
void mars_free_field(field* g);
void free_fieldset(fieldset* v);
field* mars_new_field(void);
fieldset* new_fieldset(int n);
field* read_field(gribfile* file, off_t pos, long length);
err add_field(fieldset* v, field* g);
err set_field(fieldset* v, field* g, int pos);
err check_fieldset(fieldset* v, int expect);
field* copy_field(field* gx, boolean copydata);
void copy_missing_vals(field* gc, field* ga, field* gb);
void remove_bitmap(field* gc);
void set_bitmap(field* gc);
fieldset* copy_fieldset(fieldset* x, int count, boolean copydata);
fieldset* merge_fieldsets(fieldset* x, fieldset* y);
fieldset* sub_fieldset(fieldset* v, int from, int to, int step);
int best_packing(fortint current);
void set_field_state(field* g, field_state shape);
field* get_field(fieldset* v, int n, field_state shape);
field* get_nonmissing_field(fieldset* v, field_state shape);
void inform_missing_fieldset(const char* name);
void release_field(field* g);
const void* field_message(field* g, long* s);
err write_field(FILE* f, field* g);
err save_fieldset(fieldset* v);
fieldset* read_fieldset(const char* fname, request* filter);
fieldset* request_to_fieldset(request* r);
request* fieldset_to_request(fieldset* v);
request* fieldset_to_mars_request(fieldset* fs);
request* field_to_request(field* f);

/* variable.c */
err push_scalar(double d);
err push_named_scalar(char* name, double d);
err push_fieldset(fieldset* f);
err push_named_fieldset(char* name, fieldset* f);
err push(variable* v);
variable* pop(void);
variable* stack_top(void);
variable* find_variable(const char* name);
err name_variable(variable* v, char* name);
variable* new_variable(const char* name, fieldset* f, double d);
void free_variable(variable* v);

/* externf.c */
err extern_func(math* p);

/* sh2ll.c */
err write_fieldset(fieldset* v, database* b);
err handle_read(request* r, void* data);
err handle_write(request* r, void* data);

/* account.c */
err ams_validate(request* r, request* e);
err ecmwf_validate(request* r, request* e);
int eccert_validate(request* r, request* e);
err null_validate(request* r, request* e);
err validate_request(request* r, request* e, const char* method);

/* authenticate.c */
boolean handle_restriction(request* req, request* r, request* reply, void* data);
err local_validate_request(request* req, request* env);
void print_user_restrictions(request* env, request* auth);

/* certify.c */
err certify(request* r, request* e, char* data, int length);

/* eccert.c */
char* verify_ecmars_certificate(char* data, int len, char* marsCert, int marsCertLen, eCMarsCertReply* reply);

/* restricted.c */
int restricted(void* p);

/* version.c */
long marsversion(void);
const char* marssourcebranch(void);
long marsgribapi(void);
long marsodbapi(void);

/* schedule.c */
boolean check_dissemination_schedule(request* user, request* env, boolean logstat);

/* netcdf.c */
boolean source_is_netcdf(const request* r);
boolean message_is_netcdf(unsigned char*);
request* netcdf_to_request(const char* path, int merge, mars_field_index* idx, err* e);

/* hdf5.c */
err check_hdf5_superblock(const char* path);

/* nctarget.c */
netcdf_target* netcdf_target_new(const char* path, const char* format, int more_flags);
err netcdf_target_close(netcdf_target* target);
err netcdf_target_add_buffer(netcdf_target* target, const void* message, size_t length);
err netcdf_target_add_file(netcdf_target* target, const char* path);
/*----------*/
netcdf_schema* netcdf_schema_new(const char* path);
void netcdf_schema_delete(netcdf_schema* s);
request* netcdf_schema_to_request(netcdf_schema* s, int merge, mars_field_index* idx, err* e);
