[Include] Octal Numbers
#1

Octal Numbers
Introduction

The PAWN language has base 10 (decimal) numbers (1, 9, 10, 55, 34593493, etc), base 16 (hexadecimal) numbers (0x1, 0x9, 0xA, 0xFF67BA03, etc), and base 2 (binary) numbers (0b1, 0b1001, 0b1010, 0b011011101101101000, etc). C has decimal and hex, but no binary; however, it does have base 8 (octal) numbers. Many people dislike them (especially because of their syntax) and think they’re useless, thus PAWN intentionally omitted them. This library adds them back in thanks to an unusual bug (feature?) of the compiler.

Octal

In C, any number written with a leading zero, and no x is octal: 01, 07, 015, 0777, 071235464, etc. In these numbers only the digits 01234567 are valid (just as in binary only the digits 0 and 1 are valid). Thus counting in base 8 goes:

0
1
2
3
4
5
6
7
10
11
12
13
14
15
16
17
20
.
.
.
75
76
77
100


There are several reasons why they are disliked in C:

Syntax

Any number with a leading zero is considered octal. You may try write some code with a list of numbers you wish to line up neatly, like so:

Code:
int zeroToNinetyNine[] = {
	00, 01, 02, 03, 04, 05, 06, 07, 08, 09,
	10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
	20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
	30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
	40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
	50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
	60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
	70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
	80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
	90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
}
This code is a compile-time error! The first eight numbers 00 - 07 are correctly compiled as 0 - 7, but then 08 is seen, interpreted as octal thanks to the leading 0, then rejected because 8 is not valid in octal (just as 2 is not valid in base 2). The situation gets even worse with bigger numbers. 07 is 7, but 077 is 63. Accidentally typing a hex number is hard because it needs an explicit 0x prefix, just as binary in pawn requires a 0b prefix.

Use

Many people claim that octal numbers are useless anyway because the only place they are really needed is Unix file permissions (0777 is very common there). I think this is wrong - they are great for bit shifts:

Code:
a = 255 << 010; // Left shift one byte.
b = 100 >> 001; // Right shift one bit.
c = 999 << 033; // Left shift three bytes, three bits.
Without octal that code would be:

Code:
a = 255 << 8; // Left shift one byte.
b = 100 >> 1; // Right shift one bit.
c = 999 << 27; // Left shift three bytes, three bits.
The numbers give very little clue as to what is being done, whereas 010, 020, 030, and 040 are very clear in terms of bytes.

PAWN Octal

So as I said, I found a way to add octal numbers to the language as a library, using a better prefix to avoid the problems with C. This prefix is 0o, to align with 0x and 0b:

Code:
a = 255 << 0o10; // Left shift one byte.
b = 100 >> 0o01; // Right shift one bit.
c = 999 << 0o33; // Left shift three bytes, three bits.
They can be used everywhere normal numbers can be used:

Code:
#include <octal>

SendClientMessage(playerid, 0o142, "Hello");
new x = 0o10;
However, because this is a library I needed to do each number manually, so I only went to 0o777 (511).

Download

https://gist.github.com/Y-Less/12cc5...9df10e8f047cae

There is no sampctl support yet unfortunately, and the library is only documented in this topic.

How?

So as I said, this uses a compiler bug/feature (not sure which), in which words within numbers are still replaced by the pre-compiler. For example:

Code:
#define HELLO 5

new a = 1HELLO;
Will compile as:

Code:
new a = 15;
The reason is that no symbol names can start with numbers, so the pre-processor ignores them initially when searching for text to replace. You can write some very evil code using this:

Code:
#define xFF x00
With that, anyone writing:

Code:
new a = b & 0xFF;
Will see the xFF part replaced and compiled as:

Code:
new a = b & 0x00;
Silently screwing up the code entirely! I decided not to be so evil and instead used the o prefix:

Code:
#define o10 x8

new a = 0o10;
Compiles as:

Code:
new a = 0x8;
Thus the transformation is complete.
Reply
#2

This is honestly an amazing add-on. I wish it had came earlier.

Good job!
Reply
#3

Amazing, isn't there a way to automate this rather than adding other values manually?
Reply
#4

Quote:
Originally Posted by Kar
View Post
This is honestly an amazing add-on. I wish it had came earlier.

Good job!
True!

-

Glad to see and can use this amazing work you did Alex!
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)