From:	MERC::"uunet!WKUVX1.BITNET!FILESERV-Mgr" 12-JUN-1992 15:45:05.66
To:	galaxy::gleeve
CC:	
Subj:	FGREP.04_OF_06

-+-+-+-+-+-+-+-+ START OF PART 4 -+-+-+-+-+-+-+-+
X   This is here for debugging.
X   If you use it in a program, you are probably losing.  */
X
Xint
X_obstack_allocated_p (h, obj)
X     struct obstack *h;
X     POINTER obj;
X`7B
X  register struct _obstack_chunk*  lp;`09/* below addr of any objects in thi
Vs chunk */
X  register struct _obstack_chunk*  plp;`09/* point to previous chunk if any
V */
X
X  lp = (h)->chunk;
X  while (lp != 0 && ((POINTER)lp > obj `7C`7C (POINTER)(lp)->limit < obj))
X    `7B
X      plp = lp -> prev;
X      lp = plp;
X    `7D
X  return lp != 0;
X`7D
X
X/* Free objects in obstack H, including OBJ and everything allocate
X   more recently than OBJ.  If OBJ is zero, free everything in H.  */
X
Xvoid
X#ifdef __STDC__
X#undef obstack_free
Xobstack_free (struct obstack *h, POINTER obj)
X#else
X_obstack_free (h, obj)
X     struct obstack *h;
X     POINTER obj;
X#endif
X`7B
X  register struct _obstack_chunk*  lp;`09/* below addr of any objects in thi
Vs chunk */
X  register struct _obstack_chunk*  plp;`09/* point to previous chunk if any
V */
X
X  lp = (h)->chunk;
X  while (lp != 0 && ((POINTER)lp > obj `7C`7C (POINTER)(lp)->limit < obj))
X    `7B
X      plp = lp -> prev;
X      (*h->freefun) (lp);
X      lp = plp;
X    `7D
X  if (lp)
X    `7B
X      (h)->object_base = (h)->next_free = (char *)(obj);
X      (h)->chunk_limit = lp->limit;
X      (h)->chunk = lp;
X    `7D
X  else if (obj != 0)
X    /* obj is not in any of the chunks! */
X    abort ();
X`7D
X
X/* Let same .o link with output of gcc and other compilers.  */
X
X#ifdef __STDC__
Xvoid
X_obstack_free (h, obj)
X     struct obstack *h;
X     POINTER obj;
X`7B
X  obstack_free (h, obj);
X`7D
X#endif
X`0C
X#if 0
X/* These are now turned off because the applications do not use it
X   and it uses bcopy via obstack_grow, which causes trouble on sysV.  */
X
X/* Now define the functional versions of the obstack macros.
X   Define them to simply use the corresponding macros to do the job.  */
X
X#ifdef __STDC__
X/* These function definitions do not work with non-ANSI preprocessors;
X   they won't pass through the macro names in parentheses.  */
X
X/* The function names appear in parentheses in order to prevent
X   the macro-definitions of the names from being expanded there.  */
X
XPOINTER (obstack_base) (obstack)
X     struct obstack *obstack;
X`7B
X  return obstack_base (obstack);
X`7D
X
XPOINTER (obstack_next_free) (obstack)
X     struct obstack *obstack;
X`7B
X  return obstack_next_free (obstack);
X`7D
X
Xint (obstack_object_size) (obstack)
X     struct obstack *obstack;
X`7B
X  return obstack_object_size (obstack);
X`7D
X
Xint (obstack_room) (obstack)
X     struct obstack *obstack;
X`7B
X  return obstack_room (obstack);
X`7D
X
Xvoid (obstack_grow) (obstack, pointer, length)
X     struct obstack *obstack;
X     POINTER pointer;
X     int length;
X`7B
X  obstack_grow (obstack, pointer, length);
X`7D
X
Xvoid (obstack_grow0) (obstack, pointer, length)
X     struct obstack *obstack;
X     POINTER pointer;
X     int length;
X`7B
X  obstack_grow0 (obstack, pointer, length);
X`7D
X
Xvoid (obstack_1grow) (obstack, character)
X     struct obstack *obstack;
X     int character;
X`7B
X  obstack_1grow (obstack, character);
X`7D
X
Xvoid (obstack_blank) (obstack, length)
X     struct obstack *obstack;
X     int length;
X`7B
X  obstack_blank (obstack, length);
X`7D
X
Xvoid (obstack_1grow_fast) (obstack, character)
X     struct obstack *obstack;
X     int character;
X`7B
X  obstack_1grow_fast (obstack, character);
X`7D
X
Xvoid (obstack_blank_fast) (obstack, length)
X     struct obstack *obstack;
X     int length;
X`7B
X  obstack_blank_fast (obstack, length);
X`7D
X
XPOINTER (obstack_finish) (obstack)
X     struct obstack *obstack;
X`7B
X  return obstack_finish (obstack);
X`7D
X
XPOINTER (obstack_alloc) (obstack, length)
X     struct obstack *obstack;
X     int length;
X`7B
X  return obstack_alloc (obstack, length);
X`7D
X
XPOINTER (obstack_copy) (obstack, pointer, length)
X     struct obstack *obstack;
X     POINTER pointer;
X     int length;
X`7B
X  return obstack_copy (obstack, pointer, length);
X`7D
X
XPOINTER (obstack_copy0) (obstack, pointer, length)
X     struct obstack *obstack;
X     POINTER pointer;
X     int length;
X`7B
X  return obstack_copy0 (obstack, pointer, length);
X`7D
X
X#endif /* __STDC__ */
X
X#endif /* 0 */
$ CALL UNPACK [.FGREP011]OBSTACK.C;1 67124194
$ create 'f'
X/* obstack.h - object stack macros
X   Copyright (C) 1988 Free Software Foundation, Inc.
X
XThis program is free software; you can redistribute it and/or modify it
Xunder the terms of the GNU General Public License as published by the
XFree Software Foundation; either version 1, or (at your option) any
Xlater version.
X
XThis program is distributed in the hope that it will be useful,
Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
XGNU General Public License for more details.
X
XYou should have received a copy of the GNU General Public License
Xalong with this program; if not, write to the Free Software
XFoundation, 675 Mass Ave, Cambridge, MA 02139, USA.
X
X
XIn other words, you are welcome to use, share and improve this program.
XYou are forbidden to forbid anyone else to use, share and improve
Xwhat you give them.   Help stamp out software-hoarding!  */
X
X
X/* Summary:
X
XAll the apparent functions defined here are macros. The idea
Xis that you would use these pre-tested macros to solve a
Xvery specific set of problems, and they would run fast.
XCaution: no side-effects in arguments please!! They may be
Xevaluated MANY times!!
X
XThese macros operate a stack of objects.  Each object starts life
Xsmall, and may grow to maturity.  (Consider building a word syllable
Xby syllable.)  An object can move while it is growing.  Once it has
Xbeen "finished" it never changes address again.  So the "top of the
Xstack" is typically an immature growing object, while the rest of the
Xstack is of mature, fixed size and fixed address objects.
X
XThese routines grab large chunks of memory, using a function you
Xsupply, called `60obstack_chunk_alloc'.  On occasion, they free chunks,
Xby calling `60obstack_chunk_free'.  You must define them and declare
Xthem before using any obstack macros.
X
XEach independent stack is represented by a `60struct obstack'.
XEach of the obstack macros expects a pointer to such a structure
Xas the first argument.
X
XOne motivation for this package is the problem of growing char strings
Xin symbol tables.  Unless you are "fascist pig with a read-only mind"
X`5BGosper's immortal quote from HAKMEM item 154, out of context`5D you
Xwould not like to put any arbitrary upper limit on the length of your
Xsymbols.
X
XIn practice this often means you will build many short symbols and a
Xfew long symbols.  At the time you are reading a symbol you don't know
Xhow long it is.  One traditional method is to read a symbol into a
Xbuffer, realloc()ating the buffer every time you try to read a symbol
Xthat is longer than the buffer.  This is beaut, but you still will
Xwant to copy the symbol from the buffer to a more permanent
Xsymbol-table entry say about half the time.
X
XWith obstacks, you can work differently.  Use one obstack for all symbol
Xnames.  As you read a symbol, grow the name in the obstack gradually.
XWhen the name is complete, finalize it.  Then, if the symbol exists already,
Xfree the newly read name.
X
XThe way we do this is to take a large chunk, allocating memory from
Xlow addresses.  When you want to build a symbol in the chunk you just
Xadd chars above the current "high water mark" in the chunk.  When you
Xhave finished adding chars, because you got to the end of the symbol,
Xyou know how long the chars are, and you can create a new object.
XMostly the chars will not burst over the highest address of the chunk,
Xbecause you would typically expect a chunk to be (say) 100 times as
Xlong as an average object.
X
XIn case that isn't clear, when we have enough chars to make up
Xthe object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
Xso we just point to it where it lies.  No moving of chars is
Xneeded and this is the second win: potentially long strings need
Xnever be explicitly shuffled. Once an object is formed, it does not
Xchange its address during its lifetime.
X
XWhen the chars burst over a chunk boundary, we allocate a larger
Xchunk, and then copy the partly formed object from the end of the old
Xchunk to the beginning of the new larger chunk.  We then carry on
Xaccreting characters to the end of the object as we normally would.
X
XA special macro is provided to add a single char at a time to a
Xgrowing object.  This allows the use of register variables, which
Xbreak the ordinary 'growth' macro.
X
XSummary:
X`09We allocate large chunks.
X`09We carve out one object at a time from the current chunk.
X`09Once carved, an object never moves.
X`09We are free to append data of any size to the currently
X`09  growing object.
X`09Exactly one object is growing in an obstack at any one time.
X`09You can run one obstack per control block.
X`09You may have as many control blocks as you dare.
X`09Because of the way we do it, you can `60unwind' a obstack
X`09  back to a previous state. (You may remove objects much
X`09  as you would with a stack.)
X*/
X
X
X/* Don't do the contents of this file more than once.  */
X
X#ifndef __OBSTACKS__
X#define __OBSTACKS__
X`0C
X/* We use subtraction of (char *)0 instead of casting to int
X   because on word-addressable machines a simple cast to int
X   may ignore the byte-within-word field of the pointer.  */
X
X#ifndef __PTR_TO_INT
X#define __PTR_TO_INT(P) ((P) - (char *)0)
X#endif
X
X#ifndef __INT_TO_PTR
X#define __INT_TO_PTR(P) ((P) + (char *)0)
X#endif
X
Xstruct _obstack_chunk`09`09/* Lives at front of each chunk. */
X`7B
X  char  *limit;`09`09`09/* 1 past end of this chunk */
X  struct _obstack_chunk *prev;`09/* address of prior chunk or NULL */
X  char`09contents`5B4`5D;`09`09/* objects begin here */
X`7D;
X
Xstruct obstack`09`09/* control current object in current chunk */
X`7B
X  long`09chunk_size;`09`09/* preferred size to allocate chunks in */
X  struct _obstack_chunk* chunk;`09/* address of current struct obstack_chunk
V */
X  char`09*object_base;`09`09/* address of object we are building */
X  char`09*next_free;`09`09/* where to add next char to current object */
X  char`09*chunk_limit;`09`09/* address of char after current chunk */
X  int`09temp;`09`09`09/* Temporary for some macros.  */
X  int   alignment_mask;`09`09/* Mask of alignment for each object. */
X  struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk.
V  */
X  void (*freefun) ();`09`09/* User's function to free a chunk.  */
X`7D;
X`0C
X#ifdef __STDC__
X
X/* Do the function-declarations after the structs
X   but before defining the macros.  */
X
Xvoid obstack_init (struct obstack *obstack);
X
Xvoid * obstack_alloc (struct obstack *obstack, int size);
X
Xvoid * obstack_copy (struct obstack *obstack, void *address, int size);
Xvoid * obstack_copy0 (struct obstack *obstack, void *address, int size);
X
Xvoid obstack_free (struct obstack *obstack, void *block);
X
Xvoid obstack_blank (struct obstack *obstack, int size);
X
Xvoid obstack_grow (struct obstack *obstack, void *data, int size);
Xvoid obstack_grow0 (struct obstack *obstack, void *data, int size);
X
Xvoid obstack_1grow (struct obstack *obstack, int data_char);
Xvoid obstack_ptr_grow (struct obstack *obstack, void *data);
Xvoid obstack_int_grow (struct obstack *obstack, int data);
X
Xvoid * obstack_finish (struct obstack *obstack);
X
Xint obstack_object_size (struct obstack *obstack);
X
Xint obstack_room (struct obstack *obstack);
Xvoid obstack_1grow_fast (struct obstack *obstack, int data_char);
Xvoid obstack_ptr_grow_fast (struct obstack *obstack, void *data);
Xvoid obstack_int_grow_fast (struct obstack *obstack, int data);
Xvoid obstack_blank_fast (struct obstack *obstack, int size);
X
Xvoid * obstack_base (struct obstack *obstack);
Xvoid * obstack_next_free (struct obstack *obstack);
Xint obstack_alignment_mask (struct obstack *obstack);
Xint obstack_chunk_size (struct obstack *obstack);
X
X#endif /* __STDC__ */
X
X/* Non-ANSI C cannot really support alternative functions for these macros,
X   so we do not declare them.  */
X`0C
X/* Pointer to beginning of object being allocated or to be allocated next.
X   Note that this might not be the final address of the object
X   because a new chunk might be needed to hold the final size.  */
X
X#define obstack_base(h) ((h)->object_base)
X
X/* Size for allocating ordinary chunks.  */
X
X#define obstack_chunk_size(h) ((h)->chunk_size)
X
X/* Pointer to next byte not yet allocated in current chunk.  */
X
X#define obstack_next_free(h)`09((h)->next_free)
X
X/* Mask specifying low bits that should be clear in address of an object.  *
V/
X
X#define obstack_alignment_mask(h) ((h)->alignment_mask)
X
X#define obstack_init(h) \
X  _obstack_begin ((h), 0, 0, obstack_chunk_alloc, obstack_chunk_free)
X
X#define obstack_begin(h, size) \
X  _obstack_begin ((h), (size), 0, obstack_chunk_alloc, obstack_chunk_free)
X
X#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
X
X#define obstack_blank_fast(h,n) ((h)->next_free += (n))
X`0C
X#if defined (__GNUC__) && defined (__STDC__)
X
X/* For GNU C, if not -traditional,
X   we can define these macros to compute all args only once
X   without using a global variable.
X   Also, we can avoid using the `60temp' slot, to make faster code.  */
X
X#define obstack_object_size(OBSTACK)`09`09`09`09`09\
X  (`7B struct obstack *__o = (OBSTACK);`09`09`09`09`09\
X     (unsigned) (__o->next_free - __o->object_base); `7D)
X
X#define obstack_room(OBSTACK)`09`09`09`09`09`09\
X  (`7B struct obstack *__o = (OBSTACK);`09`09`09`09`09\
X     (unsigned) (__o->chunk_limit - __o->next_free); `7D)
X
X#define obstack_grow(OBSTACK,where,length)`09`09`09`09\
X(`7B struct obstack *__o = (OBSTACK);`09`09`09`09`09\
X   int __len = (length);`09`09`09`09`09`09\
X   ((__o->next_free + __len > __o->chunk_limit)`09`09`09`09\
X    ? _obstack_newchunk (__o, __len) : 0);`09`09`09`09\
X   bcopy (where, __o->next_free, __len);`09`09`09`09\
X   __o->next_free += __len;`09`09`09`09`09`09\
X   (void) 0; `7D)
X
X#define obstack_grow0(OBSTACK,where,length)`09`09`09`09\
X(`7B struct obstack *__o = (OBSTACK);`09`09`09`09`09\
X   int __len = (length);`09`09`09`09`09`09\
X   ((__o->next_free + __len + 1 > __o->chunk_limit)`09`09`09\
X    ? _obstack_newchunk (__o, __len + 1) : 0),`09`09`09`09\
X   bcopy (where, __o->next_free, __len),`09`09`09`09\
X   __o->next_free += __len,`09`09`09`09`09`09\
X   *(__o->next_free)++ = 0;`09`09`09`09`09`09\
X   (void) 0; `7D)
X
X#define obstack_1grow(OBSTACK,datum)`09`09`09`09`09\
X(`7B struct obstack *__o = (OBSTACK);`09`09`09`09`09\
X   ((__o->next_free + 1 > __o->chunk_limit)`09`09`09`09\
X    ? _obstack_newchunk (__o, 1) : 0),`09`09`09`09`09\
X   *(__o->next_free)++ = (datum);`09`09`09`09`09\
X   (void) 0; `7D)
X
X/* These assume that the obstack alignment is good enough for pointers or in
Vts,
X   and that the data added so far to the current object
X   shares that much alignment.  */
X  `20
X#define obstack_ptr_grow(OBSTACK,datum)`09`09`09`09`09\
X(`7B struct obstack *__o = (OBSTACK);`09`09`09`09`09\
X   ((__o->next_free + sizeof (void *) > __o->chunk_limit)`09`09\
X    ? _obstack_newchunk (__o, sizeof (void *)) : 0),`09`09`09\
X   *((void **)__o->next_free)++ = ((void *)datum);`09`09`09\
X   (void) 0; `7D)
X
X#define obstack_int_grow(OBSTACK,datum)`09`09`09`09`09\
X(`7B struct obstack *__o = (OBSTACK);`09`09`09`09`09\
X   ((__o->next_free + sizeof (int) > __o->chunk_limit)`09`09`09\
X    ? _obstack_newchunk (__o, sizeof (int)) : 0),`09`09`09\
X   *((int *)__o->next_free)++ = ((int)datum);`09`09`09`09\
X   (void) 0; `7D)
X
X#define obstack_ptr_grow_fast(h,aptr) (*((void **)(h)->next_free)++ = (void
V *)aptr)
X#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)ain
Vt)
X
X#define obstack_blank(OBSTACK,length)`09`09`09`09`09\
X(`7B struct obstack *__o = (OBSTACK);`09`09`09`09`09\
X   int __len = (length);`09`09`09`09`09`09\
X   ((__o->next_free + __len > __o->chunk_limit)`09`09`09`09\
X    ? _obstack_newchunk (__o, __len) : 0);`09`09`09`09\
X   __o->next_free += __len;`09`09`09`09`09`09\
X   (void) 0; `7D)
X
X#define obstack_alloc(OBSTACK,length)`09`09`09`09`09\
X(`7B struct obstack *__h = (OBSTACK);`09`09`09`09`09\
X   obstack_blank (__h, (length));`09`09`09`09`09\
X   obstack_finish (__h); `7D)
X
X#define obstack_copy(OBSTACK,where,length)`09`09`09`09\
X(`7B struct obstack *__h = (OBSTACK);`09`09`09`09`09\
X   obstack_grow (__h, (where), (length));`09`09`09`09\
X   obstack_finish (__h); `7D)
X
X#define obstack_copy0(OBSTACK,where,length)`09`09`09`09\
X(`7B struct obstack *__h = (OBSTACK);`09`09`09`09`09\
X   obstack_grow0 (__h, (where), (length));`09`09`09`09\
X   obstack_finish (__h); `7D)
X
X#define obstack_finish(OBSTACK)  `09`09`09`09`09\
X(`7B struct obstack *__o = (OBSTACK);`09`09`09`09`09\
X   void *value = (void *) __o->object_base;`09`09`09`09\
X   __o->next_free`09`09`09`09`09`09`09\
X     = __INT_TO_PTR ((__PTR_TO_INT (__o->next_free)+__o->alignment_mask)\
X`09`09     & `7E (__o->alignment_mask));`09`09`09\
X   ((__o->next_free - (char *)__o->chunk`09`09`09`09\
X     > __o->chunk_limit - (char *)__o->chunk)`09`09`09`09\
X    ? (__o->next_free = __o->chunk_limit) : 0);`09`09`09`09\
X   __o->object_base = __o->next_free;`09`09`09`09`09\
X   value; `7D)
X
X#define obstack_free(OBSTACK, OBJ)`09`09`09`09`09\
X(`7B struct obstack *__o = (OBSTACK);`09`09`09`09`09\
X   void *__obj = (OBJ);`09`09`09`09`09`09`09\
X   if (__obj >= (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
X     __o->next_free = __o->object_base = __obj;`09`09`09`09\
X   else (obstack_free) (__o, __obj); `7D)
X`0C
X#else /* not __GNUC__ or not __STDC__ */
X
X/* The non-GNU macros copy the obstack-pointer into this global variable
X   to avoid multiple evaluation.  */
X
Xextern struct obstack *_obstack;
X
X#define obstack_object_size(h) \
X (unsigned) (_obstack = (h), (h)->next_free - (h)->object_base)
X
X#define obstack_room(h)`09`09\
X (unsigned) (_obstack = (h), (h)->chunk_limit - (h)->next_free)
X
X#define obstack_grow(h,where,length)`09`09`09`09`09\
X( (h)->temp = (length),`09`09`09`09`09`09`09\
X  (((h)->next_free + (h)->temp > (h)->chunk_limit)`09`09`09\
X   ? _obstack_newchunk ((h), (h)->temp) : 0),`09`09`09`09\
X  bcopy (where, (h)->next_free, (h)->temp),`09`09`09`09\
X  (h)->next_free += (h)->temp)
X
X#define obstack_grow0(h,where,length)`09`09`09`09`09\
X( (h)->temp = (length),`09`09`09`09`09`09`09\
X  (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit)`09`09`09\
X   ? _obstack_newchunk ((h), (h)->temp + 1) : 0),`09`09`09`09\
X  bcopy (where, (h)->next_free, (h)->temp),`09`09`09`09\
X  (h)->next_free += (h)->temp,`09`09`09`09`09`09\
X  *((h)->next_free)++ = 0)
X
X#define obstack_1grow(h,datum)`09`09`09`09`09`09\
X( (((h)->next_free + 1 > (h)->chunk_limit)`09`09`09`09\
X   ? _obstack_newchunk ((h), 1) : 0),`09`09`09`09`09\
X  *((h)->next_free)++ = (datum))
X
X#define obstack_ptr_grow(h,datum)`09`09`09`09`09\
X( (((h)->next_free + sizeof (char *) > (h)->chunk_limit)`09`09\
X   ? _obstack_newchunk ((h), sizeof (char *)) : 0),`09`09`09\
X  *((char **)(h)->next_free)++ = ((char *)datum))
X
X#define obstack_int_grow(h,datum)`09`09`09`09`09\
X( (((h)->next_free + sizeof (int) > (h)->chunk_limit)`09`09`09\
X   ? _obstack_newchunk ((h), sizeof (int)) : 0),`09`09`09\
X  *((int *)(h)->next_free)++ = ((int)datum))
X
X#define obstack_ptr_grow_fast(h,aptr) (*((char **)(h)->next_free)++ = (char
V *)aptr)
X#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)ain
Vt)
X
X#define obstack_blank(h,length)`09`09`09`09`09`09\
X( (h)->temp = (length),`09`09`09`09`09`09`09\
X  (((h)->next_free + (h)->temp > (h)->chunk_limit)`09`09`09\
X   ? _obstack_newchunk ((h), (h)->temp) : 0),`09`09`09`09\
X  (h)->next_free += (h)->temp)
X
X#define obstack_alloc(h,length)`09`09`09`09`09`09\
X (obstack_blank ((h), (length)), obstack_finish ((h)))
X
X#define obstack_copy(h,where,length)`09`09`09`09`09\
X (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
X
X#define obstack_copy0(h,where,length)`09`09`09`09`09\
X (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
X
X#define obstack_finish(h)  `09`09`09`09`09`09\
X( (h)->temp = __PTR_TO_INT ((h)->object_base),`09`09`09`09\
X  (h)->next_free`09`09`09`09`09`09`09\
X    = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask)`09\
X`09`09    & `7E ((h)->alignment_mask)),`09`09`09`09\
X  (((h)->next_free - (char *)(h)->chunk`09`09`09`09`09\
X    > (h)->chunk_limit - (char *)(h)->chunk)`09`09`09`09\
X   ? ((h)->next_free = (h)->chunk_limit) : 0),`09`09`09`09\
X  (h)->object_base = (h)->next_free,`09`09`09`09`09\
X  __INT_TO_PTR ((h)->temp))
X
X#ifdef __STDC__
X#define obstack_free(h,obj)`09`09`09`09`09`09\
X( (h)->temp = (char *)(obj) - (char *) (h)->chunk,`09`09`09\
X  (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
X   ? (int) ((h)->next_free = (h)->object_base`09`09`09`09\
X`09    = (h)->temp + (char *) (h)->chunk)`09`09`09`09\
X   : ((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0)))
X#else
X#define obstack_free(h,obj)`09`09`09`09`09`09\
X( (h)->temp = (char *)(obj) - (char *) (h)->chunk,`09`09`09\
X  (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
X   ? (int) ((h)->next_free = (h)->object_base`09`09`09`09\
X`09    = (h)->temp + (char *) (h)->chunk)`09`09`09`09\
X   : (int) _obstack_free ((h), (h)->temp + (char *) (h)->chunk)))
X#endif
X
X#endif /* not __GNUC__ or not __STDC__ */
X
X#endif /* not __OBSTACKS__ */
X
$ CALL UNPACK [.FGREP011]OBSTACK.H;1 1059078521
$ create 'f'
XThis is GNU fgrep, version 1.1.  Eventually it will disappear into the
Xsingle grep program mandated by POSIX, but for now it should be a
Xcompatible replacement for UNIX fgrep.  The options are the same
Xas those of GNU egrep, and are a proper superset of the fgrep options
Xon all UNIX systems I am aware of.
X
XI have not tried comparing this performance-wise to any of the
Xvarious other free fgreps that are floating around, but it should
Xnever be any slower, and for demanding applications will probably
Xbe substantially faster.  For single fixed-string searches the
Xspeed is about the same as that of GNU egrep; for multiple fixed
Xstrings it is substantially faster.
X
XCorrespondence regarding this program should be addressed directly
Xto me, mike@ai.mit.edu, *not* bug-gnu-utils.  Enjoy.
X
X`09Mike Haertel
X`09mike@ai.mit.edu
$ CALL UNPACK [.FGREP011]README.;1 726036057
$ create 'f'
X/******************************************************************/
X
X#ifdef VAXC`09`09`09/* v1.2-004 */
X#module SHELL_MUNG "Jym V1.2-005"       /* Only VAX C understands this. */
X#else`09`09`09`09/* v1.2-004 */
X#define`09TRUE`09`091`09/* GNU C stdio.h doesn't define TRUE and FALSE*/
X#define`09FALSE`09`090
X#endif
X
X/* SHELL_MUNG.C
X**==========================================================================
V===
X** Copyright (C) 1989 Jym Dyer (jym@wheaties.ai.mit.edu)
X**
X** This program is free software; you can redistribute it and/or modify
X** it under the terms of the GNU General Public License as published by
X** the Free Software Foundation; either version 1, or (at your option)
X** any later version.
X**
X** This program is distributed in the hope that it will be useful,
X** but WITHOUT ANY WARRANTY; without even the implied warranty of
X** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X** GNU General Public License for more details.
X**
X** You should have received a copy of the GNU General Public License
X** along with this program; if not, write to the Free Software
X** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X**--------------------------------------------------------------------------
V---
X** Version:     V1.2-005
X**--------------------------------------------------------------------------
V---
X** Facility:    GNU
X**--------------------------------------------------------------------------
V---
X** Prefix:      SHELL_
X**--------------------------------------------------------------------------
V---
X** Abstract
X** `7E`7E`7E`7E`7E`7E`7E`7E
X**  If you think "shell mung" is a step in the preparation of a good mung da
Vhl,
X** you're right, but in this context "mung" is the verb.  ("Mung" historical
Vly
X** means "mung until no good," but one could easily interpret it to mean "mu
Vng
X** until nearly gnu".  Or something to that effect.)
X**  This file provides the shell_glob() and shell_mung() functions for the
X** VMS/DCL/VAX C user.  The shell_glob() function "globs" (parses filespecs
X** with wildcards and matches them with existing files).  The shell_mung()
X** function provides GNU-shell-like IO redirection and globbing:  it changes
X** `60stderr', `60stdin', and/or `60stdout' to do the IO redirection; it mun
Vgs a
X** VAX C program's main() function's `60argc' and `60argv' variables (using
V shell_
X** glob()) to do the globbing; and it truncates `60argv`5B0`5D' down to a fi
Vlename
X** and filetype or, if the file is a .EXE file, to just the filename.
X**  This makes it easy to port many GNU utilities to VMS, as these utilities
X** often expect the shell to have done the work that shell_mung() does.  It
V can
X** also be used to port Un*x utilities as well, if anybody cares.
X**--------------------------------------------------------------------------
V---
X** Functions
X** `7E`7E`7E`7E`7E`7E`7E`7E`7E
X** shell_glob()
X** shell_mung()
X** (static) truncate_argv_0()
X**--------------------------------------------------------------------------
V---
X** Environment
X** `7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E
X**  Must be linked with the VAX C RTL.  Intended for use with the DCL CLI on
X** VMS; it would be pointless to use shell_mung() with the SHELL CLI, though
X** shell_glob() might possibly come in handy.
X**  Must be linked with xmalloc() and xrealloc() functions, which are readil
Vy
X** available from GNU source code.  These are simply malloc() and realloc()
X** functions that exit if there is an error getting memory.
X**--------------------------------------------------------------------------
V---
X** Author:      Jym Dyer (jym@wheaties.ai.mit) 8-Apr-1988
X**--------------------------------------------------------------------------
V---
X** Modifications
X** `7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E
X** 1.0-001 - Original version.  Inspired by the DECUS C getredirection()
X**           function written by Martin Minow, Jerry Leichter, and Jym Dyer.
X**           `7BJym 8-Apr-1988`7D
X** 1.1-002 - Added `60shell_default' and use of same by shell_glob(), which
X**           allows default filespecs to be used in globbing.
X**           `7BJym 9-Jan-1989`7D
X** 1.2-003 - Made shell_glob() accept unglobbable filespecs.
X**         - In addition to '-', '+' is now accepted as the start of an opti
Von.
X**           `7BJym 3-Jun-1989`7D
X** 1.2-004 - Made changes to allow compilation by GNU C.
X**`09     `7BHunter Goatley, goathunter@WKUVX1.BITNET, 12-SEP-1991`7D
X** 1.2-005 - Added Andrew Greer's patch to fix problem parsing non-filespec
X**`09     arguments to options
X**`09     `7BHunter Goatley, goathunter@WKUVX1.BITNET, 22-SEP-1991`7D
X**`09     `7BAndrew Greer, <Andrew.Greer@vuw.ac.nz>`7D
X**==========================================================================
V===
X*/
X
X/* -=- FILE INCLUSIONS -=- */
X
X#include <ctype.h>
X#include <errno.h>
X#include <stdio.h>
X#include <string.h>
X
X#include <fab.h>
X#include <nam.h>
X#include <rmsdef.h>
X#include <stsdef.h>
X
X#ifndef VAXC`09`09`09`09/* v1.2-004 */
X#define _tolower(c)     ((c) >= 'A' && (c) <= 'Z' ? (c) `7C 0x20:(c))
X#endif`09`09`09/* Also changed tolower() calls to _tolower() */
X
X/* -=- FORWARD DECLARATIONS -=- */
X
Xextern void *  xmalloc();
Xextern void *  xrealloc();
X
Xextern void  sys$exit();
Xextern int  sys$parse();
Xextern int  sys$search();
X
Xextern char **  shell_glob();
Xstatic char *  truncate_argv_0();
X
X/* -=- GLOBAL VARIABLE DEFINITION -=- */
X
X#ifdef VAXC`09`09`09`09/* v1.2-004 */
Xglobaldef char *  shell_default = NULL; /* Default filespec for shell_glob()
V.*/
X#else
Xchar *  shell_default = NULL;`09`09/* Default filespec for shell_glob().*/
X#endif
X                                        /* Initialized here to NULL, which
X                                        ** means that no default filespec is
X                                        ** used by shell_glob().
X                                        */
X
X/* -=- FUNCTIONS -=- */
X
X/* shell_glob()
X**--------------------------------------------------------------------------
V---
X** Functional Description
X** `7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E
+-+-+-+-+-+-+-+-  END  OF PART 4 +-+-+-+-+-+-+-+-
