Subversion Repositories SvarDOS

Rev

Rev 2015 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
597 mateuszvis 1
/*
1247 mateusz.vi 2
 * Copyright (C) 2021-2023 Mateusz Viste
597 mateuszvis 3
 *
1295 mateusz.vi 4
 * Dictionary-based lookups contributed by Bernd Boeckmann, 2023
5
 *
597 mateuszvis 6
 * usage: tlumacz en fr pl etc
7
 *
1295 mateusz.vi 8
 * computes an out.lng file that contains all language resources.
597 mateuszvis 9
 *
10
 */
11
 
12
 
13
#include <stdio.h>
14
#include <stdlib.h>
15
#include <string.h>
1290 bernd.boec 16
#include <ctype.h>
597 mateuszvis 17
 
1248 mateusz.vi 18
#include "svarlang.h"
597 mateuszvis 19
 
1290 bernd.boec 20
#define STRINGS_CAP 65000   /* string storage size in characters */
1293 mateusz.vi 21
#define DICT_CAP    10000   /* dictionary size in elements */
597 mateuszvis 22
 
2014 bernd.boec 23
enum {                      /* DEFLANG output format */
24
  C_OUTPUT,
25
  ASM_OUTPUT,
26
  NASM_OUTPUT
27
};
28
 
29
 
597 mateuszvis 30
/* read a single line from fd and fills it into dst, returns line length
31
 * ending CR/LF is trimmed, as well as any trailing spaces */
32
static unsigned short readl(char *dst, size_t dstsz, FILE *fd) {
33
  unsigned short l, lastnonspace = 0;
34
 
1290 bernd.boec 35
  if (fgets(dst, (int)dstsz, fd) == NULL) return(0xffff); /* EOF */
597 mateuszvis 36
  /* trim at first CR or LF and return len */
37
  for (l = 0; (dst[l] != 0) && (dst[l] != '\r') && (dst[l] != '\n'); l++) {
38
    if (dst[l] != ' ') lastnonspace = l;
39
  }
40
 
41
  if (lastnonspace < l) l = lastnonspace + 1; /* rtrim */
42
  dst[l] = 0;
43
 
44
  return(l);
45
}
46
 
47
 
1114 mateusz.vi 48
/* parse a line in format "[?]1.50:somestring". fills id and returns a pointer to
597 mateuszvis 49
 * the actual string part on success, or NULL on error */
1114 mateusz.vi 50
static const char *parseline(unsigned short *id, const char *s) {
597 mateuszvis 51
  int i;
52
  int dotpos = 0, colpos = 0, gotdigits = 0;
53
 
1114 mateusz.vi 54
  /* strings prefixed by '?' are flagged as "dirty": ignore this flag here */
55
  if (*s == '?') s++;
56
 
597 mateuszvis 57
  /* I must have a . and a : in the first 9 bytes */
58
  for (i = 0;; i++) {
59
    if (s[i] == '.') {
60
      if ((dotpos != 0) || (gotdigits == 0)) break;
61
      dotpos = i;
62
      gotdigits = 0;
63
    } else if (s[i] == ':') {
64
      if (gotdigits != 0) colpos = i;
65
      break;
66
    } else if ((s[i] < '0') || (s[i] > '9')) {
67
      break;
68
    }
69
    gotdigits++;
70
  }
71
  /* did I collect everything? */
72
  if ((dotpos == 0) || (colpos == 0)) return(NULL);
73
 
74
  *id = atoi(s);
75
  *id <<= 8;
76
  *id |= atoi(s + dotpos + 1);
77
 
78
  /* printf("parseline(): %04X = '%s'\r\n", *id, s + colpos + 1); */
79
 
80
  return(s + colpos + 1);
81
}
82
 
83
 
639 mateusz.vi 84
/* converts escape sequences like "\n" or "\t" into actual bytes, returns
85
 * the new length of the string. */
86
static unsigned short unesc_string(char *linebuff) {
87
  unsigned short i;
88
  for (i = 0; linebuff[i] != 0; i++) {
89
    if (linebuff[i] != '\\') continue;
1290 bernd.boec 90
    memmove(linebuff + i, linebuff + i + 1, strlen(linebuff + i));
639 mateusz.vi 91
    if (linebuff[i] == 0) break;
92
    switch (linebuff[i]) {
1248 mateusz.vi 93
      case 'e':
94
        linebuff[i] = 0x1B; /* ESC code, using hex because '\e' is not ANSI C */
95
        break;
639 mateusz.vi 96
      case 'n':
97
        linebuff[i] = '\n';
98
        break;
99
      case 'r':
100
        linebuff[i] = '\r';
101
        break;
102
      case 't':
103
        linebuff[i] = '\t';
104
        break;
105
    }
106
  }
107
  return(i);
108
}
109
 
1290 bernd.boec 110
#pragma pack(1)
1296 mateusz.vi 111
struct dict_entry {
1295 mateusz.vi 112
  unsigned short id;
113
  unsigned short offset;
1296 mateusz.vi 114
};
1290 bernd.boec 115
#pragma pack()
639 mateusz.vi 116
 
1296 mateusz.vi 117
struct svl_lang {
1290 bernd.boec 118
  char id[2];
119
  unsigned short num_strings;
120
 
1296 mateusz.vi 121
  struct dict_entry *dict;
1290 bernd.boec 122
  size_t dict_cap;
123
 
124
  char *strings;
125
  char *strings_end;
126
  size_t strings_cap;
127
 
1296 mateusz.vi 128
};
1290 bernd.boec 129
 
130
 
1296 mateusz.vi 131
static struct svl_lang *svl_lang_new(const char langid[2], size_t dict_cap, size_t strings_cap) {
132
  struct svl_lang *l;
1290 bernd.boec 133
 
1296 mateusz.vi 134
  l = malloc(sizeof(struct svl_lang));
1295 mateusz.vi 135
  if (!l) return(NULL);
1290 bernd.boec 136
 
137
  l->id[0] = (char)toupper(langid[0]);
138
  l->id[1] = (char)toupper(langid[1]);
139
 
1296 mateusz.vi 140
  l->dict = malloc(dict_cap * sizeof(struct dict_entry));
1295 mateusz.vi 141
  if (!l->dict) return(NULL);
142
 
1290 bernd.boec 143
  l->dict_cap = dict_cap;
144
 
145
  l->num_strings = 0;
146
  l->strings = l->strings_end = malloc(strings_cap);
147
  if (!l->strings) {
148
    free(l->dict);
1295 mateusz.vi 149
    return(NULL);
1290 bernd.boec 150
  }
151
  l->strings_cap = strings_cap;
1295 mateusz.vi 152
 
153
  return(l);
1290 bernd.boec 154
}
155
 
156
 
157
/* compacts the dict and string buffer */
1296 mateusz.vi 158
static void svl_compact_lang(struct svl_lang *l) {
1290 bernd.boec 159
  size_t bytes;
160
  bytes = l->strings_end - l->strings;
161
  if (bytes < l->strings_cap) {
162
    l->strings = l->strings_end = realloc(l->strings, bytes);
163
    l->strings_end += bytes;
164
    l->strings_cap = bytes;
165
  }
166
  l->dict_cap = l->num_strings;
1296 mateusz.vi 167
  l->dict = realloc(l->dict, l->dict_cap * sizeof(struct dict_entry));
1290 bernd.boec 168
}
169
 
170
 
1296 mateusz.vi 171
static void svl_lang_free(struct svl_lang *l) {
1290 bernd.boec 172
  l->num_strings = 0;
173
  if (l->dict) {
174
    free(l->dict);
175
    l->dict = NULL;
176
  }
177
  if (l->strings) {
178
    free(l->strings);
179
    l->strings = l->strings_end = NULL;
180
  }
181
  l->dict_cap = 0;
182
  l->strings_cap = 0;
183
}
184
 
185
 
1296 mateusz.vi 186
static size_t svl_strings_bytes(const struct svl_lang *l) {
1295 mateusz.vi 187
  return(l->strings_end - l->strings);
1290 bernd.boec 188
}
189
 
190
 
1296 mateusz.vi 191
static size_t svl_dict_bytes(const struct svl_lang *l) {
192
  return(l->num_strings * sizeof(struct dict_entry));
1290 bernd.boec 193
}
194
 
195
 
1296 mateusz.vi 196
static int svl_add_str(struct svl_lang *l, unsigned short id, const char *s) {
1290 bernd.boec 197
  size_t len = strlen(s) + 1;
198
  size_t cursor;
199
 
1296 mateusz.vi 200
  if ((l->strings_cap < svl_strings_bytes(l) + len) || (l->dict_cap < (l->num_strings + 1) * sizeof(struct dict_entry))) {
1295 mateusz.vi 201
    return(0);
1290 bernd.boec 202
  }
1293 mateusz.vi 203
 
1290 bernd.boec 204
  /* find dictionary insert position, search backwards in assumption
205
     that in translation files, strings are generally ordered ascending */
206
  for (cursor = l->num_strings; cursor > 0 && l->dict[cursor-1].id > id; cursor--);
207
 
1296 mateusz.vi 208
  memmove(&(l->dict[cursor+1]), &(l->dict[cursor]), sizeof(struct dict_entry) * (l->num_strings - cursor));
1290 bernd.boec 209
  l->dict[cursor].id = id;
210
  l->dict[cursor].offset = l->strings_end - l->strings;
211
 
212
  memcpy(l->strings_end, s, len);
213
  l->strings_end += len;
214
  l->num_strings++;
215
 
1295 mateusz.vi 216
  return(1);
1290 bernd.boec 217
}
218
 
219
 
1296 mateusz.vi 220
static int svl_find(const struct svl_lang *l, unsigned short id) {
1295 mateusz.vi 221
  size_t left = 0, right = l->num_strings - 1, x;
222
  unsigned short v;
1290 bernd.boec 223
 
1295 mateusz.vi 224
  if (l->num_strings == 0) return(0);
1290 bernd.boec 225
 
1295 mateusz.vi 226
  while (left <= right ) {
227
    x = left + ( (right - left ) >> 2 );
228
    v = l->dict[x].id;
1296 mateusz.vi 229
    if ( id == v ) return(1); /* found! */
230
 
231
    if (id > v) {
1295 mateusz.vi 232
      left = x + 1;
233
    } else {
234
      right = x - 1;
235
    }
236
  }
237
  return(0);
1290 bernd.boec 238
}
239
 
1295 mateusz.vi 240
 
1061 mateusz.vi 241
/* opens a CATS-style file and compiles it into a ressources lang block
242
 * returns 0 on error, or the size of the generated data block otherwise */
1296 mateusz.vi 243
static unsigned short svl_lang_from_cats_file(struct svl_lang *l, struct svl_lang *refl) {
1290 bernd.boec 244
  unsigned short linelen;
597 mateuszvis 245
  FILE *fd;
1290 bernd.boec 246
  char fname[] = "xx.txt";
623 mateuszvis 247
  static char linebuf[8192];
1114 mateusz.vi 248
  const char *ptr;
1290 bernd.boec 249
  unsigned short id, maxid=0, maxid_line, linecount;
250
  int i;
597 mateuszvis 251
 
1290 bernd.boec 252
  fname[strlen(fname) - 6] = (char)tolower( l->id[0] );
253
  fname[strlen(fname) - 5] = (char)tolower( l->id[1] );
597 mateuszvis 254
 
255
  fd = fopen(fname, "rb");
256
  if (fd == NULL) {
257
    printf("ERROR: FAILED TO OPEN '%s'\r\n", fname);
258
    return(0);
259
  }
260
 
261
  for (linecount = 1;; linecount++) {
262
    linelen = readl(linebuf, sizeof(linebuf), fd);
263
    if (linelen == 0xffff) break; /* EOF */
264
    if ((linelen == 0) || (linebuf[0] == '#')) continue;
265
 
639 mateusz.vi 266
    /* convert escaped chars to actual bytes (\n -> newline, etc) */
267
    linelen = unesc_string(linebuf);
268
 
597 mateuszvis 269
    /* read id and get ptr to actual string ("1.15:string") */
270
    ptr = parseline(&id, linebuf);
1272 mateusz.vi 271
 
272
    /* handle malformed lines */
597 mateuszvis 273
    if (ptr == NULL) {
1272 mateusz.vi 274
      printf("WARNING: %s[#%u] is malformed (linelen = %u):\r\n", fname, linecount, linelen);
623 mateuszvis 275
      puts(linebuf);
1272 mateusz.vi 276
      continue;
597 mateuszvis 277
    }
1272 mateusz.vi 278
 
279
    /* ignore empty strings (but emit a warning) */
280
    if (ptr[0] == 0) {
1271 bernd.boec 281
      printf("WARNING: %s[#%u] ignoring empty string %u.%u\r\n", fname, linecount, id >> 8, id & 0xff);
282
      continue;
283
    }
597 mateuszvis 284
 
1114 mateusz.vi 285
    /* warn about dirty lines */
286
    if (linebuf[0] == '?') {
287
      printf("WARNING: %s[#%u] string id %u.%u is flagged as 'dirty'\r\n", fname, linecount, id >> 8, id & 0xff);
288
    }
289
 
1290 bernd.boec 290
    /* add the string contained in current line, if conditions are met */
291
    if (!svl_find(l, id)) {
1295 mateusz.vi 292
      if ((refl == NULL) || (svl_find(refl, id))) {
1290 bernd.boec 293
        if (!svl_add_str(l, id, ptr)) {
2014 bernd.boec 294
          fprintf(stderr, "ERROR: %s[#%u] output size limit exceeded\r\n", fname, linecount);
1290 bernd.boec 295
          fclose(fd);
1295 mateusz.vi 296
          return(0);
1290 bernd.boec 297
        }
298
        if (id >= maxid) {
299
          maxid = id;
300
          maxid_line = linecount;
1295 mateusz.vi 301
        } else {
1293 mateusz.vi 302
          printf("WARNING:%s[#%u] file unsorted - line %u has higher id %u.%u\r\n", fname, linecount, maxid_line, maxid >> 8, maxid & 0xff);
1290 bernd.boec 303
        }
1295 mateusz.vi 304
      } else {
1290 bernd.boec 305
        printf("WARNING: %s[#%u] has an invalid id (%u.%u not present in ref lang)\r\n", fname, linecount, id >> 8, id & 0xff);
306
      }
1295 mateusz.vi 307
    } else {
1293 mateusz.vi 308
      printf("WARNING: %s[#%u] has a duplicated id (%u.%u)\r\n", fname, linecount, id >> 8, id & 0xff);
597 mateuszvis 309
    }
310
  }
311
 
312
  fclose(fd);
313
 
1290 bernd.boec 314
  /* if reflang provided, pull missing strings from it */
315
  if (refl != NULL) {
316
    for (i = 0; i < refl->num_strings; i++) {
317
      id = refl->dict[i].id;
318
      if (!svl_find(l, id)) {
597 mateuszvis 319
        printf("WARNING: %s is missing string %u.%u (pulled from ref lang)\r\n", fname, id >> 8, id & 0xff);
1291 bernd.boec 320
        if (!svl_add_str(l, id, refl->strings + refl->dict[i].offset)) {
2014 bernd.boec 321
          fprintf(stderr, "ERROR: %s[#%u] output size limit exceeded\r\n", fname, linecount);
1295 mateusz.vi 322
          return(0);
1290 bernd.boec 323
        }
597 mateuszvis 324
      }
325
    }
326
  }
327
 
1290 bernd.boec 328
  return(svl_strings_bytes(l));
329
}
597 mateuszvis 330
 
1290 bernd.boec 331
 
1295 mateusz.vi 332
static int svl_write_header(unsigned short num_strings, FILE *fd) {
333
  return((fwrite("SvL\x1a", 1, 4, fd) == 4) && (fwrite(&num_strings, 1, 2, fd) == 2));
597 mateuszvis 334
}
335
 
336
 
1296 mateusz.vi 337
static int svl_write_lang(const struct svl_lang *l, FILE *fd) {
1290 bernd.boec 338
  unsigned short strings_bytes = svl_strings_bytes(l);
597 mateuszvis 339
 
1295 mateusz.vi 340
  return((fwrite(&l->id, 1, 2, fd) == 2) &&
1290 bernd.boec 341
         (fwrite(&strings_bytes, 1, 2, fd) == 2) &&
342
         (fwrite(l->dict, 1, svl_dict_bytes(l), fd) == svl_dict_bytes(l)) &&
1295 mateusz.vi 343
         (fwrite(l->strings, 1, svl_strings_bytes(l), fd) == svl_strings_bytes(l)));
1290 bernd.boec 344
}
345
 
346
 
1296 mateusz.vi 347
static int svl_write_c_source(const struct svl_lang *l, const char *fn, unsigned short biggest_langsz) {
1290 bernd.boec 348
  FILE *fd;
349
  int i;
350
  unsigned short strings_bytes = svl_strings_bytes(l);
351
  unsigned short nextnlat = 0;
1295 mateusz.vi 352
  unsigned short allocsz;
1290 bernd.boec 353
 
354
  fd = fopen(fn, "wb");
355
  if (fd == NULL) {
1295 mateusz.vi 356
    return(0);
357
  }
1290 bernd.boec 358
 
1295 mateusz.vi 359
  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, allocsz);
361
  fprintf(fd, "/* THIS FILE HAS BEEN GENERATED BY TLUMACZ (PART OF THE SVARLANG LIBRARY) */\r\n");
362
  fprintf(fd, "const unsigned short svarlang_memsz = %uu;\r\n", allocsz);
363
  fprintf(fd, "const unsigned short svarlang_string_count = %uu;\r\n\r\n", l->num_strings);
364
  fprintf(fd, "char svarlang_mem[%u] = {\r\n", allocsz);
365
 
366
  for (i = 0; i < strings_bytes; i++) {
367
    if (!fprintf(fd, "0x%02x", l->strings[i])) {
368
      fclose(fd);
369
      return(0);
1290 bernd.boec 370
    }
371
 
1295 mateusz.vi 372
    if (i + 1 < strings_bytes) fprintf(fd, ",");
373
    nextnlat++;
374
    if (l->strings[i] == '\0' || nextnlat == 16) {
1290 bernd.boec 375
      fprintf(fd, "\r\n");
1295 mateusz.vi 376
      nextnlat = 0;
1290 bernd.boec 377
    }
1295 mateusz.vi 378
  }
379
  fprintf(fd, "};\r\n\r\n");
1290 bernd.boec 380
 
1295 mateusz.vi 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");
1290 bernd.boec 389
  }
1295 mateusz.vi 390
  fprintf(fd, "};\r\n");
1290 bernd.boec 391
 
1295 mateusz.vi 392
  fclose(fd);
393
 
394
  return(1);
1290 bernd.boec 395
}
396
 
397
 
2014 bernd.boec 398
static int svl_write_asm_source(const struct svl_lang *l, const char *fn, unsigned short biggest_langsz, int format) {
399
  FILE *fd;
400
  int i;
401
  unsigned short strings_bytes = svl_strings_bytes(l);
402
  unsigned short nextnlat = 0;
403
  unsigned short allocsz;
404
 
405
  const char *public = (format == ASM_OUTPUT) ? "public" : "global";
406
 
407
  fd = fopen(fn, "wb");
408
  if (fd == NULL) {
409
    return(0);
410
  }
411
 
412
  allocsz = biggest_langsz + (biggest_langsz / 20);
413
  printf("biggest lang block is %u bytes -> allocating a %u bytes buffer (5%% safety margin)\n", biggest_langsz, allocsz);
414
  fprintf(fd, "; THIS FILE HAS BEEN GENERATED BY TLUMACZ (PART OF THE SVARLANG LIBRARY)\r\n");
415
  fprintf(fd, "%s svarlang_memsz\r\n", public);
416
  fprintf(fd, "svarlang_memsz dw %u\r\n", allocsz);
417
  fprintf(fd, "%s svarlang_string_count\r\n", public);
418
  fprintf(fd, "svarlang_string_count dw %u\r\n\r\n", l->num_strings);
419
  fprintf(fd, "%s svarlang_mem\r\n", public);
420
  fprintf(fd, "svarlang_mem:\r\n");
421
 
422
  if (strings_bytes > 0) fprintf(fd, "db ");
423
 
424
  for (i = 0; i < strings_bytes; i++) {
2016 bernd.boec 425
    if (!fprintf(fd, "%u", l->strings[i])) {
2014 bernd.boec 426
      fclose(fd);
427
      return(0);
428
    }
429
 
430
    nextnlat++;
431
    if (l->strings[i] == '\0' || nextnlat == 16) {
432
      fprintf(fd, "\r\n");
433
      if (i + 1 < strings_bytes ) fprintf(fd, "db ");
434
      nextnlat = 0;
435
    }
436
    else {
437
      fprintf(fd, ",");
438
    }
439
  }
440
 
441
  fprintf(fd, "\r\n%s svarlang_dict\r\n", public);
442
  fprintf(fd, "svarlang_dict:\r\n");
443
  for (i = 0; i < l->num_strings; i++) {
2016 bernd.boec 444
    if (!fprintf(fd, "dw %u,%u\r\n", l->dict[i].id, l->dict[i].offset)) {
2014 bernd.boec 445
      fclose(fd);
446
      return(0);
447
    }
448
  }
449
 
450
  fclose(fd);
451
 
452
  return(1);
453
}
454
 
455
 
597 mateuszvis 456
int main(int argc, char **argv) {
457
  FILE *fd;
458
  int ecode = 0;
2014 bernd.boec 459
  int i, output_format = C_OUTPUT;
1061 mateusz.vi 460
  unsigned short biggest_langsz = 0;
2015 bernd.boec 461
  struct svl_lang *lang = NULL, *reflang = NULL;
597 mateuszvis 462
 
463
  if (argc < 2) {
1247 mateusz.vi 464
    puts("tlumacz ver " SVARLANGVER " - this tool is part of the SvarLANG project.");
465
    puts("converts a set of CATS-style translations in files EN.TXT, PL.TXT, etc");
466
    puts("into a single resource file (OUT.LNG).");
467
    puts("");
2014 bernd.boec 468
    puts("usage: tlumacz [/c|/asm|/nasm] en fr pl ...");
597 mateuszvis 469
    return(1);
470
  }
471
 
601 mateuszvis 472
  fd = fopen("out.lng", "wb");
597 mateuszvis 473
  if (fd == NULL) {
2014 bernd.boec 474
    fprintf(stderr, "ERROR: FAILED TO CREATE OR OPEN OUT.LNG");
597 mateuszvis 475
    return(1);
476
  }
477
 
478
  /* write lang blocks */
479
  for (i = 1; i < argc; i++) {
480
    unsigned short sz;
481
    char id[3];
482
 
2014 bernd.boec 483
    if (!strcmp(argv[i], "/c")) {
484
      output_format = C_OUTPUT;
485
      continue;
486
    }
487
    else if (!strcmp(argv[i], "/asm")) {
488
      output_format = ASM_OUTPUT;
489
      continue;
490
    } else if(!strcmp(argv[i], "/nasm")) {
491
      output_format = NASM_OUTPUT;
492
      continue;
493
    }
494
 
597 mateuszvis 495
    if (strlen(argv[i]) != 2) {
2014 bernd.boec 496
      fprintf(stderr, "INVALID LANG SPECIFIED: %s\r\n", argv[i]);
597 mateuszvis 497
      ecode = 1;
2015 bernd.boec 498
      goto exit_main;
597 mateuszvis 499
    }
500
    id[0] = argv[i][0];
501
    id[1] = argv[i][1];
502
    id[2] = 0;
503
 
1290 bernd.boec 504
    if ((lang = svl_lang_new(id, DICT_CAP, STRINGS_CAP)) == NULL) {
2014 bernd.boec 505
      fprintf(stderr, "OUT OF MEMORY\r\n");
2015 bernd.boec 506
      ecode = 1;
507
      goto exit_main;
1290 bernd.boec 508
    }
509
 
510
    sz = svl_lang_from_cats_file(lang, reflang);
597 mateuszvis 511
    if (sz == 0) {
2014 bernd.boec 512
      fprintf(stderr, "ERROR COMPUTING LANG '%s'\r\n", id);
597 mateuszvis 513
      ecode = 1;
2015 bernd.boec 514
      goto exit_main;
597 mateuszvis 515
    } else {
516
      printf("computed %s lang block of %u bytes\r\n", id, sz);
1061 mateusz.vi 517
      if (sz > biggest_langsz) biggest_langsz = sz;
597 mateuszvis 518
    }
1290 bernd.boec 519
    svl_compact_lang(lang);
520
 
521
    /* write header if first (reference) language */
522
    if (i == 1) {
523
      if (!svl_write_header(lang->num_strings, fd)) {
2014 bernd.boec 524
        fprintf(stderr, "ERROR WRITING TO OUTPUT FILE\r\n");
1290 bernd.boec 525
        ecode = 1;
2015 bernd.boec 526
        goto exit_main;
1290 bernd.boec 527
      }
528
    }
1293 mateusz.vi 529
 
1290 bernd.boec 530
    /* write lang ID to file, followed string table size, and then
531
       the dictionary and string table for current language */
532
    if (!svl_write_lang(lang, fd)) {
2014 bernd.boec 533
      fprintf(stderr, "ERROR WRITING TO OUTPUT FILE\r\n");
597 mateuszvis 534
      ecode = 1;
2015 bernd.boec 535
      goto exit_main;
597 mateuszvis 536
    }
1290 bernd.boec 537
 
1061 mateusz.vi 538
    /* remember reference data for other languages */
2014 bernd.boec 539
    if (!reflang) {
1290 bernd.boec 540
      reflang = lang;
1295 mateusz.vi 541
    } else {
1290 bernd.boec 542
      svl_lang_free(lang);
543
      lang = NULL;
544
    }
597 mateuszvis 545
  }
546
 
2014 bernd.boec 547
  if (!reflang) {
548
    fprintf(stderr, "ERROR: NO LANGUAGE GIVEN\r\n");
2015 bernd.boec 549
    ecode = 1;
550
    goto exit_main;
1061 mateusz.vi 551
  }
552
 
2014 bernd.boec 553
  /* compute the deflang file containing a dump of the reference block */
554
  if (output_format == C_OUTPUT) {
555
    if (!svl_write_c_source(reflang, "deflang.c", biggest_langsz)) {
556
      fprintf(stderr, "ERROR: FAILED TO OPEN OR CREATE DEFLANG.C\r\n");
557
      ecode = 1;
558
    }    
559
  } else {
560
    if (!svl_write_asm_source(reflang, "deflang.inc", biggest_langsz, output_format)) {
561
      fprintf(stderr, "ERROR: FAILED TO OPEN OR CREATE DEFLANG.INC\r\n");
562
      ecode = 1;
563
    }
1290 bernd.boec 564
  }
565
 
2015 bernd.boec 566
exit_main:
567
  if (lang && lang != reflang) {
568
    svl_lang_free(lang);
569
  }
570
  if (reflang) {
571
    svl_lang_free(reflang);
572
    reflang = NULL;
573
    lang = NULL;    
574
  }
2014 bernd.boec 575
 
2015 bernd.boec 576
  fclose(fd);
577
 
597 mateuszvis 578
  return(ecode);
579
}