block Number { // char toDigit( int value ) { // if ( value < 0 || 36 <= value ) // error( "Invalid invocation of toDigit()" ); // else if ( value < 10 ) // return value + '0'; // else // return value + 'a' - 10; // } private block toDigit uses proc { abs { value = a0; } abs const { align; message: asciiz "Invalid invocation of toDigit()"; align; } const code { public enter: body: { if: cmplt $value, 36, $t0; blbs $t0, elif; then1: ldiq $value, message; bsr IO.error.enter; elif: cmplt $value, 10, $t0; blbc $t0, else; then2: addq $value, '0', $v0; br end; else: addq $value, 'a' - 10, $v0; end: } return: ret; } code } block toDigit // int fromDigit( char c, int base ) { // int value; // if ( '0' <= c && c <= '9' ) // value = c - '0'; // else if ( 'a' <= c && c <= 'z' ) // value = c - 'a' + 10; // else if ( 'A' <= c && c <= 'Z' ) // value = c - 'A' + 10; // else // value = -1; // if ( value >= base ) // return -1; // else // return value; // } private block fromDigit uses proc { abs { c = a0; base = a1; } abs code { public enter: body: { if: cmplt $c, '0', $t0; blbs $t0, elif1; cmple $c, '9', $t0; blbc $t0, elif1; then1: subq $c, '0', $v0; br end; elif1: cmplt $c, 'a', $t0; blbs $t0, elif2; cmple $c, 'z', $t0; blbc $t0, elif2; then2: subq $c, 'a' - 10, $v0; br end; elif2: cmplt $c, 'A', $t0; blbs $t0, else; cmple $c, 'Z', $t0; blbc $t0, else; then3: subq $c, 'A' - 10, $v0; br end; else: negq 1, $v0; end: } { if: cmplt $v0, $base, $t0; blbs $t0, end; then: negq 1, $v0; end: } return: ret; } code } block fromDigit // int fromString( char *buffer, int base ) { // int result = 0; // int sign = 1; // char digitChar; // int digit; // if ( *buffer == '-' ) { // sign = -1; // buffer++; // } // else if ( *buffer == '+' ) { // buffer++; // } // if ( base == 0 ) { // if ( *buffer >= '1' && *buffer <= '9' ) // base = 10; // else if ( *buffer == '0' ) { // buffer++; // if ( *buffer == 0 ) { // return 0; // else if ( *buffer == 'x' || *buffer == 'X' ) { // buffer++; // base = 16; // } // else // base = 8; // } // else // return 1<<63; // } // digitChar = *buffer; // digit = fromDigit( digitChar, base ); // while ( TRUE ) { // if ( digit < 0 ) // return 1<<63; // Error indication // result = result * base + digit; // buffer++; // digitChar = *buffer; // if ( digitChar == 0 ) // return sign * result; // digit = fromDigit( digitChar, base ); // } // } public block fromString uses proc { abs { buffer = s0; base = s1; result = s2; sign = s3; } abs code { public enter: lda $sp, -sav4($sp); stq $ra, savRet($sp); stq $s0, sav0($sp); stq $s1, sav1($sp); stq $s2, sav2($sp); stq $s3, sav3($sp); decl: mov $a0, $buffer; mov $a1, $base; body: clr $result; mov 1, $sign; { if: ldbu $t1, ($buffer); cmpeq $t1, '-', $t2; blbs $t2, then1; cmpeq $t1, '+', $t2; blbs $t2, then2; br end; then1: addq $buffer, 1; negq 1, $sign; br end; then2: addq $buffer, 1; end: } { if: bne $base, end; ldbu $t1, ($buffer); cmplt $t1, '1', $t2; blbs $t2, octHex; cmple $t1, '9', $t2; blbc $t2, octHex; decimal: mov 10, $base; br end; octHex: cmpeq $t1, '0', $t2; blbc $t2, error; addq $buffer, 1; ldbu $t1, ($buffer); beq $t1, zeroValue; cmpeq $t1, 'x', $t2; blbs $t2, hexadecimal; cmpeq $t1, 'X', $t2; blbs $t2, hexadecimal; octal: mov 8, $base; br end; hexadecimal: mov 16, $base; addq $buffer, 1; br end; zeroValue: clr $v0; br return; error: ldiq $v0, 1<<63; br return; end: } ldbu $a0, ($buffer); // Get character mov $base, $a1; bsr fromDigit.enter; { do: { if: bge $v0, end; then: ldiq $v0, 1<<63; br return; end: } mulq $result, $base; // result = result * base + fromdigit( *s ); addq $result, $v0; addq $buffer, 1; ldbu $a0, ($buffer); // Get character { if: bne $a0, end; then: mulq $result, $sign, $v0; br return; end: } mov $base, $a1; bsr fromDigit.enter; br do; end: } return: ldq $s3, sav3($sp); ldq $s2, sav2($sp); ldq $s1, sav1($sp); ldq $s0, sav0($sp); ldq $ra, savRet($sp); lda $sp, +sav4($sp); ret; } code } block fromString // #define MAXBUFFER 65 // char *toUnsigned( unsigned int value, int base ) { // static char buffer[ MAXBUFFER + 1 ]; // char *ptr = buffer + MAXBUFFER; // if ( value == 0 ) // return "0"; // else { // *ptr = 0; // while ( value > 0 ) { // --ptr; // *ptr = toDigit( value % base ); // value = value / base; // } // } // } public block toUnsigned uses proc { abs { MAXBUFFER = 65; value = s0; base = s1; fieldWidth = s2; ptr = s3; } abs data { align; buffer: ubyte[ MAXBUFFER + 1 ]; align; } data code { public enter: lda $sp, -sav4($sp); stq $ra, savRet($sp); stq $s0, sav0($sp); stq $s1, sav1($sp); stq $s2, sav2($sp); stq $s3, sav3($sp); decl: mov $a0, $value; mov $a1, $base; body: ldiq $t0, buffer; addq $t0, MAXBUFFER, $ptr; // ptr = buffer + MAXBUFFER; stb $zero, ($ptr); { if: bne $value, else; then: subq $ptr, 1; ldiq $t0, '0'; stb $t0, ($ptr); br end; else: { while: beq $value, end; do: subq $ptr, 1; modqu $value, $base, $a0; bsr toDigit.enter; stb $v0, ($ptr); divqu $value, $base; br while; end: } end: } mov $ptr, $v0; return: ldq $s3, sav3($sp); ldq $s2, sav2($sp); ldq $s1, sav1($sp); ldq $s0, sav0($sp); ldq $ra, savRet($sp); lda $sp, +sav4($sp); ret; } code } block toUnsigned // char *toSigned( int value, int base ) { // char *result; // if ( value < 0 ) { // result = toUnsigned( - value, base ); // *--result = '-'; // } // else // result = toUnsigned( value, base ); // return result; // } public block toSigned uses proc { abs { value = s0; base = s1; result = s2; } abs code { public enter: lda $sp, -sav3($sp); stq $ra, savRet($sp); stq $s0, sav0($sp); stq $s1, sav1($sp); stq $s2, sav2($sp); decl: mov $a0, $value; mov $a1, $base; body: { if: bge $value, else; then: negq $value, $a0; mov $base, $a1; bsr toUnsigned.enter; subq $v0, 1, $result; ldiq $t0, '-'; stb $t0, ($result); br end; else: mov $value, $a0; mov $base, $a1; bsr toUnsigned.enter; mov $v0, $result; end: } mov $result, $v0; return: ldq $s2, sav2($sp); ldq $s1, sav1($sp); ldq $s0, sav0($sp); ldq $ra, savRet($sp); lda $sp, +sav3($sp); ret; } code } block toSigned } block Number