Subversion Repositories SvarDOS

Rev

Rev 1281 | Rev 1293 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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