home *** CD-ROM | disk | FTP | other *** search
/ Mega CD-ROM 1 / megacd_rom_1.zip / megacd_rom_1 / GNUISH / MKINF10.ZIP / MAKEINFO.C < prev    next >
C/C++ Source or Header  |  1990-11-01  |  48KB  |  1,683 lines

  1. /* Makeinfo -- convert texinfo format files into info files
  2.  
  3.    Copyright (C) 1987 Free Software Foundation, Inc.
  4.  
  5.    This file is part of GNU Info.
  6.  
  7.    Makeinfo is distributed in the hope that it will be useful,
  8.    but WITHOUT ANY WARRANTY.  No author or distributor accepts
  9.    responsibility to anyone for the consequences of using it or for
  10.    whether it serves any particular purpose or works at all, unless he
  11.    says so in writing.  Refer to the GNU Emacs General Public License
  12.    for full details.
  13.  
  14.    Everyone is granted permission to copy, modify and redistribute
  15.    Makeinfo, but only under the conditions described in the GNU Emacs
  16.    General Public License.   A copy of this license is supposed to
  17.    have been given to you along with GNU Emacs so you can know your
  18.    rights and responsibilities.  It should be in a file named COPYING.
  19.    Among other things, the copyright notice and this notice must be
  20.    preserved on all copies.  */
  21.  
  22. /* MS-DOS port (c) 1990 by Thorsten Ohl, td12@ddagsi3.bitnet
  23.    This port is also distributed under the terms of the
  24.    GNU General Public License as published by the
  25.    Free Software Foundation.
  26.  
  27.    Please note that this file is not identical to the
  28.    original GNU release, you should have received this
  29.    code as patch to the official release.
  30.  
  31.    $Header: e:/gnu/info/RCS/makeinfo.c 0.1.1.1 90/10/05 11:25:23 tho Exp $
  32.  */
  33.  
  34. /* **************************************************************** */
  35. /*                                    */
  36. /*            Include File Declarations               */
  37. /*                                    */
  38. /* **************************************************************** */
  39.  
  40. #include <stdio.h>
  41. #include <sys/types.h>
  42. #include <sys/stat.h>
  43. #include <ctype.h>
  44. #ifndef MSDOS
  45. #include <pwd.h>
  46. #endif /* not MSDOS */
  47.  
  48.  
  49. #ifdef MSDOS            /* `16+4' bit machines... */
  50. #define VOID void
  51. #define PVOID void
  52. #define SIZE_T size_t
  53. #define LONG long
  54. #if defined (_MSC_VER) && (_MSC_VER >= 600)
  55. #define HUGE _huge
  56. #define CDECL _cdecl
  57. #else
  58. #define HUGE huge
  59. #define CDECL cdecl
  60. #endif
  61. #else /* not MSDOS */
  62. #define VOID int
  63. #define PVOID char
  64. #define SIZE_T int
  65. #define LONG int
  66. #define HUGE
  67. #define CDECL
  68. #endif /* not MSDOS */
  69.  
  70.  
  71. #ifdef MSDOS
  72. #include <stdlib.h>
  73. #include <string.h>
  74. #include <stdlib.h>
  75. #include <stdarg.h>
  76. #include <assert.h>
  77. #include <malloc.h>
  78. #include <io.h>
  79. #include <dos.h>
  80. char *msdos_format_filename (char *name);
  81. void _huge *xhalloc (long size);
  82. void _huge *xhrealloc (void _huge *ptr, long new_size, long old_size);
  83. long hread (int fd, void _huge *buffer, long bytes);
  84. char **args_from_string (char *string);
  85. char *current_item_function (void);
  86. char *defun_title (int type);
  87. char *expand_filename (char *filename, char *input_name);
  88. char *filename_part (char *filename);
  89. char HUGE *find_and_load (char *filename);
  90. char *find_proc_name (VOID (*proc) ());
  91. char *full_pathname (char *filename);
  92. char *get_item_function (void);
  93. char *get_node_token (void);
  94. char *get_xref_token (void);
  95. char *insertion_type_pname (int type);
  96. char *pathname_part (char *filename);
  97. char *read_token (void);
  98. char *reftype_type_string (int type);
  99. PVOID *xmalloc (SIZE_T nbytes);
  100. PVOID *xrealloc (PVOID *pointer, SIZE_T nbytes);
  101. VOID add_char (int character);
  102. VOID add_word (char *string);
  103. VOID CDECL add_word_args (char *format, ...);
  104. VOID begin_insertion (int type);
  105. VOID canon_white (char *string);
  106. VOID close_paragraph (void);
  107. VOID close_paragraph_with_lines (int lines);
  108. VOID close_single_paragraph (void);
  109. VOID cm_appendix (void);
  110. VOID cm_appendixsec (void);
  111. VOID cm_appendixsubsec (void);
  112. VOID cm_appendixsubsubsec (void);
  113. VOID cm_asis (void);
  114. VOID cm_asterisk (void);
  115. VOID cm_bold (int arg);
  116. VOID cm_br (void);
  117. VOID cm_bullet (int arg);
  118. VOID cm_bye (void);
  119. VOID cm_center (void);
  120. VOID cm_chapter (void);
  121. VOID cm_cindex (void);
  122. VOID cm_cite (int arg, int position);
  123. VOID cm_code (int arg);
  124. VOID cm_comment (void);
  125. VOID cm_copyright (int arg);
  126. VOID cm_ctrl (int arg, int position);
  127. VOID cm_defindex (void);
  128. VOID cm_defun (void);
  129. VOID cm_dfn (int arg, int position);
  130. VOID cm_display (void);
  131. VOID cm_dots (int arg);
  132. VOID cm_emph (int arg);
  133. VOID cm_end (void);
  134. VOID cm_enumerate (void);
  135. VOID cm_equiv (int arg);
  136. VOID cm_error (int arg);
  137. VOID cm_example (void);
  138. VOID cm_exdent (void);
  139. VOID cm_expansion (int arg);
  140. VOID cm_file (int arg);
  141. VOID cm_findex (void);
  142. VOID cm_footnote (void);
  143. VOID cm_force_abbreviated_whitespace (void);
  144. VOID cm_force_sentence_end (void);
  145. VOID cm_format (void);
  146. VOID cm_group (void);
  147. VOID cm_ifinfo (void);
  148. VOID cm_iftex (void);
  149. VOID cm_ignore (void);
  150. VOID cm_include (void);
  151. VOID cm_infoinclude (void);
  152. VOID cm_inforef (int arg);
  153. VOID cm_italic (int arg);
  154. VOID cm_item (void);
  155. VOID cm_itemize (void);
  156. VOID cm_itemx (void);
  157. VOID cm_kbd (int arg);
  158. VOID cm_key (int arg);
  159. VOID cm_kindex (void);
  160. VOID cm_lisp (void);
  161. VOID cm_menu (void);
  162. VOID cm_minus (int arg);
  163. VOID cm_need (void);
  164. VOID cm_node (void);
  165. VOID cm_noindent (void);
  166. VOID cm_obsolete (int arg);
  167. VOID cm_pindex (void);
  168. VOID cm_point (int arg);
  169. VOID cm_print (int arg);
  170. VOID cm_printindex (void);
  171. VOID cm_pxref (int arg);
  172. VOID cm_quotation (void);
  173. VOID cm_refill (void);
  174. VOID cm_result (int arg);
  175. VOID cm_roman (int arg);
  176. VOID cm_samp (int arg);
  177. VOID cm_sc (int arg, int start_pos, int end_pos);
  178. VOID cm_section (void);
  179. VOID cm_setchapternewpage (void);
  180. VOID cm_setfilename (void);
  181. VOID cm_settitle (void);
  182. VOID cm_smallexample (void);
  183. VOID cm_sp (void);
  184. VOID cm_strong (int arg, int position);
  185. VOID cm_subsection (void);
  186. VOID cm_subsubsection (void);
  187. VOID cm_synindex (void);
  188. VOID cm_table (void);
  189. VOID cm_TeX (int arg);
  190. VOID cm_tex (void);
  191. VOID cm_tindex (void);
  192. VOID cm_title (int arg);
  193. VOID cm_titlepage (void);
  194. VOID cm_titlespec (void);
  195. VOID cm_unnumbered (void);
  196. VOID cm_unnumberedsec (void);
  197. VOID cm_unnumberedsubsec (void);
  198. VOID cm_unnumberedsubsubsec (void);
  199. VOID cm_var (int arg, int start_pos, int end_pos);
  200. VOID cm_vindex (void);
  201. VOID cm_w (int arg);
  202. VOID cm_xref (int arg);
  203. VOID convert (char *name);
  204. int current_insertion_type (void);
  205. VOID defindex (char *name);
  206. VOID define_alias (char *alias, char *function);
  207. VOID define_user_command (char *name, VOID (*proc) (), int needs_braces_p);
  208. int defun_insertion (int type);
  209. VOID defun_internal (int type, char *title, int x_p);
  210. VOID discard_braces (void);
  211. VOID discard_insertions (void);
  212. VOID discard_until (char *string);
  213. VOID do_nothing (void);
  214. VOID end_insertion (int type);
  215. int CDECL error (char *format, ...);
  216. VOID CDECL execute_string (char *format, ...);
  217. int find_index_offset (char *name);
  218. int find_type_from_name (char *name);
  219. VOID fix_whitespace (char *string);
  220. VOID flush_file_stack (void);
  221. VOID flush_output (void);
  222. VOID free_and_clear (char **pointer);
  223. VOID free_index (struct index_elt * index);
  224. VOID free_node_references (void);
  225. VOID free_pending_notes (void);
  226. int fs_error (char *filename);
  227. VOID gen_index (void);
  228. int get_char_len (int character);
  229. VOID get_defun_args (void);
  230. VOID get_rest_of_line (char **string);
  231. VOID get_until (char *match, char **string);
  232. VOID get_until_in_braces (char *match, char **string);
  233. VOID get_until_in_line (char *match, char **string);
  234. VOID glean_node_from_menu (void);
  235. VOID indent (int amount);
  236. VOID index_add_arg (char *name);
  237. int CDECL index_element_compare (struct index_elt **element1,
  238.                  struct index_elt **element2);
  239. VOID init_brace_stack (void);
  240. VOID init_indices (void);
  241. VOID init_insertion_stack (void);
  242. VOID init_internals (void);
  243. VOID init_paragraph (void);
  244. VOID init_tag_table (void);
  245. VOID insert (int character);
  246. VOID insert_and_underscore (int with_char);
  247. VOID insert_defun_arg (char *string, int where);
  248. VOID insert_self (void);
  249. VOID kill_self_indent (int count);
  250. int CDECL line_error (char *format, ...);
  251. VOID CDECL main (int argc, char **argv);
  252. VOID misplaced_brace (void);
  253. VOID normalize_node_name (char *string);
  254. VOID number_item (void);
  255. VOID output_pending_notes (void);
  256. VOID popfile (void);
  257. int pop_and_call_brace (void);
  258. VOID pop_insertion (void);
  259. VOID pop_node_filename (void);
  260. VOID pushfile (void);
  261. VOID push_insertion (int type, char *item_function);
  262. VOID push_node_filename (void);
  263. VOID reader_loop (void);
  264. VOID read_command (void);
  265. VOID remember_brace (VOID (*proc) ());
  266. VOID remember_brace_1 (VOID (*proc) (), LONG position);
  267. VOID remember_error (void);
  268. VOID remember_node (char *node, char *prev, char *next, char *up,
  269.            LONG position, int line_no, int no_warn);
  270. VOID remember_node_reference (char *node, int line, int type);
  271. VOID remember_note (char *marker, char *note);
  272. LONG search_forward (char *string, LONG from);
  273. int self_delimiting (int character);
  274. VOID set_footnote_style (char *string);
  275. VOID split_file (char *filename, LONG size);
  276. VOID start_numbering (int at_number);
  277. VOID start_paragraph (void);
  278. VOID stop_numbering (void);
  279. int translate_index (char *name);
  280. int undefindex (char *name);
  281. VOID usage (void);
  282. int validate (char *tag, int line, char *label);
  283. VOID validate_file (char *filename, struct tentry * tag_table);
  284. VOID validate_other_references (struct node_ref * ref_list);
  285. int CDECL warning (char *format, ...);
  286. int what_section (char *text);
  287. int write_tag_table (void);
  288. int write_tag_table_indirect (void);
  289. VOID write_tag_table_internal (int indirect_p);
  290. struct generic_list *reverse_list (struct generic_list * list);
  291. struct index_elt **sort_index (struct index_elt * index);
  292. struct index_elt *index_append (struct index_elt * head,
  293.                 struct index_elt * tail);
  294. struct index_elt *index_list (char *name);
  295. struct node_ref *find_node_reference (char *node, struct node_ref * ref_list);
  296. struct tentry *find_node (char *name);
  297. #endif /* MSDOS */
  298.  
  299. #include "getopt.h"
  300.  
  301. #ifdef SYSV
  302. #include <string.h>
  303. struct passwd *getpwnam ();
  304. #include <fcntl.h>
  305. #define bcopy(source, dest, count) memcpy (dest, source, count)
  306. #define index strchr
  307. #else
  308. #include <strings.h>
  309. #include <sys/file.h>
  310. #endif
  311.  
  312. #if defined (sparc) || defined (i386)
  313. #ifndef __GNUC__
  314. #include <alloca.h>
  315. #else
  316. #define alloca __builtin_alloca
  317. #endif
  318. #endif
  319.  
  320. /* Forward declarations. */
  321. PVOID *xmalloc (), *xrealloc ();
  322.  
  323.  
  324. /* **************************************************************** */
  325. /*                                    */
  326. /*                  Global Defines                  */
  327. /*                                    */
  328. /* **************************************************************** */
  329.  
  330. /* Error levels */
  331. #define NO_ERROR 0
  332. #define SYNTAX 1
  333. #define FATAL 2
  334.  
  335. /* Boolean values. */
  336. #define true  1
  337. #define false 0
  338. typedef int boolean;
  339.  
  340. /* I want to make sure that NULL looks like this. */
  341. #ifdef NULL
  342. #undef NULL
  343. #endif
  344. #define NULL 0x0
  345.  
  346. /* How to allocate permanent storage for STRING. */
  347. #define savestring(x) \
  348.   ((char *)strcpy (xmalloc (1 + ((x) ? strlen (x) : 0)), (x) ? (x) : ""))
  349.  
  350. /* C's standard macros don't check to make sure that the characters being
  351.    changed are within range.  So I have to check explicitly. */
  352.  
  353. /* GNU Library doesn't have toupper().  Until GNU gets this fixed, I will
  354.    have to do it. */
  355. #ifndef toupper
  356. #define toupper(c) ((c) - 32)
  357. #endif
  358.  
  359. #define coerce_to_upper(c) ((islower(c) ? toupper(c) : (c)))
  360. #define coerce_to_lower(c) ((isupper(c) ? tolower(c) : (c)))
  361.  
  362. #define control_character_bit 0x40 /* %01000000, must be off. */
  363. #define meta_character_bit 0x080/* %10000000, must be on.  */
  364. #define CTL(c) ((c) & (~control_character_bit))
  365. #define UNCTL(c) coerce_to_upper(((c)|control_character_bit))
  366. #define META(c) ((c) | (meta_character_bit))
  367. #define UNMETA(c) ((c) & (~meta_character_bit))
  368.  
  369. #define whitespace(c) (((c) == '\t') || ((c) == ' '))
  370. #define sentence_ender(c) ((c) == '.' || (c) == '?' || (c) == '!')
  371. #define cr_or_whitespace(c) (((c) == '\t') || ((c) == ' ') || ((c) == '\n'))
  372. #define member(c, s) (index (s, c) != NULL)
  373.  
  374. #define COMMAND_PREFIX '@'
  375.  
  376. /* Stuff for splitting large files. */
  377. #ifdef MSDOS
  378. #define SPLIT_SIZE_THRESHOLD 60000    /* What's good enough for Stallman... */
  379. #define DEFAULT_SPLIT_SIZE 40000    /* Is not good enough for me. */
  380. #else /* not MSDOS */
  381. #define SPLIT_SIZE_THRESHOLD 70000    /* What's good enough for Stallman... */
  382. #define DEFAULT_SPLIT_SIZE 50000/* Is probably good enough for me. */
  383. #endif /* not MSDOS */
  384. boolean splitting = true;    /* Always true for now. */
  385.  
  386. typedef VOID FUNCTION ();    /* So I can say FUNCTION *foo; */
  387.  
  388.  
  389. /* **************************************************************** */
  390. /*                                    */
  391. /*                Global Variables                */
  392. /*                                    */
  393. /* **************************************************************** */
  394.  
  395. /* Global pointer to argv[0]. */
  396. char *progname;
  397.  
  398. /* The current input file state. */
  399. char *input_filename;
  400. char HUGE *input_text;
  401. LONG size_of_input_text;
  402. LONG input_text_offset;
  403. int line_number;
  404.  
  405. #define curchar() input_text[input_text_offset]
  406.  
  407. #define command_char(c) ((!whitespace(c)) && \
  408.               ((c) != '\n') && \
  409.               ((c) != '{'))
  410. #define skip_whitespace() while (input_text_offset != size_of_input_text \
  411.                  && whitespace(curchar()))\
  412.   input_text_offset++
  413.  
  414. /* And writing to the output. */
  415.  
  416. /* The output file name. */
  417. char *output_filename, *pretty_output_filename;
  418.  
  419. /* Current output stream. */
  420. FILE *output_stream;
  421.  
  422. /* Position in the output file. */
  423. LONG output_position;
  424.  
  425. /* Output paragraph buffer. */
  426. char *output_paragraph;
  427.  
  428. /* Offset into OUTPUT_PARAGRAPH. */
  429. int output_paragraph_offset;
  430.  
  431. /* The output paragraph "cursor" horizontal position. */
  432. int output_column = 0;
  433.  
  434. /* non-zero means output_paragraph contains text. */
  435. boolean paragraph_is_open = false;
  436.  
  437. #define INITIAL_PARAGRAPH_SPACE 5000
  438. int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE;
  439.  
  440. /* Filling.. */
  441. /* True indicates that filling will take place on long lines. */
  442. boolean filling_enabled = true;
  443.  
  444. /* Non-zero means that words are not to be split, even in long lines.  This
  445.    gets changed for cm_w (). */
  446. int non_splitting_words = 0;
  447.  
  448. /* True indicates that filling a line also indents the new line. */
  449. boolean indented_fill = false;
  450.  
  451. /* The column at which long lines are broken. */
  452. int fill_column = 72;
  453.  
  454. /* The amount of indentation to apply at the start of each line. */
  455. int current_indent = 0;
  456.  
  457. /* The amount of indentation to add at the starts of paragraphs.
  458.    0 means don't change existing indentation at paragraph starts.
  459.    > 0 is amount to indent new paragraphs by.
  460.    < 0 means indent to column zero by removing indentation if necessary.
  461.  
  462.    This is normally zero, but some people prefer paragraph starts to be
  463.    somewhat more indented than paragraph bodies.  A pretty value for
  464.    this is 3. */
  465. int paragraph_start_indent = 0;
  466.  
  467. /* Non-zero means that the use of paragraph_start_indent is inhibited.
  468.    @example uses this to line up the left columns of the example text. */
  469. int inhibit_paragraph_indentation = 0;
  470.  
  471. /* Indentation that is pending insertion.  We have this for hacking lines
  472.    which look blank, but contain whitespace.  We want to treat those as
  473.    blank lines. */
  474. int pending_indent = 0;
  475.  
  476. /* The amount that indentation increases/decreases by. */
  477. int default_indentation_increment = 5;
  478.  
  479. /* True indicates that indentation is temporarily turned off. */
  480. boolean no_indent = true;
  481.  
  482. /* Command name in the process of being hacked. */
  483. char *command;
  484.  
  485. /* The index in our internal command table of the currently
  486.    executing command. */
  487. int command_index;
  488.  
  489. /* A stack of file information records.  If a new file is read in with
  490.    "@input", we remember the old input file state on this stack. */
  491. typedef struct fstack
  492. {
  493.   struct fstack *next;
  494.   char *filename;
  495.   char *text;
  496.   LONG size;
  497.   LONG offset;
  498.   int line_number;
  499. } FSTACK;
  500.  
  501. FSTACK *filestack = (FSTACK *) NULL;
  502.  
  503. /* Stuff for nodes. */
  504. /* The current nodes node name */
  505. char *current_node;
  506.  
  507. /* The current nodes section level. */
  508. int current_section = 0;
  509.  
  510. /* The filename of the current input file.  This is never freed. */
  511. char *node_filename = (char *)NULL;
  512.  
  513. /* What we remember for each node. */
  514. typedef struct tentry
  515. {
  516.   struct tentry *next_ent;
  517.   char *node;        /* name of this node. */
  518.   char *prev;        /* name of "Prev:" for this node. */
  519.   char *next;        /* name of "Next:" for this node. */
  520.   char *up;        /* name of "Up:" for this node.   */
  521.   LONG position;    /* output file position of this node. */
  522.   int line_no;        /* defining line in source file. */
  523.   char *filename;    /* The file that this node was found in. */
  524.   int touched;        /* non-zero means this node has been referenced. */
  525.   int flags;        /* Room for growth.  Right now, contains 1 bit. */
  526. } TAG_ENTRY;
  527.  
  528. /* If node-a has a "Next" for node-b, but node-b has no "Prev" for node-a,
  529.    we turn on this flag bit in node-b's tag entry.  This means that when
  530.    it is time to validate node-b, we don't report an additional error
  531.    if there was no "Prev" field. */
  532. #define PREV_ERROR 0x1
  533. #define NEXT_ERROR 0x2
  534. #define UP_ERROR   0x4
  535. #define NO_WARN       0x8
  536.  
  537. TAG_ENTRY *tag_table = (TAG_ENTRY *) NULL;
  538.  
  539. /* Menu reference, *note reference, and validation hacking. */
  540.  
  541. /* The various references that we know about. */
  542. enum reftype
  543. {
  544.   menu_reference, followed_reference
  545. };
  546.  
  547. /* A structure to remember references with.  A reference to a node is
  548.    either an entry in a menu, or a cross-reference made with [px]ref. */
  549. typedef struct node_ref
  550. {
  551.   struct node_ref *next;
  552.   char *node;            /* Name of node referred to. */
  553.   char *containing_node;    /* Name of node containing this reference. */
  554.   int line_no;            /* Line number where the reference occurs. */
  555.   int section;            /* Section level where the reference occurs. */
  556.   char *filename;        /* Name of file where the reference occurs. */
  557.   enum reftype type;        /* Type of reference, either menu or note. */
  558. } NODE_REF;
  559.  
  560. /* The linked list of such structures. */
  561. NODE_REF *node_references = (NODE_REF *) NULL;
  562.  
  563. /* Flag which tells us whether to examine menu lines or not. */
  564. int in_menu = 0;
  565.  
  566. /* Flags controlling the operation of the program. */
  567.  
  568. /* Default is to notify users of bad choices. */
  569. boolean print_warnings = true;
  570.  
  571. /* Default is to check node references. */
  572. boolean validating = true;
  573.  
  574. /* Number of errors that we tolerate on a given fileset. */
  575. int max_error_level = 100;
  576.  
  577. /* Maximum number of references to a single node before complaining. */
  578. int reference_warning_limit = 1000;
  579.  
  580. /* Non-zero means print out information about what is going on when it
  581.    is going on. */
  582. int verbose_mode = 0;
  583.  
  584. /* The list of commands that we hack in texinfo.  Each one
  585.    has an associated function.  When the command is encountered in the
  586.    text, the associated function is called with START as the argument.
  587.    If the function expects arguments in braces, it remembers itself on
  588.    the stack.  When the corresponding close brace is encountered, the
  589.    function is called with END as the argument. */
  590.  
  591. #define START 0
  592. #define END 1
  593.  
  594. typedef struct brace_element
  595. {
  596.   struct brace_element *next;
  597.   FUNCTION *proc;
  598.   LONG pos;
  599.   int line;
  600. } BRACE_ELEMENT;
  601.  
  602. BRACE_ELEMENT *brace_stack = (BRACE_ELEMENT *) NULL;
  603.  
  604. /* Forward declarations. */
  605.  
  606. VOID
  607. insert_self (), cm_tex (), cm_asterisk (), cm_dots (), cm_bullet (),
  608. cm_TeX (), cm_copyright (), cm_code (), cm_samp (), cm_file (), cm_kbd (),
  609. cm_key (), cm_ctrl (), cm_var (), cm_dfn (), cm_emph (), cm_strong (),
  610. cm_cite (), cm_italic (), cm_bold (), cm_roman (), cm_title (), cm_w (),
  611. cm_refill ();
  612.  
  613. VOID
  614. cm_chapter (), cm_unnumbered (), cm_appendix (),
  615. cm_section (), cm_unnumberedsec (), cm_appendixsec (),
  616. cm_subsection (), cm_unnumberedsubsec (), cm_appendixsubsec (),
  617. cm_subsubsection (), cm_unnumberedsubsubsec (), cm_appendixsubsubsec ();
  618.  
  619. /* All @defxxx commands map to cm_defun (). */
  620. VOID
  621. cm_defun ();
  622.  
  623. VOID
  624. cm_node (), cm_menu (), cm_xref (),
  625. cm_pxref (), cm_inforef (), cm_quotation (), cm_display (), cm_itemize (),
  626. cm_enumerate (), cm_table (), cm_itemx (), cm_noindent (), cm_setfilename (),
  627. cm_comment (), cm_ignore (), cm_br (), cm_sp (), cm_page (), cm_group (),
  628. cm_need (), cm_center (), cm_include (), cm_bye (), cm_item (), cm_end (),
  629. cm_infoinclude (), cm_ifinfo (), cm_iftex (), cm_titlepage (),
  630. cm_titlespec (),cm_kindex (), cm_cindex (), cm_findex (), cm_pindex (),
  631. cm_vindex (), cm_tindex (), cm_asis (), cm_synindex (), cm_settitle (),
  632. cm_setchapternewpage (), cm_printindex (), cm_minus (), cm_footnote (),
  633. cm_force_abbreviated_whitespace (), cm_force_sentence_end (), cm_example (),
  634. cm_smallexample (), cm_lisp (), cm_format (), cm_exdent (), cm_defindex (),
  635. cm_sc (), cm_result (), cm_expansion (), cm_equiv (), cm_print (),
  636. cm_error (), cm_point ();
  637.  
  638. VOID do_nothing ();
  639. VOID misplaced_brace (), cm_obsolete ();
  640.  
  641. typedef struct
  642. {
  643.   char *name;
  644.   FUNCTION *proc;
  645.   boolean argument_in_braces;
  646. } COMMAND;
  647.  
  648. #ifdef MSDOS
  649. COMMAND *get_command_entry (char *string);
  650. #endif /* MSDOS */
  651.  
  652. /* Stuff for defining commands on the fly. */
  653. COMMAND **user_command_array = (COMMAND **) NULL;
  654. int user_command_array_len = 0;
  655.  
  656. static COMMAND CommandTable[] = {
  657.   {"!", cm_force_sentence_end, false},
  658.   {"'", insert_self, false},
  659.   {"*", cm_asterisk, false},
  660.   {".", cm_force_sentence_end, false},
  661.   {":", cm_force_abbreviated_whitespace, false},
  662.   {"?", cm_force_sentence_end, false},
  663.   {"@", insert_self, false},
  664.   {" ", insert_self, false},
  665.   {"\n", insert_self, false},
  666.   {"TeX", cm_TeX, true},
  667.   {"`", insert_self, false},
  668.   {"appendix", cm_appendix, false},
  669.   {"appendixsec", cm_appendixsec, false},
  670.   {"appendixsubsec", cm_appendixsubsec, false},
  671.   {"appendixsubsubsec", cm_appendixsubsubsec, false},
  672.   {"asis", cm_asis, true},
  673.   {"b", cm_bold, true},
  674.   {"br", cm_br, false},
  675.   {"bullet", cm_bullet, true},
  676.   {"bye", cm_bye, false},
  677.   {"c", cm_comment, false},
  678.   {"center", cm_center, false},
  679.   {"chapter", cm_chapter, false},
  680.   {"cindex", cm_cindex, false},
  681.   {"cite", cm_cite, true},
  682.   {"code", cm_code, true},
  683.   {"comment", cm_comment, false},
  684.   {"contents", do_nothing, false},
  685.   {"copyright", cm_copyright, true},
  686.   {"ctrl", cm_ctrl, true},
  687.   {"defcodeindex", cm_defindex, false},
  688.   {"defindex", cm_defindex, false},
  689.   {"dfn", cm_dfn, true},
  690.  
  691. /* The `def' commands. */
  692.   {"defun", cm_defun, false},
  693.   {"defunx", cm_defun, false},
  694.   {"defvar", cm_defun, false},
  695.   {"defvarx", cm_defun, false},
  696.   {"defopt", cm_defun, false},
  697.   {"defoptx", cm_defun, false},
  698.   {"deffn", cm_defun, false},
  699.   {"deffnx", cm_defun, false},
  700.   {"defspec", cm_defun, false},
  701.   {"defspecx", cm_defun, false},
  702.   {"defmac", cm_defun, false},
  703.   {"defmacx", cm_defun, false},
  704. /* The end of the `def' commands. */
  705.  
  706.   {"display", cm_display, false},
  707.   {"dots", cm_dots, true},
  708.   {"emph", cm_emph, true},
  709.   {"end", cm_end, false},
  710.   {"enumerate", cm_enumerate, false},
  711.   {"equiv", cm_equiv, true},
  712.   {"error", cm_error, true},
  713.   {"example", cm_example, false},
  714.   {"exdent", cm_exdent, false},
  715.   {"expansion", cm_expansion, true},
  716.   {"file", cm_file, true},
  717.   {"findex", cm_findex, false},
  718.   {"format", cm_format, false},
  719.   {"group", cm_group, false},
  720.   {"i", cm_italic, true},
  721.   {"iappendix", cm_appendix, false},
  722.   {"iappendixsec", cm_appendixsec, false},
  723.   {"iappendixsubsec", cm_appendixsubsec, false},
  724.   {"iappendixsubsubsec", cm_appendixsubsubsec, false},
  725.   {"ichapter", cm_chapter, false},
  726.   {"ifinfo", cm_ifinfo, false},
  727.   {"iftex", cm_iftex, false},
  728.   {"ignore", cm_ignore, false},
  729.   {"include", cm_include, false},
  730.   {"inforef", cm_inforef, true},
  731.   {"input", cm_include, false},
  732.   {"isection", cm_section, false},
  733.   {"isubsection", cm_subsection, false},
  734.   {"isubsubsection", cm_subsubsection, false},
  735.   {"item", cm_item, false},
  736.   {"itemize", cm_itemize, false},
  737.   {"itemx", cm_itemx, false},
  738.   {"iunnumbered", cm_unnumbered, false},
  739.   {"iunnumberedsec", cm_unnumberedsec, false},
  740.   {"iunnumberedsubsec", cm_unnumberedsubsec, false},
  741.   {"iunnumberedsubsubsec", cm_unnumberedsubsubsec, false},
  742.   {"kbd", cm_kbd, true},
  743.   {"key", cm_key, true},
  744.   {"kindex", cm_kindex, false},
  745.   {"lisp", cm_lisp, false},
  746.   {"menu", cm_menu},
  747.   {"minus", cm_minus, true},
  748.   {"need", cm_need, false},
  749.   {"node", cm_node, false},
  750.   {"noindent", cm_noindent, false},
  751.   {"page", do_nothing, false},
  752.   {"pindex", cm_pindex, false},
  753.   {"point", cm_point, true},
  754.   {"print", cm_print, true},
  755.   {"printindex", cm_printindex, false},
  756.   {"pxref", cm_pxref, true},
  757.   {"quotation", cm_quotation, false},
  758.   {"r", cm_roman, true},
  759.   {"ref", cm_xref, true},
  760.   {"refill", cm_refill, false},
  761.   {"result", cm_result, true},
  762.   {"samp", cm_samp, true},
  763.   {"sc", cm_sc, true},
  764.   {"section", cm_section, false},
  765.   {"setchapternewpage", cm_setchapternewpage, false},
  766.   {"setfilename", cm_setfilename, false},
  767.   {"settitle", cm_settitle, false},
  768.   {"smallexample", cm_smallexample, false},
  769.   {"sp", cm_sp, false},
  770.   {"strong", cm_strong, true},
  771.   {"subsection", cm_subsection, false},
  772.   {"subsubsection", cm_subsubsection, false},
  773.   {"summarycontents", do_nothing, false},
  774.   {"syncodeindex", cm_synindex, false},
  775.   {"synindex", cm_synindex, false},
  776.   {"t", cm_title, true},
  777.   {"table", cm_table, false},
  778.   {"tex", cm_tex, false},
  779.   {"tindex", cm_tindex, false},
  780.   {"titlepage", cm_titlepage, false},
  781.   {"titlespec", cm_titlespec, false},
  782.   {"unnumbered", cm_unnumbered, false},
  783.   {"unnumberedsec", cm_unnumberedsec, false},
  784.   {"unnumberedsubsec", cm_unnumberedsubsec, false},
  785.   {"unnumberedsubsubsec", cm_unnumberedsubsubsec, false},
  786.   {"var", cm_var, true},
  787.   {"vindex", cm_vindex, false},
  788.   {"w", cm_w, true},
  789.   {"xref", cm_xref, true},
  790.   {"{", insert_self, false},
  791.   {"}", insert_self, false},
  792.  
  793.   /* Now @include does what this was supposed to. */
  794.   {"infoinclude", cm_infoinclude, false},
  795.   {"footnote", cm_footnote, false}, /* self-arg eater */
  796.  
  797.   {(char *) NULL, (FUNCTION *) NULL}, false};
  798.  
  799. /* Non-zero means we are running inside of Emacs. */
  800. int in_emacs = 0;
  801.  
  802. #ifndef MAKEINFO_MAJOR
  803. #define MAKEINFO_MAJOR 1
  804. #endif
  805.  
  806. #ifndef MAKEINFO_MINOR
  807. #define MAKEINFO_MINOR 0
  808. #endif
  809.  
  810. int major_version = MAKEINFO_MAJOR;
  811. int minor_version = MAKEINFO_MINOR;
  812.  
  813. struct option long_options[] =
  814. {
  815.   { "no-validate", 0, &validating, false },    /* formerly -nv */
  816.   { "no-warn", 0, &print_warnings, false },    /* formerly -nw */
  817.   { "no-split", 0, &splitting, false },        /* formerly -ns */
  818.   { "verbose", 0, &verbose_mode, 1 },        /* formerly -verbose */
  819.   { "fill-column", 1, 0, 'f' },            /* formerly -fc */
  820.   { "paragraph-indent", 1, 0, 'p' },        /* formerly -pi */
  821.   { "error-limit", 1, 0, 'e' },            /* formerly -el */
  822.   { "reference-limit", 1, 0, 'r' },        /* formerly -rl */
  823.   { "footnote-style", 1, 0, 's' },        /* formerly -ft */
  824.   { "version", 0, 0, 'V' },
  825.   {NULL, 0, NULL, 0}
  826. };
  827.   
  828. /* **************************************************************** */
  829. /*                                    */
  830. /*            Main ()  Start of code              */
  831. /*                                        */
  832. /* **************************************************************** */
  833.  
  834. /* For each file mentioned in the command line, process it, turning
  835.    texinfo commands into wonderfully formatted output text. */
  836. VOID CDECL
  837. main (argc, argv)
  838.      int argc;
  839.      char **argv;
  840. {
  841.   char *t = (char *) getenv ("EMACS");
  842.   int c;
  843.   int ind;
  844.  
  845.   progname = argv[0];
  846.  
  847.   if (t && strcmp (t, "t") == 0)
  848.     in_emacs++;
  849.  
  850.   /* Parse argument flags from the input line. */
  851.   while ((c = getopt_long (argc, argv, "", long_options, &ind)) != EOF)
  852.     {
  853.       if (c == 0 && long_options[ind].flag == 0)
  854.     c = long_options[ind].val;
  855.       switch (c)
  856.     {
  857.     case 'f':
  858.       /* user specified fill_column? */
  859.       if (sscanf (optarg, "%d", &fill_column) != 1)
  860.         usage ();
  861.       break;
  862.  
  863.     case 'p':
  864.       /* User specified paragraph indent (paragraph_start_index)? */
  865.       if (sscanf (optarg, "%d", ¶graph_start_indent) != 1)
  866.         usage ();
  867.       break;
  868.  
  869.     case 'e':
  870.       /* User specified error level? */
  871.       if (sscanf (optarg, "%d", &max_error_level) != 1)
  872.         usage ();
  873.       break;
  874.  
  875.     case 'r':
  876.       /* User specified reference warning limit? */
  877.       if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
  878.         usage ();
  879.       break;
  880.  
  881.     case 's':
  882.       /* User specified footnote style? */
  883.       set_footnote_style (optarg);
  884.       break;
  885.  
  886.     case 'V':        /* Use requested version info? */
  887.       fprintf (stderr, "Makeinfo verison %d.%d.\n",
  888.            major_version, minor_version);
  889.       exit (0);
  890.       break;
  891.  
  892.     case '?':
  893.       usage ();
  894.     }
  895.     }
  896.  
  897.   if (optind == argc)
  898.     usage ();
  899.  
  900.   /* Remaining arguments are file names of texinfo files.
  901.      Convert them, one by one. */
  902.   while (optind != argc)
  903.     convert (argv[optind++]);
  904.  
  905.   exit (0);
  906. }
  907.  
  908.  
  909. /* **************************************************************** */
  910. /*                                    */
  911. /*            Generic Utilities                */
  912. /*                                    */
  913. /* **************************************************************** */
  914.  
  915. /* Just like malloc, but kills the program in case of fatal error. */
  916. PVOID *
  917. xmalloc (nbytes)
  918.      SIZE_T nbytes;
  919. {
  920.   PVOID *temp = (PVOID *) malloc (nbytes);
  921.   if (temp == (PVOID *) NULL)
  922.     {
  923.       error ("Virtual memory exhausted! Needed %d bytes.", nbytes);
  924.       exit (FATAL);
  925.     }
  926.   return (temp);
  927. }
  928.  
  929. /* Like realloc (), but barfs if there isn't enough memory. */
  930. PVOID *
  931. xrealloc (pointer, nbytes)
  932.      PVOID *pointer;
  933.      SIZE_T nbytes;
  934. {
  935.   pointer = (PVOID *) realloc (pointer, nbytes);
  936.   if (!pointer)
  937.     {
  938.       error ("Virtual memory exhausted in realloc ().");
  939.       abort ();
  940.     }
  941.   return (pointer);
  942. }
  943.  
  944. /* Tell the user how to use this program. */
  945. VOID
  946. usage ()
  947. {
  948.   fprintf (stderr, "Usage: %s [options] texinfo-file...\n\
  949. \n\
  950. This program accepts as input files of texinfo commands and text\n\
  951. and outputs a file suitable for reading with GNU Info.\n\
  952. \n\
  953. The options are:\n\
  954. `+no-validate' to suppress node cross reference validation.\n\
  955. `+no-warn' to suppress warning messages (errors are still output).\n\
  956. `+no-split' to suppress the splitting of large files.\n\
  957. `+verbose' to print information about what is being done.\n\
  958. `+version' to print the version number of Makeinfo.\n\
  959. `+paragraph-indent NUM' to set the paragraph indent to NUM (default %d).\n\
  960. `+fill-column NUM' to set the filling column to NUM (default %d).\n\
  961. `+error-limit NUM' to set the error limit to NUM (default %d).\n\
  962. `+reference-limit NUM' to set the reference warning limit to NUM (default %d).\n\
  963. `+footnote-style STYLE' to set the footnote style to STYLE.  STYLE should\n\
  964.   either be `MN' for `make node', or `BN' for `bottom node'.\n\n",
  965.        progname, paragraph_start_indent,
  966.        fill_column, max_error_level, reference_warning_limit);
  967.   exit (2);
  968. }
  969.  
  970. /* **************************************************************** */
  971. /*                                    */
  972. /*            Manipulating Lists                  */
  973. /*                                        */
  974. /* **************************************************************** */
  975.  
  976. typedef struct generic_list
  977. {
  978.   struct generic_list *next;
  979. }            GENERIC_LIST;
  980.  
  981. /* Reverse the chain of structures in LIST.  Output the new head
  982.    of the chain.  You should always assign the output value of this
  983.    function to something, or you will lose the chain. */
  984. GENERIC_LIST *
  985. reverse_list (list)
  986.      register GENERIC_LIST *list;
  987. {
  988.   register GENERIC_LIST *next;
  989.   register GENERIC_LIST *prev = (GENERIC_LIST *) NULL;
  990.  
  991.   while (list)
  992.     {
  993.       next = list->next;
  994.       list->next = prev;
  995.       prev = list;
  996.       list = next;
  997.     }
  998.   return (prev);
  999. }
  1000.  
  1001.  
  1002. /* **************************************************************** */
  1003. /*                                    */
  1004. /*            Pushing and Popping Files               */
  1005. /*                                    */
  1006. /* **************************************************************** */
  1007.  
  1008. /* Find and load the file named FILENAME.  Return a pointer to
  1009.    the loaded file, or NULL if it can't be loaded. */
  1010. char HUGE *
  1011. find_and_load (filename)
  1012.      char *filename;
  1013. {
  1014. #ifdef MSDOS
  1015.   long bytes_read;
  1016. #endif /* MSDOS */
  1017.   struct stat fileinfo;
  1018.   int file;
  1019.   char HUGE *result = (char HUGE *) NULL;
  1020.  
  1021.   if ((stat (filename, &fileinfo)) != 0)
  1022.     goto error_exit;
  1023.  
  1024.   file = open (filename, O_RDONLY);
  1025.   if (file < 0)
  1026.     goto error_exit;
  1027.  
  1028.   /* Load the file. */
  1029. #ifdef MSDOS
  1030.   result = xhalloc (fileinfo.st_size);
  1031.   bytes_read = hread (file, result, fileinfo.st_size);
  1032.   if (bytes_read <= 0L)
  1033. #else /* not MSDOS */
  1034.   result = xmalloc (fileinfo.st_size);
  1035.   if (read (file, result, fileinfo.st_size) != fileinfo.st_size)
  1036. #endif /* not MSDOS */
  1037.   error_exit:
  1038.     {
  1039.       if (result)
  1040. #ifdef MSDOS
  1041.     hfree (result);
  1042. #else /* not MSDOS */
  1043.     free (result);
  1044. #endif /* not MSDOS */
  1045.       if (file != -1)
  1046.     close (file);
  1047.       return ((char *) NULL);
  1048.     }
  1049.   close (file);
  1050.  
  1051.   /* Set the globals to the new file. */
  1052.   input_text = result;
  1053. #ifdef MSDOS
  1054.   size_of_input_text = bytes_read;
  1055. #else /* not MSDOS */
  1056.   size_of_input_text = fileinfo.st_size;
  1057. #endif /* not MSDOS */
  1058.   input_filename = savestring (filename);
  1059.   node_filename = savestring (filename);
  1060.   input_text_offset = 0;
  1061.   line_number = 1;
  1062.   return (result);
  1063. }
  1064.  
  1065. /* Save the state of the current input file. */
  1066. VOID
  1067. pushfile ()
  1068. {
  1069.   FSTACK *newstack = (FSTACK *) xmalloc (sizeof (FSTACK));
  1070.   newstack->filename = input_filename;
  1071.   newstack->text = input_text;
  1072.   newstack->size = size_of_input_text;
  1073.   newstack->offset = input_text_offset;
  1074.   newstack->line_number = line_number;
  1075.   newstack->next = filestack;
  1076.  
  1077.   filestack = newstack;
  1078.   push_node_filename ();
  1079. }
  1080.  
  1081. /* Make the current file globals be what is on top of the file stack. */
  1082. VOID
  1083. popfile ()
  1084. {
  1085.   extern int executing_string;
  1086.   FSTACK *temp = filestack;
  1087.  
  1088.   if (!filestack)
  1089.     abort ();            /* My fault.  I wonder what I did? */
  1090.  
  1091.   /* Make sure that commands with braces have been satisfied. */
  1092.   if (!executing_string)
  1093.     discard_braces ();
  1094.  
  1095.   /* Get the top of the stack into the globals. */
  1096.   input_filename = filestack->filename;
  1097.   input_text = filestack->text;
  1098.   size_of_input_text = filestack->size;
  1099.   input_text_offset = filestack->offset;
  1100.   line_number = filestack->line_number;
  1101.  
  1102.   /* Pop the stack. */
  1103.   filestack = filestack->next;
  1104.   free (temp);
  1105.   pop_node_filename ();
  1106. }
  1107.  
  1108. /* Flush all open files on the file stack. */
  1109. VOID
  1110. flush_file_stack ()
  1111. {
  1112.   while (filestack)
  1113.     {
  1114.       free (input_filename);
  1115.       free (input_text);
  1116.       popfile ();
  1117.     }
  1118. }
  1119.  
  1120. int node_filename_stack_index = 0;
  1121. int node_filename_stack_size = 0;
  1122. char **node_filename_stack = (char **)NULL;
  1123.  
  1124. VOID
  1125. push_node_filename ()
  1126. {
  1127.   if (node_filename_stack_index + 1 > node_filename_stack_size)
  1128.     {
  1129.       if (!node_filename_stack)
  1130.     node_filename_stack =
  1131.       (char **)xmalloc ((node_filename_stack_size += 10)
  1132.                 * sizeof (char *));
  1133.       else
  1134.     node_filename_stack =
  1135.       (char **)xrealloc (node_filename_stack,
  1136.                  (node_filename_stack_size + 10)
  1137.                  * sizeof (char *));
  1138.     }
  1139.  
  1140.   node_filename_stack[node_filename_stack_index] = node_filename;
  1141.   node_filename_stack_index++;
  1142. }
  1143.  
  1144. VOID
  1145. pop_node_filename ()
  1146. {
  1147.   node_filename = node_filename_stack[--node_filename_stack_index];
  1148. }
  1149.  
  1150. /* Return just the simple part of the filename; i.e. the
  1151.    filename without the path information, or extensions.
  1152.    This conses up a new string. */
  1153. char *
  1154. filename_part (filename)
  1155.      char *filename;
  1156. {
  1157.   register int i = strlen (filename) - 1;
  1158.  
  1159.   while (i && filename[i] != '/')
  1160.     i--;
  1161.   if (filename[i] == '/')
  1162.     i++;
  1163.  
  1164. #ifdef REMOVE_OUTPUT_EXTENSIONS
  1165.   result = savestring (&filename[i]);
  1166.  
  1167.   /* See if there is an extension to remove.  If so, remove it. */
  1168.   if (rindex (result, '.'))
  1169.     *(rindex (result, '.')) = '\0';
  1170.   return (result);
  1171. #else
  1172.   return (savestring (&filename[i]));
  1173. #endif /* REMOVE_OUTPUT_EXTENSIONS */
  1174. }
  1175.  
  1176. /* Return the pathname part of filename.  This can be NULL. */
  1177. char *
  1178. pathname_part (filename)
  1179.      char *filename;
  1180. {
  1181.   char *expand_filename ();
  1182.   char *result = (char *) NULL;
  1183.   register int i;
  1184.  
  1185.   filename = expand_filename (filename, "");
  1186.  
  1187.   i = strlen (filename) - 1;
  1188.  
  1189.   while (i && filename[i] != '/')
  1190.     i--;
  1191.   if (filename[i] == '/')
  1192.     i++;
  1193.  
  1194.   if (i)
  1195.     {
  1196.       result = xmalloc (1 + i);
  1197.       strncpy (result, filename, i);
  1198.       result[i] = '\0';
  1199.     }
  1200.   free (filename);
  1201.   return (result);
  1202. }
  1203.  
  1204. /* Return the expansion of FILENAME. */
  1205. char *
  1206. expand_filename (filename, input_name)
  1207.      char *filename, *input_name;
  1208. {
  1209.   char *full_pathname ();
  1210.   filename = full_pathname (filename);
  1211.  
  1212.   if (filename[0] == '.')
  1213.     return (filename);
  1214.  
  1215.   if (filename[0] != '/' && input_name[0] == '/')
  1216.     {
  1217.       /* Make it so that relative names work. */
  1218.       char *result = xmalloc (1 + strlen (input_name)
  1219.                   + strlen (filename));
  1220.       int i = strlen (input_name) - 1;
  1221.  
  1222.       strcpy (result, input_name);
  1223.       while (result[i] != '/' && i)
  1224.     i--;
  1225.       if (result[i] == '/')
  1226.     i++;
  1227.       strcpy (&result[i], filename);
  1228.       free (filename);
  1229.       return (result);
  1230.     }
  1231.   return (filename);
  1232. }
  1233.  
  1234. /* Return the full path to FILENAME. */
  1235. char *
  1236. full_pathname (filename)
  1237.      char *filename;
  1238. {
  1239.   int initial_character;
  1240.  
  1241.   if (filename && (initial_character = *filename))
  1242.     {
  1243.       if (initial_character == '/')
  1244.     return (savestring (filename));
  1245.       if (initial_character != '~')
  1246.     {
  1247.       return (savestring (filename));
  1248.     }
  1249.       else
  1250.     {
  1251.       if (filename[1] == '/')
  1252.         {
  1253.           /* Return the concatenation of HOME and the rest of the string. */
  1254.           char *temp_home = (char *) getenv ("HOME");
  1255.           char *temp_name = xmalloc (strlen (&filename[2])
  1256.                      + 1
  1257.                      + temp_home ? strlen (temp_home)
  1258.                      : 0);
  1259.           if (temp_home)
  1260.         strcpy (temp_name, temp_home);
  1261.           strcat (temp_name, &filename[2]);
  1262.           return (temp_name);
  1263.         }
  1264.       else
  1265.         {
  1266. #ifdef MSDOS
  1267.           return (savestring (filename));
  1268. #else /* not MSDOS */
  1269.           struct passwd *user_entry;
  1270.           int i, c;
  1271.           char *username = xmalloc (257);
  1272.           char *temp_name;
  1273.  
  1274.           for (i = 1; c = filename[i]; i++)
  1275.         {
  1276.           if (c == '/')
  1277.             break;
  1278.           else
  1279.             username[i - 1] = c;
  1280.         }
  1281.           if (c)
  1282.         username[i - 1] = '\0';
  1283.  
  1284.           user_entry = getpwnam (username);
  1285.  
  1286.           if (!user_entry)
  1287.         return (savestring (filename));
  1288.  
  1289.           temp_name = xmalloc (1 + strlen (user_entry->pw_dir)
  1290.                    + strlen (&filename[i]));
  1291.           strcpy (temp_name, user_entry->pw_dir);
  1292.           strcat (temp_name, &filename[i]);
  1293.           return (temp_name);
  1294. #endif /* not MSDOS */
  1295.         }
  1296.     }
  1297.     }
  1298.   else
  1299.     {
  1300.       return (savestring (filename));
  1301.     }
  1302. }
  1303.  
  1304. /* **************************************************************** */
  1305. /*                                    */
  1306. /*            Error Handling                    */
  1307. /*                                    */
  1308. /* **************************************************************** */
  1309.  
  1310. /* Number of errors encountered. */
  1311. int errors_printed = 0;
  1312.  
  1313. /* Print the last error gotten from the file system. */
  1314. fs_error (filename)
  1315.      char *filename;
  1316. {
  1317.   perror (filename);
  1318.   return ((int) false);
  1319. }
  1320.  
  1321. /* Print an error message, and return false. */
  1322. #ifdef MSDOS
  1323.  
  1324. int CDECL
  1325. error (char *format, ...)
  1326. {
  1327.   va_list arg_ptr;
  1328.   va_start (arg_ptr, format);
  1329.  
  1330.   remember_error ();
  1331.   vfprintf (stderr, format, arg_ptr);
  1332.   fprintf (stderr, "\n");
  1333.   return ((int) false);
  1334. }
  1335.  
  1336. #else /* not MSDOS */
  1337.  
  1338. error (format, arg1, arg2, arg3, arg4, arg5)
  1339.      char *format;
  1340. {
  1341.   remember_error ();
  1342.   fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
  1343.   fprintf (stderr, "\n");
  1344.   return ((int) false);
  1345. }
  1346.  
  1347. #endif /* not MSDOS */
  1348.  
  1349.  
  1350. /* Just like error (), but print the line number as well. */
  1351. #ifdef MSDOS
  1352.  
  1353. int CDECL
  1354. line_error (char *format, ...)
  1355. {
  1356.   va_list arg_ptr;
  1357.   va_start (arg_ptr, format);
  1358.  
  1359.   remember_error ();
  1360.   fprintf (stderr, "%s:%d: ", input_filename, line_number);
  1361.   vfprintf (stderr, format, arg_ptr);
  1362.   fprintf (stderr, ".\n");
  1363.   return ((int) false);
  1364. }
  1365.  
  1366. #else /* not MSDOS */
  1367.  
  1368. line_error (format, arg1, arg2, arg3, arg4, arg5)
  1369.      char *format;
  1370. {
  1371.   remember_error ();
  1372.   fprintf (stderr, "%s:%d: ", input_filename, line_number);
  1373.   fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
  1374.   fprintf (stderr, ".\n");
  1375.   return ((int) false);
  1376. }
  1377.  
  1378. #endif /* not MSDOS */
  1379.  
  1380.  
  1381.  
  1382. #ifdef MSDOS
  1383.  
  1384. int CDECL
  1385. warning (char *format, ...)
  1386. {
  1387.   if (print_warnings)
  1388.     {
  1389.       va_list arg_ptr;
  1390.       va_start (arg_ptr, format);
  1391.  
  1392.       fprintf (stderr, "%s:%d: Warning: ", input_filename, line_number);
  1393.       vfprintf (stderr, format, arg_ptr);
  1394.       fprintf (stderr, ".\n");
  1395.     }
  1396.   return ((int) false);
  1397. }
  1398.  
  1399. #else /* not MSDOS */
  1400.  
  1401. warning (format, arg1, arg2, arg3, arg4, arg5)
  1402.      char *format;
  1403. {
  1404.   if (print_warnings)
  1405.     {
  1406.       fprintf (stderr, "%s:%d: Warning: ", input_filename, line_number);
  1407.       fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
  1408.       fprintf (stderr, ".\n");
  1409.     }
  1410.   return ((int) false);
  1411. }
  1412.  
  1413. #endif /* not MSDOS */
  1414.  
  1415.  
  1416. /* Remember that an error has been printed.  If this is the first
  1417.    error printed, then tell them which program is printing them.
  1418.    If more than max_error_level have been printed, then exit the
  1419.    program. */
  1420. VOID
  1421. remember_error ()
  1422. {
  1423.   errors_printed++;
  1424.   if (max_error_level && (errors_printed > max_error_level))
  1425.     {
  1426.       fprintf (stderr, "Too many errors!  Gave up.");
  1427.       flush_file_stack ();
  1428.       cm_bye ();
  1429.     }
  1430. }
  1431.  
  1432.  
  1433. /* **************************************************************** */
  1434. /*                                    */
  1435. /*            Hacking Tokens and Strings            */
  1436. /*                                    */
  1437. /* **************************************************************** */
  1438.  
  1439. /* Return the next token as a string pointer.  We cons the
  1440.    string. */
  1441. char *
  1442. read_token ()
  1443. {
  1444.   int i, character;
  1445.   char *result;
  1446.  
  1447.   /* Hack special case.  If the first character to be read is
  1448.      self-delimiting, then that is the command itself. */
  1449.  
  1450.   character = curchar ();
  1451.   if (self_delimiting (character))
  1452.     {
  1453.       input_text_offset++;
  1454.       result = savestring (" ");
  1455.       *result = character;
  1456.       return (result);
  1457.     }
  1458.  
  1459.   for (i = 0; ((input_text_offset != size_of_input_text)
  1460.            && (character = curchar ())
  1461.            && command_char (character));
  1462.        i++, input_text_offset++);
  1463.   result = xmalloc (i + 1);
  1464.   strncpy (result, &input_text[input_text_offset - i], i);
  1465.   result[i] = '\0';
  1466.   return (result);
  1467. }
  1468.  
  1469. /* Return TRUE if CHARACTER is self-delimiting. */
  1470. boolean
  1471. self_delimiting (character)
  1472.      int character;
  1473. {
  1474.   return (member (character, "{}:.@*'`,!?; \n"));
  1475. }
  1476.  
  1477. /* Clear whitespace from the front and end of string. */
  1478. VOID
  1479. canon_white (string)
  1480.      char *string;
  1481. {
  1482.   int len = strlen (string);
  1483.   int x;
  1484.  
  1485.   if (!len)
  1486.     return;
  1487.  
  1488.   for (x = 0; x < len; x++)
  1489.     {
  1490.       if (!whitespace (string[x]))
  1491.     {
  1492.       strcpy (string, string + x);
  1493.       break;
  1494.     }
  1495.     }
  1496.   len = strlen (string);
  1497.   if (len)
  1498.     len--;
  1499.   while (len > -1 && cr_or_whitespace (string[len]))
  1500.     len--;
  1501.   string[len + 1] = '\0';
  1502. }
  1503.  
  1504. /* Bash STRING, replacing all whitespace with just one space. */
  1505. VOID
  1506. fix_whitespace (string)
  1507.      char *string;
  1508. {
  1509.   char *temp = xmalloc (strlen (string) + 1);
  1510.   int string_index = 0;
  1511.   int temp_index = 0;
  1512.   int c;
  1513.  
  1514.   canon_white (string);
  1515.  
  1516.   while (string[string_index])
  1517.     {
  1518.       c = temp[temp_index++] = string[string_index++];
  1519.  
  1520.       if (c == ' ' || c == '\n' || c == '\t')
  1521.     {
  1522.       temp[temp_index - 1] = ' ';
  1523.       while ((c = string[string_index]) && (c == ' ' ||
  1524.                         c == '\t' ||
  1525.                         c == '\n'))
  1526.         string_index++;
  1527.     }
  1528.     }
  1529.   temp[temp_index] = '\0';
  1530.   strcpy (string, temp);
  1531.   free (temp);
  1532. }
  1533.  
  1534. /* Discard text until the desired string is found.  The string is
  1535.    included in the discarded text. */
  1536. VOID
  1537. discard_until (string)
  1538.      char *string;
  1539. {
  1540.   LONG temp = search_forward (string, input_text_offset);
  1541.  
  1542.   LONG tt = (temp < 0) ? size_of_input_text : temp + strlen (string);
  1543.   LONG from = input_text_offset;
  1544.  
  1545.   /* Find out what line we are on. */
  1546.   while (from != tt)
  1547.     if (input_text[from++] == '\n')
  1548.       line_number++;
  1549.  
  1550.   if (temp < 0)
  1551.     {
  1552.       input_text_offset = size_of_input_text - strlen (string);
  1553.  
  1554.       if (strcmp (string, "\n") != 0)
  1555.     {
  1556.       line_error ("Expected `%s'", string);
  1557.       return;
  1558.     }
  1559.     }
  1560.   else
  1561.     input_text_offset = temp;
  1562.  
  1563.   input_text_offset += strlen (string);
  1564. }
  1565.  
  1566. /* Read characters from the file until we are at MATCH.
  1567.    Place the characters read into STRING.
  1568.    On exit input_text_offset is after the match string.
  1569.    Return the length of STRING. */
  1570. VOID
  1571. get_until (match, string)
  1572.      char *match, **string;
  1573. {
  1574.   SIZE_T len;
  1575.   LONG current_point = input_text_offset;
  1576.   LONG x = current_point;
  1577.   LONG new_point = search_forward (match, input_text_offset);
  1578.  
  1579.   if (new_point < 0)
  1580.     new_point = size_of_input_text;
  1581. #ifdef MSDOS
  1582.   assert (new_point - current_point < (1L<<16));
  1583.   len = (size_t) (new_point - current_point);
  1584. #else /* not MSDOS */
  1585.   len = new_point - current_point;
  1586. #endif /* not MSDOS */
  1587.  
  1588.   /* Keep track of which line number we are at. */
  1589.   while (x != new_point)
  1590.     if (input_text[x++] == '\n')
  1591.       line_number++;
  1592.  
  1593.   *string = xmalloc (len + 1);
  1594.  
  1595.   strncpy (*string, &input_text[current_point], len);
  1596.   (*string)[len] = '\0';
  1597.  
  1598.   /* Now leave input_text_offset in a consistent state. */
  1599.   input_text_offset = new_point + (strlen (match) - 1);
  1600.   if (input_text_offset > size_of_input_text)
  1601.     input_text_offset = size_of_input_text;
  1602. }
  1603.  
  1604. /* Read characters from the file until we are at MATCH or end of line.
  1605.    Place the characters read into STRING.  */
  1606. VOID
  1607. get_until_in_line (match, string)
  1608.      char *match, **string;
  1609. {
  1610.   LONG real_bottom = size_of_input_text;
  1611.   LONG temp = search_forward ("\n", input_text_offset);
  1612.   if (temp < 0)
  1613.     temp = size_of_input_text;
  1614.   size_of_input_text = temp;
  1615.   get_until (match, string);
  1616.   size_of_input_text = real_bottom;
  1617. }
  1618.  
  1619. VOID
  1620. get_rest_of_line (string)
  1621.      char **string;
  1622. {
  1623.   get_until ("\n", string);
  1624.   canon_white (*string);
  1625.   if (curchar () == '\n')
  1626.     {                /* as opposed to the end of the file... */
  1627.       line_number++;
  1628.       input_text_offset++;
  1629.     }
  1630. }
  1631.  
  1632. /* Read characters from the file until we are at MATCH or closing brace.
  1633.    Place the characters read into STRING.  */
  1634. VOID
  1635. get_until_in_braces (match, string)
  1636.      char *match, **string;
  1637. {
  1638.   LONG i;
  1639.   int brace = 0;
  1640.   int match_len = strlen (match);
  1641.   char *temp;
  1642.  
  1643.   for (i = input_text_offset; i < size_of_input_text; i++)
  1644.     {
  1645.       if (input_text[i] == '{')
  1646.     brace++;
  1647.       if (input_text[i] == '}')
  1648.     brace--;
  1649.       if (input_text[i] == '\n')
  1650.     line_number++;
  1651.       if (brace < 0 ||
  1652.       (brace == 0 && strncmp (input_text + i, match, match_len) == 0))
  1653.     break;
  1654.     }
  1655.  
  1656. #ifdef MSDOS
  1657.   assert (i - input_text_offset < (1L<<16));
  1658.   match_len = (size_t) (i - input_text_offset);
  1659. #else /* not MSDOS */
  1660.   match_len = i - input_text_offset;
  1661. #endif /* not MSDOS */
  1662.   temp = xmalloc (2 + match_len);
  1663.   strncpy (temp, input_text + input_text_offset, match_len);
  1664.   temp[match_len] = '\0';
  1665.   input_text_offset = i;
  1666.   *string = temp;
  1667. }
  1668.  
  1669. /*===(cut here)===*/
  1670.  
  1671. /* Include the rest:  */
  1672.  
  1673. #include "makeinfo.d"
  1674. #include "makeinfo.e"
  1675.  
  1676.  
  1677. /* 
  1678.  * Local Variables:
  1679.  * mode:C
  1680.  * ChangeLog:ChangeLog
  1681.  * End:
  1682.  */
  1683.