xref: /netbsd-src/external/bsd/nvi/dist/common/util.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*	$NetBSD: util.c,v 1.2 2013/11/22 15:52:05 christos 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 #ifndef lint
14 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 ";
15 #endif /* not lint */
16 
17 #include <sys/types.h>
18 #include <sys/queue.h>
19 
20 #include <bitstring.h>
21 #include <errno.h>
22 #include <limits.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 
28 #include "common.h"
29 
30 /*
31  * binc --
32  *	Increase the size of a buffer.
33  *
34  * PUBLIC: void *binc __P((SCR *, void *, size_t *, size_t));
35  */
36 void *
37 binc(SCR *sp, void *bp, size_t *bsizep, size_t min)
38 	        			/* sp MAY BE NULL!!! */
39 
40 
41 {
42 	size_t csize;
43 
44 	/* If already larger than the minimum, just return. */
45 	if (min && *bsizep >= min)
46 		return (bp);
47 
48 	csize = *bsizep + MAX(min, 256);
49 	REALLOC(sp, bp, void *, csize);
50 
51 	if (bp == NULL) {
52 		/*
53 		 * Theoretically, realloc is supposed to leave any already
54 		 * held memory alone if it can't get more.  Don't trust it.
55 		 */
56 		*bsizep = 0;
57 		return (NULL);
58 	}
59 	/*
60 	 * Memory is guaranteed to be zero-filled, various parts of
61 	 * nvi depend on this.
62 	 */
63 	memset((char *)bp + *bsizep, 0, csize - *bsizep);
64 	*bsizep = csize;
65 	return (bp);
66 }
67 
68 /*
69  * nonblank --
70  *	Set the column number of the first non-blank character
71  *	including or after the starting column.  On error, set
72  *	the column to 0, it's safest.
73  *
74  * PUBLIC: int nonblank __P((SCR *, db_recno_t, size_t *));
75  */
76 int
77 nonblank(SCR *sp, db_recno_t lno, size_t *cnop)
78 {
79 	CHAR_T *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((UCHAR_T)*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: const char *tail __P((const char *));
108  */
109 const char *
110 tail(const char *path)
111 {
112 	const char *p;
113 
114 	if ((p = strrchr(path, '/')) == NULL)
115 		return (path);
116 	return (p + 1);
117 }
118 
119 /*
120  * v_strdup --
121  *	Strdup for wide character strings with an associated length.
122  *
123  * PUBLIC: char *v_strdup __P((SCR *, const char *, size_t));
124  */
125 char *
126 v_strdup(SCR *sp, const char *str, size_t len)
127 {
128 	char *copy;
129 
130 	MALLOC(sp, copy, char *, (len + 1));
131 	if (copy == NULL)
132 		return (NULL);
133 	memcpy(copy, str, len);
134 	copy[len] = '\0';
135 	return (copy);
136 }
137 
138 /*
139  * v_strdup --
140  *	Strdup for wide character strings with an associated length.
141  *
142  * PUBLIC: CHAR_T *v_wstrdup __P((SCR *, const CHAR_T *, size_t));
143  */
144 CHAR_T *
145 v_wstrdup(SCR *sp, const CHAR_T *str, size_t len)
146 {
147 	CHAR_T *copy;
148 
149 	MALLOC(sp, copy, CHAR_T *, (len + 1) * sizeof(CHAR_T));
150 	if (copy == NULL)
151 		return (NULL);
152 	MEMCPYW(copy, str, len);
153 	copy[len] = '\0';
154 	return (copy);
155 }
156 
157 /*
158  * nget_uslong --
159  *      Get an unsigned long, checking for overflow.
160  *
161  * PUBLIC: enum nresult nget_uslong __P((SCR *, u_long *, const CHAR_T *, CHAR_T **, int));
162  */
163 enum nresult
164 nget_uslong(SCR *sp, u_long *valp, const CHAR_T *p, CHAR_T **endp, int base)
165 {
166 	errno = 0;
167 	*valp = STRTOUL(p, (RCHAR_T **)endp, base);
168 	if (errno == 0)
169 		return (NUM_OK);
170 	if (errno == ERANGE && *valp == ULONG_MAX)
171 		return (NUM_OVER);
172 	return (NUM_ERR);
173 }
174 
175 /*
176  * nget_slong --
177  *      Convert a signed long, checking for overflow and underflow.
178  *
179  * PUBLIC: enum nresult nget_slong __P((SCR *, long *, const CHAR_T *, CHAR_T **, int));
180  */
181 enum nresult
182 nget_slong(SCR *sp, long int *valp, const CHAR_T *p, CHAR_T **endp, int base)
183 {
184 	errno = 0;
185 	*valp = STRTOL(p, (RCHAR_T **)endp, base);
186 	if (errno == 0)
187 		return (NUM_OK);
188 	if (errno == ERANGE) {
189 		if (*valp == LONG_MAX)
190 			return (NUM_OVER);
191 		if (*valp == LONG_MIN)
192 			return (NUM_UNDER);
193 	}
194 	return (NUM_ERR);
195 }
196