Last active
March 29, 2020 02:51
-
-
Save Fat-Zer/4035188 to your computer and use it in GitHub Desktop.
autotools-cmake-convert.pl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
# Usage sample: | |
# find <dir> -iname Makefile.am | while read m; do | |
# echo "=== processing $m ==="; | |
# ../scripts/autotools-cmake-convert.pl ${m} >"$(dirname $m)/CMakeLists.txt"; | |
# done | |
use v5.10.1; | |
use experimental qw(smartmatch); | |
use File::Basename; | |
use File::Find::Rule; | |
######### settings ############################## | |
$STR_LENGTH = 79; | |
$BOX_COMMENT_START = 5; | |
# $BOX_LENGTH = $STR_LENGTH; | |
$BOX_LENGTH = 49; | |
$TAB_SYMBOL = ' '; | |
$TAB_WIDTH = 2; | |
$PRINT_INFO='no'; | |
$PRINT_AUTO_HEADER='yes'; | |
$PRINT_COPYRIGHT='no'; | |
######### utils ################################# | |
sub usage () { | |
print STDERR "Usage:\n"; | |
print STDERR " $0 Makefile.am\n"; | |
} | |
sub error ($) { | |
print STDERR "[\033[1;31m !!! \033[0m] $_[0]\n"; | |
} | |
sub warning ($) { | |
print STDERR "[\033[1;33m ??? \033[0m] $_[0]\n"; | |
} | |
sub info ($) { | |
if( $PRINT_INFO eq 'yes' ) { | |
print STDERR "[\033[1;32m +++ \033[0m] $_[0]\n"; | |
} | |
} | |
sub box_comment ($@) { | |
my $rv, $str; | |
if( scalar(@_) == 0 ) { | |
$rv = "#" x $BOX_LENGTH; | |
} else { | |
$rv = "#" x $BOX_COMMENT_START; | |
foreach $str ( @_ ) { | |
$rv .= ' '.$str; | |
} | |
$rv .= ' #'; | |
$rv .= '#' x ($BOX_LENGTH - length($rv)); | |
} | |
$rv; | |
} | |
sub tab_string ($) { | |
my $tab_num=$_[0]; | |
$TAB_SYMBOL x ($TAB_WIDTH * $tab_num); | |
} | |
sub fix_tabs ($) { | |
my $tab_num=$_[0]; | |
my $str = $_[1]; | |
$str =~ s/^\s*//; | |
&tab_string($tab_num).$str; | |
} | |
sub fix_width ($$) { | |
my $tab_num = $_[0]; | |
my $str = $_[1]; | |
my $rv = ""; | |
$str=&fix_tabs($tab_num, $str); | |
while( length($str)> $STR_LENGTH) { | |
my $split_pos, $tmp; | |
$split_pos=rindex( $str, " ", $STR_LENGTH); | |
$tmp = substr($str, 0, $split_pos)."\n"; | |
if( $tmp =~ /^\s*$/) { | |
last; | |
} | |
$rv.=$tmp; | |
$str = substr($str, $split_pos); | |
$str=&fix_tabs($tab_num+1, $str); | |
} | |
if( ! $str =~ /^\s*$/) { | |
$rv .= $str."\n"; | |
} else { | |
$rv.="\n"; | |
} | |
$rv; | |
} | |
sub print_auto_header() { | |
print "# This file is genereted by trinity-automake-cmake-convert script by Fat-Zer\n" ; | |
} | |
sub print_copyright () { | |
print <<EOF | |
################################################# | |
# | |
# (C) 2016 Alexander Golubev | |
# fatzer2 (AT) gmail.com | |
# | |
# Improvements and feedback are welcome | |
# | |
# This file is released under GPL >= 2 | |
# | |
################################################# | |
EOF | |
; | |
} | |
sub read_makefile_hash (*) { | |
my $f=$_[0]; | |
my %rv; | |
my $k; | |
seek($f, 0, 0); | |
while(<$f>){ | |
if( /^[^#]\S+\s*=\s*/ ) { | |
$k = $_; | |
$k =~ s/\s?=.*//; | |
$k =~ s/^\s+//; | |
$k =~ s/\s+$//; | |
s/\S+\s*=\s*//; | |
while( /\\\n$/ ) { | |
my $next = <$f>; | |
$next =~ s/^\s*//; | |
s/\s*\\\n$/ /; | |
$_ .= $next; | |
} | |
s/\s/ /g; | |
s/ +/ /g; | |
s/ $//; | |
s/^ //; | |
if( exists $rv{ $k }) { | |
&error("Second declaration of statement \"$k\""); | |
} else { | |
$rv{ $k } = $_; | |
} | |
} | |
} | |
%rv; | |
} | |
sub do_skip_line () { | |
if( $skip_line != 0 ) {for($skip_line; $skip_line>0; $skip_line--) { print "\n"; } } | |
} | |
######### read Makefile.in ###################### | |
if ( $#ARGV != 1 - 1 ) { | |
&usage; | |
die("Bad arguments\n"); | |
}; | |
open(INP_F, "< $ARGV[0]") || die "cannot open $ARGV[0]"; | |
%makefile_hash=&read_makefile_hash(INP_F); | |
close INP_F; | |
######### determin the pkg_dir name ############# | |
$full_pkg_dir = dirname($ARGV[0]); | |
$pkg_dir = basename($full_pkg_dir); | |
######### detect what statements we got ######### | |
@compilation_statements=( | |
"bin_PROGRAMS", | |
"lib_LTLIBRARIES", | |
"tdeinit_LTLIBRARIES", | |
"kde_module_LTLIBRARIES", | |
"noinst_LTLIBRARIES", | |
"check_PROGRAMS"); | |
@data_statements=( | |
"xdg_apps_DATA", | |
"kde_kcfg_DATA", | |
".*_DATA"); | |
@headers_statements=( | |
".*_HEADERS", | |
); | |
@headers_statements_exclude=( | |
"noinst_HEADERS", | |
); | |
@doc_statements=( | |
"KDE_MANS", | |
"KDE_DOCS", ); | |
@translation_statements=( | |
"POFILES", ); | |
@subdir_statements=( | |
"SUBDIRS"); | |
@icon_statements=( | |
"KDE_ICON"); | |
$have_compilation=0; | |
$have_data=0; | |
$have_subdir=0; | |
$have_icon=0; | |
$have_doc=0; | |
$have_translation=0; | |
foreach $type ("subdir", "compilation", "icon", "data", "headers", "doc", "translation") { | |
foreach $var (@{${type}."_statements"}) { | |
my @vals = grep ( /${var}/ , keys %makefile_hash); | |
if( @vals && ( | |
not @{${type}."_statements_exclude"} || map ( grep ( !/$_/, @vals), @{${type}."_statements_exclude"} ) ) ) { | |
${"have_".$type}=1; | |
&info("Found $type statment(s)"); | |
last; | |
} | |
} | |
} | |
######### test if we fully support all statements # | |
@supported_statements=( | |
@compilation_statements, | |
@data_statements, | |
@subdir_statements, | |
@icon_statements, | |
@doc_statements, | |
@translation_statements, | |
@data_statements, | |
@headers_statements, | |
"INCLUDES", | |
"noinst_HEADERS", | |
"METASOURCES", | |
"EXTRA_DIST", | |
"AM_LDFLAGS", | |
"AM_CPPFLAGS", | |
"LDADD", | |
"KDE_LANG", | |
"TOPLEVEL_LANG", | |
"AUTOMAKE_OPTIONS"); | |
@checkme_statements=( | |
"check_PROGRAMS", | |
"KDE_MANS", | |
"TOPLEVEL_LANG", | |
"AUTOMAKE_OPTIONS"); | |
@supported_la=( | |
"SOURCES", | |
"LIBADD", | |
"LDFLAGS", | |
"LDADD", | |
"METASOURCES"); | |
foreach $key (keys %makefile_hash) { | |
if( !( (grep(/^$key$/, @supported_statements)) || | |
(grep {$key =~ /_(la_)?$_$/} @supported_la) || | |
($key =~ /^.*(_DATA|_HEADERS|dir)$/ ) ) ) { | |
&error("Statement $key is not supported by the script"); | |
} elsif ( grep(/^$key$/, @checkme_statements) ) { | |
given ($key) { | |
when("check_PROGRAMS") | |
{ &error("check_PROGRAMS statement is not supported in cmake."); } | |
when("KDE_MANS") | |
{ &error("KDE_MANS found but KDE_DOCS not.") | |
if ( !exists $makefile_hash{"KDE_DOCS"} ) ; } | |
default { | |
&warning("Statement $key should be checked manually"); } | |
} | |
} | |
} | |
######### header ################################ | |
if( $PRINT_COPYRIGHT eq 'yes' ) { | |
&print_copyright; | |
$skip_line=1; | |
} | |
if( $PRINT_AUTO_HEADER eq 'yes' ) { | |
&print_auto_header($ARGV[0]); | |
$skip_line=1; | |
} | |
######### subdirs ############################### | |
if( $have_subdir ) { | |
# test if we realy got subdirs | |
if( File::Find::Rule->directory | |
->maxdepth(1) | |
->not(File::Find::Rule->new->name(qr/^\.\.?$/)) | |
->in($full_pkg_dir) == 0 ) { | |
$have_subdir=0; | |
&warning("Seems we haven't got subdirs; skipping it;"); | |
} else { | |
my $was_printed=0; | |
foreach $subdir ( split(/\s/, $makefile_hash{"SUBDIRS"}) ) { | |
if( $subdir =~ /\Q$(AUTODIRS)\E/ ){ | |
&info("Adding auto subdirectory target"); | |
do_skip_line; | |
print "tde_auto_add_subdirectories( )\n"; | |
$was_printed=1; | |
}elsif( $subdir =~ /^\w+$/ ) { | |
&info("Adding subdirectory \"$subdir\""); | |
do_skip_line; | |
print "add_subdirectory( $subdir )\n"; | |
$was_printed=1; | |
} else { | |
&error("Subdir $subdir seems to be strange. Check it!"); | |
} | |
} | |
if( $was_printed=1 ) { | |
$skip_line += 1; | |
} | |
} | |
} | |
######### includes links etc #################### | |
if( $have_compilation ) { | |
if( exists $makefile_hash{"INCLUDES"}) { | |
foreach $inc ( split( /\s+/, $makefile_hash{"INCLUDES"}) ) { | |
if( $inc eq "\$\(all_includes\)" ) { | |
&info ("Found general include statement"); | |
} elsif( $inc =~ /^\Q-I$(top_srcdir)\E\/(.*)$/ ) { | |
$t = "\${CMAKE_SOURCE_DIR}/" . $1; | |
&info("Found additional include: $t"); | |
push (@additional_includes, "$t"); | |
} elsif( $inc =~ /^\Q-I$(srcdir)\E\/(.*)$/ ) { | |
$path = $1; | |
if ($path =~ /\Q..\E/) { | |
&warning("INCLUDES have relative path: $inc."); | |
} else { | |
$t = "\${CMAKE_CURRENT_SOURCE_DIR}/" . $path; | |
&info("Found additional include: $t"); | |
push (@additional_includes, "$t"); | |
} | |
} else { | |
&warning("INCLUDES statement has unsuported value: $inc."); | |
} | |
} | |
} | |
do_skip_line; | |
&info("Adding include dirs"); | |
$entry = "include_directories(\n"; | |
$entry .= " \${CMAKE_BINARY_DIR}\n"; | |
$entry .= " \${CMAKE_CURRENT_BINARY_DIR}\n"; | |
$entry .= " \${CMAKE_CURRENT_SOURCE_DIR}\n"; | |
$entry .= " " . join( "\n ", @additional_includes ) . "\n" if @additional_includes; | |
$entry .= " \${TDE_INCLUDE_DIR}\n"; | |
$entry .= " \${TQT_INCLUDE_DIRS}\n"; | |
$entry .= ")\n"; | |
print $entry; | |
&info("Adding default link dirs"); | |
print <<EOF | |
link_directories( | |
\${TQT_LIBRARY_DIRS} | |
) | |
EOF | |
; | |
$skip_line = 1; | |
######### definitions ########################### | |
if( exists $makefile_hash{"AM_CPPFLAGS"}) { | |
my $defs=$makefile_hash{"AM_CPPFLAGS"}; | |
my $entry; | |
$entry = "add_definitions(\n"; | |
foreach $def (split(/\s/, $defs) ) { | |
if ($def =~ /^-D/ ) { | |
$entry .= fix_width( 1, "$def"); | |
&info("Adding definition \"$def\""); | |
} else { | |
&warning("Definition \"$def\" wasn't added; definitions may be incomplete"); | |
} | |
} | |
$entry .= ")\n"; | |
do_skip_line; | |
print $entry; | |
$skip_line = 1; | |
} | |
######### binaries ############################## | |
%bin_types=( | |
"bin_PROGRAMS", "executable", | |
"check_PROGRAMS", "test", | |
"tdeinit_LTLIBRARIES", "tdeinit", | |
"kde_module_LTLIBRARIES" ,"kpart", | |
"noinst_LTLIBRARIES", "static", | |
"lib_LTLIBRARIES", "shared"); | |
foreach $type (keys %bin_types ) { | |
foreach $target ( split(/\s/, $makefile_hash{$type}) ) { | |
my ( $prefix, $name, $sources, $ldflags, $link, $entry, $ver); | |
$prefix = $target; | |
$prefix =~ s/\./_/g; | |
$name = $target; | |
$name =~ s/\.la$//; | |
given($bin_types{$type}) { | |
when('static') { $name =~ s/^lib//; } | |
when('shared') { $name =~ s/^lib//; } | |
} | |
$sources = $makefile_hash{$prefix."_SOURCES"}; | |
if( $sources =~ /^\s*$/) { &error("SOURCES for $name are empty"); } | |
$ldflags = $makefile_hash{$prefix."_LDFLAGS"}; | |
$ldflags .= " ".$makefile_hash{$prefix."_LDADD"}; | |
$ldflags .= " ".$makefile_hash{$prefix."_LIBADD"}; | |
$ldflags .= " ".$makefile_hash{"LIBADD"}; | |
$ldflags .= " ".$makefile_hash{"LDADD"}; | |
$ldflags .= " ".$makefile_hash{"AM_LDFLAGS"}; | |
$ver=$ldflags; | |
if( $ver =~ /-version-info (\d(\d|\.|:)+)/ ) { | |
$ver =~ s/^.*-version-info (\d(\d|\.|:)+).*$/\1/; | |
$ver =~ s/:/./g; | |
} else { | |
$ver=""; | |
} | |
$link = ""; | |
%autotools_cmake_link_map = ( | |
"\$(LIB_TDEPRINT)" , "tdeprint-shared" , | |
"\$(LIB_TDEHTML)" , "tdehtml-shared" , | |
"\$(LIB_TDEIO)" , "tdeio-shared" , | |
"\$(LIB_TDEUI)" , "tdeui-shared" , | |
"\$(LIB_TDECORE)" , "tdecore-shared" , | |
"\$(LIB_TDEDNSSD)" , "tdednssd-shared" , | |
"\$(LIB_TDESYCOCA)", "tdeio-shared" , | |
"\$(LIB_TDEGAMES)" , "tdegames-shared" , | |
"-lkateinterfaces" , "kateinterfaces-shared", | |
"-lkonq" , "konq-shared" ); | |
foreach $ld ( split ( /\s+/, $ldflags ) ) { | |
if ( exists $autotools_cmake_link_map{$ld} ) { | |
$link .= " " . $autotools_cmake_link_map{$ld}; | |
} elsif ( $ld =~ /\/lib([^\/]+?)\.la/ ) { | |
$link .= " $1-shared"; | |
} | |
} | |
$link =~ s/^\s+// | |
# TODO: check if AUTOMOC is mandatory | |
&info("Adding $bin_types{$type} target $name"); | |
$entry = "\n".&box_comment( $name." ($bin_types{$type})")."\n\n"; | |
given($bin_types{$type}) { | |
when('executable') | |
{ $entry .= "tde_add_executable( $name AUTOMOC\n"; } | |
when('test') | |
{ $entry .= "tde_add_executable( $name AUTOMOC\n"; } | |
when('tdeinit') | |
{ $entry .= "tde_add_tdeinit_executable( $name AUTOMOC\n"; } | |
when('kpart') | |
{ $entry .= "tde_add_kpart( $name AUTOMOC\n"; } | |
when('static') | |
{ $entry .= "tde_add_library( $name STATIC_PIC AUTOMOC\n"; } | |
when('shared') | |
{ $entry .= "tde_add_library( $name SHARED AUTOMOC\n"; } | |
} | |
$entry .= fix_width( 1, "SOURCES $sources"); | |
$entry .= fix_width( 1, "VERSION $ver") if( $ver ); | |
$entry .= fix_width( 1, "LINK $link") if( $link ); | |
given($bin_types{$type}) { | |
when('executable') | |
{ $entry .= fix_width( 1, "DESTINATION \$\{BIN_INSTALL_DIR\}"); } | |
when('shared') | |
{ $entry .= fix_width( 1, "DESTINATION \$\{LIB_INSTALL_DIR\}"); } | |
when('kpart') | |
{ $entry .= fix_width( 1, "DESTINATION \$\{PLUGIN_INSTALL_DIR\}"); } | |
when('test') {} | |
when('tdeinit') {} | |
when('static') {} | |
} | |
$entry .= ")\n"; | |
do_skip_line; | |
print $entry; | |
$skip_line = 1; | |
if( $bin_types{$type} eq 'test' ) { | |
$entry = "add_test( NAME $name-test\n"; | |
$entry .= fix_width( 1, "COMMAND $name)"); | |
do_skip_line; | |
print $entry; | |
$skip_line = 1; | |
} | |
} | |
} | |
$skip_line+=1; | |
} | |
######### icons ################################# | |
if( $have_icon ) { | |
if( $have_compilation || $have_subdir) { | |
do_skip_line; | |
print &box_comment("icons")."\n"; | |
$skip_line = 1; | |
} | |
if( exists $makefile_hash{"KDE_ICON"}) { | |
my ( $entry, $icons ); | |
$icons = $makefile_hash{"KDE_ICON"}; | |
if ( $icons =~ /^AUTO$/ ) { | |
&info("Adding auto icon enrty"); | |
$entry = &fix_width( 0, "tde_install_icons( )"); | |
} else { | |
&info("Adding instalation of icon \"$icons\" to default dirs"); | |
$entry = &fix_width( 0, "tde_install_icons( ".$icons." )"); | |
} | |
do_skip_line; | |
print $entry."\n"; | |
$skip_line = 1; | |
} | |
} | |
######### other data ############################ | |
sub process_install_data (*) { | |
$data_designator= shift; | |
%data_dirs=( | |
'xdg_apps', '${XDG_APPS_INSTALL_DIR}', | |
'kde_kcfg', '${KCFG_INSTALL_DIR}', | |
'autostart', '${AUTOSTART_INSTALL_DIR}'); | |
%autotools_cmake_dir_map= ( | |
'$(kde_datadir)', '${DATA_INSTALL_DIR}', | |
'$(kde_appsdir)', '${APPS_INSTALL_DIR}', | |
'$(kde_mimedir)', '${MIME_INSTALL_DIR}', | |
'$(kde_servicesdir)', '${SERVICES_INSTALL_DIR}', | |
'$(kde_confdir)', '${CONFIG_INSTALL_DIR}', | |
'$(includedir)', '${INCLUDE_INSTALL_DIR}', | |
'$(kde_datadir)/kconf_update', '${KCONF_UPDATE_INSTALL_DIR}', | |
'$(datadir)/autostart', '${AUTOSTART_INSTALL_DIR}', | |
'$(kde_servicetypesdir)', '${SERVICETYPES_INSTALL_DIR}'); | |
foreach $data (grep( /.*$data_designator/ , keys %makefile_hash)) { | |
my $type = $data; | |
$type =~ s/$data_designator$//; | |
if( exists $makefile_hash{$type."dir"} ) { | |
my $ok=0; | |
$dir=$makefile_hash{$type."dir"}; | |
foreach $guess (keys %autotools_cmake_dir_map ) { | |
if( $dir =~ /\Q$guess\E/ ) { | |
$dir =~ s/\Q$guess\E/$autotools_cmake_dir_map{$guess}/; | |
$ok=1; | |
} | |
} | |
if( $ok ) { | |
$data_dirs{$type} = $dir; | |
} else { | |
&error("Failed to guess dir for ${data}"); | |
} | |
} else { | |
if( ! grep( $type , keys %data_dirs) ) { | |
&error("Destination for ${data} is missing"); | |
} | |
} | |
} | |
foreach $type ( keys %data_dirs ) { | |
if( exists $makefile_hash{$type."$data_designator"}) { | |
my ( $entry, $files, $dest ); | |
$files = $makefile_hash{$type."$data_designator"}; | |
$dest = $data_dirs{$type}; | |
&info("Adding instalation of files \"$files\" to $dest"); | |
$entry = &fix_width( 0, "install( FILES ".$files); | |
$entry .= &fix_width(1, "DESTINATION $dest"); | |
$entry .= ")\n"; | |
do_skip_line; | |
print $entry; | |
$skip_line = 1; | |
} | |
} | |
} | |
if( $have_data ) { | |
if( $have_compilation || $have_subdir || $have_icon) { | |
do_skip_line; | |
print &box_comment("other data")."\n"; | |
$skip_line = 1; | |
} | |
&process_install_data( "_DATA" ); | |
$skip_line += 1; | |
} | |
if( $have_headers ) { | |
if( $have_compilation || $have_subdir || $have_icon || $have_data ) { | |
do_skip_line; | |
print &box_comment("headers")."\n"; | |
$skip_line = 1; | |
} | |
&process_install_data( "_HEADERS" ); | |
$skip_line += 1; | |
} | |
######### doc ################################### | |
if( $have_doc ) { | |
if( File::Find::Rule | |
->maxdepth(1) | |
->name("*.docbook") | |
->in($full_pkg_dir) == 0 ) { | |
$have_doc=0; | |
&warning("Seems we haven't got docs; skipping it;"); | |
} else { | |
if( $have_compilation || $have_subdir || $have_icon || $have_data) { | |
do_skip_line; | |
print &box_comment("documentation")."\n"; | |
$skip_line = 1; | |
} | |
if($makefile_hash{'KDE_DOCS'} =~ /\s/ ) { | |
&error("KDE_DOCS got multiple values. it is not supported yet."); | |
} else { | |
my $dest; | |
my $lang = $makefile_hash{'KDE_LANG'}; | |
my $doc=$makefile_hash{'KDE_DOCS'}; | |
# add NOINDEX if it doesn't exists | |
my $index_str=""; | |
if( File::Find::Rule | |
->maxdepth(1) | |
->name("index.docbook") | |
->in($full_pkg_dir) == 0 ) { | |
$index_str="\nNOINDEX"; | |
} | |
if ($doc =~ /^AUTO$/ ) { | |
if( $pkg_dir !~ /^(\w|-)+$/ ) { | |
&error("using bad pkg_dir name for docs."); | |
} | |
&info("adding handbook target with destination: \"$pkg_dir\" for LANG=$lang."); | |
$dest=$pkg_dir; | |
} else { | |
&info("adding handbook target with $doc destination for LANG=$lang."); | |
$dest=$doc; | |
} | |
if( $lang !~ /^en$/ ) { | |
if( $lang !~ /^\w{2,3}(_\w\w|@\w+)?$/ ) { | |
&error("using bad LANG=\"$lang\" name for docs."); | |
} | |
do_skip_line; | |
print "tde_create_handbook(\n"; | |
print &fix_width( 1,"DESTINATION $dest"); | |
print &fix_width( 1, "$index_str") if( $index_str ); | |
print &fix_width( 1, "LANG $lang").")\n"; | |
$skip_line += 1; | |
} else { | |
print &fix_width( 0, "tde_create_handbook( DESTINATION $dest $index_str )")."\n"; | |
} | |
} | |
} | |
$skip_line += 1; | |
} | |
######### translation ########################### | |
if( $have_translation ) { | |
if( File::Find::Rule | |
->maxdepth(1) | |
->name("*.po") | |
->in($full_pkg_dir) == 0 ) { | |
$have_translation=0; | |
&warning("Seems we haven't got translations; skipping it;"); | |
} else { | |
if( $have_compilation || $have_subdir || $have_icon || $have_data || $have_doc) { | |
do_skip_line; | |
print &box_comment("translations")."\n"; | |
$skip_line += 1; | |
} | |
my $lang = $makefile_hash{'KDE_LANG'}; | |
my $po=$makefile_hash{'POFILES'}; | |
if ($po !~ /^AUTO$/ ) { | |
&error("POFILES != AUTO is not supported by the script."); | |
} else { | |
if( $lang !~ /^\w{2,3}(_\w\w|@\w+)?$/ ) { | |
&error("using bad LANG=\"$lang\" name for translation."); | |
} | |
&info( "adding translation LANG=\"$lang\"." ); | |
do_skip_line; | |
print &fix_width( 0,"tde_create_translation( LANG $lang )"); | |
} | |
} | |
$skip_line += 1; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment