home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-04-18 | 60.0 KB | 1,990 lines |
- Newsgroups: comp.sources.misc,alt.binaries.pictures.utilities
- From: jstevens@teal.csn.org (John W.M. Stevens)
- Subject: v36i119: unpost - Smart multi-part uudecoder v2.1.2, Part06/07
- Message-ID: <1993Apr19.052617.29435@sparky.imd.sterling.com>
- X-Md4-Signature: a5dca11aa0a4398800ec30d4343ad257
- Date: Mon, 19 Apr 1993 05:26:17 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: jstevens@teal.csn.org (John W.M. Stevens)
- Posting-number: Volume 36, Issue 119
- Archive-name: unpost/part06
- Environment: UNIX, MS-DOS, OS/2, Windows, MacIntosh, Amiga, Vax/VMS
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: cfg/cbip.cfg cfg/def.cfg compiler.h list.c modflnm.c
- # nntp/client.doc retest.c summary.doc utils.c utils/trie.c
- # Wrapped by kent@sparky on Sun Apr 18 23:10:31 1993
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 6 (of 7)."'
- if test -f 'cfg/cbip.cfg' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cfg/cbip.cfg'\"
- else
- echo shar: Extracting \"'cfg/cbip.cfg'\" \(3793 characters\)
- sed "s/^X//" >'cfg/cbip.cfg' <<'END_OF_FILE'
- X# This is the default configuration modifed to ignore the leading
- X# stuff on the subject line of comp.binaries.ibm.pc and
- X# comp.binaries.ms-windows postings.
- X
- Xsegment "^(Article[:]?|X-NEWS:)"
- X{
- X header
- X {
- X "^Subject:"
- X {
- X "^Subject:.*:(.*)[[({]Part[_ ]*([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
- X {
- X id 1
- X segment number 2
- X segments 3
- X alternate id 4
- X case ignore
- X }
- X "^Subject:.*:(.*)Part[_ ]*[[({]([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
- X {
- X id 1
- X segment number 2
- X segments 3
- X alternate id 4
- X case ignore
- X }
- X "^Subject:.*:(.*)Part[_ ]+([0-9]+)[^0-9]+([0-9]+)(.*)"
- X {
- X id 1
- X segment number 2
- X segments 3
- X alternate id 4
- X case ignore
- X }
- X "^Subject:.*:(.*)[([{]([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
- X {
- X id 1
- X segment number 2
- X segments 3
- X alternate id 4
- X case ignore
- X }
- X "^Subject:.*:(.*)([0-9]+)([/|]|[ \t]+of[ \t]+)([0-9]+)(.*)"
- X {
- X id 1
- X segment number 2
- X segments 4
- X alternate id 5
- X case ignore
- X }
- X "^Subject:.*:(.*)"
- X {
- X id 1
- X segment number 0
- X segments 0
- X alternate id 0
- X case ignore
- X }
- X }
- X "^X-File-Name:"
- X {
- X "^X-File-Name:[ ]+(.*)"
- X {
- X id 1
- X segment number 0
- X segments 0
- X alternate id 0
- X case sensitive
- X }
- X }
- X "^X-Part:"
- X {
- X "^X-Part:[ ]+([0-9]+)"
- X {
- X id 0
- X segment number 1
- X segments 0
- X alternate id 0
- X case sensitive
- X }
- X }
- X "^X-Part-Total:"
- X {
- X "^X-Part-Total:[ ]+([0-9]+)"
- X {
- X id 0
- X segment number 0
- X segments 1
- X alternate id 0
- X case sensitive
- X }
- X }
- X "^Uusplit-part:"
- X {
- X "^Uusplit-part:[ ]+([0-9]+)"
- X {
- X id 0
- X segment number 1
- X segments 0
- X alternate id 0
- X case sensitive
- X }
- X }
- X "^Uusplit-parts:"
- X {
- X "^Uusplit-parts:[ ]+([0-9]+)"
- X {
- X id 0
- X segment number 0
- X segments 1
- X alternate id 0
- X case sensitive
- X }
- X }
- X }
- X body
- X {
- X "^section [0-9]+ of uuencode [0-9]+\.[0-9]+ of file "
- X "[^ ]+ by R.E.M."
- X {
- X "^section ([0-9]+) of uuencode [0-9]+\.[0-9]+ of file "
- X "([^ ]+)[ ]+by R.E.M."
- X {
- X id 2
- X segment number 1
- X segments 0
- X alternate id 0
- X case sensitive
- X }
- X }
- X "^[^ ]+[ ]+section[ ]+[0-9]+/[0-9]+[ ]+UUXFER "
- X "ver [^ ]+ by David M. Read"
- X {
- X "^([^ \t]+)[ \t]+section[ \t]+([0-9]+)/([0-9]+)[ \t]+UUXFER "
- X "ver [^ \t]+ by David M. Read"
- X {
- X id 1
- X segment number 2
- X segments 3
- X alternate id 0
- X case sensitive
- X }
- X }
- X }
- X}
- END_OF_FILE
- if test 3793 -ne `wc -c <'cfg/cbip.cfg'`; then
- echo shar: \"'cfg/cbip.cfg'\" unpacked with wrong size!
- fi
- # end of 'cfg/cbip.cfg'
- fi
- if test -f 'cfg/def.cfg' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cfg/def.cfg'\"
- else
- echo shar: Extracting \"'cfg/def.cfg'\" \(5229 characters\)
- sed "s/^X//" >'cfg/def.cfg' <<'END_OF_FILE'
- X# This is the default configuration of UNPOST, shown in configuration
- X# file format for instructional purposes, and for use in situations
- X# where the default needs to be modified.
- X
- Xsegment "^(Article[:]?|X-NEWS:)"
- X{
- X header
- X {
- X "^Subject:"
- X {
- X "^Subject:(.*)[[({]Part[_ ]*([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
- X {
- X id 1
- X segment number 2
- X segments 3
- X alternate id 4
- X case ignore
- X }
- X "^Subject:(.*)Part[_ ]*[[({]([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
- X {
- X id 1
- X segment number 2
- X segments 3
- X alternate id 4
- X case ignore
- X }
- X "^Subject:(.*)Part[_ ]+([0-9]+)[^0-9]+([0-9]+)(.*)"
- X {
- X id 1
- X segment number 2
- X segments 3
- X alternate id 4
- X case ignore
- X }
- X "^Subject:(.*)[([{]([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
- X {
- X id 1
- X segment number 2
- X segments 3
- X alternate id 4
- X case ignore
- X }
- X "^Subject:(.*)([0-9]+)([/|]|[ \t]+of[ \t]+)([0-9]+)(.*)"
- X {
- X id 1
- X segment number 2
- X segments 4
- X alternate id 5
- X case ignore
- X }
- X "^Subject:(.*)"
- X {
- X id 1
- X segment number 0
- X segments 0
- X alternate id 0
- X case ignore
- X }
- X }
- X "^X-File-Name:"
- X {
- X "^X-File-Name:[ ]+(.*)"
- X {
- X id 1
- X segment number 0
- X segments 0
- X alternate id 0
- X case sensitive
- X }
- X }
- X "^X-Part:"
- X {
- X "^X-Part:[ ]+([0-9]+)"
- X {
- X id 0
- X segment number 1
- X segments 0
- X alternate id 0
- X case sensitive
- X }
- X }
- X "^X-Part-Total:"
- X {
- X "^X-Part-Total:[ ]+([0-9]+)"
- X {
- X id 0
- X segment number 0
- X segments 1
- X alternate id 0
- X case sensitive
- X }
- X }
- X "^Uusplit-part:"
- X {
- X "^Uusplit-part:[ ]+([0-9]+)"
- X {
- X id 0
- X segment number 1
- X segments 0
- X alternate id 0
- X case sensitive
- X }
- X }
- X "^Uusplit-parts:"
- X {
- X "^Uusplit-parts:[ ]+([0-9]+)"
- X {
- X id 0
- X segment number 0
- X segments 1
- X alternate id 0
- X case sensitive
- X }
- X }
- X }
- X body
- X {
- X "^section [0-9]+ of uuencode [0-9]+\.[0-9]+ of file "
- X "[^ ]+ by R.E.M."
- X {
- X "^section ([0-9]+) of uuencode [0-9]+\.[0-9]+ of file "
- X "([^ ]+)[ ]+by R.E.M."
- X {
- X id 2
- X segment number 1
- X segments 0
- X alternate id 0
- X case sensitive
- X }
- X }
- X "^[^ ]+[ ]+section[ ]+[0-9]+/[0-9]+[ ]+UUXFER "
- X "ver [^ ]+ by David M. Read"
- X {
- X "^([^ \t]+)[ \t]+section[ \t]+([0-9]+)/([0-9]+)[ \t]+UUXFER "
- X "ver [^ \t]+ by David M. Read"
- X {
- X id 1
- X segment number 2
- X segments 3
- X alternate id 0
- X case sensitive
- X }
- X }
- X "^Subject:"
- X {
- X "^Subject:(.*)[[({]Part[_ ]*([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
- X {
- X id 1
- X segment number 2
- X segments 3
- X alternate id 4
- X case ignore
- X }
- X "^Subject:(.*)Part[_ ]*[[({]([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
- X {
- X id 1
- X segment number 2
- X segments 3
- X alternate id 4
- X case ignore
- X }
- X "^Subject:(.*)Part[_ ]+([0-9]+)[^0-9]+([0-9]+)(.*)"
- X {
- X id 1
- X segment number 2
- X segments 3
- X alternate id 4
- X case ignore
- X }
- X "^Subject:(.*)[([{]([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
- X {
- X id 1
- X segment number 2
- X segments 3
- X alternate id 4
- X case ignore
- X }
- X "^Subject:(.*)([0-9]+)([/|]|[ \t]+of[ \t]+)([0-9]+)(.*)"
- X {
- X id 1
- X segment number 2
- X segments 4
- X alternate id 5
- X case ignore
- X }
- X "^Subject:(.*)"
- X {
- X id 1
- X segment number 0
- X segments 0
- X alternate id 0
- X case ignore
- X }
- X }
- X }
- X}
- END_OF_FILE
- if test 5229 -ne `wc -c <'cfg/def.cfg'`; then
- echo shar: \"'cfg/def.cfg'\" unpacked with wrong size!
- fi
- # end of 'cfg/def.cfg'
- fi
- if test -f 'compiler.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'compiler.h'\"
- else
- echo shar: Extracting \"'compiler.h'\" \(4622 characters\)
- sed "s/^X//" >'compiler.h' <<'END_OF_FILE'
- X/******************************************************************************
- X* Module : Compiler include files, separated out to make configuration
- X* different systems a little easier (I hate this, I really
- X* hate this, but it has been requested, so here it is).
- X*
- X* Author : John W. M. Stevens
- X******************************************************************************/
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <ctype.h>
- X#include <errno.h>
- X#include <string.h>
- X
- X/*=============================================================================
- X* Configure the program. . .
- X*
- X* WARNING! Be sure what you are doing here. . .
- X=============================================================================*/
- X
- X/* Debug macro. Uncomment to get debug output. */
- X/* #define UNPOST_DEBUG 1 */
- X
- X/* Uncomment to give you different file name munging under OS/2
- X* on the basis of the File System.
- X*
- X* Suggestions and help courtesy of:
- X*
- X* Darrel R Hankerson <hankedr@mail.auburn.edu>
- X*
- X* Without whose help and discussion, this would not have been done.
- X* In other words, blame it all on him. . . :-)
- X*/
- X/* #define MUNGE_FILE_NAMES_PER_FS 1 */
- X
- X/* Change the one to a zero to make file name mungling default to
- X* being off.
- X*/
- X#define MUNGE_FILE_NMS 1
- X
- X/* Change the one to a zero to make description file dumping
- X* default to being off.
- X*/
- X#define DUMP_DESC_FILES 1
- X
- X/* Change zero to one to make incompletes separation be turned on
- X* by default.
- X*/
- X#define SEP_INCOMPLETES 0
- X
- X/*-----------------------------------------------------------------------------
- X* Compiler specific stuff below.
- X*
- X* The first set is for the Lattice C compiler on the Amiga.
- X-----------------------------------------------------------------------------*/
- X#if defined(LATTICE_C_COMPILER)
- X
- X/* Defines for fopen calls. */
- X#define TXT_APPEND "at"
- X#define TXT_READ "rt"
- X#define BIN_READ "rb"
- X#define TXT_WRITE "wt"
- X#define BIN_WRITE "wb"
- X
- X#define SEEK_SET 0
- X
- X/*-----------------------------------------------------------------------------
- X* This set is for the GCC compiler on Unix systems.
- X-----------------------------------------------------------------------------*/
- X#elif defined(GCC_COMPILER)
- X
- X/* Defines for fopen calls. */
- X#define TXT_APPEND "at"
- X#define TXT_READ "rt"
- X#define BIN_READ "rb"
- X#define TXT_WRITE "wt"
- X#define BIN_WRITE "wb"
- X
- X#include <malloc.h>
- X#include <unistd.h>
- X
- Xextern char *sys_errlist[];
- X
- X/*-----------------------------------------------------------------------------
- X* The GCC compiler on OS/2.
- X-----------------------------------------------------------------------------*/
- X#elif defined(EMX_GCC_COMPILER)
- X
- X/* Defines for fopen calls. */
- X#define TXT_APPEND "at"
- X#define TXT_READ "rt"
- X#define BIN_READ "rb"
- X#define TXT_WRITE "wt"
- X#define BIN_WRITE "wb"
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- X#if defined(SYSTEM_OS_2)
- X#define INCL_DOSFILEMGR
- X#include <os2.h>
- X#else
- X#include <dos.h>
- X#endif
- X
- X#include <malloc.h>
- X#include <unistd.h>
- X
- X/*-----------------------------------------------------------------------------
- X* The MSC compiler on OS/2.
- X-----------------------------------------------------------------------------*/
- X#elif defined(OS_2_MSC_COMPILER)
- X
- X/* Defines for fopen calls. */
- X#define TXT_APPEND "at"
- X#define TXT_READ "rt"
- X#define BIN_READ "rb"
- X#define TXT_WRITE "wt"
- X#define BIN_WRITE "wb"
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- X#if defined(SYSTEM_OS_2)
- X#define INCL_DOSFILEMGR
- X#include <os2.h>
- X#else
- X#include <dos.h>
- X#endif
- X
- X/*-----------------------------------------------------------------------------
- X* The BCC compiler on MS-DOS.
- X-----------------------------------------------------------------------------*/
- X#elif defined(BCC_COMPILER)
- X
- X/* Defines for fopen calls. */
- X#define TXT_APPEND "at"
- X#define TXT_READ "rt"
- X#define BIN_READ "rb"
- X#define TXT_WRITE "wt"
- X#define BIN_WRITE "wb"
- X
- X#include <malloc.h>
- X
- X/*-----------------------------------------------------------------------------
- X* All others (Non-ANSI compatible).
- X-----------------------------------------------------------------------------*/
- X#else
- X
- X/* Defines for fopen calls. */
- X#define TXT_APPEND "a"
- X#define TXT_READ "r"
- X#define BIN_READ "r"
- X#define TXT_WRITE "w"
- X#define BIN_WRITE "w"
- X
- X#include <malloc.h>
- X
- X#endif
- END_OF_FILE
- if test 4622 -ne `wc -c <'compiler.h'`; then
- echo shar: \"'compiler.h'\" unpacked with wrong size!
- fi
- # end of 'compiler.h'
- fi
- if test -f 'list.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'list.c'\"
- else
- echo shar: Extracting \"'list.c'\" \(6508 characters\)
- sed "s/^X//" >'list.c' <<'END_OF_FILE'
- X/******************************************************************************
- X* Module : List --- List building and maintenance module.
- X*
- X* Author : John Stevens.
- X******************************************************************************/
- X
- X#include "compiler.h"
- X
- X#include "unpost.h"
- X#include "list.h"
- X#include "utils.h"
- X
- X#define INIT_SIZE 2
- X#define INCREASE 5
- X
- X/*-----------------------------------------------------------------------------
- X| Routine : AddList() --- Add an element to a list.
- X|
- X| Inputs : Head - Pointer to begining of list.
- X| Elem - New element to add to list.
- X| InsPt - List ordinal for add.
- X|
- X| Returns : Pointer to list head.
- X-----------------------------------------------------------------------------*/
- X
- Xvoid *AddList(LIST *Head,
- X void *Elem,
- X int InsPt)
- X{
- X auto char *List;
- X extern FILE *ErrFile;
- X
- X /* Create or add to list. */
- X if (Head->NoElems >= Head->TotElems)
- X {
- X auto int NewSize;
- X
- X /* Reallocate the list header. */
- X NewSize = (Head->TotElems + INCREASE) * Head->ElemSz + sizeof( LIST );
- X if ((Head = (LIST *) realloc(Head, NewSize)) == NULL)
- X {
- X fprintf(ErrFile,
- X "%s %d : Error - Out of memory.\n",
- X __FILE__,
- X __LINE__);
- X exit( 1 );
- X }
- X
- X /* Update list size. */
- X Head->TotElems += INCREASE;
- X }
- X
- X /* Move list elements up to make room. */
- X List = Head->List + Head->ElemSz * InsPt;
- X if (InsPt < Head->NoElems)
- X {
- X MemMove(List + Head->ElemSz,
- X List,
- X Head->ElemSz * (Head->NoElems - InsPt));
- X }
- X
- X /* Copy new element to it's proper location. */
- X MemCopy(List, Elem, Head->ElemSz);
- X Head->NoElems++;
- X return( Head );
- X}
- X
- X/*-----------------------------------------------------------------------------
- X| Routine : CrtList() --- Create a new (empty) list.
- X|
- X| Inputs : ElemSz - Size of element in bytes.
- X|
- X| Returns : Pointer to list head.
- X-----------------------------------------------------------------------------*/
- X
- Xvoid *CrtList(int ElemSz)
- X{
- X auto LIST *Head;
- X auto int Size;
- X extern FILE *ErrFile;
- X
- X /* Calculate the size of the new list and allocate it. */
- X Size = INIT_SIZE * ElemSz + sizeof( LIST );
- X if ((Head = (LIST *) calloc(1, Size)) == NULL)
- X {
- X fprintf(ErrFile,
- X "%s %d : Error - Out of memory.\n",
- X __FILE__,
- X __LINE__);
- X exit( 1 );
- X }
- X
- X /* Return the pointer to the list. */
- X Head->ElemSz = ElemSz;
- X Head->TotElems = INIT_SIZE;
- X return( Head );
- X}
- X
- X/*-----------------------------------------------------------------------------
- X| Routine : SrchList() --- Search the list.
- X|
- X| Inputs : Head - Pointer to begining of list.
- X| Elem - Element to search list for.
- X| CmpFn - Function to compare in search.
- X| Outputs : InsPt - List pointer for insert/found.
- X|
- X| Returns : TRUE for found, FALSE for not found.
- X-----------------------------------------------------------------------------*/
- X
- Xint SrchList(LIST *Head,
- X void *Elem,
- X int (*CmpFn)(void *, void *),
- X int *InsPt)
- X{
- X /* Search the list for an element.
- X *
- X * Do binary search.
- X */
- X if (Head->NoElems > 0)
- X {
- X auto char *List;
- X auto int hi;
- X auto int lo;
- X auto int ret;
- X auto int mid;
- X
- X lo = 0;
- X hi = Head->NoElems - 1;
- X do
- X {
- X /* Get midpoint of list. */
- X mid = (hi + lo) >> 1;
- X List = Head->List + Head->ElemSz * mid;
- X
- X /* Do string compare. */
- X ret = CmpFn(Elem, List);
- X
- X /* Adjust array pointers. */
- X if (ret <= 0)
- X hi = mid - 1;
- X if (ret >= 0)
- X lo = mid + 1;
- X } while (hi >= lo);
- X
- X /* Did we find it? */
- X if (ret == 0)
- X {
- X /* We found it. */
- X *InsPt = mid;
- X return( TRUE );
- X }
- X
- X /* We did not find it. */
- X *InsPt = lo;
- X return( FALSE );
- X }
- X
- X /* Return that we did not find it, and the point at
- X * which it should be inserted.
- X */
- X *InsPt = 0;
- X return( FALSE );
- X}
- X
- X/*-----------------------------------------------------------------------------
- X| Routine : ListIdx() --- Get pointer to a list element.
- X|
- X| Inputs : Head - Pointer to begining of list.
- X| Index - Index of element to return pointer for.
- X|
- X| Returns : NULL for index outside of list limits, Pointer to list
- X| element otherwise.
- X-----------------------------------------------------------------------------*/
- X
- Xvoid *ListIdx(LIST *Head,
- X int Index)
- X{
- X /* Determine if index is inside list limits. */
- X if (Index < 0 || Index >= Head->NoElems)
- X return( NULL );
- X return( Head->List + Index * Head->ElemSz );
- X}
- X
- X/*-----------------------------------------------------------------------------
- X| Routine : AppList() --- Append an element to a list.
- X|
- X| Inputs : Head - Pointer to begining of list.
- X| Elem - New element to add to list.
- X|
- X| Returns : Pointer to list head.
- X-----------------------------------------------------------------------------*/
- X
- Xvoid *AppList(LIST *Head,
- X void *Elem)
- X{
- X auto char *List;
- X extern FILE *ErrFile;
- X
- X /* Create or add to list. */
- X if (Head->NoElems >= Head->TotElems)
- X {
- X auto int NewSize;
- X
- X /* Reallocate the list header. */
- X NewSize = (Head->TotElems + INCREASE) * Head->ElemSz + sizeof( LIST );
- X if ((Head = (LIST *) realloc(Head, NewSize)) == NULL)
- X {
- X fprintf(ErrFile,
- X "%s %d : Error - Out of memory.\n",
- X __FILE__,
- X __LINE__);
- X exit( 1 );
- X }
- X
- X /* Update list size. */
- X Head->TotElems += INCREASE;
- X }
- X
- X /* Copy new element to it's proper location. */
- X List = Head->List + Head->ElemSz * Head->NoElems;
- X MemCopy(List, Elem, Head->ElemSz);
- X Head->NoElems++;
- X return( Head );
- X}
- END_OF_FILE
- if test 6508 -ne `wc -c <'list.c'`; then
- echo shar: \"'list.c'\" unpacked with wrong size!
- fi
- # end of 'list.c'
- fi
- if test -f 'modflnm.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'modflnm.c'\"
- else
- echo shar: Extracting \"'modflnm.c'\" \(8353 characters\)
- sed "s/^X//" >'modflnm.c' <<'END_OF_FILE'
- X/******************************************************************************
- X* Module : File Names --- File name utilities.
- X*
- X* Author : John W. M. Stevens
- X******************************************************************************/
- X
- X#include "compiler.h"
- X
- X#include "unpost.h"
- X#include "sets.h"
- X#include "modflnm.h"
- X
- X/* Sets. */
- Xstatic int InitSets = 1;
- Xstatic SET StandSet;
- Xstatic SET ThrowSet;
- Xstatic SET NoSet;
- Xstatic SET AlphaSet;
- X
- X/* Strings for character sets. */
- Xstatic char *Stand = "a-z0-9_.-";
- Xstatic char *Throw = "aeiouy_-";
- Xstatic char *Numbers = "0-9";
- Xstatic char *Alpha = "a-z";
- X
- X/*-----------------------------------------------------------------------------
- X| Routine : ChkFlNmLen() --- Check the file name length.
- X|
- X| Inputs : FileName - File name.
- X-----------------------------------------------------------------------------*/
- X
- Xstatic
- Xint ChkFlNmLen(char *FileNm)
- X{
- X register int i;
- X
- X /* Count file characters. */
- X for (i = 0;
- X FileNm[i] && FileNm[i] != EXT_SEP_CHAR;
- X i++)
- X ;
- X
- X /* Return True or False. */
- X return( i );
- X}
- X
- X/*-----------------------------------------------------------------------------
- X| Routine : FlNmFilter() --- Filter a string so that only characters from
- X| the set of standard file name characters are left.
- X|
- X| Inputs :
- X-----------------------------------------------------------------------------*/
- X
- Xvoid FlNmFilter(char *FlName)
- X{
- X auto char *cp;
- X auto char *tp;
- X auto char c;
- X
- X /* Create character sets. */
- X if ( InitSets )
- X {
- X tp = Stand;
- X CrtSet(&tp, StandSet);
- X tp = Throw;
- X CrtSet(&tp, ThrowSet);
- X tp = Numbers;
- X CrtSet(&tp, NoSet);
- X tp = Alpha;
- X CrtSet(&tp, AlphaSet);
- X InitSets = 0;
- X }
- X
- X /* Convert string to lower case and strip out illegal characters. */
- X for (cp = tp = FlName; *tp; tp++)
- X {
- X /* First, convert to lower case. */
- X c = (char) tolower( *tp );
- X
- X /* Next, check for standards conformity. */
- X if (c == ' ' || c == '\t' || InSet(StandSet, c))
- X *cp++ = c;
- X }
- X *cp = '\0';
- X}
- X
- X/*-----------------------------------------------------------------------------
- X| Routine : ModifyFlNm() --- Convert to lower case and make sure that
- X| this file name conforms to MS-DOS restrictions/limitations
- X| and USENET posting standards.
- X|
- X| Inputs : FlName - File name.
- X| Ext - Extension.
- X| Outputs : OutName - Modified file name.
- X-----------------------------------------------------------------------------*/
- X
- Xint ModifyFlNm(char *FlName,
- X char *Ext,
- X char *OutName)
- X{
- X register int i;
- X auto int len;
- X auto int ChopFlag;
- X auto char *cp;
- X auto char *tp;
- X auto char c;
- X extern FILE *ErrFile;
- X
- X /* Create character sets. */
- X if ( InitSets )
- X {
- X tp = Stand;
- X CrtSet(&tp, StandSet);
- X tp = Throw;
- X CrtSet(&tp, ThrowSet);
- X tp = Numbers;
- X CrtSet(&tp, NoSet);
- X tp = Alpha;
- X CrtSet(&tp, AlphaSet);
- X InitSets = 0;
- X }
- X
- X /* Convert string to lower case and strip out illegal characters. */
- X for (cp = OutName, tp = FlName; *tp; tp++)
- X {
- X /* First, convert to lower case. */
- X c = (char) tolower( *tp );
- X
- X /* Next, check for standards conformity. */
- X if ( InSet(StandSet, c) )
- X *cp++ = c;
- X }
- X *cp = '\0';
- X
- X /* If we have more than MAX_FILE characters in the file name,
- X * then shorten the file name.
- X */
- X if ((len = ChkFlNmLen( OutName )) > MAX_FILE)
- X {
- X /* Shorten by removing vowels and separator characters. */
- X for (tp = cp = OutName, i = len;
- X *tp && *tp != EXT_SEP_CHAR && i > MAX_FILE;
- X tp++)
- X {
- X /* If this is not a throw away character, save it back
- X * in the string.
- X */
- X if (! InSet(ThrowSet, *tp))
- X {
- X *cp++ = *tp;
- X continue;
- X }
- X else if (tp == OutName)
- X {
- X *cp++ = *tp;
- X continue;
- X }
- X
- X /* Decrement the file name size. */
- X i--;
- X }
- X strcpy(cp, tp);
- X }
- X else
- X goto ShortEnough;
- X
- X /* If we still have more than MAX_FILE characters in the file
- X * name, chop off leading zeros in any numeric strings in the
- X * file name.
- X */
- X if ((len = ChkFlNmLen( OutName )) > MAX_FILE)
- X {
- X /* Loop through string. */
- X for (tp = cp = OutName, i = len;
- X *tp && *tp != EXT_SEP_CHAR && i > MAX_FILE;
- X tp++)
- X {
- X /* If this is a numeric sub-string, strip any leading
- X * zeros.
- X */
- X if (tp[1] && tp[1] != '.' &&
- X InSet(NoSet, *tp) && InSet(NoSet, tp[1]) &&
- X *tp == '0')
- X {
- X i--;
- X continue;
- X }
- X
- X /* Copy character in. */
- X *cp++ = *tp;
- X }
- X strcpy(cp, tp);
- X }
- X else
- X goto ShortEnough;
- X
- X /* If we still have more than MAX_FILE characters in the file name, chop
- X * alphabetic strings short by throwing away excess characters.
- X */
- X while ((len = ChkFlNmLen( OutName )) > MAX_FILE)
- X {
- X /* Loop through string. */
- X for (tp = cp = OutName, ChopFlag = 0, i = len;
- X *tp && *tp != EXT_SEP_CHAR && i > MAX_FILE;
- X tp++)
- X {
- X /* Do not throw away numeric characters at this point. */
- X if ( InSet(NoSet, *tp) )
- X {
- X *cp++ = *tp;
- X continue;
- X }
- X
- X /* Throw away the trailing character in an alphabetic
- X * substring.
- X */
- X if (*tp && tp[1] != EXT_SEP_CHAR &&
- X InSet(AlphaSet, *tp) && InSet(AlphaSet, tp[1]))
- X {
- X *cp++ = *tp;
- X continue;
- X }
- X
- X /* Yup, we are chopping out a character. */
- X i--;
- X ChopFlag = 1;
- X }
- X strcpy(cp, tp);
- X
- X /* If not even one character is chopped out in a pass
- X * through the file name list, drop out and issue an
- X * error.
- X */
- X if (ChopFlag == 0)
- X {
- X fprintf(ErrFile,
- X "%s %d : Error - Could not modify file name to be ",
- X __FILE__,
- X __LINE__);
- X fprintf(ErrFile,
- X "MS-DOS conformant.\n");
- X return( 1 );
- X }
- X }
- X
- X /* Done with file name, now fix extension. */
- XShortEnough:
- X for (tp = OutName;
- X *tp && *tp != EXT_SEP_CHAR;
- X tp++)
- X ;
- X if (*tp == EXT_SEP_CHAR)
- X {
- X /* Were we able to identify this file? */
- X if ( *Ext )
- X strcpy(tp, Ext);
- X else
- X {
- X /* Move four characters across (including '.') and we
- X * are done.
- X */
- X for (i = 0, tp++;
- X *tp && *tp != EXT_SEP_CHAR && i < MAX_EXT;
- X i++, tp++)
- X ;
- X *tp = '\0';
- X }
- X }
- X else
- X {
- X /* No extension, so append one. */
- X strcpy(tp, Ext);
- X }
- X
- X /* Return no error. */
- X return( 0 );
- X}
- X
- X/*-----------------------------------------------------------------------------
- X| Routine : ModExten() --- Modify the file name extension.
- X|
- X| Inputs : FlName - File name.
- X-----------------------------------------------------------------------------*/
- X
- Xvoid ModExten(char *FlName,
- X char *Exten,
- X char *OutFlNm)
- X{
- X auto char *tp;
- X auto char *op;
- X
- X /* Search for the first file name extension separator character. */
- X for (tp = FlName, op = OutFlNm;
- X *tp && *tp != EXT_SEP_CHAR;
- X )
- X *op++ = *tp++;
- X
- X /* Copy in new extension. */
- X strcpy(op, Exten);
- X}
- END_OF_FILE
- if test 8353 -ne `wc -c <'modflnm.c'`; then
- echo shar: \"'modflnm.c'\" unpacked with wrong size!
- fi
- # end of 'modflnm.c'
- fi
- if test -f 'nntp/client.doc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'nntp/client.doc'\"
- else
- echo shar: Extracting \"'nntp/client.doc'\" \(6565 characters\)
- sed "s/^X//" >'nntp/client.doc' <<'END_OF_FILE'
- XCLIENT
- X
- XName:
- X
- X client - Attach to an NNTP (network news transfer protocol) server,
- X extract all unread postings to the specified newsgroup
- X and write them to a specified file.
- X
- XSynopsis:
- X
- X client <server name> <configuration file>
- X
- XDescription:
- X
- X CLIENT is a program that is designed to act as an assitant to
- X UNPOST. It's primarily designed to create the files that UNPOST
- X works on. It is very simple, and quite stupid.
- X
- X It starts by attempting to get the server address from the
- X /etc/hosts file based on the server name given on the command
- X line, then it attempts to get the NNTP foreign port number (which,
- X according to the spec, should ALWAYS be 119, but I decided not to
- X take any chances) and then connect to the NNTP News server.
- X
- X If CLIENT successfully connects to the server, it opens the
- X configuration file and reads a line from it.
- X
- X These lines should look like:
- X
- X group <news group name> <file name> <next article number>
- X
- X Where news group name is the name of the news group that you want
- X CLIENT to read from, file name is the name of the file you want
- X CLIENT to write all articles to, and next article number is
- X the first article number to read.
- X
- X Example:
- X
- X group alt.binaries.pictures.utilites abpu.uue 231
- X
- X Which says read from group alt.binaries.pictures.utilities, write
- X all unread articles (all articles with numbers greater than or
- X equal to 231) to a file called abpu.uue.
- X
- X After reading every unread article from a.b.p.u and writing them to
- X the file abpu.uue, CLIENT will read the next line from the
- X configuration file and start all over again.
- X
- X After reading all articles from all of the specified news groups,
- X CLIENT will rewrite the configuration file to specify the next
- X new article number and then close the connection to the News
- X server and exit.
- X
- XOptions:
- X
- X <server name> - Internet server name, example: news.llmt.org
- X
- X <configuration file> - Name of configuration file.
- X
- XStandards:
- X
- X CLIENT follows the standard described in RFC 977.
- X
- XNotes:
- X
- X To use this program to collect all of the binaries posted to, say,
- X the alt.binaries.misc group on a daily basis, create a configuration
- X file that looks like:
- X
- X group alt.binaries.misc abm.uue 0
- X
- X and is named client.cfg.
- X
- X Then you need to set up a script that calls client on a daily basis,
- X using the CRON or AT facility. See your local man pages for these
- X services.
- X
- X The script should contain the line:
- X
- X client news.llmat.org client.cfg 2> client.err
- X
- X Be aware that if you use AT or CRON, you may need to add path names
- X to both the script, and the file names in the configuration file.
- X
- XDiagnostics:
- X
- X Error in writing to news server.
- X Return = #, Error number = #
- X
- X CLIENT tried to write a message to the server, but there
- X was an error. If you are C fluent, you might look in errno.h
- X to see what the Error number means, if anything.
- X
- X I can't do anything about this error, sorry.
- X
- X Error in reading from news server.
- X Return = #, Error number = #
- X
- X CLIENT tried to read a message from the server, but there
- X was an error. If you are C fluent, you might look in errno.h
- X to see what the Error number means, if anything.
- X
- X I can't do anything about this error, sorry.
- X
- X Error, response to ARTICLE = #.
- X
- X CLIENT asked for an article and got back the status # from
- X the server. Most probably, # will be 221, 222 or 223.
- X
- X Error, no news group selected.
- X
- X Ooops. This shouldn't happen. Somehow, CLIENT thinks that
- X it's GROUP selection command was succesful, and the server
- X disagrees.
- X
- X Error, no current article selected.
- X
- X Same as above, CLIENT and server disagree about the success
- X of an ARTICLE command.
- X
- X Warning - saw '\\n' before '\\r'.
- X Warning - saw '.\\r' but no '\\n'.
- X Warning - saw '.\\r' but no '\\n'.
- X
- X The standard says that all lines are terminated with a carriage
- X return followed by a line feed. Either the order is wrong
- X (LF-CR), or there is a missing line feed, or a missing
- X carriage return.
- X
- X Warning - did not use all of article.
- X
- X The server sent the whole article, but for some reason CLIENT
- X decided that it saw a ".\r\n" before the actual end of the
- X article text. (".\r\n" is the end of an article, according
- X to the standard).
- X
- X Error - Could not convert 'server' to a host address.
- X
- X Evidently, there is no server named 'server' in the hosts table.
- X You can try the actual internet address, if you know it.
- X
- X Error - bogus port number 'nntp'.
- X
- X Couldn't find the NNTP port in the services table.
- X
- X Error - could not connect to news server.
- X
- X There are any number of reasons that you might get this message,
- X and some of them will be given in the error message given just
- X before this one.
- X
- X One reason may be that the server is limited in the number of
- X clients it may serve at one time, and it may have refused
- X connection because it is at quota already.
- X
- X Error, could not open configuration file.
- X
- X Couldn't find the file, couldn't read it, whatever.
- X
- X Error, could not open new configuration file.
- X
- X CLIENT opens a temporary file to write the new configuration to
- X at the end, and for some reason, it couldn't create a new file
- X for writing. Full disk, maybe?
- X
- X Error - bad configuration file line.
- X 'configuration file line'
- X
- X Check the syntax of your configuration file. The line given
- X is not correct, according to CLIENT.
- X
- X Error, no such news group 's'.
- X
- X According to the server, there is no such group as 's'.
- X
- X No news in group 's'.
- X
- X According to the server, there are no articles in news group
- X 's'.
- X
- X Error, could not open file 's' for writing.
- X
- X CLIENT is attempting to open the file that you want the
- X articles for this group written to, but cannot, for some
- X reason.
- X
- XFuture:
- X
- X I am planning to integrate CLIENT and UNPOST in the near future, as
- X CLIENT makes it easy to know where articles begin and end.
- X
- X I will be modifying UNPOST to build either the current version
- X (work from a file) or to use CLIENT.
- X
- XBugs:
- X
- X None currently known, but I'm sure that will change.
- X
- XAuthor:
- X
- X John W. M. Stevens - jstevens@csn.org
- END_OF_FILE
- if test 6565 -ne `wc -c <'nntp/client.doc'`; then
- echo shar: \"'nntp/client.doc'\" unpacked with wrong size!
- fi
- # end of 'nntp/client.doc'
- fi
- if test -f 'retest.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'retest.c'\"
- else
- echo shar: Extracting \"'retest.c'\" \(1892 characters\)
- sed "s/^X//" >'retest.c' <<'END_OF_FILE'
- X/******************************************************************************
- X* Module : Regular Expression Test Driver --- Test the regular expression
- X* package.
- X*
- X* Author : John Stevens
- X******************************************************************************/
- X
- X#include "compiler.h"
- X
- X#include "sets.h"
- X#include "regexp.h"
- X#include "utils.h"
- X
- XFILE *ErrFile = stderr;
- X
- Xint main(int argc,
- X char **argv)
- X{
- X register int i;
- X auto REG_EXP_NODE *ReExpr;
- X auto FILE *fp;
- X auto char **SubStrs;
- X auto char Bfr[256];
- X
- X /* Check command line parameters. */
- X if (argc != 3)
- X {
- X fprintf(stderr,
- X "%s %d : Error - Syntax is: ",
- X __FILE__,
- X __LINE__);
- X fprintf(stderr,
- X "%s <regular expression> <file name>\n",
- X argv[0]);
- X exit( 1 );
- X }
- X
- X /* Compile the regular expression. */
- X ReExpr = ReCompile( argv[1] );
- X
- X /* Match against a line from a test file. */
- X if ((fp = fopen(argv[2], TXT_READ)) == NULL)
- X {
- X fprintf(stderr,
- X "Error, could not open file '%s' for reading.\n",
- X argv[2]);
- X exit( 1 );
- X }
- X
- X /* Search file for matching regular expressions, and print all
- X * matched sub-strings.
- X */
- X while (fgets(Bfr, 256, fp) != NULL)
- X {
- X /* Attempt match. */
- X SubStrs = NULL;
- X if (ReMatch(Bfr, CASE_SENSITIVE, ReExpr, &SubStrs) != 0)
- X {
- X /* Print matching line and matching sub-strings. */
- X printf("Line: '%s'\n", Bfr);
- X for (i = 0; i < MAX_SUB_EXPRS; i++)
- X if ( SubStrs[i] )
- X printf(" #%2d: '%s'\n", i, SubStrs[i]);
- X }
- X }
- X return( 0 );
- X}
- END_OF_FILE
- if test 1892 -ne `wc -c <'retest.c'`; then
- echo shar: \"'retest.c'\" unpacked with wrong size!
- fi
- # end of 'retest.c'
- fi
- if test -f 'summary.doc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'summary.doc'\"
- else
- echo shar: Extracting \"'summary.doc'\" \(6853 characters\)
- sed "s/^X//" >'summary.doc' <<'END_OF_FILE'
- XUNPOST Version 2.1.0
- X
- XMore bug fixes, documentation updates, a new configuration file, etc.
- X
- XUNPOST is a "smart" uudecoder that is designed to extract binaries from
- Xmulti-part USENET or email uuencoded binaries.
- X
- XFeatures:
- X
- X1) PORTABILITY! UNPOST has been compiled and sucessfully run on
- X MS-DOS, OS/2, Windows, Unix workstations, MacIntoshes, Amiga's
- X and VAX/VMS systems.
- X
- X The code is written to be pure ANSI C, within reasonable limits.
- X (some ANSI C capabilities are not used where they would be
- X appropriate due to lagging compliance in most compilers. Hey,
- X Unix types! MS-DOS (Borland C++ 3.1) is a MUCH better compiler
- X than anything I've seen on a Unix workstation! And their debugger
- X is the best I've used, as well). Unfortunately, there are still
- X a lot of Unix boxes that have only a K&R compiler, so it may
- X not port well to those. I personally check to make sure that it
- X will compile and run on an MS-DOS box running MS-DOS 5 and Windows
- X 3.1, using the Borland 3.1 C++ compiler, as well as a Sun (running
- X SunOs 4.1.1 sun4c) using the gcc compiler (version 2.1). I know
- X for a fact that the Sun cc compiler will NOT compile UNPOST
- X succesfully.
- X
- X K&R compatibility is being considered, but it is a low priority
- X feature.
- X
- X2) CONFIGURABILITY! UNPOST comes with a default set of rules for
- X detecting and parsing a VERY wide range of possible Subject:
- X line formats, but no configuration can be correct for every
- X situation.
- X
- X With that in mind, UNPOST can be configured by the user by creating
- X a text file that contains the regular expressions, etc. that
- X UNPOST uses to recognize, parse, etc. WARNING! UNPOST depends
- X almost ENTIRELY on the contents of it's configuration file for
- X correct operation.
- X
- X Regular expressions are complex, and writing one that works the
- X way you expect it to takes care and, most importantly,
- X experimentation.
- X
- X To this end, the standard UNPOST installation creates both the
- X UNPOST executable and a regular expression test program called
- X RETEST. RETEST is like grep, feed it a regular expression and
- X a file, and RETEST will tell you what it matched and the sub
- X strings that it extracted.
- X
- X3) INTELLIGENCE! UNPOST uses every trick in the book to try to
- X guess what the poster/sender REALLY meant.
- X
- X Also, UNPOST is not limited to finding all of it's information
- X on a single line, or even in the header of a posting/letter.
- X
- X UNPOST has succesfully extracted binaries from postings that had,
- X as a subject line,
- X
- X Subject: aaaa
- X
- X because UNPOST recognized the signature placed into the body of
- X the article by a uuencode/split program.
- X
- X4) FLEXIBILITY! UNPOST has switches that allow it to be configured
- X to do different things for different tastes. For instance, UNPOST
- X will intelligently sort out articles into four different classes:
- X
- X 1) Articles that are part of a complete and correct binary in
- X the input file. These are sorted, concatenated, uudecoded
- X and written out to a file name that is the same as that
- X on the uuencode begin line.
- X
- X Depending on the setting of the file name switch, the file
- X name of the binary may be modified. See below.
- X
- X 2) Articles that are pure text (no uuencoded data in them).
- X
- X If the -t switch and a file name are specified, these
- X articles will be written out to the file for reading.
- X
- X Obviously, these articles should NEVER be encountered in
- X a binaries news group, but not a single day has ever gone
- X by that I did not see non-binary postings to binary news
- X groups.
- X
- X 3) Articles that are part of incomplete postings (four parts,
- X but only three have shown up so far), or that comprise
- X a complete binary, but one that had an error in uudecoding,
- X interpretation, etc.
- X
- X If the -i flag and a file name are specified, these articles
- X will be written out to the file. If the -b switch is
- X on, incompletes will be written to separate files. If
- X both are on, those incompletes that can be guessed at
- X as having a file name will be written to a separate file,
- X all else will be written to the file named by the -i
- X switch.
- X
- X In my experience, two types of articles end up in an
- X incompletes file, those that have missing parts, and
- X those that have been misinterpreted by UNPOST as belonging
- X to a different binary than they really do.
- X
- X 4) Articles that are pure text that describe a posting
- X (these are usually found only in the pictures groups).
- X
- X If the -d flag is set, and the binary to which they
- X belong is correct and complete, this article, as well as
- X the header and body up to the uuencode begin line of the
- X first article, will be written to a file that has the same
- X base name as the binary, but with the extension .inf.
- X
- X UNPOST automatically mungles binary file names to be MS-DOS
- X compatible (the lowest common denominator). This is switch
- X controllable, and can be turned on or off (depending on the
- X default setting selected by the person who compiled UNPOST).
- X
- X UNPOST also has two lesser modes, sorted mode and uudecode mode.
- X
- X In sorted mode, UNPOST assumes that the articles still have
- X headers, and that there may be un-uuencoded lines in the middle
- X of a uuencoded file that have to be filtered out, but it assumes
- X that all parts are present, and that they are in order. Header
- X information, however, is ignored.
- X
- X If you use the incompletes file capability of UNPOST, you will
- X notice that it writes out the segments that it did interpret
- X correctly in sorted order.
- X
- X In uudecode mode, UNPOST acts like a simple uudecoder. UUencoded
- X files must be complete, with a begin and end line, and no
- X un-uuencoded lines can appear between the begin and end lines.
- X
- X However, uudecode mode is the ONLY mode where UNPOST will accept
- X a short line (one that was space terminated, but had the spaces
- X chopped off) as a legal uuencoded line and properly decode it.
- X
- X5) INFORMATIVE! UNPOST is a very talkative program. It detects
- X and reports many kinds of problems, tells you what it thinks
- X is going on, and tells you what it is doing. All this information
- X is written to standard error, or if the -e switch and a file
- X name are specified, written to that file.
- X
- XChanges for UNPOST Version 2.1.2
- X--------------------------------
- X
- X1) Bug fix. I screwed up the regular expression compilation for the
- X -r switch. Fixed. See note 5 for version 2.1.1 in the changes.doc
- X file for information on how to select one of four sources for your
- X news.
- X
- Xjstevens@csn.org
- END_OF_FILE
- if test 6853 -ne `wc -c <'summary.doc'`; then
- echo shar: \"'summary.doc'\" unpacked with wrong size!
- fi
- # end of 'summary.doc'
- fi
- if test -f 'utils.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'utils.c'\"
- else
- echo shar: Extracting \"'utils.c'\" \(3764 characters\)
- sed "s/^X//" >'utils.c' <<'END_OF_FILE'
- X/******************************************************************************
- X* Module : Utility Routines --- Replacement functions for compiler
- X* library functions. This module exists to avoid having to
- X* if def the hell out of the code for systems that, for
- X* example, have bcopy, but not memmove.
- X*
- X* Author : John W. M. Stevens
- X******************************************************************************/
- X
- X#include "compiler.h"
- X
- X#include "utils.h"
- X
- X/*-----------------------------------------------------------------------------
- X| Routine : StrDup() --- String duplication function.
- X|
- X| Inputs : Str - A pointer to the string to duplicate.
- X-----------------------------------------------------------------------------*/
- X
- Xchar *StrDup(char *Str)
- X{
- X register int StrLen;
- X auto char *Tmp;
- X extern FILE *ErrFile;
- X
- X /* Determine lenght of string to duplicate. */
- X StrLen = strlen( Str ) + 1;
- X
- X /* Allocate the memory. */
- X if ((Tmp = calloc(1, StrLen)) == NULL)
- X {
- X fprintf(ErrFile,
- X "%s %d : Error - out of memory.\n",
- X __FILE__,
- X __LINE__);
- X exit( 1 );
- X }
- X
- X /* Copy string contents in. */
- X strcpy(Tmp, Str);
- X return( Tmp );
- X}
- X
- X/*-----------------------------------------------------------------------------
- X| Routine : FileExists() --- Check to see if a file already exists.
- X|
- X| Inputs : FlName - Name of file.
- X|
- X| Returns : Returns zero for file does not exist, non-zero for it does.
- X-----------------------------------------------------------------------------*/
- X
- Xint FileExists(char *FlName)
- X{
- X auto FILE *fp;
- X
- X /* Attempt to open the file as read only to determine if it exists.
- X * Don't you wish that ANSI C had a standard library function for
- X * this?
- X */
- X if ((fp = fopen(FlName, TXT_READ)) != NULL)
- X {
- X /* It exists, so close it and return. */
- X fclose( fp );
- X return( 1 );
- X }
- X return( 0 );
- X}
- X
- X/*-----------------------------------------------------------------------------
- X| Routine : MemCopy() --- Copy memory.
- X|
- X| Inputs : Dest - Destination address.
- X| Source - Source address.
- X| NoBytes - Number of bytes to copy.
- X-----------------------------------------------------------------------------*/
- X
- Xvoid MemCopy(void *Dest,
- X void *Source,
- X int NoBytes)
- X{
- X register int i;
- X auto char *d;
- X auto char *s;
- X
- X /* Copy bytes. */
- X for (d = (char *) Dest, s = (char *) Source, i = 0;
- X i < NoBytes;
- X i++)
- X *d++ = *s++;
- X}
- X
- X/*-----------------------------------------------------------------------------
- X| Routine : MemMove() --- Move memory, taking into account possible
- X| overlap.
- X|
- X| Inputs : Dest - Destination address.
- X| Source - Source address.
- X| NoBytes - Number of bytes to copy.
- X-----------------------------------------------------------------------------*/
- X
- Xvoid MemMove(void *Dest,
- X void *Source,
- X int NoBytes)
- X{
- X register int i;
- X auto char *d;
- X auto char *s;
- X
- X /* Pointer conversion. */
- X d = (char *) Dest;
- X s = (char *) Source;
- X
- X /* Check copy direction. */
- X if (d < s)
- X {
- X /* Copy up. */
- X for (i = 0; i < NoBytes; i++)
- X *d++ = *s++;
- X }
- X else if (d > s)
- X {
- X /* Copy down. */
- X for (d += NoBytes - 1, s += NoBytes - 1, i = 0;
- X i < NoBytes;
- X i++)
- X *d-- = *s--;
- X }
- X}
- END_OF_FILE
- if test 3764 -ne `wc -c <'utils.c'`; then
- echo shar: \"'utils.c'\" unpacked with wrong size!
- fi
- # end of 'utils.c'
- fi
- if test -f 'utils/trie.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'utils/trie.c'\"
- else
- echo shar: Extracting \"'utils/trie.c'\" \(6820 characters\)
- sed "s/^X//" >'utils/trie.c' <<'END_OF_FILE'
- X/*****************************************************************************
- X* Program: Trie --- Create a trie in a 'C' compiler readable format.
- X*
- X* Author : John W. M. Stevens
- X*****************************************************************************/
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <fcntl.h>
- X#include <string.h>
- X#include <strings.h>
- X
- X/* Type definition. */
- Xtypedef struct {
- X char c;
- X char *val;
- X struct trie *branch;
- X} KEY;
- X
- Xtypedef struct trie {
- X int NoEls;
- X int Size;
- X char Lbl[10];
- X KEY Keys[1];
- X} TRIE;
- X
- Xstatic TRIE *Head = NULL;
- X
- X/*----------------------------------------------------------------------------
- X| Routine: TrieIns() --- Insert a string into the trie.
- X|
- X| Inputs : Trie - The trie to insert into.
- X| str - The string to insert.
- X| val - The value string for this key string.
- X| Outputs: Returns the pointer to the trie level.
- X----------------------------------------------------------------------------*/
- X
- Xstatic long LblNo = 0L;
- X
- XTRIE *TrieIns(TRIE *Trie,
- X char *str,
- X char *val)
- X{
- X register int i;
- X register int j;
- X
- X auto int hi;
- X auto int lo;
- X auto int ret;
- X
- X /* Create a level if neccesary. */
- X if (Trie == NULL)
- X {
- X /* Calculate the size of the level in bytes. */
- X i = sizeof( TRIE ) + 4 * sizeof( KEY );
- X
- X /* Allocate a level. */
- X if ((Trie = malloc( i )) == NULL)
- X {
- X perror( "TrieIns (malloc) " );
- X return( NULL );
- X }
- X
- X /* Clear the memory to all zeros. */
- X memset((char *) Trie, '\0', i);
- X
- X /* Initialize the new trie level. */
- X Trie->NoEls = 1;
- X Trie->Size = 5;
- X Trie->Keys[0].c = *str++;
- X sprintf(Trie->Lbl, "%x", LblNo++);
- X
- X /* End of string? */
- X if ( *str )
- X {
- X Trie->Keys[0].val = "0";
- X Trie->Keys[0].branch = TrieIns(NULL, str, val);
- X }
- X else
- X Trie->Keys[0].val = val;
- X return( Trie );
- X }
- X
- X /* Search for the current character of the string to insert. */
- X hi = Trie->NoEls - 1;
- X lo = 0;
- X do
- X {
- X /* Find mid point of current array piece. */
- X i = (hi + lo) >> 1;
- X
- X /* Do character comparison. */
- X ret = *str - Trie->Keys[i].c;
- X
- X /* Shrink the search limits. */
- X if (ret <= 0)
- X hi = i - 1;
- X if (ret >= 0)
- X lo = i + 1;
- X
- X } while (hi >= lo);
- X
- X /* Did we find the character? */
- X if (ret == 0)
- X {
- X /* Yes, continue the search. */
- X if ( *++str )
- X Trie->Keys[i].branch = TrieIns(Trie->Keys[i].branch, str, val);
- X return( Trie );
- X }
- X
- X /* If the trie level is not big enough, reallocate it. */
- X if (Trie->Size == Trie->NoEls)
- X {
- X /* Calculate the size of the new level. */
- X i = sizeof( TRIE ) + (5 + Trie->Size) * sizeof( KEY );
- X
- X /* Attempt to reallocate the trie level. */
- X if ((Trie = realloc(Trie, i)) == NULL)
- X {
- X perror( "TrieIns (realloc) " );
- X return( NULL );
- X }
- X
- X /* Up the size of the trie level. */
- X Trie->Size += 5;
- X }
- X
- X /* Make room for new character. */
- X if (hi < Trie->NoEls - 1)
- X {
- X j = sizeof( KEY ) * (Trie->NoEls - lo);
- X memmove(Trie->Keys + lo + 1,
- X Trie->Keys + lo,
- X j);
- X }
- X
- X /* Insert new object. */
- X i = lo;
- X Trie->Keys[i].c = *str++;
- X Trie->Keys[i].branch = NULL;
- X Trie->NoEls++;
- X
- X /* Continue insert if not at end of string. */
- X if ( *str )
- X {
- X Trie->Keys[i].val = "0";
- X Trie->Keys[i].branch = TrieIns(NULL, str, val);
- X }
- X else
- X Trie->Keys[i].val = val;
- X return( Trie );
- X
- X}
- X
- X/*----------------------------------------------------------------------------
- X| Routine: TrieDump() --- Dump the trie in a form usable by the 'C'
- X| compiler.
- X|
- X| Inputs : Trie - The trie to dump.
- X| Lable - Trie level label.
- X| Outputs: Returns the pointer to the trie level.
- X----------------------------------------------------------------------------*/
- X
- Xvoid TrieDump(TRIE *Trie)
- X{
- X register int i;
- X register int j;
- X auto char NxtLbl[12];
- X
- X /* Do a post order traversal of tree. */
- X for (i = j = 0; i < Trie->NoEls; i++)
- X {
- X /* Check for children. */
- X if (Trie->Keys[i].branch == NULL)
- X continue;
- X
- X /* Do current branch. */
- X TrieDump( Trie->Keys[i].branch );
- X }
- X
- X /* Print label for this level. */
- X printf("static\nKEY\tT%s[%d] = {\n", Trie->Lbl, Trie->NoEls + 1);
- X printf("\t{\t' ',\t%15d,\t%-20s\t}", Trie->NoEls + 1, "NULL");
- X
- X /* Dump current level. */
- X for (i = j = 0; i < Trie->NoEls; i++)
- X {
- X /* Check for children. */
- X printf(",\n\t");
- X if (Trie->Keys[i].branch == NULL)
- X {
- X printf("{\t'%c',\t%15s,\t%-20s\t}", Trie->Keys[i].c,
- X Trie->Keys[i].val, "NULL");
- X continue;
- X }
- X
- X /* Print the key. */
- X printf("{\t'%c',\t%15s,\tT%-19s\t}", Trie->Keys[i].c,
- X Trie->Keys[i].val, Trie->Keys[i].branch->Lbl);
- X }
- X printf("\n};\n\n");
- X
- X}
- X
- Xvoid main(int argc,
- X char *argv[])
- X{
- X auto FILE *fp;
- X auto char bf[256];
- X auto char *tp;
- X auto char *token;
- X auto char *val;
- X
- X /* Check the number of command line parameters. */
- X if (argc != 2)
- X {
- X fprintf(stderr, "Syntax error: trie <token file>\n");
- X exit( -1 );
- X }
- X
- X /* Open the token file for reading. */
- X if ((fp = fopen(argv[1], "rt")) == NULL)
- X {
- X perror( "trie (fopen) " );
- X exit( -1 );
- X }
- X
- X /* Get and insert all strings into the trie. */
- X while ( fgets(bf, 256, fp) )
- X {
- X /* Strip white space. */
- X tp = bf;
- X while (*tp == ' ' || *tp == '\t')
- X tp++;
- X
- X /* Find end of token. */
- X token = tp;
- X while (*tp != ' ' && *tp != '\t' && *tp != '\n')
- X tp++;
- X *tp++ = '\0';
- X
- X /* Strip white space. */
- X while (*tp == ' ' || *tp == '\t')
- X tp++;
- X
- X /* Find end of the value string. */
- X val = tp;
- X while (*tp != ' ' && *tp != '\t' && *tp != '\n')
- X tp++;
- X *tp = '\0';
- X
- X /* Duplicate the value string. */
- X if ((val = strdup( val )) == NULL)
- X {
- X perror( "trie (strdup) " );
- X exit( -1 );
- X }
- X
- X /* Do string insert into trie. */
- X Head = TrieIns(Head, token, val);
- X }
- X
- X TrieDump( Head );
- X}
- END_OF_FILE
- if test 6820 -ne `wc -c <'utils/trie.c'`; then
- echo shar: \"'utils/trie.c'\" unpacked with wrong size!
- fi
- # end of 'utils/trie.c'
- fi
- echo shar: End of archive 6 \(of 7\).
- cp /dev/null ark6isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 7 archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-