I have given below a snippet of my file.
constant BASE_C = 200;
constant FATAL_C = 4001;
constant NON_FATAL_C = 2000;
constant1_SUB_C = 0;
eror_Code_1 = BASE_C +
(2 * constant1_SUB_C) + FATAL_C;
constant2_SUB_C = 1 +
constant1_SUB_C;
error_Code_2 = BASE_C +
(2 * constant2_SUB_C) + NON_FATAL_C
.......
.......
....... and so on
So manually if i calucalte
error_Code_1 is 4201
error_Code_2 is 2002
So I have thousands of error codes in my file,
can any one guide me to write a tcl script to print the error code as
well as its name like above?
regards
Sreerama V
I do not completely understand the sort of computations you need,
but:
global count
set count 0
proc constant {name = value} {
global count
set countold $count
incr count
if { $count == 1 } {
puts "constant${count}_SUB_C = 0;"
} else {
puts "constant${count}_SUB_C = 1 +
constant${countold}_SUB_C;"
}
puts "
constant${count}_SUB_C = 0;
eror_Code_${Count} = BASE_C +
(2 * constant$count}_SUB_C) + FATAL_C;"
}
should get you started.
Regards,
Arjen
Do you want to just regenerate the "errorXXX is YYY" lines for the
specific ruleset above, or do you want to parse *any* similar C-like
ruleset syntax and output the resulting constant values ?
-Alex
Alex,
Thank you very much, for the support. TCL community is really great.
whatever _C constant names I have given in the example, are not
similar in nature. They have only _C and _SUB_C in common otherwise
they are different. So I need to parse *any* similar C-like and _SUB_C
like names and just output the names and values.
Arjen,
Thank you for your support.
Instead of constant and error code names I have given above.
Please consider
VGA_TYPE_SUB_C : constant SUB_CODE_T := 0;
RGB_TYPE_C : constant ERROR_ID_T := BASE_C +
ERROR_ID_T (VGA_TYPE_SUB_C * 2) + FATAL_C;
YCBC_SUB_C : constant SUB_CODE_T := 1 +
VGA_TYPE_SUB_C;
ILR_ERROR_C : constant ERROR_ID_T := BASE_C +
ERROR_ID_T (YCBC_SUB_C * 2) + NON_FATAL_C;
regards
Sreerama V
That is a very different format from what you showed before.
You can not (easily) use the trick that Tcl treats the first word
as a command (hence my proc "constant").
You need to define your question a bit more precisely. I can
guess what you want to achieve, but suppose you show us what
you have and what you want to get. Something along these
lines:
Given lines like:
VGA_TYPE_SUB_C : constant SUB_CODE_T := 0;
(where VGA_TYPE_SUB_C and 1000 are the things that vary)
generate additional lines like:
RGB_TYPE_C : constant ERROR_ID_T := BASE_C +
ERROR_ID_T (VGA_TYPE_SUB_C * 2) + FATAL_C;
where RGB_TYPE_C is given ...
Hm, reformulating your question like this, why not:
global prevName
set prevName ""
proc makeConstant {name errorCode type} {
global prevName
... puts-statements to generate the above code,
using prevName and type for the details
#
# Administration
#
set prevName $name
}
and you use it to generate everything:
set prevName ""
makeConstant VGA_TYPE_SUB_C RGB_TYPE_C FATAL_C
makeConstant YCBC_TYPE_SUB_C ILR_ERROR_C NON_FATAL_C
...
As there is no relationship between the names VGA_TYPE_SUB_C
and RGB_TYPE that I can see, it is impossible to make a program
that will generate the second name from the first names.
Similar to fatal/non-fatal errors.
So: provide them as data. (And no need to parse the sample
statements either :))
Regards,
Arjen
Hi Arjen,
Instead of putting the whole problem, I will devide this into smaller
problems.
1) After reading a line, how to find the first character? because i
need to compare with "-".
2) To find out the value of YCBC_SUB_C above, I need to read the next
line because the executable statement ends at next line. So how do we
do this?
regards
Sreerama V
Is it necessary to parse the original? My suggestion is to set
up a new source file with lines like I showed, so that _all_
is generated.
This relieves you of writing a program that will parse the file and
interpret the contents. With the approach I gave, you will leave
it to Tcl :)).
However, here are some parsing suggestions:
- Read the file line by line and use [string trim] to get rid of the
leading and trailing blanks
- If the line does not end with a semicolon (;), then the next one
is relevant too. Just append it with a \n, like:
append all_lines "\n$line"
- You may need to use regexp to get access to the relevant bits
and pieces, but that is for later.
Regards,
Arjen
OK to your problem is basically parsing a very limited subset of C-
like syntax, namely simple assignments.
Assuming there are no comments in the file, one can simply do:
set ch [open file r]
set whole [read $ch]
foreach statement [split $whole \;] {
regsub -all {[ \t\r\n]+} $statement {} statement
dosomething $statement
}
The above code splits on the ";" and removes all whitespace.
Then it is up to the 'dosomething' function to actually exploit them.
Since you have given two incompatible syntaxes in two posts, I don't
quite understand what the exact target is, however I assume you'll be
able to generalize.
Assuming you want to parse the form in your first post:
?constant? variable = expression ;
Then we can write it this way:
proc dosomething $st {
# extract left and right sides of the first "="
if {![regexp {^([^=]*)=(.*)$} $st -> head tail]} {
error SYNTAX:$st
}
# var name is last token of left side (to skip "constant" et
al)
set var [lindex $head end]
# then we turn the C expression into a Tcl one by
# prefixing var names with '$'
regsub -all {[A-Za-z_][A-Za-z_0-9]*} $tail {$&} exp
# the we eval in the caller's context Tcl code
# that assigns the named var to the given expr
# and then spits out "var = value"
uplevel 1 "set $var \[expr {$exp}\];puts \"$var = \$$var\""
}
HTH,
-Alex
Thank you Arjen, I will start my work with this and let you know the
results and problems.
regards
Sreerama V
Hi Alex,
I am beginner, really your stuff is going to help me in this task.
I will start working on this and let you know how it goes.
regards
Sreerama V
package VGA_ERROR_CODES_P
is
function "+" (L,R : BIT_ERROR_CODES_P.SUB_CODE_T) return
BIT_ERROR_CODES_P.SUB_CODE_T
renames BIT_ERROR_CODES_P."+";
function "*" (L,R : BIT_ERROR_CODES_P.SUB_CODE_T) return
BIT_ERROR_CODES_P.SUB_CODE_T
renames BIT_ERROR_CODES_P."*";
function "+" (L,R : BIT_ERROR_CODES_P.ERROR_ID_T) return
BIT_ERROR_CODES_P.ERROR_ID_T
renames BIT_ERROR_CODES_P."+";
BASE_C : constant BIT_ERROR_CODES_P.ERROR_ID_T := 2000;
FATAL_C : constant BIT_ERROR_CODES_P.ERROR_ID_T := 1;
NON_FATAL_C : constant BIT_ERROR_CODES_P.ERROR_ID_T := 2;
EXTERNAL_C : constant BIT_ERROR_CODES_P.ERROR_ID_T := 25;
subtype ERROR_ID_T is BIT_ERROR_CODES_P.ERROR_ID_T;
subtype SUB_CODE_T is BIT_ERROR_CODES_P.SUB_CODE_T
range 0 .. BIT_ERROR_CODES_P.SUB_CODE_T
(RBC_ERROR_CODES_P.VGA_NUMBER_C - 1);
RGB_MSG_INFO_NEW_VGA_BAD_DEST_TYPE_SUB_C : constant
SUB_CODE_T := 0;
RGB_MSG_INFO_NEW_VGA_BAD_DEST_TYPE_C : constant
ERROR_ID_T := BASE_C +
ERROR_ID_T (RGB_MSG_INFO_NEW_VGA_BAD_DEST_TYPE_SUB_C * 2) +
NON_FATAL_C;
RGB_MSG_INFO_NEW_VGA_BAD_SOU_TYPE_SUB_C : constant
SUB_CODE_T := 1 +
RGB_MSG_INFO_NEW_VGA_BAD_DEST_TYPE_SUB_C;
RGB_MSG_INFO_NEW_VGA_BAD_SOU_TYPE_C : constant
ERROR_ID_T := BASE_C +
ERROR_ID_T (RGB_MSG_INFO_NEW_VGA_BAD_SOU_TYPE_SUB_C * 2) +
NON_FATAL_C;
RGB_SAFETY_LAYER_RECEIVE_FROM_RGB_BAD_MSG_SIZE_SUB_C : constant
SUB_CODE_T := 1 +
RGB_MSG_INFO_NEW_VGA_BAD_SOU_TYPE_SUB_C;
RGB_SAFETY_LAYER_RECEIVE_FROM_RGB_BAD_MSG_SIZE_C : constant
ERROR_ID_T := BASE_C +
ERROR_ID_T (RGB_SAFETY_LAYER_RECEIVE_FROM_RGB_BAD_MSG_SIZE_SUB_C
* 2) + FATAL_C;
RGB_SAFETY_LAYER_RECEIVE_FROM_RGB_LANE_SWITCH1_SUB_C : constant
SUB_CODE_T := 1 +
RGB_SAFETY_LAYER_RECEIVE_FROM_RGB_BAD_MSG_SIZE_SUB_C;
RGB_SAFETY_LAYER_RECEIVE_FROM_RGB_LANE_SWITCH1_C : constant
ERROR_ID_T := BASE_C +
ERROR_ID_T (RGB_SAFETY_LAYER_RECEIVE_FROM_RGB_LANE_SWITCH1_SUB_C
* 2) + NON_FATAL_C;
end VGA_ERROR_CODES_P;
Above is my file content,
I need to print the below output into a different output file
RGB_MSG_INFO_NEW_VGA_BAD_DEST_TYPE_C 2002
RGB_MSG_INFO_NEW_VGA_BAD_SOU_TYPE_C 2004
RGB_SAFETY_LAYER_RECEIVE_FROM_RGB_BAD_MSG_SIZE_C 2005
RGB_SAFETY_LAYER_RECEIVE_FROM_RGB_LANE_SWITCH1_C 2008
I think now I have stated my problem clearly.
regards
Sreerama V
Seems much easier to use Ada since that is what you've got:-
with Ada.Text_IO;
with VGA_Error_Codes_P;
procedure Print is
begin
Ada.Text_IO.Put_Line ("RGB_MSG_INFO_NEW_VGA_BAD_DEST_TYPE_C "
&
VGA_Error_Codes_P.Subcode_T'Image
(VGA_Error_Codes_P.RGB_MSG_INFO_NEW_VGA_BAD_DEST_TYPE_C));
......
end Print;
My approach would be:
- Read the lines, including the continuation (so up to the semicolon)
- Get the part after :=
- Remove "ERROR_ID_T" from that part
- Insert a $ before the leading alphabetical characters
- Evaluate the resulting expression
Assuming you have read the line, the code could look like:
set pos [string first ":=" $line]
set expression [string range $line [expr {$pos+2}] end]
regsub -all { ([A-Z])} $line { $\1} $expression expression
set var [... extract the name from the first part ...]
set $var [expr $expression]
Just a sketch, of course :)
Regards,
Arjen