[comp.lang.c] What is alloca

2014_5001@uwovax.uwo.ca (09/21/89)

I was trying to compile FLEX with TurboC 2.0.  Not having a yacc, I
ran bison on parse.y.

With a minor change in the source, I managed to get the whole thing
compiled.  Unfortunately, it requests the presence of an alloca()
routine, apparently with a prototype like:
  void *alloca(size_t s);
(As well as I can tell from the context and the type casting).
It does not appear to figure in parse.y, so it appears likely to me
that it is put in by my bison.  What does alloca() do?
It does not appear in the TurboC 2.0 library, nor in Unix SysV
man pages.

-- 
Alexander Pruss, at one of: Department of Applied Mathematics, Astronomy,
Mathematics, or Physics                     University of Western Ontario 
pruss@uwovax.uwo.ca         pruss@uwovax.BITNET          A5001@nve.uwo.ca 

henry@utzoo.uucp (Henry Spencer) (09/24/89)

In article <3823.2518c141@uwovax.uwo.ca> 2014_5001@uwovax.uwo.ca writes:
>... What does alloca() do?
>It does not appear in the TurboC 2.0 library, nor in Unix SysV
>man pages.

It's a nonstandard botch (originating in some poorly-designed ancient Unix
systems) that some of the Gnoids are really fond of.  The theory is that
it's malloc() except that the storage automatically goes away when you leave
the function it was called in.  This is more than a little difficult to
implement on some machines...
-- 
"Where is D.D. Harriman now,   |     Henry Spencer at U of Toronto Zoology
when we really *need* him?"    | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

mike@thor.acc.stolaf.edu (Mike Haertel) (09/25/89)

In article <1989Sep24.050214.13898@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>In article <3823.2518c141@uwovax.uwo.ca> 2014_5001@uwovax.uwo.ca writes:
>>... What does alloca() do?
>>It does not appear in the TurboC 2.0 library, nor in Unix SysV
>>man pages.
>
>It's a nonstandard botch (originating in some poorly-designed ancient Unix
>systems) that some of the Gnoids are really fond of.  The theory is that
>it's malloc() except that the storage automatically goes away when you leave
>the function it was called in.  This is more than a little difficult to
>implement on some machines...

I'm glad you said "SOME OF the Gnoids" (emphasis mine), Henry.
Not all of us are particularly fond of alloca().

I think alloca() originated in one of the early VAX BSD's.  My guess
would be that it was invented for use implementing Franz Lisp, and
somehow wormed its way into the standard library during a lapse of
judgement on someone's part.

The practical problem with alloca() is that it cannot be implemented
on machines without a frame pointer (except by compiler hack) and
therefore is not available in all environments.

There are philosophical objections too, but I won't go into them.

Unfortunately, alloca() is sometimes necessary in programs that
call longjmp().  (longjmp(), like alloca(), is evil.  Even though
it is in the C standard.)  But two wrongs do not make a right . . .

Doug Gwyn (gwyn@smoke.brl.mil) has a semi-portable fake alloca()
written in C that people without alloca() may find useful when
installing GNU software on their machines.
-- 
Mike Haertel <mike@stolaf.edu>
``There's nothing remarkable about it.  All one has to do is hit the right
  keys at the right time and the instrument plays itself.'' -- J. S. Bach

henry@utzoo.uucp (Henry Spencer) (09/26/89)

In article <6361@thor.acc.stolaf.edu> mike@stolaf.edu (Mike Haertel) writes:
>>>... What does alloca() do?
>>It's a nonstandard botch (originating in some poorly-designed ancient Unix
>>systems) that some of the Gnoids are really fond of...
>I think alloca() originated in one of the early VAX BSD's.  My guess
>would be that it was invented for use implementing Franz Lisp...

It goes back farther than that.  The first occurrence I'm aware of was in
PWB circa 1977.  (PWB was a pdp11 Unix variant, sort of a neolithic ancestor
of System V.)  It showed up in SCCS (PWB's biggest, uh, contribution to the
user interface) in particular.
-- 
"Where is D.D. Harriman now,   |     Henry Spencer at U of Toronto Zoology
when we really *need* him?"    | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

2014_5001@uwovax.uwo.ca (09/26/89)

In article <3823.2518c141@uwovax.uwo.ca>, 2014_5001@uwovax.uwo.ca writes:
> I was trying to compile FLEX with TurboC 2.0.  Not having a yacc, I
> ran bison on parse.y.
> 
> With a minor change in the source, I managed to get the whole thing
> compiled.  Unfortunately, it requests the presence of an alloca()
> routine, apparently with a prototype like:
>   void *alloca(size_t s);
> (As well as I can tell from the context and the type casting).
> It does not appear to figure in parse.y, so it appears likely to me
> that it is put in by my bison.  What does alloca() do?
> It does not appear in the TurboC 2.0 library, nor in Unix SysV
> man pages.

I rarely follow up on my own articles, but here goes..

I have used the following alloca() implementation for the ibm pc
(highly unportable):

----- alloca.h----
static unsigned int _INtERNAL_alloca_;
#define alloca(x) \
  ( _INtERNAL_alloca_=_SP, _SP-=(x), (void *)_INtERNAL_alloca_ )
-----

I am wondering whether this does what alloca() should do.
Have I missed something?

Turbo C apparently allocates stack space for all the blocks in
a function once at the top.  i.e. given
void f(void) { int a; { int b; } },
space for both a and b will be allocated at the top of the function,
and deallocated upon return.  This means that since my alloca() macro
relies on the automatic var deallocation, the space will be in use
until a return.

-- 
Alexander Pruss, at one of: Department of Applied Mathematics, Astronomy,
Mathematics, or Physics                     University of Western Ontario 
pruss@uwovax.uwo.ca         pruss@uwovax.BITNET          A5001@nve.uwo.ca 

bill@twwells.com (T. William Wells) (09/27/89)

In article <1989Sep24.050214.13898@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
: It's a nonstandard botch (originating in some poorly-designed ancient Unix
: systems) that some of the Gnoids are really fond of.  The theory is that
: it's malloc() except that the storage automatically goes away when you leave
: the function it was called in.  This is more than a little difficult to
: implement on some machines...

The version of gas (Gnu assembler) I have uses alloca in two places;
neither of which is a particularly good place for it and one of which
is downright stupid. That latter is alloca'ing an array which can
never be over four bytes long. I found these because I won't use code
that uses alloca. And maybe when gas actually works on my system (its
opcode tables are incomplete), I'll actually use it.

---
Bill                    { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com

djones@megatest.UUCP (Dave Jones) (09/27/89)

From article <6361@thor.acc.stolaf.edu>, by mike@thor.acc.stolaf.edu (Mike Haertel):

> longjmp(), like alloca(), is evil.


I like longjmp() and alloca().  But then, I guess I like a lot of
evil things, come to think of it.

barmar@kulla (Barry Margolin) (09/27/89)

In article <1989Sep25.172824.18692@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>In article <6361@thor.acc.stolaf.edu> mike@stolaf.edu (Mike Haertel) writes:
>>I think alloca() originated in one of the early VAX BSD's.  My guess
>>would be that it was invented for use implementing Franz Lisp...
>It goes back farther than that.  The first occurrence I'm aware of was in
>PWB circa 1977.

It also exists in Multics, although I don't know whether it was in the
Multics design during the days when Bell Labs was part of the project.
On Multics it is called something like cu_$expand_stack_frame ("cu_$"
is the prefix for the "command utilities" library, which includes lots
of stack-frame-manipulation routines because it contains the
variable-argument routines that are used instead of argv[], and the
generate-call routines that are used in place of exec()).

Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

Don_A_Corbitt@cup.portal.com (09/29/89)

The alloca() you posted for Turbo C will usually work.  Notably, it
will not work for some floating point code - TC 'knows' how far the 
stack pointer is from the frame pointer.  It subtracts from the stack
pointer, then stores relative the frame pointer.  If you have alloca()'ed,
it don't work no good.
	Don_A_Corbitt@cup.portal.com 
 "Trying for next month's bandwidth-waster posting"

bga@bgalli.eds.com (Billy G. Allie) (10/04/89)

In article <3839.251f4ecf@uwovax.uwo.ca>, 2014_5001@uwovax.uwo.ca writes:
> I have used the following alloca() implementation for the ibm pc
> (highly unportable):
> 
> ----- alloca.h----
> static unsigned int _INtERNAL_alloca_;
> #define alloca(x) \
>   ( _INtERNAL_alloca_=_SP, _SP-=(x), (void *)_INtERNAL_alloca_ )
> -----
> 
> I am wondering whether this does what alloca() should do.
> Have I missed something?

The macro you gave above will fail in any of the large data models.  Also,
your macro could leave the stack pointer pointing to an odd address, some-
thing that the 80x86 processors do not like.  I am including the source for
the macro that I wrote when I ported BISON to the MS-DOS operating system
and the Turbo-C compiler.  It will work correctly for any data model.

-------------------------------><Cut Here><-------------------------------
# To unbundle, sh this file
echo alloca.h 1>&2
cat >alloca.h <<'End of alloca.h'
/***********************************************************************\
| The following gives the definition of a macro (alloca) that allocates	|
| space like malloc EXCEPT that it is allocated from the stack and does	|
| not have to be freed.  The allocated space will automatically disap-	|
| pear when the function that allocated the space exits.		|
|									|
|			      W*A*R*N*I*N*G				|
| This code is VERY compiler dependant and will only work for Turbo C	|
| versions 1.5 and 2.0.  You are forwarned.				|
|									|
| This code is released into the public domain.				|
\***********************************************************************/

#if !defined(alloca)
#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
#define alloca(i) (_SP-=((i+1)&0xFFFE),(void *)(((unsigned long)_SS<<16)|_SP))
#else
#define alloca(i) (_SP-=((i+1)&0xFFFE),(void *)_SP)
#endif
#endif
End of alloca.h
-------------------------------><Cut Here><-------------------------------
-- 
____	   | Billy G. Allie	| Internet..: bga@bgalli.eds.com
|  /|	   | 7436 Hartwell	| UUCP......: uunet!{mcf|edsews}!bgalli!bga
|-/-|----- | Dearborn, MI 48126	| Compuserve: 76337,2061
|/  |LLIE  | (313) 582-1540	| Genie.....: BGALLIE

dave@dsi.COM (Dave Rifkind) (10/06/89)

In article <417@bgalli.eds.com> bga@bgalli.eds.com (Billy G. Allie) writes:
:                                              I am including the source for
:the macro that I wrote when I ported BISON to the MS-DOS operating system
:and the Turbo-C compiler.  It will work correctly for any data model.
...
:#if !defined(alloca)
:#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
:#define alloca(i) (_SP-=((i+1)&0xFFFE),(void *)(((unsigned long)_SS<<16)|_SP))
:#else
:#define alloca(i) (_SP-=((i+1)&0xFFFE),(void *)_SP)
:#endif
:#endif

Just be careful not to use this in a function with very few local
variables.  If Turbo C does not have to adjust the stack pointer (to
allocate locals) in the function prologue, it will not generate a "mov
sp, bp" in the return sequence.  This would make returning from such a
function interesting, but not useful.