summaryrefslogtreecommitdiff
path: root/lib/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler')
-rw-r--r--[-rwxr-xr-x]lib/compiler/assembler.tcl71
-rw-r--r--[-rwxr-xr-x]lib/compiler/codelisting.tcl210
-rw-r--r--[-rwxr-xr-x]lib/compiler/compiler.tcl248
-rw-r--r--[-rwxr-xr-x]lib/compiler/compilerconsts.tcl44
-rw-r--r--[-rwxr-xr-x]lib/compiler/disassembler.tcl149
-rw-r--r--[-rwxr-xr-x]lib/compiler/external_compiler.tcl220
-rw-r--r--[-rwxr-xr-x]lib/compiler/preprocessor.tcl1564
7 files changed, 1467 insertions, 1039 deletions
diff --git a/lib/compiler/assembler.tcl b/lib/compiler/assembler.tcl
index 5c41a28..17e5244 100755..100644
--- a/lib/compiler/assembler.tcl
+++ b/lib/compiler/assembler.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,6 +21,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _ASSEMBLER_TCL ] } {
+set _ASSEMBLER_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# DESCRIPTION
# Coverts precompiled source code to IHEX 8 format.
@@ -43,7 +48,7 @@
# ...
# hash - Hexadecimal MD5 hash of source code
# file - Filename of source code
-# filenum - File number (begining from 0)
+# filenum - File number (beginning from 0)
# line - Number of line in source code
# address - Code address
# code - Processor code
@@ -78,7 +83,7 @@ namespace eval assembler {
variable offset ;# Current address
variable data_len ;# Data length (for creating IHEX records)
variable data_field ;# Data field (for creating IHEX records)
- variable address ;# Address of begining of IHEX data field
+ variable address ;# Address of beginning of IHEX data field
variable operands ;# List of operand codes
variable opcode ;# OP code of the current instruction
variable bin_len ;# Lenght of binary data
@@ -106,7 +111,7 @@ namespace eval assembler {
variable lineNumber 0 ;# Number of line currently beeing parsed
variable opcode ;# OP code of the current instruction
variable operands ;# List of operand codes
- variable address ;# Address of begining of IHEX data field
+ variable address ;# Address of beginning of IHEX data field
variable opr_types ;# List of operand types
variable offset 0 ;# Current address
variable data_len 0 ;# Data length (for creating IHEX records)
@@ -137,7 +142,7 @@ namespace eval assembler {
foreach filename $included_files {
if {[catch {
append adf [::md5::md5 -hex -file $filename]
- } result]} {
+ } result]} then {
append adf 0
CompilationError [mc "File access error:\n%s" $result]
}
@@ -152,7 +157,9 @@ namespace eval assembler {
foreach line $code {
# Update GUI after each 25 iterations
- if {[expr {$idx % 25}] == 0} ${Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 25}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"]
free_resources
@@ -179,6 +186,7 @@ namespace eval assembler {
if {$opcode == { }} {
set opcode 32
}
+
set opcode [format %X $opcode]
set digits [string length $opcode]
if {$digits < 2} {
@@ -189,7 +197,7 @@ namespace eval assembler {
}
set nolist 1
- } {
+ } else {
# Check for instruction existence
if {[notAnInstruction $instruction]} {continue}
@@ -206,7 +214,7 @@ namespace eval assembler {
set offset $address
}
- # If data length overlaps 255 or adress is too high -> flush data buffer
+ # If data length overlaps 255 or address is too high -> flush data buffer
if {($pointer < $address) || (($data_len + $len) > ${::Compiler::Settings::max_ihex_rec_length})} {
write_bin
write_hex
@@ -214,7 +222,7 @@ namespace eval assembler {
set offset $address
set pointer $address
- # Unexpected adress
+ # Unexpected address
} elseif {$pointer > $address} {
CompilationError [mc "Invalid address at %s" 0x[format %X $address]]
set pointer $address
@@ -231,7 +239,7 @@ namespace eval assembler {
# Translate operands to 16|12|8-bit hex
set operands [oprs2hex]
- # Adjust inctruction OP code acording to the OP code mask and operands
+ # Adjust instruction OP code according to the OP code mask and operands
if {$mask != 0} {
# Determinate length of the first operand
set mask_bin [hex2binlist $mask]
@@ -259,12 +267,12 @@ namespace eval assembler {
set operand0 [string range $operand0 $opr_len end]
# Adjust OP code
- set idx 0
+ set op_idx 0
foreach mask_bit $mask_bin {
if {$mask_bit} {
- set opcode [lreplace $opcode $idx $idx [lindex $opcode_opr $idx]]
+ set opcode [lreplace $opcode $op_idx $op_idx [lindex $opcode_opr $op_idx]]
}
- incr idx
+ incr op_idx
}
# Finalize
@@ -290,7 +298,7 @@ namespace eval assembler {
append opcode [lindex $operands 1]
append opcode [lindex $operands 0]
# Other instructions
- } {
+ } else {
foreach opr $operands {
append opcode $opr
}
@@ -308,12 +316,13 @@ namespace eval assembler {
write_hex
if {${::Compiler::Settings::OBJECT}} {
append hex {:00000001FF}
+ append hex "\n"
}
# Return result
if {$error_count} {
return 0
- } {
+ } else {
return 1
}
}
@@ -327,7 +336,8 @@ namespace eval assembler {
data_field address operands
opcode bin_len error_count
fileNumber
- } {
+ } \
+ {
set ::assembler::$var {}
}
}
@@ -355,7 +365,7 @@ namespace eval assembler {
variable adf ;# Output simulator data
variable fileNumber ;# File number
variable lineNumber ;# Number of line currently beeing parsed
- variable address ;# Address of begining of IHEX data field
+ variable address ;# Address of beginning of IHEX data field
variable opcode ;# OP code of the current instruction
variable operands ;# List of operand codes
@@ -370,12 +380,12 @@ namespace eval assembler {
lappend new_code [expr "0x[lindex $operands 1]"]
lappend new_code [expr "0x[lindex $operands 0]"]
# Other instructions
- } {
+ } else {
foreach hex $operands {
if {[string length $hex] == 4} {
lappend new_code [expr "0x[string range $hex 0 1]"]
lappend new_code [expr "0x[string range $hex 2 3]"]
- } {
+ } else {
lappend new_code [expr "0x$hex"]
}
}
@@ -409,7 +419,7 @@ namespace eval assembler {
# Write binary data
for {set i 0; set j 1} {$i < $data_len} {incr i 2; incr j 2} {
set hex [string range $data_field $i $j]
- append bin [subst "\\x$hex"]
+ append bin [subst -nocommands "\\x$hex"]
incr bin_len
}
}
@@ -480,13 +490,18 @@ namespace eval assembler {
# Check for validity of the given operand
set opr [string trimleft $opr {#@/}]
- if {![regexp {^\d+$} $opr]} {
+ if {![string is digit -strict $opr]} {
CompilationError [mc "Invalid operand: '%s'" $opr]
break
}
# Convert to hexadecimal string
- set opr [format %X $opr]
+ set opr [string trimleft $opr 0]
+ if {$opr == {}} {
+ set opr 0
+ } else {
+ set opr [format %X $opr]
+ }
# Adjust length
set opr_len [string length $opr]
@@ -525,7 +540,7 @@ namespace eval assembler {
variable opr_types ;# List of operand types
# Iterate over operands definitions
- foreach definition [lindex $CompilerConsts::InstructionDefinition($instruction) 1] {
+ foreach definition [lindex $::CompilerConsts::InstructionDefinition($instruction) 1] {
# Determinate operand types
set opr_list [lindex $definition 0]
@@ -585,11 +600,15 @@ namespace eval assembler {
if {${::Compiler::Settings::WARNING_LEVEL} < 3} {
if {${::Compiler::Settings::NOCOLOR}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
- [::Compiler::msgc {EL}][mc "Compilation error at line %s: %s" "${lineNumber}${filename}" $errorInfo]
- } {
+ [::Compiler::msgc {EL}][mc "Compilation error at %s: %s" "${lineNumber}${filename}" $errorInfo]
+ } else {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
- [mc "\033\[31;1mCompilation error at line \033\[31;1;4m%s\033\[m%s: %s" $lineNumber $filename $errorInfo]
+ [mc "\033\[31;1mCompilation error at \033\[31;1;4m%s\033\[m%s: %s" $lineNumber $filename $errorInfo]
}
}
}
}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/compiler/codelisting.tcl b/lib/compiler/codelisting.tcl
index 1940dc3..a760d4c 100755..100644
--- a/lib/compiler/codelisting.tcl
+++ b/lib/compiler/codelisting.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,6 +21,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _CODELISTING_TCL ] } {
+set _CODELISTING_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# DESCRIPTION
# Hepler namespace to generate code listing.
@@ -68,42 +73,42 @@ namespace eval CodeListing {
set pageLines 0
# Validate compiler settings
- if {${Compiler::Settings::PAGELENGTH} < 5} {
+ if {${::Compiler::Settings::PAGELENGTH} < 5} {
set Compiler::Settings::PAGELENGTH 5
- } elseif {${Compiler::Settings::PAGELENGTH} == 0} {
+ } elseif {${::Compiler::Settings::PAGELENGTH} == 0} {
set Compiler::Settings::PAGING 0
}
- if {${Compiler::Settings::PAGEWIDTH} < 68} {
+ if {${::Compiler::Settings::PAGEWIDTH} < 68} {
set Compiler::Settings::PAGEWIDTH 68
- } elseif {${Compiler::Settings::PAGEWIDTH} == 0} {
+ } elseif {${::Compiler::Settings::PAGEWIDTH} == 0} {
set Compiler::Settings::PAGEWIDTH 116
}
# Create page header
- set header ${Compiler::Settings::INPUT_FILE_NAME}
- set len [string length ${Compiler::Settings::INPUT_FILE_NAME}]
+ set header ${::Compiler::Settings::INPUT_FILE_NAME}
+ set len [string length ${::Compiler::Settings::INPUT_FILE_NAME}]
if {$len < 15} {
append header [string repeat { } [expr {15 - $len}]]
}
- append header { } ${Compiler::Settings::TITLE}
+ append header { } ${::Compiler::Settings::TITLE}
set len [string length $header]
incr len 23
# Adjust page header width
- if {$len > ${Compiler::Settings::PAGEWIDTH}} {
- set header [string range $header 0 [expr {${Compiler::Settings::PAGEWIDTH} - 24}]]
+ if {$len > ${::Compiler::Settings::PAGEWIDTH}} {
+ set header [string range $header 0 [expr {${::Compiler::Settings::PAGEWIDTH} - 24}]]
append header {... }
- } elseif {$len < ${Compiler::Settings::PAGEWIDTH}} {
- set len [expr {${Compiler::Settings::PAGEWIDTH} - $len}]
+ } elseif {$len < ${::Compiler::Settings::PAGEWIDTH}} {
+ set len [expr {${::Compiler::Settings::PAGEWIDTH} - $len}]
append header [string repeat { } $len]
}
# Create date
- set len [string length ${Compiler::Settings::DATE}]
+ set len [string length ${::Compiler::Settings::DATE}]
if {$len > 10} {
- set Compiler::Settings::DATE [string range 0 7 ${Compiler::Settings::DATE}]
+ set Compiler::Settings::DATE [string range 0 7 ${::Compiler::Settings::DATE}]
append Compiler::Settings::DATE {...}
} elseif {$len < 10} {
@@ -111,11 +116,11 @@ namespace eval CodeListing {
append Compiler::Settings::DATE [string repeat { } $len]
}
- append header ${Compiler::Settings::DATE} { PAGE}
+ append header ${::Compiler::Settings::DATE} { PAGE}
# Create error summary and symbol table
create_error_summary
- if {${Compiler::Settings::SYMBOLS}} {
+ if {${::Compiler::Settings::SYMBOLS}} {
create_symbol_table
}
@@ -129,7 +134,7 @@ namespace eval CodeListing {
append lst ", 1 ERROR FOUND"
} elseif {$errors_count > 1} {
append lst ", $errors_count ERRORS FOUND"
- } {
+ } else {
append lst ", NO ERRORS FOUND"
}
@@ -137,7 +142,7 @@ namespace eval CodeListing {
append lst ", 1 WARNING"
} elseif {$warnings_count > 1} {
append lst ", $warnings_count WARNINGS"
- } {
+ } else {
append lst ", NO WARNINGS"
}
@@ -151,7 +156,7 @@ namespace eval CodeListing {
}
# Symbol table
- if {${Compiler::Settings::SYMBOLS}} {
+ if {${::Compiler::Settings::SYMBOLS}} {
append lst "\n\n"
append lst $symbol_table
}
@@ -168,14 +173,14 @@ namespace eval CodeListing {
## Directive LIST
# @access public
- # @parm Int idx - index where the directive occured
+ # @parm Int idx - index where the directive occurred
# @return void
proc directive_list {idx} {
variable lst ;# Resulting LST code
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
- if {${Compiler::Settings::_list} != 0} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
+ if {${::Compiler::Settings::_list} != 0} {return}
# Adjust code listing
set idx [getIdx $idx]
@@ -185,14 +190,14 @@ namespace eval CodeListing {
## Directive NOLIST
# @access public
- # @parm Int idx - index where the directive occured
+ # @parm Int idx - index where the directive occurred
# @return void
proc directive_nolist {idx} {
variable lst ;# Resulting LST code
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
- if {${Compiler::Settings::_list} != 0} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
+ if {${::Compiler::Settings::_list} != 0} {return}
# Adjust code listing
set idx [getIdx $idx]
@@ -224,7 +229,7 @@ namespace eval CodeListing {
# @return void
proc create_listing {data} {
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
variable lst ;# Resulting LST code
variable sync_map ;# Map of lines in code listing
@@ -255,8 +260,8 @@ namespace eval CodeListing {
variable symbol_table ;# Table of symbolic names
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
- if {!${Compiler::Settings::SYMBOLS}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::SYMBOLS}} {return}
# Iterate over definition ists and write them to the table
foreach def_list {
@@ -271,14 +276,14 @@ namespace eval CodeListing {
} char {
B C D I
X C N S
- } {
-
+ } \
+ {
# Get list of defined names
- set def_list [subst "\$PreProcessor::$def_list"]
+ set def_list [subst -nocommands "\$PreProcessor::$def_list"]
# Write defined names to the table
foreach var $def_list {
- set value [subst "\$PreProcessor::${val_array}($var)"]
+ set value [subst -nocommands "\$PreProcessor::${val_array}($var)"]
# Handle special constants
if {$char == {S}} {
@@ -290,7 +295,7 @@ namespace eval CodeListing {
1 0]
# Other constants ...
- } {
+ } else {
lappend symbol_table [list \
[string toupper $var] \
$char \
@@ -302,14 +307,14 @@ namespace eval CodeListing {
}
# Write defined variables (directive "SET")
- foreach var ${PreProcessor::defined_SET} {
- set value [lindex $PreProcessor::const_SET($var) {end 1}]
+ foreach var ${::PreProcessor::defined_SET} {
+ set value [lindex $::PreProcessor::const_SET($var) {end 1}]
lappend symbol_table [list [string toupper $var] { } NUMB [get_4hex $value] 1 1]
}
# Write defined special variables (directive "SET")
- foreach var ${PreProcessor::defined_SET_SPEC} {
- set value [lindex $PreProcessor::const_SET_SPEC($var) {end 1}]
+ foreach var ${::PreProcessor::defined_SET_SPEC} {
+ set value [lindex $::PreProcessor::const_SET_SPEC($var) {end 1}]
lappend symbol_table [list [string toupper $var] {S} SPEC [string toupper $value] 1 1]
}
@@ -317,7 +322,7 @@ namespace eval CodeListing {
set symbol_table [lsort -index 0 $symbol_table]
}
- ## Set flag used to 1 for symbol writen in table of symbols
+ ## Set flag used to 1 for symbol written in table of symbols
# @access public
# @parm String symbolic_name - Symbol name
# @parm String type - Symbol type
@@ -326,8 +331,8 @@ namespace eval CodeListing {
variable symbol_table ;# Table of symbolic names
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
- if {!${Compiler::Settings::SYMBOLS}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::SYMBOLS}} {return}
# Find the specified symbol in the table
set symbolic_name [string toupper $symbolic_name]
@@ -348,19 +353,19 @@ namespace eval CodeListing {
## Write error message to the code listing
# @access public
- # @parm Int idx - Index where the error occured
+ # @parm Int idx - Index where the error occurred
# @parm String info - Error message
# @return void
proc Error {idx info} {
variable lst ;# Resulting LST code
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
# Adjust index
set idx [getIdx $idx]
if {$idx == {}} {
- puts stderr "Compiler internal failure 0 -- code listing will not be complete"
+ puts stderr "Assembler internal failure 0 -- code listing will not be complete"
return
}
incr idx
@@ -372,19 +377,19 @@ namespace eval CodeListing {
## Write warning message to the code listing
# @access public
- # @parm Int idx - Index where the warning occured
+ # @parm Int idx - Index where the warning occurred
# @parm String info - Warning message
# @return void
proc Warning {idx info} {
variable lst ;# Resulting LST code
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
# Adjust index
set idx [getIdx $idx]
if {$idx == {}} {
- puts stderr "Compiler internal failure 4 -- code listing will not be complete"
+ puts stderr "Assembler internal failure 4 -- code listing will not be complete"
return
}
incr idx
@@ -402,12 +407,12 @@ namespace eval CodeListing {
variable lst ;# Resulting LST code
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
# Adjust index
set idx [getIdx $idx]
if {$idx == {}} {
- puts stderr "Compiler internal failure 5 -- code listing will not be complete"
+ puts stderr "Assembler internal failure 5 -- code listing will not be complete"
return
}
incr idx 2
@@ -426,13 +431,14 @@ namespace eval CodeListing {
variable lst ;# Resulting LST code
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
# Determinate original values
set sub_idx [getIdx $idx]
+
if {$sub_idx != {}} {
set new_values [lindex $lst [list $sub_idx 1]]
- } {
+ } else {
set new_values {}
}
@@ -468,7 +474,7 @@ namespace eval CodeListing {
variable lst ;# Resulting LST code
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
# Create empty space in code listing
insert_lines $idx [llength $macro_code]
@@ -479,10 +485,10 @@ namespace eval CodeListing {
set tmp_lst {}
# Adjust Macro expansion level and Inclusion level
- set IncLevel [lindex $lst "$idx 3"]
- set MacLevel [lindex $lst "$idx 4"]
+ set IncLevel [lindex $lst [list $idx 3]]
+ set MacLevel [lindex $lst [list $idx 4]]
if {![regexp {^\d+$} $MacLevel]} {
- puts stderr "Compiler internal failure 1 -- code listing will not be complete"
+ puts stderr "Assembler internal failure 1 -- code listing will not be complete"
return
}
incr MacLevel
@@ -493,7 +499,7 @@ namespace eval CodeListing {
}
# Set macro expansion level
- lset lst "$idx 4" $MacLevel
+ lset lst [list $idx 4] $MacLevel
# Insert code of macro to the current code listing
incr idx
@@ -515,7 +521,7 @@ namespace eval CodeListing {
variable new_sync_map ;# Tempotary Map of lines in code listing
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
# Reformat synchronization map
set new_sync_map {}
@@ -545,7 +551,7 @@ namespace eval CodeListing {
variable lst ;# Resulting LST code
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
# Adjust code listing
set idx [getIdx $idx]
@@ -554,7 +560,7 @@ namespace eval CodeListing {
if {[catch {
lset lst [list $idx 1] $opcode
}]} then {
- puts stderr "Compiler internal failure 2 -- code listing will not be complete"
+ puts stderr "Assembler internal failure 2 -- code listing will not be complete"
return
}
}
@@ -569,15 +575,15 @@ namespace eval CodeListing {
variable sync_map ;# Map of lines in code listing
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
# Adjust code listing
set idx [getIdx $idx]
if {$idx == {}} {return}
if {[catch {
- lset lst "$idx 0" [get_4hex $addr]
+ lset lst [list $idx 0] [get_4hex $addr]
}]} then {
- puts stderr "Compiler internal failure 3 -- code listing will not be complete"
+ puts stderr "Assembler internal failure 3 -- code listing will not be complete"
return
}
}
@@ -585,13 +591,14 @@ namespace eval CodeListing {
## Directive "END"
# @access public
# @parm Int idx - Source index
+ # @parm Bool preserve_current_line=false - Do not remove the `$idx' line from the sync. map
# @return void
- proc end_directive {idx} {
+ proc end_directive {idx {preserve_current_line 0}} {
variable sync_map ;# Map of lines in code listing
variable lst ;# Resulting LST code
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
# Determinate target index
set lst_idx [getIdx $idx]
@@ -601,7 +608,12 @@ namespace eval CodeListing {
# Adjust code listing and synchronization map
set lst [lreplace $lst $lst_idx end]
- set sync_map [lreplace $sync_map $idx end]
+ if {$preserve_current_line} {
+ incr idx
+ }
+ if {$idx < [llength $sync_map]} {
+ set sync_map [lreplace $sync_map $idx end]
+ }
}
## Set value for symbol definition
@@ -613,14 +625,14 @@ namespace eval CodeListing {
variable lst ;# Resulting LST code
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
# Determinate target index
set idx [getIdx $idx]
if {$idx == {}} {return}
# Adjust code listing
- lset lst "$idx 2" [get_4hex $value]
+ lset lst [list $idx 2] [get_4hex $value]
}
## Set value for special symbol definition
@@ -642,7 +654,7 @@ namespace eval CodeListing {
variable lst ;# Resulting LST code
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
# Insert empty lines for the included code
insert_lines $idx [expr {[llength $data] - 1}]
@@ -651,8 +663,8 @@ namespace eval CodeListing {
set idx [getIdx $idx]
# Adjust macro expansion level and inclusion level
- set IncLevel [lindex $lst "$idx 3"]
- set MacLevel [lindex $lst "$idx 4"]
+ set IncLevel [lindex $lst [list $idx 3]]
+ set MacLevel [lindex $lst [list $idx 4]]
incr IncLevel
# Adjust the given source code
@@ -673,6 +685,12 @@ namespace eval CodeListing {
}
+ ## Get last index in the synchronization map
+ # @return Int - The index
+ proc get_last_index_in_sync_map {} {
+ return [expr {[llength ${::CodeListing::sync_map}] - 1}]
+ }
+
## Line removed -- adjust synchronization map
# @access public
# @parm Int idx - source index
@@ -681,24 +699,20 @@ namespace eval CodeListing {
variable sync_map ;# Map of lines in code listing
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
# Adjust synchronization map
- if {[catch {
- set sync_map [lreplace $sync_map $idx $idx]
- }]} {
- puts stderr "Still unresolved compiler bug. I am sorry for that, code listing will not be complete. (As far as I know there is only one bug of that kind)"
- }
+ set sync_map [lreplace $sync_map $idx $idx]
}
- ## Adjust synchronization map to create spece which cannot contain anything
+ ## Adjust synchronization map to create a space which cannot contain anything
# @access public
# @parm Int dest_idx - Target index
# @parm Int len - Number of lines
# @return void
proc insert_empty_lines {dest_idx len} {
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
variable sync_map ;# Map of lines in code listing
variable new_sync_map ;# Tempotary Map of lines in code listing
@@ -775,9 +789,9 @@ namespace eval CodeListing {
}
# Create new page if paging is enabled
- if {${Compiler::Settings::PAGING}} {
+ if {${::Compiler::Settings::PAGING}} {
incr pageLines
- if {$pageLines > ${Compiler::Settings::PAGELENGTH}} {
+ if {$pageLines > ${::Compiler::Settings::PAGELENGTH}} {
incr pageNum
set pageLines 1
append result "\n\f" $header { } $pageNum "\n\n"
@@ -798,7 +812,7 @@ namespace eval CodeListing {
incr lineNum -1
# Normal line
- } {
+ } else {
# Local variables
set addr [lindex $line 0] ;# Address field
set opcode [lindex $line 1] ;# Instruction OP code
@@ -810,7 +824,7 @@ namespace eval CodeListing {
# Adjust inclusion level
if {$IncLevel == 0} {
set IncLevel { }
- } {
+ } else {
set IncLevel "=$IncLevel"
if {[string length $IncLevel] == 2} {
append IncLevel { }
@@ -820,7 +834,7 @@ namespace eval CodeListing {
# Adjust macro expansion level
if {$MacLevel == 0} {
set MacLevel { }
- } {
+ } else {
set MacLevel "+$MacLevel"
if {[string length $MacLevel] == 2} {
append MacLevel { }
@@ -862,7 +876,7 @@ namespace eval CodeListing {
set line {}
append line $field0 { } $IncLevel { } $line_number
append line { } $MacLevel { } [tabs2spaces $code]
- append result [string range $line 0 [expr ${Compiler::Settings::PAGEWIDTH} - 1]] "\n"
+ append result [string range $line 0 [expr ${::Compiler::Settings::PAGEWIDTH} - 1]] "\n"
# Continue in unfinished opcode
if {$opcode_len > 10} {
@@ -887,7 +901,7 @@ namespace eval CodeListing {
# @return String - output data
proc tabs2spaces {data} {
set tmp {} ;# Auxiliary variable
- while 1 {
+ while {1} {
# Search for 1st tabulator
set idx [string first "\t" $data]
@@ -939,7 +953,7 @@ namespace eval CodeListing {
set error_summary {}
# Create new page
- if {${Compiler::Settings::PAGING}} {
+ if {${::Compiler::Settings::PAGING}} {
incr pageNum
set pageLines 0
append error_summary "\n\f" $header { } $pageNum "\n\n"
@@ -953,10 +967,10 @@ namespace eval CodeListing {
incr lineNum
# Create new page if nessesary
- if {${Compiler::Settings::PAGING}} {
+ if {${::Compiler::Settings::PAGING}} {
incr pageLines
- if {$pageLines > ${Compiler::Settings::PAGEWIDTH}} {
+ if {$pageLines > ${::Compiler::Settings::PAGEWIDTH}} {
incr pageNum
set pageLines 1
append error_summary "\n\f" $header { } $pageNum "\n\n"
@@ -968,7 +982,7 @@ namespace eval CodeListing {
if {[lindex $line {1 0}] == {ERROR:}} {
incr errors_count
- } {
+ } else {
incr warnings_count
}
@@ -992,7 +1006,7 @@ namespace eval CodeListing {
set result {}
# Create new page
- if {${Compiler::Settings::PAGING}} {
+ if {${::Compiler::Settings::PAGING}} {
incr pageNum
set pageLines 0
append result "\n\f" $header { } $pageNum "\n\n"
@@ -1006,10 +1020,10 @@ namespace eval CodeListing {
foreach var $symbol_table {
# Create new page if nessesary
- if {${Compiler::Settings::PAGING}} {
+ if {${::Compiler::Settings::PAGING}} {
incr pageLines
- if {$pageLines > ${Compiler::Settings::PAGEWIDTH}} {
+ if {$pageLines > ${::Compiler::Settings::PAGEWIDTH}} {
incr pageNum
set pageLines 1
append result "\n\f" $header { } $pageNum "\n\n"
@@ -1037,14 +1051,14 @@ namespace eval CodeListing {
# Adjust rd
if {$rd == 1} {
set rd {REDEFINABLE}
- } {
+ } else {
set rd {}
}
# Adjust nu
if {$nu == 1} {
set nu {NOT USED}
- } {
+ } else {
set nu { }
}
@@ -1056,7 +1070,7 @@ namespace eval CodeListing {
# Composite final line
if {$char != {S}} {
set h {H}
- } {
+ } else {
set nu { }
set h [string repeat { } [expr {5 - [string length $val]}]]
}
@@ -1105,7 +1119,7 @@ namespace eval CodeListing {
return $number
}
- ## Translate source index to target index acording to synchronization map
+ ## Translate source index to target index according to synchronization map
# @access private
# @parm Int idx - Source index
# @return Int - target index
@@ -1126,7 +1140,7 @@ namespace eval CodeListing {
# @return void
proc insert_lines {dest_idx len} {
# Check if code listing is enabled
- if {!${Compiler::Settings::PRINT}} {return}
+ if {!${::Compiler::Settings::PRINT}} {return}
if {$len == 0} {return}
variable sync_map ;# Map of lines in code listing
@@ -1167,3 +1181,7 @@ namespace eval CodeListing {
set sync_map $new_sync_map
}
}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/compiler/compiler.tcl b/lib/compiler/compiler.tcl
index 35dea32..932e67a 100755..100644
--- a/lib/compiler/compiler.tcl
+++ b/lib/compiler/compiler.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,20 +21,25 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _COMPILER_TCL ] } {
+set _COMPILER_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# 8051 COMPILER - BASE NAMESPACE
# --------------------------------------------------------------------------
# Include other parts
source "${::LIB_DIRNAME}/compiler/codelisting.tcl" ;# Code listing creator
-source "${::LIB_DIRNAME}/compiler/assembler.tcl" ;# Assemler
+source "${::LIB_DIRNAME}/compiler/assembler.tcl" ;# Assembler
source "${::LIB_DIRNAME}/compiler/disassembler.tcl" ;# Disassembler
source "${::LIB_DIRNAME}/compiler/preprocessor.tcl" ;# Preprocessor
source "${::LIB_DIRNAME}/compiler/compilerconsts.tcl" ;# Compiler constant definitons
source "${::LIB_DIRNAME}/compiler/external_compiler.tcl";# External compiler interface
namespace eval Compiler {
- variable error_count ;# Number of errors occured during compilation
+ variable error_count ;# Number of errors occurred during compilation
variable warning_count ;# Number of warning reported during compilation
variable in_IDE 0 ;# Bool: Running in IDE (I mean GUI)
@@ -46,10 +51,10 @@ namespace eval Compiler {
# @parm String project_dir - Project directory
# @parm String current_dir - Current working directory
# @parm String input_file_name - Name of input source code
- # @parm String input_file_extension = {} - Extension of input file
+ # @parm String input_file_extension={} - Extension of input file
# @return Bool - result
- proc compile {project_dir current_dir input_file_name input_file_extension} {
- variable error_count ;# Number of errors occured during compilation
+ proc compile {project_dir current_dir input_file_name {input_file_extension {}}} {
+ variable error_count ;# Number of errors occurred during compilation
variable warning_count ;# Number of warning reported during compilation
# Compiler settings to defaults
@@ -58,12 +63,12 @@ namespace eval Compiler {
# Adjust compiler settings
if {${::Compiler::Settings::_print} == 2} {
set ::Compiler::Settings::PRINT 0
- } {
+ } else {
set ::Compiler::Settings::PRINT 1
}
if {${::Compiler::Settings::_object} == 2} {
set ::Compiler::Settings::OBJECT 0
- } {
+ } else {
set ::Compiler::Settings::OBJECT 1
}
@@ -88,13 +93,13 @@ namespace eval Compiler {
set asm [open $file r]
set asm_data [read $asm]
close $asm
- }]} {
+ }]} then {
if {${::Compiler::Settings::NOCOLOR}} {
- ${Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Unable to open the specified file. (%s)" $file]
- ${Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Compilation FAILED !"]
- } {
- ${Settings::TEXT_OUPUT_COMMAND} [mc "Unable to open the specified file. (\033\[34;1m%s\033\[m)" $file]
- ${Settings::TEXT_OUPUT_COMMAND} [mc "\033\[31;1mCompilation FAILED !\033\[m"]
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Unable to open the specified file. (%s)" $file]
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Compilation FAILED !"]
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Unable to open the specified file. (\033\[34;1m%s\033\[m)" $file]
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\033\[31;1mCompilation FAILED !\033\[m"]
}
return 0
}
@@ -102,34 +107,34 @@ namespace eval Compiler {
# Initialize preprocessor
if {!${::Compiler::Settings::QUIET}} {
if {${::Compiler::Settings::NOCOLOR}} {
- ${Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
"\n\n[::Compiler::msgc {SN}][mc {Compiling file: %s} $input_file_name$input_file_extension]"
- } {
- ${Settings::TEXT_OUPUT_COMMAND} \
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "\n\nCompiling file: \033\[34;1m%s\033\[m" $input_file_name$input_file_extension]
}
- ${Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "Initializing pre-processor ..."]
}
set precompiledCode [PreProcessor::compile $current_dir $file $asm_data]
set asm_data {}
- incr error_count ${PreProcessor::error_count}
- incr warning_count ${PreProcessor::warning_count}
- if {${PreProcessor::error_count} > 0} {
+ incr error_count ${::PreProcessor::error_count}
+ incr warning_count ${::PreProcessor::warning_count}
+ if {${::PreProcessor::error_count} > 0} {
if {${::Compiler::Settings::NOCOLOR}} {
- ${Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Pre-processing FAILED !"]
- } {
- ${Settings::TEXT_OUPUT_COMMAND} [mc "\033\[31;1mPre-processing FAILED !\033\[m"]
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Pre-processing FAILED !"]
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\033\[31;1mPre-processing FAILED !\033\[m"]
}
report_status $current_dir $input_file_name
return 0
}
- if {${Settings::ABORT_VARIABLE}} {return 0}
+ if {${::Compiler::Settings::ABORT_VARIABLE}} {return 0}
# Initialize Assembler
if {!${::Compiler::Settings::QUIET}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Compiling ..."]
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Compiling ..."]
}
assembler::compile \
[md5::md5 -hex -file $file] \
@@ -139,152 +144,152 @@ namespace eval Compiler {
${::PreProcessor::included_files} \
$precompiledCode
set ::PreProcessor::included_files {}
- incr error_count ${assembler::error_count}
- if {${assembler::error_count} > 0} {
+ incr error_count ${::assembler::error_count}
+ if {${::assembler::error_count} > 0} {
if {${::Compiler::Settings::NOCOLOR}} {
- ${Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Compilation FAILED !"]
- } {
- ${Settings::TEXT_OUPUT_COMMAND} [mc "\033\[31;1mCompilation FAILED !\033\[m"]
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Compilation FAILED !"]
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\033\[31;1mCompilation FAILED !\033\[m"]
}
report_status $current_dir $input_file_name
return 0
}
- if {${Settings::ABORT_VARIABLE}} {return 0}
+ if {${::Compiler::Settings::ABORT_VARIABLE}} {return 0}
# Write resulting object code
- if {${Settings::OBJECT}} {
- if {${Settings::OBJECT_FILE} != {}} {
- set object_file ${Settings::OBJECT_FILE}
- } {
+ if {${::Compiler::Settings::OBJECT}} {
+ if {${::Compiler::Settings::OBJECT_FILE} != {}} {
+ set object_file ${::Compiler::Settings::OBJECT_FILE}
+ } else {
set object_file $input_file_name
append object_file {.hex}
}
if {${::Compiler::Settings::NOCOLOR}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "Creating IHEX8 ...\t\t\t-> \"%s\"" $object_file]
- } {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "Creating IHEX8 ...\t\t\t-> \"\033\[34;1m%s\033\[m\"" $object_file]
}
makeBackupFile $current_dir $object_file
if {[catch {
- set hex [open [file join $current_dir $object_file] w 420]
- }]} {
+ set hex [open [file join $current_dir $object_file] w 0640]
+ }]} then {
if {${::Compiler::Settings::NOCOLOR}} {
- ${Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[::Compiler::msgc {EN}][mc "Error: Unable to open file \"%s\" for writing" [file join $current_dir $object_file]]
- ${Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[::Compiler::msgc {EN}][mc "Compilation FAILED !"]
- } {
- ${Settings::TEXT_OUPUT_COMMAND} \
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "\033\[31;1mError\033\[m: Unable to open file \"\033\[34;1m%s\033\[m\" for writing" [file join $current_dir $object_file]]
- ${Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "\033\[31;1mCompilation FAILED !\033\[m"]
}
report_status $current_dir $input_file_name
return 0
} else {
- puts -nonewline $hex ${assembler::hex}
+ puts -nonewline $hex ${::assembler::hex}
close $hex
}
}
- if {${Settings::ABORT_VARIABLE}} {return 0}
+ if {${::Compiler::Settings::ABORT_VARIABLE}} {return 0}
# Write resulting binary object code
- if {${Settings::CREATE_BIN_FILE}} {
+ if {${::Compiler::Settings::CREATE_BIN_FILE}} {
if {!${::Compiler::Settings::QUIET}} {
if {${::Compiler::Settings::NOCOLOR}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "Creating object file ...\t\t-> \"%s\"" "${input_file_name}.bin"]
- } {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "Creating object file ...\t\t-> \"\033\[34;1m%s\033\[m\"" "${input_file_name}.bin"]
}
}
makeBackupFile $current_dir "${input_file_name}.bin"
if {[catch {
- set bin [open [file join $current_dir $input_file_name.bin] w 420]
- }]} {
+ set bin [open [file join $current_dir $input_file_name.bin] w 0640]
+ }]} then {
if {${::Compiler::Settings::NOCOLOR}} {
- ${Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[::Compiler::msgc {EN}][mc "Error: Unable to open file \"%s\" for writing" [file join $current_dir $input_file_name.bin]]
- ${Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[::Compiler::msgc {EN}][mc "Compilation FAILED !"]
- } {
- ${Settings::TEXT_OUPUT_COMMAND} \
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "Error: Unable to open file \"\033\[34;1m%s\033\[m\" for writing" [file join $current_dir "${input_file_name}.bin"]]
- ${Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "\033\[31;1mCompilation FAILED !\033\[m"]
}
report_status $current_dir $input_file_name
return 0
} else {
fconfigure $bin -translation binary
- puts -nonewline $bin ${assembler::bin}
+ puts -nonewline $bin ${::assembler::bin}
close $bin
}
set bin_data {}
}
set hex_data {}
- if {${Settings::ABORT_VARIABLE}} {return 0}
+ if {${::Compiler::Settings::ABORT_VARIABLE}} {return 0}
# Write simulator data file
- if {${Settings::CREATE_SIM_FILE}} {
+ if {${::Compiler::Settings::CREATE_SIM_FILE}} {
if {!${::Compiler::Settings::QUIET}} {
if {${::Compiler::Settings::NOCOLOR}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "Creating assembler debug file ...\t-> \"%s\"" "${input_file_name}.adf"]
- } {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "Creating simulator data file ...\t-> \"\033\[34;1m%s\033\[m\"" "${input_file_name}.adf"]
}
}
makeBackupFile $current_dir "${input_file_name}.adf"
if {[catch {
- set sim [open [file join $current_dir $input_file_name.adf] w 420]
- }]} {
+ set sim [open [file join $current_dir $input_file_name.adf] w 0640]
+ }]} then {
if {${::Compiler::Settings::NOCOLOR}} {
- ${Settings::TEXT_OUPUT_COMMAND} \
- [::Compiler::msgc {EN}][mc "Error: Unable to open file \"%s]\" for writing" [file join $current_dir $input_file_name.adf]
- ${Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ [::Compiler::msgc {EN}][mc "Error: Unable to open file \"%s]\" for writing" [file join $current_dir $input_file_name.adf]]
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[::Compiler::msgc {EN}][mc "Compilation FAILED !"]
- } {
- ${Settings::TEXT_OUPUT_COMMAND} \
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "\033\[31;1mError\033\[m: Unable to open file \"\033\[34;1m%s\033\[m\" for writing" [file join $current_dir $input_file_name.adf]]
- ${Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "\033\[31;1mCompilation FAILED !\033\[m"]
}
report_status $current_dir $input_file_name
return 0
- } {
- puts -nonewline $sim ${assembler::adf}
+ } else {
+ puts -nonewline $sim ${::assembler::adf}
close $sim
}
}
- if {${Settings::ABORT_VARIABLE}} {return 0}
+ if {${::Compiler::Settings::ABORT_VARIABLE}} {return 0}
# Report final status
report_status $current_dir $input_file_name
if {!${::Compiler::Settings::QUIET}} {
if {${::Compiler::Settings::optim_ena}} {
if {${::Compiler::Settings::NOCOLOR}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
- [mc "Number of optimalizations performed: %s" ${::PreProcessor::optims}]
- } {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
- [mc "Number of optimalizations performed: \033\[1m%s\033\[m" ${::PreProcessor::optims}]
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ [mc "Number of optimization performed: %s" ${::PreProcessor::optims}]
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ [mc "Number of optimization performed: \033\[1m%s\033\[m" ${::PreProcessor::optims}]
}
}
if {${::Compiler::Settings::NOCOLOR}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[::Compiler::msgc {SN}][mc "Compilation successful. (time: %s sec.)" [expr {[clock seconds] - $sec}]]
- } {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "\033\[32;1mCompilation successful.\033\[m (time: %s sec.)" [expr {[clock seconds] - $sec}]]
}
}
@@ -307,25 +312,25 @@ namespace eval Compiler {
# @parm String input_file_name - Name of input file
# @return void
proc report_status {current_dir input_file_name} {
- variable error_count ;# Number of errors occured during compilation
+ variable error_count ;# Number of errors occurred during compilation
variable warning_count ;# Number of warning reported during compilation
# Determinate name of code listing file
- if {${Settings::PRINT_FILE} != {}} {
- set print_file ${Settings::PRINT_FILE}
- } {
+ if {${::Compiler::Settings::PRINT_FILE} != {}} {
+ set print_file ${::Compiler::Settings::PRINT_FILE}
+ } else {
set print_file $input_file_name
append print_file {.lst}
}
- # Message "Creting code listing file"
- if {!${::Compiler::Settings::QUIET}} {
+ # Message "Creating code listing file"
+ if {!${::Compiler::Settings::QUIET} && ${::Compiler::Settings::PRINT}} {
if {${::Compiler::Settings::NOCOLOR}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
- [mc "Creting code listing file ...\t\t-> \"%s\"" $print_file]
- } {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
- [mc "Creting code listing file ...\t\t-> \"\033\[34;1m%s\033\[m\"" $print_file]
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ [mc "Creating code listing file ...\t\t-> \"%s\"" $print_file]
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ [mc "Creating code listing file ...\t\t-> \"\033\[34;1m%s\033\[m\"" $print_file]
}
}
@@ -333,7 +338,7 @@ namespace eval Compiler {
if {!${::Compiler::Settings::QUIET}} {
if {$::TRANSLATION_LOADED} {
set text [mc "%s errors, %s warnings" $error_count $warning_count]
- } {
+ } else {
set text "$error_count error"
if {$error_count != 1} {
append text "s"
@@ -344,30 +349,32 @@ namespace eval Compiler {
}
}
if {${::Compiler::Settings::NOCOLOR}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} $text
- } {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} "\033\[1m$text\033\[m"
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} $text
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} "\033\[1m$text\033\[m"
}
}
# Write code listing file
- makeBackupFile $current_dir $print_file
- if {[catch {
- set lst [open [file join $current_dir $print_file] w 420]
- }]} {
- if {${::Compiler::Settings::NOCOLOR}} {
- ${Settings::TEXT_OUPUT_COMMAND} \
- [::Compiler::msgc {EN}][mc "Error: Unable to open file \"%s\" for writing" [file join $current_dir $print_file]]
- ${Settings::TEXT_OUPUT_COMMAND} [mc "Compilation FAILED !"]
- } {
- ${Settings::TEXT_OUPUT_COMMAND} \
- [::Compiler::msgc {EN}][mc "Error: Unable to open file \"\033\[34;1m%s\033\[m\" for writing" [file join $current_dir $print_file]]
- ${Settings::TEXT_OUPUT_COMMAND} [mc "\033\[31;1mCompilation FAILED !\033\[m"]
+ if {${::Compiler::Settings::PRINT}} {
+ makeBackupFile $current_dir $print_file
+ if {[catch {
+ set lst [open [file join $current_dir $print_file] w 0640]
+ }]} then {
+ if {${::Compiler::Settings::NOCOLOR}} {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ [::Compiler::msgc {EN}][mc "Error: Unable to open file \"%s\" for writing" [file join $current_dir $print_file]]
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Compilation FAILED !"]
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ [::Compiler::msgc {EN}][mc "Error: Unable to open file \"\033\[34;1m%s\033\[m\" for writing" [file join $current_dir $print_file]]
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\033\[31;1mCompilation FAILED !\033\[m"]
+ }
+ return 0
+ } else {
+ puts -nonewline $lst [CodeListing::getListing]
+ close $lst
}
- return 0
- } else {
- puts -nonewline $lst [CodeListing::getListing]
- close $lst
}
}
@@ -388,7 +395,7 @@ namespace eval Compiler {
## Namespace containing compiler settings
namespace eval Settings {
- ## Peerhole optimalization enable flag
+ ## Peephole optimization enable flag
variable optim_ena 0 ;# Bool: 0 == disabled; 1 == enabled
## Memory limits
@@ -500,8 +507,9 @@ namespace eval Compiler {
} default {
_nomod_value _paging_value _pagelength_value _pagewidth_value
_title_value _date_value _object_file _print_file
- } {
- set $var [subst "\$$default"]
+ } \
+ {
+ set $var [subst -nocommands "\$$default"]
}
# Finalize
@@ -555,3 +563,7 @@ namespace eval Compiler {
# Compiler settings to defaults
Compiler::Settings::restoreDefaults
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/compiler/compilerconsts.tcl b/lib/compiler/compilerconsts.tcl
index 175ceb9..e8a71f4 100755..100644
--- a/lib/compiler/compilerconsts.tcl
+++ b/lib/compiler/compilerconsts.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,6 +21,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _COMPILERCONSTS_TCL ] } {
+set _COMPILERCONSTS_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# DESCRIPTION
# Defines compiler constatnts. This code is part of Compiler
@@ -67,11 +72,18 @@ namespace eval CompilerConsts {
}
# All compiler directives
variable AllDirectives {
- bit set equ code data
- xdata idata bseg dseg iseg
- xseg ds dbit cseg db
- dw include list nolist
+ endif endm end else exitm
+ list nolist dseg iseg bseg
+ xseg cseg skip name equ
+ bit set code data idata
+ xdata macro flag ds dw
+ db dbit include org if
+ using byte name rept times
+ elseif ifn elseifn ifdef elseifdef
+ ifndef elseifndef ifb elseifb
+ ifnb elseifnb local
}
+
# Addresses of SFR registers
variable MapOfSFRArea {
{P0 80} {SP 81} {DPL 82} {DPH 83}
@@ -146,7 +158,7 @@ namespace eval CompilerConsts {
# Format:
# {
# {Instruction} {Operands_count
- # {{Operand_type_0 Operand_type_1 ...} Code_length Opcode Opcode_mask Instr_cycles_per_iteration}
+ # {{Operand_type_0 Operand_type_1 ...} Code_length Opcode Opcode_mask Machine_cycles_per_iteration}
# ...
# }
# ...
@@ -705,9 +717,10 @@ namespace eval CompilerConsts {
MapOfSFRArea
MapOfSFRBitArea
progVectors
- } {
+ } \
+ {
variable $var
- set val [subst "\$$var"]
+ set val [subst -nocommands "\$$var"]
regsub -all {\s+} $val { } $var
}
@@ -743,6 +756,7 @@ namespace eval CompilerConsts {
incr def_idx
# Local variables
+ set time [lindex $code_def 4] ;# Time
set mask [lindex $code_def 3] ;# OP code mask
set opcode [lindex $code_def 2] ;# OP code
set len [lindex $code_def 1] ;# Code length
@@ -777,10 +791,10 @@ namespace eval CompilerConsts {
continue
}
lappend defined_OPCODE $opcode
- set Opcode($opcode) "$instruction {$operands} $len {}"
+ set Opcode($opcode) [list $instruction $operands $len {} $time]
}
# Non-zero OP code mask
- } {
+ } else {
# Translate OP code and its mask to list of booleans
set opcode [assembler::hex2binlist $opcode]
set mask [assembler::hex2binlist $mask]
@@ -808,7 +822,7 @@ namespace eval CompilerConsts {
}
# Determinate list of possible high-order values
- # of opreands acording to the mask
+ # of opreands according to the mask
set values {}
set tmp 0
set tmp_len 0
@@ -832,7 +846,7 @@ namespace eval CompilerConsts {
if {$mask_bit} {
append tmp [string index $val $idx]
incr idx
- } {
+ } else {
append tmp $opcode_bit
}
}
@@ -860,7 +874,7 @@ namespace eval CompilerConsts {
continue
}
lappend defined_OPCODE $opcode
- set Opcode($opcode) [list $instruction $operands $len $masked_opr]
+ set Opcode($opcode) [list $instruction $operands $len $masked_opr $time]
}
}
@@ -871,3 +885,7 @@ namespace eval CompilerConsts {
# Initialize NS variables
CompilerConsts::initialize
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/compiler/disassembler.tcl b/lib/compiler/disassembler.tcl
index b74fedf..6319c1e 100755..100644
--- a/lib/compiler/disassembler.tcl
+++ b/lib/compiler/disassembler.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,6 +21,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _DISASSEMBLER_TCL ] } {
+set _DISASSEMBLER_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# Disassembler 8051
#
@@ -46,8 +51,8 @@ namespace eval disassembler {
variable hex_data {} ;# Raw input data
variable hex {} ;# Adjusted input data, list: {addr hex0 hex1 hex2 ...}
variable lineNum {} ;# Number of line currently beeing parsed
- variable error_count {} ;# Number of errors raised during decompilation
- variable warning_count {} ;# Number of warnings occured
+ variable error_count {} ;# Number of errors raised during disassembly
+ variable warning_count {} ;# Number of warnings occurred
variable label_idx {} ;# Label index
variable final_lbls 0 ;# Number of final labels
variable label ;# Array of tempotary labels, label(int) -> addr
@@ -58,7 +63,7 @@ namespace eval disassembler {
# GENERAL PURPOSE PROCEDURES
# ----------------------------------------------------------------
- ## Initiate decompilation
+ ## Initiate disassembly
# @parm string data - Input IHEX8 code
# @return string - output asm code or {}
proc compile {data} {
@@ -66,8 +71,8 @@ namespace eval disassembler {
variable hex_data ;# Raw input
variable hex ;# Adjusted input data, list: {addr hex0 hex1 hex2 ...}
variable lineNum ;# Number of line currently beeing parsed
- variable error_count ;# Number of errors raised during decompilation
- variable warning_count ;# Number of warnings occured
+ variable error_count ;# Number of errors raised during disassembly
+ variable warning_count ;# Number of warnings occurred
variable asm ;# Resulting source code
set error_count 0 ;# reset errors count
@@ -79,7 +84,7 @@ namespace eval disassembler {
regexp -all {\r\n?} hex_data "\n" hex_data
set hex_data [split $hex_data "\n"]
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {SN}][mc "Initializing disassembler ..."]
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {SN}][mc "Initializing disassembler ..."]
# Verify input code validity and set variable 'hex'
adjust_code
@@ -87,17 +92,17 @@ namespace eval disassembler {
# Exit if the code does not seem to be valid
if {$error_count != 0} {
if {${::Compiler::Settings::NOCOLOR}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[::Compiler::msgc {EN}][mc "Disassembly FAILED ..."]
- } {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[::Compiler::msgc {EN}][mc "\033\[31;1mDisassembly FAILED\033\[m ..."]
}
return {}
}
- if {${Compiler::Settings::ABORT_VARIABLE}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"]
+ if {${::Compiler::Settings::ABORT_VARIABLE}} {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"]
free_resources
return {}
}
@@ -105,8 +110,8 @@ namespace eval disassembler {
# Convert processor code into asm code
decompile_code
- if {${Compiler::Settings::ABORT_VARIABLE}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}[mc "Aborted"]
+ if {${::Compiler::Settings::ABORT_VARIABLE}} {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"]
free_resources
return {}
}
@@ -114,8 +119,8 @@ namespace eval disassembler {
# Create labels in resulting code
parse_labels
- if {${Compiler::Settings::ABORT_VARIABLE}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"]
+ if {${::Compiler::Settings::ABORT_VARIABLE}} {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"]
free_resources
return {}
}
@@ -123,26 +128,26 @@ namespace eval disassembler {
# Final stage
final_stage
- if {${Compiler::Settings::ABORT_VARIABLE}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"]
+ if {${::Compiler::Settings::ABORT_VARIABLE}} {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"]
free_resources
return {}
}
- # Free memory used during decompilation
+ # Free memory used during disassembly
free_resources
- if {${Compiler::Settings::ABORT_VARIABLE}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"]
+ if {${::Compiler::Settings::ABORT_VARIABLE}} {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"]
free_resources
return {}
}
if {${::Compiler::Settings::NOCOLOR}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[::Compiler::msgc {SN}][mc "Disassembly complete"]
- } {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "\033\[32;1mDisassembly complete\033\[m"]
}
@@ -167,7 +172,9 @@ namespace eval disassembler {
foreach line $hex_data {
- if {[expr {$lineNum % 10}] == 0} ${Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$lineNum % 10}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
incr lineNum ;# line number
@@ -209,7 +216,7 @@ namespace eval disassembler {
set len [expr "0x$len"]
set data [string range $line 8 {end-2}]
if {$len != ([string length $data] / 2)} {
- Error $lineNum [mc "Length field do not corespond true data length"]
+ Error $lineNum [mc "Length field do not correspond true data length"]
continue
}
@@ -217,11 +224,11 @@ namespace eval disassembler {
set addr_hex [string range $line 2 5]
set addr [expr "0x$addr_hex"]
if {$addr <= $pointer} {
- Error $lineNum [mc "Unexpected address -- code is not well formated"]
+ Error $lineNum [mc "Unexpected address -- code is not well formatted"]
continue
} elseif {$addr > ($pointer + 1)} {
set pointer $addr
- } {
+ } else {
incr pointer $len
}
@@ -262,7 +269,9 @@ namespace eval disassembler {
foreach line $hex {
- if {[expr {$idx % 10}] == 0} ${Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 10}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
incr idx
@@ -276,7 +285,7 @@ namespace eval disassembler {
if {$trailing_data_length} {
# Write trailing data
foreach opcode $trailing_data {
- append asm "_$pointer {DB 0${opcode}h {}} "
+ lappend asm _$pointer [list {DB} "0${opcode}h" {}]
incr pointer
}
# Reset trailing data
@@ -286,7 +295,7 @@ namespace eval disassembler {
# Adjust pointer
set pointer $addr_dec
- append asm "{} {} {} {ORG [HEX $addr]h {}} "
+ lappend asm {} {} {} [list {ORG} "[HEX $addr]h" {}]
}
# Number of data fields
@@ -295,7 +304,7 @@ namespace eval disassembler {
# Append trailing data from last parsing to the current line
if {$trailing_data_length} {
# append
- incr len $trailing_data_length
+ incr len $trailing_data_length
set line [concat $trailing_data $line]
# reset
set trailing_data_length 0
@@ -310,13 +319,13 @@ namespace eval disassembler {
set opcode [lindex $line $idx] ;# current opcode
# Search for he given opcode
- if {[lsearch ${CompilerConsts::defined_OPCODE} $opcode] == -1} {
+ if {[lsearch ${::CompilerConsts::defined_OPCODE} $opcode] == -1} {
# opcode not found -> write opcode directly to source code
- append asm "_$pointer {DB 0${opcode}h {}} "
+ lappend asm "_$pointer" [list {DB} "0${opcode}h" {}]
set length 1
} else {
# opcode found -> resolve it's definition
- set def $CompilerConsts::Opcode($opcode)
+ set def $::CompilerConsts::Opcode($opcode)
set instruction [lindex $def 0] ;# Instruction name
set opr_types [lindex $def 1] ;# Oprand types
@@ -338,15 +347,15 @@ namespace eval disassembler {
set opr {}
foreach type $opr_types {
- if {[lsearch ${CompilerConsts::FixedOperands} [string tolower $type]] != -1} {
+ if {[lsearch ${::CompilerConsts::FixedOperands} [string tolower $type]] != -1} {
# Fixed operand -> only copy
set opr $type
- } {
+ } else {
# Get operand value
incr idx
if {$idx > $len} {
- append asm "_$pointer {DB 0${opcode}h {}} "
+ lappend asm "_$pointer" [{DB} "0${opcode}h" {}]
set instruction_skipped 1
set length 1
incr idx -1
@@ -361,7 +370,7 @@ namespace eval disassembler {
incr idx
if {$idx > $len} {
- append asm "_$pointer {DB 0${opcode}h {}} "
+ lappend asm "_$pointer" [list {DB} "0${opcode}h" {}]
set instruction_skipped 1
set length 1
incr idx -2
@@ -373,7 +382,7 @@ namespace eval disassembler {
set opr "[HEX [lindex $line $idx]]h"
set tmp_opr [string range $opr 0 {end-1}]
set tmp_opr [expr "0x$tmp_opr"]
- foreach item ${CompilerConsts::MapOfSFRBitArea} {
+ foreach item ${::CompilerConsts::MapOfSFRBitArea} {
if {[expr "0x[lindex $item 1]"] == $tmp_opr} {
set opr [lindex $item 0]
break
@@ -384,7 +393,7 @@ namespace eval disassembler {
set opr "/[HEX [lindex $line $idx]]h"
set tmp_opr [string range $opr 1 {end-1}]
set tmp_opr [expr "0x$tmp_opr"]
- foreach item ${CompilerConsts::MapOfSFRBitArea} {
+ foreach item ${::CompilerConsts::MapOfSFRBitArea} {
if {[expr "0x[lindex $item 1]"] == $tmp_opr} {
set opr [lindex $item 0]
break
@@ -395,7 +404,7 @@ namespace eval disassembler {
set opr "[HEX [lindex $line $idx]]h"
set tmp_opr [string range $opr 0 {end-1}]
set tmp_opr [expr "0x$tmp_opr"]
- foreach item ${CompilerConsts::MapOfSFRArea} {
+ foreach item ${::CompilerConsts::MapOfSFRArea} {
if {[expr "0x[lindex $item 1]"] == $tmp_opr} {
set opr [lindex $item 0]
break
@@ -417,7 +426,7 @@ namespace eval disassembler {
if {$label($label_idx) > 0x0FFFF || $label($label_idx) < 0} {
set label($label_idx) [expr {$label($label_idx) & 0x0FFFF}]
- Warning "Code address overflow, instruction: $instruction"
+ Warning [mc "Code address overflow, instruction: %s" $instruction]
} elseif {$label($label_idx) == $pointer} {
unset label($label_idx)
incr label_idx -1
@@ -429,6 +438,7 @@ namespace eval disassembler {
set opr "lbl${label_idx}-"
set label($label_idx) "$mask_opr[lindex $line $idx]"
set label($label_idx) [expr "0x$label($label_idx)"]
+ set label($label_idx) [expr {($label($label_idx) & 0x007ff) | ($pointer & 0x0f800)}]
if {$label($label_idx) == $pointer} {
unset label($label_idx)
@@ -443,7 +453,7 @@ namespace eval disassembler {
incr idx
if {$idx > $len} {
- append asm "_$pointer {DB 0${opcode}h {}} "
+ lappend asm "_$pointer" [list {DB} "0${opcode}h" {}]
set length 1
incr idx -2
set instruction_skipped 1
@@ -471,8 +481,17 @@ namespace eval disassembler {
continue
}
+ # Swap operands in case if of instruction "MOV data, data"
+ if {
+ $instruction == {mov} &&
+ [lindex $opr_types 0] == {data} &&
+ [lindex $opr_types 1] == {data}
+ } then {
+ set operands [list [lindex $operands 1] [lindex $operands 0]]
+ }
+
# Append line to source code list
- append asm "_$pointer {$instruction {$operands} {}} "
+ lappend asm "_$pointer" [list $instruction $operands {}]
}
# Increment program address pointer
incr pointer $length
@@ -501,7 +520,7 @@ namespace eval disassembler {
if {$idx != -1} {
# Reuse an existing label
regsub -all "lbl${i}-" $asm "label$idx" asm
- } {
+ } else {
# Realy a new label
lappend addrs $label($i)
incr lbl_idx
@@ -517,7 +536,7 @@ namespace eval disassembler {
if {$idx == -1} {
# Not found
append equ_block "{} {CODE [HEX [format %X $addr]]h label$i} "
- } {
+ } else {
# Found
incr idx
lset asm [list $idx 2] "label$i"
@@ -544,7 +563,9 @@ namespace eval disassembler {
# Rewrite the source code
for {set i 1} {$i <= $len} {incr i 2} {
- if {[expr {$len % 5}] == 0} ${Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$len % 5}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
set line [lindex $asm $i] ;# Get line
@@ -554,7 +575,7 @@ namespace eval disassembler {
continue
# Not an empty line
- } {
+ } else {
set label [lindex $line 2] ;# label
set instr [lindex $line 0] ;# instruction
set oprs [lindex $line 1] ;# oprands
@@ -589,7 +610,7 @@ namespace eval disassembler {
variable hex_data ;# Raw input data
variable hex ;# Adjusted input data, list: {addr hex0 hex1 hex2 ...}
variable lineNum ;# Number of line currently beeing parsed
- variable error_count ;# Number of errors raised during decompilation
+ variable error_count ;# Number of errors raised during disassembly
variable label_idx ;# Label index
variable label ;# Array of tempotary labels, label(int) -> addr
variable asm ;# Resulting source code
@@ -620,12 +641,12 @@ namespace eval disassembler {
}
## Report warning message
- # @parm Int LineNumber - Number of line where it occured
+ # @parm Int LineNumber - Number of line where it occurred
# @parm String ErrorInfo - Text of the warning
# @return void
proc Warning {ErrorInfo} {
variable idx ;# Current position in asm list
- variable warning_count ;# Number of warnings occured
+ variable warning_count ;# Number of warnings occurred
# Increment warning counter
incr warning_count
@@ -633,32 +654,36 @@ namespace eval disassembler {
# Report the warning
if {${::Compiler::Settings::WARNING_LEVEL} < 2} {
if {${::Compiler::Settings::NOCOLOR}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {WN}][mc "Warning: %s" $ErrorInfo]
- } {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\033\[33mWarning\033\[m: %s" $ErrorInfo]
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {WN}][mc "Warning: %s" $ErrorInfo]
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\033\[33mWarning\033\[m: %s" $ErrorInfo]
}
}
}
## Error
- # @parm Int lineNumber - number of line, where the error occured
+ # @parm Int lineNumber - number of line, where the error occurred
# @parm String info - error string
proc Error {lineNumber info} {
variable error_count
incr error_count
if {$lineNumber != {}} {
if {${::Compiler::Settings::NOCOLOR}} {
- set lineNumber [mc " at line %s" $lineNumber]
- } {
- set lineNumber [mc " at line \033\[31;1;4m%s\033\[m" $lineNumber]
+ set lineNumber [mc " at %s" $lineNumber]
+ } else {
+ set lineNumber [mc " at \033\[31;1;4m%s\033\[m" $lineNumber]
}
}
if {${::Compiler::Settings::WARNING_LEVEL} < 3} {
if {${::Compiler::Settings::NOCOLOR}} {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EL}][mc "Error%s: %s" $lineNumber $info]
- } {
- ${Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\033\[31;1mError%s\033\[m: %s" $lineNumber $info]
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EL}][mc "Error%s: %s" $lineNumber $info]
+ } else {
+ ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\033\[31;1mError%s\033\[m: %s" $lineNumber $info]
}
}
}
}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/compiler/external_compiler.tcl b/lib/compiler/external_compiler.tcl
index 3cf581b..5d8c6b2 100755..100644
--- a/lib/compiler/external_compiler.tcl
+++ b/lib/compiler/external_compiler.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,6 +21,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _EXTERNAL_COMPILER_TCL ] } {
+set _EXTERNAL_COMPILER_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# DESCRIPTION
# Implements interface to external compilers
@@ -163,7 +168,7 @@ namespace eval ExternalCompiler {
variable sdcc_string_options_def {
model --model-small
standard --std-sdcc89
- stack --pack-iram
+ stack {}
custom {}
}
# Current SDCC string options
@@ -192,6 +197,16 @@ namespace eval ExternalCompiler {
# Current semicolon separated optional string options
variable sdcc_scs_string_options
+ ## Make utility
+ # General options, this is an array!
+ variable makeutil_config
+ # Default values for the eneral options
+ variable makeutil_config_def {
+ c_ena 0
+ c_file {}
+ co_file {}
+ ct_file {}
+ }
## Make backup copies for files with the given extensions and remove original files
# (input_filename.extension -> input_filename.extension~)*
@@ -217,50 +232,76 @@ namespace eval ExternalCompiler {
proc compile_C {work_dir input_file iram xram code} {
variable input_filename ;# String: Name of file to compile (without extension)
variable compiler_used ;# Int: Compiler ID (1 == ASEM-51; 2 == ASL; 3 == AS31, other values have no meaning)
+ variable makeutil_config;# Make utility - general options
set compiler_used 0
set input_filename [file rootname $input_file]
backup_and_remove {asm cdb ihx}
set sdcc_opts [determinate_sdcc_options]
- if {${::PROGRAM_AVALIABLE(sdcc-sdcc)}} {
+ if {${::PROGRAM_AVAILABLE(sdcc-sdcc)}} {
set sdcc_cmd {sdcc-sdcc}
- } {
+ } else {
set sdcc_cmd {sdcc}
}
- ::X::messages_text_append [::Compiler::msgc {S}][mc "\n\nStarting compiler ..."]
+
+ # Normal way (POSIX)
if {!$::MICROSOFT_WINDOWS} {
- ::X::messages_text_append "\ncd \"$work_dir\"\n$sdcc_cmd -mmcs51 --iram-size $iram --xram-size $xram --code-size $code $sdcc_opts \"$input_file\""
- } {
- ::X::messages_text_append "\ncd \"$work_dir\"\n$sdcc_cmd -mmcs51 --iram-size $iram --xram-size $xram --code-size $code --nooverlay --noinduction --verbose --debug -V --std-sdcc89 --model-small --pack-iram \"$input_file\""
+ # Start GNU make
+ if {$makeutil_config(c_ena) && ${::PROGRAM_AVAILABLE(make)}} {
+ ::X::messages_text_append [::Compiler::msgc {S}][mc "\n\nStarting make ..."]
+ ::X::messages_text_append "\ncd \"${work_dir}\"\nmake -f \"${makeutil_config(c_file)}\" ${makeutil_config(co_file)} ${makeutil_config(ct_file)}"
+
+ # Start SDCC
+ } else {
+ ::X::messages_text_append [::Compiler::msgc {S}][mc "\n\nStarting compiler ..."]
+ ::X::messages_text_append "\ncd \"${work_dir}\"\n${sdcc_cmd} -mmcs51 --iram-size ${iram} --xram-size ${xram} --code-size ${code} ${sdcc_opts} \"${input_file}\""
+ }
+ # Microsoft Windows way
+ } else {
+ regsub -all {/} $work_dir "\\\\\\\\" work_dir
+ regsub -all {/} $input_file "\\\\\\\\" input_file
+
+ ::X::messages_text_append [::Compiler::msgc {S}][mc "\n\nStarting compiler ..."]
+ ::X::messages_text_append "\ncd \"${work_dir}\"\n${sdcc_cmd} -mmcs51 --iram-size ${iram} --xram-size ${xram} --code-size ${code} ${sdcc_opts} \"${input_file}\""
}
if {[catch {
cd $work_dir
- }]} {
+ }]} then {
::X::messages_text_append [::Compiler::msgc {E}][mc "\nError: Unable to change working directory to '%s'" $work_dir]
}
if {!$::MICROSOFT_WINDOWS} { ;# Normal way (POSIX)
- return [exec -- /bin/sh -c "$sdcc_cmd -mmcs51 \
- --iram-size $iram \
- --xram-size $xram \
- --code-size $code \
- $sdcc_opts \"$input_file\"" |& \
- tclsh "${::LIB_DIRNAME}/external_command.tcl" \
- [tk appname] \
- {::ExternalCompiler::ext_compilation_complete 1}\
- ::X::compilation_message & \
- ]
- } { ;# Microsoft Windows way
+ # Start GNU make
+ if {$makeutil_config(c_ena) && ${::PROGRAM_AVAILABLE(make)}} {
+ return [exec -- /bin/sh -c "make -f \"${makeutil_config(c_file)}\" ${makeutil_config(co_file)} ${makeutil_config(ct_file)}" |& \
+ tclsh "${::LIB_DIRNAME}/external_command.tcl" \
+ [tk appname] \
+ {::ExternalCompiler::ext_compilation_complete 1} \
+ ::X::compilation_message & \
+ ]
+
+ # Start SDCC
+ } else {
+ return [exec -- /bin/sh -c "$sdcc_cmd -mmcs51 \
+ --iram-size $iram \
+ --xram-size $xram \
+ --code-size $code \
+ $sdcc_opts \"$input_file\"" |& \
+ tclsh "${::LIB_DIRNAME}/external_command.tcl" \
+ [tk appname] \
+ {::ExternalCompiler::ext_compilation_complete 1}\
+ ::X::compilation_message & \
+ ]
+ }
+ } else { ;# Microsoft Windows way
eval [subst -nocommands {
- return [exec -- "${::LIB_DIRNAME}/sdcc.bat" \
- "${::LIB_DIRNAME}" \
- $iram \
- $xram \
- $code \
- "$input_file" \
+ return [exec -- "${::INSTALLATION_DIR}/startsdcc.bat" \
+ "${work_dir}" \
+ $sdcc_opts \
+ "${input_file}" \
|& \
- "${::LIB_DIRNAME}/external_command.bat" \
- "${::LIB_DIRNAME}/external_command.tcl" \
- [tk appname] \
+ "${::INSTALLATION_DIR}/external_command.bat" \
+ "${::INSTALLATION_DIR}/external_command.exe" \
+ "[tk appname]" \
{::ExternalCompiler::ext_compilation_complete 1} \
::X::compilation_message & \
]
@@ -292,7 +333,7 @@ namespace eval ExternalCompiler {
::X::messages_text_append "\ncd \"$work_dir\"\nas31 $as31_options \"$input_file\""
if {[catch {
cd $work_dir
- }]} {
+ }]} then {
::X::messages_text_append [::Compiler::msgc {E}][mc "\nError: Unable to change working directory to '%s'" $work_dir]
}
backup_and_remove {adf hex lst}
@@ -322,20 +363,47 @@ namespace eval ExternalCompiler {
set input_filename [file rootname $input_file_base]
set working_dir $work_dir
- set asem51_options [determinate_asem51_options]
::X::messages_text_append [::Compiler::msgc {S}][mc "\n\nStarting compiler ..."]
- ::X::messages_text_append "\ncd \"$work_dir\"\nasem $asem51_options \"$input_file\""
+
+ set asem51_options [determinate_asem51_options]
+ if {$::MICROSOFT_WINDOWS} {
+ regsub -all -- {--verbose} $asem51_options {} asem51_options
+ regsub -all -- {--} $asem51_options {/} asem51_options
+ regsub -all -- {=} $asem51_options {:} asem51_options
+ regsub -all -- {;} $asem51_options { /includes:} asem51_options
+ regsub -all {/} $work_dir "\\\\\\\\" work_dir
+ regsub -all {/} $input_file "\\\\\\\\" input_file
+ ::X::messages_text_append "\ncd \"$work_dir\"\nasem \"$input_file\" $asem51_options"
+ } else {
+ ::X::messages_text_append "\ncd \"$work_dir\"\nasem $asem51_options \"$input_file\""
+ }
if {[catch {
cd $work_dir
- }]} {
+ }]} then {
::X::messages_text_append [::Compiler::msgc {E}][mc "\nError: Unable to change working directory to '%s'" $work_dir]
}
backup_and_remove {adf hex lst omf}
- return [exec -- /bin/sh -c "asem $asem51_options \"$input_file\"" |& \
- tclsh "${::LIB_DIRNAME}/external_command.tcl" "[tk appname]" \
- ::ExternalCompiler::ext_compilation_complete ::X::compilation_message & \
- ]
+ if {!$::MICROSOFT_WINDOWS} { ;# Normal way (POSIX)
+ return [exec -- /bin/sh -c "asem $asem51_options \"$input_file\"" |& \
+ tclsh "${::LIB_DIRNAME}/external_command.tcl" "[tk appname]" \
+ ::ExternalCompiler::ext_compilation_complete ::X::compilation_message & \
+ ]
+ } else { ;# Microsoft Windows way
+ eval [subst -nocommands {
+ return [exec -- "${::INSTALLATION_DIR}/startasem.bat" \
+ "${work_dir}" \
+ "${input_file}" \
+ $asem51_options \
+ |& \
+ "${::INSTALLATION_DIR}/external_command.bat" \
+ "${::INSTALLATION_DIR}/external_command.exe" \
+ "[tk appname]" \
+ {::ExternalCompiler::ext_compilation_complete 1} \
+ ::X::compilation_message & \
+ ]
+ }]
+ }
}
## Start ASL (Assembler)
@@ -364,7 +432,7 @@ namespace eval ExternalCompiler {
::X::messages_text_append "\ncd \"$work_dir\"\nasl $asl_opts \"$input_file\""
if {[catch {
cd $work_dir
- }]} {
+ }]} then {
::X::messages_text_append [::Compiler::msgc {E}][mc "\nError: Unable to change working directory to '%s'" $work_dir]
}
return [exec -- /bin/sh -c "asl $asl_opts \"$input_file\" $additional_commands" |& \
@@ -383,18 +451,20 @@ namespace eval ExternalCompiler {
# List of files included files in the main file
set included_files [list]
+ set cbd_file {} ;# We will set this variable later ...
+
# Open C DeBug file generated by SDCC compiler
if {[catch {
set cdb_file [open $input_filename.cdb r]
- }]} {
+ }]} then {
::X::messages_text_append [::Compiler::msgc {E}][mc "\nUnable to find \"%s\"" [file rootname $input_filename].cdb]
return
}
# Open the hashes file for writing (possibly create the file)
if {[catch {
- set hs_file [open $input_filename.hashes w 420]
- }]} {
+ set hs_file [open $input_filename.hashes w 0640]
+ }]} then {
::X::messages_text_append [::Compiler::msgc {E}][mc "\nUnable to create \"%s\"" [file rootname $input_filename].hashes]
catch {close $cbd_file}
return
@@ -429,11 +499,11 @@ namespace eval ExternalCompiler {
}
## This function must be called after exteral compiler finished its work
- # @parm Int action = 0 - Action to perform after successfull compilation
+ # @parm Int action=0 - Action to perform after successfull compilation
# 0 - No action
# 1 - Copy <file>.ihx to <file>.hex
# @return void
- proc ext_compilation_complete args {
+ proc ext_compilation_complete {{action 0}} {
variable input_filename ;# String: Name of file to compile (without extension)
variable compiler_used ;# Int: Compiler ID (1 == ASEM-51; 2 == ASL; 3 == AS31, other values have no meaning)
variable assembler_ASEM51_addcfg;# Current ASEM-51 assembler configuration
@@ -464,10 +534,13 @@ namespace eval ExternalCompiler {
create_hashes_file
}
}
- ::X::messages_text_append [::Compiler::msgc {S}][mc "\nCompilation successful"]
+
+ if {$::X::compilation_successfull} {
+ ::X::messages_text_append [::Compiler::msgc {S}][mc "\nCompilation successful"]
+ }
# Perform specified after successfull compilation
- switch -- [lindex $args 0] {
+ switch -- $action {
0 { ;# No action
}
1 { ;# Copy <file>.ihx to <file>.hex
@@ -479,9 +552,10 @@ namespace eval ExternalCompiler {
}
}
}
+ }
# Compilation failed
- } {
+ if {!$::X::compilation_successfull} {
::X::messages_text_append [::Compiler::msgc {E}][mc "\nCompilation FAILED"]
}
::X::ext_compilation_complete
@@ -505,8 +579,8 @@ namespace eval ExternalCompiler {
# Try to open code listing file and some tempotary debug file
if {[catch {
set lst_file [open $input_filename.lst r]
- set adf_file [open $input_filename.adf w 420]
- } result]} {
+ set adf_file [open $input_filename.adf w 0640]
+ } result]} then {
::X::messages_text_append [::Compiler::msgc {E}][mc "File access error:\n%s" $result]
return 0
}
@@ -514,7 +588,6 @@ namespace eval ExternalCompiler {
# Write file header
puts $adf_file "# Assembler Debug File created by ${::APPNAME}"
puts $adf_file "# Used assembler: AS31"
- puts $adf_file "# Date: [clock format [clock seconds] -format {%D}]"
# Write MD5 of the source file
puts -nonewline $adf_file [::md5::md5 -hex -file $input_file_base]
@@ -550,8 +623,8 @@ namespace eval ExternalCompiler {
scan $h %x h
lappend adf_code $h
}
- }]} {
- ::X::messages_text_append [::Compiler::msgc {E}][mc "Unable to understand formulation at line %s in file %s" $line_number $input_filename.lst]
+ }]} then {
+ ::X::messages_text_append [::Compiler::msgc {E}][mc "Unable to understand formulation at %s in file %s" $line_number $input_filename.lst]
close $lst_file
close $adf_file
return 0
@@ -561,11 +634,11 @@ namespace eval ExternalCompiler {
if {$address == {}} {
puts -nonewline $adf_file { }
puts -nonewline $adf_file $adf_code
- } {
+ } else {
if {[catch {
scan $address %x address
- }]} {
- ::X::messages_text_append [::Compiler::msgc {E}][mc "Unable to understand formulation at line %s in file %s" $line_number $input_filename.lst]
+ }]} then {
+ ::X::messages_text_append [::Compiler::msgc {E}][mc "Unable to understand formulation at %s in file %s" $line_number $input_filename.lst]
close $lst_file
close $adf_file
return 0
@@ -603,8 +676,8 @@ namespace eval ExternalCompiler {
# Try to open code listing file and some tempotary debug file
if {[catch {
set lst_file [open $input_filename.lst r]
- set adf_file [open $input_filename._adf w 420]
- } result]} {
+ set adf_file [open $input_filename._adf w 0640]
+ } result]} then {
::X::messages_text_append [::Compiler::msgc {E}][mc "File access error:\n%s" $result]
return 0
}
@@ -619,7 +692,7 @@ namespace eval ExternalCompiler {
# Read 1 line
set line [gets $lst_file]
- # Normal line coresponding to certain line in source code
+ # Normal line corresponding to certain line in source code
if {[regexp {^ *\d+:(..)?} $line inclusion_level]} {
# Extract numbers after "line_num: inc_lvl "
set line [string range $line [string length $inclusion_level] end]
@@ -701,22 +774,21 @@ namespace eval ExternalCompiler {
# Open final debug file
if {[catch {
- set adf_file [open $input_filename.adf w 420]
- } result]} {
+ set adf_file [open $input_filename.adf w 0640]
+ } result]} then {
::X::messages_text_append [::Compiler::msgc {E}][mc "File access error:\n%s" $result]
return 0
}
# Write file header
puts $adf_file "# Assembler Debug File created by ${::APPNAME}"
puts $adf_file "# Used assembler: ASEM-51"
- puts $adf_file "# Date: [clock format [clock seconds] -format {%D}]"
# Create list of included files with MD5 hashes
set hashes_and_files {}
set project_dir_len [string length $project_dir]
foreach filename $included_files {
if {[catch {
lappend hashes_and_files [::md5::md5 -hex -file $filename]
- } result]} {
+ } result]} then {
lappend hashes_and_files 0
::X::messages_text_append [::Compiler::msgc {E}][mc "File access error:\n%s" $result]
}
@@ -730,7 +802,7 @@ namespace eval ExternalCompiler {
# Copy content of tempotary debug file to final debug file
if {[catch {
set adf__file [open $input_filename._adf r]
- } result]} {
+ } result]} then {
::X::messages_text_append [::Compiler::msgc {E}][mc "File access error:\n%s" $result]
return 0
}
@@ -756,8 +828,8 @@ namespace eval ExternalCompiler {
if {[catch {
set map_file [open $input_filename.map r] ;# ASL debug file
set hex_file [open $input_filename.hex r] ;# Machine code
- set adf_file [open $input_filename.adf w 420] ;# MCU 8051 IDE debug file
- } result]} {
+ set adf_file [open $input_filename.adf w 0640] ;# MCU 8051 IDE debug file
+ } result]} then {
::X::messages_text_append [::Compiler::msgc {E}][mc "File access error:\n%s" $result]
return 0
}
@@ -812,7 +884,7 @@ namespace eval ExternalCompiler {
set filename [file join $project_dir [file normalize $filename]]
if {[catch {
lappend hashes_and_files [::md5::md5 -hex -file $filename]
- } result]} {
+ } result]} then {
::X::messages_text_append [::Compiler::msgc {E}][mc "\nFile access error:\n%s" $result]
lappend hashes_and_files {0}
}
@@ -829,7 +901,6 @@ namespace eval ExternalCompiler {
seek $map_file 0
puts $adf_file "# Assembler Debug File created by ${::APPNAME}"
puts $adf_file "# Used assembler: ASL"
- puts $adf_file "# Date: [clock format [clock seconds] -format {%D}]"
puts $adf_file $hashes_and_files
unset hashes_and_files
@@ -914,7 +985,7 @@ namespace eval ExternalCompiler {
set val [::IHexTools::get_value $i]
if {$val > -1} {
lappend code [expr "0x$val"]
- } {
+ } else {
lappend code 0
}
}
@@ -956,7 +1027,7 @@ namespace eval ExternalCompiler {
if {$value != {}} {
if {[regexp {\s} $value]} {
append result { } $key { } "\"" $value "\""
- } {
+ } else {
append result { } $key { } $value
}
}
@@ -969,7 +1040,7 @@ namespace eval ExternalCompiler {
if {$value != {}} {
if {[regexp {\s} $value]} {
append result { } $key { } "\"" $value "\""
- } {
+ } else {
append result { } $key { } $value
}
}
@@ -986,7 +1057,7 @@ namespace eval ExternalCompiler {
set result $assembler_ASEM51_config(custom)
if {$assembler_ASEM51_config(-i) != {}} {
- append result { -i } {"} $assembler_ASEM51_config(i) {"}
+ append result " --includes=$assembler_ASEM51_config(-i)"
}
foreach opt {--omf-51 --columns --verbose} {
if {$assembler_ASEM51_config($opt)} {
@@ -1069,8 +1140,17 @@ namespace eval ExternalCompiler {
$::ExternalCompiler::sdcc_optional_string_options_def
array set ::ExternalCompiler::sdcc_scs_string_options \
$::ExternalCompiler::sdcc_scs_string_options_def
+
+ # Make utility
+ foreach {key value} ${::ExternalCompiler::makeutil_config_def} {
+ set ::ExternalCompiler::makeutil_config($key) $value
+ }
}
}
# Initialize NS variables
ExternalCompiler::initialize
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard
diff --git a/lib/compiler/preprocessor.tcl b/lib/compiler/preprocessor.tcl
index 4fca542..d4429ea 100755..100644
--- a/lib/compiler/preprocessor.tcl
+++ b/lib/compiler/preprocessor.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,6 +21,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _PREPROCESSOR_TCL ] } {
+set _PREPROCESSOR_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# DESCRIPTION
# 8051 Assembly language compiler preprocessor. This code is part of Compiler
@@ -34,11 +39,11 @@
#
# Basic principle of operation:
# 1) Remove comments and include files
-# 2) Process controll sequences ($SOMETHING)
+# 2) Process control sequences ($SOMETHING)
# 3) Define as much constants/variables as possible (with cross references)
# 4) Conditional compilation and directive USING
# 5) Define macro instructions
-# 6) Recomposite code acording to ORG directives
+# 6) Recomposite code according to ORG directives
# 7) Expand macro instructions (recursive with cross references)
# 8) Final stage
#
@@ -52,29 +57,30 @@
namespace eval PreProcessor {
## General
- variable asm {} ;# Resulting precompiled code
- variable tmp_asm {} ;# Tempotary auxiliary precompiled code
+ variable asm {} ;# Resulting pre-compiled code
+ variable tmp_asm {} ;# Temporary auxiliary pre-compiled code
variable lineNum 0 ;# Number of the current line
variable fileNum 0 ;# Number of the current file
variable program_memory ;# String of booleans: Map of program memory usage
variable idx 0 ;# Current position in asm list
- variable optims 0 ;# Number of performed optimalizations
+ variable optims 0 ;# Number of performed optimizations
variable macros_first 1 ;# Bool: Define and expand macro instruction before conditional
;#+ assembly and constants expansions
## Errors and warnings
- variable ErrorAtLine 0 ;# Bool: Error occured on the current line
- variable Error 0 ;# Bool: An error occured during precompilation
- variable error_count 0 ;# Number of errors occured
- variable warning_count 0 ;# Number of warnings occured
+ variable ErrorAtLine 0 ;# Bool: Error occurred on the current line
+ variable Error 0 ;# Bool: An error occurred during precompilation
+ variable error_count 0 ;# Number of errors occurred
+ variable warning_count 0 ;# Number of warnings occurred
## Conditional compilation
variable Enable 1 ;# Bool: Compilation enabled (conditional compilation)
variable IfElse_map ;# Array: Conditional compilation map ($IfElse_map($level) == $bool)
+ variable IfElse_pcam ;# Array: Conditional compilation -- Positive condition already met ($IfElse_pcam($level) == $bool)
variable IfElse_level 0 ;# Current level of conditional compilation evaluation
## Memory reservation
- variable selected_segment cseg ;# Current memory segment (one of {cseg bseg dseg iseg xseg})
+ variable selected_segment ;# Current memory segment (one of {cseg bseg dseg iseg xseg})
variable memory_reservation_map ;# Array: memory reservation map (see code)
variable segment_pointer ;# Current memory segment pointer
@@ -112,12 +118,13 @@ namespace eval PreProcessor {
## Macro expansion
variable macro ;# Array: Code of defined macro instructions
variable defined_MACRO {} ;# List of defined macro instructions
+ variable local_M_labels ;# Array of lists: Local labels in macros $local_M_labels($macro_name) == {integer label0 ... labelN}
variable macro_name_to_append ;# Name of currently defined macro instruction
## Special variables
variable original_expression ;# Auxiliary variable (see proc. 'ComputeExpr')
variable tmp ;# General purpose tempotary variable
- variable DB_asm {} ;# Tempotary asm code for creating code memory tables
+ variable DB_asm {} ;# Temporary asm code for creating code memory tables
variable included_files {} ;# List: Unique unsorted list of included files
variable working_dir {} ;# String: Current working directory
variable origin_d_addr {} ;# List: Addresses of static program blocks
@@ -126,7 +133,7 @@ namespace eval PreProcessor {
variable max_include_level 8 ;# Maximum inclusion level
variable max_macro_level 8 ;# Maximum macro expansion level
variable check_sfr_usage 0 ;# Bool: Check for legal usage of SFR and SFB
- variable avaliable_SFR {} ;# List: Avaliable SFR and SFB on the target MCU
+ variable available_SFR {} ;# List: Available SFR and SFB on the target MCU
# ----------------------------------------------------------------
@@ -143,13 +150,13 @@ namespace eval PreProcessor {
;#+ assembly and constants expansions
variable memory_reservation_map ;# Array: memory reservation map (see code)
variable working_dir ;# String: Current working directory
- variable asm ;# Resulting precompiled code
+ variable asm ;# Resulting pre-compiled code
variable segment_pointer ;# Current memory segment pointer
- variable error_count ;# Number of errors occured
- variable warning_count ;# Number of warnings occured
+ variable error_count ;# Number of errors occurred
+ variable warning_count ;# Number of warnings occurred
variable max_include_level ;# Maximum inclusion level
variable max_macro_level ;# Maximum macro expansion level
- variable optims ;# Number of performed optimalizations
+ variable optims ;# Number of performed optimizations
variable included_files ;# List: Unique unsorted list of included files
variable selected_segment ;# Current memory segment (one of {cseg bseg dseg iseg xseg})
variable const_EQU ;# Array: Constants defined by directive 'EQU'
@@ -169,11 +176,11 @@ namespace eval PreProcessor {
set memory_reservation_map(xseg) [ string repeat 0 65536]
# Set constants "??MCU_8051_IDE" and "??VERSION"
- lappend defined_EQU {??MCU_8051_IDE} {??VERSION}
- set const_EQU(??MCU_8051_IDE) 32849
+ lappend defined_EQU {??mcu_8051_ide} {??version}
+ set const_EQU(??mcu_8051_ide) 32849 ;# 8051h
scan $::VERSION "%d.%d.%d" i j k
set i [expr {($i << 8) + ($j << 4) + $k}]
- set const_EQU(??VERSION) $i
+ set const_EQU(??version) $i
# Reset counters of errors and warnings
set error_count 0
@@ -183,11 +190,7 @@ namespace eval PreProcessor {
set working_dir $current_dir
set included_files [list [file normalize [file join $current_dir $filename]]]
- # Message "formating code ..."
set asm $data
- if {!${::Compiler::Settings::QUIET}} {
- ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\tPreformating code ..."]
- }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -201,10 +204,6 @@ namespace eval PreProcessor {
# }
line_numbers
- # Message "include ..."
- if {!${::Compiler::Settings::QUIET}} {
- ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\tPutting program pieces together ..."]
- }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -213,7 +212,7 @@ namespace eval PreProcessor {
# Import code pieces (INCLUDE file.asm // $INCLUDE('file.inc'))
set counter 0
- while 1 {
+ while {1} {
if {![include_directive $current_dir]} {break}
incr counter
if {$counter > $max_include_level} {
@@ -225,10 +224,6 @@ namespace eval PreProcessor {
# Remove code after END directive
end_of_code
- # Message "encapsulating code ..."
- if {!${::Compiler::Settings::QUIET}} {
- ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\tEncapsulating code ..."]
- }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -261,11 +256,6 @@ namespace eval PreProcessor {
define_basic_symbolic_names
}
- # Message "Parsing constants, macros etc."
- if {!${::Compiler::Settings::QUIET}} {
- ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\tParsing constants, macros, etc. ..."]
- }
-
if {$macros_first} {
# Define macro instructions
define_macro_instructions
@@ -277,7 +267,7 @@ namespace eval PreProcessor {
# Expand macro instructions
set counter 0
- while 1 {
+ while {1} {
if {![expand_macro_instructions]} {break}
incr counter
if {$counter > $max_macro_level} {
@@ -299,21 +289,20 @@ namespace eval PreProcessor {
# - Data memory segment selection (BSEG, DSEG, ISEG, XSEG) (group 3)
# - Constant definitions (SET, EQU, BIT, DATA, IDATA, XDATA) (group 4)
# - Date memory reservation (DS, DBIT) (group 5)
- while 1 {
+ while {1} {
if {![parse_Consts_and_ConditionalCompilation {0 0 1 1 1 1} 1]} {
break
}
}
- parse_Consts_and_ConditionalCompilation {1 1 1 1 1 1} 1
- set selected_segment cseg
+ parse_Consts_and_ConditionalCompilation {1 1 1 1 1 1} 1
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
return
}
- # Parse code memory segmentation (CSEG DB DW)
+ # Process code memory related directives (CSEG DB DW)
code_segment 1
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
@@ -331,7 +320,7 @@ namespace eval PreProcessor {
}
}
- # Reassemble code acording to ORG directives
+ # Reassemble code according to ORG directives
origin_directive
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
@@ -339,15 +328,10 @@ namespace eval PreProcessor {
return
}
- # Message "Expanding macros"
- if {!${::Compiler::Settings::QUIET}} {
- ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\tExpanding macros ..."]
- }
-
if {!$macros_first} {
# Expand macro instructions
set counter 0
- while 1 {
+ while {1} {
if {![expand_macro_instructions]} {break}
incr counter
if {$counter > $max_macro_level} {
@@ -362,11 +346,6 @@ namespace eval PreProcessor {
}
}
- # Message "Final stage"
- if {!${::Compiler::Settings::QUIET}} {
- ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\tFinal stage ..."]
- }
-
## Do three things:
# * Convert code to this format:
# {
@@ -379,18 +358,14 @@ namespace eval PreProcessor {
# * Create map of program memory usage (bitmap)
parse_instructions
- # Perform code optimalizations
+ # Perform code optimizations
set optims 0
if {${::Compiler::Settings::optim_ena}} {
- # Message "Optimalizations"
- if {!${::Compiler::Settings::QUIET}} {
- ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\tOptimalizations ..."]
- }
- optimalization
+ optimization
}
# Final constants expansion
- while 1 {
+ while {1} {
if {![parse_Consts_and_ConditionalCompilation {0 0 1 1 1 1} 0]} {
break
}
@@ -434,6 +409,7 @@ namespace eval PreProcessor {
variable const_SET ;# Array: Constants defined by directive 'CODE'
variable const_EQU ;# Array: Constants defined by directive 'EQU'
variable macro ;# Array: Code of defined macro instructions
+ variable local_M_labels ;# Array of lists: Local labels in macros $local_M_labels($macro_name) == {integer label0 ... labelN}
variable program_memory ;# String of booleans: Map of program memory usage
variable labels ;# Array: Values of defined labels ($labels($label) == $address)
variable defined_BIT {} ;# List of defined bits (directove 'BIT')
@@ -449,6 +425,7 @@ namespace eval PreProcessor {
variable defined_MACRO {} ;# List of defined macro instructions
catch {unset macro}
+ catch {unset local_M_labels}
catch {unset memory_reservation_map}
catch {unset segment_pointer}
catch {unset const_BIT}
@@ -469,7 +446,7 @@ namespace eval PreProcessor {
# INTERNAL AUXILIARY PROCEDURES
# ----------------------------------------------------------------
- ## Define basic symbolic names acording to MapOfSFRArea, MapOfSFRBitArea and progVectors
+ ## Define basic symbolic names according to MapOfSFRArea, MapOfSFRBitArea and progVectors
# @return void
proc define_basic_symbolic_names {} {
variable const_BIT ;# Array: Bit values -- ($const_BIT($bit_name) == $value)
@@ -480,7 +457,7 @@ namespace eval PreProcessor {
variable defined_CODE ;# List of constants defined by 'CODE'
# Define bits
- foreach def ${CompilerConsts::MapOfSFRBitArea} {
+ foreach def ${::CompilerConsts::MapOfSFRBitArea} {
set var [lindex $def 0] ;# Name
set val [lindex $def 1] ;# Address
# Adjust name
@@ -491,7 +468,7 @@ namespace eval PreProcessor {
}
# Define registers
- foreach def ${CompilerConsts::MapOfSFRArea} {
+ foreach def ${::CompilerConsts::MapOfSFRArea} {
set var [lindex $def 0] ;# Name
set val [lindex $def 1] ;# Address
# Adjust name
@@ -502,7 +479,7 @@ namespace eval PreProcessor {
}
# Define Program vectors
- foreach def ${CompilerConsts::progVectors} {
+ foreach def ${::CompilerConsts::progVectors} {
set var [lindex $def 0] ;# Name
set val [lindex $def 1] ;# Address
# Adjust name
@@ -528,7 +505,7 @@ namespace eval PreProcessor {
if {[regexp {^\w+} $data control]} {
regsub {^\w+} $data {} data
set control [string tolower $control]
- } {
+ } else {
set control {}
}
@@ -548,12 +525,12 @@ namespace eval PreProcessor {
if {[string index $argument 0] == {'}} {
if {[string index $argument end] != {'}} {
SyntaxError $lineNum $fileNum [mc "Invalid argument: %s" $argument]
- } {
+ } else {
set argument [string trimleft $argument {'}]
set argument [string trimright $argument {'}]
}
}
- } {
+ } else {
set argument {}
}
@@ -572,20 +549,20 @@ namespace eval PreProcessor {
# @parm String setting - Target configuration variable
# @parm String value - New configuration value
# @return Bool - One if setting was accepted, zero if setting was dismissed
- proc AssemlerContol {condition setting value} {
+ proc AssemblerContol {condition setting value} {
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
# Determinate condition value
- set condition [subst "\${::Compiler::Settings::$condition}"]
+ set condition [subst -nocommands "\${::Compiler::Settings::$condition}"]
# Accept
if {$condition == 0} {
set Compiler::Settings::$setting $value
return 1
# Dismiss
- } {
- Notice $lineNum $fileNum [mc "Control %s has been overrriden (by compiler settings)" $setting]
+ } else {
+ Notice $lineNum $fileNum [mc "Control %s has been overridden (by compiler settings)" $setting]
return 0
}
}
@@ -594,7 +571,7 @@ namespace eval PreProcessor {
# @parm String control - Control sequence (name only)
# @parm String argument - Argument (without parantesis and quotes)
# @return Bool - result (1 == success; 0 == error message)
- proc AssemlerContol_expect_one_argument {control argument} {
+ proc AssemblerContol_expect_one_argument {control argument} {
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
@@ -610,7 +587,7 @@ namespace eval PreProcessor {
# @parm String control - Control sequence (name only)
# @parm String argument - Argument (without parantesis and quotes)
# @return Bool - result (1 == success; 0 == error message)
- proc AssemlerContol_expect_no_argument {control argument} {
+ proc AssemblerContol_expect_no_argument {control argument} {
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
@@ -624,8 +601,8 @@ namespace eval PreProcessor {
## Evaluate and remove control sequences
# @return void
proc parse_controls {} {
- variable asm ;# Resulting precompiled code
- variable tmp_asm ;# Tempotary auxiliary precompiled code
+ variable asm ;# Resulting pre-compiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable idx ;# Current position in asm list
@@ -642,7 +619,9 @@ namespace eval PreProcessor {
incr idx
# Update after each 25 iterations
- if {[expr {$idx % 25}] == 0} ${::Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 25}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -669,178 +648,178 @@ namespace eval PreProcessor {
set control [lindex $ctrl 0] ;# Name
set argument [lindex $ctrl 1] ;# Argument
- # Adjust compiler settings acording to the control sequence
+ # Adjust compiler settings according to the control sequence
switch -- $control {
{nomacrosfirst} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
set macros_first 0
}
}
{eject} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
CodeListing::directive_eject $idx
}
}
{ej} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
CodeListing::directive_eject $idx
}
}
{nolist} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
CodeListing::directive_nolist $idx
}
}
{noli} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
CodeListing::directive_nolist $idx
}
}
{list} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
CodeListing::directive_list $idx
}
}
{li} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
CodeListing::directive_list $idx
}
}
{nomod} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
- AssemlerContol _nomod NOMOD 1
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
+ AssemblerContol _nomod NOMOD 1
}
}
{nomod51} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
- AssemlerContol _nomod NOMOD 1
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
+ AssemblerContol _nomod NOMOD 1
}
}
{nomo} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
- AssemlerContol _nomod NOMOD 1
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
+ AssemblerContol _nomod NOMOD 1
}
}
{paging} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
- AssemlerContol _paging PAGING 1
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
+ AssemblerContol _paging PAGING 1
}
}
{pi} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
- AssemlerContol _paging PAGING 1
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
+ AssemblerContol _paging PAGING 1
}
}
{nopaging} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
- AssemlerContol _paging PAGING 0
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
+ AssemblerContol _paging PAGING 0
}
}
{nopi} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
- AssemlerContol _paging PAGING 0
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
+ AssemblerContol _paging PAGING 0
}
}
{pagewidth} {
- if {[AssemlerContol_expect_one_argument $control $argument]} {
+ if {[AssemblerContol_expect_one_argument $control $argument]} {
if {[regexp {^\d+$} $argument]} {
- AssemlerContol _pagewidth PAGEWIDTH $argument
- } {
+ AssemblerContol _pagewidth PAGEWIDTH $argument
+ } else {
SyntaxError $lineNum $fileNum \
[mc "Invalid argument (must be integer): %s" $argument]
}
}
}
{pw} {
- if {[AssemlerContol_expect_one_argument $control $argument]} {
+ if {[AssemblerContol_expect_one_argument $control $argument]} {
if {[regexp {^\d+$} $argument]} {
- AssemlerContol _pagewidth PAGEWIDTH $argument
- } {
+ AssemblerContol _pagewidth PAGEWIDTH $argument
+ } else {
SyntaxError $lineNum $fileNum \
[mc "Invalid argument (must be integer): %s" $argument]
}
}
}
{pagelength} {
- if {[AssemlerContol_expect_one_argument $control $argument]} {
+ if {[AssemblerContol_expect_one_argument $control $argument]} {
if {[regexp {^\d+$} $argument]} {
- AssemlerContol _pagelength PAGELENGTH $argument
- } {
+ AssemblerContol _pagelength PAGELENGTH $argument
+ } else {
SyntaxError $lineNum $fileNum \
[mc "Invalid argument (must be integer): %s" $argument]
}
}
}
{pl} {
- if {[AssemlerContol_expect_one_argument $control $argument]} {
+ if {[AssemblerContol_expect_one_argument $control $argument]} {
if {[regexp {^\d+$} $argument]} {
- AssemlerContol _pagelength PAGELENGTH $argument
- } {
+ AssemblerContol _pagelength PAGELENGTH $argument
+ } else {
SyntaxError $lineNum $fileNum \
[mc "Invalid argument (must be integer): %s" $argument]
}
}
}
{title} {
- if {[AssemlerContol_expect_one_argument $control $argument]} {
- AssemlerContol _title TITLE $argument
+ if {[AssemblerContol_expect_one_argument $control $argument]} {
+ AssemblerContol _title TITLE $argument
}
}
{tt} {
- if {[AssemlerContol_expect_one_argument $control $argument]} {
- AssemlerContol _title TITLE $argument
+ if {[AssemblerContol_expect_one_argument $control $argument]} {
+ AssemblerContol _title TITLE $argument
}
}
{date} {
- if {[AssemlerContol_expect_one_argument $control $argument]} {
- AssemlerContol _date DATE $argument
+ if {[AssemblerContol_expect_one_argument $control $argument]} {
+ AssemblerContol _date DATE $argument
}
}
{da} {
- if {[AssemlerContol_expect_one_argument $control $argument]} {
- AssemlerContol _date DATE $argument
+ if {[AssemblerContol_expect_one_argument $control $argument]} {
+ AssemblerContol _date DATE $argument
}
}
{object} {
- if {[AssemlerContol_expect_one_argument $control $argument]} {
- AssemlerContol _object OBJECT_FILE $argument
- AssemlerContol _object OBJECT 1
+ if {[AssemblerContol_expect_one_argument $control $argument]} {
+ AssemblerContol _object OBJECT_FILE $argument
+ AssemblerContol _object OBJECT 1
}
}
{noobject} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
- AssemlerContol _object OBJECT 0
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
+ AssemblerContol _object OBJECT 0
}
}
{nosb} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
- AssemlerContol _symbols SYMBOLS 0
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
+ AssemblerContol _symbols SYMBOLS 0
}
}
{nosymbols} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
- AssemlerContol _symbols SYMBOLS 0
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
+ AssemblerContol _symbols SYMBOLS 0
}
}
{noprint} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
- AssemlerContol _print PRINT 0
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
+ AssemblerContol _print PRINT 0
}
}
{symbols} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
- AssemlerContol _symbols SYMBOLS 1
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
+ AssemblerContol _symbols SYMBOLS 1
}
}
{sb} {
- if {[AssemlerContol_expect_no_argument $control $argument]} {
- AssemlerContol _symbols SYMBOLS 1
+ if {[AssemblerContol_expect_no_argument $control $argument]} {
+ AssemblerContol _symbols SYMBOLS 1
}
}
{print} {
- if {[AssemlerContol_expect_one_argument $control $argument]} {
- AssemlerContol _print PRINT_FILE $argument
- AssemlerContol _print PRINT 1
+ if {[AssemblerContol_expect_one_argument $control $argument]} {
+ AssemblerContol _print PRINT_FILE $argument
+ AssemblerContol _print PRINT 1
}
}
default {
@@ -858,20 +837,19 @@ namespace eval PreProcessor {
# @parm Bool ignore_undefined - Ignore undefined symbolic names
# @return void
proc code_segment {ignore_undefined} {
- variable asm ;# Resulting precompiled code
- variable tmp_asm ;# Tempotary auxiliary precompiled code
+ variable asm ;# Resulting pre-compiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable selected_segment ;# Current memory segment (one of {cseg bseg dseg iseg xseg})
variable segment_pointer ;# Current memory segment pointer
- variable DB_asm ;# Tempotary asm code for creating code memory tables
variable idx ;# Current position in asm list
# Reset NS variables
- set DB_asm {}
- set value {}
set tmp_asm {}
set segment_pointer(cseg) {}
+
+ set value {}
set idx -1
# Iterate over the code
@@ -879,7 +857,9 @@ namespace eval PreProcessor {
incr idx
# Update after each 25 iterations
- if {[expr {$idx % 25}] == 0} ${::Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 25}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -909,32 +889,41 @@ namespace eval PreProcessor {
# Directive 'CSEG' - code segment selection
} elseif {$directive == {cseg}} {
+ set discontinue 0
- # Check if there is no label
+ # Check if there is a label
if {[lindex $cmd 0] != {}} {
SyntaxError $lineNum $fileNum [mc "CSEG cannot take any label: %s" [lindex $cmd 0]]
- continue
+ set discontinue 1
}
- # Select code segment
- set selected_segment {cseg}
+ if {!$discontinue} {
+ # Set the code segment
+ set selected_segment {cseg}
- # Remove this line from the code listing
- CodeListing::delete_line $idx
+ # Check for presence of an address expression
+ set expr [lindex $cmd 2]
+ if {$expr == {}} {
+ set segment_pointer(cseg) {}
+ set discontinue 1
+ }
- # Check for presence of address expression
- set expr [lindex $cmd 2]
- if {$expr == {}} {
- set segment_pointer(cseg) {}
- continue
+ if {!$discontinue} {
+ # Check for presence of 'AT' operator (CSEG AT addr)
+ if {[string tolower [lindex $expr 0]] != {at}} {
+ SyntaxError $lineNum $fileNum [mc "Missing `AT' operator"]
+ set discontinue 1
+ }
+ set expr [lreplace $expr 0 0]
+ }
}
- # Check for presence of 'AT' operator (CSEG AT addr)
- if {[string tolower [lindex $expr 0]] != {at}} {
- SyntaxError $lineNum $fileNum [mc "Missing `AT' operator"]
+ # Remove this line from the code listing
+ if {$discontinue} {
+ CodeListing::delete_line $idx
+ incr idx -1
continue
}
- set expr [lreplace $expr 0 0]
# Determinate, set and validate segment pointer
set value [ComputeExpr $expr]
@@ -947,9 +936,11 @@ namespace eval PreProcessor {
# Set pointer
set segment_pointer(cseg) $value
# Adjust code
- lappend DB_asm [list $lineNum [list {ORG} $value]]
- } {
+ lappend tmp_asm [list $lineNum $fileNum [list {ORG} $value]]
+ } else {
SyntaxError $lineNum $fileNum [mc "Invalid expression `%s'" $expr]
+ CodeListing::delete_line $idx
+ incr idx -1
}
# Line does not contain any of {CSEG DB DW}
@@ -960,13 +951,12 @@ namespace eval PreProcessor {
# Finalize code adjustment
append tmp_asm { }
- append tmp_asm $DB_asm
set asm $tmp_asm
}
## Reserve code memory (byte or word) -- directives 'DB' 'DW'
# -- auxiliary procedure for proc. 'code_segment'
- # This procedure writes result to NS variable 'DB_asm' or 'tmp_asm'
+ # This procedure writes result to NS variable 'tmp_asm'
# @parm String cmd - Line of source code adjusted by proc. 'split_line'
# @parm String directive - Directive name (one of {DB DW})
# @parm String idx - Source index (precompiled code list)
@@ -977,8 +967,7 @@ namespace eval PreProcessor {
variable fileNum ;# Number of the current file
variable selected_segment ;# Current memory segment (one of {cseg bseg dseg iseg xseg})
variable segment_pointer ;# Current memory segment pointer
- variable DB_asm ;# Tempotary asm code for creating code memory tables
- variable tmp_asm ;# Tempotary auxiliary precompiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
# Determinate maximum value
if {$directive == {db}} {
@@ -987,7 +976,7 @@ namespace eval PreProcessor {
} elseif {$directive == {dw}} {
set directive_db 0
set max 65535
- } {
+ } else {
CompilationError $lineNum $fileNum "Unknown error 7"
return
}
@@ -1023,9 +1012,11 @@ namespace eval PreProcessor {
# Iterate over directive operands
set first_time 1
set undefined 0
+ set total_len 0
foreach opr $operands {
set undefined 0
set len -1
+
# Operand is a string
if {![isExpression $opr] && ([string index $opr 0] == {'}) && ([string index $opr end] == {'})} {
# Adjust operand
@@ -1052,33 +1043,27 @@ namespace eval PreProcessor {
continue
# Valid value
- } {
+ } else {
if {$first_time} {
set line [list [list $lineNum $fileNum "${label}DB $value"]]
- } {
+ } else {
set line [list [list $lineNum $fileNum [list DB $value]]]
}
set first_time 0
lappend values $value
}
- # Adjust precompiled code
- if {$segment_pointer(cseg) != {}} {
- append DB_asm { }
- append DB_asm $line
- } {
- append tmp_asm { }
- append tmp_asm $line
- }
incr len
+
+ # Adjust precompiled code
+ append tmp_asm { }
+ append tmp_asm $line
}
# Adjust code listing
CodeListing::db $idx $values
CodeListing::insert_empty_lines $idx $len
- incr idx $len
-
# Operand is a direct numerical value, expression, constant, label or variable
} else {
@@ -1093,7 +1078,7 @@ namespace eval PreProcessor {
set value $opr
# Invalid value
- } {
+ } else {
CompilationError $lineNum $fileNum [mc "Invalid expression `%s'" $opr]
continue
}
@@ -1116,20 +1101,23 @@ namespace eval PreProcessor {
if {$directive_db} {
if {$first_time} {
set line [list [list $lineNum $fileNum "${label}DB $value"]]
- } {
+ } else {
set line [list [list $lineNum $fileNum [list DB $value]]]
}
- CodeListing::db $idx $value
+
incr len
set first_time 0
+ # Adjust code listing
+ CodeListing::db $idx $value
+
# Two bytes (directive DW)
- } {
+ } else {
# Spilt value into high- and low-order bytes
if {$undefined} {
set H_value "(($value) / 256)"
set L_value "(($value) % 256)"
- } {
+ } else {
set H_value [expr {$value / 256}]
set L_value [expr {$value % 256}]
}
@@ -1138,35 +1126,34 @@ namespace eval PreProcessor {
[list $lineNum $fileNum "${label}DB {$H_value}"]\
[list $lineNum $fileNum [list {DB} $L_value]] \
]
- } {
+ } else {
set line [list \
[list $lineNum $fileNum [list {DB} $H_value]] \
[list $lineNum $fileNum [list {DB} $L_value]] \
]
}
+
+ incr len 2
set first_time 0
# Adjust code listing
CodeListing::db $idx [list $H_value $L_value]
CodeListing::insert_empty_lines $idx 1
-
- incr len 2
- incr idx $len
}
# Adjust precompiled code
- if {$segment_pointer(cseg) != {}} {
- append DB_asm { }
- append DB_asm $line
- } {
- append tmp_asm { }
- append tmp_asm $line
- }
+ append tmp_asm { }
+ append tmp_asm $line
}
+
+ incr len
+ incr total_len $len
}
CodeListing::insert_empty_lines $idx [expr {[llength $operands] - 1}]
- return $len
+
+ incr total_len -1
+ return $total_len
}
## Split the given line of code into label, command and argumet(s)
@@ -1176,7 +1163,7 @@ namespace eval PreProcessor {
# Determinate label
if {[regexp {^\w+:} $line label]} {
regsub {^\w+:\s*} $line {} line
- } {
+ } else {
set label {}
}
# If line contains only label -> return only label
@@ -1187,7 +1174,7 @@ namespace eval PreProcessor {
# Determinate command and argumet(s)
if {![regexp {^\s*\.?\w+} $line command]} {
set command {}
- } {
+ } else {
set command [string tolower [string trim $command]]
}
set argument [regsub {^[^\s]+\s*} $line {}]
@@ -1212,7 +1199,7 @@ namespace eval PreProcessor {
if {$instruction == {db}} {
set new_operands $operands
set operands {}
- } {
+ } else {
set new_operands {}
}
@@ -1221,6 +1208,7 @@ namespace eval PreProcessor {
# Fixed value (eg. 'A')
if {[isFixed $opr]} {
+ set char {}
set opr_val $opr
# Regular value
@@ -1229,14 +1217,14 @@ namespace eval PreProcessor {
set char [string index $opr 0]
if {$char == {#} || $char == {@} || $char == {/}} {
set opr [string replace $opr 0 0]
- } {
+ } else {
set char {}
}
- set opr_val $char
+ set opr_val {}
# Value is an expression
if {[isExpression $opr]} {
- append opr_val [ComputeExpr $opr {} $address]
+ append opr_val [ComputeExpr $opr $ignore_undefined $address]
# Value is bit addres represented by dot notation
} elseif {[regexp {^\w+\.\w+$} $opr]} {
@@ -1245,7 +1233,7 @@ namespace eval PreProcessor {
if {!$ignore_undefined} {
SyntaxError $lineNum $fileNum [mc "Expected bit address: %s" $opr]
}
- } {
+ } else {
set bitAddr [getBitAddr $opr $ignore_undefined]
if {$bitAddr == {}} {set bitAddr 0}
append opr_val $bitAddr
@@ -1282,33 +1270,44 @@ namespace eval PreProcessor {
}
# Adjust relative offset
- if {[string is digit -strict $opr_val] && $type == {code8}} {
- incr opr_val -$address
- incr opr_val -$instr_lenght
- if {($opr_val > 127) || ($opr_val < -128)} {
- incr opr_val -0x10000
+ if {[string is digit -strict $opr_val]} {
+ if {$type == {code8}} {
+ incr opr_val -$address
+ incr opr_val -$instr_lenght
if {($opr_val > 127) || ($opr_val < -128)} {
+ incr opr_val -0x10000
+ if {($opr_val > 127) || ($opr_val < -128)} {
+ if {!$ignore_undefined} {
+ SyntaxError $lineNum $fileNum \
+ [mc "Label is too far for 8-bit relative addressing.\nTry to disable peephole optimizations if they are on."]
+ }
+ set opr_val 0
+ }
+ }
+ if {$opr_val < 0} {
+ incr opr_val 0x100
+ }
+ } elseif {$type == {code11}} {
+ if {($opr_val & 0x0f800) != (($address + $instr_lenght) & 0x0f800)} {
if {!$ignore_undefined} {
- SyntaxError $lineNum $fileNum \
- [mc "Label is too far for 8-bit relative addressing.\nTry to disable peephole optimalizations if they are on."]
+ SyntaxError $lineNum $fileNum [mc "Operand value out of range: `%s' (`%s')" $opr $opr_val]
}
set opr_val 0
+ } else {
+ set opr_val [expr {$opr_val & 0x007ff}]
}
}
- if {$opr_val < 0} {
- incr opr_val 0x100
- }
}
}
# Adjust list of operands
- lappend new_operands $opr_val
+ lappend new_operands "${char}${opr_val}"
# Check for valid value range
if {$opr_val != {} && ![checkRange $opr_val $type]} {
if {!$ignore_undefined && [string is digit -strict $opr_val]} {
SyntaxError $lineNum $fileNum [mc "Operand value out of range: `%s' (`%s')" $opr $opr_val]
- } {
+ } else {
return {}
}
}
@@ -1321,8 +1320,8 @@ namespace eval PreProcessor {
## Finaly precompiled encapsulate code to the resulting form
# @return void
proc final_stage {} {
- variable asm ;# Resulting precompiled code
- variable tmp_asm ;# Tempotary auxiliary precompiled code
+ variable asm ;# Resulting pre-compiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable idx ;# Current position in asm list
@@ -1337,7 +1336,9 @@ namespace eval PreProcessor {
incr idx
# Update after each 25 iterations
- if {[expr {$idx % 25}] == 0} ${::Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 25}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -1367,11 +1368,11 @@ namespace eval PreProcessor {
}
# Check for instruction validity
- } elseif {[lsearch -exact -ascii ${CompilerConsts::AllInstructions} $instruction] == -1} {
+ } elseif {[lsearch -exact -ascii ${::CompilerConsts::AllInstructions} $instruction] == -1} {
if {[string index $address end] == {:}} {
- SyntaxError $lineNum $fileNum [mc "Invalid label declaration: `%s'\n\tLabels can contain alfanumeric characters only and must not begin with a digit" $address]
- } {
- SyntaxError $lineNum $fileNum [mc "Unknown keyword: `%s'\n\t`%s' is neighter macro nor instruction nor directive" [lindex $address 0] [lindex $address 0]]
+ SyntaxError $lineNum $fileNum [mc "Invalid label declaration: `%s'\n\tLabels can contain alphanumeric characters only and must not begin with a digit" $address]
+ } else {
+ SyntaxError $lineNum $fileNum [mc "Unknown keyword: `%s'\n\t`%s' is neither macro nor instruction nor directive" [lindex $address 0] [lindex $address 0]]
}
continue
}
@@ -1416,7 +1417,7 @@ namespace eval PreProcessor {
$ignore_undefined \
]
# Register is regular number
- } {
+ } else {
set regAddr [COprToDec $opr0]
}
@@ -1427,7 +1428,7 @@ namespace eval PreProcessor {
$ignore_undefined \
]
# Bit is regular number
- } {
+ } else {
set bitNum [COprToDec $opr1]
}
@@ -1439,7 +1440,7 @@ namespace eval PreProcessor {
# Register is in high bit addressable area
if {$regAddr > 31 && $regAddr < 48} {
- return [expr {$regAddr - 32 + $bitNum}]
+ return [expr {($regAddr - 32) * 8 + $bitNum}]
# Register bit addressable SFR
} elseif {[lsearch -exact -ascii {128 136 144 152 160 168 176 184 208 224 240} $regAddr] != -1} {
return [expr {$regAddr + $bitNum}]
@@ -1458,7 +1459,7 @@ namespace eval PreProcessor {
variable fileNum ;# Number of the current file
# If the given operand is fixed string -> return it unchanged
- if {[lsearch -exact -ascii ${CompilerConsts::FixedOperands} [string tolower $operand]] != -1} {
+ if {[lsearch -exact -ascii ${::CompilerConsts::FixedOperands} [string tolower $operand]] != -1} {
return $operand
}
@@ -1466,10 +1467,23 @@ namespace eval PreProcessor {
set char [string index $operand 0]
if {$char == {#} || $char == {@} || $char == {/}} {
set operand [string replace $operand 0 0]
- } {
+ } else {
set char {}
}
+ # Handle prefix notation for hexadecimal numbers, like 0xfa
+ if {
+ [string index $operand 0] == {0}
+ &&
+ ([string index $operand 1] == {x} || [string index $operand 1] == {X})
+ } then {
+ set operand [string replace $operand 0 1]
+ if {![string is digit [string index $operand 0]]} {
+ set operand "0${operand}"
+ }
+ append operand {h}
+ }
+
# Determinate numeric base and adjust operand string
set base [string index $operand end]
set operand [string range $operand 0 {end-1}]
@@ -1481,17 +1495,17 @@ namespace eval PreProcessor {
# Convert and return
if {[NumSystem::isdec $operand]} {
return "$char$operand"
- } {
+ } else {
SyntaxError $lineNum $fileNum [mc "Invalid value: `%s'" "${char}${operand}"]
}
- # Value is charater
+ # Value is a charater
} elseif {$base == {'}} {
# Remove leading quote
if {[string index $operand 0] != {'}} {
SyntaxError $lineNum $fileNum [mc "Invalid value: `%s'" "${char}${operand}"]
return {}
- } {
+ } else {
set operand [string range $operand 1 end]
}
}
@@ -1503,7 +1517,7 @@ namespace eval PreProcessor {
if {[NumSystem::ishex $operand]} {
set operand [expr "0x$operand"]
return "$char$operand"
- } {
+ } else {
SyntaxError $lineNum $fileNum [mc "Invalid value: `%s'" "${operand}${base}"]
return {}
}
@@ -1512,7 +1526,7 @@ namespace eval PreProcessor {
if {[NumSystem::isbin $operand]} {
set operand [NumSystem::bin2dec $operand]
return "$char$operand"
- } {
+ } else {
SyntaxError $lineNum $fileNum [mc "Invalid value: `%s'" "${operand}${base}"]
return {}
}
@@ -1521,7 +1535,7 @@ namespace eval PreProcessor {
if {[NumSystem::isoct $operand]} {
set operand [NumSystem::oct2dec $operand]
return "$char$operand"
- } {
+ } else {
SyntaxError $lineNum $fileNum [mc "Invalid value: `%s'" "${operand}${base}"]
return {}
}
@@ -1530,7 +1544,7 @@ namespace eval PreProcessor {
if {[NumSystem::isoct $operand]} {
set operand [NumSystem::oct2dec $operand]
return "$char$operand"
- } {
+ } else {
SyntaxError $lineNum $fileNum [mc "Invalid value: `%s'" "${operand}${base}"]
return {}
}
@@ -1538,7 +1552,7 @@ namespace eval PreProcessor {
{'} { ;# From character
if {[string length $operand] != 0} {
set operand $char[character2number [subst -nocommands -novariables $operand]]
- } {
+ } else {
SyntaxError $lineNum $fileNum [mc "Invalid value: `%s'" $operand]
return {}
}
@@ -1546,7 +1560,7 @@ namespace eval PreProcessor {
{d} { ;# From decimal (no conversion)
if {[NumSystem::isdec $operand]} {
return "$char$operand"
- } {
+ } else {
SyntaxError $lineNum $fileNum [mc "Invalid value: `%s'" "${operand}${base}"]
return {}
}
@@ -1571,10 +1585,10 @@ namespace eval PreProcessor {
set operand [string tolower $operand]
# Fixed operand
- if {[lsearch -exact -ascii ${CompilerConsts::FixedOperands} $operand] != -1} {
+ if {[lsearch -exact -ascii ${::CompilerConsts::FixedOperands} $operand] != -1} {
if {$operand == $type} {
return 1
- } {
+ } else {
return 0
}
}
@@ -1583,7 +1597,7 @@ namespace eval PreProcessor {
set char [string index $operand 0]
if {$char == {#} || $char == {@} || $char == {/}} {
set operand [string trimleft $operand {#@/}]
- } {
+ } else {
set char {}
}
@@ -1607,7 +1621,11 @@ namespace eval PreProcessor {
}
# Check for allowed range
- if {$operand > $max || $operand < 0} {return 0} {return 1}
+ if {$operand > $max || $operand < 0} {
+ return 0
+ } else {
+ return 1
+ }
}
## Determinate whether the given string is an expression
@@ -1621,9 +1639,9 @@ namespace eval PreProcessor {
set expression [string trimleft $expression "\t "]
set expression [string trimright $expression "\t "]
- if {[regexp {[ \+\-\=<>\(\)\*/%]} $expression]} {
+ if {[regexp {[ \?\+\-\=<>\(\)\*/%]} $expression]} {
return 1
- } {
+ } else {
return 0
}
}
@@ -1633,9 +1651,9 @@ namespace eval PreProcessor {
# @return Bool - result (1 == is fixed; 0 == is not fixed)
proc isFixed {operand} {
set operand [string tolower $operand]
- if {[lsearch -exact -ascii ${CompilerConsts::FixedOperands} $operand] != -1} {
+ if {[lsearch -exact -ascii ${::CompilerConsts::FixedOperands} $operand] != -1} {
return 1
- } {
+ } else {
return 0
}
}
@@ -1653,7 +1671,7 @@ namespace eval PreProcessor {
# Check if the string starts with a digit or quote
if {[regexp {^(\d|')} $symbolic_name]} {
return 0
- } {
+ } else {
return 1
}
}
@@ -1668,7 +1686,7 @@ namespace eval PreProcessor {
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable check_sfr_usage;# Bool: Check for legal usage of SFR and SFB
- variable avaliable_SFR ;# List: Avaliable SFR and SFB on the target MCU
+ variable available_SFR ;# List: Available SFR and SFB on the target MCU
variable const_BIT ;# Array: Bit values -- ($const_BIT($bit_name) == $value)
variable const_CODE ;# Array: Constants defined by directive 'CODE'
@@ -1699,13 +1717,13 @@ namespace eval PreProcessor {
if {
([lsearch -exact -ascii $defined_LABEL $symbolic_name] == -1) &&
($symbolic_name != "\$")
- } {
+ } then {
continue
}
if {$symbolic_name == "\$"} {
set value $address
- } {
+ } else {
set value $labels($symbolic_name)
}
CodeListing::symbol_used $symbolic_name {label}
@@ -1737,9 +1755,9 @@ namespace eval PreProcessor {
if {
[lsearch -ascii -exact $::CompilerConsts::defined_SFR $symbolic_name] != -1
&&
- [lsearch -ascii -exact $avaliable_SFR $symbolic_name] == -1
- } {
- Warning $lineNum $fileNum [mc "Special function register \"%s\" is not avaliable on the target MCU" [string toupper $symbolic_name]]
+ [lsearch -ascii -exact $available_SFR $symbolic_name] == -1
+ } then {
+ Warning $lineNum $fileNum [mc "Special function register \"%s\" is not available on the target MCU" [string toupper $symbolic_name]]
}
}
@@ -1754,9 +1772,9 @@ namespace eval PreProcessor {
if {
[lsearch -ascii -exact $::CompilerConsts::defined_SFRBitArea $symbolic_name] != -1
&&
- [lsearch -ascii -exact $avaliable_SFR $symbolic_name] == -1
- } {
- Warning $lineNum $fileNum [mc "Special function bit \"%s\" is not avaliable on the target MCU" [string toupper $symbolic_name]]
+ [lsearch -ascii -exact $available_SFR $symbolic_name] == -1
+ } then {
+ Warning $lineNum $fileNum [mc "Special function bit \"%s\" is not available on the target MCU" [string toupper $symbolic_name]]
}
}
@@ -1771,7 +1789,7 @@ namespace eval PreProcessor {
set val [const_value $symbolic_name $lineNum]
if {$val == {}} {
break
- } {
+ } else {
CodeListing::symbol_used $symbolic_name {equset}
return $val
}
@@ -1789,19 +1807,19 @@ namespace eval PreProcessor {
return {}
}
- ## Perform peerhole optimalization
+ ## Perform peerhole optimization
# This function must be called between "parse_instructions" and "final_stage"
# @return void
- proc optimalization {} {
- variable asm ;# Resulting precompiled code
- variable tmp_asm ;# Tempotary auxiliary precompiled code
+ proc optimization {} {
+ variable asm ;# Resulting pre-compiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable idx ;# Current position in asm list
variable labels ;# Array: Values of defined labels ($labels($label) == $address)
variable defined_LABEL ;# List of defined labels
variable program_memory ;# String of booleans: Map of program memory usage
- variable optims ;# Number of performed optimalizations
+ variable optims ;# Number of performed optimizations
variable origin_d_addr ;# List: Addresses of static program blocks
# Iterate over the code
@@ -1810,7 +1828,9 @@ namespace eval PreProcessor {
for {set idx 0} {$idx < $asm_len} {incr idx} {
# Update after each 25 iterations
- if {[expr {$idx % 25}] == 0} ${::Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 25}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -1876,7 +1896,7 @@ namespace eval PreProcessor {
} elseif {
[lindex $operand_types 0] != {code8} &&
[lindex $operand_types 0] != {code11} &&
- [lindex $operands_abs 0] < 2048
+ ($address & 0x0f800) == ([lindex $operands_abs 0] & 0x0f800)
} then {
set instruction {ajmp}
set operand_types {code11}
@@ -1888,7 +1908,7 @@ namespace eval PreProcessor {
## A)
if {[string is digit -strict [lindex $operands_abs 0]]} {
set diff [expr {$address - [lindex $operands_abs 0]}]
- } {
+ } else {
set diff 200 ;# Some value out of range [-126; 129]
}
if {$diff >= -126 && $diff <= 129} {
@@ -1906,7 +1926,7 @@ namespace eval PreProcessor {
{ajmp} { ;# AJMP code8 --> SJMP code8
if {[string is digit -strict [lindex $operands_abs 0]]} {
set diff [expr {$address - [lindex $operands_abs 0]}]
- } {
+ } else {
set diff 200 ;# Some value out of range [-126; 129]
}
if {$diff >= -126 && $diff <= 129} {
@@ -1915,7 +1935,11 @@ namespace eval PreProcessor {
}
}
{call} { ;# CALL code11 --> ACALL code11
- if {[lindex $operand_types 0] != {code11} && [lindex $operands_abs 0] < 2048} {
+ if {
+ [lindex $operand_types 0] != {code11}
+ &&
+ ($address & 0x0f800) == ([lindex $operands_abs 0] & 0x0f800)
+ } then {
set instruction {acall}
set operand_types {code11}
set bytes_saved 1
@@ -1935,7 +1959,7 @@ namespace eval PreProcessor {
[lindex $operands_abs 0] == 224
&&
[lindex $operand_types 0] == {data}
- } {
+ } then {
if {[lindex $operands_abs 1] != {A}} {
lset operands 0 A
lset operand_types 0 a
@@ -1946,7 +1970,7 @@ namespace eval PreProcessor {
[lindex $operands_abs 1] == 224
&&
[lindex $operand_types 1] == {data}
- } {
+ } then {
lset operands 1 A
lset operand_types 1 a
set bytes_saved 1
@@ -1955,7 +1979,7 @@ namespace eval PreProcessor {
}
if {$bytes_saved} {
- # Increment number of performed optimalizations
+ # Increment number of performed optimizations
incr optims
# Shift code
@@ -1995,8 +2019,8 @@ namespace eval PreProcessor {
## Evaluate and remove instructions
# @return void
proc parse_instructions {} {
- variable asm ;# Resulting precompiled code
- variable tmp_asm ;# Tempotary auxiliary precompiled code
+ variable asm ;# Resulting pre-compiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable idx ;# Current position in asm list
@@ -2027,7 +2051,9 @@ namespace eval PreProcessor {
incr idx
# Update after each 25 iterations
- if {[expr {$idx % 25}] == 0} ${::Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 25}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -2042,7 +2068,7 @@ namespace eval PreProcessor {
## Conditionaly change program pointer
if {![regexp {^\s*\w+} $line first_field]} {
set first_field {}
- } {
+ } else {
set first_field [string trim $first_field]
}
if {$first_field == {ORG}} {
@@ -2055,15 +2081,27 @@ namespace eval PreProcessor {
## Determinate label
if {[regexp {^\w+:} $line label]} {
# Check for label validity
+ set lbl [string trimright $label {:}]
if {[regexp {^\w*:$} $label] && ![regexp {^\d} $label]} {
-
- set label [string trimright $label {:}]
- if {[isReservedKeyword $label]} {
- Warning $lineNum $fileNum [mc "Reserved keyword used as label"]
+ if {
+ [lsearch -exact -ascii ${::CompilerConsts::defined_SFR} $lbl] != -1
+ ||
+ [lsearch -exact -ascii ${::CompilerConsts::defined_progVectors} $lbl] != -1
+ ||
+ [lsearch -exact -ascii ${::CompilerConsts::defined_SFRBitArea} $lbl] != -1
+ ||
+ [lsearch -exact -ascii ${::CompilerConsts::FixedOperands} $lbl] != -1
+ } then {
+ SyntaxError $lineNum $fileNum [mc "Unable redefine constant: %s" $lbl]
+ } else {
+ set label $lbl
+ if {[isReservedKeyword $label]} {
+ Warning $lineNum $fileNum [mc "Reserved keyword used as label"]
+ }
+ lappend local_labels $label
}
- lappend local_labels $label
- } {
- SyntaxError $lineNum $fileNum [mc "Invalid label: `%s' \n\t(labels can contain only alfanumeric characters and must not begin with a digit)" $label]
+ } else {
+ SyntaxError $lineNum $fileNum [mc "Invalid label: `%s' \n\t(labels can contain only alphanumeric characters and must not begin with a digit)" $label]
}
# Remove label from the line
@@ -2080,7 +2118,7 @@ namespace eval PreProcessor {
## Determinate instruction
if {![regexp {^\s*\.?\w+} $line instruction]} {
set instruction {}
- } {
+ } else {
set instruction [string tolower [string trim $instruction]]
}
@@ -2090,7 +2128,7 @@ namespace eval PreProcessor {
if {$skip == {}} {
set instruction_len 0
SyntaxError $lineNum $fileNum [mc "Invalid expression `%s'" [regsub {^\s*\.?\w+\s*} $line {}]]
- } {
+ } else {
set instruction_len $skip
}
@@ -2105,7 +2143,7 @@ namespace eval PreProcessor {
# Regular instruction
} else {
# Check for instruction validity
- if {[lsearch -exact -ascii ${CompilerConsts::AllInstructions} $instruction] == -1} {
+ if {[lsearch -exact -ascii ${::CompilerConsts::AllInstructions} $instruction] == -1} {
lappend tmp_asm [list $lineNum $fileNum {C} $line]
continue
}
@@ -2181,19 +2219,31 @@ namespace eval PreProcessor {
}
## Determinate whether the given string is reserved keyword
- # @parm String string - string to evaluate
+ # @parm String string - String to evaluate
+ # @parm Bool symbols_too - Consider also special register names
# @return Bool - result (1 == is reserved; 0 == is not reserved)
- proc isReservedKeyword {string} {
+ proc isReservedKeyword {string {symbols_too 0}} {
set string [string tolower $string]
if {
- [lsearch -exact -ascii ${CompilerConsts::AllInstructions} $string] != -1
+ [lsearch -exact -ascii ${::CompilerConsts::AllInstructions} $string] != -1
||
- [lsearch -exact -ascii ${CompilerConsts::AllDirectives} $string] != -1
- } {
+ [lsearch -exact -ascii ${::CompilerConsts::AllDirectives} $string] != -1
+ ||
+ [lsearch -exact -ascii ${::CompilerConsts::FixedOperands} $string] != -1
+ } then {
return 1
- } {
+ } elseif {$symbols_too && (
+ [lsearch -exact -ascii ${::CompilerConsts::defined_SFR} $string] != -1
+ ||
+ [lsearch -exact -ascii ${::CompilerConsts::defined_progVectors} $string] != -1
+ ||
+ [lsearch -exact -ascii ${::CompilerConsts::defined_SFRBitArea} $string] != -1
+ )
+ } then {
+ return 1
+ } else {
return 0
}
}
@@ -2215,8 +2265,8 @@ namespace eval PreProcessor {
set list_of_labels [string tolower $list_of_labels]
foreach label $list_of_labels {
if {[lsearch -exact -ascii $defined_LABEL $label] != -1} {
- SyntaxError $lineNum $fileNum [mc "Label is already defined: `%s'" $label]
- } {
+ SyntaxError $lineNum $fileNum [mc "Label was already defined: `%s'" $label]
+ } else {
lappend defined_LABEL $label
set labels($label) $address
}
@@ -2241,7 +2291,7 @@ namespace eval PreProcessor {
set l [llength $operands]
for {set i 0} {$i < $l} {incr i} {
set o [lindex $operands $i]
- if {[lsearch -exact -ascii ${CompilerConsts::FixedOperands} [string tolower $o]] != -1} {
+ if {[lsearch -exact -ascii ${::CompilerConsts::FixedOperands} [string tolower $o]] != -1} {
set operands [lreplace $operands $i $i [string toupper $o]]
}
}
@@ -2262,7 +2312,7 @@ namespace eval PreProcessor {
set n [const_value $o $lineNum 1]
set operands [lreplace $operands $i $i $n]
- Notice $lineNum $fileNum [mc "Overwriting `%s' with `%s' (acording to your previous definition!)" [string toupper $o] [string toupper $n]]
+ Notice $lineNum $fileNum [mc "Overwriting `%s' with `%s' (according to your previous definition!)" [string toupper $o] [string toupper $n]]
}
}
@@ -2273,19 +2323,19 @@ namespace eval PreProcessor {
}
# Find instruction set for given instruction
- if {[lsearch -exact -ascii ${CompilerConsts::AllInstructions} $instruction] == -1} {
+ if {[lsearch -exact -ascii ${::CompilerConsts::AllInstructions} $instruction] == -1} {
CompilationError $lineNum $fileNum "Unknown error 3"
return {}
}
- set ins_def $CompilerConsts::InstructionDefinition($instruction)
+ set ins_def $::CompilerConsts::InstructionDefinition($instruction)
# Check for valid operands count
set max_oprs [lindex $ins_def 0]
if {[llength $operands] > $max_oprs} {
- SyntaxError $lineNum $fileNum [mc "Too many operands, %s can take only %s operand[expr {$max_oprs ? {} : {s}}]" $instruction $max_oprs]
+ SyntaxError $lineNum $fileNum [mc "Too many operands, %s can take only %s operand[expr {$max_oprs == 1 ? {} : {s}}]" $instruction $max_oprs]
return {}
} elseif {[llength $operands] < $max_oprs} {
- SyntaxError $lineNum $fileNum [mc "Too few operands, %s must take exactly %s operand[expr {$max_oprs ? {} : {s}}]" $instruction $max_oprs]
+ SyntaxError $lineNum $fileNum [mc "Too few operands, %s must take exactly %s operand[expr {$max_oprs == 1 ? {} : {s}}]" $instruction $max_oprs]
return {}
}
@@ -2330,7 +2380,7 @@ namespace eval PreProcessor {
$operands_i != {C}
&&
$operands_i != {/C}
- } {
+ } then {
incr i
continue
}
@@ -2361,7 +2411,7 @@ namespace eval PreProcessor {
# No matching operand set found -> error
if {!$match} {
- SyntaxError $lineNum $fileNum [mc "Invalid operand set: %s %s" $instruction [join $operands {,}]]
+ SyntaxError $lineNum $fileNum [mc "Invalid set of operands: %s %s" $instruction [join $operands {,}]]
return {}
}
@@ -2391,7 +2441,7 @@ namespace eval PreProcessor {
set operand [string tolower $operand]
# Fixed value
- if {[lsearch -exact -ascii ${CompilerConsts::FixedOperands} $operand] != -1} {
+ if {[lsearch -exact -ascii ${::CompilerConsts::FixedOperands} $operand] != -1} {
return [string toupper $operand]
}
@@ -2401,6 +2451,13 @@ namespace eval PreProcessor {
{^#.*$} { return {imm8 imm16} }
}
+ # determinate whether the instruction can changed content of PC
+ if {[lsearch {} $instruction] == -1} {
+ set no_branch 1
+ } else {
+ set no_branch 0
+ }
+
# Variable length operand (pseudo-instructions: "CALL <code>" and "JMP <code>")
if {$instruction == {jmp} || $instruction == {call}} {
# Value is an expression
@@ -2425,7 +2482,7 @@ namespace eval PreProcessor {
return {code16}
} elseif {(abs($address - $operand) > 126) || $instruction == {call}} {
return {code11}
- } {
+ } else {
return {code8}
}
@@ -2437,7 +2494,7 @@ namespace eval PreProcessor {
} elseif {[lsearch ${::CompilerConsts::defined_SFRBitArea} $operand] != -1} {
return {bit /bit}
- # Interrupt vector
+ # Address in program memory
} elseif {[lsearch ${::CompilerConsts::defined_progVectors} $operand] != -1} {
return {code16 code11 code8}
@@ -2450,11 +2507,12 @@ namespace eval PreProcessor {
## Expand macro instructions
# @return Bool - macro expanded
proc expand_macro_instructions {} {
- variable asm ;# Resulting precompiled code
- variable tmp_asm ;# Tempotary auxiliary precompiled code
+ variable asm ;# Resulting pre-compiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable macro ;# Array: Code of defined macro instructions
+ variable local_M_labels ;# Array of lists: Local labels in macros $local_M_labels($macro_name) == {integer label0 ... labelN}
variable defined_MACRO ;# List of defined macro instructions
variable idx ;# Current position in asm list
@@ -2478,7 +2536,9 @@ namespace eval PreProcessor {
incr idx
# Update after each 25 iterations
- if {[expr {$idx % 25}] == 0} ${::Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 25}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -2499,7 +2559,7 @@ namespace eval PreProcessor {
}
if {![regexp {^\s*\.?\w+} $line instruction]} {
set instruction {}
- } {
+ } else {
set instruction [string tolower [string trim $instruction]]
}
regsub {^\.?\w+\s*} $line {} operands
@@ -2513,14 +2573,14 @@ namespace eval PreProcessor {
set repeat 1
# Get code of the macro
- set macro_code [getMacro $instruction [getOperands $operands 0]]
+ set macro_code [getMacro $instruction [getOperands $operands 1]]
if {$macro_code == {}} {continue}
# Adjust the precompiled code and code listing
if {$label != {}} {
lappend tmp_asm [list $lineNum $fileNum $label]
set del_line 0
- } {
+ } else {
set del_line 1
}
@@ -2541,11 +2601,11 @@ namespace eval PreProcessor {
return $repeat
}
- ## Debuging procedure
+ ## Debugging procedure
# Write current content of the precompiled code to stdout
# @return void
proc write_asm {} {
- variable asm ;# Resulting precompiled code
+ variable asm ;# Resulting pre-compiled code
puts ""
set idx -1
foreach line $asm {
@@ -2554,11 +2614,11 @@ namespace eval PreProcessor {
}
}
- ## Debuging procedure
+ ## Debugging procedure
# Write current content of the tempotary precompiled code to stdout
# @return void
proc write_tmp_asm {} {
- variable tmp_asm ;# Tempotary auxiliary precompiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
puts ""
set idx -1
foreach line $tmp_asm {
@@ -2573,11 +2633,12 @@ namespace eval PreProcessor {
# @return List - code of the macro
proc getMacro {macro_name args} {
variable macro ;# Array: Code of defined macro instructions
+ variable local_M_labels ;# Array of lists: Local labels in macros $local_M_labels($macro_name) == {integer label0 ... labelN}
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
- # Adjust list of armuments
- set args [join $args]
+ # Adjust list of arguments
+ set args [lindex $args 0]
# Local variables
set new_operands {} ;# Instruction operands
@@ -2585,34 +2646,57 @@ namespace eval PreProcessor {
# Determinate code of the macro and its operands
set macro_code $macro($macro_name)
- set m_args [lindex $macro_code 0]
+ set m_pars [lindex $macro_code 0]
set macro_code [lindex $macro_code 1]
# Check for valid number of arguments
- set arg_len_diff [expr {[llength $args] - [llength $m_args]}]
+ set arg_len_diff [expr {[llength $args] - [llength $m_pars]}]
if {$arg_len_diff < 0} {
set arg_len_diff [expr {$arg_len_diff * -1}]
- SyntaxError $lineNum $fileNum [mc "Too few arguments, %s argument(s) missing: %s ..." $arg_len_diff $macro_name]
+ SyntaxError $lineNum $fileNum [mc "Too few arguments, %d argument(s) missing for %s ..." $arg_len_diff $macro_name]
return {}
} elseif {$arg_len_diff > 0} {
- SyntaxError $lineNum $fileNum [mc "Too many arguments, $s extra argument(s)" $arg_len_diff]
+ SyntaxError $lineNum $fileNum [mc "Too many arguments, %d extra argument(s)" $arg_len_diff]
return {}
}
- # Substitute macro arguments
+ # Increment counter of expansions of this macro
+ lset local_M_labels($macro_name) 0 [expr {1 + [lindex $local_M_labels($macro_name) 0]}]
+
+ # Substitute macro parametrs
foreach line $macro_code {
set new_operands {}
+ # Determinate label
+ if {![regexp {^(\?\?)?[A-Za-z_][^\s:]*:\s*} $line label]} {
+ set label {}
+ } else {
+ regsub {^(\?\?)?[A-Za-z_][^\s:]:*\s*} $line {} line
+ regsub -all {\s+} $label {} label
+ set label [string trimright $label {:}]
+ if {[lsearch -ascii -exact $local_M_labels($macro_name) $label] != -1} {
+ set label "${macro_name}_[lindex $local_M_labels($macro_name) 0]__${label}"
+ }
+ }
+
# Determinate instruction and operands
if {![regexp {^\.?\w+\s*} $line instruction]} {
set instruction {}
+ } else {
+ regsub -all {\s+} $instruction {} instruction
}
regsub {^\.?\w+\s*} $line {} operands
if {$operands == {}} {
lappend result $instruction
continue
}
- set operands [getOperands $operands 0]
+
+ if {[lsearch -ascii -exact {if ifn ifdef ifndef elseif elseifn elseifdef elseifndef} [string tolower $instruction]] == -1} {
+ set operands [getOperands $operands 0]
+ set if_statement 0
+ } else {
+ set if_statement 1
+ }
# Perform substitution
foreach opr $operands {
@@ -2623,25 +2707,43 @@ namespace eval PreProcessor {
($char == {/}) ||
($char == {#}) ||
($char == {@})
- } {
+ } then {
set opr [string range $opr 1 end]
- } {
+ } else {
set char {}
}
- # Find operand in macro armunets
- set idx [lsearch -exact -ascii $m_args $opr]
- if {$idx != -1} {
- set opr [lindex $args $idx]
+ # Find operand in macro parameters
+ set new_opr [list]
+ regsub -all {[\(\)]} $opr { & } opr
+ foreach o $opr {
+ set idx [lsearch -exact -ascii $m_pars $o]
+ if {$idx != -1} {
+ set o [lindex $args $idx]
+
+ if {[isReservedKeyword [lindex $m_pars $idx] 1]} {
+ Warning $lineNum $fileNum [mc "Reserved keyword substituted with macro argument: %s --> %s" [lindex $m_pars $idx] [lindex $args $idx]]
+ }
+ }
+
+ append new_opr $o { }
}
- lappend new_operands "$char$opr"
+ lappend new_operands "$char$new_opr"
}
# Recomposite line of macro instruction code
- set operands [join $new_operands {, }]
+ if {$if_statement} {
+ set operands [join $new_operands { }]
+ } else {
+ set operands [join $new_operands {, }]
+ }
append instruction "\t"
append instruction $operands
+
+ if {$label != {}} {
+ set instruction "${label}:\t${instruction}"
+ }
lappend result $instruction
}
@@ -2660,16 +2762,16 @@ namespace eval PreProcessor {
set simple_operands $operands ;# Original string without strings and chars
set result {} ;# Resulting list
- # Convert strings and quoted charaters to underscores
- while 1 {
+ # Convert strings and quoted characters to underscores
+ while {1} {
if {![regexp {'[^']*'} $simple_operands str]} {break}
set padding [string repeat {_} [string length $str]]
regsub {'[^']*'} $simple_operands $padding simple_operands
}
- # Determinate oprands
- while 1 {
+ # Determinate operands
+ while {1} {
set idx [string first {,} $simple_operands]
if {$idx == -1} {break}
@@ -2688,7 +2790,7 @@ namespace eval PreProcessor {
lappend result $operands
if {$keep_case} {
return $result
- } {
+ } else {
return [string tolower $result]
}
}
@@ -2696,11 +2798,12 @@ namespace eval PreProcessor {
## Parse and remove definitions of macro instructions
# @return void
proc define_macro_instructions {} {
- variable asm ;# Resulting precompiled code
- variable tmp_asm ;# Tempotary auxiliary precompiled code
+ variable asm ;# Resulting pre-compiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable macro ;# Array: Code of defined macro instructions
+ variable local_M_labels ;# Array of lists: Local labels in macros $local_M_labels($macro_name) == {integer label0 ... labelN}
variable defined_MACRO ;# List of defined macro instructions
variable idx ;# Current position in asm list
variable macro_name_to_append ;# Name of currently defined macro instruction
@@ -2710,20 +2813,21 @@ namespace eval PreProcessor {
set idx -1
# Local variables
- set Macro 0 ;# Bool: definition opened
- set Exitm 0 ;# Bool: Definition terminated by directive 'EXITM'
- set NoMacro 0 ;# Definition failed
- set del_line 1 ;# Bool: remove this line
- set macro_name {} ;# Name of the macro
- set macro_args {} ;# List of arguments for the macro
- set rept_macro 0 ;# Bool: repeat macro starts
+ set Macro 0 ;# Bool: definition opened
+ set NoMacro 0 ;# Definition failed
+ set del_line 1 ;# Bool: remove this line
+ set macro_name {} ;# Name of the macro
+ set macro_params {} ;# List of the macro parameters
+ set rept_macro 0 ;# Bool: repeat macro starts
# Iterate over the code
foreach line $asm {
incr idx
# Update after each 25 iterations
- if {[expr {$idx % 25}] == 0} ${::Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 25}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -2740,12 +2844,12 @@ namespace eval PreProcessor {
# Spilt line into first 2 separate fields
if {![regexp {^\s*\.?\w+} $line field0]} {
set field0 {}
- } {
+ } else {
set field0 [string trim $field0]
}
if {![regexp {^\s*\.?\w+:?\s+\.?\w+} $line field1]} {
set field1 {}
- } {
+ } else {
regexp {\.?\w+$} $field1 field1
}
set field0_l [regsub {^\.} [string tolower $field0] {}]
@@ -2755,17 +2859,17 @@ namespace eval PreProcessor {
if {$field0_l == {rept} || $field0_l == {times}} {
if {$Macro} {
SyntaxError $lineNum $fileNum \
- [mc "Cannot define macro inside anoner one -- macro processing failed"]
- } {
- regsub {^\s*\.?\w+\s*} $line {} macro_args
- set macro_args [ComputeExpr $macro_args]
- if {$macro_args == {}} {
- SyntaxError $lineNum $fileNum [mc "Missign number of repeats"]
+ [mc "Cannot define macro inside another one -- macro processing failed"]
+ } else {
+ regsub {^\s*\.?\w+\s*} $line {} macro_params
+ set macro_params [ComputeExpr $macro_params]
+ if {$macro_params == {}} {
+ SyntaxError $lineNum $fileNum [mc "Missing number of repeats"]
set NoMacro 1
- } elseif {$macro_args < 0} {
+ } elseif {$macro_params < 0} {
Warning $lineNum $fileNum [mc "Number of repeats is lower than zero"]
set NoMacro 1
- } elseif {$macro_args == 0} {
+ } elseif {$macro_params == 0} {
Notice $lineNum $fileNum [mc "Zero number of repeats"]
set NoMacro 1
}
@@ -2781,69 +2885,66 @@ namespace eval PreProcessor {
} elseif {$field1_l == {macro}} {
if {$Macro} {
SyntaxError $lineNum $fileNum \
- [mc "Cannot define macro inside anoner one -- macro processing failed"]
- } {
- # Determinate name and arguments
- regsub {^\w+\s+\.?\w+\s*} $line {} macro_args
- set macro_args [getOperands $macro_args 0]
+ [mc "Cannot define macro inside another one -- macro processing failed"]
+ } else {
+ # Determinate name and parameters
+ regsub {^\w+\s+\.?\w+\s*} $line {} macro_params
+ set macro_params [getOperands $macro_params 0]
set macro_name $field0_l
+ foreach parm $macro_params {
+ if {[isReservedKeyword $parm 1]} {
+ Warning $lineNum $fileNum [mc "Reserved keyword used as macro parameter: %s in macro %s" $parm $macro_name]
+ }
+ }
+
# Check for validity of the name
- if {
- ([lsearch -exact -ascii ${CompilerConsts::AllInstructions} $macro_name] != -1)
- ||
- ([lsearch -exact -ascii ${CompilerConsts::AllDirectives} $macro_name] != -1)
- } {
+ if {[isReservedKeyword $macro_name]} {
# Invalid name
SyntaxError $lineNum $fileNum [mc "Macro name is reserved keyword: %s" $macro_name]
set NoMacro 1
- } {
+ } else {
+ # Check for validity of the name (again, but invoke only warning this time)
+ if {[isReservedKeyword $macro_name 1]} {
+ # Invalid name
+ Warning $lineNum $fileNum [mc "Macro name is reserved keyword: %s" $macro_name]
+ set NoMacro 1
+ }
# Valid name
if {[lsearch -exact -ascii $defined_MACRO $macro_name] != -1} {
SyntaxError $lineNum $fileNum [mc "Macro `%s' is already defined" $macro_name]
set NoMacro 1
- } {
+ } else {
set macro_name_to_append $macro_name
- set macro($macro_name) {}
+ set macro($macro_name) [list]
+ set local_M_labels($macro_name) [list 0]
}
set Macro 1
}
}
- # Exit macro definition
- } elseif {$field0_l == {exitm}} {
- if {!$Macro} {
- Warning $lineNum $fileNum [mc "Unable to exit macro, no macro is opened"]
- }
- set Exitm 1
- set rept_macro 0
-
- # Directive takes no arguments
- if {[string length $field1_l]} {
- Warning $lineNum $fileNum [mc "Directive %s takes no arguments" [string toupper $field0_l]]
- }
-
# Close macro definition
} elseif {$field0_l == {endm}} {
# No macro was opened
if {!$Macro} {
SyntaxError $lineNum $fileNum [mc "Unable to close macro, no macro is opened"]
# Close macro
- } {
+ } else {
if {$rept_macro} {
set line $macro($macro_name)
set macro($macro_name) [list]
- for {set i 0} {$i < $macro_args} {incr i} {
+ set local_M_labels($macro_name) [list 0]
+ for {set i 0} {$i < $macro_params} {incr i} {
set macro($macro_name) [concat $macro($macro_name) $line]
}
- set macro_args {}
+ set macro_params {}
set del_line 0
lappend tmp_asm [list $lineNum $fileNum $macro_name]
}
- if {!($Exitm || $NoMacro)} {
- set macro($macro_name) [list $macro_args $macro($macro_name)]
+ if {!$NoMacro} {
+ set macro($macro_name) [list $macro_params $macro($macro_name)]
regsub -all {\s+} $macro($macro_name) { } macro($macro_name)
regsub -all "\\\{ " $macro($macro_name) "\{" macro($macro_name)
@@ -2853,7 +2954,6 @@ namespace eval PreProcessor {
# Reset some local variables
set Macro 0
- set Exitm 0
set NoMacro 0
set rept_macro 0
@@ -2866,20 +2966,26 @@ namespace eval PreProcessor {
} else {
# Part of macro definition
if {$Macro} {
- if {[regexp {^\w+:} $line]} {
- Warning $lineNum $fileNum [mc "Bad layout: Macros cannot contain labels -- label deleted"]
- regsub {^\w+:\s*} $line {} line
- }
- if {!($Exitm || $NoMacro)} {
- lappend macro($macro_name) $line
+ # Register local label in the macro
+ if {$field0_l == {local}} {
+ if {[regexp {^\w+$} $field1_l]} {
+ lappend local_M_labels($macro_name) $field1_l
+ } else {
+ SyntaxError $lineNum $fileNum [mc "Invalid label specification: ``%s''" $field0_l]
+ }
+ # Append the line to the currenly opened macro
+ } else {
+ if {!$NoMacro} {
+ lappend macro($macro_name) $line
+ }
}
# Common line
- } {
+ } else {
if {$field0_l == {macro}} {
SyntaxError $lineNum $fileNum [mc "Missing name of macro"]
- } elseif {[regexp {^\s*\w+:} $line] && ($field1_l == {endm} || $field1_l == {exitm})} {
- SyntaxError $lineNum $fileNum [mc "Labels are not allowed before directives ENDM and EXITM"]
- } {
+ } elseif {[regexp {^\s*\w+:} $line] && ($field1_l == {endm})} {
+ SyntaxError $lineNum $fileNum [mc "Labels are not allowed before directives ENDM"]
+ } else {
lappend tmp_asm [list $lineNum $fileNum $line]
}
set del_line 0
@@ -2902,8 +3008,8 @@ namespace eval PreProcessor {
# @return Bool - code included
proc include_directive {dir} {
variable included_files ;# List: Unique unsorted list of included files
- variable asm ;# Resulting precompiled code
- variable tmp_asm ;# Tempotary auxiliary precompiled code
+ variable asm ;# Resulting pre-compiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable idx ;# Current position in asm list
@@ -2921,7 +3027,9 @@ namespace eval PreProcessor {
set line_org $line
# Update after each 25 iterations
- if {[expr {$idx % 25}] == 0} ${::Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 25}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -2941,14 +3049,14 @@ namespace eval PreProcessor {
regsub {^\s*\w+:\s*} $line {} line
set label [string trimleft $label " \t"]
set label [string trimright $label " \t"]
- } {
+ } else {
set label {}
}
# Determinate directive
if {![regexp {^\s*\.?\w+} $line directive]} {
set directive {}
- } {
+ } else {
set directive [string trim $directive]
}
set directive_l [string tolower $directive]
@@ -2958,7 +3066,7 @@ namespace eval PreProcessor {
regsub {^\s*\.?\w+} $line {} file_name
regsub {^\s+} $file_name {} file_name
if {![string length $file_name]} {
- SyntaxError $lineNum $fileNum [mc "Missing filename"]
+ SyntaxError $lineNum $fileNum [mc "Missing file name"]
}
set asm [lreplace $asm $idx $idx [list $lineNum $fileNum $label]]
@@ -2967,7 +3075,7 @@ namespace eval PreProcessor {
set file_name [regsub -nocase -- {^[\s ]*\$include[\s ]*} $file_name {}]
set file_name [string range $file_name 1 end-1]
if {![string length $file_name]} {
- SyntaxError $lineNum $fileNum [mc "Missing filename"]
+ SyntaxError $lineNum $fileNum [mc "Missing file name"]
}
set asm [lreplace $asm $idx $idx [list $lineNum $fileNum $label]]
@@ -2984,7 +3092,7 @@ namespace eval PreProcessor {
([string index $file_name 0] == "\"" && [string index $file_name end] == "\"")
||
([string index $file_name 0] == {'} && [string index $file_name end] == {'})
- } {
+ } then {
set file_name [string range $file_name 1 end-1]
}
set file_name [string trim $file_name]
@@ -3036,7 +3144,7 @@ namespace eval PreProcessor {
proc getFile {dir file file_number} {
variable fileNum ;# Number of the current file
variable lineNum ;# Number of the current line
- variable tmp_asm ;# Tempotary auxiliary precompiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
set tmp_asm {}
@@ -3044,13 +3152,13 @@ namespace eval PreProcessor {
if {[string index $file 0] == {'}} {
if {[string index $file end] != {'}} {
SyntaxError $lineNum $fileNum [mc "Invalid expression: `%s'" $file]
- } {
+ } else {
set file [string range $file 1 {end-1}]
}
} elseif {[string index $file 0] == "\""} {
if {[string index $file end] != "\""} {
SyntaxError $lineNum $fileNum [mc "Invalid expression: `%s'" $file]
- } {
+ } else {
set file [string range $file 1 {end-1}]
}
}
@@ -3061,10 +3169,10 @@ namespace eval PreProcessor {
set file [open $file r]
set data [read $file]
close $file
- }]} {
+ }]} then {
CompilationError $lineNum $fileNum [mc "Unable to open file: %s" $file]
return {}
- } {
+ } else {
# Any EOL to LF
regsub -all {\r\n?} $data "\n" data
@@ -3078,7 +3186,7 @@ namespace eval PreProcessor {
return $tmp_asm
}
# File does not exist
- } {
+ } else {
CompilationError $lineNum $fileNum [mc "File not found: %s" $file]
return {}
}
@@ -3087,7 +3195,7 @@ namespace eval PreProcessor {
## Parse and remove directive(s) 'END'
# @return void
proc end_of_code {} {
- variable asm ;# Resulting precompiled code
+ variable asm ;# Resulting pre-compiled code
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable idx ;# Current position in asm list
@@ -3104,7 +3212,9 @@ namespace eval PreProcessor {
incr idx
# Update after each 25 iterations
- if {[expr {$idx % 25}] == 0} ${::Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 25}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -3117,20 +3227,23 @@ namespace eval PreProcessor {
set line [lindex $line 2]
# Skip lines without word 'END'
- if {![regexp -nocase {\.?end} $line]} {
+ if {![regexp -nocase {end} $line]} {
continue
}
+ regsub {\s*;.*$} $line {} line
+ regsub -all {:} $line {: } line
+
# Determinate 1st and 2nd field of the line
- if {![regexp {^\s*\.?\w+} $line field0]} {
+ if {![regexp {^\s*[^\s]+} $line field0]} {
set field0 {}
- } {
+ } else {
set field0 [string trim $field0]
}
- if {![regexp {^\s*\.?\w+\s+\.?\w+} $line field1]} {
+ if {![regexp {^\s*[^\s]+\s+[^\s]+} $line field1]} {
set field1 {}
- } {
- regexp {\.?\w+$} $field1 field1
+ } else {
+ regexp {[^\s]+$} $field1 field1
}
set field0 [string tolower [regsub {^\.} $field0 {}]]
set field1 [string tolower [regsub {^\.} $field1 {}]]
@@ -3145,14 +3258,14 @@ namespace eval PreProcessor {
[regexp {^\w+:$} $field0]
&&
($field1 == {end})
- } {
+ } then {
# Determinate content of the last line of the code (that label)
if {![regexp {^\w+:$} $field0 last_line]} {
set last_line {}
}
# Check if the line does not contain anything except the label and 'END'
- regsub {^\w+:\s*} $line {} line
+ regsub {^\s*\w+:\s*} $line {} line
set line [string tolower $line]
if {$line != {end}} {
SyntaxError $lineNum $fileNum [mc "Extra symbols after `END' directive"]
@@ -3166,13 +3279,15 @@ namespace eval PreProcessor {
# Directive 'end' detected -> adjust the code
if {$end} {
set asm [lreplace $asm $idx end]
+ set preserve_current_line 0
if {$last_line != {}} {
lappend asm [list $lineNum $fileNum $last_line]
+ set preserve_current_line 1
}
- CodeListing::end_directive $idx
- incr idx
+ CodeListing::end_directive $idx $preserve_current_line
+
# Directive 'end' not found -> invoke warning
- } {
+ } else {
Warning 0 0 [mc "Missing `END' directive"]
}
}
@@ -3180,14 +3295,14 @@ namespace eval PreProcessor {
## Parse and remove directive(s) 'ORG' and reorganize the current code
# @return void
proc origin_directive {} {
- variable asm ;# Resulting precompiled code
- variable tmp_asm ;# Tempotary auxiliary precompiled code
+ variable asm ;# Resulting pre-compiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable idx ;# Current position in asm list
variable defined_LABEL ;# List of defined labels
variable labels ;# Array: Values of defined labels ($labels($label) == $address)
- variable ErrorAtLine ;# Bool: Error occured on the current line
+ variable ErrorAtLine ;# Bool: Error occurred on the current line
variable origin_d_addr ;# List: Addresses of static program blocks
# Reset NS variables
@@ -3209,7 +3324,9 @@ namespace eval PreProcessor {
set ErrorAtLine 0
# Update after each 25 iterations
- if {[expr {$idx % 25}] == 0} ${::Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 25}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -3239,7 +3356,7 @@ namespace eval PreProcessor {
# Directive ORG detected
if {![regexp {^\s*\.?\w+} $line field0]} {
set field0 {}
- } {
+ } else {
set field0 [string trim $field0]
}
if {[regsub {^\.} $field0 {}] == {org}} {
@@ -3250,7 +3367,7 @@ namespace eval PreProcessor {
if {$line == {}} {
SyntaxError $lineNum $fileNum [mc "Missing address"]
set error 1
- } {
+ } else {
set value [ComputeExpr $line]
}
@@ -3262,7 +3379,7 @@ namespace eval PreProcessor {
SyntaxError $lineNum $fileNum [mc "Label already defined: `%s'" $label]
set error 1
}
- } {
+ } else {
SyntaxError $lineNum $fileNum [mc "Invalid label: `%s'" $label]
set error 1
}
@@ -3292,7 +3409,7 @@ namespace eval PreProcessor {
set last_value $value
# Directive ORG wasn't detected
- } {
+ } else {
lappend tmp_asm [list $lineNum $fileNum $line]
}
}
@@ -3313,6 +3430,7 @@ namespace eval PreProcessor {
set organization [lsort -index 0 -integer $organization]
set last_line {} ;# Last line number
+ set last_file {} ;# Last file number
set last_addr {} ;# Last address or origin
set new_organization {} ;# New organization map
@@ -3368,7 +3486,7 @@ namespace eval PreProcessor {
# @parm Bool first - match the first
# @return Int - list index
proc lineNum2idx {line_number file_number first} {
- variable asm ;# Resulting precompiled code
+ variable asm ;# Resulting pre-compiled code
set idx -1
set ln 0
@@ -3387,7 +3505,7 @@ namespace eval PreProcessor {
}
if {$idx < 0} {
return 0
- } {
+ } else {
return $idx
}
}
@@ -3400,8 +3518,8 @@ namespace eval PreProcessor {
## Convert the current code into numbered list (see proc. 'compile')
# @return void
proc line_numbers {} {
- variable asm ;# Resulting precompiled code
- variable tmp_asm ;# Tempotary auxiliary precompiled code
+ variable asm ;# Resulting pre-compiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
@@ -3422,7 +3540,9 @@ namespace eval PreProcessor {
incr idx
incr lineNum
# Update after each 25 iterations
- if {[expr {$idx % 25}] == 0} ${::Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 25}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -3440,7 +3560,7 @@ namespace eval PreProcessor {
}
## Evaluate and remove directives related to:
- # - Donditional compilation (IF, ELSE, ENDIF) (group 0)
+ # - Conditional compilation (IF, ELSE, ENDIF) (group 0)
# - Code listing enable/disable (LIST, NOLIST) (group 1)
# - Active bank selection (USING) (group 2)
# - Data memory segment selection (BSEG, DSEG, ISEG, XSEG) (group 3)
@@ -3450,9 +3570,9 @@ namespace eval PreProcessor {
# @parm Bool ignore_undefined - Ignore undefined symbolic names
# @return Bool - Anything expanded
proc parse_Consts_and_ConditionalCompilation {groups ignore_undefined} {
- variable asm ;# Resulting precompiled code
- variable tmp_asm ;# Tempotary auxiliary precompiled code
- variable ErrorAtLine ;# Bool: Error occured on the current line
+ variable asm ;# Resulting pre-compiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
+ variable ErrorAtLine ;# Bool: Error occurred on the current line
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable idx ;# Current position in asm list
@@ -3460,6 +3580,8 @@ namespace eval PreProcessor {
variable memory_reservation_map ;# Array: memory reservation map (see code)
variable defined_SET ;# List of variables defined by 'SET'
variable const_SET ;# Array: Constants defined by directive 'CODE'
+ variable selected_segment ;# Current memory segment (one of {cseg bseg dseg iseg xseg})
+ variable segment_pointer ;# Current memory segment pointer
# Reset NS variables
set idx -1
@@ -3482,7 +3604,9 @@ namespace eval PreProcessor {
}
# Update after each 25 iterations
- if {[expr {$idx % 25}] == 0} ${::Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 25}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -3497,7 +3621,7 @@ namespace eval PreProcessor {
set line [lindex $line 2]
regsub -nocase -- {if\(} $line {if (} line ;# Make construction "IF(something)" valid
# Final level pass
- } {
+ } else {
set line [lindex $line 3]
}
@@ -3507,7 +3631,7 @@ namespace eval PreProcessor {
# Determinate 1st field of the line
if {![regexp {^\s*\.?\w+:?} $line line_first_field]} {
set line_first_field {}
- } {
+ } else {
set line_first_field [string trim $line_first_field]
}
set directive0 [string tolower $line_first_field]
@@ -3516,7 +3640,7 @@ namespace eval PreProcessor {
# Determinate 2nd field of the line
if {![regexp {^\s*\.?\w+:?\s*\.?\w+} $line directive1]} {
set directive1 {}
- } {
+ } else {
regsub {^\s*\.?\w+:?\s*} $directive1 {} directive1
set directive1 [string trim $directive1]
}
@@ -3527,67 +3651,67 @@ namespace eval PreProcessor {
# Constant definition (SET EQU BIT ...) without constant to define (syntax error)
if {
- [lindex $groups 4] && $Enable &&
- ([lsearch -exact -ascii ${CompilerConsts::ConstDefinitionDirectives} $directive0] != -1)
- } {
- if {[regexp {^\s*\.?\w+\s+\w+\s*\,\s*.+$} $line]} {
- Warning $lineNum $fileNum [mc "This formulation is deprecated, consider usage of \"<Const> <Directive> <Value>\" instead"]
-
- set line_expr {}
- regsub {^\s*\.?\w+\s+\w+\s*\,\s*} $line {} line_expr
- set line_aux $directive1
- append line_aux { } $directive0 { } $line_expr
-
- set loc_result [define_const $directive0 $line_aux $idx $ignore_undefined]
- if {$loc_result == 2} {
- lappend tmp_asm [list $lineNum $fileNum $line]
- set deleteLine 0
- } elseif {$loc_result == 0} {
- set fin_result 1
- }
- } {
- SyntaxError $lineNum $fileNum [mc "Missing name of constant to define"]
- }
+ [lindex $groups 4] && $Enable &&
+ ([lsearch -exact -ascii ${::CompilerConsts::ConstDefinitionDirectives} $directive0] != -1)
+ } then {
+ if {[regexp {^\s*\.?\w+\s+\w+\s*\,\s*.+$} $line]} {
+ Warning $lineNum $fileNum [mc "This formulation is deprecated, consider usage of \"<Const> <Directive> <Value>\" instead"]
- # Constant definition (SET EQU BIT ...)
- } elseif {
- [lindex $groups 4] && $Enable &&
- ([lsearch -exact -ascii ${CompilerConsts::ConstDefinitionDirectives} $directive1] != -1)
- } {
- set loc_result [define_const $directive1 $line $idx $ignore_undefined]
+ set line_expr {}
+ regsub {^\s*\.?\w+\s+\w+\s*\,\s*} $line {} line_expr
+ set line_aux $directive1
+ append line_aux { } $directive0 { } $line_expr
+
+ set loc_result [define_const $directive0 $line_aux $idx $ignore_undefined]
if {$loc_result == 2} {
lappend tmp_asm [list $lineNum $fileNum $line]
set deleteLine 0
} elseif {$loc_result == 0} {
set fin_result 1
}
+ } else {
+ SyntaxError $lineNum $fileNum [mc "Missing name of constant to define"]
+ }
+
+ # Constant definition (SET EQU BIT ...)
+ } elseif {
+ [lindex $groups 4] && $Enable &&
+ ([lsearch -exact -ascii ${::CompilerConsts::ConstDefinitionDirectives} $directive1] != -1)
+ } then {
+ set loc_result [define_const $directive1 $line $idx $ignore_undefined]
+ if {$loc_result == 2} {
+ lappend tmp_asm [list $lineNum $fileNum $line]
+ set deleteLine 0
+ } elseif {$loc_result == 0} {
+ set fin_result 1
+ }
# Listing control (LIST, NOLIST)
} elseif {
- [lindex $groups 1] && (
- ($directive0 == {list}) ||
- ($directive0 == {nolist}) ||
- ($directive1 == {list} && [regexp {^\w+:$} $directive0 label]) ||
- ($directive1 == {nolist} && [regexp {^\w+:$} $directive0 label])
- )
- } {
- # Warning messages
- if {($directive0 == {list} || $directive0 == {nolist}) && [string length $directive1]} {
- Warning $lineNum $fileNum [mc "Directive %s takes no arguments" [string toupper $directive0]]
- } elseif {($directive1 == {list} || $directive1 == {nolist}) && [string length [regsub {^\s*\.?\w+:?\s+\.?\w+} $line {}]]} {
- Warning $lineNum $fileNum [mc "Directive %s takes no arguments" [string toupper $directive1]]
- }
+ [lindex $groups 1] && (
+ ($directive0 == {list}) ||
+ ($directive0 == {nolist}) ||
+ ($directive1 == {list} && [regexp {^\w+:$} $directive0 label]) ||
+ ($directive1 == {nolist} && [regexp {^\w+:$} $directive0 label])
+ )
+ } then {
+ # Warning messages
+ if {($directive0 == {list} || $directive0 == {nolist}) && [string length $directive1]} {
+ Warning $lineNum $fileNum [mc "Directive %s takes no arguments" [string toupper $directive0]]
+ } elseif {($directive1 == {list} || $directive1 == {nolist}) && [string length [regsub {^\s*\.?\w+:?\s+\.?\w+} $line {}]]} {
+ Warning $lineNum $fileNum [mc "Directive %s takes no arguments" [string toupper $directive1]]
+ }
- if {($directive0 == {nolist}) || ($directive1 == {nolist})} {
- CodeListing::directive_nolist $idx
- } {
- CodeListing::directive_list $idx
- }
+ if {($directive0 == {nolist}) || ($directive1 == {nolist})} {
+ CodeListing::directive_nolist $idx
+ } else {
+ CodeListing::directive_list $idx
+ }
- if {($label != {}) && $Enable} {
- lappend tmp_asm [list $lineNum $fileNum $label]
- set deleteLine 0
- }
+ if {($label != {}) && $Enable} {
+ lappend tmp_asm [list $lineNum $fileNum $label]
+ set deleteLine 0
+ }
# Active bank selection directive -- in 1st field (USING)
} elseif {[lindex $groups 2] && $Enable && ($directive0 == {using})} {
@@ -3603,28 +3727,28 @@ namespace eval PreProcessor {
# Active bank selection directive -- in 2nd field (USING)
} elseif {
- [lindex $groups 2] && ($directive1 == {using}) && $Enable
- &&
- ([regexp {^\w+:$} $directive0 label])
- } {
- set loc_result [define_active_bank \
- [regsub {^\w+:\s*\.?\w+\s*} $line {}] $ignore_undefined \
- ]
- set deleteLine 0
- if {$loc_result == 2} {
- lappend tmp_asm [list $lineNum $fileNum $line]
- } elseif {$loc_result == 0} {
- lappend tmp_asm [list $lineNum $fileNum $label]
- set fin_result 1
- } else {
- lappend tmp_asm [list $lineNum $fileNum $label]
- }
+ [lindex $groups 2] && ($directive1 == {using}) && $Enable
+ &&
+ ([regexp {^\w+:$} $directive0 label])
+ } then {
+ set loc_result [define_active_bank \
+ [regsub {^\w+:\s*\.?\w+\s*} $line {}] $ignore_undefined \
+ ]
+ set deleteLine 0
+ if {$loc_result == 2} {
+ lappend tmp_asm [list $lineNum $fileNum $line]
+ } elseif {$loc_result == 0} {
+ lappend tmp_asm [list $lineNum $fileNum $label]
+ set fin_result 1
+ } else {
+ lappend tmp_asm [list $lineNum $fileNum $label]
+ }
# Data segment selection (XSEG DSEG ...)
} elseif {
[lindex $groups 3] && $Enable &&
- ([lsearch -exact -ascii ${CompilerConsts::ConstDataSegmentSelectionDirectives} $directive0] != -1)
- } {
+ ([lsearch -exact -ascii ${::CompilerConsts::ConstDataSegmentSelectionDirectives} $directive0] != -1)
+ } then {
set loc_result [data_segment_selection \
$directive0 $directive1 $line $idx $ignore_undefined \
]
@@ -3635,11 +3759,32 @@ namespace eval PreProcessor {
set fin_result 1
}
+ # ORG in other than CODE segment
+ } elseif {
+ $directive0 == {org} || $directive1 == {org}
+ } then {
+ if {$selected_segment != {cseg}} {
+ regsub {org} $line "$selected_segment at" line
+
+ set address {}
+ if {$directive0 == {org}} {
+ set address [ComputeExpr $directive1]
+ } elseif {$directive1 == {org}} {
+ set address [ComputeExpr [regsub {^\w+:\s*\.?\w+\s*} $line {}]]
+ }
+ if {$address != {}} {
+ set segment_pointer($selected_segment) $address
+ }
+ }
+
+ lappend tmp_asm [list $lineNum $fileNum $line]
+ set deleteLine 0
+
# Data memory reservation -- without label (DBIT 125)
} elseif {
[lindex $groups 5] && $Enable &&
- ([lsearch -exact -ascii ${CompilerConsts::ConstDataMemoryReservationDirectives} $directive0] != -1)
- } {
+ ([lsearch -exact -ascii ${::CompilerConsts::ConstDataMemoryReservationDirectives} $directive0] != -1)
+ } then {
regsub {^\.?\w+\s*} $line {} value
set loc_result [data_memory_reservation {} $directive0 $value $idx $ignore_undefined]
if {$loc_result == 2} {
@@ -3653,8 +3798,8 @@ namespace eval PreProcessor {
} elseif {
[lindex $groups 5] && [regexp {^\w+:$} $line_first_field] && $Enable
&&
- ([lsearch -exact -ascii ${CompilerConsts::ConstDataMemoryReservationDirectives} $directive1] != -1)
- } {
+ ([lsearch -exact -ascii ${::CompilerConsts::ConstDataMemoryReservationDirectives} $directive1] != -1)
+ } then {
regsub {^\s*\w+:\s*\.?\w+\s*} $line {} value
set loc_result [data_memory_reservation \
$line_first_field $directive1 $value $idx $ignore_undefined \
@@ -3666,14 +3811,14 @@ namespace eval PreProcessor {
set fin_result 1
}
- # Conditional compilation statement -- in 2nd field (IF ELSE ENDIF IFNDEF IFDEF IFN)
+ # Conditional compilation statement -- in 2nd field (IF ELSE ENDIF IFNDEF IFDEF IFN ELSEIF ELSEIFN ELSEIFDEF ELSEIFNDEF)
} elseif {
[lindex $groups 0] && (
- [lsearch -ascii -exact {if else endif ifndef ifdef ifn} $directive1] != -1
+ [lsearch -ascii -exact {if else endif ifndef ifdef ifn elseif elseifn elseifdef elseifndef} $directive1] != -1
) && (
[regexp {^\w+:$} $line_first_field label]
)
- } {
+ } then {
# Is compilation enabled ?
if {$Enable} {
lappend tmp_asm [list $lineNum $fileNum $label]
@@ -3689,12 +3834,12 @@ namespace eval PreProcessor {
}
} else {
- # Conditional compilation statement -- in 1st field (IF ELSE ENDIF IFNDEF IFDEF IFN)
+ # Conditional compilation statement -- in 1st field (IF ELSE ENDIF IFNDEF IFDEF IFN ELSEIFN ELSEIFDEF ELSEIFNDEF)
if {
[lindex $groups 0] && (
- [lsearch -ascii -exact {if else endif ifndef ifdef ifn} $directive0] != -1
+ [lsearch -ascii -exact {if else endif ifndef ifdef ifn elseif elseifn elseifdef elseifndef} $directive0] != -1
)
- } {
+ } then {
regsub {^\.?\w+\s*} $line {} value
@@ -3704,11 +3849,15 @@ namespace eval PreProcessor {
}
If_Else_Endif $directive0 $value
- } {
+ } else {
# Is compilation enabled ?
if {$Enable} {
lappend tmp_asm [list $lineNum $fileNum $line]
set deleteLine 0
+
+ if {$directive0 == {cseg} || $directive1 == {cseg}} {
+ set selected_segment {cseg}
+ }
}
}
}
@@ -3787,7 +3936,7 @@ namespace eval PreProcessor {
if {![string length $expr]} {
SyntaxError $lineNum $fileNum [mc "Missing size"]
set value 1
- } {
+ } else {
set value [ComputeExpr $expr $ignore_undefined]
}
@@ -3823,10 +3972,10 @@ namespace eval PreProcessor {
($selected_segment != {dseg}) &&
($selected_segment != {iseg}) &&
($selected_segment != {xseg})
- } {
+ } then {
Warning $lineNum $fileNum [mc "Using `%s' directive, but currently active segment is `%s'" [string toupper $directive] [string toupper $selected_segment]]
set seg {dseg}
- } {
+ } else {
set seg $selected_segment
}
@@ -3834,7 +3983,7 @@ namespace eval PreProcessor {
return [reserve_memory $label $seg $value $idx]
# Unknown request -> compilation error
- } {
+ } else {
CompilationError $lineNum $fileNum "Unknown error 4"
return 1
}
@@ -3907,7 +4056,7 @@ namespace eval PreProcessor {
}
}
- # Check if there is enought free space in the segment
+ # Check if there is enough free space in the segment
set end [expr {$segment_pointer($segment) + $value}]
if {$end > $max} {
Warning $lineNum $fileNum [mc "Exceeding %s segment boundary by %s $unit." $segment_name [expr {$max - $end}]]
@@ -3957,10 +4106,10 @@ namespace eval PreProcessor {
set const [string trimright $label {:}]
# Assing block pointer to symbolic name specified by label
- if {[lsearch -exact -ascii [subst "\$defined_$const_type"] $const] != -1} {
+ if {[lsearch -exact -ascii [subst -nocommands "\$defined_$const_type"] $const] != -1} {
SyntaxError $lineNum $fileNum [mc "Unable redefine constant: %s" $const]
return 1
- } {
+ } else {
# Check if this symbol is not already defined
if {[isConstAlreadyDefined $const]} {
Warning $lineNum $fileNum [mc "Ambiguous symbol definition: %s" $const]
@@ -3997,11 +4146,17 @@ namespace eval PreProcessor {
set const_name [string tolower $const_name]
# Search all lists of symbolic names
- if {[lsearch -exact -ascii [concat \
- $defined_BIT $defined_CODE $defined_DATA \
- $defined_IDATA $defined_XDATA $defined_SET \
- $defined_EQU $defined_MACRO $defined_SET_SPEC \
- $defined_EQU_SPEC] $const_name] != -1} {
+ if {
+ [lsearch -exact -ascii [concat \
+ $defined_BIT $defined_CODE $defined_DATA \
+ $defined_IDATA $defined_XDATA $defined_SET \
+ $defined_EQU $defined_MACRO $defined_SET_SPEC \
+ $defined_EQU_SPEC \
+ ${::CompilerConsts::defined_progVectors} \
+ ${::CompilerConsts::defined_SFRBitArea} \
+ ${::CompilerConsts::defined_SFR} \
+ ] $const_name] != -1
+ } then {
return 1
}
return 0
@@ -4021,7 +4176,7 @@ namespace eval PreProcessor {
variable selected_segment ;# Current memory segment (one of {cseg bseg dseg iseg xseg})
variable segment_pointer ;# Current memory segment pointer
- # Change memory segment
+ # Change memory segment
set selected_segment $directive
if {[regsub {^\.} [string tolower $line] {}] == $directive} {
return 0
@@ -4064,12 +4219,17 @@ namespace eval PreProcessor {
} else {
set segment_pointer($selected_segment) $value
CodeListing::set_addr $idx $value
- return 0
+
+ if {$ignore_undefined} {
+ return 2
+ } else {
+ return 0
+ }
}
return 1
}
- ## Take care of conditional compilation control directives (IF, ELSE, ENDIF)
+ ## Take care of conditional compilation control directives (IF, ELSE, ENDIF, IFN, IFDEF, IFNDEF, ELSEIF ELSEIFN ELSEIFDEF ELSEIFNDEF)
# --auxiliary procedure for 'parse_Consts_and_ConditionalCompilation'
# @parm String directive - Directive
# @parm String cond - Expression of the condition
@@ -4078,9 +4238,11 @@ namespace eval PreProcessor {
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable IfElse_map ;# Array: Conditional compilation map ($IfElse_map($level) == $bool)
+ variable IfElse_pcam ;# Array: Conditional compilation -- Positive condition already met ($IfElse_pcam($level) == $bool)
variable IfElse_level ;# Current level of conditional compilation evaluation
variable Enable ;# Bool: Compilation enabled (conditional compilation)
+ set cond_orig $cond
switch -- $directive {
{if} {
# Missing condition expression
@@ -4090,10 +4252,14 @@ namespace eval PreProcessor {
}
# Evaluate the condition expression
- set cond [ComputeExpr $cond]
- if {$cond == {}} {
- SyntaxError $lineNum $fileNum [mc "Invalid expression `%s'" $cond]
- set cond 1
+ if {$Enable} {
+ set cond [ComputeExpr $cond]
+ if {$cond == {}} {
+ SyntaxError $lineNum $fileNum [mc "Invalid expression `%s'" $cond_orig]
+ set cond 1
+ }
+ } else {
+ set cond 0
}
# Increment counter of nested block level
@@ -4101,6 +4267,7 @@ namespace eval PreProcessor {
# Adjust map of conditional compilation map and flag "Enable"
set IfElse_map($IfElse_level) $cond
+ set IfElse_pcam($IfElse_level) $cond
if {!$Enable || !$cond} {
set Enable 0
}
@@ -4113,9 +4280,13 @@ namespace eval PreProcessor {
}
# Evaluate the condition expression
- set cond [ComputeExpr $cond]
- if {$cond == {}} {
- SyntaxError $lineNum $fileNum [mc "Invalid expression `%s'" $cond]
+ if {$Enable} {
+ set cond [ComputeExpr $cond]
+ if {$cond == {}} {
+ SyntaxError $lineNum $fileNum [mc "Invalid expression `%s'" $cond_orig]
+ set cond 1
+ }
+ } else {
set cond 1
}
@@ -4127,6 +4298,7 @@ namespace eval PreProcessor {
# Adjust map of conditional compilation map and flag "Enable"
set IfElse_map($IfElse_level) $cond
+ set IfElse_pcam($IfElse_level) $cond
if {!$Enable || !$cond} {
set Enable 0
}
@@ -4142,13 +4314,14 @@ namespace eval PreProcessor {
}
# Evaluate the condition expression
- set cond [isConstAlreadyDefined $cond]
+ set cond [expr {$Enable && [isConstAlreadyDefined $cond]}]
# Increment counter of nested block level
incr IfElse_level
# Adjust map of conditional compilation map and flag "Enable"
set IfElse_map($IfElse_level) $cond
+ set IfElse_pcam($IfElse_level) $cond
if {!$Enable || !$cond} {
set Enable 0
}
@@ -4164,13 +4337,14 @@ namespace eval PreProcessor {
}
# Evaluate the condition expression
- set cond [expr {![isConstAlreadyDefined $cond]}]
+ set cond [expr {$Enable && ![isConstAlreadyDefined $cond]}]
# Increment counter of nested block level
incr IfElse_level
# Adjust map of conditional compilation map and flag "Enable"
set IfElse_map($IfElse_level) $cond
+ set IfElse_pcam($IfElse_level) $cond
if {!$Enable || !$cond} {
set Enable 0
}
@@ -4178,8 +4352,62 @@ namespace eval PreProcessor {
{else} {
if {[llength [array names IfElse_map $IfElse_level]] == 0} {
SyntaxError $lineNum $fileNum [mc "Unexpected `ELSE'"]
- } {
- set IfElse_map($IfElse_level) [expr {!$IfElse_map($IfElse_level)}]
+ } else {
+ set IfElse_map($IfElse_level) [expr {!$IfElse_pcam($IfElse_level)}]
+ set Enable 1
+ for {set i 1} {$i <= $IfElse_level} {incr i} {
+ set Enable [expr {$IfElse_map($i) && $Enable}]
+ }
+ }
+ }
+ {elseifn} -
+ {elseifdef} -
+ {elseifndef} -
+ {elseif} {
+ if {[llength [array names IfElse_map $IfElse_level]] == 0} {
+ SyntaxError $lineNum $fileNum [mc "Unexpected `ELSEIF'"]
+ } else {
+ # Missing condition expression
+ if {![string length $cond]} {
+ SyntaxError $lineNum $fileNum [mc "Missing condition"]
+ set cond 1
+ }
+
+ # Evaluate the condition expression
+ if {
+ !$IfElse_pcam($IfElse_level)
+ &&
+ ($IfElse_level == 1 || $IfElse_map([expr {$IfElse_level - 1}]))
+ } then {
+ switch -- $directive {
+ {elseif} {
+ set cond [ComputeExpr $cond]
+ }
+ {elseifn} {
+ set cond [ComputeExpr $cond]
+ if {$cond != {}} {
+ set cond [expr {!$cond}]
+ }
+ }
+ {elseifdef} {
+ set cond [isConstAlreadyDefined $cond]
+ }
+ {elseifndef} {
+ set cond [expr {![isConstAlreadyDefined $cond]}]
+ }
+ }
+ if {$cond == {}} {
+ SyntaxError $lineNum $fileNum [mc "Invalid expression `%s'" $cond_orig]
+ set cond 1
+ }
+ } else {
+ set cond 0
+ }
+
+ if {$cond} {
+ set IfElse_pcam($IfElse_level) 1
+ }
+ set IfElse_map($IfElse_level) $cond
set Enable 1
for {set i 1} {$i <= $IfElse_level} {incr i} {
set Enable [expr {$IfElse_map($i) && $Enable}]
@@ -4197,13 +4425,13 @@ namespace eval PreProcessor {
}
# Invalid directive usage
- } {
+ } else {
incr IfElse_level
SyntaxError $lineNum $fileNum [mc "Unexpected `ENDIF'"]
}
}
default {
- CompilationError $lineNum $fileNum "`$directive' is not a if/else/endif directive (procedure: If_Else_Endif)"
+ CompilationError $lineNum $fileNum "`$directive' is not a if/else/endif/ifn/ifdef/ifndef/elseif directive (procedure: If_Else_Endif)"
}
}
}
@@ -4239,7 +4467,7 @@ namespace eval PreProcessor {
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
- variable ErrorAtLine ;# Bool: Error occured on the current line
+ variable ErrorAtLine ;# Bool: Error occurred on the current line
# Handle directive "FLAG", which has the same meaning as "BIT"
if {$directive == {flag}} {
@@ -4249,7 +4477,7 @@ namespace eval PreProcessor {
# Detrminate 1st field and the last (3rd) field
if {![regexp {^\s*\w+} $line const]} {
set const {} ;# symbolic name
- } {
+ } else {
set const [string tolower [string trim $const]] ;# symbolic name
}
if {![regsub {^\w+\s+\.?\w+\s+} $line {} value]} {
@@ -4266,14 +4494,14 @@ namespace eval PreProcessor {
# Does value field contain comma ?
if {[string first {,} $value] != -1} {
# Is const field an instruction ?
- if {[lsearch -exact -ascii ${CompilerConsts::AllInstructions} $const] != -1} {
+ if {[lsearch -exact -ascii ${::CompilerConsts::AllInstructions} $const] != -1} {
# yes -> skip this line
if {$ignore_undefined} {
return 2
- } {
+ } else {
return 1
}
- } {
+ } else {
# no -> remove line & report syntax error
SyntaxError $lineNum $fileNum [mc "Invalid expression: `%s'" $value]
return 1
@@ -4306,6 +4534,7 @@ namespace eval PreProcessor {
Notice $lineNum $fileNum [mc "Special value (with no numerical representation) assigned to constant: %s <- %s" [string toupper $const] [string toupper $value]]
set special_value 1
} else {
+ set value_orig $value
set value [ComputeExpr $value $ignore_undefined]
}
@@ -4314,14 +4543,14 @@ namespace eval PreProcessor {
if {$ignore_undefined} {
return 2
}
- SyntaxError $lineNum $fileNum [mc "Invalid expression `%s'" $value]
+ SyntaxError $lineNum $fileNum [mc "Invalid expression `%s'" $value_orig]
return 1
}
# Adjust code listing
if {$special_value} {
CodeListing::set_spec_value $idx $value
- } {
+ } else {
CodeListing::set_value $idx $value
}
# Define symbolic name
@@ -4360,12 +4589,12 @@ namespace eval PreProcessor {
}
{data} {
if {
- ([lsearch -exact -ascii $defined_IDATA $const] != -1)
- ||
- ([lsearch -exact -ascii $defined_DATA $const] != -1)
- } {
- SyntaxError $lineNum $fileNum [mc "Trying to overwrite constant: %s" $const]
- return 1
+ ([lsearch -exact -ascii $defined_IDATA $const] != -1)
+ ||
+ ([lsearch -exact -ascii $defined_DATA $const] != -1)
+ } then {
+ SyntaxError $lineNum $fileNum [mc "Trying to overwrite constant: %s" $const]
+ return 1
}
if {$value > 0xFF} {
SyntaxError $lineNum $fileNum [mc "Expression out of range"]
@@ -4381,12 +4610,12 @@ namespace eval PreProcessor {
}
{idata} {
if {
- ([lsearch -exact -ascii $defined_IDATA $const] != -1)
- ||
- ([lsearch -exact -ascii $defined_DATA $const] != -1)
- } {
- SyntaxError $lineNum $fileNum [mc "Trying to overwrite constant: %s" $const]
- return 1
+ ([lsearch -exact -ascii $defined_IDATA $const] != -1)
+ ||
+ ([lsearch -exact -ascii $defined_DATA $const] != -1)
+ } then {
+ SyntaxError $lineNum $fileNum [mc "Trying to overwrite constant: %s" $const]
+ return 1
}
if {$value > 0xFF} {
SyntaxError $lineNum $fileNum [mc "Expression out of range"]
@@ -4426,7 +4655,7 @@ namespace eval PreProcessor {
set idx [lsearch -exact -ascii $defined_SET $const]
if {$idx != -1} {
set defined_SET [lreplace $defined_SET $idx $idx]
- } {
+ } else {
set idx [lsearch -exact -ascii $defined_SET_SPEC $const]
if {$idx != -1} {
set defined_SET_SPEC [lreplace $defined_SET_SPEC $idx $idx]
@@ -4440,7 +4669,7 @@ namespace eval PreProcessor {
if {$special_value} {
set const_EQU_SPEC($const) [string tolower $value]
lappend defined_EQU_SPEC $const
- } {
+ } else {
set const_EQU($const) $value
lappend defined_EQU $const
}
@@ -4483,19 +4712,19 @@ namespace eval PreProcessor {
# Set (new) variable value
if {[lsearch -exact -ascii $defined_SET $const] != -1} {
Notice $lineNum $fileNum [mc "Setting new variable value: %s <- %s" $const $value]
- } {
+ } else {
if {[isConstAlreadyDefined $const]} {
Warning $lineNum $fileNum [mc "Ambiguous symbol definition: %s" $const]
}
if {$special_value} {
lappend defined_SET_SPEC $const
- } {
+ } else {
lappend defined_SET $const
}
}
if {$special_value} {
lappend const_SET_SPEC($const) [list $lineNum $value]
- } {
+ } else {
lappend const_SET($const) [list $lineNum $value]
}
return 0
@@ -4511,18 +4740,19 @@ namespace eval PreProcessor {
if {
([lsearch -exact -ascii $defined_SET $const] != -1) ||
([lsearch -exact -ascii $defined_EQU $const] != -1)
- } {
+ } then {
return 1
- } {
+ } else {
return 0
}
}
## Get constant/variable value
- # @parm list args - {const_name [lineNumber]}
- # @parm Bool special_value = 0 - Allow special values like (A, AB, R0, etc.)
+ # @parm String const - const_name
+ # @parm Int line={} -lineNumber
+ # @parm Bool special_value=0 - Allow special values like (A, AB, R0, etc.)
# @return mixed - value or emty string if nothing found
- proc const_value args {
+ proc const_value {const {line {}} {special_value 0}} {
variable defined_SET ;# List of variables defined by 'SET'
variable defined_EQU ;# List of constants defined by 'EQU'
variable const_SET ;# Array: Constants defined by directive 'CODE'
@@ -4533,16 +4763,6 @@ namespace eval PreProcessor {
variable defined_SET_SPEC ;# List of special variables defined by 'SET'
variable defined_EQU_SPEC ;# List of special constants defined by 'EQU'
-
- # Determinate name of the constant and line number
- set const [lindex $args 0]
- set line [lindex $args 1]
-
- set special_value [lindex $args 2]
- if {$special_value != 1} {
- set special_value 0
- }
-
# Constants defined by directive 'EQU'
if {[lsearch -exact -ascii $defined_EQU $const] != -1} {
return $const_EQU($const)
@@ -4585,18 +4805,18 @@ namespace eval PreProcessor {
}
## Compute value of the given expression
- # @parm String - Expression to evaluate
- # @parm Bool = 0 - Ignore undefined symbolic names
- # @parm Int = {} - Current instruction address (for `$' expansion)
+ # @parm String expression - Expression to evaluate
+ # @parm Bool ignore_undefined=0 - Ignore undefined symbolic names
+ # @parm Int address={} - Current instruction address (for `$' expansion)
# @return Int - result or {}
- proc ComputeExpr args {
+ proc ComputeExpr {expression {ignore_undefined 0} {address {}}} {
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable original_expression ;# Auxiliary variable (see proc. 'ComputeExpr')
variable tmp ;# General purpose tempotary variable
- variable ErrorAtLine ;# Bool: Error occured on the current line
+ variable ErrorAtLine ;# Bool: Error occurred on the current line
variable check_sfr_usage ;# Bool: Check for legal usage of SFR and SFB
- variable avaliable_SFR ;# List: Avaliable SFR and SFB on the target MCU
+ variable available_SFR ;# List: available SFR and SFB on the target MCU
variable const_BIT ;# Array: Bit values -- ($const_BIT($bit_name) == $value)
variable const_CODE ;# Array: Constants defined by directive 'CODE'
@@ -4617,15 +4837,11 @@ namespace eval PreProcessor {
variable labels ;# Array: Values of defined labels ($labels($label) == $address)
variable defined_LABEL ;# List of defined labels
+ variable selected_segment ;# Current memory segment (one of {cseg bseg dseg iseg xseg})
+ variable segment_pointer ;# Current memory segment pointer
+
set ErrorAtLine 0
- # Parse arguments
- set expression [lindex $args 0]
- set ignore_undefined [lindex $args 1]
- set address [lindex $args 2]
- if {$ignore_undefined == {}} {
- set ignore_undefined 0
- }
# Make backup copy of the original expression
set original_expression $expression
@@ -4639,7 +4855,7 @@ namespace eval PreProcessor {
if {[regexp {[\(\)]} $expression]} {
set left_p 0
set idx 0
- while 1 {
+ while {1} {
set idx [string first {(} $expression $idx]
if {$idx == -1} {break}
incr idx
@@ -4647,7 +4863,7 @@ namespace eval PreProcessor {
}
set right_p 0
set idx 0
- while 1 {
+ while {1} {
set idx [string first {)} $expression $idx]
if {$idx == -1} {break}
incr idx
@@ -4655,7 +4871,7 @@ namespace eval PreProcessor {
}
if {$right_p != $left_p} {
- SyntaxError $lineNum $fileNum [mc "Invalid expression - paranthesis are not balanced: `%s'" $original_expression]
+ SyntaxError $lineNum $fileNum [mc "Invalid expression - parentheses are not balanced: `%s'" $original_expression]
}
}
@@ -4678,12 +4894,12 @@ namespace eval PreProcessor {
([string first {low} [string tolower $expression]] != -1)
||
([string first {high} [string tolower $expression]] != -1)
- } {
- foreach operator {low high} \
- before {0xFF&int( int(} \
+ } then {
+ foreach operator {low high} \
+ before {0xFF&int( int(} \
after {) )/0x100} \
{
- while 1 {
+ while {1} {
if {![regexp -nocase -- "\\s$operator\\s+((\\w+)|(\\(\[^\\(\\)\]+\\)))" $expression str]} {
break
}
@@ -4709,6 +4925,21 @@ namespace eval PreProcessor {
foreach word [replace_in_strings $expression { } "\a"] {
if {$word == {}} {continue}
+ # Handle prefix notation for hexadecimal numbers, like 0xfa
+ if {
+ [string index $word 0] == {0}
+ &&
+ ([string index $word 1] == {x} || [string index $word 1] == {X})
+ &&
+ [string is xdigit [string index $word 2]]
+ } then {
+ set word [string replace $word 0 1]
+ if {![string is digit [string index $word 0]]} {
+ set word "0${word}"
+ }
+ append word {h}
+ }
+
if {[regexp {^\d\w+$} $word] && ![regexp {^\d+$} $word]} {
set base [string index $word end]
set word [string range $word 0 {end-1}]
@@ -4722,37 +4953,37 @@ namespace eval PreProcessor {
{h} {
if {![NumSystem::ishex $word]} {
SyntaxError $lineNum $fileNum [mc "Invalid numeric value: %s (should be hexadecimal number)" "${word}h"]
- } {
+ } else {
set word [expr "0x$word"]
}
}
{b} {
if {![NumSystem::isbin $word]} {
SyntaxError $lineNum $fileNum [mc "Invalid numeric value: %s (should be binary number)" "${word}b"]
- } {
+ } else {
set word [NumSystem::bin2dec $word]
}
}
{o} {
if {![NumSystem::isoct $word]} {
SyntaxError $lineNum $fileNum [mc "Invalid numeric value: %s (should be octal number)" "${word}o"]
- } {
+ } else {
set word [NumSystem::oct2dec $word]
}
}
{q} {
if {![NumSystem::isoct $word]} {
SyntaxError $lineNum $fileNum [mc "Invalid numeric value: %s (should be octal number)" "${word}q"]
- } {
+ } else {
set word [NumSystem::oct2dec $word]
}
}
}
- } {
+ } else {
if {[string index $word end] == {'}} {
if {[string index $word 0] != {'}} {
SyntaxError $lineNum $fileNum [mc "Invalid value: `%s' (should be char)" $word]
- } {
+ } else {
set word [string range $word 1 end-1]
regsub -all "\a" $word { } word
set word [character2number [subst -nocommands -novariables $word]]
@@ -4767,15 +4998,29 @@ namespace eval PreProcessor {
# Expand possible constants and variables
foreach word $expression {
if {$word == {}} {continue}
- # Current instruction address `$'
- if {$address != {} && $word == {$}} {
- set word $address
+ # Dollar sign (`$')
+ if {$word == {$}} {
+ # Current instruction address
+ if {$address != {}} {
+ set word $address
+ # Address pointer in the selected memory segment
+ } elseif {$selected_segment != {cseg}} {
+ set word $segment_pointer($selected_segment)
+ } elseif {!$ignore_undefined} {
+ SyntaxError $lineNum $fileNum [mc "Value of `\$' is unknown at this point" $word]
+ set ErrorAtLine 1
+ }
+
lappend tmp $word
continue
}
# Normal symbolic name
- if {![regexp {^[A-Za-z_].*$} $word]} {
+ if {![regexp {^(\?\?)?[A-Za-z_].*$} $word]} {
+ set word [string trimleft $word 0]
+ if {$word == {}} {
+ set word 0
+ }
lappend tmp $word
continue
}
@@ -4792,9 +5037,9 @@ namespace eval PreProcessor {
if {
[lsearch -ascii -exact $::CompilerConsts::defined_SFR $word] != -1
&&
- [lsearch -ascii -exact $avaliable_SFR $word] == -1
- } {
- Warning $lineNum $fileNum [mc "Special function register \"%s\" is not avaliable on the target MCU" [string toupper $word]]
+ [lsearch -ascii -exact $available_SFR $word] == -1
+ } then {
+ Warning $lineNum $fileNum [mc "Special function register \"%s\" is not available on the target MCU" [string toupper $word]]
}
}
set word $const_DATA($word)
@@ -4820,9 +5065,9 @@ namespace eval PreProcessor {
if {
[lsearch -ascii -exact $::CompilerConsts::defined_SFRBitArea $word] != -1
&&
- [lsearch -ascii -exact $avaliable_SFR $word] == -1
- } {
- Warning $lineNum $fileNum [mc "Special function bit \"%s\" is not avaliable on the target MCU" [string toupper $word]]
+ [lsearch -ascii -exact $available_SFR $word] == -1
+ } then {
+ Warning $lineNum $fileNum [mc "Special function bit \"%s\" is not available on the target MCU" [string toupper $word]]
}
}
CodeListing::symbol_used $word {bit}
@@ -4839,6 +5084,7 @@ namespace eval PreProcessor {
return {}
}
SyntaxError $lineNum $fileNum [mc "Undefined symbol name: %s" $word]
+ set ErrorAtLine 1
set word 1
}
@@ -4853,11 +5099,15 @@ namespace eval PreProcessor {
# Compute expression and return possible result
if {[catch {
set expression [expr "$expression"]
- }]} {
+ }]} then {
return {}
}
- set tmp [expr {int($expression)}]
+ if {[catch {
+ set tmp [expr {int($expression)}]
+ }]} then {
+ return {}
+ }
if {($tmp - $expression) != 0} {
Notice $lineNum $fileNum [mc "Floating point value converted to integer value `%s' -> `%s'" $expression $tmp]
}
@@ -4880,8 +5130,8 @@ namespace eval PreProcessor {
## Remove comments and redutant white space
# @return void
proc trim_code {} {
- variable asm ;# Resulting precompiled code
- variable tmp_asm ;# Tempotary auxiliary precompiled code
+ variable asm ;# Resulting pre-compiled code
+ variable tmp_asm ;# Temporary auxiliary pre-compiled code
variable lineNum ;# Number of the current line
variable fileNum ;# Number of the current file
variable idx ;# Current position in asm list
@@ -4896,7 +5146,9 @@ namespace eval PreProcessor {
incr idx
# Update after each 25 iterations
- if {[expr {$idx % 25}] == 0} ${::Compiler::Settings::UPDATE_COMMAND}
+ if {[expr {$idx % 25}] == 0} {
+ ${::Compiler::Settings::UPDATE_COMMAND}
+ }
if {${::Compiler::Settings::ABORT_VARIABLE}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Aborted"]
free_resources
@@ -4917,10 +5169,10 @@ namespace eval PreProcessor {
# Remove comment
set tmp_line $line
- while 1 {
+ while {1} {
if {[regexp {'[^']*'} $tmp_line str]} {
regsub {'[^']*'} $tmp_line [string repeat {_} [string length $str]] tmp_line
- } {
+ } else {
break
}
}
@@ -4954,7 +5206,7 @@ namespace eval PreProcessor {
# @return String - result
proc replace_in_strings {string search replacement} {
set idx 0
- while 1 {
+ while {1} {
if {![regexp -start $idx -- {'[^']*'} $string str]} {
break
}
@@ -4980,7 +5232,7 @@ namespace eval PreProcessor {
if {[string length $value] == 1} {
binary scan $value c value
return $value
- } {
+ } else {
if {[string index $value 0] == "\\"} {
set value [string range $value 1 end]
switch -- $value {
@@ -5016,7 +5268,7 @@ namespace eval PreProcessor {
return {}
}
}
- } {
+ } else {
SyntaxError $lineNum $fileNum [mc "Cannot to use string `%s' as value" $value]
return {}
}
@@ -5024,15 +5276,15 @@ namespace eval PreProcessor {
}
## Report error message -- compilation error (bug in compiler ?)
- # @parm Int LineNumber - Number of line where the error occured
- # @parm Int FileNumber - Number of file where the error occured, {} == unknown
+ # @parm Int LineNumber - Number of line where the error occurred
+ # @parm Int FileNumber - Number of file where the error occurred, {} == unknown
# @parm String ErrorInfo - Error string
# @return void
proc CompilationError {LineNumber FileNumber ErrorInfo} {
variable included_files ;# List: Unique unsorted list of included files
variable working_dir ;# String: Current working directory
variable idx ;# Current position in asm list
- variable error_count ;# Number of errors occured
+ variable error_count ;# Number of errors occurred
# Increment error counter
incr error_count
@@ -5050,14 +5302,14 @@ namespace eval PreProcessor {
set filename "\"$filename\""
}
set filename [mc " in %s" $filename]
- } {
+ } else {
set filename {}
}
if {${::Compiler::Settings::WARNING_LEVEL} < 3} {
if {${::Compiler::Settings::NOCOLOR}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[::Compiler::msgc {EL}][mc "Compilation error at %s: %s" "$LineNumber$filename" $ErrorInfo]
- } {
+ } else {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "\033\[31;1mCompilation error\033\[m at \033\[31;1;4m%s\033\[m%s: %s" $LineNumber $filename $ErrorInfo]
}
@@ -5065,8 +5317,8 @@ namespace eval PreProcessor {
}
## Report notice
- # @parm Int LineNumber - Number of line where it occured
- # @parm Int FileNumber - Number of file where the error occured, {} == unknown
+ # @parm Int LineNumber - Number of line where it occurred
+ # @parm Int FileNumber - Number of file where the error occurred, {} == unknown
# @parm String ErrorInfo - Text of the notice
# @return void
proc Notice {LineNumber FileNumber ErrorInfo} {
@@ -5082,14 +5334,14 @@ namespace eval PreProcessor {
set filename "\"$filename\""
}
set filename [mc " in %s" $filename]
- } {
+ } else {
set filename {}
}
if {${::Compiler::Settings::WARNING_LEVEL} < 1} {
if {${::Compiler::Settings::NOCOLOR}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[::Compiler::msgc {WL}][mc "Notice at %s: %s" "$LineNumber$filename" $ErrorInfo]
- } {
+ } else {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "\033\[33;1mNotice\033\[m at \033\[33;1;4m%s\033\[m%s: %s" $LineNumber $filename $ErrorInfo]
}
@@ -5097,15 +5349,15 @@ namespace eval PreProcessor {
}
## Report warning message
- # @parm Int LineNumber - Number of line where it occured
- # @parm Int FileNumber - Number of file where the error occured, {} == unknown
+ # @parm Int LineNumber - Number of line where it occurred
+ # @parm Int FileNumber - Number of file where the error occurred, {} == unknown
# @parm String ErrorInfo - Text of the warning
# @return void
proc Warning {LineNumber FileNumber ErrorInfo} {
variable working_dir ;# String: Current working directory
variable included_files ;# List: Unique unsorted list of included files
variable idx ;# Current position in asm list
- variable warning_count ;# Number of warnings occured
+ variable warning_count ;# Number of warnings occurred
# Increment warning counter
incr warning_count
@@ -5123,32 +5375,32 @@ namespace eval PreProcessor {
set filename "\"$filename\""
}
set filename [mc " in %s" $filename]
- } {
+ } else {
set filename {}
}
if {${::Compiler::Settings::WARNING_LEVEL} < 2} {
if {${::Compiler::Settings::NOCOLOR}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[::Compiler::msgc {WL}][mc "Warning at %s: %s" "$LineNumber$filename" $ErrorInfo]
- } {
+ } else {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "\033\[33mWarning\033\[m at \033\[33;4m%s\033\[m%s: %s" $LineNumber $filename $ErrorInfo]
}
}
}
- ## Report error message -- syntax error (badly formated input code)
- # @parm Int LineNumber - Number of line where the error occured
- # @parm Int FileNumber - Number of file where the error occured, {} == unknown
+ ## Report error message -- syntax error (badly formatted input code)
+ # @parm Int LineNumber - Number of line where the error occurred
+ # @parm Int FileNumber - Number of file where the error occurred, {} == unknown
# @parm String ErrorInfo - Error string
# @return void
proc SyntaxError {LineNumber FileNumber ErrorInfo} {
variable working_dir ;# String: Current working directory
variable included_files ;# List: Unique unsorted list of included files
variable idx ;# Current position in asm list
- variable error_count ;# Number of errors occured
- variable ErrorAtLine ;# Bool: Error occured on the current line
- variable Error ;# Bool: An error occured during precompilation
+ variable error_count ;# Number of errors occurred
+ variable ErrorAtLine ;# Bool: Error occurred on the current line
+ variable Error ;# Bool: An error occurred during precompilation
# Adjust NS variable
incr error_count
@@ -5168,17 +5420,21 @@ namespace eval PreProcessor {
set filename "\"$filename\""
}
set filename [mc " in %s" $filename]
- } {
+ } else {
set filename {}
}
if {${::Compiler::Settings::WARNING_LEVEL} < 3} {
if {${::Compiler::Settings::NOCOLOR}} {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[::Compiler::msgc {EL}][mc "Syntax error at %s: %s" "$LineNumber$filename" $ErrorInfo]
- } {
+ } else {
${::Compiler::Settings::TEXT_OUPUT_COMMAND} \
[mc "\033\[31;1mSyntax error\033\[m at \033\[31;1;4m%s\033\[m%s: %s" $LineNumber $filename $ErrorInfo]
}
}
}
}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard