Google
 

Trailing-Edge - PDP-10 Archives - mit_emacs_170_teco_1220 - emacs/info.emacs
There are no other files named info.emacs in the archive.
!* -*-TECO-*-!

!~Filename~:! !Tree-structured document file perusal program INFO.!
INFO
!& Info Enter:! !Info Enter:! !C Peruse documentation of system programs.
With null suffix argument, as in MM Info,
enters the hierarchy at the highest node,
or returns to the last thing you were looking at with Info.
A non-null suffix argument should be composed of words separated by
spaces, which are used as a "pathname" of successive menu items
to look up.  A negative numeric arg means to interpret the
suffix arg as a node name (a la the G command).!

    :I*[3			    !* Read arg before pushing qregs so ^]1 in arg wins.!
    1F[BOTHCASE -F[FNAM SY 1F[^R MORE
    [Previous_Buffer
    QBuffer_Name[1		    !* Push the selected buffer!
    FN M(M.M Select_Buffer) 1  [1
    M(M.M Select_Buffer)*INFO*    !* and select a special one for INFO.!
    [..J			    !* Push ..J now;  Select Node sets it.!
    FS RGETTY"E 1M.V INFO_Inhibit_Typeout'	    !* We may be about to visit several nodes!
		 !* sequentially, and it would be a loss to type the 1st 4 lines of each.!
    QBuffer_Filenames"E	    !* If INFO buffer was just created (no node in it yet),!
      500FS Q VEC M.V INFO_Nodes  !* create the stack of visited nodes!
      :I*(DIR) M(M.M &_Info_Select_Node)' !* and start by visiting the directory.!
    FQ3"G			    !* If our string arg is non-null,!
      "LQ3M(M.M&_Info_Select_Node)'"#    !* It is either a node to Goto!
      F[B BIND G3 32I J	    !* or it is a list of menu items to trace.!
      < :S_;R IM2 S_R @I//>   !* Make a series of M2arg's, one for each arg!
      1:< M(HFX*( M.M&_Info_Trace_MenuU2
	      F]B BIND
	      :I*(DIR) M(M.M&_Info_Select_Node)
	      ))>F"L @:FG'''	    !* Then run it, down from top.!
    FS RGETTY"E 0UINFO_Inhibit_Typeout
        4L-4T
	FT 
	   If_this_is_your_first_time_using_INFO,_type_H.
	   That_will_start_you_on_a_course_in_using_INFO.
	   Type_"?"_for_a_brief_refresher.
	 !''! '
    Q:Info_Nodes(0)U3
    :I..J INFO_documentation_reader__Node_3__    !* Put node's name in MORE line.!
    FS ^R MODE"N :M(M.M&_Info_Loop)'
 !* INFO expects to be inside a ^R.  If that isn't so, we must call
    a ^R, after arranging for the ^R to call Info Loop.!
    FS ^R ENTER[1
    :I* Q1 F[^R ENTER
	M(M.M&_Info_Loop)
	FS ^R EXIT
       F[^R ENTER
    
    
!& Info Loop:! !C INFO's command-reading loop.!

!* We read a character, then call the macro "# INFO <that character>".
 For control characters such as ^X, we use # INFO ^X", with an uparrow.!

    [1 [2
    QEMACS_Version-140"L -F[NOQUIT'
    F<!Info-catch!
     @:<
      @V
      @:FIU1 FI:FCU2 @FT 2   !* Read and echo character, converted to upper case.!
      Q2-"E  !<!>'	    !* ^R means call ^R recursively.!
      Q2-40."G :I1#_Info_2'
	"# Q2+100.U1 :I1 #_Info_^1'
      1,M.M 1U1		    !* Find the macro for this command.!
      Q1"E :I*Illegal_Command:_2 @:FG !<!>'  !* Complain if can't find it.!
      M1			    !* If it exists, call it.!
	!* Command may assume that Q2 holds the character.!
      >U1
     QEMACS_Version-140"L
       @FE QIT-Q1"N :Q1'@FG'	    !* Get here on error in loop: print message and go on.!
     >
    
!# Info ?:! !& Print documentation on INFO.!
    FS RGETTY"E
       FT On_printing_terminals,_Space_prints_ten_more_lines
	  and_T_prints_all_the_rest_of_the_node_you_are_in.
	  After_an_F_or_M,_?_will_print_a_brief_list_of_the
	  footnotes_or_menu_items_you_can_choose_from.
	  After_that,_you_are_still_expected_to_type_one,
	  or_Rubout_to_cancel.
	  
	  '
    M.M ~Doc~_&_Info_Description[1
    :FT1 
!& Info Description:! !INFO command brief description:

?	show this brief description.
H	visit a tutorial to teach you how to use Info.
Space	show next screenful of this node.
Backspace
	show previous screenful of this node.
B	show Beginning of this node.
N	go to Next node in a sequence.
P	go to Previous node in a sequence.
U	go Up to this node's father.
M	display this node's Menu and go to something listed
	 therein.  If you see "* item: node", type M item <cr>.
1 - 5	go to 1st (etc) subnode in the menu.
F	go to a Footnote.  If you see "*Note name: node",
	 you type F name <cr>.  Use L command to come back.
D	go to Directory node (the top node, from which all
	 other nodes can be reached with one or more M's).
Q, ^]	exit from Info.
^Z,^C	return to superior job (HACTRN, usually).
L	go back to Last node visited before this one.
^L	redisplay the screen.
X	eXecute EMACS extended command.
K	show all lines containing a specified Keyword.  You type
	 K keyword <cr> and all those lines are printed.
	 Then, use the S command specifying the desired context.
S	Search whole file for string.  Type S string <cr>.
G	Go to node.  Type G nodename<cr>.  Filename may be included.
	 * as nodename means "the whole file".
^R	Edit this node with EMACS.
O	Output (append) this node to file.  Type O filename <cr>.
!
    !* This macro exists just to carry documentation, which ? prints.!
    !Make the body non-empty!
!# Info D:! !S Visit the Info directory node.
This node has all files as subnodes.!
    :I*(DIR) :M(M.M&_Info_Select_Node)
!# Info H:! !S Visit the course in using Info.!
    FS RGETTY"E :I*(INFO)Help-Printing :M(M.M &_Info_Select_Node)'
    FS HEIGHT-24"L :I*(INFO)Help-Small-Screen' !
!     "# :I*(INFO)Help' :M(M.M &_Info_Select_Node)
!& Info Select Node:! !S Selects a node specified by name.
The node name as a string should be a prefix argument.
A node name may contain a filename, as in (INFO;DIR >)TOP.
If there is no filename, the current file is the default.
If there is no node name, the default is TOP.!

    [2 -1[3 [4		    !* Get node name.!
    .[P				    !* Remember old point, to save for later L command.!
    FN
    FQ2"E  O No File'
    <%3:G2-32:@;>		    !* Remove leading spaces from arg.!
    Q3,FQ2:G2U2
    0:G2-("N  O No File'
!*** If the node name specifies a file, yank it.!
	F[B BIND
	  G2 J			    !* First, put node name in buffer to extract filename.!
	  :S)"E :I*Bad_Node_Name:_2 FS ERR'
	  1,.-1FX3		    !* Q3 has filename.!
	  -DD HFX2		    !* Q2 has node name within file!
	F]B BIND
	F[D FILE
	ET DSK:INFO;DIR_>
	FS OSTECO"N ET_INFO     !* On Twenex, default extension is INFO.!
	    1F[ FNAM SY'
	ET3			    !* Merge defaults into specified filename.!
	FS D FILE U3		    !* Get merged names as string.!
	F=(QBuffer_FilenamesF"E :I*')3"N	    !* Is it the same file as looking at now?!
	  ER EC		    !* Open file just so get error if non-existent.!
	  @:I..N| Q:Info_Nodes(0)M(M.M&_INFO_Select_Node) QPJ|
				    !* If we don't find the node, switch !
				    !* back to previous file and reselect node.!
	  1,M(M.M Visit_File)3
	  :I* *M(M.M&_INFO_Set_Modeline)
	  0M.VINFO_Tags_Pointer    !* First assume info file has no tags table,!
	  1F[BOTHCASE
	  ZJ -10:FB End_Tag_Table:"L	    !* then see if that's true.!
	    -S
	    tag_table: l	    !* If not, remember addr (relative to Z) of tag table start!
	    .-Z UINFO_Tags_Pointer'
	  J
	  '
 !No File!
    .[1 0F[VB 0F[VZ  FN Q1J	    !* Save current point and bounds in case node not found!
    FS QP PTRU3
    FQ2"E :I2 Top'		    !* (default is Top).!
    F=2 *"E O Win'		    !* Node name of "*" means whole file.!
    J
    QINFO_Tags_PointerF"N+ZJ	    !* If this info file has a tag table, search it.  Go to it!
      :SNode:_2"L		    !* Find entry in it for desired node.!
         \J :1000R"E J''	    !* Go to that node's approx. location (a little before).!
      "# ZJ''			    !* Not in tag table => make next search fail fast.!
!* Note that we don't win if the node moves very far and you don't regenerate the tag table.!
    < :S"E F~2Top"EJ O Win'    !* If looking for Top, settle for file!
            :I*No_Such_Node:_2 FS ERR'
	2:FB Node:"E !<!>'
	@F_	R
	FQ2F~2"N !<!>'
	FQ2+1AF,		    !* STop when we reach a node with desired name.!
    0L .FS VB			    !* Set B at line after the ^_ that starts this node.!
    :S
"E ZJ' "# R'			    !* Find end of node (next CRLF^_ or EOF)!
    Z-.FS VZ			    !* and put Z there.!
 !Win!
	!* We found it;  prevent restoration of old state.!
    FS QP PTR-Q3"N @FE DSI FS ERR'	    !* Before explicit popping, make sure pdl not screwed!
    ]..N -2FS QP PTR		    !* discard VB and VZ, not Q1 though, so it is restored.!
    :I..N			    !* Don't switch files back.!
    Q2m(m.m&_INFO_Set_Modeline)u2
    QInfo_Nodes[..O		    !* Push this node on ring of recent nodes:  ..!
      Q:..O(0)"E :I:..O(0)'	    !* But don't push one node twice in a row.!
      F~:..O(0)2"N
        ZJ-10D J10,0I		    !* Push everything down 2 words,!
        Q2U:..O(0)		    !* Make an entry for this node; also save old point.!
        QPU:..O(1)'
      ]..O
    J
    FS RGETTY"E
       0FO..Q INFO_Inhibit_Typeout"E
         :FT
	 4L-4T''		    !* On printing tty, type header line and 1st text line.!
    
!& INFO Set Modeline:! !S Set Modeline to say what node we are in.
Takes name of node as postcomma argument.
Gets name of file from Buffer Filenames.
Returns the full node name.!

    [2
    F[B BIND GBuffer_Filenames
    j 11f~INFO:<INFO>"e 5c6d'
    zj -7F~.INFO.0"E -7D'
    ji( zj i) g2
    HX2 F]B BIND
    :I..J INFO_documentation_reader__Node_2__    !* Put node's name in MORE line.!
    q2
!& Info Select Location:! !S Selects a node specified by location.
The desired value of point should be a numeric arg.
The node containing that point is selected and point is put there.!

    [4 [3 [2 .[P
    .[1 0F[VB 0F[VZ  FN Q1J	    !* Save current point and bounds in case node not found!
    Q4J -S			    !* Find the start of the node containing that point.!
    2:FB Node:			    !* Find the name of that node.!
    Z-.<1AF_	:;C>
  .,(FB.) X2 !* Get the name into Q2.!
    0L .FS VB			    !* Set B at line after the ^_ that we starts this node.!
    :S
"E ZJ' "# R'	    !* Find end of node (next ^L or ^_ or EOF)!
    Z-.FS VZ			    !* and put Z there.!
    ]..N -2FS QP PTR
    Q2m(m.m&_INFO_Set_Modeline)
    QInfo_Nodes[..O		    !* Push this node on ring of recent nodes:  ..!
      ZJ-10D J10,0I		    !* Push everything down 2 words,!
      Q2U:..O(0)		    !* Make an entry for this node; also save old point.!
      QPU:..O(1)
      ]..O
    Q4J
    FS RGETTY"E -2T2T'		    !* On printing TTY, print some context.!
    
!& Info Select Property:! !S Trace a specific property (eg, Next) from this node.
The property name, as a string, is given as a prefix argument.
For example, :I*FatherM(M.M &_Info_Select_Property) will
select the current node's father.!

    [2 .[1 J
    :2FB2:"E		    !* Find this node's Father, Next or Previous spec.!
        F~2Up"E :M(M.M&_Info_Last)'
	Q1J :I*This_Node_has_no_2 FS ERR'
    @F_	R		    !* Skip all padding after the property name.!
(Q1:@F,	 !* Put name of father node in Q1.  Restore old Point.!
    Q1 :M(M.M&_Info_Select_Node)    !* Try selecting that node.  Since Point was restored,!
				    !* if that node can't be found nothing is changed.!
!# Info U:! !S Go Up - select the current node's father.!
    :I*Up :M(M.M&_Info_Select_Property)
!# Info N:! !S Select the current node's Next.!
    :I*Next :M(M.M&_Info_Select_Property)
!# Info P:! !S Select the current node's Previous.!
    :I*Previous :M(M.M&_Info_Select_Property)
!# Info T:! !& Info Type Node:! !S Type the current node.
The lines that were typed when the node was selected are not typed.!
    -1F[NO QUIT -1F[ ^H Print
    1:< :FT <.-Z; L-T> FS LISTEN>"L @FG'  "# J' 
!# Info G:! !S Selects a node (reading name from TTY).!
    [1
    [..J :I..J INFO,_awaiting_Node_name FR
    1,M(M.M &_Read_Line)Go_to_Node_ U1 ]..J
    Q1"E '
    Q1 :M(M.M &_Info_Select_Node)
!# Info L:! !& Info Last:! !S Go back to Last node selected.!

    [0 [1 [2 [3
    qInfo_Nodes[..o q:..o(0)u0 q:..o(1)u1 q:..o(2)u2 q:..o(3)u3
    q2*q1"e ]..o :I*No_Node_visited_before_this_one FS ERR'
    j20d zj 20,0i
      q0,z-20 fs word		    !* Q0 is current node.  Put at end.!
      q1,z-15 fs word		    !* Q1 is old point, in previous node.!
      q2,z-10 fs word		    !* Q2 is previous node name.!
      q3,z-5  fs word		    !* Q3 is old point, when previous node was selected.!
      ]..o
    q2 m(m.m &_Info_Select_Node)   !* Reselect previous node,!
    q1j				    !* jump to previous point.!
    q3u:Info_Nodes(1)		    !* store back this old node's previous point.!
    
!# Info B:! !# Info .:! !S Move cursor to Beginning of this node.!
    J
!# Info 1:! !# Info 2:! !# Info 3:! !# Info 4:! !# Info 5:! !S Move via N'th Menu item.!

    [2 J:S
	 *_Menu:"E		    !* First find this node's menu.!
	      :I*This_Node_has_no_Menu_(no_subnodes) FS ERR'
    Q2-0:S
*"E !"! :I*This_Menu_doesn't_have_2_items FS ERR'
    S:
    1A-:"E .-1(0L 2C .,)X2'	    !* If item is FOO::, then FOO is node name.!
      "# Z-.<1AF_	:; C>	    !* Else it is FOO:NODE.  Skip all padding after the topic name.!
R.)X2' !.,(S,	hat comes the name of the node it points to.!
    Q2 :M(M.M &_Info_Select_Node)  !* Go to that node.!
!# Info M:! !& Info Offer Menu:! !S Display this node's menu and move through it.
We read from the TTY the name of a menu item, look it up
in the menu, and go to the corresponding node named there.!

    [1 [2 [3 .[4
    J:S
*_Menu:"E			    !* First find this node's menu.!
      :I*This_Node_has_no_Menu_(no_subnodes) FS ERR'
    0L .U1 Q4J			    !* Q1 has addr of the "*" in "* Menu"!
    M.M&_INFO_Brief_MenuF[HELPMAC
    [..J :I..J INFO,_awaiting_Menu_item
      FS WINDOW+B-Q1"L		    !* Unless we are already past the start of the menu,!
        Q1J 0F[% CENTER 0@V F]% CENTER' !* make sure that the start appears on the screen.!
      FS RGETTY"E Q1J'		    !* On printing tty, go to menu start so space works.!
      0U3
      < @V
        0:"E :I*C FS ECHO DIS
	       FS RGETTY"N @FTM'
	       @FT enu_item:_'
	!FOO!
	:FIU2			    !* right now, space and bs move up and down a screen.!
	Q2-32"E FIW FS RGETTY"E    !* On printing TTY, space prints next entry in menu,!
		:S
		 *_"L :0L .U2 L :S
		       *_"L :0L Q2,.T'
		       1U3	    !* Requiring us to type out "Menu Item' again!
		       Q2J L OFOO''	    !* leaving Point before it.!
		"# @M(M.M ^R_Next_Screen)''
	"# Q2-10."E FIW @M(M.M ^R_Previous_Screen)'
	   "# Q2-
"E FIW M(M.M #_Info_^L)'
	      "# 0;'''>		    !* Any other character starts name of menu alternative.!
      Q3+2,M(M.M&_Read_Line)Menu_item:_U2	    !* Read its name.!
    ]..J
    FQ2-1,FQ2:G2U3 F=3:"E 0,FQ2-1:G2U2'    !* Flush any trailing colon from arg.!
    FQ2-1"L '
    Q1J :S
	*_2:"E		    !* Look for exact match of menu item.!
	  :S
	  *_2"E		    !* Else look for abbreviation.!
	        :I*No_item_2_in_menu FS ERR''
    0LS:
    Z-.<1AF_	:; C>	    !* Skip all padding after the topic name.!
    1A-:"E R.(0L2C .,)X2'	    !* If topic followed by "::", node name = topic name!
R.)X"# .,(S,	that comes the name of the node it points to.!
    Q2 :M(M.M &_Info_Select_Node)  !* Go to that node.!
!& Info Brief Menu:! !S List the names of all items in this node's menu.!

    [4 .[1  FN Q1J
    [2 J:S
	 *_Menu:"E		    !* First find this node's menu.!
	      :I*This_Node_has_no_Menu_(no_subnodes) FS ERR'
    FT Type_the_name_of_an_item_in_the_menu.__The_alternatives_are:
       
    -1[3
    < :S
*_;				    !* Find next item.!
      .U4 S:
      %3"N FT,			    !* Put commas between items (not before first, though).!
           FS TYO HPOS+8/8*8+.-Q4-(FS WIDTH)"G    !* If next item won't fit, CRLF,!
	       FT
'
	   "# FT	''	    !* else tab.!
      Q4,.-1T			    !* Print the next item.!
      >
    FT
    
    FS RGETTY"N FT Type_a_space_to_restore_the_screen.
		     Q1J 0@V'
    "# FT
Menu_Item:_'
    
!# Info F:! !& Info Trace Footnote:! !S Visit a footnote.  Reads note name from TTY.
A footnote looks like "*Note <name>: <node>."!

    [2 [3 F[S STRING
    .( J :S*Note"E
      )J :I*This_node_has_no_footnotes FS ERR'
      )J
      M.M &_Info_List_FootnotesF[HELPMAC
    [..J :I..J INFO,_awaiting_footnote_name__ FS RGETTY"N FR'
    3,M(M.M&_Read_Line)Footnote:_U2	    !* Read footnote name.!
    ]..J
    FQ2-1"L '			    !* Arg empty => was all rubbed out, give up.!
    FQ2-1:G2-:"E 0,FQ2-1:G2U2'   !* Flush any trailing colon from arg.!
    FQ2-1"L '			    !* Arg empty => just a colon, flushed: Quit.!
    J < :S*note"E
	  :I*No_footnote_named_2 FS ERR'
	 @F
R
	 FQ2F~2@;>		    !* Try to find footnote with specified name.!
    FKC S:
    @F
	R	    !* Skip all padding after topic name, reaching node name.!
    .,(1a-("e s)'		    !* If node name starts with (, it can't end before the ).!
	R.)@:F,. !* Find end of node name.!
    Q2 :M(M.M &_Info_Select_Node)  !* Go to that node.!
!& Info List Footnotes:! !S List names of this node's footnotes.!
    .[1  fn q1j
    -1[2 j
    < :S *Note;
      %2"G FT,'
        "# FT Type_one_of:_'
      .,(S:R.)T >
      FT			    !* CR at end of choices.!

    fs rgetty"e ft
Footnote:_'
    q1j @V 
!& Info Trace Menu:! !S Follow a Menu item - takes item as string arg.!
    [2 :I2
    J:S
*_Menu:"E O Lose'
    :S
*_2"E O Lose'
    0LS:
    1a-:"e			    !* FOO:: means that FOO is node name as well as menu item!
      r .(0l 2c .,)x2'		    !* so get the FOO into Q2.  Otherwise,!
    "# Z-.<1AF_	:; C>	    !* Skip all padding after the topic name.!
R.)X2'.,(S,	 that comes the name of the node it points to.!
    Q2 :M(M.M &_Info_Select_Node)  !* Go to that node.!

 !LOSE!
    :I*Can't_find_Menu_item_2 FS ERR
!# Info K:! !S Search for occurrences of keyword in whole file.!
    1,M(M.M &_Read_Line)Keyword:_[0
    0F[VB 0F[VZ .[1 FN Q1J [1 J
    M(M.M List_Matching_Lines)0
    
!# Info ^R:! !S Go into ^R on current node.!
     0U..H 
!# Info Q:! !# Info ^X:! !# Info ^]:! !S Exit from Info.!
    F;Info-catch
!# Info ^Z:! !# Info ^C:! !S Return to superior.!
    :m(m.m ^R_Return_to_Superior)
!# Info X:! !S Execute extended (MM) command).!
    :M(M.M ^R_Extended_Command)
!# Info ^`:! !# Info ^V:! !S Go to next screenful of current node.!
    FS RGETTY"E -F[^H PRINT FT .,(10L .)T' !* On printing tty type 10 lines.!
    @:M(M.M ^R_Next_Screen)
!# Info ^H:! !S Go to previous screenful of current node.!
    FS RGETTY"E -10L '
    @:M(M.M ^R_Previous_Screen)
!# Info ^L:! !S Redisplay screen.!
    FS RGETTY"E .[1  FN Q1J :FT J 4T '
    F[WINDOW F+ 
!# Info ^J:! !# Info ^[:! !# Info ^@:! !# Info :! !S No-op.!
    
!# Info ^M:! !S Say that a CR is not necessary.!
    @FT
It_is_not_necessary_to_type_a_CR_after_an_INFO_command.

    
!# Info O:! !S Write current node (visible part of buffer) to file.!

    F[D FILE
    0FO..Q INFO_O_Filename[1	    !* Default the file to that used in previous O, if any,!
    Q1"N ET1'
      "# FS MSNAME FS DSNAME ET DSK:INFO_OUT'    !* Else to <msname>;INFO OUT!
    FS D FILE U1
    1,M(M.M &_Read_Line)Append_node_to_(1):_U1
    FQ1"L '  ET1
    FS D FILEM.V INFO_O_Filename  !* He went through with it => remember altered filenames!
    H M(M.M Append_to_File)	    !* and append the node to the file.!
    
!# Info S:! !# Info ^S:! !S Search whole file for a string.!

    M.M &_Info_Select_Location[1   !* Get the subroutine we need, and make it fast to call!
    1,M(M.M &_Read_Line) Search:_ [2	    !* Read our argument.!
    FQ2"E 0FO..Q INFO_S_DefaultU2' !* Empty arg means same arg as previous S.!
    FQ2"L 0'			    !* Give up if user rubbed past start of arg.!
    Q2 M.V INFO_S_Default	    !* Remember arg in case next S defaults to it.!
    .[3 0F[VZ  S2		    !* Find that string!
    .U3 F]VZ
    B"N Q3:M1' 		    !* Select the node containing the place we found,!
		    !* except that if whole file was selected, leave it that way.!
!Check INFO File:! !C Verify proper pointer structure in INFO file.
Makes sure that each Next, Previous and Up points at
a node which exists, and that Next and Previous are inverses.!

!*** First, make a temp buffer full of the headers of all nodes,
 to reduce searching time to find whether a node exists, etc.!

    Q..O[1 J			    !* Start at beginning of INFO file.!
    F[BBIND [..O Q..O[2	    !* Make temp buffer in Q2.!
    M.M &_Check_INFO_Test_Nodename
    I
				    !* Have blank line at front of temp bfr!
    				    !* so SNode: doesn't lose at front of 1st line.!
    < Q1U..O
      :S;			    !* Find next node.!
      0@F"E !<!>'
      L G(X*( Q2U..O )) >	    !* Copy node header into Q2.!
!*** Go through temp buffer checking each Next, Previous and Up.!
    Q2U..O J [3 [4 [5
    < :SNext:Previous:Up:;	    !* Find next property.!
      .+FK+1U5			    !* Remember address of start of property name.!
      @F_	R		    !* Skip all padding after the property name.!
      1A-("E !<!>'		    !* Ignore if node pointed to is in other file.!
,X3		:@F	Get name of node pointed to in Q3.!
      .U4 J
      Q3MT			    !* Find the nodename.  Put point there or at Z.!
      .U6
      Q5,Q4+FQ3X3		    !* Get property name and name of node pointed to.!
      Q5J :0L SNode:
      @F_	R
	X4:@F,!* Get name of node containing the pointer.!
      Q5J			    !* Make sure next search finds next property.!
      Q6-Z"E			    !* If node was not found,!
	FT Node_4_contains_undefined_pointer_3

	!<!>'
      :@F:F~Next"E		    !* If this is a Next,!
        Q6J 0L :FBPrevious:"L    !* see if the Next node points back with Previous.!
	  @F_	R
		:@F,"E   !* if so,!
	    Q5J !<!>''		    !* this Next is ok.!
	FT Node_4_contains_pointer_3_but_no_Previous_points_back

	Q5J'
      >

!*** QN gets subroutine to do Q5J in the original buffer.
and also set Q4 to the name of the node containing that point.!
    [N @:IN|
	Q1U..O
	Q5J			    !* Now find node containing the footnote.!
	< -:S; 0@F@; >	    !* Move up to a  at the start of a line.!
	SNode: @F_	R  !* Find start of node name.!
	:@F,	    !* Q4 gets node name.!
	Q5J|

!*** Now look through original file for all footnotes.!
    Q1U..O J			    !* Start from beginning.!
    < Q1U..O :S*Note;	    !* Find next footnote.!
      @F	_
R
      .U5 S: @F
_	R			    !* Save start of footnote name; find start of node name.!
      1A-("E !<!>'		    !* Ignore footnote pointing into another file.!
X3		 :@F	.,gets node name footnote points to.!
      .U4
      Q3MT			    !* Find the nodename.  Put point there or at Z.!
      .-Z"E			    !* If node doesn't exist, complain.!
        Q1U..O
	Q5-6,Q4+FQ3X3		    !* get entire footnote in Q3.!
	MN			    !* Q4 gets name of node containing footnote (using Q5).!
	FT Node_4_contains_undefined_footnote_3
'
      >				    !* Find next footnote.!
!*** Now look through original file for all menu items.!
    Q1U..O J			    !* Start from beginning.!
    0U6				    !* We have not found a menu yet.!
				    !* Q6 is 1 inside a menu, 0 looking for next menu.!
    < Q1U..O
      Q6"E :S
*_Menu:; 1U6'			    !* If not inside a menu, search for start of next one.!
      :S			    !* Then, search for next menu item, or end of node.!
*_
; 0A-"E 0U6 !<!>''	    !* If it's end of node, find next menu and its 1st item.!
      .U5 S: 1A-:"E 0LC'	    !* If it's a * FOO:: menu item, go to before FOO;!
				    !* otherwise it's a * FOO: BAR item, so stay before BAR.!
      @F_	R		    !* Find start of node name.!
      1A-("E !<!>'		    !* Ignore if node is in another file.!
X3	  :@F	.,:ts node name menu item points to.!
      Q3MT			    !* Find the nodename.  Put point there or at Z.!
      .-Z"E			    !* If it doesn't exist, complain.!
	MN			    !* Q4 gets name of node containing the menu.!
	FT Node_4_menu_refers_to_nonexistent_node_3
'
      >				    !* Find next menu item.!
    
!& Check INFO Test Nodename:! !S Does a node exist with a certain name?
We assume the calling environment of Check INFO File.
A string pointer to the name is given as a prefix arg.
We return with the temp buffer selected and point pointing
at the line for that node, or at Z if the node doesn't exist.!

    Q2U..O J [3
    < :S3;			    !* Look for an occurrence of the node name!
	"L1AF,'   !* followed by a terminator!
      FKC -@F_	L	    !* and preceded by Node: before some whitespace.!
      -5F~Node:"E
	-5A"B 0;''		    !* with a break character before Node:.!
      S >			    !* If not in right surroundings, look for next occurrence.!