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