Home | History | Annotate | Line # | Download | only in makeinfo
      1 /*	$NetBSD: defun.c,v 1.4 2025/12/31 22:18:50 oster Exp $	*/
      2 
      3 /* defun.c -- @defun and friends.
      4    Id: defun.c,v 1.11 2004/04/11 17:56:46 karl Exp
      5 
      6    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
      7    Foundation, Inc.
      8 
      9    This program is free software; you can redistribute it and/or modify
     10    it under the terms of the GNU General Public License as published by
     11    the Free Software Foundation; either version 2, or (at your option)
     12    any later version.
     13 
     14    This program is distributed in the hope that it will be useful,
     15    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17    GNU General Public License for more details.
     18 
     19    You should have received a copy of the GNU General Public License
     20    along with this program; if not, write to the Free Software Foundation,
     21    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
     22 
     23 #include "system.h"
     24 #include "defun.h"
     25 #include "xml.h"
     26 #include "insertion.h"
     27 #include "makeinfo.h"
     28 #include "cmds.h"
     29 #include "html.h"
     30 
     31 
     32 #define DEFUN_SELF_DELIMITING(c) \
     33   ((c) == '(' || (c) == ')' || (c) == '[' || (c) == ']')
     34 
     35 struct token_accumulator
     36 {
     37   unsigned int length;
     38   unsigned int index;
     39   char **tokens;
     40 };
     41 
     42 static void
     43 initialize_token_accumulator (struct token_accumulator *accumulator)
     44 {
     45   accumulator->length = 0;
     46   accumulator->index = 0;
     47   accumulator->tokens = NULL;
     48 }
     49 
     50 static void
     51 accumulate_token (struct token_accumulator *accumulator, char *token)
     52 {
     53   if (accumulator->index >= accumulator->length)
     54     {
     55       accumulator->length += 10;
     56       accumulator->tokens = xrealloc (accumulator->tokens,
     57                                       (accumulator->length * sizeof (char *)));
     58     }
     59   accumulator->tokens[accumulator->index] = token;
     60   accumulator->index += 1;
     61 }
     62 
     63 /* Given STRING_POINTER pointing at an open brace, skip forward and return a
     64    pointer to just past the matching close brace. */
     65 static int
     66 scan_group_in_string (char **string_pointer)
     67 {
     68   char *scan_string = (*string_pointer) + 1;
     69   unsigned int level = 1;
     70   int started_command = 0;
     71 
     72   for (;;)
     73     {
     74       int c;
     75       if (level == 0)
     76         {
     77           *string_pointer = scan_string;
     78           return 1;
     79         }
     80       c = *scan_string++;
     81       if (c == 0)
     82         {
     83           /* Tweak line_number to compensate for fact that
     84              we gobbled the whole line before coming here. */
     85           line_number--;
     86           line_error (_("Missing `}' in @def arg"));
     87           line_number++;
     88           *string_pointer = scan_string - 1;
     89           return 0;
     90         }
     91 
     92       if (c == '{' && !started_command)
     93         level++;
     94       if (c == '}' && !started_command)
     95         level--;
     96 
     97       /* remember if at @.  */
     98       started_command = (c == '@' && !started_command);
     99     }
    100 }
    101 
    102 /* Return a list of tokens from the contents of STRING.
    103    Commands and brace-delimited groups count as single tokens.
    104    Contiguous whitespace characters are converted to a token
    105    consisting of a single space. */
    106 static char **
    107 args_from_string (char *string)
    108 {
    109   struct token_accumulator accumulator;
    110   char *token_start, *token_end;
    111   char *scan_string = string;
    112 
    113   initialize_token_accumulator (&accumulator);
    114 
    115   while (*scan_string)
    116     { /* Replace arbitrary whitespace by a single space. */
    117       if (whitespace (*scan_string))
    118         {
    119           scan_string += 1;
    120           while (whitespace (*scan_string))
    121             scan_string += 1;
    122           accumulate_token ((&accumulator), (xstrdup (" ")));
    123           continue;
    124         }
    125 
    126       /* Commands count as single tokens. */
    127       if (*scan_string == COMMAND_PREFIX)
    128         {
    129           token_start = scan_string;
    130           scan_string += 1;
    131           if (self_delimiting (*scan_string))
    132             scan_string += 1;
    133           else
    134             {
    135               int c;
    136               while (1)
    137                 {
    138                   c = *scan_string++;
    139 
    140                   if ((c == 0) || (c == '{') || (whitespace (c)))
    141                     {
    142                       scan_string -= 1;
    143                       break;
    144                     }
    145                 }
    146 
    147               if (*scan_string == '{')
    148                 {
    149                   char *s = scan_string;
    150                   (void) scan_group_in_string (&s);
    151                   scan_string = s;
    152                 }
    153             }
    154           token_end = scan_string;
    155         }
    156 
    157       /* Parentheses and brackets are self-delimiting. */
    158       else if (DEFUN_SELF_DELIMITING (*scan_string))
    159         {
    160           token_start = scan_string;
    161           scan_string += 1;
    162           token_end = scan_string;
    163         }
    164 
    165       /* Open brace introduces a group that is a single token. */
    166       else if (*scan_string == '{')
    167         {
    168           char *s = scan_string;
    169           int balanced = scan_group_in_string (&s);
    170 
    171           token_start = scan_string + 1;
    172           scan_string = s;
    173           token_end = balanced ? (scan_string - 1) : scan_string;
    174         }
    175 
    176       /* Make commas separate tokens so to differentiate them from
    177          parameter types in XML output. */
    178       else if (*scan_string == ',')
    179 	{
    180           token_start = scan_string;
    181           scan_string += 1;
    182           token_end = scan_string;
    183 	}
    184 
    185       /* Otherwise a token is delimited by whitespace, parentheses,
    186          brackets, or braces.  A token is also ended by a command. */
    187       else
    188         {
    189           token_start = scan_string;
    190 
    191           for (;;)
    192             {
    193               int c;
    194 
    195               c = *scan_string++;
    196 
    197               /* Do not back up if we're looking at a }; since the only
    198                  valid }'s are those matched with {'s, we want to give
    199                  an error.  If we back up, we go into an infinite loop.  */
    200               if (!c || whitespace (c) || DEFUN_SELF_DELIMITING (c)
    201                   || c == '{')
    202                 {
    203                   scan_string--;
    204                   break;
    205                 }
    206 
    207 	      /* End token if we are looking at a comma, as commas are
    208 		 delimiters too. */
    209 	      if (c == ',')
    210 		{
    211 		  scan_string--;
    212 		  break;
    213 		}
    214 
    215               /* If we encounter a command embedded within a token,
    216                  then end the token. */
    217               if (c == COMMAND_PREFIX)
    218                 {
    219                   scan_string--;
    220                   break;
    221                 }
    222             }
    223           token_end = scan_string;
    224         }
    225 
    226       accumulate_token (&accumulator, substring (token_start, token_end));
    227     }
    228   accumulate_token (&accumulator, NULL);
    229   return accumulator.tokens;
    230 }
    231 
    232 static void
    233 process_defun_args (char **defun_args, int auto_var_p)
    234 {
    235   int pending_space = 0;
    236 
    237   if (xml)
    238     {
    239       xml_process_defun_args (defun_args, auto_var_p);
    240       return;
    241     }
    242 
    243   for (;;)
    244     {
    245       char *defun_arg = *defun_args++;
    246 
    247       if (defun_arg == NULL)
    248         break;
    249 
    250       if (defun_arg[0] == ' ')
    251         {
    252           pending_space = 1;
    253           continue;
    254         }
    255 
    256       if (pending_space)
    257         {
    258           add_char (' ');
    259           pending_space = 0;
    260         }
    261 
    262       if (DEFUN_SELF_DELIMITING (defun_arg[0]))
    263         {
    264           /* Within @deffn and friends, texinfo.tex makes parentheses
    265              sans serif and brackets bold.  We use roman instead.  */
    266           if (html)
    267             insert_html_tag (START, "");
    268 
    269           add_char (defun_arg[0]);
    270 
    271           if (html)
    272             insert_html_tag (END, "");
    273         }
    274       /* else if (defun_arg[0] == '&' || defun_arg[0] == COMMAND_PREFIX) */
    275         /* execute_string ("%s", defun_arg); */
    276       /* else if (auto_var_p) */
    277         /* execute_string ("%s", defun_arg); */
    278       else
    279         execute_string ("%s", defun_arg);
    280     }
    281 }
    282 
    283 static char *
    284 next_nonwhite_defun_arg (char ***arg_pointer)
    285 {
    286   char **scan = (*arg_pointer);
    287   char *arg = (*scan++);
    288 
    289   if ((arg != 0) && (*arg == ' '))
    290     arg = *scan++;
    291 
    292   if (arg == 0)
    293     scan -= 1;
    294 
    295   *arg_pointer = scan;
    296 
    297   return (arg == 0) ? "" : arg;
    298 }
    299 
    300 
    301 /* This is needed also in insertion.c.  */
    302 
    303 enum insertion_type
    304 get_base_type (int type)
    305 {
    306   int base_type;
    307   switch (type)
    308     {
    309     case defivar:	base_type = defcv; break;
    310     case defmac:	base_type = deffn; break;
    311     case defmethod:	base_type = defop; break;
    312     case defopt:	base_type = defvr; break;
    313     case defspec:	base_type = deffn; break;
    314     case deftypecv:	base_type = deftypecv; break;
    315     case deftypefun:	base_type = deftypefn; break;
    316     case deftypeivar:	base_type = deftypeivar; break;
    317     case deftypemethod:	base_type = deftypemethod; break;
    318     case deftypeop:	base_type = deftypeop; break;
    319     case deftypevar:	base_type = deftypevr; break;
    320     case defun:		base_type = deffn; break;
    321     case defvar:	base_type = defvr; break;
    322     default:
    323       base_type = type;
    324       break;
    325     }
    326 
    327   return base_type;
    328 }
    329 
    330 /* Make the defun type insertion.
    332    TYPE says which insertion this is.
    333    X_P, if nonzero, says not to start a new insertion. */
    334 static void
    335 defun_internal (int type, int x_p)
    336 {
    337   int base_type;
    338   char **defun_args, **scan_args;
    339   const char *category;
    340   char *defined_name;
    341   char *type_name = NULL;
    342   char *type_name2 = NULL;
    343 
    344   {
    345     char *line;
    346 
    347     /* The @def.. line is the only place in Texinfo where you are
    348        allowed to use unquoted braces that don't delimit arguments of
    349        a command or a macro; in any other place it will trigger an
    350        error message from the reader loop.  The special handling of
    351        this case inside `args_from_string' is an extra special hack
    352        which allows this.  The side effect is that if we try to expand
    353        the rest of the line below, the recursive reader loop will
    354        signal an error if there are brace-delimited arguments on that line.
    355 
    356        The best solution to this would be to change the syntax of
    357        @def.. commands so that it doesn't violate Texinfo's own rules.
    358        But it's probably too late for this now, as it will break a lot
    359        of existing manuals.
    360 
    361        Unfortunately, this means that you can't call macros, use @value, etc.
    362        inside @def.. commands, sigh.  */
    363     get_rest_of_line (0, &line);
    364 
    365     /* Basic line continuation.  If a line ends with \s*@\s* concatanate
    366        the next line. */
    367     {
    368       char *next_line, *new_line;
    369       int i;
    370 
    371       line_continuation:
    372         i = strlen (line) - 1;
    373 
    374         if (line[i] == '@' && line[i-1] != '@')
    375           {
    376             get_rest_of_line (0, &next_line);
    377             new_line = (char *) xmalloc (i + strlen (next_line) + 2);
    378             strncpy (new_line, line, i);
    379             new_line[i] = '\0';
    380             free (line);
    381             strcat (new_line, " ");
    382             strcat (new_line, next_line);
    383             line = xstrdup (new_line);
    384             free (next_line);
    385             free (new_line);
    386 
    387             goto line_continuation;
    388           }
    389     }
    390 
    391     defun_args = (args_from_string (line));
    392     free (line);
    393   }
    394 
    395   scan_args = defun_args;
    396 
    397   /* Get base type and category string.  */
    398   base_type = get_base_type (type);
    399 
    400   /* xx all these const strings should be determined upon
    401      documentlanguage argument and NOT via gettext  (kama).  */
    402   switch (type)
    403     {
    404     case defun:
    405     case deftypefun:
    406       category = _("Function");
    407       break;
    408     case defmac:
    409       category = _("Macro");
    410       break;
    411     case defspec:
    412       category = _("Special Form");
    413       break;
    414     case defvar:
    415     case deftypevar:
    416       category = _("Variable");
    417       break;
    418     case defopt:
    419       category = _("User Option");
    420       break;
    421     case defivar:
    422     case deftypeivar:
    423       category = _("Instance Variable");
    424       break;
    425     case defmethod:
    426     case deftypemethod:
    427       category = _("Method");
    428       break;
    429     default:
    430       category = next_nonwhite_defun_arg (&scan_args);
    431       break;
    432     }
    433 
    434   /* The class name.  */
    435   if ((base_type == deftypecv)
    436       || (base_type == deftypefn)
    437       || (base_type == deftypevr)
    438       || (base_type == defcv)
    439       || (base_type == defop)
    440       || (base_type == deftypeivar)
    441       || (base_type == deftypemethod)
    442       || (base_type == deftypeop)
    443      )
    444     type_name = next_nonwhite_defun_arg (&scan_args);
    445 
    446   /* The type name for typed languages.  */
    447   if ((base_type == deftypecv)
    448       || (base_type == deftypeivar)
    449       || (base_type == deftypemethod)
    450       || (base_type == deftypeop)
    451      )
    452     type_name2 = next_nonwhite_defun_arg (&scan_args);
    453 
    454   /* The function or whatever that's actually being defined.  */
    455   defined_name = next_nonwhite_defun_arg (&scan_args);
    456 
    457   /* This hack exists solely for the purposes of formatting the Texinfo
    458      manual.  I couldn't think of a better way.  The token might be a
    459      simple @@ followed immediately by more text.  If this is the case,
    460      then the next defun arg is part of this one, and we should
    461      concatenate them. */
    462   if (*scan_args && **scan_args && !whitespace (**scan_args)
    463        && STREQ (defined_name, "@@"))
    464     {
    465       char *tem = xmalloc (3 + strlen (scan_args[0]));
    466 
    467       sprintf (tem, "@@%s", scan_args[0]);
    468 
    469       free (scan_args[0]);
    470       scan_args[0] = tem;
    471       scan_args++;
    472       defined_name = tem;
    473     }
    474 
    475   /* It's easy to write @defun foo(arg1 arg2), but a following ( is
    476      misparsed by texinfo.tex and this is next to impossible to fix.
    477      Warn about it.  */
    478   if (*scan_args && **scan_args && **scan_args == '(')
    479     warning ("`%c' follows defined name `%s' instead of whitespace",
    480              **scan_args, defined_name);
    481 
    482   if (!x_p)
    483     begin_insertion (type);
    484 
    485   /* Write the definition header line.
    486      This should start at the normal indentation.  */
    487   current_indent -= default_indentation_increment;
    488   start_paragraph ();
    489 
    490   if (!html && !xml)
    491     switch (base_type)
    492       {
    493       case deffn:
    494       case defvr:
    495       case deftp:
    496         execute_string (" --- %s: %s", category, defined_name);
    497         break;
    498       case deftypefn:
    499       case deftypevr:
    500         execute_string (" --- %s: %s %s", category, type_name, defined_name);
    501         break;
    502       case defcv:
    503         execute_string (" --- %s %s %s: %s", category, _("of"), type_name,
    504                         defined_name);
    505         break;
    506       case deftypecv:
    507       case deftypeivar:
    508         execute_string (" --- %s %s %s: %s %s", category, _("of"), type_name,
    509                         type_name2, defined_name);
    510         break;
    511       case defop:
    512         execute_string (" --- %s %s %s: %s", category, _("on"), type_name,
    513                         defined_name);
    514         break;
    515       case deftypeop:
    516         execute_string (" --- %s %s %s: %s %s", category, _("on"), type_name,
    517                         type_name2, defined_name);
    518         break;
    519       case deftypemethod:
    520         execute_string (" --- %s %s %s: %s %s", category, _("on"), type_name,
    521                         type_name2, defined_name);
    522         break;
    523       }
    524   else if (html)
    525     {
    526       /* If this is not a @def...x version, it could only
    527          be a normal version @def.... So start the table here.  */
    528       if (!x_p)
    529         insert_string ("<div class=\"defun\">\n");
    530       else
    531         rollback_empty_tag ("blockquote");
    532 
    533       /* xx The single words (on, off) used here, should depend on
    534          documentlanguage and NOT on gettext  --kama.  */
    535       switch (base_type)
    536         {
    537         case deffn:
    538         case defvr:
    539         case deftp:
    540         case deftypefn:
    541         case deftypevr:
    542           execute_string ("--- %s: ", category);
    543           break;
    544 
    545         case defcv:
    546         case deftypecv:
    547         case deftypeivar:
    548 	  execute_string ("--- %s %s %s: ", category, _("of"), type_name);
    549 	  break;
    550 
    551         case defop:
    552         case deftypemethod:
    553         case deftypeop:
    554 	  execute_string ("--- %s %s %s: ", category, _("on"), type_name);
    555 	  break;
    556 	} /* switch (base_type)... */
    557 
    558       switch (base_type)
    559         {
    560         case deffn:
    561         case defvr:
    562         case deftp:
    563           /* <var> is for the following function arguments.  */
    564           insert_html_tag (START, "b");
    565           execute_string ("%s", defined_name);
    566           insert_html_tag (END, "b");
    567           insert_html_tag (START, "var");
    568           break;
    569         case deftypefn:
    570         case deftypevr:
    571           execute_string ("%s ", type_name);
    572           insert_html_tag (START, "b");
    573           execute_string ("%s", defined_name);
    574           insert_html_tag (END, "b");
    575           insert_html_tag (START, "var");
    576           break;
    577         case defcv:
    578         case defop:
    579           insert_html_tag (START, "b");
    580           execute_string ("%s", defined_name);
    581           insert_html_tag (END, "b");
    582           insert_html_tag (START, "var");
    583           break;
    584         case deftypecv:
    585         case deftypeivar:
    586         case deftypemethod:
    587         case deftypeop:
    588           execute_string ("%s ", type_name2);
    589           insert_html_tag (START, "b");
    590           execute_string ("%s", defined_name);
    591           insert_html_tag (END, "b");
    592           insert_html_tag (START, "var");
    593           break;
    594         }
    595     }
    596   else if (xml)
    597     xml_begin_def_term (base_type, category, defined_name, type_name,
    598 	type_name2);
    599 
    600   current_indent += default_indentation_increment;
    601 
    602   /* Now process the function arguments, if any.  If these carry onto
    603      the next line, they should be indented by two increments to
    604      distinguish them from the body of the definition, which is indented
    605      by one increment.  */
    606   current_indent += default_indentation_increment;
    607 
    608   switch (base_type)
    609     {
    610     case deffn:
    611     case defop:
    612       process_defun_args (scan_args, 1);
    613       break;
    614 
    615       /* Through Makeinfo 1.67 we processed remaining args only for deftp,
    616          deftypefn, and deftypemethod.  But the libc manual, for example,
    617          needs to say:
    618             @deftypevar {char *} tzname[2]
    619          And simply allowing the extra text seems far simpler than trying
    620          to invent yet more defn commands.  In any case, we should either
    621          output it or give an error, not silently ignore it.  */
    622     default:
    623       process_defun_args (scan_args, 0);
    624       break;
    625     }
    626 
    627   current_indent -= default_indentation_increment;
    628   if (!html)
    629     close_single_paragraph ();
    630 
    631   /* Make an entry in the appropriate index.  (XML and
    632      Docbook already got their entries, so skip them.)  */
    633   if (!xml)
    634     switch (base_type)
    635       {
    636       case deffn:
    637       case deftypefn:
    638 	execute_string ("@findex %s\n", defined_name);
    639 	break;
    640       case defcv:
    641       case deftypecv:
    642       case deftypevr:
    643       case defvr:
    644 	execute_string ("@vindex %s\n", defined_name);
    645 	break;
    646       case deftypeivar:
    647 	execute_string ("@vindex %s %s %s\n", defined_name, _("of"),
    648                         type_name);
    649 	break;
    650       case defop:
    651       case deftypeop:
    652       case deftypemethod:
    653 	execute_string ("@findex %s %s %s\n", defined_name, _("on"),
    654                         type_name);
    655 	break;
    656       case deftp:
    657 	execute_string ("@tindex %s\n", defined_name);
    658 	break;
    659       }
    660 
    661   if (xml)
    662     xml_end_def_term ();
    663   else if (html)
    664     {
    665       inhibit_paragraph_indentation = 1;
    666       no_indent = 1;
    667       insert_html_tag (END, "var");
    668       insert_string ("<br>\n");
    669       /* Indent the definition a bit.  */
    670       add_html_block_elt ("<blockquote>");
    671       no_indent = 0;
    672       inhibit_paragraph_indentation = 0;
    673       paragraph_is_open = 0;
    674     }
    675 
    676   /* Deallocate the token list. */
    677   scan_args = defun_args;
    678   while (1)
    679     {
    680       char * arg = (*scan_args++);
    681       if (arg == NULL)
    682         break;
    683       free (arg);
    684     }
    685   free (defun_args);
    686 }
    687 
    688 /* Add an entry for a function, macro, special form, variable, or option.
    689    If the name of the calling command ends in `x', then this is an extra
    690    entry included in the body of an insertion of the same type. */
    691 void
    692 cm_defun (int arg, int arg2, int arg3)
    693 {
    694   int type;
    695   char *base_command = xstrdup (command);  /* command with any `x' removed */
    696   int x_p = (command[strlen (command) - 1] == 'x');
    697 
    698   if (x_p)
    699     base_command[strlen (base_command) - 1] = 0;
    700 
    701   type = find_type_from_name (base_command);
    702 
    703   /* If we are adding to an already existing insertion, then make sure
    704      that we are already in an insertion of type TYPE. */
    705   if (x_p)
    706     {
    707       INSERTION_ELT *i = insertion_stack;
    708       /* Skip over ifclear and ifset conditionals.  */
    709       while (i && (i->insertion == ifset || i->insertion == ifclear))
    710         i = i->next;
    711 
    712       if (!i || i->insertion != type)
    713         {
    714           line_error (_("Must be in `@%s' environment to use `@%s'"),
    715                       base_command, command);
    716           discard_until ("\n");
    717           return;
    718         }
    719     }
    720 
    721   defun_internal (type, x_p);
    722   free (base_command);
    723 }
    724