Subversion Repositories SvarDOS

Rev

Rev 989 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
427 mateuszvis 1
/* This file is part of the SvarCOM project and is published under the terms
2
 * of the MIT license.
3
 *
1823 mateusz.vi 4
 * Copyright (C) 2021-2024 Mateusz Viste
427 mateuszvis 5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
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
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
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,
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
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
22
 * DEALINGS IN THE SOFTWARE.
23
 */
24
 
25
/*
26
 * time [time]
27
 */
28
 
29
 
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) {
32
  unsigned short i;
33
 
34
  for (i = 0; i < 3; i++) {
35
    if ((s[i] < '0') || (s[i] > '9')) {
36
      buff[i] = 0;
37
      return(0);
38
    }
39
    buff[i] = s[i];
40
  }
41
 
42
  /* err */
43
  *buff = 0;
44
  return(-1);
45
}
46
 
47
 
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, ...
50
 */
1823 mateusz.vi 51
static int cmd_time_parse(const char *s, unsigned char *ho, unsigned char *mi, unsigned char *se, struct nls_patterns *nls) {
427 mateuszvis 52
  unsigned short i;
53
  const char *ptrs[2] = {NULL, NULL}; /* minutes, seconds */
54
  char buff[3];
55
  char ampm = 0;
56
 
57
  *ho = -1;
58
  *mi = 0;
59
  *se = 0;
60
 
61
  /* validate input - must contain only chars 0-9, time separator and 'a' or 'p' */
62
  for (i = 0; s[i] != 0; i++) {
63
    switch (s[i]) {
64
      case '0':
65
      case '1':
66
      case '2':
67
      case '3':
68
      case '4':
69
      case '5':
70
      case '6':
71
      case '7':
72
      case '8':
73
      case '9':
74
        break;
75
      case 'a':
76
      case 'A':
77
      case 'p':
78
      case 'P':
79
        /* these can be only at last position and never at the first */
80
        if ((s[i + 1] != 0) || (i == 0)) return(-1);
81
        ampm = s[i];
82
        if (ampm >= 'a') ampm -= ('a' - 'A');
83
        break;
84
      default:
85
        if ((s[i] != nls->timesep[0]) || (i == 0)) return(-1);
86
        if (ptrs[0] == NULL) {
87
          ptrs[0] = s + i + 1;
88
        } else if (ptrs[1] == NULL) {
89
          ptrs[1] = s + i + 1;
90
        } else { /* too many separators */
91
          return(-1);
92
        }
93
        break;
94
    }
95
  }
96
 
97
  /* read hour */
98
  if (cmd_time_get_item(buff, s) != 0) goto FAIL;
99
  if (atous(&i, buff) != 0) goto FAIL;
100
  *ho = i;
101
 
102
  /* if minutes provided, read them */
103
  if (ptrs[0] != NULL) {
104
    if (cmd_time_get_item(buff, ptrs[0]) != 0) goto FAIL;
105
    if (atous(&i, buff) != 0) goto FAIL;
106
    *mi = i;
107
  }
108
 
429 mateuszvis 109
  /* if seconds provided, read them */
427 mateuszvis 110
  if (ptrs[1] != NULL) {
111
    if (cmd_time_get_item(buff, ptrs[1]) != 0) goto FAIL;
112
    if (atous(&i, buff) != 0) goto FAIL;
113
    *se = i;
114
  }
115
 
116
  /* validate ranges */
117
  if ((*ho > 23) || (*mi > 59) || (*se > 59)) goto FAIL;
118
 
119
  /* am? */
120
  if ((ampm == 'A') && (*ho > 12)) goto FAIL;
121
  if ((ampm == 'A') && (*ho == 12)) *ho = 0; /* 12:00am is 00:00 (midnight) */
122
 
123
  /* pm? */
124
  if (ampm == 'P') {
125
    if (*ho > 12) goto FAIL;
126
    if (*ho < 12) *ho += 12;
127
  }
128
 
129
  return(0);
130
 
131
  FAIL:
1823 mateusz.vi 132
  *ho = 255;
427 mateuszvis 133
  return(-1);
134
}
135
 
136
 
533 mateuszvis 137
static enum cmd_result cmd_time(struct cmd_funcparam *p) {
427 mateuszvis 138
  struct nls_patterns *nls = (void *)(p->BUFFER);
501 mateuszvis 139
  char *buff = p->BUFFER + sizeof(*nls);
427 mateuszvis 140
  unsigned short i;
1823 mateusz.vi 141
  unsigned char ho = 255, mi, se;
427 mateuszvis 142
 
143
  if (cmd_ishlp(p)) {
989 mateusz.vi 144
    nls_outputnl(22,0); /* "Displays or sets the system time." */
427 mateuszvis 145
    outputnl("");
989 mateusz.vi 146
    nls_outputnl(22,1); /* "TIME [time]" */
427 mateuszvis 147
    outputnl("");
989 mateusz.vi 148
    nls_outputnl(22,2); /* "Type TIME with no parameters to display the current time and (...)" */
533 mateuszvis 149
    return(CMD_OK);
427 mateuszvis 150
  }
151
 
152
  i = nls_getpatterns(nls);
153
  if (i != 0) {
538 mateuszvis 154
    nls_outputnl_doserr(i);
533 mateuszvis 155
    return(CMD_FAIL);
427 mateuszvis 156
  }
157
 
158
  /* display current time if no args */
159
  if (p->argc == 0) {
160
    /* get cur time */
1823 mateusz.vi 161
    dos_get_time(&ho, &mi, &se);
427 mateuszvis 162
 
163
    buff[0] = ' ';
164
    nls_format_time(buff + 1, ho, mi, se, nls);
989 mateusz.vi 165
    nls_output(22,3); /* "Current time is" */
427 mateuszvis 166
    outputnl(buff);
1823 mateusz.vi 167
    ho = 255;
427 mateuszvis 168
  } else { /* parse time if provided */
169
    if (cmd_time_parse(p->argv[0], &ho, &mi, &se, nls) != 0) {
989 mateusz.vi 170
      nls_outputnl(22,4); /* "Invalid time" */
1823 mateusz.vi 171
      ho = 255;
427 mateuszvis 172
    }
173
  }
174
 
175
  /* ask for time if not provided or if input was malformed */
1823 mateusz.vi 176
  while (ho == 255) {
989 mateusz.vi 177
    nls_output(22,5); /* "Enter new time:" */
427 mateuszvis 178
    output(" ");
179
    /* collect user input into buff */
180
    _asm {
181
      push ax
182
      push bx
183
      push dx
184
 
185
      mov ah, 0x0a   /* DOS 1+ -- Buffered String Input */
186
      mov bx, buff
187
      mov dx, bx
188
      mov al, 16
189
      mov [bx], al   /* max input length */
190
      mov al, 1
191
      mov [bx+1], al /* zero out the "previous entry" length */
192
      int 0x21
193
      /* terminate the string with a NULL terminator */
194
      xor ax, ax
195
      inc bx
196
      mov al, [bx] /* read length of input string */
197
      mov bx, ax
198
      add bx, dx
199
      mov [bx+2], ah
200
      /* output a \n */
201
      mov ah, 2
202
      mov dl, 0x0A
203
      int 0x21
204
 
205
      pop dx
206
      pop bx
207
      pop ax
208
    }
428 mateuszvis 209
    if (buff[1] == 0) break; /* empty string = do not change time */
427 mateuszvis 210
    if (cmd_time_parse(buff + 2, &ho, &mi, &se, nls) == 0) break;
989 mateusz.vi 211
    nls_outputnl(22,4); /* "Invalid time" */
533 mateuszvis 212
    return(CMD_FAIL);
427 mateuszvis 213
  }
214
 
1823 mateusz.vi 215
  if (ho != 255) {
427 mateuszvis 216
    /* set time */
217
    _asm {
218
      push ax
219
      push bx
220
      push cx
221
      push dx
222
 
223
      mov ah, 0x2d   /* DOS 1+ -- Set DOS Time */
224
      mov ch, [ho]   /* hour (0-23) */
225
      mov cl, [mi]   /* minutes (0-59) */
226
      mov dh, [se]   /* seconds (0-59) */
227
      mov dl, 0      /* 1/100th seconds (0-99) */
228
      int 0x21
229
 
230
      pop dx
231
      pop cx
232
      pop bx
233
      pop ax
234
    }
235
  }
236
 
533 mateuszvis 237
  return(CMD_OK);
427 mateuszvis 238
}