No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / texinfo / makeinfo / macro.c
blob9194b2adb28c9d8443d8c187c102eba68616bd1c
1 /* $NetBSD$ */
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)
11 any later version.
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. */
22 #include "system.h"
23 #include "cmds.h"
24 #include "files.h"
25 #include "macro.h"
26 #include "makeinfo.h"
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. */
59 int
60 array_len (char **array)
62 int i = 0;
64 if (array)
65 for (i = 0; array[i]; i++);
67 return i;
70 void
71 free_array (char **array)
73 if (array)
75 int i;
76 for (i = 0; array[i]; i++)
77 free (array[i]);
79 free (array);
83 /* Return the macro definition of NAME or NULL if NAME is not defined. */
84 MACRO_DEF *
85 find_macro (char *name)
87 int i;
88 MACRO_DEF *def;
90 def = NULL;
91 for (i = 0; macro_list && (def = macro_list[i]); i++)
93 if ((!def->inhibited) && (strcmp (def->name, name) == 0))
94 break;
96 return def;
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. */
104 static void
105 add_macro (char *name, char **arglist, char *body, char *source_file,
106 int source_lineno, int flags)
108 MACRO_DEF *def;
110 def = find_macro (name);
112 if (!def)
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];
122 macro_list_len += 1;
123 def->name = name;
125 else
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;
139 if (def->arglist)
141 int i;
143 for (i = 0; def->arglist[i]; i++)
144 free (def->arglist[i]);
146 free (def->arglist);
148 free (def->source_file);
149 free (def->body);
152 def->source_file = xstrdup (source_file);
153 def->source_lineno = source_lineno;
154 def->body = body;
155 def->arglist = arglist;
156 def->inhibited = 0;
157 def->flags = flags;
161 char **
162 get_brace_args (int quote_single)
164 char **arglist, *word;
165 int arglist_index, arglist_size;
166 int character, escape_seen, start;
167 int depth = 1;
169 /* There is an arglist in braces here, so gather the args inside of it. */
170 skip_whitespace_and_newlines ();
171 input_text_offset++;
172 arglist = NULL;
173 arglist_index = arglist_size = 0;
175 get_arg:
176 skip_whitespace_and_newlines ();
177 start = input_text_offset;
178 escape_seen = 0;
180 while ((character = curchar ()))
182 if (character == '\\')
184 input_text_offset += 2;
185 escape_seen = 1;
187 else if (character == '{')
189 depth++;
190 input_text_offset++;
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);
201 word[len] = 0;
203 /* Clean up escaped characters. */
204 if (escape_seen)
206 int i;
207 for (i = 0; word[i]; i++)
208 if (word[i] == '\\')
209 memmove (word + i, word + i + 1,
210 1 + strlen (word + i + 1));
213 if (arglist_index + 2 >= arglist_size)
214 arglist = xrealloc
215 (arglist, (arglist_size += 10) * sizeof (char *));
217 arglist[arglist_index++] = word;
218 arglist[arglist_index] = NULL;
221 input_text_offset++;
222 if (character == '}')
223 break;
224 else
225 goto get_arg;
227 else if (character == '}')
229 depth--;
230 input_text_offset++;
232 else
234 input_text_offset++;
235 if (character == '\n') line_number++;
238 return arglist;
241 static char **
242 get_macro_args (MACRO_DEF *def)
244 int i;
245 char *word;
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]))
251 break;
253 if (input_text[i] != '{')
255 if (braces_required_for_macro_args)
257 return NULL;
259 else
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])
266 char **arglist;
268 get_rest_of_line (0, &word);
269 if (input_text[input_text_offset - 1] == '\n')
271 input_text_offset--;
272 line_number--;
274 /* canon_white (word); */
275 arglist = xmalloc (2 * sizeof (char *));
276 arglist[0] = word;
277 arglist[1] = NULL;
278 return arglist;
280 else
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. */
285 return NULL;
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\. */
295 static char *
296 apply (char **named, char **actuals, char *body)
298 int i;
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. */
308 i = 0;
309 new_body_index = 0;
311 while (body[i])
312 { /* Anything but a \ is easy. */
313 if (body[i] != '\\')
314 new_body[new_body_index++] = body[i++];
315 else
316 { /* Snarf parameter name, check against named parameters. */
317 char *param;
318 int param_start, len;
320 param_start = ++i;
321 while (body[i] && body[i] != '\\')
322 i++;
324 len = i - param_start;
325 param = xmalloc (1 + len);
326 memcpy (param, body + param_start, len);
327 param[len] = 0;
329 if (body[i]) /* move past \ */
330 i++;
332 if (len == 0)
333 { /* \\ always means \, even if macro has no args. */
334 len++;
335 text = xmalloc (1 + len);
336 sprintf (text, "\\%s", param);
338 else
340 int which;
342 /* Check against named parameters. */
343 for (which = 0; named && named[which]; which++)
344 if (STREQ (named[which], param))
345 break;
347 if (named && named[which])
349 text = which < length_of_actuals ? actuals[which] : NULL;
350 if (!text)
351 text = "";
352 len = strlen (text);
353 text = xstrdup (text); /* so we can free it */
355 else
356 { /* not a parameter, so it's an error. */
357 warning (_("\\ in macro expansion followed by `%s' instead of parameter name"),
358 param);
359 len++;
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);
371 free (param);
373 strcpy (new_body + new_body_index, text);
374 new_body_index += len;
376 free (text);
380 new_body[new_body_index] = 0;
381 return new_body;
384 /* Expand macro passed in DEF, a pointer to a MACRO_DEF, and
385 return its expansion as a string. */
386 char *
387 expand_macro (MACRO_DEF *def)
389 char **arglist;
390 int num_args;
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;
408 if (def->body)
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. */
416 void
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)
427 return;
429 if (def->body)
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);
444 else
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. */
456 static void
457 define_macro (char *mactype, int recursive)
459 int i, start;
460 char *name, *line;
461 char *last_end = NULL;
462 char *body = NULL;
463 char **arglist = NULL;
464 int body_size = 0, body_index = 0;
465 int depth = 1;
466 int flags = 0;
467 int defining_line = line_number;
469 if (macro_expansion_output_stream && !executing_string)
470 me_append_before_this_command ();
472 skip_whitespace ();
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;
478 int len;
480 for (i = start; i < input_text_length && input_text[i] != '{'
481 && !cr_or_whitespace (input_text[i]);
482 i++) ;
484 len = i - start;
485 name = xmalloc (1 + len);
486 memcpy (name, input_text + start, len);
487 name[len] = 0;
488 input_text_offset = i;
491 skip_whitespace ();
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 () == '{')
497 int character;
498 int arglist_index = 0, arglist_size = 0;
499 int gathering_words = 1;
500 char *word = NULL;
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
504 execution time. */
506 input_text_offset++;
507 skip_whitespace_and_newlines ();
509 while (gathering_words)
511 int len;
513 for (i = input_text_offset;
514 (character = input_text[i]);
515 i++)
517 switch (character)
519 case '\n':
520 line_number++;
521 case ' ':
522 case '\t':
523 case ',':
524 case '}':
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);
529 word[len] = 0;
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 ())
535 && character != ','
536 && character != '}')
538 input_text_offset++;
539 if (character == '\n')
540 line_number++;
543 /* Add the word to our list of words. */
544 if (arglist_index + 2 >= arglist_size)
546 arglist_size += 10;
547 arglist = xrealloc (arglist,
548 arglist_size * sizeof (char *));
551 arglist[arglist_index++] = word;
552 arglist[arglist_index] = NULL;
553 break;
556 if (character == '}')
558 input_text_offset++;
559 gathering_words = 0;
560 break;
563 if (character == ',')
565 input_text_offset++;
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 ();
583 while (depth)
585 if ((input_text_offset + 9) > input_text_length)
587 file_line_error (input_filename, defining_line,
588 _("%cend macro not found"), COMMAND_PREFIX);
589 return;
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);
601 flags |= ME_RECURSE;
602 if (!*line)
604 free (line);
605 continue;
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;
619 if (!*line)
621 free (line);
622 continue;
625 else
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))
632 depth++;
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)
639 depth--;
640 last_end = "macro";
642 if (*line == COMMAND_PREFIX && strncmp (line + 1, "end rmacro", 10) == 0)
644 depth--;
645 last_end = "rmacro";
648 if (depth)
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;
657 free (line);
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
665 @macro foo
666 @end macro
667 create an empty body. (Otherwise, the macro is not expanded.) */
668 if (!body)
670 body = (char *)malloc(1);
671 *body = 0;
674 /* We now have the name, the arglist, and the body. However, BODY
675 includes the final newline which preceded the `@end macro' text.
676 Delete it. */
677 if (body && strlen (body))
678 body[strlen (body) - 1] = 0;
680 if (recursive)
681 flags |= ME_RECURSE;
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);
704 void
705 cm_macro (void)
707 define_macro ("macro", 0);
710 void
711 cm_rmacro (void)
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
718 returned. */
720 static MACRO_DEF *
721 delete_macro (char *name)
723 int i;
724 MACRO_DEF *def;
726 def = NULL;
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 *));
733 macro_list_len--;
734 break;
736 return def;
739 void
740 cm_unmacro (void)
742 int i;
743 char *line, *name;
744 MACRO_DEF *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);
754 name[i] = 0;
756 def = delete_macro (name);
758 if (def)
760 free (def->source_file);
761 free (def->name);
762 free (def->body);
764 if (def->arglist)
766 int i;
768 for (i = 0; def->arglist[i]; i++)
769 free (def->arglist[i]);
771 free (def->arglist);
774 free (def);
777 free (line);
778 free (name);
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. */
787 ITEXT *
788 remember_itext (char *pointer, int offset)
790 int i;
791 ITEXT *itext = NULL;
793 /* If we have no info, initialize a blank list. */
794 if (!itext_info)
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;
808 break;
811 if (i == itext_size)
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)
817 break;
819 /* If not found, then add some slots. */
820 if (i == itext_size)
822 int j;
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];
837 return itext;
840 /* Forget the input text associated with POINTER. */
841 void
842 forget_itext (char *pointer)
844 int i;
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;
851 break;
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. */
857 void
858 me_append_before_this_command (void)
860 int i;
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. */
869 void
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;
875 in_paragraph = 0;
877 pushfile ();
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++;
887 reader_loop ();
888 free (input_text);
889 free (input_filename);
890 popfile ();
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. */
901 void
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;
914 filling_enabled = 0;
915 indent_orig = no_indent;
916 no_indent = 1;
917 me_execute_string (execution_string);
918 if (append_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. */
931 void
932 append_to_expansion_output (int offset)
934 int i;
935 ITEXT *itext = NULL;
937 for (i = 0; i < itext_size; i++)
938 if (itext_info[i] && itext_info[i]->pointer == input_text)
940 itext = itext_info[i];
941 break;
944 if (!itext)
945 return;
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. */
955 void
956 maybe_write_itext (char *pointer, int offset)
958 int i;
959 ITEXT *itext = NULL;
961 for (i = 0; i < itext_size; i++)
962 if (itext_info[i] && (itext_info[i]->pointer == pointer))
964 itext = itext_info[i];
965 break;
968 if (itext && (itext->offset < offset))
970 write_region_to_macro_output (itext->pointer, itext->offset, offset);
971 remember_itext (pointer, offset);
975 void
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);
982 /* Aliases. */
984 typedef struct alias_struct
986 char *alias;
987 char *mapto;
988 struct alias_struct *next;
989 } alias_type;
991 static alias_type *aliases;
993 /* @alias aname = cmdname */
995 void
996 cm_alias (void)
998 alias_type *a = xmalloc (sizeof (alias_type));
1000 skip_whitespace ();
1001 get_until_in_line (0, "=", &(a->alias));
1002 canon_white (a->alias);
1004 discard_until ("=");
1005 skip_whitespace ();
1006 get_until_in_line (0, " ", &(a->mapto));
1008 a->next = aliases;
1009 aliases = a;
1012 /* Perform an alias expansion. Called from read_command. */
1013 char *
1014 alias_expand (char *tok)
1016 alias_type *findit = aliases;
1018 while (findit)
1019 if (strcmp (findit->alias, tok) == 0)
1021 free (tok);
1022 return alias_expand (xstrdup (findit->mapto));
1024 else
1025 findit = findit->next;
1027 return tok;
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
1037 char *enclose;
1038 char *before;
1039 char *after;
1040 struct enclose_struct *next;
1041 } enclosure_type;
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 */
1054 void
1055 cm_definfoenclose (void)
1057 enclosure_type *e = xmalloc (sizeof (enclosure_type));
1059 skip_whitespace ();
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;
1067 enclosures = e;
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;
1078 while (findit)
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;
1086 return 1;
1088 else
1089 findit = findit->next;
1091 return 0;
1094 /* actually perform the enclosure expansion */
1095 void
1096 enclosure_expand (int arg, int start, int end)
1098 if (arg == START)
1099 add_word (enclosure_stack->current->before);
1100 else
1102 enclosure_stack_type *temp;
1104 add_word (enclosure_stack->current->after);
1106 temp = enclosure_stack;
1107 enclosure_stack = enclosure_stack->next;
1108 free (temp);