1#!/usr/bin/tclsh 2 3# Copyright (C) 2000 artofcode LLC. All rights reserved. 4# 5# This program is free software; you can redistribute it and/or modify it 6# under the terms of the GNU General Public License as published by the 7# Free Software Foundation; either version 2 of the License, or (at your 8# option) any later version. 9# 10# This program is distributed in the hope that it will be useful, but 11# WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 13# Public License for more details. 14# 15# You should have received a copy of the GNU General Public License along 16# with this program; if not, write to the Free Software Foundation, Inc., 17# 59 Temple Place, Suite 330, Boston, MA, 02111-1307. 18 19# $Id: hrefcov.tcl,v 1.5.4.1.2.1 2003/04/12 14:02:39 giles Exp $ 20 21# hrefcov.tcl - check that the hrefs in an HTML document mention all of a 22# set of files. The requirement is that the union of all the docfiles 23# must somewhere reference all the files. Usage: 24set USAGE {Usage: 25 hrefcov (+src | +lib | [+-]from <docfile> | [+-]to (<directory> | <file>))* 26} 27# +from or +to adds files; -from or -to removes them; 28# +src and +lib execute SRC_LIST and LIB_LIST below. 29 30# Define the Ghostscript-specific parameter lists. 31set SRC_LIST [list\ 32 +from doc/Develop.htm\ 33 +to lib src\ 34 -to lib/CVS src/CVS\ 35 -to src/*.mak.tcl\ 36 -to lib/*.upp\ 37 -to lib/*.ps +to lib/gs_*.ps lib/pdf_*.ps 38] 39set LIB_LIST [list\ 40 +from doc/Psfiles.htm\ 41 +to examples/*.ps lib/*.ps 42] 43 44# Global variables: 45# TO(file) is defined for every file in the "to" list 46# TO_DIR(dir) is defined for every directory in the "to" list 47# FROM(file) is defined for every file mentioned in a "from" document 48# In both cases, path names are normalized by removing ./ and/or ../ 49# whenever possible, to produce file names relative to the directory where 50# this program is being run. 51 52# Initialize the internal data base. 53proc init {} { 54 global FROM TO TO_DIR 55 56 catch {unset FROM} 57 catch {unset TO} 58 catch {unset TO_DIR} 59} 60 61# Normalize a file name by removing all occurrences of ./ and 62# all occurrences of <dir>/../. 63proc normalize_fname {fname} { 64 set name $fname 65 # Remove a trailing / 66 regsub {/$} $name "" name 67 # Remove occurrences of ./ 68 while {[regsub {^\./} $name "" name]} {} 69 while {[regsub {/\./} $name / name]} {} 70 while {[regsub {/\.$} $name "" name]} {} 71 if {$name == ""} {return /} 72 # Remove occurrences of <dir>/../ 73 while {[regsub {(^|/)([^./]|.[^./])[^/]*/../} $name {\1} name]} {} 74 if {$name == ""} {return .} 75 return $name 76} 77 78# Add or remove a file, or all the files in a directory, to/from TO. 79proc add_to {to} { 80 global TO TO_DIR 81 82 if {[file isfile $to]} { 83 set TO($to) 1 84 } elseif {[file isdirectory $to]} { 85 set TO_DIR($to) 1 86 foreach f [glob $to/*] {add_to $f} 87 } 88} 89proc remove_to {to} { 90 global TO TO_DIR 91 92 if {[file isfile $to]} { 93 catch {unset TO($to)} 94 } elseif {[file isdirectory $to]} { 95 catch {unset TO_DIR($to)} 96 foreach f [glob $to/*] {remove_to $f} 97 } 98} 99 100# Add or remove all the files mentioned in a document to/from FROM. 101# Note that we only add/remove files mentioned as a whole, i.e., without #. 102proc for_from {doc proc} { 103 set lines "" 104 set prefix "" 105 regexp {^(.*/)[^/]+$} $doc skip prefix 106 catch {set lines [split [exec egrep -i {href="[^#]} $doc] "\n"]} 107 set href_exp {href="([^"#]*)"(.*)$} 108 foreach line $lines { 109 while {[regexp -nocase $href_exp $line skip ref line]} { 110 $proc [normalize_fname $prefix$ref] 111 } 112 } 113} 114proc add_from {doc} {for_from $doc add1_from} 115proc add1_from {from} {global FROM; set FROM($from) 1} 116proc remove_from {doc} {for_from $doc remove1_from} 117proc remove1_from {from} {global FROM; catch {unset FROM($from)}} 118 119# Main program. 120proc main_args {arglist} { 121 global FROM TO SRC_LIST LIB_LIST 122 123 foreach arg $arglist { 124 switch -glob -- $arg { 125 +src {main_args $SRC_LIST} 126 +lib {main_args $LIB_LIST} 127 +from {set do add_from} 128 -from {set do remove_from} 129 +to {set do add_to} 130 -to {set do remove_to} 131 {[+-]*} { 132 puts stderr "Unknown switch: $arg" 133 exit 1 134 } 135 default { 136 if {[regexp {[*]} $arg]} { 137 foreach a [glob -nocomplain $arg] {$do $a} 138 } else { 139 $do $arg 140 } 141 } 142 } 143 } 144} 145proc main {argv} { 146 global FROM TO TO_DIR 147 148 init 149 main_args $argv 150 set dirs_exp {^$} 151 foreach dir [array names TO_DIR] { 152 append dirs_exp "|$dir/" 153 } 154 set list {} 155 foreach f [array names TO] { 156 if {![info exists FROM($f)]} {lappend list $f} 157 } 158 if {$list != {}} { 159 puts " ****** Files defined but not referenced ******" 160 foreach f [lsort $list] {puts $f} 161 } 162 set list {} 163 foreach f [array names FROM] { 164 if {![info exists TO($f)]} { 165 # Only report files that should be in a scanned directory. 166 if {[regexp "(${dirs_exp})\[^/\]+$" $f]} { 167 lappend list $f 168 } 169 } 170 } 171 if {$list != {}} { 172 puts " ****** Files referenced but not defined ******" 173 foreach f [lsort $list] {puts $f} 174 } 175} 176 177main $argv 178