#include <stdio.h>
#include <sys/types.h>
#ifdef SYSV
#include <sys/fcntl.h>
#include <string.h>
#else
#include <strings.h>
#endif
#include <sys/file.h>
#include <sys/stat.h>
#include "gencat.h"
#ifndef L_SET
#define L_SET SEEK_SET
#endif
#ifndef L_INCR
#define L_INCR SEEK_CUR
#endif
static void writeIfChanged(
#if defined(__STDC__) || defined(__cplusplus)
char *fname, int lang, int orConsts
#endif
);
void usage() {
fprintf(stderr, "Use: gencat [-new] [-or] [-lang C|C++|ANSIC] catfile msgfile [-h <header-file>]...\n");
}
int main(
#if defined(__STDC__) || defined(__cplusplus)
int argc, char *argv[])
#else
argc, argv)
int argc;
char *argv[];
#endif
{
int ofd, ifd, i;
FILE *fptr;
char *catfile = NULL;
char *input = NULL;
int lang = MCLangC;
int new = False;
int orConsts = False;
for (i = 1; i < argc; ++i) {
if (argv[i][0] == '-') {
if (strcmp(argv[i], "-lang") == 0) {
++i;
if (strcmp(argv[i], "C") == 0) lang = MCLangC;
else if (strcmp(argv[i], "C++") == 0) lang = MCLangCPlusPlus;
else if (strcmp(argv[i], "ANSIC") == 0) lang = MCLangANSIC;
else {
fprintf(stderr, "gencat: Unrecognized language: %s\n", argv[i]);
exit(1);
}
} else if (strncmp(argv[i], "-h", 2) == 0) {
if (!input) {
fprintf(stderr, "gencat: Can't write to a header before reading something.\n");
exit(1);
}
++i;
writeIfChanged(argv[i], lang, orConsts);
} else if (strncmp(argv[i], "-new", 4) == 0) {
if (catfile) {
fprintf(stderr, "gencat: You must specify -new before the catalog file name\n");
exit(1);
}
new = True;
} else if (strncmp(argv[i], "-or", 3) == 0) {
orConsts = ~orConsts;
} else {
usage();
exit(1);
}
} else {
if (!catfile) {
catfile = argv[i];
if (new) {
if ((ofd = open(catfile, O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) {
fprintf(stderr, "gencat: Unable to create a new %s.\n", catfile);
exit(1);
}
} else if ((ofd = open(catfile, O_RDONLY)) < 0) {
if ((ofd = open(catfile, O_WRONLY|O_CREAT, 0666)) < 0) {
fprintf(stderr, "gencat: Unable to create %s.\n", catfile);
exit(1);
}
} else {
MCReadCat(ofd);
close(ofd);
if ((ofd = open(catfile, O_WRONLY|O_TRUNC)) < 0) {
fprintf(stderr, "gencat: Unable to truncate %s.\n", catfile);
exit(1);
}
}
} else {
input = argv[i];
if ((ifd = open(input, O_RDONLY)) < 0) {
fprintf(stderr, "gencat: Unable to read %s\n", input);
exit(1);
}
MCParse(ifd);
close(ifd);
}
}
}
if (catfile) {
MCWriteCat(ofd);
exit(0);
} else {
usage();
exit(1);
}
return 0;
}
static void writeIfChanged(
#if defined(__STDC__) || defined(__cplusplus)
char *fname, int lang, int orConsts)
#else
fname, lang, orConsts)
char *fname;
int lang;
int orConsts;
#endif
{
char tmpname[32];
char buf[BUFSIZ], tbuf[BUFSIZ], *cptr, *tptr;
int fd, tfd;
int diff = False;
int c, len, tlen;
struct stat sbuf;
if (stat(fname, &sbuf)) {
if ((fd = open(fname, O_WRONLY|O_CREAT, 0666)) < 0) {
fprintf(stderr, "gencat: Unable to create header file %s.\n", fname);
exit(1);
}
MCWriteConst(fd, lang, orConsts);
close(fd);
return;
}
sprintf(tmpname, "/tmp/gencat.%d", (int) getpid());
if ((tfd = open(tmpname, O_RDWR|O_CREAT, 0666)) < 0) {
fprintf(stderr, "gencat: Unable to open temporary file: %s\n", tmpname);
exit(1);
}
unlink(tmpname);
MCWriteConst(tfd, lang, orConsts);
if ((fd = open(fname, O_RDONLY)) < 0) {
fprintf(stderr, "gencat: Unable to read header file: %s\n", fname);
exit(1);
}
if (lseek(tfd, 0L, L_SET) < 0) {
fprintf(stderr, "gencat: Unable to seek in tempfile: %s\n", tmpname);
exit(1);
}
while ((tlen = read(tfd, tbuf, BUFSIZ)) > 0) {
if ((len = read(fd, buf, BUFSIZ)) != tlen) {
diff = True;
goto done;
}
for (cptr = buf, tptr = tbuf; cptr < buf+len; ++cptr, ++tptr) {
if (*tptr != *cptr) {
diff = True;
goto done;
}
}
}
done:
if (diff) {
if (lseek(tfd, 0L, L_SET) < 0) {
fprintf(stderr, "gencat: Unable to seek in tempfile: %s\n", tmpname);
exit(1);
}
close(fd);
if ((fd = open(fname, O_WRONLY|O_TRUNC)) < 0) {
fprintf(stderr, "gencat: Unable to truncate header file: %s\n", fname);
exit(1);
}
while ((len = read(tfd, buf, BUFSIZ)) > 0) {
if (write(fd, buf, len) != len) {
fprintf(stderr, "gencat: Error writing to header file: %s\n", fname);
}
}
}
close(fd);
close(tfd);
}