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