summaryrefslogtreecommitdiffhomepage
path: root/libs/lmo/src
diff options
context:
space:
mode:
authorJo-Philipp Wich <jow@openwrt.org>2012-11-25 19:17:55 +0000
committerJo-Philipp Wich <jow@openwrt.org>2012-11-25 19:17:55 +0000
commit0e50aa690af6cd9f37fa97b4a521fe523cce3c39 (patch)
treec0ab4edc0dd221dfa3e6fb4eeba049ecc05326fe /libs/lmo/src
parentc647ff9f0e1af211a762dc9a773c1b5c4aacd168 (diff)
libs/web: rewrite template engine, merge lmo library
- template parser: merge lmo library - template parser: rewrite to operate on memory mapped files - template parser: implement proper line number reporting on syntax errors - template parser: process translate tags directly and bypass Lua - template lmo: introduce load_catalog(), change_catalog() and close_catalog() - template lmo: rewrite index processing to operate directly on the memory mapped file - template lmo: implement binary search keys, reducing the lookup complexity to O(log n) - po2lmo: write sorted indixes when generating *.lmo archives - i18n: use the template parser for translations - i18n: stub load(), loadc() and clear() - i18n: map setlanguage() to load_catalog()
Diffstat (limited to 'libs/lmo/src')
-rw-r--r--libs/lmo/src/lmo.h72
-rw-r--r--libs/lmo/src/lmo_core.c234
-rw-r--r--libs/lmo/src/lmo_hash.c53
-rw-r--r--libs/lmo/src/lmo_lookup.c58
-rw-r--r--libs/lmo/src/lmo_lualib.c263
-rw-r--r--libs/lmo/src/lmo_lualib.h43
-rw-r--r--libs/lmo/src/lmo_po2lmo.c226
7 files changed, 0 insertions, 949 deletions
diff --git a/libs/lmo/src/lmo.h b/libs/lmo/src/lmo.h
deleted file mode 100644
index ab17e873f..000000000
--- a/libs/lmo/src/lmo.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * lmo - Lua Machine Objects - General header
- *
- * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _LMO_H_
-#define _LMO_H_
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <errno.h>
-
-
-#if (defined(__GNUC__) && defined(__i386__))
-#define sfh_get16(d) (*((const uint16_t *) (d)))
-#else
-#define sfh_get16(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
- +(uint32_t)(((const uint8_t *)(d))[0]) )
-#endif
-
-
-struct lmo_entry {
- uint32_t key_id;
- uint32_t val_id;
- uint32_t offset;
- uint32_t length;
- struct lmo_entry *next;
-} __attribute__((packed));
-
-typedef struct lmo_entry lmo_entry_t;
-
-
-struct lmo_archive {
- int fd;
- uint32_t length;
- lmo_entry_t *index;
- char *mmap;
-};
-
-typedef struct lmo_archive lmo_archive_t;
-
-
-uint32_t sfh_hash(const char * data, int len);
-
-char _lmo_error[1024];
-const char * lmo_error(void);
-
-lmo_archive_t * lmo_open(const char *file);
-int lmo_lookup(lmo_archive_t *ar, const char *key, char *dest, int len);
-void lmo_close(lmo_archive_t *ar);
-
-#endif
diff --git a/libs/lmo/src/lmo_core.c b/libs/lmo/src/lmo_core.c
deleted file mode 100644
index 08141383e..000000000
--- a/libs/lmo/src/lmo_core.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * lmo - Lua Machine Objects - Base functions
- *
- * Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "lmo.h"
-
-extern char _lmo_error[1024];
-
-static int lmo_read32( int fd, uint32_t *val )
-{
- if( read(fd, val, 4) < 4 )
- return -1;
-
- *val = ntohl(*val);
-
- return 4;
-}
-
-static char * error(const char *message, int add_errno)
-{
- memset(_lmo_error, 0, sizeof(_lmo_error));
-
- if( add_errno )
- snprintf(_lmo_error, sizeof(_lmo_error),
- "%s: %s", message, strerror(errno));
- else
- snprintf(_lmo_error, sizeof(_lmo_error), "%s", message);
-
- return NULL;
-}
-
-const char * lmo_error(void)
-{
- return _lmo_error;
-}
-
-lmo_archive_t * lmo_open(const char *file)
-{
- int in = -1;
- uint32_t idx_offset = 0;
- uint32_t i;
- struct stat s;
-
- lmo_archive_t *ar = NULL;
- lmo_entry_t *head = NULL;
- lmo_entry_t *entry = NULL;
-
- if( stat(file, &s) == -1 )
- {
- error("Can not stat file", 1);
- goto cleanup;
- }
-
- if( (in = open(file, O_RDONLY)) == -1 )
- {
- error("Can not open file", 1);
- goto cleanup;
- }
-
- if( lseek(in, -sizeof(uint32_t), SEEK_END) == -1 )
- {
- error("Can not seek to eof", 1);
- goto cleanup;
- }
-
- if( lmo_read32(in, &idx_offset) != 4 )
- {
- error("Unexpected EOF while reading index offset", 0);
- goto cleanup;
- }
-
- if( lseek(in, (off_t)idx_offset, SEEK_SET) == -1 )
- {
- error("Can not seek to index offset", 1);
- goto cleanup;
- }
-
- if( (ar = (lmo_archive_t *) malloc(sizeof(lmo_archive_t))) != NULL )
- {
- ar->fd = in;
- ar->length = idx_offset;
-
- fcntl(ar->fd, F_SETFD, fcntl(ar->fd, F_GETFD) | FD_CLOEXEC);
-
- for( i = idx_offset;
- i < (s.st_size - sizeof(uint32_t));
- i += (4 * sizeof(uint32_t))
- ) {
- if( (entry = (lmo_entry_t *) malloc(sizeof(lmo_entry_t))) != NULL )
- {
- if( (lmo_read32(ar->fd, &entry->key_id) == 4) &&
- (lmo_read32(ar->fd, &entry->val_id) == 4) &&
- (lmo_read32(ar->fd, &entry->offset) == 4) &&
- (lmo_read32(ar->fd, &entry->length) == 4)
- ) {
- entry->next = head;
- head = entry;
- }
- else
- {
- error("Unexpected EOF while reading index entry", 0);
- goto cleanup;
- }
- }
- else
- {
- error("Out of memory", 0);
- goto cleanup;
- }
- }
-
- ar->index = head;
-
- if( lseek(ar->fd, 0, SEEK_SET) == -1 )
- {
- error("Can not seek to start", 1);
- goto cleanup;
- }
-
- if( (ar->mmap = mmap(NULL, ar->length, PROT_READ, MAP_PRIVATE, ar->fd, 0)) == MAP_FAILED )
- {
- error("Failed to memory map archive contents", 1);
- goto cleanup;
- }
-
- return ar;
- }
- else
- {
- error("Out of memory", 0);
- goto cleanup;
- }
-
-
- cleanup:
-
- if( in > -1 )
- close(in);
-
- if( head != NULL )
- {
- entry = head;
-
- while( entry != NULL )
- {
- head = entry->next;
- free(entry);
- entry = head;
- }
-
- head = entry = NULL;
- }
-
- if( ar != NULL )
- {
- if( (ar->mmap != NULL) && (ar->mmap != MAP_FAILED) )
- munmap(ar->mmap, ar->length);
-
- free(ar);
- ar = NULL;
- }
-
- return NULL;
-}
-
-void lmo_close(lmo_archive_t *ar)
-{
- lmo_entry_t *head = NULL;
- lmo_entry_t *entry = NULL;
-
- if( ar != NULL )
- {
- entry = ar->index;
-
- while( entry != NULL )
- {
- head = entry->next;
- free(entry);
- entry = head;
- }
-
- head = entry = NULL;
-
- if( (ar->mmap != NULL) && (ar->mmap != MAP_FAILED) )
- munmap(ar->mmap, ar->length);
-
- close(ar->fd);
- free(ar);
-
- ar = NULL;
- }
-}
-
-int lmo_lookup(lmo_archive_t *ar, const char *key, char *dest, int len)
-{
- uint32_t look_key = sfh_hash(key, strlen(key));
- int copy_len = -1;
- lmo_entry_t *entry;
-
- if( !ar )
- return copy_len;
-
- entry = ar->index;
-
- while( entry != NULL )
- {
- if( entry->key_id == look_key )
- {
- copy_len = ((len - 1) > entry->length) ? entry->length : (len - 1);
- memcpy(dest, &ar->mmap[entry->offset], copy_len);
- dest[copy_len] = '\0';
-
- break;
- }
-
- entry = entry->next;
- }
-
- return copy_len;
-}
diff --git a/libs/lmo/src/lmo_hash.c b/libs/lmo/src/lmo_hash.c
deleted file mode 100644
index bc8e6fe4e..000000000
--- a/libs/lmo/src/lmo_hash.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Hash function from http://www.azillionmonkeys.com/qed/hash.html
- * Copyright (C) 2004-2008 by Paul Hsieh
- */
-
-#include "lmo.h"
-
-uint32_t sfh_hash(const char * data, int len)
-{
- uint32_t hash = len, tmp;
- int rem;
-
- if (len <= 0 || data == NULL) return 0;
-
- rem = len & 3;
- len >>= 2;
-
- /* Main loop */
- for (;len > 0; len--) {
- hash += sfh_get16(data);
- tmp = (sfh_get16(data+2) << 11) ^ hash;
- hash = (hash << 16) ^ tmp;
- data += 2*sizeof(uint16_t);
- hash += hash >> 11;
- }
-
- /* Handle end cases */
- switch (rem) {
- case 3: hash += sfh_get16(data);
- hash ^= hash << 16;
- hash ^= data[sizeof(uint16_t)] << 18;
- hash += hash >> 11;
- break;
- case 2: hash += sfh_get16(data);
- hash ^= hash << 11;
- hash += hash >> 17;
- break;
- case 1: hash += *data;
- hash ^= hash << 10;
- hash += hash >> 1;
- }
-
- /* Force "avalanching" of final 127 bits */
- hash ^= hash << 3;
- hash += hash >> 5;
- hash ^= hash << 4;
- hash += hash >> 17;
- hash ^= hash << 25;
- hash += hash >> 6;
-
- return hash;
-}
-
diff --git a/libs/lmo/src/lmo_lookup.c b/libs/lmo/src/lmo_lookup.c
deleted file mode 100644
index 8b48f7fac..000000000
--- a/libs/lmo/src/lmo_lookup.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * lmo - Lua Machine Objects - Lookup utility
- *
- * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "lmo.h"
-
-extern char _lmo_error[1024];
-
-static void die(const char *msg)
-{
- printf("Error: %s\n", msg);
- exit(1);
-}
-
-static void usage(const char *name)
-{
- printf("Usage: %s input.lmo key\n", name);
- exit(1);
-}
-
-int main(int argc, char *argv[])
-{
- char val[4096];
- lmo_archive_t *ar = NULL;
-
- if( argc != 3 )
- usage(argv[0]);
-
- if( (ar = (lmo_archive_t *) lmo_open(argv[1])) != NULL )
- {
- if( lmo_lookup(ar, argv[2], val, sizeof(val)) > -1 )
- {
- printf("%s\n", val);
- }
-
- lmo_close(ar);
- }
- else
- {
- die(lmo_error());
- }
-
- return 0;
-}
diff --git a/libs/lmo/src/lmo_lualib.c b/libs/lmo/src/lmo_lualib.c
deleted file mode 100644
index 5cc1e7d69..000000000
--- a/libs/lmo/src/lmo_lualib.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * lmo - Lua Machine Objects - Lua binding
- *
- * Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "lmo_lualib.h"
-
-extern char _lmo_error[1024];
-
-
-static int lmo_L_open(lua_State *L) {
- const char *filename = luaL_checklstring(L, 1, NULL);
- lmo_archive_t *ar, **udata;
-
- if( (ar = lmo_open(filename)) != NULL )
- {
- if( (udata = lua_newuserdata(L, sizeof(lmo_archive_t *))) != NULL )
- {
- *udata = ar;
- luaL_getmetatable(L, LMO_ARCHIVE_META);
- lua_setmetatable(L, -2);
- return 1;
- }
-
- lmo_close(ar);
- lua_pushnil(L);
- lua_pushstring(L, "out of memory");
- return 2;
- }
-
- lua_pushnil(L);
- lua_pushstring(L, lmo_error());
- return 2;
-}
-
-static uint32_t _lmo_hash_string(lua_State *L, int n) {
- size_t len;
- const char *str = luaL_checklstring(L, n, &len);
- char res[4096];
- char *ptr, prev;
-
- if (!str || len >= sizeof(res))
- return 0;
-
- for (prev = ' ', ptr = res; *str; prev = *str, str++)
- {
- if (isspace(*str))
- {
- if (!isspace(prev))
- *ptr++ = ' ';
- }
- else
- {
- *ptr++ = *str;
- }
- }
-
- if ((ptr > res) && isspace(*(ptr-1)))
- ptr--;
-
- return sfh_hash(res, ptr - res);
-}
-
-static int lmo_L_hash(lua_State *L) {
- uint32_t hash = _lmo_hash_string(L, 1);
- lua_pushinteger(L, (lua_Integer)hash);
- return 1;
-}
-
-static lmo_luaentry_t *_lmo_push_entry(lua_State *L) {
- lmo_luaentry_t *le;
-
- if( (le = lua_newuserdata(L, sizeof(lmo_luaentry_t))) != NULL )
- {
- luaL_getmetatable(L, LMO_ENTRY_META);
- lua_setmetatable(L, -2);
-
- return le;
- }
-
- return NULL;
-}
-
-static int _lmo_lookup(lua_State *L, lmo_archive_t *ar, uint32_t hash) {
- lmo_entry_t *e = ar->index;
- lmo_luaentry_t *le = NULL;
-
- while( e != NULL )
- {
- if( e->key_id == hash )
- {
- if( (le = _lmo_push_entry(L)) != NULL )
- {
- le->archive = ar;
- le->entry = e;
- return 1;
- }
- else
- {
- lua_pushnil(L);
- lua_pushstring(L, "out of memory");
- return 2;
- }
- }
-
- e = e->next;
- }
-
- lua_pushnil(L);
- return 1;
-}
-
-static int lmo_L_get(lua_State *L) {
- lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
- uint32_t hash = (uint32_t) luaL_checkinteger(L, 2);
- return _lmo_lookup(L, *ar, hash);
-}
-
-static int lmo_L_lookup(lua_State *L) {
- lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
- uint32_t hash = _lmo_hash_string(L, 2);
- return _lmo_lookup(L, *ar, hash);
-}
-
-static int lmo_L_foreach(lua_State *L) {
- lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
- lmo_entry_t *e = (*ar)->index;
-
- if( lua_isfunction(L, 2) )
- {
- while( e != NULL )
- {
- lua_pushvalue(L, 2);
- lua_pushinteger(L, e->key_id);
- lua_pushlstring(L, &(*ar)->mmap[e->offset], e->length);
- lua_pcall(L, 2, 0, 0);
- e = e->next;
- }
- }
-
- return 0;
-}
-
-static int lmo_L__gc(lua_State *L) {
- lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
-
- if( (*ar) != NULL )
- lmo_close(*ar);
-
- *ar = NULL;
-
- return 0;
-}
-
-static int lmo_L__tostring(lua_State *L) {
- lmo_archive_t **ar = luaL_checkudata(L, 1, LMO_ARCHIVE_META);
- lua_pushfstring(L, "LMO Archive (%d bytes)", (*ar)->length);
- return 1;
-}
-
-
-static int _lmo_convert_entry(lua_State *L, int idx) {
- lmo_luaentry_t *le = luaL_checkudata(L, idx, LMO_ENTRY_META);
-
- lua_pushlstring(L,
- &le->archive->mmap[le->entry->offset],
- le->entry->length
- );
-
- return 1;
-}
-
-static int lmo_L_entry__tostring(lua_State *L) {
- return _lmo_convert_entry(L, 1);
-}
-
-static int lmo_L_entry__concat(lua_State *L) {
- if( lua_isuserdata(L, 1) )
- _lmo_convert_entry(L, 1);
- else
- lua_pushstring(L, lua_tostring(L, 1));
-
- if( lua_isuserdata(L, 2) )
- _lmo_convert_entry(L, 2);
- else
- lua_pushstring(L, lua_tostring(L, 2));
-
- lua_concat(L, 2);
-
- return 1;
-}
-
-static int lmo_L_entry__len(lua_State *L) {
- lmo_luaentry_t *le = luaL_checkudata(L, 1, LMO_ENTRY_META);
- lua_pushinteger(L, le->entry->length);
- return 1;
-}
-
-static int lmo_L_entry__gc(lua_State *L) {
- lmo_luaentry_t *le = luaL_checkudata(L, 1, LMO_ENTRY_META);
- le->archive = NULL;
- le->entry = NULL;
- return 0;
-}
-
-
-/* lmo method table */
-static const luaL_reg M[] = {
- {"close", lmo_L__gc},
- {"get", lmo_L_get},
- {"lookup", lmo_L_lookup},
- {"foreach", lmo_L_foreach},
- {"__tostring", lmo_L__tostring},
- {"__gc", lmo_L__gc},
- {NULL, NULL}
-};
-
-/* lmo.entry method table */
-static const luaL_reg E[] = {
- {"__tostring", lmo_L_entry__tostring},
- {"__concat", lmo_L_entry__concat},
- {"__len", lmo_L_entry__len},
- {"__gc", lmo_L_entry__gc},
- {NULL, NULL}
-};
-
-/* module table */
-static const luaL_reg R[] = {
- {"open", lmo_L_open},
- {"hash", lmo_L_hash},
- {NULL, NULL}
-};
-
-LUALIB_API int luaopen_lmo(lua_State *L) {
- luaL_newmetatable(L, LMO_ARCHIVE_META);
- luaL_register(L, NULL, M);
- lua_pushvalue(L, -1);
- lua_setfield(L, -2, "__index");
- lua_setglobal(L, LMO_ARCHIVE_META);
-
- luaL_newmetatable(L, LMO_ENTRY_META);
- luaL_register(L, NULL, E);
- lua_pushvalue(L, -1);
- lua_setfield(L, -2, "__index");
- lua_setglobal(L, LMO_ENTRY_META);
-
- luaL_register(L, LMO_LUALIB_META, R);
-
- return 1;
-}
diff --git a/libs/lmo/src/lmo_lualib.h b/libs/lmo/src/lmo_lualib.h
deleted file mode 100644
index 887889d04..000000000
--- a/libs/lmo/src/lmo_lualib.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * lmo - Lua Machine Objects - Lua library header
- *
- * Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _LMO_LUALIB_H_
-#define _LMO_LUALIB_H_
-
-#include <lua.h>
-#include <lualib.h>
-#include <lauxlib.h>
-#include <ctype.h>
-
-#include "lmo.h"
-
-#define LMO_LUALIB_META "lmo"
-#define LMO_ARCHIVE_META "lmo.archive"
-#define LMO_ENTRY_META "lmo.entry"
-
-struct lmo_luaentry {
- lmo_archive_t *archive;
- lmo_entry_t *entry;
-};
-
-typedef struct lmo_luaentry lmo_luaentry_t;
-
-
-LUALIB_API int luaopen_lmo(lua_State *L);
-
-#endif
diff --git a/libs/lmo/src/lmo_po2lmo.c b/libs/lmo/src/lmo_po2lmo.c
deleted file mode 100644
index f6f399423..000000000
--- a/libs/lmo/src/lmo_po2lmo.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * lmo - Lua Machine Objects - PO to LMO conversion tool
- *
- * Copyright (C) 2009-2011 Jo-Philipp Wich <xm@subsignal.org>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "lmo.h"
-
-static void die(const char *msg)
-{
- fprintf(stderr, "Error: %s\n", msg);
- exit(1);
-}
-
-static void usage(const char *name)
-{
- fprintf(stderr, "Usage: %s input.po output.lmo\n", name);
- exit(1);
-}
-
-static void print(const void *ptr, size_t size, size_t nmemb, FILE *stream)
-{
- if( fwrite(ptr, size, nmemb, stream) == 0 )
- die("Failed to write stdout");
-}
-
-static int extract_string(const char *src, char *dest, int len)
-{
- int pos = 0;
- int esc = 0;
- int off = -1;
-
- for( pos = 0; (pos < strlen(src)) && (pos < len); pos++ )
- {
- if( (off == -1) && (src[pos] == '"') )
- {
- off = pos + 1;
- }
- else if( off >= 0 )
- {
- if( esc == 1 )
- {
- switch (src[pos])
- {
- case '"':
- case '\\':
- off++;
- break;
- }
- dest[pos-off] = src[pos];
- esc = 0;
- }
- else if( src[pos] == '\\' )
- {
- dest[pos-off] = src[pos];
- esc = 1;
- }
- else if( src[pos] != '"' )
- {
- dest[pos-off] = src[pos];
- }
- else
- {
- dest[pos-off] = '\0';
- break;
- }
- }
- }
-
- return (off > -1) ? strlen(dest) : -1;
-}
-
-int main(int argc, char *argv[])
-{
- char line[4096];
- char key[4096];
- char val[4096];
- char tmp[4096];
- int state = 0;
- int offset = 0;
- int length = 0;
- uint32_t key_id, val_id;
-
- FILE *in;
- FILE *out;
-
- lmo_entry_t *head = NULL;
- lmo_entry_t *entry = NULL;
-
- if( (argc != 3) || ((in = fopen(argv[1], "r")) == NULL) || ((out = fopen(argv[2], "w")) == NULL) )
- usage(argv[0]);
-
- memset(line, 0, sizeof(key));
- memset(key, 0, sizeof(val));
- memset(val, 0, sizeof(val));
-
- while( (NULL != fgets(line, sizeof(line), in)) || (state >= 2 && feof(in)) )
- {
- if( state == 0 && strstr(line, "msgid \"") == line )
- {
- switch(extract_string(line, key, sizeof(key)))
- {
- case -1:
- die("Syntax error in msgid");
- case 0:
- state = 1;
- break;
- default:
- state = 2;
- }
- }
- else if( state == 1 || state == 2 )
- {
- if( strstr(line, "msgstr \"") == line || state == 2 )
- {
- switch(extract_string(line, val, sizeof(val)))
- {
- case -1:
- state = 4;
- break;
- default:
- state = 3;
- }
- }
- else
- {
- switch(extract_string(line, tmp, sizeof(tmp)))
- {
- case -1:
- state = 2;
- break;
- default:
- strcat(key, tmp);
- }
- }
- }
- else if( state == 3 )
- {
- switch(extract_string(line, tmp, sizeof(tmp)))
- {
- case -1:
- state = 4;
- break;
- default:
- strcat(val, tmp);
- }
- }
-
- if( state == 4 )
- {
- if( strlen(key) > 0 && strlen(val) > 0 )
- {
- key_id = sfh_hash(key, strlen(key));
- val_id = sfh_hash(val, strlen(val));
-
- if( key_id != val_id )
- {
- if( (entry = (lmo_entry_t *) malloc(sizeof(lmo_entry_t))) != NULL )
- {
- memset(entry, 0, sizeof(entry));
- length = strlen(val) + ((4 - (strlen(val) % 4)) % 4);
-
- entry->key_id = htonl(key_id);
- entry->val_id = htonl(val_id);
- entry->offset = htonl(offset);
- entry->length = htonl(strlen(val));
-
- print(val, length, 1, out);
- offset += length;
-
- entry->next = head;
- head = entry;
- }
- else
- {
- die("Out of memory");
- }
- }
- }
-
- state = 0;
- memset(key, 0, sizeof(key));
- memset(val, 0, sizeof(val));
- }
-
- memset(line, 0, sizeof(line));
- }
-
- entry = head;
- while( entry != NULL )
- {
- print(&entry->key_id, sizeof(uint32_t), 1, out);
- print(&entry->val_id, sizeof(uint32_t), 1, out);
- print(&entry->offset, sizeof(uint32_t), 1, out);
- print(&entry->length, sizeof(uint32_t), 1, out);
- entry = entry->next;
- }
-
- if( offset > 0 )
- {
- offset = htonl(offset);
- print(&offset, sizeof(uint32_t), 1, out);
- fsync(fileno(out));
- fclose(out);
- }
- else
- {
- fclose(out);
- unlink(argv[2]);
- }
-
- fclose(in);
- return(0);
-}