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