xref: /freebsd/contrib/nvi/common/util.c (revision f0adf7f5cdd241db2f2c817683191a6ef64a4e95)
1 /*-
2  * Copyright (c) 1991, 1993, 1994
3  *	The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 1991, 1993, 1994, 1995, 1996
5  *	Keith Bostic.  All rights reserved.
6  *
7  * See the LICENSE file for redistribution information.
8  */
9 
10 #include "config.h"
11 
12 #ifndef lint
13 static const char sccsid[] = "@(#)util.c	10.11 (Berkeley) 9/15/96";
14 #endif /* not lint */
15 
16 #include <sys/types.h>
17 #include <sys/queue.h>
18 
19 #include <bitstring.h>
20 #include <errno.h>
21 #include <limits.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 
27 #include "common.h"
28 
29 /*
30  * binc --
31  *	Increase the size of a buffer.
32  *
33  * PUBLIC: void *binc __P((SCR *, void *, size_t *, size_t));
34  */
35 void *
36 binc(sp, bp, bsizep, min)
37 	SCR *sp;			/* sp MAY BE NULL!!! */
38 	void *bp;
39 	size_t *bsizep, min;
40 {
41 	size_t csize;
42 
43 	/* If already larger than the minimum, just return. */
44 	if (min && *bsizep >= min)
45 		return (bp);
46 
47 	csize = *bsizep + MAX(min, 256);
48 	REALLOC(sp, bp, void *, csize);
49 
50 	if (bp == NULL) {
51 		/*
52 		 * Theoretically, realloc is supposed to leave any already
53 		 * held memory alone if it can't get more.  Don't trust it.
54 		 */
55 		*bsizep = 0;
56 		return (NULL);
57 	}
58 	/*
59 	 * Memory is guaranteed to be zero-filled, various parts of
60 	 * nvi depend on this.
61 	 */
62 	memset((char *)bp + *bsizep, 0, csize - *bsizep);
63 	*bsizep = csize;
64 	return (bp);
65 }
66 
67 /*
68  * nonblank --
69  *	Set the column number of the first non-blank character
70  *	including or after the starting column.  On error, set
71  *	the column to 0, it's safest.
72  *
73  * PUBLIC: int nonblank __P((SCR *, recno_t, size_t *));
74  */
75 int
76 nonblank(sp, lno, cnop)
77 	SCR *sp;
78 	recno_t lno;
79 	size_t *cnop;
80 {
81 	char *p;
82 	size_t cnt, len, off;
83 	int isempty;
84 
85 	/* Default. */
86 	off = *cnop;
87 	*cnop = 0;
88 
89 	/* Get the line, succeeding in an empty file. */
90 	if (db_eget(sp, lno, &p, &len, &isempty))
91 		return (!isempty);
92 
93 	/* Set the offset. */
94 	if (len == 0 || off >= len)
95 		return (0);
96 
97 	for (cnt = off, p = &p[off],
98 	    len -= off; len && isblank(*p); ++cnt, ++p, --len);
99 
100 	/* Set the return. */
101 	*cnop = len ? cnt : cnt - 1;
102 	return (0);
103 }
104 
105 /*
106  * tail --
107  *	Return tail of a path.
108  *
109  * PUBLIC: char *tail __P((char *));
110  */
111 char *
112 tail(path)
113 	char *path;
114 {
115 	char *p;
116 
117 	if ((p = strrchr(path, '/')) == NULL)
118 		return (path);
119 	return (p + 1);
120 }
121 
122 /*
123  * v_strdup --
124  *	Strdup for wide character strings with an associated length.
125  *
126  * PUBLIC: CHAR_T *v_strdup __P((SCR *, const CHAR_T *, size_t));
127  */
128 CHAR_T *
129 v_strdup(sp, str, len)
130 	SCR *sp;
131 	const CHAR_T *str;
132 	size_t len;
133 {
134 	CHAR_T *copy;
135 
136 	MALLOC(sp, copy, CHAR_T *, len + 1);
137 	if (copy == NULL)
138 		return (NULL);
139 	memcpy(copy, str, len * sizeof(CHAR_T));
140 	copy[len] = '\0';
141 	return (copy);
142 }
143 
144 /*
145  * nget_uslong --
146  *      Get an unsigned long, checking for overflow.
147  *
148  * PUBLIC: enum nresult nget_uslong __P((u_long *, const char *, char **, int));
149  */
150 enum nresult
151 nget_uslong(valp, p, endp, base)
152 	u_long *valp;
153 	const char *p;
154 	char **endp;
155 	int base;
156 {
157 	errno = 0;
158 	*valp = strtoul(p, endp, base);
159 	if (errno == 0)
160 		return (NUM_OK);
161 	if (errno == ERANGE && *valp == ULONG_MAX)
162 		return (NUM_OVER);
163 	return (NUM_ERR);
164 }
165 
166 /*
167  * nget_slong --
168  *      Convert a signed long, checking for overflow and underflow.
169  *
170  * PUBLIC: enum nresult nget_slong __P((long *, const char *, char **, int));
171  */
172 enum nresult
173 nget_slong(valp, p, endp, base)
174 	long *valp;
175 	const char *p;
176 	char **endp;
177 	int base;
178 {
179 	errno = 0;
180 	*valp = strtol(p, endp, base);
181 	if (errno == 0)
182 		return (NUM_OK);
183 	if (errno == ERANGE) {
184 		if (*valp == LONG_MAX)
185 			return (NUM_OVER);
186 		if (*valp == LONG_MIN)
187 			return (NUM_UNDER);
188 	}
189 	return (NUM_ERR);
190 }
191 
192 #ifdef DEBUG
193 #ifdef __STDC__
194 #include <stdarg.h>
195 #else
196 #include <varargs.h>
197 #endif
198 
199 /*
200  * TRACE --
201  *	debugging trace routine.
202  *
203  * PUBLIC: void TRACE __P((SCR *, const char *, ...));
204  */
205 void
206 #ifdef __STDC__
207 TRACE(SCR *sp, const char *fmt, ...)
208 #else
209 TRACE(sp, fmt, va_alist)
210 	SCR *sp;
211 	char *fmt;
212 	va_dcl
213 #endif
214 {
215 	FILE *tfp;
216 	va_list ap;
217 
218 	if ((tfp = sp->gp->tracefp) == NULL)
219 		return;
220 #ifdef __STDC__
221 	va_start(ap, fmt);
222 #else
223 	va_start(ap);
224 #endif
225 	(void)vfprintf(tfp, fmt, ap);
226 	va_end(ap);
227 
228 	(void)fflush(tfp);
229 }
230 #endif
231