Subversion Repositories SvarDOS

Rev

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

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