Home | History | Annotate | Line # | Download | only in common
      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