diff options
Diffstat (limited to 'src/pj_internal.c')
| -rw-r--r-- | src/pj_internal.c | 288 |
1 files changed, 259 insertions, 29 deletions
diff --git a/src/pj_internal.c b/src/pj_internal.c index 8a5d2d15..7bfd192b 100644 --- a/src/pj_internal.c +++ b/src/pj_internal.c @@ -33,6 +33,7 @@ #include "projects.h" #include <geodesic.h> +#include <ctype.h> #include <stddef.h> #include <stdarg.h> #include <errno.h> @@ -114,14 +115,15 @@ void proj_context_inherit (PJ *parent, PJ *child) { -size_t pj_strlcpy(char *dst, const char *src, size_t siz) { -/******************************************************************* +/**************************************************************************************/ +size_t pj_strlcpy(char *dst, const char *src, size_t dsize) { +/*************************************************************************************** Copy src to string dst of size siz. At most siz-1 characters will be copied. Always NUL terminates (unless siz == 0). Returns strlen(src); if retval >= siz, truncation occurred. - - * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -134,40 +136,243 @@ size_t pj_strlcpy(char *dst, const char *src, size_t siz) { * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * - Source: http://www.i-pi.com/Training/EthicalHacking/Solutions/strlcpy.c + Source: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/string/strlcpy.c -********************************************************************/ - register char *d = dst; - register const char *s = src; - register size_t n = siz; +***************************************************************************************/ + const char *osrc = src; + size_t nleft = dsize; - /* Copy as many bytes as will fit */ - if (n != 0 && --n != 0) { - do { - if ((*d++ = *s++) == 0) + /* Copy as many bytes as will fit. */ + if (nleft != 0) { + while (--nleft != 0) { + if ((*dst++ = *src++) == '\0') break; - } while (--n != 0); + } } - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) + /* Not enough room in dst, add NUL and traverse rest of src. */ + if (nleft == 0) { + if (dsize != 0) + *dst = '\0'; /* NUL-terminate dst */ + while (*src++) ; } - return(s - src - 1); /* count does not include NUL */ + return(src - osrc - 1); /* count does not include NUL */ } -/* stuff below is *not* considered API, and will be moved to an "internal plumbing toolset" */ +/*****************************************************************************/ +char *pj_chomp (char *c) { +/****************************************************************************** +Strip pre- and postfix whitespace. Inline comments (indicated by '#') are +considered whitespace. +******************************************************************************/ + size_t i, n; + char *comment; + char *start = c; + + if (0==c) + return 0; + + comment = strchr (c, '#'); + if (comment) + *comment = 0; + + n = strlen (c); + if (0==n) + return c; + + /* Eliminate postfix whitespace */ + for (i = n - 1; (i > 0) && (isspace (c[i]) || ';'==c[i]); i--) + c[i] = 0; + + /* Find start of non-whitespace */ + while (0 != *start && (';'==*start || isspace (*start))) + start++; + + n = strlen (start); + if (0==n) { + c[0] = 0; + return c; + } + + memmove (c, start, n + 1); + return c; +} +/*****************************************************************************/ +char *pj_shrink (char *c) { +/****************************************************************************** +Collapse repeated whitespace. Remove '+' and ';'. Make ',' and '=' greedy, +consuming their surrounding whitespace. +******************************************************************************/ + size_t i, j, n; + + /* Flag showing that a whitespace (ws) has been written after last non-ws */ + size_t ws; + + if (0==c) + return 0; + + pj_chomp (c); + n = strlen (c); + + /* First collapse repeated whitespace (including +/;) */ + for (i = j = 0, ws = 0; j < n; j++) { + + /* Eliminate prefix '+', only if preceeded by whitespace */ + /* (i.e. keep it in 1.23e+08) */ + if ((i > 0) && ('+'==c[j]) && isspace (c[i])) + c[j] = ' '; + + if (isspace (c[j]) || ';'==c[j]) { + if (0==ws && (i > 0)) + c[i++] = ' '; + ws = 1; + continue; + } + else { + ws = 0; + c[i++] = c[j]; + } + } + c[i] = 0; + n = strlen(c); + + /* Then make ',' and '=' greedy */ + for (i = j = 0; j < n; j++) { + if (i==0) { + c[i++] = c[j]; + continue; + } + + /* Skip space before '='/',' */ + if ('='==c[j] || ','==c[j]) { + if (c[i - 1]==' ') + c[i - 1] = c[j]; + else + c[i++] = c[j]; + continue; + } + + if (' '==c[j] && ('='==c[i - 1] || ','==c[i - 1]) ) + continue; + + c[i++] = c[j]; + } + c[i] = 0; + return c; +} + + + +/*****************************************************************************/ +size_t pj_trim_argc (char *args) { +/****************************************************************************** +Trim all unnecessary whitespace (and non-essential syntactic tokens) from the +argument string, args, and count its number of elements. +******************************************************************************/ + size_t i, m, n; + pj_shrink (args); + n = strlen (args); + if (n==0) + return 0; + for (i = m = 0; i < n; i++) { + if (' '==args[i]) { + args[i] = 0; + m++; + } + } + return m + 1; +} + + + +/*****************************************************************************/ +char **pj_trim_argv (size_t argc, char *args) { +/****************************************************************************** +Create an argv-style array from elements placed in the argument string, args. + +args is a trimmed string as returned by pj_trim_argc(), and argc is the number +of trimmed strings found (i.e. the return value of pj_trim_args()). Hence, + int argc = pj_trim_argc (args); + char **argv = pj_trim_argv (argc, args); +will produce a classic style (argc, argv) pair from a string of whitespace +separated args. No new memory is allocated for storing the individual args +(they stay in the args string), but for the pointers to the args a new array +is allocated and returned. + +It is the duty of the caller to free this array. +******************************************************************************/ + size_t i, j; + char **argv; + + if (0==args) + return 0; + if (0==argc) + return 0; + + + /* turn the input string into an array of strings */ + argv = (char **) calloc (argc, sizeof (char *)); + if (0==argv) + return 0; + argv[0] = args; + for (i = 0, j = 1; ; i++) { + if (0==args[i]) { + argv[j++] = args + (i + 1); + } + if (j==argc) + break; + } + return argv; +} + + + +/*****************************************************************************/ +char *pj_make_args (size_t argc, char **argv) { +/****************************************************************************** +pj_make_args is the inverse of the pj_trim_argc/pj_trim_argv combo: It +converts free format command line input to something proj_create can consume. + +Allocates, and returns, an array of char, large enough to hold a whitespace +separated copy of the args in argv. It is the duty of the caller to free this +array. +******************************************************************************/ + size_t i, n; + char *p; + + for (i = n = 0; i < argc; i++) + n += strlen (argv[i]); + + p = pj_calloc (n + argc + 1, sizeof (char)); + if (0==p) + return 0; + if (0==argc) + return p; + + for (i = n = 0; i < argc; i++) { + strcat (p, argv[i]); + strcat (p, " "); + } + return pj_shrink (p); +} + + + +/*****************************************************************************/ void proj_context_errno_set (PJ_CONTEXT *ctx, int err) { +/****************************************************************************** +Raise an error directly on a context, without going through a PJ belonging +to that context. +******************************************************************************/ if (0==ctx) ctx = pj_get_default_ctx(); pj_ctx_set_errno (ctx, err); @@ -176,8 +381,20 @@ void proj_context_errno_set (PJ_CONTEXT *ctx, int err) { -/* Set logging level 0-3. Higher number means more debug info. 0 turns it off */ + + + +/* logging */ + +/* pj_vlog resides in pj_log.c and relates to pj_log as vsprintf relates to sprintf */ +void pj_vlog( projCtx ctx, int level, const char *fmt, va_list args ); + + +/***************************************************************************************/ enum proj_log_level proj_log_level (PJ_CONTEXT *ctx, enum proj_log_level log_level) { +/**************************************************************************************** + Set logging level 0-3. Higher number means more debug info. 0 turns it off +****************************************************************************************/ enum proj_log_level previous; if (0==ctx) ctx = pj_get_default_ctx(); @@ -191,35 +408,48 @@ enum proj_log_level proj_log_level (PJ_CONTEXT *ctx, enum proj_log_level log_lev } - -/* logging */ - -/* pj_vlog resides in pj_log.c and relates to pj_log as vsprintf relates to sprintf */ -void pj_vlog( projCtx ctx, int level, const char *fmt, va_list args ); - +/*****************************************************************************/ void proj_log_error (PJ *P, const char *fmt, ...) { +/****************************************************************************** + For reporting the most severe events. +******************************************************************************/ va_list args; va_start( args, fmt ); pj_vlog (pj_get_ctx (P), PJ_LOG_ERROR , fmt, args); va_end( args ); } + +/*****************************************************************************/ void proj_log_debug (PJ *P, const char *fmt, ...) { +/****************************************************************************** + For reporting debugging information. +******************************************************************************/ va_list args; va_start( args, fmt ); pj_vlog (pj_get_ctx (P), PJ_LOG_DEBUG_MAJOR , fmt, args); va_end( args ); } + +/*****************************************************************************/ void proj_log_trace (PJ *P, const char *fmt, ...) { +/****************************************************************************** + For reporting embarrasingly detailed debugging information. +******************************************************************************/ va_list args; va_start( args, fmt ); pj_vlog (pj_get_ctx (P), PJ_LOG_DEBUG_MINOR , fmt, args); va_end( args ); } -/* Put a new logging function into P's context. The opaque object app_data is passed as first arg at each call to the logger */ + +/*****************************************************************************/ void proj_log_func (PJ_CONTEXT *ctx, void *app_data, PJ_LOG_FUNCTION log) { +/****************************************************************************** + Put a new logging function into P's context. The opaque object app_data is + passed as first arg at each call to the logger +******************************************************************************/ if (0==ctx) pj_get_default_ctx (); if (0==ctx) |
