【问题标题】:Convert .c to .java [closed]将 .c 转换为 .java [关闭]
【发布时间】:2015-11-29 20:18:30
【问题描述】:

有任何工具可以将 C 代码转换为 Java 代码吗?我有兴趣将此代码转换为 Java:

***************************************************************************/
/*
** UNECM - Decoder for ECM (Error Code Modeler) format.
** Version 1.0
** Copyright (C) 2002 Neill Corlett
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
/***************************************************************************/
/*
** Portability notes:
**
** - Assumes a 32-bit or higher integer size
** - No assumptions about byte order
** - No assumptions about struct packing
** - No unaligned memory access
*/
/***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/***************************************************************************/

void banner(void) {
  fprintf(stderr,
    "UNECM - Decoder for Error Code Modeler format v1.0\n"
    "Copyright (C) 2002 Neill Corlett\n\n"
  );
}

/***************************************************************************/

/* Data types */
#define ecc_uint8 unsigned char
#define ecc_uint16 unsigned short
#define ecc_uint32 unsigned

/* LUTs used for computing ECC/EDC */
static ecc_uint8 ecc_f_lut[256];
static ecc_uint8 ecc_b_lut[256];
static ecc_uint32 edc_lut[256];

/* Init routine */
static void eccedc_init(void) {
  ecc_uint32 i, j, edc;
  for(i = 0; i < 256; i++) {
    j = (i << 1) ^ (i & 0x80 ? 0x11D : 0);
    ecc_f_lut[i] = j;
    ecc_b_lut[i ^ j] = i;
    edc = i;
    for(j = 0; j < 8; j++) edc = (edc >> 1) ^ (edc & 1 ? 0xD8018001 : 0);
    edc_lut[i] = edc;
  }
}

/***************************************************************************/
/*
** Compute EDC for a block
*/
ecc_uint32 edc_partial_computeblock(
        ecc_uint32  edc,
  const ecc_uint8  *src,
        ecc_uint16  size
) {
  while(size--) edc = (edc >> 8) ^ edc_lut[(edc ^ (*src++)) & 0xFF];
  return edc;
}

void edc_computeblock(
  const ecc_uint8  *src,
        ecc_uint16  size,
        ecc_uint8  *dest
) {
  ecc_uint32 edc = edc_partial_computeblock(0, src, size);
  dest[0] = (edc >>  0) & 0xFF;
  dest[1] = (edc >>  8) & 0xFF;
  dest[2] = (edc >> 16) & 0xFF;
  dest[3] = (edc >> 24) & 0xFF;
}

/***************************************************************************/
/*
** Compute ECC for a block (can do either P or Q)
*/
static void ecc_computeblock(
  ecc_uint8 *src,
  ecc_uint32 major_count,
  ecc_uint32 minor_count,
  ecc_uint32 major_mult,
  ecc_uint32 minor_inc,
  ecc_uint8 *dest
) {
  ecc_uint32 size = major_count * minor_count;
  ecc_uint32 major, minor;
  for(major = 0; major < major_count; major++) {
    ecc_uint32 index = (major >> 1) * major_mult + (major & 1);
    ecc_uint8 ecc_a = 0;
    ecc_uint8 ecc_b = 0;
    for(minor = 0; minor < minor_count; minor++) {
      ecc_uint8 temp = src[index];
      index += minor_inc;
      if(index >= size) index -= size;
      ecc_a ^= temp;
      ecc_b ^= temp;
      ecc_a = ecc_f_lut[ecc_a];
    }
    ecc_a = ecc_b_lut[ecc_f_lut[ecc_a] ^ ecc_b];
    dest[major              ] = ecc_a;
    dest[major + major_count] = ecc_a ^ ecc_b;
  }
}

/*
** Generate ECC P and Q codes for a block
*/
static void ecc_generate(
  ecc_uint8 *sector,
  int        zeroaddress
) {
  ecc_uint8 address[4], i;
  /* Save the address and zero it out */
  if(zeroaddress) for(i = 0; i < 4; i++) {
    address[i] = sector[12 + i];
    sector[12 + i] = 0;
  }
  /* Compute ECC P code */
  ecc_computeblock(sector + 0xC, 86, 24,  2, 86, sector + 0x81C);
  /* Compute ECC Q code */
  ecc_computeblock(sector + 0xC, 52, 43, 86, 88, sector + 0x8C8);
  /* Restore the address */
  if(zeroaddress) for(i = 0; i < 4; i++) sector[12 + i] = address[i];
}

/***************************************************************************/
/*
** Generate ECC/EDC information for a sector (must be 2352 = 0x930 bytes)
** Returns 0 on success
*/
void eccedc_generate(ecc_uint8 *sector, int type) {
  ecc_uint32 i;
  switch(type) {
  case 1: /* Mode 1 */
    /* Compute EDC */
    edc_computeblock(sector + 0x00, 0x810, sector + 0x810);
    /* Write out zero bytes */
    for(i = 0; i < 8; i++) sector[0x814 + i] = 0;
    /* Generate ECC P/Q codes */
    ecc_generate(sector, 0);
    break;
  case 2: /* Mode 2 form 1 */
    /* Compute EDC */
    edc_computeblock(sector + 0x10, 0x808, sector + 0x818);
    /* Generate ECC P/Q codes */
    ecc_generate(sector, 1);
    break;
  case 3: /* Mode 2 form 2 */
    /* Compute EDC */
    edc_computeblock(sector + 0x10, 0x91C, sector + 0x92C);
    break;
  }
}

/***************************************************************************/

unsigned mycounter;
unsigned mycounter_total;

void resetcounter(unsigned total) {
  mycounter = 0;
  mycounter_total = total;
}

void setcounter(unsigned n) {
  if((n >> 20) != (mycounter >> 20)) {
    unsigned a = (n+64)/128;
    unsigned d = (mycounter_total+64)/128;
    if(!d) d = 1;
    fprintf(stderr, "Decoding (%02d%%)\r", (100*a) / d);
  }
  mycounter = n;
}

int unecmify(
  FILE *in,
  FILE *out
) {
  unsigned checkedc = 0;
  unsigned char sector[2352];
  unsigned type;
  unsigned num;
  fseek(in, 0, SEEK_END);
  resetcounter(ftell(in));
  fseek(in, 0, SEEK_SET);
  if(
    (fgetc(in) != 'E') ||
    (fgetc(in) != 'C') ||
    (fgetc(in) != 'M') ||
    (fgetc(in) != 0x00)
  ) {
    fprintf(stderr, "Header not found!\n");
    goto corrupt;
  }
  for(;;) {
    int c = fgetc(in);
    int bits = 5;
    if(c == EOF) goto uneof;
    type = c & 3;
    num = (c >> 2) & 0x1F;
    while(c & 0x80) {
      c = fgetc(in);
      if(c == EOF) goto uneof;
      num |= ((unsigned)(c & 0x7F)) << bits;
      bits += 7;
    }
    if(num == 0xFFFFFFFF) break;
    num++;
    if(num >= 0x80000000) goto corrupt;
    if(!type) {
      while(num) {
        int b = num;
        if(b > 2352) b = 2352;
        if(fread(sector, 1, b, in) != b) goto uneof;
        checkedc = edc_partial_computeblock(checkedc, sector, b);
        fwrite(sector, 1, b, out);
        num -= b;
        setcounter(ftell(in));
      }
    } else {
      while(num--) {
        memset(sector, 0, sizeof(sector));
        memset(sector + 1, 0xFF, 10);
        switch(type) {
        case 1:
          sector[0x0F] = 0x01;
          if(fread(sector + 0x00C, 1, 0x003, in) != 0x003) goto uneof;
          if(fread(sector + 0x010, 1, 0x800, in) != 0x800) goto uneof;
          eccedc_generate(sector, 1);
          checkedc = edc_partial_computeblock(checkedc, sector, 2352);
          fwrite(sector, 2352, 1, out);
          setcounter(ftell(in));
          break;
        case 2:
          sector[0x0F] = 0x02;
          if(fread(sector + 0x014, 1, 0x804, in) != 0x804) goto uneof;
          sector[0x10] = sector[0x14];
          sector[0x11] = sector[0x15];
          sector[0x12] = sector[0x16];
          sector[0x13] = sector[0x17];
          eccedc_generate(sector, 2);
          checkedc = edc_partial_computeblock(checkedc, sector + 0x10, 2336);
          fwrite(sector + 0x10, 2336, 1, out);
          setcounter(ftell(in));
          break;
        case 3:
          sector[0x0F] = 0x02;
          if(fread(sector + 0x014, 1, 0x918, in) != 0x918) goto uneof;
          sector[0x10] = sector[0x14];
          sector[0x11] = sector[0x15];
          sector[0x12] = sector[0x16];
          sector[0x13] = sector[0x17];
          eccedc_generate(sector, 3);
          checkedc = edc_partial_computeblock(checkedc, sector + 0x10, 2336);
          fwrite(sector + 0x10, 2336, 1, out);
          setcounter(ftell(in));
          break;
        }
      }
    }
  }
  if(fread(sector, 1, 4, in) != 4) goto uneof;
  fprintf(stderr, "Decoded %ld bytes -> %ld bytes\n", ftell(in), ftell(out));
  if(
    (sector[0] != ((checkedc >>  0) & 0xFF)) ||
    (sector[1] != ((checkedc >>  8) & 0xFF)) ||
    (sector[2] != ((checkedc >> 16) & 0xFF)) ||
    (sector[3] != ((checkedc >> 24) & 0xFF))
  ) {
    fprintf(stderr, "EDC error (%08X, should be %02X%02X%02X%02X)\n",
      checkedc,
      sector[3],
      sector[2],
      sector[1],
      sector[0]
    );
    goto corrupt;
  }
  fprintf(stderr, "Done; file is OK\n");
  return 0;
uneof:
  fprintf(stderr, "Unexpected EOF!\n");
corrupt:
  fprintf(stderr, "Corrupt ECM file!\n");
  return 1;
}

/***************************************************************************/

int main(int argc, char **argv) {
  FILE *fin, *fout;
  char *infilename;
  char *outfilename;
  banner();
  /*
  ** Initialize the ECC/EDC tables
  */
  eccedc_init();
  /*
  ** Check command line
  */
  if((argc != 2) && (argc != 3)) {
    fprintf(stderr, "usage: %s ecmfile [outputfile]\n", argv[0]);
    return 1;
  }
  /*
  ** Verify that the input filename is valid
  */
  infilename = argv[1];
  if(strlen(infilename) < 5) {
    fprintf(stderr, "filename '%s' is too short\n", infilename);
    return 1;
  }
  if(strcasecmp(infilename + strlen(infilename) - 4, ".ecm")) {
    fprintf(stderr, "filename must end in .ecm\n");
    return 1;
  }
  /*
  ** Figure out what the output filename should be
  */
  if(argc == 3) {
    outfilename = argv[2];
  } else {
    outfilename = malloc(strlen(infilename) - 3);
    if(!outfilename) abort();
    memcpy(outfilename, infilename, strlen(infilename) - 4);
    outfilename[strlen(infilename) - 4] = 0;
  }
  fprintf(stderr, "Decoding %s to %s.\n", infilename, outfilename);
  /*
  ** Open both files
  */
  fin = fopen(infilename, "rb");
  if(!fin) {
    perror(infilename);
    return 1;
  }
  fout = fopen(outfilename, "wb");
  if(!fout) {
    perror(outfilename);
    fclose(fin);
    return 1;
  }
  /*
  ** Decode
  */
  unecmify(fin, fout);
  /*
  ** Close everything
  */
  fclose(fout);
  fclose(fin);
  return 0;
}

【问题讨论】:

  • @Madara Uchiha:既然这个问题在这里跑题了,我们可以把它迁移到softwarerecs.stackexchange.com吗?
  • @AndersonGreen 超过 60 天的问题无法迁移(即使是版主)。此外,这个问题也几乎不是那里的话题。
  • 这个在线工具也很有帮助:mtsystems.com

标签: java c translation


【解决方案1】:

最好的办法是重写代码。

任何自动转换充其量只会产生质量差且无法维护的代码。

【讨论】:

  • 加上如果有一个工作的“转换器”,我们都失业了。一个聪明的家伙证明了这是不可能的。所有的转换器都很烂!
  • @lzap 谁证明这是不可能的? (此外,有一些编程语言可以转换为多种编程语言,包括 Haxe(其设计目的是尽可能多地编译成其他语言),因此“所有转换器很烂”。)
  • 他的名字是艾伦图灵老兄:-)
  • @Izap - 如果您指的是停机问题,这不是停机问题。老兄。停止定理说没有程序可以在有限的时间内告诉您任意其他程序+输入是否会终止。与程序翻译的可行性无关。
  • @lzap 给定程序的计算机完全有可能用另一种语言创建等效程序。这个概念被称为编译器。
【解决方案2】:

C 的世界观与 Java 的世界观不能很好地融合。如果您真的想编译为 Java 可执行的表单,请查看 NestedVM - http://nestedvm.ibex.org/ - 这是一个编译为 MIPS 方言的交叉编译器,然后可以通过解释或转换轻松地在 Java 中“运行”到反映原始 MIPS 指令的实际字节码。

我建议获取 Java 版本的代码。

【讨论】:

  • +1 表示非常奇怪、新颖的方法。
  • 这看起来很有趣。放假后我一定要试试!
  • 让交叉编译器运行是棘手的部分。
  • 在你交叉编译之后,也许可以尝试jd.benow.ca 来创建Java源...... ;-)
  • @user1050755 您的评论没有意义。 NestedVM 可以生成 Java 源代码
【解决方案3】:

曾经有名为 Ephedra、Convert2Java 和 C2J++ 的工具。但是它们并没有真正起作用,并且不再可用。剩下的 3 家公司提供的自动 C 到 Java 翻译在不可用、有用和良好的范围内:

  1. Novosoft,C2J:创建的 Java 代码需要大量的手工工作。 C2J 创建了一些不可读的代码(对指针的支持非常有限)并且不支持无符号类型/goto 语句/本机库/宏/cmets/...
  2. Tangible Software Solutions,C++2Java:创建的 Java 代码需要相当多的手动工作。 C++2Java 不支持指针/无符号类型/goto 语句/本机库/宏/...(Sachin Bhansali 在上面发布了 unecm C 代码的翻译)
  3. mtSystems,Coot:创建功能等效的代码(通过完全支持指针、函数指针、无符号类型、goto 语句、本机库……)和可读代码(保留宏/cmets,重命名标识符,应用各种优化, ...)。

这里是从 mtSystems 创建的类(未更改):

import static ch.mtsystems.coot.String8.cs8;
import static ch.mtsystems.coot.String8.nnc;

import ch.mtsystems.coot.String8;

import java.io.IOException;
import java.io.RandomAccessFile;

public class Unecm {
    public static void banner() {
        System.err.println("UNECM - Decoder for Error Code Modeler format v1.0\nCopyright (C) 2002 Neill Corlett\n");
    }

    /**
     * LUTs used for computing ECC/EDC
     */
    private static byte[] eccFLut_U = new byte[256];

    private static byte[] eccBLut_U = new byte[256];

    private static int[] edcLut_U = new int[256];

    /**
     * Init routine
     */
    private static void eccedcInit() {
        int j_U, edc_U;
        for(int i_U = 0; Integer.compareUnsigned(i_U, 256) < 0; i_U++) {
            j_U = i_U << 1 ^ ((i_U & 0x80) != 0 ? 0x11D : 0);
            eccFLut_U[i_U] = (byte)j_U;
            eccBLut_U[i_U ^ j_U] = (byte)i_U;
            edc_U = i_U;
            for(j_U = 0; Integer.compareUnsigned(j_U, 8) < 0; j_U++) {
                edc_U = edc_U >>> 1 ^ ((edc_U & 1) != 0 ? 0xD8018001 : 0);
            }
            edcLut_U[i_U] = edc_U;
        }
    }

    /**
     * Compute EDC for a block
     */
    public static int edcPartialComputeblock_U(int edc_U, String8 src_U, short size_U) {
        while(size_U-- != 0) {
            edc_U = edc_U >>> 8 ^ edcLut_U[(edc_U ^ Byte.toUnsignedInt((src_U = nnc(src_U).shift(1)).get(-1))) & 0xFF];
        }
        return edc_U;
    }

    public static void edcComputeblock(String8 src_U, short size_U, String8 dest_U) {
        int edc_U = edcPartialComputeblock_U(0, src_U, size_U);
        dest_U.set(0, (byte)(edc_U >>> 0 & 0xFF));
        dest_U.set(1, (byte)(edc_U >>> 8 & 0xFF));
        dest_U.set(2, (byte)(edc_U >>> 16 & 0xFF));
        dest_U.set(3, (byte)(edc_U >>> 24 & 0xFF));
    }

    /**
     * Compute ECC for a block (can do either P or Q)
     */
    private static void eccComputeblock(String8 src_U, int majorCount_U, int minorCount_U, int majorMult_U, int minorInc_U, String8 dest_U) {
        int size_U = majorCount_U * minorCount_U;
        for(int major_U = 0; Integer.compareUnsigned(major_U, majorCount_U) < 0; major_U++) {
            int index_U = (major_U >>> 1) * majorMult_U + (major_U & 1);
            byte eccA_U = 0;
            byte eccB_U = 0;
            for(int minor_U = 0; Integer.compareUnsigned(minor_U, minorCount_U) < 0; minor_U++) {
                byte temp_U = src_U.get(index_U);
                index_U += minorInc_U;
                if(Integer.compareUnsigned(index_U, size_U) >= 0) {
                    index_U -= size_U;
                }
                eccA_U = (byte)(Byte.toUnsignedInt(eccA_U) ^ Byte.toUnsignedInt(temp_U));
                eccB_U = (byte)(Byte.toUnsignedInt(eccB_U) ^ Byte.toUnsignedInt(temp_U));
                eccA_U = eccFLut_U[Byte.toUnsignedInt(eccA_U)];
            }
            eccA_U = eccBLut_U[Byte.toUnsignedInt(eccFLut_U[Byte.toUnsignedInt(eccA_U)]) ^ Byte.toUnsignedInt(eccB_U)];
            dest_U.set(major_U, eccA_U);
            dest_U.set(major_U + majorCount_U, (byte)(Byte.toUnsignedInt(eccA_U) ^ Byte.toUnsignedInt(eccB_U)));
        }
    }

    /**
     * Generate ECC P and Q codes for a block
     */
    private static void eccGenerate(String8 sector_U, int zeroaddress) {
        byte[] address_U = new byte[4];
        /* Save the address and zero it out */
        if(zeroaddress != 0) {
            for(byte i_U = 0; Byte.toUnsignedInt(i_U) < 4; i_U++) {
                address_U[Byte.toUnsignedInt(i_U)] = sector_U.get(12 + Byte.toUnsignedInt(i_U));
                sector_U.set(12 + Byte.toUnsignedInt(i_U), (byte)0);
            }
        }
        /* Compute ECC P code */
        eccComputeblock(nnc(sector_U).shift(0xC), 86, 24, 2, 86, nnc(sector_U).shift(0x81C));
        /* Compute ECC Q code */
        eccComputeblock(nnc(sector_U).shift(0xC), 52, 43, 86, 88, nnc(sector_U).shift(0x8C8));
        /* Restore the address */
        if(zeroaddress != 0) {
            for(byte i_U = 0; Byte.toUnsignedInt(i_U) < 4; i_U++) {
                sector_U.set(12 + Byte.toUnsignedInt(i_U), address_U[Byte.toUnsignedInt(i_U)]);
            }
        }
    }

    /**
     * Generate ECC/EDC information for a sector (must be 2352 = 0x930 bytes)
     * Returns 0 on success
     */
    public static void eccedcGenerate(String8 sector_U, int type) {
        switch(type) {
        case 1: /* Mode 1 */
            /* Compute EDC */
            edcComputeblock(nnc(sector_U).shift(0x00), (short)0x810, nnc(sector_U).shift(0x810));
            /* Write out zero bytes */
            for(int i_U = 0; Integer.compareUnsigned(i_U, 8) < 0; i_U++) {
                sector_U.set(0x814 + i_U, (byte)0);
            }
            /* Generate ECC P/Q codes */
            eccGenerate(sector_U, 0);
            break;
        case 2: /* Mode 2 form 1 */
            /* Compute EDC */
            edcComputeblock(nnc(sector_U).shift(0x10), (short)0x808, nnc(sector_U).shift(0x818));
            /* Generate ECC P/Q codes */
            eccGenerate(sector_U, 1);
            break;
        case 3: /* Mode 2 form 2 */
            /* Compute EDC */
            edcComputeblock(nnc(sector_U).shift(0x10), (short)0x91C, nnc(sector_U).shift(0x92C));
            break;
        }
    }

    public static int mycounter_U;

    public static int mycounterTotal_U;

    public static void resetcounter(int total_U) {
        mycounter_U = 0;
        mycounterTotal_U = total_U;
    }

    public static void setcounter(int n_U) {
        if(n_U >>> 20 != mycounter_U >>> 20) {
            int a_U = Integer.divideUnsigned(n_U + 64, 128);
            int d_U = Integer.divideUnsigned(mycounterTotal_U + 64, 128);
            if(d_U == 0) {
                d_U = 1;
            }
            System.err.printf("Decoding (%02d%%)\r", Integer.divideUnsigned(100 * a_U, d_U));
        }
        mycounter_U = n_U;
    }

    public static int unecmify(RandomAccessFile in, RandomAccessFile out) throws IOException {
        final int posUneof = 1, posCorrupt = 2;
        positionLoop:
        for(int pos = 0; true;) switch(pos) {
        default:
            int checkedc_U = 0;
            String8 sector_U = new String8(2_352);
            int type_U;
            int num_U;
            in.seek(in.length());
            resetcounter((int)in.getFilePointer());
            in.seek(0);
            if(in.read() != 'E' || in.read() != 'C' || in.read() != 'M' || in.read() != 0x00) {
                System.err.println("Header not found!");
                pos = posCorrupt;
                continue positionLoop;
            }
            for(;;) {
                int c = in.read();
                int bits = 5;
                if(c == -1) {
                    pos = posUneof;
                    continue positionLoop;
                }
                type_U = c & 3;
                num_U = c >> 2 & 0x1F;
                while((c & 0x80) != 0) {
                    c = in.read();
                    if(c == -1) {
                        pos = posUneof;
                        continue positionLoop;
                    }
                    num_U |= (c & 0x7F) << bits;
                    bits += 7;
                }
                if(num_U == 0xFFFFFFFF) {
                    break;
                }
                num_U++;
                if(Integer.compareUnsigned(num_U, 0x80000000) >= 0) {
                    pos = posCorrupt;
                    continue positionLoop;
                }
                if(type_U == 0) {
                    while(num_U != 0) {
                        int b = num_U;
                        if(b > 2_352) {
                            b = 2_352;
                        }
                        byte[] tmpBuf = new byte[b];
                        int readCount = Math.max(in.read(tmpBuf), 0);
                        sector_U.copyFrom(tmpBuf, readCount);
                        if(readCount != b) {
                            pos = posUneof;
                            continue positionLoop;
                        }
                        checkedc_U = edcPartialComputeblock_U(checkedc_U, sector_U, (short)b);
                        byte[] tmpBuf2 = new byte[b];
                        sector_U.copyTo(tmpBuf2);
                        out.write(tmpBuf2);
                        num_U -= b;
                        setcounter((int)in.getFilePointer());
                    }
                } else {
                    while(num_U-- != 0) {
                        sector_U.fill(0, sector_U.size(), (byte)0);
                        sector_U.shift(1).fill(0, 10, (byte)0xFF);
                        switch(type_U) {
                        case 1:
                            sector_U.set(0x0F, (byte)0x01);
                            byte[] tmpBuf = new byte[0x003];
                            int readCount = Math.max(in.read(tmpBuf), 0);
                            nnc(sector_U.shift(0x00C)).copyFrom(tmpBuf, readCount);
                            if(readCount != 0x003) {
                                pos = posUneof;
                                continue positionLoop;
                            }
                            byte[] tmpBuf2 = new byte[0x800];
                            int readCount2 = Math.max(in.read(tmpBuf2), 0);
                            nnc(sector_U.shift(0x010)).copyFrom(tmpBuf2, readCount2);
                            if(readCount2 != 0x800) {
                                pos = posUneof;
                                continue positionLoop;
                            }
                            eccedcGenerate(sector_U, 1);
                            checkedc_U = edcPartialComputeblock_U(checkedc_U, sector_U, (short)2_352);
                            byte[] tmpBuf3 = new byte[2_352];
                            sector_U.copyTo(tmpBuf3);
                            out.write(tmpBuf3);
                            setcounter((int)in.getFilePointer());
                            break;
                        case 2:
                            sector_U.set(0x0F, (byte)0x02);
                            byte[] tmpBuf4 = new byte[0x804];
                            int readCount3 = Math.max(in.read(tmpBuf4), 0);
                            nnc(sector_U.shift(0x014)).copyFrom(tmpBuf4, readCount3);
                            if(readCount3 != 0x804) {
                                pos = posUneof;
                                continue positionLoop;
                            }
                            sector_U.set(0x10, sector_U.get(0x14));
                            sector_U.set(0x11, sector_U.get(0x15));
                            sector_U.set(0x12, sector_U.get(0x16));
                            sector_U.set(0x13, sector_U.get(0x17));
                            eccedcGenerate(sector_U, 2);
                            checkedc_U = edcPartialComputeblock_U(checkedc_U, sector_U.shift(0x10), (short)2_336);
                            byte[] tmpBuf5 = new byte[2_336];
                            sector_U.shift(0x10).copyTo(tmpBuf5);
                            out.write(tmpBuf5);
                            setcounter((int)in.getFilePointer());
                            break;
                        case 3:
                            sector_U.set(0x0F, (byte)0x02);
                            byte[] tmpBuf6 = new byte[0x918];
                            int readCount4 = Math.max(in.read(tmpBuf6), 0);
                            nnc(sector_U.shift(0x014)).copyFrom(tmpBuf6, readCount4);
                            if(readCount4 != 0x918) {
                                pos = posUneof;
                                continue positionLoop;
                            }
                            sector_U.set(0x10, sector_U.get(0x14));
                            sector_U.set(0x11, sector_U.get(0x15));
                            sector_U.set(0x12, sector_U.get(0x16));
                            sector_U.set(0x13, sector_U.get(0x17));
                            eccedcGenerate(sector_U, 3);
                            checkedc_U = edcPartialComputeblock_U(checkedc_U, sector_U.shift(0x10), (short)2_336);
                            byte[] tmpBuf7 = new byte[2_336];
                            sector_U.shift(0x10).copyTo(tmpBuf7);
                            out.write(tmpBuf7);
                            setcounter((int)in.getFilePointer());
                            break;
                        }
                    }
                }
            }
            byte[] tmpBuf = new byte[4];
            int readCount = Math.max(in.read(tmpBuf), 0);
            sector_U.copyFrom(tmpBuf, readCount);
            if(readCount != 4) {
                pos = posUneof;
                continue positionLoop;
            }
            System.err.println("Decoded " + in.getFilePointer() + " bytes -> " + out.getFilePointer() + " bytes");
            if(Byte.toUnsignedInt(sector_U.get(0)) != (checkedc_U >>> 0 & 0xFF) || Byte.toUnsignedInt(sector_U.get(1)) != (checkedc_U >>> 8 & 0xFF) || Byte.toUnsignedInt(sector_U.get(2)) != (checkedc_U >>> 16 & 0xFF) || Byte.toUnsignedInt(sector_U.get(3)) != (checkedc_U >>> 24 & 0xFF)) {
                System.err.printf("EDC error (%08X, should be %02X%02X%02X%02X)\n", checkedc_U, Byte.toUnsignedInt(sector_U.get(3)), Byte.toUnsignedInt(sector_U.get(2)), Byte.toUnsignedInt(sector_U.get(1)), Byte.toUnsignedInt(sector_U.get(0)));
                pos = posCorrupt;
                continue positionLoop;
            }
            System.err.println("Done; file is OK");
            return 0;
        case posUneof:
            System.err.println("Unexpected EOF!");
        case posCorrupt:
            System.err.println("Corrupt ECM file!");
            return 1;
        }
    }

    public static void main(String[] args) throws IOException {
        RandomAccessFile fin, fout;
        String8 infilename;
        String8 outfilename;
        banner();
        /*
         ** Initialize the ECC/EDC tables
         */
        eccedcInit();
        /*
         ** Check command line
         */
        if(args.length != 1 && args.length != 2) {
            System.err.println("usage: " + Unecm.class.getSimpleName() + " ecmfile [outputfile]");
            System.exit(1);
        }
        /*
         ** Verify that the input filename is valid
         */
        infilename = cs8(args[0]);
        if(Integer.compareUnsigned(infilename.length(), 5) < 0) {
            System.err.println("filename '" + infilename + "' is too short");
            System.exit(1);
        }
        if(!nnc(infilename).shift(infilename.length() - 4).equalsIgnoreCase(".ecm")) {
            System.err.println("filename must end in .ecm");
            System.exit(1);
        }
        /*
         ** Figure out what the output filename should be
         */
        if(args.length == 2) {
            outfilename = cs8(args[1]);
        } else {
            outfilename = new String8(true, infilename.length() - 3);
            nnc(outfilename).copyFrom(infilename, infilename.length() - 4);
            outfilename.set(infilename.length() - 4, (byte)0);
        }
        System.err.println("Decoding " + infilename + " to " + outfilename + ".");
        /*
         ** Open both files
         */
        try {
            fin = new RandomAccessFile(infilename.toString(), "r");
        } catch(IOException ex) {
            fin = null;
            ex.printStackTrace();
            System.exit(1);
        }
        try {
            fout = new RandomAccessFile(outfilename.toString(), "rw");
            fout.setLength(0);
        } catch(IOException ex) {
            fout = null;
            ex.printStackTrace();
            fin.close();
            System.exit(1);
        }
        /*
         ** Decode
         */
        unecmify(fin, fout);
        /*
         ** Close everything
         */
        fout.close();
        fin.close();
    }
}

【讨论】:

    【解决方案4】:

    您是否考虑过使用JNI 而不是费心将C 转换为Java?

    【讨论】:

    • 一个更好的主意是用Java手工重写C代码。 JNI 引入了一大堆问题;例如可移植性、构建、JVM 稳定性等
    • @Aymon:任何图灵完备语言(C 和 Java 都是)可以表示任何其他图灵完备语言可以表示的任何东西。虽然语法和方法可能不同(甚至大相径庭),但在 C 或 Java 中的输入输出方面,没有什么是您可以在其他语言中做不到的。
    • @Adam,但一个可能比另一个快得多 - 图灵的东西不考虑时间。
    • @Thorbjørn OP(在他上面的评论中)问“上面代码中的所有函数都可以翻译成 Java 吗?”,答案是“是”(如两者都是图灵完备的)。他没有问性能。
    • @Adam,只有当 OP 还不知道这一点时,才具有图灵完备性的回答才有意义,然后了解其含义很重要。您是否坦率地认为在进行位操作以计算纠错码的程序中性能并不重要?
    【解决方案5】:

    我使用C++ to Java converter 来转换上面的代码。它不会 100% 正确,但至少它给出了需要做什么的基本思路。

    public class GlobalMembersTest
    {
        /*
        ** UNECM - Decoder for ECM (Error Code Modeler) format.
        ** Version 1.0
        ** Copyright (C) 2002 Neill Corlett
        **
        ** This program is free software; you can redistribute it and/or
        ** modify it under the terms of the GNU General Public License
        ** as published by the Free Software Foundation; either version 2
        ** of the License, or (at your option) any later version.
        **
        ** This program is distributed in the hope that it will be useful,
        ** but WITHOUT ANY WARRANTY; without even the implied warranty of
        ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        ** GNU General Public License for more details.
        **
        ** You should have received a copy of the GNU General Public License
        ** along with this program; if not, write to the Free Software
        ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
        */
        /***************************************************************************/
        /*
        ** Portability notes:
        **
        ** - Assumes a 32-bit or higher integer size
        ** - No assumptions about byte order
        ** - No assumptions about struct packing
        ** - No unaligned memory access
        */
        /***************************************************************************/
        /***************************************************************************/
        public static void banner()
        {
          fprintf(stderr, "UNECM - Decoder for Error Code Modeler format v1.0\n" + "Copyright (C) 2002 Neill Corlett\n\n");
        }
    
        /***************************************************************************/
    
        /* Data types */
        //C++ TO JAVA CONVERTER NOTE: The following #define macro was replaced in-line:
        ///#define ecc_uint8 unsigned char
        //C++ TO JAVA CONVERTER NOTE: The following #define macro was replaced in-line:
        ///#define ecc_uint16 unsigned short
        //C++ TO JAVA CONVERTER NOTE: The following #define macro was replaced in-line:
        ///#define ecc_uint32 unsigned
    
        /* LUTs used for computing ECC/EDC */
        public static byte[] ecc_f_lut = new byte[256];
        public static byte[] ecc_b_lut = new byte[256];
        public static int[] edc_lut = new int[256];
    
        /* Init routine */
        public static void eccedc_init()
        {
          int i;
          int j;
          int edc;
          for (i = 0; i < 256; i++)
          {
            j = (i << 1)  (i & 0x80 ? 0x11D : 0);
            ecc_f_lut[i] = j;
            ecc_b_lut[i ^ j] = i;
            edc = i;
            for (j = 0; j < 8; j++)
                edc = (edc >> 1) ^ (edc & 1 ? 0xD8018001 : 0);
            edc_lut[i] = edc;
          }
        }
    
        /***************************************************************************/
        /*
        ** Compute EDC for a block
        */
        public static int edc_partial_computeblock(int edc, String src, short size)
        {
          while (size--)
              edc = (edc >> 8) ^ edc_lut[(edc ^ (src++)) & 0xFF];
          return edc;
        }
    
        public static void edc_computeblock(String src, short size, byte[] dest)
        {
          int edc = GlobalMembersTest.edc_partial_computeblock(0, src, size);
          dest[0] = (edc >> 0) & 0xFF;
          dest[1] = (edc >> 8) & 0xFF;
          dest[2] = (edc >> 16) & 0xFF;
          dest[3] = (edc >> 24) & 0xFF;
        }
    
        /***************************************************************************/
        /*
        ** Compute ECC for a block (can do either P or Q)
        */
        public static void ecc_computeblock(byte[] src, int major_count, int minor_count, int major_mult, int minor_inc, byte[] dest)
        {
          int size = major_count * minor_count;
          int major;
          int minor;
          for (major = 0; major < major_count; major++)
          {
            int index = (major >> 1) * major_mult + (major & 1);
            byte ecc_a = 0;
            byte ecc_b = 0;
            for (minor = 0; minor < minor_count; minor++)
            {
              byte temp = src[index];
              index += minor_inc;
              if (index >= size)
                  index -= size;
              ecc_a ^= temp;
              ecc_b ^= temp;
              ecc_a = ecc_f_lut[ecc_a];
            }
            ecc_a = ecc_b_lut[ecc_f_lut[ecc_a] ^ ecc_b];
            dest[major] = ecc_a;
            dest[major + major_count] = ecc_a ^ ecc_b;
          }
        }
    
        /*
        ** Generate ECC P and Q codes for a block
        */
        public static void ecc_generate(byte[] sector, int zeroaddress)
        {
          byte[] address = new byte[4];
          byte i;
          /* Save the address and zero it out */
          if (zeroaddress != 0)
              for (i = 0; i < 4; i++)
              {
            address[i] = sector[12 + i];
            sector[12 + i] = 0;
              }
          /* Compute ECC P code */
          GlobalMembersTest.ecc_computeblock(sector + 0xC, 86, 24, 2, 86, sector + 0x81C);
          /* Compute ECC Q code */
          GlobalMembersTest.ecc_computeblock(sector + 0xC, 52, 43, 86, 88, sector + 0x8C8);
          /* Restore the address */
          if (zeroaddress != 0)
              for (i = 0; i < 4; i++)
                  sector[12 + i] = address[i];
        }
    
        /***************************************************************************/
        /*
        ** Generate ECC/EDC information for a sector (must be 2352 = 0x930 bytes)
        ** Returns 0 on success
        */
        public static void eccedc_generate(byte[] sector, int type)
        {
          int i;
          switch (type)
          {
          case 1: // Mode 1
            /* Compute EDC */
            GlobalMembersTest.edc_computeblock(sector + 0x00, 0x810, sector + 0x810);
            /* Write out zero bytes */
            for (i = 0; i < 8; i++)
                sector[0x814 + i] = 0;
            /* Generate ECC P/Q codes */
            GlobalMembersTest.ecc_generate(sector, 0);
            break;
          case 2: // Mode 2 form 1
            /* Compute EDC */
            GlobalMembersTest.edc_computeblock(sector + 0x10, 0x808, sector + 0x818);
            /* Generate ECC P/Q codes */
            GlobalMembersTest.ecc_generate(sector, 1);
            break;
          case 3: // Mode 2 form 2
            /* Compute EDC */
            GlobalMembersTest.edc_computeblock(sector + 0x10, 0x91C, sector + 0x92C);
            break;
          }
        }
    
        /***************************************************************************/
    
        public static int mycounter;
        public static int mycounter_total;
    
        public static void resetcounter(int total)
        {
          mycounter = 0;
          mycounter_total = total;
        }
    
        public static void setcounter(int n)
        {
          if ((n >> 20) != (mycounter >> 20))
          {
            int a = (n + 64) / 128;
            int d = (mycounter_total + 64) / 128;
            if (d == 0)
                d = 1;
            fprintf(stderr, "Decoding (%02d%%)\r", (100 * a) / d);
          }
          mycounter = n;
        }
    
        public static int unecmify(FILE in, FILE out)
        {
          int checkedc = 0;
          byte[] sector = new byte[2352];
          int type;
          int num;
          fseek(in, 0, SEEK_END);
          GlobalMembersTest.resetcounter(ftell(in));
          fseek(in, 0, SEEK_SET);
          if ((fgetc(in) != 'E') || (fgetc(in) != 'C') || (fgetc(in) != 'M') || (fgetc(in) != 0x00))
          {
            fprintf(stderr, "Header not found!\n");
    //C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
            goto corrupt;
          }
          for (;;)
          {
            int c = fgetc(in);
            int bits = 5;
            if (c == EOF)
    //C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
                goto uneof;
            type = c & 3;
            num = (c >> 2) & 0x1F;
            while (c & 0x80 != 0)
            {
              c = fgetc(in);
              if (c == EOF)
    //C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
                  goto uneof;
              num |= ((int)(c & 0x7F)) << bits;
              bits += 7;
            }
            if (num == 0xFFFFFFFF)
                break;
            num++;
            if (num >= 0x80000000)
    //C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
                goto corrupt;
            if (type == 0)
            {
              while (num != 0)
              {
                int b = num;
                if (b > 2352)
                    b = 2352;
                if (fread(sector, 1, b, in) != b)
    //C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
                    goto uneof;
                checkedc = GlobalMembersTest.edc_partial_computeblock(checkedc, sector, b);
                fwrite(sector, 1, b, out);
                num -= b;
                GlobalMembersTest.setcounter(ftell(in));
              }
            }
            else
            {
              while (num--)
              {
    //C++ TO JAVA CONVERTER TODO TASK: The memory management function 'memset' has no equivalent in Java:
    //C++ TO JAVA CONVERTER TODO TASK: There is no Java equivalent to 'sizeof':
                memset(sector, 0, sizeof(sector));
    //C++ TO JAVA CONVERTER TODO TASK: The memory management function 'memset' has no equivalent in Java:
                memset(sector + 1, 0xFF, 10);
                switch (type)
                {
                case 1:
                  sector[0x0F] = 0x01;
                  if (fread(sector + 0x00C, 1, 0x003, in) != 0x003)
    //C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
                      goto uneof;
                  if (fread(sector + 0x010, 1, 0x800, in) != 0x800)
    //C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
                      goto uneof;
                  GlobalMembersTest.eccedc_generate(sector, 1);
                  checkedc = GlobalMembersTest.edc_partial_computeblock(checkedc, sector, 2352);
                  fwrite(sector, 2352, 1, out);
                  GlobalMembersTest.setcounter(ftell(in));
                  break;
                case 2:
                  sector[0x0F] = 0x02;
                  if (fread(sector + 0x014, 1, 0x804, in) != 0x804)
    //C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
                      goto uneof;
                  sector[0x10] = sector[0x14];
                  sector[0x11] = sector[0x15];
                  sector[0x12] = sector[0x16];
                  sector[0x13] = sector[0x17];
                  GlobalMembersTest.eccedc_generate(sector, 2);
                  checkedc = GlobalMembersTest.edc_partial_computeblock(checkedc, sector + 0x10, 2336);
                  fwrite(sector + 0x10, 2336, 1, out);
                  GlobalMembersTest.setcounter(ftell(in));
                  break;
                case 3:
                  sector[0x0F] = 0x02;
                  if (fread(sector + 0x014, 1, 0x918, in) != 0x918)
    //C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
                      goto uneof;
                  sector[0x10] = sector[0x14];
                  sector[0x11] = sector[0x15];
                  sector[0x12] = sector[0x16];
                  sector[0x13] = sector[0x17];
                  GlobalMembersTest.eccedc_generate(sector, 3);
                  checkedc = GlobalMembersTest.edc_partial_computeblock(checkedc, sector + 0x10, 2336);
                  fwrite(sector + 0x10, 2336, 1, out);
                  GlobalMembersTest.setcounter(ftell(in));
                  break;
                }
              }
            }
          }
          if (fread(sector, 1, 4, in) != 4)
    //C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
              goto uneof;
          fprintf(stderr, "Decoded %ld bytes -> %ld bytes\n", ftell(in), ftell(out));
          if ((sector[0] != ((checkedc >> 0) & 0xFF)) || (sector[1] != ((checkedc >> 8) & 0xFF)) || (sector[2] != ((checkedc >> 16) & 0xFF)) || (sector[3] != ((checkedc >> 24) & 0xFF)))
          {
            fprintf(stderr, "EDC error (%08X, should be %02X%02X%02X%02X)\n", checkedc, sector[3], sector[2], sector[1], sector[0]);
    //C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
            goto corrupt;
          }
          fprintf(stderr, "Done; file is OK\n");
          return 0;
    //C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
        uneof:
          fprintf(stderr, "Unexpected EOF!\n");
    //C++ TO JAVA CONVERTER TODO TASK: There are no gotos or labels in Java:
        corrupt:
          fprintf(stderr, "Corrupt ECM file!\n");
          return 1;
        }
    
        /***************************************************************************/
    
        public static int Main(int argc, String[] args)
        {
          FILE fin;
          FILE fout;
          String infilename;
          String outfilename;
          GlobalMembersTest.banner();
          /*
          ** Initialize the ECC/EDC tables
          */
          GlobalMembersTest.eccedc_init();
          /*
          ** Check command line
          */
          if ((argc != 2) && (argc != 3))
          {
            fprintf(stderr, "usage: %s ecmfile [outputfile]\n", args[0]);
            return 1;
          }
          /*
          ** Verify that the input filename is valid
          */
          infilename = args[1];
          if (infilename.length() < 5)
          {
            fprintf(stderr, "filename '%s' is too short\n", infilename);
            return 1;
          }
          if (strcasecmp(infilename + infilename.length() - 4, ".ecm"))
          {
            fprintf(stderr, "filename must end in .ecm\n");
            return 1;
          }
          /*
          ** Figure out what the output filename should be
          */
          if (argc == 3)
          {
            outfilename = args[2];
          }
          else
          {
    //C++ TO JAVA CONVERTER TODO TASK: The memory management function 'malloc' has no equivalent in Java:
            outfilename = malloc(infilename.length() - 3);
            if (outfilename == null)
                abort();
    //C++ TO JAVA CONVERTER TODO TASK: The memory management function 'memcpy' has no equivalent in Java:
            memcpy(outfilename, infilename, infilename.length() - 4);
            outfilename = outfilename.substring(0, infilename.length() - 4);
          }
          fprintf(stderr, "Decoding %s to %s.\n", infilename, outfilename);
          /*
          ** Open both files
          */
          fin = fopen(infilename, "rb");
          if (fin == null)
          {
            perror(infilename);
            return 1;
          }
          fout = fopen(outfilename, "wb");
          if (fout == null)
          {
            perror(outfilename);
            fclose(fin);
            return 1;
          }
          /*
          ** Decode
          */
          GlobalMembersTest.unecmify(fin, fout);
          /*
          ** Close everything
          */
          fclose(fout);
          fclose(fin);
        }
    }
    

    【讨论】:

    • 感谢您分享该转换器的愚蠢示例。
    【解决方案6】:

    问题是问“任何工具?”,所以这里有一个工具。
    请不要仅仅因为您不喜欢工具就投反对票。

    我尝试了一个名为“Novosoft C2J”的 C 到 Java 转换工具。结论:

    • 非常有问题
    • 经常崩溃
    • 专有(尽管它声称“C2J 的 Beta 版本受 GNU 许可”,但找不到源代码)

    我设法转换了一个依赖很少的 C 文件,但必须通过将头文件的内容复制粘贴到头文件来“预处理”它,因为 C2J 不允许我选择 .h 文件以包含在项目。

    翻译后的代码是静态的,带有奇怪的“nextlevel()”和“prevlevel()”调用。
    有些翻译后的代码需要人工处理,例如:UndefFcs.cisnan([...])

    结论:工具有问题,但可能没有更好的工具。

    【讨论】:

      【解决方案7】:

      我意识到我从未发布过我的解决方案

      在 Android 活动中:

      Public class UnECMActivity extends Activity {
      ...
      
          static {
          System.loadLibrary("unecm");
      }
      private native int rununecm(String fileName);
      

      在 unecm.c 中添加:

      jint Java_com_romcessed_unecm_UnECMActivity_rununecm(JNIEnv* env, jobject javaThis, jstring fileName) {
        FILE *fin, *fout;
        jboolean *iscopy;
        char *infilename = (*env)->GetStringUTFChars(env, fileName, iscopy);
        char *outfilename;
        banner();
        eccedc_init();
      
        /*
        ** Verify that the input filename is valid
        */
        if(strlen(infilename) < 5) {
          fprintf(stderr, "filename '%s' is too short\n", infilename);
          return 1;
        }
        if(strcasecmp(infilename + strlen(infilename) - 4, ".ecm")) {
          fprintf(stderr, "filename must end in .ecm\n");
          return 1;
        }
      
        /*
        ** Figure out what the output filename should be
        */
          outfilename = malloc(strlen(infilename) - 3);
          if(!outfilename) abort();
          memcpy(outfilename, infilename, strlen(infilename) - 4);
          outfilename[strlen(infilename) - 4] = 0;
      
        fprintf(stderr, "Decoding %s to %s.\n", infilename, outfilename);
        /*
        ** Open both files
        */
        fin = fopen(infilename, "rb");
        if(!fin) {
          perror(infilename);
          return 1;
        }
        fout = fopen(outfilename, "wb");
        if(!fout) {
          perror(outfilename);
          fclose(fin);
          return 1;
        }
        /*
        ** Decode
        */
        unecmify(fin, fout);
        /*
        ** Close everything
        */
        fclose(fout);
        fclose(fin);
        return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 2013-09-17
        • 1970-01-01
        • 1970-01-01
        • 2012-05-09
        • 2012-10-29
        • 1970-01-01
        • 2015-12-29
        • 2015-09-16
        • 2011-05-11
        相关资源
        最近更新 更多