How to use text file as input to feed in the interactive input of smalltalk and redirect output to a file - smalltalk

I am struggling to find out is there a way to feed input
to the interactive command of gst a.st b.st ... -
and redirect the output. Normally, the interactive buffer will
have st> ... and when you type a command it will output something by calling
the default/override displayString method to the interactive output. How to get the input
and feed the output using linux command or maybe a tiny smalltalk test script to do that.
Thank you.

Here's a contrived demonstration program. It reads in strings from standard input until EOF, sorts them, then prints them out:
input := stdin nextLine.
c := OrderedCollection new.
[ input ~= nil ] whileTrue: [
c add: input.
input := stdin nextLine.
].
c sort do: [ :each | each printNl ]
You can run it interactively (pressed Ctrl-D after entering hhh):
$ gst sortprog.st
tttt
aaa
vvvv
hhh
'aaa'
'hhh'
'tttt'
'vvvv'
Or I can create a text file test.in with the following contents:
tttt
aaa
vvvv
hhh
Then run:
$ gst sortprog.st < test.in > test.out
And then check the contents of the output file:
$ cat test.out
'aaa'
'hhh'
'tttt'
'vvvv'
If your program has prompts, they will appear in the output file, of course. Anything going to stdout will go to that file.

Related

Issues converting a small Hex value to a Binary value

I am trying to take the contents of a file that has a Hex number and convert that number to Binary and output to a file.
This is what I am trying but not getting the binary value:
xxd -r -p Hex.txt > Binary.txt
The contents of Hex.txt is: ff
I have also tried FF and 0xFF, but would like to just use ff since the device I am pulling the info from has it in that format.
Instead of 11111111 which it should be, I get a y with 2 dots above it.
If I change it to ee, I get an i with 2 dots. It seems to be reading it just fine but according to what I have read on the xxd -r -p command, it is not outputing it in the correct format.
The other ways I have found to convert Hex to Binary have either also not worked or is a pretty big Bash script that seems unnecessary to do what I thought would be a simple task.
This also gives me the y with 2 dots.
$ for i in $(cat Hex.txt) ; do printf "\x$i" ; done > Binary.txt
For some reason almost every solution I find gives me this format instead of a human readable Binary value with 1s and 0s.
Any help is appreciated. I am planning on using this in a script to pull the Relay values from Digital Loggers devices using curl and giving Home Assistant a readable file to record the Relay State. Digital Loggers curl cmd gives the state of all 8 relays at once using Hex instead of being able to pull the status of a specific relay.
If "file.txt" contains:
fe
0a
and you run this:
perl -ane 'printf("%08b\n",hex($_))' file.txt
You'll get this:
11111110
00001010
If you use it a lot, you might want to make a bash function of it in your login profile along these lines - being extremely respectful of spaces and semi-colons that might look unnecessary:
bin(){ perl -ane 'printf("%08b\n",hex($_))' $1 ; }
Then you'll be able to do:
bin file.txt
If you dislike Perl for some reason, you can achieve something similar without it as follows:
tr '[:lower:]' '[:upper:]' < file.txt |
while read h ; do
echo "obase=2; ibase=16; $h" | bc
done

How to store a result to a variable in HP OpenVMS DCL?

I want to save the output of a program to a variable.
I use the following approach ,but fail.
$ PIPE RUN TEST | DEFINE/JOB VALUE #SYS$PIPE
$ x = f$logical("VALUE")
I got an error:%DCL-W-MAXPARM, too many parameters - reenter command with fewer parameters
\WORLD\
reference :
How to assign the output of a program to a variable in a DCL com script on VMS?
The usual way to do this is to write the output to a file and read from the file and put that into a DCL symbol (or logical). Although not obvious, you can do this with the PIPE command was well:
$ pipe r 2words
hello world
$ pipe r 2words |(read sys$pipe line ; line=""""+line+"""" ; def/job value &line )
$ sh log value
"VALUE" = "hello world" (LNM$JOB_85AB4440)
$
IF you are able to change the program, add some code to it to write the required values into symbols or logicals (see LIB$ routines)
If you can modify the program, using LIB$SET_SYMBOL in the program defines a DCL symbol (what you are calling a variable) for DCL. That's the cleanest way to do this. If it really needs to be a logical, then there are system calls that define logicals.

How to store a command output in OpenVMS

Im having an issue writing a DCL in OpenVMS in that I need the DCL to call a command and capture its output (but not output the output to the screen) Later on in the DCL I then need to print that output I stored.
Heres an example:
ICE SET FASTER !This command sets my environment to the "Faster" environment.
The above command outputs this if executed directly in OpenVMS:
Initialising TEST Environment to FASTER
--------------------------------------------------------------------------------
Using Test Search rules FASTER
Using Test Search rules FASTER
--------------------------------------------------------------------------------
dcl>
So I created a DCL in an attempt to wrap this output in order to display a more simplified output. Heres my code so far:
!************************************************************************
$ !* Wrapper for setting ICE account. Outputs Environment
$ !************************************************************************
$ on error then goto ABORT_PROCESS
$ICE_DCL_MAIN:
$ ice set 'P1'
$ ICE SHOW
$ EXIT
$ABORT_PROCESS:
$ say "Error ICING to: " + P1
$ EXIT 2
[End of file]
In the lines above ICE SET 'P1' is setting the ice environment, but I dont want this output to be echoed to VMS. But what I do want is to write the output of $ICE SHOW into a variable and then echo that out later on in the DCL (most of which ive omitted for simplification purposes)
So what should be outputted should be:
current Test Environment is DISK$DEVELOPERS:[FASTER.DEVELOP]
Instead of:
Initialising TEST Environment to FASTER
--------------------------------------------------------------------------------
Using Test Search rules FASTER
Using Test Search rules FASTER
--------------------------------------------------------------------------------
current Test Environment is DISK$DEVELOPERS:[FASTER.DEVELOP]
Ive had a look through the manual and im getting a bit confused so I figured I tried here. Id appreciate any pointers. Thanks.
EDIT
Here is what ive come up with after the comments, the problem im having is when I connect to VMS using an emulator such as SecureCRT the correct output is echoed. But when I run the DCL via my SSH2 library in .NET it doesnt output anything. I guess thats because it closes the SYS$OUTPUT stream temporarily or something?
$ !************************************************************************
$ !* Wrapper for setting ICE account. Outputs Environment
$ !************************************************************************
$ on error then goto ABORT_PROCESS
$ICE_DCL_MAIN:
$ DEFINE SYS$OUTPUT NL:
$ ice set 'P1'
$ DEASSIGN SYS$OUTPUT
$ ice show
$ EXIT
$ABORT_PROCESS:
$ say "Error ICING to: " + P1
$ EXIT 2
[End of file]
EDIT 2
So I guess really I need to clarify what im trying to do here. Blocking the output doesnt so matter so much, im merely trying to capture it into a Symbol for example.
So in C# for example you can have a method that returns a string. So you'd have string myResult = vms.ICETo("FASTER"); and it would return that and store it in the variable.
I guess im looking for a similar thing in VMS so that once ive iced to the environment I can call:
$ environment == $ICE SHOW
But I of course get errors with that statement
The command $ assign/user_mode Thing Sys$Output will cause output to be redirected to Thing until you $ deassign/user_mode Sys$Output or next executable image exits. An assignment without the /USER_MODE qualifier will persist until deassigned.
Thing can be a logical name, a file specification (LOG.TXT) or the null device (NLA0:) if you simply want to flush the output.
When a command procedure is executed the output can be redirected using an /OUTPUT qualifier, e.g. $ #FOO/output=LOG.TXT.
And then there is piping ... .
You can redirect the output to a temp file and then print its content later:
$ pipe write sys$output "hi" > tmp.tmp
$ ty tmp.tmp
VMS is not Unix, DCL is not Bash: you can not easily set a DCL symbol from the output of a command.
Your ICE SHOW prints one line, correct? The first word is always "current", correct?
So you can create a hack.
First let me fake your ICE command:
$ create ice.com
$ write sys$output "current Test Environment is DISK$DEVELOPERS:[FASTER.DEVELOP]"
^Z
$
and I define a dcl$path pointing to the directory where this command procedure is
so that I can use/fake the command ICE
$ define dcl$path sys$disk[]
$ ice show
current Test Environment is DISK$DEVELOPERS:[FASTER.DEVELOP]
$
Now what you need, create a command procedure which sets a job logical
$ cre deflog.com
$ def/job/nolog mylog "current''p1'"
^Z
$
And I define a command "current" to run that command procedure:
$ current="#deflog """
Yes, you need three of the double quotes at the end of the line!
And finally:
$ pipe (ice show | #sys$pipe) && mysym="''f$log("mylog")'"
$ sh symb mysym
MYSYM = "current Test Environment is DISK$DEVELOPERS:[FASTER.DEVELOP]"
$
On the other hand, I don't know what you are referring to C# and Java. Can you elaborate on that and tell us what runs where?
You can try using: DEFINE /USER SYS$OUTPUT NL:.
It works only for the next command and you dont need to deassign.
Sharing some of my experience here. I used below methods to redirect outputs to files.
Define/Assign the user output and then execute the required command/script afterwards. Output will be written to .
$define /user sys$output <file_path>
execute your command/script
OR
assign /user <file_path> sys$output
execute your command/script
deassign sys$output
To re-direct in to null device like in Unix (mentioned in above answers), you can use 'nl:' instead of
define /user sys$output nl:
or
assign /user nl: sys$output

4.1 ANTLR accepts illegal input for palindrome grammar

Given the following simple palindrome grammar,
the resulting parser seems to accept any combination
of a's and b's rather than just palindromes.
[well, that was true when I incorrectly specified the start symbol; now I've revised to fix that but still don't get the desired behavior, so I'm adding my exact commands to run as well]
[and revised again, displaying suggested changes and resulting problems.]
// test1.g4
grammar test1;
palindrome
: 'z' entry EOF ;
entry
: 'a' entry 'a'
| 'b' entry 'b'
| 'a'
| 'b'
|
;
WS : [ \t\r\n]+ -> skip ;
Given this exact test1.g, I then execute the following shell script:
#!bash
# script for running ANTLR tests
ANTLR4="java -jar /usr/local/lib/antlr-4.1-complete.jar"
$ANTLR4 test1.g4
echo "grammar compiled"
x=/usr/local/lib/antlr-4.1-complete.jar
javac -classpath $x *.java 2>&1
echo "parser compiled"
#java -cp $x:. org.antlr.v4.runtime.misc.TestRig test1 start -tokens -trace -diagnost
java -cp $x:. org.antlr.v4.runtime.misc.TestRig test1 palindrome -tokens
And then running it on input "aab" gives:
aab
[#0,0:0='a',<2>,1:0]
[#1,1:1='a',<2>,1:1]
[#2,2:2='b',<1>,1:2]
[#3,4:3='<EOF>',<-1>,2:0]
No method for rule palindrome or it has arguments
If I pass aab to it, I get the following output:
line 1:3 no viable alternative at input 'b'
Are you sure you're telling it to start with entry instead of start now? If you start with entry, the generated code literally does not contain a code flow path that will not produce a syntax error for the input aab. You could hide the message by overriding the output listener, piping stdout somewhere you can't see, or terminating the process before parsing completes, but the syntax error will happen otherwise.

Using Squeak from a shell

Can I launch Squeak as a REPL (no GUI), where I can enter and evaluate Smalltalk expressions? I know the default image don't allow this. Is there any documentation on how to build a minimum image that can be accessed from a command-line shell?
Here is a (hackish) solution:
First, you need OSProcess, so run this in a Workspace:
Gofer new squeaksource:'OSProcess'; package:'OSProcess';load.
Next, put this in the file repl.st:
OSProcess thisOSProcess stdOut
nextPutAll: 'Welcome to the simple Smalltalk REPL';
nextPut: Character lf; nextPut: $>; flush.
[ |input|
[ input := OSProcess readFromStdIn.
input size > 0 ifTrue: [
OSProcess thisOSProcess stdOut
nextPutAll: ((Compiler evaluate: input) asString;
nextPut: Character lf; nextPut: $>; flush
]
] repeat.
]forkAt: (Processor userBackgroundPriority)
And last, run this command:
squeak -headless path/to/squeak.image /absolute/path/to/repl.st
You can now have fun with a Smalltalk REPL. Dont forget to type in the command:
Smalltalk snapshot:true andQuit:true
if you want to save your changes.
Now, onto the explanation of this solution:
OSProcess is a package that allows to run other processes, read from stdin, and write to stdout and stderr. You can access the stdout AttachableFileStream with OSProcess thisOSProcess (the current process, aka squeak).
Next, you run an infinite loop at userBackgroundPriority (to let other processes run). In this infinite loop, you use Compiler evaluate: to execute the input.
And you run this in a script with a headless image.
As of Pharo 2.0 (and 1.3/1.4 with the fix described below), there are no more hacks necessary. The following snippet will turn your vanilla Pharo image into a REPL server...
From https://gist.github.com/2604215:
"Works out of the box in Pharo 2.0. For prior versions (definitely works in 1.3 and 1.4), first file in https://gist.github.com/2602113"
| command |
[
command := FileStream stdin nextLine.
command ~= 'exit' ] whileTrue: [ | result |
result := Compiler evaluate: command.
FileStream stdout nextPutAll: result asString; lf ].
Smalltalk snapshot: false andQuit: true.
If you want the image to always be a REPL, put the code in a #startup: method; otherwise, pass the script at the command line when you want REPL mode, like:
"/path/to/vm" -headless "/path/to/Pharo-2.0.image" "/path/to/gistfile1.st"
Please visit:
http://map.squeak.org/package/2c3b916b-75e2-455b-b25d-eba1bbc94b84
and Run Smalltalk on server without GUI?
The project http://www.squeaksource.com/SecureSqueak.html includes a REPL package that may provide much of what you are looking for.