is needed for the GAS .uleb128 and .sleb128 directives.
* intnum.c (yasm_intnum_sign): New signedness discovery function.
* intnum.h (yasm_intnum_sign): Prototype.
* intnum.c (yasm_intnum_get_leb128, yasm_intnum_size_leb128): New.
* intnum.h (yasm_intnum_get_leb128, yasm_intnum_size_leb128): Prototype.
* leb128_test.c: New test for intnum-level LEB128 functions.
* bytecode.c (bytecode_leb128): New bytecode and supporting functions.
(yasm_bc_create_leb128): New creation function.
* bytecode.h (yasm_bc_create_leb128): Prototype.
* gas-token.re: Recognize .uleb128 and .sleb128.
* gas-bison.y: Ditto.
(gas_define_leb128): New.
* leb128.asm: New test for GAS .uleb128 and .sleb128 directives.
svn path=/trunk/yasm/; revision=1287
unsigned char size;
} bytecode_data;
+typedef struct bytecode_leb128 {
+ /* source data (linked list) */
+ yasm_datavalhead datahead;
+
+ /* signedness (0=unsigned, 1=signed) */
+ int sign;
+
+ /* total length (calculated at finalize time) */
+ unsigned long len;
+} bytecode_leb128;
+
typedef struct bytecode_reserve {
/*@only@*/ yasm_expr *numitems; /* number of items to reserve */
unsigned char itemsize; /* size of each item (in bytes) */
yasm_output_expr_func output_expr,
/*@null@*/ yasm_output_reloc_func output_reloc);
+static void bc_leb128_destroy(void *contents);
+static void bc_leb128_print(const void *contents, FILE *f, int indent_level);
+static void bc_leb128_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static yasm_bc_resolve_flags bc_leb128_resolve
+ (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
+static int bc_leb128_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_expr_func output_expr,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
static void bc_reserve_destroy(void *contents);
static void bc_reserve_print(const void *contents, FILE *f, int indent_level);
static yasm_bc_resolve_flags bc_reserve_resolve
bc_data_tobytes
};
+static const yasm_bytecode_callback bc_leb128_callback = {
+ bc_leb128_destroy,
+ bc_leb128_print,
+ bc_leb128_finalize,
+ bc_leb128_resolve,
+ bc_leb128_tobytes
+};
+
static const yasm_bytecode_callback bc_reserve_callback = {
bc_reserve_destroy,
bc_reserve_print,
return yasm_bc_create_common(&bc_data_callback, data, line);
}
+static void
+bc_leb128_destroy(void *contents)
+{
+ bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)contents;
+ yasm_dvs_destroy(&bc_leb128->datahead);
+ yasm_xfree(contents);
+}
+
+static void
+bc_leb128_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_leb128 *bc_leb128 = (const bytecode_leb128 *)contents;
+ fprintf(f, "%*s_Data_\n", indent_level, "");
+ fprintf(f, "%*sSign=%u\n", indent_level+1, "",
+ (unsigned int)bc_leb128->sign);
+ fprintf(f, "%*sElements:\n", indent_level+1, "");
+ yasm_dvs_print(&bc_leb128->datahead, f, indent_level+2);
+}
+
+static void
+bc_leb128_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents;
+ yasm_dataval *dv;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
+
+ /* Only constant expressions are allowed.
+ * Because of this, go ahead and calculate length.
+ */
+ bc_leb128->len = 0;
+ STAILQ_FOREACH(dv, &bc_leb128->datahead, link) {
+ switch (dv->type) {
+ case DV_EMPTY:
+ break;
+ case DV_EXPR:
+ intn = yasm_expr_get_intnum(&dv->data.expn, NULL);
+ if (!intn) {
+ yasm__error(bc->line,
+ N_("LEB128 requires constant values"));
+ return;
+ }
+ /* Warn for negative values in unsigned environment.
+ * This could be an error instead: the likelihood this is
+ * desired is very low!
+ */
+ if (yasm_intnum_sign(intn) == -1 && !bc_leb128->sign)
+ yasm__warning(YASM_WARN_GENERAL, bc->line,
+ N_("negative value in unsigned LEB128"));
+ bc_leb128->len +=
+ yasm_intnum_size_leb128(intn, bc_leb128->sign);
+ break;
+ case DV_STRING:
+ yasm__error(bc->line,
+ N_("LEB128 does not allow string constants"));
+ return;
+ }
+ }
+}
+
+static yasm_bc_resolve_flags
+bc_leb128_resolve(yasm_bytecode *bc, int save,
+ yasm_calc_bc_dist_func calc_bc_dist)
+{
+ bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents;
+ bc->len += bc_leb128->len;
+ return YASM_BC_RESOLVE_MIN_LEN;
+}
+
+static int
+bc_leb128_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
+ yasm_output_expr_func output_expr,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents;
+ yasm_dataval *dv;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
+
+ STAILQ_FOREACH(dv, &bc_leb128->datahead, link) {
+ switch (dv->type) {
+ case DV_EMPTY:
+ break;
+ case DV_EXPR:
+ intn = yasm_expr_get_intnum(&dv->data.expn, NULL);
+ if (!intn)
+ yasm_internal_error(N_("non-constant in leb128_tobytes"));
+ *bufp += yasm_intnum_get_leb128(intn, *bufp, bc_leb128->sign);
+ break;
+ case DV_STRING:
+ yasm_internal_error(N_("string in leb128_tobytes"));
+ }
+ }
+
+ return 0;
+}
+
+yasm_bytecode *
+yasm_bc_create_leb128(yasm_datavalhead *datahead, int sign, unsigned long line)
+{
+ bytecode_leb128 *leb128 = yasm_xmalloc(sizeof(bytecode_leb128));
+
+ leb128->datahead = *datahead;
+ leb128->sign = sign;
+
+ return yasm_bc_create_common(&bc_leb128_callback, leb128, line);
+}
+
static void
bc_reserve_destroy(void *contents)
{
/*@only@*/ yasm_bytecode *yasm_bc_create_data
(yasm_datavalhead *datahead, unsigned int size, unsigned long line);
+/** Create a bytecode containing LEB128-encoded data value(s).
+ * \param datahead list of data values (kept, do not free)
+ * \param sign signedness (1=signed, 0=unsigned) of each data value
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ */
+/*@only@*/ yasm_bytecode *yasm_bc_create_leb128
+ (yasm_datavalhead *datahead, int sign, unsigned long line);
+
/** Create a bytecode reserving space.
* \param numitems number of reserve "items" (kept, do not free)
* \param itemsize reserved size (in bytes) for each item
return (intn->type == INTNUM_BV && BitVector_is_full(intn->val.bv));
}
+int
+yasm_intnum_sign(yasm_intnum *intn)
+{
+ if (intn->type == INTNUM_UL) {
+ if (intn->val.ul == 0)
+ return 0;
+ else
+ return 1;
+ } else
+ return BitVector_Sign(intn->val.bv);
+}
+
unsigned long
yasm_intnum_get_uint(const yasm_intnum *intn)
{
return (Set_Max(val) < (long)size);
}
+unsigned long
+yasm_intnum_get_leb128(const yasm_intnum *intn, unsigned char *ptr, int sign)
+{
+ wordptr val = op1static;
+ unsigned long i, size;
+ unsigned char *ptr_orig = ptr;
+
+ /* Shortcut 0 */
+ if (intn->type == INTNUM_UL && intn->val.ul == 0) {
+ *ptr = 0;
+ return 1;
+ }
+
+ /* If not already a bitvect, convert value to be written to a bitvect */
+ if (intn->type == INTNUM_BV)
+ val = intn->val.bv;
+ else {
+ BitVector_Empty(val);
+ BitVector_Chunk_Store(val, 32, 0, intn->val.ul);
+ }
+
+ if (sign) {
+ /* Signed mode */
+ if (BitVector_msb_(val)) {
+ /* Negative */
+ BitVector_Negate(conv_bv, val);
+ size = Set_Max(conv_bv)+2;
+ } else {
+ /* Positive */
+ size = Set_Max(val)+2;
+ }
+ } else {
+ /* Unsigned mode */
+ size = Set_Max(val)+1;
+ }
+
+ /* Positive/Unsigned write */
+ for (i=0; i<size; i += 7) {
+ *ptr = (unsigned char)BitVector_Chunk_Read(val, 7, i);
+ *ptr |= 0x80;
+ ptr++;
+ }
+ *(ptr-1) &= 0x7F; /* Clear MSB of last byte */
+ return (unsigned long)(ptr-ptr_orig);
+}
+
+unsigned long
+yasm_intnum_size_leb128(const yasm_intnum *intn, int sign)
+{
+ wordptr val = op1static;
+
+ /* Shortcut 0 */
+ if (intn->type == INTNUM_UL && intn->val.ul == 0) {
+ return 1;
+ }
+
+ /* If not already a bitvect, convert value to a bitvect */
+ if (intn->type == INTNUM_BV)
+ val = intn->val.bv;
+ else {
+ BitVector_Empty(val);
+ BitVector_Chunk_Store(val, 32, 0, intn->val.ul);
+ }
+
+ if (sign) {
+ /* Signed mode */
+ if (BitVector_msb_(val)) {
+ /* Negative */
+ BitVector_Negate(conv_bv, val);
+ return (Set_Max(conv_bv)+8)/7;
+ } else {
+ /* Positive */
+ return (Set_Max(val)+8)/7;
+ }
+ } else {
+ /* Unsigned mode */
+ return (Set_Max(val)+7)/7;
+ }
+}
+
void
yasm_intnum_print(const yasm_intnum *intn, FILE *f)
{
*/
int yasm_intnum_is_neg1(yasm_intnum *acc);
+/** Simple sign check.
+ * \param acc intnum
+ * \return -1 if negative, 0 if zero, +1 if positive
+ */
+int yasm_intnum_sign(yasm_intnum *acc);
+
/** Convert an intnum to an unsigned 32-bit value. The value is in "standard"
* C format (eg, of unknown endian).
* \note Parameter intnum is truncated to fit into 32 bits. Use
int yasm_intnum_check_size(const yasm_intnum *intn, size_t size,
size_t rshift, int rangetype);
+/** Output #yasm_intnum to buffer in LEB128-encoded form.
+ * \param intn intnum
+ * \param ptr pointer to storage for output bytes
+ * \param sign signedness of LEB128 encoding (0=unsigned, 1=signed)
+ * \return Number of bytes generated.
+ */
+unsigned long yasm_intnum_get_leb128(const yasm_intnum *intn,
+ unsigned char *ptr, int sign);
+
+/** Calculate number of bytes LEB128-encoded form of #yasm_intnum will take.
+ * \param intn intnum
+ * \param sign signedness of LEB128 encoding (0=unsigned, 1=signed)
+ * \return Number of bytes.
+ */
+unsigned long yasm_intnum_size_leb128(const yasm_intnum *intn, int sign);
+
/** Print an intnum. For debugging purposes.
* \param f file
* \param intn intnum
TESTS += bitvect_test
TESTS += floatnum_test
+TESTS += leb128_test
TESTS += libyasm/tests/libyasm_test.sh
EXTRA_DIST += libyasm/tests/libyasm_test.sh
check_PROGRAMS += bitvect_test
check_PROGRAMS += floatnum_test
+check_PROGRAMS += leb128_test
bitvect_test_SOURCES = libyasm/tests/bitvect_test.c
bitvect_test_LDADD = libyasm.a $(INTLLIBS)
floatnum_test_SOURCES = libyasm/tests/floatnum_test.c
floatnum_test_LDADD = libyasm.a $(INTLLIBS)
+leb128_test_SOURCES = libyasm/tests/leb128_test.c
+leb128_test_LDADD = libyasm.a $(INTLLIBS)
+
--- /dev/null
+/* $Id$
+ *
+ * Copyright (C) 2005 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+#include <stdio.h>
+
+#include "libyasm/intnum.c"
+
+typedef struct Test_Entry {
+ /* signedness (0=unsigned, 1=signed) */
+ int sign;
+
+ /* whether input value should be negated */
+ int negate;
+
+ /* input value (as hex string) */
+ const char *input;
+
+ /* correct size returned from both size_leb128 and get_leb128 */
+ unsigned long outsize;
+
+ /* correct return data from get_leb128 */
+ const unsigned char *result;
+} Test_Entry;
+
+static Test_Entry tests[] = {
+ /* Unsigned values */
+ {0, 0, "0", 1, (const unsigned char *)"\x00"},
+ {0, 0, "2", 1, (const unsigned char *)"\x02"},
+ {0, 0, "7F", 1, (const unsigned char *)"\x7F"},
+ {0, 0, "80", 2, (const unsigned char *)"\x80\x01"},
+ {0, 0, "81", 2, (const unsigned char *)"\x81\x01"},
+ {0, 0, "82", 2, (const unsigned char *)"\x82\x01"},
+ {0, 0, "3239", 2, (const unsigned char *)"\xB9\x64"},
+ /* Signed zero value */
+ {1, 0, "0", 1, (const unsigned char *)"\x00"},
+ /* Signed positive values */
+ {1, 0, "2", 1, (const unsigned char *)"\x02"},
+ {1, 0, "7F", 2, (const unsigned char *)"\xFF\x00"},
+ {1, 0, "80", 2, (const unsigned char *)"\x80\x01"},
+ {1, 0, "81", 2, (const unsigned char *)"\x81\x01"},
+ /* Signed negative values */
+ {1, 1, "2", 1, (const unsigned char *)"\x7E"},
+ {1, 1, "7F", 2, (const unsigned char *)"\x81\x7F"},
+ {1, 1, "80", 2, (const unsigned char *)"\x80\x7F"},
+ {1, 1, "81", 2, (const unsigned char *)"\xFF\x7E"},
+};
+
+static char failed[1000];
+static char failmsg[100];
+
+static int
+run_test(Test_Entry *test)
+{
+ char *valstr = yasm__xstrdup(test->input);
+ yasm_intnum *intn = yasm_intnum_create_hex(valstr, 0);
+ unsigned long size, i;
+ unsigned char out[100];
+ int bad;
+
+ yasm_xfree(valstr);
+
+ if (test->negate)
+ yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL, 0);
+
+ size = yasm_intnum_size_leb128(intn, test->sign);
+ if (size != test->outsize) {
+ yasm_intnum_destroy(intn);
+ sprintf(failmsg, "%ssigned %s%s size() bad size: expected %lu, got %lu!",
+ test->sign?"":"un", test->negate?"-":"", test->input,
+ test->outsize, size);
+ return 1;
+ }
+
+ for (i=0; i<sizeof(out); i++)
+ out[i] = 0xFF;
+ size = yasm_intnum_get_leb128(intn, out, test->sign);
+ if (size != test->outsize) {
+ yasm_intnum_destroy(intn);
+ sprintf(failmsg, "%ssigned %s%s get() bad size: expected %lu, got %lu!",
+ test->sign?"":"un", test->negate?"-":"", test->input,
+ test->outsize, size);
+ return 1;
+ }
+
+ bad = 0;
+ for (i=0; i<test->outsize && !bad; i++) {
+ if (out[i] != test->result[i])
+ bad = 1;
+ }
+ if (bad) {
+ yasm_intnum_destroy(intn);
+ sprintf(failmsg, "%ssigned %s%s get() bad output!",
+ test->sign?"":"un", test->negate?"-":"", test->input);
+ return 1;
+ }
+
+ yasm_intnum_destroy(intn);
+ return 0;
+}
+
+int
+main(void)
+{
+ int nf = 0;
+ int numtests = sizeof(tests)/sizeof(Test_Entry);
+ int i;
+
+ if (BitVector_Boot() != ErrCode_Ok)
+ return EXIT_FAILURE;
+ yasm_intnum_initialize();
+
+ failed[0] = '\0';
+ printf("Test leb128_test: ");
+ for (i=0; i<numtests; i++) {
+ int fail = run_test(&tests[i]);
+ printf("%c", fail>0 ? 'F':'.');
+ fflush(stdout);
+ if (fail)
+ sprintf(failed, "%s ** F: %s\n", failed, failmsg);
+ nf += fail;
+ }
+
+ yasm_intnum_cleanup();
+
+ printf(" +%d-%d/%d %d%%\n%s",
+ numtests-nf, nf, numtests, 100*(numtests-nf)/numtests, failed);
+ return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
static yasm_bytecode *gas_define_data(yasm_parser_gas *parser_gas,
yasm_valparamhead *vps,
unsigned int size);
+static yasm_bytecode *gas_define_leb128(yasm_parser_gas *parser_gas,
+ yasm_valparamhead *vps,
+ int sign);
static void gas_parser_directive
(yasm_parser_gas *parser_gas, const char *name,
yasm_valparamhead *valparams,
%token DIR_BSS DIR_BYTE DIR_COMM DIR_DATA DIR_DOUBLE DIR_ENDR DIR_EXTERN
%token DIR_EQU DIR_FILE DIR_FLOAT DIR_GLOBAL DIR_IDENT DIR_INT DIR_LOC
%token DIR_LCOMM DIR_OCTA DIR_ORG DIR_P2ALIGN DIR_REPT DIR_SECTION
-%token DIR_SHORT DIR_SIZE DIR_SKIP DIR_STRING
-%token DIR_TEXT DIR_TFLOAT DIR_TYPE DIR_QUAD DIR_WEAK DIR_WORD DIR_ZERO
+%token DIR_SHORT DIR_SIZE DIR_SKIP DIR_SLEB128 DIR_STRING
+%token DIR_TEXT DIR_TFLOAT DIR_TYPE DIR_QUAD DIR_ULEB128 DIR_WEAK DIR_WORD
+%token DIR_ZERO
%type <bc> line lineexp instr
yasm_bc_set_multiple($$, $2);
}
+ | DIR_SLEB128 datavals {
+ $$ = gas_define_leb128(parser_gas, &$2, 1);
+ yasm_vps_delete(&$2);
+ }
+ | DIR_ULEB128 datavals {
+ $$ = gas_define_leb128(parser_gas, &$2, 0);
+ yasm_vps_delete(&$2);
+ }
/* Floating point data definition directives */
| DIR_FLOAT datavals {
$$ = gas_define_data(parser_gas, &$2, 4);
return NULL;
}
+static yasm_bytecode *
+gas_define_leb128(yasm_parser_gas *parser_gas, yasm_valparamhead *vps,
+ int sign)
+{
+ if (yasm_vps_first(vps)) {
+ yasm_datavalhead dvs;
+ yasm_valparam *cur;
+
+ yasm_dvs_initialize(&dvs);
+ yasm_vps_foreach(cur, vps) {
+ if (!cur->param)
+ yasm__error(cur_line, N_("missing data value"));
+ else
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(cur->param));
+ cur->param = NULL;
+ }
+ return yasm_bc_create_leb128(&dvs, sign, cur_line);
+ } else
+ return NULL;
+}
+
static void
gas_parser_directive(yasm_parser_gas *parser_gas, const char *name,
yasm_valparamhead *valparams,
'.single' { RETURN(DIR_FLOAT); }
'.size' { RETURN(DIR_SIZE); }
'.skip' { RETURN(DIR_SKIP); }
+ '.sleb128' { RETURN(DIR_SLEB128); }
'.space' { RETURN(DIR_SKIP); }
'.string' { RETURN(DIR_ASCIZ); }
'.text' { RETURN(DIR_TEXT); }
'.tfloat' { RETURN(DIR_TFLOAT); }
'.type' { RETURN(DIR_TYPE); }
'.quad' { RETURN(DIR_QUAD); }
+ '.uleb128' { RETURN(DIR_ULEB128); }
'.weak' { RETURN(DIR_WEAK); }
'.word' { RETURN(DIR_WORD); }
'.zero' { RETURN(DIR_ZERO); }
EXTRA_DIST += modules/parsers/gas/tests/jmpcall.asm
EXTRA_DIST += modules/parsers/gas/tests/jmpcall.errwarn
EXTRA_DIST += modules/parsers/gas/tests/jmpcall.hex
+EXTRA_DIST += modules/parsers/gas/tests/leb128.asm
+EXTRA_DIST += modules/parsers/gas/tests/leb128.errwarn
+EXTRA_DIST += modules/parsers/gas/tests/leb128.hex
EXTRA_DIST += modules/parsers/gas/tests/reggroup-err.asm
EXTRA_DIST += modules/parsers/gas/tests/reggroup-err.errwarn
EXTRA_DIST += modules/parsers/gas/tests/reggroup.asm
--- /dev/null
+.data
+.uleb128 0
+.uleb128 2
+.uleb128 127
+.uleb128 128
+.uleb128 129
+.uleb128 130
+.uleb128 12857
+
+.sleb128 0
+.sleb128 2
+.sleb128 -2
+.sleb128 127
+.sleb128 -127
+.sleb128 128
+.sleb128 -128
+.sleb128 129
+.sleb128 -129
--- /dev/null
+7f
+45
+4c
+46
+01
+01
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+01
+00
+03
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+d0
+00
+00
+00
+00
+00
+00
+00
+34
+00
+00
+00
+00
+00
+28
+00
+06
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+02
+7f
+80
+01
+81
+01
+82
+01
+b9
+64
+00
+02
+7e
+ff
+00
+81
+7f
+80
+01
+80
+7f
+81
+01
+ff
+7e
+00
+00
+00
+2e
+74
+65
+78
+74
+00
+2e
+64
+61
+74
+61
+00
+2e
+73
+74
+72
+74
+61
+62
+00
+2e
+73
+79
+6d
+74
+61
+62
+00
+2e
+73
+68
+73
+74
+72
+74
+61
+62
+00
+00
+00
+2d
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+f1
+ff
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+03
+00
+05
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+03
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+1d
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+5c
+00
+00
+00
+27
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+0d
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+84
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+15
+00
+00
+00
+02
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+88
+00
+00
+00
+40
+00
+00
+00
+02
+00
+00
+00
+04
+00
+00
+00
+04
+00
+00
+00
+10
+00
+00
+00
+01
+00
+00
+00
+01
+00
+00
+00
+06
+00
+00
+00
+00
+00
+00
+00
+40
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+00
+00
+00
+00
+00
+00
+00
+07
+00
+00
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+40
+00
+00
+00
+1a
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00