Thanks for the incredibly fast response Ralf -
The code you supplied has helped me to get around the problem.
By the way, I had to remove the lines:
> #ifndef emacs
> #define malloc xmalloc
> #endif
Otherwise xmalloc is an undefined symbol. The logic here seems to be the wrong
way around: according to the comment, only emacs needs xmalloc, so the #ifndef
should probably be #ifdef.
Best regards
- Paul.
> -----Original Message-----
> From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]]
> Sent: Monday, January 11, 1999 5:37 PM
> To: [EMAIL PROTECTED]
> Cc: [EMAIL PROTECTED]
> Subject: Re: Build problem: 'alloca' unresolved symbol on HPUX
>
>
> On Mon, Jan 11, 1999,
> [EMAIL PROTECTED] wrote:
>
> > I'm getting an unresolved symbol error for 'alloca' when
> linking mod_ssl 2.1.6
> > with Apache 1.3.3 on HP-UX 10. The make output looks like this:
> >
> > [snip]
> > cc -DHPUX10 -Aa -D_HPUX_SOURCE -DMOD_SSL=201106
> -DUSE_HSREGEX -DEAPI
> > `./apaci` -L/home/jupiter/dev/src/web/SSLeay-0.9.0b \
> > -o httpd buildmark.o modules.o modules/ssl/libssl.a
> > modules/standard/libstandard.a main/libmain.a
> ./os/unix/libos.a ap/libap.a
> > regex/libregex.a -lssl -lcrypto
> > /usr/ccs/bin/ld: (Warning) At least one PA 2.0 object file
> (buildmark.o) was
> > detected. The linked output may not run on a PA 1.x system.
> > /usr/ccs/bin/ld: Unsatisfied symbols:
> > alloca (code)
> > *** Error exit code 1
> > Stop.
> >
> > 'alloca' is used in ssl_expr_parse.c:
> > % cd src/modules/ssl
> > % nm ssl_expr_parse.o |grep alloca
> > alloca | |undef |code |
> >
> > The problem didn't happen with v2.0.14, could anyone
> explain how I should
> > resolve it, please?
>
> Hmmm.. the ssl_expr_parse.c is _generated_ by GNU Bison, so I
> cannot change it
> easily. A workaround for you is to compile an alloca()
> function yourself. I
> append you the source of GNU's alloca.c. This should at least
> solve the
> problem for you. But does anybody know how I can convince GNU
> Bison to not use
> alloca?
> Ralf S. Engelschall
> [EMAIL PROTECTED]
> www.engelschall.com
>
> /* alloca.c -- allocate automatically reclaimed memory
> (Mostly) portable public-domain implementation -- D A Gwyn
>
> This implementation of the PWB library alloca function,
> which is used to allocate space off the run-time stack so
> that it is automatically reclaimed upon procedure exit,
> was inspired by discussions with J. Q. Johnson of Cornell.
> J.Otto Tennant <[EMAIL PROTECTED]> contributed the Cray support.
>
> There are some preprocessor constants that can
> be defined when compiling for your specific system, for
> improved efficiency; however, the defaults should be okay.
>
> The general concept of this implementation is to keep
> track of all alloca-allocated blocks, and reclaim any
> that are found to be deeper in the stack than the current
> invocation. This heuristic does not reclaim storage as
> soon as it becomes invalid, but it will do so eventually.
>
> As a special case, alloca(0) reclaims storage without
> allocating any. It is a good idea to use alloca(0) in
> your main control loop, etc. to force garbage collection. */
>
> #ifdef HAVE_CONFIG_H
> #include <config.h>
> #endif
>
> #ifdef HAVE_STRING_H
> #include <string.h>
> #endif
> #ifdef HAVE_STDLIB_H
> #include <stdlib.h>
> #endif
>
> #ifdef emacs
> #include "blockinput.h"
> #endif
>
> /* If compiling with GCC 2, this file's not needed. */
> #if !defined (__GNUC__) || __GNUC__ < 2
>
> /* If someone has defined alloca as a macro,
> there must be some other way alloca is supposed to work. */
> #ifndef alloca
>
> #ifdef emacs
> #ifdef static
> /* actually, only want this if static is defined as ""
> -- this is for usg, in which emacs must undefine static
> in order to make unexec workable
> */
> #ifndef STACK_DIRECTION
> you
> lose
> -- must know STACK_DIRECTION at compile-time
> #endif /* STACK_DIRECTION undefined */
> #endif /* static */
> #endif /* emacs */
>
> /* If your stack is a linked list of frames, you have to
> provide an "address metric" ADDRESS_FUNCTION macro. */
>
> #if defined (CRAY) && defined (CRAY_STACKSEG_END)
> long i00afunc ();
> #define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
> #else
> #define ADDRESS_FUNCTION(arg) &(arg)
> #endif
>
> #if __STDC__
> typedef void *pointer;
> #else
> typedef char *pointer;
> #endif
>
> #ifndef NULL
> #define NULL 0
> #endif
>
> /* Different portions of Emacs need to call different versions of
> malloc. The Emacs executable needs alloca to call xmalloc, because
> ordinary malloc isn't protected from input signals. On the other
> hand, the utilities in lib-src need alloca to call malloc; some of
> them are very simple, and don't have an xmalloc routine.
>
> Non-Emacs programs expect this to call use xmalloc.
>
> Callers below should use malloc. */
>
> #ifndef emacs
> #define malloc xmalloc
> #endif
> extern pointer malloc ();
>
> /* Define STACK_DIRECTION if you know the direction of stack
> growth for your system; otherwise it will be automatically
> deduced at run-time.
>
> STACK_DIRECTION > 0 => grows toward higher addresses
> STACK_DIRECTION < 0 => grows toward lower addresses
> STACK_DIRECTION = 0 => direction of growth unknown */
>
> #ifndef STACK_DIRECTION
> #define STACK_DIRECTION 0 /* Direction unknown. */
> #endif
>
> #if STACK_DIRECTION != 0
>
> #define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
>
> #else /* STACK_DIRECTION == 0; need run-time code. */
>
> static int stack_dir; /* 1 or -1 once known. */
> #define STACK_DIR stack_dir
>
> static void
> find_stack_direction ()
> {
> static char *addr = NULL; /* Address of first `dummy', once
> known. */
> auto char dummy; /* To get stack address. */
>
> if (addr == NULL)
> { /* Initial entry. */
> addr = ADDRESS_FUNCTION (dummy);
>
> find_stack_direction (); /* Recurse once. */
> }
> else
> {
> /* Second entry. */
> if (ADDRESS_FUNCTION (dummy) > addr)
> stack_dir = 1; /* Stack grew upward. */
> else
> stack_dir = -1; /* Stack grew downward. */
> }
> }
>
> #endif /* STACK_DIRECTION == 0 */
>
> /* An "alloca header" is used to:
> (a) chain together all alloca'ed blocks;
> (b) keep track of stack depth.
>
> It is very important that sizeof(header) agree with malloc
> alignment chunk size. The following default should work okay. */
>
> #ifndef ALIGN_SIZE
> #define ALIGN_SIZE sizeof(double)
> #endif
>
> typedef union hdr
> {
> char align[ALIGN_SIZE]; /* To force sizeof(header). */
> struct
> {
> union hdr *next; /* For chaining headers. */
> char *deep; /* For stack depth measure. */
> } h;
> } header;
>
> static header *last_alloca_header = NULL; /* -> last alloca
> header. */
>
> /* Return a pointer to at least SIZE bytes of storage,
> which will be automatically reclaimed upon exit from
> the procedure that called alloca. Originally, this space
> was supposed to be taken from the current stack frame of the
> caller, but that method cannot be made to work for some
> implementations of C, for example under Gould's UTX/32. */
>
> pointer
> alloca (size)
> unsigned size;
> {
> auto char probe; /* Probes stack depth: */
> register char *depth = ADDRESS_FUNCTION (probe);
>
> #if STACK_DIRECTION == 0
> if (STACK_DIR == 0) /* Unknown growth direction. */
> find_stack_direction ();
> #endif
>
> /* Reclaim garbage, defined as all alloca'd storage that
> was allocated from deeper in the stack than currently. */
>
> {
> register header *hp; /* Traverses linked list. */
>
> #ifdef emacs
> BLOCK_INPUT;
> #endif
>
> for (hp = last_alloca_header; hp != NULL;)
> if ((STACK_DIR > 0 && hp->h.deep > depth)
> || (STACK_DIR < 0 && hp->h.deep < depth))
> {
> register header *np = hp->h.next;
>
> free ((pointer) hp); /* Collect garbage. */
>
> hp = np; /* -> next header. */
> }
> else
> break; /* Rest are not deeper. */
>
> last_alloca_header = hp; /* -> last valid storage. */
>
> #ifdef emacs
> UNBLOCK_INPUT;
> #endif
> }
>
> if (size == 0)
> return NULL; /* No allocation required. */
>
> /* Allocate combined header + user data storage. */
>
> {
> register pointer new = malloc (sizeof (header) + size);
> /* Address of header. */
>
> if (new == 0)
> abort();
>
> ((header *) new)->h.next = last_alloca_header;
> ((header *) new)->h.deep = depth;
>
> last_alloca_header = (header *) new;
>
> /* User storage begins just after header. */
>
> return (pointer) ((char *) new + sizeof (header));
> }
> }
>
> #if defined (CRAY) && defined (CRAY_STACKSEG_END)
>
> #ifdef DEBUG_I00AFUNC
> #include <stdio.h>
> #endif
>
> #ifndef CRAY_STACK
> #define CRAY_STACK
> #ifndef CRAY2
> /* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
> struct stack_control_header
> {
> long shgrow:32; /* Number of times stack has grown. */
> long shaseg:32; /* Size of increments to stack. */
> long shhwm:32; /* High water mark of stack. */
> long shsize:32; /* Current size of stack (all segments). */
> };
>
> /* The stack segment linkage control information occurs at
> the high-address end of a stack segment. (The stack
> grows from low addresses to high addresses.) The initial
> part of the stack segment linkage control information is
> 0200 (octal) words. This provides for register storage
> for the routine which overflows the stack. */
>
> struct stack_segment_linkage
> {
> long ss[0200]; /* 0200 overflow words. */
> long sssize:32; /* Number of words in this segment. */
> long ssbase:32; /* Offset to stack base. */
> long:32;
> long sspseg:32; /* Offset to linkage control of previous
> segment of stack. */
> long:32;
> long sstcpt:32; /* Pointer to task common address block. */
> long sscsnm; /* Private control structure number for
> microtasking. */
> long ssusr1; /* Reserved for user. */
> long ssusr2; /* Reserved for user. */
> long sstpid; /* Process ID for pid based multi-tasking. */
> long ssgvup; /* Pointer to multitasking thread giveup. */
> long sscray[7]; /* Reserved for Cray Research. */
> long ssa0;
> long ssa1;
> long ssa2;
> long ssa3;
> long ssa4;
> long ssa5;
> long ssa6;
> long ssa7;
> long sss0;
> long sss1;
> long sss2;
> long sss3;
> long sss4;
> long sss5;
> long sss6;
> long sss7;
> };
>
> #else /* CRAY2 */
> /* The following structure defines the vector of words
> returned by the STKSTAT library routine. */
> struct stk_stat
> {
> long now; /* Current total stack size. */
> long maxc; /* Amount of contiguous space which would
> be required to satisfy the maximum
> stack demand to date. */
> long high_water; /* Stack high-water mark. */
> long overflows; /* Number of stack overflow
> ($STKOFEN) calls. */
> long hits; /* Number of internal buffer hits. */
> long extends; /* Number of block extensions. */
> long stko_mallocs; /* Block allocations by $STKOFEN. */
> long underflows; /* Number of stack underflow
> calls ($STKRETN). */
> long stko_free; /* Number of deallocations by $STKRETN. */
> long stkm_free; /* Number of deallocations by $STKMRET. */
> long segments; /* Current number of stack segments. */
> long maxs; /* Maximum number of stack segments
> so far. */
> long pad_size; /* Stack pad size. */
> long current_address; /* Current stack segment address. */
> long current_size; /* Current stack segment size. This
> number is actually corrupted by STKSTAT to
> include the fifteen word trailer area. */
> long initial_address; /* Address of initial segment. */
> long initial_size; /* Size of initial segment. */
> };
>
> /* The following structure describes the data structure which trails
> any stack segment. I think that the description in 'asdef' is
> out of date. I only describe the parts that I am sure about. */
>
> struct stk_trailer
> {
> long this_address; /* Address of this block. */
> long this_size; /* Size of this block (does not include
> this trailer). */
> long unknown2;
> long unknown3;
> long link; /* Address of trailer block of previous
> segment. */
> long unknown5;
> long unknown6;
> long unknown7;
> long unknown8;
> long unknown9;
> long unknown10;
> long unknown11;
> long unknown12;
> long unknown13;
> long unknown14;
> };
>
> #endif /* CRAY2 */
> #endif /* not CRAY_STACK */
>
> #ifdef CRAY2
> /* Determine a "stack measure" for an arbitrary ADDRESS.
> I doubt that "lint" will like this much. */
>
> static long
> i00afunc (long *address)
> {
> struct stk_stat status;
> struct stk_trailer *trailer;
> long *block, size;
> long result = 0;
>
> /* We want to iterate through all of the segments. The first
> step is to get the stack status structure. We could do this
> more quickly and more directly, perhaps, by referencing the
> $LM00 common block, but I know that this works. */
>
> STKSTAT (&status);
>
> /* Set up the iteration. */
>
> trailer = (struct stk_trailer *) (status.current_address
> + status.current_size
> - 15);
>
> /* There must be at least one stack segment. Therefore it is
> a fatal error if "trailer" is null. */
>
> if (trailer == 0)
> abort ();
>
> /* Discard segments that do not contain our argument address. */
>
> while (trailer != 0)
> {
> block = (long *) trailer->this_address;
> size = trailer->this_size;
> if (block == 0 || size == 0)
> abort ();
> trailer = (struct stk_trailer *) trailer->link;
> if ((block <= address) && (address < (block + size)))
> break;
> }
>
> /* Set the result to the offset in this segment and add the sizes
> of all predecessor segments. */
>
> result = address - block;
>
> if (trailer == 0)
> {
> return result;
> }
>
> do
> {
> if (trailer->this_size <= 0)
> abort ();
> result += trailer->this_size;
> trailer = (struct stk_trailer *) trailer->link;
> }
> while (trailer != 0);
>
> /* We are done. Note that if you present a bogus address (one
> not in any segment), you will get a different number back, formed
> from subtracting the address of the first block. This
> is probably
> not what you want. */
>
> return (result);
> }
>
> #else /* not CRAY2 */
> /* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
> Determine the number of the cell within the stack,
> given the address of the cell. The purpose of this
> routine is to linearize, in some sense, stack addresses
> for alloca. */
>
> static long
> i00afunc (long address)
> {
> long stkl = 0;
>
> long size, pseg, this_segment, stack;
> long result = 0;
>
> struct stack_segment_linkage *ssptr;
>
> /* Register B67 contains the address of the end of the
> current stack segment. If you (as a subprogram) store
> your registers on the stack and find that you are past
> the contents of B67, you have overflowed the segment.
>
> B67 also points to the stack segment linkage control
> area, which is what we are really interested in. */
>
> stkl = CRAY_STACKSEG_END ();
> ssptr = (struct stack_segment_linkage *) stkl;
>
> /* If one subtracts 'size' from the end of the segment,
> one has the address of the first word of the segment.
>
> If this is not the first segment, 'pseg' will be
> nonzero. */
>
> pseg = ssptr->sspseg;
> size = ssptr->sssize;
>
> this_segment = stkl - size;
>
> /* It is possible that calling this routine itself caused
> a stack overflow. Discard stack segments which do not
> contain the target address. */
>
> while (!(this_segment <= address && address <= stkl))
> {
> #ifdef DEBUG_I00AFUNC
> fprintf (stderr, "%011o %011o %011o\n", this_segment,
> address, stkl);
> #endif
> if (pseg == 0)
> break;
> stkl = stkl - pseg;
> ssptr = (struct stack_segment_linkage *) stkl;
> size = ssptr->sssize;
> pseg = ssptr->sspseg;
> this_segment = stkl - size;
> }
>
> result = address - this_segment;
>
> /* If you subtract pseg from the current end of the stack,
> you get the address of the previous stack segment's end.
> This seems a little convoluted to me, but I'll bet you save
> a cycle somewhere. */
>
> while (pseg != 0)
> {
> #ifdef DEBUG_I00AFUNC
> fprintf (stderr, "%011o %011o\n", pseg, size);
> #endif
> stkl = stkl - pseg;
> ssptr = (struct stack_segment_linkage *) stkl;
> size = ssptr->sssize;
> pseg = ssptr->sspseg;
> result += size;
> }
> return (result);
> }
>
> #endif /* not CRAY2 */
> #endif /* CRAY */
>
> #endif /* no alloca */
> #endif /* not GCC version 2 */
> ______________________________________________________________________
> Apache Interface to SSLeay (mod_ssl) www.engelschall.com/sw/mod_ssl/
> Official Support Mailing List [EMAIL PROTECTED]
> Automated List Manager [EMAIL PROTECTED]
>