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
/
iprint.icn
< prev
next >
Wrap
Text File
|
2002-03-26
|
7KB
|
259 lines
############################################################################
#
# File: iprint.icn
#
# Subject: Program to print Icon program
#
# Author: Robert J. Alexander
#
# Date: March 26, 2002
#
############################################################################
#
# This file is in the public domain.
#
############################################################################
#
# The defaults are set up for printing of Icon programs, but
# through command line options it can be set up to print programs
# in other languages, too (such as C). This program has several
# features:
#
# If a program is written in a consistent style, this program
# will attempt to keep whole procedures on the same page. The
# default is to identify the end of a print group (i.e. a pro-
# cedure) by looking for the string "end" at the beginning of a
# line. Through the -g option, alternative strings can be used to
# signal end of a group. Using "end" as the group delimiter
# (inclusive), comments and declarations prior to the procedure are
# grouped with the procedure. Specifying a null group delimiter
# string (-g '') suppresses grouping.
#
# Page creases are skipped over, and form-feeds (^L) embedded in
# the file are handled properly. (Form-feeds are treated as spaces
# by many C compilers, and signal page ejects in a listing). Page
# headings (file name, date, time, page number) are normally
# printed unless suppressed by the -h option.
#
# Options:
#
# -n number lines.
#
# -pN page length: number of lines per page (default: 60
# lines).
#
# -tN tab stop spacing (default: 8).
#
# -h suppress page headings.
#
# -l add three lines at top of each page for laser printer.
#
# -gS end of group string (default: "end").
#
# -cS start of comment string (default: "#").
#
# -xS end of comment string (default: none).
#
# -i ignore FF at start of line.
#
# Any number of file names specified will be printed, each
# starting on a new page.
#
# For example, to print C source files such as the Icon source
# code, use the following options:
#
# iprint -g ' }' -c '/*' -x '*/' file ...
#
# Control lines:
#
# Control lines are special character strings that occur at the
# beginnings of lines that signal special action. Control lines
# begin with the start of comment string (see options). The control
# lines currently recognized are:
#
# <comment string>eject -- page eject (line containing "eject"
# does not print).
#
# <comment string>title -- define a title line to print at top
# of each page. Title text is separated from the <comment
# string>title control string by one space and is terminated by
# <end of comment string> or end of line, whichever comes first.
#
# <comment string>subtitle -- define a sub-title line to print
# at top of each page. Format is parallel to the "title" control
# line, above.
#
# If a page eject is forced by maximum lines per page being
# exceeded (rather than intentional eject via control line, ff, or
# grouping), printing of blank lines at the top of the new page is
# suppressed. Line numbers will still be printed correctly.
#
############################################################################
global pagelines,tabsize,lines,page,datetime,title,subtitle,pagestatus,blanks,
group,numbers,noheaders,hstuff,gpat,comment,comment_end,laser,
ignore_ff
procedure main(arg)
local files,x
&dateline ? {tab(find(",")) ; move(2) ; datetime := tab(0)}
files := []
pagelines := 60
tabsize := 8
gpat := "end"
comment := "#"
while x := get(arg) do {
if match("-",x) then { # Arg is an option
case x[2] of {
"n": numbers := "yes"
"p": {
pagelines := ("" ~== x[3:0]) | get(arg)
if not (pagelines := integer(pagelines)) then
stop("Invalid -p parameter: ",pagelines)
}
"t": {
tabsize := ("" ~== x[3:0]) | get(arg)
if not (tabsize := integer(tabsize)) then
stop("Invalid -t parameter: ",tabsize)
}
"h": noheaders := "yes"
"l": laser := "yes"
"g": {
gpat := ("" ~== x[3:0]) | get(arg)
}
"c": {
comment := ("" ~== x[3:0]) | get(arg)
}
"x": {
comment_end := ("" ~== x[3:0]) | get(arg)
}
"i": ignore_ff := "yes"
default: stop("Invalid option ",x)
}
}
else put(files,x)
}
if *files = 0 then stop("usage: iprint -options file ...\n_
options:\n_
\t-n\tnumber the lines\n_
\t-p N\tspecify lines per page (default 60)\n_
\t-t N\tspecify tab width (default 8)\n_
\t-h\tsuppress page headers\n_
\t-l\tadd 3 blank lines at top of each page\n_
\t-g S\tpattern for last line in group\n_
\t-c S\t'start of comment' string\n_
\t-x S\t'end of comment' string\n_
\t-i\tignore FF")
every x := !files do expand(x)
end
procedure expand(fn)
local f,line,cmd,linenbr,fname
f := open(fn) | stop("Can't open ",fn)
fn ? {
while tab(find("/")) & move(1)
fname := tab(0)
}
hstuff := fname || " " || datetime || " page "
title := subtitle := &null
lines := pagelines
page := 0 ; linenbr := 0
group := []
while line := trim(read(f)) do {
if \ignore_ff then while match("\f",line) do line[1] := ""
linenbr +:= 1
if match("\f",line) then {
dumpgroup()
lines := pagelines
repeat {
line[1] := ""
if not match("\f",line) then break
}
}
line ? {
if =comment & cmd := =("eject" | "title" | "subtitle") then {
dumpgroup()
case cmd of { # Command line
"title": (move(1) & title := trim(tab(find(comment_end)))) |
(title := &null)
"subtitle": (move(1) & subtitle := trim(tab(find(comment_end)))) |
(subtitle := &null)
}
lines := pagelines
}
else { # Ordinary (non-command) line
if not (*group = 0 & *line = 0) then {
put(group,line)
if \numbers then put(group,linenbr)
}
if endgroup(line) then dumpgroup()
}
}
}
dumpgroup()
close(f)
lines := pagelines
end
procedure dumpgroup()
local line,linenbr
if *group > 0 then {
if lines + *group / ((\numbers & 2) | 1) + 2 >= pagelines then
lines := pagelines
else {write("\n") ; lines +:= 2}
while line := get(group) do {
if \numbers then linenbr := get(group)
if lines >= pagelines then {
printhead()
}
if *line = 0 then {
if pagestatus ~== "empty" then {blanks +:= 1 ; lines +:= 1}
next
}
every 1 to blanks do write()
blanks := 0
pagestatus := "not empty"
if \numbers then writes(right(linenbr,5)," ")
write(detab(line))
lines +:= 1
}
}
return
end
procedure endgroup(s)
return match("" ~== gpat,s)
end
procedure printhead()
static ff,pg
writes(ff) ; ff := "\f"
lines := 0
pg := string(page +:= 1)
if /noheaders then {
if \laser then write("\n\n")
write(left(\title | "",79 - *hstuff - *pg),hstuff,pg)
lines +:= 2
write(\subtitle) & lines +:= 1
write()
}
pagestatus := "empty"
blanks := 0
return
end
procedure detab(s)
local t
t := ""
s ? {
while t ||:= tab(find("\t")) do {
t ||:= repl(" ",tabsize - *t % tabsize)
move(1)
}
t ||:= tab(0)
}
return t
end