1,9 → 1,11 |
/* |
* Copyright (C) 2021-2023 Mateusz Viste |
* |
* Dictionary-based lookups contributed by Bernd Boeckmann, 2023 |
* |
* usage: tlumacz en fr pl etc |
* |
* computes an out.lng file that contains all language ressources. |
* computes an out.lng file that contains all language resources. |
* |
*/ |
|
119,20 → 121,18 |
} svl_lang_t; |
|
|
static svl_lang_t * svl_lang_new(char langid[2], size_t dict_cap, size_t strings_cap) |
{ |
static svl_lang_t *svl_lang_new(const char langid[2], size_t dict_cap, size_t strings_cap) { |
svl_lang_t *l; |
|
l = malloc(sizeof(svl_lang_t)); |
if (!l) return NULL; |
if (!l) return(NULL); |
|
l->id[0] = (char)toupper(langid[0]); |
l->id[1] = (char)toupper(langid[1]); |
|
l->dict = malloc(dict_cap * sizeof(dict_entry_t)); |
if (!l->dict) { |
return NULL; |
} |
if (!l->dict) return(NULL); |
|
l->dict_cap = dict_cap; |
|
l->num_strings = 0; |
139,16 → 139,16 |
l->strings = l->strings_end = malloc(strings_cap); |
if (!l->strings) { |
free(l->dict); |
return NULL; |
return(NULL); |
} |
l->strings_cap = strings_cap; |
return l; |
|
return(l); |
} |
|
|
/* compacts the dict and string buffer */ |
static void svl_compact_lang(svl_lang_t *l) |
{ |
static void svl_compact_lang(svl_lang_t *l) { |
size_t bytes; |
bytes = l->strings_end - l->strings; |
if (bytes < l->strings_cap) { |
161,8 → 161,7 |
} |
|
|
static void svl_lang_free(svl_lang_t *l) |
{ |
static void svl_lang_free(svl_lang_t *l) { |
l->num_strings = 0; |
if (l->dict) { |
free(l->dict); |
177,26 → 176,22 |
} |
|
|
static size_t svl_strings_bytes(svl_lang_t *l) |
{ |
return l->strings_end - l->strings; |
static size_t svl_strings_bytes(const svl_lang_t *l) { |
return(l->strings_end - l->strings); |
} |
|
|
static size_t svl_dict_bytes(svl_lang_t *l) |
{ |
return l->num_strings * sizeof(dict_entry_t); |
static size_t svl_dict_bytes(const svl_lang_t *l) { |
return(l->num_strings * sizeof(dict_entry_t)); |
} |
|
|
static int svl_add_str(svl_lang_t *l, unsigned short id, const char *s) |
{ |
static int svl_add_str(svl_lang_t *l, unsigned short id, const char *s) { |
size_t len = strlen(s) + 1; |
size_t cursor; |
|
if (l->strings_cap < svl_strings_bytes(l) + len || |
l->dict_cap < (l->num_strings + 1) * sizeof(dict_entry_t)) { |
return 0; |
if ((l->strings_cap < svl_strings_bytes(l) + len) || (l->dict_cap < (l->num_strings + 1) * sizeof(dict_entry_t))) { |
return(0); |
} |
|
/* find dictionary insert position, search backwards in assumption |
211,27 → 206,31 |
l->strings_end += len; |
l->num_strings++; |
|
return 1; |
return(1); |
} |
|
|
static int svl_find(svl_lang_t *l, unsigned short id) |
{ |
static int svl_find(const svl_lang_t *l, unsigned short id) { |
size_t left = 0, right = l->num_strings - 1, x; |
unsigned short v; |
|
if (l->num_strings == 0) return 0; |
if (l->num_strings == 0) return(0); |
|
while (left <= right ) { |
x = left + ( (right - left ) >> 2 ); |
v = l->dict[x].id; |
if ( id == v ) return 1; |
else if ( id > v ) left = x + 1; |
else right = x - 1; |
if ( id == v ) { |
return(1); |
} else if (id > v) { |
left = x + 1; |
} else { |
right = x - 1; |
} |
return 0; |
} |
return(0); |
} |
|
|
/* opens a CATS-style file and compiles it into a ressources lang block |
* returns 0 on error, or the size of the generated data block otherwise */ |
static unsigned short svl_lang_from_cats_file(svl_lang_t *l, svl_lang_t *refl) { |
283,25 → 282,22 |
|
/* add the string contained in current line, if conditions are met */ |
if (!svl_find(l, id)) { |
if (refl == NULL || svl_find(refl, id)) { |
if ((refl == NULL) || (svl_find(refl, id))) { |
if (!svl_add_str(l, id, ptr)) { |
printf("ERROR: %s[#%u] output size limit exceeded\r\n", fname, linecount); |
fclose(fd); |
return 0; |
return(0); |
} |
if (id >= maxid) { |
maxid = id; |
maxid_line = linecount; |
} |
else { |
} else { |
printf("WARNING:%s[#%u] file unsorted - line %u has higher id %u.%u\r\n", fname, linecount, maxid_line, maxid >> 8, maxid & 0xff); |
} |
} |
else { |
} else { |
printf("WARNING: %s[#%u] has an invalid id (%u.%u not present in ref lang)\r\n", fname, linecount, id >> 8, id & 0xff); |
} |
} |
else { |
} else { |
printf("WARNING: %s[#%u] has a duplicated id (%u.%u)\r\n", fname, linecount, id >> 8, id & 0xff); |
} |
} |
316,7 → 312,7 |
printf("WARNING: %s is missing string %u.%u (pulled from ref lang)\r\n", fname, id >> 8, id & 0xff); |
if (!svl_add_str(l, id, refl->strings + refl->dict[i].offset)) { |
printf("ERROR: %s[#%u] output size limit exceeded\r\n", fname, linecount); |
return 0; |
return(0); |
} |
} |
} |
326,47 → 322,45 |
} |
|
|
static int svl_write_header(unsigned short num_strings, FILE *fd) |
{ |
return (fwrite("SvL\x1a", 1, 4, fd) == 4) && |
(fwrite(&num_strings, 1, 2, fd) == 2); |
static int svl_write_header(unsigned short num_strings, FILE *fd) { |
return((fwrite("SvL\x1a", 1, 4, fd) == 4) && (fwrite(&num_strings, 1, 2, fd) == 2)); |
} |
|
|
static int svl_write_lang(svl_lang_t *l, FILE *fd) |
{ |
static int svl_write_lang(const svl_lang_t *l, FILE *fd) { |
unsigned short strings_bytes = svl_strings_bytes(l); |
|
return (fwrite(&l->id, 1, 2, fd) == 2) && |
return((fwrite(&l->id, 1, 2, fd) == 2) && |
(fwrite(&strings_bytes, 1, 2, fd) == 2) && |
(fwrite(l->dict, 1, svl_dict_bytes(l), fd) == svl_dict_bytes(l)) && |
(fwrite(l->strings, 1, svl_strings_bytes(l), fd) == svl_strings_bytes(l)); |
(fwrite(l->strings, 1, svl_strings_bytes(l), fd) == svl_strings_bytes(l))); |
} |
|
|
static int svl_write_c_source(svl_lang_t *l, const char *fn, unsigned short biggest_langsz) |
{ |
static int svl_write_c_source(const svl_lang_t *l, const char *fn, unsigned short biggest_langsz) { |
FILE *fd; |
int i; |
unsigned short strings_bytes = svl_strings_bytes(l); |
unsigned short nextnlat = 0; |
unsigned short allocsz; |
|
fd = fopen(fn, "wb"); |
if (fd == NULL) { |
puts("ERROR: FAILED TO OPEN OR CREATE DEFLANG.C"); |
return 0; |
} else { |
unsigned short allocsz = biggest_langsz + (biggest_langsz / 20); |
printf("biggest lang block is %u bytes -> allocating a %u bytes buffer (5%% safety margin)\n", biggest_langsz, |
allocsz); |
return(0); |
} |
|
allocsz = biggest_langsz + (biggest_langsz / 20); |
printf("biggest lang block is %u bytes -> allocating a %u bytes buffer (5%% safety margin)\n", biggest_langsz, allocsz); |
fprintf(fd, "/* THIS FILE HAS BEEN GENERATED BY TLUMACZ (PART OF THE SVARLANG LIBRARY) */\r\n"); |
fprintf(fd, "const unsigned short svarlang_memsz = %uu;\r\n", allocsz); |
fprintf(fd, "const unsigned short svarlang_string_count = %uu;\r\n\r\n", l->num_strings); |
fprintf(fd, "char svarlang_mem[%u] = {\r\n", allocsz); |
|
for (i = 0; i < strings_bytes; i++) { |
if (!fprintf(fd, "0x%02x", l->strings[i])) { |
fclose(fd); |
return 0; |
return(0); |
} |
|
if (i + 1 < strings_bytes) fprintf(fd, ","); |
382,7 → 376,7 |
for (i = 0; i < l->num_strings; i++) { |
if (!fprintf(fd, "0x%04x,0x%04x", l->dict[i].id, l->dict[i].offset)) { |
fclose(fd); |
return 0; |
return(0); |
} |
if (i + 1 < l->num_strings) fprintf(fd, ","); |
fprintf(fd, "\r\n"); |
390,9 → 384,8 |
fprintf(fd, "};\r\n"); |
|
fclose(fd); |
} |
|
return 1; |
return(1); |
} |
|
|
399,10 → 392,9 |
int main(int argc, char **argv) { |
FILE *fd; |
int ecode = 0; |
svl_lang_t *lang, *reflang = NULL; |
|
int i; |
unsigned short biggest_langsz = 0; |
svl_lang_t *lang, *reflang = NULL; |
|
if (argc < 2) { |
puts("tlumacz ver " SVARLANGVER " - this tool is part of the SvarLANG project."); |
469,8 → 461,7 |
/* remember reference data for other languages */ |
if (i == 1) { |
reflang = lang; |
} |
else { |
} else { |
svl_lang_free(lang); |
lang = NULL; |
} |