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