Subversion Repositories SvarDOS

Rev

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

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