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