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