FreeBASIC  0.91.0
gosub.c
Go to the documentation of this file.
1 /* GOSUB support */
2 
3 #include "fb.h"
4 #include <setjmp.h>
5 
6 /* slow but easy to manage dynamic GOSUB call-stack */
7 typedef struct gosubnode {
8  jmp_buf buf;
9  struct gosubnode *next;
10 } GOSUBNODE;
11 
12 /* the gosub context allocated in auto-local storage by the compiler */
13 typedef struct {
15 } GOSUBCTX;
16 
17 /*
18  NOTES:
19  On the compiler side, GOSUBCTX is an ANY PTR. To extend
20  GOSUBCTX, the compiler must allocate additional space for
21  the GOSUBCTX pseudo-object.
22 
23  GOSUBCTX does not have a constructor, but it is expected that
24  the compiler will initialize the variable to zero.
25 
26  See ast-gosub.bas::astGosubAddInit()
27 */
28 
29 
30 /*:::::*/
32 {
33  GOSUBNODE *node = malloc( sizeof( GOSUBNODE ) );
34  node->next = ctx->top;
35  ctx->top = node;
36 
37  /* returns address of ctx->top->buf */
38  return &(ctx->top->buf);
39 }
40 
41 /*:::::*/
43 {
44  if( ctx && ctx->top )
45  {
46  GOSUBNODE *node = ctx->top->next;
47  free(ctx->top);
48  ctx->top = node;
49 
50  /* return success */
51  return fb_ErrorSetNum( FB_RTERROR_OK );
52  }
53 
54  /* don't know where to go next so return an error */
56 }
57 
58 /*:::::*/
60 {
61  if( ctx && ctx->top )
62  {
63  GOSUBNODE *node = ctx->top->next;
64 
65  /* TODO: with a different stack allocation strategy, this
66  * temporary copy won't be needed */
67  jmp_buf buf;
68  FB_MEMCPY( buf, ctx->top->buf, sizeof(jmp_buf));
69 
70  free(ctx->top);
71  ctx->top = node;
72 
73  longjmp( buf, -1 );
74  }
75 
76  /* don't know where to go next so return an error */
78 }
79 
80 /*:::::*/
82 {
83  if( ctx )
84  {
85  while( ctx->top )
86  {
87  GOSUBNODE *node = ctx->top->next;
88  free(ctx->top);
89  ctx->top = node;
90  }
91  }
92 }