1/*	$NetBSD: util.c,v 1.4 2011/03/21 14:53:02 tnozaki 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#ifndef lint
15static 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";
16#endif /* not lint */
17
18#include <sys/types.h>
19#include <sys/queue.h>
20
21#include <bitstring.h>
22#include <errno.h>
23#include <limits.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <unistd.h>
28
29#include "common.h"
30
31/*
32 * binc --
33 *	Increase the size of a buffer.
34 *
35 * PUBLIC: void *binc __P((SCR *, void *, size_t *, size_t));
36 */
37void *
38binc(SCR *sp, void *bp, size_t *bsizep, size_t min)
39	        			/* sp MAY BE NULL!!! */
40
41
42{
43	size_t csize;
44
45	/* If already larger than the minimum, just return. */
46	if (min && *bsizep >= min)
47		return (bp);
48
49	csize = *bsizep + MAX(min, 256);
50	REALLOC(sp, bp, void *, csize);
51
52	if (bp == NULL) {
53		/*
54		 * Theoretically, realloc is supposed to leave any already
55		 * held memory alone if it can't get more.  Don't trust it.
56		 */
57		*bsizep = 0;
58		return (NULL);
59	}
60	/*
61	 * Memory is guaranteed to be zero-filled, various parts of
62	 * nvi depend on this.
63	 */
64	memset((char *)bp + *bsizep, 0, csize - *bsizep);
65	*bsizep = csize;
66	return (bp);
67}
68
69/*
70 * nonblank --
71 *	Set the column number of the first non-blank character
72 *	including or after the starting column.  On error, set
73 *	the column to 0, it's safest.
74 *
75 * PUBLIC: int nonblank __P((SCR *, db_recno_t, size_t *));
76 */
77int
78nonblank(SCR *sp, db_recno_t lno, size_t *cnop)
79{
80	CHAR_T *p;
81	size_t cnt, len, off;
82	int isempty;
83
84	/* Default. */
85	off = *cnop;
86	*cnop = 0;
87
88	/* Get the line, succeeding in an empty file. */
89	if (db_eget(sp, lno, &p, &len, &isempty))
90		return (!isempty);
91
92	/* Set the offset. */
93	if (len == 0 || off >= len)
94		return (0);
95
96	for (cnt = off, p = &p[off],
97	    len -= off; len && ISBLANK((UCHAR_T)*p); ++cnt, ++p, --len);
98
99	/* Set the return. */
100	*cnop = len ? cnt : cnt - 1;
101	return (0);
102}
103
104/*
105 * tail --
106 *	Return tail of a path.
107 *
108 * PUBLIC: char *tail __P((char *));
109 */
110const char *
111tail(const char *path)
112{
113	const 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 *v_strdup __P((SCR *, const char *, size_t));
125 */
126char *
127v_strdup(SCR *sp, const char *str, size_t len)
128{
129	char *copy;
130
131	MALLOC(sp, copy, char *, (len + 1));
132	if (copy == NULL)
133		return (NULL);
134	memcpy(copy, str, len);
135	copy[len] = '\0';
136	return (copy);
137}
138
139/*
140 * v_strdup --
141 *	Strdup for wide character strings with an associated length.
142 *
143 * PUBLIC: CHAR_T *v_wstrdup __P((SCR *, const CHAR_T *, size_t));
144 */
145CHAR_T *
146v_wstrdup(SCR *sp, const CHAR_T *str, size_t len)
147{
148	CHAR_T *copy;
149
150	MALLOC(sp, copy, CHAR_T *, (len + 1) * sizeof(CHAR_T));
151	if (copy == NULL)
152		return (NULL);
153	MEMCPYW(copy, str, len);
154	copy[len] = '\0';
155	return (copy);
156}
157
158/*
159 * nget_uslong --
160 *      Get an unsigned long, checking for overflow.
161 *
162 * PUBLIC: enum nresult nget_uslong __P((SCR *, u_long *, const CHAR_T *, CHAR_T **, int));
163 */
164enum nresult
165nget_uslong(SCR *sp, u_long *valp, const CHAR_T *p, CHAR_T **endp, int base)
166{
167	errno = 0;
168	*valp = STRTOUL(p, (RCHAR_T **)endp, base);
169	if (errno == 0)
170		return (NUM_OK);
171	if (errno == ERANGE && *valp == ULONG_MAX)
172		return (NUM_OVER);
173	return (NUM_ERR);
174}
175
176/*
177 * nget_slong --
178 *      Convert a signed long, checking for overflow and underflow.
179 *
180 * PUBLIC: enum nresult nget_slong __P((SCR *, long *, const CHAR_T *, CHAR_T **, int));
181 */
182enum nresult
183nget_slong(SCR *sp, long int *valp, const CHAR_T *p, CHAR_T **endp, int base)
184{
185	errno = 0;
186	*valp = STRTOL(p, (RCHAR_T **)endp, base);
187	if (errno == 0)
188		return (NUM_OK);
189	if (errno == ERANGE) {
190		if (*valp == LONG_MAX)
191			return (NUM_OVER);
192		if (*valp == LONG_MIN)
193			return (NUM_UNDER);
194	}
195	return (NUM_ERR);
196}
197