Subversion Repositories SvarDOS

Rev

Rev 1779 | Rev 1781 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1779 Rev 1780
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-2024 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
 * I use pragma aux directives for more compact size. open-watcom only. */
81
#ifndef WITHSTDIO
81
#ifndef WITHSTDIO
82
 
82
 
83
static unsigned short FOPEN(const char *s);
83
static unsigned short FOPEN(const char *s);
84
 
84
 
85
#pragma aux FOPEN = \
85
#pragma aux FOPEN = \
86
"push ds" \
86
"push ds" \
87
"mov ds, ax" \
87
"mov ds, ax" \
88
"mov ax, 0x3D00" /* open file, read-only (fname at DS:DX) */ \
88
"mov ax, 0x3D00" /* open file, read-only (fname at DS:DX) */ \
89
"int 0x21" \
89
"int 0x21" \
90
"jnc DONE" \
90
"jnc DONE" \
91
"xor ax, ax" \
91
"xor ax, ax" \
92
"DONE:" \
92
"DONE:" \
93
"pop ds" \
93
"pop ds" \
94
parm [ax dx] \
94
parm [ax dx] \
95
value [ax];
95
value [ax];
96
 
96
 
97
 
97
 
98
static void FCLOSE(unsigned short handle) {
98
static void FCLOSE(unsigned short handle);
99
  _asm {
99
 
100
    mov ah, 0x3e
100
#pragma aux FCLOSE = \
101
    mov bx, handle
101
"mov ah, 0x3E" \
102
    int 0x21
102
"int 0x21" \
-
 
103
modify [ax]  /* AX might contain an error code on failure */ \
103
  }
104
parm [bx]
104
}
-
 
105
 
105
 
106
 
106
 
107
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) {
108
  unsigned short buff_seg = FP_SEG(buff);
108
  unsigned short buff_seg = FP_SEG(buff);
109
  unsigned short buff_off = FP_OFF(buff);
109
  unsigned short buff_off = FP_OFF(buff);
110
  unsigned short res = 0;
110
  unsigned short res = 0;
111
 
111
 
112
  _asm {
112
  _asm {
113
    push bx
113
    push bx
114
    push cx
114
    push cx
115
    push dx
115
    push dx
116
 
116
 
117
    mov bx, handle
117
    mov bx, handle
118
    mov cx, bytes
118
    mov cx, bytes
119
    mov dx, buff_off
119
    mov dx, buff_off
120
    mov ax, buff_seg
120
    mov ax, buff_seg
121
    push ds
121
    push ds
122
    mov ds, ax
122
    mov ds, ax
123
    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 */
124
    int 0x21
124
    int 0x21
125
    pop ds
125
    pop ds
126
    jc ERR
126
    jc ERR
127
 
127
 
128
    mov res, ax
128
    mov res, ax
129
    ERR:
129
    ERR:
130
 
130
 
131
    pop dx
131
    pop dx
132
    pop cx
132
    pop cx
133
    pop bx
133
    pop bx
134
  }
134
  }
135
 
135
 
136
  return(res);
136
  return(res);
137
}
137
}
138
 
138
 
139
 
139
 
140
static void FSEEK(unsigned short handle, unsigned short bytes) {
140
static void FSEEK(unsigned short handle, unsigned short bytes) {
141
  _asm {
141
  _asm {
142
    mov ax, 0x4201  /* move file pointer from cur pos + CX:DX */
142
    mov ax, 0x4201  /* move file pointer from cur pos + CX:DX */
143
    mov bx, handle
143
    mov bx, handle
144
    xor cx, cx
144
    xor cx, cx
145
    mov dx, bytes
145
    mov dx, bytes
146
    int 0x21
146
    int 0x21
147
  }
147
  }
148
}
148
}
149
#endif
149
#endif
150
 
150
 
151
 
151
 
152
int svarlang_load(const char *fname, const char *lang) {
152
int svarlang_load(const char *fname, const char *lang) {
153
  unsigned short langid;
153
  unsigned short langid;
154
  unsigned short buff16[2];
154
  unsigned short buff16[2];
155
  FHANDLE fd;
155
  FHANDLE fd;
156
  signed char exitcode = 0;
156
  signed char exitcode = 0;
157
  struct {
157
  struct {
158
    unsigned long sig;
158
    unsigned long sig;
159
    unsigned short string_count;
159
    unsigned short string_count;
160
  } hdr;
160
  } hdr;
161
 
161
 
162
  langid = *((unsigned short *)lang);
162
  langid = *((unsigned short *)lang);
163
  langid &= 0xDFDF; /* make sure lang is upcase */
163
  langid &= 0xDFDF; /* make sure lang is upcase */
164
 
164
 
165
  fd = FOPEN(fname);
165
  fd = FOPEN(fname);
166
  if (!fd) return(-1);
166
  if (!fd) return(-1);
167
 
167
 
168
  /* read hdr, sig should be "SvL\x1a" (0x1a4c7653) */
168
  /* read hdr, sig should be "SvL\x1a" (0x1a4c7653) */
169
  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)) {
170
    exitcode = -2;
170
    exitcode = -2;
171
    goto FCLOSE_AND_EXIT;
171
    goto FCLOSE_AND_EXIT;
172
  }
172
  }
173
 
173
 
174
  for (;;) {
174
  for (;;) {
175
    /* read next lang id and string table size in file */
175
    /* read next lang id and string table size in file */
176
    if (FREAD(fd, buff16, 4) != 4) {
176
    if (FREAD(fd, buff16, 4) != 4) {
177
      exitcode = -3;
177
      exitcode = -3;
178
      goto FCLOSE_AND_EXIT;
178
      goto FCLOSE_AND_EXIT;
179
    }
179
    }
180
 
180
 
181
    /* is it the lang I am looking for? */
181
    /* is it the lang I am looking for? */
182
    if (buff16[0] == langid) break;
182
    if (buff16[0] == langid) break;
183
 
183
 
184
    /* 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) */
185
    FSEEK(fd, svarlang_string_count * 4);
185
    FSEEK(fd, svarlang_string_count * 4);
186
    FSEEK(fd, buff16[1]);
186
    FSEEK(fd, buff16[1]);
187
  }
187
  }
188
 
188
 
189
  /* load dictionary & strings, but only if I have enough memory space */
189
  /* load dictionary & strings, but only if I have enough memory space */
190
  if ((buff16[1] >= svarlang_memsz)
190
  if ((buff16[1] >= svarlang_memsz)
191
   || (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)
192
   || (FREAD(fd, svarlang_mem, buff16[1]) != buff16[1])) {
192
   || (FREAD(fd, svarlang_mem, buff16[1]) != buff16[1])) {
193
    exitcode = -4;
193
    exitcode = -4;
194
  }
194
  }
195
 
195
 
196
  FCLOSE_AND_EXIT:
196
  FCLOSE_AND_EXIT:
197
 
197
 
198
  FCLOSE(fd);
198
  FCLOSE(fd);
199
  return(exitcode);
199
  return(exitcode);
200
}
200
}
201
 
201