Gitweb links:
...log
http://git.netsurf-browser.org/netsurf.git/shortlog/f31fb08c73b9f4c93f3f89fa865715502afcf390
...commit
http://git.netsurf-browser.org/netsurf.git/commit/f31fb08c73b9f4c93f3f89fa865715502afcf390
...tree
http://git.netsurf-browser.org/netsurf.git/tree/f31fb08c73b9f4c93f3f89fa865715502afcf390
The branch, master has been updated
via f31fb08c73b9f4c93f3f89fa865715502afcf390 (commit)
via b0a3eba82d691b550aa7221049738bfa7cd0fc60 (commit)
via d5d14df76bbb2b50727c00584effbc9f5e52ba4e (commit)
from 154a6b69870f215ae05f98daa4e2713aac706d36 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=f31fb08c73b9f4c93f3f89fa865715502afcf390
commit f31fb08c73b9f4c93f3f89fa865715502afcf390
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
add gzip compression support to c split-messages implementation
diff --git a/utils/Makefile b/utils/Makefile
index 01c5ee7..7b20978 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -35,4 +35,4 @@ $(TOOLROOT)/xxd: utils/xxd.c $(TOOLROOT)/created
#
$(TOOLROOT)/split-messages: utils/split-messages.c $(TOOLROOT)/created
$(VQ)echo "BUILD CC: $@"
- $(Q)$(BUILD_CC) $(BUILD_CFLAGS) -o $@ $< $(BUILD_LDFLAGS)
+ $(Q)$(BUILD_CC) $(BUILD_CFLAGS) -o $@ $< $(BUILD_LDFLAGS) -lz
diff --git a/utils/split-messages.c b/utils/split-messages.c
index 76224cb..fa384fe 100644
--- a/utils/split-messages.c
+++ b/utils/split-messages.c
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <zlib.h>
#include "errors.h"
@@ -456,25 +457,32 @@ fatmessages_read(struct param *param, struct
trnsltn_entry **tlist)
static nserror
message_write(struct param *param, struct trnsltn_entry *tlist)
{
- FILE *outf;
+ gzFile outf;
+ const char *mode;
- outf = fopen(param->outfilename, "w");
+ if (param->compress == 0) {
+ mode = "wbT";
+ } else {
+ mode = "wb9";
+ }
+
+ outf = gzopen(param->outfilename, mode);
if (outf == NULL) {
perror("Unable to open output file");
return NSERROR_PERMISSION;
}
- fprintf(outf,
+ gzprintf(outf,
"# This messages file is automatically generated from %s\n"
"# at build-time. Please go and edit that instead of
this.\n\n",
param->infilename);
while (tlist != NULL) {
- fprintf(outf, "%s:%s\n", tlist->key, tlist->value);
+ gzprintf(outf, "%s:%s\n", tlist->key, tlist->value);
tlist = tlist->next;
}
- fclose(outf);
+ gzclose(outf);
return NSERROR_OK;
}
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=b0a3eba82d691b550aa7221049738bfa7cd0fc60
commit b0a3eba82d691b550aa7221049738bfa7cd0fc60
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
fix italian ObjInfo key being labelled french
diff --git a/resources/FatMessages b/resources/FatMessages
index 9b15485..68095dc 100644
--- a/resources/FatMessages
+++ b/resources/FatMessages
@@ -1927,7 +1927,7 @@ nl.all.LinkText:Tekstbestand
#
en.all.ObjInfo:Info
fr.all.ObjInfo:Information
-fr.all.ObjInfo:Informazioni
+it.all.ObjInfo:Informazioni
nl.all.ObjInfo:Informatie
en.all.ObjSave:Save
de.all.ObjSave:Speichern
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=d5d14df76bbb2b50727c00584effbc9f5e52ba4e
commit d5d14df76bbb2b50727c00584effbc9f5e52ba4e
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
initial implementation of split messages in c
functional but the compression switch still needs implementing
diff --git a/Makefile b/Makefile
index ae1325f..9aee147 100644
--- a/Makefile
+++ b/Makefile
@@ -150,6 +150,9 @@ VQ=@
# Override this only if the host compiler is called something different
BUILD_CC := cc
+BUILD_CFLAGS = -g -W -Wall -Wundef -Wpointer-arith -Wcast-align \
+ -Wwrite-strings -Wmissing-declarations -Wuninitialized \
+ -Wno-unused-parameter
ifeq ($(TARGET),riscos)
ifeq ($(HOST),riscos)
diff --git a/content/handlers/javascript/duktape/Makefile
b/content/handlers/javascript/duktape/Makefile
index 096bd2c..638ca44 100644
--- a/content/handlers/javascript/duktape/Makefile
+++ b/content/handlers/javascript/duktape/Makefile
@@ -11,12 +11,6 @@ content/handlers/javascript/duktape/dukky.c: \
BINDINGS := $(wildcard content/handlers/javascript/duktape/*.bnd)
-# Host tool to convert file to comiled data
-#
-$(TOOLROOT)/xxd: utils/xxd.c $(TOOLROOT)/created
- $(VQ)echo "BUILD CC: $@"
- $(Q)$(BUILD_CC) $(BUILD_CFLAGS) -o $@ $< $(BUILD_LDFLAGS)
-
# Generator for the C include representing the generics.js
$(OBJROOT)/duktape/generics.js.inc:
content/handlers/javascript/duktape/generics.js $(TOOLROOT)/xxd
$(Q)$(MKDIR) -p $(OBJROOT)/duktape
diff --git a/utils/Makefile b/utils/Makefile
index b186cd1..01c5ee7 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -24,3 +24,15 @@ S_UTILS := \
utils.c
S_UTILS := $(addprefix utils/,$(S_UTILS))
+
+# Host tool to convert file to comiled data
+#
+$(TOOLROOT)/xxd: utils/xxd.c $(TOOLROOT)/created
+ $(VQ)echo "BUILD CC: $@"
+ $(Q)$(BUILD_CC) $(BUILD_CFLAGS) -o $@ $< $(BUILD_LDFLAGS)
+
+# Host tool to convert file to comiled data
+#
+$(TOOLROOT)/split-messages: utils/split-messages.c $(TOOLROOT)/created
+ $(VQ)echo "BUILD CC: $@"
+ $(Q)$(BUILD_CC) $(BUILD_CFLAGS) -o $@ $< $(BUILD_LDFLAGS)
diff --git a/utils/split-messages.c b/utils/split-messages.c
new file mode 100644
index 0000000..76224cb
--- /dev/null
+++ b/utils/split-messages.c
@@ -0,0 +1,513 @@
+/**
+ * \file
+ * simple tool to split fat messages file without the capabilities of
+ * the full tool but without the dependancy on perl.
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "errors.h"
+
+enum out_fmt {
+ OUTPUTFMT_NONE = 0,
+ OUTPUTFMT_MESSAGES,
+};
+
+/**
+ * parameters that control behaviour of tool
+ */
+struct param {
+ /**
+ * compress output
+ */
+ int compress;
+ /**
+ * select language
+ */
+ char *selected;
+ /**
+ * fallback language for items unavailable in selecte dlanguage
+ */
+ char *fallback;
+ int warnings;
+ char *platform;
+ enum out_fmt format;
+ char *infilename;
+ char *outfilename;
+};
+
+struct trnsltn_entry {
+ struct trnsltn_entry *next;
+ char *lang;
+ char *key;
+ char *value;
+};
+
+static nserror usage(int argc, char **argv)
+{
+ fprintf(stderr,
+ "Usage: %s -l lang [-z] [-d lang] [-W warning] [-o <file>] [-i
<file>] [-p platform] [-f format] [<file> [<file>]]\n"
+ "Options:\n"
+ " -z Gzip output\n"
+ " -l lang Language to select for\n"
+ " -d lang Fallback language [default: en]\n"
+ " -W warning Warnings generated none, all [default: none]\n"
+ " -p platform Platform to select for any, gtk, ami [default:
any]\n"
+ " -f format Output format [default: messages]\n"
+ " -i filename Input file\n"
+ " -o filename Output file\n",
+ argv[0]);
+ return NSERROR_OK;
+}
+
+/**
+ * process command line arguments
+ *
+ *
+ */
+static nserror process_cmdline(int argc, char **argv, struct param *param)
+{
+ int opt;
+
+ memset(param, 0, sizeof(*param));
+
+ while ((opt = getopt(argc, argv, "zl:d:W:o:i:p:f:")) != -1) {
+ switch (opt) {
+ case 'z':
+ param->compress = 1;
+ break;
+
+ case 'l':
+ param->selected = strdup(optarg);
+ break;
+
+ case 'd':
+ param->fallback = strdup(optarg);
+ break;
+
+ case 'W':
+ param->warnings = 1;
+ break;
+
+ case 'o':
+ param->outfilename = strdup(optarg);
+ break;
+
+ case 'i':
+ param->infilename = strdup(optarg);
+ break;
+
+ case 'p':
+ param->platform = strdup(optarg);
+ break;
+
+ case 'f':
+ if (strcmp(optarg, "messages") == 0) {
+ param->format = OUTPUTFMT_MESSAGES;
+ } else {
+ fprintf(stderr,
+ "output format %s not supported",
+ optarg);
+ usage(argc, argv);
+ return NSERROR_NOT_IMPLEMENTED;
+ }
+ break;
+
+ default:
+ usage(argc, argv);
+ return NSERROR_BAD_PARAMETER;
+ }
+ }
+
+ /* trailing filename arguments */
+ if (optind < argc) {
+ param->infilename = strdup(argv[optind]);
+ optind++;
+ }
+
+ if (optind < argc) {
+ param->outfilename = strdup(argv[optind]);
+ optind++;
+ }
+
+ /* parameter checks */
+ if (param->selected == NULL) {
+ fprintf(stderr, "A language to select must be specified\n");
+ usage(argc, argv);
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if (param->infilename == NULL) {
+ fprintf(stderr, "Input file required\n");
+ usage(argc, argv);
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if (param->outfilename == NULL) {
+ fprintf(stderr, "Output file required\n");
+ usage(argc, argv);
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if ((param->platform != NULL) &&
+ (strcmp(param->platform, "any") ==0)) {
+ free(param->platform);
+ param->platform = NULL;
+ }
+
+ /* defaults */
+ if (param->fallback == NULL) {
+ param->fallback = strdup("en");
+ }
+
+ if (param->format == OUTPUTFMT_NONE) {
+ param->format = OUTPUTFMT_MESSAGES;
+ }
+
+ return NSERROR_OK;
+}
+
+/***
+ * extract key/value from a line
+ */
+static nserror
+get_key_value(char *line, ssize_t linelen, char **key_out, char **value_out)
+{
+ char *key;
+ char *value;
+
+ /* skip leading whitespace for start of key */
+ for (key = line; *key != 0; key++) {
+ if ((*key != ' ') && (*key != '\t') && (*key != '\n')) {
+ break;
+ }
+ }
+
+ /* empty line or only whitespace */
+ if (*key == 0) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* comment */
+ if (*key == '#') {
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* get start of value */
+ for (value = key; *value != 0; value++) {
+ if (*value == ':') {
+ *value = 0;
+ value++;
+ break;
+ }
+ }
+
+ /* missing colon separator */
+ if (*value == 0) {
+ return NSERROR_INVALID;
+ }
+
+ /* remove delimiter from value */
+ if (line[linelen - 1] == '\n') {
+ linelen--;
+ line[linelen] = 0;
+ }
+
+ *key_out = key;
+ *value_out = value;
+ return NSERROR_OK;
+}
+
+static nserror
+get_lang_plat_tok(char *str, char **lang_out, char **plat_out, char **tok_out)
+{
+ char *plat;
+ char *tok;
+
+ for (plat = str; *plat != 0; plat++) {
+ if (*plat == '.') {
+ *plat = 0;
+ plat++;
+ break;
+ }
+ }
+ if (*plat == 0) {
+ return NSERROR_INVALID;
+ }
+
+ for (tok = plat; *tok != 0; tok++) {
+ if (*tok == '.') {
+ *tok = 0;
+ tok++;
+ break;
+ }
+ }
+ if (*tok == 0) {
+ return NSERROR_INVALID;
+ }
+
+ *lang_out = str;
+ *plat_out = plat;
+ *tok_out = tok;
+
+ return NSERROR_OK;
+}
+
+
+static nserror
+translation_list_reverse(struct trnsltn_entry **tlist)
+{
+ struct trnsltn_entry *prev;
+ struct trnsltn_entry *next;
+ struct trnsltn_entry *curr;
+
+ prev = NULL;
+ next = NULL;
+ curr = *tlist;
+
+ while (curr != NULL) {
+ next = curr->next;
+ curr->next = prev;
+ prev = curr;
+ curr = next;
+ }
+
+ *tlist = prev;
+ return NSERROR_OK;
+}
+
+/**
+ * find a translation entry from a key
+ *
+ * \todo This implementation is imcomplete! it only considers the very
+ * first entry on the list. this introduces the odd ordering
+ * requirement for keys in the fatmessages file. This is done to avoid
+ * an O(n^2) list search for every line of input.
+ *
+ * \param tlist translation list head
+ * \param key The key of the translation to search for
+ * \param trans_out The sucessful result
+ * \return NSERROR_OK and trans_out updated on success else NSERROR_NOT_FOUND;
+ */
+static nserror
+translation_from_key(struct trnsltn_entry *tlist,
+ char *key,
+ struct trnsltn_entry **trans_out)
+{
+ if (tlist == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ if (strcmp(tlist->key, key) != 0) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ *trans_out = tlist;
+ return NSERROR_OK;
+}
+
+
+static nserror
+translation_add(struct trnsltn_entry **tlist,
+ const char *lang,
+ const char *key,
+ const char *value)
+{
+ struct trnsltn_entry *tnew;
+
+ tnew = malloc(sizeof(*tnew));
+ if (tnew == NULL) {
+ return NSERROR_NOMEM;
+ }
+ tnew->next = *tlist;
+ tnew->lang = strdup(lang);
+ tnew->key = strdup(key);
+ tnew->value = strdup(value);
+
+ *tlist = tnew;
+ return NSERROR_OK;
+}
+
+
+static nserror
+translation_replace(struct trnsltn_entry *tran,
+ const char *lang,
+ const char *key,
+ const char *value)
+{
+ free(tran->lang);
+ tran->lang = strdup(lang);
+ free(tran->key);
+ tran->key = strdup(key);
+ free(tran->value);
+ tran->value = strdup(value);
+
+ return NSERROR_OK;
+}
+
+/**
+ * process a line of the input file
+ *
+ */
+static nserror
+messageline(struct param *param,
+ struct trnsltn_entry **tlist,
+ char *line, ssize_t linelen)
+{
+ nserror res;
+ char *key;
+ char *value;
+ char *lang;
+ char *plat;
+ char *tok;
+ struct trnsltn_entry *tran;
+
+ res = get_key_value(line, linelen, &key, &value);
+ if (res != NSERROR_OK) {
+ /* skip line as no valid key value pair found */
+ return res;
+ }
+
+ res = get_lang_plat_tok(key, &lang, &plat, &tok);
+ if (res != NSERROR_OK) {
+ /* malformed key */
+ return res;
+ }
+
+ if ((param->platform != NULL) &&
+ (strcmp(plat, "all") != 0) &&
+ (strcmp(plat, param->platform) != 0)) {
+ /* this translation is not for the selected platform */
+ return NSERROR_OK;
+ }
+
+ res = translation_from_key(*tlist, tok, &tran);
+ if (res == NSERROR_OK) {
+ if (strcmp(tran->lang, param->selected) != 0) {
+ /* current entry is not the selected language */
+ if (strcmp(lang, param->selected) == 0) {
+ /*
+ * new entry is in selected language and
+ * current entry is not
+ */
+ res = translation_replace(tran, lang, tok,
value); } else if ((strcmp(lang, param->fallback) != 0) &&
+ (strcmp(tran->lang, param->fallback) != 0)) {
+ /*
+ * new entry is in fallback language and
+ * current entry is not.
+ */
+ res = translation_replace(tran, lang, tok,
value);
+ }
+ } else {
+ if (strcmp(tran->lang, lang) == 0) {
+ /* second entry with matching language */
+ res = translation_replace(tran, lang, tok,
value);
+ }
+ }
+ } else if (res == NSERROR_NOT_FOUND) {
+ res = translation_add(tlist, lang, tok, value);
+ }
+
+ return res;
+}
+
+
+static nserror
+fatmessages_read(struct param *param, struct trnsltn_entry **tlist)
+{
+ nserror res;
+ FILE *infile;
+ char *line = NULL;
+ size_t linealloc = 0;
+ ssize_t linelen;
+ int linenum = 0;
+
+ infile = fopen(param->infilename, "r");
+ if (infile == NULL) {
+ perror("Unable to open input file");
+ return NSERROR_NOT_FOUND;
+ }
+
+ while (1) {
+ linelen = getline(&line, &linealloc, infile);
+ if (linelen == -1) {
+ break;
+ }
+ linenum++;
+
+ res = messageline(param, tlist, line, linelen);
+ if ((res == NSERROR_INVALID) && (param->warnings > 0)) {
+ fprintf(stderr, "line %d Malformed: \"%s\"\n",
+ linenum, line);
+ }
+ }
+
+ fclose(infile);
+
+ res = translation_list_reverse(tlist);
+
+ return res;
+}
+
+static nserror
+message_write(struct param *param, struct trnsltn_entry *tlist)
+{
+ FILE *outf;
+
+ outf = fopen(param->outfilename, "w");
+ if (outf == NULL) {
+ perror("Unable to open output file");
+ return NSERROR_PERMISSION;
+ }
+
+ fprintf(outf,
+ "# This messages file is automatically generated from %s\n"
+ "# at build-time. Please go and edit that instead of
this.\n\n",
+ param->infilename);
+
+ while (tlist != NULL) {
+ fprintf(outf, "%s:%s\n", tlist->key, tlist->value);
+ tlist = tlist->next;
+ }
+
+ fclose(outf);
+
+ return NSERROR_OK;
+}
+
+int main(int argc, char **argv)
+{
+ nserror res;
+ struct param param; /* control paramters */
+ struct trnsltn_entry *translations = NULL;
+
+ res = process_cmdline(argc, argv, ¶m);
+ if (res != NSERROR_OK) {
+ return EXIT_FAILURE;
+ }
+
+ res = fatmessages_read(¶m, &translations);
+ if (res != NSERROR_OK) {
+ return EXIT_FAILURE;
+ }
+
+ switch (param.format) {
+ case OUTPUTFMT_NONE:
+ res = NSERROR_OK;
+ break;
+
+ case OUTPUTFMT_MESSAGES:
+ res = message_write(¶m, translations);
+ break;
+ }
+
+ if (res != NSERROR_OK) {
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/utils/split-messages.pl b/utils/split-messages.pl
index 4b50dde..0504b24 100644
--- a/utils/split-messages.pl
+++ b/utils/split-messages.pl
@@ -187,7 +187,7 @@ sub usage ()
print(STDERR <<TXT );
usage:
$0 -l lang-code [-d def-lang-code] [-W warning] \
- [-o output-file] [-i input-file] [-p platform] [-f format]
+ [-o output-file] [-i input-file] [-p platform] [-f format] [-z]
$0 -l lang-code ... [input-file [output-file]]
-----------------------------------------------------------------------
Summary of changes:
Makefile | 3 +
content/handlers/javascript/duktape/Makefile | 6 -
resources/FatMessages | 2 +-
utils/Makefile | 12 +
utils/split-messages.c | 521 ++++++++++++++++++++++++++
utils/split-messages.pl | 2 +-
6 files changed, 538 insertions(+), 8 deletions(-)
create mode 100644 utils/split-messages.c
diff --git a/Makefile b/Makefile
index ae1325f..9aee147 100644
--- a/Makefile
+++ b/Makefile
@@ -150,6 +150,9 @@ VQ=@
# Override this only if the host compiler is called something different
BUILD_CC := cc
+BUILD_CFLAGS = -g -W -Wall -Wundef -Wpointer-arith -Wcast-align \
+ -Wwrite-strings -Wmissing-declarations -Wuninitialized \
+ -Wno-unused-parameter
ifeq ($(TARGET),riscos)
ifeq ($(HOST),riscos)
diff --git a/content/handlers/javascript/duktape/Makefile
b/content/handlers/javascript/duktape/Makefile
index 096bd2c..638ca44 100644
--- a/content/handlers/javascript/duktape/Makefile
+++ b/content/handlers/javascript/duktape/Makefile
@@ -11,12 +11,6 @@ content/handlers/javascript/duktape/dukky.c: \
BINDINGS := $(wildcard content/handlers/javascript/duktape/*.bnd)
-# Host tool to convert file to comiled data
-#
-$(TOOLROOT)/xxd: utils/xxd.c $(TOOLROOT)/created
- $(VQ)echo "BUILD CC: $@"
- $(Q)$(BUILD_CC) $(BUILD_CFLAGS) -o $@ $< $(BUILD_LDFLAGS)
-
# Generator for the C include representing the generics.js
$(OBJROOT)/duktape/generics.js.inc:
content/handlers/javascript/duktape/generics.js $(TOOLROOT)/xxd
$(Q)$(MKDIR) -p $(OBJROOT)/duktape
diff --git a/resources/FatMessages b/resources/FatMessages
index 9b15485..68095dc 100644
--- a/resources/FatMessages
+++ b/resources/FatMessages
@@ -1927,7 +1927,7 @@ nl.all.LinkText:Tekstbestand
#
en.all.ObjInfo:Info
fr.all.ObjInfo:Information
-fr.all.ObjInfo:Informazioni
+it.all.ObjInfo:Informazioni
nl.all.ObjInfo:Informatie
en.all.ObjSave:Save
de.all.ObjSave:Speichern
diff --git a/utils/Makefile b/utils/Makefile
index b186cd1..7b20978 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -24,3 +24,15 @@ S_UTILS := \
utils.c
S_UTILS := $(addprefix utils/,$(S_UTILS))
+
+# Host tool to convert file to comiled data
+#
+$(TOOLROOT)/xxd: utils/xxd.c $(TOOLROOT)/created
+ $(VQ)echo "BUILD CC: $@"
+ $(Q)$(BUILD_CC) $(BUILD_CFLAGS) -o $@ $< $(BUILD_LDFLAGS)
+
+# Host tool to convert file to comiled data
+#
+$(TOOLROOT)/split-messages: utils/split-messages.c $(TOOLROOT)/created
+ $(VQ)echo "BUILD CC: $@"
+ $(Q)$(BUILD_CC) $(BUILD_CFLAGS) -o $@ $< $(BUILD_LDFLAGS) -lz
diff --git a/utils/split-messages.c b/utils/split-messages.c
new file mode 100644
index 0000000..fa384fe
--- /dev/null
+++ b/utils/split-messages.c
@@ -0,0 +1,521 @@
+/**
+ * \file
+ * simple tool to split fat messages file without the capabilities of
+ * the full tool but without the dependancy on perl.
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <zlib.h>
+
+#include "errors.h"
+
+enum out_fmt {
+ OUTPUTFMT_NONE = 0,
+ OUTPUTFMT_MESSAGES,
+};
+
+/**
+ * parameters that control behaviour of tool
+ */
+struct param {
+ /**
+ * compress output
+ */
+ int compress;
+ /**
+ * select language
+ */
+ char *selected;
+ /**
+ * fallback language for items unavailable in selecte dlanguage
+ */
+ char *fallback;
+ int warnings;
+ char *platform;
+ enum out_fmt format;
+ char *infilename;
+ char *outfilename;
+};
+
+struct trnsltn_entry {
+ struct trnsltn_entry *next;
+ char *lang;
+ char *key;
+ char *value;
+};
+
+static nserror usage(int argc, char **argv)
+{
+ fprintf(stderr,
+ "Usage: %s -l lang [-z] [-d lang] [-W warning] [-o <file>] [-i
<file>] [-p platform] [-f format] [<file> [<file>]]\n"
+ "Options:\n"
+ " -z Gzip output\n"
+ " -l lang Language to select for\n"
+ " -d lang Fallback language [default: en]\n"
+ " -W warning Warnings generated none, all [default: none]\n"
+ " -p platform Platform to select for any, gtk, ami [default:
any]\n"
+ " -f format Output format [default: messages]\n"
+ " -i filename Input file\n"
+ " -o filename Output file\n",
+ argv[0]);
+ return NSERROR_OK;
+}
+
+/**
+ * process command line arguments
+ *
+ *
+ */
+static nserror process_cmdline(int argc, char **argv, struct param *param)
+{
+ int opt;
+
+ memset(param, 0, sizeof(*param));
+
+ while ((opt = getopt(argc, argv, "zl:d:W:o:i:p:f:")) != -1) {
+ switch (opt) {
+ case 'z':
+ param->compress = 1;
+ break;
+
+ case 'l':
+ param->selected = strdup(optarg);
+ break;
+
+ case 'd':
+ param->fallback = strdup(optarg);
+ break;
+
+ case 'W':
+ param->warnings = 1;
+ break;
+
+ case 'o':
+ param->outfilename = strdup(optarg);
+ break;
+
+ case 'i':
+ param->infilename = strdup(optarg);
+ break;
+
+ case 'p':
+ param->platform = strdup(optarg);
+ break;
+
+ case 'f':
+ if (strcmp(optarg, "messages") == 0) {
+ param->format = OUTPUTFMT_MESSAGES;
+ } else {
+ fprintf(stderr,
+ "output format %s not supported",
+ optarg);
+ usage(argc, argv);
+ return NSERROR_NOT_IMPLEMENTED;
+ }
+ break;
+
+ default:
+ usage(argc, argv);
+ return NSERROR_BAD_PARAMETER;
+ }
+ }
+
+ /* trailing filename arguments */
+ if (optind < argc) {
+ param->infilename = strdup(argv[optind]);
+ optind++;
+ }
+
+ if (optind < argc) {
+ param->outfilename = strdup(argv[optind]);
+ optind++;
+ }
+
+ /* parameter checks */
+ if (param->selected == NULL) {
+ fprintf(stderr, "A language to select must be specified\n");
+ usage(argc, argv);
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if (param->infilename == NULL) {
+ fprintf(stderr, "Input file required\n");
+ usage(argc, argv);
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if (param->outfilename == NULL) {
+ fprintf(stderr, "Output file required\n");
+ usage(argc, argv);
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if ((param->platform != NULL) &&
+ (strcmp(param->platform, "any") ==0)) {
+ free(param->platform);
+ param->platform = NULL;
+ }
+
+ /* defaults */
+ if (param->fallback == NULL) {
+ param->fallback = strdup("en");
+ }
+
+ if (param->format == OUTPUTFMT_NONE) {
+ param->format = OUTPUTFMT_MESSAGES;
+ }
+
+ return NSERROR_OK;
+}
+
+/***
+ * extract key/value from a line
+ */
+static nserror
+get_key_value(char *line, ssize_t linelen, char **key_out, char **value_out)
+{
+ char *key;
+ char *value;
+
+ /* skip leading whitespace for start of key */
+ for (key = line; *key != 0; key++) {
+ if ((*key != ' ') && (*key != '\t') && (*key != '\n')) {
+ break;
+ }
+ }
+
+ /* empty line or only whitespace */
+ if (*key == 0) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* comment */
+ if (*key == '#') {
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* get start of value */
+ for (value = key; *value != 0; value++) {
+ if (*value == ':') {
+ *value = 0;
+ value++;
+ break;
+ }
+ }
+
+ /* missing colon separator */
+ if (*value == 0) {
+ return NSERROR_INVALID;
+ }
+
+ /* remove delimiter from value */
+ if (line[linelen - 1] == '\n') {
+ linelen--;
+ line[linelen] = 0;
+ }
+
+ *key_out = key;
+ *value_out = value;
+ return NSERROR_OK;
+}
+
+static nserror
+get_lang_plat_tok(char *str, char **lang_out, char **plat_out, char **tok_out)
+{
+ char *plat;
+ char *tok;
+
+ for (plat = str; *plat != 0; plat++) {
+ if (*plat == '.') {
+ *plat = 0;
+ plat++;
+ break;
+ }
+ }
+ if (*plat == 0) {
+ return NSERROR_INVALID;
+ }
+
+ for (tok = plat; *tok != 0; tok++) {
+ if (*tok == '.') {
+ *tok = 0;
+ tok++;
+ break;
+ }
+ }
+ if (*tok == 0) {
+ return NSERROR_INVALID;
+ }
+
+ *lang_out = str;
+ *plat_out = plat;
+ *tok_out = tok;
+
+ return NSERROR_OK;
+}
+
+
+static nserror
+translation_list_reverse(struct trnsltn_entry **tlist)
+{
+ struct trnsltn_entry *prev;
+ struct trnsltn_entry *next;
+ struct trnsltn_entry *curr;
+
+ prev = NULL;
+ next = NULL;
+ curr = *tlist;
+
+ while (curr != NULL) {
+ next = curr->next;
+ curr->next = prev;
+ prev = curr;
+ curr = next;
+ }
+
+ *tlist = prev;
+ return NSERROR_OK;
+}
+
+/**
+ * find a translation entry from a key
+ *
+ * \todo This implementation is imcomplete! it only considers the very
+ * first entry on the list. this introduces the odd ordering
+ * requirement for keys in the fatmessages file. This is done to avoid
+ * an O(n^2) list search for every line of input.
+ *
+ * \param tlist translation list head
+ * \param key The key of the translation to search for
+ * \param trans_out The sucessful result
+ * \return NSERROR_OK and trans_out updated on success else NSERROR_NOT_FOUND;
+ */
+static nserror
+translation_from_key(struct trnsltn_entry *tlist,
+ char *key,
+ struct trnsltn_entry **trans_out)
+{
+ if (tlist == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ if (strcmp(tlist->key, key) != 0) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ *trans_out = tlist;
+ return NSERROR_OK;
+}
+
+
+static nserror
+translation_add(struct trnsltn_entry **tlist,
+ const char *lang,
+ const char *key,
+ const char *value)
+{
+ struct trnsltn_entry *tnew;
+
+ tnew = malloc(sizeof(*tnew));
+ if (tnew == NULL) {
+ return NSERROR_NOMEM;
+ }
+ tnew->next = *tlist;
+ tnew->lang = strdup(lang);
+ tnew->key = strdup(key);
+ tnew->value = strdup(value);
+
+ *tlist = tnew;
+ return NSERROR_OK;
+}
+
+
+static nserror
+translation_replace(struct trnsltn_entry *tran,
+ const char *lang,
+ const char *key,
+ const char *value)
+{
+ free(tran->lang);
+ tran->lang = strdup(lang);
+ free(tran->key);
+ tran->key = strdup(key);
+ free(tran->value);
+ tran->value = strdup(value);
+
+ return NSERROR_OK;
+}
+
+/**
+ * process a line of the input file
+ *
+ */
+static nserror
+messageline(struct param *param,
+ struct trnsltn_entry **tlist,
+ char *line, ssize_t linelen)
+{
+ nserror res;
+ char *key;
+ char *value;
+ char *lang;
+ char *plat;
+ char *tok;
+ struct trnsltn_entry *tran;
+
+ res = get_key_value(line, linelen, &key, &value);
+ if (res != NSERROR_OK) {
+ /* skip line as no valid key value pair found */
+ return res;
+ }
+
+ res = get_lang_plat_tok(key, &lang, &plat, &tok);
+ if (res != NSERROR_OK) {
+ /* malformed key */
+ return res;
+ }
+
+ if ((param->platform != NULL) &&
+ (strcmp(plat, "all") != 0) &&
+ (strcmp(plat, param->platform) != 0)) {
+ /* this translation is not for the selected platform */
+ return NSERROR_OK;
+ }
+
+ res = translation_from_key(*tlist, tok, &tran);
+ if (res == NSERROR_OK) {
+ if (strcmp(tran->lang, param->selected) != 0) {
+ /* current entry is not the selected language */
+ if (strcmp(lang, param->selected) == 0) {
+ /*
+ * new entry is in selected language and
+ * current entry is not
+ */
+ res = translation_replace(tran, lang, tok,
value); } else if ((strcmp(lang, param->fallback) != 0) &&
+ (strcmp(tran->lang, param->fallback) != 0)) {
+ /*
+ * new entry is in fallback language and
+ * current entry is not.
+ */
+ res = translation_replace(tran, lang, tok,
value);
+ }
+ } else {
+ if (strcmp(tran->lang, lang) == 0) {
+ /* second entry with matching language */
+ res = translation_replace(tran, lang, tok,
value);
+ }
+ }
+ } else if (res == NSERROR_NOT_FOUND) {
+ res = translation_add(tlist, lang, tok, value);
+ }
+
+ return res;
+}
+
+
+static nserror
+fatmessages_read(struct param *param, struct trnsltn_entry **tlist)
+{
+ nserror res;
+ FILE *infile;
+ char *line = NULL;
+ size_t linealloc = 0;
+ ssize_t linelen;
+ int linenum = 0;
+
+ infile = fopen(param->infilename, "r");
+ if (infile == NULL) {
+ perror("Unable to open input file");
+ return NSERROR_NOT_FOUND;
+ }
+
+ while (1) {
+ linelen = getline(&line, &linealloc, infile);
+ if (linelen == -1) {
+ break;
+ }
+ linenum++;
+
+ res = messageline(param, tlist, line, linelen);
+ if ((res == NSERROR_INVALID) && (param->warnings > 0)) {
+ fprintf(stderr, "line %d Malformed: \"%s\"\n",
+ linenum, line);
+ }
+ }
+
+ fclose(infile);
+
+ res = translation_list_reverse(tlist);
+
+ return res;
+}
+
+static nserror
+message_write(struct param *param, struct trnsltn_entry *tlist)
+{
+ gzFile outf;
+ const char *mode;
+
+ if (param->compress == 0) {
+ mode = "wbT";
+ } else {
+ mode = "wb9";
+ }
+
+ outf = gzopen(param->outfilename, mode);
+ if (outf == NULL) {
+ perror("Unable to open output file");
+ return NSERROR_PERMISSION;
+ }
+
+ gzprintf(outf,
+ "# This messages file is automatically generated from %s\n"
+ "# at build-time. Please go and edit that instead of
this.\n\n",
+ param->infilename);
+
+ while (tlist != NULL) {
+ gzprintf(outf, "%s:%s\n", tlist->key, tlist->value);
+ tlist = tlist->next;
+ }
+
+ gzclose(outf);
+
+ return NSERROR_OK;
+}
+
+int main(int argc, char **argv)
+{
+ nserror res;
+ struct param param; /* control paramters */
+ struct trnsltn_entry *translations = NULL;
+
+ res = process_cmdline(argc, argv, ¶m);
+ if (res != NSERROR_OK) {
+ return EXIT_FAILURE;
+ }
+
+ res = fatmessages_read(¶m, &translations);
+ if (res != NSERROR_OK) {
+ return EXIT_FAILURE;
+ }
+
+ switch (param.format) {
+ case OUTPUTFMT_NONE:
+ res = NSERROR_OK;
+ break;
+
+ case OUTPUTFMT_MESSAGES:
+ res = message_write(¶m, translations);
+ break;
+ }
+
+ if (res != NSERROR_OK) {
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/utils/split-messages.pl b/utils/split-messages.pl
index 4b50dde..0504b24 100644
--- a/utils/split-messages.pl
+++ b/utils/split-messages.pl
@@ -187,7 +187,7 @@ sub usage ()
print(STDERR <<TXT );
usage:
$0 -l lang-code [-d def-lang-code] [-W warning] \
- [-o output-file] [-i input-file] [-p platform] [-f format]
+ [-o output-file] [-i input-file] [-p platform] [-f format] [-z]
$0 -l lang-code ... [input-file [output-file]]
--
NetSurf Browser
_______________________________________________
netsurf-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]