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