0

Here is the code excerpt:

#
# search the header for the base addresses of my slaves and other interesting properties
#
puts ""
puts "Searching \"$system_header_file_path\" for various system information..."

set C_M_N   [ string toupper $console_master_name ]

set sysid_base_re       "^\[ \t\]*#define\[ \t\]+$C_M_N\_SYSID_BASE\[ \t\]+(0x\[0-9a-fA-F\]+)"
set sysid_id_re         "^\[ \t\]*#define\[ \t\]+$C_M_N\_SYSID_ID\[ \t\]+(\[0-9a-fA-F\]+)u"
set sysid_timestamp_re  "^\[ \t\]*#define\[ \t\]+$C_M_N\_SYSID_TIMESTAMP\[ \t\]+(\[0-9a-fA-F\]+)u"
set build_id_base_re    "^\[ \t\]*#define\[ \t\]+$C_M_N\_BUILD_ID_BASE\[ \t\]+(0x\[0-9a-fA-F\]+)"
set gate_base_re        "^\[ \t\]*#define\[ \t\]+$C_M_N\_GATE_BASE\[ \t\]+(0x\[0-9a-fA-F\]+)"
set define_re           "^\[ \t\]*#define\[ \t\]+.*"

set sysid_base              "unknown"
set sysid_id                "unknown"
set sysid_timestamp         "unknown"
set build_id_base           "unknown"
set gate_base               "unknown"

set header_file [ open $system_header_file_path r ]
while { [ gets $header_file next_line ] >= 0 } {
    if { [ regexp $define_re $next_line ] } {
        if { [ regexp $sysid_base_re $next_line -> value ] } {
            set sysid_base              $value
        } elseif { [ regexp $sysid_id_re $next_line -> value ] } {
            set sysid_id                $value
        } elseif { [ regexp $sysid_timestamp_re $next_line -> value ] } {
            set sysid_timestamp         $value
        } elseif { [ regexp $build_id_base_re $next_line -> value ] } {
            set build_id_base           $value
        } elseif { [ regexp $gate_base_re $next_line -> value ] } {
            set gate_base           $value
        }
    }
}
close $header_file

I am trying to figure out these things:

File I/O

  1. Does the open command open the file as text file or binary file? If it opens as text file, how to make it open as binary file instead?
  2. How does gets $header_file cause next line to be read from file? Is the header_file some sort of file pointer?
  3. Why are we checking if the value returned by the gets is >= 0, is there no eof function in TCL?

Regular expressions

  1. What is this -> operator being used in the line with the regexp command? As far as I am aware, the regular expression command can be used without this operator as well.
gyuunyuu
  • 526
  • 5
  • 17

1 Answers1

3

This is 4 different questions in one, so don't be surprised if it ends up being closed as needing more focus. Anyways...

File I/O

  1. open by default uses text mode, converting to/from a character encoding that's based on your locale. Add b to the open mode to open in binary mode, or use fconfigure $header_file -translation binary after opening it. Details in the help for open.

  2. The variable header_file holds a symbol that tcl i/o functions translate into an internal file descriptor. The first argument of gets is the name of one of these descriptors.

  3. gets with two arguments returns the number of characters (Or bytes in binary mode) read, or -1 on an attempt to read when at end of file (Or if there's not a full line available in non-blocking mode). You can have empty lines, which would return 0. If you don't expect to ever encounter a blank line, looping using > instead of >= might be appropriate; depends on what you're doing. Details in the help for gets.

Regular expressions:

  1. -> isn't an operator, it's a variable name. It's just a convention to use it with regexp in the argument that is used to hold the entire match when you only care about captured subexpressions.
Shawn
  • 47,241
  • 3
  • 26
  • 60
  • You shouldn't use `while {![eof $f]} { gets $f line }` in tcl for the same reasons you [shouldn't do the equivalent in C](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). – Shawn Oct 10 '20 at 19:58
  • Could you kindly elaborate the last part please? I was only going to ask the last question but then ending up asking 3 other questions so I don't end up posting two set of questions for the same piece of code. – gyuunyuu Oct 10 '20 at 20:10
  • @Quantum0xE7 See the documentation for [`regexp`](https://www.tcl.tk/man/tcl8.6/TclCmd/regexp.htm). `->` is even used in one of the examples there. It's just a placeholder for when you don't care about the value being assigned to that variable (Personally, I prefer to use `_`). – Shawn Oct 10 '20 at 20:23
  • I have seen this example but did not understand why they chose -> which is a symbol and not really a name as such. Basically the -> is used in C and C++ to deference a pointer to struct and access an item inside it. We use it often when working with linked lists and other complex data structures. – gyuunyuu Oct 10 '20 at 20:26
  • 1
    @Quantum0xE7 tcl isn't C... (And virtually any string can be used as a variable name in tcl). – Shawn Oct 10 '20 at 20:30