aboutsummaryrefslogtreecommitdiff
path: root/common/util.c
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2013-08-11 09:44:58 +0000
committerPeter Wemm <peter@FreeBSD.org>2013-08-11 09:44:58 +0000
commitbe3e4646eef6a3abcf58590dac24a5dfe54540f6 (patch)
tree5a0e2514f154d0eb24f2235092423adb95ac75ac /common/util.c
parent84ed61ee234d2654ec965be5bfdda4269f9dc4fd (diff)
downloadsrc-be3e4646eef6a3abcf58590dac24a5dfe54540f6.tar.gz
src-be3e4646eef6a3abcf58590dac24a5dfe54540f6.zip
Import nvi-2.1.1-4334a8297f into the work area. This is the gsoc-2011vendor/nvi/2.1.1-4334a8297f
project to clean up and backport multibyte support from other nvi forks in a form we can use. GSoC info: http://www.google-melange.com/gsoc/proposal/review/google/gsoc2011/zy/1 Repo at: https://github.com/lichray/nvi2 Obtained from: Zhihao Yuan <lichray@gmail.com>
Notes
Notes: svn path=/vendor/nvi/dist/; revision=254211 svn path=/vendor/nvi/2.1.1-4334a8297f/; revision=254212; tag=vendor/nvi/2.1.1-4334a8297f
Diffstat (limited to 'common/util.c')
-rw-r--r--common/util.c303
1 files changed, 248 insertions, 55 deletions
diff --git a/common/util.c b/common/util.c
index 5a4422a2c422..43fa9d1e9f20 100644
--- a/common/util.c
+++ b/common/util.c
@@ -10,18 +10,27 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)util.c 10.11 (Berkeley) 9/15/96";
+static const char sccsid[] = "$Id: util.c,v 10.30 2013/03/19 10:00:27 yamt Exp $";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
+#ifdef __APPLE__
+#include <mach/clock.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#endif
+
#include <bitstring.h>
+#include <ctype.h>
#include <errno.h>
#include <limits.h>
+#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
#include "common.h"
@@ -33,10 +42,11 @@ static const char sccsid[] = "@(#)util.c 10.11 (Berkeley) 9/15/96";
* PUBLIC: void *binc __P((SCR *, void *, size_t *, size_t));
*/
void *
-binc(sp, bp, bsizep, min)
- SCR *sp; /* sp MAY BE NULL!!! */
- void *bp;
- size_t *bsizep, min;
+binc(
+ SCR *sp, /* sp MAY BE NULL!!! */
+ void *bp,
+ size_t *bsizep,
+ size_t min)
{
size_t csize;
@@ -44,14 +54,10 @@ binc(sp, bp, bsizep, min)
if (min && *bsizep >= min)
return (bp);
- csize = *bsizep + MAX(min, 256);
+ csize = p2roundup(MAX(min, 256));
REALLOC(sp, bp, void *, csize);
if (bp == NULL) {
- /*
- * Theoretically, realloc is supposed to leave any already
- * held memory alone if it can't get more. Don't trust it.
- */
*bsizep = 0;
return (NULL);
}
@@ -73,12 +79,12 @@ binc(sp, bp, bsizep, min)
* PUBLIC: int nonblank __P((SCR *, recno_t, size_t *));
*/
int
-nonblank(sp, lno, cnop)
- SCR *sp;
- recno_t lno;
- size_t *cnop;
+nonblank(
+ SCR *sp,
+ recno_t lno,
+ size_t *cnop)
{
- char *p;
+ CHAR_T *p;
size_t cnt, len, off;
int isempty;
@@ -95,7 +101,7 @@ nonblank(sp, lno, cnop)
return (0);
for (cnt = off, p = &p[off],
- len -= off; len && isblank(*p); ++cnt, ++p, --len);
+ len -= off; len && ISBLANK(*p); ++cnt, ++p, --len);
/* Set the return. */
*cnop = len ? cnt : cnt - 1;
@@ -109,8 +115,7 @@ nonblank(sp, lno, cnop)
* PUBLIC: char *tail __P((char *));
*/
char *
-tail(path)
- char *path;
+tail(char *path)
{
char *p;
@@ -120,23 +125,161 @@ tail(path)
}
/*
+ * join --
+ * Join two paths; need free.
+ *
+ * PUBLIC: char *join __P((char *, char *));
+ */
+char *
+join(
+ char *path1,
+ char *path2)
+{
+ char *p;
+
+ if (path1[0] == '\0' || path2[0] == '/')
+ return strdup(path2);
+ (void)asprintf(&p, path1[strlen(path1)-1] == '/' ?
+ "%s%s" : "%s/%s", path1, path2);
+ return p;
+}
+
+/*
+ * expanduser --
+ * Return a "~" or "~user" expanded path; need free.
+ *
+ * PUBLIC: char *expanduser __P((char *));
+ */
+char *
+expanduser(char *str)
+{
+ struct passwd *pwd;
+ char *p, *t, *u, *h;
+
+ /*
+ * This function always expands the content between the
+ * leading '~' and the first '/' or '\0' from the input.
+ * Return NULL whenever we fail to do so.
+ */
+ if (*str != '~')
+ return (NULL);
+ p = str + 1;
+ for (t = p; *t != '/' && *t != '\0'; ++t)
+ continue;
+ if (t == p) {
+ /* ~ */
+ if (issetugid() != 0 ||
+ (h = getenv("HOME")) == NULL) {
+ if (((h = getlogin()) != NULL &&
+ (pwd = getpwnam(h)) != NULL) ||
+ (pwd = getpwuid(getuid())) != NULL)
+ h = pwd->pw_dir;
+ else
+ return (NULL);
+ }
+ } else {
+ /* ~user */
+ if ((u = strndup(p, t - p)) == NULL)
+ return (NULL);
+ if ((pwd = getpwnam(u)) == NULL) {
+ free(u);
+ return (NULL);
+ } else
+ h = pwd->pw_dir;
+ free(u);
+ }
+
+ for (; *t == '/' && *t != '\0'; ++t)
+ continue;
+ return (join(h, t));
+}
+
+/*
+ * quote --
+ * Return a escaped string for /bin/sh; need free.
+ *
+ * PUBLIC: char *quote __P((char *));
+ */
+char *
+quote(char *str)
+{
+ char *p, *t;
+ size_t i = 0, n = 0;
+ int unsafe = 0;
+
+ for (p = str; *p != '\0'; p++, i++) {
+ if (*p == '\'')
+ n++;
+ if (unsafe)
+ continue;
+ if (isascii(*p)) {
+ if (isalnum(*p))
+ continue;
+ switch (*p) {
+ case '%': case '+': case ',': case '-': case '.':
+ case '/': case ':': case '=': case '@': case '_':
+ continue;
+ }
+ }
+ unsafe = 1;
+ }
+ if (!unsafe)
+ t = strdup(str);
+#define SQT "'\\''"
+ else if ((p = t = malloc(i + n * (sizeof(SQT) - 2) + 3)) != NULL) {
+ *p++ = '\'';
+ for (; *str != '\0'; str++) {
+ if (*str == '\'') {
+ (void)memcpy(p, SQT, sizeof(SQT) - 1);
+ p += sizeof(SQT) - 1;
+ } else
+ *p++ = *str;
+ }
+ *p++ = '\'';
+ *p = '\0';
+ }
+ return t;
+}
+
+/*
* v_strdup --
+ * Strdup for 8-bit character strings with an associated length.
+ *
+ * PUBLIC: char *v_strdup __P((SCR *, const char *, size_t));
+ */
+char *
+v_strdup(
+ SCR *sp,
+ const char *str,
+ size_t len)
+{
+ char *copy;
+
+ MALLOC(sp, copy, char *, len + 1);
+ if (copy == NULL)
+ return (NULL);
+ memcpy(copy, str, len);
+ copy[len] = '\0';
+ return (copy);
+}
+
+/*
+ * v_wstrdup --
* Strdup for wide character strings with an associated length.
*
- * PUBLIC: CHAR_T *v_strdup __P((SCR *, const CHAR_T *, size_t));
+ * PUBLIC: CHAR_T *v_wstrdup __P((SCR *, const CHAR_T *, size_t));
*/
CHAR_T *
-v_strdup(sp, str, len)
- SCR *sp;
- const CHAR_T *str;
- size_t len;
+v_wstrdup(SCR *sp,
+ const CHAR_T *str,
+ size_t len)
{
CHAR_T *copy;
- MALLOC(sp, copy, CHAR_T *, len + 1);
+ MALLOC(sp, copy, CHAR_T *, (len + 1) * sizeof(CHAR_T));
if (copy == NULL)
return (NULL);
- memcpy(copy, str, len * sizeof(CHAR_T));
+ MEMCPY(copy, str, len);
copy[len] = '\0';
return (copy);
}
@@ -145,17 +288,17 @@ v_strdup(sp, str, len)
* nget_uslong --
* Get an unsigned long, checking for overflow.
*
- * PUBLIC: enum nresult nget_uslong __P((u_long *, const char *, char **, int));
+ * PUBLIC: enum nresult nget_uslong __P((u_long *, const CHAR_T *, CHAR_T **, int));
*/
enum nresult
-nget_uslong(valp, p, endp, base)
- u_long *valp;
- const char *p;
- char **endp;
- int base;
+nget_uslong(
+ u_long *valp,
+ const CHAR_T *p,
+ CHAR_T **endp,
+ int base)
{
errno = 0;
- *valp = strtoul(p, endp, base);
+ *valp = STRTOUL(p, endp, base);
if (errno == 0)
return (NUM_OK);
if (errno == ERANGE && *valp == ULONG_MAX)
@@ -167,17 +310,17 @@ nget_uslong(valp, p, endp, base)
* nget_slong --
* Convert a signed long, checking for overflow and underflow.
*
- * PUBLIC: enum nresult nget_slong __P((long *, const char *, char **, int));
+ * PUBLIC: enum nresult nget_slong __P((long *, const CHAR_T *, CHAR_T **, int));
*/
enum nresult
-nget_slong(valp, p, endp, base)
- long *valp;
- const char *p;
- char **endp;
- int base;
+nget_slong(
+ long *valp,
+ const CHAR_T *p,
+ CHAR_T **endp,
+ int base)
{
errno = 0;
- *valp = strtol(p, endp, base);
+ *valp = STRTOL(p, endp, base);
if (errno == 0)
return (NUM_OK);
if (errno == ERANGE) {
@@ -189,12 +332,70 @@ nget_slong(valp, p, endp, base)
return (NUM_ERR);
}
-#ifdef DEBUG
-#ifdef __STDC__
-#include <stdarg.h>
+/*
+ * timepoint_steady --
+ * Get a timestamp from a monotonic clock.
+ *
+ * PUBLIC: void timepoint_steady __P((struct timespec *));
+ */
+void
+timepoint_steady(
+ struct timespec *ts)
+{
+#ifdef __APPLE__
+ static mach_timebase_info_data_t base = { 0 };
+ uint64_t val;
+ uint64_t ns;
+
+ if (base.denom == 0)
+ (void)mach_timebase_info(&base);
+
+ val = mach_absolute_time();
+ ns = val * base.numer / base.denom;
+ ts->tv_sec = ns / 1000000000;
+ ts->tv_nsec = ns % 1000000000;
+#else
+#ifdef CLOCK_MONOTONIC_FAST
+ (void)clock_gettime(CLOCK_MONOTONIC_FAST, ts);
#else
-#include <varargs.h>
+ (void)clock_gettime(CLOCK_MONOTONIC, ts);
+#endif
#endif
+}
+
+/*
+ * timepoint_system --
+ * Get the current calendar time.
+ *
+ * PUBLIC: void timepoint_system __P((struct timespec *));
+ */
+void
+timepoint_system(
+ struct timespec *ts)
+{
+#ifdef __APPLE__
+ clock_serv_t clk;
+ mach_timespec_t mts;
+ kern_return_t kr;
+
+ kr = host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &clk);
+ if (kr != KERN_SUCCESS)
+ return;
+ (void)clock_get_time(clk, &mts);
+ (void)mach_port_deallocate(mach_task_self(), clk);
+ ts->tv_sec = mts.tv_sec;
+ ts->tv_nsec = mts.tv_nsec;
+#else
+#ifdef CLOCK_REALTIME_FAST
+ (void)clock_gettime(CLOCK_REALTIME_FAST, ts);
+#else
+ (void)clock_gettime(CLOCK_REALTIME, ts);
+#endif
+#endif
+}
+
+#ifdef DEBUG
+#include <stdarg.h>
/*
* TRACE --
@@ -203,25 +404,17 @@ nget_slong(valp, p, endp, base)
* PUBLIC: void TRACE __P((SCR *, const char *, ...));
*/
void
-#ifdef __STDC__
-TRACE(SCR *sp, const char *fmt, ...)
-#else
-TRACE(sp, fmt, va_alist)
- SCR *sp;
- char *fmt;
- va_dcl
-#endif
+TRACE(
+ SCR *sp,
+ const char *fmt,
+ ...)
{
FILE *tfp;
va_list ap;
if ((tfp = sp->gp->tracefp) == NULL)
return;
-#ifdef __STDC__
va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
(void)vfprintf(tfp, fmt, ap);
va_end(ap);