Subversion Repositories SvarDOS

Rev

Rev 538 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 538 Rev 989
1
/* This file is part of the SvarCOM project and is published under the terms
1
/* This file is part of the SvarCOM project and is published under the terms
2
 * of the MIT license.
2
 * of the MIT license.
3
 *
3
 *
4
 * Copyright (C) 2021 Mateusz Viste
4
 * Copyright (C) 2021-2022 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
/*
25
/*
26
 * time [time]
26
 * time [time]
27
 */
27
 */
28
 
28
 
29
 
29
 
30
/* read a one or two digit number and write it to buff */
30
/* read a one or two digit number and write it to buff */
31
static int cmd_time_get_item(char *buff, const char *s) {
31
static int cmd_time_get_item(char *buff, const char *s) {
32
  unsigned short i;
32
  unsigned short i;
33
 
33
 
34
  for (i = 0; i < 3; i++) {
34
  for (i = 0; i < 3; i++) {
35
    if ((s[i] < '0') || (s[i] > '9')) {
35
    if ((s[i] < '0') || (s[i] > '9')) {
36
      buff[i] = 0;
36
      buff[i] = 0;
37
      return(0);
37
      return(0);
38
    }
38
    }
39
    buff[i] = s[i];
39
    buff[i] = s[i];
40
  }
40
  }
41
 
41
 
42
  /* err */
42
  /* err */
43
  *buff = 0;
43
  *buff = 0;
44
  return(-1);
44
  return(-1);
45
}
45
}
46
 
46
 
47
 
47
 
48
/* parse a NULL-terminated string int hour, minutes and seconds, returns 0 on success
48
/* parse a NULL-terminated string int hour, minutes and seconds, returns 0 on success
49
 * valid inputs: 0, 7, 5:5, 23:23, 17:54:45, 9p, 9:05, ...
49
 * valid inputs: 0, 7, 5:5, 23:23, 17:54:45, 9p, 9:05, ...
50
 */
50
 */
51
static int cmd_time_parse(const char *s, signed char *ho, signed char *mi, signed char *se, struct nls_patterns *nls) {
51
static int cmd_time_parse(const char *s, signed char *ho, signed char *mi, signed char *se, struct nls_patterns *nls) {
52
  unsigned short i;
52
  unsigned short i;
53
  const char *ptrs[2] = {NULL, NULL}; /* minutes, seconds */
53
  const char *ptrs[2] = {NULL, NULL}; /* minutes, seconds */
54
  char buff[3];
54
  char buff[3];
55
  char ampm = 0;
55
  char ampm = 0;
56
 
56
 
57
  *ho = -1;
57
  *ho = -1;
58
  *mi = 0;
58
  *mi = 0;
59
  *se = 0;
59
  *se = 0;
60
 
60
 
61
  /* validate input - must contain only chars 0-9, time separator and 'a' or 'p' */
61
  /* validate input - must contain only chars 0-9, time separator and 'a' or 'p' */
62
  for (i = 0; s[i] != 0; i++) {
62
  for (i = 0; s[i] != 0; i++) {
63
    switch (s[i]) {
63
    switch (s[i]) {
64
      case '0':
64
      case '0':
65
      case '1':
65
      case '1':
66
      case '2':
66
      case '2':
67
      case '3':
67
      case '3':
68
      case '4':
68
      case '4':
69
      case '5':
69
      case '5':
70
      case '6':
70
      case '6':
71
      case '7':
71
      case '7':
72
      case '8':
72
      case '8':
73
      case '9':
73
      case '9':
74
        break;
74
        break;
75
      case 'a':
75
      case 'a':
76
      case 'A':
76
      case 'A':
77
      case 'p':
77
      case 'p':
78
      case 'P':
78
      case 'P':
79
        /* these can be only at last position and never at the first */
79
        /* these can be only at last position and never at the first */
80
        if ((s[i + 1] != 0) || (i == 0)) return(-1);
80
        if ((s[i + 1] != 0) || (i == 0)) return(-1);
81
        ampm = s[i];
81
        ampm = s[i];
82
        if (ampm >= 'a') ampm -= ('a' - 'A');
82
        if (ampm >= 'a') ampm -= ('a' - 'A');
83
        break;
83
        break;
84
      default:
84
      default:
85
        if ((s[i] != nls->timesep[0]) || (i == 0)) return(-1);
85
        if ((s[i] != nls->timesep[0]) || (i == 0)) return(-1);
86
        if (ptrs[0] == NULL) {
86
        if (ptrs[0] == NULL) {
87
          ptrs[0] = s + i + 1;
87
          ptrs[0] = s + i + 1;
88
        } else if (ptrs[1] == NULL) {
88
        } else if (ptrs[1] == NULL) {
89
          ptrs[1] = s + i + 1;
89
          ptrs[1] = s + i + 1;
90
        } else { /* too many separators */
90
        } else { /* too many separators */
91
          return(-1);
91
          return(-1);
92
        }
92
        }
93
        break;
93
        break;
94
    }
94
    }
95
  }
95
  }
96
 
96
 
97
  /* read hour */
97
  /* read hour */
98
  if (cmd_time_get_item(buff, s) != 0) goto FAIL;
98
  if (cmd_time_get_item(buff, s) != 0) goto FAIL;
99
  if (atous(&i, buff) != 0) goto FAIL;
99
  if (atous(&i, buff) != 0) goto FAIL;
100
  *ho = i;
100
  *ho = i;
101
 
101
 
102
  /* if minutes provided, read them */
102
  /* if minutes provided, read them */
103
  if (ptrs[0] != NULL) {
103
  if (ptrs[0] != NULL) {
104
    if (cmd_time_get_item(buff, ptrs[0]) != 0) goto FAIL;
104
    if (cmd_time_get_item(buff, ptrs[0]) != 0) goto FAIL;
105
    if (atous(&i, buff) != 0) goto FAIL;
105
    if (atous(&i, buff) != 0) goto FAIL;
106
    *mi = i;
106
    *mi = i;
107
  }
107
  }
108
 
108
 
109
  /* if seconds provided, read them */
109
  /* if seconds provided, read them */
110
  if (ptrs[1] != NULL) {
110
  if (ptrs[1] != NULL) {
111
    if (cmd_time_get_item(buff, ptrs[1]) != 0) goto FAIL;
111
    if (cmd_time_get_item(buff, ptrs[1]) != 0) goto FAIL;
112
    if (atous(&i, buff) != 0) goto FAIL;
112
    if (atous(&i, buff) != 0) goto FAIL;
113
    *se = i;
113
    *se = i;
114
  }
114
  }
115
 
115
 
116
  /* validate ranges */
116
  /* validate ranges */
117
  if ((*ho > 23) || (*mi > 59) || (*se > 59)) goto FAIL;
117
  if ((*ho > 23) || (*mi > 59) || (*se > 59)) goto FAIL;
118
 
118
 
119
  /* am? */
119
  /* am? */
120
  if ((ampm == 'A') && (*ho > 12)) goto FAIL;
120
  if ((ampm == 'A') && (*ho > 12)) goto FAIL;
121
  if ((ampm == 'A') && (*ho == 12)) *ho = 0; /* 12:00am is 00:00 (midnight) */
121
  if ((ampm == 'A') && (*ho == 12)) *ho = 0; /* 12:00am is 00:00 (midnight) */
122
 
122
 
123
  /* pm? */
123
  /* pm? */
124
  if (ampm == 'P') {
124
  if (ampm == 'P') {
125
    if (*ho > 12) goto FAIL;
125
    if (*ho > 12) goto FAIL;
126
    if (*ho < 12) *ho += 12;
126
    if (*ho < 12) *ho += 12;
127
  }
127
  }
128
 
128
 
129
  return(0);
129
  return(0);
130
 
130
 
131
  FAIL:
131
  FAIL:
132
  *ho = -1;
132
  *ho = -1;
133
  return(-1);
133
  return(-1);
134
}
134
}
135
 
135
 
136
 
136
 
137
static enum cmd_result cmd_time(struct cmd_funcparam *p) {
137
static enum cmd_result cmd_time(struct cmd_funcparam *p) {
138
  struct nls_patterns *nls = (void *)(p->BUFFER);
138
  struct nls_patterns *nls = (void *)(p->BUFFER);
139
  char *buff = p->BUFFER + sizeof(*nls);
139
  char *buff = p->BUFFER + sizeof(*nls);
140
  unsigned short i;
140
  unsigned short i;
141
  signed char ho = -1, mi = -1, se = -1;
141
  signed char ho = -1, mi = -1, se = -1;
142
 
142
 
143
  if (cmd_ishlp(p)) {
143
  if (cmd_ishlp(p)) {
144
    outputnl("Displays or sets the system time.");
144
    nls_outputnl(22,0); /* "Displays or sets the system time." */
145
    outputnl("");
145
    outputnl("");
146
    outputnl("TIME [time]");
146
    nls_outputnl(22,1); /* "TIME [time]" */
147
    outputnl("");
147
    outputnl("");
148
    outputnl("Type TIME with no parameters to display the current time and a prompt for a");
148
    nls_outputnl(22,2); /* "Type TIME with no parameters to display the current time and (...)" */
149
    outputnl("new one. Press ENTER to keep the same time.");
-
 
150
    return(CMD_OK);
149
    return(CMD_OK);
151
  }
150
  }
152
 
151
 
153
  i = nls_getpatterns(nls);
152
  i = nls_getpatterns(nls);
154
  if (i != 0) {
153
  if (i != 0) {
155
    nls_outputnl_doserr(i);
154
    nls_outputnl_doserr(i);
156
    return(CMD_FAIL);
155
    return(CMD_FAIL);
157
  }
156
  }
158
 
157
 
159
  /* display current time if no args */
158
  /* display current time if no args */
160
  if (p->argc == 0) {
159
  if (p->argc == 0) {
161
    /* get cur time */
160
    /* get cur time */
162
    _asm {
161
    _asm {
163
      push ax
162
      push ax
164
      push bx
163
      push bx
165
      push cx
164
      push cx
166
      push dx
165
      push dx
167
 
166
 
168
      mov ah, 0x2c  /* DOS 1+ -- Query DOS Time */
167
      mov ah, 0x2c  /* DOS 1+ -- Query DOS Time */
169
      int 0x21      /* CH=hour CL=minutes DH=seconds DL=1/100sec */
168
      int 0x21      /* CH=hour CL=minutes DH=seconds DL=1/100sec */
170
      mov [ho], ch
169
      mov [ho], ch
171
      mov [mi], cl
170
      mov [mi], cl
172
      mov [se], dh
171
      mov [se], dh
173
 
172
 
174
      pop dx
173
      pop dx
175
      pop cx
174
      pop cx
176
      pop bx
175
      pop bx
177
      pop ax
176
      pop ax
178
    }
177
    }
179
    buff[0] = ' ';
178
    buff[0] = ' ';
180
    nls_format_time(buff + 1, ho, mi, se, nls);
179
    nls_format_time(buff + 1, ho, mi, se, nls);
181
    output("Current time is");
180
    nls_output(22,3); /* "Current time is" */
182
    outputnl(buff);
181
    outputnl(buff);
183
    ho = -1;
182
    ho = -1;
184
  } else { /* parse time if provided */
183
  } else { /* parse time if provided */
185
    if (cmd_time_parse(p->argv[0], &ho, &mi, &se, nls) != 0) {
184
    if (cmd_time_parse(p->argv[0], &ho, &mi, &se, nls) != 0) {
186
      outputnl("Invalid time");
185
      nls_outputnl(22,4); /* "Invalid time" */
187
      ho = -1;
186
      ho = -1;
188
    }
187
    }
189
  }
188
  }
190
 
189
 
191
  /* ask for time if not provided or if input was malformed */
190
  /* ask for time if not provided or if input was malformed */
192
  while (ho < 0) {
191
  while (ho < 0) {
193
    output("Enter new time:");
192
    nls_output(22,5); /* "Enter new time:" */
194
    output(" ");
193
    output(" ");
195
    /* collect user input into buff */
194
    /* collect user input into buff */
196
    _asm {
195
    _asm {
197
      push ax
196
      push ax
198
      push bx
197
      push bx
199
      push dx
198
      push dx
200
 
199
 
201
      mov ah, 0x0a   /* DOS 1+ -- Buffered String Input */
200
      mov ah, 0x0a   /* DOS 1+ -- Buffered String Input */
202
      mov bx, buff
201
      mov bx, buff
203
      mov dx, bx
202
      mov dx, bx
204
      mov al, 16
203
      mov al, 16
205
      mov [bx], al   /* max input length */
204
      mov [bx], al   /* max input length */
206
      mov al, 1
205
      mov al, 1
207
      mov [bx+1], al /* zero out the "previous entry" length */
206
      mov [bx+1], al /* zero out the "previous entry" length */
208
      int 0x21
207
      int 0x21
209
      /* terminate the string with a NULL terminator */
208
      /* terminate the string with a NULL terminator */
210
      xor ax, ax
209
      xor ax, ax
211
      inc bx
210
      inc bx
212
      mov al, [bx] /* read length of input string */
211
      mov al, [bx] /* read length of input string */
213
      mov bx, ax
212
      mov bx, ax
214
      add bx, dx
213
      add bx, dx
215
      mov [bx+2], ah
214
      mov [bx+2], ah
216
      /* output a \n */
215
      /* output a \n */
217
      mov ah, 2
216
      mov ah, 2
218
      mov dl, 0x0A
217
      mov dl, 0x0A
219
      int 0x21
218
      int 0x21
220
 
219
 
221
      pop dx
220
      pop dx
222
      pop bx
221
      pop bx
223
      pop ax
222
      pop ax
224
    }
223
    }
225
    if (buff[1] == 0) break; /* empty string = do not change time */
224
    if (buff[1] == 0) break; /* empty string = do not change time */
226
    if (cmd_time_parse(buff + 2, &ho, &mi, &se, nls) == 0) break;
225
    if (cmd_time_parse(buff + 2, &ho, &mi, &se, nls) == 0) break;
227
    outputnl("Invalid time");
226
    nls_outputnl(22,4); /* "Invalid time" */
228
    return(CMD_FAIL);
227
    return(CMD_FAIL);
229
  }
228
  }
230
 
229
 
231
  if (ho >= 0) {
230
  if (ho >= 0) {
232
    /* set time */
231
    /* set time */
233
    _asm {
232
    _asm {
234
      push ax
233
      push ax
235
      push bx
234
      push bx
236
      push cx
235
      push cx
237
      push dx
236
      push dx
238
 
237
 
239
      mov ah, 0x2d   /* DOS 1+ -- Set DOS Time */
238
      mov ah, 0x2d   /* DOS 1+ -- Set DOS Time */
240
      mov ch, [ho]   /* hour (0-23) */
239
      mov ch, [ho]   /* hour (0-23) */
241
      mov cl, [mi]   /* minutes (0-59) */
240
      mov cl, [mi]   /* minutes (0-59) */
242
      mov dh, [se]   /* seconds (0-59) */
241
      mov dh, [se]   /* seconds (0-59) */
243
      mov dl, 0      /* 1/100th seconds (0-99) */
242
      mov dl, 0      /* 1/100th seconds (0-99) */
244
      int 0x21
243
      int 0x21
245
 
244
 
246
      pop dx
245
      pop dx
247
      pop cx
246
      pop cx
248
      pop bx
247
      pop bx
249
      pop ax
248
      pop ax
250
    }
249
    }
251
  }
250
  }
252
 
251
 
253
  return(CMD_OK);
252
  return(CMD_OK);
254
}
253
}
255
 
254