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