Subversion Repositories SvarDOS

Rev

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

Rev 603 Rev 606
1
/*
1
/*
2
 * Locales configuration for SvarDOS
2
 * Locales configuration for SvarDOS
3
 *
3
 *
4
 * Copyright (C) Mateusz Viste 2015-2022
4
 * Copyright (C) Mateusz Viste 2015-2022
5
 *
5
 *
6
 * MIT license
6
 * MIT license
7
 *
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9
 * of this software and associated documentation files (the "Software"), to
9
 * of this software and associated documentation files (the "Software"), to
10
 * deal in the Software without restriction, including without limitation the
10
 * deal in the Software without restriction, including without limitation the
11
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12
 * sell copies of the Software, and to permit persons to whom the Software is
12
 * sell copies of the Software, and to permit persons to whom the Software is
13
 * furnished to do so, subject to the following conditions:
13
 * furnished to do so, subject to the following conditions:
14
 *
14
 *
15
 * The above copyright notice and this permission notice shall be included in
15
 * The above copyright notice and this permission notice shall be included in
16
 * all copies or substantial portions of the Software.
16
 * all copies or substantial portions of the Software.
17
 *
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24
 * IN THE SOFTWARE.
24
 * IN THE SOFTWARE.
25
 */
25
 */
26
 
26
 
27
#include <stdio.h>
27
#include <stdio.h>
28
#include <stdlib.h> /* atoi() */
28
#include <stdlib.h> /* atoi() */
29
#include <string.h> /* strchr */
29
#include <string.h> /* strchr */
30
 
30
 
31
#include "svarlang.lib/svarlang.h"
31
#include "svarlang.lib/svarlang.h"
32
 
32
 
33
#include "country.h"
33
#include "country.h"
34
 
34
 
35
#define PVER "20220203"
35
#define PVER "20220203"
36
#define PDATE "2015-2022"
36
#define PDATE "2015-2022"
37
 
37
 
38
 
38
 
39
enum NLS_STRINGS {
39
enum NLS_STRINGS {
40
  NLS_HLP_VER           = 0x0000,
40
  NLS_HLP_VER           = 0x0000,
41
  NLS_HLP_DESC          = 0x0001,
41
  NLS_HLP_DESC          = 0x0001,
42
  NLS_HLP_USAGE         = 0x0002,
42
  NLS_HLP_USAGE         = 0x0002,
43
  NLS_HLP_OPTIONS       = 0x0003,
43
  NLS_HLP_OPTIONS       = 0x0003,
44
  NLS_HLP_COUNTRY       = 0x000A,
44
  NLS_HLP_COUNTRY       = 0x000A,
45
  NLS_HLP_CP            = 0x000B,
45
  NLS_HLP_CP            = 0x000B,
46
  NLS_HLP_DECIM         = 0x000C,
46
  NLS_HLP_DECIM         = 0x000C,
47
  NLS_HLP_THOUS         = 0x000D,
47
  NLS_HLP_THOUS         = 0x000D,
48
  NLS_HLP_DATESEP       = 0x000E,
48
  NLS_HLP_DATESEP       = 0x000E,
49
  NLS_HLP_DATEFMT       = 0x000F,
49
  NLS_HLP_DATEFMT       = 0x000F,
50
  NLS_HLP_TIMESEP       = 0x0010,
50
  NLS_HLP_TIMESEP       = 0x0010,
51
  NLS_HLP_TIMEFMT       = 0x0011,
51
  NLS_HLP_TIMEFMT       = 0x0011,
52
  NLS_HLP_CURR          = 0x0012,
52
  NLS_HLP_CURR          = 0x0012,
53
  NLS_HLP_CURRPOS0      = 0x0013,
53
  NLS_HLP_CURRPOS0      = 0x0013,
54
  NLS_HLP_CURRPOS1      = 0x0014,
54
  NLS_HLP_CURRPOS1      = 0x0014,
55
  NLS_HLP_CURRPOS2      = 0x0015,
55
  NLS_HLP_CURRPOS2      = 0x0015,
56
  NLS_HLP_CURRSPC       = 0x0016,
56
  NLS_HLP_CURRSPC       = 0x0016,
57
  NLS_HLP_CURRPREC      = 0x0017,
57
  NLS_HLP_CURRPREC      = 0x0017,
58
  NLS_HLP_YESNO         = 0x0018,
58
  NLS_HLP_YESNO         = 0x0018,
59
  NLS_HLP_INFOLOC1      = 0x0032,
59
  NLS_HLP_INFOLOC1      = 0x0032,
60
  NLS_HLP_INFOLOC2      = 0x0033,
60
  NLS_HLP_INFOLOC2      = 0x0033,
61
 
61
 
62
  NLS_INFO_COUNTRY      = 0x0700,
62
  NLS_INFO_COUNTRY      = 0x0700,
63
  NLS_INFO_CODEPAGE     = 0x0701,
63
  NLS_INFO_CODEPAGE     = 0x0701,
64
  NLS_INFO_DECSEP       = 0x0702,
64
  NLS_INFO_DECSEP       = 0x0702,
65
  NLS_INFO_THOUSEP      = 0x0703,
65
  NLS_INFO_THOUSEP      = 0x0703,
66
  NLS_INFO_DATEFMT      = 0x0704,
66
  NLS_INFO_DATEFMT      = 0x0704,
67
  NLS_INFO_TIMEFMT      = 0x0705,
67
  NLS_INFO_TIMEFMT      = 0x0705,
68
  NLS_INFO_YESNO        = 0x0706,
68
  NLS_INFO_YESNO        = 0x0706,
69
  NLS_INFO_CURREXAMPLE  = 0x0707,
69
  NLS_INFO_CURREXAMPLE  = 0x0707,
70
  NLS_MAKESURE          = 0x0709,
70
  NLS_MAKESURE          = 0x0709,
71
 
71
 
72
  NLS_ERR_FILEPATHTWICE = 0x0900,
72
  NLS_ERR_FILEPATHTWICE = 0x0900,
73
  NLS_ERR_BADPATH       = 0x0901,
73
  NLS_ERR_BADPATH       = 0x0901,
74
  NLS_ERR_READFAIL      = 0x0902,
74
  NLS_ERR_READFAIL      = 0x0902,
75
  NLS_ERR_INVPARAM      = 0x0903
75
  NLS_ERR_INVPARAM      = 0x0903
76
};
76
};
77
 
77
 
78
 
78
 
79
static void nls_puts(enum NLS_STRINGS id) {
79
static void output(const char *s) {
-
 
80
  _asm {
80
  puts(svarlang_strid(id));
81
    /* set cx to strlen(s) */
-
 
82
    push ds
-
 
83
    pop es
-
 
84
    mov di, s
-
 
85
    xor al, al
-
 
86
    cld
-
 
87
    mov cx, 0xff
-
 
88
    repne scasb  /* compare ES:DI with AL, inc DI until match */
-
 
89
    mov cx, di
-
 
90
    sub cx, s
-
 
91
    dec cx
-
 
92
    /* output via DOS */
-
 
93
    mov ah, 0x40  /* write to handle */
-
 
94
    mov bx, 1     /* 1=stdout */
-
 
95
    mov dx, s
-
 
96
    int 0x21
-
 
97
  }
-
 
98
}
-
 
99
 
-
 
100
 
-
 
101
static void crlf(void) {
-
 
102
  output("\r\n");
-
 
103
}
-
 
104
 
-
 
105
 
-
 
106
static void outputnl(const char *s) {
-
 
107
  output(s);
-
 
108
  crlf();
81
}
109
}
82
 
110
 
83
 
111
 
84
static void nls_put(enum NLS_STRINGS id) {
112
static void nls_put(enum NLS_STRINGS id) {
85
  printf("%s", svarlang_strid(id));
113
  output(svarlang_strid(id));
86
}
114
}
87
 
115
 
88
 
116
 
89
static void crlf(void) {
117
static void nls_puts(enum NLS_STRINGS id) {
90
  puts("");
118
  nls_put(id);
-
 
119
  crlf();
91
}
120
}
92
 
121
 
93
 
122
 
94
static void about(void) {
123
static void about(void) {
95
  printf("localcfg ");
124
  output("localcfg ");
96
  nls_put(NLS_HLP_VER);
125
  nls_put(NLS_HLP_VER);
97
  puts(" " PVER ", (C) " PDATE " Mateusz Viste");
126
  outputnl(" " PVER ", (C) " PDATE " Mateusz Viste");
98
  crlf();
-
 
99
  nls_puts(NLS_HLP_DESC);
127
  nls_puts(NLS_HLP_DESC);
100
  crlf();
128
  crlf();
101
  nls_puts(NLS_HLP_USAGE);
129
  nls_puts(NLS_HLP_USAGE);
102
  crlf();
130
  crlf();
103
  nls_puts(NLS_HLP_OPTIONS);
131
  nls_puts(NLS_HLP_OPTIONS);
104
  crlf();
132
  crlf();
105
  nls_puts(NLS_HLP_COUNTRY);
133
  nls_puts(NLS_HLP_COUNTRY);
106
  nls_puts(NLS_HLP_CP);
134
  nls_puts(NLS_HLP_CP);
107
  nls_puts(NLS_HLP_DECIM);
135
  nls_puts(NLS_HLP_DECIM);
108
  nls_puts(NLS_HLP_THOUS);
136
  nls_puts(NLS_HLP_THOUS);
109
  nls_puts(NLS_HLP_DATESEP);
137
  nls_puts(NLS_HLP_DATESEP);
110
  nls_puts(NLS_HLP_DATEFMT);
138
  nls_puts(NLS_HLP_DATEFMT);
111
  nls_puts(NLS_HLP_TIMESEP);
139
  nls_puts(NLS_HLP_TIMESEP);
112
  nls_puts(NLS_HLP_TIMEFMT);
140
  nls_puts(NLS_HLP_TIMEFMT);
113
  nls_puts(NLS_HLP_CURR);
141
  nls_puts(NLS_HLP_CURR);
114
  nls_puts(NLS_HLP_CURRPOS0);
142
  nls_puts(NLS_HLP_CURRPOS0);
115
  nls_puts(NLS_HLP_CURRPOS1);
143
  nls_puts(NLS_HLP_CURRPOS1);
116
  nls_puts(NLS_HLP_CURRPOS2);
144
  nls_puts(NLS_HLP_CURRPOS2);
117
  nls_puts(NLS_HLP_CURRSPC);
145
  nls_puts(NLS_HLP_CURRSPC);
118
  nls_puts(NLS_HLP_CURRPREC);
146
  nls_puts(NLS_HLP_CURRPREC);
119
  nls_puts(NLS_HLP_YESNO);
147
  nls_puts(NLS_HLP_YESNO);
120
  crlf();
148
  crlf();
121
  nls_puts(NLS_HLP_INFOLOC1);
149
  nls_puts(NLS_HLP_INFOLOC1);
122
  nls_puts(NLS_HLP_INFOLOC2);
150
  nls_puts(NLS_HLP_INFOLOC2);
123
}
151
}
124
 
152
 
125
 
153
 
126
static char *datestring(struct country *c) {
154
static char *datestring(struct country *c) {
127
  static char result[16];
155
  static char result[16];
128
  switch (c->CTYINFO.datefmt) {
156
  switch (c->CTYINFO.datefmt) {
129
    case COUNTRY_DATE_MDY:
157
    case COUNTRY_DATE_MDY:
130
      sprintf(result, "12%c31%c1990", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
158
      sprintf(result, "12%c31%c1990", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
131
      break;
159
      break;
132
    case COUNTRY_DATE_DMY:
160
    case COUNTRY_DATE_DMY:
133
      sprintf(result, "31%c12%c1990", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
161
      sprintf(result, "31%c12%c1990", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
134
      break;
162
      break;
135
    case COUNTRY_DATE_YMD:
163
    case COUNTRY_DATE_YMD:
136
    default:
164
    default:
137
      sprintf(result, "1990%c12%c31", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
165
      sprintf(result, "1990%c12%c31", c->CTYINFO.datesep[0], c->CTYINFO.datesep[0]);
138
      break;
166
      break;
139
  }
167
  }
140
  return(result);
168
  return(result);
141
}
169
}
142
 
170
 
143
 
171
 
144
static char *timestring(struct country *c) {
172
static char *timestring(struct country *c) {
145
  static char result[16];
173
  static char result[16];
146
  if (c->CTYINFO.timefmt == COUNTRY_TIME12) {
174
  if (c->CTYINFO.timefmt == COUNTRY_TIME12) {
147
    sprintf(result, "11%c59%c59 PM", c->CTYINFO.timesep[0], c->CTYINFO.timesep[0]);
175
    sprintf(result, "11%c59%c59 PM", c->CTYINFO.timesep[0], c->CTYINFO.timesep[0]);
148
  } else {
176
  } else {
149
    sprintf(result, "23%c59%c59", c->CTYINFO.timesep[0], c->CTYINFO.timesep[0]);
177
    sprintf(result, "23%c59%c59", c->CTYINFO.timesep[0], c->CTYINFO.timesep[0]);
150
  }
178
  }
151
  return(result);
179
  return(result);
152
}
180
}
153
 
181
 
154
 
182
 
155
static char *currencystring(struct country *c) {
183
static char *currencystring(struct country *c) {
156
  static char result[16];
184
  static char result[16];
157
  char decimalpart[16];
185
  char decimalpart[16];
158
  char space[2] = {0, 0};
186
  char space[2] = {0, 0};
159
  char decsym[8];
187
  char decsym[8];
160
  char cursym[8];
188
  char cursym[8];
161
  decimalpart[0] = '1';
189
  decimalpart[0] = '1';
162
  decimalpart[1] = '2';
190
  decimalpart[1] = '2';
163
  decimalpart[2] = '3';
191
  decimalpart[2] = '3';
164
  decimalpart[3] = '4';
192
  decimalpart[3] = '4';
165
  decimalpart[4] = '5';
193
  decimalpart[4] = '5';
166
  decimalpart[5] = '6';
194
  decimalpart[5] = '6';
167
  decimalpart[6] = '7';
195
  decimalpart[6] = '7';
168
  decimalpart[7] = '8';
196
  decimalpart[7] = '8';
169
  decimalpart[8] = '9';
197
  decimalpart[8] = '9';
170
  decimalpart[9] = 0;
198
  decimalpart[9] = 0;
171
  /* prepare the decimal string first */
199
  /* prepare the decimal string first */
172
  if (c->CTYINFO.currprec < 9) {
200
  if (c->CTYINFO.currprec < 9) {
173
    decimalpart[c->CTYINFO.currprec] = 0;
201
    decimalpart[c->CTYINFO.currprec] = 0;
174
  }
202
  }
175
  /* prepare the currency space string */
203
  /* prepare the currency space string */
176
  if (c->CTYINFO.currspace != 0) {
204
  if (c->CTYINFO.currspace != 0) {
177
    space[0] = ' ';
205
    space[0] = ' ';
178
  }
206
  }
179
  /* prepare the currency and decimal symbols */
207
  /* prepare the currency and decimal symbols */
180
  if (c->CTYINFO.currdecsym != 0) { /* currency replaces the decimal point */
208
  if (c->CTYINFO.currdecsym != 0) { /* currency replaces the decimal point */
181
    sprintf(decsym, "%s", c->CTYINFO.currsym);
209
    sprintf(decsym, "%s", c->CTYINFO.currsym);
182
    cursym[0] = 0;
210
    cursym[0] = 0;
183
  } else {
211
  } else {
184
    sprintf(decsym, "%c", c->CTYINFO.decimal[0]);
212
    sprintf(decsym, "%c", c->CTYINFO.decimal[0]);
185
    sprintf(cursym, "%s", c->CTYINFO.currsym);
213
    sprintf(cursym, "%s", c->CTYINFO.currsym);
186
  }
214
  }
187
  if (c->CTYINFO.currprec == 0) decsym[0] = 0;
215
  if (c->CTYINFO.currprec == 0) decsym[0] = 0;
188
  /* compute the final string */
216
  /* compute the final string */
189
  if (c->CTYINFO.currpos == 0) { /* currency precedes value */
217
  if (c->CTYINFO.currpos == 0) { /* currency precedes value */
190
    sprintf(result, "%s%s99%s%s", cursym, space, decsym, decimalpart);
218
    sprintf(result, "%s%s99%s%s", cursym, space, decsym, decimalpart);
191
  } else { /* currency follows value or replaces decimal symbol */
219
  } else { /* currency follows value or replaces decimal symbol */
192
    sprintf(result, "99%s%s%s%s", decsym, decimalpart, space, cursym);
220
    sprintf(result, "99%s%s%s%s", decsym, decimalpart, space, cursym);
193
  }
221
  }
194
  return(result);
222
  return(result);
195
}
223
}
196
 
224
 
197
 
225
 
198
/* checks if str starts with prefix. returns 0 if so, non-zero otherwise. */
226
/* checks if str starts with prefix. returns 0 if so, non-zero otherwise. */
199
static int stringstartswith(char *str, char *prefix) {
227
static int stringstartswith(char *str, char *prefix) {
200
  for (;;) {
228
  for (;;) {
201
    /* end of prefix means success */
229
    /* end of prefix means success */
202
    if (*prefix == 0) return(0);
230
    if (*prefix == 0) return(0);
203
    /* otherwise there is no match */
231
    /* otherwise there is no match */
204
    if (*str != *prefix) return(-1);
232
    if (*str != *prefix) return(-1);
205
    /* if match good so far, look at next char */
233
    /* if match good so far, look at next char */
206
    str += 1;
234
    str += 1;
207
    prefix += 1;
235
    prefix += 1;
208
  }
236
  }
209
}
237
}
210
 
238
 
211
 
239
 
212
/* processes an argument. returns 0 on success, non-zero otherwise. */
240
/* processes an argument. returns 0 on success, non-zero otherwise. */
213
static int processarg(char *arg, struct country *c) {
241
static int processarg(char *arg, struct country *c) {
214
  char *value;
242
  char *value;
215
  int intvalue;
243
  int intvalue;
216
  /* an option must start with a '/' */
244
  /* an option must start with a '/' */
217
  if (arg[0] != '/') return(-1);
245
  if (arg[0] != '/') return(-1);
218
  arg += 1; /* skip the slash */
246
  arg += 1; /* skip the slash */
219
  /* find where the value starts */
247
  /* find where the value starts */
220
  value = strchr(arg, ':');
248
  value = strchr(arg, ':');
221
  /* if no value present, fail */
249
  /* if no value present, fail */
222
  if (value == NULL) return(-2);
250
  if (value == NULL) return(-2);
223
  value += 1;
251
  value += 1;
224
  if (*value == 0) return(-3);
252
  if (*value == 0) return(-3);
225
  /* interpret the option now */
253
  /* interpret the option now */
226
  if (stringstartswith(arg, "country:") == 0) {
254
  if (stringstartswith(arg, "country:") == 0) {
227
    intvalue = atoi(value);
255
    intvalue = atoi(value);
228
    if ((intvalue > 0) && (intvalue < 1000)) {
256
    if ((intvalue > 0) && (intvalue < 1000)) {
229
      c->CTYINFO.id = intvalue;
257
      c->CTYINFO.id = intvalue;
230
      return(0);
258
      return(0);
231
    }
259
    }
232
  } else if (stringstartswith(arg, "cp:") == 0) {
260
  } else if (stringstartswith(arg, "cp:") == 0) {
233
    intvalue = atoi(value);
261
    intvalue = atoi(value);
234
    if ((intvalue > 0) && (intvalue < 1000)) {
262
    if ((intvalue > 0) && (intvalue < 1000)) {
235
      c->CTYINFO.codepage = intvalue;
263
      c->CTYINFO.codepage = intvalue;
236
      return(0);
264
      return(0);
237
    }
265
    }
238
  } else if (stringstartswith(arg, "decim:") == 0) {
266
  } else if (stringstartswith(arg, "decim:") == 0) {
239
    if (value[1] == 0) { /* value must be exactly one character */
267
    if (value[1] == 0) { /* value must be exactly one character */
240
      c->CTYINFO.decimal[0] = *value;
268
      c->CTYINFO.decimal[0] = *value;
241
      return(0);
269
      return(0);
242
    }
270
    }
243
  } else if (stringstartswith(arg, "thous:") == 0) {
271
  } else if (stringstartswith(arg, "thous:") == 0) {
244
    if (value[1] == 0) { /* value must be exactly one character */
272
    if (value[1] == 0) { /* value must be exactly one character */
245
      c->CTYINFO.thousands[0] = *value;
273
      c->CTYINFO.thousands[0] = *value;
246
      return(0);
274
      return(0);
247
    }
275
    }
248
  } else if (stringstartswith(arg, "datesep:") == 0) {
276
  } else if (stringstartswith(arg, "datesep:") == 0) {
249
    if (value[1] == 0) { /* value must be exactly one character */
277
    if (value[1] == 0) { /* value must be exactly one character */
250
      c->CTYINFO.datesep[0] = *value;
278
      c->CTYINFO.datesep[0] = *value;
251
      return(0);
279
      return(0);
252
    }
280
    }
253
  } else if (stringstartswith(arg, "timesep:") == 0) {
281
  } else if (stringstartswith(arg, "timesep:") == 0) {
254
    if (value[1] == 0) { /* value must be exactly one character */
282
    if (value[1] == 0) { /* value must be exactly one character */
255
      c->CTYINFO.timesep[0] = *value;
283
      c->CTYINFO.timesep[0] = *value;
256
      return(0);
284
      return(0);
257
    }
285
    }
258
  } else if (stringstartswith(arg, "datefmt:") == 0) {
286
  } else if (stringstartswith(arg, "datefmt:") == 0) {
259
    if (strcmp(value, "MDY") == 0) {
287
    if (strcmp(value, "MDY") == 0) {
260
      c->CTYINFO.datefmt = COUNTRY_DATE_MDY;
288
      c->CTYINFO.datefmt = COUNTRY_DATE_MDY;
261
      return(0);
289
      return(0);
262
    } else if (strcmp(value, "DMY") == 0) {
290
    } else if (strcmp(value, "DMY") == 0) {
263
      c->CTYINFO.datefmt = COUNTRY_DATE_DMY;
291
      c->CTYINFO.datefmt = COUNTRY_DATE_DMY;
264
      return(0);
292
      return(0);
265
    } else if (strcmp(value, "YMD") == 0) {
293
    } else if (strcmp(value, "YMD") == 0) {
266
      c->CTYINFO.datefmt = COUNTRY_DATE_YMD;
294
      c->CTYINFO.datefmt = COUNTRY_DATE_YMD;
267
      return(0);
295
      return(0);
268
    }
296
    }
269
  } else if (stringstartswith(arg, "timefmt:") == 0) {
297
  } else if (stringstartswith(arg, "timefmt:") == 0) {
270
    if (value[1] == 0) {
298
    if (value[1] == 0) {
271
      if ((value[0] >= '0') && (value[0] <= '1')) {
299
      if ((value[0] >= '0') && (value[0] <= '1')) {
272
        c->CTYINFO.timefmt = value[0] - '0';
300
        c->CTYINFO.timefmt = value[0] - '0';
273
        return(0);
301
        return(0);
274
      }
302
      }
275
    }
303
    }
276
  } else if (stringstartswith(arg, "curr:") == 0) {
304
  } else if (stringstartswith(arg, "curr:") == 0) {
277
    if (strlen(value) <= 4) {
305
    if (strlen(value) <= 4) {
278
      strcpy(c->CTYINFO.currsym, value);
306
      strcpy(c->CTYINFO.currsym, value);
279
      return(0);
307
      return(0);
280
    }
308
    }
281
  } else if (stringstartswith(arg, "currpos:") == 0) {
309
  } else if (stringstartswith(arg, "currpos:") == 0) {
282
    if (value[1] == 0) {
310
    if (value[1] == 0) {
283
      if (value[0] == '0') {
311
      if (value[0] == '0') {
284
        c->CTYINFO.currpos = 0;
312
        c->CTYINFO.currpos = 0;
285
        return(0);
313
        return(0);
286
      } else if (value[0] == '1') {
314
      } else if (value[0] == '1') {
287
        c->CTYINFO.currpos = 1;
315
        c->CTYINFO.currpos = 1;
288
        return(0);
316
        return(0);
289
      } else if (value[0] == '2') {
317
      } else if (value[0] == '2') {
290
        c->CTYINFO.currpos = 0;
318
        c->CTYINFO.currpos = 0;
291
        c->CTYINFO.currdecsym = 1;
319
        c->CTYINFO.currdecsym = 1;
292
        return(0);
320
        return(0);
293
      }
321
      }
294
    }
322
    }
295
  } else if (stringstartswith(arg, "currspc:") == 0) {
323
  } else if (stringstartswith(arg, "currspc:") == 0) {
296
    if (value[1] == 0) {
324
    if (value[1] == 0) {
297
      if ((value[0] >= '0') && (value[0] <= '1')) {
325
      if ((value[0] >= '0') && (value[0] <= '1')) {
298
        c->CTYINFO.currspace = value[0] - '0';
326
        c->CTYINFO.currspace = value[0] - '0';
299
        return(0);
327
        return(0);
300
      }
328
      }
301
    }
329
    }
302
  } else if (stringstartswith(arg, "currprec:") == 0) {
330
  } else if (stringstartswith(arg, "currprec:") == 0) {
303
    if (value[1] == 0) {
331
    if (value[1] == 0) {
304
      if ((value[0] >= '0') && (value[0] <= '9')) {
332
      if ((value[0] >= '0') && (value[0] <= '9')) {
305
        c->CTYINFO.currprec = value[0] - '0';
333
        c->CTYINFO.currprec = value[0] - '0';
306
        return(0);
334
        return(0);
307
      }
335
      }
308
    }
336
    }
309
  } else if (stringstartswith(arg, "yesno:") == 0) {
337
  } else if (stringstartswith(arg, "yesno:") == 0) {
310
    /* string must be exactly 2 characters long */
338
    /* string must be exactly 2 characters long */
311
    if ((value[0] != 0) && (value[1] != 0) && (value[2] == 0)) {
339
    if ((value[0] != 0) && (value[1] != 0) && (value[2] == 0)) {
312
      c->YESNO.yes[0] = value[0];
340
      c->YESNO.yes[0] = value[0];
313
      c->YESNO.no[0] = value[1];
341
      c->YESNO.no[0] = value[1];
314
      return(0);
342
      return(0);
315
    }
343
    }
316
  }
344
  }
317
  /* if I'm here, something went wrong */
345
  /* if I'm here, something went wrong */
318
  return(-4);
346
  return(-4);
319
}
347
}
320
 
348
 
321
 
349
 
322
/* converts a path to its canonic representation, returns 0 on success
350
/* converts a path to its canonic representation, returns 0 on success
323
 * or DOS err on failure (invalid drive) */
351
 * or DOS err on failure (invalid drive) */
324
static unsigned short file_truename(const char *dst, char *src) {
352
static unsigned short file_truename(const char *dst, char *src) {
325
  unsigned short res = 0;
353
  unsigned short res = 0;
326
  _asm {
354
  _asm {
327
    push es
355
    push es
328
    mov ah, 0x60  /* query truename, DS:SI=src, ES:DI=dst */
356
    mov ah, 0x60  /* query truename, DS:SI=src, ES:DI=dst */
329
    push ds
357
    push ds
330
    pop es
358
    pop es
331
    mov si, src
359
    mov si, src
332
    mov di, dst
360
    mov di, dst
333
    int 0x21
361
    int 0x21
334
    jnc DONE
362
    jnc DONE
335
    mov [res], ax
363
    mov [res], ax
336
    DONE:
364
    DONE:
337
    pop es
365
    pop es
338
  }
366
  }
339
  return(res);
367
  return(res);
340
}
368
}
341
 
369
 
342
 
370
 
343
static void default_country_path(char *s) {
371
static void default_country_path(char *s) {
344
  char *dosdir = getenv("DOSDIR");
372
  char *dosdir = getenv("DOSDIR");
345
  size_t dosdirlen;
373
  size_t dosdirlen;
346
  s[0] = 0;
374
  s[0] = 0;
347
  if (dosdir == NULL) return;
375
  if (dosdir == NULL) return;
348
  dosdirlen = strlen(dosdir);
376
  dosdirlen = strlen(dosdir);
349
  if (dosdirlen == 0) return;
377
  if (dosdirlen == 0) return;
350
  /* drop trailing backslash if present */
378
  /* drop trailing backslash if present */
351
  if (dosdir[dosdirlen - 1] == '\\') dosdirlen--;
379
  if (dosdir[dosdirlen - 1] == '\\') dosdirlen--;
352
  /* copy dosdir to s and append the rest of the path */
380
  /* copy dosdir to s and append the rest of the path */
353
  memcpy(s, dosdir, dosdirlen);
381
  memcpy(s, dosdir, dosdirlen);
354
  strcpy(s + dosdirlen, "\\CFG\\COUNTRY.SYS");
382
  strcpy(s + dosdirlen, "\\CFG\\COUNTRY.SYS");
355
}
383
}
356
 
384
 
357
 
385
 
358
int main(int argc, char **argv) {
386
int main(int argc, char **argv) {
359
  struct country cntdata;
387
  struct country cntdata;
360
  int changedflag;
388
  int changedflag;
361
  int x;
389
  int x;
362
  static char fname[130];
390
  char fname[130];
-
 
391
  char buff[128];
363
 
392
 
364
  svarlang_autoload("localcfg");
393
  svarlang_autoload("localcfg");
365
 
394
 
366
  /* scan argv looking for the path to country.sys */
395
  /* scan argv looking for the path to country.sys */
367
  for (x = 1; x < argc; x++) {
396
  for (x = 1; x < argc; x++) {
368
    if (argv[x][0] != '/') {
397
    if (argv[x][0] != '/') {
369
      if (fname[0] != 0) {
398
      if (fname[0] != 0) {
370
        nls_puts(NLS_ERR_FILEPATHTWICE);
399
        nls_puts(NLS_ERR_FILEPATHTWICE);
371
        return(1);
400
        return(1);
372
      }
401
      }
373
      /* */
402
      /* */
374
      if (file_truename(fname, argv[x]) != 0) {
403
      if (file_truename(fname, argv[x]) != 0) {
375
        nls_puts(NLS_ERR_BADPATH);
404
        nls_puts(NLS_ERR_BADPATH);
376
        return(1);
405
        return(1);
377
      }
406
      }
378
    } else if (strcmp(argv[x], "/?") == 0) { /* is it /? */
407
    } else if (strcmp(argv[x], "/?") == 0) { /* is it /? */
379
      about();
408
      about();
380
      return(1);
409
      return(1);
381
    }
410
    }
382
  }
411
  }
383
 
412
 
384
  /* if no file path provided, look into %DOSDIR%\CFG\COUNTRY.SYS */
413
  /* if no file path provided, look into %DOSDIR%\CFG\COUNTRY.SYS */
385
  if (fname[0] == 0) default_country_path(fname);
414
  if (fname[0] == 0) default_country_path(fname);
386
 
415
 
387
  x = country_read(&cntdata, fname);
416
  x = country_read(&cntdata, fname);
388
  if (x != 0) {
417
  if (x != 0) {
389
    nls_puts(NLS_ERR_READFAIL);
418
    nls_puts(NLS_ERR_READFAIL);
390
    return(2);
419
    return(2);
391
  }
420
  }
392
 
421
 
393
  changedflag = 0;
422
  changedflag = 0;
394
 
423
 
395
  /* process command line arguments */
424
  /* process command line arguments */
396
  for (x = 1; x < argc; x++) {
425
  for (x = 1; x < argc; x++) {
397
    if (argv[x][0] != '/') continue; /* skip country.sys filename (processed earlier) */
426
    if (argv[x][0] != '/') continue; /* skip country.sys filename (processed earlier) */
398
    changedflag++;
427
    changedflag++;
399
    if (processarg(argv[x], &cntdata) != 0) {
428
    if (processarg(argv[x], &cntdata) != 0) {
400
      nls_puts(NLS_ERR_INVPARAM);
429
      nls_puts(NLS_ERR_INVPARAM);
401
      return(3);
430
      return(3);
402
    }
431
    }
403
  }
432
  }
404
 
433
 
405
  nls_put(NLS_INFO_COUNTRY);
434
  nls_put(NLS_INFO_COUNTRY);
406
  printf(" %03d\r\n", cntdata.CTYINFO.id);
435
  sprintf(buff, " %03d", cntdata.CTYINFO.id);
-
 
436
  outputnl(buff);
407
  nls_put(NLS_INFO_CODEPAGE);
437
  nls_put(NLS_INFO_CODEPAGE);
408
  printf(" %d\r\n", cntdata.CTYINFO.codepage);
438
  sprintf(buff, " %d", cntdata.CTYINFO.codepage);
-
 
439
  outputnl(buff);
409
  nls_put(NLS_INFO_DECSEP);
440
  nls_put(NLS_INFO_DECSEP);
410
  printf(" %c\r\n", cntdata.CTYINFO.decimal[0]);
441
  sprintf(buff, " %c", cntdata.CTYINFO.decimal[0]);
-
 
442
  outputnl(buff);
411
  nls_put(NLS_INFO_THOUSEP);
443
  nls_put(NLS_INFO_THOUSEP);
412
  printf(" %c\r\n", cntdata.CTYINFO.thousands[0]);
444
  sprintf(buff, " %c", cntdata.CTYINFO.thousands[0]);
-
 
445
  outputnl(buff);
413
  nls_put(NLS_INFO_DATEFMT);
446
  nls_put(NLS_INFO_DATEFMT);
414
  printf(" %s\r\n", datestring(&cntdata));
447
  sprintf(buff, " %s", datestring(&cntdata));
-
 
448
  outputnl(buff);
415
  nls_put(NLS_INFO_TIMEFMT);
449
  nls_put(NLS_INFO_TIMEFMT);
416
  printf(" %s\r\n", timestring(&cntdata));
450
  sprintf(buff, " %s", timestring(&cntdata));
-
 
451
  outputnl(buff);
417
  nls_put(NLS_INFO_YESNO);
452
  nls_put(NLS_INFO_YESNO);
418
  printf(" %c/%c\r\n", cntdata.YESNO.yes[0], cntdata.YESNO.no[0]);
453
  sprintf(buff, " %c/%c", cntdata.YESNO.yes[0], cntdata.YESNO.no[0]);
-
 
454
  outputnl(buff);
419
  nls_put(NLS_INFO_CURREXAMPLE);
455
  nls_put(NLS_INFO_CURREXAMPLE);
420
  printf(" %s\r\n", currencystring(&cntdata));
456
  sprintf(" %s", currencystring(&cntdata));
-
 
457
  outputnl(buff);
421
 
458
 
422
  crlf();
459
  crlf();
423
  nls_puts(NLS_MAKESURE);
460
  nls_puts(NLS_MAKESURE);
424
  printf("COUNTRY=%03d,%03d,%s", cntdata.CTYINFO.id, cntdata.CTYINFO.codepage, fname);
461
  sprintf(buff, "COUNTRY=%03d,%03d,%s", cntdata.CTYINFO.id, cntdata.CTYINFO.codepage, fname);
425
  crlf();
462
  outputnl(buff);
426
 
463
 
427
  /* if anything changed, write the new file */
464
  /* if anything changed, write the new file */
428
  if (changedflag != 0) country_write(fname, &cntdata);
465
  if (changedflag != 0) country_write(fname, &cntdata);
429
 
466
 
430
  return(0);
467
  return(0);
431
}
468
}
432
 
469