]> granicus.if.org Git - yasm/commitdiff
* intnum.c (yasm_intnum_create_leb128): Create an intnum from a LEB128
authorPeter Johnson <peter@tortall.net>
Sun, 12 Feb 2006 23:12:10 +0000 (23:12 -0000)
committerPeter Johnson <peter@tortall.net>
Sun, 12 Feb 2006 23:12:10 +0000 (23:12 -0000)
encoded value.
* intnum.h (yasm_intnum_create_leb128): Prototype.
* leb128_test.c: Test above.

svn path=/trunk/yasm/; revision=1386

libyasm/intnum.c
libyasm/intnum.h
libyasm/tests/leb128_test.c

index 5e22dc47ff8a0f297439132a2080e43590ce1748..b4d82821b76c5009a788ad5ac642240a541c8abb 100644 (file)
@@ -258,6 +258,44 @@ yasm_intnum_create_int(long i)
     return intn;
 }
 
+yasm_intnum *
+yasm_intnum_create_leb128(const unsigned char *ptr, int sign,
+                         unsigned long *size, unsigned long line)
+{
+    yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+    const unsigned char *ptr_orig = ptr;
+    unsigned long i = 0;
+
+    intn->origsize = 0;
+
+    BitVector_Empty(conv_bv);
+    for (;;) {
+       BitVector_Chunk_Store(conv_bv, 7, i, *ptr);
+       i += 7;
+       if ((*ptr & 0x80) != 0x80)
+           break;
+       ptr++;
+    }
+
+    *size = (ptr-ptr_orig)+1;
+
+    if(i > BITVECT_NATIVE_SIZE)
+       yasm__warning(YASM_WARN_GENERAL, line,
+                     N_("Numeric constant too large for internal format"));
+    else if (sign && (*ptr & 0x40) == 0x40)
+       BitVector_Interval_Fill(conv_bv, i, BITVECT_NATIVE_SIZE-1);
+
+    if (Set_Max(conv_bv) < 32) {
+       intn->type = INTNUM_UL;
+       intn->val.ul = BitVector_Chunk_Read(conv_bv, 32, 0);
+    } else {
+       intn->type = INTNUM_BV;
+       intn->val.bv = BitVector_Clone(conv_bv);
+    }
+
+    return intn;
+}
+
 yasm_intnum *
 yasm_intnum_copy(const yasm_intnum *intn)
 {
index 9cb4f66cbfff4418d87e04c818724cc818ce8229..779534a86648822dba01558117da9c0b1d535b68 100644 (file)
@@ -90,6 +90,18 @@ void yasm_intnum_cleanup(void);
  */
 /*@only@*/ yasm_intnum *yasm_intnum_create_int(long i);
 
+/** Create a new intnum from LEB128-encoded form.
+ * \param ptr  pointer to start of LEB128 encoded form
+ * \param sign signed (1) or unsiged (0) LEB128 format
+ * \param size number of bytes read from ptr (output)
+ * \param line virtual line (where the number came from)
+ * \return Newly allocated intnum.  Number of bytes read returned into
+ *         bytes_read parameter.
+ */
+/*@only@*/ yasm_intnum *yasm_intnum_create_leb128
+    (const unsigned char *ptr, int sign, /*@out@*/ unsigned long *size,
+     unsigned long line);
+
 /** Duplicate an intnum.
  * \param intn intnum
  * \return Newly allocated intnum with the same value as intn.
index f8ab3465b7a714af25408476464891cea8aab371..100e4837762baa06829e967768610fca8a1fe63f 100644 (file)
@@ -80,7 +80,7 @@ static char failed[1000];
 static char failmsg[100];
 
 static int
-run_test(Test_Entry *test)
+run_output_test(Test_Entry *test)
 {
     char *valstr = yasm__xstrdup(test->input);
     yasm_intnum *intn = yasm_intnum_create_hex(valstr, 0);
@@ -129,6 +129,44 @@ run_test(Test_Entry *test)
     return 0;
 }
 
+static int
+run_input_test(Test_Entry *test)
+{
+    char *valstr = yasm__xstrdup(test->input);
+    yasm_intnum *intn = yasm_intnum_create_hex(valstr, 0);
+    yasm_intnum *testn;
+    unsigned long size, i;
+    unsigned char out[100];
+
+    yasm_xfree(valstr);
+
+    if (test->negate)
+       yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL, 0);
+
+    testn = yasm_intnum_create_leb128(test->result, test->sign, &size, 0);
+    if (size != test->outsize) {
+       yasm_intnum_destroy(testn);
+       yasm_intnum_destroy(intn);
+       sprintf(failmsg, "%ssigned %s%s create() bad size: expected %lu, got %lu!",
+               test->sign?"":"un", test->negate?"-":"", test->input,
+               test->outsize, size);
+       return 1;
+    }
+
+    yasm_intnum_calc(intn, YASM_EXPR_EQ, testn, 0);
+    if (!yasm_intnum_is_pos1(intn)) {
+       yasm_intnum_destroy(testn);
+       yasm_intnum_destroy(intn);
+       sprintf(failmsg, "%ssigned %s%s create() bad output!",
+               test->sign?"":"un", test->negate?"-":"", test->input);
+       return 1;
+    }
+
+    yasm_intnum_destroy(testn);
+    yasm_intnum_destroy(intn);
+    return 0;
+}
+
 int
 main(void)
 {
@@ -143,7 +181,16 @@ main(void)
     failed[0] = '\0';
     printf("Test leb128_test: ");
     for (i=0; i<numtests; i++) {
-       int fail = run_test(&tests[i]);
+       int fail;
+
+       fail = run_output_test(&tests[i]);
+       printf("%c", fail>0 ? 'F':'.');
+       fflush(stdout);
+       if (fail)
+           sprintf(failed, "%s ** F: %s\n", failed, failmsg);
+       nf += fail;
+
+       fail = run_input_test(&tests[i]);
        printf("%c", fail>0 ? 'F':'.');
        fflush(stdout);
        if (fail)
@@ -154,6 +201,7 @@ main(void)
     yasm_intnum_cleanup();
 
     printf(" +%d-%d/%d %d%%\n%s",
-          numtests-nf, nf, numtests, 100*(numtests-nf)/numtests, failed);
+          numtests*2-nf, nf, numtests*2, 100*(numtests*2-nf)/(numtests*2),
+          failed);
     return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
 }