util.c revision 1.12
1/*	$OpenBSD: util.c,v 1.12 2015/12/07 20:39:19 mmcc 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 */
35void *
36binc(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 */
72int
73nonblank(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 * tail --
101 *	Return tail of a path.
102 *
103 * PUBLIC: char *tail(char *);
104 */
105char *
106tail(char *path)
107{
108	char *p;
109
110	if ((p = strrchr(path, '/')) == NULL)
111		return (path);
112	return (p + 1);
113}
114
115/*
116 * v_strdup --
117 *	Strdup for wide character strings with an associated length.
118 *
119 * PUBLIC: CHAR_T *v_strdup(SCR *, const CHAR_T *, size_t);
120 */
121CHAR_T *
122v_strdup(SCR *sp, const CHAR_T *str, size_t len)
123{
124	CHAR_T *copy;
125
126	MALLOC(sp, copy, len + 1);
127	if (copy == NULL)
128		return (NULL);
129	memcpy(copy, str, len * sizeof(CHAR_T));
130	copy[len] = '\0';
131	return (copy);
132}
133
134/*
135 * nget_uslong --
136 *      Get an unsigned long, checking for overflow.
137 *
138 * PUBLIC: enum nresult nget_uslong(u_long *, const char *, char **, int);
139 */
140enum nresult
141nget_uslong(u_long *valp, const char *p, char **endp, int base)
142{
143	errno = 0;
144	*valp = strtoul(p, endp, base);
145	if (errno == 0)
146		return (NUM_OK);
147	if (errno == ERANGE && *valp == ULONG_MAX)
148		return (NUM_OVER);
149	return (NUM_ERR);
150}
151
152/*
153 * nget_slong --
154 *      Convert a signed long, checking for overflow and underflow.
155 *
156 * PUBLIC: enum nresult nget_slong(long *, const char *, char **, int);
157 */
158enum nresult
159nget_slong(long *valp, const char *p, char **endp, int base)
160{
161	errno = 0;
162	*valp = strtol(p, endp, base);
163	if (errno == 0)
164		return (NUM_OK);
165	if (errno == ERANGE) {
166		if (*valp == LONG_MAX)
167			return (NUM_OVER);
168		if (*valp == LONG_MIN)
169			return (NUM_UNDER);
170	}
171	return (NUM_ERR);
172}
173
174#ifdef DEBUG
175#include <stdarg.h>
176
177/*
178 * TRACE --
179 *	debugging trace routine.
180 *
181 * PUBLIC: void TRACE(SCR *, const char *, ...);
182 */
183void
184TRACE(SCR *sp, const char *fmt, ...)
185{
186	FILE *tfp;
187	va_list ap;
188
189	if ((tfp = sp->gp->tracefp) == NULL)
190		return;
191	va_start(ap, fmt);
192	(void)vfprintf(tfp, fmt, ap);
193	va_end(ap);
194
195	(void)fflush(tfp);
196}
197#endif
198