1 /* $OpenBSD: util.c,v 1.15 2016/05/27 09:18:11 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 va_end(ap); 178 179 (void)fflush(tfp); 180 } 181 #endif 182