Why hoc1 grammar has the following rules - unix

I was going through hoc program written in The Unix Programming Environment. Came across the grammar as
list: /* nothing */
| list '\n'
| list expr '\n' { printf("\t%.8g\n", $2); }
;
What is the need of
| list '\n'
Looks like it will work even if we dont give that part of grammar! Then what is the importance of that part?
Printf is given with %.8g. What does that mean?
What to do if I need to give a prompt symbol? Just like $ in shell ?

Three completely unrelated questions here
The rule list: list '\n' allows it to accept (and ignore) blank lines in the input. Without it, any blank line would cause a syntax error.
The format specifier %.8g mean print a double argument with 8 digits of precision, using either normal or scientific notation, depending on what the exponent is.
If you want to print a prompt symbol, the easiest way is to do it in the lexer -- each time your yylex function reads a newline, it should print the prompt for the next line before returning the newline to the parser. If you're using flex, this could be a rule like:
\n { if (interactive) {
printf("$ ");
fflush(stdout); }
return '\n'; }
you might want to check if your input is coming from a terminal or file and set the global interactive flag appropriately.

Related

Need help in identifying what this piece of code does EXACTLY (I have a general idea)

let $removeLastCR:=fn:replace($output.output_FileContent , '(\r?\n|\r)$', '')
let $lines := tokenize($removeLastCR, '\n')
return
for $line at $counter in $lines
let $x :=
for $i in fn:tokenize($line,'"')
return
if(fn:starts-with($i,',') and fn:ends-with($i,','))
then fn:substring($i,2,fn:string-length($i)-2)
else
if(fn:starts-with($i,','))
then fn:substring-after($i,',')
else
if(fn:ends-with($i,','))
then fn:substring($i,1,fn:string-length($i)-1)
else $i
let $fields :=
for $j at $k in $x
return
if(fn:starts-with($line,'"'))
then
if($k mod 2 = 0)
then fn:tokenize($j,',')
else $j
else
if($k mod 2 = 0)
then $j
else fn:tokenize($j,',')
return
The real issue is that I am trying to understand why the parsing fails for the below data record, but works for the rest of the data in the file (File is a .CSV file):
xyz#example.com,XYZ LastName,Merchant,15/08/2022,199.98,USD,199.98,USD,61001,,,xyz#example.com | R1111111,"Qty 10- 4"" X 4"" X 5.7"" - Color: Custom Box 1",,XYZ,CC 1 August,R1111111,P&E \: PS mama,,policyid,CCP,https://www.example.com/report?reportID=R1111111,cdf,1234XXXXXX5678,https://example.com,
For the above record, the code should have parsed each comma separated value into it's own field,(Field1: xyz#example.com, Field2: XYZ LastName etc) but I think it falls apart on the field value "Qty 10- 4"" X 4"" X 5.7"" - Color: Custom Box 1". It SHOULD parse this whole value into 1 field, but it only gets "Qty 10- 4" into Field#13. And all the fields after this are also all not parsed properly.
So I was trying to better understand this code (someone else wrote it) so i can make the appropriate changes to handle this scenario.
There are many variants of CSV syntax, and it looks as if this data file is using a convention of escaping " within a quoted field by doubling the quotation marks. But the query code that parses the CSV is making no attempt to handle such escaped quotation marks.
It's easy to tell you what each line of code does, but I suspect that's not your problem. What's harder is to understand the overall logic.
The first part creates a variable $x by tokenizing on " and removing leading and trailing commas from every token. That makes no sense to me. The second part then takes the tokens that weren't in quotes and splits them on "," separators.
I think this code is already fairly broken, and it certainly can't be extended to handle quotes that are escaped by doubling. It needs to be rewritten. I don't think it can be done with simple tokenisation.
A bit of googling shows a variety of attempts at CSV to XML converters. Unfortunately few of them are very explicit about exactly what flavour of CSV they handle, and many don't even attempt to handle commas within quoted fields. Not very satisfactory, but I'm afraid that writing a better one isn't possible within the 10 minutes I allow myself for answering StackOverflow questions.

zsh: command substitution, proper quoting and backslash (again)

(Note: This is a successor question to my posting zsh: Command substitution and proper quoting , but now with an additional complication).
I have a function _iwpath_helper, which outputs to stdout a path, which possibly contains spaces. For the sake of this discussion, let's assume that _iwpath_helper always returns a constant text, for instance
function _iwpath_helper
{
echo "home/rovf/my directory with spaces"
}
I also have a function quote_stripped expects one parameter and if this parameter is surrounded by quotes, it removes them and returns the remaining text. If the parameter is not surrounded by quotes, it returns it unchanged. Here is its definition:
function quote_stripped
{
echo ${1//[\"\']/}
}
Now I combine both functions in the following way:
target=$(quote_stripped "${(q)$(_iwpath_helper)}")
(Of course, 'quote_stripped' would be unnecessary in this toy example, because _iwpath_helper doesn't return a quote-delimited path here, but in the real application, it sometimes does).
The problem now is that the variable target contains a real backslash character, i.e. if I do a
echo +++$target+++
I see
+++home/rovf/my\ directory\ with\ spaces
and if I try to
cd $target
I get on my system the error message, that the directory
home/rovf/my/ directory/ with/ spaces
would not exist.
(In case you are wondering where the forward slashes come from: I'm running on Cygwin, and I guess that the cd command just interprets backslashes as forward slashes in this case, to accomodate better for the Windows environment).
I guess the backslashes, which physically appear in the variable target are caused by the (q) expansion flag which I apply to $(_iwpath_helper). My problem is now that I can not simply drop the (q), because without it, the function quote_stripped would get on parameter $1 only the first part of the string, up to the first space (/home/rovf/my).
How can I write this correctly?
I think you just want to avoid trying to strip quotes manually, and use the (Q) expansion flag. Compare:
% v="a b c d"
% echo "$v"
a b c d
% echo "${(q)v}"
a\ b\ c\ d
% echo "${(Q)${(q)v}}"
a b c d
chepner was right: The way I tried to unquote the string was silly (I was thinking too much in a "Bourne Shell way"), and I should have used the (Q) flag.
Here is my solution:
target="${(Q)$(_iwpath_helper)}"
No need for the quote_stripped function anymore....

not able to understand NAWK use

I found a command which takes the input data from a binary file and writes into a output file.
nawk 'c-->0;$0~s{if(b)for(c=b+1;c>1;c--)print r[(NR-c+1)%b];print;c=a}b{r[NR%b]=$0}' b=1 a=19 s="<Comment>Ericsson_OCS_V1_0.0.0.7" /var/opt/fds/config/ServiceConfig/ServiceConfig.cfg > /opt/temp/"$circle"_"$sdpid"_RG.cfg
It's working but I am not able to find out how...Could anyone please help me out how above command is working and what is it doing?...this nawk is too tough to understand...:(
Thanks in advance......
nawk is not tough to understand and is same like other languages, I guess you are not able to understand it because it not properly formatted, if you format it you will know how it's working.
To answer your question this command is searching lines containing an input text in given input file, and prints few lines before matched line(s) and few lines after the matched line. How many lines to be printed are controlled by variable "b" (no of lines before) and "a" (no of lines after) and string/text to be searched is passed using variable "s".
This command will be helpful in debugging/troubleshooting where one want to extract lines from large size log files (difficult to open in vi or other editor on UNIX/LINUX) by searching some error text and print some lines above it and some line after it.
So in your command
b=1 ## means print only 1 line before the matching line
a=19 ## means print 19 lines after the matching line
s="<Comment>Ericsson_OCS_V1_0.0.0.7" ## means search for this string
/var/opt/fds/config/ServiceConfig/ServiceConfig.cfg ## search in this file
/opt/temp/"$circle"_"$sdpid"_RG.cfg ## store the output in this file
Your formatted command is below, the very first condition which was looking like c-->0 before format is easy to interpret which means c-- greater than 0. NR variable in AWK gives the line number of presently processing line in input file being processed.
nawk '
c-- > 0;
$0 ~ s
{
if(b)
for(c=b+1;c>1;c--)
print r[(NR-c+1)%b];
print;
c=a
}
b
{
r[NR%b]=$0
}' b=1 a=19 s="<Comment>Ericsson_OCS_V1_0.0.0.7" /var/opt/fds/config/ServiceConfig/ServiceConfig.cfg > /opt/temp/"$circle"_"$sdpid"_RG.cfg

Add a newline to a string in Scilab

Create a simple string in Scilab containing a newline.
Seems simple enough, but Scilab only seems to interpret escape sequences through printf style functions and msprintf / sprintf splits the string into a vector of strings at the newline!
The only way I can see to achieve this is to actually write a newline out to a file and read it back in again. Surely there is a simpler way to do this!
Ok, found it. The ascii function will do the job, a newline can be added via its ascii decimal -
str = 'hello' + ascii(10) + 'world'

Ungoogleble machine-code or otherwise hard to read EUID part

Not sure whether obfuscated, machine-code or something else. Please, let me know what the part is for and how to read it. The part is from the file.
###############################################################################
# Set prompt based on EUID
################################################################################
if (( EUID == 0 )); then
PROMPT=$'%{\e[01;31m%}%n#%m%{\e[0m%}[%{\e[01;34m%}%3~%{\e[0;m%}]$(pc_scm_f)%# '
else
PROMPT=$'%{\e[01;32m%}%n#%m%{\e[0m%}[%{\e[01;34m%}%3~%{\e[0;m%}]$(pc_scm_f)%% '
fi
could someone break it a bit more into parts?
What does the conditional EUID == 0 do?
I get an error about pc_scm_f, using OBSD, is it some sort of value in other OS?
the \e starts some sort of logical part, what do the rest do?
Looks like ANSI escape sequences to me.
I found this link which seems to contain the whole thing in proper context.
Also tells me Ferruccio is right: It's an ANSI escape string, used to change the style of the command-prompt. \e starts the escape codes, the rest is the code itself. Used to be very popular in the old DOS time, especially with a game called NetHack. It's just pretty-print for your console.

Resources