sbase/paste.c
FRIGN 73577f10a0 Scrap chartorunearr(), introducing utftorunestr()
Interface and function as proposed by cls.

The reasoning behind this function is that cls expressed his
interest to keep memory allocation out of libutf, which is a
very good motive.
This simplifies the function a lot and should also increase the
speed a bit, but the most important factor here is that there's
no malloc anywhere in libutf, making it a lot smaller and more
robust with a smaller attack-surface.

Look at the paste(1) and tr(1) changes for an idiomatic way to
allocate the right amount of space for the Rune-array.
2015-02-11 21:32:09 +01:00

139 lines
2.3 KiB
C

/* See LICENSE file for copyright and license details. */
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "utf.h"
#include "util.h"
struct fdescr {
FILE *fp;
const char *name;
};
static void
sequential(struct fdescr *dsc, int fdescrlen, Rune *delim, size_t delimlen)
{
Rune c, last;
size_t i, d;
for (i = 0; i < fdescrlen; i++) {
d = 0;
last = 0;
while (efgetrune(&c, dsc[i].fp, dsc[i].name)) {
if (last == '\n') {
if (delim[d] != '\0')
efputrune(&delim[d], stdout, "<stdout>");
d = (d + 1) % delimlen;
}
if (c != '\n')
efputrune(&c, stdout, "<stdout>");
last = c;
}
if (last == '\n')
efputrune(&last, stdout, "<stdout>");
}
}
static void
parallel(struct fdescr *dsc, int fdescrlen, Rune *delim, size_t delimlen)
{
Rune c, d;
size_t i, m;
ssize_t last;
nextline:
last = -1;
for (i = 0; i < fdescrlen; i++) {
d = delim[i % delimlen];
c = 0;
for (; efgetrune(&c, dsc[i].fp, dsc[i].name) ;) {
for (m = last + 1; m < i; m++)
efputrune(&(delim[m % delimlen]), stdout, "<stdout>");
last = i;
if (c == '\n') {
if (i != fdescrlen - 1)
c = d;
efputrune(&c, stdout, "<stdout>");
break;
}
efputrune(&c, stdout, "<stdout>");
}
if (c == 0 && last != -1) {
if (i == fdescrlen - 1)
putchar('\n');
else
efputrune(&d, stdout, "<stdout>");
last++;
}
}
if (last != -1)
goto nextline;
}
static void
usage(void)
{
eprintf("usage: %s [-s] [-d list] file ...\n", argv0);
}
int
main(int argc, char *argv[])
{
struct fdescr *dsc;
Rune *delim;
size_t i, len;
int seq = 0;
char *adelim = "\t";
ARGBEGIN {
case 's':
seq = 1;
break;
case 'd':
adelim = EARGF(usage());
break;
default:
usage();
} ARGEND;
if (argc == 0)
usage();
/* populate delimiters */
unescape(adelim);
delim = emalloc((utflen(adelim) + 1) * sizeof(*delim));
len = utftorunestr(adelim, delim);
/* populate file list */
dsc = emalloc(argc * sizeof(*dsc));
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "-") == 0)
dsc[i].fp = stdin;
else
dsc[i].fp = fopen(argv[i], "r");
if (!dsc[i].fp)
eprintf("fopen %s:", argv[i]);
dsc[i].name = argv[i];
}
if (seq)
sequential(dsc, argc, delim, len);
else
parallel(dsc, argc, delim, len);
for (i = 0; i < argc; i++)
fclose(dsc[i].fp);
return 0;
}