Lately, I have been writing procs that handle hexadecimal numbers. And if I understand how the TCL interpreter works, it performs the following in order:
1) Grouping
2) Single round of Substitution
3) Command Invocation
While learning TCL, I was confused on how curly braces' literal interpretation allowed various TCL commands like 'foreach' or 'if' to work. I then convinced myself that it is these 3 basic rules which allow TCL commands to separate its arguments with curly braces and evaluate each of the arguments' value at Command Invocation.
Until today, all was well until I noticed some peculiar observations while handling hexadecimal strings containing '0x'. I have been able to workaround these issues but am more curious as to "why" TCL is behaving as it is.
Problem #1
==========
In one of my (poorly written) procedures, I perform an operation on a hexadecimal number that is NOT preceeded by the string '0x'. So therefore, when I want 'expr' to add two hexadecimal numbers, I prepend an '0x' to them. Here's an example:
% expr {0x80 + 0x01}
129 <==== This is expected
% set value1 80
% set value2 01
% expr {0x$value1 + 0x$value2}
syntax error in expression "0x$value1 + 0x$value2": extra tokens at end of expression
This is obviously not what I expected. Why is this error happening? Doesn't this completely go against the 3 basic rules which I listed above?
As a workaround, I changed all of my procs to return a hexadecimal number WITH an 0x attached. By doing this, it makes 'expr' cleaner and causes it to work as I expect (i.e. expr {$value1 + $value2} works well since value1 and value2 already contain an '0x')
Problem #2
==========
I then needed to convert a decimal number to a hexadecimal number. It is essential that these hexadecimal numbers contain padded zeroes in the header. I decided that the 'format' command was the proper command to use. In one of my TCL references, it states that the format flag # causes a leading 0x to be printed and the format flag 0 causes leading zeroes to be printed. However, based on the ordering, the following doesn't seem right.
% format %#04x 129
0x81 <==== Shouldn't this have returned 0x0081
% format %#06x 129
0x0081 <==== Shouldn't this have returned 0x000081
Is the field width specifier also counting the 0x string?
Problem #3
==========
Finally, to account for Problem #1, I decided that my procs should be smart enough to accept hexadecimal numbers that may or may not be preceeded with an '0x' string. So in the first line of my proc, I decided to use the 'string trimleft' command. But as you'll see below, leading zeroes also got trimmed off.
% string trimleft 123abc 0x
123abc <==== This is expected
% string trimleft 0x123abc 0x
123abc <==== This is expected
% string trimleft 0x0123abc 0x
123abc <==== Shouldn't this have returned 0123abc
Well, those 3 problems are it in a nutshell and basically caused me to strongly second guess my knowledge of TCL. Any help would be greatly appreciated.
1) Grouping
2) Single round of Substitution
3) Command Invocation
While learning TCL, I was confused on how curly braces' literal interpretation allowed various TCL commands like 'foreach' or 'if' to work. I then convinced myself that it is these 3 basic rules which allow TCL commands to separate its arguments with curly braces and evaluate each of the arguments' value at Command Invocation.
Until today, all was well until I noticed some peculiar observations while handling hexadecimal strings containing '0x'. I have been able to workaround these issues but am more curious as to "why" TCL is behaving as it is.
Problem #1
==========
In one of my (poorly written) procedures, I perform an operation on a hexadecimal number that is NOT preceeded by the string '0x'. So therefore, when I want 'expr' to add two hexadecimal numbers, I prepend an '0x' to them. Here's an example:
% expr {0x80 + 0x01}
129 <==== This is expected
% set value1 80
% set value2 01
% expr {0x$value1 + 0x$value2}
syntax error in expression "0x$value1 + 0x$value2": extra tokens at end of expression
This is obviously not what I expected. Why is this error happening? Doesn't this completely go against the 3 basic rules which I listed above?
As a workaround, I changed all of my procs to return a hexadecimal number WITH an 0x attached. By doing this, it makes 'expr' cleaner and causes it to work as I expect (i.e. expr {$value1 + $value2} works well since value1 and value2 already contain an '0x')
Problem #2
==========
I then needed to convert a decimal number to a hexadecimal number. It is essential that these hexadecimal numbers contain padded zeroes in the header. I decided that the 'format' command was the proper command to use. In one of my TCL references, it states that the format flag # causes a leading 0x to be printed and the format flag 0 causes leading zeroes to be printed. However, based on the ordering, the following doesn't seem right.
% format %#04x 129
0x81 <==== Shouldn't this have returned 0x0081
% format %#06x 129
0x0081 <==== Shouldn't this have returned 0x000081
Is the field width specifier also counting the 0x string?
Problem #3
==========
Finally, to account for Problem #1, I decided that my procs should be smart enough to accept hexadecimal numbers that may or may not be preceeded with an '0x' string. So in the first line of my proc, I decided to use the 'string trimleft' command. But as you'll see below, leading zeroes also got trimmed off.
% string trimleft 123abc 0x
123abc <==== This is expected
% string trimleft 0x123abc 0x
123abc <==== This is expected
% string trimleft 0x0123abc 0x
123abc <==== Shouldn't this have returned 0123abc
Well, those 3 problems are it in a nutshell and basically caused me to strongly second guess my knowledge of TCL. Any help would be greatly appreciated.