Subversion Repositories SvarDOS

Rev

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

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