#! /usr/bin/original-awk -f # HAS is Home Accounting System written in AT&T AWK # Copyright (C) 2008 Matous J. Fialka, # Release under the terms of The MIT License BEGIN { Operator = "+" } { proceedLine() } END { exit ExitCode } function error(_Message) { printf("Error: %s on line %d\n", _Message, FNR) > "/dev/stderr" close("/dev/stderr") exit ExitCode = 1 } function getValue(_Variable) { return Variables[_Variable] } function getVariable(_Variable) { while (! (isEmpty() || isAssignment())) { if (_Variable == "") { _Variable = shift() } else { _Variable = ((_Variable " ") shift()) } } return _Variable } function hasVariable(_Variable, _Temp) { for (_Temp in Variables) { if (_Variable == _Temp) { return 1 } } return 0 } function isAssignment() { return $1 == ":" } function isBlankBeginning() { return $0 ~ /^[[:blank:]]+/ } function isBlank() { return $1 ~ /^[[:blank:]]*$/ } function isConstant() { return $1 ~ /^[-+]?([[:digit:]]+\.?|\.[[:digit:]])[[:digit:]]*([eE][-+]?[[:digit:]]+)?$/ } function isEmpty() { return $1 == "" } function isOperator() { return $1 ~ /^[-+x\/%?!=]$/ } function isVariableStart() { return ! (isOperator() || isConstant() || isAssignment() || isEmpty()) } function performOperation() { if (LeftSide == 2) { LeftPart = getValue(LeftPart) } if (Operator == "+") { Answer += LeftPart return 0 } if (Operator == "-") { Answer -= LeftPart return 0 } if (Operator == "x") { Answer *= LeftPart return 0 } if (Operator == "/") { if (LeftPart == 0) { error("divizion by zero") } Answer /= LeftPart return 0 } if (Operator == "%") { Answer *= LeftPart / 100 return 0 } if (Operator == "!") { Answer = LeftPart return 0 } if (Operator == "=") { Answer = 0 Operator = "+" } } function prepareOperation() { if (Operator ~ /[?!]/) { if (LeftSide == 0) { LeftSide = 1 LeftPart = Answer } } if (Operator == "=") { LeftSide = 1 LeftPart = Answer if (RightSide == 2) { setValue(RightPart, LeftPart) } if (RightSide == 1) { RightSide = 1 RightPart = LeftPart } } } function printLine(_WordNumber, _WordsCount, _Word, _LineLength) { _WordNumber = 1 _WordsCount = NF _LineLength = length(_Word = shift()) while (_WordsCount++) { if (_LineLength > 72) { printf "\n", _Word _LineLength = length(_Word) } printf "%s", _Word if (isEmpty()) { break } if (_WordNumber <= _WordsCount) { printf " " _LineLength += 1 } _LineLength += length(_Word = shift()) } printf "\n" } function printOperation() { if (OperatorForced) { OperatorForced = 0 printf "\t" } else { printf "%c\t", Operator } if (LeftSide == 2) { printf " % 30s", LeftPart } else { printf " % 30.2f", LeftPart } printf " :" if (RightSide == 2) { printf " % 30s", RightPart } else { if (RightSide == 1) { printf " % 30.2f", RightPart } } printf "\n" } function proceedLine() { if (isBlank()) { if (! BlankPrinted) { BlankPrinted = 1 print $0 } return 0 } BlankPrinted = 0 if (isBlankBeginning() && ! isOperator()) { OperatorForced = 1 } if (isOperator() || OperatorForced) { if (! OperatorForced) { Operator = shift() } LeftSide = 0 RightSide = 0 if (isConstant()) { LeftSide = 1 LeftPart = shift() if (isAssignment()) { shift() if (isVariableStart()) { RightSide = 2 setValue(RightPart = getVariable(), LeftPart) } } else { RightPart = 0 } } else { if (isVariableStart()) { LeftSide = 2 LeftPart = getVariable() if (isAssignment()) { shift() if (isVariableStart()) { RightSide = 2 setValue(LeftPart, getValue(RightPart = getVariable())) } else { if (isConstant()) { RightSide = 1 if (! hasVariable(LeftPart)) { setValue(LeftPart, RightPart = shift()) } else { RightPart = getValue(LeftPart) } } else { RightSide = 1 RightPart = getValue(LeftPart) } } } else { RightSide = 1 RightPart = getValue(LeftPart) } } else { if (isAssignment()) { shift() if (isVariableStart()) { RightSide = 2 setValue(RightPart = getVariable(), LeftPart) } else { RightPart = 0 } } } } prepareOperation() printOperation() performOperation() return 0 } unEscape() printLine() } function setValue(_Variable, _Value) { Variables[_Variable] = _Value } function shift(_Temporary) { _Temporary = $1 gsub(/^[[:blank:]]*[^[:blank:]]+[[:blank:]]*/, "", $0) return _Temporary } function unEscape() { gsub(/^\\/, "", $1) }