Fixed bug zmixing accents.
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include "dictre.h"
enum
{
SIZESTEP=1000
};
extern struct Def defs[];
extern int ndefs;
extern int dont_touch[];
extern int ndont_touch;
static void more_memory(void **ptr, int size)
{
void *new;
new = realloc(*ptr, size);
*ptr = new;
}
static
char * manage_filter(const char *def, int deflen, int writeto, int readfrom,
int *outlen)
{
int maxfd;
int defptr;
int outptr;
char *out;
int outsize;
int outrest;
int res;
out = 0;
outsize = SIZESTEP;
outptr = 0;
more_memory((void **) &out, outsize);
outrest = SIZESTEP;
/* We need unblocking write for select() */
res = fcntl(writeto, F_SETFL, O_NONBLOCK);
if (res == -1)
{
perror("Error setting nonblock to writeto");
exit(-1);
}
maxfd = writeto;
if (readfrom > maxfd)
maxfd = readfrom;
defptr = 0;
do
{
fd_set writeset, readset;
FD_ZERO(&writeset);
FD_ZERO(&readset);
if (defptr < deflen)
FD_SET(writeto, &writeset);
FD_SET(readfrom, &readset);
select(maxfd+1, &readset, &writeset, 0, 0);
if (FD_ISSET(readfrom, &readset))
{
int res;
res = read(readfrom, out + outptr, outrest);
if (res == 0)
{
close(readfrom);
break;
}
outrest -= res;
outptr += res;
if (outrest == 0)
{
outrest = SIZESTEP;
outsize += SIZESTEP;
more_memory((void **) &out, outsize);
}
}
if (FD_ISSET(writeto, &writeset))
{
int res;
res = write(writeto, def+defptr, deflen - defptr);
defptr += res;
if (defptr >= deflen)
close(writeto);
}
} while(1);
/*
{
int i;
printf("In : ");
for(i=0; i < deflen; ++i)
putchar(def[i]);
printf("\nOut: ");
for(i=0; i < outptr; ++i)
putchar(out[i]);
putchar('\n');
}
*/
if (defptr < deflen)
{
fprintf(stderr, "Error in filter! not all written.\n");
exit(-1);
}
/* Give away memory don't needed */
more_memory((void **) &out, outptr);
*outlen = outptr;
return out;
}
static char * filter(char *def, int deflen, const char *filter_par, int *outlen)
{
int write_pipe[2];
int read_pipe[2];
int pid;
int res;
int status;
char *out;
pipe(write_pipe);
pipe(read_pipe);
pid = fork();
switch(pid)
{
case 0: /* child */
close(0);
dup(write_pipe[0]);
close(write_pipe[0]);
close(write_pipe[1]);
close(1);
dup(read_pipe[1]);
close(read_pipe[1]);
close(read_pipe[0]);
execl(filter_par, filter_par, 0);
perror("execlp");
exit(-1);
break;
case -1:
perror("fork");
exit(-1);
break;
default: /* parent */
close(write_pipe[0]);
close(read_pipe[1]);
break;
}
/* parent */
out = manage_filter(def, deflen, write_pipe[1], read_pipe[0], outlen);
res = wait(&status);
if (res != pid || WEXITSTATUS(status) != 0)
{
fprintf(stderr, "Error filtering: pid=%i status=%i",
pid, WEXITSTATUS(status));
exit(-1);
}
return out;
}
static int in_dont_touch(int n)
{
int i;
for(i =0; i < ndont_touch; ++i)
{
if (n == dont_touch[i])
{
return 1;
}
}
return 0;
}
void filter_all(const char *filter_par)
{
int i;
static int dispndefs = 0;
static int filtereddefs = 0;
for(i=0; i < ndefs; ++i)
{
char *newdef;
int newdeflen;
if (!in_dont_touch(i))
{
if (defs[i].length > 0)
{
newdef = filter(defs[i].d, defs[i].length,
filter_par, &newdeflen);
defs[i].length = newdeflen;
free(defs[i].d);
defs[i].d = newdef;
}
filtereddefs++; /* Not really all filtered. All but the 00-database* */
dispndefs++;
if (dispndefs >= 1000)
{
dispndefs = 0;
printf("Filtered: %i/%i (%f%%)\n", filtereddefs, ndefs,
(float) filtereddefs / (float) ndefs * 100.);
}
}
}
}