3 /* macro.c -- user-defined macros for Texinfo.
4 Id: macro.c,v 1.6 2004/04/11 17:56:47 karl Exp
6 Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software Foundation,
20 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
27 #include "insertion.h"
29 /* If non-NULL, this is an output stream to write the full macro expansion
30 of the input text to. The result is another texinfo file, but
31 missing @include, @infoinclude, @macro, and macro invocations. Instead,
32 all of the text is placed within the file. */
33 FILE *macro_expansion_output_stream
= NULL
;
35 /* Output file for -E. */
36 char *macro_expansion_filename
;
38 /* Nonzero means a macro string is in execution, as opposed to a file. */
39 int me_executing_string
= 0;
41 /* Nonzero means we want only to expand macros and
42 leave everything else intact. */
43 int only_macro_expansion
= 0;
45 static ITEXT
**itext_info
= NULL
;
46 static int itext_size
= 0;
48 /* Return the arglist on the current line. This can behave in two different
49 ways, depending on the variable BRACES_REQUIRED_FOR_MACRO_ARGS. */
50 int braces_required_for_macro_args
= 0;
52 /* Array of macros and definitions. */
53 MACRO_DEF
**macro_list
= NULL
;
55 int macro_list_len
= 0; /* Number of elements. */
56 int macro_list_size
= 0; /* Number of slots in total. */
58 /* Return the length of the array in ARRAY. */
60 array_len (char **array
)
65 for (i
= 0; array
[i
]; i
++);
71 free_array (char **array
)
76 for (i
= 0; array
[i
]; i
++)
83 /* Return the macro definition of NAME or NULL if NAME is not defined. */
85 find_macro (char *name
)
91 for (i
= 0; macro_list
&& (def
= macro_list
[i
]); i
++)
93 if ((!def
->inhibited
) && (strcmp (def
->name
, name
) == 0))
99 /* Add the macro NAME with ARGLIST and BODY to the list of defined macros.
100 SOURCE_FILE is the name of the file where this definition can be found,
101 and SOURCE_LINENO is the line number within that file. If a macro already
102 exists with NAME, then a warning is produced, and that previous
103 definition is overwritten. */
105 add_macro (char *name
, char **arglist
, char *body
, char *source_file
,
106 int source_lineno
, int flags
)
110 def
= find_macro (name
);
114 if (macro_list_len
+ 2 >= macro_list_size
)
115 macro_list
= xrealloc
116 (macro_list
, ((macro_list_size
+= 10) * sizeof (MACRO_DEF
*)));
118 macro_list
[macro_list_len
] = xmalloc (sizeof (MACRO_DEF
));
119 macro_list
[macro_list_len
+ 1] = NULL
;
121 def
= macro_list
[macro_list_len
];
127 char *temp_filename
= input_filename
;
128 int temp_line
= line_number
;
130 warning (_("macro `%s' previously defined"), name
);
132 input_filename
= def
->source_file
;
133 line_number
= def
->source_lineno
;
134 warning (_("here is the previous definition of `%s'"), name
);
136 input_filename
= temp_filename
;
137 line_number
= temp_line
;
143 for (i
= 0; def
->arglist
[i
]; i
++)
144 free (def
->arglist
[i
]);
148 free (def
->source_file
);
152 def
->source_file
= xstrdup (source_file
);
153 def
->source_lineno
= source_lineno
;
155 def
->arglist
= arglist
;
162 get_brace_args (int quote_single
)
164 char **arglist
, *word
;
165 int arglist_index
, arglist_size
;
166 int character
, escape_seen
, start
;
169 /* There is an arglist in braces here, so gather the args inside of it. */
170 skip_whitespace_and_newlines ();
173 arglist_index
= arglist_size
= 0;
176 skip_whitespace_and_newlines ();
177 start
= input_text_offset
;
180 while ((character
= curchar ()))
182 if (character
== '\\')
184 input_text_offset
+= 2;
187 else if (character
== '{')
192 else if ((character
== ',' && !quote_single
) ||
193 ((character
== '}') && depth
== 1))
195 int len
= input_text_offset
- start
;
197 if (len
|| (character
!= '}'))
199 word
= xmalloc (1 + len
);
200 memcpy (word
, input_text
+ start
, len
);
203 /* Clean up escaped characters. */
207 for (i
= 0; word
[i
]; i
++)
209 memmove (word
+ i
, word
+ i
+ 1,
210 1 + strlen (word
+ i
+ 1));
213 if (arglist_index
+ 2 >= arglist_size
)
215 (arglist
, (arglist_size
+= 10) * sizeof (char *));
217 arglist
[arglist_index
++] = word
;
218 arglist
[arglist_index
] = NULL
;
222 if (character
== '}')
227 else if (character
== '}')
235 if (character
== '\n') line_number
++;
242 get_macro_args (MACRO_DEF
*def
)
247 /* Quickly check to see if this macro has been invoked with any arguments.
248 If not, then don't skip any of the following whitespace. */
249 for (i
= input_text_offset
; i
< input_text_length
; i
++)
250 if (!cr_or_whitespace (input_text
[i
]))
253 if (input_text
[i
] != '{')
255 if (braces_required_for_macro_args
)
261 /* Braces are not required to fill out the macro arguments. If
262 this macro takes one argument, it is considered to be the
263 remainder of the line, sans whitespace. */
264 if (def
->arglist
&& def
->arglist
[0] && !def
->arglist
[1])
268 get_rest_of_line (0, &word
);
269 if (input_text
[input_text_offset
- 1] == '\n')
274 /* canon_white (word); */
275 arglist
= xmalloc (2 * sizeof (char *));
282 /* The macro either took no arguments, or took more than
283 one argument. In that case, it must be invoked with
284 arguments surrounded by braces. */
289 return get_brace_args (def
->flags
& ME_QUOTE_ARG
);
292 /* Substitute actual parameters for named parameters in body.
293 The named parameters which appear in BODY must by surrounded
294 reverse slashes, as in \foo\. */
296 apply (char **named
, char **actuals
, char *body
)
299 int new_body_index
, new_body_size
;
300 char *new_body
, *text
;
301 int length_of_actuals
;
303 length_of_actuals
= array_len (actuals
);
304 new_body_size
= strlen (body
);
305 new_body
= xmalloc (1 + new_body_size
);
307 /* Copy chars from BODY into NEW_BODY. */
312 { /* Anything but a \ is easy. */
314 new_body
[new_body_index
++] = body
[i
++];
316 { /* Snarf parameter name, check against named parameters. */
318 int param_start
, len
;
321 while (body
[i
] && body
[i
] != '\\')
324 len
= i
- param_start
;
325 param
= xmalloc (1 + len
);
326 memcpy (param
, body
+ param_start
, len
);
329 if (body
[i
]) /* move past \ */
333 { /* \\ always means \, even if macro has no args. */
335 text
= xmalloc (1 + len
);
336 sprintf (text
, "\\%s", param
);
342 /* Check against named parameters. */
343 for (which
= 0; named
&& named
[which
]; which
++)
344 if (STREQ (named
[which
], param
))
347 if (named
&& named
[which
])
349 text
= which
< length_of_actuals
? actuals
[which
] : NULL
;
353 text
= xstrdup (text
); /* so we can free it */
356 { /* not a parameter, so it's an error. */
357 warning (_("\\ in macro expansion followed by `%s' instead of parameter name"),
360 text
= xmalloc (1 + len
);
361 sprintf (text
, "\\%s", param
);
365 if (strlen (param
) + 2 < len
)
367 new_body_size
+= len
+ 1;
368 new_body
= xrealloc (new_body
, new_body_size
);
373 strcpy (new_body
+ new_body_index
, text
);
374 new_body_index
+= len
;
380 new_body
[new_body_index
] = 0;
384 /* Expand macro passed in DEF, a pointer to a MACRO_DEF, and
385 return its expansion as a string. */
387 expand_macro (MACRO_DEF
*def
)
391 char *execution_string
= NULL
;
392 int start_line
= line_number
;
394 /* Find out how many arguments this macro definition takes. */
395 num_args
= array_len (def
->arglist
);
397 /* Gather the arguments present on the line if there are any. */
398 arglist
= get_macro_args (def
);
400 if (num_args
< array_len (arglist
))
402 free_array (arglist
);
403 line_error (_("Macro `%s' called on line %d with too many args"),
404 def
->name
, start_line
);
405 return execution_string
;
409 execution_string
= apply (def
->arglist
, arglist
, def
->body
);
411 free_array (arglist
);
412 return execution_string
;
415 /* Execute the macro passed in DEF, a pointer to a MACRO_DEF. */
417 execute_macro (MACRO_DEF
*def
)
419 char *execution_string
;
420 int start_line
= line_number
, end_line
;
422 if (macro_expansion_output_stream
&& !executing_string
&& !me_inhibit_expansion
)
423 me_append_before_this_command ();
425 execution_string
= expand_macro (def
);
426 if (!execution_string
)
431 /* Reset the line number to where the macro arguments began.
432 This makes line numbers reported in error messages correct in
433 case the macro arguments span several lines and the expanded
434 arguments invoke other commands. */
435 end_line
= line_number
;
436 line_number
= start_line
;
438 if (macro_expansion_output_stream
439 && !executing_string
&& !me_inhibit_expansion
)
441 remember_itext (input_text
, input_text_offset
);
442 me_execute_string (execution_string
);
445 execute_string ("%s", execution_string
);
447 free (execution_string
);
448 line_number
= end_line
;
453 /* Read and remember the definition of a macro. If RECURSIVE is set,
454 set the ME_RECURSE flag. MACTYPE is either "macro" or "rmacro", and
455 tells us what the matching @end should be. */
457 define_macro (char *mactype
, int recursive
)
461 char *last_end
= NULL
;
463 char **arglist
= NULL
;
464 int body_size
= 0, body_index
= 0;
467 int defining_line
= line_number
;
469 if (macro_expansion_output_stream
&& !executing_string
)
470 me_append_before_this_command ();
474 /* Get the name of the macro. This is the set of characters which are
475 not whitespace and are not `{' immediately following the @macro. */
476 start
= input_text_offset
;
480 for (i
= start
; i
< input_text_length
&& input_text
[i
] != '{'
481 && !cr_or_whitespace (input_text
[i
]);
485 name
= xmalloc (1 + len
);
486 memcpy (name
, input_text
+ start
, len
);
488 input_text_offset
= i
;
493 /* It is not required that the definition of a macro includes an arglist.
494 If not, don't try to get the named parameters, just use a null list. */
495 if (curchar () == '{')
498 int arglist_index
= 0, arglist_size
= 0;
499 int gathering_words
= 1;
502 /* Read the words inside of the braces which determine the arglist.
503 These words will be replaced within the body of the macro at
507 skip_whitespace_and_newlines ();
509 while (gathering_words
)
513 for (i
= input_text_offset
;
514 (character
= input_text
[i
]);
525 /* Found the end of the current arglist word. Save it. */
526 len
= i
- input_text_offset
;
527 word
= xmalloc (1 + len
);
528 memcpy (word
, input_text
+ input_text_offset
, len
);
530 input_text_offset
= i
;
532 /* Advance to the comma or close-brace that signified
533 the end of the argument. */
534 while ((character
= curchar ())
539 if (character
== '\n')
543 /* Add the word to our list of words. */
544 if (arglist_index
+ 2 >= arglist_size
)
547 arglist
= xrealloc (arglist
,
548 arglist_size
* sizeof (char *));
551 arglist
[arglist_index
++] = word
;
552 arglist
[arglist_index
] = NULL
;
556 if (character
== '}')
563 if (character
== ',')
566 skip_whitespace_and_newlines ();
567 i
= input_text_offset
- 1;
572 /* If we have exactly one argument, do @quote-arg implicitly. Not
573 only does this match TeX's behavior (which can't feasibly be
574 changed), but it's a good idea. */
575 if (arglist_index
== 1)
576 flags
|= ME_QUOTE_ARG
;
579 /* Read the text carefully until we find an "@end macro" which
580 matches this one. The text in between is the body of the macro. */
581 skip_whitespace_and_newlines ();
585 if ((input_text_offset
+ 9) > input_text_length
)
587 file_line_error (input_filename
, defining_line
,
588 _("%cend macro not found"), COMMAND_PREFIX
);
592 get_rest_of_line (0, &line
);
594 /* Handle commands only meaningful within a macro. */
595 if ((*line
== COMMAND_PREFIX
) && (depth
== 1) &&
596 (strncmp (line
+ 1, "allow-recursion", 15) == 0) &&
597 (line
[16] == 0 || whitespace (line
[16])))
599 for (i
= 16; whitespace (line
[i
]); i
++);
600 strcpy (line
, line
+ i
);
609 if ((*line
== COMMAND_PREFIX
) && (depth
== 1) &&
610 (strncmp (line
+ 1, "quote-arg", 9) == 0) &&
611 (line
[10] == 0 || whitespace (line
[10])))
613 for (i
= 10; whitespace (line
[i
]); i
++);
614 strcpy (line
, line
+ i
);
616 if (arglist
&& arglist
[0] && !arglist
[1])
618 flags
|= ME_QUOTE_ARG
;
626 line_error (_("@quote-arg only useful for single-argument macros"));
629 if (*line
== COMMAND_PREFIX
630 && (strncmp (line
+ 1, "macro ", 6) == 0
631 || strncmp (line
+ 1, "rmacro ", 7) == 0))
634 /* Incorrect implementation of nesting -- just check that the last
635 @end matches what we started with. Since nested macros don't
636 work in TeX anyway, this isn't worth the trouble to get right. */
637 if (*line
== COMMAND_PREFIX
&& strncmp (line
+ 1, "end macro", 9) == 0)
642 if (*line
== COMMAND_PREFIX
&& strncmp (line
+ 1, "end rmacro", 10) == 0)
650 if ((body_index
+ strlen (line
) + 3) >= body_size
)
651 body
= xrealloc (body
, body_size
+= 3 + strlen (line
));
652 strcpy (body
+ body_index
, line
);
653 body_index
+= strlen (line
);
654 body
[body_index
++] = '\n';
655 body
[body_index
] = 0;
660 /* Check that @end matched the macro command. */
661 if (!STREQ (last_end
, mactype
))
662 warning (_("mismatched @end %s with @%s"), last_end
, mactype
);
664 /* If it was an empty macro like
667 create an empty body. (Otherwise, the macro is not expanded.) */
670 body
= (char *)malloc(1);
674 /* We now have the name, the arglist, and the body. However, BODY
675 includes the final newline which preceded the `@end macro' text.
677 if (body
&& strlen (body
))
678 body
[strlen (body
) - 1] = 0;
683 add_macro (name
, arglist
, body
, input_filename
, defining_line
, flags
);
685 if (macro_expansion_output_stream
&& !executing_string
)
687 /* Remember text for future expansions. */
688 remember_itext (input_text
, input_text_offset
);
690 /* Bizarrely, output the @macro itself. This is so texinfo.tex
691 will have a chance to read it when texi2dvi calls makeinfo -E.
692 The problem is that we don't really expand macros in all
693 contexts; a @table's @item is one. And a fix is not obvious to
694 me, since it appears virtually identical to any other internal
695 expansion. Just setting a variable in cm_item caused other
696 strange expansion problems. */
697 write_region_to_macro_output ("@", 0, 1);
698 write_region_to_macro_output (mactype
, 0, strlen (mactype
));
699 write_region_to_macro_output (" ", 0, 1);
700 write_region_to_macro_output (input_text
, start
, input_text_offset
);
707 define_macro ("macro", 0);
713 define_macro ("rmacro", 1);
716 /* Delete the macro with name NAME. The macro is deleted from the list,
717 but it is also returned. If there was no macro defined, NULL is
721 delete_macro (char *name
)
728 for (i
= 0; macro_list
&& (def
= macro_list
[i
]); i
++)
729 if (strcmp (def
->name
, name
) == 0)
731 memmove (macro_list
+ i
, macro_list
+ i
+ 1,
732 ((macro_list_len
+ 1) - i
) * sizeof (MACRO_DEF
*));
746 if (macro_expansion_output_stream
&& !executing_string
)
747 me_append_before_this_command ();
749 get_rest_of_line (0, &line
);
751 for (i
= 0; line
[i
] && !whitespace (line
[i
]); i
++);
752 name
= xmalloc (i
+ 1);
753 memcpy (name
, line
, i
);
756 def
= delete_macro (name
);
760 free (def
->source_file
);
768 for (i
= 0; def
->arglist
[i
]; i
++)
769 free (def
->arglist
[i
]);
780 if (macro_expansion_output_stream
&& !executing_string
)
781 remember_itext (input_text
, input_text_offset
);
784 /* How to output sections of the input file verbatim. */
786 /* Set the value of POINTER's offset to OFFSET. */
788 remember_itext (char *pointer
, int offset
)
793 /* If we have no info, initialize a blank list. */
796 itext_info
= xmalloc ((itext_size
= 10) * sizeof (ITEXT
*));
797 for (i
= 0; i
< itext_size
; i
++)
798 itext_info
[i
] = NULL
;
801 /* If the pointer is already present in the list, then set the offset. */
802 for (i
= 0; i
< itext_size
; i
++)
803 if ((itext_info
[i
]) &&
804 (itext_info
[i
]->pointer
== pointer
))
806 itext
= itext_info
[i
];
807 itext_info
[i
]->offset
= offset
;
813 /* Find a blank slot (or create a new one), and remember the
814 pointer and offset. */
815 for (i
= 0; i
< itext_size
; i
++)
816 if (itext_info
[i
] == NULL
)
819 /* If not found, then add some slots. */
824 itext_info
= xrealloc
825 (itext_info
, (itext_size
+= 10) * sizeof (ITEXT
*));
827 for (j
= i
; j
< itext_size
; j
++)
828 itext_info
[j
] = NULL
;
831 /* Now add the pointer and the offset. */
832 itext_info
[i
] = xmalloc (sizeof (ITEXT
));
833 itext_info
[i
]->pointer
= pointer
;
834 itext_info
[i
]->offset
= offset
;
835 itext
= itext_info
[i
];
840 /* Forget the input text associated with POINTER. */
842 forget_itext (char *pointer
)
846 for (i
= 0; i
< itext_size
; i
++)
847 if (itext_info
[i
] && (itext_info
[i
]->pointer
== pointer
))
849 free (itext_info
[i
]);
850 itext_info
[i
] = NULL
;
855 /* Append the text which appeared in input_text from the last offset to
856 the character just before the command that we are currently executing. */
858 me_append_before_this_command (void)
862 for (i
= input_text_offset
; i
&& (input_text
[i
] != COMMAND_PREFIX
); i
--)
864 maybe_write_itext (input_text
, i
);
867 /* Similar to execute_string, but only takes a single string argument,
868 and remembers the input text location, etc. */
870 me_execute_string (char *execution_string
)
872 int saved_escape_html
= escape_html
;
873 int saved_in_paragraph
= in_paragraph
;
874 escape_html
= me_executing_string
== 0;
878 input_text_offset
= 0;
879 /* The following xstrdup is so we can relocate input_text at will. */
880 input_text
= xstrdup (execution_string
);
881 input_filename
= xstrdup (input_filename
);
882 input_text_length
= strlen (execution_string
);
884 remember_itext (input_text
, 0);
886 me_executing_string
++;
889 free (input_filename
);
891 me_executing_string
--;
893 in_paragraph
= saved_in_paragraph
;
894 escape_html
= saved_escape_html
;
897 /* A wrapper around me_execute_string which saves and restores
898 variables important for output generation. This is called
899 when we need to produce macro-expanded output for input which
900 leaves no traces in the Info output. */
902 me_execute_string_keep_state (char *execution_string
, char *append_string
)
904 int op_orig
, opcol_orig
, popen_orig
;
905 int fill_orig
, newline_orig
, indent_orig
, meta_pos_orig
;
907 remember_itext (input_text
, input_text_offset
);
908 op_orig
= output_paragraph_offset
;
909 meta_pos_orig
= meta_char_pos
;
910 opcol_orig
= output_column
;
911 popen_orig
= paragraph_is_open
;
912 fill_orig
= filling_enabled
;
913 newline_orig
= last_char_was_newline
;
915 indent_orig
= no_indent
;
917 me_execute_string (execution_string
);
919 write_region_to_macro_output (append_string
, 0, strlen (append_string
));
920 output_paragraph_offset
= op_orig
;
921 meta_char_pos
= meta_pos_orig
;
922 output_column
= opcol_orig
;
923 paragraph_is_open
= popen_orig
;
924 filling_enabled
= fill_orig
;
925 last_char_was_newline
= newline_orig
;
926 no_indent
= indent_orig
;
929 /* Append the text which appears in input_text from the last offset to
930 the current OFFSET. */
932 append_to_expansion_output (int offset
)
937 for (i
= 0; i
< itext_size
; i
++)
938 if (itext_info
[i
] && itext_info
[i
]->pointer
== input_text
)
940 itext
= itext_info
[i
];
947 if (offset
> itext
->offset
)
949 write_region_to_macro_output (input_text
, itext
->offset
, offset
);
950 remember_itext (input_text
, offset
);
954 /* Only write this input text iff it appears in our itext list. */
956 maybe_write_itext (char *pointer
, int offset
)
961 for (i
= 0; i
< itext_size
; i
++)
962 if (itext_info
[i
] && (itext_info
[i
]->pointer
== pointer
))
964 itext
= itext_info
[i
];
968 if (itext
&& (itext
->offset
< offset
))
970 write_region_to_macro_output (itext
->pointer
, itext
->offset
, offset
);
971 remember_itext (pointer
, offset
);
976 write_region_to_macro_output (char *string
, int start
, int end
)
978 if (macro_expansion_output_stream
)
979 fwrite (string
+ start
, 1, end
- start
, macro_expansion_output_stream
);
984 typedef struct alias_struct
988 struct alias_struct
*next
;
991 static alias_type
*aliases
;
993 /* @alias aname = cmdname */
998 alias_type
*a
= xmalloc (sizeof (alias_type
));
1001 get_until_in_line (0, "=", &(a
->alias
));
1002 canon_white (a
->alias
);
1004 discard_until ("=");
1006 get_until_in_line (0, " ", &(a
->mapto
));
1012 /* Perform an alias expansion. Called from read_command. */
1014 alias_expand (char *tok
)
1016 alias_type
*findit
= aliases
;
1019 if (strcmp (findit
->alias
, tok
) == 0)
1022 return alias_expand (xstrdup (findit
->mapto
));
1025 findit
= findit
->next
;
1030 /* definfoenclose implementation. */
1032 /* This structure is used to track enclosure macros. When an enclosure
1033 macro is recognized, a pointer to the enclosure block corresponding
1034 to its name is saved in the brace element for its argument. */
1035 typedef struct enclose_struct
1040 struct enclose_struct
*next
;
1043 static enclosure_type
*enclosures
;
1045 typedef struct enclosure_stack_struct
1047 enclosure_type
*current
;
1048 struct enclosure_stack_struct
*next
;
1049 } enclosure_stack_type
;
1051 static enclosure_stack_type
*enclosure_stack
;
1053 /* @definfoenclose */
1055 cm_definfoenclose (void)
1057 enclosure_type
*e
= xmalloc (sizeof (enclosure_type
));
1060 get_until_in_line (1, ",", &(e
->enclose
));
1061 discard_until (",");
1062 get_until_in_line (0, ",", &(e
->before
));
1063 discard_until (",");
1064 get_until_in_line (0, "\n", &(e
->after
));
1066 e
->next
= enclosures
;
1070 /* If TOK is an enclosure command, push it on the enclosure stack and
1071 return 1. Else return 0. */
1074 enclosure_command (char *tok
)
1076 enclosure_type
*findit
= enclosures
;
1079 if (strcmp (findit
->enclose
, tok
) == 0)
1081 enclosure_stack_type
*new = xmalloc (sizeof (enclosure_stack_type
));
1082 new->current
= findit
;
1083 new->next
= enclosure_stack
;
1084 enclosure_stack
= new;
1089 findit
= findit
->next
;
1094 /* actually perform the enclosure expansion */
1096 enclosure_expand (int arg
, int start
, int end
)
1099 add_word (enclosure_stack
->current
->before
);
1102 enclosure_stack_type
*temp
;
1104 add_word (enclosure_stack
->current
->after
);
1106 temp
= enclosure_stack
;
1107 enclosure_stack
= enclosure_stack
->next
;