Subversion Repositories SvarDOS

Rev

Rev 1272 | Rev 1291 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1272 Rev 1290
Line 3... Line 3...
3
 *
3
 *
4
 * usage: tlumacz en fr pl etc
4
 * usage: tlumacz en fr pl etc
5
 *
5
 *
6
 * computes an out.lng file that contains all language ressources.
6
 * computes an out.lng file that contains all language ressources.
7
 *
7
 *
8
 * DAT format:
-
 
9
 *
-
 
10
 * 4-bytes signature:
-
 
11
 * "SvL\x1b"
-
 
12
 *
-
 
13
 * Then "LANG BLOCKS" follow. Each LANG BLOCK is prefixed with 4 bytes:
-
 
14
 * II LL    - II is the LANG identifier ("EN", "PL", etc) and LL is the size
-
 
15
 *            of the block (65535 bytes max).
-
 
16
 *
-
 
17
 * Inside a LANG BLOCK is a set of strings:
-
 
18
 *
-
 
19
 * II LL S  where II is the string's 16-bit identifier, LL is its length
-
 
20
 *          (1-65535) and S is the actual string. All strings are ASCIIZ (ie.
-
 
21
 *          they end with a NULL terminator).
-
 
22
 *
-
 
23
 * The list of strings ends with a single 0-long string.
-
 
24
 */
8
 */
25
 
9
 
26
 
10
 
27
#include <stdio.h>
11
#include <stdio.h>
28
#include <stdlib.h>
12
#include <stdlib.h>
29
#include <string.h>
13
#include <string.h>
-
 
14
#include <ctype.h>
30
 
15
 
31
#include "svarlang.h"
16
#include "svarlang.h"
32
 
17
 
33
 
-
 
34
struct bitmap {
-
 
35
  unsigned char bits[8192];
-
 
36
};
-
 
37
 
-
 
38
static void bitmap_set(struct bitmap *b, unsigned short id) {
18
#define STRINGS_CAP 65000   /* string storage size in characters */
39
  b->bits[id >> 3] |= 1 << (id & 7);
-
 
40
}
-
 
41
 
-
 
42
static int bitmap_get(const struct bitmap *b, unsigned short id) {
19
#define DICT_CAP    10000   /* dictionary size in elements */ 
43
  return(b->bits[id >> 3] & (1 << (id & 7)));
-
 
44
}
-
 
45
 
-
 
46
static void bitmap_init(struct bitmap *b) {
-
 
47
  bzero(b, sizeof(struct bitmap));
-
 
48
}
-
 
49
 
-
 
50
 
-
 
51
 
20
 
52
/* read a single line from fd and fills it into dst, returns line length
21
/* read a single line from fd and fills it into dst, returns line length
53
 * ending CR/LF is trimmed, as well as any trailing spaces */
22
 * ending CR/LF is trimmed, as well as any trailing spaces */
54
static unsigned short readl(char *dst, size_t dstsz, FILE *fd) {
23
static unsigned short readl(char *dst, size_t dstsz, FILE *fd) {
55
  unsigned short l, lastnonspace = 0;
24
  unsigned short l, lastnonspace = 0;
56
 
25
 
57
  if (fgets(dst, dstsz, fd) == NULL) return(0xffff); /* EOF */
26
  if (fgets(dst, (int)dstsz, fd) == NULL) return(0xffff); /* EOF */
58
  /* trim at first CR or LF and return len */
27
  /* trim at first CR or LF and return len */
59
  for (l = 0; (dst[l] != 0) && (dst[l] != '\r') && (dst[l] != '\n'); l++) {
28
  for (l = 0; (dst[l] != 0) && (dst[l] != '\r') && (dst[l] != '\n'); l++) {
60
    if (dst[l] != ' ') lastnonspace = l;
29
    if (dst[l] != ' ') lastnonspace = l;
61
  }
30
  }
62
 
31
 
Line 107... Line 76...
107
 * the new length of the string. */
76
 * the new length of the string. */
108
static unsigned short unesc_string(char *linebuff) {
77
static unsigned short unesc_string(char *linebuff) {
109
  unsigned short i;
78
  unsigned short i;
110
  for (i = 0; linebuff[i] != 0; i++) {
79
  for (i = 0; linebuff[i] != 0; i++) {
111
    if (linebuff[i] != '\\') continue;
80
    if (linebuff[i] != '\\') continue;
112
    strcpy(linebuff + i, linebuff + i + 1);
81
    memmove(linebuff + i, linebuff + i + 1, strlen(linebuff + i));
113
    if (linebuff[i] == 0) break;
82
    if (linebuff[i] == 0) break;
114
    switch (linebuff[i]) {
83
    switch (linebuff[i]) {
115
      case 'e':
84
      case 'e':
116
        linebuff[i] = 0x1B; /* ESC code, using hex because '\e' is not ANSI C */
85
        linebuff[i] = 0x1B; /* ESC code, using hex because '\e' is not ANSI C */
117
        break;
86
        break;
Line 127... Line 96...
127
    }
96
    }
128
  }
97
  }
129
  return(i);
98
  return(i);
130
}
99
}
131
 
100
 
-
 
101
#pragma pack(1)
-
 
102
typedef struct dict_entry {
-
 
103
    unsigned short id;
-
 
104
    unsigned short offset;
-
 
105
} dict_entry_t;
-
 
106
#pragma pack()
-
 
107
 
-
 
108
typedef struct svl_lang {
-
 
109
  char id[2];
-
 
110
  unsigned short num_strings;
-
 
111
 
-
 
112
  dict_entry_t *dict;
-
 
113
  size_t dict_cap;
-
 
114
 
-
 
115
  char *strings;
-
 
116
  char *strings_end;
-
 
117
  size_t strings_cap;
-
 
118
 
-
 
119
} svl_lang_t;
-
 
120
 
-
 
121
 
-
 
122
static svl_lang_t * svl_lang_new(char langid[2], size_t dict_cap, size_t strings_cap)
-
 
123
{
-
 
124
  svl_lang_t *l;
-
 
125
 
-
 
126
  l = malloc(sizeof(svl_lang_t));
-
 
127
  if (!l) return NULL;
-
 
128
 
-
 
129
  l->id[0] = (char)toupper(langid[0]);
-
 
130
  l->id[1] = (char)toupper(langid[1]);
-
 
131
 
-
 
132
  l->dict = malloc(dict_cap * sizeof(dict_entry_t));
-
 
133
  if (!l->dict) {
-
 
134
    return NULL;
-
 
135
  }
-
 
136
  l->dict_cap = dict_cap;
-
 
137
 
-
 
138
  l->num_strings = 0;
-
 
139
  l->strings = l->strings_end = malloc(strings_cap);
-
 
140
  if (!l->strings) {
-
 
141
    free(l->dict);
-
 
142
    return NULL;
-
 
143
  }
-
 
144
  l->strings_cap = strings_cap;
-
 
145
  return l;
-
 
146
}
-
 
147
 
-
 
148
 
-
 
149
/* compacts the dict and string buffer */
-
 
150
static void svl_compact_lang(svl_lang_t *l)
-
 
151
{
-
 
152
  size_t bytes;
-
 
153
  bytes = l->strings_end - l->strings;
-
 
154
  if (bytes < l->strings_cap) {
-
 
155
    l->strings = l->strings_end = realloc(l->strings, bytes);
-
 
156
    l->strings_end += bytes;
-
 
157
    l->strings_cap = bytes;
-
 
158
  }
-
 
159
  l->dict_cap = l->num_strings;
-
 
160
  l->dict = realloc(l->dict, l->dict_cap * sizeof(dict_entry_t));
-
 
161
}
-
 
162
 
-
 
163
 
-
 
164
static void svl_lang_free(svl_lang_t *l)
-
 
165
{
-
 
166
  l->num_strings = 0;
-
 
167
  if (l->dict) {
-
 
168
    free(l->dict);
-
 
169
    l->dict = NULL;
-
 
170
  }
-
 
171
  if (l->strings) {
-
 
172
    free(l->strings);
-
 
173
    l->strings = l->strings_end = NULL;
-
 
174
  }
-
 
175
  l->dict_cap = 0;
-
 
176
  l->strings_cap = 0;
-
 
177
}
-
 
178
 
-
 
179
 
-
 
180
static size_t svl_strings_bytes(svl_lang_t *l)
-
 
181
{
-
 
182
  return l->strings_end - l->strings;
-
 
183
}
-
 
184
 
-
 
185
 
-
 
186
static size_t svl_dict_bytes(svl_lang_t *l)
-
 
187
{
-
 
188
  return l->num_strings * sizeof(dict_entry_t);
-
 
189
}
-
 
190
 
-
 
191
 
-
 
192
static int svl_add_str(svl_lang_t *l, unsigned short id, const char *s)
-
 
193
{
-
 
194
  size_t len = strlen(s) + 1;
-
 
195
  size_t cursor;
-
 
196
 
-
 
197
  if (l->strings_cap < svl_strings_bytes(l) + len ||
-
 
198
      l->dict_cap < (l->num_strings + 1) * sizeof(dict_entry_t)) {
-
 
199
    return 0;
-
 
200
  }
-
 
201
  
-
 
202
  /* find dictionary insert position, search backwards in assumption
-
 
203
     that in translation files, strings are generally ordered ascending */
-
 
204
  for (cursor = l->num_strings; cursor > 0 && l->dict[cursor-1].id > id; cursor--);
-
 
205
 
-
 
206
  memmove(&(l->dict[cursor+1]), &(l->dict[cursor]), sizeof(dict_entry_t)*(l->num_strings - cursor));
-
 
207
  l->dict[cursor].id = id;
-
 
208
  l->dict[cursor].offset = l->strings_end - l->strings;
-
 
209
 
-
 
210
  memcpy(l->strings_end, s, len);
-
 
211
  l->strings_end += len;
-
 
212
  l->num_strings++;
-
 
213
 
-
 
214
  return 1;
-
 
215
}
-
 
216
 
-
 
217
 
-
 
218
static int svl_find(svl_lang_t *l, unsigned short id)
-
 
219
{
-
 
220
   size_t left = 0, right = l->num_strings - 1, x;
-
 
221
   unsigned short v;
-
 
222
 
-
 
223
   if (l->num_strings == 0) return 0;
-
 
224
 
-
 
225
   while (left <= right ) {
-
 
226
      x = left + ( (right - left ) >> 2 );
-
 
227
      v = l->dict[x].id;
-
 
228
      if ( id == v ) return 1;
-
 
229
      else if ( id > v ) left = x + 1;
-
 
230
      else right = x - 1;
-
 
231
   }
-
 
232
   return 0;
-
 
233
}
132
 
234
 
133
/* opens a CATS-style file and compiles it into a ressources lang block
235
/* opens a CATS-style file and compiles it into a ressources lang block
134
 * returns 0 on error, or the size of the generated data block otherwise */
236
 * returns 0 on error, or the size of the generated data block otherwise */
135
static unsigned short gen_langstrings(unsigned char *buff, const char *langid, struct bitmap *b, const struct bitmap *refb, const unsigned char *refblock) {
237
static unsigned short svl_lang_from_cats_file(svl_lang_t *l, svl_lang_t *refl) {
136
  unsigned short len = 0, linelen;
238
  unsigned short linelen;
137
  FILE *fd;
239
  FILE *fd;
138
  char fname[] = "XX.TXT";
240
  char fname[] = "xx.txt";
139
  static char linebuf[8192];
241
  static char linebuf[8192];
140
  const char *ptr;
242
  const char *ptr;
141
  unsigned short id, linecount;
243
  unsigned short id, maxid=0, maxid_line, linecount;
142
 
-
 
143
  bitmap_init(b);
244
  int i;
144
 
245
 
145
  memcpy(fname + strlen(fname) - 6, langid, 2);
246
  fname[strlen(fname) - 6] = (char)tolower( l->id[0] );
-
 
247
  fname[strlen(fname) - 5] = (char)tolower( l->id[1] );
146
 
248
 
147
  fd = fopen(fname, "rb");
249
  fd = fopen(fname, "rb");
148
  if (fd == NULL) {
250
  if (fd == NULL) {
149
    printf("ERROR: FAILED TO OPEN '%s'\r\n", fname);
251
    printf("ERROR: FAILED TO OPEN '%s'\r\n", fname);
150
    return(0);
252
    return(0);
151
  }
253
  }
152
 
254
 
153
  for (linecount = 1;; linecount++) {
255
  for (linecount = 1;; linecount++) {
154
 
-
 
155
    linelen = readl(linebuf, sizeof(linebuf), fd);
256
    linelen = readl(linebuf, sizeof(linebuf), fd);
156
    if (linelen == 0xffff) break; /* EOF */
257
    if (linelen == 0xffff) break; /* EOF */
157
    if ((linelen == 0) || (linebuf[0] == '#')) continue;
258
    if ((linelen == 0) || (linebuf[0] == '#')) continue;
158
 
259
 
159
    /* convert escaped chars to actual bytes (\n -> newline, etc) */
260
    /* convert escaped chars to actual bytes (\n -> newline, etc) */
Line 178... Line 279...
178
    /* warn about dirty lines */
279
    /* warn about dirty lines */
179
    if (linebuf[0] == '?') {
280
    if (linebuf[0] == '?') {
180
      printf("WARNING: %s[#%u] string id %u.%u is flagged as 'dirty'\r\n", fname, linecount, id >> 8, id & 0xff);
281
      printf("WARNING: %s[#%u] string id %u.%u is flagged as 'dirty'\r\n", fname, linecount, id >> 8, id & 0xff);
181
    }
282
    }
182
 
283
 
183
    /* write string into block (II LL S) */
284
    /* add the string contained in current line, if conditions are met */
184
    memcpy(buff + len, &id, 2);
285
    if (!svl_find(l, id)) {
-
 
286
      if (refl == NULL || svl_find(refl, id)) {
-
 
287
        if (!svl_add_str(l, id, ptr)) {
-
 
288
          printf("ERROR: %s[#%u] output size limit exceeded\r\n", fname, linecount);
-
 
289
          fclose(fd);
185
    len += 2;
290
          return 0;
186
    {
291
        }
187
      unsigned short slen = strlen(ptr) + 1;
292
        if (id >= maxid) {
-
 
293
          maxid = id;
188
      memcpy(buff + len, &slen, 2);
294
          maxid_line = linecount;
189
      len += 2;
295
        }
190
      memcpy(buff + len, ptr, slen);
296
        else {
-
 
297
          printf("WARNING:%s[#%u] file unsorted - line %u has higher id %u.%u\r\n", fname, linecount, maxid_line, maxid >> 8, maxid & 0xff);          
191
      len += slen;
298
        }
192
    }
299
      }
193
 
-
 
194
    /* if reference bitmap provided: check that the id is valid */
-
 
195
    if ((refb != NULL) && (bitmap_get(refb, id) == 0)) {
300
      else {
196
      printf("WARNING: %s[#%u] has an invalid id (%u.%u not present in ref lang)\r\n", fname, linecount, id >> 8, id & 0xff);
301
        printf("WARNING: %s[#%u] has an invalid id (%u.%u not present in ref lang)\r\n", fname, linecount, id >> 8, id & 0xff);
197
    }
302
      }
198
 
303
    }
199
    /* make sure this id is not already present */
-
 
200
    if (bitmap_get(b, id) == 0) {
-
 
201
      /* set bit in bitmap to remember I have this string */
-
 
202
      bitmap_set(b, id);
-
 
203
    } else {
304
    else {
204
      printf("WARNING: %s[#%u] has a duplicated id (%u.%u)\r\n", fname, linecount, id >> 8, id & 0xff);
305
      printf("WARNING: %s[#%u] has a duplicated id (%u.%u)\r\n", fname, linecount, id >> 8, id & 0xff);      
205
    }
306
    }
206
  }
307
  }
207
 
308
 
208
  fclose(fd);
309
  fclose(fd);
209
 
310
 
210
  /* if refblock provided, pull missing strings from it */
311
  /* if reflang provided, pull missing strings from it */
211
  if (refblock != NULL) {
312
  if (refl != NULL) {
212
    for (;;) {
-
 
213
      unsigned short slen;
-
 
214
      id = ((unsigned short *)refblock)[0];
313
    for (i = 0; i < refl->num_strings; i++) {
215
      slen = ((unsigned short *)refblock)[1];
-
 
216
      if ((id == 0) && (slen == 0)) break;
314
      id = refl->dict[i].id;
217
      if (bitmap_get(b, id) == 0) {
315
      if (!svl_find(l, id)) {
218
        printf("WARNING: %s is missing string %u.%u (pulled from ref lang)\r\n", fname, id >> 8, id & 0xff);
316
        printf("WARNING: %s is missing string %u.%u (pulled from ref lang)\r\n", fname, id >> 8, id & 0xff);
219
        /* copy missing string from refblock */
317
        if (!svl_add_str(l, id, ptr)) {
220
        memcpy(buff + len, refblock, slen + 4);
318
          printf("ERROR: %s[#%u] output size limit exceeded\r\n", fname, linecount);
221
        len += slen + 4;
319
          return 0;
-
 
320
        }
222
      }
321
      }
223
      refblock += slen + 4;
-
 
224
    }
322
    }
225
  }
323
  }
226
 
324
 
227
  /* write the block terminator (0-long string) */
-
 
228
  buff[len++] = 0; /* id */
-
 
229
  buff[len++] = 0; /* id */
325
  return(svl_strings_bytes(l));
230
  buff[len++] = 0; /* len */
-
 
231
  buff[len++] = 0; /* len */
-
 
232
  buff[len++] = 0; /* empty string */
-
 
-
 
326
}
233
 
327
 
-
 
328
 
-
 
329
static int svl_write_header(unsigned short num_strings, FILE *fd)
-
 
330
{
234
  return(len);
331
  return (fwrite("SvL1\x1a", 1, 5, fd) == 5) &&
-
 
332
          (fwrite(&num_strings, 1, 2, fd) == 2);
235
}
333
}
236
 
334
 
237
 
335
 
-
 
336
static int svl_write_lang(svl_lang_t *l, FILE *fd)
-
 
337
{
-
 
338
  unsigned short strings_bytes = svl_strings_bytes(l);
-
 
339
 
-
 
340
  return (fwrite(&l->id, 1, 2, fd) == 2) &&
-
 
341
         (fwrite(&strings_bytes, 1, 2, fd) == 2) &&
-
 
342
         (fwrite(l->dict, 1, svl_dict_bytes(l), fd) == svl_dict_bytes(l)) &&
-
 
343
         (fwrite(l->strings, 1, svl_strings_bytes(l), fd) == svl_strings_bytes(l));
-
 
344
}
-
 
345
 
-
 
346
 
-
 
347
static int svl_write_c_source(svl_lang_t *l, const char *fn, unsigned short biggest_langsz)
-
 
348
{
-
 
349
  FILE *fd;
-
 
350
  int i;
-
 
351
  unsigned short strings_bytes = svl_strings_bytes(l);
-
 
352
  unsigned short nextnlat = 0;
-
 
353
 
-
 
354
  fd = fopen(fn, "wb");
-
 
355
  if (fd == NULL) {
-
 
356
    puts("ERROR: FAILED TO OPEN OR CREATE DEFLANG.C");
-
 
357
    return 0;
-
 
358
  } else {
-
 
359
    unsigned short allocsz = biggest_langsz + (biggest_langsz / 20);
-
 
360
    printf("biggest lang block is %u bytes -> allocating a %u bytes buffer (5%% safety margin)\n", biggest_langsz,
-
 
361
           allocsz);
-
 
362
    fprintf(fd, "/* THIS FILE HAS BEEN GENERATED BY TLUMACZ (PART OF THE SVARLANG LIBRARY) */\r\n");
-
 
363
    fprintf(fd, "const unsigned short svarlang_memsz = %uu;\r\n", allocsz);
-
 
364
    fprintf(fd, "const unsigned short svarlang_string_count = %uu;\r\n\r\n", l->num_strings);
-
 
365
    fprintf(fd, "char svarlang_mem[%u] = {\r\n", allocsz);
-
 
366
    for (i = 0; i < strings_bytes; i++) {
-
 
367
      if (!fprintf(fd, "0x%02x", l->strings[i])) {
-
 
368
        fclose(fd);
-
 
369
        return 0;
-
 
370
      }
-
 
371
 
-
 
372
      if (i + 1 < strings_bytes) fprintf(fd, ",");
-
 
373
      nextnlat++;
-
 
374
      if (l->strings[i] == '\0' || nextnlat == 16) {
-
 
375
        fprintf(fd, "\r\n");
238
#define MEMBLOCKSZ 65000
376
        nextnlat = 0;
-
 
377
      }
-
 
378
    }
-
 
379
    fprintf(fd, "};\r\n\r\n");
-
 
380
 
-
 
381
    fprintf(fd, "unsigned short svarlang_dict[%u] = {\r\n", l->num_strings * 2);
-
 
382
    for (i = 0; i < l->num_strings; i++) {
-
 
383
      if (!fprintf(fd, "0x%04x,0x%04x", l->dict[i].id, l->dict[i].offset)) {
-
 
384
        fclose(fd);
-
 
385
        return 0;
-
 
386
      }
-
 
387
      if (i + 1 < l->num_strings) fprintf(fd, ",");
-
 
388
      fprintf(fd, "\r\n");
-
 
389
    }
-
 
390
    fprintf(fd, "};\r\n");
-
 
391
 
-
 
392
    fclose(fd);
-
 
393
  }
-
 
394
 
-
 
395
  return 1;
-
 
396
}
-
 
397
 
239
 
398
 
240
int main(int argc, char **argv) {
399
int main(int argc, char **argv) {
241
  FILE *fd;
400
  FILE *fd;
242
  int ecode = 0;
401
  int ecode = 0;
243
  char *buff, *refblock;
-
 
244
  unsigned short refblocksz = 0;
402
  svl_lang_t *lang, *reflang = NULL;
245
  static struct bitmap bufbitmap;
-
 
246
  static struct bitmap refbitmap;
-
 
-
 
403
 
247
  unsigned short i;
404
  int i;
248
  unsigned short biggest_langsz = 0;
405
  unsigned short biggest_langsz = 0;
249
 
406
 
250
  if (argc < 2) {
407
  if (argc < 2) {
251
    puts("tlumacz ver " SVARLANGVER " - this tool is part of the SvarLANG project.");
408
    puts("tlumacz ver " SVARLANGVER " - this tool is part of the SvarLANG project.");
252
    puts("converts a set of CATS-style translations in files EN.TXT, PL.TXT, etc");
409
    puts("converts a set of CATS-style translations in files EN.TXT, PL.TXT, etc");
Line 254... Line 411...
254
    puts("");
411
    puts("");
255
    puts("usage: tlumacz en fr pl ...");
412
    puts("usage: tlumacz en fr pl ...");
256
    return(1);
413
    return(1);
257
  }
414
  }
258
 
415
 
259
  buff = malloc(MEMBLOCKSZ);
-
 
260
  refblock = malloc(MEMBLOCKSZ);
-
 
261
  if ((buff == NULL) || (refblock == NULL)) {
-
 
262
    puts("out of memory");
-
 
263
    return(1);
-
 
264
  }
-
 
265
 
-
 
266
  fd = fopen("out.lng", "wb");
416
  fd = fopen("out.lng", "wb");
267
  if (fd == NULL) {
417
  if (fd == NULL) {
268
    puts("ERR: failed to open or create OUT.LNG");
418
    puts("ERR: failed to open or create OUT.LNG");
269
    return(1);
419
    return(1);
270
  }
420
  }
271
 
421
 
272
  /* write sig */
-
 
273
  fwrite("SvL\x1b", 1, 4, fd);
-
 
274
 
-
 
275
  /* write lang blocks */
422
  /* write lang blocks */
276
  for (i = 1; i < argc; i++) {
423
  for (i = 1; i < argc; i++) {
277
    unsigned short sz;
424
    unsigned short sz;
278
    char id[3];
425
    char id[3];
279
 
426
 
280
    if (strlen(argv[i]) != 2) {
427
    if (strlen(argv[i]) != 2) {
281
      printf("INVALID LANG SPECIFIED: %s\r\n", argv[i]);
428
      printf("INVALID LANG SPECIFIED: %s\r\n", argv[i]);
282
      ecode = 1;
429
      ecode = 1;
283
      break;
430
      break;
284
    }
431
    }
285
 
-
 
286
    id[0] = argv[i][0];
432
    id[0] = argv[i][0];
287
    id[1] = argv[i][1];
433
    id[1] = argv[i][1];
288
    id[2] = 0;
434
    id[2] = 0;
289
    if (id[0] >= 'a') id[0] -= 'a' - 'A';
-
 
290
    if (id[1] >= 'a') id[1] -= 'a' - 'A';
-
 
291
 
435
 
292
    sz = gen_langstrings(buff, id, &bufbitmap, (i != 1)?&refbitmap:NULL, (i != 1)?refblock:NULL);
436
    if ((lang = svl_lang_new(id, DICT_CAP, STRINGS_CAP)) == NULL) {
-
 
437
      printf("OUT OF MEMORY\r\n");
-
 
438
      return(1);
-
 
439
    }
-
 
440
 
-
 
441
    sz = svl_lang_from_cats_file(lang, reflang);
293
    if (sz == 0) {
442
    if (sz == 0) {
294
      printf("ERROR COMPUTING LANG '%s'\r\n", id);
443
      printf("ERROR COMPUTING LANG '%s'\r\n", id);
295
      ecode = 1;
444
      ecode = 1;
296
      break;
445
      break;
297
    } else {
446
    } else {
298
      printf("computed %s lang block of %u bytes\r\n", id, sz);
447
      printf("computed %s lang block of %u bytes\r\n", id, sz);
299
      if (sz > biggest_langsz) biggest_langsz = sz;
448
      if (sz > biggest_langsz) biggest_langsz = sz;
300
    }
449
    }
-
 
450
    svl_compact_lang(lang);
-
 
451
 
301
    /* write lang ID to file, followed by block size and then the actual block */
452
    /* write header if first (reference) language */
-
 
453
    if (i == 1) {
302
    if ((fwrite(id, 1, 2, fd) != 2) ||
454
      if (!svl_write_header(lang->num_strings, fd)) {
303
        (fwrite(&sz, 1, 2, fd) != 2) ||
455
        printf("ERROR WRITING TO OUTPUT FILE\r\n");
-
 
456
        ecode = 1;
-
 
457
        break;
-
 
458
      }
-
 
459
    }
-
 
460
    
-
 
461
    /* write lang ID to file, followed string table size, and then
-
 
462
       the dictionary and string table for current language */
304
        (fwrite(buff, 1, sz, fd) != sz)) {
463
    if (!svl_write_lang(lang, fd)) {
305
      printf("ERROR WRITING TO OUTPUT FILE\r\n");
464
      printf("ERROR WRITING TO OUTPUT FILE\r\n");
306
      ecode = 1;
465
      ecode = 1;
307
      break;
466
      break;
308
    }
467
    }
-
 
468
 
309
    /* remember reference data for other languages */
469
    /* remember reference data for other languages */
310
    if (i == 1) {
470
    if (i == 1) {
311
      refblocksz = sz;
471
      reflang = lang;
-
 
472
    }
-
 
473
    else {
312
      memcpy(refblock, buff, MEMBLOCKSZ);
474
      svl_lang_free(lang);
313
      memcpy(&refbitmap, &bufbitmap, sizeof(struct bitmap));
475
      lang = NULL;
314
    }
476
    }
315
  }
477
  }
316
 
478
 
317
  fclose(fd);
-
 
318
 
-
 
319
  /* compute the deflang.c file containing a dump of the reference block */
479
  /* compute the deflang.c file containing a dump of the reference block */
320
  fd = fopen("DEFLANG.C", "wb");
480
  if (!svl_write_c_source(reflang, "deflang.c", biggest_langsz)) {
321
  if (fd == NULL) {
-
 
322
    puts("ERROR: FAILED TO OPEN OR CREATE DEFLANG.C");
481
    puts("ERROR: FAILED TO OPEN OR CREATE DEFLANG.C");
323
    ecode = 1;
482
    ecode = 1;
324
  } else {
-
 
325
    unsigned short allocsz = biggest_langsz + (biggest_langsz / 20);
-
 
326
    unsigned short nextstringin = 0, nextnlat = 40;
-
 
327
    printf("biggest lang block is %u bytes -> allocating a %u bytes buffer (5%% safety margin)\n", biggest_langsz, allocsz);
-
 
328
    fprintf(fd, "/* THIS FILE HAS BEEN GENERATED BY TLUMACZ (PART OF THE SVARLANG LIBRARY) */\r\n");
-
 
329
    fprintf(fd, "const unsigned short svarlang_memsz = %uu;\r\n", allocsz);
-
 
330
    fprintf(fd, "char svarlang_mem[%u] = {", allocsz);
-
 
331
    for (i = 0; i < refblocksz; i++) {
-
 
332
      if (nextstringin == 0) {
-
 
333
        fprintf(fd, "\r\n");
-
 
334
        nextnlat = i + 40;
-
 
335
        nextstringin = 4 + (refblock[i + 3] << 8) + refblock[i + 2];
-
 
336
        if (nextstringin == 4) nextstringin = 20000; /* last string in block */
-
 
337
      }
483
  }
338
      if (i == nextnlat) {
-
 
339
        nextnlat += 40;
-
 
340
        fprintf(fd, "\r\n");
-
 
341
      }
484
 
342
      nextnlat--;
485
  /* clean up */
343
      nextstringin--;
486
  if (reflang) {
344
      fprintf(fd, "%u", refblock[i]);
-
 
345
      if (i + 1 < refblocksz) fprintf(fd, ",");
-
 
346
    }
-
 
347
    fprintf(fd, "};\r\n");
487
    svl_lang_free(reflang);
348
    fclose(fd);
488
    reflang = NULL;
349
  }
489
  }
350
 
490
 
351
  return(ecode);
491
  return(ecode);
352
}
492
}