Subversion Repositories SvarDOS

Rev

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

Rev 1293 Rev 1298
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-2023 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>
38
#include <i86.h>
39
typedef unsigned short FHANDLE;
39
typedef unsigned short FHANDLE;
40
 
40
 
41
#endif
41
#endif
42
 
42
 
43
#include <stdlib.h>  /* NULL */
-
 
-
 
43
 
44
#include <string.h>  /* memcmp(), strcpy() */
44
#include <string.h>  /* strcpy() */
45
 
45
 
46
#include "svarlang.h"
46
#include "svarlang.h"
47
 
47
 
48
 
48
 
49
/* supplied through DEFLANG.C */
49
/* supplied through DEFLANG.C */
50
extern char svarlang_mem[];
50
extern char svarlang_mem[];
51
extern unsigned short svarlang_dict[];
51
extern unsigned short svarlang_dict[];
52
extern const unsigned short svarlang_memsz;
52
extern const unsigned short svarlang_memsz;
53
extern const unsigned short svarlang_string_count;
53
extern const unsigned short svarlang_string_count;
54
 
54
 
-
 
55
 
55
const char *svarlang_strid(unsigned short id) {
56
const char *svarlang_strid(unsigned short id) {
56
   size_t left = 0, right = svarlang_string_count - 1, x;
57
  size_t left = 0, right = svarlang_string_count - 1, x;
57
   unsigned short v;
58
  unsigned short v;
-
 
59
 
-
 
60
  if (svarlang_string_count == 0) return("");
-
 
61
 
-
 
62
  while (left <= right) {
-
 
63
    x = left + ( (right - left ) >> 2 );
-
 
64
    v = svarlang_dict[x * 2];
-
 
65
 
-
 
66
    if (id == v) return(svarlang_mem + svarlang_dict[x * 2 + 1]);
58
 
67
 
-
 
68
    if (id > v) {
-
 
69
      left = x + 1;
-
 
70
    } else {
59
   if (svarlang_string_count == 0) return "";
71
      right = x - 1;
-
 
72
    }
-
 
73
  }
60
 
74
 
61
   while (left <= right ) {
-
 
62
      x = left + ( (right - left ) >> 2 );
-
 
63
      v = svarlang_dict[x * 2];
-
 
64
      if ( id == v )  {
-
 
65
        return svarlang_mem + svarlang_dict[x * 2 + 1];
-
 
66
      }
-
 
67
      else if ( id > v ) left = x + 1;
-
 
68
      else right = x - 1;
-
 
69
   }
-
 
70
   return "";
75
  return("");
71
}
76
}
72
 
77
 
73
 
78
 
74
/* routines below are simplified (dos-based) versions of the libc FILE-related
79
/* routines below are simplified (dos-based) versions of the libc FILE-related
75
 * functions. Using them avoids a dependency on FILE, hence makes the binary
80
 * functions. Using them avoids a dependency on FILE, hence makes the binary
76
 * smaller if the application does not need to pull fopen() and friends */
81
 * smaller if the application does not need to pull fopen() and friends */
77
#ifndef WITHSTDIO
82
#ifndef WITHSTDIO
78
static unsigned short FOPEN(const char *s) {
83
static unsigned short FOPEN(const char *s) {
79
  unsigned short fname_seg = FP_SEG(s);
84
  unsigned short fname_seg = FP_SEG(s);
80
  unsigned short fname_off = FP_OFF(s);
85
  unsigned short fname_off = FP_OFF(s);
81
  unsigned short res = 0; /* fd 0 is already used by stdout so it's a good error value */
86
  unsigned short res = 0; /* fd 0 is already used by stdout so it's a good error value */
82
  _asm {
87
  _asm {
83
    push dx
88
    push dx
84
    push ds
89
    push ds
85
 
90
 
86
    mov ax, fname_seg
91
    mov ax, fname_seg
87
    mov dx, fname_off
92
    mov dx, fname_off
88
    mov ds, ax
93
    mov ds, ax
89
    mov ax, 0x3d00  /* open file, read-only (fname at DS:DX) */
94
    mov ax, 0x3d00  /* open file, read-only (fname at DS:DX) */
90
    int 0x21
95
    int 0x21
91
    pop ds
96
    pop ds
92
    jc ERR
97
    jc ERR
93
    mov res, ax
98
    mov res, ax
94
 
99
 
95
    ERR:
100
    ERR:
96
    pop dx
101
    pop dx
97
  }
102
  }
98
 
103
 
99
  return(res);
104
  return(res);
100
}
105
}
101
 
106
 
102
 
107
 
103
static void FCLOSE(unsigned short handle) {
108
static void FCLOSE(unsigned short handle) {
104
  _asm {
109
  _asm {
105
    push bx
110
    push bx
106
 
111
 
107
    mov ah, 0x3e
112
    mov ah, 0x3e
108
    mov bx, handle
113
    mov bx, handle
109
    int 0x21
114
    int 0x21
110
 
115
 
111
    pop bx
116
    pop bx
112
  }
117
  }
113
}
118
}
114
 
119
 
115
 
120
 
116
static unsigned short FREAD(unsigned short handle, void *buff, unsigned short bytes) {
121
static unsigned short FREAD(unsigned short handle, void *buff, unsigned short bytes) {
117
  unsigned short buff_seg = FP_SEG(buff);
122
  unsigned short buff_seg = FP_SEG(buff);
118
  unsigned short buff_off = FP_OFF(buff);
123
  unsigned short buff_off = FP_OFF(buff);
119
  unsigned short res = 0;
124
  unsigned short res = 0;
120
 
125
 
121
  _asm {
126
  _asm {
122
    push bx
127
    push bx
123
    push cx
128
    push cx
124
    push dx
129
    push dx
125
 
130
 
126
    mov bx, handle
131
    mov bx, handle
127
    mov cx, bytes
132
    mov cx, bytes
128
    mov dx, buff_off
133
    mov dx, buff_off
129
    mov ax, buff_seg
134
    mov ax, buff_seg
130
    push ds
135
    push ds
131
    mov ds, ax
136
    mov ds, ax
132
    mov ah, 0x3f    /* read cx bytes from file handle bx to DS:DX */
137
    mov ah, 0x3f    /* read cx bytes from file handle bx to DS:DX */
133
    int 0x21
138
    int 0x21
134
    pop ds
139
    pop ds
135
    jc ERR
140
    jc ERR
136
 
141
 
137
    mov res, ax
142
    mov res, ax
138
    ERR:
143
    ERR:
139
 
144
 
140
    pop dx
145
    pop dx
141
    pop cx
146
    pop cx
142
    pop bx
147
    pop bx
143
  }
148
  }
144
 
149
 
145
  return(res);
150
  return(res);
146
}
151
}
147
 
152
 
148
 
153
 
149
static void FSEEK(unsigned short handle, unsigned short bytes) {
154
static void FSEEK(unsigned short handle, unsigned short bytes) {
150
  _asm {
155
  _asm {
151
    push bx
156
    push bx
152
    push cx
157
    push cx
153
    push dx
158
    push dx
154
 
159
 
155
    mov ax, 0x4201  /* move file pointer from cur pos + CX:DX */
160
    mov ax, 0x4201  /* move file pointer from cur pos + CX:DX */
156
    mov bx, handle
161
    mov bx, handle
157
    xor cx, cx
162
    xor cx, cx
158
    mov dx, bytes
163
    mov dx, bytes
159
    int 0x21
164
    int 0x21
160
 
165
 
161
    pop dx
166
    pop dx
162
    pop cx
167
    pop cx
163
    pop bx
168
    pop bx
164
  }
169
  }
165
}
170
}
166
#endif
171
#endif
167
 
172
 
168
 
173
 
169
int svarlang_load(const char *fname, const char *lang) {
174
int svarlang_load(const char *fname, const char *lang) {
170
  unsigned short langid;
175
  unsigned short langid;
171
  unsigned long hdr;
176
  unsigned long hdr;
172
  unsigned short buff16[2];
177
  unsigned short buff16[2];
173
  FHANDLE fd;
178
  FHANDLE fd;
174
  unsigned short string_count;
179
  unsigned short string_count;
175
 
180
 
176
  langid = *((unsigned short *)lang);
181
  langid = *((unsigned short *)lang);
177
  langid &= 0xDFDF; /* make sure lang is upcase */
182
  langid &= 0xDFDF; /* make sure lang is upcase */
178
 
183
 
179
  fd = FOPEN(fname);
184
  fd = FOPEN(fname);
180
  if (!fd) return(-1);
185
  if (!fd) return(-1);
181
 
186
 
182
  /* read hdr, should be "SvL\x1a" */
187
  /* read hdr, should be "SvL\x1a" */
183
  if ((FREAD(fd, &hdr, 4) != 4) || (hdr != 0x1a4c7653L)) { /* 0x1a4c7653 = 'SvL\x1a' */
188
  if ((FREAD(fd, &hdr, 4) != 4) || (hdr != 0x1a4c7653L)) { /* 0x1a4c7653 = 'SvL\x1a' */
184
    FCLOSE(fd);
189
    FCLOSE(fd);
185
    return(-3);
190
    return(-3);
186
  }
191
  }
187
 
192
 
188
  /* read string count */
193
  /* read string count */
189
  if ((FREAD(fd, &string_count, 2) != 2) || (string_count != svarlang_string_count)) {
194
  if ((FREAD(fd, &string_count, 2) != 2) || (string_count != svarlang_string_count)) {
190
    FCLOSE(fd);
195
    FCLOSE(fd);
191
    return(-6);
196
    return(-6);
192
  }
197
  }
193
 
198
 
194
  /* read next lang id and string table size in file */
199
  /* read next lang id and string table size in file */
195
  while (FREAD(fd, buff16, 4) == 4) {
200
  while (FREAD(fd, buff16, 4) == 4) {
196
 
201
 
197
    /* is it the lang I am looking for? */
202
    /* is it the lang I am looking for? */
198
    if (buff16[0] != langid) { /* skip to next lang */
203
    if (buff16[0] != langid) { /* skip to next lang */
199
      FSEEK(fd, svarlang_string_count * 4);
204
      FSEEK(fd, svarlang_string_count * 4);
200
      FSEEK(fd, buff16[1]);
205
      FSEEK(fd, buff16[1]);
201
      continue;
206
      continue;
202
    }
207
    }
203
 
208
 
204
    /* found - but do I have enough memory space? */
209
    /* found - but do I have enough memory space? */
205
    if (buff16[1] >= svarlang_memsz) {
210
    if (buff16[1] >= svarlang_memsz) {
206
      FCLOSE(fd);
211
      FCLOSE(fd);
207
      return(-4);
212
      return(-4);
208
    }
213
    }
209
 
214
 
210
    /* load dictionary & strings */
215
    /* load dictionary & strings */
211
    if ((FREAD(fd, svarlang_dict, svarlang_string_count * 4) != svarlang_string_count * 4) ||
216
    if ((FREAD(fd, svarlang_dict, svarlang_string_count * 4) != svarlang_string_count * 4) ||
212
       (FREAD(fd, svarlang_mem, buff16[1]) != buff16[1])) {
217
       (FREAD(fd, svarlang_mem, buff16[1]) != buff16[1])) {
213
      FCLOSE(fd);
218
      FCLOSE(fd);
214
      return -7;
219
      return -7;
215
    }
220
    }
216
    FCLOSE(fd);
221
    FCLOSE(fd);
217
    return(0);
222
    return(0);
218
  }
223
  }
219
 
224
 
220
  FCLOSE(fd);
225
  FCLOSE(fd);
221
  return(-5);
226
  return(-5);
222
}
227
}
223
 
228