1 /*
2 Copyright (c) 1991, 1992, 1995 Simon Marshall
3
4 If you still end up late, don't blame me!
5
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose and without fee is hereby granted,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation.
11
12 This software is provided AS IS with no warranties of any kind. The author
13 shall have no liability with respect to the infringement of copyrights,
14 trade secrets or any patents by this file or any part thereof. In no
15 event will the author be liable for any lost revenue or profits or
16 other special, indirect and consequential damages.
17 */
18
19 /*
20 * Parse times.
21 */
22
23
24
25 #include "xalarm.h"
26 #include "dates.h"
27
28 #define VALUE(ch) ((int) (ch) - (int) '0')
29 #define INSTRING(ch, s) (((ch) != '\0') and (index ((s), (ch))))
30
31
32 long TimeToMilliSeconds();
33 Boolean ParseTimeString();
34 extern time_t time();
35 extern struct tm *localtime();
36
37
38
39 extern AlarmData xalarm;
40
41
42
43 /*
44 * Convert the string into milliseconds, or INVALID if
45 * not recognised.
46 * Recognises quite a lot, really, but doesn't like non absolute times
47 * having "am" or "pm" etc.
48 */
49
TimeToMilliSeconds(timestr)50 long TimeToMilliSeconds (timestr)
51 String timestr;
52 {
53 Boolean in24hrformat;
54 int hours, minutes, seconds;
55 time_t abstime;
56 struct tm *now;
57
58 if (not ParseTimeString (timestr, &hours, &minutes, &in24hrformat))
59 return ((long) INVALID);
60
61 if ((*timestr == '+') or (STREQUAL (timestr, NOW)))
62 seconds = (hours * SECSIN1HR) + (minutes * SECSIN1MIN);
63 else {
64 (void) time (&abstime);
65 now = localtime (&abstime);
66 seconds = ((hours - now->tm_hour) * SECSIN1HR) +
67 ((minutes - now->tm_min) * SECSIN1MIN) - now->tm_sec;
68 if ((seconds < 0) and (not in24hrformat))
69 seconds += (12 * SECSIN1HR);
70 }
71
72 if ((xalarm.dateout > 0) or ((xalarm.dateout == 0) and (seconds >= 0)))
73 return ((long) seconds * MSECSIN1SEC);
74 else {
75 ADDERROR (TIMEPASSED, (String) NULL);
76 return ((long) INVALID);
77 }
78 }
79
80
81
82 /*
83 * Parse that string. Robbed and hacked from xcal (3.2) by Peter
84 * Collinson et al.
85 */
86
ParseTimeString(str,hrs,mins,in24hrf)87 Boolean ParseTimeString (str, hrs, mins, in24hrf)
88 String str;
89 int *hrs, *mins;
90 Boolean *in24hrf;
91 {
92 enum {Hhmm, hHmm, hh_mm, hhMm, hhmM, AmPm, aMpM} state;
93 Boolean relative, finished = False;
94 int numdigits = 0;
95 char *s = str, badtime[TEXT];
96
97 RESETERROR ();
98
99 if (relative = (*str == '+'))
100 str++;
101 else if (STREQUAL (str, NOW)) {
102 *hrs = *mins = 0;
103 return (True);
104 } else if (STREQUAL (str, NOON)) {
105 *hrs = 12;
106 *mins = 0;
107 return (*in24hrf = True);
108 }
109
110 while (*s != '\0')
111 if (isdigit (*s++))
112 numdigits++;
113
114 if (relative)
115 switch (numdigits) {
116 case 1: state = hhmM; break;
117 case 2: state = hhMm; break;
118 case 3: state = hHmm; break;
119 case 4: state = Hhmm; break;
120 default:
121 (void) sprintf (badtime, "just %d", numdigits);
122 ADDERROR (WRONGNUMDIGITS, badtime);
123 return (False);
124 }
125 else
126 switch (numdigits) {
127 case 1:
128 case 2:
129 case 4: state = Hhmm; break;
130 case 3: state = hHmm; break;
131 default:
132 (void) sprintf (badtime, "just %d", numdigits);
133 ADDERROR (WRONGNUMDIGITS, badtime);
134 return (False);
135 }
136
137 *hrs = *mins = 0;
138 *in24hrf = False;
139
140 while (not finished)
141 switch (state) {
142 case Hhmm:
143 if (isdigit (*str)) {
144 *hrs = VALUE (*str++);
145 state = hHmm;
146 continue;
147 } else {
148 ADDERROR (UNRECOGNISED, str);
149 return (False);
150 }
151 case hHmm:
152 if (isdigit (*str)) {
153 *hrs = *hrs*10 + VALUE (*str++);
154 state = hh_mm;
155 continue;
156 }
157 case hh_mm:
158 if (INSTRING (*str, ".:-")) {
159 state = hhMm;
160 str++;
161 continue;
162 }
163 case hhMm:
164 if (isdigit (*str)) {
165 *mins = VALUE (*str++);
166 state = hhmM;
167 continue;
168 }
169 case hhmM:
170 if (isdigit (*str)) {
171 *mins = *mins*10 + VALUE (*str++);
172 state = AmPm;
173 continue;
174 }
175 case AmPm:
176 if (*str == '\0') {
177 *in24hrf = (*hrs > 12) or ((*hrs < 10) and (numdigits % 2 == 0));
178 finished = True;
179 continue;
180 } else if (relative) {
181 ADDERROR (UNRECOGNISED, str);
182 return (False);
183 }
184
185 if (INSTRING (*str, "Aa")) {
186 if (*hrs == 12)
187 *hrs = 0;
188 state = aMpM;
189 continue;
190 } else if (INSTRING (*str, "Pp")) {
191 if (*hrs < 12)
192 *hrs = *hrs + 12;
193 state = aMpM;
194 continue;
195 }
196 ADDERROR (EXPECTEDAMPM, str);
197 return (False);
198 case aMpM:
199 str++;
200 if (INSTRING (*str, "Mm")) {
201 *in24hrf = finished = True;
202 str++;
203 } else {
204 ADDERROR (EXPECTEDAMPM, str);
205 return (False);
206 }
207 }
208
209 if ((*hrs < 24) and (*mins < 60) and (*str == '\0'))
210 return (True);
211 else {
212 if (*hrs >= 24) {
213 (void) sprintf (badtime, "%d", *hrs);
214 ADDERROR (BADHOURS, badtime);
215 } else if (*mins >= 60) {
216 (void) sprintf (badtime, "%d", *mins);
217 ADDERROR (BADMINUTES, badtime);
218 } else {
219 ADDERROR (UNRECOGNISED, str);
220 }
221 return (False);
222 }
223 }
224