in reply to did you mean python
The main problem is that pyton and perl interpreters have different command line arguments and so detecting the script name is a pain. Otherwise, once you have the code, detecting computer language is a solved problem if avoiding the edges.
My line of attack is to pass the whole CLI (edit: CLI means command-line params really) to a Perl diy interpreter which uses builtin CLI and script parsing (perl_parse()) to assess if the CLI and the provided script/one-liner parse as valid Perl CLI/Perl code. If it does not it passes the whole CLI to pyton via exec. This check is lame because if you intended to run Perl code which has syntax errors or your Perl CLI has errors then it will assume it is not Perl.
This is better done by whipping our own Perl interpreter via perlembed and taking advantage of its builtin CLI and script parsing. Doing it via a Perl script is also possible following a similar approach using eval().
Well, hopefully this can ascend you a step or two in the PyAno process, leading to Liberation soon,
bw bliako
EDIT: usage:
after compiling it:
gcc python.c -o python `perl -MExtUtils::Embed -e ccopts -e ldopts`run it with a perl or python script or one-liner, using any valid switches for any of the two interpreters:
python myperl.pl python -e 'print reverse reverse split//,"Just another Perl Hacker"' python mypy.py python -c 'import sys'
Note, the below program has been modified a couple of times already
/* python.c - 27/01/2026 by bliako (bliako at cpan org) for https://perlmonks.org/?node_id=11167241 Run perl or python scripts without caring for what is which. It runs the whole command-line first through the Perl interpreter and if it encounters syntax errors or params errors, it runs the whole command-line with all switches passed, through the python interpreter. Unless evnironment variable PERL_PYTHON_EXECUTOR_DEBUG is set, the output from the Perl interpreter will be redirected to ./logger.stderr Run it either with a Perl command-line params and a Perl script, like you would normally do with perl script.pl, e.g. perl -e ... etc. or with python CL params and a python script. If the script does not parse as valid Perl code, it will pass the CLI and the script to a python interpreter. CAVEAT: it will fallback to python if your script is Perl but has syntax errors. Note the distinction between syntax errors and runtime errors. compile it with: gcc python.c -o python `perl -MExtUtils::Embed -e ccopts -e ldopt +s` Tested only on Linux but it should be portable as it uses only POSIX and perlembed functions. */ #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <EXTERN.h> /* from the Perl distribution */ #include <perl.h> /* from the Perl distribution */ static PerlInterpreter *my_perl; /*** The Perl interpreter ***/ /* You gotta love Perl */ /* You gotta love C too! */ /* these are used for muting and redirecting stderr/stdout to a file and restoring it back */ typedef struct _STD_MUTE_DATA { int old[2]; int new[2]; char *logger_filename[2]; } std_mute_data_t; int std_mute(unsigned char mute, int fd, std_mute_data_t *smd); int main(int argc, char **argv, char **env) { // export PERL_PYTHON_EXECUTOR_DEBUG=1 // or PERL_PYTHON_EXECUTOR_DEBUG=1 python ... // will enable debug mode // debug or not error messages from failed execution // of input script will persist. char *debug = getenv("PERL_PYTHON_EXECUTOR_DEBUG"); /* if( debug && env ){ // this prints the current ENV if PERL_PYTHON_EXECUTOR_DEBUG i +s set (to something) printf("CURRENT ENVIRPONMENT:\n"); char **p = env; while( *p ){ printf("%s\n", *p); p++; } } */ std_mute_data_t mydata; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; // with last param being NULL we don't pass any env // instead the current env will be used, which means is the same // as passing env from main() if( ! debug ){ // redirect stderr only so we don't see syntax errors // errors go to file 'logger.stderr' mydata.logger_filename[0] = "logger.stdout"; mydata.logger_filename[1] = "logger.stderr"; if( -1 == std_mute(1, 2, &mydata) ){ fprintf(stderr, "%s : std +_mute(ON) has failed.\n"); exit(1); } } int ret = perl_parse(my_perl, NULL, argc, argv, (char **)NULL); if( ! debug ){ // unmute stderr if( -1 == std_mute(0, 2, &mydata) ){ fprintf(stderr, "%s : std +_mute(ON) has failed.\n"); exit(1); } } if( ret ){ perl_destruct(my_perl); perl_free(my_perl); // add here language detection logic, // various options available open source if( debug != NULL ) fprintf(stderr, "I guess it is &*^#$* pyto +n /sic/ ...\n"); // this needs #define _GNU_SOURCE and a compiler // which understands it, e.g. gcc: //execvpe("/usr/bin/python", argv, env); // else use this: execv("/usr/bin/python", argv); // this program terminates here because of exec*() // it does not leave this branch and moves below until exit() // btw we have already cleanup perl above } if( debug != NULL ) printf("It parses as Perl so I am running it . +..\n"); perl_run(my_perl); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); exit(EXIT_SUCCESS); } /* Mute or restore stdout (fd=1) or stderr (fd=2). Muting redirects std* to a file named in smd->logger_filename[0] and smd->logger_filename[1] mute will mute if set to 1 and unmute if set to 0. There may be bugs in the following code. Since it uses POSIX functions I assume it runs on OS other than Linux which was tested on. */ int std_mute(unsigned char mute, int fd, std_mute_data_t *smd){ int i = fd - 1; if( (fd < 0) || (fd > 2 ) ){ fprintf(stderr, "std_mute(): fd must be + 1 or 2 and not %d.\n", fd); return(-1); } if( mute > 0 ){ if( -1 == (smd->old[i]=dup(fd)) ){ fprintf(stderr, "std_mute(): on + dup(fd=%d) : %s\n", fd, strerror(errno)); return(-1); } if( -1 == (smd->new[i]=open(smd->logger_filename[i], O_CREAT|O_TRU +NC|O_WRONLY, 0600)) ){ fprintf(stderr, "std_mute(): on open logger, f +ilename '%s': %s\n", smd->logger_filename[i], strerror(errno)); exit( +1); } if( close(fd) == -1 ){ fprintf(stderr, "std_mute(): on close(fd=%d +) : %s\n", fd, strerror(errno)); return(-1); } dup2(smd->new[i], fd); // now all STD* send to the loggers } else { // reopen stdout if( smd->new[i] < 0 ){ fprintf(stderr, "std_mute(): attempting to +run std_mute(OFF) before std_mute(ON), ignoring.\n"); return(-1); } if( dup2(smd->new[i], fd) == -1 ){ fprintf(stderr, "std_mute(): on + dup2(fd=%d) : %s\n", fd, strerror(errno)); exit(1); } close(smd->new[i]); smd->new[i] = -1; if( fd == 1 ){ stdout =fdopen(smd->old[i++], "w"); } else if( fd == 2 ){ stderr =fdopen(smd->old[i++], "w"); } } return(0); // success }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: did you mean python
by Anonymous Monk on Jan 28, 2026 at 08:04 UTC | |
by bliako (Abbot) on Jan 28, 2026 at 12:39 UTC | |
by Anonymous Monk on Jan 28, 2026 at 14:10 UTC | |
by bliako (Abbot) on Jan 28, 2026 at 19:41 UTC | |
by Anonymous Monk on Jan 29, 2026 at 04:01 UTC | |
by bliako (Abbot) on Jan 29, 2026 at 12:00 UTC | |
by Anonymous Monk on Jan 29, 2026 at 04:10 UTC |