randy@utcsri.UUCP (Randall S. Becker) (05/27/85)
This is a version of FIELD written in C for programmers. My system doesn't have such a facility so I decided to spend the brief time to write my own library. The package is written with long identifiers which are unique to 6 characters. Install it in /usr/lib. Cc .. -lfield will give programmers access to the library. If you find any bugs, let me know. If there are any significant changes, I'll eventually repost the corrected version. A sample (very bad) program is provided in test.c. Try it! You may not like it. The software IS public domain and is NOT taken from Software Tools. Any similarities are coincidental and unintentional. Please forgive the verbosity of the makefile. I have a bunch of standard makefile templates (which I can post is anyone is interested) and software to tell me what's going on with various products. Ignore it or use it at your discretion. I always welcome comments and suggestions for enhancement. Randy Randall S. Becker Usenet: ..!utcsri!randy or ..!utcsri!nucleus!randy CSNET: randy@toronto or nucleus!randy@toronto --------- cut here -------- (there's nothing by source to the end of file) -- : This is a 'shar' archive. : Run this through 'sh' and not 'csh'. : echo 'x - makefile (2108 bytes)' sed 's/^X//' > makefile << //END*OF*FILE X X# makefile for field(3) X X# product identification: X# XNAME = field XAUTHOR = R. Becker XORIGIN = net.sources (utcsri!nucleus) XMANUAL = 3 XSECTION = 3 XPRODUCT = lib${NAME}.a XPRODUCTLIST = ${PRODUCT} X X# support information: X# XOWNER = local XEXECGRP = sysadmin XDOCGRP = doc XUMASK = 644 X X# Locations of the sources, products and working directories X# XSRCDIR = /usr/src/usr.lib/${NAME} XDSTDIR = /usr/lib XMANDIR = /usr/man/man${SECTION} XINCDIR = /usr/include X X# compilation instructions X# XCFLAGS = -i -O XSYSINC = XINCLUDES= field.h XSOURCES = field.c XOBJECTS = field.o XLIBS = X X# products required for compilation and installation: X# note: LINK should be set to 'cp' if the source directory X# is not on the same file system as the destination directory. XLANG = cc XLINK = ln X X# dependencies: X# This section lists the dependencies and any necessary rules X# for the compilation of the development version of the product X${PRODUCT}: ${OBJECTS} X ar rcv ${PRODUCT} `lorder ${OBJECTS} | tsort` X ranlib ${PRODUCT} X X${OBJECTS}: ${INCLUDES} ${SYSINC} X Xtester: ${PRODUCT} X cc test.c ${PRODUCT} -o tester X X# installation instructions X# The installation is broken down into two parts (install and installdoc) X X# install: X# sets the correct mode of the product X# removes any members of the product list from the destination X# directory X# sets up the links to the new product Xinstall: X @echo "make: installing " ${PRODUCT} X chgrp ${EXECGRP} ${PRODUCT} X chmod ${UMASK} ${PRODUCT} X -@for i in ${PRODUCTLIST}; do \ X echo "rm ${DSTDIR}/"$$i; \ X rm ${DSTDIR}/$$i; \ X done X @for i in ${PRODUCTLIST}; do \ X echo "(cd ${DSTDIR}; ln ${SRCDIR}/${PRODUCT}" $$i")"; \ X (cd ${DSTDIR}; ${LINK} ${SRCDIR}/${PRODUCT} $$i) \ X done X (cd /usr/include; ${LINK} ${SRCDIR}/field.h field.h) X X# installdoc: X# removes the old copy of the manual page X# established the link to the new manual page Xinstalldoc: X chgrp ${DOCGRP} ${NAME}.${MANUAL} X -rm ${MANDIR}/${NAME}.${MANUAL} X (cd ${MANDIR}; ${LINK} ${SRCDIR}/${NAME}.${MANUAL} ${NAME}.${MANUAL}) X X# clean up any old object files to conserve space on the disk or tape. X# Xclean: X rm -f ${OBJECTS} //END*OF*FILE echo 'x - field.3 (1262 bytes)' sed 's/^X//' > field.3 << //END*OF*FILE X.tr ~ \ X.TH FIELD 3L "25 May 1985" X.SH NAME Xfield, fsetstr, frelstr, fmaxfields \- field extraction processor X.SH SYNOPSIS X.B Xint fsetstr(source) X.br Xchar *source; X.br X.sp Xchar *field(n) X.br X.sp Xfrelstr() X.br X.sp Xint fmaxfields() X.SH DESCRIPTION X.PP X.I Field Xprovides a general purpose routine for extracting fields from strings. Fields Xare considered to be strings delimited by colons (':') within other strings. XFor example, the string "hello:there:you:\\::" has four fields "hello", "there", X"you", and "\\:". Note that colons may be escaped by suffixing them with a Xbackslash. X.PP XA call to fsetstr() must be made to inform Xfield() of the address of the string being scanned. X.PP XWhen the program is Xfinished with the string it should call frelstr() to free the memory used by Xfield(). X.PP XFmaxfields() can be called to determine the number of fields actually present Xin the current string. X.SH AUTHOR XRandall S. Becker X.SH DIAGNOSTICS XFsetstr() can fail if there is not enough free memory to accomodate a copy Xof the source string and an array of field pointers. A -2 is returned in this Xcase. Otherwise a 0 is returned. X.PP XIf the field number specified in field() is out of range (outside 1..n) Xa -1 is returned. X.SH BUGS XNone detected as of yet. //END*OF*FILE echo 'x - field.h (274 bytes)' sed 's/^X//' > field.h << //END*OF*FILE X/* include file for the field(3L) package */ X Xextern int fsetstr(); /* define a new string for parsing */ Xextern frelstr(); /* release the string being parsed */ Xextern char *field(); /* extract a field */ Xextern int fmaxfields(); /* determine how many fields there are */ //END*OF*FILE echo 'x - field.c (2886 bytes)' sed 's/^X//' > field.c << //END*OF*FILE X/* Author: Randall S. Becker, 26 May 1985 */ X X/* field(3) - field extraction algorithm */ X X/* field maintains its own copy of the source string, __string, with all X delimiter characters replaced by NULLS (ascii 0). An unterminated X list of pointers to the beginning of each field, __fields, is X created when the list is defined. The length of the list is stored X in __maxfields. Access to the __fields list and __maxfields variable X is obtained through the routines field() and fmaxfields() respectively. X X There is no implicit or explicit warrantee associated with this X piece of software. You are free to us it but do so at your own risk. X The author requests that the line of the file be kept in this and X any subsequent modifications to this code. Thank you. */ X X/* Any resemblance to the FIELD(1) code in Software Tools, K&P, is X purely coincidental. This code is the original work of the author. X */ X X#ifdef CHECKING X# include <stdio.h> X# include <assert.h> X#endif CHECKING X X/* error codes */ X#define F_OK 0 X#define F_ENDOFLIST -1 X#define F_NOMEMORY -2 X X#ifndef NULL X# define NULL (0) X#endif NULL X#define BACKSLASH '\\' X#define DELIMITER ':' X#define TRUE (1) X#define FALSE (0) X Xstatic char *__string; Xstatic char **__fields; Xstatic int __maxfields; Xstatic int __present = FALSE; X Xfsetstr(source) X char *source; /* the string being parsed */ X{ X char **fieldptr; X char *strptr; X int length = strlen(source); X char *malloc(), *realloc(); X X if (__present) X frelstr(); X# ifdef CHECKING X assert(! __present); X# endif CHECKING X X __string = malloc( length + 1 ); X strptr = __string; X /* copy the source string to the working area */ X while ( *strptr++ = *source++ ) X ; X X /* alloc space for all possible fields */ X __fields = (char **) malloc ( (length+1) * sizeof(char *) ); X fieldptr = __fields; X if (! __fields && ! __string) X return(F_NOMEMORY); X X __present = TRUE; X strptr = __string; X while (*strptr) { X *fieldptr++ = strptr; X __maxfields++; X /* skip to the next field */ X while (*strptr && *strptr != DELIMITER) { X /* check for escaped delimiter (or anything) */ X if (*strptr == BACKSLASH && *(strptr+1) ) X strptr++; X strptr++; X } X if (*strptr) X *strptr++ = NULL; X# ifdef DEBUG X printf("found field %d = [%s]\n",__maxfields, X *(fieldptr-1)); X# endif DEBUG X } X X /* reduce the size of __fields to the actual number of fields */ X __fields = (char **) realloc(__fields, __maxfields * sizeof(char *)); X X return (F_OK); X} X Xfrelstr() X{ X if (__present) { X free(__string); X __string = NULL; X free(__fields); X __fields = NULL; X __maxfields = 0; X __present = FALSE; X } X# ifdef CHECKING X assert(! __present) X# endif CHECKING X} X Xchar *field(n) X int n; /* the field number */ X{ X if (n < 0 || n > __maxfields) X return(F_ENDOFLIST); X else X return(__fields[n-1]); X} X Xint fmaxfields() X{ X if (__present) X return(__maxfields); X else X return(0); X} //END*OF*FILE echo 'x - test.c (264 bytes)' sed 's/^X//' > test.c << //END*OF*FILE X#include "field.h" X#include "stdio.h" X Xmain() X{ X char buf[256]; X int i; X X while (!feof(stdin)) { X gets(&buf); X printf("string=[%s]\n", buf); X fsetstr(&buf); X for(i=1; i<= fmaxfields(); i++) { X printf(" field %d: [%s]\n", i,field(i)); X }; X frelstr(); X } X} //END*OF*FILE -- Randall S. Becker Usenet: ..!utcsri!randy CSNET: randy@toronto