home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
historic
/
v941.tgz
/
icon.v941src.tar
/
icon.v941src
/
ipl
/
progs
/
duplproc.icn
< prev
next >
Wrap
Text File
|
2000-07-29
|
9KB
|
326 lines
############################################################################
#
# File: duplproc.icn
#
# Subject: Program to find duplicate declarations
#
# Author: Richard L. Goerwitz
#
# Date: December 30, 1991
#
############################################################################
#
# This file is in the public domain.
#
############################################################################
#
# Version: 1.8
#
############################################################################
#
# Use this if you plan on posting utility procedures suitable for
# inclusion in someone's Icon library directories.
#
# duplproc.icn compiles into a program which will search through
# every directory in your ILIBS environment variable (and/or in the
# directories supplied as arguments to the program). If it finds any
# duplicate procedure or record identifiers, it will report this on
# the standard output.
#
# It is important to try to use unique procedure names in programs
# you write, especially if you intend to link in some of the routines
# contained in the IPL. Checking for duplicate procedure names has
# been somewhat tedious in the past, and many of us (me included)
# must be counted as guilty for not checking more thoroughly. Now,
# however, checking should be a breeze.
#
# BUGS: Duplproc thinks that differently written names for the same
# directory are in fact different directories. Use absolute path
# names, and you'll be fine.
#
############################################################################
#
# Requires: UNIX (MS-DOS will work if all files are in MS-DOS format)
#
############################################################################
record procedure_stats(name, file, lineno)
procedure main(a)
local proc_table, fname, elem, lib_file, tmp, too_many_table
# usage: duplproc [libdirs]
#
# Where libdirs is a series of space-separated directories in
# which relevant library files are to be found. To the
# directories listed in libdirs are added any directories found in
# the ILIBS environment variable.
proc_table := table()
too_many_table := table()
# Put all command-line option paths, and ILIBS paths, into one sorted
# list. Then get the names of all .icn filenames in those paths.
every fname := !get_icn_filenames(getlibpaths(a)) do {
# For each .icn filename, open that file, and find all procedure
# calls in it.
if not (lib_file := open(fname, "r")) then
write(&errout,"Can't open ",fname," for reading.")
else {
# Find all procedure calls in lib_file.
every elem := !get_procedures(lib_file,fname) do {
/proc_table[elem.name] := set()
insert(proc_table[elem.name],elem)
}
close(lib_file)
}
}
every elem := key(proc_table) do {
if *proc_table[elem] > 1 then {
write("\"", elem, "\" is defined in ",*proc_table[elem]," places:")
every tmp := !proc_table[elem] do {
write(" ",tmp.file, ", line ",tmp.lineno)
}
}
}
end
procedure getlibpaths(ipl_paths)
# Unite command-line args and ILIBS environment variable into one
# path list.
local i, path
# Make sure all paths have a consistent format (one trailing slash).a
if *\ipl_paths > 0 then {
every i := 1 to *ipl_paths do {
ipl_paths[i] := fixup_path(ipl_paths[i])
}
ipl_paths := set(ipl_paths)
}
else ipl_paths := set()
# If the ILIBS environment variable is set, read it into
# ipl_paths. Spaces - NOT COLONS - are used as separators.
getenv("ILIBS") ? {
while path := tab(find(" ")) do {
insert(ipl_paths, fixup_path(path))
tab(many(' '))
}
insert(ipl_paths, fixup_path(tab(0)))
}
return sort(ipl_paths)
end
procedure fixup_path(s)
# Make sure paths have a consistent format.
return "/" ~== (trim(s,'/') || "/")
end
procedure get_procedures(intext,fname)
# Extracts the names of all procedures declared in file f.
# Returns them in a list, each of whose elements have the
# form record procedure_stats(procedurename, filename, lineno).
local psl, f_pos, line_no, line
static name_chars
initial {
name_chars := &ucase ++ &lcase ++ &digits ++ '_'
}
# Initialize procedure-name list, line count.
psl := list()
line_no := 0
# Find procedure declarations in intext.
while line := read(intext) & line_no +:= 1 do {
take_out_comments(line) ? {
if tab(match("procedure")) then {
tab(many(' \t')) &
put(psl, procedure_stats(
"main" ~== tab(many(name_chars)), fname, line_no))
}
}
}
return psl # returns empty list if no procedures found
end
procedure take_out_comments(s)
# Commented-out portions of Icon code - strip 'em. Fails on lines
# which, either stripped or otherwise, come out as an empty string.
#
# BUG: Does not handle lines which use the _ string-continuation
# notation. Typically take_out_comments barfs on the next line.
local i, j, c, c2, s2
s ? {
tab(many(' \t'))
pos(0) & fail
find("#") | (return trim(tab(0),' \t'))
match("#") & fail
(s2 <- tab(find("#"))) ? {
c2 := &null
while tab(upto('\\"\'')) do {
case c := move(1) of {
"\\" : {
if match("^")
then move(2)
else move(1)
}
default: {
if \c2
then (c == c2, c2 := &null)
else c2 := c
}
}
}
/c2
}
return "" ~== trim((\s2 | tab(0)) \ 1, ' \t')
}
end
procedure get_icn_filenames(lib_paths)
# Return the names of all .icn files in all of the paths in the
# list lib_paths. The dir routine used depends on which OS we
# are running under.
local procedure_stat_list
static get_dir
initial get_dir := set_getdir_by_os()
procedure_stat_list := list()
# Run through every possible path in which files might be found,
# and get a list of procedures contained in those files.
every procedure_stat_list |||:= get_dir(!lib_paths)
return procedure_stat_list
end
procedure set_getdir_by_os()
if find("UNIX", &features)
then return unix_get_dir
else if find("MS-DOS", &features)
then return msdos_get_dir
else stop("Your operating system is not (yet) supported.")
end
procedure msdos_get_dir(dir)
local temp_name, filename
# Returns a sorted list of all filenames (full paths included) in
# directory "dir." The list is sorted. Fails on invalid or empty
# directory. Aborts if temp file cannot be opened.
#
# Temp files can be directed to one or another directory either by
# manually setting the variable temp_dir below, or by setting the
# value of the environment variable TEMPDIR to an appropriate
# directory name.
local in_dir, filename_list, line
static temp_dir
initial {
temp_dir :=
(trim(map(getenv("TEMPDIR"), "/", "\\"), '\\') || "\\") |
".\\"
}
# Get name of tempfile to be used.
temp_name := get_dos_tempname(temp_dir) |
stop("No more available tempfile names!")
# Make sure we have an unambiguous directory name, with backslashes
# instead of UNIX-like forward slashes.
dir := trim(map(dir, "/", "\\"), '\\') || "\\"
# Put dir listing into a temp file.
system("dir "||dir||" > "||temp_name)
# Put tempfile entries into a list, removing blank- and
# space-initial lines. Exclude directories (i.e. return file
# names only).
in_dir := open(temp_name,"r") |
stop("Can't open temp file in directory ",temp_dir,".")
filename_list := list()
every filename := ("" ~== !in_dir) do {
match(" ",filename) | find(" <DIR>", filename) & next
filename ?:= trim(trim(tab(10)) || "." || tab(13), '. ')
if filename ? (tab(find(".ICN")+4), pos(0))
then put(filename_list, map(dir || filename))
}
# Clean up.
close(in_dir) & remove(temp_name)
# Check to be sure we actually managed to read some files.
if *filename_list = 0 then fail
else return sort(filename_list)
end
procedure get_dos_tempname(dir)
local temp_name, temp_file
# Don't clobber existing files. Get a unique temp file name for
# use as a temporary storage site.
every temp_name := dir || "icondir." || right(string(1 to 999),3,"0") do {
temp_file := open(temp_name,"r") | break
close(temp_file)
}
return \temp_name
end
procedure unix_get_dir(dir)
local filename_list, in_dir, filename
dir := trim(dir, '/') || "/"
filename_list := list()
in_dir := open("/bin/ls -F "||dir, "pr")
every filename := ("" ~== !in_dir) do {
match("/",filename,*filename) & next
if filename ? (not match("s."), tab(find(".icn")+4), pos(0))
then put(filename_list, trim(dir || filename, '*'))
}
close(in_dir)
if *filename_list = 0 then fail
else return filename_list
end