summaryrefslogtreecommitdiff
path: root/lib/compiler/compiler.tcl
diff options
context:
space:
mode:
authorAndrej Shadura <andrewsh@debian.org>2018-05-08 15:59:29 +0200
committerAndrej Shadura <andrewsh@debian.org>2018-05-08 15:59:29 +0200
commit5b8466f7fae0e071c0f4eda13051c93313910028 (patch)
tree7061957f770e5e245ba00666dad912a2d44e7fdc /lib/compiler/compiler.tcl
Import Upstream version 1.3.7
Diffstat (limited to 'lib/compiler/compiler.tcl')
-rwxr-xr-xlib/compiler/compiler.tcl557
1 files changed, 557 insertions, 0 deletions
diff --git a/lib/compiler/compiler.tcl b/lib/compiler/compiler.tcl
new file mode 100755
index 0000000..35dea32
--- /dev/null
+++ b/lib/compiler/compiler.tcl
@@ -0,0 +1,557 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+############################################################################
+# Copyright (C) 2007-2009 by Martin Ošmera #
+# martin.osmera@gmail.com #
+# #
+# This program is free software; you can redistribute it and#or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation; either version 2 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program; if not, write to the #
+# Free Software Foundation, Inc., #
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
+############################################################################
+
+# --------------------------------------------------------------------------
+# 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/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 warning_count ;# Number of warning reported during compilation
+
+ variable in_IDE 0 ;# Bool: Running in IDE (I mean GUI)
+
+ # Procedure which do nothing (for better portability)
+ proc doNothing args {}
+
+ ## Initiate compilation
+ # @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
+ # @return Bool - result
+ proc compile {project_dir current_dir input_file_name input_file_extension} {
+ variable error_count ;# Number of errors occured during compilation
+ variable warning_count ;# Number of warning reported during compilation
+
+ # Compiler settings to defaults
+ Compiler::Settings::restoreDefaults
+
+ # Adjust compiler settings
+ if {${::Compiler::Settings::_print} == 2} {
+ set ::Compiler::Settings::PRINT 0
+ } {
+ set ::Compiler::Settings::PRINT 1
+ }
+ if {${::Compiler::Settings::_object} == 2} {
+ set ::Compiler::Settings::OBJECT 0
+ } {
+ set ::Compiler::Settings::OBJECT 1
+ }
+
+ # Reset errors and warnings counters
+ set error_count 0
+ set warning_count 0
+
+ # Set input filename and determinate time of start of compilation
+ set Settings::INPUT_FILE_NAME $input_file_name
+ set sec [clock seconds]
+
+ # Adjust input file extension
+ if {$input_file_extension != {}} {
+ set input_file_extension ".$input_file_extension"
+ }
+
+ # Check for usability of the given input file
+ set file [file join $current_dir $input_file_name$input_file_extension]
+
+ # Open and read contents of the input file
+ if {[catch {
+ set asm [open $file r]
+ set asm_data [read $asm]
+ close $asm
+ }]} {
+ 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"]
+ }
+ return 0
+ }
+
+ # Initialize preprocessor
+ if {!${::Compiler::Settings::QUIET}} {
+ if {${::Compiler::Settings::NOCOLOR}} {
+ ${Settings::TEXT_OUPUT_COMMAND} \
+ "\n\n[::Compiler::msgc {SN}][mc {Compiling file: %s} $input_file_name$input_file_extension]"
+ } {
+ ${Settings::TEXT_OUPUT_COMMAND} \
+ [mc "\n\nCompiling file: \033\[34;1m%s\033\[m" $input_file_name$input_file_extension]
+ }
+ ${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} {
+ 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"]
+ }
+ report_status $current_dir $input_file_name
+ return 0
+ }
+
+ if {${Settings::ABORT_VARIABLE}} {return 0}
+
+ # Initialize Assembler
+ if {!${::Compiler::Settings::QUIET}} {
+ ${Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "Compiling ..."]
+ }
+ assembler::compile \
+ [md5::md5 -hex -file $file] \
+ [clock format [clock seconds] -format "%D"] \
+ $project_dir \
+ [file join $current_dir $input_file_name$input_file_extension] \
+ ${::PreProcessor::included_files} \
+ $precompiledCode
+ set ::PreProcessor::included_files {}
+ 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"]
+ }
+ report_status $current_dir $input_file_name
+ return 0
+ }
+
+ if {${Settings::ABORT_VARIABLE}} {return 0}
+
+ # Write resulting object code
+ if {${Settings::OBJECT}} {
+ if {${Settings::OBJECT_FILE} != {}} {
+ set object_file ${Settings::OBJECT_FILE}
+ } {
+ set object_file $input_file_name
+ append object_file {.hex}
+ }
+ if {${::Compiler::Settings::NOCOLOR}} {
+ ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ [mc "Creating IHEX8 ...\t\t\t-> \"%s\"" $object_file]
+ } {
+ ${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]
+ }]} {
+ if {${::Compiler::Settings::NOCOLOR}} {
+ ${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::msgc {EN}][mc "Compilation FAILED !"]
+ } {
+ ${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} \
+ [mc "\033\[31;1mCompilation FAILED !\033\[m"]
+ }
+ report_status $current_dir $input_file_name
+ return 0
+ } else {
+ puts -nonewline $hex ${assembler::hex}
+ close $hex
+ }
+ }
+
+ if {${Settings::ABORT_VARIABLE}} {return 0}
+
+ # Write resulting binary object code
+ if {${Settings::CREATE_BIN_FILE}} {
+ if {!${::Compiler::Settings::QUIET}} {
+ if {${::Compiler::Settings::NOCOLOR}} {
+ ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ [mc "Creating object file ...\t\t-> \"%s\"" "${input_file_name}.bin"]
+ } {
+ ${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]
+ }]} {
+ 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.bin]]
+ ${Settings::TEXT_OUPUT_COMMAND} \
+ [::Compiler::msgc {EN}][mc "Compilation FAILED !"]
+ } {
+ ${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} \
+ [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}
+ close $bin
+ }
+ set bin_data {}
+ }
+ set hex_data {}
+
+ if {${Settings::ABORT_VARIABLE}} {return 0}
+
+ # Write simulator data file
+ if {${Settings::CREATE_SIM_FILE}} {
+ if {!${::Compiler::Settings::QUIET}} {
+ if {${::Compiler::Settings::NOCOLOR}} {
+ ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ [mc "Creating assembler debug file ...\t-> \"%s\"" "${input_file_name}.adf"]
+ } {
+ ${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]
+ }]} {
+ 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::msgc {EN}][mc "Compilation FAILED !"]
+ } {
+ ${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} \
+ [mc "\033\[31;1mCompilation FAILED !\033\[m"]
+ }
+ report_status $current_dir $input_file_name
+ return 0
+ } {
+ puts -nonewline $sim ${assembler::adf}
+ close $sim
+ }
+ }
+
+ if {${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}]
+ }
+ }
+ if {${::Compiler::Settings::NOCOLOR}} {
+ ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ [::Compiler::msgc {SN}][mc "Compilation successful. (time: %s sec.)" [expr {[clock seconds] - $sec}]]
+ } {
+ ${Compiler::Settings::TEXT_OUPUT_COMMAND} \
+ [mc "\033\[32;1mCompilation successful.\033\[m (time: %s sec.)" [expr {[clock seconds] - $sec}]]
+ }
+ }
+
+ # Successful
+ return 1
+ }
+
+ ## Free resureces reserved during compilation
+ # @return void
+ proc free_resources {} {
+ ::assembler::free_resources
+ ::CodeListing::free_resources
+ set ::PreProcessor::asm {}
+ set ::PreProcessor::tmp_asm {}
+ }
+
+ ## Report final status and write code listing file
+ # @parm String current_dir - Working directory
+ # @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 warning_count ;# Number of warning reported during compilation
+
+ # Determinate name of code listing file
+ if {${Settings::PRINT_FILE} != {}} {
+ set print_file ${Settings::PRINT_FILE}
+ } {
+ set print_file $input_file_name
+ append print_file {.lst}
+ }
+
+ # Message "Creting code listing file"
+ if {!${::Compiler::Settings::QUIET}} {
+ 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]
+ }
+ }
+
+ # Report number of errors and warning
+ if {!${::Compiler::Settings::QUIET}} {
+ if {$::TRANSLATION_LOADED} {
+ set text [mc "%s errors, %s warnings" $error_count $warning_count]
+ } {
+ set text "$error_count error"
+ if {$error_count != 1} {
+ append text "s"
+ }
+ append text ", $warning_count warning"
+ if {$warning_count != 1} {
+ append text "s"
+ }
+ }
+ if {${::Compiler::Settings::NOCOLOR}} {
+ ${Compiler::Settings::TEXT_OUPUT_COMMAND} $text
+ } {
+ ${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"]
+ }
+ return 0
+ } else {
+ puts -nonewline $lst [CodeListing::getListing]
+ close $lst
+ }
+ }
+
+ ## Create backup copy of the specified file
+ # @parm String current_dir - Working directory
+ # @parm String filename - File name
+ # @parm String extension - File extension
+ # @return void
+ proc makeBackupFile {current_dir filename} {
+ if {[file exists [file join $current_dir $filename]]} {
+ catch {
+ file rename -force \
+ [file join $current_dir $filename] \
+ "[file join $current_dir $filename]~"
+ }
+ }
+ }
+
+ ## Namespace containing compiler settings
+ namespace eval Settings {
+ ## Peerhole optimalization enable flag
+ variable optim_ena 0 ;# Bool: 0 == disabled; 1 == enabled
+
+ ## Memory limits
+ variable iram_size 0x100 ;# Internal data memory
+ variable xram_size 0x10000 ;# External data memory
+ variable code_size 0x10000 ;# Overall program memory
+
+ ## Enable/Disable controls
+ # options:
+ # 0 - Controled by compiler
+ # 1 - Always
+ # 2 - Never
+ variable _symbols 0 ;# Control: $SYMBOLS
+ variable _print 0 ;# Control: $PRINT
+ variable _object 0 ;# Control: $OBJECT
+
+ # Options:
+ # 0 - use value defined in source code
+ # 1 - ignore
+ variable _nomod 0 ;# Control: $NOMOD
+ variable _paging 0 ;# Control: $PAGING
+ variable _pagelength 0 ;# Control: $PAGELENGTH(int)
+ variable _pagewidth 0 ;# Control: $PAGEWIDTH(int)
+ variable _title 0 ;# Control: $TITLE('string')
+ variable _date 0 ;# Control: $DATE('date')
+ variable _list 0 ;# Controls: $LIST $NOLIST; Directives: list nolist
+
+ # Default values for some controls
+ variable _object_file {} ;# Location of IHEX8 object file
+ variable _print_file {} ;# Location of Code Listing file
+ variable _title_value {} ;# Title string for code listing
+ variable _date_value {} ;# Date string for code listing
+ variable _nomod_value 0 ;# Bool: use predefined SFR addresses
+ variable _paging_value 0 ;# Bool: Use Form Feeds in code listing
+ variable _pagelength_value 0 ;# Number of lines per page in code listing
+ variable _pagewidth_value 132 ;# Number of characters per line in code listing
+
+ # Active settings
+ variable SYMBOLS {} ;# Bool: Include table of symbols to code listing
+ variable NOMOD {} ;# Bool: Do not use predefined SFR register addresses
+ variable PAGING {} ;# Bool: Use 'FF' in code listing
+ variable PAGELENGTH {} ;# Number of characters per line in code listing
+ variable PAGEWIDTH {} ;# Number of characters per line in code listing
+ variable TITLE {} ;# Title string for code listing
+ variable DATE {} ;# Date string for code listing
+ variable OBJECT {} ;# Bool: Generate IHEX8 object file
+ variable OBJECT_FILE {} ;# Location of IHEX8 object file
+ variable PRINT {} ;# Bool: Generate Code Listing file
+ variable PRINT_FILE {} ;# Location of Code Listing file
+ variable INPUT_FILE_NAME {} ;# Location of input file
+
+ variable CREATE_SIM_FILE 1 ;# Bool: Crete simulator data file
+ variable CREATE_BIN_FILE 1 ;# Bool: Create binary object code
+
+ variable max_ihex_rec_length 16 ;# Int: Maximum length of IHEX-8 record
+
+ ## Warning level
+ # 0 - all
+ # 1 - Errors + Warnings
+ # 2 - Errros only
+ # 3 - Nothing
+ variable WARNING_LEVEL 0
+
+ # Do not print what's going on
+ variable QUIET 0
+ # Update command (eg. 'update')
+ variable UPDATE_COMMAND {::Compiler::doNothing}
+ # Bool: 1 == abort now
+ variable ABORT_VARIABLE 0
+ # Text output command (eg. 'puts')
+ variable TEXT_OUPUT_COMMAND {puts}
+ # Disable color output
+ variable NOCOLOR 1
+
+ ## Restore default settings
+ # @return void
+ proc restoreDefaults {} {
+
+ variable _symbols ;# Control: $SYMBOLS
+ variable _print ;# Control: $PRINT
+ variable _object ;# Control: $OBJECT
+
+ variable SYMBOLS ;# Bool: Include table of symbols to code listing
+ variable NOMOD ;# Bool: Do not use predefined SFR register addresses
+ variable PAGING ;# Bool: Use 'FF' in code listing
+ variable PAGELENGTH ;# Number of characters per line in code listing
+ variable PAGEWIDTH ;# Number of characters per line in code listing
+ variable TITLE ;# Title string for code listing
+ variable DATE ;# Date string for code listing
+ variable OBJECT ;# Bool: Generate IHEX8 object file
+ variable OBJECT_FILE ;# Location of IHEX8 object file
+ variable PRINT ;# Bool: Generate Code Listing file
+ variable PRINT_FILE ;# Location of Code Listing file
+ variable INPUT_FILE_NAME ;# Location of input file
+
+ variable _object_file ;# Location of IHEX8 object file
+ variable _print_file ;# Location of Code Listing file
+ variable _title_value ;# Title string for code listing
+ variable _date_value ;# Date string for code listing
+ variable _nomod_value ;# Bool: use predefined SFR addresses
+ variable _paging_value ;# Bool: Use Form Feeds in code listing
+ variable _pagelength_value ;# Number of lines per page in code listing
+ variable _pagewidth_value ;# Number of characters per line in code listing
+
+ # Reset settings
+ foreach var {
+ NOMOD PAGING PAGELENGTH PAGEWIDTH
+ TITLE DATE OBJECT_FILE PRINT_FILE
+ } default {
+ _nomod_value _paging_value _pagelength_value _pagewidth_value
+ _title_value _date_value _object_file _print_file
+ } {
+ set $var [subst "\$$default"]
+ }
+
+ # Finalize
+ if {($_symbols == 1) || ($_symbols == 0)} {
+ set SYMBOLS 1
+ } elseif {$_symbols == 2} {
+ set SYMBOLS 0
+ }
+ if {($_print == 1) || ($_print == 0)} {
+ set PRINT 1
+ } elseif {$_print == 2} {
+ set PRINT 0
+ }
+ if {($_object == 1) || ($_object == 0)} {
+ set OBJECT 1
+ } elseif {$_object == 2} {
+ set OBJECT 0
+ }
+ }
+ }
+
+ ## Generate parser-friendly error code
+ # @parm String code - Basic message specification (e.g. EL means ERROR and LINE)
+ # @return Char - A special (unprintable) character represention the message
+ proc msgc {code} {
+ variable in_IDE ;# Bool: Running in IDE (I mean GUI)
+
+ if {!$in_IDE} {
+ return {}
+ }
+
+ switch -- $code {
+ {EL} { ;# ERROR and LINE specification
+ return "|EL|"
+ }
+ {EN} { ;# Just ERROR
+ return "|EN|"
+ }
+ {WL} { ;# WARNING and LINE specification
+ return "|WL|"
+ }
+ {WN} { ;# Just WARNING
+ return "|WN|"
+ }
+ {SN} { ;# SUCCESS
+ return "|SN|"
+ }
+ }
+ }
+}
+
+# Compiler settings to defaults
+Compiler::Settings::restoreDefaults