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 * 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 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 * 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 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 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 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