Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Initial implementation of titxt & rawbin. Update comments for better documentation.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:3196e062001691e6478be7ade36ba34d9130347e
User & Date: erikj 2017-11-09 18:12:14
Context
2017-11-13
10:59
Add ability for caller args for writefile to be passed down to format-specific writer. Use this mechanism for SREC subformats. check-in: f138c2972c user: erikj tags: trunk
2017-11-09
18:12
Initial implementation of titxt & rawbin. Update comments for better documentation. check-in: 3196e06200 user: erikj tags: trunk
2017-11-08
02:17
Add index.html for docs check-in: 0fc121c0ca user: erikj tags: trunk
Changes

Changes to binconvert.tcl.

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
..
58
59
60
61
62
63
64




65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
..
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104
...
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
...
147
148
149
150
151
152
153
154






155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172


173
174
175
176
177
178
179
...
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
...
356
357
358
359
360
361
362

363
364
365
366
367
368
369

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384

385
386
#
# Use "pycco *filename*" to re-generate HTML documentation in ./docs .
#

package require Tcl 8.6
package require logger

package provide binconvert $::BINCONVERT_PKG_VERSION

set dir [file dirname [info script]]

#--------------------------------------------------------------------------
### binconvert
#
# **binconvert** is a Tcl package that converts to & from a Tcl
# representation of a segment list.  binconvert handles multiple binary
# formats and their subtypes.  It currently handles:
#
#  * "ihex" - Intel Hex format. Includes all three subtypes: I8hex, I16hex, & I32hex.
#  * "srec" - Motorola SREC format.  Includes all three subtypes: S19, S28, & S37.
#  * "titxt" - TI .txt format, which has no subtypes.
................................................................................
##### Internal Data Representation
# Binconvert stores its memory version of the binary data in a segment list.
# A Segment List is a list of paired elements. The even elements are segment
# addresses and the odd elements are blocks of segment data, represented as
# a list of numbers 0-255 that are the values of each byte of the segment.
# Being a list of bytes, endian issues are not relevant.





##### Usage
# The package procedures are assembled into an ensemble command for external
# use.  Normal usages are:
#
#   * binconvert [readFile](binconvert.html#readfile) <i>format fileName</i>
# (returns *segmentList*)
#   * binconvert [writeFile](binconvert.html#writefile) <i>format segmentList
# fileName</i>
#  * binconvert [addparser](binconvert.html#addparser) <i>fmtId lineParserName
# outputWriterName</i>
#  * loglevel *newLogLevel*
#
# For Ihex and Srec files, *writeFile* detects the address space needed
# by the Segment List and will automatically select the appropriate subformat
# for the actual data.
# In case the user wants to force their output into a particular subformat
# (e.g., write a file in I16hex format that could have fit in I8hex format),
# the individual subformats are also exposed, e.g.:
................................................................................
# interfaces are described below.  Once those are defined, the user calls
# *addparser* as above, and the format called *fmtId* will be added to the
# list of available formats, and can be called in exactly the same way as
# the package-supplied formats.  The perceptive reader will see that this
# interface is actually used to provision the package-supplied formats.
#
# The loglevel command just exports the logger::setlevel command so the user
# can adjust the level of logging done by the package.  For details, see the

# normal [Tcl package documentation](https://core.tcl.tk/tcllib/doc/trunk/embedded/www/tcllib/files/modules/log/logger.html).

namespace eval ::binconvert {
    namespace export readfile
    namespace export writefile
    namespace export addparser
    namespace export loglevel
    namespace ensemble create
................................................................................

    logger::init ::binconvert
    logger::import -all -namespace ::binconvert::log ::binconvert
}

::binconvert::log::setlevel warn

# The list of valid subtypes is:
#
# * [ihex](ihex.html)
# * i8hex
# * i16hex
# * i32hex
source [file join $dir ihex.tcl]
# * [srec](srec.html)
# * s19
................................................................................
source [file join $dir srec.tcl]
# * [titxt](titxt.html)
source [file join $dir titxt.tcl]
# * [rawbin](rawbin.html)
source [file join $dir rawbin.tcl]



#--------------------------------------------------------------------------
# <a name="readfile"></a>
## readfile

# *readfile* accepts the name of an input file and a format by which to
# parse it as its argument.  It will attempt to open the file, read the
# contents, and parse them into a segment list.  A new segment is begun
# with each new segment offset/address command in the input, or when
# there is a discontinuity in the sequential data addressing even if the
# segment address was not changed by an address command.
................................................................................
    set address 0
    set segAddr 0
    set startAddress 0

    ##### Select a parsing format
    # Based on the data format argument, select the correct line parser.
    # The formats are added using [addparser](binconvert.html#addparser),
    # as can be seen [below](binconvert.html#importformats)






    if {![info exists ::binconvert::Formats($datafmt,parser)]} {
        log::error "binconvert::readfile: Unknown data format $datafmt."
        error "Unknown data format $datafmt"
    }
    set parser $::binconvert::Formats($datafmt,parser)

    ##### Read input file
    # The input file is opened and read into a list of lines.  Because these
    # formats are normally only used on relatively small files, we're
    # temporarily storing the whole thing in memory.  If you run out of
    # memory here, your file is on the order of a Gigabyte or more... and
    # these are really not appropriate formats for something that large.
    set cnt 1
    set chan [open $fname r]
    try {
        while {$cnt > 0} {
            set cnt [chan gets $chan line]
            lappend dataL $line


        }
    } finally {
        chan close $chan
    }

    ##### Parse input data
    # Note that actual input parsing here is done by the parser selected
................................................................................
        lappend resultL $startAddress $segData
    }
    return $resultL
}

#--------------------------------------------------------------------------
# <a name="writefile"></a>
## writefile

# *writefile* will examine the file format token, then call the appropriate
# output format writer for that file type.
proc ::binconvert::writefile {datafmt segmentList fileName} {
    if {![info exists ::binconvert::Formats($datafmt,writer)]} {
        log::error "binconvert::writefile: Unknown data format $datafmt."
        error "Unknown data format $datafmt"
................................................................................
    } finally {
        chan close $outchan
    }
}

#--------------------------------------------------------------------------
# <a name="addparser"></a>
## addparser

# *addparser* accepts three arguments:
#
# * a format symbol, used to identify when this format is desired,
# * the name of a line parsing procedure
# * the name of an output writer procedure
#
................................................................................
# in the ::binconvert:: namespace, or must provide a fully-qualified
# namespace path to their procedures.
proc ::binconvert::addparser {formatSymbol parseProcName writeProcName} {
    set ::binconvert::Formats($formatSymbol,parser) $parseProcName
    set ::binconvert::Formats($formatSymbol,writer) $writeProcName
}


##### loglevel
# simple accessor to change the level of the package's log for debugging.
proc ::binconvert::loglevel {newLevel} {
    ::binconvert::log::setlevel $newLevel
}



# <a name="importformats"></a>
# Here is where we actually set up all the package-supplied formats.
#
# * Intel Hex ("ihex"): [ValidateIhexLine](ihex.html#ValidateIhexLine)
# * Motorola SREC ("srec"): [ValidateSrecLine](srec.html#ValidateSrecLine)
# * TI txt ("titxt"): [ValidateTitxtLine](titxt.html#ValidateTitxtLine)
# * Raw Binary ("rawbin"): [ValidateRawBinInput](rawbin.html#ValidateRawBinInput)
::binconvert::addparser ihex ValidateIhexLine WriteIhexFile
::binconvert::addparser i8hex ValidateIhexLine WriteI8hexFile
::binconvert::addparser i16hex ValidateIhexLine WriteI16hexFile
::binconvert::addparser i32hex ValidateIhexLine WriteI32hexFile
::binconvert::addparser srec ValidateSrecLine {WriteSrecFile 00}
::binconvert::addparser S19 ValidateSrecLine {WriteSrecFile S19}
::binconvert::addparser S28 ValidateSrecLine {WriteSrecFile S28}
::binconvert::addparser S37 ValidateSrecLine {WriteSrecFile S37}


unset ::BINCONVERT_PKG_VERSION







<
<
<
<

|
|







 







>
>
>
>










|







 







|
>
|







 







|
|







 







<


|







 







|
>
>
>
>
>
>







|
|






|
|
|
>
>







 







|







 







|







 







>
|






>


<
<
<
<
<
|
|
|
|
|
|
|
|
>


28
29
30
31
32
33
34




35
36
37
38
39
40
41
42
43
44
..
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
..
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
...
124
125
126
127
128
129
130

131
132
133
134
135
136
137
138
139
140
...
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
...
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
...
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381





382
383
384
385
386
387
388
389
390
391
392
#
# Use "pycco *filename*" to re-generate HTML documentation in ./docs .
#

package require Tcl 8.6
package require logger





#--------------------------------------------------------------------------
## binconvert

# **binconvert** is a Tcl package that converts to & from a Tcl
# representation of a segment list.  binconvert handles multiple binary
# formats and their subtypes.  It currently handles:
#
#  * "ihex" - Intel Hex format. Includes all three subtypes: I8hex, I16hex, & I32hex.
#  * "srec" - Motorola SREC format.  Includes all three subtypes: S19, S28, & S37.
#  * "titxt" - TI .txt format, which has no subtypes.
................................................................................
##### Internal Data Representation
# Binconvert stores its memory version of the binary data in a segment list.
# A Segment List is a list of paired elements. The even elements are segment
# addresses and the odd elements are blocks of segment data, represented as
# a list of numbers 0-255 that are the values of each byte of the segment.
# Being a list of bytes, endian issues are not relevant.

package provide binconvert $::BINCONVERT_PKG_VERSION

set dir [file dirname [info script]]

##### Usage
# The package procedures are assembled into an ensemble command for external
# use.  Normal usages are:
#
#   * binconvert [readFile](binconvert.html#readfile) <i>format fileName</i>
# (returns *segmentList*)
#   * binconvert [writeFile](binconvert.html#writefile) <i>format segmentList
# fileName</i>
#  * binconvert [addparser](binconvert.html#addparser) <i>fmtId lineParserName
# outputWriterName</i>
#  * binconvert loglevel *newLogLevel*
#
# For Ihex and Srec files, *writeFile* detects the address space needed
# by the Segment List and will automatically select the appropriate subformat
# for the actual data.
# In case the user wants to force their output into a particular subformat
# (e.g., write a file in I16hex format that could have fit in I8hex format),
# the individual subformats are also exposed, e.g.:
................................................................................
# interfaces are described below.  Once those are defined, the user calls
# *addparser* as above, and the format called *fmtId* will be added to the
# list of available formats, and can be called in exactly the same way as
# the package-supplied formats.  The perceptive reader will see that this
# interface is actually used to provision the package-supplied formats.
#
# The loglevel command just exports the logger::setlevel command so the user
# can adjust the level of logging done by the package.  For details and the
# list of valid levels, see the normal
# [Tcl package documentation](https://core.tcl.tk/tcllib/doc/trunk/embedded/www/tcllib/files/modules/log/logger.html).

namespace eval ::binconvert {
    namespace export readfile
    namespace export writefile
    namespace export addparser
    namespace export loglevel
    namespace ensemble create
................................................................................

    logger::init ::binconvert
    logger::import -all -namespace ::binconvert::log ::binconvert
}

::binconvert::log::setlevel warn

# The list of valid subtypes supplied in the package is:

# * [ihex](ihex.html)
# * i8hex
# * i16hex
# * i32hex
source [file join $dir ihex.tcl]
# * [srec](srec.html)
# * s19
................................................................................
source [file join $dir srec.tcl]
# * [titxt](titxt.html)
source [file join $dir titxt.tcl]
# * [rawbin](rawbin.html)
source [file join $dir rawbin.tcl]



#--------------------------------------------------------------------------
# <a name="readfile"></a>
### readfile

# *readfile* accepts the name of an input file and a format by which to
# parse it as its argument.  It will attempt to open the file, read the
# contents, and parse them into a segment list.  A new segment is begun
# with each new segment offset/address command in the input, or when
# there is a discontinuity in the sequential data addressing even if the
# segment address was not changed by an address command.
................................................................................
    set address 0
    set segAddr 0
    set startAddress 0

    ##### Select a parsing format
    # Based on the data format argument, select the correct line parser.
    # The formats are added using [addparser](binconvert.html#addparser),
    # as can be seen [below](binconvert.html#importformats).  Package
    # supplied line parsers are:
    #
    # * Intel Hex ("ihex"): [ProcessIhexLine](ihex.html#ProcessIhexLine)
    # * Motorola SREC ("srec"): [ProcessSrecLine](srec.html#ProcessSrecLine)
    # * TI txt ("titxt"): [ProcessTitxtLine](titxt.html#ProcessTitxtLine)
    # * Raw Binary ("rawbin"): [ProcessRawbinInput](rawbin.html#ProcessRawbinInput)
    if {![info exists ::binconvert::Formats($datafmt,parser)]} {
        log::error "binconvert::readfile: Unknown data format $datafmt."
        error "Unknown data format $datafmt"
    }
    set parser $::binconvert::Formats($datafmt,parser)

    ##### Read input file
    # The input file is opened read, and split into a list of lines.  Because
    # these formats are normally only used on relatively small files, we're
    # temporarily storing the whole thing in memory.  If you run out of
    # memory here, your file is on the order of a Gigabyte or more... and
    # these are really not appropriate formats for something that large.
    set cnt 1
    set chan [open $fname r]
    try {
        set dataS [read $chan]
        # Unless the data is raw binary, split the input data into lines.
        # If the format *is* raw binary, there's no lines to split.
        if {$datafmt ne "rawbin"} {
            set dataL [split $dataS \n]
        }
    } finally {
        chan close $chan
    }

    ##### Parse input data
    # Note that actual input parsing here is done by the parser selected
................................................................................
        lappend resultL $startAddress $segData
    }
    return $resultL
}

#--------------------------------------------------------------------------
# <a name="writefile"></a>
### writefile

# *writefile* will examine the file format token, then call the appropriate
# output format writer for that file type.
proc ::binconvert::writefile {datafmt segmentList fileName} {
    if {![info exists ::binconvert::Formats($datafmt,writer)]} {
        log::error "binconvert::writefile: Unknown data format $datafmt."
        error "Unknown data format $datafmt"
................................................................................
    } finally {
        chan close $outchan
    }
}

#--------------------------------------------------------------------------
# <a name="addparser"></a>
### addparser

# *addparser* accepts three arguments:
#
# * a format symbol, used to identify when this format is desired,
# * the name of a line parsing procedure
# * the name of an output writer procedure
#
................................................................................
# in the ::binconvert:: namespace, or must provide a fully-qualified
# namespace path to their procedures.
proc ::binconvert::addparser {formatSymbol parseProcName writeProcName} {
    set ::binconvert::Formats($formatSymbol,parser) $parseProcName
    set ::binconvert::Formats($formatSymbol,writer) $writeProcName
}

#--------------------------------------------------------------------------
#### loglevel
# simple accessor to change the level of the package's log for debugging.
proc ::binconvert::loglevel {newLevel} {
    ::binconvert::log::setlevel $newLevel
}


#--------------------------------------------------------------------------
# <a name="importformats"></a>
# Here is where we actually set up all the package-supplied formats.





::binconvert::addparser ihex ProcessIhexLine WriteIhexFile
::binconvert::addparser i8hex ProcessIhexLine WriteI8hexFile
::binconvert::addparser i16hex ProcessIhexLine WriteI16hexFile
::binconvert::addparser i32hex ProcessIhexLine WriteI32hexFile
::binconvert::addparser srec ProcessSrecLine {WriteSrecFile 00}
::binconvert::addparser S19 ProcessSrecLine {WriteSrecFile S19}
::binconvert::addparser S28 ProcessSrecLine {WriteSrecFile S28}
::binconvert::addparser S37 ProcessSrecLine {WriteSrecFile S37}
::binconvert::addparser titxt ProcessTitxtLine WriteTitxtFile

unset ::BINCONVERT_PKG_VERSION

Changes to docs/binconvert.html.

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57











58
59
60
61
62
63
64
65
..
73
74
75
76
77
78
79
80


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
...
111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
126
...
130
131
132
133
134
135
136
137
138
139
140
141
142











143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275












276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
...
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
...
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
...
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
...
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
...
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
...
575
576
577
578
579
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594
595
596
597
598
599
600
601

602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618

619
620
621
622
623
624
625
626
627
628
<h6></h6>
<p>This package documentation is auto-generated with
Pycco: <a href="https://pycco-docs.github.io/pycco/">https://pycco-docs.github.io/pycco/</a></p>
<p>Use "pycco <em>filename</em>" to re-generate HTML documentation in ./docs .</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span></span><span class="nb">package</span> require Tcl <span class="mf">8.6</span>
<span class="nb">package</span> require logger

<span class="nb">package</span> provide binconvert <span class="nv">$::BINCONVERT_PKG_VERSION</span>

<span class="k">set</span> dir <span class="k">[</span><span class="nb">file</span> dirname <span class="k">[</span><span class="nb">info</span> script<span class="k">]]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-1'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-1'>#</a>
      </div>
      <hr />
<h2>binconvert</h2>











<p><strong>binconvert</strong> is a Tcl package that converts to &amp; from a Tcl
representation of a segment list.  binconvert handles multiple binary
formats and their subtypes.  It currently handles:</p>
<ul>
<li>"ihex" - Intel Hex format. Includes all three subtypes: I8hex, I16hex, &amp; I32hex.</li>
<li>"srec" - Motorola SREC format.  Includes all three subtypes: S19, S28, &amp; S37.</li>
<li>"titxt" - TI .txt format, which has no subtypes.</li>
<li>"rawbin" - flat binary data, starting at address 0 on read, and also on
................................................................................
<p>Binconvert stores its memory version of the binary data in a segment list.
A Segment List is a list of paired elements. The even elements are segment
addresses and the odd elements are blocks of segment data, represented as
a list of numbers 0-255 that are the values of each byte of the segment.
Being a list of bytes, endian issues are not relevant.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>


    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-2'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-2'>#</a>
      </div>
      <h4>Usage</h4>
<p>The package procedures are assembled into an ensemble command for external
use.  Normal usages are:</p>
<ul>
<li>binconvert <a href="binconvert.html#readfile">readFile</a> <i>format fileName</i>
(returns <em>segmentList</em>)</li>
<li>binconvert <a href="binconvert.html#writefile">writeFile</a> <i>format segmentList
fileName</i></li>
<li>binconvert <a href="binconvert.html#addparser">addparser</a> <i>fmtId lineParserName
outputWriterName</i></li>
<li>loglevel <em>newLogLevel</em></li>
</ul>
<p>For Ihex and Srec files, <em>writeFile</em> detects the address space needed
by the Segment List and will automatically select the appropriate subformat
for the actual data.
In case the user wants to force their output into a particular subformat
(e.g., write a file in I16hex format that could have fit in I8hex format),
the individual subformats are also exposed, e.g.:</p>
................................................................................
must supply two procs: a line parser, and a output format writer.  The
interfaces are described below.  Once those are defined, the user calls
<em>addparser</em> as above, and the format called <em>fmtId</em> will be added to the
list of available formats, and can be called in exactly the same way as
the package-supplied formats.  The perceptive reader will see that this
interface is actually used to provision the package-supplied formats.</p>
<p>The loglevel command just exports the logger::setlevel command so the user
can adjust the level of logging done by the package.  For details, see the

normal <a href="https://core.tcl.tk/tcllib/doc/trunk/embedded/www/tcllib/files/modules/log/logger.html">Tcl package documentation</a>.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">namespace</span> eval <span class="o">::</span>binconvert <span class="k">{</span>
    <span class="k">namespace</span> export readfile
    <span class="k">namespace</span> export writefile
    <span class="k">namespace</span> export addparser
    <span class="k">namespace</span> export loglevel
................................................................................
    <span class="nv">logger</span><span class="o">::</span>import <span class="o">-</span>all <span class="o">-</span>namespace <span class="o">::</span>binconvert::log <span class="o">::</span>binconvert
<span class="k">}</span>

<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>log::setlevel warn</pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-3'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-3'>#</a>
      </div>
      <p>The list of valid subtypes is:</p>











<ul>
<li><a href="ihex.html">ihex</a></li>
<li>i8hex</li>
<li>i16hex</li>
<li>i32hex</li>
</ul>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="nb">source</span> <span class="k">[</span><span class="nb">file</span> join <span class="nv">$dir</span> ihex.tcl<span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-4'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-4'>#</a>
      </div>
      <ul>
<li><a href="srec.html">srec</a></li>
<li>s19</li>
<li>s28</li>
<li>s37</li>
</ul>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="nb">source</span> <span class="k">[</span><span class="nb">file</span> join <span class="nv">$dir</span> srec.tcl<span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-5'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-5'>#</a>
      </div>
      <ul>
<li><a href="titxt.html">titxt</a></li>
</ul>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="nb">source</span> <span class="k">[</span><span class="nb">file</span> join <span class="nv">$dir</span> titxt.tcl<span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-6'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-6'>#</a>
      </div>
      <ul>
<li><a href="rawbin.html">rawbin</a></li>
</ul>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="nb">source</span> <span class="k">[</span><span class="nb">file</span> join <span class="nv">$dir</span> rawbin.tcl<span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-7'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-7'>#</a>
      </div>
      <hr />
<p><a name="readfile"></a></p>
<h1>readfile</h1>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-8'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-8'>#</a>
      </div>
      <p><em>readfile</em> accepts the name of an input file and a format by which to
parse it as its argument.  It will attempt to open the file, read the
contents, and parse them into a segment list.  A new segment is begun
with each new segment offset/address command in the input, or when
there is a discontinuity in the sequential data addressing even if the
segment address was not changed by an address command.</p>
................................................................................
    <span class="k">set</span> <span class="o">::</span>binconvert::SrecLineCount <span class="mi">0</span>
    <span class="k">set</span> address <span class="mi">0</span>
    <span class="k">set</span> segAddr <span class="mi">0</span>
    <span class="k">set</span> startAddress <span class="mi">0</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-9'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-9'>#</a>
      </div>
      <h4>Select a parsing format</h4>
<p>Based on the data format argument, select the correct line parser.
The formats are added using <a href="binconvert.html#addparser">addparser</a>,
as can be seen <a href="binconvert.html#importformats">below</a></p>







    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">if</span> <span class="k">{</span><span class="o">!</span><span class="k">[</span><span class="nb">info</span> exists <span class="o">::</span>binconvert::Formats<span class="k">(</span><span class="nv">$datafmt</span><span class="err">,</span><span class="nv">parser</span><span class="k">)]}</span> <span class="k">{</span>
        <span class="nv">log</span><span class="o">::</span>error <span class="s2">&quot;binconvert::readfile: Unknown data format $datafmt.&quot;</span>
        <span class="k">error</span> <span class="s2">&quot;Unknown data format $datafmt&quot;</span>
    <span class="k">}</span>
    <span class="k">set</span> parser <span class="nv">$::binconvert::Formats</span><span class="k">(</span><span class="nv">$datafmt</span><span class="err">,</span><span class="nv">parser</span><span class="k">)</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-10'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-10'>#</a>
      </div>
      <h4>Read input file</h4>
<p>The input file is opened and read into a list of lines.  Because these
formats are normally only used on relatively small files, we're
temporarily storing the whole thing in memory.  If you run out of
memory here, your file is on the order of a Gigabyte or more... and
these are really not appropriate formats for something that large.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">set</span> cnt <span class="mi">1</span>
    <span class="k">set</span> chan <span class="k">[</span><span class="nb">open</span> <span class="nv">$fname</span> r<span class="k">]</span>
    <span class="nv">try</span> <span class="k">{</span>
        <span class="k">while</span> <span class="k">{</span><span class="nv">$cnt</span> <span class="o">&gt;</span> <span class="nv">0</span><span class="k">}</span> <span class="k">{</span>
            <span class="k">set</span> cnt <span class="k">[</span><span class="nb">chan</span> gets <span class="nv">$chan</span> line<span class="k">]</span>
            <span class="nb">lappend</span> dataL <span class="nv">$line</span>












        <span class="k">}</span>
    <span class="k">}</span> finally <span class="k">{</span>
        <span class="nb">chan</span> close <span class="nv">$chan</span>
    <span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-11'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-11'>#</a>
      </div>
      <h4>Parse input data</h4>
<p>Note that actual input parsing here is done by the parser selected
above.  Each parser accepts one line of data and emits a list that
consists of a canonical tag and its associated data.
The <em>readFile</em> level manages the segment list structure based on
those tags.  Generally, format-specific consistency checks are
................................................................................
      <div class="highlight"><pre>    <span class="k">foreach</span> line <span class="nv">$dataL</span> <span class="k">{</span>
        <span class="k">set</span> lineL <span class="k">[{</span><span class="o">*</span><span class="k">}</span><span class="nv">$parser</span> <span class="nv">$line</span><span class="k">]</span>
        <span class="k">switch</span> <span class="o">--</span> <span class="k">[</span><span class="nb">lindex</span> <span class="nv">$lineL</span> <span class="mi">0</span><span class="k">]</span> <span class="k">{</span>
            <span class="nv">default</span> <span class="k">{</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-12'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-12'>#</a>
      </div>
      <p>Unknown line types are warned about, but we continue and
allow the user to decide what to do about the issue.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>                <span class="nv">log</span><span class="o">::</span>warn <span class="s2">&quot;binconvert::readfile: Unknown line type\</span>
<span class="s2">                            [lindex $lineL 0] in line: $line&quot;</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-13'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-13'>#</a>
      </div>
      <h4>Data line.</h4>
<p>Check the address.  If it's not continuous with the
current segment, wrap up the current segment and init a
new segment.
Either way, after any fix-up work, append the line data
to the current active segment.</p>
................................................................................
                    <span class="k">set</span> segData <span class="k">[</span><span class="nb">list</span><span class="k">]</span>
                <span class="k">}</span>
                <span class="nb">lappend</span> segData <span class="k">{</span><span class="o">*</span><span class="k">}[</span><span class="nb">lindex</span> <span class="nv">$lineL</span> <span class="mi">2</span><span class="k">]</span>
                <span class="nb">incr</span> address <span class="k">[</span><span class="nb">llength</span> <span class="k">[</span><span class="nb">lindex</span> <span class="nv">$lineL</span> <span class="mi">2</span><span class="k">]</span> <span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-14'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-14'>#</a>
      </div>
      <h4>EOF line.</h4>
<p>Force end of processing.  No more lines (if any) will be
processed.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">}</span>
            <span class="nv">EOF</span> <span class="k">{</span>
                <span class="nv">log</span><span class="o">::</span>debug <span class="s2">&quot;Found EOF&quot;</span>
                <span class="k">break</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-15'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-15'>#</a>
      </div>
      <h4>Header line.</h4>
<p>Srec header line.  Data is still a list of hex bytes, but
usually holds a null terminated string.  The data is saved in
the segment list, but will be output only if the data is written
in Srec format.</p>
<p>N.B. that the "address" for this segment is the text
................................................................................
                <span class="k">}</span>
                <span class="k">set</span> address <span class="s2">&quot;HEADER&quot;</span>
                <span class="k">set</span> startAddress <span class="nv">$address</span>
                <span class="nb">lappend</span> segData <span class="k">{</span><span class="o">*</span><span class="k">}[</span><span class="nb">lindex</span> <span class="nv">$lineL</span> <span class="mi">1</span><span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-16'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-16'>#</a>
      </div>
      <p><a name="addrs"></a></p>
<h4>Segment Address line.</h4>
<p>New segment offset address, where segAddr is an offset that will
be added to all line addresses until the next segment addr line.</p>
<p>Wrap up any ongoing segment and init a new segment.</p>
    </div>
................................................................................
                <span class="k">}</span>
                <span class="k">set</span> address <span class="nv">$segAddr</span>
                <span class="k">set</span> startAddress <span class="nv">$address</span>
                <span class="k">set</span> segData <span class="k">[</span><span class="nb">list</span><span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-17'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-17'>#</a>
      </div>
      <h4>Start Address line.</h4>
<p>Contains processor address at which to start execution from,
if this was a processor.</p>
<p>Note: All start address types map to this.  Because it's
relevant to their output format, I16hex and I32hex include an
extra field in their output with the format type.  This is
................................................................................
                <span class="k">}</span>
                <span class="k">set</span> address <span class="s2">&quot;STARTADDR&quot;</span>
                <span class="k">set</span> startAddress <span class="nv">$address</span>
                <span class="k">set</span> segData <span class="k">[</span><span class="nb">lrange</span> <span class="nv">$lineL</span> <span class="mi">1</span> end<span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-18'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-18'>#</a>
      </div>
      <h4>No-op / No segment data</h4>
<p>Certain lines exist for format internal reasons (e.g., SREC
count records) and have no data that goes into the Segment List.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">}</span>
................................................................................
            <span class="nv">NOP</span> <span class="k">{</span>
            <span class="k">}</span>
        <span class="k">}</span>
    <span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-19'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-19'>#</a>
      </div>
      <p>Put final segment on result list and return it.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">if</span> <span class="k">{[</span><span class="nb">llength</span> <span class="nv">$segData</span><span class="k">]</span> <span class="o">!=</span> <span class="nv">0</span><span class="k">}</span> <span class="k">{</span>
        <span class="nb">lappend</span> resultL <span class="nv">$startAddress</span> <span class="nv">$segData</span>
    <span class="k">}</span>
    <span class="k">return</span> <span class="nv">$resultL</span>
<span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-20'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-20'>#</a>
      </div>
      <hr />
<p><a name="writefile"></a></p>
<h1>writefile</h1>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-21'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-21'>#</a>
      </div>
      <p><em>writefile</em> will examine the file format token, then call the appropriate
output format writer for that file type.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::writefile <span class="k">{</span><span class="nv">datafmt</span> segmentList fileName<span class="k">}</span> <span class="k">{</span>
    <span class="k">if</span> <span class="k">{</span><span class="o">!</span><span class="k">[</span><span class="nb">info</span> exists <span class="o">::</span>binconvert::Formats<span class="k">(</span><span class="nv">$datafmt</span><span class="err">,</span><span class="nv">writer</span><span class="k">)]}</span> <span class="k">{</span>
................................................................................
    <span class="k">}</span> finally <span class="k">{</span>
        <span class="nb">chan</span> close <span class="nv">$outchan</span>
    <span class="k">}</span>
<span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-22'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-22'>#</a>
      </div>
      <hr />
<p><a name="addparser"></a></p>
<h1>addparser</h1>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-23'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-23'>#</a>
      </div>
      <p><em>addparser</em> accepts three arguments:</p>
<ul>
<li>a format symbol, used to identify when this format is desired,</li>
<li>the name of a line parsing procedure</li>
<li>the name of an output writer procedure</li>
</ul>
................................................................................
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::addparser <span class="k">{</span><span class="nv">formatSymbol</span> parseProcName writeProcName<span class="k">}</span> <span class="k">{</span>
    <span class="k">set</span> <span class="o">::</span>binconvert::Formats<span class="k">(</span><span class="nv">$formatSymbol</span><span class="err">,</span><span class="nv">parser</span><span class="k">)</span> <span class="nv">$parseProcName</span>
    <span class="k">set</span> <span class="o">::</span>binconvert::Formats<span class="k">(</span><span class="nv">$formatSymbol</span><span class="err">,</span><span class="nv">writer</span><span class="k">)</span> <span class="nv">$writeProcName</span>
<span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-24'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-24'>#</a>
      </div>

      <h4>loglevel</h4>
<p>simple accessor to change the level of the package's log for debugging.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::loglevel <span class="k">{</span><span class="nv">newLevel</span><span class="k">}</span> <span class="k">{</span>
    <span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>log::setlevel <span class="nv">$newLevel</span>
<span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-25'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-25'>#</a>
      </div>

      <p><a name="importformats"></a>
Here is where we actually set up all the package-supplied formats.</p>
<ul>
<li>Intel Hex ("ihex"): <a href="ihex.html#ValidateIhexLine">ValidateIhexLine</a></li>
<li>Motorola SREC ("srec"): <a href="srec.html#ValidateSrecLine">ValidateSrecLine</a></li>
<li>TI txt ("titxt"): <a href="titxt.html#ValidateTitxtLine">ValidateTitxtLine</a></li>
<li>Raw Binary ("rawbin"): <a href="rawbin.html#ValidateRawBinInput">ValidateRawBinInput</a></li>
</ul>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser ihex ValidateIhexLine WriteIhexFile
<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser i8hex ValidateIhexLine WriteI8hexFile
<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser i16hex ValidateIhexLine WriteI16hexFile
<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser i32hex ValidateIhexLine WriteI32hexFile
<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser srec ValidateSrecLine <span class="k">{</span><span class="nv">WriteSrecFile</span> <span class="mo">00</span><span class="k">}</span>
<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser S19 ValidateSrecLine <span class="k">{</span><span class="nv">WriteSrecFile</span> S19<span class="k">}</span>
<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser S28 ValidateSrecLine <span class="k">{</span><span class="nv">WriteSrecFile</span> S28<span class="k">}</span>

<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser S37 ValidateSrecLine <span class="k">{</span><span class="nv">WriteSrecFile</span> S37<span class="k">}</span>

<span class="k">unset</span> <span class="o">::</span>BINCONVERT_PKG_VERSION

</pre></div>
    </div>
  </div>
  <div class='clearall'></div>
</div>
</body>







|
<
<
<
<









|
>
>
>
>
>
>
>
>
>
>
>
|







 







|
>
>



|


|











|







 







|
>
|







 







|


|

|
>
>
>
>
>
>
>
>
>
>
>
|











|


|













|


|










|


|










|


|



|






|


|







 







|


|




|
>
>
>
>
>
>
>










|


|


|
|








|
|
|
>
>
>
>
>
>
>
>
>
>
>
>







|


|







 







|


|










|


|







 







|


|













|


|







 







|


|







 







|


|







 







|


|







 







|


|












|


|



|






|


|







 







|


|



|






|


|







 







|


|

>
|









|


|

>
|

<
<
<
<
<
<


|
|
|
|
|
|
|
>
|









36
37
38
39
40
41
42
43




44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
..
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
...
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
...
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
...
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
...
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
...
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
...
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645






646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
<h6></h6>
<p>This package documentation is auto-generated with
Pycco: <a href="https://pycco-docs.github.io/pycco/">https://pycco-docs.github.io/pycco/</a></p>
<p>Use "pycco <em>filename</em>" to re-generate HTML documentation in ./docs .</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span></span><span class="nb">package</span> require Tcl <span class="mf">8.6</span>
<span class="nb">package</span> require logger</pre></div>




    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-1'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-1'>#</a>
      </div>
      <hr />
<h1>binconvert</h1>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-2'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-2'>#</a>
      </div>
      <p><strong>binconvert</strong> is a Tcl package that converts to &amp; from a Tcl
representation of a segment list.  binconvert handles multiple binary
formats and their subtypes.  It currently handles:</p>
<ul>
<li>"ihex" - Intel Hex format. Includes all three subtypes: I8hex, I16hex, &amp; I32hex.</li>
<li>"srec" - Motorola SREC format.  Includes all three subtypes: S19, S28, &amp; S37.</li>
<li>"titxt" - TI .txt format, which has no subtypes.</li>
<li>"rawbin" - flat binary data, starting at address 0 on read, and also on
................................................................................
<p>Binconvert stores its memory version of the binary data in a segment list.
A Segment List is a list of paired elements. The even elements are segment
addresses and the odd elements are blocks of segment data, represented as
a list of numbers 0-255 that are the values of each byte of the segment.
Being a list of bytes, endian issues are not relevant.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="nb">package</span> provide binconvert <span class="nv">$::BINCONVERT_PKG_VERSION</span>

<span class="k">set</span> dir <span class="k">[</span><span class="nb">file</span> dirname <span class="k">[</span><span class="nb">info</span> script<span class="k">]]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-3'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-3'>#</a>
      </div>
      <h4>Usage</h4>
<p>The package procedures are assembled into an ensemble command for external
use.  Normal usages are:</p>
<ul>
<li>binconvert <a href="binconvert.html#readfile">readFile</a> <i>format fileName</i>
(returns <em>segmentList</em>)</li>
<li>binconvert <a href="binconvert.html#writefile">writeFile</a> <i>format segmentList
fileName</i></li>
<li>binconvert <a href="binconvert.html#addparser">addparser</a> <i>fmtId lineParserName
outputWriterName</i></li>
<li>binconvert loglevel <em>newLogLevel</em></li>
</ul>
<p>For Ihex and Srec files, <em>writeFile</em> detects the address space needed
by the Segment List and will automatically select the appropriate subformat
for the actual data.
In case the user wants to force their output into a particular subformat
(e.g., write a file in I16hex format that could have fit in I8hex format),
the individual subformats are also exposed, e.g.:</p>
................................................................................
must supply two procs: a line parser, and a output format writer.  The
interfaces are described below.  Once those are defined, the user calls
<em>addparser</em> as above, and the format called <em>fmtId</em> will be added to the
list of available formats, and can be called in exactly the same way as
the package-supplied formats.  The perceptive reader will see that this
interface is actually used to provision the package-supplied formats.</p>
<p>The loglevel command just exports the logger::setlevel command so the user
can adjust the level of logging done by the package.  For details and the
list of valid levels, see the normal
<a href="https://core.tcl.tk/tcllib/doc/trunk/embedded/www/tcllib/files/modules/log/logger.html">Tcl package documentation</a>.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">namespace</span> eval <span class="o">::</span>binconvert <span class="k">{</span>
    <span class="k">namespace</span> export readfile
    <span class="k">namespace</span> export writefile
    <span class="k">namespace</span> export addparser
    <span class="k">namespace</span> export loglevel
................................................................................
    <span class="nv">logger</span><span class="o">::</span>import <span class="o">-</span>all <span class="o">-</span>namespace <span class="o">::</span>binconvert::log <span class="o">::</span>binconvert
<span class="k">}</span>

<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>log::setlevel warn</pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-4'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-4'>#</a>
      </div>
      <p>The list of valid subtypes supplied in the package is:</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-5'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-5'>#</a>
      </div>
      <ul>
<li><a href="ihex.html">ihex</a></li>
<li>i8hex</li>
<li>i16hex</li>
<li>i32hex</li>
</ul>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="nb">source</span> <span class="k">[</span><span class="nb">file</span> join <span class="nv">$dir</span> ihex.tcl<span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-6'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-6'>#</a>
      </div>
      <ul>
<li><a href="srec.html">srec</a></li>
<li>s19</li>
<li>s28</li>
<li>s37</li>
</ul>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="nb">source</span> <span class="k">[</span><span class="nb">file</span> join <span class="nv">$dir</span> srec.tcl<span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-7'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-7'>#</a>
      </div>
      <ul>
<li><a href="titxt.html">titxt</a></li>
</ul>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="nb">source</span> <span class="k">[</span><span class="nb">file</span> join <span class="nv">$dir</span> titxt.tcl<span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-8'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-8'>#</a>
      </div>
      <ul>
<li><a href="rawbin.html">rawbin</a></li>
</ul>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="nb">source</span> <span class="k">[</span><span class="nb">file</span> join <span class="nv">$dir</span> rawbin.tcl<span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-9'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-9'>#</a>
      </div>
      <hr />
<p><a name="readfile"></a></p>
<h2>readfile</h2>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-10'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-10'>#</a>
      </div>
      <p><em>readfile</em> accepts the name of an input file and a format by which to
parse it as its argument.  It will attempt to open the file, read the
contents, and parse them into a segment list.  A new segment is begun
with each new segment offset/address command in the input, or when
there is a discontinuity in the sequential data addressing even if the
segment address was not changed by an address command.</p>
................................................................................
    <span class="k">set</span> <span class="o">::</span>binconvert::SrecLineCount <span class="mi">0</span>
    <span class="k">set</span> address <span class="mi">0</span>
    <span class="k">set</span> segAddr <span class="mi">0</span>
    <span class="k">set</span> startAddress <span class="mi">0</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-11'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-11'>#</a>
      </div>
      <h4>Select a parsing format</h4>
<p>Based on the data format argument, select the correct line parser.
The formats are added using <a href="binconvert.html#addparser">addparser</a>,
as can be seen <a href="binconvert.html#importformats">below</a>.  Package
supplied line parsers are:</p>
<ul>
<li>Intel Hex ("ihex"): <a href="ihex.html#ProcessIhexLine">ProcessIhexLine</a></li>
<li>Motorola SREC ("srec"): <a href="srec.html#ProcessSrecLine">ProcessSrecLine</a></li>
<li>TI txt ("titxt"): <a href="titxt.html#ProcessTitxtLine">ProcessTitxtLine</a></li>
<li>Raw Binary ("rawbin"): <a href="rawbin.html#ProcessRawbinInput">ProcessRawbinInput</a></li>
</ul>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">if</span> <span class="k">{</span><span class="o">!</span><span class="k">[</span><span class="nb">info</span> exists <span class="o">::</span>binconvert::Formats<span class="k">(</span><span class="nv">$datafmt</span><span class="err">,</span><span class="nv">parser</span><span class="k">)]}</span> <span class="k">{</span>
        <span class="nv">log</span><span class="o">::</span>error <span class="s2">&quot;binconvert::readfile: Unknown data format $datafmt.&quot;</span>
        <span class="k">error</span> <span class="s2">&quot;Unknown data format $datafmt&quot;</span>
    <span class="k">}</span>
    <span class="k">set</span> parser <span class="nv">$::binconvert::Formats</span><span class="k">(</span><span class="nv">$datafmt</span><span class="err">,</span><span class="nv">parser</span><span class="k">)</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-12'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-12'>#</a>
      </div>
      <h4>Read input file</h4>
<p>The input file is opened read, and split into a list of lines.  Because
these formats are normally only used on relatively small files, we're
temporarily storing the whole thing in memory.  If you run out of
memory here, your file is on the order of a Gigabyte or more... and
these are really not appropriate formats for something that large.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">set</span> cnt <span class="mi">1</span>
    <span class="k">set</span> chan <span class="k">[</span><span class="nb">open</span> <span class="nv">$fname</span> r<span class="k">]</span>
    <span class="nv">try</span> <span class="k">{</span>
        <span class="k">set</span> dataS <span class="k">[</span><span class="nb">read</span> <span class="nv">$chan</span><span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-13'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-13'>#</a>
      </div>
      <p>Unless the data is raw binary, split the input data into lines.
If the format <em>is</em> raw binary, there's no lines to split.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>        <span class="k">if</span> <span class="k">{</span><span class="nv">$datafmt</span> <span class="nv">ne</span> <span class="s2">&quot;rawbin&quot;</span><span class="k">}</span> <span class="k">{</span>
            <span class="k">set</span> dataL <span class="k">[</span><span class="nb">split</span> <span class="nv">$dataS</span> <span class="err">\</span>n<span class="k">]</span>
        <span class="k">}</span>
    <span class="k">}</span> finally <span class="k">{</span>
        <span class="nb">chan</span> close <span class="nv">$chan</span>
    <span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-14'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-14'>#</a>
      </div>
      <h4>Parse input data</h4>
<p>Note that actual input parsing here is done by the parser selected
above.  Each parser accepts one line of data and emits a list that
consists of a canonical tag and its associated data.
The <em>readFile</em> level manages the segment list structure based on
those tags.  Generally, format-specific consistency checks are
................................................................................
      <div class="highlight"><pre>    <span class="k">foreach</span> line <span class="nv">$dataL</span> <span class="k">{</span>
        <span class="k">set</span> lineL <span class="k">[{</span><span class="o">*</span><span class="k">}</span><span class="nv">$parser</span> <span class="nv">$line</span><span class="k">]</span>
        <span class="k">switch</span> <span class="o">--</span> <span class="k">[</span><span class="nb">lindex</span> <span class="nv">$lineL</span> <span class="mi">0</span><span class="k">]</span> <span class="k">{</span>
            <span class="nv">default</span> <span class="k">{</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-15'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-15'>#</a>
      </div>
      <p>Unknown line types are warned about, but we continue and
allow the user to decide what to do about the issue.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>                <span class="nv">log</span><span class="o">::</span>warn <span class="s2">&quot;binconvert::readfile: Unknown line type\</span>
<span class="s2">                            [lindex $lineL 0] in line: $line&quot;</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-16'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-16'>#</a>
      </div>
      <h4>Data line.</h4>
<p>Check the address.  If it's not continuous with the
current segment, wrap up the current segment and init a
new segment.
Either way, after any fix-up work, append the line data
to the current active segment.</p>
................................................................................
                    <span class="k">set</span> segData <span class="k">[</span><span class="nb">list</span><span class="k">]</span>
                <span class="k">}</span>
                <span class="nb">lappend</span> segData <span class="k">{</span><span class="o">*</span><span class="k">}[</span><span class="nb">lindex</span> <span class="nv">$lineL</span> <span class="mi">2</span><span class="k">]</span>
                <span class="nb">incr</span> address <span class="k">[</span><span class="nb">llength</span> <span class="k">[</span><span class="nb">lindex</span> <span class="nv">$lineL</span> <span class="mi">2</span><span class="k">]</span> <span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-17'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-17'>#</a>
      </div>
      <h4>EOF line.</h4>
<p>Force end of processing.  No more lines (if any) will be
processed.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">}</span>
            <span class="nv">EOF</span> <span class="k">{</span>
                <span class="nv">log</span><span class="o">::</span>debug <span class="s2">&quot;Found EOF&quot;</span>
                <span class="k">break</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-18'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-18'>#</a>
      </div>
      <h4>Header line.</h4>
<p>Srec header line.  Data is still a list of hex bytes, but
usually holds a null terminated string.  The data is saved in
the segment list, but will be output only if the data is written
in Srec format.</p>
<p>N.B. that the "address" for this segment is the text
................................................................................
                <span class="k">}</span>
                <span class="k">set</span> address <span class="s2">&quot;HEADER&quot;</span>
                <span class="k">set</span> startAddress <span class="nv">$address</span>
                <span class="nb">lappend</span> segData <span class="k">{</span><span class="o">*</span><span class="k">}[</span><span class="nb">lindex</span> <span class="nv">$lineL</span> <span class="mi">1</span><span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-19'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-19'>#</a>
      </div>
      <p><a name="addrs"></a></p>
<h4>Segment Address line.</h4>
<p>New segment offset address, where segAddr is an offset that will
be added to all line addresses until the next segment addr line.</p>
<p>Wrap up any ongoing segment and init a new segment.</p>
    </div>
................................................................................
                <span class="k">}</span>
                <span class="k">set</span> address <span class="nv">$segAddr</span>
                <span class="k">set</span> startAddress <span class="nv">$address</span>
                <span class="k">set</span> segData <span class="k">[</span><span class="nb">list</span><span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-20'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-20'>#</a>
      </div>
      <h4>Start Address line.</h4>
<p>Contains processor address at which to start execution from,
if this was a processor.</p>
<p>Note: All start address types map to this.  Because it's
relevant to their output format, I16hex and I32hex include an
extra field in their output with the format type.  This is
................................................................................
                <span class="k">}</span>
                <span class="k">set</span> address <span class="s2">&quot;STARTADDR&quot;</span>
                <span class="k">set</span> startAddress <span class="nv">$address</span>
                <span class="k">set</span> segData <span class="k">[</span><span class="nb">lrange</span> <span class="nv">$lineL</span> <span class="mi">1</span> end<span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-21'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-21'>#</a>
      </div>
      <h4>No-op / No segment data</h4>
<p>Certain lines exist for format internal reasons (e.g., SREC
count records) and have no data that goes into the Segment List.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">}</span>
................................................................................
            <span class="nv">NOP</span> <span class="k">{</span>
            <span class="k">}</span>
        <span class="k">}</span>
    <span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-22'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-22'>#</a>
      </div>
      <p>Put final segment on result list and return it.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">if</span> <span class="k">{[</span><span class="nb">llength</span> <span class="nv">$segData</span><span class="k">]</span> <span class="o">!=</span> <span class="nv">0</span><span class="k">}</span> <span class="k">{</span>
        <span class="nb">lappend</span> resultL <span class="nv">$startAddress</span> <span class="nv">$segData</span>
    <span class="k">}</span>
    <span class="k">return</span> <span class="nv">$resultL</span>
<span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-23'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-23'>#</a>
      </div>
      <hr />
<p><a name="writefile"></a></p>
<h2>writefile</h2>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-24'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-24'>#</a>
      </div>
      <p><em>writefile</em> will examine the file format token, then call the appropriate
output format writer for that file type.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::writefile <span class="k">{</span><span class="nv">datafmt</span> segmentList fileName<span class="k">}</span> <span class="k">{</span>
    <span class="k">if</span> <span class="k">{</span><span class="o">!</span><span class="k">[</span><span class="nb">info</span> exists <span class="o">::</span>binconvert::Formats<span class="k">(</span><span class="nv">$datafmt</span><span class="err">,</span><span class="nv">writer</span><span class="k">)]}</span> <span class="k">{</span>
................................................................................
    <span class="k">}</span> finally <span class="k">{</span>
        <span class="nb">chan</span> close <span class="nv">$outchan</span>
    <span class="k">}</span>
<span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-25'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-25'>#</a>
      </div>
      <hr />
<p><a name="addparser"></a></p>
<h2>addparser</h2>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-26'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-26'>#</a>
      </div>
      <p><em>addparser</em> accepts three arguments:</p>
<ul>
<li>a format symbol, used to identify when this format is desired,</li>
<li>the name of a line parsing procedure</li>
<li>the name of an output writer procedure</li>
</ul>
................................................................................
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::addparser <span class="k">{</span><span class="nv">formatSymbol</span> parseProcName writeProcName<span class="k">}</span> <span class="k">{</span>
    <span class="k">set</span> <span class="o">::</span>binconvert::Formats<span class="k">(</span><span class="nv">$formatSymbol</span><span class="err">,</span><span class="nv">parser</span><span class="k">)</span> <span class="nv">$parseProcName</span>
    <span class="k">set</span> <span class="o">::</span>binconvert::Formats<span class="k">(</span><span class="nv">$formatSymbol</span><span class="err">,</span><span class="nv">writer</span><span class="k">)</span> <span class="nv">$writeProcName</span>
<span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-27'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-27'>#</a>
      </div>
      <hr />
<h3>loglevel</h3>
<p>simple accessor to change the level of the package's log for debugging.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::loglevel <span class="k">{</span><span class="nv">newLevel</span><span class="k">}</span> <span class="k">{</span>
    <span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>log::setlevel <span class="nv">$newLevel</span>
<span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-28'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-28'>#</a>
      </div>
      <hr />
<p><a name="importformats"></a>
Here is where we actually set up all the package-supplied formats.</p>






    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser ihex ProcessIhexLine WriteIhexFile
<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser i8hex ProcessIhexLine WriteI8hexFile
<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser i16hex ProcessIhexLine WriteI16hexFile
<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser i32hex ProcessIhexLine WriteI32hexFile
<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser srec ProcessSrecLine <span class="k">{</span><span class="nv">WriteSrecFile</span> <span class="mo">00</span><span class="k">}</span>
<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser S19 ProcessSrecLine <span class="k">{</span><span class="nv">WriteSrecFile</span> S19<span class="k">}</span>
<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser S28 ProcessSrecLine <span class="k">{</span><span class="nv">WriteSrecFile</span> S28<span class="k">}</span>
<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser S37 ProcessSrecLine <span class="k">{</span><span class="nv">WriteSrecFile</span> S37<span class="k">}</span>
<span class="o">::</span><span class="nv">binconvert</span><span class="o">::</span>addparser titxt ProcessTitxtLine WriteTitxtFile

<span class="k">unset</span> <span class="o">::</span>BINCONVERT_PKG_VERSION

</pre></div>
    </div>
  </div>
  <div class='clearall'></div>
</div>
</body>

Changes to docs/ihex.html.

62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-2'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-2'>#</a>
      </div>

      <p><a name="ValidateIhexLine"></a></p>
<h3>ValidateIhexLine</h3>
<p><em>ValidateIhexLine</em> is the parser for the readline proc.  It takes a line
of formatted input, parses out the fields with a regexp, and computes the
line checksum.  If the checksum is invalid, it errors. If the checksum is
valid, it returns a list of up to three fields:  the symbolic type of the
line per the spec, the local address, and/or the list of data bytes, either
of which may not exist depending on the type.</p>
<p>The list is in the order  {type, address, dataList}.</p>
<p>If the parsing or checksum fail, error out - there's no real recovery from a
truly corrupted file.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::ValidateIhexLine <span class="k">{</span><span class="nv">line</span><span class="k">}</span> <span class="k">{</span>
    <span class="k">set</span> matchStr <span class="k">{</span><span class="o">:</span><span class="k">([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]{</span><span class="nv">2</span><span class="k">})([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]{</span><span class="nv">4</span><span class="k">})([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]{</span><span class="nv">2</span><span class="k">})([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]</span><span class="o">*</span><span class="k">)([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]{</span><span class="nv">2</span><span class="k">})}</span>
    <span class="k">if</span> <span class="k">{</span><span class="o">!</span><span class="k">[</span><span class="nb">regexp</span> <span class="nv">$matchStr</span> <span class="nv">$line</span> <span class="o">-&gt;</span> count addr type data chksum<span class="k">]}</span> <span class="k">{</span>
        <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ValidateIhexLine: Input file syntax error: could not parse $line&quot;</span>
        <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
        <span class="k">error</span> <span class="nv">$errMsg</span>
    <span class="k">}</span>
    <span class="err">;</span><span class="c"># N.B.: count is in bytes while string length is in digits.</span>
    <span class="k">if</span> <span class="k">{(</span><span class="s2">&quot;0x$count&quot;</span> <span class="o">*</span> <span class="nv">2</span><span class="k">)</span> <span class="o">!=</span> <span class="k">[</span><span class="nb">string</span> length <span class="nv">$data</span><span class="k">]}</span> <span class="k">{</span>
        <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ValidateIhexLine: Incorrect data field size! \</span>
<span class="s2">                    Expected [expr {$count * 2}], got\</span>
<span class="s2">                    [string length $data].\nLine was: $line&quot;</span>
        <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
        <span class="k">error</span> <span class="nv">$errMsg</span>
    <span class="k">}</span>
    <span class="k">set</span> csum <span class="mi">0</span>
    <span class="k">foreach</span> <span class="k">{</span><span class="nv">digit1</span> digit2<span class="k">}</span> <span class="k">[</span><span class="nb">lrange</span> <span class="k">[</span><span class="nb">split</span> <span class="nv">$line</span> <span class="s2">&quot;&quot;</span><span class="k">]</span> <span class="mi">1</span> end<span class="k">]</span> <span class="k">{</span>
        <span class="nb">incr</span> csum <span class="k">[expr</span> <span class="k">{</span><span class="s2">&quot;0x$digit1$digit2&quot;</span><span class="k">}]</span>
    <span class="k">}</span>
    <span class="k">if</span> <span class="k">{(</span><span class="nv">$csum</span> <span class="o">&amp;</span> <span class="nv">0xFF</span><span class="k">)</span> <span class="o">!=</span> <span class="nv">0</span><span class="k">}</span> <span class="k">{</span>
        <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ValidateIhexLine: line checksum fail: computed $csum,\</span>
<span class="s2">                    expected 0, line was: $line&quot;</span>
        <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
        <span class="k">error</span> <span class="nv">$errMsg</span>
    <span class="k">}</span>
    <span class="k">switch</span> <span class="nv">$type</span> <span class="k">{</span>
        <span class="nv">00</span> <span class="k">{</span>
            <span class="k">set</span> dataL <span class="k">{}</span>
................................................................................
            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;DATA&quot;</span> <span class="k">[expr</span> <span class="s2">&quot;0x$addr&quot;</span><span class="k">]</span> <span class="nv">$dataL</span><span class="k">]</span>
        <span class="k">}</span>
        <span class="nv">01</span> <span class="k">{</span>
            <span class="k">return</span> <span class="k">{</span><span class="s2">&quot;EOF&quot;</span> <span class="k">{}</span> <span class="k">}</span>
        <span class="k">}</span>
        <span class="nv">02</span> <span class="k">{</span>
            <span class="k">if</span> <span class="k">{</span><span class="nv">$::binconvert::IhexFileType</span> <span class="nv">eq</span> <span class="s2">&quot;I32&quot;</span><span class="k">}</span> <span class="k">{</span>
                <span class="nv">log</span><span class="o">::</span>error <span class="s2">&quot;binconvert: ValidateIhexLine: File mixes I16 &amp; I32 segment offsets!&quot;</span>
            <span class="k">}</span>
            <span class="k">set</span> <span class="o">::</span>binconvert::IhexFileType <span class="s2">&quot;I16&quot;</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-3'>
    <div class='docs'>
................................................................................
      <p>Upshifting address by 4 bits as we output it</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;SEGADDR&quot;</span> <span class="k">[expr</span> <span class="s2">&quot;0x${data}0&quot;</span><span class="k">]</span> <span class="k">]</span>
        <span class="k">}</span>
        <span class="nv">03</span> <span class="k">{</span>
            <span class="k">if</span> <span class="k">{</span><span class="nv">$::binconvert::IhexFileType</span> <span class="nv">eq</span> <span class="s2">&quot;I32&quot;</span><span class="k">}</span> <span class="k">{</span>
                <span class="nv">log</span><span class="o">::</span>error <span class="s2">&quot;binconvert: ValidateIhexLine: File mixes I16 &amp; I32 segment offsets!&quot;</span>
            <span class="k">}</span>
            <span class="k">set</span> <span class="o">::</span>binconvert::IhexFileType <span class="s2">&quot;I16&quot;</span>
            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;STARTADDR&quot;</span> <span class="k">[expr</span> <span class="s2">&quot;0x$data&quot;</span><span class="k">]</span> <span class="s2">&quot;I16&quot;</span> <span class="k">]</span>
        <span class="k">}</span>
        <span class="nv">04</span> <span class="k">{</span>
            <span class="k">if</span> <span class="k">{</span><span class="nv">$::binconvert::IhexFileType</span> <span class="nv">eq</span> <span class="s2">&quot;I16&quot;</span><span class="k">}</span> <span class="k">{</span>
                <span class="nv">log</span><span class="o">::</span>error <span class="s2">&quot;binconvert: ValidateIhexLine: File mixes I16 &amp; I32 segment offsets!&quot;</span>
            <span class="k">}</span>
            <span class="k">set</span> <span class="o">::</span>binconvert::IhexFileType <span class="s2">&quot;I32&quot;</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-4'>
    <div class='docs'>
................................................................................
      <p>Upshifting address by 16 bits as we output it</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;SEGADDR&quot;</span> <span class="k">[expr</span> <span class="s2">&quot;0x${data}0000&quot;</span><span class="k">]</span> <span class="k">]</span>
        <span class="k">}</span>
        <span class="nv">05</span> <span class="k">{</span>
            <span class="k">if</span> <span class="k">{</span><span class="nv">$::binconvert::IhexFileType</span> <span class="nv">eq</span> <span class="s2">&quot;I16&quot;</span><span class="k">}</span> <span class="k">{</span>
                <span class="nv">log</span><span class="o">::</span>error <span class="s2">&quot;binconvert: ValidateIhexLine: File mixes I16 &amp; I32 segment offsets!&quot;</span>
            <span class="k">}</span>
            <span class="k">set</span> <span class="o">::</span>binconvert::IhexFileType <span class="s2">&quot;I32&quot;</span>
            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;STARTADDR&quot;</span> <span class="k">[expr</span> <span class="s2">&quot;0x$data&quot;</span><span class="k">]</span> <span class="s2">&quot;I32&quot;</span> <span class="k">]</span>
        <span class="k">}</span>
        <span class="nv">default</span> <span class="k">{</span>
            <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ValidateIhexLine: Unrecognized line type! \</span>
<span class="s2">                    $type not in 0-5 per spec. \nLine was: $line&quot;</span>
            <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
            <span class="k">error</span> <span class="nv">$errMsg</span>
        <span class="k">}</span>
    <span class="k">}</span>
<span class="k">}</span></pre></div>
    </div>







>
|
|
|










|


|





|










|







 







|







 







|






|







 







|





|







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-2'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-2'>#</a>
      </div>
      <hr />
<p><a name="ProcessIhexLine"></a></p>
<h3>ProcessIhexLine</h3>
<p><em>ProcessIhexLine</em> is the parser for the readline proc.  It takes a line
of formatted input, parses out the fields with a regexp, and computes the
line checksum.  If the checksum is invalid, it errors. If the checksum is
valid, it returns a list of up to three fields:  the symbolic type of the
line per the spec, the local address, and/or the list of data bytes, either
of which may not exist depending on the type.</p>
<p>The list is in the order  {type, address, dataList}.</p>
<p>If the parsing or checksum fail, error out - there's no real recovery from a
truly corrupted file.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::ProcessIhexLine <span class="k">{</span><span class="nv">line</span><span class="k">}</span> <span class="k">{</span>
    <span class="k">set</span> matchStr <span class="k">{</span><span class="o">:</span><span class="k">([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]{</span><span class="nv">2</span><span class="k">})([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]{</span><span class="nv">4</span><span class="k">})([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]{</span><span class="nv">2</span><span class="k">})([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]</span><span class="o">*</span><span class="k">)([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]{</span><span class="nv">2</span><span class="k">})}</span>
    <span class="k">if</span> <span class="k">{</span><span class="o">!</span><span class="k">[</span><span class="nb">regexp</span> <span class="nv">$matchStr</span> <span class="nv">$line</span> <span class="o">-&gt;</span> count addr type data chksum<span class="k">]}</span> <span class="k">{</span>
        <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ProcessIhexLine: Input file syntax error: could not parse $line&quot;</span>
        <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
        <span class="k">error</span> <span class="nv">$errMsg</span>
    <span class="k">}</span>
    <span class="err">;</span><span class="c"># N.B.: count is in bytes while string length is in digits.</span>
    <span class="k">if</span> <span class="k">{(</span><span class="s2">&quot;0x$count&quot;</span> <span class="o">*</span> <span class="nv">2</span><span class="k">)</span> <span class="o">!=</span> <span class="k">[</span><span class="nb">string</span> length <span class="nv">$data</span><span class="k">]}</span> <span class="k">{</span>
        <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ProcessIhexLine: Incorrect data field size! \</span>
<span class="s2">                    Expected [expr {$count * 2}], got\</span>
<span class="s2">                    [string length $data].\nLine was: $line&quot;</span>
        <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
        <span class="k">error</span> <span class="nv">$errMsg</span>
    <span class="k">}</span>
    <span class="k">set</span> csum <span class="mi">0</span>
    <span class="k">foreach</span> <span class="k">{</span><span class="nv">digit1</span> digit2<span class="k">}</span> <span class="k">[</span><span class="nb">lrange</span> <span class="k">[</span><span class="nb">split</span> <span class="nv">$line</span> <span class="s2">&quot;&quot;</span><span class="k">]</span> <span class="mi">1</span> end<span class="k">]</span> <span class="k">{</span>
        <span class="nb">incr</span> csum <span class="k">[expr</span> <span class="k">{</span><span class="s2">&quot;0x$digit1$digit2&quot;</span><span class="k">}]</span>
    <span class="k">}</span>
    <span class="k">if</span> <span class="k">{(</span><span class="nv">$csum</span> <span class="o">&amp;</span> <span class="nv">0xFF</span><span class="k">)</span> <span class="o">!=</span> <span class="nv">0</span><span class="k">}</span> <span class="k">{</span>
        <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ProcessIhexLine: line checksum fail: computed $csum,\</span>
<span class="s2">                    expected 0, line was: $line&quot;</span>
        <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
        <span class="k">error</span> <span class="nv">$errMsg</span>
    <span class="k">}</span>
    <span class="k">switch</span> <span class="nv">$type</span> <span class="k">{</span>
        <span class="nv">00</span> <span class="k">{</span>
            <span class="k">set</span> dataL <span class="k">{}</span>
................................................................................
            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;DATA&quot;</span> <span class="k">[expr</span> <span class="s2">&quot;0x$addr&quot;</span><span class="k">]</span> <span class="nv">$dataL</span><span class="k">]</span>
        <span class="k">}</span>
        <span class="nv">01</span> <span class="k">{</span>
            <span class="k">return</span> <span class="k">{</span><span class="s2">&quot;EOF&quot;</span> <span class="k">{}</span> <span class="k">}</span>
        <span class="k">}</span>
        <span class="nv">02</span> <span class="k">{</span>
            <span class="k">if</span> <span class="k">{</span><span class="nv">$::binconvert::IhexFileType</span> <span class="nv">eq</span> <span class="s2">&quot;I32&quot;</span><span class="k">}</span> <span class="k">{</span>
                <span class="nv">log</span><span class="o">::</span>error <span class="s2">&quot;binconvert: ProcessIhexLine: File mixes I16 &amp; I32 segment offsets!&quot;</span>
            <span class="k">}</span>
            <span class="k">set</span> <span class="o">::</span>binconvert::IhexFileType <span class="s2">&quot;I16&quot;</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-3'>
    <div class='docs'>
................................................................................
      <p>Upshifting address by 4 bits as we output it</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;SEGADDR&quot;</span> <span class="k">[expr</span> <span class="s2">&quot;0x${data}0&quot;</span><span class="k">]</span> <span class="k">]</span>
        <span class="k">}</span>
        <span class="nv">03</span> <span class="k">{</span>
            <span class="k">if</span> <span class="k">{</span><span class="nv">$::binconvert::IhexFileType</span> <span class="nv">eq</span> <span class="s2">&quot;I32&quot;</span><span class="k">}</span> <span class="k">{</span>
                <span class="nv">log</span><span class="o">::</span>error <span class="s2">&quot;binconvert: ProcessIhexLine: File mixes I16 &amp; I32 segment offsets!&quot;</span>
            <span class="k">}</span>
            <span class="k">set</span> <span class="o">::</span>binconvert::IhexFileType <span class="s2">&quot;I16&quot;</span>
            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;STARTADDR&quot;</span> <span class="k">[expr</span> <span class="s2">&quot;0x$data&quot;</span><span class="k">]</span> <span class="s2">&quot;I16&quot;</span> <span class="k">]</span>
        <span class="k">}</span>
        <span class="nv">04</span> <span class="k">{</span>
            <span class="k">if</span> <span class="k">{</span><span class="nv">$::binconvert::IhexFileType</span> <span class="nv">eq</span> <span class="s2">&quot;I16&quot;</span><span class="k">}</span> <span class="k">{</span>
                <span class="nv">log</span><span class="o">::</span>error <span class="s2">&quot;binconvert: ProcessIhexLine: File mixes I16 &amp; I32 segment offsets!&quot;</span>
            <span class="k">}</span>
            <span class="k">set</span> <span class="o">::</span>binconvert::IhexFileType <span class="s2">&quot;I32&quot;</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-4'>
    <div class='docs'>
................................................................................
      <p>Upshifting address by 16 bits as we output it</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;SEGADDR&quot;</span> <span class="k">[expr</span> <span class="s2">&quot;0x${data}0000&quot;</span><span class="k">]</span> <span class="k">]</span>
        <span class="k">}</span>
        <span class="nv">05</span> <span class="k">{</span>
            <span class="k">if</span> <span class="k">{</span><span class="nv">$::binconvert::IhexFileType</span> <span class="nv">eq</span> <span class="s2">&quot;I16&quot;</span><span class="k">}</span> <span class="k">{</span>
                <span class="nv">log</span><span class="o">::</span>error <span class="s2">&quot;binconvert: ProcessIhexLine: File mixes I16 &amp; I32 segment offsets!&quot;</span>
            <span class="k">}</span>
            <span class="k">set</span> <span class="o">::</span>binconvert::IhexFileType <span class="s2">&quot;I32&quot;</span>
            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;STARTADDR&quot;</span> <span class="k">[expr</span> <span class="s2">&quot;0x$data&quot;</span><span class="k">]</span> <span class="s2">&quot;I32&quot;</span> <span class="k">]</span>
        <span class="k">}</span>
        <span class="nv">default</span> <span class="k">{</span>
            <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ProcessIhexLine: Unrecognized line type! \</span>
<span class="s2">                    $type not in 0-5 per spec. \nLine was: $line&quot;</span>
            <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
            <span class="k">error</span> <span class="nv">$errMsg</span>
        <span class="k">}</span>
    <span class="k">}</span>
<span class="k">}</span></pre></div>
    </div>

Changes to docs/rawbin.html.

24
25
26
27
28
29
30
31



32
33
34
35
36
37
38



















































































































39
40
41
42
43
44
45
<p>AUTHOR:      erik.johnson@jogle.us</p>
<p>DESCRIPTION:
  rawbin.tcl is part of the binconvert package.  binconvert is a package
  that reads &amp; writes EEPROM memory files in multiple formats.
  It converts the data to &amp; from a Tcl representation as a list of
  data segments, which is available for processing.</p>
<p>rawbin.tcl contains all the support procs to manage input from binary
  files of no particular format.  It will</p>



<h6></h6>
<p>This package documentation is auto-generated with
Pycco: <a href="https://pycco-docs.github.io/pycco/">https://pycco-docs.github.io/pycco/</a></p>
<p>Use "pycco <em>filename</em>" to re-generate HTML documentation in ./docs .</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span></span>




















































































































</pre></div>
    </div>
  </div>
  <div class='clearall'></div>
</div>
</body>







|
>
>
>






|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
<p>AUTHOR:      erik.johnson@jogle.us</p>
<p>DESCRIPTION:
  rawbin.tcl is part of the binconvert package.  binconvert is a package
  that reads &amp; writes EEPROM memory files in multiple formats.
  It converts the data to &amp; from a Tcl representation as a list of
  data segments, which is available for processing.</p>
<p>rawbin.tcl contains all the support procs to manage input from binary
  files of no particular format.  It assumes a starting address of 0
  and packs all data read into one initial segment.  When writing out
  data, it will start at 0 or such other address as the user sets, and
  will fill in undefined data with bytes of 0xFF or as the user sets.</p>
<h6></h6>
<p>This package documentation is auto-generated with
Pycco: <a href="https://pycco-docs.github.io/pycco/">https://pycco-docs.github.io/pycco/</a></p>
<p>Use "pycco <em>filename</em>" to re-generate HTML documentation in ./docs .</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span></span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-1'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-1'>#</a>
      </div>
      <hr />
<h1>Procedures for Raw Binary Format</h1>
<p>This format is not really a format.  This is intended to be used to input
things like memory dumps from tools to be saved in another format, or to
write</p>
<hr />
<p><a name="ProcessRawbinLine"></a></p>
<h2>ProcessRawbinLine</h2>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-2'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-2'>#</a>
      </div>
      <p><em>ProcessRawbinLine</em> is the parser for the readline proc.  Since the input
file did not have lines, we don't expect more than one lump of data.
Use <em>binary scan</em> to convert the whole thing to a list of byte values.</p>
<p>N.B. that there are no checksums or CRCs, and thus no way of detecting a
corrupted file unless the corruption makes a line not interpretable.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::ProcessRawbinLine <span class="k">{</span><span class="nv">dataIn</span><span class="k">}</span> <span class="k">{</span>
    <span class="k">set</span> addr <span class="mi">0</span>
    <span class="nb">binary</span> scan <span class="nv">$dataIn</span> cu<span class="o">*</span> dataL
    <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> DATA <span class="nv">$addr</span> <span class="nv">$dataL</span><span class="k">]</span>
<span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-3'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-3'>#</a>
      </div>
      <hr />
<p><a name="WriteRawbinFile"></a></p>
<h2>WriteRawbinFile</h2>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-4'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-4'>#</a>
      </div>
      <p><em>WriteRawbinFile</em> will iterate over the segments of the segment list.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::WriteRawbinFile <span class="k">{</span><span class="nv">segmentList</span> outchan <span class="k">{</span><span class="nv">startAddr</span> <span class="mi">0</span><span class="k">}</span> <span class="k">{</span><span class="nv">fillValue</span> <span class="mh">0x255</span><span class="k">}}</span> <span class="k">{</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-5'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-5'>#</a>
      </div>
      <p>Scan the list for the end address.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">set</span> maxAddr <span class="mi">0</span>
    <span class="k">foreach</span> <span class="k">{</span><span class="nv">addr</span> dataL<span class="k">}</span> <span class="nv">$segmentList</span> <span class="k">{</span>
        <span class="k">if</span> <span class="k">{</span><span class="nv">$maxAddr</span> <span class="o">&lt;</span> <span class="k">(</span><span class="nv">$addr</span> <span class="o">+</span> <span class="k">[</span><span class="nb">llength</span> <span class="nv">$dataL</span><span class="k">])}</span> <span class="k">{</span>
            <span class="k">set</span> maxAddr <span class="k">[expr</span> <span class="k">{</span><span class="nv">$addr</span> <span class="o">+</span> <span class="k">[</span><span class="nb">llength</span> <span class="nv">$dataL</span><span class="k">]}]</span>
        <span class="k">}</span>
    <span class="k">}</span>
    <span class="k">set</span> outL <span class="k">[</span><span class="nb">lrepeat</span> <span class="nv">$fillValue</span> <span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-6'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-6'>#</a>
      </div>
      <p>We have our filled output list.  For each segment, replace the data
in the appropriate range with the segment data.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">foreach</span> <span class="k">{</span><span class="nv">addr</span> dataL<span class="k">}</span> <span class="nv">$segmentList</span> <span class="k">{</span>
        <span class="k">set</span> outL <span class="k">[</span><span class="nb">lreplace</span> <span class="nv">$outL</span> <span class="nv">$addr</span> <span class="k">[expr</span> <span class="k">{</span><span class="nv">$addr</span> <span class="o">+</span> <span class="k">[</span><span class="nb">llength</span> <span class="nv">$dataL</span><span class="k">]}]</span> <span class="k">{</span><span class="o">*</span><span class="k">}</span><span class="nv">$dataL</span><span class="k">]</span><span class="err">]</span>
    <span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-7'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-7'>#</a>
      </div>
      <p>After the output list is completely filled, convert it to a binary
string and write it to disk.  Don't forget to set the output channel to
binary too, to keep line feeds from being corrupted.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">set</span> outS <span class="k">[</span><span class="nb">binary</span> format c<span class="o">*</span> <span class="nv">$outL</span><span class="k">]</span>
    <span class="nb">chan</span> configure <span class="nv">$outchan</span> <span class="o">-</span>translation binary
    <span class="nb">puts</span> <span class="nv">$outchan</span> <span class="nv">$outS</span>
<span class="k">}</span>

</pre></div>
    </div>
  </div>
  <div class='clearall'></div>
</div>
</body>

Changes to docs/srec.html.

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
..
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
...
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
...
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
...
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
...
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
...
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
...
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
  <div class='clearall'></div>
  <div class='section' id='section-1'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-1'>#</a>
      </div>
      <hr />
<h2>Procedures for Motorola SREC Format</h2>
<p>For details on the Motorola SREC format, see:
<a href="https://en.wikipedia.org/wiki/SREC_(file_format)">https://en.wikipedia.org/wiki/SREC_(file_format)</a></p>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
................................................................................
  <div class='clearall'></div>
  <div class='section' id='section-2'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-2'>#</a>
      </div>
      <hr />
<p><a name="ValidateSrecLine"></a></p>
<h3>ValidateSrecLine</h3>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-3'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-3'>#</a>
      </div>
      <p><em>ValidateSrecLine</em> takes a line of formatted input and parses out the fields
with a regexp, and computes and checks the line checksum.  If the checksum
is valid, it checks the byte count against the number of actual digits in
the line.  If those match, it returns a list of up to three fields:
the symbolic type of the line per the spec, the local address, and/or the
list of data bytes, either of which may not exist depending on the type.</p>
<p>If the parsing or checksum fail, error out - there's no real recovery from a
truly corrupted file.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::ValidateSrecLine <span class="k">{</span><span class="nv">line</span><span class="k">}</span> <span class="k">{</span>
    <span class="k">set</span> matchStr <span class="k">{</span><span class="nv">S</span><span class="k">([[</span><span class="o">:</span><span class="nv">digit</span><span class="o">:</span><span class="k">]])([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]{</span><span class="nv">2</span><span class="k">})([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]</span><span class="o">*</span><span class="k">)([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]{</span><span class="nv">2</span><span class="k">})}</span>
    <span class="k">if</span> <span class="k">{</span><span class="o">!</span><span class="k">[</span><span class="nb">regexp</span> <span class="nv">$matchStr</span> <span class="nv">$line</span> <span class="o">-&gt;</span> type count payload chksum<span class="k">]}</span> <span class="k">{</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-4'>
    <div class='docs'>
................................................................................
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-5'>#</a>
      </div>
      <p>Not a comment.  Bad input data - error out of it.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>        <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ValidateSrecLine: Input file syntax error: \</span>
<span class="s2">                    could not parse $line (line $::binconvert::SrecLineCount)&quot;</span>
        <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
        <span class="k">error</span> <span class="nv">$errMsg</span>
    <span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
................................................................................
      <div class='octowrap'>
        <a class='octothorpe' href='#section-6'>#</a>
      </div>
      <p>N.B.: count is in bytes while string length is in digits.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">if</span> <span class="k">{(</span><span class="s2">&quot;0x$count&quot;</span> <span class="o">*</span> <span class="nv">2</span><span class="k">)</span> <span class="o">!=</span> <span class="k">([</span><span class="nb">string</span> length <span class="nv">$payload</span><span class="k">]</span> <span class="o">+</span> <span class="nv">2</span><span class="k">)}</span> <span class="k">{</span>
        <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ValidateSrecLine: Incorrect record length! \</span>
<span class="s2">                    Expected [expr {$count * 2}], got\</span>
<span class="s2">                    [expr {[string length $payload] + 2}].\nLine was: $line&quot;</span>
        <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
        <span class="k">error</span> <span class="nv">$errMsg</span>
    <span class="k">}</span>
    <span class="k">set</span> csum <span class="mi">0</span>
    <span class="k">foreach</span> <span class="k">{</span><span class="nv">digit1</span> digit2<span class="k">}</span> <span class="k">[</span><span class="nb">lrange</span> <span class="k">[</span><span class="nb">split</span> <span class="nv">$line</span> <span class="s2">&quot;&quot;</span><span class="k">]</span> <span class="mi">2</span> end<span class="k">]</span> <span class="k">{</span>
        <span class="nb">incr</span> csum <span class="k">[expr</span> <span class="k">{</span><span class="s2">&quot;0x$digit1$digit2&quot;</span><span class="k">}]</span>
    <span class="k">}</span>
    <span class="k">if</span> <span class="k">{(</span><span class="nv">$csum</span> <span class="o">&amp;</span> <span class="nv">0xFF</span><span class="k">)</span> <span class="o">!=</span> <span class="nv">0xFF</span><span class="k">}</span> <span class="k">{</span>
        <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ValidateSrecLine: line checksum fail. Computed</span>
<span class="s2">                    [expr {$csum &amp; 0xFF}], expected 0xFF, line was: $line&quot;</span>
        <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
        <span class="k">error</span> <span class="nv">$errMsg</span>
    <span class="k">}</span>
    <span class="k">switch</span> <span class="nv">$type</span> <span class="k">{</span>
        <span class="nv">0</span> <span class="k">{</span></pre></div>
    </div>
................................................................................
        <a class='octothorpe' href='#section-7'>#</a>
      </div>
      <p>Header</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">set</span> dataL <span class="k">{}</span>
            <span class="k">if</span> <span class="k">{[</span><span class="nb">string</span> range <span class="nv">$payload</span> <span class="mi">0</span> <span class="mi">3</span><span class="k">]</span> <span class="nv">ne</span> <span class="s2">&quot;0000&quot;</span><span class="k">}</span> <span class="k">{</span>
                <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ValidateSrecLine: invalid address\</span>
<span class="s2">                            in header. Spec requires &#39;0000&#39;, got \</span>
<span class="s2">                            [string range $payload 0 3]. Line was: $line&quot;</span>
                <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
                <span class="k">error</span> <span class="nv">$errMsg</span>
            <span class="k">}</span>
            <span class="k">set</span> <span class="o">::</span>binconvert::SrecLineCount <span class="mi">0</span>
            <span class="k">foreach</span> <span class="k">{</span><span class="nv">digit1</span> digit2<span class="k">}</span> <span class="k">[</span><span class="nb">split</span> <span class="k">[</span><span class="nb">string</span> range <span class="nv">$payload</span> <span class="mi">4</span> end<span class="k">]</span> <span class="s2">&quot;&quot;</span><span class="k">]</span> <span class="k">{</span>
................................................................................
      <div class='octowrap'>
        <a class='octothorpe' href='#section-11'>#</a>
      </div>
      <p>16-bit line count</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">if</span> <span class="k">{</span><span class="nv">$::binconvert::SrecLineCount</span> <span class="o">!=</span> <span class="k">[expr</span> <span class="k">{</span><span class="s2">&quot;0x$payload&quot;</span><span class="k">}]}</span> <span class="k">{</span>
                <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ValidateSrecLine: Line count does\</span>
<span class="s2">                            not match!  [expr {&quot;0x$payload&quot;}] lines expected,\</span>
<span class="s2">                            $::binconvert::SrecLineCount lines seen.&quot;</span>
                <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
                <span class="k">error</span> <span class="nv">$errMsg</span>
            <span class="k">}</span>
            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;NOP&quot;</span> <span class="k">{}]</span>
        <span class="k">}</span>
................................................................................
      <div class='octowrap'>
        <a class='octothorpe' href='#section-12'>#</a>
      </div>
      <p>24-bit line count</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">if</span> <span class="k">{</span><span class="nv">$::binconvert::SrecLineCount</span> <span class="o">!=</span> <span class="k">[expr</span> <span class="k">{</span><span class="s2">&quot;0x$payload&quot;</span><span class="k">}]}</span> <span class="k">{</span>
                <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ValidateSrecLine: Line count does\</span>
<span class="s2">                            not match!  [expr {&quot;0x$payload&quot;}] lines expected,\</span>
<span class="s2">                            $::binconvert::SrecLineCount lines seen.&quot;</span>
                <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
                <span class="k">error</span> <span class="nv">$errMsg</span>
            <span class="k">}</span>
            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;NOP&quot;</span> <span class="k">{}]</span>
        <span class="k">}</span>
................................................................................
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">if</span> <span class="k">{[expr</span> <span class="k">{</span><span class="s2">&quot;0x$payload&quot;</span><span class="k">}]</span> <span class="o">==</span> <span class="nv">0</span><span class="k">}</span> <span class="k">{</span>
                <span class="k">return</span> <span class="k">{</span> <span class="s2">&quot;EOF&quot;</span> <span class="k">{}</span> <span class="k">}</span>
            <span class="k">}</span>
            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;STARTADDR&quot;</span> <span class="k">[expr</span> <span class="k">{</span><span class="s2">&quot;0x$payload&quot;</span><span class="k">}</span> <span class="k">]</span> <span class="k">]</span>
        <span class="k">}</span>
        <span class="nv">default</span> <span class="k">{</span>
            <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ValidateSrecLine: Invalid record type! \</span>
<span class="s2">                    $type not in 0-3 or 5-9 per spec.\nLine was: $line&quot;</span>
            <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
            <span class="k">error</span> <span class="nv">$errMsg</span>
        <span class="k">}</span>
    <span class="k">}</span>
<span class="k">}</span></pre></div>
    </div>
................................................................................
  <div class='section' id='section-24'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-24'>#</a>
      </div>
      <hr />
<p><a name="WriteSrecSegment"></a></p>
<h4>WriteSrecSegment</h4>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-25'>
................................................................................
  <div class='section' id='section-26'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-26'>#</a>
      </div>
      <hr />
<p><a name="makeSrecDataLine"></a></p>
<h4>makeSrecDataLine</h4>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-27'>
................................................................................
  <div class='section' id='section-28'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-28'>#</a>
      </div>
      <hr />
<p><a name="makeSrecLineChecksum"></a></p>
<h4>makeSrecLineChecksum</h4>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-29'>
................................................................................
It does <em>not</em> append it to the line; it leaves that to the caller.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::makeSrecLineChecksum <span class="k">{</span><span class="nv">line</span><span class="k">}</span> <span class="k">{</span>
    <span class="k">set</span> csum <span class="mi">0</span>
    <span class="k">foreach</span> <span class="k">{</span><span class="nv">digit1</span> digit2<span class="k">}</span> <span class="k">[</span><span class="nb">lrange</span> <span class="k">[</span><span class="nb">split</span> <span class="nv">$line</span> <span class="s2">&quot;&quot;</span><span class="k">]</span> <span class="mi">2</span> end<span class="k">]</span> <span class="k">{</span>
        <span class="nb">incr</span> csum <span class="k">[expr</span> <span class="k">{</span><span class="s2">&quot;0x$digit1$digit2&quot;</span><span class="k">}]</span>
    <span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-30'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-30'>#</a>
      </div>
      <p>@@@ puts -nonewline [format "csum in = 0x%02X;" $csum]</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">set</span> csum <span class="k">[expr</span> <span class="k">{</span><span class="o">~</span><span class="nv">$csum</span> <span class="o">&amp;</span> <span class="nv">0xFF</span><span class="k">}]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-31'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-31'>#</a>
      </div>
      <p>@@@ puts [format "csum out = 0x%02X" $csum ]</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">return</span> <span class="k">[</span><span class="nb">format</span> <span class="s2">&quot;%02X&quot;</span> <span class="nv">$csum</span><span class="k">]</span>
<span class="k">}</span>

</pre></div>
    </div>
  </div>
  <div class='clearall'></div>
</div>
</body>







|







 







|
|











|









|







 







|







 







|










|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|








48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
..
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
...
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
...
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
...
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
...
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
...
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
...
628
629
630
631
632
633
634
635











636











637
638
639
640
641
642
643
644
645
  <div class='clearall'></div>
  <div class='section' id='section-1'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-1'>#</a>
      </div>
      <hr />
<h1>Procedures for Motorola SREC Format</h1>
<p>For details on the Motorola SREC format, see:
<a href="https://en.wikipedia.org/wiki/SREC_(file_format)">https://en.wikipedia.org/wiki/SREC_(file_format)</a></p>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
................................................................................
  <div class='clearall'></div>
  <div class='section' id='section-2'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-2'>#</a>
      </div>
      <hr />
<p><a name="ProcessSrecLine"></a></p>
<h2>ProcessSrecLine</h2>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-3'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-3'>#</a>
      </div>
      <p><em>ProcessSrecLine</em> takes a line of formatted input and parses out the fields
with a regexp, and computes and checks the line checksum.  If the checksum
is valid, it checks the byte count against the number of actual digits in
the line.  If those match, it returns a list of up to three fields:
the symbolic type of the line per the spec, the local address, and/or the
list of data bytes, either of which may not exist depending on the type.</p>
<p>If the parsing or checksum fail, error out - there's no real recovery from a
truly corrupted file.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::ProcessSrecLine <span class="k">{</span><span class="nv">line</span><span class="k">}</span> <span class="k">{</span>
    <span class="k">set</span> matchStr <span class="k">{</span><span class="nv">S</span><span class="k">([[</span><span class="o">:</span><span class="nv">digit</span><span class="o">:</span><span class="k">]])([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]{</span><span class="nv">2</span><span class="k">})([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]</span><span class="o">*</span><span class="k">)([[</span><span class="o">:</span><span class="nv">xdigit</span><span class="o">:</span><span class="k">]]{</span><span class="nv">2</span><span class="k">})}</span>
    <span class="k">if</span> <span class="k">{</span><span class="o">!</span><span class="k">[</span><span class="nb">regexp</span> <span class="nv">$matchStr</span> <span class="nv">$line</span> <span class="o">-&gt;</span> type count payload chksum<span class="k">]}</span> <span class="k">{</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-4'>
    <div class='docs'>
................................................................................
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-5'>#</a>
      </div>
      <p>Not a comment.  Bad input data - error out of it.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>        <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ProcessSrecLine: Input file syntax error: \</span>
<span class="s2">                    could not parse $line (line $::binconvert::SrecLineCount)&quot;</span>
        <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
        <span class="k">error</span> <span class="nv">$errMsg</span>
    <span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
................................................................................
      <div class='octowrap'>
        <a class='octothorpe' href='#section-6'>#</a>
      </div>
      <p>N.B.: count is in bytes while string length is in digits.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">if</span> <span class="k">{(</span><span class="s2">&quot;0x$count&quot;</span> <span class="o">*</span> <span class="nv">2</span><span class="k">)</span> <span class="o">!=</span> <span class="k">([</span><span class="nb">string</span> length <span class="nv">$payload</span><span class="k">]</span> <span class="o">+</span> <span class="nv">2</span><span class="k">)}</span> <span class="k">{</span>
        <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ProcessSrecLine: Incorrect record length! \</span>
<span class="s2">                    Expected [expr {$count * 2}], got\</span>
<span class="s2">                    [expr {[string length $payload] + 2}].\nLine was: $line&quot;</span>
        <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
        <span class="k">error</span> <span class="nv">$errMsg</span>
    <span class="k">}</span>
    <span class="k">set</span> csum <span class="mi">0</span>
    <span class="k">foreach</span> <span class="k">{</span><span class="nv">digit1</span> digit2<span class="k">}</span> <span class="k">[</span><span class="nb">lrange</span> <span class="k">[</span><span class="nb">split</span> <span class="nv">$line</span> <span class="s2">&quot;&quot;</span><span class="k">]</span> <span class="mi">2</span> end<span class="k">]</span> <span class="k">{</span>
        <span class="nb">incr</span> csum <span class="k">[expr</span> <span class="k">{</span><span class="s2">&quot;0x$digit1$digit2&quot;</span><span class="k">}]</span>
    <span class="k">}</span>
    <span class="k">if</span> <span class="k">{(</span><span class="nv">$csum</span> <span class="o">&amp;</span> <span class="nv">0xFF</span><span class="k">)</span> <span class="o">!=</span> <span class="nv">0xFF</span><span class="k">}</span> <span class="k">{</span>
        <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ProcessSrecLine: line checksum fail. Computed</span>
<span class="s2">                    [expr {$csum &amp; 0xFF}], expected 0xFF, line was: $line&quot;</span>
        <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
        <span class="k">error</span> <span class="nv">$errMsg</span>
    <span class="k">}</span>
    <span class="k">switch</span> <span class="nv">$type</span> <span class="k">{</span>
        <span class="nv">0</span> <span class="k">{</span></pre></div>
    </div>
................................................................................
        <a class='octothorpe' href='#section-7'>#</a>
      </div>
      <p>Header</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">set</span> dataL <span class="k">{}</span>
            <span class="k">if</span> <span class="k">{[</span><span class="nb">string</span> range <span class="nv">$payload</span> <span class="mi">0</span> <span class="mi">3</span><span class="k">]</span> <span class="nv">ne</span> <span class="s2">&quot;0000&quot;</span><span class="k">}</span> <span class="k">{</span>
                <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ProcessSrecLine: invalid address\</span>
<span class="s2">                            in header. Spec requires &#39;0000&#39;, got \</span>
<span class="s2">                            [string range $payload 0 3]. Line was: $line&quot;</span>
                <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
                <span class="k">error</span> <span class="nv">$errMsg</span>
            <span class="k">}</span>
            <span class="k">set</span> <span class="o">::</span>binconvert::SrecLineCount <span class="mi">0</span>
            <span class="k">foreach</span> <span class="k">{</span><span class="nv">digit1</span> digit2<span class="k">}</span> <span class="k">[</span><span class="nb">split</span> <span class="k">[</span><span class="nb">string</span> range <span class="nv">$payload</span> <span class="mi">4</span> end<span class="k">]</span> <span class="s2">&quot;&quot;</span><span class="k">]</span> <span class="k">{</span>
................................................................................
      <div class='octowrap'>
        <a class='octothorpe' href='#section-11'>#</a>
      </div>
      <p>16-bit line count</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">if</span> <span class="k">{</span><span class="nv">$::binconvert::SrecLineCount</span> <span class="o">!=</span> <span class="k">[expr</span> <span class="k">{</span><span class="s2">&quot;0x$payload&quot;</span><span class="k">}]}</span> <span class="k">{</span>
                <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ProcessSrecLine: Line count does\</span>
<span class="s2">                            not match!  [expr {&quot;0x$payload&quot;}] lines expected,\</span>
<span class="s2">                            $::binconvert::SrecLineCount lines seen.&quot;</span>
                <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
                <span class="k">error</span> <span class="nv">$errMsg</span>
            <span class="k">}</span>
            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;NOP&quot;</span> <span class="k">{}]</span>
        <span class="k">}</span>
................................................................................
      <div class='octowrap'>
        <a class='octothorpe' href='#section-12'>#</a>
      </div>
      <p>24-bit line count</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">if</span> <span class="k">{</span><span class="nv">$::binconvert::SrecLineCount</span> <span class="o">!=</span> <span class="k">[expr</span> <span class="k">{</span><span class="s2">&quot;0x$payload&quot;</span><span class="k">}]}</span> <span class="k">{</span>
                <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ProcessSrecLine: Line count does\</span>
<span class="s2">                            not match!  [expr {&quot;0x$payload&quot;}] lines expected,\</span>
<span class="s2">                            $::binconvert::SrecLineCount lines seen.&quot;</span>
                <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
                <span class="k">error</span> <span class="nv">$errMsg</span>
            <span class="k">}</span>
            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;NOP&quot;</span> <span class="k">{}]</span>
        <span class="k">}</span>
................................................................................
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">if</span> <span class="k">{[expr</span> <span class="k">{</span><span class="s2">&quot;0x$payload&quot;</span><span class="k">}]</span> <span class="o">==</span> <span class="nv">0</span><span class="k">}</span> <span class="k">{</span>
                <span class="k">return</span> <span class="k">{</span> <span class="s2">&quot;EOF&quot;</span> <span class="k">{}</span> <span class="k">}</span>
            <span class="k">}</span>
            <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="s2">&quot;STARTADDR&quot;</span> <span class="k">[expr</span> <span class="k">{</span><span class="s2">&quot;0x$payload&quot;</span><span class="k">}</span> <span class="k">]</span> <span class="k">]</span>
        <span class="k">}</span>
        <span class="nv">default</span> <span class="k">{</span>
            <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ProcessSrecLine: Invalid record type! \</span>
<span class="s2">                    $type not in 0-3 or 5-9 per spec.\nLine was: $line&quot;</span>
            <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
            <span class="k">error</span> <span class="nv">$errMsg</span>
        <span class="k">}</span>
    <span class="k">}</span>
<span class="k">}</span></pre></div>
    </div>
................................................................................
  <div class='section' id='section-24'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-24'>#</a>
      </div>
      <hr />
<p><a name="WriteSrecSegment"></a></p>
<h3>WriteSrecSegment</h3>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-25'>
................................................................................
  <div class='section' id='section-26'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-26'>#</a>
      </div>
      <hr />
<p><a name="makeSrecDataLine"></a></p>
<h3>makeSrecDataLine</h3>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-27'>
................................................................................
  <div class='section' id='section-28'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-28'>#</a>
      </div>
      <hr />
<p><a name="makeSrecLineChecksum"></a></p>
<h3>makeSrecLineChecksum</h3>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-29'>
................................................................................
It does <em>not</em> append it to the line; it leaves that to the caller.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::makeSrecLineChecksum <span class="k">{</span><span class="nv">line</span><span class="k">}</span> <span class="k">{</span>
    <span class="k">set</span> csum <span class="mi">0</span>
    <span class="k">foreach</span> <span class="k">{</span><span class="nv">digit1</span> digit2<span class="k">}</span> <span class="k">[</span><span class="nb">lrange</span> <span class="k">[</span><span class="nb">split</span> <span class="nv">$line</span> <span class="s2">&quot;&quot;</span><span class="k">]</span> <span class="mi">2</span> end<span class="k">]</span> <span class="k">{</span>
        <span class="nb">incr</span> csum <span class="k">[expr</span> <span class="k">{</span><span class="s2">&quot;0x$digit1$digit2&quot;</span><span class="k">}]</span>
    <span class="k">}</span>











    <span class="k">set</span> csum <span class="k">[expr</span> <span class="k">{</span><span class="o">~</span><span class="nv">$csum</span> <span class="o">&amp;</span> <span class="nv">0xFF</span><span class="k">}]</span>











    <span class="k">return</span> <span class="k">[</span><span class="nb">format</span> <span class="s2">&quot;%02X&quot;</span> <span class="nv">$csum</span><span class="k">]</span>
<span class="k">}</span>

</pre></div>
    </div>
  </div>
  <div class='clearall'></div>
</div>
</body>

Changes to docs/titxt.html.

30
31
32
33
34
35
36
37



















































































































































































38
39
40
41
42
43
44
<p>titxt.tcl contains all the support procs for the form generated by TI's</p>
<h6></h6>
<p>This package documentation is auto-generated with
Pycco: <a href="https://pycco-docs.github.io/pycco/">https://pycco-docs.github.io/pycco/</a></p>
<p>Use "pycco <em>filename</em>" to re-generate HTML documentation in ./docs .</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span></span>




















































































































































































</pre></div>
    </div>
  </div>
  <div class='clearall'></div>
</div>
</body>







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
<p>titxt.tcl contains all the support procs for the form generated by TI's</p>
<h6></h6>
<p>This package documentation is auto-generated with
Pycco: <a href="https://pycco-docs.github.io/pycco/">https://pycco-docs.github.io/pycco/</a></p>
<p>Use "pycco <em>filename</em>" to re-generate HTML documentation in ./docs .</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span></span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-1'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-1'>#</a>
      </div>
      <hr />
<h1>Procedures for TI Text Format</h1>
<p>For details on the TI Text format, see
<a href="http://manpages.ubuntu.com/manpages/trusty/man5/srec_ti_txt.5.html">http://manpages.ubuntu.com/manpages/trusty/man5/srec_ti_txt.5.html</a></p>
<hr />
<p><a name="ProcessTitxtLine"></a></p>
<h2>ProcessTitxtLine</h2>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-2'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-2'>#</a>
      </div>
      <p><em>ProcessTitxtLine</em> is the parser for the readline proc.  Since TI-TXT is a
very simple format, and since the line types do not have a common format,
we don't bother using a regexp to parse it.</p>
<p>N.B. that there are no checksums or CRCs, and thus no way of detecting a
corrupted file unless the corruption makes a line not interpretable.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::ProcessTitxtLine <span class="k">{</span><span class="nv">line</span><span class="k">}</span> <span class="k">{</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-3'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-3'>#</a>
      </div>
      <p>If the line starts with "@", it's an address.
Address lines are reported as segment addresses.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">if</span> <span class="k">{[</span><span class="nb">string</span> range <span class="nv">$line</span> <span class="mi">0</span> <span class="mi">0</span><span class="k">]</span> <span class="nv">eq</span> <span class="s2">&quot;@&quot;</span><span class="k">}</span> <span class="k">{</span>
        <span class="k">set</span> <span class="o">::</span>binconvert::TitxtLineAddr <span class="mi">0</span>
        <span class="k">set</span> segAddr <span class="k">[expr</span> <span class="k">{[</span><span class="nb">format</span> <span class="s2">&quot;0x%x&quot;</span> <span class="k">[</span><span class="nb">string</span> range <span class="nv">$line</span> <span class="mi">1</span> end<span class="k">]]}]</span>
        <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> SEGADDR <span class="nv">$segAddr</span><span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-4'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-4'>#</a>
      </div>
      <p>If the line is "q", it's the file terminator, reported as EOF.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">}</span> <span class="k">elseif</span> <span class="k">{([</span><span class="nb">string</span> range <span class="nv">$line</span> <span class="mi">0</span> <span class="mi">0</span><span class="k">]</span> <span class="nv">eq</span> <span class="s2">&quot;q&quot;</span><span class="k">)</span> <span class="o">&amp;&amp;</span> <span class="k">([</span><span class="nb">string</span> length <span class="nv">$line</span><span class="k">]</span> <span class="o">==</span> <span class="nv">1</span><span class="k">)}</span> <span class="k">{</span>
        <span class="k">return</span> <span class="k">{</span><span class="s2">&quot;EOF&quot;</span> <span class="k">{}</span> <span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-5'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-5'>#</a>
      </div>
      <p>Otherwise, the line should have 1-16 two-digit hexadecimal numbers,
each representing one byte, separated by spaces.  Data lines keep a
running count of bytes processed since the last segment, to be used
as a line address.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">}</span> <span class="k">else</span> <span class="k">{</span>
        <span class="nv">try</span> <span class="k">{</span>
            <span class="k">foreach</span> databyte <span class="k">[</span><span class="nb">split</span> <span class="nv">$line</span> <span class="s2">&quot; &quot;</span><span class="k">]</span> <span class="k">{</span>
                <span class="nb">lappend</span> dataL <span class="k">[expr</span> <span class="k">{[</span><span class="nb">format</span> <span class="s2">&quot;0x%x&quot;</span> <span class="nv">$databyte</span><span class="k">]</span> <span class="o">%</span> <span class="nv">256</span><span class="k">}]</span>
            <span class="k">}</span>
        <span class="k">}</span> on error <span class="k">{</span><span class="nv">result</span><span class="k">}</span> <span class="k">{</span>
            <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ValidateTitxtLine: Input file syntax error: \</span>
<span class="s2">                        could not parse line: $line&quot;</span>
            <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
            <span class="nb">puts</span> <span class="nv">$result</span>
            <span class="nb">puts</span> <span class="nv">$::errorCode</span>
            <span class="nb">puts</span> <span class="nv">$::errorInfo</span>
            <span class="k">error</span> <span class="nv">$errMsg</span>
        <span class="k">}</span>
        <span class="k">if</span> <span class="k">{[</span><span class="nb">llength</span> <span class="nv">$dataL</span><span class="k">]</span> <span class="o">&gt;</span> <span class="nv">16</span><span class="k">}</span> <span class="k">{</span>
            <span class="k">set</span> errMsg <span class="s2">&quot;binconvert: ValidateTitxtLine: Input file syntax error: \</span>
<span class="s2">                        data line too long (&gt;16 bytes): $line&quot;</span>
            <span class="nv">log</span><span class="o">::</span>error <span class="nv">$errMsg</span>
            <span class="k">error</span> <span class="nv">$errMsg</span>
        <span class="k">}</span>
        <span class="k">set</span> addr <span class="nv">$::binconvert::TitxtLineAddr</span>
        <span class="nb">incr</span> <span class="o">::</span>binconvert::TitxtLineAddr <span class="k">[</span><span class="nb">llength</span> <span class="nv">$dataL</span><span class="k">]</span>
        <span class="k">return</span> <span class="k">[</span><span class="nb">list</span> <span class="nv">$addr</span> <span class="nv">$dataL</span><span class="k">]</span>
    <span class="k">}</span>
<span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-6'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-6'>#</a>
      </div>
      <hr />
<p><a name="WriteTitxtFile"></a></p>
<h2>WriteTitxtFile</h2>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-7'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-7'>#</a>
      </div>
      <p><em>WriteTitxtFile</em> will iterate over the segments of the segment list.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::WriteTitxtFile <span class="k">{</span><span class="nv">segmentList</span> outchan<span class="k">}</span> <span class="k">{</span>
    <span class="k">foreach</span> <span class="k">{</span><span class="nv">addr</span> dataL<span class="k">}</span> <span class="nv">$segmentList</span> <span class="k">{</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-8'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-8'>#</a>
      </div>
      <p>For each segment, it will write the address as an address line
(e.g., @5C00).</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>        <span class="nb">puts</span> <span class="nv">$outchan</span> <span class="k">[</span><span class="nb">format</span> <span class="s2">&quot;\@%x&quot;</span> <span class="nv">$addr</span><span class="k">]</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-9'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-9'>#</a>
      </div>
      <p>The address is followed by the data in lines of 16 bytes,
with any short line at the end.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>        <span class="k">set</span> outS <span class="s2">&quot;&quot;</span>
        <span class="k">foreach</span> databyte <span class="nv">$dataL</span> <span class="k">{</span>
            <span class="nb">append</span> outS <span class="k">[</span><span class="nb">format</span> <span class="s2">&quot;%02x &quot;</span> <span class="nv">$databyte</span><span class="k">]</span>
            <span class="k">if</span> <span class="k">{[</span><span class="nb">string</span> length <span class="nv">$outS</span><span class="k">]</span> <span class="o">&gt;</span> <span class="nv">45</span><span class="k">}</span> <span class="k">{</span>
                <span class="nb">puts</span> <span class="nv">$outchan</span> <span class="k">[</span><span class="nb">string</span> trimright <span class="nv">$outS</span><span class="k">]</span>
                <span class="k">set</span> outS <span class="s2">&quot;&quot;</span>
            <span class="k">}</span>
        <span class="k">}</span>
        <span class="k">if</span> <span class="k">{[</span><span class="nb">string</span> length <span class="nv">$outS</span><span class="k">]</span> <span class="o">&gt;</span> <span class="nv">0</span><span class="k">}</span> <span class="k">{</span>
            <span class="nb">puts</span> <span class="nv">$outchan</span> <span class="k">[</span><span class="nb">string</span> trimright <span class="nv">$outS</span><span class="k">]</span>
        <span class="k">}</span>
    <span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-10'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-10'>#</a>
      </div>
      <p>After all segments are written out, it will write the "q" line and end.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="nb">puts</span> <span class="nv">$outchan</span> <span class="s2">&quot;q&quot;</span>
<span class="k">}</span>

</pre></div>
    </div>
  </div>
  <div class='clearall'></div>
</div>
</body>

Changes to ihex.tcl.

34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
..
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128

#--------------------------------------------------------------------------
### Procedures for Intel Hex Format
#
# For details on the Intel Ihex format, see
# <https://en.wikipedia.org/wiki/Intel_HEX>


# <a name="ValidateIhexLine"></a>
#### ValidateIhexLine
# *ValidateIhexLine* is the parser for the readline proc.  It takes a line
# of formatted input, parses out the fields with a regexp, and computes the
# line checksum.  If the checksum is invalid, it errors. If the checksum is
# valid, it returns a list of up to three fields:  the symbolic type of the
# line per the spec, the local address, and/or the list of data bytes, either
# of which may not exist depending on the type.
#
# The list is in the order  {type, address, dataList}.
#
# If the parsing or checksum fail, error out - there's no real recovery from a
# truly corrupted file.
proc ::binconvert::ValidateIhexLine {line} {
    set matchStr {:([[:xdigit:]]{2})([[:xdigit:]]{4})([[:xdigit:]]{2})([[:xdigit:]]*)([[:xdigit:]]{2})}
    if {![regexp $matchStr $line -> count addr type data chksum]} {
        set errMsg "binconvert: ValidateIhexLine: Input file syntax error: could not parse $line"
        log::error $errMsg
        error $errMsg
    }
    ;# N.B.: count is in bytes while string length is in digits.
    if {("0x$count" * 2) != [string length $data]} {
        set errMsg "binconvert: ValidateIhexLine: Incorrect data field size! \
                    Expected [expr {$count * 2}], got\
                    [string length $data].\nLine was: $line"
        log::error $errMsg
        error $errMsg
    }
    set csum 0
    foreach {digit1 digit2} [lrange [split $line ""] 1 end] {
        incr csum [expr {"0x$digit1$digit2"}]
    }
    if {($csum & 0xFF) != 0} {
        set errMsg "binconvert: ValidateIhexLine: line checksum fail: computed $csum,\
                    expected 0, line was: $line"
        log::error $errMsg
        error $errMsg
    }
    switch $type {
        00 {
            set dataL {}
................................................................................
            return [list "DATA" [expr "0x$addr"] $dataL]
        }
        01 {
            return {"EOF" {} }
        }
        02 {
            if {$::binconvert::IhexFileType eq "I32"} {
                log::error "binconvert: ValidateIhexLine: File mixes I16 & I32 segment offsets!"
            }
            set ::binconvert::IhexFileType "I16"
            # Upshifting address by 4 bits as we output it
            return [list "SEGADDR" [expr "0x${data}0"] ]
        }
        03 {
            if {$::binconvert::IhexFileType eq "I32"} {
                log::error "binconvert: ValidateIhexLine: File mixes I16 & I32 segment offsets!"
            }
            set ::binconvert::IhexFileType "I16"
            return [list "STARTADDR" [expr "0x$data"] "I16" ]
        }
        04 {
            if {$::binconvert::IhexFileType eq "I16"} {
                log::error "binconvert: ValidateIhexLine: File mixes I16 & I32 segment offsets!"
            }
            set ::binconvert::IhexFileType "I32"
            # Upshifting address by 16 bits as we output it
            return [list "SEGADDR" [expr "0x${data}0000"] ]
        }
        05 {
            if {$::binconvert::IhexFileType eq "I16"} {
                log::error "binconvert: ValidateIhexLine: File mixes I16 & I32 segment offsets!"
            }
            set ::binconvert::IhexFileType "I32"
            return [list "STARTADDR" [expr "0x$data"] "I32" ]
        }
        default {
            set errMsg "binconvert: ValidateIhexLine: Unrecognized line type! \
                    $type not in 0-5 per spec. \nLine was: $line"
            log::error $errMsg
            error $errMsg
        }
    }
}








>
|
|
|










|


|





|










|







 







|







|






|







|





|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
..
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

#--------------------------------------------------------------------------
### Procedures for Intel Hex Format
#
# For details on the Intel Ihex format, see
# <https://en.wikipedia.org/wiki/Intel_HEX>

#--------------------------------------------------------------------------
# <a name="ProcessIhexLine"></a>
#### ProcessIhexLine
# *ProcessIhexLine* is the parser for the readline proc.  It takes a line
# of formatted input, parses out the fields with a regexp, and computes the
# line checksum.  If the checksum is invalid, it errors. If the checksum is
# valid, it returns a list of up to three fields:  the symbolic type of the
# line per the spec, the local address, and/or the list of data bytes, either
# of which may not exist depending on the type.
#
# The list is in the order  {type, address, dataList}.
#
# If the parsing or checksum fail, error out - there's no real recovery from a
# truly corrupted file.
proc ::binconvert::ProcessIhexLine {line} {
    set matchStr {:([[:xdigit:]]{2})([[:xdigit:]]{4})([[:xdigit:]]{2})([[:xdigit:]]*)([[:xdigit:]]{2})}
    if {![regexp $matchStr $line -> count addr type data chksum]} {
        set errMsg "binconvert: ProcessIhexLine: Input file syntax error: could not parse $line"
        log::error $errMsg
        error $errMsg
    }
    ;# N.B.: count is in bytes while string length is in digits.
    if {("0x$count" * 2) != [string length $data]} {
        set errMsg "binconvert: ProcessIhexLine: Incorrect data field size! \
                    Expected [expr {$count * 2}], got\
                    [string length $data].\nLine was: $line"
        log::error $errMsg
        error $errMsg
    }
    set csum 0
    foreach {digit1 digit2} [lrange [split $line ""] 1 end] {
        incr csum [expr {"0x$digit1$digit2"}]
    }
    if {($csum & 0xFF) != 0} {
        set errMsg "binconvert: ProcessIhexLine: line checksum fail: computed $csum,\
                    expected 0, line was: $line"
        log::error $errMsg
        error $errMsg
    }
    switch $type {
        00 {
            set dataL {}
................................................................................
            return [list "DATA" [expr "0x$addr"] $dataL]
        }
        01 {
            return {"EOF" {} }
        }
        02 {
            if {$::binconvert::IhexFileType eq "I32"} {
                log::error "binconvert: ProcessIhexLine: File mixes I16 & I32 segment offsets!"
            }
            set ::binconvert::IhexFileType "I16"
            # Upshifting address by 4 bits as we output it
            return [list "SEGADDR" [expr "0x${data}0"] ]
        }
        03 {
            if {$::binconvert::IhexFileType eq "I32"} {
                log::error "binconvert: ProcessIhexLine: File mixes I16 & I32 segment offsets!"
            }
            set ::binconvert::IhexFileType "I16"
            return [list "STARTADDR" [expr "0x$data"] "I16" ]
        }
        04 {
            if {$::binconvert::IhexFileType eq "I16"} {
                log::error "binconvert: ProcessIhexLine: File mixes I16 & I32 segment offsets!"
            }
            set ::binconvert::IhexFileType "I32"
            # Upshifting address by 16 bits as we output it
            return [list "SEGADDR" [expr "0x${data}0000"] ]
        }
        05 {
            if {$::binconvert::IhexFileType eq "I16"} {
                log::error "binconvert: ProcessIhexLine: File mixes I16 & I32 segment offsets!"
            }
            set ::binconvert::IhexFileType "I32"
            return [list "STARTADDR" [expr "0x$data"] "I32" ]
        }
        default {
            set errMsg "binconvert: ProcessIhexLine: Unrecognized line type! \
                    $type not in 0-5 per spec. \nLine was: $line"
            log::error $errMsg
            error $errMsg
        }
    }
}

Changes to rawbin.tcl.

11
12
13
14
15
16
17
18



19
20
21
22
23
24
25
26






















































# DESCRIPTION:
#   rawbin.tcl is part of the binconvert package.  binconvert is a package
#   that reads & writes EEPROM memory files in multiple formats.
#   It converts the data to & from a Tcl representation as a list of
#   data segments, which is available for processing.
#
#   rawbin.tcl contains all the support procs to manage input from binary
#   files of no particular format.  It will



#
###########################################################################
#
# This package documentation is auto-generated with
# Pycco: <https://pycco-docs.github.io/pycco/>
#
# Use "pycco *filename*" to re-generate HTML documentation in ./docs .
#





























































|
>
>
>








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# DESCRIPTION:
#   rawbin.tcl is part of the binconvert package.  binconvert is a package
#   that reads & writes EEPROM memory files in multiple formats.
#   It converts the data to & from a Tcl representation as a list of
#   data segments, which is available for processing.
#
#   rawbin.tcl contains all the support procs to manage input from binary
#   files of no particular format.  It assumes a starting address of 0
#   and packs all data read into one initial segment.  When writing out
#   data, it will start at 0 or such other address as the user sets, and
#   will fill in undefined data with bytes of 0xFF or as the user sets.
#
###########################################################################
#
# This package documentation is auto-generated with
# Pycco: <https://pycco-docs.github.io/pycco/>
#
# Use "pycco *filename*" to re-generate HTML documentation in ./docs .
#

#--------------------------------------------------------------------------
## Procedures for Raw Binary Format
#
# This format is not really a format.  This is intended to be used to input
# things like memory dumps from tools to be saved in another format, or to
# write
#
#--------------------------------------------------------------------------
# <a name="ProcessRawbinLine"></a>
### ProcessRawbinLine

# *ProcessRawbinLine* is the parser for the readline proc.  Since the input
# file did not have lines, we don't expect more than one lump of data.
# Use *binary scan* to convert the whole thing to a list of byte values.
#
# N.B. that there are no checksums or CRCs, and thus no way of detecting a
# corrupted file unless the corruption makes a line not interpretable.
proc ::binconvert::ProcessRawbinLine {dataIn} {
    set addr 0
    binary scan $dataIn cu* dataL
    return [list DATA $addr $dataL]
}


#--------------------------------------------------------------------------
# <a name="WriteRawbinFile"></a>
### WriteRawbinFile

# *WriteRawbinFile* will iterate over the segments of the segment list.
#
proc ::binconvert::WriteRawbinFile {segmentList outchan {startAddr 0} {fillValue 0x255}} {
    # Scan the list for the end address.
    set maxAddr 0
    foreach {addr dataL} $segmentList {
        if {$maxAddr < ($addr + [llength $dataL])} {
            set maxAddr [expr {$addr + [llength $dataL]}]
        }
    }
    set outL [lrepeat $fillValue ]

    # We have our filled output list.  For each segment, replace the data
    # in the appropriate range with the segment data.
    foreach {addr dataL} $segmentList {
        set outL [lreplace $outL $addr [expr {$addr + [llength $dataL]}] {*}$dataL]]
    }

    # After the output list is completely filled, convert it to a binary
    # string and write it to disk.  Don't forget to set the output channel to
    # binary too, to keep line feeds from being corrupted.
    set outS [binary format c* $outL]
    chan configure $outchan -translation binary
    puts $outchan $outS
}

Changes to srec.tcl.

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
...
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
# Pycco: <https://pycco-docs.github.io/pycco/>
#
# Use "pycco *filename*" to re-generate HTML documentation in ./docs .
#


#--------------------------------------------------------------------------
### Procedures for Motorola SREC Format
#
# For details on the Motorola SREC format, see:
# <https://en.wikipedia.org/wiki/SREC_(file_format)>


#--------------------------------------------------------------------------
# <a name="ValidateSrecLine"></a>
#### ValidateSrecLine

# *ValidateSrecLine* takes a line of formatted input and parses out the fields
# with a regexp, and computes and checks the line checksum.  If the checksum
# is valid, it checks the byte count against the number of actual digits in
# the line.  If those match, it returns a list of up to three fields:
# the symbolic type of the line per the spec, the local address, and/or the
# list of data bytes, either of which may not exist depending on the type.
#
# If the parsing or checksum fail, error out - there's no real recovery from a
# truly corrupted file.
#
proc ::binconvert::ValidateSrecLine {line} {
    set matchStr {S([[:digit:]])([[:xdigit:]]{2})([[:xdigit:]]*)([[:xdigit:]]{2})}
    if {![regexp $matchStr $line -> type count payload chksum]} {
        # Some SREC implementations put in comments, though it's not in the
        # strict format.  If this is a comment, treat it as a NoOp.
        if {([string index $line 0] eq ";") || ($line eq "")} {
            log::debug "Found COMMENT"
            return {NOP {} }
        }
        # Not a comment.  Bad input data - error out of it.
        set errMsg "binconvert: ValidateSrecLine: Input file syntax error: \
                    could not parse $line (line $::binconvert::SrecLineCount)"
        log::error $errMsg
        error $errMsg
    }
    # N.B.: count is in bytes while string length is in digits.
    if {("0x$count" * 2) != ([string length $payload] + 2)} {
        set errMsg "binconvert: ValidateSrecLine: Incorrect record length! \
                    Expected [expr {$count * 2}], got\
                    [expr {[string length $payload] + 2}].\nLine was: $line"
        log::error $errMsg
        error $errMsg
    }
    set csum 0
    foreach {digit1 digit2} [lrange [split $line ""] 2 end] {
        incr csum [expr {"0x$digit1$digit2"}]
    }
    if {($csum & 0xFF) != 0xFF} {
        set errMsg "binconvert: ValidateSrecLine: line checksum fail. Computed
                    [expr {$csum & 0xFF}], expected 0xFF, line was: $line"
        log::error $errMsg
        error $errMsg
    }
    switch $type {
        0 {
            # Header
            set dataL {}
            if {[string range $payload 0 3] ne "0000"} {
                set errMsg "binconvert: ValidateSrecLine: invalid address\
                            in header. Spec requires '0000', got \
                            [string range $payload 0 3]. Line was: $line"
                log::error $errMsg
                error $errMsg
            }
            set ::binconvert::SrecLineCount 0
            foreach {digit1 digit2} [split [string range $payload 4 end] ""] {
................................................................................
            }
            incr ::binconvert::SrecLineCount
            return [list "DATA" $addr $dataL]
        }
        5 {
            # 16-bit line count
            if {$::binconvert::SrecLineCount != [expr {"0x$payload"}]} {
                set errMsg "binconvert: ValidateSrecLine: Line count does\
                            not match!  [expr {"0x$payload"}] lines expected,\
                            $::binconvert::SrecLineCount lines seen."
                log::error $errMsg
                error $errMsg
            }
            return [list "NOP" {}]
        }
        6 {
            # 24-bit line count
            if {$::binconvert::SrecLineCount != [expr {"0x$payload"}]} {
                set errMsg "binconvert: ValidateSrecLine: Line count does\
                            not match!  [expr {"0x$payload"}] lines expected,\
                            $::binconvert::SrecLineCount lines seen."
                log::error $errMsg
                error $errMsg
            }
            return [list "NOP" {}]
        }
................................................................................
            # 16-bit start address
            if {[expr {"0x$payload"}] == 0} {
                return { "EOF" {} }
            }
            return [list "STARTADDR" [expr {"0x$payload"} ] ]
        }
        default {
            set errMsg "binconvert: ValidateSrecLine: Invalid record type! \
                    $type not in 0-3 or 5-9 per spec.\nLine was: $line"
            log::error $errMsg
            error $errMsg
        }
    }
}

................................................................................
    puts $outchan $outS
}



#--------------------------------------------------------------------------
# <a name="WriteSrecSegment"></a>
##### WriteSrecSegment

# This helper proc is common to Srec file subformats.  It
# takes a segment (starting address & data, with segment offset already
# subtracted) as input along with the file *handle* (not name) and subtype,
# and writes to the file handle a sequence of correctly formatted lines, 16
# data bytes per line, until all the segment data has been written.  If the
# segment data length is not a multiple of 16 bytes, the last line will be
................................................................................
        incr count
    }
    return $count
}

#--------------------------------------------------------------------------
# <a name="makeSrecDataLine"></a>
##### makeSrecDataLine

# This helper proc is only used by *writeSrecSegment*, ensuring that data line
# formatting is only done in one place in the code.
# It returns the line as a string; it does *not* attempt to output it.
#
proc ::binconvert::makeSrecDataLine {filetype addr dataL} {
    set len [llength $dataL]
................................................................................
    }
    append outS [makeSrecLineChecksum $outS]
    return $outS
}

#--------------------------------------------------------------------------
# <a name="makeSrecLineChecksum"></a>
##### makeSrecLineChecksum

# This helper proc is common to all Srec subformats.  It takes the current
# line as a string of hex characters (starting with the type field, which is
# discarded), groups them appropriately into 2-character bytes, and sums them.
# It then computes a checksum value that is the 1's complement of the least
# significant byte of the result, and returns that as a string.
# It does *not* append it to the line; it leaves that to the caller.
#
proc ::binconvert::makeSrecLineChecksum {line} {
    set csum 0
    foreach {digit1 digit2} [lrange [split $line ""] 2 end] {
        incr csum [expr {"0x$digit1$digit2"}]
    }
# @@@ puts -nonewline [format "csum in = 0x%02X;" $csum]
    set csum [expr {~$csum & 0xFF}]
# @@@ puts [format "csum out = 0x%02X" $csum ]
    return [format "%02X" $csum]
}







|






|
|

|









|









|






|










|









|







 







|










|







 







|







 







|







 







|







 







|













<

<


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
...
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354

355

356
357
# Pycco: <https://pycco-docs.github.io/pycco/>
#
# Use "pycco *filename*" to re-generate HTML documentation in ./docs .
#


#--------------------------------------------------------------------------
## Procedures for Motorola SREC Format
#
# For details on the Motorola SREC format, see:
# <https://en.wikipedia.org/wiki/SREC_(file_format)>


#--------------------------------------------------------------------------
# <a name="ProcessSrecLine"></a>
### ProcessSrecLine

# *ProcessSrecLine* takes a line of formatted input and parses out the fields
# with a regexp, and computes and checks the line checksum.  If the checksum
# is valid, it checks the byte count against the number of actual digits in
# the line.  If those match, it returns a list of up to three fields:
# the symbolic type of the line per the spec, the local address, and/or the
# list of data bytes, either of which may not exist depending on the type.
#
# If the parsing or checksum fail, error out - there's no real recovery from a
# truly corrupted file.
#
proc ::binconvert::ProcessSrecLine {line} {
    set matchStr {S([[:digit:]])([[:xdigit:]]{2})([[:xdigit:]]*)([[:xdigit:]]{2})}
    if {![regexp $matchStr $line -> type count payload chksum]} {
        # Some SREC implementations put in comments, though it's not in the
        # strict format.  If this is a comment, treat it as a NoOp.
        if {([string index $line 0] eq ";") || ($line eq "")} {
            log::debug "Found COMMENT"
            return {NOP {} }
        }
        # Not a comment.  Bad input data - error out of it.
        set errMsg "binconvert: ProcessSrecLine: Input file syntax error: \
                    could not parse $line (line $::binconvert::SrecLineCount)"
        log::error $errMsg
        error $errMsg
    }
    # N.B.: count is in bytes while string length is in digits.
    if {("0x$count" * 2) != ([string length $payload] + 2)} {
        set errMsg "binconvert: ProcessSrecLine: Incorrect record length! \
                    Expected [expr {$count * 2}], got\
                    [expr {[string length $payload] + 2}].\nLine was: $line"
        log::error $errMsg
        error $errMsg
    }
    set csum 0
    foreach {digit1 digit2} [lrange [split $line ""] 2 end] {
        incr csum [expr {"0x$digit1$digit2"}]
    }
    if {($csum & 0xFF) != 0xFF} {
        set errMsg "binconvert: ProcessSrecLine: line checksum fail. Computed
                    [expr {$csum & 0xFF}], expected 0xFF, line was: $line"
        log::error $errMsg
        error $errMsg
    }
    switch $type {
        0 {
            # Header
            set dataL {}
            if {[string range $payload 0 3] ne "0000"} {
                set errMsg "binconvert: ProcessSrecLine: invalid address\
                            in header. Spec requires '0000', got \
                            [string range $payload 0 3]. Line was: $line"
                log::error $errMsg
                error $errMsg
            }
            set ::binconvert::SrecLineCount 0
            foreach {digit1 digit2} [split [string range $payload 4 end] ""] {
................................................................................
            }
            incr ::binconvert::SrecLineCount
            return [list "DATA" $addr $dataL]
        }
        5 {
            # 16-bit line count
            if {$::binconvert::SrecLineCount != [expr {"0x$payload"}]} {
                set errMsg "binconvert: ProcessSrecLine: Line count does\
                            not match!  [expr {"0x$payload"}] lines expected,\
                            $::binconvert::SrecLineCount lines seen."
                log::error $errMsg
                error $errMsg
            }
            return [list "NOP" {}]
        }
        6 {
            # 24-bit line count
            if {$::binconvert::SrecLineCount != [expr {"0x$payload"}]} {
                set errMsg "binconvert: ProcessSrecLine: Line count does\
                            not match!  [expr {"0x$payload"}] lines expected,\
                            $::binconvert::SrecLineCount lines seen."
                log::error $errMsg
                error $errMsg
            }
            return [list "NOP" {}]
        }
................................................................................
            # 16-bit start address
            if {[expr {"0x$payload"}] == 0} {
                return { "EOF" {} }
            }
            return [list "STARTADDR" [expr {"0x$payload"} ] ]
        }
        default {
            set errMsg "binconvert: ProcessSrecLine: Invalid record type! \
                    $type not in 0-3 or 5-9 per spec.\nLine was: $line"
            log::error $errMsg
            error $errMsg
        }
    }
}

................................................................................
    puts $outchan $outS
}



#--------------------------------------------------------------------------
# <a name="WriteSrecSegment"></a>
#### WriteSrecSegment

# This helper proc is common to Srec file subformats.  It
# takes a segment (starting address & data, with segment offset already
# subtracted) as input along with the file *handle* (not name) and subtype,
# and writes to the file handle a sequence of correctly formatted lines, 16
# data bytes per line, until all the segment data has been written.  If the
# segment data length is not a multiple of 16 bytes, the last line will be
................................................................................
        incr count
    }
    return $count
}

#--------------------------------------------------------------------------
# <a name="makeSrecDataLine"></a>
#### makeSrecDataLine

# This helper proc is only used by *writeSrecSegment*, ensuring that data line
# formatting is only done in one place in the code.
# It returns the line as a string; it does *not* attempt to output it.
#
proc ::binconvert::makeSrecDataLine {filetype addr dataL} {
    set len [llength $dataL]
................................................................................
    }
    append outS [makeSrecLineChecksum $outS]
    return $outS
}

#--------------------------------------------------------------------------
# <a name="makeSrecLineChecksum"></a>
#### makeSrecLineChecksum

# This helper proc is common to all Srec subformats.  It takes the current
# line as a string of hex characters (starting with the type field, which is
# discarded), groups them appropriately into 2-character bytes, and sums them.
# It then computes a checksum value that is the 1's complement of the least
# significant byte of the result, and returns that as a string.
# It does *not* append it to the line; it leaves that to the caller.
#
proc ::binconvert::makeSrecLineChecksum {line} {
    set csum 0
    foreach {digit1 digit2} [lrange [split $line ""] 2 end] {
        incr csum [expr {"0x$digit1$digit2"}]
    }

    set csum [expr {~$csum & 0xFF}]

    return [format "%02X" $csum]
}

Changes to titxt.tcl.

19
20
21
22
23
24
25























































































###########################################################################
#
# This package documentation is auto-generated with
# Pycco: <https://pycco-docs.github.io/pycco/>
#
# Use "pycco *filename*" to re-generate HTML documentation in ./docs .
#






























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
###########################################################################
#
# This package documentation is auto-generated with
# Pycco: <https://pycco-docs.github.io/pycco/>
#
# Use "pycco *filename*" to re-generate HTML documentation in ./docs .
#

#--------------------------------------------------------------------------
## Procedures for TI Text Format
#
# For details on the TI Text format, see
# <http://manpages.ubuntu.com/manpages/trusty/man5/srec_ti_txt.5.html>
#
#--------------------------------------------------------------------------
# <a name="ProcessTitxtLine"></a>
### ProcessTitxtLine

# *ProcessTitxtLine* is the parser for the readline proc.  Since TI-TXT is a
# very simple format, and since the line types do not have a common format,
# we don't bother using a regexp to parse it.
#
# N.B. that there are no checksums or CRCs, and thus no way of detecting a
# corrupted file unless the corruption makes a line not interpretable.
proc ::binconvert::ProcessTitxtLine {line} {
    # If the line starts with "@", it's an address.
    # Address lines are reported as segment addresses.
    if {[string range $line 0 0] eq "@"} {
        set ::binconvert::TitxtLineAddr 0
        set segAddr [expr {[format "0x%x" [string range $line 1 end]]}]
        return [list SEGADDR $segAddr]
    # If the line is "q", it's the file terminator, reported as EOF.
    } elseif {([string range $line 0 0] eq "q") && ([string length $line] == 1)} {
        return {"EOF" {} }
    # Otherwise, the line should have 1-16 two-digit hexadecimal numbers,
    # each representing one byte, separated by spaces.  Data lines keep a
    # running count of bytes processed since the last segment, to be used
    # as a line address.
    } else {
        try {
            foreach databyte [split $line " "] {
                lappend dataL [expr {[format "0x%x" $databyte] % 256}]
            }
        } on error {result} {
            set errMsg "binconvert: ValidateTitxtLine: Input file syntax error: \
                        could not parse line: $line"
            log::error $errMsg
            puts $result
            puts $::errorCode
            puts $::errorInfo
            error $errMsg
        }
        if {[llength $dataL] > 16} {
            set errMsg "binconvert: ValidateTitxtLine: Input file syntax error: \
                        data line too long (>16 bytes): $line"
            log::error $errMsg
            error $errMsg
        }
        set addr $::binconvert::TitxtLineAddr
        incr ::binconvert::TitxtLineAddr [llength $dataL]
        return [list $addr $dataL]
    }
}


#--------------------------------------------------------------------------
# <a name="WriteTitxtFile"></a>
### WriteTitxtFile

# *WriteTitxtFile* will iterate over the segments of the segment list.
#
proc ::binconvert::WriteTitxtFile {segmentList outchan} {
    foreach {addr dataL} $segmentList {
        # For each segment, it will write the address as an address line
        # (e.g., @5C00).
        puts $outchan [format "\@%x" $addr]

        # The address is followed by the data in lines of 16 bytes,
        # with any short line at the end.
        set outS ""
        foreach databyte $dataL {
            append outS [format "%02x " $databyte]
            if {[string length $outS] > 45} {
                puts $outchan [string trimright $outS]
                set outS ""
            }
        }
        if {[string length $outS] > 0} {
            puts $outchan [string trimright $outS]
        }
    }
    # After all segments are written out, it will write the "q" line and end.
    puts $outchan "q"
}