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
/
utrim.icn
< prev
next >
Wrap
Text File
|
2000-07-29
|
6KB
|
209 lines
############################################################################
#
# File: utrim.icn
#
# Subject: Program to remove unneeded procs from ucode
#
# Author: Gregg M. Townsend
#
# Date: August 7, 1993
#
############################################################################
#
# This file is in the public domain.
#
############################################################################
#
# Usage: utrim [-s | -v] file...
#
# Utrim alters a set of uncode files comprising a complete Icon program
# by removing unreferenced procedures. The resulting files are smaller,
# and they produce a smaller icode file.
#
# The basename of each command argument is used to find a pair of
# .u1 and .u2 files; each pair is renamed to .u1o and .u2o and
# replaced by new .u1 and .u2 files.
#
# -s invokes silent mode; -v invokes verbose mode.
#
# Warning: utrim may break programs that use string invocation.
#
############################################################################
#
# Links: options
#
############################################################################
link options
record prc(name, size, calls, need) # proc record
record lcl(name, flags) # local record
global pnames, ptable # proc names and table
# main procedure
procedure main(args)
local opts, fname, name, need
# process options
opts := options(args, "sv")
if *args = 0 then
stop("usage: ", &progname, " [-s | -v] file.u1 ...")
every !args ?:= tab(upto('.'))
# scan .u1 files to decide what's needed
pnames := set()
ptable := table()
every scan1(!args)
if /ptable["main"] then
stop(&progname, ": no main procedure")
dependencies()
report(opts)
# write new .u1 and .u2 files
every fname := !args || (".u1" | ".u2") do {
remove(fname || "o")
rename(fname, fname || "o") | stop("can't rename ", fname)
}
every filter1(!args)
every filter2(!args)
end
# scan1(fname) -- read .u1 file, add proc names and refs to ptable
procedure scan1(fname)
local u1, line, i, name, flags, curr, locals
u1 := open(fname || ".u1") | stop(&progname, ": can't open", fname || ".u1")
while line := read(u1) do line ? {
if ="proc " then {
# new proc: make table entry
name := tab(0)
insert(pnames, name)
ptable[name] := curr := prc(name, 0, set())
locals := []
}
else if ="\tlocal\t" then {
# new local: remember its name
i := tab(many(&digits))
=","
flags := tab(upto(','))
=","
name := tab(0)
put(locals, lcl(name, flags))
}
else if ="\tvar\t" then {
# ref to "local": note as needed if it's a global
i := tab(0) + 1
if locals[i].flags = 0 then
insert(curr.calls, locals[i].name)
}
curr.size +:= 1 # tally number of lines
}
close(u1)
return
end
# dependencies() -- mark procs called directly or indirectly from main proc
procedure dependencies()
local need, p
need := ["main"]
while name := get(need) do
if (p := \ptable[name]) & (/p.need := 1) then
every put(need, !p.calls)
return
end
# report(opts) -- write reports as selected by command options
procedure report(opts)
local name, p, ptrim, ltrim, ltotal
ltotal := ltrim := ptrim := 0
every name := !sort(pnames) do {
p := ptable[name]
ltotal +:= p.size
if /p.need then {
ltrim +:= p.size
ptrim +:= 1
}
if /opts["v"] then
next
writes(right(p.size, 6))
writes(if \p.need then " * " else " ")
writes(left(p.name, 16))
every writes(" ", !sort(p.calls))
write()
}
if /opts["s"] then
write(&errout, "Trimming ", ptrim, "/", *pnames, " procedures (",
(100 * ptrim + 5) / *pnames, "%), ", ltrim, "/", ltotal, " lines (",
(100 * ltrim + 5) / ltotal, "%)")
return
end
# filter1(fname) -- filter .u1o file to make new .u1 file
#
# For each proc body, copy only if marked as needed in ptable.
procedure filter1(fname)
local old, new, line
old := open(fname||".u1o") | stop(&progname, ": can't open", fname||".u1o")
new := open(fname||".u1","w") | stop(&progname,": can't write",fname||".u1")
while line := read(old) do line ?
if ="proc " & /ptable[tab(0)].need then # check new proc
until (line ? ="\tend") | not (line := read(old)) # skip to proc end
else
write(new, line)
close(old)
close(new)
return
end
# filter2(fname) -- filter .u2o file to make new .u2 file
#
# Copy header verbatim; read list of globals, remove procs trimmed from .u1,
# and write new (renumbered) global list.
procedure filter2(fname)
local old, new, line, n, glist, flags, name, args, p
old := open(fname||".u2o") | stop(&progname, ": can't open ", fname||".u2o")
new := open(fname||".u2","w") | stop(&progname,": can't write ",fname||".u2")
write(new, read(old)) | stop(&progname, ": empty ", fname || ".u2o")
while (line := read(old)) & not (line ? ="global") do
write(new, line)
glist := []
while line := read(old) do line ? {
="\t"
tab(many(&digits))
p := &pos
=","
flags := tab(upto(','))
=","
name := tab(upto(','))
if flags = 5 & /(\ptable[name]).need then
next
tab(p)
put(glist, tab(0))
}
write(new, "global\t", *glist)
every write(new, "\t", 0 to *glist - 1, get(glist))
close(old)
close(new)
return
end