af9631b09e7d4092dbd004c88cda70e07807c907
[shellsnippets/shellsnippets.git] / mksh / debian-dev / mkdebidx.sh
1 #!/bin/mksh
2 rcsid='$MirOS: contrib/hosted/tg/deb/mkdebidx.sh,v 1.56 2012/08/02 21:01:39 tg Exp $'
3 #-
4 # Copyright (c) 2008, 2009, 2010, 2011, 2012
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 armel armhf avr32 hppa hurd-i386 i386 \
37     ia64 kfreebsd-amd64 kfreebsd-i386 m68k mips mipsel powerpc powerpcspe \
38     ppc64 s390 s390x sh4 sparc sparc64
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         (( release_sign_detached )) && $gpg_remote gpg -u $repo_keyid \
232             -sab <$suite/Release-tmp >$suite/Release-sig
233         (( release_sign_inline )) && $gpg_remote gpg -u $repo_keyid \
234             --clearsign <$suite/Release-tmp >$suite/Release-inl
235
236         if (( release_sign_inline )); then
237                 mv -f $suite/Release-inl $suite/InRelease
238         else
239                 rm -f $suite/InRelease
240         fi
241         if (( release_sign_detached )); then
242                 mv -f $suite/Release-tmp $suite/Release
243                 mv -f $suite/Release-sig $suite/Release.gpg
244         else
245                 rm -f $suite/Release*
246         fi
247         rm -f $suite/Release-*
248 done
249
250 print "\n===> Creating debidx.htm\n"
251
252 set -A preplsrc
253 set -A prepldst
254 integer nsrc=0 nbin=0 nrpl=0
255 br='<br />'
256
257 # syntax:       ${suitename}/${distname}/${pN}/${pp} <suite>
258 # example:      sid/wtf/openntpd/i386 lenny
259 if [[ -s mkdebidx.lnk ]]; then
260         while read pn pd; do
261                 [[ $pn = '#'* ]] && continue
262                 if [[ $pn != +([a-z0-9_])/+([a-z0-9_-])/+([!/])/@(%|=|+([a-z0-9])) || \
263                     $pd != +([a-z0-9_]) ]]; then
264                         print -u2 "Invalid lnk line '$pn' '$pd'"
265                         continue
266                 fi
267                 preplsrc[nrpl]=$pn
268                 prepldst[nrpl++]=$pd
269         done <mkdebidx.lnk
270 fi
271
272 for suite in dists/*; do
273         for dist in $suite/*; do
274                 [[ -d $dist/. ]] || continue
275                 suitename=${suite##*/}
276                 if [[ $suitename != +([a-z0-9_]) ]]; then
277                         print -u2 "Invalid suite name '$suitename'"
278                         continue 2
279                 fi
280                 distname=${dist##*/}
281                 if [[ $distname != +([a-z0-9_-]) ]]; then
282                         print -u2 "Invalid dist name '$distname'"
283                         continue
284                 fi
285
286                 gzip -dc $dist/source/Sources.gz |&
287                 pn=; pv=; pd=; pp=; Lf=
288                 while IFS= read -pr line; do
289                         case $line {
290                         (" "*)
291                                 if [[ -n $Lf ]]; then
292                                         eval x=\$$Lf
293                                         x=$x$line
294                                         eval $Lf=\$x
295                                 fi
296                                 ;;
297                         ("Package: "*)
298                                 pn=${line##Package:*([   ])}
299                                 Lf=pn
300                                 ;;
301                         ("Version: "*)
302                                 pv=${line##Version:*([   ])}
303                                 Lf=pv
304                                 ;;
305                         ("Binary: "*)
306                                 pd=${line##Binary:*([    ])}
307                                 Lf=pd
308                                 ;;
309                         ("Directory: "*)
310                                 pp=${line##Directory:*([         ])}
311                                 Lf=pp
312                                 ;;
313                         (?*)    # anything else
314                                 Lf=
315                                 ;;
316                         (*)     # empty line
317                                 if [[ -n $pn && -n $pv && -n $pd && -n $pp ]]; then
318                                         i=0
319                                         while (( i < nsrc )); do
320                                                 [[ ${sp_name[i]} = "$pn" && \
321                                                     ${sp_dist[i]} = "$distname" ]] && break
322                                                 let i++
323                                         done
324                                         if (( i == nsrc )); then
325                                                 let nsrc++
326                                                 pvo=
327                                                 ppo=
328                                         else
329                                                 eval pvo=\$\{sp_ver_${suitename}[i]\}
330                                                 eval ppo=\$\{sp_dir_${suitename}[i]\}
331                                         fi
332                                         sp_name[i]=$pn
333                                         sp_dist[i]=$distname
334                                         #sp_suites[i]="${sp_suites[i]} $suitename"
335                                         if (( nrpl )); then
336                                                 x=${suitename}/${distname}/${pn}/source
337                                                 j=0
338                                                 while (( j < nrpl )); do
339                                                         [[ ${preplsrc[j]} = "$x" ]] && break
340                                                         let j++
341                                                 done
342                                                 (( j < nrpl )) && pv="${pv}\1afrom ${prepldst[j]}"
343                                         fi
344                                         eval sp_ver_${suitename}[i]='${pvo:+$pvo,}$pv'
345                                         eval sp_dir_${suitename}[i]='${ppo:+$ppo,}$pp/'
346                                         sp_desc[i]=${sp_desc[i]},$pd
347                                 fi
348                                 pn=; pv=; pd=; pp=; Lf=
349                                 ;;
350                         }
351                 done
352
353                 gzip -dc $(for f in $dist/binary-*/Packages.gz; do
354                         [[ -e $f ]] || continue
355                         realpath "$f"
356                 done | sort -u) |&
357                 pn=; pv=; pd=; pp=; pN=; pf=; Lf=
358                 while IFS= read -pr line; do
359                         case $line {
360                         (" "*)
361                                 if [[ -n $Lf ]]; then
362                                         eval x=\$$Lf
363                                         x=$x$line
364                                         eval $Lf=\$x
365                                 fi
366                                 ;;
367                         ("Package: "*)
368                                 pN=${line##Package:*([   ])}
369                                 Lf=pN
370                                 ;;
371                         ("Source: "*)
372                                 pn=${line##Source:*([    ])}
373                                 pn=${pn%% *}
374                                 Lf=pn
375                                 ;;
376                         ("Version: "*)
377                                 pv=${line##Version:*([   ])}
378                                 Lf=pv
379                                 ;;
380                         ("Description: "*)
381                                 pd=${line##Description:*([       ])}
382                                 ;;
383                         ("Architecture: "*)
384                                 pp=${line##Architecture:*([      ])}
385                                 Lf=pp
386                                 ;;
387                         ("Filename: "*)
388                                 pf=${line##Filename:*([  ])}
389                                 Lf=pf
390                                 ;;
391                         (?*)    # anything else
392                                 Lf=
393                                 ;;
394                         (*)     # empty line
395                                 if [[ $pf = *:* || $pf = *'%'* ]]; then
396                                         print -u2 Illegal character in $dist \
397                                             packages $pp "'Filename: $pf'"
398                                         exit 1
399                                 fi
400                                 [[ -n $pn ]] || pn=$pN
401                                 if [[ -n $pn && -n $pv && -n $pd && -n $pp ]]; then
402                                         i=0
403                                         while (( i < nbin )); do
404                                                 [[ ${bp_disp[i]} = "$pN" && ${bp_desc[i]} = "$pd" && \
405                                                     ${bp_dist[i]} = "$distname" ]] && break
406                                                 let i++
407                                         done
408                                         (( i == nbin )) && let nbin++
409                                         bp_name[i]=$pn
410                                         bp_disp[i]=$pN
411                                         bp_dist[i]=$distname
412                                         #bp_suites[i]="${bp_suites[i]} $suitename"
413                                         if (( nrpl )); then
414                                                 x=${suitename}/${distname}/${pN}/${pp}
415                                                 j=0
416                                                 while (( j < nrpl )); do
417                                                         [[ ${preplsrc[j]} = "$x" ]] && break
418                                                         let j++
419                                                 done
420                                                 (( j < nrpl )) && pv="from ${prepldst[j]}"
421                                         fi
422                                         [[ -n $pf ]] && pv="<a href=\"$pf\">$pv</a>"
423                                         pv="$pp: $pv"
424                                         eval x=\${bp_ver_${suitename}[i]}
425                                         [[ $br$x$br = *"$br$pv$br"* ]] || x=$x${x:+$br}$pv
426                                         eval bp_ver_${suitename}[i]=\$x
427                                         bp_desc[i]=$pd
428                                 fi
429                                 pn=; pv=; pd=; pp=; pN=; pf=; Lf=
430                                 ;;
431                         }
432                 done
433         done
434 done
435
436 (cat <<'EOF'
437 <?xml version="1.0"?>\r
438 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
439  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
440 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head>
441  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
442  <meta name="MSSmartTagsPreventParsing" content="TRUE" />
443 EOF
444 print -r -- " <title>${repo_title} Index</title>"
445 cat <<'EOF'
446  <meta name="generator" content="$MirOS: contrib/hosted/tg/deb/mkdebidx.sh,v 1.56 2012/08/02 21:01:39 tg Exp $" />
447  <style type="text/css">
448   table {
449    border: 1px solid black;
450    border-collapse: collapse;
451    text-align: left;
452    vertical-align: top;
453   }
454   tr {
455    border: 1px solid black;
456    text-align: left;
457    vertical-align: top;
458   }
459   td {
460    border: 1px solid black;
461    text-align: left;
462    vertical-align: top;
463   }
464   th {
465    background-color: #000000;
466    color: #FFFFFF;
467   }
468   .tableheadcell {
469    border: 1px solid #999999;
470    padding: 3px;
471    white-space: nowrap;
472   }
473   .srcpkgline {
474    background-color: #CCCCCC;
475   }
476   .srcpkgdist {
477    background-color: #666666;
478    color: #FFFFFF;
479    font-weight: bold;
480   }
481   .binpkgdist {
482    background-color: #999999;
483    color: #FFFFFF;
484    font-weight: bold;
485   }
486  </style>
487 </head><body>
488 EOF
489 print -r -- "<h1>${repo_title}</h1>"
490 cat <<'EOF'
491 <p><a href="dists/">Browse</a> the repository or read about how to amend <a
492  href="sources.txt">/etc/apt/sources.list</a> in order to use it.
493 EOF
494 [[ -s 0-NOTE.txt ]] && print ' Also read my <a href="0-NOTE.txt">notes</a>.'
495 cat <<EOF
496  This repository uses <a
497   href="http://pgp.uni-mainz.de:11371/pks/lookup?search=${repo_keyid}&amp;op=vindex">${repo_keyid}</a>
498  as signing key.
499 </p>
500 <h2>Suites</h2>
501 <ul>
502 EOF
503
504 allsuites=$(for suitename in $allsuites; do
505         print $suitename
506 done | sort -u)
507
508 for suitename in $allsuites; do
509         suite=dists/$suitename
510         . $suite/distinfo.sh
511         print -n " <li>${suite##*/}: <a href=\"$suite/\">$desc</a> (dists:"
512         for dist in $suite/*; do
513                 [[ -d $dist/. ]] || continue
514                 distname=${dist##*/}
515                 print -n " <a href=\"$suite/$distname/\">$distname</a>"
516         done
517         print ")</li>"
518 done
519 print "</ul>"
520 print "<h2>Packages</h2>"
521 print "<table width=\"100%\"><thead>"
522 print "<tr class=\"tablehead\">"
523 print " <th class=\"tableheadcell\">dist</th>"
524 print " <th class=\"tableheadcell\" rowspan=\"2\">Binary / Description</th>"
525 for suitename in $allsuites; do
526         print " <th class=\"tableheadcell\" rowspan=\"2\">$suitename</th>"
527 done
528 print "</tr><tr class=\"tablehead\">"
529 print " <th class=\"tableheadcell\">package name</th>"
530 print "</tr></thead><tbody>"
531
532 set -A bp_sort
533 i=0
534 while (( i < nbin )); do
535         print $i ${bp_disp[i++]} #${bp_suites[i]}
536 done | sort -k2 |&
537 while read -p num rest; do
538         bp_sort[${#bp_sort[*]}]=$num
539 done
540
541 i=0
542 while (( i < nsrc )); do
543         print $i ${sp_name[i++]}
544 done | sort -k2 |&
545 while read -p num rest; do
546         print "\n<!-- sp #$num = ${sp_name[num]} -->"
547         print "<tr class=\"srcpkgline\">"
548         print " <td class=\"srcpkgdist\">${sp_dist[num]}</td>"
549         pd=
550         for x in $(tr ', ' '\n' <<<"${sp_desc[num]}" | sort -u); do
551                 [[ -n $x ]] && pd="$pd, $x"
552         done
553         print " <td rowspan=\"2\" class=\"srcpkgdesc\">${pd#, }</td>"
554         for suitename in $allsuites; do
555                 eval pvo=\${sp_ver_${suitename}[num]}
556                 eval ppo=\${sp_dir_${suitename}[num]}
557                 IFS=,
558                 set -A pva -- $pvo
559                 set -A ppa -- $ppo
560                 IFS=$saveIFS
561                 (( ${#pva[*]} )) || pva[0]=
562                 y=
563                 i=0
564                 while (( i < ${#pva[*]} )); do
565                         pv=${pva[i]}
566                         pp=${ppa[i]}
567                         if [[ $pv = *"\1a"* ]]; then
568                                 pvdsc=${pv%%"\1a"*}
569                                 pv=${pv##*"\1a"}
570                         else
571                                 pvdsc=$pv
572                         fi
573                         if [[ -z $pv ]]; then
574                                 pv=-
575                                 if (( nrpl )); then
576                                         x=${suitename}/${sp_dist[num]}/${sp_name[num]}/%
577                                         j=0
578                                         while (( j < nrpl )); do
579                                                 [[ ${preplsrc[j]} = "$x" ]] && break
580                                                 let j++
581                                         done
582                                         (( j < nrpl )) && pv=${prepldst[j]}
583                                 fi
584                         elif [[ $pp != ?(/) ]]; then
585                                 pv="<a href=\"$pp${sp_name[num]}_${pvdsc##+([0-9]):}.dsc\">$pv</a>"
586                         fi
587                         [[ $pp != ?(/) ]] && pv="<a href=\"$pp\">[dir]</a> $pv"
588                         y=${y:+"$y<br />"}$pv
589                         let i++
590                 done
591                 print " <td rowspan=\"2\" class=\"srcpkgitem\">$y</td>"
592         done
593         print "</tr><tr class=\"srcpkgline\">"
594         print " <td class=\"srcpkgname\">${sp_name[num]}</td>"
595         print "</tr>"
596         k=0
597         while (( k < nbin )); do
598                 (( (i = bp_sort[k++]) < 0 )) && continue
599                 [[ ${bp_name[i]} = "${sp_name[num]}" && \
600                     ${bp_dist[i]} = "${sp_dist[num]}" ]] || continue
601                 bp_sort[k - 1]=-1
602                 #print "<!-- bp #$i for${bp_suites[i]} -->"
603                 print "<!-- bp #$i -->"
604                 print "<tr class=\"binpkgline\">"
605                 print " <td class=\"binpkgname\">${bp_disp[i]}</td>"
606                 print " <td class=\"binpkgdesc\">${bp_desc[i]}</td>"
607                 for suitename in $allsuites; do
608                         eval pv=\${bp_ver_${suitename}[i]}
609                         if [[ -z $pv ]]; then
610                                 pv=-
611                                 if (( nrpl )); then
612                                         x=${suitename}/${sp_dist[num]}/${sp_name[num]}/%
613                                         j=0
614                                         while (( j < nrpl )); do
615                                                 [[ ${preplsrc[j]} = "$x" ]] && break
616                                                 let j++
617                                         done
618                                         (( j < nrpl )) && pv=${prepldst[j]}
619                                 fi
620                         fi
621                         print " <td class=\"binpkgitem\">$pv</td>"
622                 done
623                 print "</tr>"
624         done
625 done
626
627 num=0
628 for i in ${bp_sort[*]}; do
629         (( i < 0 )) && continue
630         if (( !num )); then
631                 print "\n<!-- sp ENOENT -->"
632                 print "<tr class=\"srcpkgline\">"
633                 print " <td class=\"srcpkgname\">~ENOENT~</td>"
634                 print " <td class=\"srcpkgdesc\">binary" \
635                     "packages without a matching source package</td>"
636                 for suitename in $allsuites; do
637                         print " <td class=\"srcpkgitem\">-</td>"
638                 done
639                 print "</tr>"
640                 num=1
641         fi
642         #print "<!-- bp #$i for${bp_suites[i]} -->"
643         print "<!-- bp #$i -->"
644         print "<tr class=\"binpkgline\">"
645         print " <td class=\"binpkgdist\">${bp_dist[i]}</td>"
646         print " <td rowspan=\"2\" class=\"binpkgdesc\">${bp_desc[i]}</td>"
647         for suitename in $allsuites; do
648                 eval pv=\${bp_ver_${suitename}[i]}
649                 if [[ -z $pv ]]; then
650                         pv=-
651                         if (( nrpl )); then
652                                 x=${suitename}/${bp_dist[num]}/${bp_disp[num]}/=
653                                 j=0
654                                 while (( j < nrpl )); do
655                                         [[ ${preplsrc[j]} = "$x" ]] && break
656                                         let j++
657                                 done
658                                 (( j < nrpl )) && pv=${prepldst[j]}
659                         fi
660                 fi
661                 print " <td rowspan=\"2\" class=\"binpkgitem\">$pv</td>"
662         done
663         print "</tr><tr class=\"binpkgline\">"
664         print " <td class=\"binpkgname\">${bp_disp[i]}</td>"
665         print "</tr>"
666 done
667
668 cat <<EOF
669
670 </tbody></table>
671
672 <p>• <a href="http://validator.w3.org/check/referer">Valid XHTML/1.1!</a>
673  • <small>Generated on $(date -u +'%F %T') by <tt
674  style="white-space:pre;">$rcsid</tt></small> •</p>
675 </body></html>
676 EOF
677
678 :) >debidx.htm
679 print done.