done_progress_bar shan’t output a newline; fix from ⮡ tarent
[shellsnippets/shellsnippets.git] / mksh / bdfctool.sh
1 #!/bin/mksh
2 # $MirOS: X11/extras/bdfctool/bdfctool.sh,v 1.12 2013/05/17 21:51:40 tg Exp $
3 #-
4 # Copyright © 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 -o noglob
23
24 uascii=-1
25 ufast=0
26 while getopts "acdeFh" ch; do
27         case $ch {
28         (a) uascii=1 ;;
29         (+a) uascii=0 ;;
30         (c|d|e|+e) mode=$ch ;;
31         (F) ufast=1 ;;
32         (+F) ufast=0 ;;
33         (h) mode=$ch ;;
34         (*) mode= ;;
35         }
36 done
37 shift $((OPTIND - 1))
38 (( $# )) && mode=
39
40 if [[ $mode = ?(h) ]] || [[ $mode != e && $uascii != -1 ]] || \
41     [[ $mode != d && $ufast != 0 ]]; then
42         print -ru2 "Usage: ${0##*/} -c | -d [-F] | -e [-a] | +e"
43         [[ $mode = h ]]; exit $?
44 fi
45
46 lno=0
47 if [[ $mode = e ]]; then
48         if (( uascii == 1 )); then
49                 set -A BITv -- '.' '#' '|'
50         else
51                 set -A BITv -- ' ' '䷀' '▌'
52         fi
53         while IFS= read -r line; do
54                 (( ++lno ))
55                 if [[ $line = 'e '* ]]; then
56                         set -A f -- $line
57                         i=${f[3]}
58                         print -r -- "$line"
59                         while (( i-- )); do
60                                 if IFS= read -r line; then
61                                         print -r -- "$line"
62                                         continue
63                                 fi
64                                 print -ru2 "E: Unexpected end of 'e' command" \
65                                     "at line $lno"
66                                 exit 2
67                         done
68                         (( lno += f[3] ))
69                         continue
70                 fi
71                 if [[ $line != 'c '* ]]; then
72                         print -r -- "$line"
73                         continue
74                 fi
75                 set -A f -- $line
76                 if (( (w = f[2]) > 32 || w < 1 )); then
77                         print -ru2 "E: width ${f[2]} not in 1‥32 at line $lno"
78                         exit 2
79                 fi
80                 if (( w <= 8 )); then
81                         adds=000000
82                 elif (( w <= 16 )); then
83                         adds=0000
84                 elif (( w <= 24 )); then
85                         adds=00
86                 else
87                         adds=
88                 fi
89                 (( shiftbits = 32 - w ))
90                 (( uw = 2 + w ))
91                 IFS=:
92                 set -A bmp -- ${f[3]}
93                 IFS=$' \t\n'
94                 f[0]=e
95                 f[3]=${#bmp[*]}
96                 print -r -- "${f[*]}"
97                 chl=0
98                 for ch in "${bmp[@]}"; do
99                         (( ++chl ))
100                         if [[ $ch != +([0-9A-F]) ]]; then
101                                 print -ru2 "E: char '$ch' at #$chl in line $lno not hex"
102                                 exit 2
103                         fi
104                         ch=$ch$adds
105                         if (( ${#ch} != 8 )); then
106                                 print -ru2 "E: char '$ch' at #$chl in line $lno not valid"
107                                 exit 2
108                         fi
109                         typeset -Uui2 -Z$uw bbin=16#$ch
110                         (( bbin >>= shiftbits ))
111                         b=${bbin#2#}
112                         b=${b//0/${BITv[0]}}
113                         b=${b//1/${BITv[1]}}
114                         print -r -- $b${BITv[2]}
115                 done
116         done
117         exit 0
118 fi
119
120 Fdef=           # currently valid 'd' line
121 set -A Fhead    # lines of file header, including comments intersparsed
122 set -A Fprop    # lines of file properties, same
123 set -A Gprop    # glyph property line (from Fdef), per glyph
124 set -A Gdata    # glyph data line, per glyph
125 set -A Gcomm    # glyph comments (if any) as string, per glyph
126 set -A Fcomm    # lines of comments at end of file
127
128 state=0
129
130 function parse_bdfc_file {
131         local last
132
133         set -A last
134         while IFS= read -r line; do
135                 (( ++lno ))
136                 if [[ $line = C ]]; then
137                         Fprop+=("${last[@]}")
138                         state=1
139                         return
140                 elif [[ $line = '=bdfc 1' ]]; then
141                         continue
142                 fi
143                 last+=("$line")
144                 [[ $line = \' || $line = "' "* ]] && continue
145                 if [[ $line = h* ]]; then
146                         Fhead+=("${last[@]}")
147                 elif [[ $line = p* ]]; then
148                         Fprop+=("${last[@]}")
149                 else
150                         print -ru2 "E: invalid line #$lno: '$line'"
151                         exit 2
152                 fi
153                 set -A last
154         done
155         Fprop+=("${last[@]}")
156         state=2
157 }
158
159 function parse_bdfc_edit {
160         local w shiftbits uw line r i
161
162         if (( (w = f[2]) <= 8 )); then
163                 (( shiftbits = 8 - w ))
164                 (( uw = 5 ))
165         elif (( w <= 16 )); then
166                 (( shiftbits = 16 - w ))
167                 (( uw = 7 ))
168         elif (( w <= 24 )); then
169                 (( shiftbits = 24 - w ))
170                 (( uw = 9 ))
171         else
172                 (( shiftbits = 32 - w ))
173                 (( uw = 11 ))
174         fi
175
176         if (( (i = f[3]) < 1 || i > 999 )); then
177                 print -ru2 "E: nonsensical number of lines '${f[3]}' in" \
178                     "line $lno, U+${ch#16#}"
179                 exit 2
180         fi
181
182         while (( i-- )); do
183                 if ! IFS= read -r line; then
184                         print -ru2 "E: Unexpected end of 'e' command" \
185                             "at line $lno, U+${ch#16#}"
186                         exit 2
187                 fi
188                 (( ++lno ))
189                 linx=${line// /.}
190                 linx=${linx//䷀/#}
191                 linx=${linx//▌/|}
192                 linx=${linx//[ .]/0}
193                 linx=${linx//[#*]/1}
194                 if [[ $linx != +([01])'|' || ${#linx} != $((w + 1)) ]]; then
195                         print -ru2 "E: U+${ch#16#} (line #$lno) bitmap line" \
196                             $((f[3] - i)) "invalid: '$line'"
197                         exit 2
198                 fi
199                 linx=${linx%'|'}
200                 typeset -Uui16 -Z$uw bhex=2#$linx
201                 (( bhex <<= shiftbits ))
202                 r+=${bhex#16#}:
203         done
204         f[3]=${r%:}
205         f[0]=c
206 }
207
208 function parse_bdfc_glyph {
209         local last
210
211         set -A last
212         while IFS= read -r line; do
213                 (( ++lno ))
214                 if [[ $line = . ]]; then
215                         Fcomm+=("${last[@]}")
216                         state=0
217                         return
218                 fi
219                 if [[ $line = \' || $line = "' "* ]]; then
220                         last+=("$line")
221                         continue
222                 fi
223                 set -A f -- $line
224                 if [[ ${f[0]} = d ]]; then
225                         Fdef="${f[*]}"
226                         continue
227                 fi
228                 if [[ ${f[0]} != [ce] ]]; then
229                         print -ru2 "E: invalid line #$lno: '$line'"
230                         exit 2
231                 fi
232                 if [[ $Fdef != 'd '* ]]; then
233                         print -ru2 "E: char at line $lno without defaults set"
234                         exit 2
235                 fi
236                 if [[ ${f[1]} != [0-9A-F][0-9A-F][0-9A-F][0-9A-F] ]]; then
237                         print -ru2 "E: invalid encoding '${f[1]}' at line $lno"
238                         exit 2
239                 fi
240                 typeset -Uui16 -Z7 ch=16#${f[1]}
241                 if (( ${#f[*]} < 4 || ${#f[*]} > 5 )); then
242                         print -ru2 "E: invalid number of fields on line $lno" \
243                             "at U+${ch#16#}: ${#f[*]}: '$line'"
244                         exit 2
245                 fi
246                 if (( f[2] < 1 || f[2] > 32 )); then
247                         print -ru2 "E: width ${f[2]} not in 1‥32 at line $lno"
248                         exit 2
249                 fi
250                 [[ ${f[4]} = "uni${ch#16#}" ]] && unset f[4]
251                 if [[ ${f[0]} = e ]]; then
252                         parse_bdfc_edit
253                 else
254                         if (( f[2] <= 8 )); then
255                                 x='+([0-9A-F][0-9A-F]:)'
256                         elif (( f[2] <= 16 )); then
257                                 x='+([0-9A-F][0-9A-F][0-9A-F][0-9A-F]:)'
258                         elif (( f[2] <= 24 )); then
259                                 x='+([0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]:)'
260                         else
261                                 x='+([0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]:)'
262                         fi
263                         if eval [[ '${f[3]}:' != "$x" ]]; then
264                                 print -ru2 "E: invalid hex encoding for" \
265                                     "U+${ch#16#}, line $lno: '${f[3]}'"
266                                 exit 2
267                         fi
268                 fi
269                 Gdata[ch]="${f[*]}"
270                 for line in "${last[@]}"; do
271                         Gcomm[ch]+=$line$'\n'
272                 done
273                 set -A last
274                 Gprop[ch]=$Fdef
275         done
276         Fcomm+=("${last[@]}")
277         state=2
278 }
279
280 function parse_bdfc {
281         while :; do
282                 case $state {
283                 (0) parse_bdfc_file ;;
284                 (1) parse_bdfc_glyph ;;
285                 (2) return 0 ;;
286                 }
287         done
288         print -ru2 "E: internal error (at line $lno), shouldn't happen"
289         exit 255
290 }
291
292 function parse_bdf {
293         while IFS= read -r line; do
294                 (( ++lno ))
295                 case $line {
296                 (COMMENT)
297                         Fhead+=("'")
298                         ;;
299                 (COMMENT@([      ])*)
300                         Fhead+=("' ${line#COMMENT[       ]}")
301                         ;;
302                 (STARTPROPERTIES\ +([0-9]))
303                         break
304                         ;;
305                 (*)
306                         Fhead+=("h$line")
307                         ;;
308                 }
309         done
310         set -A f -- $line
311         numprop=${f[1]}
312         while IFS= read -r line; do
313                 (( ++lno ))
314                 case $line {
315                 (COMMENT)
316                         Fprop+=("'")
317                         ;;
318                 (COMMENT@([      ])*)
319                         Fprop+=("' ${line#COMMENT[       ]}")
320                         ;;
321                 (ENDPROPERTIES)
322                         break
323                         ;;
324                 (*)
325                         Fprop+=("p$line")
326                         let --numprop
327                         ;;
328                 }
329         done
330         if (( numprop )); then
331                 print -ru2 "E: expected ${f[1]} properties, got" \
332                     "$((f[1] - numprop)) in line $lno"
333                 exit 2
334         fi
335         while IFS= read -r line; do
336                 (( ++lno ))
337                 case $line {
338                 (COMMENT)
339                         Fprop+=("'")
340                         ;;
341                 (COMMENT@([      ])*)
342                         Fprop+=("' ${line#COMMENT[       ]}")
343                         ;;
344                 (CHARS\ +([0-9]))
345                         break
346                         ;;
347                 (*)
348                         print -ru2 "E: expected CHARS not '$line' in line $lno"
349                         exit 2
350                         ;;
351                 }
352         done
353         set -A f -- $line
354         numchar=${f[1]}
355         set -A cc
356         set -A cn
357         set -A ce
358         set -A cs
359         set -A cd
360         set -A cb
361         while IFS= read -r line; do
362                 (( ++lno ))
363                 case $line {
364                 (COMMENT)
365                         cc+=("'")
366                         ;;
367                 (COMMENT@([      ])*)
368                         cc+=("' ${line#COMMENT[  ]}")
369                         ;;
370                 (STARTCHAR\ *)
371                         set -A cn -- $line
372                         ;;
373                 (ENCODING\ +([0-9]))
374                         set -A ce -- $line
375                         ;;
376                 (SWIDTH\ +([0-9-])\ +([0-9-]))
377                         set -A cs -- $line
378                         ;;
379                 (DWIDTH\ +([0-9-])\ +([0-9-]))
380                         set -A cd -- $line
381                         ;;
382                 (BBX\ +([0-9])\ +([0-9])\ +([0-9-])\ +([0-9-]))
383                         set -A cb -- $line
384                         ;;
385                 (BITMAP)
386                         if [[ -z $cn ]]; then
387                                 print -ru2 "E: missing STARTCHAR in line $lno"
388                                 exit 2
389                         fi
390                         if [[ -z $ce ]]; then
391                                 print -ru2 "E: missing ENCODING in line $lno"
392                                 exit 2
393                         fi
394                         if [[ -z $cs ]]; then
395                                 print -ru2 "E: missing SWIDTH in line $lno"
396                                 exit 2
397                         fi
398                         if [[ -z $cd ]]; then
399                                 print -ru2 "E: missing DWIDTH in line $lno"
400                                 exit 2
401                         fi
402                         if [[ -z $cb ]]; then
403                                 print -ru2 "E: missing BBX in line $lno"
404                                 exit 2
405                         fi
406                         typeset -Uui16 -Z7 ch=10#${ce[1]}
407                         if (( ch < 0 || ch > 0xFFFF )); then
408                                 print -ru2 "E: encoding ${ce[1]} out of" \
409                                     "bounds in line $lno"
410                                 exit 2
411                         fi
412                         Gprop[ch]="d ${cs[1]} ${cs[2]} ${cd[1]} ${cd[2]} ${cb[3]} ${cb[4]}"
413                         set -A f c ${ch#16#} ${cb[1]} - ${cn[1]}
414                         [[ ${f[4]} = "uni${ch#16#}" ]] && unset f[4]
415                         if (( f[2] <= 8 )); then
416                                 ck='[0-9A-F][0-9A-F]'
417                         elif (( f[2] <= 16 )); then
418                                 ck='[0-9A-F][0-9A-F][0-9A-F][0-9A-F]'
419                         elif (( f[2] <= 24 )); then
420                                 ck='[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]'
421                         else
422                                 ck='[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]'
423                         fi
424                         if (( (numlines = cb[2]) )); then
425                                 bmps=
426                                 typeset -u linu
427                                 while IFS= read -r linu; do
428                                         (( ++lno ))
429                                         if eval [[ '$linu' != "$ck" ]]; then
430                                                 print -ru2 "E: invalid hex encoding" \
431                                                     "for U+${ch#16#} (dec. $((ch)))" \
432                                                     "on line $lno: '$linu'"
433                                                 exit 2
434                                         fi
435                                         bmps+=$linu:
436                                         (( --numlines )) || break
437                                 done
438                                 f[3]=${bmps%:}
439                         else
440                                 f[2]=1
441                                 f[3]=00
442                         fi
443                         if ! IFS= read -r line || [[ $line != ENDCHAR ]]; then
444                                 print -ru2 "E: expected ENDCHAR after line $lno"
445                                 exit 2
446                         fi
447                         (( ++lno ))
448                         Gdata[ch]="${f[*]}"
449                         [[ -n $cc ]] && for line in "${cc[@]}"; do
450                                 Gcomm[ch]+=$line$'\n'
451                         done
452                         set -A cc
453                         set -A cn
454                         set -A ce
455                         set -A cs
456                         set -A cd
457                         set -A cb
458                         ;;
459                 (ENDFONT)
460                         break
461                         ;;
462                 (*)
463                         print -ru2 "E: unexpected '$line' in line $lno"
464                         exit 2
465                         ;;
466                 }
467         done
468         Fcomm+=("${cc[@]}")
469         for line in "${cn[*]}" "${ce[*]}" "${cs[*]}" "${cd[*]}" "${cb[*]}"; do
470                 [[ -n $line ]] || continue
471                 print -ru2 "E: unexpected '$line' between last char and ENDFONT"
472                 exit 2
473         done
474         if (( numchar != ${#Gdata[*]} )); then
475                 print -ru2 "E: expected $numchar glyphs, got ${#Gdata[*]}"
476                 exit 2
477         fi
478         while IFS= read -r line; do
479                 (( ++lno ))
480                 case $line {
481                 (COMMENT)
482                         Fcomm+=("'")
483                         ;;
484                 (COMMENT@([      ])*)
485                         Fcomm+=("' ${line#COMMENT[       ]}")
486                         ;;
487                 (*)
488                         print -ru2 "E: unexpected '$line' past ENDFONT" \
489                             "in line $lno"
490                         exit 2
491                         ;;
492                 }
493         done
494 }
495
496 if [[ $mode = c ]]; then
497         if ! IFS= read -r line; then
498                 print -ru2 "E: read error at BOF"
499                 exit 2
500         fi
501         lno=1
502         if [[ $line = 'STARTFONT 2.1' ]]; then
503                 parse_bdf
504         elif [[ $line = '=bdfc 1' ]]; then
505                 parse_bdfc
506         else
507                 print -ru2 "E: not BDF or bdfc at BOF: '$line'"
508                 exit 2
509         fi
510
511         # write .bdfc stream
512
513         for line in '=bdfc 1' "${Fhead[@]}" "${Fprop[@]}"; do
514                 print -r -- "$line"
515         done
516         print C
517         Fdef=
518         for x in ${!Gdata[*]}; do
519                 if [[ ${Gprop[x]} != "$Fdef" ]]; then
520                         Fdef=${Gprop[x]}
521                         print -r -- $Fdef
522                 fi
523                 print -r -- "${Gcomm[x]}${Gdata[x]}"
524         done
525         for line in "${Fcomm[@]}"; do
526                 print -r -- "$line"
527         done
528         print .
529         exit 0
530 fi
531
532 if [[ $mode = +e ]]; then
533         while IFS= read -r line; do
534                 (( ++lno ))
535                 if [[ $line = \' || $line = "' "* ]]; then
536                         print -r -- "$line"
537                         continue
538                 fi
539                 set -A f -- $line
540                 if [[ ${f[0]} != [ce] ]]; then
541                         print -ru2 "E: invalid line #$lno: '$line'"
542                         exit 2
543                 fi
544                 if [[ ${f[1]} != [0-9A-F][0-9A-F][0-9A-F][0-9A-F] ]]; then
545                         print -ru2 "E: invalid encoding '${f[1]}' at line $lno"
546                         exit 2
547                 fi
548                 typeset -Uui16 -Z7 ch=16#${f[1]}
549                 if (( ${#f[*]} < 4 || ${#f[*]} > 5 )); then
550                         print -ru2 "E: invalid number of fields on line $lno" \
551                             "at U+${ch#16#}: ${#f[*]}: '$line'"
552                         exit 2
553                 fi
554                 if (( f[2] < 1 || f[2] > 32 )); then
555                         print -ru2 "E: width ${f[2]} not in 1‥32 at line $lno"
556                         exit 2
557                 fi
558                 [[ ${f[4]} = "uni${ch#16#}" ]] && unset f[4]
559                 if [[ ${f[0]} = e ]]; then
560                         parse_bdfc_edit
561                 else
562                         if (( f[2] <= 8 )); then
563                                 x='+([0-9A-F][0-9A-F]:)'
564                         elif (( f[2] <= 16 )); then
565                                 x='+([0-9A-F][0-9A-F][0-9A-F][0-9A-F]:)'
566                         elif (( f[2] <= 24 )); then
567                                 x='+([0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]:)'
568                         else
569                                 x='+([0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]:)'
570                         fi
571                         if eval [[ '${f[3]}:' != "$x" ]]; then
572                                 print -ru2 "E: invalid hex encoding for" \
573                                     "U+${ch#16#}, line $lno: '${f[3]}'"
574                                 exit 2
575                         fi
576                 fi
577                 print -r -- "${f[@]}"
578         done
579         exit 0
580 fi
581
582 if [[ $mode != d ]]; then
583         print -ru2 "E: cannot happen (control flow issue in ${0##*/}:$LINENO)"
584         exit 255
585 fi
586
587 if ! IFS= read -r line; then
588         print -ru2 "E: read error at BOF"
589         exit 2
590 fi
591 lno=1
592 if [[ $line != '=bdfc 1' ]]; then
593         print -ru2 "E: not bdfc at BOF: '$line'"
594         exit 2
595 fi
596
597 if (( ufast )); then
598         if ! T=$(mktemp /tmp/bdfctool.XXXXXXXXXX); then
599                 print -u2 E: cannot make temporary file
600                 exit 4
601         fi
602         # quickly parse bdfc header
603         set -A last
604         while IFS= read -r line; do
605                 [[ $line = C ]] && break
606                 last+=("$line")
607                 [[ $line = \' || $line = "' "* ]] && continue
608                 if [[ $line = h* ]]; then
609                         Fhead+=("${last[@]}")
610                 else
611                         Fprop+=("${last[@]}")
612                 fi
613                 set -A last
614         done
615         Fprop+=("${last[@]}")
616 else
617         # parse entire bdfc file into memory
618         parse_bdfc
619 fi
620
621 # analyse data for BDF
622 numprop=0
623 for line in "${Fprop[@]}"; do
624         [[ $line = p* ]] && let ++numprop
625 done
626 (( ufast )) || numchar=${#Gdata[*]}
627
628 # write BDF stream
629 print 'STARTFONT 2.1'
630 for line in "${Fhead[@]}"; do
631         if [[ $line = h* ]]; then
632                 print -r -- "${line#h}"
633         else
634                 print -r -- "COMMENT${line#\'}"
635         fi
636 done
637 set -A last
638 print STARTPROPERTIES $((numprop))
639 for line in "${Fprop[@]}"; do
640         if [[ $line = p* ]]; then
641                 last+=("${line#p}")
642         else
643                 last+=("COMMENT${line#\'}")
644                 continue
645         fi
646         for line in "${last[@]}"; do
647                 print -r -- "$line"
648         done
649         set -A last
650 done
651 print ENDPROPERTIES
652 for line in "${last[@]}"; do
653         print -r -- "$line"
654 done
655 if (( ufast )); then
656         numchar=0
657         # directly transform font data
658         set -A last
659         while IFS= read -r line; do
660                 [[ $line = . ]] && break
661                 if [[ $line = \' || $line = "' "* ]]; then
662                         last+=("$line")
663                         continue
664                 fi
665                 set -A f -- $line
666                 if [[ ${f[0]} = d ]]; then
667                         set -A xprop -- $line
668                         continue
669                 fi
670                 typeset -Uui16 -Z7 ch=16#${f[1]}
671                 for line in "${last[@]}"; do
672                         print -r -- "COMMENT${line#\'}"
673                 done
674                 set -A last
675                 IFS=:
676                 set -A bmp -- ${f[3]}
677                 IFS=$' \t\n'
678                 cat <<-EOF
679                         STARTCHAR ${f[4]:-uni${ch#16#}}
680                         ENCODING $((ch))
681                         SWIDTH ${xprop[1]} ${xprop[2]}
682                         DWIDTH ${xprop[3]} ${xprop[4]}
683                         BBX ${f[2]} ${#bmp[*]} ${xprop[5]} ${xprop[6]}
684                         BITMAP
685                 EOF
686                 for line in "${bmp[@]}"; do
687                         print $line
688                 done
689                 print ENDCHAR
690                 let ++numchar
691         done >"$T"
692         Fcomm+=("${last[@]}")
693         print CHARS $((numchar))
694         cat "$T"
695         rm -f "$T"
696 else
697         print CHARS $((numchar))
698         for x in ${!Gdata[*]}; do
699                 IFS=$'\n'
700                 set -A xcomm -- ${Gcomm[x]}
701                 IFS=$' \t\n'
702                 for line in "${xcomm[@]}"; do
703                         print -r -- "COMMENT${line#\'}"
704                 done
705                 set -A xprop -- ${Gprop[x]}
706                 set -A f -- ${Gdata[x]}
707                 IFS=:
708                 set -A bmp -- ${f[3]}
709                 IFS=$' \t\n'
710                 typeset -Uui16 -Z7 ch=16#${f[1]}
711                 cat <<-EOF
712                         STARTCHAR ${f[4]:-uni${ch#16#}}
713                         ENCODING $((ch))
714                         SWIDTH ${xprop[1]} ${xprop[2]}
715                         DWIDTH ${xprop[3]} ${xprop[4]}
716                         BBX ${f[2]} ${#bmp[*]} ${xprop[5]} ${xprop[6]}
717                         BITMAP
718                 EOF
719                 for line in "${bmp[@]}"; do
720                         print $line
721                 done
722                 print ENDCHAR
723         done
724 fi
725 for line in "${Fcomm[@]}"; do
726         print -r -- "COMMENT${line#\'}"
727 done
728 print ENDFONT
729 exit 0