#line 1026 "../../src/builtin/snarf.m4"
/* -*- buffer-read-only: t -*- vi: set ro:
   THIS FILE IS GENERATED AUTOMATICALLY.  PLEASE DO NOT EDIT.
*/
#line 1026
#ifdef HAVE_CONFIG_H
#line 1026
# include <config.h>
#line 1026
#endif
#line 1026
#include <sys/types.h>
#line 1026

#line 1026
#include "mailfromd.h"
#line 1026
#include "prog.h"
#line 1026
#include "builtin.h"
#line 1026

#line 1026

#line 1066 "../../src/builtin/snarf.m4"

/* End of snarf.m4 */
#line 1 "filter.bi"
/* This file is part of Mailfromd.             -*- c -*-
   Copyright (C) 2008-2025 Sergey Poznyakoff

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */



#include "msg.h"

struct error_closure {
	size_t msglen;
	char *msgstr;
};

#define ERROR_CLOSURE_INITIALIZER { 0, NULL }

static void
errfunc(int ec, char const *errmsg, char const *input, int start, int end,
	void *closure)
{
	struct error_closure *cl = closure;
	mu_asnprintf(&cl->msgstr, &cl->msglen, "%s, near %.*s",
		     errmsg, end - start, input + start);
}

void
msgstr_cleanup(void *ptr)
{
	free(ptr);
}


void
#line 44
bi_filter_string(eval_environ_t env)
#line 44

#line 44

#line 44 "filter.bi"
{
#line 44
	
#line 44

#line 44
        char * MFL_DATASEG input;
#line 44
        char * MFL_DATASEG filter_pipe;
#line 44
        
#line 44

#line 44
        get_string_arg(env, 0, &input);
#line 44
        get_string_arg(env, 1, &filter_pipe);
#line 44
        
#line 44
        adjust_stack(env, 2);
#line 44

#line 44

#line 44
	if (builtin_module_trace(BUILTIN_IDX_filter))
#line 44
		prog_trace(env, "filter_string %s %s",input, filter_pipe);;
#line 44

{
	int rc;
	mu_stream_t in, temp;
	struct error_closure err = ERROR_CLOSURE_INITIALIZER;
	size_t buflen;
	char *buf;
	size_t n;
	
	rc = mu_static_memory_stream_create(&in, input, strlen(input));
		if (!(rc == 0))
#line 54
		(
#line 54
	env_throw_bi(env, mfe_failure, "filter_string", "mu_static_memory_stream_create: %s",mu_strerror(rc))
#line 54
)
#line 57
;

	env_function_cleanup_add(env, CLEANUP_ALWAYS, err.msgstr, msgstr_cleanup);
	
	rc = mfl_filter_pipe_create(&temp, in,
				    MU_FILTER_ENCODE,
				    MU_STREAM_READ,
				    filter_pipe,
				    NULL,
				    errfunc,
				    &err);
	mu_stream_unref(in);
	if (rc == 0) {
		in = temp;
	} else {
		(
#line 72
	env_throw_bi(env, mfe_failure, "filter_string", "%s",err.msgstr)
#line 72
);
	}
	env_function_cleanup_add(env, CLEANUP_ALWAYS, in, _builtin_stream_cleanup);

	buflen = strlen(input);
	buf = mf_c_val(heap_tempspace(env, buflen), ptr);
	heap_obstack_begin(env);
	
	while ((rc = mu_stream_read(in, buf, buflen, &n)) == 0 && n > 0) {
		heap_obstack_grow(env, buf, n);
	}

		if (!(rc == 0))
#line 84
		(
#line 84
	env_throw_bi(env, mfe_failure, "filter_string", "mu_stream_read: %s",mu_strerror(rc))
#line 84
)
#line 87
;

	do { char __c = 0; heap_obstack_grow(env, &__c, 1); } while(0);
	
#line 90
do {
#line 90
  push(env, (STKVAL) (heap_obstack_finish(env)));
#line 90
  goto endlab;
#line 90
} while (0);
}
endlab:
#line 92
        env_function_cleanup_flush(env, CLEANUP_RETURN);
#line 92
	return;
#line 92
}

void
#line 94
bi_filter_fd(eval_environ_t env)
#line 94

#line 94

#line 94 "filter.bi"
{
#line 94
	
#line 94

#line 94
        long  src_fd;
#line 94
        long  dst_fd;
#line 94
        char *  filter_pipe;
#line 94
        
#line 94

#line 94
        get_numeric_arg(env, 0, &src_fd);
#line 94
        get_numeric_arg(env, 1, &dst_fd);
#line 94
        get_string_arg(env, 2, &filter_pipe);
#line 94
        
#line 94
        adjust_stack(env, 3);
#line 94

#line 94

#line 94
	if (builtin_module_trace(BUILTIN_IDX_filter))
#line 94
		prog_trace(env, "filter_fd %lu %lu %s",src_fd, dst_fd, filter_pipe);;
#line 94

{
	int rc;
	mu_stream_t src, dst, flt;
	int yes = 1;
	struct error_closure err = ERROR_CLOSURE_INITIALIZER;
	
	rc = mu_fd_stream_create(&dst, NULL, _bi_io_fd(env, dst_fd, 1),
				 MU_STREAM_WRITE);
		if (!(rc == 0))
#line 103
		(
#line 103
	env_throw_bi(env, mfe_failure, "filter_fd", "mu_fd_stream_create(dest): %s",mu_strerror(rc))
#line 103
)
#line 106
;
	mu_stream_ioctl(dst, MU_IOCTL_FD, MU_IOCTL_FD_SET_BORROW, &yes);
	env_function_cleanup_add(env, CLEANUP_ALWAYS, dst, _builtin_stream_cleanup);
	
	rc = mu_fd_stream_create(&src, NULL, _bi_io_fd(env, src_fd, 0),
				 MU_STREAM_READ);
		if (!(rc == 0))
#line 112
		(
#line 112
	env_throw_bi(env, mfe_failure, "filter_fd", "mu_fd_stream_create(source): %s",mu_strerror(rc))
#line 112
)
#line 115
;
	mu_stream_ioctl(dst, MU_IOCTL_FD, MU_IOCTL_FD_SET_BORROW, &yes);

	env_function_cleanup_add(env, CLEANUP_ALWAYS, err.msgstr, msgstr_cleanup);
	rc = mfl_filter_pipe_create(&flt, src,
				    MU_FILTER_ENCODE,
				    MU_STREAM_READ,
				    filter_pipe,
				    NULL,
				    errfunc,
				    &err);
	mu_stream_unref(src);
	if (rc == 0) {
		src = flt;
	} else {
		(
#line 130
	env_throw_bi(env, mfe_failure, "filter_fd", "%s",err.msgstr)
#line 130
);
	}
	env_function_cleanup_add(env, CLEANUP_ALWAYS, src, _builtin_stream_cleanup);

	rc = mu_stream_copy(dst, src, 0, NULL);
		if (!(rc == 0))
#line 135
		(
#line 135
	env_throw_bi(env, mfe_failure, "filter_fd", "mu_stream_copy: %s",mu_strerror(rc))
#line 135
)
#line 138
;
}

#line 140
        env_function_cleanup_flush(env, CLEANUP_RETURN);
#line 140
	return;
#line 140
}
#line 1026 "../../src/builtin/snarf.m4"

#line 1026

#line 1026

#line 1026
void
#line 1026
filter_init_builtin(void)
#line 1026
{
#line 1026
	
#line 1026
	#line 44 "filter.bi"
va_builtin_install_ex("filter_string", bi_filter_string, 0, dtype_string, 2, 0, 0|0, dtype_string, dtype_string);
#line 94 "filter.bi"
va_builtin_install_ex("filter_fd", bi_filter_fd, 0, dtype_unspecified, 3, 0, 0|0, dtype_number, dtype_number, dtype_string);

#line 1026 "../../src/builtin/snarf.m4"
	
#line 1026
}
#line 1026 "../../src/builtin/snarf.m4"

