Subversion Repositories SvarDOS

Rev

Rev 433 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
433 mateuszvis 1
/*
2
 * Copyright (C) 2021 Mateusz Viste
3
 *
4
 * usage: tlumacz en fr pl etc
5
 *
6
 * computes a svarcom.lng file that contains all language ressources found
7
 * inside dirname.
8
 *
9
 * DAT format:
10
 *
11
 * 4-bytes signature:
12
 * "SvL\x1b"
13
 *
14
 * Then "LANG BLOCKS" follow. Each LANG BLOCK is prefixed with 4 bytes:
15
 * II LL    - II is the LANG identifier ("EN", "PL", etc) and LL is the size
16
 *            of the block (65535 bytes max).
17
 *
18
 * Inside a LANG BLOCK is a set of strings:
19
 *
20
 * II L S  where II is the string's 16-bit identifier, L is its length (1-255)
21
 *         and S is the actual string. All strings are ASCIIZ-formatted (ie.
22
 *         end with a NULL terminator).
23
 *
24
 * The list of strings ends with a single 0-long string.
25
 */
26
 
27
 
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <string.h>
31
 
32
 
33
/* read a single line from fd and fills it into dst, returns line length
34
 * ending CR/LF is trimmed, as well as any trailing spaces */
35
static unsigned short readl(char *dst, size_t dstsz, FILE *fd) {
36
  unsigned short l, lastnonspace = 0;
37
 
38
  if (fgets(dst, dstsz, fd) == NULL) return(0xffff); /* EOF */
39
  /* trim at first CR or LF and return len */
40
  for (l = 0; (dst[l] != 0) && (dst[l] != '\r') && (dst[l] != '\n'); l++) {
41
    if (dst[l] != ' ') lastnonspace = l;
42
  }
43
 
44
  if (lastnonspace < l) l = lastnonspace + 1; /* rtrim */
45
  dst[l] = 0;
46
 
47
  return(l);
48
}
49
 
50
 
51
/* parse a line in format "1.50:somestring". fills id and returns a pointer to
52
 * the actual string part on success, or NULL on error */
53
static char *parseline(unsigned short *id, char *s) {
54
  int i;
55
  int dotpos = 0, colpos = 0, gotdigits = 0;
56
 
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
  if (s[colpos + 1] == 0) return(NULL);
74
 
75
  *id = atoi(s);
76
  *id <<= 8;
77
  *id |= atoi(s + dotpos + 1);
78
 
79
  /* printf("parseline(): %04X = '%s'\r\n", *id, s + colpos + 1); */
80
 
81
  return(s + colpos + 1);
82
}
83
 
84
 
85
/* opens a CATS-style file and compiles it into a ressources lang block */
86
static unsigned short gen_langstrings(unsigned char *buff, const char *langid) {
87
  unsigned short len = 0, linelen;
88
  FILE *fd;
89
  char fname[] = "NLS\\SVARCOM.XX";
90
  char linebuf[512];
91
  char *ptr;
92
  unsigned short id, linecount;
93
 
94
  strcpy(fname + strlen(fname) - 2, langid);
95
 
96
  fd = fopen(fname, "rb");
97
  if (fd == NULL) {
98
    printf("ERROR: FAILED TO OPEN '%s'\r\n", fname);
99
    return(0);
100
  }
101
 
102
  for (linecount = 1;; linecount++) {
103
 
104
    linelen = readl(linebuf, sizeof(linebuf), fd);
105
    if (linelen == 0xffff) break; /* EOF */
106
    if ((linelen == 0) || (linebuf[0] == '#')) continue;
107
 
108
    /* read id and get ptr to actual string ("1.15:string") */
109
    ptr = parseline(&id, linebuf);
110
    if (ptr == NULL) {
111
      printf("ERROR: line #%u of %s is malformed\r\n", linecount, fname);
112
      len = 0;
113
      break;
114
    }
115
 
116
    /* write string into block (II L S) */
117
    memcpy(buff + len, &id, 2);
118
    len += 2;
119
    buff[len++] = strlen(ptr) + 1;
120
    memcpy(buff + len, ptr, strlen(ptr) + 1);
121
    len += strlen(ptr) + 1;
122
  }
123
 
124
  /* write the block terminator (0-long string) */
125
  buff[len++] = 0; /* id */
126
  buff[len++] = 0; /* id */
127
  buff[len++] = 0; /* len */
128
 
129
  fclose(fd);
130
 
131
  return(len);
132
}
133
 
134
 
135
int main(int argc, char **argv) {
136
  FILE *fd;
137
  int ecode = 0;
138
  char *buff;
139
  unsigned short i;
140
 
141
  if (argc < 2) {
142
    puts("usage: tlumacz en fr pl etc");
143
    return(1);
144
  }
145
 
146
  buff = malloc(65500);
147
  if (buff == NULL) {
148
    puts("out of memory");
149
    return(1);
150
  }
151
 
152
  fd = fopen("svarcom.lng", "wb");
153
  if (fd == NULL) {
154
    puts("ERR: failed to open or create SVARCOM.LNG");
155
    return(1);
156
  }
157
 
158
  /* write sig */
159
  fwrite("SvL\x1b", 1, 4, fd);
160
 
161
  /* write lang blocks */
162
  for (i = 1; i < argc; i++) {
163
    unsigned short sz;
164
    char id[3];
165
 
166
    if (strlen(argv[i]) != 2) {
167
      printf("INVALID LANG SPECIFIED: %s\r\n", argv[i]);
168
      ecode = 1;
169
      break;
170
    }
171
 
172
    id[0] = argv[i][0];
173
    id[1] = argv[i][1];
174
    id[2] = 0;
175
    if (id[0] >= 'a') id[0] -= 'a' - 'A';
176
    if (id[1] >= 'a') id[1] -= 'a' - 'A';
177
 
178
    sz = gen_langstrings(buff, id);
179
    if (sz == 0) {
180
      printf("ERROR COMPUTING LANG '%s'\r\n", id);
181
      ecode = 1;
182
      break;
183
    } else {
184
      printf("computed %s lang block of %u bytes\r\n", id, sz);
185
    }
186
    /* write lang ID to file, followed by block size and then the actual block */
187
    if ((fwrite(id, 1, 2, fd) != 2) ||
188
        (fwrite(&sz, 1, 2, fd) != 2) ||
189
        (fwrite(buff, 1, sz, fd) != sz)) {
190
      printf("ERROR WRITING TO OUTPUT FILE\r\n");
191
      ecode = 1;
192
      break;
193
    }
194
    /* if EN, then it is also the default block */
195
    if (strcmp(id, "EN") == 0) {
196
      FILE *fd2;
197
      fd2 = fopen("DEFAULT.LNG", "wb");
198
      if (fd2 == NULL) {
199
        puts("ERROR: FAILED TO OPEN OR CREATE DEFAULT.LNG");
200
        break;
201
      }
437 mateuszvis 202
      fwrite(id, 1, 2, fd2);    /* lang block id */
203
      fwrite(&sz, 1, 2, fd2);   /* lang block size */
204
      fwrite(buff, 1, sz, fd2); /* langblock content (strings) */
433 mateuszvis 205
      fclose(fd2);
206
    }
207
  }
208
 
209
  fclose(fd);
210
 
211
  return(ecode);
212
}