my $self = shift; • Takahiro SHIMIZU (id:ANATOFUZ) • a.k.a “anagra” • I’m from Okinawa in Japan. • I belong to Okinawa.pm • A graduate student in Ryukyu-Univ. • My graduate study was MoarVM.
This talk is… • We usually use plenv, perlbrew, homebrew, apt and yum when install perl5. • These commands automatically execute shell scripts and execute make command.
This talk is… • What if you have to install Perl without using package manager commands? • I think to get Perl Source Code, do compile and execute install. (copy to contain PATH directory) • These processes are called “builds".
the historical Perl version is located • At the beginning of this talk, let’s think about where the source code of the historical Perl version is located.
the historical Perl version is located • At the beginning of this talk, let’s think about where the source code of the historical Perl version is located.
the historical Perl version is located • At the beginning of this talk, let’s think about where the source code of the historical Perl version is located.
How to get a traditional Perl Source Code • Easy to download from GitHub. • If you want to get commit logs. • If you do not want to get commit logs. git clone -b perl-1.0 —single-branch [email protected]:Perl/perl5.git wget https://github.com/Perl/perl5/archive/perl-1.0.tar.gz
Traditional Perl build flow. • makedpened is actually executed at also perl5 (it is executed automatically) • Basically it is almost the same as modern perl5!! • old perl (strictly around Perl3) depends manually on make
How to create Configure • Handwriting✍ (we must follow update OS) • Not use Configure (using Cmake, using other build tools) • create Configure from Some tools.
How to create Configure • I think people often use so-called GNU tools such as autoconf and automake. • autoconf commands, create Configure using setting file called configure.in. • Created Configure create Makefile using makefile.in. (It is automake to automatically generate makefile.in)
Configure in Perl • Perl does not have a configure.in at from 1.0 • First of all, autoconf was not released in Perl 1.0 era. (Autoconf 1991 release, Perl 1987 release) • I wondered how Larry was creating the settings.
A.「He creates dist toolkit by himself」 • Larry creates dist toolkit by himself. • dist is create Configure using setting files. • —> create package from codes. • —> sent the package to email. • Also, the maintenance right was handed over to other people immediately after publication.
metaconfig • Perl script named metaconfig to generate configure. • Older brother of autoconf (also written in wikipedia) • Not metaconfig in the current GitHub Perl 5 repository.
present day dist/metaconfig • The dist toolkit's metaconfig is plainly maintained. • But, Perl 4 flavored source code that can run on Perl 5. • Some dist toolkits are not maintained as Perl 5 (eg there is code left requiring getopts.pl)
present day dist/metaconfig • metaconfig ins in the dist toolkit. • They are continuously maintained. • metaconfig can execute by Perl5! But, It is Perl4 flavor source code.
a part of metaconfig source code sub main'profile { &auto_main'profile; } sub auto_main'profile { &main'dataload; } # Load the calling function from DATA segment and call it. This function is # called only once per routine to be loaded. sub main'dataload { local($__packname__) = (caller(1))[3]; $__packname__ =~ s/::/'/; local($__rpackname__) = $__packname__; local($__at__) = $@; $__rpackname__ =~ s/^auto_//; &perload'load_from_data($__rpackname__); local($__fun__) = "$__rpackname__"; $__fun__ =~ s/'/'load_/; eval "*$__packname__ = *$__fun__;"; # Change symbol table entry die $@ if $@; # Should not happen $@ = $__at__; # Restore value $@ had on entrance &$__fun__; # Call newly loaded function
present-day dist/metaconfig • For historical Perl, Perl's configuration file (* .SH) required to run metaconfig can be used at that time, which is convenient. • Perl5's Configure is not just using dist's metaconfig, but it is becoming more and more often direct rewriting itself.
Historical Perl rough structure • Written in C and yacc, there is no big difference between Perl 5 and other Perls. • perly.c have main function. • perl.c is a parsing phase generated by perl.y (YACC) • The names of perl.c and perly.c are replaced from Perl 5.
Perl1.0 • 1987 release. The oldest existing Perl. • Older than IRC at historical. • Published at comp.sources.misc newsgroups. • Grammar definitions are done by yacc, others are written in C
In Perl man page • Perl is a interpreted language optimized for scanning arbitrary text files, extracting information from those text files, and printing reports based on that information. It's also a good language for many system management tasks. •It combines (in the author's opinion, anyway) some of the best features of C, sed, awk, and sh, so people familiar with those languages should have little difficulty with it. — by Perl1 man page
example Perl1 Scripts (subroutine) sub MAX { $max = pop(@_); while ($foo = pop(@_)) { $max = $foo if $max < $foo; } $max; } ... $bestday = do MAX($mon,$tue,$wed,$thu,$fri);
today Perl1.0 • PerlMonger has the habit of writing Perl 1.0 patches regularly (100% test passing version exists) • I was implementation Perl1.0 Docker Images. • You can easy execute Perl1.0 when using Docker.
Perl1.0 structure characteristics. • SV type advance, STR type is a simple configuration that only has char * • Naturally depends on the machine environment because it depends on the char type
Perl1.0 structure Source Code • Written in C before published K&R C second edition (Perl1.0 is written in C before ANSI-C) • Since C at that time did not have a standard, the return type of the library function was different depending on the processing system. • These are controlled by the macro.
Perl1.0 main function in C main(argc,argv,env) register int argc; register char **argv; register char **env; { register STR *str; register char *s; char *index(); linestr = str_new(80); str = str_make("-I/usr/lib/perl "); /* first There is no type in the main function. Receive environment in env. The keyword register hints to compiler that a given variable can be put in a register.
Perl1.0 main function in C main(argc,argv,env) register int argc; register char **argv; register char **env; { register STR *str; register char *s; char *index(); linestr = str_new(80); str = str_make("-I/usr/lib/perl "); /* first In the first place, the declaration of arguments is so-called K & R style
today Perl5 #ifdef NO_ENV_ARRAY_IN_MAIN extern char **environ; int main(int argc, char **argv) #else int main(int argc, char **argv, char **env) #endif { int exitstatus, i; #ifdef PERL_GLOBAL_STRUCT struct perl_vars *my_vars = init_global_struct(); # ifdef PERL_GLOBAL_STRUCT_PRIVATE int veto; main function is int type, written in perlmain.c
Perl 1.0 process flow • First of all analyze the option • Load one file at a time with the files entered • YACC parsing while lexical analysis • I will just continue to run !!
Perl2.0 is difficult… • The included Configure can be used as it is • but when make depend it is destroyed in relation to the header file of mac os ./config.h:172:19: warning: '/*' within block comment [-Wcomment] #/*undef TMINSYS /**/ ^ /usr/include/AvailabilityInternal.h:38846:2: error: #else after #else #else ^ /usr/include/AvailabilityInternal.h:38203:10: error: unterminated conditional directive #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_13 ^ /usr/include/AvailabilityInternal.h:38116:10: error: unterminated conditional
VS Configure<1> • Remake Configure itself using metaconfig that is maintained. • The newly created Configure will export files according to your environment, which will allow you to make. • You can execute make.
VS Configure<2> • We try install gcc or llvm/clang. • If you try to build gcc from source code, I think you need to use llvm / clang installed with brew. brew install gcc brew install llvm #should include PATH (at /usr/libexec/bin)
fix Makefile • and suddenly appear in Makefile • It can not be built because it does not exist as a header file…. arg.o: /usr/include/time.h arg.o: arg.o:
How to fix Makefile • The header file to be used is written to the Makefile after makedpend • So We want to change do not generate command-line etc. in makedepend's configuration file makedepend.SH
I remember •It combines (in the author's opinion, anyway) some of the best features of C, sed, awk, and sh, so people familiar with those languages should have little difficulty with it. — by Perl1 man page
I remember •It combines (in the author's opinion, anyway) some of the best features of C, sed, awk, and sh, so people familiar with those languages should have little difficulty with it. — by Perl1 man page
Forced resolution • But, We have a Per1!!!! • I use Perl1 “one liner”!!! • Of course you can do it with Perl5 !!! $./perl -ni -e 'print unless /(built-in)|(command line)/;’ Makefile
Forced resolution • But, We have a Per1!!!! • I use Perl1 “one liner”!!! • Of course you can do it with Perl5 !!! $./perl -ni -e 'print unless /(built-in)|(command line)/;’ Makefile
fix YACC • An error is generated by stabval for which nothing is described in YACC %type prog decl format %type %type block lineseq line loop cond sideff nexpr else
fix YACC • sprintf separates char pointer or int ... • Currently int type • It is not necessary because sprintf includes header files in the first place #ifdef CHARSPRINTF char *sprintf(); #else int sprintf(); #endif
correct C language Source • unkown type name UIDTYPE…!? Really…!? ./perl.h:235:1: error: unknown type name 'UIDTYPE' UIDTYPE getuid(); ^ ./perl.h:236:1: error: unknown type name 'UIDTYPE' UIDTYPE geteuid(); ^ ./perl.h:237:1: error: unknown type name 'GIDTYPE' GIDTYPE getgid(); ^ ./perl.h:238:1: error: unknown type name 'GIDTYPE' GIDTYPE getegid();
correct C language Source • Modified typed!!!!!!!! NAME geteuid, getuid -- get user identification SYNOPSIS #include uid_t geteuid(void); uid_t getuid(void);
correct C language Source • conflicting types …!!! In file included from arg.c:10: ./perl.h:275:14: error: conflicting types for 'times' long time(), times(); ^
correct C language Source • It is heartbreaking that errors increase.... arg.c:934:43: error: incomplete definition of type 'struct tms' apush(ary,str_nmake(((double)timesbuf.tms_utime)/HZ)); ~~~~~~~~^ ./perl.h:226:12: note: forward declaration of 'struct tms' EXT struct tms timesbuf; ^ arg.c:935:43: error: incomplete definition of type 'struct tms' apush(ary,str_nmake(((double)timesbuf.tms_stime)/HZ)); ~~~~~~~~^ ./perl.h:226:12: note: forward declaration of 'struct tms' EXT struct tms timesbuf; ^ arg.c:936:43: error: incomplete definition of type 'struct tms' apush(ary,str_nmake(((double)timesbuf.tms_cutime)/HZ));
correct C language Source • morecoer is not defined as static, etc… malloc.c:155:1: error: static declaration of 'morecore' follows non-static declaration malloc.c:126:5: note: previous implicit declaration is here morecore(bucket); ^ malloc.c:164:5: error: non-void function 'morecore' should return a value [- Wreturn-type] return; ^ malloc.c:181:5: error: non-void function 'morecore' should return a value [- Wreturn-type] return; ^
correct C language Source • I will put a word of magic! • If you do something with Gcc, it will automatically enter but not clang static morecore(register); static findbucket(union overhead*, int);
Perl4.0 • There is a problem of conflict with C library that function name includes • We have Perl 5 so replace to other function's name with using one-liner.
about Perl6 • The current Perl 6 is mainstream Rakudo • Rakudo is a three-stage configuration of VM + NQP (NotQuitPerl) + Perl 6 (made by NQP) • Traditional Perl 6 is probably like Pugs and Parrot
Next • I have 3 projects related to traditional Perl. • rewrite Perl1 sourcecode C to Rust. • Implementing Inline::Perl1 as Perl5 CPAN. • Implementing scripts to run all Perl versions with one liner (PERL-ALL?)