156160Sru/* defun.c -- @defun and friends.
2146515Sru   $Id: defun.c,v 1.11 2004/04/11 17:56:46 karl Exp $
356160Sru
4146515Sru   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
5116525Sru   Foundation, Inc.
656160Sru
756160Sru   This program is free software; you can redistribute it and/or modify
856160Sru   it under the terms of the GNU General Public License as published by
956160Sru   the Free Software Foundation; either version 2, or (at your option)
1056160Sru   any later version.
1156160Sru
1256160Sru   This program is distributed in the hope that it will be useful,
1356160Sru   but WITHOUT ANY WARRANTY; without even the implied warranty of
1456160Sru   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1556160Sru   GNU General Public License for more details.
1656160Sru
1756160Sru   You should have received a copy of the GNU General Public License
1856160Sru   along with this program; if not, write to the Free Software Foundation,
1956160Sru   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
2056160Sru
2156160Sru#include "system.h"
2256160Sru#include "defun.h"
23114472Sru#include "xml.h"
2456160Sru#include "insertion.h"
2556160Sru#include "makeinfo.h"
26114472Sru#include "cmds.h"
27114472Sru#include "html.h"
2856160Sru
2956160Sru
3056160Sru#define DEFUN_SELF_DELIMITING(c) \
3156160Sru  ((c) == '(' || (c) == ')' || (c) == '[' || (c) == ']')
3256160Sru
3356160Srustruct token_accumulator
3456160Sru{
3556160Sru  unsigned int length;
3656160Sru  unsigned int index;
3756160Sru  char **tokens;
3856160Sru};
3956160Sru
4056160Srustatic void
41146515Sruinitialize_token_accumulator (struct token_accumulator *accumulator)
4256160Sru{
4356160Sru  accumulator->length = 0;
4456160Sru  accumulator->index = 0;
4556160Sru  accumulator->tokens = NULL;
4656160Sru}
4756160Sru
4856160Srustatic void
49146515Sruaccumulate_token (struct token_accumulator *accumulator, char *token)
5056160Sru{
5156160Sru  if (accumulator->index >= accumulator->length)
5256160Sru    {
5356160Sru      accumulator->length += 10;
5456160Sru      accumulator->tokens = xrealloc (accumulator->tokens,
5556160Sru                                      (accumulator->length * sizeof (char *)));
5656160Sru    }
5756160Sru  accumulator->tokens[accumulator->index] = token;
5856160Sru  accumulator->index += 1;
5956160Sru}
6056160Sru
6156160Sru/* Given STRING_POINTER pointing at an open brace, skip forward and return a
6256160Sru   pointer to just past the matching close brace. */
6356160Srustatic int
64146515Sruscan_group_in_string (char **string_pointer)
6556160Sru{
6656160Sru  char *scan_string = (*string_pointer) + 1;
6756160Sru  unsigned int level = 1;
68100513Sru  int started_command = 0;
6956160Sru
7056160Sru  for (;;)
7156160Sru    {
7256160Sru      int c;
7356160Sru      if (level == 0)
7456160Sru        {
7556160Sru          *string_pointer = scan_string;
7656160Sru          return 1;
7756160Sru        }
7856160Sru      c = *scan_string++;
7956160Sru      if (c == 0)
8056160Sru        {
8156160Sru          /* Tweak line_number to compensate for fact that
8256160Sru             we gobbled the whole line before coming here. */
83100513Sru          line_number--;
8456160Sru          line_error (_("Missing `}' in @def arg"));
85100513Sru          line_number++;
8656160Sru          *string_pointer = scan_string - 1;
8756160Sru          return 0;
8856160Sru        }
8956160Sru
90100513Sru      if (c == '{' && !started_command)
91100513Sru        level++;
92100513Sru      if (c == '}' && !started_command)
93100513Sru        level--;
94100513Sru
95100513Sru      /* remember if at @.  */
96100513Sru      started_command = (c == '@' && !started_command);
9756160Sru    }
9856160Sru}
9956160Sru
10056160Sru/* Return a list of tokens from the contents of STRING.
10156160Sru   Commands and brace-delimited groups count as single tokens.
10256160Sru   Contiguous whitespace characters are converted to a token
10356160Sru   consisting of a single space. */
10456160Srustatic char **
105146515Sruargs_from_string (char *string)
10656160Sru{
10756160Sru  struct token_accumulator accumulator;
10856160Sru  char *token_start, *token_end;
10956160Sru  char *scan_string = string;
11056160Sru
11156160Sru  initialize_token_accumulator (&accumulator);
11256160Sru
11356160Sru  while (*scan_string)
11456160Sru    { /* Replace arbitrary whitespace by a single space. */
11556160Sru      if (whitespace (*scan_string))
11656160Sru        {
11756160Sru          scan_string += 1;
11856160Sru          while (whitespace (*scan_string))
11956160Sru            scan_string += 1;
12056160Sru          accumulate_token ((&accumulator), (xstrdup (" ")));
12156160Sru          continue;
12256160Sru        }
12356160Sru
12456160Sru      /* Commands count as single tokens. */
12556160Sru      if (*scan_string == COMMAND_PREFIX)
12656160Sru        {
12756160Sru          token_start = scan_string;
12856160Sru          scan_string += 1;
12956160Sru          if (self_delimiting (*scan_string))
13056160Sru            scan_string += 1;
13156160Sru          else
13256160Sru            {
13356160Sru              int c;
13456160Sru              while (1)
13556160Sru                {
13656160Sru                  c = *scan_string++;
13756160Sru
13856160Sru                  if ((c == 0) || (c == '{') || (whitespace (c)))
13956160Sru                    {
14056160Sru                      scan_string -= 1;
14156160Sru                      break;
14256160Sru                    }
14356160Sru                }
14456160Sru
14556160Sru              if (*scan_string == '{')
14656160Sru                {
14756160Sru                  char *s = scan_string;
14856160Sru                  (void) scan_group_in_string (&s);
14956160Sru                  scan_string = s;
15056160Sru                }
15156160Sru            }
15256160Sru          token_end = scan_string;
15356160Sru        }
15456160Sru
15556160Sru      /* Parentheses and brackets are self-delimiting. */
15656160Sru      else if (DEFUN_SELF_DELIMITING (*scan_string))
15756160Sru        {
15856160Sru          token_start = scan_string;
15956160Sru          scan_string += 1;
16056160Sru          token_end = scan_string;
16156160Sru        }
16256160Sru
16356160Sru      /* Open brace introduces a group that is a single token. */
16456160Sru      else if (*scan_string == '{')
16556160Sru        {
16656160Sru          char *s = scan_string;
16756160Sru          int balanced = scan_group_in_string (&s);
16856160Sru
16956160Sru          token_start = scan_string + 1;
17056160Sru          scan_string = s;
17156160Sru          token_end = balanced ? (scan_string - 1) : scan_string;
17256160Sru        }
17356160Sru
174146515Sru      /* Make commas separate tokens so to differentiate them from
175146515Sru         parameter types in XML output. */
176146515Sru      else if (*scan_string == ',')
177146515Sru	{
178146515Sru          token_start = scan_string;
179146515Sru          scan_string += 1;
180146515Sru          token_end = scan_string;
181146515Sru	}
182146515Sru
18356160Sru      /* Otherwise a token is delimited by whitespace, parentheses,
18456160Sru         brackets, or braces.  A token is also ended by a command. */
18556160Sru      else
18656160Sru        {
18756160Sru          token_start = scan_string;
18856160Sru
18956160Sru          for (;;)
19056160Sru            {
19156160Sru              int c;
19256160Sru
19356160Sru              c = *scan_string++;
19456160Sru
19556160Sru              /* Do not back up if we're looking at a }; since the only
19656160Sru                 valid }'s are those matched with {'s, we want to give
19756160Sru                 an error.  If we back up, we go into an infinite loop.  */
19856160Sru              if (!c || whitespace (c) || DEFUN_SELF_DELIMITING (c)
19956160Sru                  || c == '{')
20056160Sru                {
20156160Sru                  scan_string--;
20256160Sru                  break;
20356160Sru                }
20456160Sru
205146515Sru	      /* End token if we are looking at a comma, as commas are
206146515Sru		 delimiters too. */
207146515Sru	      if (c == ',')
208146515Sru		{
209146515Sru		  scan_string--;
210146515Sru		  break;
211146515Sru		}
212146515Sru
21356160Sru              /* If we encounter a command embedded within a token,
21456160Sru                 then end the token. */
21556160Sru              if (c == COMMAND_PREFIX)
21656160Sru                {
21756160Sru                  scan_string--;
21856160Sru                  break;
21956160Sru                }
22056160Sru            }
22156160Sru          token_end = scan_string;
22256160Sru        }
22356160Sru
22456160Sru      accumulate_token (&accumulator, substring (token_start, token_end));
22556160Sru    }
22656160Sru  accumulate_token (&accumulator, NULL);
22756160Sru  return accumulator.tokens;
22856160Sru}
22956160Sru
23056160Srustatic void
231146515Sruprocess_defun_args (char **defun_args, int auto_var_p)
23256160Sru{
23356160Sru  int pending_space = 0;
23456160Sru
235146515Sru  if (xml)
236146515Sru    {
237146515Sru      xml_process_defun_args (defun_args, auto_var_p);
238146515Sru      return;
239146515Sru    }
240146515Sru
24156160Sru  for (;;)
24256160Sru    {
24356160Sru      char *defun_arg = *defun_args++;
24456160Sru
24556160Sru      if (defun_arg == NULL)
24656160Sru        break;
24756160Sru
24856160Sru      if (defun_arg[0] == ' ')
24956160Sru        {
25056160Sru          pending_space = 1;
25156160Sru          continue;
25256160Sru        }
25356160Sru
25456160Sru      if (pending_space)
25556160Sru        {
25656160Sru          add_char (' ');
25756160Sru          pending_space = 0;
25856160Sru        }
25956160Sru
26056160Sru      if (DEFUN_SELF_DELIMITING (defun_arg[0]))
261114472Sru        {
262114472Sru          /* Within @deffn and friends, texinfo.tex makes parentheses
263114472Sru             sans serif and brackets bold.  We use roman instead.  */
264146515Sru          if (html)
265146515Sru            insert_html_tag (START, "");
266146515Sru
267114472Sru          add_char (defun_arg[0]);
268146515Sru
269146515Sru          if (html)
270146515Sru            insert_html_tag (END, "");
271114472Sru        }
272146515Sru      /* else if (defun_arg[0] == '&' || defun_arg[0] == COMMAND_PREFIX) */
273146515Sru        /* execute_string ("%s", defun_arg); */
274146515Sru      /* else if (auto_var_p) */
275146515Sru        /* execute_string ("%s", defun_arg); */
276146515Sru      else
27756160Sru        execute_string ("%s", defun_arg);
27856160Sru    }
27956160Sru}
28056160Sru
28156160Srustatic char *
282146515Srunext_nonwhite_defun_arg (char ***arg_pointer)
28356160Sru{
28456160Sru  char **scan = (*arg_pointer);
28556160Sru  char *arg = (*scan++);
28656160Sru
28756160Sru  if ((arg != 0) && (*arg == ' '))
28856160Sru    arg = *scan++;
28956160Sru
29056160Sru  if (arg == 0)
29156160Sru    scan -= 1;
29256160Sru
29356160Sru  *arg_pointer = scan;
29456160Sru
29556160Sru  return (arg == 0) ? "" : arg;
29656160Sru}
29756160Sru
29856160Sru
29956160Sru/* This is needed also in insertion.c.  */
30056160Sru
30156160Sruenum insertion_type
302146515Sruget_base_type (int type)
30356160Sru{
304146515Sru  int base_type;
30556160Sru  switch (type)
30656160Sru    {
30756160Sru    case defivar:	base_type = defcv; break;
30856160Sru    case defmac:	base_type = deffn; break;
30956160Sru    case defmethod:	base_type = defop; break;
31056160Sru    case defopt:	base_type = defvr; break;
31156160Sru    case defspec:	base_type = deffn; break;
312146515Sru    case deftypecv:	base_type = deftypecv; break;
31356160Sru    case deftypefun:	base_type = deftypefn; break;
31456160Sru    case deftypeivar:	base_type = deftypeivar; break;
31556160Sru    case deftypemethod:	base_type = deftypemethod; break;
31656160Sru    case deftypeop:	base_type = deftypeop; break;
31756160Sru    case deftypevar:	base_type = deftypevr; break;
31856160Sru    case defun:		base_type = deffn; break;
31956160Sru    case defvar:	base_type = defvr; break;
32056160Sru    default:
32156160Sru      base_type = type;
32256160Sru      break;
32356160Sru    }
32456160Sru
32556160Sru  return base_type;
32656160Sru}
32756160Sru
32856160Sru/* Make the defun type insertion.
32956160Sru   TYPE says which insertion this is.
33056160Sru   X_P, if nonzero, says not to start a new insertion. */
33156160Srustatic void
332146515Srudefun_internal (int type, int x_p)
33356160Sru{
334146515Sru  int base_type;
33556160Sru  char **defun_args, **scan_args;
336116525Sru  const char *category;
337146515Sru  char *defined_name;
338146515Sru  char *type_name = NULL;
339146515Sru  char *type_name2 = NULL;
34056160Sru
34156160Sru  {
34256160Sru    char *line;
34356160Sru
34456160Sru    /* The @def.. line is the only place in Texinfo where you are
34556160Sru       allowed to use unquoted braces that don't delimit arguments of
34656160Sru       a command or a macro; in any other place it will trigger an
34756160Sru       error message from the reader loop.  The special handling of
34856160Sru       this case inside `args_from_string' is an extra special hack
34956160Sru       which allows this.  The side effect is that if we try to expand
35056160Sru       the rest of the line below, the recursive reader loop will
35156160Sru       signal an error if there are brace-delimited arguments on that line.
35256160Sru
35356160Sru       The best solution to this would be to change the syntax of
35456160Sru       @def.. commands so that it doesn't violate Texinfo's own rules.
35556160Sru       But it's probably too late for this now, as it will break a lot
35656160Sru       of existing manuals.
35756160Sru
35856160Sru       Unfortunately, this means that you can't call macros, use @value, etc.
35956160Sru       inside @def.. commands, sigh.  */
36056160Sru    get_rest_of_line (0, &line);
361146515Sru
362146515Sru    /* Basic line continuation.  If a line ends with \s*@\s* concatanate
363146515Sru       the next line. */
364146515Sru    {
365146515Sru      char *next_line, *new_line;
366146515Sru      int i;
367146515Sru
368146515Sru      line_continuation:
369146515Sru        i = strlen (line) - 1;
370146515Sru
371146515Sru        if (line[i] == '@' && line[i-1] != '@')
372146515Sru          {
373146515Sru            get_rest_of_line (0, &next_line);
374146515Sru            new_line = (char *) xmalloc (i + strlen (next_line) + 2);
375146515Sru            strncpy (new_line, line, i);
376146515Sru            new_line[i] = '\0';
377146515Sru            free (line);
378146515Sru            strcat (new_line, " ");
379146515Sru            strcat (new_line, next_line);
380146515Sru            line = xstrdup (new_line);
381146515Sru            free (next_line);
382146515Sru            free (new_line);
383146515Sru
384146515Sru            goto line_continuation;
385146515Sru          }
386146515Sru    }
387146515Sru
38856160Sru    defun_args = (args_from_string (line));
38956160Sru    free (line);
39056160Sru  }
39156160Sru
39256160Sru  scan_args = defun_args;
39356160Sru
39456160Sru  /* Get base type and category string.  */
39556160Sru  base_type = get_base_type (type);
39656160Sru
39756160Sru  /* xx all these const strings should be determined upon
39856160Sru     documentlanguage argument and NOT via gettext  (kama).  */
39956160Sru  switch (type)
40056160Sru    {
40156160Sru    case defun:
40256160Sru    case deftypefun:
40356160Sru      category = _("Function");
40456160Sru      break;
40556160Sru    case defmac:
40656160Sru      category = _("Macro");
40756160Sru      break;
40856160Sru    case defspec:
40956160Sru      category = _("Special Form");
41056160Sru      break;
41156160Sru    case defvar:
41256160Sru    case deftypevar:
41356160Sru      category = _("Variable");
41456160Sru      break;
41556160Sru    case defopt:
41656160Sru      category = _("User Option");
41756160Sru      break;
41856160Sru    case defivar:
41956160Sru    case deftypeivar:
42056160Sru      category = _("Instance Variable");
42156160Sru      break;
42256160Sru    case defmethod:
42356160Sru    case deftypemethod:
42456160Sru      category = _("Method");
42556160Sru      break;
42656160Sru    default:
42756160Sru      category = next_nonwhite_defun_arg (&scan_args);
42856160Sru      break;
42956160Sru    }
43056160Sru
43156160Sru  /* The class name.  */
432146515Sru  if ((base_type == deftypecv)
433146515Sru      || (base_type == deftypefn)
43456160Sru      || (base_type == deftypevr)
43556160Sru      || (base_type == defcv)
43656160Sru      || (base_type == defop)
43756160Sru      || (base_type == deftypeivar)
43856160Sru      || (base_type == deftypemethod)
43956160Sru      || (base_type == deftypeop)
44056160Sru     )
44156160Sru    type_name = next_nonwhite_defun_arg (&scan_args);
44256160Sru
44356160Sru  /* The type name for typed languages.  */
444146515Sru  if ((base_type == deftypecv)
44593139Sru      || (base_type == deftypeivar)
446146515Sru      || (base_type == deftypemethod)
44793139Sru      || (base_type == deftypeop)
44856160Sru     )
44956160Sru    type_name2 = next_nonwhite_defun_arg (&scan_args);
45056160Sru
45156160Sru  /* The function or whatever that's actually being defined.  */
45256160Sru  defined_name = next_nonwhite_defun_arg (&scan_args);
45356160Sru
45456160Sru  /* This hack exists solely for the purposes of formatting the Texinfo
45556160Sru     manual.  I couldn't think of a better way.  The token might be a
45656160Sru     simple @@ followed immediately by more text.  If this is the case,
45756160Sru     then the next defun arg is part of this one, and we should
45856160Sru     concatenate them. */
45956160Sru  if (*scan_args && **scan_args && !whitespace (**scan_args)
46056160Sru       && STREQ (defined_name, "@@"))
46156160Sru    {
46256160Sru      char *tem = xmalloc (3 + strlen (scan_args[0]));
46356160Sru
46456160Sru      sprintf (tem, "@@%s", scan_args[0]);
46556160Sru
46656160Sru      free (scan_args[0]);
46756160Sru      scan_args[0] = tem;
46856160Sru      scan_args++;
46956160Sru      defined_name = tem;
47056160Sru    }
47156160Sru
47293139Sru  /* It's easy to write @defun foo(arg1 arg2), but a following ( is
47393139Sru     misparsed by texinfo.tex and this is next to impossible to fix.
47493139Sru     Warn about it.  */
47593139Sru  if (*scan_args && **scan_args && **scan_args == '(')
47693139Sru    warning ("`%c' follows defined name `%s' instead of whitespace",
47793139Sru             **scan_args, defined_name);
478116525Sru
47956160Sru  if (!x_p)
48056160Sru    begin_insertion (type);
48156160Sru
48256160Sru  /* Write the definition header line.
48356160Sru     This should start at the normal indentation.  */
48456160Sru  current_indent -= default_indentation_increment;
48556160Sru  start_paragraph ();
48656160Sru
487146515Sru  if (!html && !xml)
48856160Sru    switch (base_type)
48956160Sru      {
49056160Sru      case deffn:
49156160Sru      case defvr:
49256160Sru      case deftp:
493146515Sru        execute_string (" --- %s: %s", category, defined_name);
49456160Sru        break;
49556160Sru      case deftypefn:
49656160Sru      case deftypevr:
497146515Sru        execute_string (" --- %s: %s %s", category, type_name, defined_name);
49856160Sru        break;
49956160Sru      case defcv:
500146515Sru        execute_string (" --- %s %s %s: %s", category, _("of"), type_name,
50156160Sru                        defined_name);
50256160Sru        break;
503146515Sru      case deftypecv:
50456160Sru      case deftypeivar:
505146515Sru        execute_string (" --- %s %s %s: %s %s", category, _("of"), type_name,
50656160Sru                        type_name2, defined_name);
50756160Sru        break;
50856160Sru      case defop:
509146515Sru        execute_string (" --- %s %s %s: %s", category, _("on"), type_name,
51056160Sru                        defined_name);
51156160Sru        break;
51256160Sru      case deftypeop:
513146515Sru        execute_string (" --- %s %s %s: %s %s", category, _("on"), type_name,
51456160Sru                        type_name2, defined_name);
51556160Sru        break;
51656160Sru      case deftypemethod:
517146515Sru        execute_string (" --- %s %s %s: %s %s", category, _("on"), type_name,
51856160Sru                        type_name2, defined_name);
51956160Sru        break;
52056160Sru      }
521146515Sru  else if (html)
52256160Sru    {
52356160Sru      /* If this is not a @def...x version, it could only
52456160Sru         be a normal version @def.... So start the table here.  */
52556160Sru      if (!x_p)
526146515Sru        insert_string ("<div class=\"defun\">\n");
527146515Sru      else
528146515Sru        rollback_empty_tag ("blockquote");
52956160Sru
530146515Sru      /* xx The single words (on, off) used here, should depend on
531146515Sru         documentlanguage and NOT on gettext  --kama.  */
532146515Sru      switch (base_type)
533146515Sru        {
534146515Sru        case deffn:
535146515Sru        case defvr:
536146515Sru        case deftp:
537146515Sru        case deftypefn:
538146515Sru        case deftypevr:
539146515Sru          execute_string ("--- %s: ", category);
540146515Sru          break;
54156160Sru
542146515Sru        case defcv:
543146515Sru        case deftypecv:
544146515Sru        case deftypeivar:
545146515Sru	  execute_string ("--- %s %s %s: ", category, _("of"), type_name);
546146515Sru	  break;
547146515Sru
548146515Sru        case defop:
549146515Sru        case deftypemethod:
550146515Sru        case deftypeop:
551146515Sru	  execute_string ("--- %s %s %s: ", category, _("on"), type_name);
552146515Sru	  break;
553146515Sru	} /* switch (base_type)... */
554146515Sru
55556160Sru      switch (base_type)
55656160Sru        {
55756160Sru        case deffn:
55856160Sru        case defvr:
55956160Sru        case deftp:
560146515Sru          /* <var> is for the following function arguments.  */
561114472Sru          insert_html_tag (START, "b");
56293139Sru          execute_string ("%s", defined_name);
563114472Sru          insert_html_tag (END, "b");
564146515Sru          insert_html_tag (START, "var");
56556160Sru          break;
56656160Sru        case deftypefn:
56756160Sru        case deftypevr:
56893139Sru          execute_string ("%s ", type_name);
569114472Sru          insert_html_tag (START, "b");
57093139Sru          execute_string ("%s", defined_name);
571114472Sru          insert_html_tag (END, "b");
572146515Sru          insert_html_tag (START, "var");
57356160Sru          break;
57456160Sru        case defcv:
57556160Sru        case defop:
576114472Sru          insert_html_tag (START, "b");
57793139Sru          execute_string ("%s", defined_name);
578114472Sru          insert_html_tag (END, "b");
579146515Sru          insert_html_tag (START, "var");
58056160Sru          break;
581146515Sru        case deftypecv:
582146515Sru        case deftypeivar:
58356160Sru        case deftypemethod:
58456160Sru        case deftypeop:
58593139Sru          execute_string ("%s ", type_name2);
586114472Sru          insert_html_tag (START, "b");
58793139Sru          execute_string ("%s", defined_name);
588114472Sru          insert_html_tag (END, "b");
589146515Sru          insert_html_tag (START, "var");
59056160Sru          break;
59156160Sru        }
592146515Sru    }
593146515Sru  else if (xml)
594146515Sru    xml_begin_def_term (base_type, category, defined_name, type_name,
595146515Sru	type_name2);
59656160Sru
59756160Sru  current_indent += default_indentation_increment;
59856160Sru
59956160Sru  /* Now process the function arguments, if any.  If these carry onto
60056160Sru     the next line, they should be indented by two increments to
60156160Sru     distinguish them from the body of the definition, which is indented
60256160Sru     by one increment.  */
60356160Sru  current_indent += default_indentation_increment;
60456160Sru
60556160Sru  switch (base_type)
60656160Sru    {
60756160Sru    case deffn:
60856160Sru    case defop:
60956160Sru      process_defun_args (scan_args, 1);
61056160Sru      break;
61156160Sru
61256160Sru      /* Through Makeinfo 1.67 we processed remaining args only for deftp,
61356160Sru         deftypefn, and deftypemethod.  But the libc manual, for example,
61456160Sru         needs to say:
61556160Sru            @deftypevar {char *} tzname[2]
61656160Sru         And simply allowing the extra text seems far simpler than trying
61756160Sru         to invent yet more defn commands.  In any case, we should either
61856160Sru         output it or give an error, not silently ignore it.  */
61956160Sru    default:
62056160Sru      process_defun_args (scan_args, 0);
62156160Sru      break;
62256160Sru    }
62356160Sru
62456160Sru  current_indent -= default_indentation_increment;
625146515Sru  if (!html)
626146515Sru    close_single_paragraph ();
62756160Sru
628146515Sru  /* Make an entry in the appropriate index.  (XML and
629146515Sru     Docbook already got their entries, so skip them.)  */
630146515Sru  if (!xml)
631146515Sru    switch (base_type)
632146515Sru      {
633146515Sru      case deffn:
634146515Sru      case deftypefn:
635146515Sru	execute_string ("@findex %s\n", defined_name);
636146515Sru	break;
637146515Sru      case defcv:
638146515Sru      case deftypecv:
639146515Sru      case deftypevr:
640146515Sru      case defvr:
641146515Sru	execute_string ("@vindex %s\n", defined_name);
642146515Sru	break;
643146515Sru      case deftypeivar:
644146515Sru	execute_string ("@vindex %s %s %s\n", defined_name, _("of"),
645146515Sru                        type_name);
646146515Sru	break;
647146515Sru      case defop:
648146515Sru      case deftypeop:
649146515Sru      case deftypemethod:
650146515Sru	execute_string ("@findex %s %s %s\n", defined_name, _("on"),
651146515Sru                        type_name);
652146515Sru	break;
653146515Sru      case deftp:
654146515Sru	execute_string ("@tindex %s\n", defined_name);
655146515Sru	break;
656146515Sru      }
65793139Sru
658146515Sru  if (xml)
659146515Sru    xml_end_def_term ();
660146515Sru  else if (html)
66156160Sru    {
662146515Sru      inhibit_paragraph_indentation = 1;
663146515Sru      no_indent = 1;
664146515Sru      insert_html_tag (END, "var");
665146515Sru      insert_string ("<br>\n");
666146515Sru      /* Indent the definition a bit.  */
667146515Sru      add_html_block_elt ("<blockquote>");
668146515Sru      no_indent = 0;
669146515Sru      inhibit_paragraph_indentation = 0;
670146515Sru      paragraph_is_open = 0;
67156160Sru    }
67256160Sru
67356160Sru  /* Deallocate the token list. */
67456160Sru  scan_args = defun_args;
67556160Sru  while (1)
67656160Sru    {
67756160Sru      char * arg = (*scan_args++);
67856160Sru      if (arg == NULL)
67956160Sru        break;
68056160Sru      free (arg);
68156160Sru    }
68256160Sru  free (defun_args);
68356160Sru}
68456160Sru
68556160Sru/* Add an entry for a function, macro, special form, variable, or option.
68656160Sru   If the name of the calling command ends in `x', then this is an extra
68756160Sru   entry included in the body of an insertion of the same type. */
68856160Sruvoid
689146515Srucm_defun (void)
69056160Sru{
691146515Sru  int type;
692116525Sru  char *base_command = xstrdup (command);  /* command with any `x' removed */
693116525Sru  int x_p = (command[strlen (command) - 1] == 'x');
69456160Sru
69556160Sru  if (x_p)
696116525Sru    base_command[strlen (base_command) - 1] = 0;
69756160Sru
698116525Sru  type = find_type_from_name (base_command);
69956160Sru
70056160Sru  /* If we are adding to an already existing insertion, then make sure
70156160Sru     that we are already in an insertion of type TYPE. */
702146515Sru  if (x_p)
70356160Sru    {
704146515Sru      INSERTION_ELT *i = insertion_stack;
705146515Sru      /* Skip over ifclear and ifset conditionals.  */
706146515Sru      while (i && (i->insertion == ifset || i->insertion == ifclear))
707146515Sru        i = i->next;
708146515Sru
709146515Sru      if (!i || i->insertion != type)
710146515Sru        {
711146515Sru          line_error (_("Must be in `@%s' environment to use `@%s'"),
712146515Sru                      base_command, command);
713146515Sru          discard_until ("\n");
714146515Sru          return;
715146515Sru        }
71656160Sru    }
71756160Sru
718146515Sru  defun_internal (type, x_p);
719116525Sru  free (base_command);
72056160Sru}
721