xref: /openbsd/usr.bin/vi/common/util.c (revision 8b325477)
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