187 lines
3.7 KiB
C
187 lines
3.7 KiB
C
#include "compat.h"
|
||
#include "transliteration.h"
|
||
#include "transcription.h"
|
||
#include "velthuis.h"
|
||
#include "config.h"
|
||
|
||
#define PROGNAME "iast"
|
||
|
||
#define FLAG_REVERSE 1 << 0
|
||
#define FLAG_ENCODE 1 << 1
|
||
#define FLAG_CZECH 1 << 2
|
||
|
||
static const char *usage_str =
|
||
PROGNAME ", a helper for Sanskrit transliteration.\n"
|
||
"\n"
|
||
"usage:\n"
|
||
" " PROGNAME " [flags and text arguments in any order]\n"
|
||
"\n"
|
||
"options:\n"
|
||
" -h shows this help and exits\n"
|
||
" -v shows version number and exits\n"
|
||
" -f specifies file for conversion (‘-’ means standard input)\n"
|
||
" -r reverse transliteration (from Latin to Devanagari)\n"
|
||
" -e convert Velthuis scheme text to IAST representation\n"
|
||
" -c transcript Devanagari to Czech language\n"
|
||
"\n"
|
||
" By default, ‘" PROGNAME "’ takes all input arguments written in Devanagari\n"
|
||
" and transliterates them to the IAST version.\n"
|
||
"\n"
|
||
" When the flag ‘-e’ is set up, the program converts purely ASCII-encoded\n"
|
||
" strings into the special characters of the IAST alphabet. For example, it\n"
|
||
" converts ‘sam.skr.tam’ to ‘saṃskṛtam’ or ‘s,a-stram’ to ‘śāstram’.\n";
|
||
|
||
static void print_usage()
|
||
{
|
||
fprintf(stdout, "%s\n", usage_str);
|
||
}
|
||
|
||
static void print_version()
|
||
{
|
||
fprintf(stdout, PROGNAME " v" PACKAGE_VERSION "\n");
|
||
}
|
||
|
||
static void error(const char *msg, ...)
|
||
{
|
||
va_list params;
|
||
char buf[256];
|
||
|
||
va_start(params, msg);
|
||
vsnprintf(buf, sizeof(buf), msg, params);
|
||
fprintf(stderr, "[" PROGNAME "] error: %s\n", buf);
|
||
va_end(params);
|
||
}
|
||
|
||
static char *process_input(const char *input, unsigned int flags)
|
||
{
|
||
if (flags & FLAG_ENCODE)
|
||
return encode_velthuis_to_iast_punctation(input);
|
||
|
||
if (flags & FLAG_REVERSE)
|
||
return transliterate_latin_to_devanagari(input);
|
||
|
||
if (flags & FLAG_CZECH)
|
||
return transcript_devanagari_to_czech(input);
|
||
|
||
return transliterate_devanagari_to_latin(input);
|
||
}
|
||
|
||
#define CHUNKSIZE 1024
|
||
static int read_fd(char **out, int fd)
|
||
{
|
||
int n, alloc = 0, space, len = 0;
|
||
char *buf = NULL;
|
||
|
||
while (1) {
|
||
space = alloc - len;
|
||
if (space == 0) {
|
||
space = CHUNKSIZE;
|
||
alloc += space;
|
||
buf = realloc(buf, alloc + 1); /* + 1 is '\0' */
|
||
}
|
||
n = read(fd, buf + len, space);
|
||
if (n > 0) {
|
||
len += n;
|
||
continue;
|
||
} else if (n == 0) {
|
||
break;
|
||
}
|
||
|
||
free(buf);
|
||
return -errno;
|
||
}
|
||
|
||
if (buf)
|
||
buf[len] = '\0';
|
||
|
||
*out = buf;
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int read_file(char **out, const char *path)
|
||
{
|
||
int fd, retval;
|
||
|
||
fd = open(path, O_RDONLY);
|
||
if (fd == -1)
|
||
return -errno;
|
||
|
||
retval = read_fd(out, fd);
|
||
close(fd);
|
||
|
||
return retval;
|
||
}
|
||
|
||
int main(int argc, const char **argv)
|
||
{
|
||
int i, retval;
|
||
const char *arg;
|
||
const char *files[argc], *texts[argc];
|
||
unsigned int nfiles = 0, ntexts = 0;
|
||
unsigned int flags = 0;
|
||
char *input, *output;
|
||
|
||
if (argc == 1) {
|
||
print_usage();
|
||
return -1;
|
||
}
|
||
|
||
for (i = 1; i < argc; i++) {
|
||
arg = argv[i];
|
||
|
||
if (*arg == '-') {
|
||
switch (arg[1]) {
|
||
case 'r':
|
||
flags |= FLAG_REVERSE;
|
||
continue;
|
||
case 'e':
|
||
flags |= FLAG_ENCODE;
|
||
continue;
|
||
case 'c':
|
||
flags |= FLAG_CZECH;
|
||
continue;
|
||
case 'f':
|
||
files[nfiles++] = argv[++i];
|
||
continue;
|
||
case 'h':
|
||
print_usage();
|
||
return 0;
|
||
case 'v':
|
||
print_version();
|
||
return 0;
|
||
}
|
||
|
||
error("unknown option '%s'.", arg);
|
||
return -1;
|
||
} else {
|
||
texts[ntexts++] = arg;
|
||
}
|
||
}
|
||
|
||
for (i = 0; i < ntexts; i++) {
|
||
output = process_input(texts[i], flags);
|
||
fprintf(stdout, "%s\n", output);
|
||
free(output);
|
||
}
|
||
|
||
for (i = 0; i < nfiles; i++) {
|
||
if (strcmp(files[i], "-") == 0) {
|
||
retval = read_fd(&input, STDIN_FILENO);
|
||
} else {
|
||
retval = read_file(&input, files[i]);
|
||
}
|
||
|
||
if (retval != 0) {
|
||
error("failed to read file '%s'.", files[i]);
|
||
return retval;
|
||
}
|
||
|
||
output = process_input(input, flags);
|
||
fprintf(stdout, "%s", output);
|
||
free(output);
|
||
free(input);
|
||
}
|
||
|
||
return 0;
|
||
}
|