diff options
author | Chris Hall <chris.hall@highwayman.com> | 2011-02-13 22:53:14 +0000 |
---|---|---|
committer | Chris Hall <chris.hall@highwayman.com> | 2011-02-13 22:53:14 +0000 |
commit | 64be6d766a65dc0749d17f5023d714678e9c96a6 (patch) | |
tree | f97e04068600d0851687b58d25ff198d1eb6cc73 /lib/elstring.c | |
parent | 8443ca08672e0cf5b779f59db9d556dadf763de7 (diff) | |
download | quagga-ex10p.tar.bz2 quagga-ex10p.tar.xz |
Initial commit to seed the "pipework" branchex10p
This is a major revision of the command processing, in order to support
new lexical level for command lines, plus all the necessary I/O
redirection for the pipes.
This is version 0.99.15ex10p.
This supports:
< filename
<+ filename
.... > filename
.... >> filename
.... >*
Also contains all lexical level handling of '...', "...." and \x in order
to allow use of '>' et al if required.
Updated command line completion and help is a work in progress.
Diffstat (limited to 'lib/elstring.c')
-rw-r--r-- | lib/elstring.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/lib/elstring.c b/lib/elstring.c new file mode 100644 index 00000000..41fc88ed --- /dev/null +++ b/lib/elstring.c @@ -0,0 +1,269 @@ +/* Length/String string handling + * Copyright (C) 2009 Chris Hall (GMCH), Highwayman + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <ctype.h> + +#include "elstring.h" +#include "memory.h" + +/*============================================================================== + * Create and free + */ + +/*------------------------------------------------------------------------------ + * Create a new elstring + */ +extern elstring +els_new(void) +{ + return XCALLOC(MTYPE_TMP, sizeof(elstring_t)) ; + + confirm(ELSTRING_INIT_ALL_ZEROS) ; +} ; + +/*------------------------------------------------------------------------------ + * Initialise or create a new elstring + */ +extern elstring +els_init_new(elstring els) +{ + if (els == NULL) + els = els_new() ; + else + memset(els, 0, sizeof(elstring_t)) ; + + confirm(ELSTRING_INIT_ALL_ZEROS) ; + + return els ; +} ; + +/*------------------------------------------------------------------------------ + * Release dynamically allocated elstring. + * + * Returns NULL. + * + * NB: it is the callers responsibility to free the contents of the elstring. + * if that is required, before freeing the elstring itself. + */ +extern elstring +els_free(elstring els) +{ + if (els != NULL) + XFREE(MTYPE_TMP, els) ; + + return NULL ; +} ; + +/*============================================================================== + * Various comparisons + */ + +/*------------------------------------------------------------------------------ + * Compare two elstrings -- returns the usual -ve, 0, +ve cmp result. + * + * NULL elstring is treated as empty. + */ +extern int +els_cmp(elstring a, elstring b) +{ + const uchar* ap ; + const uchar* bp ; + ulen al, bl ; + ulen n ; + + ap = els_body(a) ; /* NULL if a is NULL */ + bp = els_body(b) ; + al = els_len(a) ; /* zero if a is NULL */ + bl = els_len(b) ; + + n = (al <= bl) ? al : bl ; /* min(al, bl) */ + + while (n) + { + int d = *ap++ - *bp++ ; + if (d != 0) + return d ; + --n ; + } ; + + return al < bl ? -1 : (al == bl) ? 0 : +1 ; +} ; + +/*------------------------------------------------------------------------------ + * Compare elstring against word. + * + * Returns: -1 => elstring and word match to end of elstring + * 0 => elstring and word match completely + * +1 => elstring and word do not match + * + * NULLs are treated as empty strings. + * + * An empty elstring will completely match an empty word. + * An empty elstring will partly match any non-empty word. + */ +extern int +els_cmp_word(elstring a, const char* w) +{ + const uchar* ap, * ep ; + ulen al, wl ; + + al = els_len(a) ; /* zero if a is NULL */ + wl = (w != NULL) ? strlen(w) : 0 ; /* zero if w is NULL */ + + if (al > wl) + return +1 ; /* no match if longer */ + + if (al == 0) + return (wl == 0) ? 0 : -1 ; /* exact or partial if empty */ + + ap = els_body_nn(a) ; + + /* Neither string is empty */ + + if (*ap != *w) + return +1 ; /* quick out if no match for 1st char */ + + ep = ap + al - 1 ; + while (ap < ep) + { + if (*++ap != *++w) + return 1 ; + } ; + + return al == wl ? 0 : -1 ; /* full or partial match */ +} ; + +/*------------------------------------------------------------------------------ + * Compare significant parts of two qstrings -- returns the usual -ve, 0, +ve + * cmp result. + * + * By significant, mean excluding leading/trailing isspace() and treating + * multiple isspace() as single isspace(). + * + * Compares the 'len' portions of the strings. + * + * NULL elstring is treated as empty. + */ +extern int +els_cmp_sig(elstring a, elstring b) +{ + cpp_t ap ; + cpp_t bp ; + + /* Set up pointers and dispense with leading and trailing isspace() + * + * Dummy up if NULL + */ + els_cpp(ap, a) ; /* NULL if a is NULL */ + + while ((ap->p < ap->e) && isspace(*ap->p)) + ++ap->p ; + while ((ap->p < ap->e) && isspace(*(ap->e - 1))) + --ap->e ; + + els_cpp(bp, b) ; + + while ((bp->p < bp->e) && isspace(*bp->p)) + ++bp->p ; + while ((bp->p < bp->e) && isspace(*(bp->e - 1))) + --bp->e ; + + /* Now set about finding the first difference */ + while ((ap->p != ap->e) && (bp->p != bp->e)) + { + if (isspace(*ap->p) && isspace(*bp->p)) + { + do { ++ap->p ; } while (isspace(*ap->p)) ; + do { ++bp->p ; } while (isspace(*bp->p)) ; + } ; + + if (*ap->p != *bp->p) + return (*ap->p < *bp->p) ? -1 : +1 ; + + ++ap->p ; + ++bp->p ; + } ; + + /* No difference before ran out of one or both */ + if (ap->p != ap->e) + return +1 ; + else if (bp->p != bp->e) + return -1 ; + else + return 0 ; +} ; + +/*------------------------------------------------------------------------------ + * Are two elstrings equal ? -- returns true if strings equal. + */ +extern bool +els_equal(elstring a, elstring b) +{ + const uchar* ap ; + const uchar* bp ; + ulen n ; + + n = els_len(b) ; /* zero if b is NULL */ + if (n != els_len(a)) + return false ; + + ap = els_body(a) ; /* NULL if a is NULL */ + bp = els_body(b) ; + + while (n) + { + if (*ap++ != *bp++) + return false ; + --n ; + } ; + + return true ; +} ; + +/*------------------------------------------------------------------------------ + * Is 'b' a leading substring of 'a' ? -- returns true if it is. + * + * If 'b' is empty it is always a leading substring. + */ +extern bool +els_substring(elstring a, elstring b) +{ + const uchar* ap ; + const uchar* bp ; + ulen n ; + + n = els_len(b) ; /* zero if b is NULL */ + if (n > els_len(a)) + return false ; + + ap = els_body(a) ; + bp = els_body(b) ; + + while (n) + { + if (*ap++ != *bp++) + return false ; + --n ; + } ; + + return true ; +} ; + |