Subversion Repositories SvarDOS

Rev

Rev 1271 | Rev 1290 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1271 Rev 1272
1
/*
1
/*
2
 * Copyright (C) 2021-2023 Mateusz Viste
2
 * Copyright (C) 2021-2023 Mateusz Viste
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:
8
 * DAT format:
9
 *
9
 *
10
 * 4-bytes signature:
10
 * 4-bytes signature:
11
 * "SvL\x1b"
11
 * "SvL\x1b"
12
 *
12
 *
13
 * Then "LANG BLOCKS" follow. Each LANG BLOCK is prefixed with 4 bytes:
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
14
 * II LL    - II is the LANG identifier ("EN", "PL", etc) and LL is the size
15
 *            of the block (65535 bytes max).
15
 *            of the block (65535 bytes max).
16
 *
16
 *
17
 * Inside a LANG BLOCK is a set of strings:
17
 * Inside a LANG BLOCK is a set of strings:
18
 *
18
 *
19
 * II LL S  where II is the string's 16-bit identifier, LL is its length
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.
20
 *          (1-65535) and S is the actual string. All strings are ASCIIZ (ie.
21
 *          they end with a NULL terminator).
21
 *          they end with a NULL terminator).
22
 *
22
 *
23
 * The list of strings ends with a single 0-long string.
23
 * The list of strings ends with a single 0-long string.
24
 */
24
 */
25
 
25
 
26
 
26
 
27
#include <stdio.h>
27
#include <stdio.h>
28
#include <stdlib.h>
28
#include <stdlib.h>
29
#include <string.h>
29
#include <string.h>
30
 
30
 
31
#include "svarlang.h"
31
#include "svarlang.h"
32
 
32
 
33
 
33
 
34
struct bitmap {
34
struct bitmap {
35
  unsigned char bits[8192];
35
  unsigned char bits[8192];
36
};
36
};
37
 
37
 
38
static void bitmap_set(struct bitmap *b, unsigned short id) {
38
static void bitmap_set(struct bitmap *b, unsigned short id) {
39
  b->bits[id >> 3] |= 1 << (id & 7);
39
  b->bits[id >> 3] |= 1 << (id & 7);
40
}
40
}
41
 
41
 
42
static int bitmap_get(const struct bitmap *b, unsigned short id) {
42
static int bitmap_get(const struct bitmap *b, unsigned short id) {
43
  return(b->bits[id >> 3] & (1 << (id & 7)));
43
  return(b->bits[id >> 3] & (1 << (id & 7)));
44
}
44
}
45
 
45
 
46
static void bitmap_init(struct bitmap *b) {
46
static void bitmap_init(struct bitmap *b) {
47
  bzero(b, sizeof(struct bitmap));
47
  bzero(b, sizeof(struct bitmap));
48
}
48
}
49
 
49
 
50
 
50
 
51
 
51
 
52
/* read a single line from fd and fills it into dst, returns line length
52
/* 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 */
53
 * ending CR/LF is trimmed, as well as any trailing spaces */
54
static unsigned short readl(char *dst, size_t dstsz, FILE *fd) {
54
static unsigned short readl(char *dst, size_t dstsz, FILE *fd) {
55
  unsigned short l, lastnonspace = 0;
55
  unsigned short l, lastnonspace = 0;
56
 
56
 
57
  if (fgets(dst, dstsz, fd) == NULL) return(0xffff); /* EOF */
57
  if (fgets(dst, dstsz, fd) == NULL) return(0xffff); /* EOF */
58
  /* trim at first CR or LF and return len */
58
  /* trim at first CR or LF and return len */
59
  for (l = 0; (dst[l] != 0) && (dst[l] != '\r') && (dst[l] != '\n'); l++) {
59
  for (l = 0; (dst[l] != 0) && (dst[l] != '\r') && (dst[l] != '\n'); l++) {
60
    if (dst[l] != ' ') lastnonspace = l;
60
    if (dst[l] != ' ') lastnonspace = l;
61
  }
61
  }
62
 
62
 
63
  if (lastnonspace < l) l = lastnonspace + 1; /* rtrim */
63
  if (lastnonspace < l) l = lastnonspace + 1; /* rtrim */
64
  dst[l] = 0;
64
  dst[l] = 0;
65
 
65
 
66
  return(l);
66
  return(l);
67
}
67
}
68
 
68
 
69
 
69
 
70
/* parse a line in format "[?]1.50:somestring". fills id and returns a pointer to
70
/* parse a line in format "[?]1.50:somestring". fills id and returns a pointer to
71
 * the actual string part on success, or NULL on error */
71
 * the actual string part on success, or NULL on error */
72
static const char *parseline(unsigned short *id, const char *s) {
72
static const char *parseline(unsigned short *id, const char *s) {
73
  int i;
73
  int i;
74
  int dotpos = 0, colpos = 0, gotdigits = 0;
74
  int dotpos = 0, colpos = 0, gotdigits = 0;
75
 
75
 
76
  /* strings prefixed by '?' are flagged as "dirty": ignore this flag here */
76
  /* strings prefixed by '?' are flagged as "dirty": ignore this flag here */
77
  if (*s == '?') s++;
77
  if (*s == '?') s++;
78
 
78
 
79
  /* I must have a . and a : in the first 9 bytes */
79
  /* I must have a . and a : in the first 9 bytes */
80
  for (i = 0;; i++) {
80
  for (i = 0;; i++) {
81
    if (s[i] == '.') {
81
    if (s[i] == '.') {
82
      if ((dotpos != 0) || (gotdigits == 0)) break;
82
      if ((dotpos != 0) || (gotdigits == 0)) break;
83
      dotpos = i;
83
      dotpos = i;
84
      gotdigits = 0;
84
      gotdigits = 0;
85
    } else if (s[i] == ':') {
85
    } else if (s[i] == ':') {
86
      if (gotdigits != 0) colpos = i;
86
      if (gotdigits != 0) colpos = i;
87
      break;
87
      break;
88
    } else if ((s[i] < '0') || (s[i] > '9')) {
88
    } else if ((s[i] < '0') || (s[i] > '9')) {
89
      break;
89
      break;
90
    }
90
    }
91
    gotdigits++;
91
    gotdigits++;
92
  }
92
  }
93
  /* did I collect everything? */
93
  /* did I collect everything? */
94
  if ((dotpos == 0) || (colpos == 0)) return(NULL);
94
  if ((dotpos == 0) || (colpos == 0)) return(NULL);
95
 
95
 
96
  *id = atoi(s);
96
  *id = atoi(s);
97
  *id <<= 8;
97
  *id <<= 8;
98
  *id |= atoi(s + dotpos + 1);
98
  *id |= atoi(s + dotpos + 1);
99
 
99
 
100
  /* printf("parseline(): %04X = '%s'\r\n", *id, s + colpos + 1); */
100
  /* printf("parseline(): %04X = '%s'\r\n", *id, s + colpos + 1); */
101
 
101
 
102
  return(s + colpos + 1);
102
  return(s + colpos + 1);
103
}
103
}
104
 
104
 
105
 
105
 
106
/* converts escape sequences like "\n" or "\t" into actual bytes, returns
106
/* converts escape sequences like "\n" or "\t" into actual bytes, returns
107
 * the new length of the string. */
107
 * the new length of the string. */
108
static unsigned short unesc_string(char *linebuff) {
108
static unsigned short unesc_string(char *linebuff) {
109
  unsigned short i;
109
  unsigned short i;
110
  for (i = 0; linebuff[i] != 0; i++) {
110
  for (i = 0; linebuff[i] != 0; i++) {
111
    if (linebuff[i] != '\\') continue;
111
    if (linebuff[i] != '\\') continue;
112
    strcpy(linebuff + i, linebuff + i + 1);
112
    strcpy(linebuff + i, linebuff + i + 1);
113
    if (linebuff[i] == 0) break;
113
    if (linebuff[i] == 0) break;
114
    switch (linebuff[i]) {
114
    switch (linebuff[i]) {
115
      case 'e':
115
      case 'e':
116
        linebuff[i] = 0x1B; /* ESC code, using hex because '\e' is not ANSI C */
116
        linebuff[i] = 0x1B; /* ESC code, using hex because '\e' is not ANSI C */
117
        break;
117
        break;
118
      case 'n':
118
      case 'n':
119
        linebuff[i] = '\n';
119
        linebuff[i] = '\n';
120
        break;
120
        break;
121
      case 'r':
121
      case 'r':
122
        linebuff[i] = '\r';
122
        linebuff[i] = '\r';
123
        break;
123
        break;
124
      case 't':
124
      case 't':
125
        linebuff[i] = '\t';
125
        linebuff[i] = '\t';
126
        break;
126
        break;
127
    }
127
    }
128
  }
128
  }
129
  return(i);
129
  return(i);
130
}
130
}
131
 
131
 
132
 
132
 
133
/* opens a CATS-style file and compiles it into a ressources lang block
133
/* 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 */
134
 * 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) {
135
static unsigned short gen_langstrings(unsigned char *buff, const char *langid, struct bitmap *b, const struct bitmap *refb, const unsigned char *refblock) {
136
  unsigned short len = 0, linelen;
136
  unsigned short len = 0, linelen;
137
  FILE *fd;
137
  FILE *fd;
138
  char fname[] = "XX.TXT";
138
  char fname[] = "XX.TXT";
139
  static char linebuf[8192];
139
  static char linebuf[8192];
140
  const char *ptr;
140
  const char *ptr;
141
  unsigned short id, linecount;
141
  unsigned short id, linecount;
142
 
142
 
143
  bitmap_init(b);
143
  bitmap_init(b);
144
 
144
 
145
  memcpy(fname + strlen(fname) - 6, langid, 2);
145
  memcpy(fname + strlen(fname) - 6, langid, 2);
146
 
146
 
147
  fd = fopen(fname, "rb");
147
  fd = fopen(fname, "rb");
148
  if (fd == NULL) {
148
  if (fd == NULL) {
149
    printf("ERROR: FAILED TO OPEN '%s'\r\n", fname);
149
    printf("ERROR: FAILED TO OPEN '%s'\r\n", fname);
150
    return(0);
150
    return(0);
151
  }
151
  }
152
 
152
 
153
  for (linecount = 1;; linecount++) {
153
  for (linecount = 1;; linecount++) {
154
 
154
 
155
    linelen = readl(linebuf, sizeof(linebuf), fd);
155
    linelen = readl(linebuf, sizeof(linebuf), fd);
156
    if (linelen == 0xffff) break; /* EOF */
156
    if (linelen == 0xffff) break; /* EOF */
157
    if ((linelen == 0) || (linebuf[0] == '#')) continue;
157
    if ((linelen == 0) || (linebuf[0] == '#')) continue;
158
 
158
 
159
    /* convert escaped chars to actual bytes (\n -> newline, etc) */
159
    /* convert escaped chars to actual bytes (\n -> newline, etc) */
160
    linelen = unesc_string(linebuf);
160
    linelen = unesc_string(linebuf);
161
 
161
 
162
    /* read id and get ptr to actual string ("1.15:string") */
162
    /* read id and get ptr to actual string ("1.15:string") */
163
    ptr = parseline(&id, linebuf);
163
    ptr = parseline(&id, linebuf);
-
 
164
 
-
 
165
    /* handle malformed lines */
164
    if (ptr == NULL) {
166
    if (ptr == NULL) {
165
      printf("ERROR: line #%u of %s is malformed (linelen = %u):\r\n", linecount, fname, linelen);
167
      printf("WARNING: %s[#%u] is malformed (linelen = %u):\r\n", fname, linecount, linelen);
166
      puts(linebuf);
168
      puts(linebuf);
167
      len = 0;
169
      continue;
168
      break;
-
 
169
    }
170
    }
-
 
171
 
-
 
172
    /* ignore empty strings (but emit a warning) */
170
    if (strlen(ptr) == 0) {
173
    if (ptr[0] == 0) {
171
      printf("WARNING: %s[#%u] ignoring empty string %u.%u\r\n", fname, linecount, id >> 8, id & 0xff);
174
      printf("WARNING: %s[#%u] ignoring empty string %u.%u\r\n", fname, linecount, id >> 8, id & 0xff);
172
      continue;
175
      continue;
173
    }
176
    }
174
 
177
 
175
    /* warn about dirty lines */
178
    /* warn about dirty lines */
176
    if (linebuf[0] == '?') {
179
    if (linebuf[0] == '?') {
177
      printf("WARNING: %s[#%u] string id %u.%u is flagged as 'dirty'\r\n", fname, linecount, id >> 8, id & 0xff);
180
      printf("WARNING: %s[#%u] string id %u.%u is flagged as 'dirty'\r\n", fname, linecount, id >> 8, id & 0xff);
178
    }
181
    }
179
 
182
 
180
    /* write string into block (II LL S) */
183
    /* write string into block (II LL S) */
181
    memcpy(buff + len, &id, 2);
184
    memcpy(buff + len, &id, 2);
182
    len += 2;
185
    len += 2;
183
    {
186
    {
184
      unsigned short slen = strlen(ptr) + 1;
187
      unsigned short slen = strlen(ptr) + 1;
185
      memcpy(buff + len, &slen, 2);
188
      memcpy(buff + len, &slen, 2);
186
      len += 2;
189
      len += 2;
187
      memcpy(buff + len, ptr, slen);
190
      memcpy(buff + len, ptr, slen);
188
      len += slen;
191
      len += slen;
189
    }
192
    }
190
 
193
 
191
    /* if reference bitmap provided: check that the id is valid */
194
    /* if reference bitmap provided: check that the id is valid */
192
    if ((refb != NULL) && (bitmap_get(refb, id) == 0)) {
195
    if ((refb != NULL) && (bitmap_get(refb, id) == 0)) {
193
      printf("WARNING: %s[#%u] has an invalid id (%u.%u not present in ref lang)\r\n", fname, linecount, id >> 8, id & 0xff);
196
      printf("WARNING: %s[#%u] has an invalid id (%u.%u not present in ref lang)\r\n", fname, linecount, id >> 8, id & 0xff);
194
    }
197
    }
195
 
198
 
196
    /* make sure this id is not already present */
199
    /* make sure this id is not already present */
197
    if (bitmap_get(b, id) == 0) {
200
    if (bitmap_get(b, id) == 0) {
198
      /* set bit in bitmap to remember I have this string */
201
      /* set bit in bitmap to remember I have this string */
199
      bitmap_set(b, id);
202
      bitmap_set(b, id);
200
    } else {
203
    } else {
201
      printf("WARNING: %s[#%u] has a duplicated id (%u.%u)\r\n", fname, linecount, id >> 8, id & 0xff);
204
      printf("WARNING: %s[#%u] has a duplicated id (%u.%u)\r\n", fname, linecount, id >> 8, id & 0xff);
202
    }
205
    }
203
  }
206
  }
204
 
207
 
205
  fclose(fd);
208
  fclose(fd);
206
 
209
 
207
  /* if refblock provided, pull missing strings from it */
210
  /* if refblock provided, pull missing strings from it */
208
  if (refblock != NULL) {
211
  if (refblock != NULL) {
209
    for (;;) {
212
    for (;;) {
210
      unsigned short slen;
213
      unsigned short slen;
211
      id = ((unsigned short *)refblock)[0];
214
      id = ((unsigned short *)refblock)[0];
212
      slen = ((unsigned short *)refblock)[1];
215
      slen = ((unsigned short *)refblock)[1];
213
      if ((id == 0) && (slen == 0)) break;
216
      if ((id == 0) && (slen == 0)) break;
214
      if (bitmap_get(b, id) == 0) {
217
      if (bitmap_get(b, id) == 0) {
215
        printf("WARNING: %s is missing string %u.%u (pulled from ref lang)\r\n", fname, id >> 8, id & 0xff);
218
        printf("WARNING: %s is missing string %u.%u (pulled from ref lang)\r\n", fname, id >> 8, id & 0xff);
216
        /* copy missing string from refblock */
219
        /* copy missing string from refblock */
217
        memcpy(buff + len, refblock, slen + 4);
220
        memcpy(buff + len, refblock, slen + 4);
218
        len += slen + 4;
221
        len += slen + 4;
219
      }
222
      }
220
      refblock += slen + 4;
223
      refblock += slen + 4;
221
    }
224
    }
222
  }
225
  }
223
 
226
 
224
  /* write the block terminator (0-long string) */
227
  /* write the block terminator (0-long string) */
225
  buff[len++] = 0; /* id */
228
  buff[len++] = 0; /* id */
226
  buff[len++] = 0; /* id */
229
  buff[len++] = 0; /* id */
227
  buff[len++] = 0; /* len */
230
  buff[len++] = 0; /* len */
228
  buff[len++] = 0; /* len */
231
  buff[len++] = 0; /* len */
229
  buff[len++] = 0; /* empty string */
232
  buff[len++] = 0; /* empty string */
230
 
233
 
231
  return(len);
234
  return(len);
232
}
235
}
233
 
236
 
234
 
237
 
235
#define MEMBLOCKSZ 65000
238
#define MEMBLOCKSZ 65000
236
 
239
 
237
int main(int argc, char **argv) {
240
int main(int argc, char **argv) {
238
  FILE *fd;
241
  FILE *fd;
239
  int ecode = 0;
242
  int ecode = 0;
240
  char *buff, *refblock;
243
  char *buff, *refblock;
241
  unsigned short refblocksz = 0;
244
  unsigned short refblocksz = 0;
242
  static struct bitmap bufbitmap;
245
  static struct bitmap bufbitmap;
243
  static struct bitmap refbitmap;
246
  static struct bitmap refbitmap;
244
  unsigned short i;
247
  unsigned short i;
245
  unsigned short biggest_langsz = 0;
248
  unsigned short biggest_langsz = 0;
246
 
249
 
247
  if (argc < 2) {
250
  if (argc < 2) {
248
    puts("tlumacz ver " SVARLANGVER " - this tool is part of the SvarLANG project.");
251
    puts("tlumacz ver " SVARLANGVER " - this tool is part of the SvarLANG project.");
249
    puts("converts a set of CATS-style translations in files EN.TXT, PL.TXT, etc");
252
    puts("converts a set of CATS-style translations in files EN.TXT, PL.TXT, etc");
250
    puts("into a single resource file (OUT.LNG).");
253
    puts("into a single resource file (OUT.LNG).");
251
    puts("");
254
    puts("");
252
    puts("usage: tlumacz en fr pl ...");
255
    puts("usage: tlumacz en fr pl ...");
253
    return(1);
256
    return(1);
254
  }
257
  }
255
 
258
 
256
  buff = malloc(MEMBLOCKSZ);
259
  buff = malloc(MEMBLOCKSZ);
257
  refblock = malloc(MEMBLOCKSZ);
260
  refblock = malloc(MEMBLOCKSZ);
258
  if ((buff == NULL) || (refblock == NULL)) {
261
  if ((buff == NULL) || (refblock == NULL)) {
259
    puts("out of memory");
262
    puts("out of memory");
260
    return(1);
263
    return(1);
261
  }
264
  }
262
 
265
 
263
  fd = fopen("out.lng", "wb");
266
  fd = fopen("out.lng", "wb");
264
  if (fd == NULL) {
267
  if (fd == NULL) {
265
    puts("ERR: failed to open or create OUT.LNG");
268
    puts("ERR: failed to open or create OUT.LNG");
266
    return(1);
269
    return(1);
267
  }
270
  }
268
 
271
 
269
  /* write sig */
272
  /* write sig */
270
  fwrite("SvL\x1b", 1, 4, fd);
273
  fwrite("SvL\x1b", 1, 4, fd);
271
 
274
 
272
  /* write lang blocks */
275
  /* write lang blocks */
273
  for (i = 1; i < argc; i++) {
276
  for (i = 1; i < argc; i++) {
274
    unsigned short sz;
277
    unsigned short sz;
275
    char id[3];
278
    char id[3];
276
 
279
 
277
    if (strlen(argv[i]) != 2) {
280
    if (strlen(argv[i]) != 2) {
278
      printf("INVALID LANG SPECIFIED: %s\r\n", argv[i]);
281
      printf("INVALID LANG SPECIFIED: %s\r\n", argv[i]);
279
      ecode = 1;
282
      ecode = 1;
280
      break;
283
      break;
281
    }
284
    }
282
 
285
 
283
    id[0] = argv[i][0];
286
    id[0] = argv[i][0];
284
    id[1] = argv[i][1];
287
    id[1] = argv[i][1];
285
    id[2] = 0;
288
    id[2] = 0;
286
    if (id[0] >= 'a') id[0] -= 'a' - 'A';
289
    if (id[0] >= 'a') id[0] -= 'a' - 'A';
287
    if (id[1] >= 'a') id[1] -= 'a' - 'A';
290
    if (id[1] >= 'a') id[1] -= 'a' - 'A';
288
 
291
 
289
    sz = gen_langstrings(buff, id, &bufbitmap, (i != 1)?&refbitmap:NULL, (i != 1)?refblock:NULL);
292
    sz = gen_langstrings(buff, id, &bufbitmap, (i != 1)?&refbitmap:NULL, (i != 1)?refblock:NULL);
290
    if (sz == 0) {
293
    if (sz == 0) {
291
      printf("ERROR COMPUTING LANG '%s'\r\n", id);
294
      printf("ERROR COMPUTING LANG '%s'\r\n", id);
292
      ecode = 1;
295
      ecode = 1;
293
      break;
296
      break;
294
    } else {
297
    } else {
295
      printf("computed %s lang block of %u bytes\r\n", id, sz);
298
      printf("computed %s lang block of %u bytes\r\n", id, sz);
296
      if (sz > biggest_langsz) biggest_langsz = sz;
299
      if (sz > biggest_langsz) biggest_langsz = sz;
297
    }
300
    }
298
    /* write lang ID to file, followed by block size and then the actual block */
301
    /* write lang ID to file, followed by block size and then the actual block */
299
    if ((fwrite(id, 1, 2, fd) != 2) ||
302
    if ((fwrite(id, 1, 2, fd) != 2) ||
300
        (fwrite(&sz, 1, 2, fd) != 2) ||
303
        (fwrite(&sz, 1, 2, fd) != 2) ||
301
        (fwrite(buff, 1, sz, fd) != sz)) {
304
        (fwrite(buff, 1, sz, fd) != sz)) {
302
      printf("ERROR WRITING TO OUTPUT FILE\r\n");
305
      printf("ERROR WRITING TO OUTPUT FILE\r\n");
303
      ecode = 1;
306
      ecode = 1;
304
      break;
307
      break;
305
    }
308
    }
306
    /* remember reference data for other languages */
309
    /* remember reference data for other languages */
307
    if (i == 1) {
310
    if (i == 1) {
308
      refblocksz = sz;
311
      refblocksz = sz;
309
      memcpy(refblock, buff, MEMBLOCKSZ);
312
      memcpy(refblock, buff, MEMBLOCKSZ);
310
      memcpy(&refbitmap, &bufbitmap, sizeof(struct bitmap));
313
      memcpy(&refbitmap, &bufbitmap, sizeof(struct bitmap));
311
    }
314
    }
312
  }
315
  }
313
 
316
 
314
  fclose(fd);
317
  fclose(fd);
315
 
318
 
316
  /* compute the deflang.c file containing a dump of the reference block */
319
  /* compute the deflang.c file containing a dump of the reference block */
317
  fd = fopen("DEFLANG.C", "wb");
320
  fd = fopen("DEFLANG.C", "wb");
318
  if (fd == NULL) {
321
  if (fd == NULL) {
319
    puts("ERROR: FAILED TO OPEN OR CREATE DEFLANG.C");
322
    puts("ERROR: FAILED TO OPEN OR CREATE DEFLANG.C");
320
    ecode = 1;
323
    ecode = 1;
321
  } else {
324
  } else {
322
    unsigned short allocsz = biggest_langsz + (biggest_langsz / 20);
325
    unsigned short allocsz = biggest_langsz + (biggest_langsz / 20);
323
    unsigned short nextstringin = 0, nextnlat = 40;
326
    unsigned short nextstringin = 0, nextnlat = 40;
324
    printf("biggest lang block is %u bytes -> allocating a %u bytes buffer (5%% safety margin)\n", biggest_langsz, allocsz);
327
    printf("biggest lang block is %u bytes -> allocating a %u bytes buffer (5%% safety margin)\n", biggest_langsz, allocsz);
325
    fprintf(fd, "/* THIS FILE HAS BEEN GENERATED BY TLUMACZ (PART OF THE SVARLANG LIBRARY) */\r\n");
328
    fprintf(fd, "/* THIS FILE HAS BEEN GENERATED BY TLUMACZ (PART OF THE SVARLANG LIBRARY) */\r\n");
326
    fprintf(fd, "const unsigned short svarlang_memsz = %uu;\r\n", allocsz);
329
    fprintf(fd, "const unsigned short svarlang_memsz = %uu;\r\n", allocsz);
327
    fprintf(fd, "char svarlang_mem[%u] = {", allocsz);
330
    fprintf(fd, "char svarlang_mem[%u] = {", allocsz);
328
    for (i = 0; i < refblocksz; i++) {
331
    for (i = 0; i < refblocksz; i++) {
329
      if (nextstringin == 0) {
332
      if (nextstringin == 0) {
330
        fprintf(fd, "\r\n");
333
        fprintf(fd, "\r\n");
331
        nextnlat = i + 40;
334
        nextnlat = i + 40;
332
        nextstringin = 4 + (refblock[i + 3] << 8) + refblock[i + 2];
335
        nextstringin = 4 + (refblock[i + 3] << 8) + refblock[i + 2];
333
        if (nextstringin == 4) nextstringin = 20000; /* last string in block */
336
        if (nextstringin == 4) nextstringin = 20000; /* last string in block */
334
      }
337
      }
335
      if (i == nextnlat) {
338
      if (i == nextnlat) {
336
        nextnlat += 40;
339
        nextnlat += 40;
337
        fprintf(fd, "\r\n");
340
        fprintf(fd, "\r\n");
338
      }
341
      }
339
      nextnlat--;
342
      nextnlat--;
340
      nextstringin--;
343
      nextstringin--;
341
      fprintf(fd, "%u", refblock[i]);
344
      fprintf(fd, "%u", refblock[i]);
342
      if (i + 1 < refblocksz) fprintf(fd, ",");
345
      if (i + 1 < refblocksz) fprintf(fd, ",");
343
    }
346
    }
344
    fprintf(fd, "};\r\n");
347
    fprintf(fd, "};\r\n");
345
    fclose(fd);
348
    fclose(fd);
346
  }
349
  }
347
 
350
 
348
  return(ecode);
351
  return(ecode);
349
}
352
}
350
 
353