Changeset 90


Ignore:
Timestamp:
03/27/07 06:22:21 (5 years ago)
Author:
matthiasm
Message:

Added a pretty complete NEwton Package reader. For best results, you need LIBICONV and no NAMED_MAGIC_POINTER.. This is not bound into the Xcode project or the Makefile system until I can verify that this works flawlessly on those platforms.

Just call "newtRef pkg = NewtReadPkg(buffer, n);" where "buffer" is a copy of the Package in RAM and "n" is its size. This will create an object describing the entire package.

The biggest flaw at this point is that the same object may get instantiated many times instead of simple referenced multiple times. And I just can't find out what the special ref 0x32 is... .

Location:
NEWT0/trunk/src/newt_core
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • NEWT0/trunk/src/newt_core/NewtPkg.c

    r89 r90  
    1111 
    1212 
    13 /* ヘッダファイル  includes */ 
     13/* header files */ 
    1414#include <string.h> 
    1515 
     
    1717#include "NewtErrs.h" 
    1818#include "NewtObj.h" 
    19 //#include "NewtEnv.h" 
    20 //#include "NewtFns.h" 
    21 //#include "NewtVM.h" 
    22 //#include "NewtIconv.h" 
     19#include "NewtEnv.h" 
     20#include "NewtFns.h" 
     21#include "NewtVM.h" 
     22#include "NewtIconv.h" 
    2323 
    2424#include "utils/endian_utils.h" 
    2525 
    26  
    27 /* マクロ  defines */ 
     26#undef DEBUG_PKG_DIS 
     27#define DEBUG_PKG 
     28#ifdef DEBUG_PKG 
     29#   include "NewtPrint.h" 
     30#endif 
     31 
     32/* macros */ 
    2833 
    2934/// Test first 8 bytes for package signature 
    30 #define PkgIsPackage(data) ((strncmp(data, "package0", 8)==0) || (strncmp(data, "package0", 8)==0)) 
    31  
    32  
    33 /* 型宣言  types */ 
     35#define PkgIsPackage(data) ((strncmp(data, "package0", 8)==0) || (strncmp(data, "package1", 8)==0)) 
     36 
     37 
     38/* types */ 
    3439 
    3540/// info refs are a shorthand version of pointers into a userdata area of the package 
     
    4853    pkg_info_ref_t name;        ///< utf16 package name 
    4954    uint32_t    size;           ///< entire size of package 
    50     uint32_t    data;           ///< creation data 
     55    uint32_t    date;           ///< creation date 
    5156    uint32_t    reserverd2; 
    5257    uint32_t    reserverd3; 
     
    7277    uint8_t *   data;           ///< package data 
    7378    uint32_t    size;           ///< size of package 
    74     pkg_header_t *header;       ///< pointer to the package header 
    75     pkg_part_t  *part_headers;  ///< pointer to first part header - can be used as an array 
     79    pkg_header_t * header;      ///< pointer to the package header 
     80    uint8_t *   var_len_data;   ///< extra data for header 
     81    uint32_t    num_parts;      ///< number of parts in package 
     82    pkg_part_t* part_headers;   ///< pointer to first part header - can be used as an array 
     83    pkg_part_t* part_header;    ///< header of current part 
     84    uint8_t *   part;           ///< start of current part data 
    7685    newtErr     lastErr;        ///< a way to return error from deep below 
     86#ifdef HAVE_LIBICONV 
     87    iconv_t     from_utf16;     ///< strings in compatible packages are UTF16 
     88#endif /* HAVE_LIBICONV */ 
    7789} pkg_stream_t; 
    7890 
    7991 
    80 /* 関数プロトタイプ  functions */ 
     92/* functions */ 
     93uint32_t PkgReadU32(uint8_t *d); 
     94 
     95newtRef PkgReadRef(pkg_stream_t *pkg, uint32_t p_obj); 
     96newtRef PkgReadBinaryObject(pkg_stream_t *pkg, uint32_t p_obj); 
     97newtRef PkgReadArrayObject(pkg_stream_t *pkg, uint32_t p_obj); 
     98newtRef PkgReadFrameObject(pkg_stream_t *pkg, uint32_t p_obj); 
     99newtRef PkgReadObject(pkg_stream_t *pkg, uint32_t p_obj); 
     100 
    81101newtRef PkgReadPart(pkg_stream_t *pkg, int32_t index); 
     102 
     103newtRef PkgReadVardataString(pkg_stream_t *pkg, pkg_info_ref_t *info_ref); 
     104newtRef PkgReadVardataBinary(pkg_stream_t *pkg, pkg_info_ref_t *info_ref); 
     105newtRef PkgReadHeader(pkg_stream_t *pkg); 
     106 
    82107newtRef NewtReadPkg(uint8_t * data, size_t size); 
    83108 
    84109/*------------------------------------------------------------------------*/ 
     110/** Endian-neutral conversion of four bytes into one uint32 
     111 *  
     112 * @param d     [in] pointer to byte array 
     113 * 
     114 * @retval  uint32 assembled from four bytes 
     115 */ 
     116uint32_t PkgReadU32(uint8_t *d)  
     117{ 
     118    return ((d[0]<<24)|(d[1]<<16)|(d[2]<<8)|(d[3])); 
     119} 
     120 
     121/*------------------------------------------------------------------------*/ 
     122/** Generate a ref from package data 
     123 *  
     124 * @param pkg       [inout] the package 
     125 * @param p_obj     [in] offset to Ref data relative to package start 
     126 * 
     127 * @retval  Newt object version of package Ref 
     128 */ 
     129newtRef PkgReadRef(pkg_stream_t *pkg, uint32_t p_obj) 
     130{ 
     131    uint32_t ref = PkgReadU32(pkg->data + p_obj); 
     132    newtRef result = kNewtRefNIL; 
     133 
     134    switch (ref&3) { 
     135    case 0: // integer 
     136        result = NSINT(ref>>2); 
     137        break; 
     138    case 1: // pointer 
     139        result = PkgReadObject(pkg, ref&~3); 
     140        break; 
     141    case 2: // special 
     142        if (ref==kNewtRefTRUE) result = kNewtRefTRUE; 
     143        else if (ref==kNewtRefNIL) result = kNewtRefNIL; 
     144        else if (ref&0x0f==0x0a) result = NewtMakeCharacter(ref>>4); 
     145        else if (ref==kNewtSymbolClass) result = kNewtSymbolClass; 
     146        else if (ref==0x32) { 
     147            result = 0x32; 
     148            printf("*** PkgReader: PkgReadRef - unsupported ref 0x%08x - what is this?\n", ref); 
     149        } else { 
     150#           ifdef DEBUG_PKG 
     151                printf("*** PkgReader: PkgReadRef - unsupported ref 0x%08x\n", ref); 
     152#           endif 
     153            result = ref;  
     154        } 
     155        break; 
     156    case 3: // magic pointer 
     157#       ifdef __NAMED_MAGIC_POINTER__ 
     158            result = kNewtRefNIL; // no timplemented 
     159#       else 
     160            result = ref; // already a correct magic pointer 
     161#       endif 
     162        break; 
     163    } 
     164 
     165    return result; 
     166} 
     167 
     168/*------------------------------------------------------------------------*/ 
     169/** Generate a binary object from package data 
     170 *  
     171 * @param pkg       [inout] the package 
     172 * @param p_obj     [in] offset to binary data object relative to package start 
     173 * 
     174 * @retval  Newt object version of binary object 
     175 */ 
     176newtRef PkgReadBinaryObject(pkg_stream_t *pkg, uint32_t p_obj) 
     177{ 
     178    uint32_t size = PkgReadU32(pkg->data + p_obj) >> 8; 
     179    newtRef klass, result = kNewtRefNIL; 
     180    newtRef ins = NSSYM0(instructions); 
     181 
     182    klass = PkgReadRef(pkg, p_obj+8); 
     183 
     184    if (klass==kNewtSymbolClass) { 
     185        result = NewtMakeSymbol(pkg->data + p_obj + 16); 
     186    } else if (klass==NSSYM0(string)) { 
     187        char *src = pkg->data + p_obj + 12; 
     188        int sze = size-12; 
     189#       ifdef HAVE_LIBICONV 
     190            size_t buflen; 
     191            char *buf = NewtIconv(pkg->from_utf16, src, sze, &buflen); 
     192            if (buf) { 
     193                result = NewtMakeString2(buf, buflen, false); 
     194            } 
     195#       endif /* HAVE_LIBICONV */ 
     196        if (result==kNewtRefNIL) 
     197            result = NewtMakeString2(src, sze, false); 
     198    } else if (klass==NSSYM0(int32)) { 
     199        uint32_t v = PkgReadU32(pkg->data + p_obj + 12); 
     200        result = NewtMakeInt32(v); 
     201    } else if (klass==NSSYM0(real)) { 
     202        double *v = (double*)(pkg->data + p_obj + 12); 
     203        result = NewtMakeReal(ntohd(*v)); 
     204    } else if (klass==NSSYM0(instructions)) { 
     205        result = NewtMakeBinary(klass, pkg->data + p_obj + 12, size-12, false); 
     206#       ifdef DEBUG_PKG_DIS 
     207            printf("*** PkgReader: PkgReadBinaryObject - dumping byte code\n"); 
     208            NVMDumpBC(stdout, result); 
     209#       endif 
     210    } else { 
     211        // bits: the bits in the icon 
     212        // mask: the transparency mask for the icon 
     213#       ifdef DEBUG_PKG 
     214            if (klass) { 
     215                printf("*** PkgReader: PkgReadBinaryObject - unknown class "); 
     216                NewtPrintObject(stdout, klass); 
     217            } 
     218#       endif 
     219        result = NewtMakeBinary(klass, pkg->data + p_obj + 12, size-12, false); 
     220    } 
     221 
     222    return result; 
     223} 
     224 
     225/*------------------------------------------------------------------------*/ 
     226/** Generate an array from package data 
     227 *  
     228 * @param pkg       [inout] the package 
     229 * @param p_obj     [in] offset to array data relative to package start 
     230 * 
     231 * @retval  Newt object version of package Array 
     232 */ 
     233newtRef PkgReadArrayObject(pkg_stream_t *pkg, uint32_t p_obj) 
     234{ 
     235    uint32_t size = PkgReadU32(pkg->data + p_obj) >> 8; 
     236    uint32_t num_slots = size/4 - 3; 
     237    uint32_t i; 
     238    newtRef array, klass; 
     239 
     240    klass = PkgReadRef(pkg, p_obj+8); 
     241    array = NewtMakeArray(klass, num_slots); 
     242 
     243    if (NewtRefIsNotNIL(array)) { 
     244        for (i=0; i<num_slots; i++) { 
     245            NewtSetArraySlot(array, i, PkgReadRef(pkg, p_obj+12 + 4*i)); 
     246        } 
     247    } 
     248 
     249    return array; 
     250} 
     251 
     252 
     253/*------------------------------------------------------------------------*/ 
     254/** Generate a frame from package data 
     255 *  
     256 * @param pkg       [inout] the package 
     257 * @param p_obj     [in] offset to frame data relative to package start 
     258 * 
     259 * @retval  Newt object version of package Frame 
     260 */ 
     261newtRef PkgReadFrameObject(pkg_stream_t *pkg, uint32_t p_obj) 
     262{ 
     263    uint32_t size = PkgReadU32(pkg->data + p_obj) >> 8; 
     264    uint32_t i, num_slots = size/4 - 3; 
     265    newtRef frame = kNewtRefNIL, map; 
     266 
     267    map = PkgReadRef(pkg, p_obj+8); 
     268 
     269    frame = NewtMakeFrame(map, num_slots); 
     270 
     271    if (NewtRefIsNotNIL(frame)) { 
     272 
     273        newtRef *slot = NewtRefToSlots(frame); 
     274        for (i=0; i<num_slots; i++) { 
     275            slot[i] = PkgReadRef(pkg, p_obj+12 + 4*i); 
     276        } 
     277    } 
     278 
     279    return frame; 
     280} 
     281 
     282/*------------------------------------------------------------------------*/ 
     283/** Recursively read the object at the given offset 
     284 *  
     285 * @param pkg       [inout] the package 
     286 * @param p_obj     [in] offset to object relative to package start 
     287 * 
     288 * @retval  Newt object version of package object 
     289 */ 
     290newtRef PkgReadObject(pkg_stream_t *pkg, uint32_t p_obj) 
     291{ 
     292    uint32_t obj = PkgReadU32(pkg->data + p_obj); 
     293    newtRef ret = kNewtRefNIL; 
     294 
     295    switch (obj & 0xff) { 
     296    case 0x40: // binary object 
     297        ret = PkgReadBinaryObject(pkg, p_obj); 
     298        break; 
     299    case 0x40 | kObjSlotted: // array 
     300        ret = PkgReadArrayObject(pkg, p_obj); 
     301        break; 
     302    case 0x40 | kObjSlotted | kObjFrame: // frame 
     303        ret = PkgReadFrameObject(pkg, p_obj); 
     304        break; 
     305    case 0x40 | kObjFrame: // not defined 
     306    default: 
     307#       ifdef DEBUG_PKG 
     308            printf("*** PkgReader: PkgReadObject - unsupported object 0x%08x\n", obj); 
     309#       endif 
     310        break; 
     311    } 
     312    return ret; 
     313} 
     314 
     315/*------------------------------------------------------------------------*/ 
     316/** Read a NOS part from the package file. 
     317 *  
     318 * @param pkg       [inout] the package 
     319 * 
     320 * @retval  Newt object with contents of NOS part 
     321 */ 
     322newtRef PkgReadNOSPart(pkg_stream_t *pkg) 
     323{ 
     324    uint32_t p_obj = PkgReadU32(pkg->part+12); 
     325    return PkgReadObject(pkg, p_obj&~3); 
     326} 
     327 
     328/*------------------------------------------------------------------------*/ 
    85329/** Read a part from the package file. 
    86330 *  
     
    92336newtRef PkgReadPart(pkg_stream_t *pkg, int32_t index) 
    93337{ 
    94     newtRefVar  r = kNewtRefNIL; 
    95     // FIXME prepare pkg with offsets and pointer for reading this Part 
    96     // FIXME store 8/4 byte alignment flag (no so important for reading though) 
    97     // FIXME call PkgReadPart2 to recursively scan all Refs in the part 
    98     return r; 
     338    uint32_t    flags; 
     339    newtRefVar  frame; 
     340    newtRefVar  ptv[] = { 
     341                            NS_CLASS,               NSSYM(PackagePart), 
     342                            NSSYM(info),            kNewtRefNIL, 
     343                            NSSYM(flags),           kNewtRefNIL, 
     344                            NSSYM(type),            kNewtRefNIL, 
     345                            NSSYM(data),            kNewtRefNIL 
     346                        }; 
     347 
     348    pkg->part_header = pkg->part_headers + index; 
     349    pkg->part = pkg->data  
     350                + ntohl(pkg->header->directorySize)  
     351                + ntohl(pkg->part_header->offset); 
     352    flags = ntohl(pkg->part_header->flags); 
     353 
     354    frame = NewtMakeFrame2(sizeof(ptv) / (sizeof(newtRefVar) * 2), ptv); 
     355 
     356    NcSetSlot(frame, NSSYM(flags), NewtMakeInt32(flags)); 
     357    NcSetSlot(frame, NSSYM(type), NewtMakeBinary(kNewtRefUnbind,  
     358                (uint8_t*)&pkg->part_header->type, 4, true)); 
     359 
     360    switch (flags&0x03) { 
     361    case kNOSPart: 
     362        if (   PkgReadU32(pkg->part)  !=0x00001041 
     363            || PkgReadU32(pkg->part+8)!=0x00000002)  
     364        { 
     365#           ifdef DEBUG_PKG 
     366                printf("*** PkgReader: PkgReadPart - unsupported NOS Part intro at %d\n", 
     367                    pkg->part-pkg->data); 
     368#           endif 
     369            break; 
     370        } 
     371        NcSetSlot(frame, NSSYM(info), PkgReadVardataBinary(pkg, &pkg->part_header->info)); 
     372        NcSetSlot(frame, NSSYM(data), PkgReadNOSPart(pkg)); 
     373        break; 
     374    case kProtocolPart: 
     375    case kRawPart: 
     376    default: 
     377#       ifdef DEBUG_PKG 
     378            printf("*** PkgReader: PkgReadPart - unsupported part 0x%08x\n", flags); 
     379#       endif 
     380        break; 
     381    } 
     382    return frame; 
     383} 
     384 
     385/*------------------------------------------------------------------------*/ 
     386/** Read binary data from the Variable Data area 
     387 *  
     388 * @param pkg       [inout] the package 
     389 * @param info_ref  [in] pointer to the reference 
     390 * 
     391 * @retval  Binary object 
     392 */ 
     393newtRef PkgReadVardataBinary(pkg_stream_t *pkg, pkg_info_ref_t *info_ref) 
     394{ 
     395    if (info_ref->size==0) { 
     396        return kNewtRefNIL; 
     397    } else { 
     398        uint8_t *src = pkg->var_len_data + ntohs(info_ref->offset); 
     399        int size = ntohs(info_ref->size); 
     400        return NewtMakeBinary(kNewtRefUnbind, src, size, true); 
     401    } 
     402} 
     403 
     404/*------------------------------------------------------------------------*/ 
     405/** Read a UTF16 string from the Variable Data area 
     406 *  
     407 * @param pkg       [inout] the package 
     408 * @param info_ref  [in] pointer to the reference 
     409 * 
     410 * @retval  String object 
     411 */ 
     412newtRef PkgReadVardataString(pkg_stream_t *pkg, pkg_info_ref_t *info_ref) 
     413{ 
     414    if (info_ref->size==0) { 
     415        return kNewtRefNIL; 
     416    } else { 
     417        char *src = pkg->var_len_data + ntohs(info_ref->offset); 
     418        int size = ntohs(info_ref->size); 
     419#       ifdef HAVE_LIBICONV 
     420            size_t buflen; 
     421            char *buf = NewtIconv(pkg->from_utf16, src, size, &buflen); 
     422            if (buf) { 
     423                return NewtMakeString2(buf, buflen, false); 
     424            } 
     425#       endif /* HAVE_LIBICONV */ 
     426        return NewtMakeString2(src, size, false); 
     427    } 
     428} 
     429 
     430/*------------------------------------------------------------------------*/ 
     431/** Read the package header and create a Frame object describing it. 
     432 *  
     433 * @param pkg       [inout] the package 
     434 * 
     435 * @retval  Frame describing the package 
     436 */ 
     437newtRef PkgReadHeader(pkg_stream_t *pkg) 
     438{ 
     439    newtRefVar  fnv[] = { 
     440                            NS_CLASS,               NSSYM(PackageHeader), 
     441                            NSSYM(version),         kNewtRefNIL, 
     442                            NSSYM(copyright),       kNewtRefNIL, 
     443                            NSSYM(name),            kNewtRefNIL, 
     444                            NSSYM(flags),           kNewtRefNIL, 
     445                            NSSYM(parts),           kNewtRefNIL 
     446                        }; 
     447    newtRefVar  frame = NewtMakeFrame2(sizeof(fnv) / (sizeof(newtRefVar) * 2), fnv); 
     448    newtRefVar  parts; 
     449 
     450    NcSetSlot(frame, NSSYM(version), NSINT(pkg->verno)); 
     451    NcSetSlot(frame, NSSYM(copyright), PkgReadVardataString(pkg, &pkg->header->copyright)); 
     452    NcSetSlot(frame, NSSYM(name), PkgReadVardataString(pkg, &pkg->header->name)); 
     453    NcSetSlot(frame, NSSYM(flags), NewtMakeInt32(ntohl(pkg->header->flags))); 
     454    // all other header values can be derived form the archive itself 
     455    // or can be calculated at creation time 
     456 
     457    parts = NewtMakeArray(kNewtRefNIL, pkg->num_parts); 
     458 
     459    if (NewtRefIsNotNIL(parts)) 
     460    { 
     461        int32_t i, n = pkg->num_parts; 
     462 
     463        NcSetSlot(frame, NSSYM(parts), parts); 
     464        for (i = 0; i < n; i++) 
     465        { 
     466            NewtSetArraySlot(parts, i, PkgReadPart(pkg, i)); 
     467            if (pkg->lastErr != kNErrNone) break; 
     468        } 
     469    } 
     470 
     471    return frame; 
    99472} 
    100473 
     
    102475/** Read a Package and create an array of parts 
    103476 * 
    104  * @param data      [in] Package data memory 
     477 * @param data      [in] Package data memory, can be read-only 
    105478 * @param size      [in] size of memory array 
    106479 * 
     
    109482 * @todo    There is no support for relocation data yet. 
    110483 */ 
    111  
    112484newtRef NewtReadPkg(uint8_t * data, size_t size) 
    113485{ 
    114486    pkg_stream_t    pkg; 
    115     newtRefVar      result; 
     487    newtRef         result; 
    116488 
    117489    if (size<sizeof(pkg_header_t)) 
    118         return 0; // FIXME return a meaningful error 
     490        return kNewtRefNIL; 
    119491 
    120492    if (!PkgIsPackage(data)) 
    121         return 0; // FIXME return a meaningful error 
     493        return kNewtRefNIL; 
    122494 
    123495    memset(&pkg, 0, sizeof(pkg)); 
     
    126498    pkg.size = size; 
    127499    pkg.header = (pkg_header_t*)data; 
    128  
    129     result = NewtMakeArray(kNewtRefNIL, pkg.header->numParts+1); 
    130  
    131     if (NewtRefIsNotNIL(result)) 
    132     { 
    133         // FIXME the first slot of the array will contain information form the package 
    134         // FIXME header arranged in a frame 
    135         newtRef *slots; 
    136         int32_t i, n; 
    137  
    138         slots = NewtRefToSlots(result); 
    139         n = pkg.header->numParts; 
    140  
    141         for (i = 0; i < n; i++) 
    142         { 
    143             slots[i+1] = PkgReadPart(&pkg, i); 
    144             if (pkg.lastErr != kNErrNone) break; 
    145         } 
    146     } 
     500    pkg.num_parts = ntohl(pkg.header->numParts); 
     501    pkg.part_headers = (pkg_part_t*)(data + sizeof(pkg_header_t)); 
     502    pkg.var_len_data = data + sizeof(pkg_header_t) + pkg.num_parts*sizeof(pkg_part_t); 
     503#   ifdef HAVE_LIBICONV 
     504    {   char *encoding = NewtDefaultEncoding(); 
     505        pkg.from_utf16 = iconv_open(encoding, "UTF-16BE"); 
     506    } 
     507#   endif /* HAVE_LIBICONV */ 
     508 
     509    result = PkgReadHeader(&pkg); 
     510 
     511#   ifdef HAVE_LIBICONV 
     512        iconv_close(pkg.from_utf16); 
     513#   endif /* HAVE_LIBICONV */ 
    147514 
    148515    return result; 
  • NEWT0/trunk/src/newt_core/incs/NewtType.h

    r68 r90  
    104104 
    105105 
     106/// Newton Package Format: Part Flags 
     107enum { 
     108    kProtocolPart   = 0,        ///< part contains protocol data 
     109    kNOSPart        = 1,        ///< part contains NOS data 
     110    kRawPart        = 2,        ///< raw part data, no defined type 
     111    kAutoLoadFlag   = 0x0010,   ///< protocols will be registered automatically 
     112    kAutoRemoveFlag = 0x0020,   ///< protocols will be unregistered automatically 
     113    kNotifyFlag     = 0x0080,   ///< notify system handler of installation 
     114    kAutoCopyFlag   = 0x0100    ///< part must be moved into precious RAM before activation 
     115}; 
     116 
     117 
     118/// Newton Package Format: Object Header Flags 
     119enum { 
     120    kObjSlotted = 0x01, ///< object is an array 
     121    kObjFrame   = 0x02, ///< object is a frame if both flags are set 
     122}; 
     123 
     124 
    106125/* 型宣言 */ 
    107126 
  • NEWT0/trunk/src/newt_core/incs/VC6/NewtConf.h

    r87 r90  
    1818 
    1919/// 名前付マジックポインタを使用 
    20 #define __NAMED_MAGIC_POINTER__ 1 
     20#undef __NAMED_MAGIC_POINTER__ 
    2121 
    2222/* VM */ 
Note: See TracChangeset for help on using the changeset viewer.