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