hansen@pegasus.UUCP (05/24/84)
A year ago, I posted the following functions to the net. They are a set of functions that are similar to strcat and strcpy, except that they accept a variable number of string arguments. The reason that I am reposting them is that, recently, I found out that my use of <varargs.h> may not have been completely portable! It seems that there may be certain architectures or implementations of C that do not allow one to declare a varargs program as: #include <varargs.h> foo (format, va_alist) char *format; va_dcl { Instead, one must declare them as: #include <varargs.h> foo (va_alist) va_dcl { and then pick ALL of the arguments off of the stack, as in: va_list argptr; char *format; va_start(argptr); format = va_arg(argptr, char *); Note that I have NOT actually SEEN any computer with this problem, but it seems to me that I've heard of certain implementations where pointers and integers are actually placed on different stacks rather than intermixed on the same stack. The documentation for varargs in 4.xBSD and System V Release 2 have an example similar to the second one above. However, I have seen many programs that implemented an error() function with the first couple of arguments defined, as I did in my first set of xstring functions. The sample implementation of error() to be found on the vprintf(3S) manual page in Sys Vr2 does NOT declare any additional arguments, but picks them off. Anyways, I thought you should all get the latest version of xstring.3 with its new and improved portability. If anyone knows more about the purposed problems, please keep the discussion only to net.unix-wizards and not to net.sources. Sincerely, Tony Hansen pegasus!hansen ---------------- cut here ---------------- echo x - xstring.3c sed 's/^X//' > xstring.3c << '~FUNKY STUFF~' X.TH XSTRING 3C X.SH NAME Xstrxcat, strxncat, strxcpy, strxncpy \- string operations with variable number of arguments X.SH SYNOPSIS X.nf X.P X.B "char \(**strxcat (dest, s1, s2, ..., (char \(**) 0)" X.B "char \(**dest, \(**s1, \(**s2, ...;" X.P X.B "char \(**strxncat (dest, n, s1, s2, ..., (char \(**) 0)" X.B "char \(**dest, \(**s1, \(**s2, ...;" X.B "int n;" X.P X.B "char \(**strxcpy (dest, s1, s2, ..., (char \(**) 0)" X.B "char \(**dest, \(**s1, \(**s2, ...;" X.P X.B "char \(**strxncpy (dest, n, s1, s2, ..., (char \(**) 0)" X.B "char \(**dest, \(**s1, \(**s2, ...;" X.B "int n;" X.SH DESCRIPTION XThese functions operate on null-terminated strings. XThey are equivalent to the corresponding functions X.IR strcat (3c), X.IR strncat (3c), X.IR strcpy (3c), Xand X.IR strncpy (3c), Xexcept that they allow more than one source string to be named. XAll routines return a pointer to their destination. XThey do not check for overflow of any receiving string. X.P X.I Strxcat\^ Xappends a copy of the strings X.IR s1 , X.IR s2 , Xand so on, to X.IR dest . X.I Strxncat\^ Xcopies at most X.I n\^ Xcharacters. XThe resulting string will always be null-terminated. X.P X.I Strxcpy\^ Xcopies the strings X.IR s1 , X.IR s2 , Xand so on, into X.IR dest . X.I Strxncpy\^ Xcopies at most X.I n\^ Xcharacters. XThe resulting string will not be null-terminated if X.I n\^ Xor more characters were in the source strings. X.SH CAVEATS XThe placement for the X.I n\^ Xvariable is different from the placement in the functions X.IR strncat (3c) Xand X.IR strncpy (3c). ~FUNKY STUFF~ echo x - makefile sed 's/^X//' > makefile << '~FUNKY STUFF~' XSRC= strxcat.c strxcpy.c strxncat.c strxncpy.c XOBJ= $(SRC:.c=.o) XLIB= xstring.a X X$(LIB): $(OBJ) X ar rv $(LIB) $? X Xxstrtest: xstrtest.c $(LIB) X cc $@.c $(LIB) -o $@ ~FUNKY STUFF~ echo x - str*.c.3c sed 's/^X//' > str*.c.3c << '~FUNKY STUFF~' ~FUNKY STUFF~