rusty (06/10/82)
====> charb.3 <==== .TH CHARB 3 .SH NAME cballoc, cbrealloc, fgetcb, makcb, cbbuf, cbmax, cbcat, cbncat, cbcpy, cbncpy \- operations for variable length strings .SH SYNOPSIS .nf .PP .B #include <local/charb.h> .PP .B charb *cballoc(n) .B unsigned int n; .PP .B charb *cbrealloc(cb, n) .B charb *cb; .B unsigned int n; .PP .B fgetcb(cb, stream) .B charb *cb; .SM .B FILE *stream; .PP .B charb *makcb(str) .B char *str; .PP .B cbbuf(cb) .B charb *cb; .PP .B cbmax(cb) .B charb *cb; .PP .B charb *cbcat(cb1, cb2) .B charb *cb1, *cb2; .PP .B charb *cbncat(cb1, cb2, n) .B charb *cb1, *cb2; .PP .B char *cbcpy(cb1, cb2) .B charb *cb1, *cb2; .PP .B char *cbncpy(cb1, cb2, n) .B charb *cb1, *cb2; .fi .SH DESCRIPTION These functions operate on variable length strings whose type is .IR charb . The definition of .I charb is in the include file. In the cases of copying or concatenation the target .IR charb 's string buffer size is increased, if necessary, so that the result will fit. In all cases (except for .IR cbncpy , see below) the .IR charb 's string buffer is null terminated. .PP .I cballoc returns a pointer to a .I charb whose string buffer is of size .IR n . .I cbrealloc returns a pointer to a .I charb whose string buffer's size is changed to .IR n, the previous contents of the string buffer are unchanged. .PP .I fgetcb reads a line of characters, up to and and including the newline from the .I stream into .IR cb . .PP .I makcb returns a pointer to a .I charb whose string buffer contains the string pointed to by .IR str . .PP .I cbbuf yields the string buffer of .IR cb . .I cbmax yields the size of the string buffer of .IR cb , this is not necessarily the same as the length of the string therein. .I cbbuf would be used, for example, when one wants to .B printf(3) the .IR charb . .I cbmax isn't normally needed but is provided for diagnostice purposes. Both are macros. .PP .I cbcat appends a copy of .I cb2 to the end of .IR cb1 . .I cbncat copies at most .I n characters. Both return .IR cb1 . .PP .I cbcpy copies .I cb2 to .I cb1, stopping after the null character has been moved. .I cbncpy copies exactly .I n characters, truncating or null-padding .I cb2; the target may not be null-terminated if the size of .I cb2 is .I n or more. Both return .IR cb1 . .SH "SEE ALSO" fgets(3), malloc(3), string(3) .SH DIAGNOSTICS All routines that return a pointer to a .I charb return NULL upon error (usually running out of memory). .I fgetcb returns EOF upon end of file or error, otherwise 0. .SH BUGS The maximum size of a .I charb string buffer is limited to 65535. ====> makefile <==== SRC = cballoc.c cbcat.c cbcpy.c fgetcb.c makcb.c OBJ = cballoc.o cbcat.o cbcpy.o fgetcb.o makcb.o CFLAGS = -O libcb.a: ${OBJ} ar uv libcb.a ${OBJ} ranlib libcb.a ${OBJ}: charb.h install: libcb.a charb.h cp libcb.a /usr/local/lib cp charb.h /usr/include/local clean: rm -f *.o errs core libcb.a ====> charb.h <==== # ifdef debug # define CBINC 1 # else debug # define CBINC 16 # endif debug /* * macros to get at * parts of a charb */ # define cbbuf(cb) (cb->c_buf) # define cbmax(cb) (cb->c_max) typedef struct { unsigned short c_max; char *c_buf; } charb; extern charb *cbrealloc(); extern charb *cballoc(); extern charb *cbncat(); extern charb *cbcat(); extern charb *cbncpy(); extern charb *cbcpy(); extern charb *makcb(); ====> cballoc.c <==== # include <stdio.h> # include "charb.h" extern char *realloc(); extern char *malloc(); charb * cballoc(n) unsigned int n; { register charb *cb; if ((cb = (charb *) malloc(sizeof(charb))) == NULL) return(NULL); if ((cb->c_buf = malloc(n)) == NULL) { free((char *) cb); return(NULL); } cb->c_max = n; return(cb); } charb * cbrealloc(cb, n) charb *cb; unsigned int n; { if ((cb->c_buf = realloc(cb->c_buf, n)) == NULL) return(NULL); cb->c_max = n; return(cb); } cbfree(cb) charb *cb; { free(cb->c_buf); free((char *) cb); } ====> cbcat.c <==== # include <stdio.h> # include "charb.h" charb * cbcat(cb1, cb2) charb *cb1, *cb2; { register int len1, len2; len1 = strlen(cb1->c_buf); len2 = strlen(cb2->c_buf); if (len1+len2+1 >= cb1->c_max) { if ((cb1 = cbrealloc(cb1, len1+len2+1)) == NULL) return(NULL); } strcat(cb1->c_buf, cb2->c_buf); return(cb1); } charb * cbncat(cb1, cb2, n) charb *cb1, *cb2; { if (n+1 >= cb1->c_max) { if ((cb1 = cbrealloc(cb1, n+1)) == NULL) return(NULL); } strncat(cb1->c_buf, cb2->c_buf, n); return(cb1); } ====> cbcpy.c <==== # include <stdio.h> # include "charb.h" charb * cbcpy(cb1, cb2) charb *cb1, *cb2; { register int len; len = strlen(cb2->c_buf); if (len+1 >= cb1->c_max) { if ((cb1 = cbrealloc(cb1, len+1)) == NULL) return(NULL); } strcpy(cb1->c_buf, cb2->c_buf); return(cb1); } charb * cbncpy(cb1, cb2, n) charb *cb1, *cb2; { if (n+1 >= cb1->c_max) { if ((cb1 = cbrealloc(cb1, n+1)) == NULL) return(NULL); } strncpy(cb1->c_buf, cb2->c_buf, n); return(cb1); } ====> fgetcb.c <==== # include <stdio.h> # include "charb.h" /* * read a newline terminated * string from FILE fd into * charb cb. * * returns EOF upon end of file * or error. * * no indication given for lines * not newline terminated. */ fgetcb(cb, fd) register charb *cb; FILE *fd; { register int ch; register int i; i = 0; while ((ch = getc(fd)) != EOF) { if (i >= cb->c_max) { if ((cb = cbrealloc(cb, i+CBINC)) == NULL) return(EOF); } cb->c_buf[i++] = ch; if (ch == '\n') break; } if (i == 0) return(EOF); if (i >= cb->c_max) { if ((cb = cbrealloc(cb, i+CBINC)) == NULL) return(EOF); } cb->c_buf[i] = NULL; return(NULL); } ====> makcb.c <==== # include <stdio.h> # include "charb.h" charb * makcb(str) char *str; { register charb *cb; if ((cb = cballoc(strlen(str)+1)) == NULL) return(NULL); strcpy(cb->c_buf, str); return(cb); }