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 *
binc(sp,bp,bsizep,min)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
nonblank(sp,lno,cnop)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 *
tail(path)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 *
v_strdup(sp,str,len)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
nget_uslong(valp,p,endp,base)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
nget_slong(valp,p,endp,base)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
TRACE(SCR * sp,const char * fmt,...)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