Subversion Repositories SvarDOS

Rev

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

Rev 1377 Rev 1779
1
/* This file is part of the svarlang project and is published under the terms
1
/* This file is part of the svarlang project and is published under the terms
2
 * of the MIT license.
2
 * of the MIT license.
3
 *
3
 *
4
 * Copyright (C) 2021-2023 Mateusz Viste
4
 * Copyright (C) 2021-2024 Mateusz Viste
5
 *
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
12
 *
13
 * The above copyright notice and this permission notice shall be included in
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
14
 * all copies or substantial portions of the Software.
15
 *
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
22
 * DEALINGS IN THE SOFTWARE.
23
 */
23
 */
24
 
24
 
25
/* if WITHSTDIO is enabled, then remap file operations to use the standard
25
/* if WITHSTDIO is enabled, then remap file operations to use the standard
26
 * stdio amenities */
26
 * stdio amenities */
27
#ifdef WITHSTDIO
27
#ifdef WITHSTDIO
28
 
28
 
29
#include <stdio.h>   /* FILE, fopen(), fseek(), etc */
29
#include <stdio.h>   /* FILE, fopen(), fseek(), etc */
30
typedef FILE* FHANDLE;
30
typedef FILE* FHANDLE;
31
#define FOPEN(x) fopen(x, "rb")
31
#define FOPEN(x) fopen(x, "rb")
32
#define FCLOSE(x) fclose(x)
32
#define FCLOSE(x) fclose(x)
33
#define FSEEK(f,b) fseek(f,b,SEEK_CUR)
33
#define FSEEK(f,b) fseek(f,b,SEEK_CUR)
34
#define FREAD(f,t,b) fread(t, 1, b, f)
34
#define FREAD(f,t,b) fread(t, 1, b, f)
35
 
35
 
36
#else
36
#else
37
 
37
 
38
#include <i86.h>  /* FP_SEG, FP_OFF */
38
#include <i86.h>  /* FP_SEG, FP_OFF */
39
typedef unsigned short FHANDLE;
39
typedef unsigned short FHANDLE;
40
 
40
 
41
#endif
41
#endif
42
 
42
 
43
 
43
 
44
#include "svarlang.h"
44
#include "svarlang.h"
45
 
45
 
46
 
46
 
47
/* supplied through DEFLANG.C */
47
/* supplied through DEFLANG.C */
48
extern char svarlang_mem[];
48
extern char svarlang_mem[];
49
extern unsigned short svarlang_dict[];
49
extern unsigned short svarlang_dict[];
50
extern const unsigned short svarlang_memsz;
50
extern const unsigned short svarlang_memsz;
51
extern const unsigned short svarlang_string_count;
51
extern const unsigned short svarlang_string_count;
52
 
52
 
53
 
53
 
54
const char *svarlang_strid(unsigned short id) {
54
const char *svarlang_strid(unsigned short id) {
55
  unsigned short left = 0, right = svarlang_string_count - 1, x;
55
  unsigned short left = 0, right = svarlang_string_count - 1, x;
56
  unsigned short v;
56
  unsigned short v;
57
 
57
 
58
  if (svarlang_string_count == 0) return("");
58
  if (svarlang_string_count == 0) return("");
59
 
59
 
60
  while (left <= right) {
60
  while (left <= right) {
61
    x = left + ((right - left ) >> 2);
61
    x = left + ((right - left ) >> 2);
62
    v = svarlang_dict[x * 2];
62
    v = svarlang_dict[x * 2];
63
 
63
 
64
    if (id == v) return(svarlang_mem + svarlang_dict[x * 2 + 1]);
64
    if (id == v) return(svarlang_mem + svarlang_dict[x * 2 + 1]);
65
 
65
 
66
    if (id > v) {
66
    if (id > v) {
67
      left = x + 1;
67
      left = x + 1;
68
    } else {
68
    } else {
69
      right = x - 1;
69
      right = x - 1;
70
    }
70
    }
71
  }
71
  }
72
 
72
 
73
  return("");
73
  return("");
74
}
74
}
75
 
75
 
76
 
76
 
77
/* routines below are simplified (dos-based) versions of the libc FILE-related
77
/* routines below are simplified (dos-based) versions of the libc FILE-related
78
 * functions. Using them avoids a dependency on FILE, hence makes the binary
78
 * functions. Using them avoids a dependency on FILE, hence makes the binary
79
 * smaller if the application does not need to pull fopen() and friends */
79
 * smaller if the application does not need to pull fopen() and friends
-
 
80
 * I use pragma aux directives for more compact size. open-watcom only. */
80
#ifndef WITHSTDIO
81
#ifndef WITHSTDIO
81
static unsigned short FOPEN(const char *s) {
-
 
82
  unsigned short fname_seg = FP_SEG(s);
-
 
83
  unsigned short fname_off = FP_OFF(s);
-
 
84
  unsigned short res = 0; /* fd 0 is already used by stdout so it's a good error value */
-
 
85
  _asm {
-
 
86
    push dx
-
 
87
    push ds
-
 
88
 
-
 
89
    mov ax, fname_seg
-
 
90
    mov dx, fname_off
-
 
91
    mov ds, ax
-
 
92
    mov ax, 0x3d00  /* open file, read-only (fname at DS:DX) */
-
 
93
    int 0x21
-
 
94
    pop ds
-
 
95
    jc ERR
-
 
96
    mov res, ax
-
 
97
 
82
 
98
    ERR:
-
 
99
    pop dx
83
static unsigned short FOPEN(const char *s);
100
  }
-
 
101
 
84
 
-
 
85
#pragma aux FOPEN = \
-
 
86
"push ds" \
-
 
87
"mov ds, ax" \
-
 
88
"mov ax, 0x3D00" /* open file, read-only (fname at DS:DX) */ \
102
  return(res);
89
"int 0x21" \
-
 
90
"jnc DONE" \
-
 
91
"xor ax, ax" \
103
}
92
"DONE:" \
-
 
93
"pop ds" \
-
 
94
parm [ax dx] \
-
 
95
value [ax];
104
 
96
 
105
 
97
 
106
static void FCLOSE(unsigned short handle) {
98
static void FCLOSE(unsigned short handle) {
107
  _asm {
99
  _asm {
108
    mov ah, 0x3e
100
    mov ah, 0x3e
109
    mov bx, handle
101
    mov bx, handle
110
    int 0x21
102
    int 0x21
111
  }
103
  }
112
}
104
}
113
 
105
 
114
 
106
 
115
static unsigned short FREAD(unsigned short handle, void *buff, unsigned short bytes) {
107
static unsigned short FREAD(unsigned short handle, void *buff, unsigned short bytes) {
116
  unsigned short buff_seg = FP_SEG(buff);
108
  unsigned short buff_seg = FP_SEG(buff);
117
  unsigned short buff_off = FP_OFF(buff);
109
  unsigned short buff_off = FP_OFF(buff);
118
  unsigned short res = 0;
110
  unsigned short res = 0;
119
 
111
 
120
  _asm {
112
  _asm {
121
    push bx
113
    push bx
122
    push cx
114
    push cx
123
    push dx
115
    push dx
124
 
116
 
125
    mov bx, handle
117
    mov bx, handle
126
    mov cx, bytes
118
    mov cx, bytes
127
    mov dx, buff_off
119
    mov dx, buff_off
128
    mov ax, buff_seg
120
    mov ax, buff_seg
129
    push ds
121
    push ds
130
    mov ds, ax
122
    mov ds, ax
131
    mov ah, 0x3f    /* read cx bytes from file handle bx to DS:DX */
123
    mov ah, 0x3f    /* read cx bytes from file handle bx to DS:DX */
132
    int 0x21
124
    int 0x21
133
    pop ds
125
    pop ds
134
    jc ERR
126
    jc ERR
135
 
127
 
136
    mov res, ax
128
    mov res, ax
137
    ERR:
129
    ERR:
138
 
130
 
139
    pop dx
131
    pop dx
140
    pop cx
132
    pop cx
141
    pop bx
133
    pop bx
142
  }
134
  }
143
 
135
 
144
  return(res);
136
  return(res);
145
}
137
}
146
 
138
 
147
 
139
 
148
static void FSEEK(unsigned short handle, unsigned short bytes) {
140
static void FSEEK(unsigned short handle, unsigned short bytes) {
149
  _asm {
141
  _asm {
150
    mov ax, 0x4201  /* move file pointer from cur pos + CX:DX */
142
    mov ax, 0x4201  /* move file pointer from cur pos + CX:DX */
151
    mov bx, handle
143
    mov bx, handle
152
    xor cx, cx
144
    xor cx, cx
153
    mov dx, bytes
145
    mov dx, bytes
154
    int 0x21
146
    int 0x21
155
  }
147
  }
156
}
148
}
157
#endif
149
#endif
158
 
150
 
159
 
151
 
160
int svarlang_load(const char *fname, const char *lang) {
152
int svarlang_load(const char *fname, const char *lang) {
161
  unsigned short langid;
153
  unsigned short langid;
162
  unsigned short buff16[2];
154
  unsigned short buff16[2];
163
  FHANDLE fd;
155
  FHANDLE fd;
164
  signed char exitcode = 0;
156
  signed char exitcode = 0;
165
  struct {
157
  struct {
166
    unsigned long sig;
158
    unsigned long sig;
167
    unsigned short string_count;
159
    unsigned short string_count;
168
  } hdr;
160
  } hdr;
169
 
161
 
170
  langid = *((unsigned short *)lang);
162
  langid = *((unsigned short *)lang);
171
  langid &= 0xDFDF; /* make sure lang is upcase */
163
  langid &= 0xDFDF; /* make sure lang is upcase */
172
 
164
 
173
  fd = FOPEN(fname);
165
  fd = FOPEN(fname);
174
  if (!fd) return(-1);
166
  if (!fd) return(-1);
175
 
167
 
176
  /* read hdr, sig should be "SvL\x1a" (0x1a4c7653) */
168
  /* read hdr, sig should be "SvL\x1a" (0x1a4c7653) */
177
  if ((FREAD(fd, &hdr, 6) != 6) || (hdr.sig != 0x1a4c7653L) || (hdr.string_count != svarlang_string_count)) {
169
  if ((FREAD(fd, &hdr, 6) != 6) || (hdr.sig != 0x1a4c7653L) || (hdr.string_count != svarlang_string_count)) {
178
    exitcode = -2;
170
    exitcode = -2;
179
    goto FCLOSE_AND_EXIT;
171
    goto FCLOSE_AND_EXIT;
180
  }
172
  }
181
 
173
 
182
  for (;;) {
174
  for (;;) {
183
    /* read next lang id and string table size in file */
175
    /* read next lang id and string table size in file */
184
    if (FREAD(fd, buff16, 4) != 4) {
176
    if (FREAD(fd, buff16, 4) != 4) {
185
      exitcode = -3;
177
      exitcode = -3;
186
      goto FCLOSE_AND_EXIT;
178
      goto FCLOSE_AND_EXIT;
187
    }
179
    }
188
 
180
 
189
    /* is it the lang I am looking for? */
181
    /* is it the lang I am looking for? */
190
    if (buff16[0] == langid) break;
182
    if (buff16[0] == langid) break;
191
 
183
 
192
    /* skip to next lang (in two steps to avoid a potential uint16 overflow) */
184
    /* skip to next lang (in two steps to avoid a potential uint16 overflow) */
193
    FSEEK(fd, svarlang_string_count * 4);
185
    FSEEK(fd, svarlang_string_count * 4);
194
    FSEEK(fd, buff16[1]);
186
    FSEEK(fd, buff16[1]);
195
  }
187
  }
196
 
188
 
197
  /* load dictionary & strings, but only if I have enough memory space */
189
  /* load dictionary & strings, but only if I have enough memory space */
198
  if ((buff16[1] >= svarlang_memsz)
190
  if ((buff16[1] >= svarlang_memsz)
199
   || (FREAD(fd, svarlang_dict, svarlang_string_count * 4) != svarlang_string_count * 4)
191
   || (FREAD(fd, svarlang_dict, svarlang_string_count * 4) != svarlang_string_count * 4)
200
   || (FREAD(fd, svarlang_mem, buff16[1]) != buff16[1])) {
192
   || (FREAD(fd, svarlang_mem, buff16[1]) != buff16[1])) {
201
    exitcode = -4;
193
    exitcode = -4;
202
  }
194
  }
203
 
195
 
204
  FCLOSE_AND_EXIT:
196
  FCLOSE_AND_EXIT:
205
 
197
 
206
  FCLOSE(fd);
198
  FCLOSE(fd);
207
  return(exitcode);
199
  return(exitcode);
208
}
200
}
209
 
201