translate: some casting improvements
[ia32rtools.git] / tools / translate.c
index e3d8f5b..67211e9 100644 (file)
@@ -128,9 +128,10 @@ struct parsed_opr {
   unsigned int size_mismatch:1; // type override differs from C
   unsigned int size_lt:1;  // type override is larger than C
   unsigned int had_ds:1;   // had ds: prefix
+  const struct parsed_proto *pp; // for OPT_LABEL
   int reg;
   unsigned int val;
-  char name[256];
+  char name[112];
 };
 
 struct parsed_op {
@@ -148,7 +149,7 @@ struct parsed_op {
   int cc_scratch;         // scratch storage during analysis
   int bt_i;               // branch target for branches
   struct parsed_data *btj;// branch targets for jumptables
-  struct parsed_proto *pp;
+  struct parsed_proto *pp;// parsed_proto for OP_CALL
   void *datap;
 };
 
@@ -507,6 +508,24 @@ static int guess_lmod_from_c_type(enum opr_lenmod *lmod,
   return 0;
 }
 
+static char *default_cast_to(char *buf, size_t buf_size,
+  struct parsed_opr *opr)
+{
+  buf[0] = 0;
+
+  if (!opr->is_ptr)
+    return buf;
+  if (opr->pp == NULL || opr->pp->type.name == NULL
+    || opr->pp->is_fptr)
+  {
+    snprintf(buf, buf_size, "%s", "(void *)");
+    return buf;
+  }
+
+  snprintf(buf, buf_size, "(%s)", opr->pp->type.name);
+  return buf;
+}
+
 static enum opr_type lmod_from_directive(const char *d)
 {
   if (IS(d, "dd"))
@@ -699,6 +718,7 @@ do_label:
     }
     opr->is_array = pp->type.is_array;
   }
+  opr->pp = pp;
 
   if (opr->lmod == OPLM_UNSPEC)
     guess_lmod_from_name(opr);
@@ -3807,9 +3827,10 @@ tailcall:
         assert_operand_cnt(2);
         propagate_lmod(po, &po->operand[0], &po->operand[1]);
         out_dst_opr(buf1, sizeof(buf1), po, &po->operand[0]);
+        default_cast_to(buf3, sizeof(buf3), &po->operand[0]);
         fprintf(fout, "  %s = %s;", buf1,
             out_src_opr(buf2, sizeof(buf2), po, &po->operand[1],
-              po->operand[0].is_ptr ? "(void *)" : "", 0));
+              buf3, 0));
         break;
 
       case OP_LEA:
@@ -3853,9 +3874,11 @@ tailcall:
           out_src_opr(buf1, sizeof(buf1), po, &po->operand[0], "", 0));
         fprintf(fout, " %s = %s;",
           out_dst_opr(buf1, sizeof(buf1), po, &po->operand[0]),
-          out_src_opr(buf2, sizeof(buf2), po, &po->operand[1], "", 0));
-        fprintf(fout, " %s = tmp;",
-          out_dst_opr(buf1, sizeof(buf1), po, &po->operand[1]));
+          out_src_opr(buf2, sizeof(buf2), po, &po->operand[1],
+            default_cast_to(buf3, sizeof(buf3), &po->operand[0]), 0));
+        fprintf(fout, " %s = %stmp;",
+          out_dst_opr(buf1, sizeof(buf1), po, &po->operand[1]),
+          default_cast_to(buf3, sizeof(buf3), &po->operand[1]));
         snprintf(g_comment, sizeof(g_comment), "xchg");
         break;
 
@@ -4544,7 +4567,7 @@ tailcall:
           fprintf(fout, "  %s = %s;", buf1,
             out_src_opr(buf2, sizeof(buf2),
               tmp_op, &tmp_op->operand[0],
-              po->operand[0].is_ptr ? "(void *)" : "", 0));
+              default_cast_to(buf3, sizeof(buf3), &po->operand[0]), 0));
           break;
         }
         else if (g_func_pp->is_userstack) {
@@ -4745,6 +4768,9 @@ static void scan_ahead(FILE *fasm)
 
         add_func_chunk(fasm, words[0], asmln);
       }
+      else if (IS_START(p, "; sctend"))
+        break;
+
       continue;
     } // *p == ';'
 
@@ -4790,6 +4816,7 @@ int main(int argc, char *argv[])
   int eq_alloc;
   int verbose = 0;
   int multi_seg = 0;
+  int end = 0;
   int arg_out;
   int arg;
   int pi = 0;
@@ -5020,6 +5047,11 @@ parse_words:
       if (IS_START(p, "; sctproto:")) {
         sctproto = strdup(p + 11);
       }
+      else if (IS_START(p, "; sctend")) {
+        end = 1;
+        if (!pending_endp)
+          break;
+      }
     }
 
     if (wordc == 0) {
@@ -5040,7 +5072,7 @@ parse_words:
 do_pending_endp:
     // do delayed endp processing to collect switch jumptables
     if (pending_endp) {
-      if (in_func && !skip_func && wordc >= 2
+      if (in_func && !skip_func && !end && wordc >= 2
           && ((words[0][0] == 'd' && words[0][2] == 0)
               || (words[1][0] == 'd' && words[1][2] == 0)))
       {
@@ -5123,6 +5155,9 @@ do_pending_endp:
       }
       g_func_pd_cnt = 0;
       pd = NULL;
+
+      if (end)
+        break;
       if (wordc == 0)
         continue;
     }
@@ -5187,8 +5222,12 @@ do_pending_endp:
     }
 
     if (wordc == 2 && IS(words[1], "ends")) {
-      if (!multi_seg)
+      if (!multi_seg) {
+        end = 1;
+        if (pending_endp)
+          goto do_pending_endp;
         break;
+      }
 
       // scan for next text segment
       while (fgets(line, sizeof(line), fasm)) {