run a prolog code with swipl in a command line - command-line

I am searching for swipl the similar feature as perl -e
In particular, I want to run prolog code in this fashion:
swipl --wanted-flag "fact(a). message:-writeln('hello')." -g "message" -t halt
This is possible to do with
swipl -f file -g "message" -t halt
where the prolog clauses are written in file
I am running swipl on the server side that takes user input as prolog clauses, therefore writing a file on the server is not a good idea.

One thing you can do is to use load_files/2 with the option stream, and load from standard input, not from an argument (you can still pass the entry point as an argument, I guess):
Say in a file fromstdin.pl you have:
main :-
load_files(stdin, [stream(user_input)]),
current_prolog_flag(argv, [Goal|_]),
call(Goal),
halt.
main :- halt(1).
and with this you can do:
$ echo 'message :- format("hello~n").' | swipl -q -t main fromstdin.pl -- message
|: hello
The comments by #false to this answer and the question will tell you what this |: is, if you are wondering, but if it annoys you, just do:
$ echo 'message :- format("hello~n").' \
| swipl -q -t main fromstdin.pl -- message \
| cat
hello
instead.
This will let you read any Prolog from standard input and call an arbitrary predicate from it. Whether this is a clever thing to do, I don't know. I would also not be surprised if there is a much easier way to achieve the same.

Related

LFS: GCC links wrong

I'm stuck on chapter 6.20 of the current LFS book. I get:
$ readelf -l a.out | grep Requesting
[Requesting program interpreter: /tools/lib64/ld-linux-x86-64.so.2]
instead of the desired:
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
The other tests lower down in the chapter all succeed.
This is my second time through the whole book being extremely careful and I got the same result last time around. Could there be some mistake?
For guidance it just said "The most likely reason is that something went wrong with the specs file adjustment.". That's a reference to 6.10 where it says "It is a good idea to visually inspect the specs file to verify the intended change was actually made" but there's no guidance as to what these intended changes are. But on this second go round I did check in /tools/lib/gcc/x86_64-pc-linux-gnu/7.2.0/specs that there was no mention of "tools" and the /usr paths were mentioned.
I seem to have solved it by making another specs file for the new compiler:
gcc -dumpspecs | sed -e 's#/tools##g' > `dirname $(gcc --print-libgcc-file-name)`/specs
After that, I redo the test:
echo 'int main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'
And all is well.

'sed' command does not work normally in PBS scripts

I use torque to submit the test script shown blow
#!/bin/bash
#PBS -N test
#PBS -l nodes=1:ppn=1
#PBS -q ser
#PBS -V
#PBS -S /bin/bash
sed 's/a//' <<< aaabbbaaa
sed 's/\(a\)//' <<< aaabbbaaa
sed 's/a\+//' <<< aaabbbaaa
The expect output should be
aabbbaaa
aabbbaaa
bbbaaa
but actually when i use qsub to submit this file, the output becomes
aabbbaaa
aaabbbaaa
aaabbbaaa
The last two commands do not work. And it seems that the character '\' leads to the fault. But why does this happen.
The sed implementation on the server probably has a different syntax than what you have locally.
Without details about the remote system, this is mildly speculative; but look for the manual page and search for an option to enable Extended Regular Expression syntax (usually -E or -r; if available, probably lose the backslash before the regex specials then).
As a partial and obvious workaround, aa* is equivalent to a\+ but no similar workaround exists for grouping.
Maybe also read up on the differences between POSIX Basic Regular Expression syntax (BRE) and ERE; though chances are your PBS system is using something which even predates POSIX if it's legacy big iron.
If you want to write code which is portable between Linux, MacOS, and whatever behemoth dinosaur OS you have on the PBS system, maybe try Perl instead of sed. Even if you can only rely on Perl 4.x constructs, that's a platform which is a lot more uniform (and also a lot more versatile) than trying to figure out how to write portable sed scripts.
perl -pe 's/(a+)//'

how to retrive a perl file using wget and execute it using a one-liner?

I'm looking to use wget to retrieve a perl file and execute it in one line. Does anyone know if this is possible/how I would go about doing this?
In order to use wget for this purpose, you would use the -O flag and give it the '-' character as an argument. From the manpage:
-O file
--output-document=file
Giving '-' as the "file" option to -O tells it to send it's output to stdout, which can then be piped into the Perl command.
You can provide the -q flag as well to turn off wget's own warning and message output:
-q
--quiet
Turn off Wget's output.
This will make things look cleaner in the shell.
So you would end up with something like:
wget -qO - http://127.0.0.1/myscript.pl | perl -
For more information on I/O redirection take a look at this:
http://www.tldp.org/LDP/abs/html/io-redirection.html
Just download and pipe to perl
curl -L http://your_location.pl | perl -
You'll sometimes see code like for install modules like cpanm.

Check if program is in path

Can sh itself check if a program exists or is in path?
I.e., not with the help of the "which" program.
I don't believe sh can directly. But perhaps something like:
which() {
save_IFS=$IFS
IFS=:
for d in $PATH; do
test -x $d/$1 && echo $d/$1
done
IFS=$save_IFS
}
and here's a nice variation that uses a subshell so that restoring IFS is not necessary:
which() (
IFS=:
for d in $PATH; do
test -x $d/$1 && echo $d/$1
done
)
Also, (in bash) if the command has been executed in the past and bash has already done the PATH search, you can see what it found with hash -t.
bash-3.2$ hash -t which
bash: hash: which: not found
bash-3.2$ which foo
bash-3.2$ hash -t which
/usr/bin/which
The utility command -v $CMD is apparently a portable option (in the sense of being part of POSIX); see also the very similar (though bash-specific) question, in particular this answer.

ExtUtils::MakeMaker PERL_MM_OPT split on whitespace work-around

ExtUtils::MakeMaker splits PERL_MM_OPT on whitespace, which means that something like the following will not work.
export PERL_MM_OPT='LIBS="-L/usr/sfw/lib -lssl -lcrypto" INC=/usr/sfw/include'
Is there a known workaround for this, or will I have to avoid using PERL_MM_OPT in this scenario?
-- update --
mobrule came up with the excellent suggestion to use tabs instead of spaces. mobrule is right about it splitting on spaces only. However, the solution doesn't work because it looks like tabs are converted to spaces in environment variables.
> cat tmp.sh
export PERL_MM_OPT='LIBS="-L/usr/sfw/lib -lssl -lcrypto" INC=-I/usr/sfw/include'
echo $PERL_MM_OPT | perl -pe 's/\t/[t]/g' | perl -pe 's/ /[s]/g'
> head -1 tmp.sh | perl -pe 's/\t/[t]/g' | perl -pe 's/ /[s]/g'
export[s]PERL_MM_OPT='LIBS="-L/usr/sfw/lib[t]-lssl[t]-lcrypto"[s]INC=-I/usr/sfw/include'
> bash tmp.sh
LIBS="-L/usr/sfw/lib[s]-lssl[s]-lcrypto"[s]INC=-I/usr/sfw/include
-- update 2 --
So, the tab suggestion worked (I was misled by the behavior of echo, and came to the wrong conclusion as to why it failed,) but it doesn't solve the problem.
Now the problem is that ExtUtils/Liblist/Kid.pm isn't expecting a leading doublequote (same result happens with singlequote.)
Unrecognized argument in LIBS ignored: '"-L/usr/sfw/lib
So, it seems that the solution to this problem (if one exists) can't depend on quotes.
Actually, MakeMaker.pm splits on spaces but not on all whitespace. Could you use tabs?
export PERL_MM_OPT='LIBS="-L/usr/sfw/libTab-lsslTab-lcrypto" INC=/usr/sfw/include
I think you the way you have set environment variables with tabs is OK -- it is the echo command that is converting tabs to spaces:
$ VAR='abc^Idef'
$ echo $VAR | od -c
0000000 a b c d e f \n
0000010
That looks like it didn't work. But wait:
$ export VAR
$ perl -e 'print $ENV{VAR}' | od -c
0000000 a b c \t d e f
0000007
This still might or might not work in ExtUtils::MakeMaker depending on how the parameters in $ENV{PERL_MM_OPT} get passed to a subprocess (via system, exec, open |, etc.):
system("gcc helloworld.c -lssl\t-lcrypto\t-L/usr/sfw/lib") ### 1 ###
system("gcc", "helloworld.c", "-lssl\t-lcrypto\t-L/usr/sfw/lib") ### 2 ###
system call 1 will work because when the system call has one arg with any metacharacters, it passes the command to the shell. The shell will parse the arguments correctly.
system call 2 fails because multi-arg system always bypasses the shell and gcc is stuck looking for a library with the unlikely name of"libssl^I-lcrypto^I-L/usf/sfw/lib.a". If ExtUtils::MakeMaker is using this calling style to run the compiler, then this workaround won't get the job done.