4 # @(#) pages.sh 1.0 92/09/26
5 # 92/09/05 John H. DuBois III (jhdiii@armory.com)
8 # conversion to bash v2 syntax by Chet Ramey
10 Usage
="$0 [-h] [-n lines/page] page-ranges [file ...]"
19 echo "$0: print selected pages.
22 If no file names are given, the standard input is read.
24 The input is grouped into pages and a selected subset of them is printed.
25 Formfeeds are acted on correctly.
27 If the output device does automatic line wrap, lines that longer than
28 the width of the output device will result in incorrect output.
29 The first non-option argument is a list of pages to print.
31 Pages are given as a list of ranges separated by commas.
32 A range is either one number, two numbers separted by a dash,
33 or one number followed by a dash. A range consisting of one
34 number followed by a dash extends to the end of the document.
37 -n sets the number of lines per page to n. The default is 66."
40 while getopts "n:h" opt
; do
42 n
) LinesPerPage
=$OPTARG;;
48 shift $
(($OPTIND - 1))
51 echo $0: no page ranges given.
1>&2
61 PageList = \"$PageList\"; LinesPerPage = \"$LinesPerPage\""'
62 if (LinesPerPage == "")
65 if (LinesPerPage !~ "[1-9][0-9]*")
66 ErrExit("Bad value for lines per page: " LinesPerPage)
68 NumRanges = split(PageList,Ranges,",")
69 for (i = 1; i <= NumRanges; i++) {
70 if ((StartRange = EndRange = Ranges[i]) !~ "^[0-9]+(-([0-9]+)?)?$")
71 ErrExit("Bad range \"" StartRange "\"")
72 sub("-.*","",StartRange)
73 sub(".*-","",EndRange)
76 # Force StartRange and EndRange to be numeric values
77 if ((StartRange += 0) == 0 || (EndRange += 0) == 0)
78 ErrExit("Invalid page number \"0\" in range " Ranges[i])
79 if (StartRange > EndRange)
80 ErrExit("Start page comes after end page in range " Ranges[i])
81 TmpRangeStarts[i] = StartRange
82 TmpRangeEnds[i] = EndRange
86 qsort(TmpRangeStarts,k)
88 for (i = 1; i <= NumRanges; i++) {
89 RangeEnds[i] = TmpRangeEnds[k[i]]
90 if ((RangeStarts[i] = TmpRangeStarts[k[i]]) <= RangeEnds[i - 1])
91 ErrExit("Overlapping ranges: " Ranges[k[i]] "," Ranges[k[i - 1]])
94 RangeNum = LineNum = PageNum = 1
95 InRange = In(PageNum,RangeStarts[RangeNum],RangeEnds[RangeNum])
100 if (LineNum > LinesPerPage)
104 # Deal with formfeeds
105 for (i = 2; i <= NF; i++) {
120 # At the start of each page, check whether we are in a print range
121 WereInRange = InRange
122 InRange = In(PageNum,RangeStarts[RangeNum],RangeEnds[RangeNum])
123 # If last page was in range and we no longer are, move to next range
124 if (WereInRange && !InRange && ++RangeNum > NumRanges)
128 function In(a,Min,Max) {
129 return (Min <= a && a <= Max)
132 function ErrExit(S) {
133 print S > "/dev/stderr"
138 # Arr is an array of values with arbitrary indices.
139 # Array k is returned with numeric indices 1..n.
140 # The values in k are the indices of array arr,
141 # ordered so that if array arr is stepped through
142 # in the order arr[k[1]] .. arr[k[n]], it will be stepped
143 # through in order of the values of its elements.
144 # The return value is the number of elements in the array (n).
145 function qsort(arr,k, ArrInd,end) {
149 qsortseg(arr,k,1,end);
153 function qsortseg(arr,k,start,end, left,right,sepval,tmp,tmpe,tmps) {
154 # handle two-element case explicitely for a tiny speedup
155 if ((end - start) == 1) {
156 if (arr[tmps = k[start]] > arr[tmpe = k[end]]) {
164 sepval = arr[k[int((left + right) / 2)]]
165 # Make every element <= sepval be to the left of every element > sepval
166 while (left < right) {
167 while (arr[k[left]] < sepval)
169 while (arr[k[right]] > sepval)
178 if (arr[k[left]] < sepval)
183 qsortseg(arr,k,start,right)
185 qsortseg(arr,k,left,end)