1#! /bin/sh
2# $MirOS: src/gnu/usr.bin/cvs/contrib/rcs2log.sh,v 1.6 2011/05/06 22:44:59 tg Exp $
3
4# Copyright (C) 1995-2005 The Free Software Foundation, Inc.
5
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2, or (at your option)
9# any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15
16# RCS to ChangeLog generator
17
18# Generate a change log prefix from RCS files (perhaps in the CVS repository)
19# and the ChangeLog (if any).
20# Output the new prefix to standard output.
21# You can edit this prefix by hand, and then prepend it to ChangeLog.
22
23# Ignore log entries that start with `#'.
24# Clump together log entries that start with `{topic} ',
25# where `topic' contains neither white space nor `}'.
26
27Help='The default FILEs are the files registered under the working directory.
28Options:
29
30  -c CHANGELOG  Output a change log prefix to CHANGELOG (default ChangeLog).
31  -h HOSTNAME  Use HOSTNAME in change log entries (default current host).
32  -i INDENT  Indent change log lines by INDENT spaces (default 8).
33  -l LENGTH  Try to limit log lines to LENGTH characters (default 79).
34  -L FILE  Use rlog-format FILE for source of logs.
35  -n  Obsolete, use -u instead (whose syntax differs).
36  -R  If no FILEs are given and RCS is used, recurse through working directory.
37  -r OPTION  Pass OPTION to subsidiary log command.
38  -t TABWIDTH  Tab stops are every TABWIDTH characters (default 8).
39  -u "LOGIN<tab>FULLNAME<tab>MAILADDR"  Assume LOGIN has FULLNAME and MAILADDR.
40  -v  Append RCS revision to file names in log lines.
41  --help  Output help.
42  --version  Output version number.
43
44Report bugs to <bug-gnu-emacs@gnu.org>.'
45
46Id='$Id: rcs2log,v 1.48 2001/09/05 23:07:46 eggert Exp $'
47
48# Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2001, 2003
49#  Free Software Foundation, Inc.
50
51# This program is free software; you can redistribute it and/or modify
52# it under the terms of the GNU General Public License as published by
53# the Free Software Foundation; either version 2, or (at your option)
54# any later version.
55#
56# This program is distributed in the hope that it will be useful,
57# but WITHOUT ANY WARRANTY; without even the implied warranty of
58# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
59# GNU General Public License for more details.
60#
61# You should have received a copy of the GNU General Public License
62# along with this program; see the file COPYING.  If not, write to the
63# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
64# Boston, MA 02111-1307, USA.
65
66Copyright='Copyright 1992-2003 Free Software Foundation, Inc.
67This program comes with NO WARRANTY, to the extent permitted by law.
68You may redistribute copies of this program
69under the terms of the GNU General Public License.
70For more information about these matters, see the files named COPYING.
71Author: Paul Eggert <eggert@twinsun.com>'
72
73# functions
74@MKTEMP_SH_FUNCTION@
75
76# Use the traditional C locale.
77LANG=C
78LANGUAGE=C
79LC_ALL=C
80LC_COLLATE=C
81LC_CTYPE=C
82LC_MESSAGES=C
83LC_NUMERIC=C
84LC_TIME=C
85export LANG LANGUAGE LC_ALL LC_COLLATE LC_CTYPE LC_MESSAGES LC_NUMERIC LC_TIME
86
87# These variables each contain a single ASCII character.
88# Unfortunately, there's no portable way of writing these characters
89# in older Unix implementations, other than putting them directly into
90# this text file.
91SOH='' # SOH, octal code 001
92tab='	'
93nl='
94'
95
96# Parse options.
97
98# defaults
99: ${MKTEMP="@MKTEMP@"}
100: ${AWK=awk}
101: ${TMPDIR=/tmp}
102
103changelog=ChangeLog # change log file name
104datearg= # rlog date option
105hostname= # name of local host (if empty, will deduce it later)
106indent=8 # indent of log line
107length=79 # suggested max width of log line
108logins= # login names for people we know fullnames and mailaddrs of
109loginFullnameMailaddrs= # login<tab>fullname<tab>mailaddr triplets
110logTZ= # time zone for log dates (if empty, use local time)
111recursive= # t if we want recursive rlog
112revision= # t if we want revision numbers
113rlog_options= # options to pass to rlog
114rlogfile= # log file to read from
115tabwidth=8 # width of horizontal tab
116
117while :
118do
119	case $1 in
120	-c)	changelog=${2?}; shift;;
121	-i)	indent=${2?}; shift;;
122	-h)	hostname=${2?}; shift;;
123	-l)	length=${2?}; shift;;
124	-L)	rlogfile=${2?}; shift;;
125	-[nu])	# -n is obsolescent; it is replaced by -u.
126		case $1 in
127		-n)	case ${2?}${3?}${4?} in
128			*"$tab"* | *"$nl"*)
129				echo >&2 "$0: -n '$2' '$3' '$4': tabs, newlines not allowed"
130				exit 1;;
131			esac
132			login=$2
133			lfm=$2$tab$3$tab$4
134			shift; shift; shift;;
135		-u)
136			# If $2 is not tab-separated, use colon for separator.
137			case ${2?} in
138			*"$nl"*)
139				echo >&2 "$0: -u '$2': newlines not allowed"
140				exit 1;;
141			*"$tab"*)
142				t=$tab;;
143			*)
144				t=':';;
145			esac
146			case $2 in
147			*"$t"*"$t"*"$t"*)
148				echo >&2 "$0: -u '$2': too many fields"
149				exit 1;;
150			*"$t"*"$t"*)
151				uf="[^$t]*$t" # An unselected field, followed by a separator.
152				sf="\\([^$t]*\\)" # The selected field.
153				login=`expr "X$2" : "X$sf"`
154				lfm="$login$tab"`
155					expr "X$2" : "$uf$sf"
156				  `"$tab"`
157					expr "X$2" : "$uf$uf$sf"
158				`;;
159			*)
160				echo >&2 "$0: -u '$2': not enough fields"
161				exit 1;;
162			esac
163			shift;;
164		esac
165		case $logins in
166		'') logins=$login;;
167		?*) logins=$logins$nl$login;;
168		esac
169		case $loginFullnameMailaddrs in
170		'') loginFullnameMailaddrs=$lfm;;
171		?*) loginFullnameMailaddrs=$loginFullnameMailaddrs$nl$lfm;;
172		esac;;
173	-r)
174		case $rlog_options in
175		'') rlog_options=${2?};;
176		?*) rlog_options=$rlog_options$nl${2?};;
177		esac
178		shift;;
179	-R)	recursive=t;;
180	-t)	tabwidth=${2?}; shift;;
181	-v)	revision=t;;
182	--version)
183		set $Id
184		rcs2logVersion=$3
185		echo >&2 "rcs2log (GNU Emacs) $rcs2logVersion$nl$Copyright"
186		exit 0;;
187	-*)	echo >&2 "Usage: $0 [OPTION]... [FILE ...]$nl$Help"
188		case $1 in
189		--help) exit 0;;
190		*) exit 1;;
191		esac;;
192	*)	break;;
193	esac
194	shift
195done
196
197month_data='
198	m[0]="Jan"; m[1]="Feb"; m[2]="Mar"
199	m[3]="Apr"; m[4]="May"; m[5]="Jun"
200	m[6]="Jul"; m[7]="Aug"; m[8]="Sep"
201	m[9]="Oct"; m[10]="Nov"; m[11]="Dec"
202'
203
204logdir=$($MKTEMP -d $TMPDIR/rcs2log.XXXXXXXXXX)
205test -n "$logdir" || exit
206llogout=$logdir/l
207trap exit 1 2 13 15
208trap "rm -fr $logdir 2>/dev/null" 0
209
210# If no rlog-format log file is given, generate one into $rlogfile.
211case $rlogfile in
212'')
213	rlogfile=$logdir/r
214
215	# If no rlog options are given,
216	# log the revisions checked in since the first ChangeLog entry.
217	# Since ChangeLog is only by date, some of these revisions may be duplicates of
218	# what's already in ChangeLog; it's the user's responsibility to remove them.
219	case $rlog_options in
220	'')
221		if test -s "$changelog"
222		then
223			e='
224				/^[0-9]+-[0-9][0-9]-[0-9][0-9]/{
225					# ISO 8601 date
226					print $1
227					exit
228				}
229				/^... ... [ 0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9]+ /{
230					# old-fashioned date and time (Emacs 19.31 and earlier)
231					'"$month_data"'
232					year = $5
233					for (i=0; i<=11; i++) if (m[i] == $2) break
234					dd = $3
235					printf "%d-%02d-%02d\n", year, i+1, dd
236					exit
237				}
238			'
239			d=`$AWK "$e" <"$changelog"` || exit
240			case $d in
241			?*) datearg="-d>$d";;
242			esac
243		fi;;
244	esac
245
246	# Use TZ specified by ChangeLog local variable, if any.
247	if test -s "$changelog"
248	then
249		extractTZ='
250			/^.*change-log-time-zone-rule['"$tab"' ]*:['"$tab"' ]*"\([^"]*\)".*/{
251				s//\1/; p; q
252			}
253			/^.*change-log-time-zone-rule['"$tab"' ]*:['"$tab"' ]*t.*/{
254				s//UTC0/; p; q
255			}
256		'
257		logTZ=`tail "$changelog" | sed -n "$extractTZ"`
258		case $logTZ in
259		?*) TZ=$logTZ; export TZ;;
260		esac
261	fi
262
263	# If CVS is in use, examine its repository, not the normal RCS files.
264	if test ! -f CVS/Repository
265	then
266		rlog=rlog
267		repository=
268	else
269		rlog='cvs -q log'
270		repository=`sed 1q <CVS/Repository` || exit
271		test ! -f CVS/Root || CVSROOT=`cat <CVS/Root` || exit
272		case $CVSROOT in
273		*:/*:/*)
274			echo >&2 "$0: $CVSROOT: CVSROOT has multiple ':/'s"
275			exit 1;;
276		*:/*)
277			# remote repository
278			pository=`expr "X$repository" : '.*:\(/.*\)'`;;
279		*)
280			# local repository
281			case $repository in
282			/*) ;;
283			*) repository=${CVSROOT?}/$repository;;
284			esac
285			if test ! -d "$repository"
286			then
287				echo >&2 "$0: $repository: bad repository (see CVS/Repository)"
288				exit 1
289			fi
290			pository=$repository;;
291		esac
292
293		# Ensure that $pository ends in exactly one slash.
294		while :
295		do
296			case $pository in
297			*//) pository=`expr "X$pository" : 'X\(.*\)/'`;;
298			*/) break;;
299			*) pository=$pository/; break;;
300			esac
301		done
302
303	fi
304
305	# Use $rlog's -zLT option, if $rlog supports it.
306	case `$rlog -zLT 2>&1` in
307	*' option'*) ;;
308	*)
309		case $rlog_options in
310		'') rlog_options=-zLT;;
311		?*) rlog_options=-zLT$nl$rlog_options;;
312		esac;;
313	esac
314
315	# With no arguments, examine all files under the RCS directory.
316	case $# in
317	0)
318		case $repository in
319		'')
320			oldIFS=$IFS
321			IFS=$nl
322			case $recursive in
323			t)
324				RCSdirs=`find . -name RCS -type d -print`
325				filesFromRCSfiles='s|,v$||; s|/RCS/|/|; s|^\./||'
326				files=`
327					{
328						case $RCSdirs in
329						?*) find $RCSdirs \
330								-type f \
331								! -name '*_' \
332								! -name ',*,' \
333								! -name '.*_' \
334								! -name .rcsfreeze.log \
335								! -name .rcsfreeze.ver \
336								-print;;
337						esac
338						find . -name '*,v' -print
339					} |
340					sort -u |
341					sed "$filesFromRCSfiles"
342				`;;
343			*)
344				files=
345				for file in RCS/.* RCS/* .*,v *,v
346				do
347					case $file in
348					RCS/. | RCS/.. | RCS/,*, | RCS/*_) continue;;
349					RCS/.rcsfreeze.log | RCS/.rcsfreeze.ver) continue;;
350					RCS/.\* | RCS/\* | .\*,v | \*,v) test -f "$file" || continue;;
351					RCS/*,v | RCS/.*,v) ;;
352					RCS/* | RCS/.*) test -f "$file" || continue;;
353					esac
354					case $files in
355					'') files=$file;;
356					?*) files=$files$nl$file;;
357					esac
358				done
359				case $files in
360				'') exit 0;;
361				esac;;
362			esac
363			set x $files
364			shift
365			IFS=$oldIFS;;
366		esac;;
367	esac
368
369	case $datearg in
370	?*) $rlog $rlog_options "$datearg" ${1+"$@"} >$rlogfile;;
371	'') $rlog $rlog_options ${1+"$@"} >$rlogfile;;
372	esac || exit;;
373esac
374
375
376# Get the full name of each author the logs mention, and set initialize_fullname
377# to awk code that initializes the `fullname' awk associative array.
378# Warning: foreign authors (i.e. not known in the passwd file) are mishandled;
379# you have to fix the resulting output by hand.
380
381initialize_fullname=
382initialize_mailaddr=
383
384case $loginFullnameMailaddrs in
385?*)
386	case $loginFullnameMailaddrs in
387	*\"* | *\\*)
388		sed 's/["\\]/\\&/g' >$llogout <<EOF || exit
389$loginFullnameMailaddrs
390EOF
391		loginFullnameMailaddrs=`cat $llogout`;;
392	esac
393
394	oldIFS=$IFS
395	IFS=$nl
396	for loginFullnameMailaddr in $loginFullnameMailaddrs
397	do
398		IFS=$tab
399		set x $loginFullnameMailaddr
400		login=$2
401		fullname=$3
402		mailaddr=$4
403		initialize_fullname="$initialize_fullname
404			fullname[\"$login\"] = \"$fullname\""
405		initialize_mailaddr="$initialize_mailaddr
406			mailaddr[\"$login\"] = \"$mailaddr\""
407	done
408	IFS=$oldIFS;;
409esac
410
411case $logins in
412?*)
413	sort -u -o $llogout <<EOF
414$logins
415EOF
416	;;
417'')
418	: ;;
419esac >$llogout || exit
420
421output_authors='/^date: / {
422	if ($2 ~ /^[0-9]*[-\/][0-9][0-9][-\/][0-9][0-9]$/ && $3 ~ /^[0-9][0-9]:[0-9][0-9]:[0-9][0-9][-+0-9:]*;$/ && $4 == "author:" && $5 ~ /^[^;]*;$/) {
423		print substr($5, 1, length($5)-1)
424	}
425}'
426authors=`
427	$AWK "$output_authors" <"$rlogfile" | sort -u | comm -23 - $llogout
428`
429case $authors in
430?*)
431	cat >$llogout <<EOF || exit
432$authors
433EOF
434	initialize_author_script='s/["\\]/\\&/g; s/.*/author[\"&\"] = 1/'
435	initialize_author=`sed -e "$initialize_author_script" <$llogout`
436	awkscript='
437		BEGIN {
438			alphabet = "abcdefghijklmnopqrstuvwxyz"
439			ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
440			'"$initialize_author"'
441		}
442		{
443			if (author[$1]) {
444				fullname = $5
445				if (fullname ~ /[0-9]+-[^(]*\([0-9]+\)$/) {
446					# Remove the junk from fullnames like "0000-Admin(0000)".
447					fullname = substr(fullname, index(fullname, "-") + 1)
448					fullname = substr(fullname, 1, index(fullname, "(") - 1)
449				}
450				if (fullname ~ /,[^ ]/) {
451					# Some sites put comma-separated junk after the fullname.
452					# Remove it, but leave "Bill Gates, Jr" alone.
453					fullname = substr(fullname, 1, index(fullname, ",") - 1)
454				}
455				abbr = index(fullname, "&")
456				if (abbr) {
457					a = substr($1, 1, 1)
458					A = a
459					i = index(alphabet, a)
460					if (i) A = substr(ALPHABET, i, 1)
461					fullname = substr(fullname, 1, abbr-1) A substr($1, 2) substr(fullname, abbr+1)
462				}
463
464				# Quote quotes and backslashes properly in full names.
465				# Do not use gsub; traditional awk lacks it.
466				quoted = ""
467				rest = fullname
468				for (;;) {
469					p = index(rest, "\\")
470					q = index(rest, "\"")
471					if (p) {
472						if (q && q<p) p = q
473					} else {
474						if (!q) break
475						p = q
476					}
477					quoted = quoted substr(rest, 1, p-1) "\\" substr(rest, p, 1)
478					rest = substr(rest, p+1)
479				}
480
481				printf "fullname[\"%s\"] = \"%s%s\"\n", $1, quoted, rest
482				author[$1] = 0
483			}
484		}
485	'
486
487	initialize_fullname=`
488		{
489			(getent passwd $authors) ||
490			(
491				cat /etc/passwd
492				for author in $authors
493				do NIS_PATH= nismatch $author passwd.org_dir
494				done
495				ypmatch $authors passwd
496			)
497		} 2>/dev/null |
498		$AWK -F: "$awkscript"
499	`$initialize_fullname;;
500esac
501
502
503# Function to print a single log line.
504# We don't use awk functions, to stay compatible with old awk versions.
505# `Log' is the log message.
506# `files' contains the affected files.
507printlogline='{
508
509	# Following the GNU coding standards, rewrite
510	#	* file: (function): comment
511	# to
512	#	* file (function): comment
513	if (Log ~ /^\([^)]*\): /) {
514		i = index(Log, ")")
515		filefunc = substr(Log, 1, i)
516		while ((j = index(filefunc, "\n"))) {
517			files = files " " substr(filefunc, 1, j-1)
518			filefunc = substr(filefunc, j+1)
519		}
520		files = files " " filefunc
521		Log = substr(Log, i+3)
522	}
523
524	# If "label: comment" is too long, break the line after the ":".
525	sep = " "
526	i = index(Log, "\n")
527	if ('"$length"' <= '"$indent"' + 1 + length(files) + i) sep = "\n" indent_string
528
529	# Print the label.
530	printf "%s*%s:", indent_string, files
531
532	# Print each line of the log.
533	while (i) {
534		logline = substr(Log, 1, i-1)
535		if (logline ~ /[^'"$tab"' ]/) {
536			printf "%s%s\n", sep, logline
537		} else {
538			print ""
539		}
540		sep = indent_string
541		Log = substr(Log, i+1)
542		i = index(Log, "\n")
543	}
544}'
545
546# Pattern to match the `revision' line of rlog output.
547rlog_revision_pattern='^revision [0-9]+\.[0-9]+(\.[0-9]+\.[0-9]+)*(['"$tab"' ]+locked by: [^'"$tab"' $,.0-9:;@]*[^'"$tab"' $,:;@][^'"$tab"' $,.0-9:;@]*;)?['"$tab"' ]*$'
548
549case $hostname in
550'')
551	hostname=`(
552		hostname || uname -n || uuname -l || cat /etc/whoami
553	) 2>/dev/null` || {
554		echo >&2 "$0: cannot deduce hostname"
555		exit 1
556	}
557
558	case $hostname in
559	*.*) ;;
560	*)
561		domainname=`(domainname) 2>/dev/null` &&
562		case $domainname in
563		*.*) hostname=$hostname.$domainname;;
564		esac;;
565	esac;;
566esac
567
568
569# Process the rlog output, generating ChangeLog style entries.
570
571# First, reformat the rlog output so that each line contains one log entry.
572# Transliterate \n to SOH so that multiline entries fit on a single line.
573# Discard irrelevant rlog output.
574$AWK '
575	BEGIN {
576		pository = "'"$pository"'"
577		SOH="'"$SOH"'"
578	}
579	/^RCS file: / {
580		if (pository != "") {
581			filename = substr($0, 11)
582			if (substr(filename, 1, length(pository)) == pository) {
583				filename = substr(filename, length(pository) + 1)
584			}
585			if (filename ~ /,v$/) {
586				filename = substr(filename, 1, length(filename) - 2)
587			}
588			if (filename ~ /(^|\/)Attic\/[^\/]*$/) {
589				i = length(filename)
590				while (substr(filename, i, 1) != "/") i--
591				filename = substr(filename, 1, i - 6) substr(filename, i + 1)
592			}
593		}
594		rev = "?"
595	}
596	/^Working file: / { if (repository == "") filename = substr($0, 15) }
597	/'"$rlog_revision_pattern"'/, /^(-----------*|===========*)$/ {
598		line = $0
599		if (line ~ /'"$rlog_revision_pattern"'/) {
600			rev = $2
601			next
602		}
603		if (line ~ /^date: [0-9][- +\/0-9:]*;/) {
604			date = $2
605			if (date ~ /\//) {
606				# This is a traditional RCS format date YYYY/MM/DD.
607				# Replace "/"s with "-"s to get ISO format.
608				newdate = ""
609				while ((i = index(date, "/")) != 0) {
610					newdate = newdate substr(date, 1, i-1) "-"
611					date = substr(date, i+1)
612				}
613				date = newdate date
614			}
615			time = substr($3, 1, length($3) - 1)
616			author = substr($5, 1, length($5)-1)
617			printf "%s%s%s%s%s%s%s%s%s%s", filename, SOH, rev, SOH, date, SOH, time, SOH, author, SOH
618			rev = "?"
619			next
620		}
621		if (line ~ /^branches: /) { next }
622		if (line ~ /^(-----------*|===========*)$/) { print ""; next }
623		if (line == "Initial revision" || line ~ /^file .+ was initially added on branch .+\.$/) {
624			line = "New file."
625		}
626		printf "%s%s", line, SOH
627	}
628' <"$rlogfile" |
629
630# Now each line is of the form
631# FILENAME@REVISION@YYYY-MM-DD@HH:MM:SS[+-TIMEZONE]@AUTHOR@LOG
632#	where @ stands for an SOH (octal code 001),
633#	and each line of LOG is terminated by SOH instead of \n.
634# Sort the log entries, first by date+time (in reverse order),
635# then by author, then by log entry, and finally by file name and revision
636# (just in case).
637sort -t"$SOH" -k 3,4r -k 5 -k 1 |
638
639# Finally, reformat the sorted log entries.
640$AWK -F"$SOH" '
641	BEGIN {
642		logTZ = "'"$logTZ"'"
643		revision = "'"$revision"'"
644
645		# Initialize the fullname and mailaddr associative arrays.
646		'"$initialize_fullname"'
647		'"$initialize_mailaddr"'
648
649		# Initialize indent string.
650		indent_string = ""
651		i = '"$indent"'
652		if (0 < '"$tabwidth"')
653			for (;  '"$tabwidth"' <= i;  i -= '"$tabwidth"')
654				indent_string = indent_string "\t"
655		while (1 <= i--)
656			indent_string = indent_string " "
657	}
658
659	{
660		newlog = ""
661		for (i = 6; i < NF; i++) newlog = newlog $i "\n"
662
663		# Ignore log entries prefixed by "#".
664		if (newlog ~ /^#/) { next }
665
666		if (Log != newlog || date != $3 || author != $5) {
667
668			# The previous log and this log differ.
669
670			# Print the old log.
671			if (date != "") '"$printlogline"'
672
673			# Logs that begin with "{clumpname} " should be grouped together,
674			# and the clumpname should be removed.
675			# Extract the new clumpname from the log header,
676			# and use it to decide whether to output a blank line.
677			newclumpname = ""
678			sep = "\n"
679			if (date == "") sep = ""
680			if (newlog ~ /^\{[^'"$tab"' }]*}['"$tab"' ]/) {
681				i = index(newlog, "}")
682				newclumpname = substr(newlog, 1, i)
683				while (substr(newlog, i+1) ~ /^['"$tab"' ]/) i++
684				newlog = substr(newlog, i+1)
685				if (clumpname == newclumpname) sep = ""
686			}
687			printf sep
688			clumpname = newclumpname
689
690			# Get ready for the next log.
691			Log = newlog
692			if (files != "")
693				for (i in filesknown)
694					filesknown[i] = 0
695			files = ""
696		}
697		if (date != $3  ||  author != $5) {
698			# The previous date+author and this date+author differ.
699			# Print the new one.
700			date = $3
701			time = $4
702			author = $5
703
704			zone = ""
705			if (logTZ && ((i = index(time, "-")) || (i = index(time, "+"))))
706				zone = " " substr(time, i)
707
708			# Print "date[ timezone]  fullname  <email address>".
709			# Get fullname and email address from associative arrays;
710			# default to author and author@hostname if not in arrays.
711			if (fullname[author])
712				auth = fullname[author]
713			else
714				auth = author
715			printf "%s%s  %s  ", date, zone, auth
716			if (mailaddr[author])
717				printf "<%s>\n\n", mailaddr[author]
718			else
719				printf "<%s@%s>\n\n", author, "'"$hostname"'"
720		}
721		if (! filesknown[$1]) {
722			filesknown[$1] = 1
723			if (files == "") files = " " $1
724			else files = files ", " $1
725			if (revision && $2 != "?") files = files " " $2
726		}
727	}
728	END {
729		# Print the last log.
730		if (date != "") {
731			'"$printlogline"'
732			printf "\n"
733		}
734	}
735' &&
736
737
738# Exit successfully.
739
740exec rm -fr $logdir
741
742# Local Variables:
743# tab-width:4
744# End:
745