1 /***************************************************************/
2 /* */
3 /* UTILS.C */
4 /* */
5 /* Useful utility functions. */
6 /* */
7 /* This file is part of REMIND. */
8 /* Copyright (C) 1992-2021 by Dianne Skoll */
9 /* */
10 /***************************************************************/
11
12 static char const DontEscapeMe[] =
13 "1234567890_-=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@.,/";
14
15 #include "config.h"
16 #include "err.h"
17
18 #include <string.h>
19 #include <stdio.h>
20 #include <ctype.h>
21
22 #include <stdlib.h>
23 #include "types.h"
24 #include "globals.h"
25 #include "protos.h"
26
27 #define UPPER(c) toupper(c)
28
29 /***************************************************************/
30 /* */
31 /* StrnCpy */
32 /* */
33 /* Just like strncpy EXCEPT we ALWAYS copy the trailing 0. */
34 /* */
35 /***************************************************************/
StrnCpy(char * dest,char const * source,int n)36 char *StrnCpy(char *dest, char const *source, int n)
37 {
38 char *odest = dest;
39
40 while (n-- && (*dest++ = *source++)) ;
41 if (*(dest-1)) *dest = 0;
42 return odest;
43 }
44
45 /***************************************************************/
46 /* */
47 /* StrMatch */
48 /* */
49 /* Checks that two strings match (case-insensitive) to at */
50 /* least the specified number of characters, or the length */
51 /* of the first string, whichever is greater. */
52 /* */
53 /***************************************************************/
StrMatch(char const * s1,char const * s2,int n)54 int StrMatch(char const *s1, char const *s2, int n)
55 {
56 int l;
57 if ((l = strlen(s1)) < n) return 0;
58 return !StrinCmp(s1, s2, l);
59 }
60
61 /***************************************************************/
62 /* */
63 /* StrinCmp - compare strings, case-insensitive */
64 /* */
65 /***************************************************************/
StrinCmp(char const * s1,char const * s2,int n)66 int StrinCmp(char const *s1, char const *s2, int n)
67 {
68 register int r;
69 while (n && *s1 && *s2) {
70 n--;
71 r = UPPER(*s1) - UPPER(*s2);
72 if (r) return r;
73 s1++;
74 s2++;
75 }
76 if (n) return (UPPER(*s1) - UPPER(*s2)); else return 0;
77 }
78
79 /***************************************************************/
80 /* */
81 /* StrDup */
82 /* */
83 /* Like ANSI strdup */
84 /* */
85 /***************************************************************/
StrDup(char const * s)86 char *StrDup(char const *s)
87 {
88 char *ret = malloc(strlen(s)+1);
89 if (!ret) return NULL;
90 strcpy(ret, s);
91 return ret;
92 }
93
94 /***************************************************************/
95 /* */
96 /* StrCmpi */
97 /* */
98 /* Compare strings, case insensitive. */
99 /* */
100 /***************************************************************/
StrCmpi(char const * s1,char const * s2)101 int StrCmpi(char const *s1, char const *s2)
102 {
103 int r;
104 while (*s1 && *s2) {
105 r = UPPER(*s1) - UPPER(*s2);
106 if (r) return r;
107 s1++;
108 s2++;
109 }
110 return UPPER(*s1) - UPPER(*s2);
111 }
112
113 /***************************************************************/
114 /* */
115 /* DateOK */
116 /* */
117 /* Return 1 if the date is OK, 0 otherwise. */
118 /* */
119 /***************************************************************/
DateOK(int y,int m,int d)120 int DateOK(int y, int m, int d)
121 {
122 if (d < 1 ||
123 m < 0 ||
124 y < BASE ||
125 m > 11 ||
126 y > BASE + YR_RANGE ||
127 d > DaysInMonth(m, y) ) return 0;
128 else return 1;
129 }
130
131 /* Functions designed to defeat gcc optimizer */
132
_private_div(int a,int b)133 int _private_div(int a, int b) { return a/b; }
_private_add_overflow(int result,int b,int old)134 int _private_add_overflow(int result, int b, int old)
135 {
136 if (b > 0 && result < old) return 1;
137 if (b < 0 && result > old) return 1;
138 return 0;
139 }
_private_sub_overflow(int result,int b,int old)140 int _private_sub_overflow(int result, int b, int old)
141 {
142 if (b < 0 && result < old) return 1;
143 if (b > 0 && result > old) return 1;
144 return 0;
145 }
146
_private_unminus_overflow(int a,int b)147 int _private_unminus_overflow(int a, int b)
148 {
149 if (a > 0 && b > 0) return 1;
150 if (a < 0 && b < 0) return 1;
151 return 0;
152 }
153
154 int
ShellEscape(char const * in,DynamicBuffer * out)155 ShellEscape(char const *in, DynamicBuffer *out)
156 {
157 while(*in) {
158 if (!strchr(DontEscapeMe, *in)) {
159 if (DBufPutc(out, '\\') != OK) return E_NO_MEM;
160 }
161 if (DBufPutc(out, *in++) != OK) return E_NO_MEM;
162 }
163 return OK;
164 }
165