1 /* $OpenBSD: util.c,v 1.17 2018/07/11 06:39:23 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 *
binc(SCR * sp,void * bp,size_t * bsizep,size_t min)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 *bsizep = 0;
49 return (NULL);
50 }
51 /*
52 * Memory is guaranteed to be zero-filled, various parts of
53 * nvi depend on this.
54 */
55 memset((char *)bp + *bsizep, 0, csize - *bsizep);
56 *bsizep = csize;
57 return (bp);
58 }
59
60 /*
61 * nonblank --
62 * Set the column number of the first non-blank character
63 * including or after the starting column. On error, set
64 * the column to 0, it's safest.
65 *
66 * PUBLIC: int nonblank(SCR *, recno_t, size_t *);
67 */
68 int
nonblank(SCR * sp,recno_t lno,size_t * cnop)69 nonblank(SCR *sp, recno_t lno, size_t *cnop)
70 {
71 char *p;
72 size_t cnt, len, off;
73 int isempty;
74
75 /* Default. */
76 off = *cnop;
77 *cnop = 0;
78
79 /* Get the line, succeeding in an empty file. */
80 if (db_eget(sp, lno, &p, &len, &isempty))
81 return (!isempty);
82
83 /* Set the offset. */
84 if (len == 0 || off >= len)
85 return (0);
86
87 for (cnt = off, p = &p[off],
88 len -= off; len && isblank(*p); ++cnt, ++p, --len);
89
90 /* Set the return. */
91 *cnop = len ? cnt : cnt - 1;
92 return (0);
93 }
94
95 /*
96 * v_strdup --
97 * Strdup for wide character strings with an associated length.
98 *
99 * PUBLIC: CHAR_T *v_strdup(SCR *, const CHAR_T *, size_t);
100 */
101 CHAR_T *
v_strdup(SCR * sp,const CHAR_T * str,size_t len)102 v_strdup(SCR *sp, const CHAR_T *str, size_t len)
103 {
104 CHAR_T *copy;
105
106 MALLOC(sp, copy, len + 1);
107 if (copy == NULL)
108 return (NULL);
109 memcpy(copy, str, len * sizeof(CHAR_T));
110 copy[len] = '\0';
111 return (copy);
112 }
113
114 /*
115 * nget_uslong --
116 * Get an unsigned long, checking for overflow.
117 *
118 * PUBLIC: enum nresult nget_uslong(u_long *, const char *, char **, int);
119 */
120 enum nresult
nget_uslong(u_long * valp,const char * p,char ** endp,int base)121 nget_uslong(u_long *valp, const char *p, char **endp, int base)
122 {
123 errno = 0;
124 *valp = strtoul(p, endp, base);
125 if (errno == 0)
126 return (NUM_OK);
127 if (errno == ERANGE && *valp == ULONG_MAX)
128 return (NUM_OVER);
129 return (NUM_ERR);
130 }
131
132 /*
133 * nget_slong --
134 * Convert a signed long, checking for overflow and underflow.
135 *
136 * PUBLIC: enum nresult nget_slong(long *, const char *, char **, int);
137 */
138 enum nresult
nget_slong(long * valp,const char * p,char ** endp,int base)139 nget_slong(long *valp, const char *p, char **endp, int base)
140 {
141 errno = 0;
142 *valp = strtol(p, endp, base);
143 if (errno == 0)
144 return (NUM_OK);
145 if (errno == ERANGE) {
146 if (*valp == LONG_MAX)
147 return (NUM_OVER);
148 if (*valp == LONG_MIN)
149 return (NUM_UNDER);
150 }
151 return (NUM_ERR);
152 }
153
154 #ifdef DEBUG
155 #include <stdarg.h>
156
157 /*
158 * TRACE --
159 * debugging trace routine.
160 *
161 * PUBLIC: void TRACE(SCR *, const char *, ...);
162 */
163 void
TRACE(SCR * sp,const char * fmt,...)164 TRACE(SCR *sp, const char *fmt, ...)
165 {
166 FILE *tfp;
167 va_list ap;
168
169 if ((tfp = sp->gp->tracefp) == NULL)
170 return;
171 va_start(ap, fmt);
172 (void)vfprintf(tfp, fmt, ap);
173 fflush(tfp);
174 va_end(ap);
175
176 (void)fflush(tfp);
177 }
178 #endif
179