1#! /usr/local/bin/gawk -f
2
3# fixref.awk --- fix xrefs in texinfo documents
4# Copyright, 1991, Arnold David Robbins, arnold@skeeve.atl.ga.us
5# Copyright, 1998, Arnold David Robbins, arnold@gnu.org
6
7# FIXREF is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11# 
12# FIXREF is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16# 
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
20
21# Updated: Jul 21  1992	--- change unknown
22# Updated: Jul 18  1997 --- bug fix
23
24# usage:		gawk -f fixref.awk input-file > output-file
25# or if you have #!:	fixref.awk input-file > output-file
26
27# Limitations:
28#	1. no more than one cross reference on a line
29#	2. cross references may not cross a newline
30
31BEGIN	\
32{
33	# we make two passes over the file.  To do that we artificially
34	# tweak the argument vector to do a variable assignment
35
36	if (ARGC != 2) {
37		printf("usage: %s texinfo-file\n", ARGV[0]) > "/dev/stderr"
38		exit 1
39	}
40	ARGV[2] = "pass=2"
41	ARGV[3] = ARGV[1]
42	ARGC = 4
43
44	# examine paragraphs
45	RS = ""
46
47	heading = "@(chapter|appendix|unnumbered|(appendix(sec|subsec|subsubsec))|section|subsection|subsubsection|unnumberedsec|heading|top)"
48
49	pass = 1
50
51	# put space between paragraphs on output
52	ORS = "\n\n"
53}
54
55pass == 1 && NF == 0	{ next }
56
57# pass == 1 && /@node/	\
58# bug fix 7/18/96
59pass == 1 && /^@node/	\
60{
61	lname = name = ""
62	n = split($0, lines, "\n")
63	for (i = 1; i <= n; i++) {
64		if (lines[i] ~ ("^" heading)) {
65			sub(heading, "", lines[i])
66			sub(/^[ \t]*/, "", lines[i])
67			lname = lines[i]
68#			printf "long name is '%s'\n", lines[i]
69		} else if (lines[i] ~ /@node/) {
70			sub(/@node[ \t]*/, "", lines[i])
71			sub(/[ \t]*,.*$/, "", lines[i])
72			name = lines[i]
73#			printf "node name is '%s'\n", lines[i]
74		}
75	}
76	if (name && lname)
77		names[name] = lname
78	else if (lname)
79		printf("node name for %s missing!\n", lname) > "/dev/stderr"
80	else
81		printf("long name for %s missing!\n", name) > "/dev/stderr"
82
83	if (name ~ /:/)
84		printf("node `%s' contains a `:'\n", name) > "/dev/stderr"
85
86	if (lname) {
87		if (lname ~ /:/)
88			printf("name `%s' contains a `:'\n", lname) > "/dev/stderr"
89		else if (lname ~ /,/) {
90			printf("name `%s' contains a `,'\n", lname) > "/dev/stderr"
91			gsub(/,/, " ", lname)
92			names[name] = lname	# added 7/18/97
93		}
94	}
95}
96
97pass == 2 && /@(x|px)?ref{/	\
98{
99	# split the paragraph into lines
100	# write them out one by one after fixing them
101	n = split($0, lines, "\n")
102	for (i = 1; i <= n; i++)
103		if (lines[i] ~ /@(x|px)?ref{/) {
104			res = updateref(lines[i])
105			printf "%s\n", res
106		} else
107			printf "%s\n", lines[i]
108
109	printf "\n"	# avoid ORS
110	next
111}
112
113function updateref(orig,	refkind, line)
114{
115	line = orig	# work on a copy
116
117	# find the beginning of the reference
118	match(line, "@(x|px)?ref{")
119	refkind = substr(line, RSTART, RLENGTH)
120
121	# pull out just the node name
122	sub(/.*ref{/, "", line)
123	sub(/}.*$/, "", line)
124	sub(/,.*/, "", line)
125
126#	debugging
127#	printf("found ref to node '%s'\n", line) > "/dev/stderr"
128
129	# If the node name and the section name are the same
130	# we don't want to bother doing this.
131
132	if (! (line in names))	# sanity checking
133		printf("no long name for %s\n", line) > "/dev/stderr"
134	else if (names[line] != line && names[line] !~ /[:,]/) {
135		# build up new ref
136		newref = refkind line ", ," names[line] "}"
137		pat = refkind line "[^}]*}"
138
139		sub(pat, newref, orig)
140	}
141
142	return orig
143}
144
145pass == 2	{ print }
146