2 * Copyright (C) 2012, 2013
6 * Permission is hereby granted, free of charge, to any person obtaining a copy of
7 * this software and associated documentation files (the "Software"), to deal in
8 * the Software without restriction, including without limitation the rights to
9 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10 * of the Software, and to permit persons to whom the Software is furnished to do
11 * so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * Initially this was handled with a table in the gmqcc.h header, but
32 * much to my surprise the contents of the table was duplicated for
33 * each translation unit, causing all these strings to be duplicated
34 * for every .c file it was included into. This method culls back on
35 * it. This is a 'utility' function because the executor also depends
36 * on this for disassembled byte-code.
38 const char *util_instr_str[VINSTR_END] = {
39 "DONE", "MUL_F", "MUL_V", "MUL_FV",
40 "MUL_VF", "DIV_F", "ADD_F", "ADD_V",
41 "SUB_F", "SUB_V", "EQ_F", "EQ_V",
42 "EQ_S", "EQ_E", "EQ_FNC", "NE_F",
43 "NE_V", "NE_S", "NE_E", "NE_FNC",
44 "LE", "GE", "LT", "GT",
45 "LOAD_F", "LOAD_V", "LOAD_S", "LOAD_ENT",
46 "LOAD_FLD", "LOAD_FNC", "ADDRESS", "STORE_F",
47 "STORE_V", "STORE_S", "STORE_ENT", "STORE_FLD",
48 "STORE_FNC", "STOREP_F", "STOREP_V", "STOREP_S",
49 "STOREP_ENT", "STOREP_FLD", "STOREP_FNC", "RETURN",
50 "NOT_F", "NOT_V", "NOT_S", "NOT_ENT",
51 "NOT_FNC", "IF", "IFNOT", "CALL0",
52 "CALL1", "CALL2", "CALL3", "CALL4",
53 "CALL5", "CALL6", "CALL7", "CALL8",
54 "STATE", "GOTO", "AND", "OR",
59 * only required if big endian .. otherwise no need to swap
62 #if PLATFORM_BYTE_ORDER == GMQCC_BYTE_ORDER_BIG
63 static GMQCC_INLINE void util_swap16(uint16_t *d, size_t l) {
65 d[l] = (d[l] << 8) | (d[l] >> 8);
69 static GMQCC_INLINE void util_swap32(uint32_t *d, size_t l) {
72 v = ((d[l] << 8) & 0xFF00FF00) | ((d[l] >> 8) & 0x00FF00FF);
73 d[l] = (v << 16) | (v >> 16);
77 /* Some strange system doesn't like constants that big, AND doesn't recognize an ULL suffix
78 * so let's go the safe way
80 static GMQCC_INLINE void util_swap64(uint32_t *d, size_t l) {
84 v = ((d[l] << 8) & 0xFF00FF00FF00FF00) | ((d[l] >> 8) & 0x00FF00FF00FF00FF);
85 v = ((v << 16) & 0xFFFF0000FFFF0000) | ((v >> 16) & 0x0000FFFF0000FFFF);
86 d[l] = (v << 32) | (v >> 32);
90 for (i = 0; i < l; i += 2) {
99 void util_endianswap(void *_data, size_t length, unsigned int typesize) {
100 # if PLATFORM_BYTE_ORDER == -1 /* runtime check */
101 if (*((char*)&typesize))
104 /* prevent unused warnings */
109 # if PLATFORM_BYTE_ORDER == GMQCC_BYTE_ORDER_LITTLE
115 util_swap16((uint16_t*)_data, length>>1);
118 util_swap32((uint32_t*)_data, length>>2);
121 util_swap64((uint32_t*)_data, length>>3);
124 default: exit(EXIT_FAILURE); /* please blow the fuck up! */
131 * CRC algorithms vary in the width of the polynomial, the value of said polynomial,
132 * the initial value used for the register, weather the bits of each byte are reflected
133 * before being processed, weather the algorithm itself feeds input bytes through the
134 * register or XORs them with a byte from one end and then straight into the table, as
135 * well as (but not limited to the idea of reflected versions) where the final register
136 * value becomes reversed, and finally weather the value itself is used to XOR the final
137 * register value. AS such you can already imagine how painfully annoying CRCs are,
138 * of course we stand to target Quake, which expects it's certain set of rules for proper
139 * calculation of a CRC.
141 * In most traditional CRC algorithms on uses a reflected table driven method where a value
142 * or register is reflected if it's bits are swapped around it's center. For example:
143 * take the bits 0101 is the 4-bit reflection of 1010, and respectfully 0011 would be the
144 * reflection of 1100. Quake however expects a NON-Reflected CRC on the output, but still
145 * requires a final XOR on the values (0xFFFF and 0x0000) this is a standard CCITT CRC-16
146 * which I respectfully as a programmer don't agree with.
148 * So now you know what we target, and why we target it, despite how unsettling it may seem
149 * but those are what Quake seems to request.
152 static const uint16_t util_crc16_table[] = {
153 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108,
154 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210,
155 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B,
156 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401,
157 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE,
158 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6,
159 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D,
160 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
161 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5,
162 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC,
163 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4,
164 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD,
165 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13,
166 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A,
167 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E,
168 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
169 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1,
170 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB,
171 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0,
172 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8,
173 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657,
174 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9,
175 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882,
176 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
177 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E,
178 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07,
179 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D,
180 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74,
181 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
184 /* Non - Reflected */
185 uint16_t util_crc16(uint16_t current, const char *k, size_t len) {
186 register uint16_t h = current;
187 for (; len; --len, ++k)
188 h = util_crc16_table[(h>>8)^((unsigned char)*k)]^(h<<8);
191 /* Reflective Variation (for reference) */
193 uint16_t util_crc16(const char *k, int len, const short clamp) {
194 register uint16_t h= (uint16_t)0xFFFFFFFF;
195 for (; len; --len, ++k)
196 h = util_crc16_table[(h^((unsigned char)*k))&0xFF]^(h>>8);
202 * modifier is the match to make and the transposition from it, while add is the upper-value that determines the
203 * transposition from uppercase to lower case.
205 static GMQCC_INLINE size_t util_strtransform(const char *in, char *out, size_t outsz, const char *mod, int add) {
207 for (; *in && sz < outsz; ++in, ++out, ++sz) {
208 *out = (*in == mod[0])
210 : (util_isalpha(*in) && ((add > 0) ? util_isupper(*in) : !util_isupper(*in)))
218 size_t util_strtocmd(const char *in, char *out, size_t outsz) {
219 return util_strtransform(in, out, outsz, "-_", 'A'-'a');
221 size_t util_strtononcmd(const char *in, char *out, size_t outsz) {
222 return util_strtransform(in, out, outsz, "_-", 'a'-'A');
224 size_t util_optimizationtostr(const char *in, char *out, size_t outsz) {
225 return util_strtransform(in, out, outsz, "_ ", 'a'-'A');
228 int util_asprintf(char **ret, const char *fmt, ...) {
232 read = platform_vasprintf(ret, fmt, args);
238 void util_seed(uint32_t value) {
241 uint32_t util_rand() {