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