diff options
Diffstat (limited to 'lib/compiler')
-rw-r--r--[-rwxr-xr-x] | lib/compiler/assembler.tcl | 71 | ||||
-rw-r--r--[-rwxr-xr-x] | lib/compiler/codelisting.tcl | 210 | ||||
-rw-r--r--[-rwxr-xr-x] | lib/compiler/compiler.tcl | 248 | ||||
-rw-r--r--[-rwxr-xr-x] | lib/compiler/compilerconsts.tcl | 44 | ||||
-rw-r--r--[-rwxr-xr-x] | lib/compiler/disassembler.tcl | 149 | ||||
-rw-r--r--[-rwxr-xr-x] | lib/compiler/external_compiler.tcl | 220 | ||||
-rw-r--r--[-rwxr-xr-x] | lib/compiler/preprocessor.tcl | 1564 |
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 |