updates from MirBSD CVS
[shellsnippets/shellsnippets.git] / mksh / debian-dev / mkdebidx.sh
1 #!/bin/mksh
2 rcsid='$MirOS: contrib/hosted/tg/deb/mkdebidx.sh,v 1.58 2013/03/18 16:55:37 tg Exp $'
3 #-
4 # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013
5 #       Thorsten Glaser <tg@mirbsd.org>
6 #
7 # Provided that these terms and disclaimer and all copyright notices
8 # are retained or reproduced in an accompanying document, permission
9 # is granted to deal in this work without restriction, including un-
10 # limited rights to use, publicly perform, distribute, sell, modify,
11 # merge, give away, or sublicence.
12 #
13 # This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
14 # the utmost extent permitted by applicable law, neither express nor
15 # implied; without malicious intent or gross negligence. In no event
16 # may a licensor, author or contributor be held liable for indirect,
17 # direct, other damage, loss, or other issues arising in any way out
18 # of dealing in the work, even if advised of the possibility of such
19 # damage or existence of a defect, except proven that it results out
20 # of said person's immediate fault when using the work as intended.
21
22 set -A normarchs -- i386
23 repo_keyid=0x405422DD
24 # either '' (locally) or 'remsign user@host.domain.com' (remote ssh)
25 gpg_remote=
26 repo_origin='The MirOS Project'
27 repo_label=wtf
28 repo_title='MirDebian “WTF” Repository'
29 function repo_description {
30         typeset suite_nick=$1
31
32         print -nr -- "WTF ${suite_nick} Repository"
33 }
34
35
36 set -A dpkgarchs -- alpha amd64 arm arm64 armel armhf hppa hurd-i386 i386 \
37     ia64 kfreebsd-amd64 kfreebsd-i386 m68k mips mipsel powerpc powerpcspe \
38     ppc64 s390 s390x sh4 sparc sparc64 x32
39
40 function remsign {
41         target=$1; shift
42         master=remsign.ctl$$
43         tmpfnm=remsign.tmp$$
44         ssh -fNM -o ControlPath=$tmpfnm "$target"
45         ssh -o ControlPath=$tmpfnm "$target" cat \>$tmpfnm
46         ssh -o ControlPath=$tmpfnm -t "$target" "$* $tmpfnm" 0<&2 1>&2
47         rv=$?
48         ssh -o ControlPath=$tmpfnm "$target" "cat $tmpfnm.asc; rm -f $tmpfnm $tmpfnm.asc"
49         ssh -o ControlPath=$tmpfnm "$target" -O exit
50         return $rv
51 }
52
53 function putfile {
54         tee $1 | gzip -n9 >$1.gz
55 }
56
57 function sortlist {
58         typeset x u=$1
59
60         if [[ $u = -u ]]; then
61                 shift
62         else
63                 u=
64         fi
65
66         for x in "$@"; do
67                 print -r -- "$x"
68         done | sort $u
69 }
70
71 # DJB cdb hash (not via stdio, for speed)
72 typeset -Z11 -Uui16 Lcdbhash_result
73 function Lcdbhash_add {
74         typeset s="$*"
75         typeset -i i=0 n=${#s}
76
77         while (( i < n )); do
78                 ((# Lcdbhash_result = (Lcdbhash_result * 33) ^ 1#${s:(i++):1} ))
79         done
80 }
81
82 set +U
83 export LC_ALL=C
84 unset LANGUAGE
85 saveIFS=$IFS
86 cd "$(dirname "$0")"
87 rm -f dpkg_578162_workaround
88
89 IFS=:
90 dpkgarchl=:all:"${dpkgarchs[*]}":
91 IFS=$saveIFS
92
93 suites=:
94 for suite in "$@"; do
95         suites=:dists/$suite$suites
96 done
97
98 allsuites=
99 for suite in dists/*; do
100         allsuites="$allsuites${allsuites:+ }${suite##*/}"
101         [[ $suites = : || $suites = *:"$suite":* ]] || continue
102         archs=
103         distribution=
104         debootstrap_compat=0
105         . $suite/distinfo.sh
106         suitearchs=${archs:-${normarchs[*]}}
107         components=Components:
108         for dist in $suite/*; do
109                 [[ -d $dist/. ]] || continue
110                 rm -rf $dist/binary-* $dist/source
111                 ovf= oef= osf= om=-m
112                 (( debootstrap_compat )) && om=
113                 [[ -s $dist/override.file ]] && ovf=$dist/override.file
114                 [[ -s $dist/override.extra ]] && oef="-e $dist/override.extra"
115                 [[ -s $dist/override.src ]] && osf="-s $dist/override.src"
116                 components="$components ${dist##*/}"
117                 archs=
118                 [[ -s $dist/distinfo.sh ]] && . $dist/distinfo.sh
119                 set -A distarchs -- $(sortlist -u all ${archs:-$suitearchs})
120                 IFS=:; distarchl=:"${distarchs[*]}":; IFS=$saveIFS
121                 nmds=0
122                 for arch in $(sortlist -u ${distarchs[*]} ${dpkgarchs[*]}) /; do
123                         # put "all" last
124                         [[ $arch = all ]] && continue
125                         [[ $arch = / ]] && arch=all
126                         # create index
127                         if [[ $dpkgarchl != *:"$arch":* ]]; then
128                                 print -u2 "Invalid arch '$arch' in $dist"
129                                 exit 1
130                         elif [[ $distarchl != *:"$arch":* ]]; then
131                                 print "\n===> Linking all =>" \
132                                     "${dist#dists/}/$arch/Packages"
133                                 ln -s binary-all $dist/binary-$arch
134                         elif [[ $arch = all ]] && (( nmds == 1 )); then
135                                 print "\n===> Linking $firstmd =>" \
136                                     "${dist#dists/}/all/Packages"
137                                 ln -s binary-$firstmd $dist/binary-all
138                         else
139                                 print "\n===> Creating" \
140                                     "${dist#dists/}/$arch/Packages\n"
141                                 mkdir -p $dist/binary-$arch
142                                 dpkg-scanpackages $oef $om -a $arch \
143                                     $dist $ovf | \
144                                     putfile $dist/binary-$arch/Packages
145                                 (( nmds++ )) || firstmd=$arch
146                         fi
147                 done
148                 print "\n===> Creating ${dist#dists/}/Sources"
149                 mkdir -p $dist/source
150                 [[ -e dpkg_578162_workaround ]] || (dpkg-scansources $oef $osf \
151                     $dist $ovf || touch dpkg_578162_workaround) | \
152                     putfile $dist/source/Sources
153                 [[ -e dpkg_578162_workaround ]] && dpkg-scansources $osf \
154                     $dist $ovf | \
155                     putfile $dist/source/Sources
156                 print done.
157         done
158         print "\n===> Creating ${suite#dists/}/Release"
159         rm -f $suite/Release-*
160         (cat <<-EOF
161                 Origin: ${repo_origin}
162                 Label: ${repo_label}
163                 Suite: ${distribution:-${suite##*/}}
164                 Codename: ${suite##*/}
165                 Date: $(date -u)
166                 Architectures: all ${dpkgarchs[*]} source
167                 $components
168                 Description: $(repo_description "$nick")
169                 MD5Sum:
170         EOF
171         exec 4>$suite/Release-sha1
172         exec 5>$suite/Release-sha2
173         print -u4 SHA1:
174         print -u5 SHA256:
175         cd $suite
176         set -A cache_fn
177         set -A cache_md5
178         set -A cache_sha1
179         set -A cache_sha2
180         set -A cache_size
181         for n in Contents-* */{binary-*,source}/{Packag,Sourc}es*; do
182                 [[ -f $n ]] || continue
183                 # realpath-ise $n and cache the checksum
184                 nn=$(realpath "$n")
185                 #XXX once mksh can, use associative arrays instead
186                 Lcdbhash_result=5381
187                 Lcdbhash_add "$nn"
188                 # simple hash collision solver by increment
189                 nc=${cache_fn[Lcdbhash_result]}
190                 while [[ -n $nc && $nc != "$nn" ]]; do
191                         nc=${cache_fn[++Lcdbhash_result]}
192                 done
193                 if [[ $nc = "$nn" ]]; then
194                         nm=${cache_md5[Lcdbhash_result]}
195                         ns=${cache_size[Lcdbhash_result]}
196                         nsha1=${cache_sha1[Lcdbhash_result]}
197                         nsha2=${cache_sha2[Lcdbhash_result]}
198                 else
199                         # GNU *sum tools are horridly inefficient
200                         set -A x -- $(md5sum "$nn")
201                         nm=${x[0]}
202                         set -A x -- $(sha1sum "$nn")
203                         nsha1=${x[0]}
204                         set -A x -- $(sha256sum "$nn")
205                         nsha2=${x[0]}
206                         ns=$(stat -c '%s' "$nn")
207                         cache_md5[Lcdbhash_result]=$nm
208                         cache_size[Lcdbhash_result]=$ns
209                         cache_fn[Lcdbhash_result]=$nn
210                         cache_sha1[Lcdbhash_result]=$nsha1
211                         cache_sha2[Lcdbhash_result]=$nsha2
212                 fi
213                 print " $nm $ns $n"
214                 print -u4 " $nsha1 $ns $n"
215                 print -u5 " $nsha2 $ns $n"
216         done) >$suite/Release-tmp
217         cat $suite/Release-sha1 $suite/Release-sha2 >>$suite/Release-tmp
218
219         # note: InRelease files can only be safely used by wheezy
220         # onwards, and oneiric onwards; known to be insecure on
221         # natty, but usable concurrent to detached files on squeeze
222
223         unset release_sign_detached release_sign_inline
224         release_sign_detached=x
225         release_sign_inline=0
226         . $suite/distinfo.sh
227         [[ $release_sign_inline = [01] ]] || release_sign_inline=0
228         [[ $release_sign_detached = [01] ]] || \
229             (( release_sign_detached = release_sign_inline ? 0 : 1 ))
230
231         # Debian's fix for CVE-2013-1051 consists of disabling
232         # support for InRelease files altogether (WTF!)
233         release_sign_detached=1
234         release_sign_inline=0
235
236         (( release_sign_detached )) && $gpg_remote gpg -u $repo_keyid \
237             -sab <$suite/Release-tmp >$suite/Release-sig
238         (( release_sign_inline )) && $gpg_remote gpg -u $repo_keyid \
239             --clearsign <$suite/Release-tmp >$suite/Release-inl
240
241         if (( release_sign_inline )); then
242                 mv -f $suite/Release-inl $suite/InRelease
243         else
244                 rm -f $suite/InRelease
245         fi
246         if (( release_sign_detached )); then
247                 mv -f $suite/Release-tmp $suite/Release
248                 mv -f $suite/Release-sig $suite/Release.gpg
249         else
250                 rm -f $suite/Release*
251         fi
252         rm -f $suite/Release-*
253 done
254
255 print "\n===> Creating debidx.htm\n"
256
257 set -A preplsrc
258 set -A prepldst
259 integer nsrc=0 nbin=0 nrpl=0
260 br='<br />'
261
262 # syntax:       ${suitename}/${distname}/${pN}/${pp} <suite>
263 # example:      sid/wtf/openntpd/i386 lenny
264 if [[ -s mkdebidx.lnk ]]; then
265         while read pn pd; do
266                 [[ $pn = '#'* ]] && continue
267                 if [[ $pn != +([a-z0-9_])/+([a-z0-9_-])/+([!/])/@(%|=|+([a-z0-9])) || \
268                     $pd != +([a-z0-9_]) ]]; then
269                         print -u2 "Invalid lnk line '$pn' '$pd'"
270                         continue
271                 fi
272                 preplsrc[nrpl]=$pn
273                 prepldst[nrpl++]=$pd
274         done <mkdebidx.lnk
275 fi
276
277 for suite in dists/*; do
278         for dist in $suite/*; do
279                 [[ -d $dist/. ]] || continue
280                 suitename=${suite##*/}
281                 if [[ $suitename != +([a-z0-9_]) ]]; then
282                         print -u2 "Invalid suite name '$suitename'"
283                         continue 2
284                 fi
285                 distname=${dist##*/}
286                 if [[ $distname != +([a-z0-9_-]) ]]; then
287                         print -u2 "Invalid dist name '$distname'"
288                         continue
289                 fi
290
291                 gzip -dc $dist/source/Sources.gz |&
292                 pn=; pv=; pd=; pp=; Lf=
293                 while IFS= read -pr line; do
294                         case $line {
295                         (" "*)
296                                 if [[ -n $Lf ]]; then
297                                         eval x=\$$Lf
298                                         x=$x$line
299                                         eval $Lf=\$x
300                                 fi
301                                 ;;
302                         ("Package: "*)
303                                 pn=${line##Package:*([   ])}
304                                 Lf=pn
305                                 ;;
306                         ("Version: "*)
307                                 pv=${line##Version:*([   ])}
308                                 Lf=pv
309                                 ;;
310                         ("Binary: "*)
311                                 pd=${line##Binary:*([    ])}
312                                 Lf=pd
313                                 ;;
314                         ("Directory: "*)
315                                 pp=${line##Directory:*([         ])}
316                                 Lf=pp
317                                 ;;
318                         (?*)    # anything else
319                                 Lf=
320                                 ;;
321                         (*)     # empty line
322                                 if [[ -n $pn && -n $pv && -n $pd && -n $pp ]]; then
323                                         i=0
324                                         while (( i < nsrc )); do
325                                                 [[ ${sp_name[i]} = "$pn" && \
326                                                     ${sp_dist[i]} = "$distname" ]] && break
327                                                 let i++
328                                         done
329                                         if (( i == nsrc )); then
330                                                 let nsrc++
331                                                 pvo=
332                                                 ppo=
333                                         else
334                                                 eval pvo=\$\{sp_ver_${suitename}[i]\}
335                                                 eval ppo=\$\{sp_dir_${suitename}[i]\}
336                                         fi
337                                         sp_name[i]=$pn
338                                         sp_dist[i]=$distname
339                                         #sp_suites[i]="${sp_suites[i]} $suitename"
340                                         if (( nrpl )); then
341                                                 x=${suitename}/${distname}/${pn}/source
342                                                 j=0
343                                                 while (( j < nrpl )); do
344                                                         [[ ${preplsrc[j]} = "$x" ]] && break
345                                                         let j++
346                                                 done
347                                                 (( j < nrpl )) && pv="${pv}\1afrom ${prepldst[j]}"
348                                         fi
349                                         eval sp_ver_${suitename}[i]='${pvo:+$pvo,}$pv'
350                                         eval sp_dir_${suitename}[i]='${ppo:+$ppo,}$pp/'
351                                         sp_desc[i]=${sp_desc[i]},$pd
352                                 fi
353                                 pn=; pv=; pd=; pp=; Lf=
354                                 ;;
355                         }
356                 done
357
358                 gzip -dc $(for f in $dist/binary-*/Packages.gz; do
359                         [[ -e $f ]] || continue
360                         realpath "$f"
361                 done | sort -u) |&
362                 pn=; pv=; pd=; pp=; pN=; pf=; Lf=
363                 while IFS= read -pr line; do
364                         case $line {
365                         (" "*)
366                                 if [[ -n $Lf ]]; then
367                                         eval x=\$$Lf
368                                         x=$x$line
369                                         eval $Lf=\$x
370                                 fi
371                                 ;;
372                         ("Package: "*)
373                                 pN=${line##Package:*([   ])}
374                                 Lf=pN
375                                 ;;
376                         ("Source: "*)
377                                 pn=${line##Source:*([    ])}
378                                 pn=${pn%% *}
379                                 Lf=pn
380                                 ;;
381                         ("Version: "*)
382                                 pv=${line##Version:*([   ])}
383                                 Lf=pv
384                                 ;;
385                         ("Description: "*)
386                                 pd=${line##Description:*([       ])}
387                                 ;;
388                         ("Architecture: "*)
389                                 pp=${line##Architecture:*([      ])}
390                                 Lf=pp
391                                 ;;
392                         ("Filename: "*)
393                                 pf=${line##Filename:*([  ])}
394                                 Lf=pf
395                                 ;;
396                         (?*)    # anything else
397                                 Lf=
398                                 ;;
399                         (*)     # empty line
400                                 if [[ $pf = *:* || $pf = *'%'* ]]; then
401                                         print -u2 Illegal character in $dist \
402                                             packages $pp "'Filename: $pf'"
403                                         exit 1
404                                 fi
405                                 [[ -n $pn ]] || pn=$pN
406                                 if [[ -n $pn && -n $pv && -n $pd && -n $pp ]]; then
407                                         i=0
408                                         while (( i < nbin )); do
409                                                 [[ ${bp_disp[i]} = "$pN" && ${bp_desc[i]} = "$pd" && \
410                                                     ${bp_dist[i]} = "$distname" ]] && break
411                                                 let i++
412                                         done
413                                         (( i == nbin )) && let nbin++
414                                         bp_name[i]=$pn
415                                         bp_disp[i]=$pN
416                                         bp_dist[i]=$distname
417                                         #bp_suites[i]="${bp_suites[i]} $suitename"
418                                         if (( nrpl )); then
419                                                 x=${suitename}/${distname}/${pN}/${pp}
420                                                 j=0
421                                                 while (( j < nrpl )); do
422                                                         [[ ${preplsrc[j]} = "$x" ]] && break
423                                                         let j++
424                                                 done
425                                                 (( j < nrpl )) && pv="from ${prepldst[j]}"
426                                         fi
427                                         [[ -n $pf ]] && pv="<a href=\"$pf\">$pv</a>"
428                                         pv="$pp: $pv"
429                                         eval x=\${bp_ver_${suitename}[i]}
430                                         [[ $br$x$br = *"$br$pv$br"* ]] || x=$x${x:+$br}$pv
431                                         eval bp_ver_${suitename}[i]=\$x
432                                         bp_desc[i]=$pd
433                                 fi
434                                 pn=; pv=; pd=; pp=; pN=; pf=; Lf=
435                                 ;;
436                         }
437                 done
438         done
439 done
440
441 (cat <<'EOF'
442 <?xml version="1.0"?>\r
443 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
444  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
445 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head>
446  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
447  <meta name="MSSmartTagsPreventParsing" content="TRUE" />
448 EOF
449 print -r -- " <title>${repo_title} Index</title>"
450 cat <<'EOF'
451  <meta name="generator" content="$MirOS: contrib/hosted/tg/deb/mkdebidx.sh,v 1.58 2013/03/18 16:55:37 tg Exp $" />
452  <style type="text/css">
453   table {
454    border: 1px solid black;
455    border-collapse: collapse;
456    text-align: left;
457    vertical-align: top;
458   }
459   tr {
460    border: 1px solid black;
461    text-align: left;
462    vertical-align: top;
463   }
464   td {
465    border: 1px solid black;
466    text-align: left;
467    vertical-align: top;
468   }
469   th {
470    background-color: #000000;
471    color: #FFFFFF;
472   }
473   .tableheadcell {
474    border: 1px solid #999999;
475    padding: 3px;
476    white-space: nowrap;
477   }
478   .srcpkgline {
479    background-color: #CCCCCC;
480   }
481   .srcpkgdist {
482    background-color: #666666;
483    color: #FFFFFF;
484    font-weight: bold;
485   }
486   .binpkgdist {
487    background-color: #999999;
488    color: #FFFFFF;
489    font-weight: bold;
490   }
491  </style>
492 </head><body>
493 EOF
494 print -r -- "<h1>${repo_title}</h1>"
495 cat <<'EOF'
496 <p><a href="dists/">Browse</a> the repository or read about how to amend <a
497  href="sources.txt">/etc/apt/sources.list</a> in order to use it.
498 EOF
499 [[ -s 0-NOTE.txt ]] && print ' Also read my <a href="0-NOTE.txt">notes</a>.'
500 cat <<EOF
501  This repository uses <a
502   href="http://pgp.uni-mainz.de:11371/pks/lookup?search=${repo_keyid}&amp;op=vindex">${repo_keyid}</a>
503  as signing key.
504 </p>
505 <h2>Suites</h2>
506 <ul>
507 EOF
508
509 allsuites=$(for suitename in $allsuites; do
510         print $suitename
511 done | sort -u)
512
513 for suitename in $allsuites; do
514         suite=dists/$suitename
515         . $suite/distinfo.sh
516         print -n " <li>${suite##*/}: <a href=\"$suite/\">$desc</a> (dists:"
517         for dist in $suite/*; do
518                 [[ -d $dist/. ]] || continue
519                 distname=${dist##*/}
520                 print -n " <a href=\"$suite/$distname/\">$distname</a>"
521         done
522         print ")</li>"
523 done
524 print "</ul>"
525 print "<h2>Packages</h2>"
526 print "<table width=\"100%\"><thead>"
527 print "<tr class=\"tablehead\">"
528 print " <th class=\"tableheadcell\">dist</th>"
529 print " <th class=\"tableheadcell\" rowspan=\"2\">Binary / Description</th>"
530 for suitename in $allsuites; do
531         print " <th class=\"tableheadcell\" rowspan=\"2\">$suitename</th>"
532 done
533 print "</tr><tr class=\"tablehead\">"
534 print " <th class=\"tableheadcell\">package name</th>"
535 print "</tr></thead><tbody>"
536
537 set -A bp_sort
538 i=0
539 while (( i < nbin )); do
540         print $i ${bp_disp[i++]} #${bp_suites[i]}
541 done | sort -k2 |&
542 while read -p num rest; do
543         bp_sort[${#bp_sort[*]}]=$num
544 done
545
546 i=0
547 while (( i < nsrc )); do
548         print $i ${sp_name[i++]}
549 done | sort -k2 |&
550 while read -p num rest; do
551         print "\n<!-- sp #$num = ${sp_name[num]} -->"
552         print "<tr class=\"srcpkgline\">"
553         print " <td class=\"srcpkgdist\">${sp_dist[num]}</td>"
554         pd=
555         for x in $(tr ', ' '\n' <<<"${sp_desc[num]}" | sort -u); do
556                 [[ -n $x ]] && pd="$pd, $x"
557         done
558         print " <td rowspan=\"2\" class=\"srcpkgdesc\">${pd#, }</td>"
559         for suitename in $allsuites; do
560                 eval pvo=\${sp_ver_${suitename}[num]}
561                 eval ppo=\${sp_dir_${suitename}[num]}
562                 IFS=,
563                 set -A pva -- $pvo
564                 set -A ppa -- $ppo
565                 IFS=$saveIFS
566                 (( ${#pva[*]} )) || pva[0]=
567                 y=
568                 i=0
569                 while (( i < ${#pva[*]} )); do
570                         pv=${pva[i]}
571                         pp=${ppa[i]}
572                         if [[ $pv = *"\1a"* ]]; then
573                                 pvdsc=${pv%%"\1a"*}
574                                 pv=${pv##*"\1a"}
575                         else
576                                 pvdsc=$pv
577                         fi
578                         if [[ -z $pv ]]; then
579                                 pv=-
580                                 if (( nrpl )); then
581                                         x=${suitename}/${sp_dist[num]}/${sp_name[num]}/%
582                                         j=0
583                                         while (( j < nrpl )); do
584                                                 [[ ${preplsrc[j]} = "$x" ]] && break
585                                                 let j++
586                                         done
587                                         (( j < nrpl )) && pv=${prepldst[j]}
588                                 fi
589                         elif [[ $pp != ?(/) ]]; then
590                                 pv="<a href=\"$pp${sp_name[num]}_${pvdsc##+([0-9]):}.dsc\">$pv</a>"
591                         fi
592                         [[ $pp != ?(/) ]] && pv="<a href=\"$pp\">[dir]</a> $pv"
593                         y=${y:+"$y<br />"}$pv
594                         let i++
595                 done
596                 print " <td rowspan=\"2\" class=\"srcpkgitem\">$y</td>"
597         done
598         print "</tr><tr class=\"srcpkgline\">"
599         print " <td class=\"srcpkgname\">${sp_name[num]}</td>"
600         print "</tr>"
601         k=0
602         while (( k < nbin )); do
603                 (( (i = bp_sort[k++]) < 0 )) && continue
604                 [[ ${bp_name[i]} = "${sp_name[num]}" && \
605                     ${bp_dist[i]} = "${sp_dist[num]}" ]] || continue
606                 bp_sort[k - 1]=-1
607                 #print "<!-- bp #$i for${bp_suites[i]} -->"
608                 print "<!-- bp #$i -->"
609                 print "<tr class=\"binpkgline\">"
610                 print " <td class=\"binpkgname\">${bp_disp[i]}</td>"
611                 print " <td class=\"binpkgdesc\">${bp_desc[i]}</td>"
612                 for suitename in $allsuites; do
613                         eval pv=\${bp_ver_${suitename}[i]}
614                         if [[ -z $pv ]]; then
615                                 pv=-
616                                 if (( nrpl )); then
617                                         x=${suitename}/${sp_dist[num]}/${sp_name[num]}/%
618                                         j=0
619                                         while (( j < nrpl )); do
620                                                 [[ ${preplsrc[j]} = "$x" ]] && break
621                                                 let j++
622                                         done
623                                         (( j < nrpl )) && pv=${prepldst[j]}
624                                 fi
625                         fi
626                         print " <td class=\"binpkgitem\">$pv</td>"
627                 done
628                 print "</tr>"
629         done
630 done
631
632 num=0
633 for i in ${bp_sort[*]}; do
634         (( i < 0 )) && continue
635         if (( !num )); then
636                 print "\n<!-- sp ENOENT -->"
637                 print "<tr class=\"srcpkgline\">"
638                 print " <td class=\"srcpkgname\">~ENOENT~</td>"
639                 print " <td class=\"srcpkgdesc\">binary" \
640                     "packages without a matching source package</td>"
641                 for suitename in $allsuites; do
642                         print " <td class=\"srcpkgitem\">-</td>"
643                 done
644                 print "</tr>"
645                 num=1
646         fi
647         #print "<!-- bp #$i for${bp_suites[i]} -->"
648         print "<!-- bp #$i -->"
649         print "<tr class=\"binpkgline\">"
650         print " <td class=\"binpkgdist\">${bp_dist[i]}</td>"
651         print " <td rowspan=\"2\" class=\"binpkgdesc\">${bp_desc[i]}</td>"
652         for suitename in $allsuites; do
653                 eval pv=\${bp_ver_${suitename}[i]}
654                 if [[ -z $pv ]]; then
655                         pv=-
656                         if (( nrpl )); then
657                                 x=${suitename}/${bp_dist[num]}/${bp_disp[num]}/=
658                                 j=0
659                                 while (( j < nrpl )); do
660                                         [[ ${preplsrc[j]} = "$x" ]] && break
661                                         let j++
662                                 done
663                                 (( j < nrpl )) && pv=${prepldst[j]}
664                         fi
665                 fi
666                 print " <td rowspan=\"2\" class=\"binpkgitem\">$pv</td>"
667         done
668         print "</tr><tr class=\"binpkgline\">"
669         print " <td class=\"binpkgname\">${bp_disp[i]}</td>"
670         print "</tr>"
671 done
672
673 cat <<EOF
674
675 </tbody></table>
676
677 <p>• <a href="http://validator.w3.org/check/referer">Valid XHTML/1.1!</a>
678  • <small>Generated on $(date -u +'%F %T') by <tt
679  style="white-space:pre;">$rcsid</tt></small> •</p>
680 </body></html>
681 EOF
682
683 :) >debidx.htm
684 print done.