mkptinc.c
ttdpatch_ttdpatch/mkptinc.c
/*
  mkptinc.c - convert lang/<lang>.txt into <lang>.inc

  Copyright (C) 2002-2003 by Josef Drexler <jdrexler@uwo.ca>
  Portions copyright (C) 2006 by Dale McCoy <dalestan@gmail.com>

  Distributed under the GNU General Public License.
*/

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>

#define WANTINGAMETEXTNAMES
#include "inc/ourtext.h"

static int allocsize = 32768;

static void error(const char s[], ...)
{
  va_list args;

  va_start(args, s);
  vfprintf(stderr, s, args);
  va_end(args);

  exit(1);
}

static void warning(const char s[], ...)
{
  va_list args;

  va_start(args, s);
  vfprintf(stdout, s, args);
  fprintf(stdout, "\n");
  va_end(args);
}

static char *data;
static char *entries[TXT_last+1];
static int lengths[TXT_last+1];
static int defined[TXT_last+1];
static int txtindex, linelen;

static void store(int isdef)
{
  if (txtindex == -1) {
	linelen = 0;
	return;
  }

  entries[txtindex] = malloc(linelen);
  if (!entries[txtindex])
	error("Not enough memory.\n");

  memcpy(entries[txtindex], data, linelen);
  lengths[txtindex] = linelen;
  defined[txtindex] = isdef;

  linelen = 0;
  txtindex = -1;
}

#define entertxt() \
	if(!istxt){ \
		fprintf(txt, "\""); \
		istxt = 1; \
	} else

#define exittxt() \
	if(istxt){ \
		fprintf(txt, "\","); \
		istxt=0; \
	} else

static void printdefault(FILE *txt, char *name, int txtindex, int withname)
{
  int i, istxt=0;
  unsigned char c;

  if (txtindex == -1) {
	fprintf(txt,
		"; Autogenerated file. DO NOT EDIT.\n"
		"; Edit lang/%s.txt or lang/american.txt instead\n"
		";\n\n", name);
	return;
  }

  if (!defined[txtindex])
	warning("%s: No translation for %s.", name, ingametextnames[txtindex]);

  fprintf(txt, "def %s, db ", ingametextnames[txtindex]);

  for (i=0; i<lengths[txtindex]; i++) {
	c=entries[txtindex][i];
	if (c == '\r') {
		exittxt();
		fprintf(txt, "13,");
	} else if (c < ' ' || ( (c > 'z') && (c <= 0x9e) ) || c == '\\' || c == '"') {
		exittxt();
		fprintf(txt, "0x%02x,", c);
	} else {
		entertxt();
		putc(c, txt);
	}
  }
  exittxt();
  fprintf(txt, "0\n");
}

void readfile(FILE *txt, char istrans){
  int i, lineno = 0, deflang = -1;
  char *baseline = malloc(allocsize), *line, *name, c;

  if (!baseline || !data)
	error("Not enough memory.\n");

  while (!feof(txt)) {
	lineno++;
	line = baseline;
	if (!fgets(line, 16384, txt))
		break;
	if ( (strncmp(line, "//", 2) == 0) || (line[0] == ';') || line[0] == '\n' || line[0] == '\r')
		continue;

	// does it begin with whitespace?
	i = strspn(line, " \t");
	if (i) {
		line += i;	// continuation; skip whitespace
	} else {
		store(istrans);	// new entry
		name = line;
		line = strchr(line, '=');
		if (!line) error("Not an assignment on line %d\n", lineno);
		*line = 0;
		line++;

		txtindex = -1;
		for (i=0; i<TXT_last; i++) {
			if (strcmp(name, ingametextnames[i]) == 0) {
				txtindex = i;
				break;
			}
		}
		if (txtindex == -1)
			error("Unknown entry '%s' on line %d skipped.\n", 
				name, lineno);
	}

	// skip whitespace
	line += strspn(line, " \t");
	if (line[0] != '"')
		error("Value is not in quotes on line %d\n", lineno);
	line++;	// skip quote

	// terminate at final quote
	name = strrchr(line, '"');
	if (!name)
		error("Value is not in quotes on line %d\n", lineno);
	*name = 0;

	// unescape all chars
	while (line[0]) {
		if (line[0] == '\\') {
			switch (line[1]) {
				case 'n':
					data[linelen++] = '\r';
					line+=2;
					break;
				case '\\':
				case '"':
					data[linelen++] = line[1];
					line+=2;
					break;
				default:
					c = line[3];
					line[3] = 0;
					i = strtol(line+1, NULL, 16);
					line[3] = c;
					data[linelen++] = i;
					line+=3;
			}
		} else {
			data[linelen++] = line[0];
			line++;
		}
	}
  }

  store(istrans);

  free(baseline);
}

int main(int argc, char **argv)
{
  FILE *def,*real,*inc;
  char buf[64];


	// FIXME: if size ever potentially goes above 32kb (allocsize)
	// need to realloc these arrays as necessary
  data = malloc(allocsize);

  def = fopen("lang/american.txt", "rt");
  sprintf(buf,"lang/%s.txt",argv[1]);
  real = fopen(buf,"rt");
  sprintf(buf,"lang/%s.inc",argv[1]);
  inc = fopen(buf,"wt");

  if (!def)
	error("Error opening lang/american.txt: %s\n", strerror(errno));
  if (!real)
	error("Error opening lang/%s.txt: %s\n", argv[1], strerror(errno));
  if (!inc)
	error("Error opening lang/%s.inc: %s\n", argv[1], strerror(errno));

  txtindex=-1;
  linelen = 0;

  readfile(def,0);	//american as default
  fclose(def);
  readfile(real,1);	//overwrite with argv[1] texts
  fclose(real);

  printdefault(inc, argv[1], -1, 1);	// header

  for (txtindex=0; txtindex<TXT_last; txtindex++)
	printdefault(inc, argv[1], txtindex, 1);

  fclose(inc);

  return 0;
}
