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

Overview
Comment:Updated documentation/comments.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:e5ef76b0f8dc27bc269e53040f8d550bbf216739
User & Date: erikj 2017-11-14 07:11:51
Context
2017-11-14
07:14
Deleted 0-length file that somehow got added. check-in: 7b1f1bf6fd user: erikj tags: trunk
07:11
Updated documentation/comments. check-in: e5ef76b0f8 user: erikj tags: trunk
2017-11-13
11:20
Updated comments/documentation check-in: a1d097d628 user: erikj tags: trunk
Changes

Changes to binconvert.tcl.

104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
123
124
125
126
127
128
129












130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
...
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
...
226
227
228
229
230
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
...
297
298
299
300
301
302
303

































304
305
306
307
308
309
310
...
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
    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]
................................................................................
# * s37
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.
#
proc ::binconvert::readfile {datafmt fname} {
    set resultL [list]
    set segData [list]
    set ::binconvert::IhexFileType ""
................................................................................
    # consists of a canonical tag and its associated data.
    #
    # The specification for the interfaces to the procedures are as follows:
    # the line parser must take exactly one argument, the line to be parsed.
    # It must return a list consisting of one data type token plus one or two
    # data fields appropriate to the token.  The list of supported tokens is:
    #
    # * DATA *lineAddress* *dataList*
    # * SEGADDR *segAddressOffset*
    # * HEADER *headerData*
    # * NOP {}
    # * STARTADDR *executionStartAddress* *optionalProcessorType*
    # * EOF {}
    #
    # The *readFile* level manages the segment list structure based on those
    # tags.  Format-specific consistency checks are handled in the parsers.
    foreach line $dataL {
        set lineL [{*}$parser $line]
        switch -- [lindex $lineL 0] {
            default {
................................................................................
                    set address [expr {[lindex $lineL 1] + $segAddr}]
                    set startAddress $address
                    set segData [list]
                }
                lappend segData {*}[lindex $lineL 2]
                incr address [llength [lindex $lineL 2] ]

            ##### EOF line.
            # Force end of processing.  No more lines (if any) will be
            # processed.
            }
            EOF {
                log::debug "Found EOF"
                break

            ##### Header line.
            # 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.
            #
            # N.B. that the "address" for this segment is the text
            # string "HEADER", not an actual numeric address.
            #
            # Note also that the header is specified as the first line of
            # a strictly formatted SREC file.  If other lines precede it,
            # we will emit a warning and discard any prior data, but we
            # will continue processing.
            }
            HEADER {
                log::debug "Found HEADER [lindex $lineL 1]"
                if {[llength $segData] != 0} {
                    log::warn "binconvert::readfile: Data in file before header: line $cnt."
                    log::info "binconvert::readfile: Data was $segData"
                    set segData [list]
                }
                set address "HEADER"
                set startAddress $address
                lappend segData {*}[lindex $lineL 1]

            # <a name="addrs"></a>
            ##### Segment Address line.
            # New segment offset address, where segAddr is an offset that will
            # be added to all line addresses until the next segment addr line.
            #
            # Wrap up any ongoing segment and init a new segment.
            }
            SEGADDR {
................................................................................
                log::debug "Found STARTADDR"
                if {[llength $segData] != 0} {
                    lappend resultL $startAddress $segData
                }
                set address "STARTADDR"
                set startAddress $address
                set segData [lrange $lineL 1 end]


































            ##### No-op / No segment data
            # Certain lines exist for format internal reasons (e.g., SREC
            # count records) and have no data that goes into the Segment List.
            }
            NOP {
            }
................................................................................
# in the ::binconvert:: namespace, or must provide a fully-qualified
# namespace path to their procedures.
proc ::binconvert::addparser {formatSymbol parseProcName writeProcName args} {
    set ::binconvert::Formats($formatSymbol,parser) $parseProcName
    set ::binconvert::Formats($formatSymbol,writer) $writeProcName
    set ::binconvert::Formats($formatSymbol,writeArgs) $args
}

#--------------------------------------------------------------------------
#### 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







<
<







 







>
>
>
>
>
>
>
>
>
>
>
>





|
|
|
|







 







|
|
|
|
|
|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<
<
<
<
<
<







104
105
106
107
108
109
110


111
112
113
114
115
116
117
...
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
...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
...
236
237
238
239
240
241
242


































243
244
245
246
247
248
249
...
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
...
387
388
389
390
391
392
393








394
395
396
397
398
399
400
    namespace export loglevel
    namespace ensemble create

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



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

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


#--------------------------------------------------------------------------
#### loglevel

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

# The default log setting for *binconvert* is warning or higher.
loglevel warn


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

# *readfile* accepts as  its arguments the name of an input file and a token
# designating which format to parse it as.  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.
#
proc ::binconvert::readfile {datafmt fname} {
    set resultL [list]
    set segData [list]
    set ::binconvert::IhexFileType ""
................................................................................
    # consists of a canonical tag and its associated data.
    #
    # The specification for the interfaces to the procedures are as follows:
    # the line parser must take exactly one argument, the line to be parsed.
    # It must return a list consisting of one data type token plus one or two
    # data fields appropriate to the token.  The list of supported tokens is:
    #
    # + DATA *lineAddress* *dataList*
    # + SEGADDR *segAddressOffset*
    # + HEADER *headerData*
    # + NOP {}
    # + STARTADDR *executionStartAddress* *optionalProcessorType*
    # + EOF {}
    #
    # The *readFile* level manages the segment list structure based on those
    # tags.  Format-specific consistency checks are handled in the parsers.
    foreach line $dataL {
        set lineL [{*}$parser $line]
        switch -- [lindex $lineL 0] {
            default {
................................................................................
                    set address [expr {[lindex $lineL 1] + $segAddr}]
                    set startAddress $address
                    set segData [list]
                }
                lappend segData {*}[lindex $lineL 2]
                incr address [llength [lindex $lineL 2] ]



































            ##### Segment Address line.
            # New segment offset address, where segAddr is an offset that will
            # be added to all line addresses until the next segment addr line.
            #
            # Wrap up any ongoing segment and init a new segment.
            }
            SEGADDR {
................................................................................
                log::debug "Found STARTADDR"
                if {[llength $segData] != 0} {
                    lappend resultL $startAddress $segData
                }
                set address "STARTADDR"
                set startAddress $address
                set segData [lrange $lineL 1 end]

            ##### Header line.
            # 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.
            #
            # N.B. that the "address" for this segment is the text
            # string "HEADER", not an actual numeric address.
            #
            # Note also that the header is specified as the first line of
            # a strictly formatted SREC file.  If other lines precede it,
            # we will emit a warning and discard any prior data, but we
            # will continue processing.
            }
            HEADER {
                log::debug "Found HEADER [lindex $lineL 1]"
                if {[llength $segData] != 0} {
                    log::warn "binconvert::readfile: Data in file before header: line $cnt."
                    log::info "binconvert::readfile: Data was $segData"
                    set segData [list]
                }
                set address "HEADER"
                set startAddress $address
                lappend segData {*}[lindex $lineL 1]

            ##### EOF line.
            # Force end of processing.  No more lines (if any) will be
            # processed.
            }
            EOF {
                log::debug "Found EOF"
                break

            ##### No-op / No segment data
            # Certain lines exist for format internal reasons (e.g., SREC
            # count records) and have no data that goes into the Segment List.
            }
            NOP {
            }
................................................................................
# in the ::binconvert:: namespace, or must provide a fully-qualified
# namespace path to their procedures.
proc ::binconvert::addparser {formatSymbol parseProcName writeProcName args} {
    set ::binconvert::Formats($formatSymbol,parser) $parseProcName
    set ::binconvert::Formats($formatSymbol,writer) $writeProcName
    set ::binconvert::Formats($formatSymbol,writeArgs) $args
}









#--------------------------------------------------------------------------
# <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

Changes to docs/binconvert.html.

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
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
246
247
248
249
250
...
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
...
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
...
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
374
375
376
377
378
379
...
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404

405
406
407
408






























409


410



411
412
413
414
415
416
417
418
419
420
421
422
423
424
...
439
440
441
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
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
548
549
550
551
552
553
554
555
556
557
558
...
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
...
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
    <span class="k">namespace</span> export writefile
    <span class="k">namespace</span> export addparser
    <span class="k">namespace</span> export loglevel
    <span class="k">namespace</span> ensemble create

    <span class="nv">logger</span><span class="o">::</span>init <span class="o">::</span>binconvert
    <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 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>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::readfile <span class="k">{</span><span class="nv">datafmt</span> fname<span class="k">}</span> <span class="k">{</span>
    <span class="k">set</span> resultL <span class="k">[</span><span class="nb">list</span><span class="k">]</span>
    <span class="k">set</span> segData <span class="k">[</span><span class="nb">list</span><span class="k">]</span>
................................................................................
    <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>
................................................................................
        <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 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.</p>
<p>The specification for the interfaces to the procedures are as follows:
the line parser must take exactly one argument, the line to be parsed.
................................................................................
      <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>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">}</span>
            <span class="nv">SEGADDR</span> <span class="k">{</span>
                <span class="nv">log</span><span class="o">::</span>debug <span class="s2">&quot;Found OFFSETADDR [lindex $lineL 1]&quot;</span>
                <span class="k">set</span> segAddr <span class="k">[</span><span class="nb">lindex</span> <span class="nv">$lineL</span> <span class="mi">1</span><span class="k">]</span>
                <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">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
passed along and must be dealt with in the writers.</p>
<p>N.B. that the "address" for this segment is the text
string "STARTADDR", and the data is a single address number
rather than a byte list.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">}</span>
            <span class="nv">STARTADDR</span> <span class="k">{</span>
                <span class="nv">log</span><span class="o">::</span>debug <span class="s2">&quot;Found STARTADDR&quot;</span>
                <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">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. Prepend any special writer arguments
to any extra caller args when calling the writer.</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 args<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>
................................................................................
    <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">set</span> <span class="o">::</span>binconvert::Formats<span class="k">(</span><span class="nv">$formatSymbol</span><span class="err">,</span><span class="nv">writeArgs</span><span class="k">)</span> <span class="nv">$args</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







|
<
<







 







|
<











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







 







|


|







 







|


|







 







|


|







 







|


|







 







|


|










|


|







 







|


|

|
|
|
>



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



|


|







 







|


|

<
|
>
|
<
<



|
|
<
<
<
|
<
<
<



|


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







 







|


|












|


|










|


|







 







|


|










|


|







 







|


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







134
135
136
137
138
139
140
141


142
143
144
145
146
147
148
...
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
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
...
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
...
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
...
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
360
361
362
363
364
365
366
367
368
369
370
...
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
414
415
416
...
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
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
...
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
548
549
550
551
552
553
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
586
587
588
589
590
591
592
593
594
...
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
629
630
631
632
633
634
...
665
666
667
668
669
670
671
672
673
674
675
















676
677
678
679
680
681
682
    <span class="k">namespace</span> export writefile
    <span class="k">namespace</span> export addparser
    <span class="k">namespace</span> export loglevel
    <span class="k">namespace</span> ensemble create

    <span class="nv">logger</span><span class="o">::</span>init <span class="o">::</span>binconvert
    <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></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 class='clearall'></div>
  <div class='section' id='section-9'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-9'>#</a>
      </div>
      <hr />
<h3>loglevel</h3>

    </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>A simple accessor to change the logging level of the package 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-11'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-11'>#</a>
      </div>
      <p>The default log setting for <em>binconvert</em> is warning or higher.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="nv">loglevel</span> warn</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>
      <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-13'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-13'>#</a>
      </div>
      <p><em>readfile</em> accepts as  its arguments the name of an input file and a token
designating which format to parse it as.  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>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::readfile <span class="k">{</span><span class="nv">datafmt</span> fname<span class="k">}</span> <span class="k">{</span>
    <span class="k">set</span> resultL <span class="k">[</span><span class="nb">list</span><span class="k">]</span>
    <span class="k">set</span> segData <span class="k">[</span><span class="nb">list</span><span class="k">]</span>
................................................................................
    <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-14'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-14'>#</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>
................................................................................
        <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-15'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-15'>#</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 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-16'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-16'>#</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-17'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-17'>#</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.</p>
<p>The specification for the interfaces to the procedures are as follows:
the line parser must take exactly one argument, the line to be parsed.
................................................................................
      <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-18'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-18'>#</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-19'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-19'>#</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-20'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-20'>#</a>
      </div>
      <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>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">}</span>
            <span class="nv">SEGADDR</span> <span class="k">{</span>
                <span class="nv">log</span><span class="o">::</span>debug <span class="s2">&quot;Found OFFSETADDR [lindex $lineL 1]&quot;</span>
                <span class="k">set</span> segAddr <span class="k">[</span><span class="nb">lindex</span> <span class="nv">$lineL</span> <span class="mi">1</span><span class="k">]</span>
                <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">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-21'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-21'>#</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
passed along and must be dealt with in the writers.</p>
<p>N.B. that the "address" for this segment is the text
string "STARTADDR", and the data is a single address number
rather than a byte list.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">}</span>
            <span class="nv">STARTADDR</span> <span class="k">{</span>
                <span class="nv">log</span><span class="o">::</span>debug <span class="s2">&quot;Found STARTADDR&quot;</span>
                <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">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-22'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-22'>#</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-23'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-23'>#</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-24'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-24'>#</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-25'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-25'>#</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-26'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-26'>#</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-27'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-27'>#</a>
      </div>
      <p><em>writefile</em> will examine the file format token, then call the appropriate
output format writer for that file type. Prepend any special writer arguments
to any extra caller args when calling the writer.</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 args<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-28'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-28'>#</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-29'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-29'>#</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>
................................................................................
    <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">set</span> <span class="o">::</span>binconvert::Formats<span class="k">(</span><span class="nv">$formatSymbol</span><span class="err">,</span><span class="nv">writeArgs</span><span class="k">)</span> <span class="nv">$args</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>
      <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

Changes to docs/ihex.html.

65
66
67
68
69
70
71











72
73
74
75
76
77
78
79
80
81
82
83
84
85
...
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
...
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
...
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
...
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
334
335
336
337
338
...
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
...
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
...
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
...
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
...
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
...
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
548
549
550
...
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
...
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
...
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
668
669
670
671
672
673
674
    <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">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">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="nv">$data</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="s2">&quot;0x$digit1$digit2&quot;</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;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'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-3'>#</a>
      </div>
      <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'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-4'>#</a>
      </div>
      <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="k">error</span> <span class="nv">$errMsg</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-5'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-5'>#</a>
      </div>
      <hr />
<p><a name="WriteIhexFile"></a></p>
<h2>WriteIhexFile</h2>
    </div>
    <div class='code'>
      <div class="highlight"><pre></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><em>WriteIhexFile</em> will scan the segment list, look for the largest ending
address, then call the appropriate output format writer.  (I.e., if
maxAdd &lt;= 64K, use I8hex; if maxAddr &lt;= 1M, use I16hex, else use I32hex.
If maxAdd is &gt;4 GB, error out... and wtf are you doing using this format
with that data anyway?!)  If it finds a STARTADDR segment statement with,
an I16 or I32 format tag, it will immediately declare the format to match
................................................................................
    <span class="k">set</span> formatter <span class="s2">&quot;WriteI${bits}File&quot;</span>
    <span class="nv">log</span><span class="o">::</span>info <span class="s2">&quot;Formatting output file as I${bits}hex file...&quot;</span>
    <span class="nv">tailcall</span> <span class="nv">$formatter</span> <span class="nv">$segmentList</span> <span class="nv">$outchan</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>
      <hr />
<p><a name="WriteI8File"></a></p>
<h3>WriteI8File</h3>
    </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>I8hex format uses no segments; addresses are verbatim
since they can by definition fit in the 16-bit field of the line.  We
expect to only need DATA and EOF lines.</p>
<p>Start by checking the input segment list to make sure we can use
the format.</p>
    </div>
................................................................................
            <span class="k">error</span> <span class="nv">$errMsg</span>
        <span class="k">}</span>
        <span class="nb">lappend</span> outSegL <span class="nv">$addr</span> <span class="nv">$dataL</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>For each segment, write the data starting at the start address</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">$outSegL</span> <span class="k">{</span>
        <span class="nv">writeIhexSegment</span> <span class="nv">$outchan</span> <span class="nv">$addr</span> <span class="nv">$dataL</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>Finish by writing the EOF marker</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="nb">puts</span> <span class="nv">$outchan</span> <span class="s2">&quot;:00000001FF&quot;</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>
      <hr />
<p><a name="WriteI16File"></a></p>
<h3>WriteI16File</h3>
    </div>
    <div class='code'>
      <div class="highlight"><pre></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>I16hex format uses "real mode" segments, where 16-bit
segment address is shifted up 4 and added to all other addresses in the
segment.</p>
<p>Start by checking the input segment list to make sure we can use
the format. We will also need to examine the segment data and split any
segments that (a) are longer than 64K or (b) cross a 64K boundary
(not strictly necessary in-spec, but a good idea).
Actually, if a segment is too large it's guaranteed to cross a boundary,
................................................................................
        <span class="k">}</span> <span class="k">else</span> <span class="k">{</span>
            <span class="nb">lappend</span> outSegL <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-13'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-13'>#</a>
      </div>
      <p>For each segment, write the data starting at the start address
<em>after</em> subtracting off the segment address offset.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">set</span> lastSeg <span class="o">-</span><span class="mi">1</span>
    <span class="k">foreach</span> <span class="k">{</span><span class="nv">addr</span> dataL<span class="k">}</span> <span class="nv">$outSegL</span> <span class="k">{</span>
................................................................................
            <span class="k">continue</span>
        <span class="k">}</span>
        <span class="k">set</span> segAddr <span class="k">[expr</span> <span class="k">{</span><span class="nv">$addr</span> <span class="o">&amp;</span> <span class="nv">0xF0000</span><span class="k">}]</span>
        <span class="k">set</span> startAddr <span class="k">[expr</span> <span class="k">{</span><span class="nv">$addr</span> <span class="nv">-</span> <span class="nv">$segAddr</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>
      <p>If we crossed a segment boundary, update &amp; output a new segAddr.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>        <span class="k">if</span> <span class="k">{</span><span class="nv">$segAddr</span> <span class="o">!=</span> <span class="nv">$lastSeg</span><span class="k">}</span> <span class="k">{</span>
            <span class="k">set</span> outS <span class="k">[</span><span class="nb">format</span> <span class="s2">&quot;:02000002%04X&quot;</span> <span class="k">[expr</span> <span class="k">{</span><span class="nv">$segAddr</span> <span class="o">&gt;&gt;</span> <span class="nv">4</span><span class="k">}]</span> <span class="k">]</span>
            <span class="nb">append</span> outS <span class="k">[</span><span class="nv">makeIhexLineChecksum</span> <span class="nv">$outS</span><span class="k">]</span>
................................................................................
            <span class="k">set</span> lastSeg <span class="nv">$segAddr</span>
        <span class="k">}</span>
        <span class="nv">writeIhexSegment</span> <span class="nv">$outchan</span> <span class="nv">$startAddr</span> <span class="nv">$dataL</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>All segments processed.  Write EOF marker.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="nb">puts</span> <span class="nv">$outchan</span> <span class="s2">&quot;:00000001FF&quot;</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>
      <hr />
<p><a name="WriteI32File"></a></p>
<h3>WriteI32File</h3>
    </div>
    <div class='code'>
      <div class="highlight"><pre></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>
      <p>I32hex format uses extended linear addressing, where the 16-bit segment
address forms the upper 16 bits of the 32 bit address, and is added to
the 16-bit line address to form the full 32-bit byte address.  I32hex
segments must break on <em>all</em> 64K boundaries, and <em>only</em> on 64K boundaries.</p>
<p>Start by checking the input segment list to make sure we can use
the format. We will also need to examine the segment data and split any
................................................................................
        <span class="k">}</span> <span class="k">else</span> <span class="k">{</span>
            <span class="nb">lappend</span> outSegL <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-18'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-18'>#</a>
      </div>
      <p>For each segment, write the data starting at the start address
<em>after</em> subtracting off the segment address offset.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">set</span> lastSeg <span class="o">-</span><span class="mi">1</span>
    <span class="k">foreach</span> <span class="k">{</span><span class="nv">addr</span> dataL<span class="k">}</span> <span class="nv">$outSegL</span> <span class="k">{</span>
................................................................................
            <span class="k">continue</span>
        <span class="k">}</span>
        <span class="k">set</span> segAddr <span class="k">[expr</span> <span class="k">{</span><span class="nv">$addr</span> <span class="o">&amp;</span> <span class="nv">0xFFFF0000</span><span class="k">}]</span>
        <span class="k">set</span> startAddr <span class="k">[expr</span> <span class="k">{</span><span class="nv">$addr</span> <span class="nv">-</span> <span class="nv">$segAddr</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>If we crossed a segment boundary, update &amp; output a new segAddr.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>        <span class="k">if</span> <span class="k">{</span><span class="nv">$segAddr</span> <span class="o">!=</span> <span class="nv">$lastSeg</span><span class="k">}</span> <span class="k">{</span>
            <span class="k">set</span> outS <span class="k">[</span><span class="nb">format</span> <span class="s2">&quot;:02000004%04X&quot;</span> <span class="k">[expr</span> <span class="k">{</span><span class="nv">$segAddr</span> <span class="o">&gt;&gt;</span> <span class="nv">16</span><span class="k">}]</span> <span class="k">]</span>
            <span class="nb">append</span> outS <span class="k">[</span><span class="nv">makeIhexLineChecksum</span> <span class="nv">$outS</span><span class="k">]</span>
................................................................................
            <span class="k">set</span> lastSeg <span class="nv">$segAddr</span>
        <span class="k">}</span>
        <span class="nv">writeIhexSegment</span> <span class="nv">$outchan</span> <span class="nv">$startAddr</span> <span class="nv">$dataL</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>
      <p>All segments processed.  Write EOF marker.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="nb">puts</span> <span class="nv">$outchan</span> <span class="s2">&quot;:00000001FF&quot;</span>
<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>
      <hr />
<p><a name="splitSegment"></a></p>
<h4>splitSegment</h4>
    </div>
    <div class='code'>
      <div class="highlight"><pre></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>This helper proc is used by <em>WriteI16File</em> and <em>WriteI32File</em>.  It takes
as input the address &amp; data list of a segment that's too long or crosses
a 64K boundary, and breaks it into multiple segments across all 64K
boundaries.</p>
<p>It returns a new list of segments, formatted as a segment list per above.</p>
    </div>
................................................................................
        <span class="k">set</span> addr <span class="nv">$boundary</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="writeIhexSegment"></a></p>
<h4>writeIhexSegment</h4>
    </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>This helper proc is common to Ihex file subformats.  It
takes a segment (starting address &amp; data, with segment offset already
subtracted) as input along with the file <em>handle</em> (not name), 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 the short line.</p>
................................................................................
            <span class="nb">incr</span> addr <span class="k">[</span><span class="nb">llength</span> <span class="nv">$lineData</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-25'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-25'>#</a>
      </div>
      <hr />
<p><a name="makeIhexDataLine"></a></p>
<h4>makeIhexDataLine</h4>
    </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>This helper proc is only used by <em>writeIhexSegment</em>, ensuring that data line
formatting is only done in one place in the code.
It returns the line as a string; it does <em>not</em> attempt to output it.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::makeIhexDataLine <span class="k">{</span><span class="nv">addr</span> dataL<span class="k">}</span> <span class="k">{</span>
................................................................................
    <span class="k">}</span>
    <span class="nb">append</span> outS <span class="k">[</span><span class="nv">makeIhexLineChecksum</span> <span class="nv">$outS</span><span class="k">]</span>
    <span class="k">return</span> <span class="nv">$outS</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 />
<p><a name="makeIhexLineChecksum"></a></p>
<h4>makeIhexLineChecksum</h4>
    </div>
    <div class='code'>
      <div class="highlight"><pre></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>
      <p>This helper proc is common to all Ihex subformats.  It takes the current
line as a string of hex characters (starting with a colon, which is
discarded), groups them appropriately into 2-character bytes, and sums them.
It then computes a checksum value that will make the complete line sum to 0
and returns that as a string.  It does <em>not</em> append it to the line; it leaves
that to the caller.</p>







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





|







 







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



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

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








|


|




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





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








|


|




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







 







|


|










|


|







 







|


|










|


|







 







|


|










|


|









|


|










|


|

|







 







|


|







 







|


|







 







|


|









|


|










|


|







 







|


|







 







|


|







 







|


|









|


|










|


|







 







|


|










|


|







 







|


|










|


|







 







|


|










|


|







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
...
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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
...
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
...
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
...
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
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
414
415
416
417
418
...
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
...
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
...
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
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
...
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
...
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
...
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
629
630
...
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
668
669
670
671
672
673
...
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
...
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-2'>#</a>
      </div>
      <hr />
<p><a name="ProcessIhexLine"></a></p>
<h3>ProcessIhexLine</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>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 output 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">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></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>Base Data record</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>            <span class="k">set</span> dataL <span class="k">{}</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="nv">$data</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="s2">&quot;0x$digit1$digit2&quot;</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;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></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>Last line of the file is a terminator record</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>        <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></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>8086-style "real-mode" segment address:  upshifted 4 bits by
the processor and added to the base address.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>        <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-7'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-7'>#</a>
      </div>
      <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></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>8086-style execution address.  upper 16 bits are loaded into the
CS register; lower 16 bits into the IP register.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>        <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></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>386+ style address: segment is upper 16 bits of 32-bit address,
line address is lower 16 bits.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>        <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-10'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-10'>#</a>
      </div>
      <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></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>
      <p>386+ style execution address:  address is loaded into EIP.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>        <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="k">error</span> <span class="nv">$errMsg</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-12'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-12'>#</a>
      </div>
      <hr />
<p><a name="WriteIhexFile"></a></p>
<h2>WriteIhexFile</h2>
    </div>
    <div class='code'>
      <div class="highlight"><pre></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><em>WriteIhexFile</em> will scan the segment list, look for the largest ending
address, then call the appropriate output format writer.  (I.e., if
maxAdd &lt;= 64K, use I8hex; if maxAddr &lt;= 1M, use I16hex, else use I32hex.
If maxAdd is &gt;4 GB, error out... and wtf are you doing using this format
with that data anyway?!)  If it finds a STARTADDR segment statement with,
an I16 or I32 format tag, it will immediately declare the format to match
................................................................................
    <span class="k">set</span> formatter <span class="s2">&quot;WriteI${bits}File&quot;</span>
    <span class="nv">log</span><span class="o">::</span>info <span class="s2">&quot;Formatting output file as I${bits}hex file...&quot;</span>
    <span class="nv">tailcall</span> <span class="nv">$formatter</span> <span class="nv">$segmentList</span> <span class="nv">$outchan</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>
      <hr />
<p><a name="WriteI8File"></a></p>
<h3>WriteI8File</h3>
    </div>
    <div class='code'>
      <div class="highlight"><pre></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>I8hex format uses no segments; addresses are verbatim
since they can by definition fit in the 16-bit field of the line.  We
expect to only need DATA and EOF lines.</p>
<p>Start by checking the input segment list to make sure we can use
the format.</p>
    </div>
................................................................................
            <span class="k">error</span> <span class="nv">$errMsg</span>
        <span class="k">}</span>
        <span class="nb">lappend</span> outSegL <span class="nv">$addr</span> <span class="nv">$dataL</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>For each segment, write the data starting at the start address</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">$outSegL</span> <span class="k">{</span>
        <span class="nv">writeIhexSegment</span> <span class="nv">$outchan</span> <span class="nv">$addr</span> <span class="nv">$dataL</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>
      <p>Finish by writing the EOF marker</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="nb">puts</span> <span class="nv">$outchan</span> <span class="s2">&quot;:00000001FF&quot;</span>
<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>
      <hr />
<p><a name="WriteI16File"></a></p>
<h3>WriteI16File</h3>
    </div>
    <div class='code'>
      <div class="highlight"><pre></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>I16hex format uses 8086-style "real mode" segments, where 16-bit
segment address is shifted up 4 and added to all other addresses in the
segment.</p>
<p>Start by checking the input segment list to make sure we can use
the format. We will also need to examine the segment data and split any
segments that (a) are longer than 64K or (b) cross a 64K boundary
(not strictly necessary in-spec, but a good idea).
Actually, if a segment is too large it's guaranteed to cross a boundary,
................................................................................
        <span class="k">}</span> <span class="k">else</span> <span class="k">{</span>
            <span class="nb">lappend</span> outSegL <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-20'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-20'>#</a>
      </div>
      <p>For each segment, write the data starting at the start address
<em>after</em> subtracting off the segment address offset.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">set</span> lastSeg <span class="o">-</span><span class="mi">1</span>
    <span class="k">foreach</span> <span class="k">{</span><span class="nv">addr</span> dataL<span class="k">}</span> <span class="nv">$outSegL</span> <span class="k">{</span>
................................................................................
            <span class="k">continue</span>
        <span class="k">}</span>
        <span class="k">set</span> segAddr <span class="k">[expr</span> <span class="k">{</span><span class="nv">$addr</span> <span class="o">&amp;</span> <span class="nv">0xF0000</span><span class="k">}]</span>
        <span class="k">set</span> startAddr <span class="k">[expr</span> <span class="k">{</span><span class="nv">$addr</span> <span class="nv">-</span> <span class="nv">$segAddr</span><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>
      <p>If we crossed a segment boundary, update &amp; output a new segAddr.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>        <span class="k">if</span> <span class="k">{</span><span class="nv">$segAddr</span> <span class="o">!=</span> <span class="nv">$lastSeg</span><span class="k">}</span> <span class="k">{</span>
            <span class="k">set</span> outS <span class="k">[</span><span class="nb">format</span> <span class="s2">&quot;:02000002%04X&quot;</span> <span class="k">[expr</span> <span class="k">{</span><span class="nv">$segAddr</span> <span class="o">&gt;&gt;</span> <span class="nv">4</span><span class="k">}]</span> <span class="k">]</span>
            <span class="nb">append</span> outS <span class="k">[</span><span class="nv">makeIhexLineChecksum</span> <span class="nv">$outS</span><span class="k">]</span>
................................................................................
            <span class="k">set</span> lastSeg <span class="nv">$segAddr</span>
        <span class="k">}</span>
        <span class="nv">writeIhexSegment</span> <span class="nv">$outchan</span> <span class="nv">$startAddr</span> <span class="nv">$dataL</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>All segments processed.  Write EOF marker.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="nb">puts</span> <span class="nv">$outchan</span> <span class="s2">&quot;:00000001FF&quot;</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="WriteI32File"></a></p>
<h3>WriteI32File</h3>
    </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>I32hex format uses extended linear addressing, where the 16-bit segment
address forms the upper 16 bits of the 32 bit address, and is added to
the 16-bit line address to form the full 32-bit byte address.  I32hex
segments must break on <em>all</em> 64K boundaries, and <em>only</em> on 64K boundaries.</p>
<p>Start by checking the input segment list to make sure we can use
the format. We will also need to examine the segment data and split any
................................................................................
        <span class="k">}</span> <span class="k">else</span> <span class="k">{</span>
            <span class="nb">lappend</span> outSegL <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-25'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-25'>#</a>
      </div>
      <p>For each segment, write the data starting at the start address
<em>after</em> subtracting off the segment address offset.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="k">set</span> lastSeg <span class="o">-</span><span class="mi">1</span>
    <span class="k">foreach</span> <span class="k">{</span><span class="nv">addr</span> dataL<span class="k">}</span> <span class="nv">$outSegL</span> <span class="k">{</span>
................................................................................
            <span class="k">continue</span>
        <span class="k">}</span>
        <span class="k">set</span> segAddr <span class="k">[expr</span> <span class="k">{</span><span class="nv">$addr</span> <span class="o">&amp;</span> <span class="nv">0xFFFF0000</span><span class="k">}]</span>
        <span class="k">set</span> startAddr <span class="k">[expr</span> <span class="k">{</span><span class="nv">$addr</span> <span class="nv">-</span> <span class="nv">$segAddr</span><span class="k">}]</span></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>If we crossed a segment boundary, update &amp; output a new segAddr.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>        <span class="k">if</span> <span class="k">{</span><span class="nv">$segAddr</span> <span class="o">!=</span> <span class="nv">$lastSeg</span><span class="k">}</span> <span class="k">{</span>
            <span class="k">set</span> outS <span class="k">[</span><span class="nb">format</span> <span class="s2">&quot;:02000004%04X&quot;</span> <span class="k">[expr</span> <span class="k">{</span><span class="nv">$segAddr</span> <span class="o">&gt;&gt;</span> <span class="nv">16</span><span class="k">}]</span> <span class="k">]</span>
            <span class="nb">append</span> outS <span class="k">[</span><span class="nv">makeIhexLineChecksum</span> <span class="nv">$outS</span><span class="k">]</span>
................................................................................
            <span class="k">set</span> lastSeg <span class="nv">$segAddr</span>
        <span class="k">}</span>
        <span class="nv">writeIhexSegment</span> <span class="nv">$outchan</span> <span class="nv">$startAddr</span> <span class="nv">$dataL</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>
      <p>All segments processed.  Write EOF marker.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre>    <span class="nb">puts</span> <span class="nv">$outchan</span> <span class="s2">&quot;:00000001FF&quot;</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="splitSegment"></a></p>
<h4>splitSegment</h4>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-29'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-29'>#</a>
      </div>
      <p>This helper proc is used by <em>WriteI16File</em> and <em>WriteI32File</em>.  It takes
as input the address &amp; data list of a segment that's too long or crosses
a 64K boundary, and breaks it into multiple segments across all 64K
boundaries.</p>
<p>It returns a new list of segments, formatted as a segment list per above.</p>
    </div>
................................................................................
        <span class="k">set</span> addr <span class="nv">$boundary</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-30'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-30'>#</a>
      </div>
      <hr />
<p><a name="writeIhexSegment"></a></p>
<h4>writeIhexSegment</h4>
    </div>
    <div class='code'>
      <div class="highlight"><pre></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>This helper proc is common to Ihex file subformats.  It
takes a segment (starting address &amp; data, with segment offset already
subtracted) as input along with the file <em>handle</em> (not name), 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 the short line.</p>
................................................................................
            <span class="nb">incr</span> addr <span class="k">[</span><span class="nb">llength</span> <span class="nv">$lineData</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-32'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-32'>#</a>
      </div>
      <hr />
<p><a name="makeIhexDataLine"></a></p>
<h4>makeIhexDataLine</h4>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-33'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-33'>#</a>
      </div>
      <p>This helper proc is only used by <em>writeIhexSegment</em>, ensuring that data line
formatting is only done in one place in the code.
It returns the line as a string; it does <em>not</em> attempt to output it.</p>
    </div>
    <div class='code'>
      <div class="highlight"><pre><span class="k">proc</span> <span class="o">::</span>binconvert::makeIhexDataLine <span class="k">{</span><span class="nv">addr</span> dataL<span class="k">}</span> <span class="k">{</span>
................................................................................
    <span class="k">}</span>
    <span class="nb">append</span> outS <span class="k">[</span><span class="nv">makeIhexLineChecksum</span> <span class="nv">$outS</span><span class="k">]</span>
    <span class="k">return</span> <span class="nv">$outS</span>
<span class="k">}</span></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-34'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-34'>#</a>
      </div>
      <hr />
<p><a name="makeIhexLineChecksum"></a></p>
<h4>makeIhexLineChecksum</h4>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>
  </div>
  <div class='clearall'></div>
  <div class='section' id='section-35'>
    <div class='docs'>
      <div class='octowrap'>
        <a class='octothorpe' href='#section-35'>#</a>
      </div>
      <p>This helper proc is common to all Ihex subformats.  It takes the current
line as a string of hex characters (starting with a colon, which is
discarded), groups them appropriately into 2-character bytes, and sums them.
It then computes a checksum value that will make the complete line sum to 0
and returns that as a string.  It does <em>not</em> append it to the line; it leaves
that to the caller.</p>

Changes to docs/rawbin.html.

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  <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 binary data to output channels that expect it.</p>
<hr />
<p><a name="ProcessRawbinLine"></a></p>
<h2>ProcessRawbinLine</h2>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>







|
|
|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  <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 driver is intended to be used
to input flat binary dumps, e.g. memory dumps, to be saved in another format,
or to write binary data to output channels that expect raw binary images.</p>
<hr />
<p><a name="ProcessRawbinLine"></a></p>
<h2>ProcessRawbinLine</h2>
    </div>
    <div class='code'>
      <div class="highlight"><pre></pre></div>
    </div>

Changes to docs/titxt.html.

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
...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  </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>
................................................................................
  </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>







|












|













|
>







 







|











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
...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  </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> iterates 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, 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.  Each byte is represented by
two hex digits, separated by a space.</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>
................................................................................
  </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, 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.

37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
..
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
...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#
# 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"
................................................................................
        set errMsg "binconvert: ProcessIhexLine: line checksum fail: computed $csum,\
                    expected 0, line was: $line"
        log::error $errMsg
        error $errMsg
    }
    switch $type {
        00 {

            set dataL {}
            foreach {digit1 digit2} [split $data ""] {
                lappend dataL [expr {"0x$digit1$digit2"}]
            }
            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" ]
................................................................................
}


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

# I16hex format uses "real mode" segments, where 16-bit
# segment address is shifted up 4 and added to all other addresses in the
# segment.
#
# Start by checking the input segment list to make sure we can use
# the format. We will also need to examine the segment data and split any
# segments that (a) are longer than 64K or (b) cross a 64K boundary
# (not strictly necessary in-spec, but a good idea).







>







|







 







>





>



>
>








>
>







>
>








>







 







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
..
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
...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#
# 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 output 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"
................................................................................
        set errMsg "binconvert: ProcessIhexLine: line checksum fail: computed $csum,\
                    expected 0, line was: $line"
        log::error $errMsg
        error $errMsg
    }
    switch $type {
        00 {
        # Base Data record
            set dataL {}
            foreach {digit1 digit2} [split $data ""] {
                lappend dataL [expr {"0x$digit1$digit2"}]
            }
            return [list "DATA" [expr "0x$addr"] $dataL]
        # Last line of the file is a terminator record
        }
        01 {
            return {"EOF" {} }
        # 8086-style "real-mode" segment address:  upshifted 4 bits by
        # the processor and added to the base address.
        }
        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"] ]
        # 8086-style execution address.  upper 16 bits are loaded into the
        # CS register; lower 16 bits into the IP register.
        }
        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" ]
        # 386+ style address: segment is upper 16 bits of 32-bit address,
        # line address is lower 16 bits.
        }
        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"] ]
        # 386+ style execution address:  address is loaded into EIP.
        }
        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" ]
................................................................................
}


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

# I16hex format uses 8086-style "real mode" segments, where 16-bit
# segment address is shifted up 4 and added to all other addresses in the
# segment.
#
# Start by checking the input segment list to make sure we can use
# the format. We will also need to examine the segment data and split any
# segments that (a) are longer than 64K or (b) cross a 64K boundary
# (not strictly necessary in-spec, but a good idea).

Changes to rawbin.tcl.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#
# 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 binary data to output channels that expect it.
#
#--------------------------------------------------------------------------
# <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.







|
|
|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#
# Use "pycco *filename*" to re-generate HTML documentation in ./docs .
#

#--------------------------------------------------------------------------
## Procedures for Raw Binary Format
#
# This format is not really a format.  This driver is intended to be used
# to input flat binary dumps, e.g. memory dumps, to be saved in another format,
# or to write binary data to output channels that expect raw binary images.
#
#--------------------------------------------------------------------------
# <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.

Changes to titxt.tcl.

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
}


#--------------------------------------------------------------------------
# <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"
}







|



|




|
>












|


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
}


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

# *WriteTitxtFile* iterates over the segments of the segment list.
#
proc ::binconvert::WriteTitxtFile {segmentList outchan} {
    foreach {addr dataL} $segmentList {
        # For each segment, 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.  Each byte is represented by
        # two hex digits, separated by a space.
        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, write the "q" line and end.
    puts $outchan "q"
}