home *** CD-ROM | disk | FTP | other *** search
- Subject: strings (2 of 3)
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 4, Issue 111
- Submitted by: <talcott!wjh12!maynard!campbell>
-
- #!/bin/sh
- # shar: Shell Archiver
- # Run the following text with /bin/sh to create:
- # str2int.c
- # strcat.c
- # strchr.c
- # strcmp.c
- # strcpack.c
- # strcpbrk.c
- # strcpy.c
- # strcspn.c
- # strctrim.c
- # strend.c
- # strfield.c
- # strfind.c
- # strings.h
- # strkey.c
- # strlen.c
- # strmov.c
- # strncat.c
- # strncmp.c
- # strncpy.c
- # strnend.c
- # strnlen.c
- # strnmov.c
- # strnrev.c
- # strnrpt.c
- # strntran.c
- sed 's/^X//' << 'SHAR_EOF' > str2int.c
- X/* File : str2int.c
- X Author : Richard A. O'Keefe
- X Updated: 27 April 1984
- X Defines: str2int(), atoi(), atol()
- X
- X str2int(src, radix, lower, upper, &val)
- X converts the string pointed to by src to an integer and stores it in
- X val. It skips leading spaces and tabs (but not newlines, formfeeds,
- X backspaces), then it accepts an optional sign and a sequence of digits
- X in the specified radix. The result should satisfy lower <= *val <= upper.
- X The result is a pointer to the first character after the number;
- X trailing spaces will NOT be skipped.
- X
- X If an error is detected, the result will be NullS, the value put
- X in val will be 0, and errno will be set to
- X EDOM if there are no digits
- X ERANGE if the result would overflow or otherwise fail to lie
- X within the specified bounds.
- X Check that the bounds are right for your machine.
- X This looks amazingly complicated for what you probably thought was an
- X easy task. Coping with integer overflow and the asymmetric range of
- X twos complement machines is anything but easy.
- X
- X So that users of atoi and atol can check whether an error occured,
- X I have taken a wholly unprecedented step: errno is CLEARED if this
- X call has no problems.
- X*/
- X
- X#include "strings.h"
- X#include "ctypes.h"
- X#include <errno.h>
- Xextern int errno;
- X
- X/* CHECK THESE CONSTANTS FOR YOUR MACHINE!!! */
- X
- X#if pdp11
- X# define MaxInt 0x7fffL /* int = 16 bits */
- X# define MinInt 0x8000L
- X# define MaxLong 0x7fffffffL /* long = 32 bits */
- X# define MinLong 0x80000000L
- X#else !pdp11
- X# define MaxInt 0x7fffffffL /* int = 32 bits */
- X# define MinInt 0x80000000L
- X# define MaxLong 0x7fffffffL /* long = 32 bits */
- X# define MinLong 0x80000000L
- X#endif pdp11
- X
- X
- Xchar *str2int(src, radix, lower, upper, val)
- X register char *src;
- X register int radix;
- X long lower, upper, *val;
- X {
- X int sign; /* is number negative (+1) or positive (-1) */
- X int n; /* number of digits yet to be converted */
- X long limit; /* "largest" possible valid input */
- X long scale; /* the amount to multiply next digit by */
- X long sofar; /* the running value */
- X register int d; /* (negative of) next digit */
- X char *answer;
- X
- X /* Make sure *val is sensible in case of error */
- X
- X *val = 0;
- X
- X /* Check that the radix is in the range 2..36 */
- X
- X if (radix < 2 || radix > 36) {
- X errno = EDOM;
- X return NullS;
- X }
- X
- X /* The basic problem is: how do we handle the conversion of
- X a number without resorting to machine-specific code to
- X check for overflow? Obviously, we have to ensure that
- X no calculation can overflow. We are guaranteed that the
- X "lower" and "upper" arguments are valid machine integers.
- X On sign-and-magnitude, twos-complement, and ones-complement
- X machines all, if +|n| is representable, so is -|n|, but on
- X twos complement machines the converse is not true. So the
- X "maximum" representable number has a negative representative.
- X Limit is set to min(-|lower|,-|upper|); this is the "largest"
- X number we are concerned with. */
- X
- X /* Calculate Limit using Scale as a scratch variable */
- X
- X if ((limit = lower) > 0) limit = -limit;
- X if ((scale = upper) > 0) scale = -scale;
- X if (scale < limit) limit = scale;
- X
- X /* Skip leading spaces and check for a sign.
- X Note: because on a 2s complement machine MinLong is a valid
- X integer but |MinLong| is not, we have to keep the current
- X converted value (and the scale!) as *negative* numbers,
- X so the sign is the opposite of what you might expect.
- X Should the test in the loop be isspace(*src)?
- X */
- X while (*src == ' ' || *src == '\t') src++;
- X sign = -1;
- X if (*src == '+') src++; else
- X if (*src == '-') src++, sign = 1;
- X
- X /* Check that there is at least one digit */
- X
- X if (_c2type[1+ *src] >= radix) {
- X errno = EDOM;
- X return NullS;
- X }
- X
- X /* Skip leading zeros so that we never compute a power of radix
- X in scale that we won't have a need for. Otherwise sticking
- X enough 0s in front of a number could cause the multiplication
- X to overflow when it neededn't.
- X */
- X while (*src == '0') src++;
- X
- X /* Move over the remaining digits. We have to convert from left
- X to left in order to avoid overflow. Answer is after last digit.
- X */
- X for (n = 0; _c2type[1+ *src++] < radix; n++) ;
- X answer = --src;
- X
- X /* The invariant we want to maintain is that src is just
- X to the right of n digits, we've converted k digits to
- X sofar, scale = -radix**k, and scale < sofar < 0. Now
- X if the final number is to be within the original
- X Limit, we must have (to the left)*scale+sofar >= Limit,
- X or (to the left)*scale >= Limit-sofar, i.e. the digits
- X to the left of src must form an integer <= (Limit-sofar)/(scale).
- X In particular, this is true of the next digit. In our
- X incremental calculation of Limit,
- X
- X IT IS VITAL that (-|N|)/(-|D|) = |N|/|D|
- X */
- X
- X for (sofar = 0, scale = -1; --n >= 0; ) {
- X d = _c2type[1+ *--src];
- X if (-d < limit) {
- X errno = ERANGE;
- X return NullS;
- X }
- X limit = (limit+d)/radix, sofar += d*scale;
- X if (n != 0) scale *= radix; /* watch out for overflow!!! */
- X }
- X /* Now it might still happen that sofar = -32768 or its equivalent,
- X so we can't just multiply by the sign and check that the result
- X is in the range lower..upper. All of this caution is a right
- X pain in the neck. If only there were a standard routine which
- X says generate thus and such a signal on integer overflow...
- X But not enough machines can do it *SIGH*.
- X */
- X if (sign < 0 && sofar < -MaxLong /* twos-complement problem */
- X || (sofar*=sign) < lower || sofar > upper) {
- X errno = ERANGE;
- X return NullS;
- X }
- X *val = sofar;
- X errno = 0; /* indicate that all went well */
- X return answer;
- X }
- X
- X
- Xint atoi(src)
- X char *src;
- X {
- X long val;
- X str2int(src, 10, MinInt, MaxInt, &val);
- X return (int)val;
- X }
- X
- X
- Xlong atol(src)
- X char *src;
- X {
- X long val;
- X str2int(src, 10, MinLong, MaxLong, &val);
- X return val;
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strcat.c
- X/* File : strcat.c
- X Author : Richard A. O'Keefe.
- X Updated: 10 April 1984
- X Defines: strcat()
- X
- X strcat(s, t) concatenates t on the end of s. There had better be
- X enough room in the space s points to; strcat has no way to tell.
- X Note that strcat has to search for the end of s, so if you are doing
- X a lot of concatenating it may be better to use strmov, e.g.
- X strmov(strmov(strmov(strmov(s,a),b),c),d)
- X rather than
- X strcat(strcat(strcat(strcpy(s,a),b),c),d).
- X strcat returns the old value of s.
- X*/
- X
- X#include "strings.h"
- X
- Xchar *strcat(s, t)
- X register char *s, *t;
- X {
- X char *save;
- X
- X for (save = s; *s++; ) ;
- X for (--s; *s++ = *t++; ) ;
- X return save;
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strchr.c
- X/* File : strchr.c
- X Author : Richard A. O'Keefe.
- X Updated: 20 April 1984
- X Defines: strchr(), index()
- X
- X strchr(s, c) returns a pointer to the first place in s where c
- X occurs, or NullS if c does not occur in s. This function is called
- X index in V7 and 4.?bsd systems; while not ideal the name is clearer
- X than strchr, so index remains in strings.h as a macro. NB: strchr
- X looks for single characters, not for sets or strings. To find the
- X NUL character which closes s, use strchr(s, '\0') or strend(s). The
- X parameter 'c' is declared 'int' so it will go in a register; if your
- X C compiler is happy with register _char_ change it to that.
- X*/
- X
- X#include "strings.h"
- X
- Xchar *strchr(s, c)
- X register _char_ *s;
- X register int c;
- X {
- X for (;;) {
- X if (*s == c) return s;
- X if (!*s++) return NullS;
- X }
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strcmp.c
- X/* File : strcmp.c
- X Author : Richard A. O'Keefe.
- X Updated: 10 April 1984
- X Defines: strcmp()
- X
- X strcmp(s, t) returns > 0, = 0, or < 0 when s > t, s = t, or s < t
- X according to the ordinary lexicographical order. To test for
- X equality, the macro streql(s,t) is clearer than !strcmp(s,t). Note
- X that if the string contains characters outside the range 0..127 the
- X result is machine-dependent; PDP-11s and VAXen use signed bytes,
- X some other machines use unsigned bytes.
- X*/
- X
- X#include "strings.h"
- X
- Xint strcmp(s, t)
- X register char *s, *t;
- X {
- X while (*s == *t++) if (!*s++) return 0;
- X return s[0]-t[-1];
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strcpack.c
- X/* File : strcpack.c
- X Author : Richard A. O'Keefe.
- X Updated: 20 April 1984
- X Defines: strcpack()
- X
- X strcpack(dst, src, set, c)
- X copies characters from src to dst, stopping when it finds a NUL. If
- X c is NUL, characters not in the set are not copied to dst. If c is
- X not NUL, sequences of characters not in the set are copied as a
- X single c. strcpack is to strpack as strcspn is to strspn. If your C
- X compiler is happy with register _char_, change the declaration of c.
- X The result is the address of the NUL byte that now terminates "dst".
- X Note that dst may safely be the same as src.
- X*/
- X
- X#include "strings.h"
- X#include "_str2set.h"
- X
- Xchar *strcpack(dst, src, set, c)
- X register _char_ *dst, *src;
- X char *set;
- X register int c;
- X {
- X register int chr;
- X
- X _str2set(set);
- X while (chr = *src++) {
- X if (_set_vec[chr] != _set_ctr) {
- X while ((chr = *src++) && _set_vec[chr] != _set_ctr) ;
- X if (c) *dst++ = c; /* 1. If you don't want trailing */
- X if (!chr) break; /* 2. things turned into "c", swap */
- X } /* lines 1 and 2. */
- X *dst++ = chr;
- X }
- X *dst = 0;
- X return dst;
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strcpbrk.c
- X/* File : strcpbrk.c
- X Author : Richard A. O'Keefe.
- X Updated: 20 April 1984
- X Defines: strcpbrk()
- X
- X strcpbrk(s1, s2) returns a pointer to the first character of s1 which
- X does not occur in s2. It is to strpbrk as strcspn is to strspn. It
- X relies on NUL never being in a set.
- X*/
- X
- X#include "strings.h"
- X#include "_str2set.h"
- X
- Xchar *strcpbrk(str, set)
- X register _char_ *str;
- X char *set;
- X {
- X _str2set(set);
- X while (_set_vec[*str++] == _set_ctr);
- X return *--str ? str : NullS;
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strcpy.c
- X/* File : strcpy.c
- X Author : Richard A. O'Keefe.
- X Updated: 20 April 1984
- X Defines: strcpy()
- X
- X strcpy(dst, src) copies all the characters of src (including the
- X closing NUL) to dst, and returns the old value of dst. Maybe this
- X is useful for doing i = strlen(strcpy(dst, src)); I've always found
- X strmov handier.
- X*/
- X
- X#include "strings.h"
- X
- Xchar *strcpy(dst, src)
- X register char *dst, *src;
- X {
- X char *save;
- X
- X for (save = dst; *dst++ = *src++; ) ;
- X return save;
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strcspn.c
- X/* File : strcspn.c
- X Author : Richard A. O'Keefe.
- X Updated: 11 April 1984
- X Defines: strspn()
- X
- X strcspn(s1, s2) returns the length of the longest prefix of s1
- X consisting entirely of characters which are NOT in s2 ("c" is
- X "complement"). NUL is considered to be part of s2. As _str2set
- X will never include NUL in a set, we have to check for it explicitly.
- X*/
- X
- X#include "strings.h"
- X#include "_str2set.h"
- X
- Xint strcspn(str, set)
- X register _char_ *str;
- X char *set;
- X {
- X register int L;
- X
- X _str2set(set);
- X for (L = 0; *str && _set_vec[*str++] != _set_ctr; L++) ;
- X return L;
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strctrim.c
- X/* File : strctrim.c
- X Author : Richard A. O'Keefe.
- X Updated: 20 April 1984
- X Defines: strctrim()
- X
- X strctrim(dst, src, set, ends)
- X copies src to dst, but will skip leading characters not in set if
- X ends <= 0 and will skip trailing characters not in set if ends >= 0.
- X Thus there are three cases:
- X ends < 0 : trim a prefix
- X ends = 0 : trim a prefix and a suffix both
- X ends > 0 : trim a suffix
- X This is to strtrim as strcspn is to strspn.
- X*/
- X
- X#include "strings.h"
- X#include "_str2set.h"
- X
- Xchar *strctrim(dst, src, set, ends)
- X register char *dst, *src;
- X char *set;
- X int ends;
- X {
- X _str2set(set);
- X if (ends <= 0) {
- X register int chr;
- X while ((chr = *src++) && _set_vec[chr] != _set_ctr) ;
- X --src;
- X }
- X if (ends >= 0) {
- X register int chr;
- X register char *save = dst;
- X while (chr = *src++) {
- X *dst++ = chr;
- X if (_set_vec[chr] == _set_ctr) save = dst;
- X }
- X dst = save, *dst = NUL;
- X } else {
- X while (*dst++ = *src++) ;
- X --dst;
- X }
- X return dst;
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strend.c
- X/* File : strend.c
- X Author : Richard A. O'Keefe.
- X Updated: 23 April 1984
- X Defines: strend()
- X
- X strend(s) returns a character pointer to the NUL which ends s. That
- X is, strend(s)-s == strlen(s). This is useful for adding things at
- X the end of strings. It is redundant, because strchr(s,'\0') could
- X be used instead, but this is clearer and faster.
- X Beware: the asm version works only if strlen(s) < 65535.
- X*/
- X
- X#include "strings.h"
- X
- X#if VaxAsm
- X
- Xchar *strend(s)
- X char *s;
- X {
- X asm("locc $0,$65535,*4(ap)");
- X asm("movl r1,r0");
- X }
- X
- X#else ~VaxAsm
- X
- Xchar *strend(s)
- X register char *s;
- X {
- X while (*s++);
- X return s-1;
- X }
- X
- X#endif VaxAsm
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strfield.c
- X/* File : strfield.c
- X Author : Richard A. O'Keefe.
- X Updated: 21 April 1984
- X Defines: strfield()
- X
- X strfield(src, fields, chars, blanks, tabch)
- X is based on the key specifications of the sort(1) command.
- X
- X tabch corresponds to 'x' in -t'x'. If it is NUL, a field
- X is leading layout (spaces, tabs &c) followed by at least
- X one non-layout character, and is terminated by the next
- X layout character or NUL. If it is not NUL, a field is
- X terminated by tabch or NUL.
- X
- X fields is the number of fields to skip over. It corresponds
- X to m in -m.n or +m.n . There must be at least this many
- X fields, and only the last may be terminated by NUL.
- X
- X chars is the number of characters to skip after the fields
- X have been skipped. At least this many non-NUL characters
- X must remain after the fields have been skipped. Note that
- X it is entirely possible for this skip to cross one or more
- X field boundaries. This corresponds to n in +m.n or -m.n .
- X
- X Finally, if blanks is not 0, any layout characters will be
- X skipped. There need not be any. This corresponds to the
- X letter b in +2.0b or -0.4b .
- X
- X The result is NullS if the source ran out of fields or ran
- X out of chars. Otherwise it is a pointer to the first
- X character of src which was not skipped. It is quite possible
- X for this character to be the terminating NUL.
- X
- X Example:
- X to skip to the user-id field of /etc/passwd:
- X user_id = strfield(line, 2, 0, 0, ':');
- X
- X to check whether "line" is at least 27 characters long:
- X if (strfield(line, 0, 27, 0, 0)) then-it-is;
- X
- X to select the third blank-delimited field in a line:
- X head = strfield(line, 2, 0, 1, 0);
- X tail = strfield(head, 1, 0, 0, 0);
- X (* the field is the tail-head characters starting at head *)
- X
- X It's not a bug, it's a feature: "layout" means any ASCII character
- X in the range '\1' .. ' ', including '\n', '\f' and so on.
- X*/
- X
- X#include "strings.h"
- X
- Xchar *strfield(src, fields, chars, blanks, tabch)
- X register char *src;
- X int fields, chars, blanks, tabch;
- X {
- X if (tabch <= 0) {
- X while (--fields >= 0) {
- X while (*src <= ' ') if (!*src++) return NullS;
- X while (*++src > ' ') ;
- X }
- X } else
- X if (fields > 0) {
- X do if (!*src) return NullS;
- X while (*src++ != tabch || --fields > 0);
- X }
- X while (--chars >= 0) if (!*src++) return NullS;
- X if (blanks) while (*src && *src++ <= ' ') ;
- X return src;
- X }
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strfind.c
- X/* File : strfind.c
- X Author : Richard A. O'Keefe.
- X Updated: 23 April 1984
- X Defines: strfind()
- X
- X strfind(src, pat) looks for an instance of pat in src. pat is not a
- X regex(3) pattern, it is a literal string which must be matched exactly.
- X As a special hack to prevent infinite loops, the empty string will be
- X found just once, at the far end of src. This is hard to justify. The
- X result is a pointer to the first character AFTER the located instance,
- X or NullS if pat does not occur in src. The reason for returning the
- X place after the instance is so that you can count the number of instances
- X by writing
- X _str2pat(ToBeFound);
- X for (p = src, n = 0; p = strfind(p, NullS); n++) ;
- X If you want a pointer to the first character of the instance, it is up
- X to you to subtract strlen(pat).
- X
- X If there were a strnfind it wouldn't have to look at all the characters
- X of src, this version does otherwise it could miss the closing NUL.
- X*/
- X
- X#include "strings.h"
- X#include "_str2pat.h"
- X
- Xchar *strfind(src, pat)
- X char *src, *pat;
- X {
- X register char *s, *p;
- X register int c, lastch;
- X
- X pat = _str2pat(pat);
- X if (_pat_lim < 0) {
- X for (s = src; *s++; ) ;
- X return s-1;
- X }
- X /* The pattern is non-empty */
- X for (c = _pat_lim, lastch = pat[c]; ; c = _pat_vec[c]) {
- X for (s = src; --c >= 0; )
- X if (!*s++) return NullS;
- X c = *s, src = s;
- X if (c == lastch) {
- X for (s -= _pat_lim, p = pat; *p; )
- X if (*s++ != *p++) goto not_yet;
- X return s;
- Xnot_yet:; }
- X }
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strings.h
- X/* File : strings.h
- X Author : Richard A. O'Keefe.
- X Updated: 1 June 1984
- X Purpose: Header file for the "string(3C)" package.
- X
- X All the routines in this package are the original work of
- X R.A.O'Keefe. Any resemblance between them and any routines in
- X licensed software is due entirely to these routines having been
- X written using the "man 3 string" UNIX manual page, or in some cases
- X the "man 1 sort" manual page as a specification. See the READ-ME to
- X find the conditions under which these routines may be used & copied.
- X*/
- X
- X#ifndef NullS
- X#define NullS (char*)0
- X#define NUL '\0'
- X
- X/* MAKE SURE THE RIGHT VERSION OF THE FOLLOWING MACRO IS INSTALLED! */
- X
- X#if vax | pdp11 | m68000 | perq
- X#define CharsAreSigned 1 /* default is unsigned */
- X#endif vax | pdp11 | m68000 | perq
- X
- X#if CharsAreSigned
- X#define int2char(i) (((i)<<((sizeof (int) -1)*8))>>((sizeof (int) -1)*8))
- X#else !CharsAreSigned
- X#define int2char(i) ((i)&255)
- X#endif CharsAreSigned
- X/* If characters are signed, but the above doesn't work,
- X try ((127-(255&~(i)))^(-128))
- X*/
- X
- X#ifndef _AlphabetSize
- X#define _AlphabetSize 128
- X#endif
- X
- X#if _AlphabetSize == 128
- Xtypedef char _char_;
- X#endif
- X#if _AlphabetSize == 256
- Xtypedef unsigned char _char_;
- X#endif
- X
- X/* NullS is the "nil" character pointer. NULL would work in most
- X cases, but in some C compilers pointers and integers may be of
- X different sizes, so it is handy to have a nil pointer that one can
- X pass to a function as well as compare pointers against.
- X
- X NUL is the ASCII name for the character with code 0. Its use to end
- X strings is a convention of the C programming language. There are in
- X fact three different end of string conventions supported by routines
- X in this package:
- X str<opn> : end at the first NUL character
- X strn<opn> : end at the first NUL character, or when the
- X extra "len" parameter runs out.
- X mem<opn>,b<opn> : length determined solely by "len" parameter.
- X Unfortunately, the VAX hardware only supports the last convention, a
- X pity really. Fortran 77 users BEWARE: Fortran 77's convention is an
- X entirely different one, and there are NO routines in this package as
- X yet which support it. (But see section 3F of the 4.2 BSD manual.)
- X
- X The routines which move characters around don't care whether they
- X are signed or unsigned. But the routines which compare a character
- X in a string with an argument, or use a character from a string as an
- X index into an array, do care. I have assumed that
- X _AlphabetSize = 128 => only 0..127 appear in strings
- X _AlphabetSize = 256 => only 0..255 appear in strings
- X The files _str2set.c and _str2map.c declare character vectors using
- X this size. If you don't have unsigned char, your machine may treat
- X char as unsigned anyway.
- X
- X Some string operations (*cmp, *chr) are explicitly defined in various
- X UNIX manuals to use "native" comparison, so I have not used _char_ in
- X them. This package is meant to be compatible, not rational!
- X*/
- X
- Xextern char *strcat(/*char^,char^*/);
- Xextern char *strncat(/*char^,char^,int*/);
- X
- Xextern int strcmp(/*char^,char^*/);
- Xextern int strncmp(/*char^,char^,int*/);
- X
- X#define streql !strcmp
- X#define strneql !strncmp /* (str-N)-eql not str-(neq-l)! */
- X
- Xextern char *strcpy(/*char^,char^*/);
- Xextern char *strncpy(/*char^,char^,int*/);
- X
- Xextern int strlen(/*char^*/);
- Xextern int strnlen(/*char^,int*/);
- X
- Xextern char *strchr(/*char^,_char_*/);
- Xextern char *strrchr(/*char^,_char_*/);
- X#define index strchr
- X#define rindex strrchr
- X
- Xextern char *strmov(/*char^,char^*/);
- Xextern char *strnmov(/*char^,char^,int*/);
- X
- Xextern void strrev(/*char^,char^*/);
- Xextern void strnrev(/*char^,char^,int*/);
- X
- Xextern char *strend(/*char^*/);
- Xextern char *strnend(/*char^*/);
- X
- Xextern char *strpbrk(/*char^,char^*/);
- Xextern char *strcpbrk(/*char^,char^*/);
- X
- Xextern int strspn(/*char^,char^*/);
- Xextern int strcspn(/*char^,char^*/);
- X
- Xextern char *strtok(/*char^,char^*/);
- Xextern void istrtok(/*char^,char^*/);
- X
- Xextern char *strpack(/*_char_^,_char_^,char^,int*/);
- Xextern char *strcpack(/*_char_^,_char_^,char^,int*/);
- X
- Xextern int strrpt(/*char^,char^,int*/);
- Xextern int strnrpt(/*char^,int,char^,int*/);
- X
- Xextern void strtrans(/*_char_^,_char_^,_char_^,_char_^*/);
- Xextern void strntrans(/*_char_^,_char_^,int,_char_^,_char_^*/);
- X
- Xextern char *strtrim(/*char^,char^,char^,int*/);
- Xextern char *strctrim(/*char^,char^,char^,int*/);
- X
- Xextern char *strfield(/*char^,int,int,int,int*/);
- Xextern char *strkey(/*char^,char^,char^,char^*/);
- X
- Xextern char *strfind(/*char^,char^*/);
- Xextern char *strrepl(/*char^,char^,char^,char^*/);
- X
- Xextern void bcopy(/*char^,char^,int*/);
- Xextern void bmove(/*char^,char^,int*/);
- X
- Xextern void bfill(/*char^,int,char*/);
- Xextern void bzero(/*char^,int*/);
- X
- Xextern int bcmp(/*char^,char^,int*/);
- X#define beql !bcmp
- X
- Xextern int ffs(/*int*/);
- Xextern int ffc(/*int*/);
- X
- Xextern char *substr(/*char^,char^,int,int*/);
- X
- Xextern char *strxcat(/*VARARGS*/);
- Xextern char *strxcpy(/*VARARGS*/);
- Xextern char *strxmov(/*VARARGS*/);
- X
- Xextern char *strxncat(/*VARARGS*/);
- Xextern char *strxncpy(/*VARARGS*/);
- Xextern char *strxnmov(/*VARARGS*/);
- X
- X#endif NullS
- X
- X#ifndef memeql
- X#include "memory.h"
- X#endif memeql
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strkey.c
- X/* File : strkey.c
- X Author : Richard A. O'Keefe.
- X Updated: 20 April 1984
- X Defines: strkey()
- X
- X strkey(dst, head, tail, options)
- X copies tail-head characters from head to dst according to the
- X options. If tail is NullS, it copies up to the terminating
- X NUL of head. This function is meant for doing comparisons as
- X by sort(1). The options are thus a string of characters
- X taken from "bdfin". In case the options came from somewhere
- X else other letters are ignored.
- X
- X -b: leading layout characters are not copied.
- X
- X -d: only letters, digits, and blanks are copied.
- X -i: only graphic characters (32..126) are copied.
- X -n: a numeric string is copied.
- X These options are incompatible, and the last is taken.
- X
- X -f: upper case letters are copied as lower case.
- X
- X The question of what to do with a numeric string is an interesting
- X one, and I don't claim that this is a brilliant answer. However,
- X the solution used here does mean that the caller can compare two
- X strings as strings without needing to know that they are numeric. A
- X number is copied as <sign><9 digits>.<remaining digits>, where
- X <sign> is '-' for a negative number and '0' for a positive number.
- X The magic number 9 is defined to be DigitMagic.
- X
- X The idea is that to compare two lines using the keys
- X -tx +m1.n1<flags> -m2.n2
- X you do
- X h1 = strfield(line1, m1, n1, 0, 'x');
- X t1 = strfield(h1, 1, 0, 0, 'x');
- X strkey(buff1, h1, t1, "flags");
- X h2 = strfield(line2, m2, n2, 0, 'x');
- X t2 = strfield(h2, 1, 0, 0, 'x');
- X strkey(buff2, h2, t2, "flags");
- X ... strcmp(buff1, buff2) ...
- X
- X The point of all this, of course, is to make it easier to write new
- X utilities which are compatible with sort(1) than ones which are not.
- X*/
- X
- X#include "strings.h"
- X
- X#define DigitMagic 9
- X
- Xchar *strkey(dst, head, tail, flags)
- X register char *dst, *head, *tail;
- X char *flags;
- X {
- X register int c;
- X int b = 0; /* b option? */
- X int f = 0; /* f option? */
- X int k = 0; /* 3->n, 2->d, 1->i, 0->none of them */
- X
- X while (*flags) switch (*flags++|32) {
- X case 'b': b++; break;
- X case 'f': f++; break;
- X case 'i': k = 1; break;
- X case 'd': k = 2; break;
- X case 'n': k = 3; break;
- X default : /*ignore*/break;
- X }
- X flags = dst; /* save return value */
- X
- X if (tail == NullS) for (tail = head; *tail; tail++) ;
- X
- X if (b) while (head != tail && *head <= ' ') head++;
- X
- X switch (k) {
- X case 0:
- X if (f) {
- X while (head != tail) {
- X c = *head++;
- X if (c >= 'A' && c <= 'Z') c |= 32;
- X *dst++ = c;
- X }
- X } else {
- X while (head != tail) *dst++ = *head++;
- X }
- X break;
- X case 1:
- X if (f) {
- X while (head != tail) {
- X c = *head++;
- X if (c >= 32 && c <= 126) {
- X if (c >= 'A' && c <= 'Z') c |= 32;
- X *dst++ = c;
- X }
- X }
- X } else {
- X while (head != tail) {
- X c = *head++;
- X if (c >= 32 && c <= 126) *dst++ = c;
- X }
- X }
- X break;
- X case 2:
- X if (f) f = 32;
- X while (head != tail) {
- X c = *head++;
- X if (c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c == ' ') {
- X *dst++ = c;
- X } else
- X if (c >= 'A' && c <= 'Z') {
- X *dst++ = c|f;
- X }
- X }
- X break;
- X case 3:
- X if (*head == '-' && head != tail) {
- X *dst++ = *head++;
- X head++;
- X } else {
- X *dst++ = '0';
- X }
- X b = 0;
- X while (head != tail) {
- X c = *head;
- X if (c < '0' || c > '9') break;
- X b++, head++;
- X }
- X f = DigitMagic-b;
- X while (--f >= 0) *dst++ = '0';
- X head -= b;
- X while (--b >= 0) *dst++ = *head++;
- X if (*head == '.' && head != tail) {
- X *dst++ = *head++;
- X while (head != tail) {
- X c = *head++;
- X if (c < '0' || c > '9') break;
- X *dst++ = c;
- X }
- X /* now remove trailing 0s and possibly the '.' as well */
- X while (*--dst == '0') ;
- X if (*dst != '.') dst++;
- X }
- X break;
- X }
- X *dst = NUL;
- X return flags; /* saved initial value of dst */
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strlen.c
- X/* File : strlen.c
- X Author : Richard A. O'Keefe.
- X Updated: 23 April 1984
- X Defines: strlen()
- X
- X strlen(s) returns the number of characters in s, that is, the number
- X of non-NUL characters found before the closing NULEosCh. Note: some
- X non-standard C compilers for 32-bit machines take int to be 16 bits,
- X either put up with short strings or change int to long throughout
- X this package. Better yet, BOYCOTT such shoddy compilers.
- X Beware: the asm version works only if strlen(s) < 65536.
- X*/
- X
- X#include "strings.h"
- X
- X#if VaxAsm
- X
- Xint strlen(s)
- X char *s;
- X {
- X asm("locc $0,$65535,*4(ap)");
- X asm("subl3 r0,$65535,r0");
- X }
- X
- X#else ~VaxAsm
- X
- Xint strlen(s)
- X register char *s;
- X {
- X register int L;
- X
- X for (L = 0; *s++; L++) ;
- X return L;
- X }
- X
- X#endif VaxAsm
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strmov.c
- X/* File : strmov.c
- X Author : Richard A. O'Keefe.
- X Updated: 20 April 1984
- X Defines: strmov()
- X
- X strmov(dst, src) moves all the characters of src (including the
- X closing NUL) to dst, and returns a pointer to the new closing NUL in
- X dst. The similar UNIX routine strcpy returns the old value of dst,
- X which I have never found useful. strmov(strmov(dst,a),b) moves a//b
- X into dst, which seems useful.
- X*/
- X
- X#include "strings.h"
- X
- Xchar *strmov(dst, src)
- X register char *dst, *src;
- X {
- X while (*dst++ = *src++) ;
- X return dst-1;
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strncat.c
- X/* File : strncat.c
- X Author : Richard A. O'Keefe.
- X Updated: 20 April 1984
- X Defines: strncat()
- X
- X strncat(dst, src, n) copies up to n characters of src to the end of
- X dst. As with strcat, it has to search for the end of dst. Even if
- X it abandons src early because n runs out it will still close dst
- X with a NUL. See also strnmov.
- X*/
- X
- X#include "strings.h"
- X
- Xchar *strncat(dst, src, n)
- X register char *dst, *src;
- X register int n;
- X {
- X char *save;
- X
- X for (save = dst; *dst++; ) ;
- X for (--dst; --n >= 0; )
- X if (!(*dst++ = *src++)) return save;
- X *dst = NUL;
- X return save;
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strncmp.c
- X/* File : strncmp.c
- X Author : Richard A. O'Keefe.
- X Updated: 10 April 1984
- X Defines: strncmp()
- X
- X strncmp(s, t, n) compares the first n characters of s and t.
- X If they are the same in the first n characters it returns 0,
- X otherwise it returns the same value as strcmp(s, t) would.
- X*/
- X
- X#include "strings.h"
- X
- Xint strncmp(s, t, n)
- X register char *s, *t;
- X register int n;
- X {
- X while (--n >= 0) {
- X if (*s != *t++) return s[0]-t[-1];
- X if (!*s++) return 0;
- X }
- X return 0;
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strncpy.c
- X/* File : strncpy.c
- X Author : Richard A. O'Keefe.
- X Updated: 20 April 1984
- X Defines: strncpy()
- X
- X strncpy(dst, src, n) copies up to n characters of src to dst. It
- X will pad dst on the right with NUL or truncate it as necessary to
- X ensure that n characters exactly are transferred. It returns the
- X old value of dst as strcpy does.
- X*/
- X
- X#include "strings.h"
- X
- Xchar *strncpy(dst, src, n)
- X register char *dst, *src;
- X register int n;
- X {
- X char *save;
- X
- X for (save = dst; --n >= 0; ) {
- X if (!(*dst++ = *src++)) {
- X while (--n >= 0) *dst++ = NUL;
- X return save;
- X }
- X }
- X return save;
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strnend.c
- X/* File : strnend.c
- X Author : Richard A. O'Keefe.
- X Updated: 1 June 1984
- X Defines: strnend()
- X
- X strnend(src, len)
- X returns a pointer to just after the end of the string src, which is
- X terminated by a NUL character, or by exhaustion of the length bound
- X len. That is, strnend(s,L)-s = strnlen(s,L). s+strnlen(s,L) could
- X of course be used instead, but this is sometimes clearer.
- X Beware: the asm version works only if 0 <= len < 65535.
- X*/
- X
- X#include "strings.h"
- X
- X#if VaxAsm
- X
- Xchar *strnend(src, len)
- X char *src;
- X int len;
- X {
- X asm("locc $0,8(ap),*4(ap)");
- X asm("movl r1,r0");
- X }
- X
- X#else ~VaxAsm
- X
- Xchar *strnend(src, len)
- X register char *src;
- X register int len;
- X {
- X while (--len >= 0 && *src) src++;
- X return src;
- X }
- X
- X#endif VaxAsm
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strnlen.c
- X/* File : strnlen.c
- X Author : Richard A. O'Keefe.
- X Updated: 10 April 1984
- X Defines: strnlen()
- X
- X strnlen(src, len)
- X returns the number of characters up to the first NUL in src, or len,
- X whichever is smaller. This is the same as strnend(src,len)-src.
- X
- X Beware: the VaxAsm version only works for 0 <= len < 65535.
- X*/
- X
- X#include "strings.h"
- X
- X#if VaxAsm
- X
- Xint strnlen(src, len)
- X char *src;
- X int len;
- X {
- X asm("locc $0,8(ap),*4(ap)");
- X asm("subl3 4(ap),r1,r0");
- X }
- X
- X#else ~VaxAsm
- X
- Xint strnlen(s, n)
- X register char *s;
- X register int n;
- X {
- X register int L;
- X
- X for (L = 0; --n >= 0 && *s++; L++) ;
- X return L;
- X }
- X
- X#endif VaxAsm
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strnmov.c
- X/* File : strnmov.c
- X Author : Richard A. O'Keefe.
- X Updated: 20 April 1984
- X Defines: strnmov()
- X
- X strnmov(dst, src, n) moves up to n characters of src to dst. It
- X always moves exactly n characters to dst; if src is shorter than n
- X characters dst will be extended on the right with NULs, while if src
- X is longer than n characters dst will be a truncated version of src
- X and will not have a closing NUL. The result is a pointer to the
- X first NUL in dst, or is dst+n if dst was truncated.
- X*/
- X
- X#include "strings.h"
- X
- Xchar *strnmov(dst, src, n)
- X register char *dst, *src;
- X register int n;
- X {
- X while (--n >= 0) {
- X if (!(*dst++ = *src++)) {
- X src = dst-1;
- X while (--n >= 0) *dst++ = NUL;
- X return src;
- X }
- X }
- X return dst;
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strnrev.c
- X/* File : strnrev.c
- X Author : Richard A. O'Keefe.
- X Updated: 1 June 1984
- X Defines: strnrev()
- X
- X strnrev(dst, src, len)
- X copies all the characters of src to dst, in REVERSE order. If src
- X was terminated by a NUL character, so will dst be, otherwise dst &
- X src are both exactly len non-NUL characters long. This returns no
- X result. It is to strrev as strncpy is to strcpy.
- X
- X Note: this function is perfectly happy to reverse a string into the
- X same place, strnrev(x, x, L) will work.
- X It will not work for partially overlapping source and destination.
- X*/
- X
- X#include "strings.h"
- X
- Xvoid strnrev(dsta, srca, len)
- X register char *dsta, *srca;
- X register int len;
- X {
- X register char *dstz, *srcz;
- X register int t;
- X /* On a machine which doesn't supply 6 register variables,
- X you could #define t len, as the two variables don't overlap.
- X */
- X
- X for (srcz = srca; --len >= 0 && *srcz; srcz++) ;
- X dstz = dsta+(srcz-srca);
- X /* If srcz was stopped by len running out, it points just after
- X the last character of the source string, and it and dstz are
- X just right. Otherwise, it was stopped by hitting NUL, and is
- X in the right place, but dstz should get a NUL as well.
- X */
- X if (len >= 0) *dstz = NUL;
- X /* That was the very last use of len */
- X while (srcz > srca) {
- X t = *--srcz;
- X *--dstz = *srca++;
- X *dsta++ = t;
- X }
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strnrpt.c
- X/* File : strnrpt.c
- X Author : Richard A. O'Keefe.
- X Updated: 20 April 1984
- X Defines: strnrpt()
- X
- X strnrpt(dst, n, src, k) "RePeaTs" the string src into dst k times,
- X but will truncate the result at n characters if necessary. E.g.
- X strnrpt(dst, 7, "hack ", 2) will move "hack ha" to dst WITHOUT the
- X closing NUL. The result is the number of characters moved, not
- X counting the closing NUL. Equivalent to strrpt-ing into an infinite
- X buffer and then strnmov-ing the result.
- X*/
- X
- X#include "strings.h"
- X
- Xint strnrpt(dst, n, src, k)
- X register char *dst;
- X register int n;
- X char *src;
- X int k;
- X {
- X char *save;
- X
- X for (save = dst; --k >= 0; dst--) {
- X register char *p;
- X for (p = src; ; ) {
- X if (--n < 0) return dst-save;
- X if (!(*dst++ = *p++)) break;
- X }
- X }
- X return dst-save;
- X }
- X
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > strntran.c
- X/* File : strntrans.c
- X Author : Richard A. O'Keefe.
- X Updated: 2 June 1984
- X Defines: strntrans()
- X
- X strntrans(dst, src, len, from, to)
- X Moves characters from src to dst, translating characters in from[]
- X to the corresponding characters in to[], until either len characters
- X have been moved or a NUL has been moved. If fewer than len characters
- X are moved, the remainder of dst will be filled with NULs, much like
- X strncpy and family. No value is returned.
- X
- X Apology: in the previous distribution of this package, strntrans was
- X defined the way memtrans is now defined. This is more consistent with
- X the general naming conventions.
- X*/
- X
- X#include "strings.h"
- X#include "_str2map.h"
- X
- X#if VaxAsm
- X
- Xvoid strntrans(dst, src, len, from, to)
- X _char_ *dst, *src, *from, *to;
- X int len;
- X {
- X _str2map(0, from, to);
- X asm("movtuc 20(ap),*8(ap),$0,__map_vec,20(ap),*4(ap)");
- X /* now pad the destination out with NUL characters */
- X asm("movc5 $0,*8(ap),$0,r4,(r5)");
- X }
- X
- X#else ~VaxAsm
- X
- Xvoid strntrans(dst, src, len, from, to)
- X register _char_ *dst, *src;
- X register int len;
- X _char_ *from, *to;
- X {
- X _str2map(0, from, to);
- X while (--len >= 0 && (*dst++ = _map_vec[*src++])) ;
- X while (--len >= 0) *dst++ = NUL;
- X }
- X
- X#endif VaxAsm
- X
- SHAR_EOF
- exit
-
-
-