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