1 /*	-*- mode: c; mode: fold -*-	*/
2 # include	"config.h"
3 # include	<stdio.h>
4 # include	<stdlib.h>
5 # include	<stdarg.h>
6 # include	<ctype.h>
7 # include	<string.h>
8 # include	<time.h>
9 # include	"pager.h"
10 
11 /*{{{	utility functions */
12 char *
skip(char * str)13 skip (char *str)
14 {
15 	while (*str && (! isspace (*str)))
16 		++str;
17 	if (*str) {
18 		*str++ = '\0';
19 		while (isspace (*str))
20 			++str;
21 	}
22 	return str;
23 }
24 
25 char *
skipch(char * str,char ch)26 skipch (char *str, char ch)
27 {
28 	while (*str && (*str != ch))
29 		++str;
30 	if (*str) {
31 		*str++ = '\0';
32 		while (isspace (*str))
33 			++str;
34 	}
35 	return str;
36 }
37 
38 char *
get_line(FILE * fp,Bool cont)39 get_line (FILE *fp, Bool cont)
40 {
41 	char	*buf;
42 	int	size;
43 	char	*ret;
44 	int	len;
45 	char	*ptr;
46 
47 	size = 256;
48 	if (! (buf = malloc (size + 2)))
49 		return NULL;
50 	len = 0;
51 	while (ret = fgets (buf + len, size - len - 2, fp)) {
52 		if (ptr = strchr (buf + len, '\n')) {
53 			*ptr = '\0';
54 			len += strlen (buf + len);
55 			if (! cont)
56 				break;
57 			if (len && (buf[len - 1] == '\\')) {
58 				--len;
59 				buf[len] = '\0';
60 			} else
61 				break;
62 		} else
63 			len += strlen (buf + len);
64 		if (len + 64 >= size) {
65 			size += size;
66 			if (! (buf = Realloc (buf, size + 2)))
67 				break;
68 		}
69 	}
70 	if ((! ret) && buf) {
71 		free (buf);
72 		buf = NULL;
73 	}
74 	return len || ret ? buf : NULL;
75 }
76 
77 int
verbose_out(char * fmt,...)78 verbose_out (char *fmt, ...)
79 {
80 	va_list	par;
81 
82 	va_start (par, fmt);
83 	vfprintf (stdout, fmt, par);
84 	va_end (par);
85 	return 0;
86 }
87 /*}}}*/
88 /*{{{	string_t handling */
89 string_t *
snewc(char * str)90 snewc (char *str)
91 {
92 	string_t	*s;
93 
94 	if (s = (string_t *) malloc (sizeof (string_t))) {
95 		s -> str = NULL;
96 		if (str) {
97 			s -> len = strlen (str);
98 			s -> size = s -> len + 1;
99 			if (s -> str = (char_t *) malloc (sizeof (char_t) * s -> size))
100 				memcpy (s -> str, str, s -> len);
101 			else {
102 				free (s);
103 				s = NULL;
104 			}
105 		} else {
106 			s -> len = 0;
107 			s -> size = 0;
108 		}
109 	}
110 	return s;
111 }
112 
113 string_t *
snew(char_t * str,int len)114 snew (char_t *str, int len)
115 {
116 	string_t	*s;
117 
118 	if (s = (string_t *) malloc (sizeof (string_t))) {
119 		s -> str = NULL;
120 		s -> len = 0;
121 		s -> size = 0;
122 		if (len > 0)
123 			if (s -> str = (char_t *) malloc (sizeof (char_t) * (len + 1))) {
124 				s -> size = len + 1;
125 				if (str) {
126 					s -> len = len;
127 					memcpy (s -> str, str, len);
128 				} else
129 					s -> len = 0;
130 			} else {
131 				free (s);
132 				s = NULL;
133 			}
134 	}
135 	return s;
136 }
137 
138 Bool
sexpand(string_t * s,int nsize)139 sexpand (string_t *s, int nsize)
140 {
141 	if (s && (nsize + 2 > s -> size)) {
142 		s -> size = nsize + 2;
143 		if (! (s -> str = (char_t *) Realloc (s -> str, sizeof (char_t) * s -> size))) {
144 			s -> size = 0;
145 			s -> len = 0;
146 			return False;
147 		}
148 	}
149 	return True;
150 }
151 
152 Bool
scopy(string_t * dst,string_t * src)153 scopy (string_t *dst, string_t *src)
154 {
155 	if (dst && src && sexpand (dst, src -> len + 1)) {
156 		if (src -> str) {
157 			memcpy (dst -> str, src -> str, src -> len);
158 			dst -> len = src -> len;
159 		} else
160 			dst -> len = 0;
161 		return True;
162 	}
163 	return False;
164 }
165 
166 Bool
scat(string_t * dst,string_t * src)167 scat (string_t *dst, string_t *src)
168 {
169 	if (dst && src && sexpand (dst, dst -> len + src -> len + 1)) {
170 		if (src -> str) {
171 			memcpy (dst -> str + dst -> len, src -> str, src -> len);
172 			dst -> len += src -> len;
173 		}
174 		return True;
175 	}
176 	return False;
177 }
178 
179 static Bool
dostr(string_t * dst,char * src,Bool (* func)(string_t *,string_t *))180 dostr (string_t *dst, char *src, Bool (*func) (string_t *, string_t *))
181 {
182 	Bool		ret;
183 	string_t	*rsrc;
184 
185 	ret = False;
186 	if (dst)
187 		if (src) {
188 			if (rsrc = snewc (src)) {
189 				ret = (*func) (dst, rsrc);
190 				sfree (rsrc);
191 			}
192 		} else
193 			ret = True;
194 	return ret;
195 }
196 
197 Bool
scopyc(string_t * dst,char * src)198 scopyc (string_t *dst, char *src)
199 {
200 	return dostr (dst, src, scopy);
201 }
202 
203 Bool
scatc(string_t * dst,char * src)204 scatc (string_t *dst, char *src)
205 {
206 	return dostr (dst, src, scat);
207 }
208 
209 string_t *
scut(string_t * str,int start,int len)210 scut (string_t *str, int start, int len)
211 {
212 	string_t	*res;
213 
214 	if (len < 0)
215 		len = str ? str -> len - start : 0;
216 	if (res = snew (NULL, len + 1)) {
217 		if (str -> len > start) {
218 			if (str -> len - start < len)
219 				len = str -> len - start;
220 		} else
221 			len = 0;
222 		if (len > 0)
223 			memcpy (res -> str, str -> str + start, len);
224 		res -> len = len;
225 	}
226 	return res;
227 }
228 
229 void
sdel(string_t * str,int start,int len)230 sdel (string_t *str, int start, int len)
231 {
232 	int	size;
233 
234 	if (str -> len > start) {
235 		if (str -> len - start < len)
236 			len = str -> len - start;
237 	} else
238 		len = 0;
239 	if (len > 0) {
240 		size = str -> len - (start + len);
241 		if (size > 0)
242 			memcpy (str -> str + start, str -> str + start + len, str -> len - (start + len));
243 		str -> len -= len;
244 	}
245 }
246 
247 Bool
sput(string_t * str,string_t * ins,int pos,int len)248 sput (string_t *str, string_t *ins, int pos, int len)
249 {
250 	if ((len < 0) || (len > ins -> len))
251 		len = ins -> len;
252 	if (len + pos >= str -> size)
253 		if (! sexpand (str, len + pos + 1))
254 			return False;
255 	memcpy (str -> str + pos, ins -> str, len);
256 	if (str -> len < len + pos)
257 		str -> len = len + pos;
258 	return True;
259 }
260 
261 Bool
sputc(string_t * str,char * ins,int pos,int len)262 sputc (string_t *str, char *ins, int pos, int len)
263 {
264 	Bool		ret;
265 	string_t	*rins;
266 
267 	ret = False;
268 	if (str && ins && (rins = snewc (ins))) {
269 		ret = sput (str, rins, pos, len);
270 		sfree (rins);
271 	}
272 	return ret;
273 }
274 
275 char *
sextract(string_t * s)276 sextract (string_t *s)
277 {
278 	char	*ret;
279 
280 	ret = NULL;
281 	if (s)
282 		if (ret = malloc (s -> len + 1))
283 			if (s -> str) {
284 				memcpy (ret, s -> str, s -> len);
285 				ret[s -> len] = '\0';
286 			} else
287 				ret[0] = '\0';
288 	return ret;
289 }
290 
291 char *
schar(string_t * s)292 schar (string_t *s)
293 {
294 	if (s) {
295 		if (s -> len + 1>= s -> size)
296 			sexpand (s, s -> len + 2);
297 		if (s -> len + 1 < s -> size) {
298 			s -> str[s -> len] = '\0';
299 			return (char *) s -> str;
300 		}
301 	}
302 	return NULL;
303 }
304 
305 void *
sfree(string_t * s)306 sfree (string_t *s)
307 {
308 	if (s) {
309 		if (s -> str)
310 			free (s -> str);
311 		free (s);
312 	}
313 	return NULL;
314 }
315 
316 void
srelease(string_t * s)317 srelease (string_t *s)
318 {
319 	if (s -> size + 1 > s -> len) {
320 		s -> size = s -> len + 1;
321 		if (! (s -> str = (char_t *) Realloc (s -> str, sizeof (char_t) * (s -> size + 2)))) {
322 			s -> size = 0;
323 			s -> len = 0;
324 		}
325 	}
326 }
327 
328 Bool
siscntrl(string_t * s,int pos)329 siscntrl (string_t *s, int pos)
330 {
331 	return (s && (pos >= 0) && (pos < s -> len) && iscntrl (s -> str[pos])) ? True : False;
332 }
333 
334 Bool
sisspace(string_t * s,int pos)335 sisspace (string_t *s, int pos)
336 {
337 	return (s && (pos >= 0) && (pos < s -> len) && isspace (s -> str[pos])) ? True : False;
338 }
339 
340 Bool
sisdigit(string_t * s,int pos)341 sisdigit (string_t *s, int pos)
342 {
343 	return (s && (pos >= 0) && (pos < s -> len) && isdigit (s -> str[pos])) ? True : False;
344 }
345 
346 int
stoi(string_t * s)347 stoi (string_t *s)
348 {
349 	int	ret;
350 
351 	ret = 0;
352 	if (s && s -> str) {
353 		s -> str[s -> len] = '\0';
354 		ret = atoi ((char *) s -> str);
355 	}
356 	return ret;
357 }
358 /*}}}*/
359 /*{{{	date_t handling */
360 # if		! HAVE_MEMSET && ! HAVE_BZERO
361 static void
dozero(void * p,int len)362 dozero (void *p, int len)
363 {
364 	unsigned char	*ptr = (char *) p;
365 
366 	while (len-- > 0)
367 		*ptr++ = 0;
368 }
369 # endif		/* ! HAVE_MEMSET && ! HAVE_BZERO */
370 
371 date_t *
dat_free(date_t * d)372 dat_free (date_t *d)
373 {
374 	if (d)
375 		free (d);
376 	return NULL;
377 }
378 
379 date_t *
dat_parse(char * str)380 dat_parse (char *str)
381 {
382 	date_t		*d;
383 	time_t		tim;
384 	struct tm	*tt;
385 	struct tm	tm;
386 	Bool		add;
387 	char		*ptr, *sav;
388 	char		*p1, *p2;
389 	int		mode;
390 	int		n, val;
391 	char		sep;
392 	date_t		tmp;
393 
394 	d = NULL;
395 	if ((! str) || (str = strdup (str))) {
396 		if (d = (date_t *) malloc (sizeof (date_t))) {
397 			time (& tim);
398 			if (tt = localtime (& tim)) {
399 				d -> day = tt -> tm_mday;
400 				d -> mon = tt -> tm_mon + 1;
401 				d -> year = tt -> tm_year + 1900;
402 				d -> hour = tt -> tm_hour;
403 				d -> min = tt -> tm_min;
404 				d -> sec = tt -> tm_sec;
405 			} else {
406 				d -> day = 1;
407 				d -> mon = 1;
408 				d -> year = 1970;
409 				d -> hour = 0;
410 				d -> min = 0;
411 				d -> sec = 0;
412 			}
413 			if (str && strcmp (str, "now")) {
414 				if (*str == '+') {
415 					add = True;
416 					ptr = str + 1;
417 				} else {
418 					add = False;
419 					ptr = str;
420 				}
421 				tmp.day = -1;
422 				tmp.mon = -1;
423 				tmp.year = -1;
424 				tmp.hour = -1;
425 				tmp.min = -1;
426 				tmp.sec = -1;
427 				while (*ptr) {
428 					sav = ptr;
429 					ptr = skip (ptr);
430 					if (strchr (sav, '.')) {
431 						sep = '.';
432 						mode = 1;
433 					} else if (strchr (sav, '/')) {
434 						sep = '/';
435 						mode = 2;
436 					} else if (strchr (sav, ':')) {
437 						sep = ':';
438 						mode = 3;
439 					} else {
440 						sep = '\0';
441 						mode = 0;
442 					}
443 					for (p1 = sav, n = 0; *p1; ++n) {
444 						p2 = p1;
445 						p1 = skipch (p1, sep);
446 						val = atoi (p2);
447 						switch (mode) {
448 						case 0:
449 							tmp.sec = 0;
450 							if (val < 30) {
451 								tmp.hour = val;
452 								tmp.min = 0;
453 							} else {
454 								tmp.hour = val / 60;
455 								tmp.min = val % 60;
456 							}
457 							break;
458 						case 1:
459 							if (n == 0)
460 								tmp.day = val;
461 							else if (n == 1)
462 								tmp.mon = val;
463 							else if (n == 2) {
464 								if ((! add) && (val < 1900))
465 									val += 1900;
466 								tmp.year = val;
467 							}
468 							break;
469 						case 2:
470 							if (n == 0)
471 								tmp.mon = val;
472 							else if (n == 1)
473 								tmp.day = val;
474 							else if (n == 2) {
475 								if ((! add) && (val < 1900))
476 									val += 1900;
477 								tmp.year = val;
478 							}
479 							break;
480 						case 3:
481 							if (n == 0) {
482 								tmp.hour = val;
483 								tmp.min = 0;
484 								tmp.sec = 0;
485 							} else if (n == 1)
486 								tmp.min = val;
487 							else if (n == 2)
488 								tmp.sec = val;
489 							break;
490 						}
491 					}
492 				}
493 				if (add) {
494 					if (tmp.day != -1)
495 						d -> day += tmp.day;
496 					if (tmp.mon != -1)
497 						d -> mon += tmp.mon;
498 					if (tmp.year != -1)
499 						d -> year += tmp.year;
500 					if (tmp.hour != -1)
501 						d -> hour += tmp.hour;
502 					if (tmp.min != -1)
503 						d -> min += tmp.min;
504 					if (tmp.sec != -1)
505 						d -> sec += tmp.sec;
506 				} else {
507 					if (tmp.day != -1)
508 						d -> day = tmp.day;
509 					if (tmp.mon != -1)
510 						d -> mon = tmp.mon;
511 					if (tmp.year != -1)
512 						d -> year = tmp.year;
513 					if (tmp.hour != -1)
514 						d -> hour = tmp.hour;
515 					if (tmp.min != -1)
516 						d -> min = tmp.min;
517 					if (tmp.sec != -1)
518 						d -> sec = tmp.sec;
519 				}
520 # if		HAVE_MEMSET
521 				memset (& tm, 0, sizeof (tm));
522 # elif		HAVE_BZERO
523 				bzero (& tm, sizeof (tm));
524 # else
525 				dozero (& tm, sizeof (tm));
526 # endif		/* ! HAVE_MEMSET && ! HAVE_BZERO */
527 				tm.tm_mday = d -> day;
528 				tm.tm_mon = d -> mon - 1;
529 				tm.tm_year = d -> year - 1900;
530 				tm.tm_hour = d -> hour;
531 				tm.tm_min = d -> min;
532 				tm.tm_sec = d -> sec;
533 				tm.tm_isdst = tt -> tm_isdst;
534 				if (mktime (& tm) == (time_t) -1)
535 					d = dat_free (d);
536 				else {
537 					d -> day = tm.tm_mday;
538 					d -> mon = tm.tm_mon + 1;
539 					d -> year = tm.tm_year + 1900;
540 					d -> hour = tm.tm_hour;
541 					d -> min = tm.tm_min;
542 					d -> sec = tm.tm_sec;
543 				}
544 			}
545 		}
546 		if (str)
547 			free (str);
548 	}
549 	return d;
550 }
551 
552 int
dat_diff(date_t * d1,date_t * d2)553 dat_diff (date_t *d1, date_t *d2)
554 {
555 	int	v1, v2;
556 
557 	if (d1)
558 		v1 = (((((d1 -> year * 12 + d1 -> mon) * 31 + d1 -> day) * 24 + d1 -> hour) * 60 + d1 -> min) * 60 + d1 -> sec);
559 	else
560 		v1 = 0;
561 	if (d2)
562 		v2 = (((((d2 -> year * 12 + d2 -> mon) * 31 + d2 -> day) * 24 + d2 -> hour) * 60 + d2 -> min) * 60 + d2 -> sec);
563 	else
564 		v2 = 0;
565 	return v2 - v1;
566 }
567 
568 void
dat_clear(date_t * d)569 dat_clear (date_t *d)
570 {
571 	d -> day = 0;
572 	d -> mon = 0;
573 	d -> year = 0;
574 	d -> hour = 0;
575 	d -> min = 0;
576 	d -> sec = 0;
577 }
578 
579 void
dat_localtime(date_t * d)580 dat_localtime (date_t *d)
581 {
582 	time_t		tim;
583 	struct tm	*tt;
584 
585 	time (& tim);
586 	if (tt = localtime (& tim)) {
587 		d -> day = tt -> tm_mday;
588 		d -> mon = tt -> tm_mon + 1;
589 		d -> year = tt -> tm_year + 1900;
590 		d -> hour = tt -> tm_hour;
591 		d -> min = tt -> tm_min;
592 		d -> sec = tt -> tm_sec;
593 	} else
594 		dat_clear (d);
595 }
596 /*}}}*/
597