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