xref: /freebsd/contrib/ncurses/misc/ncu2openbsd (revision 5b56413d04e608379c9a306373554a8e4d321bc0)
1#!/usr/bin/env perl
2# $Id: ncu2openbsd,v 1.67 2023/09/09 15:59:17 tom Exp $
3# -----------------------------------------------------------------------------
4# Copyright 2021,2023 by Thomas E. Dickey
5#
6#                         All Rights Reserved
7#
8# Permission is hereby granted, free of charge, to any person obtaining a
9# copy of this software and associated documentation files (the
10# "Software"), to deal in the Software without restriction, including
11# without limitation the rights to use, copy, modify, merge, publish,
12# distribute, sublicense, and/or sell copies of the Software, and to
13# permit persons to whom the Software is furnished to do so, subject to
14# the following conditions:
15#
16# The above copyright notice and this permission notice shall be included
17# in all copies or substantial portions of the Software.
18#
19# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22# IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
23# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26#
27# Except as contained in this notice, the name(s) of the above copyright
28# holders shall not be used in advertising or otherwise to promote the
29# sale, use or other dealings in this Software without prior written
30# authorization.
31# -----------------------------------------------------------------------------
32# https://invisible-island.net/ncurses/ncurses-openbsd.html
33#
34# Update the OpenBSD source-tree given an ncurses tarball or build-tree.
35
36use strict;
37use warnings;
38
39use Getopt::Std;
40use Cwd;
41use Cwd 'abs_path';
42use File::Path qw/ remove_tree /;
43use File::Temp qw/ tempdir /;
44
45$| = 1;
46
47our ( $opt_d, $opt_n, $opt_r, $opt_t, $opt_v, $opt_x, $opt_6 );
48our $source_dir;
49our $target_dir;
50our $update_dir;
51our $backup_dir;
52
53our $tempdir = tempdir( CLEANUP => 1 );
54my $current = getcwd;
55my $working = $current;
56
57our $generated_by = "generated by: ncu2openbsd";
58
59our %setup_dir = qw(
60  lib/libcurses         ncurses
61  lib/libform           form
62  lib/libmenu           menu
63  lib/libpanel          panel
64  usr.bin/infocmp       progs
65  usr.bin/tabs          progs
66  usr.bin/tic           progs
67  usr.bin/toe           progs
68  usr.bin/tput          progs
69  usr.bin/tset          progs
70  share/termtypes       misc
71);
72
73our %generated = qw(
74  codes.c 1
75  comp_captab.c         1
76  comp_userdefs.c       1
77  expanded.c            1
78  fallback.c            1
79  init_keytry.h         1
80  keys.list             1
81  lib_gen.c             1
82  lib_keyname.c         1
83  make_hash             1
84  make_keys             1
85  names.c               1
86  termsort.c            1
87  unctrl.c              1
88);
89
90our %definitions = qw(
91  CAPTOINFO             captoinfo
92  DATADIR               /usr/share
93  INFOCMP               infocmp
94  INFOTOCAP             infotocap
95  NCURSES_MAJOR         5
96  NCURSES_MINOR         7
97  NCURSES_OSPEED        int
98  NCURSES_PATCH         20081102
99  TERMINFO              /usr/share/terminfo
100  TIC                   tic
101  TOE                   toe
102  TPUT                  tput
103  TSET                  tset
104);
105
106sub patchdate() {
107    return $definitions{"NCURSES_PATCH"};
108}
109
110sub failed($) {
111    chdir $current;
112    printf STDERR "? %s\n", $_[0];
113    exit;
114}
115
116sub verbose($) {
117    my $text = shift;
118    printf "%s\n", $text if ($opt_v);
119}
120
121sub read_file($) {
122    my $name = shift;
123    open( my $fp, $name ) || &failed("cannot open $name");
124    my (@input) = <$fp>;
125    chomp @input;
126    close($fp);
127    return @input;
128}
129
130sub read_dir($) {
131    my $path = shift;
132    my @result;
133    if ( opendir( my $dh, $path ) ) {
134        my @data = sort readdir($dh);
135        closedir $dh;
136        for my $d ( 0 .. $#data ) {
137            next if ( $data[$d] =~ /^\.(\.)?$/ );
138            next if ( -l $path . "/" . $data[$d] );
139            $result[ $#result + 1 ] = $data[$d];
140        }
141    }
142    return @result;
143}
144
145sub rename_dir($$) {
146    my $src = shift;
147    my $dst = shift;
148    printf "%% mv %s -> %s\n", $src, $dst if ($opt_v);
149    rename $src, $dst unless ($opt_n);
150}
151
152sub check_sourcedir($) {
153    my $path = shift;
154    &failed("not a directory: $path") unless ( -d $path );
155    my $full = abs_path($path);
156    chdir $full;
157    &failed("not an ncurses source-tree: $path")
158      unless ( -f "NEWS" and -f "dist.mk" );
159    $source_dir = $full;
160}
161
162sub unpack($) {
163    my $path    = shift;
164    my $full    = abs_path($path);
165    my $command = "";
166    if ( $path =~ /\.tgz$/ or $path =~ /\.tar\.gz$/ ) {
167        $command = "tar xzf %s";
168    }
169    elsif ( $path =~ /\.zip$/ ) {
170        $command = "unzip -q %s";
171    }
172    else {
173        &failed("not a gzip'd tarball or zip-file: $path");
174    }
175    chdir $tempdir;
176    system( sprintf( $command, $full ) );
177
178    # there should be exactly one subdirectory -- the source-tree
179    my @data = &read_dir(".");
180    &failed("found no subdirectories of $path") if ( $#data < 0 );
181    &failed( "too many subdirectories: " . $data[0] . " vs " . $data[1] )
182      if ( $#data > 0 );
183    &check_sourcedir( $data[0] );
184}
185
186sub remove_dir($) {
187    my $tree = shift;
188    if ( -d $tree ) {
189        printf "%% rm -rf %s\n", $tree if ($opt_v);
190        remove_tree( $tree, $opt_v ? 1 : 0, 1 ) unless ($opt_n);
191    }
192}
193
194sub copy_CVS($) {
195    my $leaf    = shift;
196    my $src     = $target_dir . $leaf . "/CVS";
197    my $dst     = $update_dir . $leaf . "/CVS";
198    my $verbose = $opt_v ? "v" : "";
199    if ( -d $src and !-d $dst ) {
200        my $mid = $update_dir . $leaf;
201        mkdir $mid unless ( -d $mid );
202        mkdir $dst unless ( -d $dst );
203        system("cp -a$verbose $src/* $dst/");
204    }
205}
206
207sub is_tic_code($) {
208    my $item   = shift;
209    my $result = 0;
210    $result = 1
211      if (
212        $item =~ /^(capconvert
213                   |tic
214                   |dump
215                   |progs
216                   |termsort
217                   |transform
218                   |MKtermsort)/x
219      );
220    return $result;
221}
222
223sub is_ident($$) {
224    my $name = shift;
225    my $text = shift;
226    my $code = 0;
227    $code = 1 if ( $text =~ /\$$name:.*\$/ );
228    return $code;
229}
230
231# We "could", filter out differences with ident's using the diff -I option,
232# but in practice, that is cumbersome.
233sub munge_ident($) {
234    my $target = shift;
235    my $source = $target;
236    $source =~ s/\.update\b//;
237    &failed("bug at $source") if ( $source eq $target );
238    return unless ( -f $source );
239    my @source = &read_file($source);
240    my @target = &read_file($target);
241    my $old_id = "";
242    my $gap_id = 0;
243    my $new_id = "";
244    my $skipit = -1;
245
246    for my $n ( 0 .. $#source ) {
247        if ( &is_ident( "OpenBSD", $source[$n] ) ) {
248            $old_id = $source[$n];
249            $skipit = $n + 1;
250        }
251        elsif ( &is_ident( "Id", $source[$n] ) ) {
252            $new_id = $source[$n];
253            last;
254        }
255        elsif ( $n == $skipit ) {
256            $source[$n] =~ s/\s+$//;
257            if ( $source[$n] eq "" ) {
258                $gap_id = $source[$n];
259            }
260            elsif ( $source[$n] eq '.\"' ) {
261                $gap_id = $source[$n];
262            }
263        }
264    }
265    if ( $old_id ne "" ) {
266        my @update;
267        my $tables = &uses_tables($target);
268        $update[ $#update + 1 ] = $target[0] if ($tables);
269        $update[ $#update + 1 ] = $old_id;
270        $update[ $#update + 1 ] = $gap_id unless ( $gap_id eq 0 );
271        for my $n ( $tables .. $#target ) {
272            if ( &is_ident( "Id", $target[$n] ) ) {
273                $update[ $#update + 1 ] = $new_id;
274            }
275            else {
276                $update[ $#update + 1 ] = $target[$n];
277            }
278        }
279        system("chmod u+w $target");
280        if ( open my $fp, ">", $target ) {
281            for my $n ( 0 .. $#update ) {
282                printf $fp "%s\n", $update[$n];
283            }
284            close $fp;
285            system("chmod u-w $target");
286        }
287    }
288}
289
290# ncurses manual pages provide for renaming the utilities, normally as part of
291# the scripts provided in its sources.  OpenBSD developers do not use those.
292sub munge_docs($) {
293    my $path = shift;
294    my @data = &read_file($path);
295    my $done = 0;
296    for my $n ( 0 .. $#data ) {
297        my $text = $data[$n];
298        $text =~ s/\b1M\b/1/g;
299        $text =~ s/\b3X\b/3/g;
300        $text =~ s/\bcurs_(term(info|cap)\s*3\b)/$1/g;
301        $text =~ s/(\\fB)curs_(term(info|cap)\\f[RP]\(3\))/$1$2/g;
302        my $left = "";
303        while ( $text =~ /@[[:alnum:]_]+@/ ) {
304            my $next = index( $text, "@" );
305            last if ( $next < 0 );
306            $left .= substr( $text, 0, $next++ );
307            $text = substr( $text, $next );
308            $next = index( $text, "@" );
309            last if ( $next < 0 );
310            my $word = substr( $text, 0, $next );
311            if ( $word =~ /^[[:alnum:]_]+/ ) {
312
313                if ( $definitions{$word} ) {
314                    $word = $definitions{$word};
315                }
316                else {
317                    $word = "?";
318                }
319                $left .= $word;
320                $text = substr( $text, $next + 1 );
321            }
322            else {
323                &failed("unexpected definition @$word@");
324            }
325        }
326        $text = $left . $text;
327        if ( $text ne $data[$n] ) {
328            $done++;
329            $data[$n] = $text;
330        }
331    }
332    if ($done) {
333        system("chmod u+w $path");
334        if ( open my $fp, ">", $path ) {
335            for my $n ( 0 .. $#data ) {
336                printf $fp "%s\n", $data[$n];
337            }
338            close $fp;
339            system("chmod u-w $path");
340        }
341    }
342}
343
344sub copy_file($$) {
345    my $src     = shift;
346    my $dst     = shift;
347    my $verbose = $opt_v ? "v" : "";
348    if ( -d $dst ) {
349        my $leaf = $src;
350        $leaf =~ s,^.*/,,;
351        $dst .= "/" . $leaf;
352    }
353    system("chmod u+w $dst") if ( -f $dst );
354    system("cp -a$verbose $src $dst");
355    &munge_ident($dst);
356}
357
358sub copy_code($) {
359    my $src = shift;
360    my $dst = shift;
361    &copy_CVS( substr( $dst, length($update_dir) ) );
362    printf ".. copying files for $dst\n";
363    my @data = &read_dir($src);
364    printf ".. %d entries\n", $#data + 1;
365    my $verbose = $opt_v ? "v" : "";
366    for my $d ( 0 .. $#data ) {
367        my $item     = $data[$d];
368        my $src_item = $src . "/" . $item;
369        next if ( -d $src_item );
370        next if ( -l $src_item );
371        next if ( $item =~ /^\.(\.)?$/ );
372        next if ( $item =~ /\.(bak|in|log|status)$/ );
373        next if ( $item =~ /^llib-/ );
374        next if ( $item =~ /^modules/ );
375        next if ( $item =~ /^[fm]_trace\.c/ and not $opt_t );
376        next
377          if ( $item =~ /^Makefile/ and index( $update_dir, "/share/" ) < 0 );
378        next if ( $item =~ /^README/ );
379        next if ( $item eq "headers" );
380        next if ( $generated{$item} );
381        next if ( $item eq "link_test.c" );
382
383        if ( index( $dst, "/usr.bin/" ) >= 0 ) {
384            next if ( $item =~ /^(clear)/ );    # OpenBSD uses "tput clear"
385            my $prog = $dst;
386            $prog =~ s%^.*/%%;
387            $prog =~ s/(update|backup)//;
388            $prog .= "c";
389            if ( $dst =~ /infocmp/ ) {
390                next if ( $item ne $prog );
391            }
392            elsif ( $dst =~ /tabs/ ) {
393                next if ( $item ne $prog );
394            }
395            elsif ( $dst =~ /tic/ ) {
396                next if ( &is_tic_code($item) == 0 );
397            }
398            elsif ( $dst =~ /toe/ ) {
399                next if ( $item ne $prog );
400            }
401            elsif ( $dst =~ /tput/ ) {
402                next if ( $item ne $prog );
403            }
404            elsif ( $dst =~ /tset/ ) {
405                next if ( $item ne $prog );
406            }
407            else {
408                next;
409            }
410        }
411        system( sprintf( "cp -a$verbose %s %s/%s", $src_item, $dst, $item ) );
412        &munge_ident("$dst/$item");
413    }
414}
415
416# Checking if nroff supports tables is a long-obsolete issue, and is not really
417# necessary, except to match OpenBSD's source-tree.
418sub uses_tables($) {
419    my $docs = shift;
420    my @docs = &read_file($docs);
421    my $code = 0;
422    for my $n ( 0 .. $#docs ) {
423        if ( $docs[$n] =~ /^[.']\\"\s+t\b.*/ ) {
424            $code = 1;
425            last;
426        }
427        elsif ( $docs[$n] =~ /^\./ ) {
428            last;
429        }
430    }
431    return $code;
432}
433
434sub copy_1doc($$) {
435    my $docs = shift;
436    my $src  = "$source_dir/man/$docs";
437    my $dst  = "$update_dir/$docs";
438    $src .= "m" if ( -f "${src}m" );
439    $dst =~ s/x$//;
440    if ( $dst =~ /\.3/ ) {
441        $dst =~ s/\bncurses/curses/ if ( $dst =~ /ncurses\./ );
442        $dst =~ s/\bcurs_//         if ( $dst =~ /_term(cap|info)\./ );
443    }
444    &copy_file( $src, $dst );
445    &munge_docs($dst);
446}
447
448sub copy_docs($) {
449    my $docs = shift;
450    if ( index( $update_dir, "/usr.bin/" ) >= 0 ) {
451        &copy_1doc( $docs . ".1" );
452        if ( $docs eq "tic" ) {
453            &copy_1doc("captoinfo.1");
454            &copy_1doc("infotocap.1");
455        }
456    }
457    else {
458        my @docs = &read_dir("$source_dir/man");
459        if ( $docs eq "curses" ) {
460            for my $n ( 0 .. $#docs ) {
461                next if ( $docs[$n] eq "Makefile" );
462                next if ( $docs[$n] eq "make_sed.sh" );
463                next if ( $docs[$n] eq "man_db.renames" );
464                next if ( $docs[$n] eq "manlinks.sed" );
465                next if ( $docs[$n] =~ /\.(1|head|tail|in)/ );
466                next if ( $docs[$n] =~ /^(form|menu|mitem|panel)/ );
467                &copy_1doc( $docs[$n] );
468            }
469        }
470        elsif ( $docs eq "form" ) {
471            for my $n ( 0 .. $#docs ) {
472                next unless ( $docs[$n] =~ /^form/ );
473                &copy_1doc( $docs[$n] );
474            }
475        }
476        elsif ( $docs eq "menu" ) {
477            for my $n ( 0 .. $#docs ) {
478                next unless ( $docs[$n] =~ /^(menu|mitem)/ );
479                &copy_1doc( $docs[$n] );
480            }
481        }
482        elsif ( $docs eq "panel" ) {
483            for my $n ( 0 .. $#docs ) {
484                next unless ( $docs[$n] =~ /^panel/ );
485                &copy_1doc( $docs[$n] );
486            }
487        }
488    }
489}
490
491sub setup_dir($) {
492    my $dst = shift;
493    &failed("no definition for $dst")
494      unless ( defined $setup_dir{$dst} or $opt_r );
495    $target_dir = sprintf( "%s/%s", $opt_d, $dst );
496    $update_dir = $target_dir . ".update";
497    $backup_dir = $target_dir . ".backup";
498    my $result = 0;
499    if ($opt_r) {
500        &remove_dir($update_dir);
501        if ( $target_dir =~ /\/(tabs|toe)$/ ) {
502            &remove_dir($target_dir);
503        }
504        elsif ( -d $backup_dir ) {
505            &remove_dir($target_dir);
506            &rename_dir( $backup_dir, $target_dir );
507        }
508    }
509    else {
510        &remove_dir($update_dir);
511        mkdir $update_dir;
512
513        # reuse the shared-library version, assuming ABI=5 would involve at
514        # most a minor-version bump.
515        &copy_file( "$target_dir/shlib_version", $update_dir )
516          if ( $dst =~ /^lib\// );
517        &copy_code( $source_dir . "/" . $setup_dir{$dst}, $update_dir )
518          unless ( $setup_dir{$dst} eq "misc" );
519        $result = 1;
520    }
521    return $result;
522}
523
524sub do_build($) {
525    my $command = shift;
526    printf "%% %s\n", $command if ($opt_v);
527    system($command);
528}
529
530sub finish_dir() {
531    printf "** $target_dir\n";
532    system("diff -Naurb $target_dir $update_dir | diffstat -n 30")
533      if ( -d $target_dir );
534    if ($opt_n) {
535        &do_build("cd $update_dir && make -n") if ($opt_x);
536    }
537    else {
538        if ( -d $backup_dir ) {
539            printf STDERR "? backup directory exists: %s\n", $backup_dir;
540        }
541        else {
542            &rename_dir( $target_dir, $backup_dir );
543            &rename_dir( $update_dir, $target_dir );
544        }
545        &do_build("cd $target_dir && make") if ($opt_x);
546    }
547}
548
549################################################################################
550
551sub only_c_files($) {
552    my @data = @{ $_[0] };
553    my %data;
554    for my $n ( 0 .. $#data ) {
555        my $text = $data[$n];
556        $data{$text}++ if ( $text =~ /\.c$/ );
557    }
558    return sort keys %data;
559}
560
561sub makefile_list($$$) {
562    my @data = @{ $_[0] };
563    my $name = $_[1];
564    my $skip = $_[2];
565    my %data;
566    my $state = 0;
567    for my $n ( 0 .. $#data ) {
568        my $text = $data[$n];
569        $text =~ s/^\s+//;
570        next if ( index( $text, $skip ) == 0 );
571        $text =~ s/\s+=/=/;
572        $text =~ s/=\s+/=/;
573        $text =~ s/\s*\\//;
574        $state = 1 if ( $text =~ /^${name}=/ );
575        next unless ( $state == 1 );
576
577        if ( index( $text, "(trace)" ) >= 0 and not $opt_t ) {
578            next unless ( $text =~ /\b(lib_trace|visbuf)\.c$/ );
579        }
580        if ( not $opt_t ) {
581            next if ( $text =~ /\b[fm]_trace\.c$/ );
582        }
583        $text =~ s/^.*=//;
584        $text =~ s/\$o/.o/g;
585        $text =~ s/^.*\///;
586        next           if ( $text eq "link_test.c" );
587        next           if ( $text eq "mf_common.h" );
588        next           if ( $text eq "transform.h" );
589        $data{$text}++ if ( $text ne "" );
590        last           if ( $data[$n] !~ /\\$/ );
591    }
592    return sort keys %data;
593}
594
595sub manpage_list($) {
596    my $path = shift;
597    my @data = &read_dir($path);
598    my %data;
599    for my $n ( 0 .. $#data ) {
600        my $text = $data[$n];
601        $data{$text}++ if ( $text =~ /\.\d$/ );
602    }
603    return sort keys %data;
604}
605
606sub columns_of($) {
607    my $string = shift;
608    my $result = 0;
609    for my $n ( 0 .. length($string) - 1 ) {
610        my $c = substr( $string, $n, 1 );
611        if ( $c eq "\t" ) {
612            $result |= 7;
613            $result++;
614        }
615        elsif ( $c eq "\n" ) {
616            $result = 0;
617        }
618        else {
619            ++$result;
620        }
621    }
622    return $result;
623}
624
625sub format_list($$) {
626    my $name = $_[0];
627    my @data = @{ $_[1] };
628    my $keep = ( defined $_[2] ) ? 1 : 0;
629    my $base;
630    my $fill;
631    if ( length($name) >= 9 ) {
632        $fill = " ";
633        $base = length($name) + 1;
634    }
635    else {
636        $base = 9;
637        $fill = "\t";
638    }
639    my $result = sprintf( "%s%s", $name, $fill );
640    if ( $keep == 0 ) {
641        my %data;
642        for my $n ( 0 .. $#data ) {
643            $data{ $data[$n] } = 1 if ( defined $data[$n] );
644        }
645        @data = sort keys %data;
646    }
647    for my $n ( 0 .. $#data ) {
648        my $data = $data[$n];
649        my $col  = &columns_of($result);
650        my $add  = 1 + length($data);
651        if ( ( $col + $add ) > 76 ) {
652            $result .= " " if ( $col > $base );
653            $base = 9;
654            $fill = "\t";
655            $result .= "\\\n" . $fill . $data;
656        }
657        else {
658            $result .= " " if ( $col > $base );
659            $result .= $data;
660        }
661    }
662    return $result;
663}
664
665################################################################################
666
667sub compare_makefiles($) {
668    if ($opt_v) {
669        my $newfile = shift;
670        my $bakfile =
671          ( -d $backup_dir ? $backup_dir : $target_dir ) . "/Makefile";
672        system("diff -u $bakfile $newfile") if ( -f $bakfile );
673    }
674}
675
676# The curses makefile has to build build-time utilities and generate source.
677sub gen_1st_makefile() {
678    my $libname = "curses";
679    my $oldfile = "$source_dir/n$libname/Makefile";
680    my @oldfile = &read_file($oldfile);
681
682    my $newfile = "$update_dir/Makefile";
683    open( my $fp, ">", $newfile ) || &failed("cannot open $newfile");
684    my @subdirs = (
685        '${.CURDIR}/base', '${.CURDIR}/tinfo',
686        '${.CURDIR}/tty',  '${.CURDIR}/widechar'
687    );
688    $subdirs[ $#subdirs + 1 ] = '${.CURDIR}/trace' if ($opt_t);
689    printf $fp <<EOF;
690# $generated_by
691
692LIB=	$libname
693
694# Uncomment this to enable tracing in libcurses
695#CURSESTRACE=-DTRACE
696
697# This is used to compile terminal info directly into the library
698FALLBACK_LIST=
699
700# XXX - should be defined elsewhere
701AWK?=	/usr/bin/awk
702
703# Search in subdirs
704EOF
705    printf $fp "%s\n", &format_list( ".PATH:", \@subdirs );
706
707    my @autosrc = &makefile_list( \@oldfile, "AUTO_SRC", "?" );
708    my @auto_cc = &only_c_files( \@autosrc );
709    printf $fp "%s\n", &format_list( "SRCS=", \@auto_cc );
710
711    my @sources = &makefile_list( \@oldfile, "C_SRC", "./" );
712    printf $fp "%s\n", &format_list( "SRCS+=", \@sources );
713
714    printf $fp <<EOF;
715
716HOSTCFLAGS?=	\${CFLAGS}
717HOSTLDFLAGS?=	\${LDFLAGS}
718HOSTCFLAGS+=	-I. -I\${.CURDIR} \${CURSESTRACE}
719CFLAGS+=	-I. -I\${.CURDIR} \${CURSESTRACE} -D_XOPEN_SOURCE_EXTENDED -DNDEBUG
720
721EOF
722    my @manpages = &manpage_list($update_dir);
723    printf $fp "%s\n", &format_list( "MAN=", \@manpages );
724
725    $autosrc[ $#autosrc++ ] = "make_hash";
726    $autosrc[ $#autosrc++ ] = "make_keys";
727    printf $fp "%s\n", &format_list( "GENERATED=", \@autosrc );
728    printf $fp <<EOF;
729
730CAPLIST	= \${.CURDIR}/Caps
731USE_BIG_STRINGS	= 1
732
733CLEANFILES+= \${GENERATED}
734
735BUILDFIRST = \${GENERATED}
736
737includes:
738	\@cmp -s \${DESTDIR}/usr/include/ncurses.h \${.CURDIR}/curses.h || \\
739	  \${INSTALL} \${INSTALL_COPY} -m 444 -o \$(BINOWN) -g \$(BINGRP) \\
740	  \${.CURDIR}/curses.h \${DESTDIR}/usr/include/ncurses.h
741	\@cd \${.CURDIR}; for i in ncurses_dll.h unctrl.h term.h termcap.h; do \\
742	  cmp -s \$\$i \${DESTDIR}/usr/include/\$\$i || \\
743	  \${INSTALL} \${INSTALL_COPY} -m 444 -o \$(BINOWN) -g \$(BINGRP) \$\$i \\
744	  \${DESTDIR}/usr/include; done
745
746keys.list: \${.CURDIR}/tinfo/MKkeys_list.sh
747	sh \${.CURDIR}/tinfo/MKkeys_list.sh \${.CURDIR}/Caps | sort > \${.TARGET}
748
749fallback.c: \${.CURDIR}/tinfo/MKfallback.sh
750	sh \${.CURDIR}/tinfo/MKfallback.sh /usr/share/terminfo \${.CURDIR}/../../share/termtypes/termtypes.master \$(FALLBACK_LIST) > \${.TARGET}
751
752lib_gen.c: \${.CURDIR}/base/MKlib_gen.sh
753	sh \${.CURDIR}/base/MKlib_gen.sh "\${CC} -E -P -I\${.CURDIR}" \\
754		"\${AWK}" generated < \${.CURDIR}/curses.h > lib_gen.c
755
756init_keytry.h: make_keys keys.list
757	./make_keys keys.list > \${.TARGET}
758
759make_keys: \${.CURDIR}/tinfo/make_keys.c \${.CURDIR}/curses.priv.h names.c
760	\${HOSTCC} \${LDSTATIC} \${HOSTCFLAGS} \${HOSTLDFLAGS} \\
761		-o \${.TARGET} \${.CURDIR}/tinfo/make_keys.c \${LDADD}
762EOF
763
764    if ( &patchdate >= 20090808 ) {
765        printf $fp <<EOF;
766make_hash:	\${.CURDIR}/tinfo/make_hash.c \\
767		\${.CURDIR}/curses.priv.h \\
768		\${.CURDIR}/hashsize.h
769	\${HOSTCC} \${LDSTATIC} \${HOSTCFLAGS} -DMAIN_PROGRAM \${HOSTLDFLAGS} \\
770		-o \${.TARGET} \${.CURDIR}/tinfo/make_hash.c \${LDADD}
771EOF
772    }
773    else {
774        printf $fp <<EOF;
775make_hash: \${.CURDIR}/tinfo/comp_hash.c \\
776		\${.CURDIR}/curses.priv.h \\
777		\${.CURDIR}/hashsize.h
778	\${HOSTCC} \${LDSTATIC} \${HOSTCFLAGS} -DMAIN_PROGRAM \${HOSTLDFLAGS} \\
779		-o \${.TARGET} \${.CURDIR}/tinfo/comp_hash.c \${LDADD}
780EOF
781    }
782
783    if ( &patchdate >= 20190309 ) {
784        printf $fp <<EOF;
785CAPLIST += \${.CURDIR}/Caps-ncurses
786
787comp_userdefs.c: make_hash \\
788		\${.CURDIR}/hashsize.h \\
789		\${.CURDIR}/tinfo/MKuserdefs.sh
790	sh \${.CURDIR}/tinfo/MKuserdefs.sh \${AWK} \${USE_BIG_STRINGS} \${CAPLIST} > \${.TARGET}
791EOF
792    }
793    printf $fp <<EOF;
794
795expanded.c: \${.CURDIR}/term.h \${.CURDIR}/curses.priv.h \\
796		\${.CURDIR}/ncurses_cfg.h \${.CURDIR}/tty/MKexpanded.sh
797	sh \${.CURDIR}/tty/MKexpanded.sh "\${CC} -E -P" \${CPPFLAGS} > \${.TARGET}
798
799comp_captab.c: make_hash
800	sh \${.CURDIR}/tinfo/MKcaptab.sh \${AWK} \${USE_BIG_STRINGS} \\
801		\${.CURDIR}/tinfo/MKcaptab.awk \${CAPLIST} > \${.TARGET}
802
803lib_keyname.c: keys.list \${.CURDIR}/base/MKkeyname.awk
804	\${AWK} -f \${.CURDIR}/base/MKkeyname.awk \\
805		bigstrings=\${USE_BIG_STRINGS} \\
806		keys.list > \${.TARGET}
807
808names.c: \${.CURDIR}/tinfo/MKnames.awk
809	\${AWK} -f \${.CURDIR}/tinfo/MKnames.awk \\
810		bigstrings=\${USE_BIG_STRINGS} \\
811		\${CAPLIST} > \${.TARGET}
812codes.c: \${.CURDIR}/tinfo/MKcodes.awk
813	\${AWK} -f \${.CURDIR}/tinfo/MKcodes.awk \\
814		bigstrings=\${USE_BIG_STRINGS} \\
815		\${CAPLIST} > \${.TARGET}
816
817unctrl.c: \${.CURDIR}/base/MKunctrl.awk
818	echo | \${AWK} -f \${.CURDIR}/base/MKunctrl.awk bigstrings=1 > \${.TARGET}
819
820.include <bsd.own.mk>
821
822# Link libtermlib, libtermcap to libcurses so we don't break people's Makefiles
823afterinstall:
824	-cd \${DESTDIR}\${LIBDIR}; \\
825	for i in \${_LIBS}; do \\
826	    ln -f \$\$i `echo \$\$i | sed 's/curses/termlib/'`; \\
827	    ln -f \$\$i `echo \$\$i | sed 's/curses/termcap/'`; \\
828	    ln -f \$\$i `echo \$\$i | sed 's/curses/ncurses/'`; \\
829	    ln -f \$\$i `echo \$\$i | sed 's/curses/ncursesw/'`; \\
830	done
831
832.include <bsd.lib.mk>
833EOF
834    close $fp;
835    &compare_makefiles($newfile);
836}
837
838sub gen_lib_makefile($) {
839    my $libname = shift;
840    my $oldfile = "$source_dir/$libname/Makefile";
841    my @oldfile = &read_file($oldfile);
842
843    # in ncurses, header-files are quasi-generated, because the original
844    # header file for form/menu/panel lives in the source-directory, but is
845    # copied to the include-directory with "make sources".
846    my @headers = &makefile_list( \@oldfile, "AUTO_SRC", "?" );
847
848    # The C source is more straightforward.
849    my @sources = &makefile_list( \@oldfile, "C_SRC", "?" );
850    my $newfile = "$update_dir/Makefile";
851    open( my $fp, ">", $newfile ) || &failed("cannot open $newfile");
852    printf $fp <<EOF;
853# $generated_by
854
855LIB=	$libname
856EOF
857
858    printf $fp "%s\n", &format_list( "SRCS=", \@sources );
859    printf $fp "%s\n", &format_list( "HDRS=", \@headers );
860    my $includes = '-I${.CURDIR}/../libcurses';
861    $includes .= ' -I${.CURDIR}/../libmenu' if ( $libname eq "form" );
862    printf $fp <<EOF;
863CFLAGS+=$includes -D_XOPEN_SOURCE_EXTENDED -DNDEBUG
864EOF
865    my @manpages = &manpage_list($update_dir);
866    printf $fp "%s\n", &format_list( "MAN=", \@manpages );
867    printf $fp <<EOF;
868
869includes:
870	\@cd \$\{.CURDIR}; for i in \$\{HDRS}; do \\
871	  cmp -s \$\$i \${DESTDIR}/usr/include/\$\$i || \\
872	  \${INSTALL} \${INSTALL_COPY} -m 444 -o \$(BINOWN) -g \$(BINGRP) \$\$i \\
873	  \${DESTDIR}/usr/include; done
874
875.include <bsd.own.mk>
876
877afterinstall:
878	-cd \${DESTDIR}\${LIBDIR}; \\
879	for i in \${_LIBS}; do \\
880	    ln -f \$\$i `echo \$\$i | sed 's/${libname}/${libname}w/'`; \\
881	done
882
883.include <bsd.lib.mk>
884EOF
885    close $fp;
886    &compare_makefiles($newfile);
887}
888
889sub gen_bin_makefile($) {
890    my $binname = shift;
891    my $oldfile = "$source_dir/progs/Makefile";
892    my @oldfile = &read_file($oldfile);
893    my $newfile = "$update_dir/Makefile";
894
895    open( my $fp, ">", $newfile ) || &failed("cannot open $newfile");
896    my @sources = ("$binname.c");
897    my @links   = ();
898    my @autosrc = &makefile_list( \@oldfile, "AUTO_SRC", "?" );
899
900    my $tput_ver       = 0;
901    my $use_dump_entry = 0;
902    my $use_termsort   = 0;
903    my $use_tparm_type = 0;
904    my $use_transform  = 0;
905
906    $use_dump_entry = 1 if ( $binname eq "infocmp" or $binname eq "tic" );
907    $use_termsort   = 1 if ( $use_dump_entry       or $binname eq "tput" );
908
909    if ( &patchdate >= 20090314 ) {
910        $use_transform = 1 if ( $binname =~ /^(tic|tput|tset)/ );
911    }
912    if ( &patchdate >= 20140521 ) {
913        $use_tparm_type = 1 if ( $binname =~ /^(tic|tput)$/ );
914    }
915    if ( &patchdate >= 20160806 ) {
916        $tput_ver = &patchdate;
917    }
918
919    $sources[ ++$#sources ] = "dump_entry.c" if ($use_dump_entry);
920    $sources[ ++$#sources ] = "tparm_type.c" if ($use_tparm_type);
921    $sources[ ++$#sources ] = "transform.c"  if ($use_transform);
922
923    $autosrc[ ++$#autosrc ] = "termsort.c" if ($use_termsort);
924
925    # transform.h also is generated, but OpenBSD checked-in a copy
926
927    if ( $binname eq "tic" ) {
928        $links[ ++$#links ] = "captoinfo";
929        $links[ ++$#links ] = "infotocap";
930    }
931    elsif ( $binname eq "tabs" ) {
932        $sources[ ++$#sources ] = "tty_settings.c" if ( $tput_ver >= 20161224 );
933    }
934    elsif ( $binname eq "tput" ) {
935        $sources[ ++$#sources ] = "clear_cmd.c"    if ( $tput_ver >= 20161022 );
936        $sources[ ++$#sources ] = "reset_cmd.c"    if ( $tput_ver >= 20160806 );
937        $sources[ ++$#sources ] = "tty_settings.c" if ( $tput_ver >= 20161224 );
938        $links[ ++$#links ]     = "clear";
939    }
940    elsif ( $binname eq "tset" ) {
941        $sources[ ++$#sources ] = "reset_cmd.c"    if ( $tput_ver >= 20160806 );
942        $sources[ ++$#sources ] = "tty_settings.c" if ( $tput_ver >= 20161224 );
943        $links[ ++$#links ]     = "reset";
944    }
945
946    printf $fp <<EOF;
947# $generated_by
948
949PROG=	$binname
950EOF
951    printf $fp "%s\n", &format_list( "SRCS=", \@sources );
952    printf $fp <<EOF;
953CURSES=	\${.CURDIR}/../../lib/libcurses
954DPADD=	\${LIBCURSES}
955LDADD=	-L\${CURSES} -lcurses\t# in-tree link to add _nc_strict_bsd, etc
956EOF
957    if ( $#links >= 0 ) {
958        my @bin_links;
959        for my $n ( 0 .. $#links ) {
960            $bin_links[ ++$#bin_links ] = '${BINDIR}/' . $binname;
961            $bin_links[ ++$#bin_links ] = '${BINDIR}/' . $links[$n];
962        }
963        printf $fp "%s\n", &format_list( "LINKS=", \@bin_links, 1 );
964    }
965    my $ticfix = '${.CURDIR}/';
966    if ( $binname eq "tic" ) {
967        printf $fp <<EOF;
968CFLAGS+= -I\${CURSES} -I\${.CURDIR} -I.
969EOF
970    }
971    else {
972        $ticfix = '${TIC}/';
973        printf $fp <<EOF;
974TIC= \${.CURDIR}/../tic
975CFLAGS+= -I\${CURSES} -I\${TIC} -I\${.CURDIR} -I.
976.PATH:  \${TIC}
977EOF
978    }
979    printf $fp "%s\n", &format_list( "CLEANFILES+=", \@autosrc );
980    if ($use_dump_entry) {
981        printf $fp <<EOF;
982
983dump_entry.o: termsort.c
984EOF
985    }
986    if ($use_termsort) {
987        printf $fp <<EOF;
988
989termsort.c: ${ticfix}MKtermsort.sh
990	sh ${ticfix}MKtermsort.sh awk \${CURSES}/Caps > \${.TARGET}
991EOF
992    }
993    printf $fp <<EOF;
994
995.include <bsd.prog.mk>
996EOF
997    close $fp;
998
999    &compare_makefiles($newfile);
1000}
1001
1002################################################################################
1003
1004sub setup_lib_libcurses() {
1005    if ( &setup_dir("lib/libcurses") ) {
1006        &copy_code( "$source_dir/ncurses/base",     "$update_dir/base" );
1007        &copy_code( "$source_dir/ncurses/tinfo",    "$update_dir/tinfo" );
1008        &copy_code( "$source_dir/ncurses/tty",      "$update_dir/tty" );
1009        &copy_code( "$source_dir/ncurses/widechar", "$update_dir/widechar" );
1010        &copy_file( "$source_dir/include/Caps",           $update_dir );
1011        &copy_file( "$source_dir/include/capdefaults.c",  $update_dir );
1012        &copy_file( "$source_dir/include/curses.h",       $update_dir );
1013        &copy_file( "$source_dir/include/hashed_db.h",    $update_dir );
1014        &copy_file( "$source_dir/include/hashsize.h",     $update_dir );
1015        &copy_file( "$source_dir/include/nc_alloc.h",     $update_dir );
1016        &copy_file( "$source_dir/include/nc_panel.h",     $update_dir );
1017        &copy_file( "$source_dir/include/nc_tparm.h",     $update_dir );
1018        &copy_file( "$source_dir/include/ncurses_cfg.h",  $update_dir );
1019        &copy_file( "$source_dir/include/ncurses_def.h",  $update_dir );
1020        &copy_file( "$source_dir/include/ncurses_dll.h",  $update_dir );
1021        &copy_file( "$source_dir/include/parametrized.h", $update_dir );
1022        &copy_file( "$source_dir/include/term.h",         $update_dir );
1023        &copy_file( "$source_dir/include/termcap.h",      $update_dir );
1024        &copy_file( "$source_dir/include/term_entry.h",   $update_dir );
1025        &copy_file( "$source_dir/include/tic.h",          $update_dir );
1026        &copy_file( "$source_dir/include/unctrl.h",       $update_dir );
1027        &copy_file( "$source_dir/man/terminfo.5",         $update_dir );
1028        &copy_docs("curses");
1029
1030        &verbose(".. work around a bug in /bin/sh in OpenBSD");
1031        system( "sed -i"
1032              . " -e 's,^shift,test \$# != 0 \\&\\& shift,'"
1033              . " $update_dir/tinfo/MKfallback.sh" );
1034
1035        # OpenBSD dropped support for sys/ttydev.h, without mentioning the
1036        # system version.  Just trim it.
1037        &verbose(".. work around mishandled sys/ttydef.h");
1038        system( "sed -i"
1039              . " -e '/__FreeBSD_version/s,|| defined(__OpenBSD__),,'"
1040              . " $update_dir/tinfo/lib_baudrate.c" );
1041
1042        if ($opt_t) {
1043            &copy_code( "$source_dir/ncurses/trace", "$update_dir/trace" );
1044        }
1045        else {
1046            &copy_file( "$source_dir/ncurses/trace/lib_trace.c", $update_dir );
1047            &copy_file( "$source_dir/ncurses/trace/visbuf.c",    $update_dir );
1048        }
1049        &copy_file( "$source_dir/include/nc_termios.h", $update_dir )
1050          if ( &patchdate >= 20110625 );
1051        &copy_file( "$source_dir/include/nc_string.h", $update_dir )
1052          if ( &patchdate >= 20120222 );
1053        &copy_file( "$source_dir/include/nc_access.h", $update_dir )
1054          if ( &patchdate >= 20210626 );
1055        &copy_file( "$source_dir/include/Caps-ncurses", $update_dir )
1056          if ( &patchdate >= 20190302 );
1057        &gen_1st_makefile;
1058        &finish_dir;
1059    }
1060}
1061
1062sub setup_lib_libform() {
1063    if ( &setup_dir("lib/libform") ) {
1064        &copy_docs("form");
1065        &gen_lib_makefile("form");
1066        &finish_dir;
1067    }
1068}
1069
1070sub setup_lib_libmenu() {
1071    if ( &setup_dir("lib/libmenu") ) {
1072        &copy_docs("menu");
1073        &gen_lib_makefile("menu");
1074        &finish_dir;
1075    }
1076}
1077
1078sub setup_lib_libpanel() {
1079    if ( &setup_dir("lib/libpanel") ) {
1080        &copy_docs("panel");
1081        &gen_lib_makefile("panel");
1082        &finish_dir;
1083    }
1084}
1085
1086sub setup_bin_infocmp() {
1087    if ( &setup_dir("usr.bin/infocmp") ) {
1088        &copy_docs("infocmp");
1089        &gen_bin_makefile("infocmp");
1090        &finish_dir;
1091    }
1092}
1093
1094sub setup_bin_tabs() {
1095    if ( &setup_dir("usr.bin/tabs") ) {
1096        &copy_docs("tabs");
1097        &gen_bin_makefile("tabs");
1098        &finish_dir;
1099    }
1100}
1101
1102sub setup_bin_tic() {
1103    if ( &setup_dir("usr.bin/tic") ) {
1104        if ( &patchdate >= 20140521 ) {
1105            &copy_file( "$source_dir/progs/tparm_type.c", $update_dir );
1106            &copy_file( "$source_dir/progs/tparm_type.h", $update_dir );
1107        }
1108
1109        # shared files for tput/tset
1110        if ( &patchdate >= 20160806 ) {
1111            &copy_file( "$source_dir/progs/reset_cmd.c", $update_dir );
1112            &copy_file( "$source_dir/progs/reset_cmd.h", $update_dir );
1113        }
1114        if ( &patchdate >= 20161022 ) {
1115            &copy_file( "$source_dir/progs/clear_cmd.c", $update_dir );
1116            &copy_file( "$source_dir/progs/clear_cmd.h", $update_dir );
1117        }
1118        if ( &patchdate >= 20161224 ) {
1119            &copy_file( "$source_dir/progs/tty_settings.c", $update_dir );
1120            &copy_file( "$source_dir/progs/tty_settings.h", $update_dir );
1121        }
1122        &copy_docs("tic");
1123        &gen_bin_makefile("tic");
1124        &finish_dir;
1125    }
1126}
1127
1128sub setup_bin_toe() {
1129    if ( &setup_dir("usr.bin/toe") ) {
1130        &copy_docs("toe");
1131        &gen_bin_makefile("toe");
1132        &finish_dir;
1133    }
1134}
1135
1136sub setup_bin_tput() {
1137    if ( &setup_dir("usr.bin/tput") ) {
1138        &copy_docs("tput");
1139        &gen_bin_makefile("tput");
1140        &finish_dir;
1141    }
1142}
1143
1144sub setup_bin_tset() {
1145    if ( &setup_dir("usr.bin/tset") ) {
1146        &copy_docs("tset");
1147        &gen_bin_makefile("tset");
1148        &finish_dir;
1149    }
1150}
1151
1152sub setup_terminfo() {
1153    if ( &setup_dir("share/termtypes") ) {
1154        &copy_code( $target_dir, $update_dir );
1155        &copy_file( "$source_dir/misc/terminfo.src",
1156            "$update_dir/termtypes.master" );
1157
1158        # build the terminfo database using the in-tree tic.
1159        # This is always best practice, but for ncurses 6.2 in particular is
1160        # required.
1161        my $prog = abs_path("$target_dir/../../usr.bin/tic");
1162        my $libs = abs_path("$target_dir/../../lib/libcurses");
1163        if ( defined $prog and defined $libs ) {
1164            $prog .= "/tic";
1165            &verbose(".. changing makefile to use in-tree tic");
1166            system( "sed -i -E "
1167                  . "-e 's,(TIC=).*,\\1\t$prog,' "
1168                  . "-e 's,(\\\${TIC}),LD_LIBRARY_PATH=$libs \\1,' "
1169                  . "$update_dir/Makefile" );
1170        }
1171        &finish_dir;
1172    }
1173}
1174
1175sub configure_tree() {
1176    return if ( -f "ncurses/Makefile" );
1177    my @search = ( "/usr/share/terminfo", "/usr/local/share/terminfo" );
1178    my @prefix = ("./configure");
1179    $prefix[ ++$#prefix ] = "--with-abi-version=5"
1180      if ( &patchdate >= 20150502 && !$opt_6 );
1181    my @options = (
1182        "--with-ospeed=int",                               #
1183        "--with-shared",                                   #
1184        "--without-normal",                                #
1185        "--without-debug",                                 #
1186        "--with-terminfo-dirs=" . join( ':', @search ),    #
1187        "--without-ada",                                   #
1188        "--disable-hard-tabs",                             #
1189        "--enable-const",                                  #
1190        "--enable-getcap",                                 #
1191        "--enable-bsdpad",                                 #
1192        "--enable-signed-char",                            #
1193        "--enable-termcap",                                #
1194        "--enable-widec",                                  #
1195        "--disable-setuid-environ"
1196    );
1197    $options[ ++$#options ] = "--with-trace" if ($opt_t);
1198    $options[ ++$#options ] = "--enable-string-hacks"
1199      if ( &patchdate >= 20120225 );
1200    system( join( ' ', @prefix ) . ' ' . join( ' ', @options ) );
1201    &failed("problem with configuring") unless ( -f "ncurses/Makefile" );
1202
1203    system("make sources");
1204
1205    # OpenBSD developers edit the generated file and do not regen it when
1206    # doing upgrades.  This script reflects those edits.
1207    system( "sed -i" . " -E"
1208          . " -e '/TYPEOF_CHTYPE/s,int,long,'"
1209          . " -e '/USE_TERMCAP/d'"
1210          . " -e '/HAVE_LIB(FORM|MENU|PANEL)/s,^(.*)\$,/* \\1 */,'"
1211          . " -e 's/TERMPATH.*/PURE_TERMINFO 0/'"
1212          . " -e '/SYSTEM_NAME/s,\[0-9.\]+,,'"
1213          . " include/ncurses_cfg.h" );
1214}
1215
1216sub get_definitions() {
1217    my @data = &read_file("dist.mk");
1218    for my $n ( 0 .. $#data ) {
1219        my $text = $data[$n];
1220        $text =~ s/^\s*//;
1221        next unless ( $text =~ /^NCURSES.*=/ );
1222        $text =~ s/\s*=\s+/=/;
1223        my $name = $text;
1224        $name =~ s/=.*//;
1225        my $value = $text;
1226        $value =~ s/^[^=]*=//;
1227        $value =~ s/\s.*//;
1228        $definitions{$name} = $value;
1229    }
1230}
1231
1232sub setup_all_dirs() {
1233    printf "** %s all build-directories\n", $opt_r ? "removing" : "setting up";
1234    &get_definitions;
1235    &configure_tree unless ($opt_r);
1236    &setup_lib_libcurses;
1237    &setup_lib_libmenu;
1238    &setup_lib_libform;    # build after libmenu, for mf_common.h
1239    &setup_lib_libpanel;
1240    &setup_bin_tic;        # do this first, for shared headers
1241    &setup_bin_infocmp;
1242    &setup_bin_tabs if ( -f "$source_dir/progs/tabs.c" );
1243    &setup_bin_toe;
1244    &setup_bin_tput;
1245    &setup_bin_tset;
1246    &setup_terminfo;
1247}
1248
1249sub usage() {
1250    print <<EOF;
1251Usage: ncu2openbsd [options] [sourcetree]
1252
1253Options:
1254  -6       use ABI 6 rather than 5 if available
1255  -d DST   specify destination (default: /usr/src)
1256  -n       no-op, do not update destination
1257  -r       remove update, restore sources from ".orig"
1258  -t       enable ncurses trace
1259  -v       verbose
1260  -x       build each directory after setting up
1261EOF
1262    exit;
1263}
1264
1265$Getopt::Std::STANDARD_HELP_VERSION = 1;
1266&getopts('6d:nrtvx') || &usage();
1267$opt_d = "/usr/src" unless ($opt_d);
1268&usage() unless ( $#ARGV <= 0 );
1269
1270if ( $#ARGV == 0 ) {
1271    if ( -f $ARGV[0] ) {
1272        printf "** unpacking sources: %s\n", $ARGV[0];
1273        &unpack( $ARGV[0] );
1274    }
1275    else {
1276        &check_sourcedir( $ARGV[0] );
1277    }
1278}
1279else {
1280    &check_sourcedir(".");
1281}
1282
1283&setup_all_dirs;
1284
1285# move out of temp-directory to allow cleanup.
1286chdir $current;
1287
12881;
1289