home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-11-01 | 39.4 KB | 1,817 lines |
- /* Makeinfo -- convert texinfo format files into info files
-
- Copyright (C) 1987 Free Software Foundation, Inc.
-
- This file is part of GNU Info.
-
- Makeinfo is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU Emacs General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- Makeinfo, but only under the conditions described in the GNU Emacs
- General Public License. A copy of this license is supposed to
- have been given to you along with GNU Emacs so you can know your
- rights and responsibilities. It should be in a file named COPYING.
- Among other things, the copyright notice and this notice must be
- preserved on all copies. */
-
- /* MS-DOS port (c) 1990 by Thorsten Ohl, td12@ddagsi3.bitnet
- This port is also distributed under the terms of the
- GNU General Public License as published by the
- Free Software Foundation.
-
- Please note that this file is not identical to the
- original GNU release, you should have received this
- code as patch to the official release.
-
- $Header: e:/gnu/info/RCS/makeinfo.e 0.1.1.1 90/10/05 11:25:42 tho Exp $
- */
-
- /* cont'd from makeinfo.c */
-
- /*===(cut here)===*/
-
- /* **************************************************************** */
- /* */
- /* Cross Reference Hacking */
- /* */
- /* **************************************************************** */
-
- char *
- get_xref_token ()
- {
- char *string;
-
- get_until_in_braces (",", &string);
- if (curchar () == ',')
- input_text_offset++;
- fix_whitespace (string);
- normalize_node_name (string);
- return (string);
- }
-
- int px_ref_flag = 0; /* Controls initial output string. */
-
- /* Make a cross reference. */
- VOID
- cm_xref (arg)
- int arg;
- {
-
- if (arg == START)
- {
-
- char *arg1, *arg2, *arg3, *arg4, *arg5;
-
- arg1 = get_xref_token ();
- arg2 = get_xref_token ();
- arg3 = get_xref_token ();
- arg4 = get_xref_token ();
- arg5 = get_xref_token ();
-
- add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
-
- if (*arg5 || *arg4)
- {
- add_word_args ("%s: (%s)%s", arg2, arg4, arg1);
- return;
- }
- else
- remember_node_reference (arg1, line_number, followed_reference);
-
- if (*arg3)
- {
- if (!*arg2)
- {
- add_word_args ("%s: %s", arg3, arg1);
- }
- else
- {
- add_word_args ("%s: %s", arg2, arg1);
- }
- return;
- }
-
- if (*arg2)
- {
- execute_string ("%s", arg2);
- add_word_args (": %s", arg1);
- }
- else
- {
- add_word_args ("%s::", arg1);
- }
-
- }
- else
- {
-
- /* Check to make sure that the next non-whitespace character is either
- a period or a comma. input_text_offset is pointing at the "}" which
- ended the xref or pxref command. */
-
- LONG temp = input_text_offset + 1;
-
- if (output_paragraph[output_paragraph_offset - 2] == ':' &&
- output_paragraph[output_paragraph_offset - 1] == ':')
- return;
- while (temp < size_of_input_text)
- {
- if (cr_or_whitespace (input_text[temp]))
- temp++;
- else
- {
- if (input_text[temp] == '.' ||
- input_text[temp] == ',' ||
- input_text[temp] == '\t')
- return;
- else
- {
- line_error ("Cross-reference must be terminated with a period or a comma");
- return;
- }
- }
- }
- }
- }
-
- VOID
- cm_pxref (arg)
- int arg;
- {
- if (arg == START)
- {
- px_ref_flag++;
- cm_xref (arg);
- px_ref_flag--;
- }
- else
- add_char ('.');
- }
-
- VOID
- cm_inforef (arg)
- int arg;
- {
- if (arg == START)
- {
- char *node, *pname, *file;
-
- node = get_xref_token ();
- pname = get_xref_token ();
- file = get_xref_token ();
-
- add_word_args ("*note %s: (%s)%s", pname, file, node);
- }
- }
-
- /* **************************************************************** */
- /* */
- /* Insertion Command Stubs */
- /* */
- /* **************************************************************** */
-
- VOID
- cm_quotation ()
- {
- begin_insertion (quotation);
- }
-
- VOID
- cm_example ()
- {
- begin_insertion (example);
- }
-
- VOID
- cm_smallexample ()
- {
- begin_insertion (smallexample);
- }
-
- VOID
- cm_lisp ()
- {
- begin_insertion (lisp);
- }
-
- VOID
- cm_format ()
- {
- begin_insertion (format);
- }
-
- VOID
- cm_display ()
- {
- begin_insertion (display);
- }
-
- VOID
- cm_itemize ()
- {
- begin_insertion (itemize);
- }
-
- VOID
- cm_enumerate ()
- {
- begin_insertion (enumerate);
- }
-
- VOID
- cm_table ()
- {
- begin_insertion (table);
- }
-
- VOID
- cm_group ()
- {
- begin_insertion (group);
- }
-
- VOID
- cm_ifinfo ()
- {
- begin_insertion (ifinfo);
- }
-
- VOID
- cm_tex ()
- {
- discard_until ("\n@end tex");
- discard_until ("\n");
- }
-
- VOID
- cm_iftex ()
- {
- discard_until ("\n@end iftex");
- discard_until ("\n");
- }
-
- VOID
- cm_titlespec ()
- {
- discard_until ("\n@end titlespec");
- discard_until ("\n");
- }
-
- VOID
- cm_titlepage ()
- {
- discard_until ("\n@end titlepage");
- discard_until ("\n");
- }
-
- VOID
- cm_ignore ()
- {
- discard_until ("\n@end ignore");
- discard_until ("\n");
- }
-
- /* **************************************************************** */
- /* */
- /* @itemx, @item */
- /* */
- /* **************************************************************** */
-
- /* Non-zero means a string is in execution, as opposed to a file. */
- int executing_string = 0;
-
- /* Execute the string produced by formatting the ARGs with FORMAT. This
- is like submitting a new file with @include. */
- #ifdef MSDOS
-
- VOID CDECL
- execute_string (char *format, ...)
- {
- static char temp_string[4000];
- va_list arg_ptr;
- va_start (arg_ptr, format);
-
- vsprintf (temp_string, format, arg_ptr);
- strcat (temp_string, "@bye\n");
- pushfile ();
- input_text_offset = 0;
- input_text = temp_string;
- input_filename = savestring (input_filename);
- size_of_input_text = strlen (temp_string);
-
- executing_string++;
- reader_loop ();
-
- popfile ();
- executing_string--;
-
- free_and_clear (&command);
- command = savestring ("not bye");
- }
-
- #else /* not MSDOS */
-
- VOID
- execute_string (format, arg1, arg2, arg3, arg4, arg5)
- char *format;
- {
- static char temp_string[4000];
- sprintf (temp_string, format, arg1, arg2, arg3, arg4, arg5);
- strcat (temp_string, "@bye\n");
- pushfile ();
- input_text_offset = 0;
- input_text = temp_string;
- input_filename = savestring (input_filename);
- size_of_input_text = strlen (temp_string);
-
- executing_string++;
- reader_loop ();
-
- popfile ();
- executing_string--;
-
- free_and_clear (&command);
- command = savestring ("not bye");
- }
-
- #endif /* not MSDOS */
-
- int itemx_flag = 0;
-
- VOID
- cm_itemx ()
- {
- itemx_flag++;
- cm_item ();
- itemx_flag--;
- }
-
-
- VOID
- cm_item ()
- {
- char *rest_of_line, *item_func;
-
- /* Can only hack "@item" while inside of an insertion. */
- if (insertion_level)
- {
- get_until ("\n", &rest_of_line);
- canon_white (rest_of_line);
- item_func = current_item_function ();
-
- /* Okay, do the right thing depending on which insertion function
- is active. */
-
- switch (current_insertion_type ())
- {
- case menu:
- case quotation:
- case example:
- case smallexample:
- case lisp:
- case format:
- case display:
- case group:
- case ifinfo:
- line_error ("The `@%s' command is meaningless within a `@%s' block",
- command,
- insertion_type_pname (current_insertion_type ()));
- break;
-
- case itemize:
- case enumerate:
- if (itemx_flag)
- {
- line_error ("@itemx is not meaningful inside of a `%s' block",
- insertion_type_pname (current_insertion_type ()));
- }
- else
- {
- start_paragraph ();
- kill_self_indent (-1);
- discard_until ("\n");
- filling_enabled = indented_fill = true;
-
- if (current_insertion_type () == itemize)
- {
- indent (output_column = current_indent - 2);
-
- /* I need some way to determine whether this command
- takes braces or not. I believe the user can type
- either "@bullet" or "@bullet{}". Of course, they
- can also type "o" or "#" or whatever else they want. */
- if (item_func && *item_func)
- {
- if (*item_func == '@')
- if (item_func[strlen (item_func) - 1] != '}')
- execute_string ("%s{}", item_func);
- else
- execute_string ("%s", item_func);
- else
- execute_string ("%s", item_func);
- }
- insert (' ');
- output_column++;
- }
- else
- number_item ();
-
- /* Special hack. This makes close paragraph ignore you until
- the start_paragraph () function has been called. */
- must_start_paragraph = 1;
- }
- break;
-
- case table:
- {
- /* Get rid of extra characters. */
- kill_self_indent (-1);
-
- /* close_paragraph () almost does what we want. The problem
- is when paragraph_is_open, and last_char_was_newline, and
- the last newline has been turned into a space, because
- filling_enabled. I handle it here. */
- if (last_char_was_newline && filling_enabled && paragraph_is_open)
- insert ('\n');
- close_paragraph ();
-
- /* Indent on a new line, but back up one indentation level. */
- /* force existing indentation. */
- add_char ('i');
- output_paragraph_offset--;
- kill_self_indent (default_indentation_increment + 1);
-
- /* Add item's argument to the line. */
- filling_enabled = false;
- if (!item_func && !(*item_func))
- execute_string ("%s", rest_of_line);
- else
- execute_string ("%s{%s}", item_func, rest_of_line);
-
- /* Start a new line, and let start_paragraph ()
- do the indenting of it for you. */
- close_single_paragraph ();
- indented_fill = filling_enabled = true;
- }
- }
- free (rest_of_line);
- }
- else
- line_error ("@%s found outside of an insertion block", command);
- }
-
-
- /* **************************************************************** */
- /* */
- /* Defun and Friends */
- /* */
- /* **************************************************************** */
-
- /* The list of args that were passed to the def**** command. */
- char **defun_args = (char **)NULL;
-
- /* An alist mapping defun insertion types to the text that we use
- to describe them. */
- struct {
- enum insertion_type type;
- char *title;
- } type_title_alist[] = {
- { defun, "Function" },
- { defmac, "Macro" },
- { defspec, "Special form" },
- { defopt, "Option" },
- { deffn, (char *)NULL },
- { defvar, "Variable" },
- { (enum insertion_type)0, (char *)NULL }
- };
-
- /* Return the title string for this type of defun. */
- char *
- defun_title (type)
- enum insertion_type type;
- {
- register int i;
-
- for (i = 0; type_title_alist[i].type || type_title_alist[i].title; i++)
- if (type_title_alist[i].type == type)
- return (type_title_alist[i].title);
- return (char *)NULL;
- }
-
- /* Return a list of words from the contents of STRING.
- You can group words with braces. */
- char **
- args_from_string (string)
- char *string;
- {
- char **result = (char **) NULL;
- register int i, start, result_index, size;
- int len, skip_til_brace = 0;
-
- i = result_index = size = 0;
-
- /* Get a token, and stuff it into RESULT. The tokens are split
- at spaces or tabs. */
- while (string[i])
- {
- /* Skip leading whitespace. */
- for (; string[i] && whitespace (string[i]); i++);
-
- start = i;
-
- if (!string[i])
- return (result);
-
- /* If this is a command which takes it's argument in braces, then
- gobble the whole thing. */
- if (string[i] == COMMAND_PREFIX)
- {
- register int j;
- for (j = i; string[j] &&
- !whitespace (string[j]) &&
- string[j] != '{'; j++);
-
- if (string[j] == '{')
- {
- while (string[j] && string[j] != '}')
- j++;
-
- if (string[j])
- j++;
-
- i = j;
- goto add_arg;
- }
- }
-
- if (string[i] == '{' && !whitespace (string[i + 1]))
- {
- skip_til_brace = 1;
- start = ++i;
- }
-
- /* Skip until whitespace or close brace. */
- while (string[i] &&
- ((skip_til_brace && string[i] != '}') ||
- (!skip_til_brace && !whitespace (string[i]))))
- i++;
-
- add_arg:
- len = i - start;
- if (result_index + 2 >= size)
- {
- if (!size)
- result = (char **) xmalloc ((size = 10) * (sizeof (char *)));
- else
- result =
- (char **) xrealloc (result, ((size += 10) * (sizeof (char *))));
- }
- result[result_index] = (char *) xmalloc (1 + len);
- strncpy (result[result_index], string + start, len);
- result[result_index][len] = '\0';
- result_index++;
- result[result_index] = (char *) NULL;
-
- if (skip_til_brace)
- {
- skip_til_brace = 0;
- if (string[i])
- i++;
- }
- }
-
- return (result);
- }
-
- VOID
- get_defun_args ()
- {
- register int i;
- char *line;
-
- get_rest_of_line (&line);
-
- if (defun_args)
- {
- for (i = 0; defun_args[i]; i++)
- free (defun_args[i]);
- free (defun_args);
- }
-
- defun_args = args_from_string (line);
- free (line);
- }
-
- VOID
- insert_defun_arg (string, where)
- char *string;
- int where;
- {
- register int i;
-
- for (i = 0; defun_args[i]; i++);
- defun_args = (char **)xrealloc (defun_args, (i + 2) * sizeof (char *));
- defun_args[i + 1] = (char *)NULL;
-
- for (; i != where; --i)
- defun_args[i] = defun_args[i - 1];
-
- defun_args[i] = savestring (string);
- }
-
- /* Make the defun type insertion.
- TYPE says which insertion this is.
- TITLE is the string to describe the object being described, or NULL
- for no title string.
- X_P says not to start a new insertion if non-zero. */
- VOID
- defun_internal (type, title, x_p)
- enum insertion_type type;
- char *title;
- int x_p;
- {
- register int i = 0;
- char *type_name, *func_name;
- int old_no_indent = no_indent;
-
- get_defun_args ();
-
- if (title)
- insert_defun_arg (title, 0);
-
- if (defun_args[0])
- {
- type_name = defun_args[0];
- i++;
-
- if (defun_args[1])
- {
- func_name = defun_args[1];
- i++;
- }
- else
- func_name = "";
- }
- else
- type_name = "";
-
- no_indent = true;
- start_paragraph ();
- execute_string (" * %s: %s", type_name, func_name);
- no_indent = old_no_indent;
-
- for (; defun_args[i]; i++)
- {
- if (*defun_args[i] == '&')
- add_word_args (" %s", defun_args[i]);
- else
- execute_string (" @var{%s}", defun_args[i]);
- }
- add_char ('\n');
- if (type == defvar || type == defopt)
- execute_string ("@vindex %s\n", func_name);
- else
- execute_string ("@findex %s\n", func_name);
-
- if (!x_p)
- begin_insertion (type);
- }
-
- /* Add an entry for a function, macro, special form, variable, or option.
- If the name of the calling command ends in `x', then this is an extra
- entry included in the body of an insertion of the same type. */
- VOID
- cm_defun ()
- {
- int x_p;
- enum insertion_type type;
- char *title, *temp = savestring (command);
-
- x_p = (command[strlen (command) - 1] == 'x');
-
- if (x_p)
- temp[strlen (temp) - 1] = '\0';
-
- type = find_type_from_name (temp);
- free (temp);
-
- /* If we are adding to an already existing insertion, then make sure
- that we are already in an insertion of type TYPE. */
- if (x_p &&
- (!insertion_level || insertion_stack->insertion != type))
- {
- line_error ("Must be in a `%s' insertion in order to use `%s'x",
- command, command);
- return;
- }
-
- title = defun_title (type);
- defun_internal (type, title, x_p);
- }
-
- /* End existing insertion block. */
- VOID
- cm_end ()
- {
- char *temp;
- enum insertion_type type;
-
- if (!insertion_level)
- {
- line_error ("Unmatched `@%s'", command);
- return;
- }
- get_rest_of_line (&temp);
- canon_white (temp);
-
- if (strlen (temp) == 0)
- line_error ("`@%s' needs something after it", command);
- type = find_type_from_name (temp);
- if (type == bad_type)
- {
- line_error ("Bad argument to `%s', `%s', using `%s'",
- command, temp, insertion_type_pname (current_insertion_type ()));
- }
- end_insertion (type);
- free (temp);
- }
-
-
- /* **************************************************************** */
- /* */
- /* Other Random Commands */
- /* */
- /* **************************************************************** */
-
- /* noindent () used to do something valueable, but it didn't follow the
- spec for noindent in the texinfo manual. Now it does nothing, which,
- in the case of makeinfo, is correct. */
- VOID
- cm_noindent ()
- {
- /* no_indent = true;
- indented_fill = false; */
- }
-
- /* I don't know exactly what to do with this. Should I allow
- someone to switch filenames in the middle of output? Since the
- file could be partially written, this doesn't seem to make sense.
- Another option: ignore it, since they don't *really* want to
- switch files. Finally, complain, or at least warn. */
- VOID
- cm_setfilename ()
- {
- char *filename;
- get_rest_of_line (&filename);
- /* warning ("`@%s %s' encountered and ignored", command, filename); */
- free (filename);
- }
-
- VOID
- cm_comment ()
- {
- discard_until ("\n");
- }
-
- VOID
- cm_br ()
- {
- close_paragraph ();
- }
-
- /* Insert the number of blank lines passed as argument. */
- VOID
- cm_sp ()
- {
- int lines;
- char *line;
-
- close_paragraph ();
- get_rest_of_line (&line);
-
- sscanf (line, "%d", &lines);
- while (lines--)
- add_char ('\n');
- free (line);
- }
-
- VOID
- cm_settitle ()
- {
- discard_until ("\n");
- }
-
- VOID
- cm_need ()
- {
- }
-
- /* Start a new line with just this text on it.
- Then center the line of text.
- This always ends the current paragraph. */
- VOID
- cm_center ()
- {
- char *line;
-
- close_paragraph ();
- filling_enabled = indented_fill = false;
-
- get_rest_of_line (&line);
-
- if (strlen (line) < fill_column)
- {
- int i = (fill_column - strlen (line)) / 2;
- while (i--)
- insert (' ');
- }
- add_word_args ("%s", line);
- free (line);
- insert ('\n');
- close_paragraph ();
- filling_enabled = true;
- }
-
- /* Show what an expression returns. */
- VOID
- cm_result (arg)
- int arg;
- {
- if (arg == END)
- add_word ("=>");
- }
-
- /* What an expression expands to. */
- VOID
- cm_expansion (arg)
- int arg;
- {
- if (arg == END)
- add_word ("==>");
- }
-
- /* Indicates two expressions are equivalent. */
- VOID
- cm_equiv (arg)
- int arg;
- {
- if (arg == END)
- add_word ("==");
- }
-
- /* What an expression may print. */
- VOID
- cm_print (arg)
- int arg;
- {
- if (arg == END)
- add_word ("-|");
- }
-
- /* An error signaled. */
- VOID
- cm_error (arg)
- int arg;
- {
- if (arg == END)
- add_word ("error-->");
- }
-
- /* The location of point in an example of a buffer. */
- VOID
- cm_point (arg)
- int arg;
- {
- if (arg == END)
- add_word ("-!-");
- }
-
- /* Start a new line with just this text on it.
- The text is outdented one level if possible. */
- VOID
- cm_exdent ()
- {
- char *line;
- int i = current_indent;
-
- if (current_indent)
- current_indent -= default_indentation_increment;
-
- get_rest_of_line (&line);
- close_single_paragraph ();
- add_word_args ("%s", line);
- current_indent = i;
- free (line);
- close_single_paragraph ();
- }
-
- VOID
- cm_include ()
- {
- cm_infoinclude ();
- }
-
- /* Remember this file, and move onto the next. */
- VOID
- cm_infoinclude ()
- {
- char *filename;
-
- close_paragraph ();
- get_rest_of_line (&filename);
- pushfile ();
-
- /* In verbose mode we print info about including another file. */
- if (verbose_mode)
- {
- register int i = 0;
- register FSTACK *stack = filestack;
-
- for (i = 0, stack = filestack; stack; stack = stack->next, i++);
-
- i *= 2;
-
- printf ("%*s", i, "");
- printf ("%c%s %s\n", COMMAND_PREFIX, command, filename);
- fflush (stdout);
- }
-
- if (!find_and_load (filename))
- {
- #ifndef MSDOS
- extern char *sys_errlist[];
- extern int errno, sys_nerr;
- #endif /* not MSDOS */
-
- popfile ();
-
- /* Cannot "@include foo", in line 5 of "/wh/bar". */
- line_error ("`%c%s %s': %s", COMMAND_PREFIX, command, filename,
- ((errno < sys_nerr) ?
- sys_errlist[errno] : "Unknown file system error"));
- }
- free (filename);
- }
-
- /* The other side of a malformed expression. */
- VOID
- misplaced_brace ()
- {
- line_error ("Misplaced `}'");
- }
-
- /* Don't let the filling algorithm insert extra whitespace here. */
- VOID
- cm_force_abbreviated_whitespace ()
- {
- }
-
- /* Make the output paragraph end the sentence here, even though it
- looks like it shouldn't. This also inserts the character which
- invoked it. */
- VOID
- cm_force_sentence_end ()
- {
- add_char (META ((*command)));
- }
-
- /* Signals end of processing. Easy to make this happen. */
- VOID
- cm_bye ()
- {
- input_text_offset = size_of_input_text;
- }
-
- VOID
- cm_asis ()
- {
- }
-
- VOID
- cm_setchapternewpage ()
- {
- discard_until ("\n");
- }
-
-
- /* **************************************************************** */
- /* */
- /* Indexing Stuff */
- /* */
- /* **************************************************************** */
-
-
- /* An index element... */
- typedef struct index_elt
- {
- struct index_elt *next;
- char *entry; /* The index entry itself. */
- char *node; /* The node from whence it came. */
- } INDEX_ELT;
-
- /* A list of short-names for each index, and the index to that index in our
- index array, the_indices. (Sorry, I couldn't resist.) */
- typedef struct
- {
- char *name;
- int index;
- } INDEX_ALIST;
-
- INDEX_ALIST **name_index_alist = (INDEX_ALIST **) NULL;
-
- #ifdef MSDOS
- INDEX_ALIST *find_index (char *name);
- #endif /* MSDOS */
-
- /* An array of pointers. Each one is for a different index. The
- "synindex" command changes which array slot is pointed to by a
- given "index". */
- INDEX_ELT **the_indices = (INDEX_ELT **) NULL;
-
- /* The number of defined indices. */
- int defined_indices = 0;
-
- /* We predefine these. */
- #define program_index 0
- #define function_index 1
- #define concept_index 2
- #define variable_index 3
- #define datatype_index 4
- #define key_index 5
-
- VOID
- init_indices ()
- {
- int i;
-
- /* Create the default data structures. */
-
- /* Initialize data space. */
- if (!the_indices)
- {
- the_indices = (INDEX_ELT **) xmalloc ((1 + defined_indices) *
- sizeof (INDEX_ELT *));
- the_indices[defined_indices] = (INDEX_ELT *) NULL;
-
- name_index_alist = (INDEX_ALIST **) xmalloc ((1 + defined_indices) *
- sizeof (INDEX_ALIST *));
- name_index_alist[defined_indices] = (INDEX_ALIST *) NULL;
- }
-
- /* If there were existing indices, get rid of them now. */
- for (i = 0; i < defined_indices; i++)
- undefindex (name_index_alist[i]->name);
-
- /* Add the default indices. */
- defindex ("pg");
- defindex ("fn");
- defindex ("cp");
- defindex ("vr");
- defindex ("tp");
- defindex ("ky");
- }
-
- /* Find which element in the known list of indices has this name.
- Returns -1 if NAME isn't found. */
- find_index_offset (name)
- char *name;
- {
- register int i;
- for (i = 0; i < defined_indices; i++)
- if (name_index_alist[i] &&
- stricmp (name, name_index_alist[i]->name) == 0)
- return (name_index_alist[i]->index);
- return (-1);
- }
-
- /* Return a pointer to the entry of (name . index) for this name.
- Return -1 if the index doesn't exist. */
- INDEX_ALIST *
- find_index (name)
- char *name;
- {
- int offset = find_index_offset (name);
- if (offset > -1)
- return (name_index_alist[offset]);
- else
- return ((INDEX_ALIST *) - 1);
- }
-
- /* Given an index name, return the offset in the_indices of this index,
- or -1 if there is no such index. */
- translate_index (name)
- char *name;
- {
- INDEX_ALIST *which = find_index (name);
-
- if ((LONG) which > -1)
- return (which->index);
- else
- return (-1);
- }
-
- /* Return the index list which belongs to NAME. */
- INDEX_ELT *
- index_list (name)
- char *name;
- {
- int which = translate_index (name);
- if (which < 0)
- return ((INDEX_ELT *) - 1);
- else
- return (the_indices[which]);
- }
-
- /* Please release me, let me go... */
- VOID
- free_index (index)
- INDEX_ELT *index;
- {
- INDEX_ELT *temp;
-
- while ((temp = index) != (INDEX_ELT *) NULL)
- {
- free (temp->entry);
- free (temp->node);
- index = index->next;
- free (temp);
- }
- }
-
- /* Flush an index by name. */
- undefindex (name)
- char *name;
- {
- int i;
- int which = find_index_offset (name);
-
- if (which < 0)
- return (which);
-
- i = name_index_alist[which]->index;
-
-
- free_index (the_indices[i]);
- the_indices[i] = (INDEX_ELT *) NULL;
-
- free (name_index_alist[which]->name);
- free (name_index_alist[which]);
- name_index_alist[which] = (INDEX_ALIST *) NULL;
- }
-
- /* Define an index known as NAME. We assign the slot number. */
- VOID
- defindex (name)
- char *name;
- {
- register int i, slot;
-
- /* If it already exists, flush it. */
- undefindex (name);
-
- /* Try to find an empty slot. */
- slot = -1;
- for (i = 0; i < defined_indices; i++)
- if (!name_index_alist[i])
- {
- slot = i;
- break;
- }
-
- if (slot < 0)
- {
- /* No such luck. Make space for another index. */
- slot = defined_indices;
- defined_indices++;
-
- name_index_alist = (INDEX_ALIST **) xrealloc (name_index_alist,
- (1 + defined_indices)
- * sizeof (INDEX_ALIST *));
- the_indices = (INDEX_ELT **) xrealloc (the_indices,
- (1 + defined_indices)
- * sizeof (INDEX_ELT *));
- }
-
- /* We have a slot. Start assigning. */
- name_index_alist[slot] = (INDEX_ALIST *) xmalloc (sizeof (INDEX_ALIST));
- name_index_alist[slot]->name = savestring (name);
- name_index_alist[slot]->index = slot;
-
- the_indices[slot] = (INDEX_ELT *) NULL;
- }
-
- /* Add the arguments to the current index command to the index NAME. */
- VOID
- index_add_arg (name)
- char *name;
- {
- int which = translate_index (name);
- char *index_entry;
-
- /* close_paragraph (); */
- get_rest_of_line (&index_entry);
-
- if (which < 0)
- {
- line_error ("Unknown index reference `%s'", name);
- free (index_entry);
- }
- else
- {
- INDEX_ELT *new = (INDEX_ELT *) xmalloc (sizeof (INDEX_ELT));
- new->next = the_indices[which];
- new->entry = index_entry;
- new->node = current_node;
- the_indices[which] = new;
- }
- }
-
- #define INDEX_COMMAND_SUFFIX "index"
-
- /* The function which user defined index commands call. */
- VOID
- gen_index ()
- {
- char *name = savestring (command);
- if (strlen (name) >= strlen ("index"))
- name[strlen (name) - strlen ("index")] = '\0';
- index_add_arg (name);
- free (name);
- }
-
- /* Define a new index command. Arg is name of index. */
- VOID
- cm_defindex ()
- {
- char *name;
- get_rest_of_line (&name);
-
- if ((LONG) find_index (name) > -1)
- {
- line_error ("Index `%s' already exists", name);
- free (name);
- return;
- }
- else
- {
- char *temp = (char *) alloca (1 + strlen (name) + strlen ("index"));
- sprintf (temp, "%sindex", name);
- define_user_command (temp, gen_index, 0);
- defindex (name);
- free (name);
- }
- }
-
- /* Append LIST2 to LIST1. Return the head of the list. */
- INDEX_ELT *
- index_append (head, tail)
- INDEX_ELT *head, *tail;
- {
- register INDEX_ELT *t_head = head;
-
- if (!t_head)
- return (tail);
-
- while (t_head->next)
- t_head = t_head->next;
- t_head->next = tail;
- return (head);
- }
-
- /* Expects 2 args, on the same line. Both are index abbreviations.
- Make the first one be a synonym for the second one, i.e. make the
- first one have the same index as the second one. */
- VOID
- cm_synindex ()
- {
- int redirector, redirectee;
- char *temp;
-
- skip_whitespace ();
- get_until_in_line (" ", &temp);
- redirectee = find_index_offset (temp);
- skip_whitespace ();
- free_and_clear (&temp);
- get_until_in_line (" ", &temp);
- redirector = find_index_offset (temp);
- free (temp);
- if (redirector < 0 || redirectee < 0)
- {
- line_error ("Unknown index reference");
- }
- else
- {
- /* I think that we should let the user make indices synonymous to
- each other without any lossage of info. This means that one can
- say @synindex cp dt anywhere in the file, and things that used to
- be in cp will go into dt. */
- INDEX_ELT *i1 = the_indices[redirectee], *i2 = the_indices[redirector];
-
- if (i1 || i2)
- {
- if (i1)
- the_indices[redirectee] = index_append (i1, i2);
- else
- the_indices[redirectee] = index_append (i2, i1);
- }
-
- name_index_alist[redirectee]->index =
- name_index_alist[redirector]->index;
- }
- }
-
- VOID
- cm_pindex () /* Pinhead index. */
- {
- index_add_arg ("pg");
- }
-
- VOID
- cm_vindex () /* variable index */
- {
- index_add_arg ("vr");
- }
-
- VOID
- cm_kindex () /* key index */
- {
- index_add_arg ("ky");
- }
-
- VOID
- cm_cindex () /* concept index */
- {
- index_add_arg ("cp");
- }
-
- VOID
- cm_findex () /* function index */
- {
- index_add_arg ("fn");
- }
-
- VOID
- cm_tindex () /* data type index */
- {
- index_add_arg ("tp");
- }
-
- /* Sorting the index. */
- int CDECL
- index_element_compare (element1, element2)
- INDEX_ELT **element1, **element2;
- {
- return (strcmp ((*element1)->entry, (*element2)->entry));
- }
-
- /* Sort the index passed in INDEX, returning an array of
- pointers to elements. The array is terminated with a NULL
- pointer. We call qsort because it's supposed to be fast.
- I think this looks bad. */
- INDEX_ELT **
- sort_index (index)
- INDEX_ELT *index;
- {
- INDEX_ELT *temp = index;
- INDEX_ELT **array;
- int count = 0;
-
- while (temp != (INDEX_ELT *) NULL)
- {
- count++;
- temp = temp->next;
- }
-
- /* We have the length. Make an array. */
-
- array = (INDEX_ELT **) xmalloc ((count + 1) * sizeof (INDEX_ELT *));
- count = 0;
- temp = index;
-
- while (temp != (INDEX_ELT *) NULL)
- {
- array[count++] = temp;
- temp = temp->next;
- }
- array[count] = (INDEX_ELT *) NULL; /* terminate the array. */
-
- /* Sort the array. */
- qsort (array, count, sizeof (INDEX_ELT *), index_element_compare);
-
- return (array);
- }
-
- /* Takes one arg, a short name of an index to print.
- Outputs a menu of the sorted elements of the index. */
- VOID
- cm_printindex ()
- {
- int item;
- INDEX_ELT *index;
- INDEX_ELT **array;
- char *index_name;
- int old_inhibitions = inhibit_paragraph_indentation;
- boolean previous_filling_enabled_value = filling_enabled;
-
- close_paragraph ();
- get_rest_of_line (&index_name);
-
- index = index_list (index_name);
- if ((LONG) index < 0)
- {
- line_error ("Unknown index name `%s'", index_name);
- free (index_name);
- return;
- }
- else
- free (index_name);
-
- array = sort_index (index);
-
- filling_enabled = false;
- inhibit_paragraph_indentation = 1;
- close_paragraph ();
- add_word ("* Menu:\n\n");
-
- for (item = 0; (index = array[item]); item++)
- {
- execute_string ("* %s: %s.\n", index->entry, index->node);
- flush_output ();
- }
- free (array);
- close_paragraph ();
- filling_enabled = previous_filling_enabled_value;
- inhibit_paragraph_indentation = old_inhibitions;
- }
-
-
- /* **************************************************************** */
- /* */
- /* Making User Defined Commands */
- /* */
- /* **************************************************************** */
-
- VOID
- define_user_command (name, proc, needs_braces_p)
- char *name;
- FUNCTION *proc;
- int needs_braces_p;
- {
- int slot = user_command_array_len;
- user_command_array_len++;
-
- if (!user_command_array)
- user_command_array = (COMMAND **) xmalloc (1 * sizeof (COMMAND *));
-
- user_command_array = (COMMAND **) xrealloc (user_command_array,
- (1 + user_command_array_len) *
- sizeof (COMMAND *));
-
- user_command_array[slot] = (COMMAND *) xmalloc (sizeof (COMMAND));
- user_command_array[slot]->name = savestring (name);
- user_command_array[slot]->proc = proc;
- user_command_array[slot]->argument_in_braces = needs_braces_p;
- }
-
- /* Make ALIAS run the named FUNCTION. Copies properties from FUNCTION. */
- VOID
- define_alias (alias, function)
- char *alias, *function;
- {
- }
-
- /* Some support for footnotes. */
-
- /* Footnotes are a new construct in Info. We don't know the best method
- of implementing them for sure, so we present two possiblities.
-
- MN 1) Make them look like followed references, with the reference
- destinations in a makeinfo manufactured node or,
-
- BN 2) Make them appear at the bottom of the node that they originally
- appeared in.
- */
-
- #define MN 0
- #define BN 1
-
- int footnote_style = MN;
- boolean first_footnote_this_node = true;
- int footnote_count = 0;
-
- /* Set the footnote style based on he style identifier in STRING. */
- VOID
- set_footnote_style (string)
- char *string;
- {
- if (stricmp (string, "MN") == 0)
- {
- footnote_style = MN;
- return;
- }
-
- if (stricmp (string, "BN") == 0)
- {
- footnote_style = BN;
- return;
- }
- }
-
- typedef struct fn
- {
- struct fn *next;
- char *marker;
- char *note;
- } FN;
-
- FN *pending_notes = (FN *) NULL;
-
- /* A method for remembering footnotes. Note that this list gets output
- at the end of the current node. */
- VOID
- remember_note (marker, note)
- char *marker, *note;
- {
- FN *temp = (FN *) xmalloc (sizeof (FN));
-
- temp->marker = savestring (marker);
- temp->note = savestring (note);
- temp->next = pending_notes;
- pending_notes = temp;
- footnote_count++;
- }
-
- /* How to get rid of existing footnotes. */
- VOID
- free_pending_notes ()
- {
- FN *temp;
-
- while ((temp = pending_notes) != (FN *) NULL)
- {
- free (temp->marker);
- free (temp->note);
- pending_notes = pending_notes->next;
- free (temp);
- }
- first_footnote_this_node = true;
- footnote_count = 0;
- }
-
- /* What to do when you see a @footnote construct. */
-
- /* Handle a "footnote".
- footnote *{this is a footnote}
- where "*" is the marker character for this note. */
- VOID
- cm_footnote ()
- {
- char *marker;
- char *note;
-
- get_until ("{", &marker);
- canon_white (marker);
-
- /* Read the argument in braces. */
- if (curchar () != '{')
- {
- line_error ("`@%s' expected more than just `%s'. It needs something in `{...}'", command, marker);
- free (marker);
- return;
- }
- else
- {
- int braces = 1;
- LONG temp = ++input_text_offset;
- int len;
-
- while (braces)
- {
- if (temp == size_of_input_text)
- {
- line_error ("No closing brace for footnote `%s'", marker);
- return;
- }
- if (input_text[temp] == '{')
- braces++;
- else if (input_text[temp] == '}')
- braces--;
- temp++;
- }
-
- #ifdef MSDOS
- assert (temp - input_text_offset < (1L<<16));
- len = (size_t) (temp - input_text_offset) - 1;
- #else /* not MSDOS */
- len = (temp - input_text_offset) - 1;
- #endif /* not MSDOS */
- note = xmalloc (len + 1);
- strncpy (note, &input_text[input_text_offset], len);
- note[len] = '\0';
- input_text_offset = temp;
- }
-
- if (!current_node || !*current_node)
- {
- line_error ("Footnote defined without parent node");
- free (marker);
- free (note);
- return;
- }
-
- remember_note (marker, note);
-
- switch (footnote_style)
- { /* your method should at least insert marker. */
-
- case MN:
- add_word_args ("(%s)", marker);
- if (first_footnote_this_node)
- {
- char *temp_string = xmalloc ((strlen (current_node))
- + (strlen ("-Footnotes")) + 1);
- add_word_args (" (*note %s-Footnotes::)", current_node);
- strcpy (temp_string, current_node);
- strcat (temp_string, "-Footnotes");
- remember_node_reference (temp_string, line_number, followed_reference);
- free (temp_string);
- first_footnote_this_node = false;
- }
- break;
-
- case BN:
- add_word_args ("(%s)", marker);
- break;
-
- default:
- break;
- }
- free (marker);
- free (note);
- }
-
- /* Non-zero means that we are currently in the process of outputting
- footnotes. */
- int already_outputting_pending_notes = 0;
-
- /* Output the footnotes. We are at the end of the current node. */
- VOID
- output_pending_notes ()
- {
- FN *footnote = pending_notes;
-
- if (!pending_notes)
- return;
-
- switch (footnote_style)
- {
-
- case MN:
- {
- char *old_current_node = current_node;
- char *old_command = savestring (command);
-
- already_outputting_pending_notes++;
- execute_string ("@node %s-Footnotes,,,%s\n", current_node, current_node);
- already_outputting_pending_notes--;
- current_node = old_current_node;
- free (command);
- command = old_command;
- }
- break;
-
- case BN:
- close_paragraph ();
- execute_string ("---------- Footnotes ----------\n\n");
- break;
- }
-
-
- /* Handle the footnotes in reverse order. */
- {
- FN **array = (FN **) xmalloc ((footnote_count + 1) * sizeof (FN *));
-
- array[footnote_count] = (FN *) NULL;
-
- while (--footnote_count > -1)
- {
- array[footnote_count] = footnote;
- footnote = footnote->next;
- }
-
- filling_enabled = true;
- indented_fill = true;
-
- while (footnote = array[++footnote_count])
- {
-
- switch (footnote_style)
- {
-
- case MN:
- case BN:
- execute_string ("(%s) %s", footnote->marker, footnote->note);
- close_paragraph ();
- break;
- }
- }
- close_paragraph ();
- free (array);
- }
- }
-
- #ifdef MSDOS
- void _huge *
- xhalloc (long size)
- {
- void _huge *value = (void _huge *) halloc (size, (size_t) 1);
-
- if (value == (void HUGE *) 0 )
- {
- error ("Virtual memory exhausted! Needed %ld bytes.", size);
- exit (FATAL);
- }
- return value;
- }
-
-
- #if 0
- /* Here we do a huge "realloc" by allocating a new block and
- moving the old block afterwards. This is *slow*, but should
- be reliable. */
-
- void _huge *
- xhrealloc (void _huge *ptr, long new_size, long old_size)
- {
- void _huge *value = (void _huge *) halloc (new_size, (size_t)1 );
-
- if (!value)
- {
- error ("Virtual memory exhausted in realloc ().");
- abort ();
- }
- else
- {
- char _huge *dest = value;
- char _huge *src = ptr;
-
- while (old_size > 0L)
- {
- unsigned int bytes = (unsigned int) min (0x8000L, old_size);
- memcpy (dest, src, bytes);
- old_size -= (long) bytes;
- dest += (long) bytes;
- src += (long) bytes;
- }
- }
- hfree (ptr);
- return value;
- }
- #endif /* not needed */
-
-
- long
- hread (int fd, void _huge *buffer, long bytes)
- {
- long bytes_read = 0L;
-
- while (1)
- {
- int n = read (fd, buffer, (unsigned int) min (0x4000L, bytes));
-
- if (n > 0)
- {
- bytes_read += (long) n;
- bytes -= (long) n;
- /* we can't say buffer += n here, because we have to make
- sure that the offset of BUFFER doesn't overflow during
- the read() system call. Therefore we add what we read
- to the segment of BUFFER. */
- FP_SEG(buffer) += (n >> 4);
- FP_OFF(buffer) += (n & 0x0F);
- }
- else if (n == 0)
- return bytes_read; /* done */
- else
- {
- perror ("Can't read input");
- exit (FATAL);
- }
- }
- }
-
- #endif /* MSDOS */
-
-
- /*
- * Local Variables:
- * mode:C
- * ChangeLog:ChangeLog
- * End:
- */
-