Changeset 95
- Timestamp:
- 03/29/07 19:51:22 (20 months ago)
- Files:
-
- 1 modified
-
NEWT0/trunk/src/newt_core/NewtPkg.c (modified) (37 diffs)
Legend:
- Unmodified
- Added
- Removed
-
NEWT0/trunk/src/newt_core/NewtPkg.c
r94 r95 24 24 #include "utils/endian_utils.h" 25 25 26 #include <time.h> 27 26 28 #undef DEBUG_PKG_DIS 27 29 #define DEBUG_PKG … … 30 32 #endif 31 33 34 32 35 /* macros */ 33 36 34 /// Test first 8 bytes for package signature37 /// Test first 8 bytes for any of the package signatures 35 38 #define PkgIsPackage(data) ((strncmp(data, "package0", 8)==0) || (strncmp(data, "package1", 8)==0)) 36 39 … … 47 50 typedef struct { 48 51 uint8_t sig[8]; ///< 8 byte signature 49 uint 8_t type[4];///< 4 bytes describing package class52 uint32_t type; ///< 4 bytes describing package class 50 53 uint32_t flags; ///< describing how to store and load the package 51 54 uint32_t version; ///< user definable; higher numbers are newer version … … 72 75 } pkg_part_t; 73 76 74 /// structure to manage the package reading process 77 /// structure to manage the package reading process 75 78 typedef struct { 76 int8_t verno; ///< r package version 0 or 179 uint8_t pkg_version; ///< rw corrsponds to the last charof the signature 77 80 uint8_t * data; ///< rw package data 78 81 uint32_t size; ///< rw size of package … … 82 85 uint8_t * var_data; ///< r extra data for header 83 86 uint32_t var_data_size; ///< w size of variable length data block 87 uint32_t directory_size; ///< w size of all headers plus var data 84 88 uint32_t num_parts; ///< r number of parts in package 85 89 pkg_part_t* part_headers; ///< r pointer to first part header - can be used as an array … … 87 91 uint8_t * part; ///< r start of current part data 88 92 uint32_t part_offset; ///< r offset of current part to the beginning of data 93 uint32_t part_header_offset; ///< r offset of current part header 89 94 newtRefVar instances; ///< rw array holding the previously generated instance of any ref per part 90 95 newtRefVar precedents; ///< w array referencing the instances array … … 98 103 99 104 /* functions */ 100 static newtRef PkgPartGetPrecedent(pkg_stream_t *pkg, newtRefArg r); 101 static void PkgPartSetPrecedent(pkg_stream_t *pkg, newtRefArg r, newtRefArg val); 102 105 106 static int32_t PkgArraySearch(newtRefArg array, newtRefArg r); 107 static uint32_t PkgAlign(pkg_stream_t *pkg, uint32_t offset); 108 static uint32_t PkgGetSlotInt(newtRefArg frame, newtRefArg name, uint32_t def); 109 110 static newtRef PkgPartGetPrecedent(pkg_stream_t *pkg, newtRefArg ref); 111 static void PkgPartSetPrecedent(pkg_stream_t *pkg, newtRefArg ref, newtRefArg val); 112 113 static void PkgMakeRoom(pkg_stream_t *pkg, uint32_t offset, uint32_t size); 114 static void PkgWriteData(pkg_stream_t *pkg, uint32_t offset, void *data, uint32_t size); 115 static void PkgWriteU32(pkg_stream_t *pkg, uint32_t offset, uint32_t v); 116 static void PgkWriteVarData(pkg_stream_t *pkg, uint32_t offset, newtRefVar frame, newtRefVar sym); 117 static newtRef PkgWriteFrame(pkg_stream_t *pkg, newtRefArg frame); 118 static newtRef PkgWriteArray(pkg_stream_t *pkg, newtRefArg array); 119 static newtRef PkgWriteBinary(pkg_stream_t *pkg, newtRefArg obj); 103 120 static newtRef PkgWriteObject(pkg_stream_t *pkg, newtRefArg obj); 104 121 static void PkgWritePart(pkg_stream_t *pkg, newtRefArg part); 122 123 static uint32_t PkgReadU32(uint8_t *d) ; 105 124 static newtRef PkgPartGetInstance(pkg_stream_t *pkg, uint32_t p_obj); 106 125 static void PkgPartSetInstance(pkg_stream_t *pkg, uint32_t p_obj, newtRefArg r); 107 108 static uint32_t PkgReadU32(uint8_t *d);109 126 static newtRef PkgReadRef(pkg_stream_t *pkg, uint32_t p_obj); 110 127 static newtRef PkgReadBinaryObject(pkg_stream_t *pkg, uint32_t p_obj); … … 112 129 static newtRef PkgReadFrameObject(pkg_stream_t *pkg, uint32_t p_obj); 113 130 static newtRef PkgReadObject(pkg_stream_t *pkg, uint32_t p_obj); 131 static newtRef PkgReadNOSPart(pkg_stream_t *pkg); 114 132 static newtRef PkgReadPart(pkg_stream_t *pkg, int32_t index); 133 static newtRef PkgReadVardataBinary(pkg_stream_t *pkg, pkg_info_ref_t *info_ref); 115 134 static newtRef PkgReadVardataString(pkg_stream_t *pkg, pkg_info_ref_t *info_ref); 116 static newtRef PkgReadVardataBinary(pkg_stream_t *pkg, pkg_info_ref_t *info_ref);117 135 static newtRef PkgReadHeader(pkg_stream_t *pkg); 118 136 137 138 /*------------------------------------------------------------------------*/ 119 139 /** Duplicate of same function in NSOF. 120 * Maybe we could make the original file publicly accessible 140 * Maybe we should make the original file publicly accessible 141 * 142 * @see NewtSearchArray(newtRefArg array, newtRefArg r) 121 143 */ 122 144 int32_t PkgArraySearch(newtRefArg array, newtRefArg r) … … 151 173 int32_t ix = PkgArraySearch(pkg->precedents, ref); 152 174 if (ix>=0) { 153 printf("*** Multiple: ");154 NewtPrintObject(stdout, ref);155 175 return NewtGetArraySlot(pkg->instances, ix); 156 176 } else { … … 169 189 { 170 190 uint32_t n = NewtArrayLength(pkg->instances); 191 // the code below gets horribly slow and fragments memory 192 // we should consider implementing a binary search tree at some point 171 193 NewtInsertArraySlot(pkg->instances, n, val); 172 194 NewtInsertArraySlot(pkg->precedents, n, ref); … … 227 249 if (pkg->data_size<new_size) { 228 250 uint32_t os = pkg->data_size; 229 uint32_t ns = (new_size+16383) & (~16383); // alocate ein 16k blocks251 uint32_t ns = (new_size+16383) & (~16383); // alocate in 16k blocks 230 252 pkg->data = realloc(pkg->data, ns); 231 253 memset(pkg->data+os, 0xbf, ns-os); // filler byte … … 442 464 PkgWriteU32(pkg, dst+8, klass_ref); 443 465 444 // add a verbose copy of the binary data 445 PkgWriteData(pkg, dst+12, data, size-12); 466 // copy the binary data over 467 if (klass==NSSYM0(int32)) { 468 uint32_t *s = (uint32_t*)data; 469 uint32_t v = htonl(*s); 470 PkgWriteData(pkg, dst+12, &v, sizeof(v)); 471 } else if (klass==NSSYM0(real)) { 472 // this code fails miserably if 'double' is not an 8-byte IEEE value! 473 double *s = (double*)data; 474 double v = htond(*s); 475 PkgWriteData(pkg, dst+12, &v, sizeof(v)); 476 } else { 477 PkgWriteData(pkg, dst+12, data, size-12); 478 } 446 479 447 480 return NewtMakePointer(dst); … … 461 494 newtRef prec; 462 495 496 // FIXME add handling named magic pointers here 463 497 if (NewtRefIsImmediate(obj)) { 464 printf("*** immediate: ");465 NewtPrintObject(stdout, obj);498 // immediates have the same form in memory as in packages 499 // immediates include magic pointers 466 500 return obj; 467 501 } … … 479 513 dst = PkgWriteBinary(pkg, obj); 480 514 } else { 481 printf("*** unsupported write: "); 482 NewtPrintObject(stdout, obj); 483 PkgMakeRoom(pkg, dst, 16); 484 PkgWriteU32(pkg, dst, 0xdeadbeef); 485 // FIXME add all possible types... 515 # ifdef DEBUG_PKG 516 // we do not know how to write this object 517 printf("*** unsupported write: "); 518 NewtPrintObject(stdout, obj); 519 # endif 520 return kNewtRefNIL; // do not create a precedent 486 521 } 487 522 … … 495 530 /** Create a part in package format based on this object. 496 531 * 532 * This function makes heavy use of the "pkg" structure, updating all 533 * members to allow writing multiple consecutive parts by repeatedly 534 * caling this function. Multiple part packages are untested. 535 * 497 536 * @param pkg [inout] the package 498 537 * @param part [in] object containing part data … … 500 539 * @retval ref to binary part data 501 540 */ 502 newtRefPkgWritePart(pkg_stream_t *pkg, newtRefArg part)541 void PkgWritePart(pkg_stream_t *pkg, newtRefArg part) 503 542 { 504 543 uint32_t dst = pkg->part_offset; 544 uint32_t hdr = pkg->part_header_offset; 505 545 int32_t ix; 506 546 newtRef data; 547 uint32_t part_size; 507 548 508 549 ix = NewtFindSlotIndex(part, NSSYM(data)); 509 550 if (ix<0) 510 return kNewtRefNIL;551 return; 511 552 data = NewtGetFrameSlot(part, ix); 512 553 … … 523 564 NewtSetLength(pkg->instances, 0); 524 565 525 return kNewtRefNIL; 526 } 527 528 /*------------------------------------------------------------------------*/ 529 /** Create a new binary object that conatins the object tree in package format 530 * 531 * @param rpkg [in] object tree describing the package 566 PkgMakeRoom(pkg, PkgAlign(pkg, pkg->size), 0); 567 part_size = pkg->size - pkg->part_offset; 568 // offset 569 PkgWriteU32(pkg, hdr, pkg->part_offset - pkg->directory_size); 570 // size 571 PkgWriteU32(pkg, hdr+4, part_size); 572 // size2 573 PkgWriteU32(pkg, hdr+8, part_size); 574 // type 575 PkgWriteU32(pkg, hdr+12, PkgGetSlotInt(part, NSSYM(type), 0x666f726d)); // "form" 576 // reserved1 577 PkgWriteU32(pkg, hdr+16, 0); 578 // flags 579 PkgWriteU32(pkg, hdr+20, PkgGetSlotInt(part, NSSYM(flags), 0)); 580 // reserved2 581 PkgWriteU32(pkg, hdr+28, 0); 582 583 pkg->part_offset += part_size; 584 } 585 586 /*------------------------------------------------------------------------*/ 587 /** Create a new binary object that contains the object tree in package format. 588 * 589 * This function creates a binary object, containing the representaion of 590 * a whole hierarchy of objects in the Newton package format. The binary 591 * data can be written directly to disk to create a Newton readable .pkg file. 592 * 593 * NewtWritePkg was tested on hierarchies created by NewtReadPackage, reading 594 * a random bunch of .pkg files containing Newton Script applications. The 595 * packages created were identiacla to the original packages. 596 * 597 * @todo NewtWritePkg does not support a relocation table yet which may 598 * be needed to save native function of a higher complexity. 599 * @todo Error handling is not yet implemented. 600 * @todo Named magic poiners are not supported yet. 601 * @todo Only NOS parts are currently supported. We still must implement 602 * Protocol parts and Raw parts. 603 * 604 * @param rpkg [in] object hierarchy describing the package 532 605 * 533 606 * @retval binary object with package … … 536 609 { 537 610 pkg_stream_t pkg; 538 int32_t num_parts, i, ix , directory_size;539 newtRef parts ;540 611 int32_t num_parts, i, ix; 612 newtRef parts, result; 613 541 614 // setup pkg_stream_t 542 615 memset(&pkg, 0, sizeof(pkg)); … … 548 621 # endif /* HAVE_LIBICONV */ 549 622 623 // find the array of parts that we will write 550 624 ix = NewtFindSlotIndex(package, NSSYM(parts)); 551 625 if (ix>=0) { … … 557 631 // sig 558 632 PkgWriteData(&pkg, 0, "package0", 8); 633 pkg.data[7] = (uint8_t)('0' + PkgGetSlotInt(package, NSSYM(pkg_version), 0)); 559 634 // type 560 PkgWrite Data(&pkg, 8, "xxxx", 4);635 PkgWriteU32(&pkg, 8, PkgGetSlotInt(package, NSSYM(type), 0x78787878)); // "xxxx" 561 636 // flags 562 637 PkgWriteU32(&pkg, 12, PkgGetSlotInt(package, NSSYM(flags), 0)); … … 568 643 PgkWriteVarData(&pkg, 24, package, NSSYM(name)); 569 644 // date 570 PkgWriteU32(&pkg, 32, 0xc2296aa5); // FIXME some fake creation date645 PkgWriteU32(&pkg, 32, time(0L)+2082844800); 571 646 // reserved2 572 647 PkgWriteU32(&pkg, 36, 0); … … 588 663 } 589 664 590 pkg.part_offset = directory_size = PkgAlign(&pkg, pkg.header_size + pkg.var_data_size);665 pkg.part_offset = pkg.directory_size = PkgAlign(&pkg, pkg.header_size + pkg.var_data_size); 591 666 // directorySize 592 PkgWriteU32(&pkg, 44, directory_size);667 PkgWriteU32(&pkg, 44, pkg.directory_size); 593 668 594 669 // create all parts 595 670 for (i=0; i<num_parts; i++) { 596 uint32_t part_size;597 uint32_t hdr = sizeof(pkg_header_t) + i*sizeof(pkg_part_t);598 671 newtRef part = NewtGetArraySlot(parts, i); 599 672 pkg.part_header_offset = sizeof(pkg_header_t) + i*sizeof(pkg_part_t); 600 673 PkgWritePart(&pkg, part); 601 PkgMakeRoom(&pkg, PkgAlign(&pkg, pkg.size), 0);602 part_size = pkg.size - pkg.part_offset;603 // offset604 PkgWriteU32(&pkg, hdr, pkg.part_offset - directory_size);605 // size & size2606 PkgWriteU32(&pkg, hdr+4, part_size);607 PkgWriteU32(&pkg, hdr+8, part_size);608 // type609 // FIXME the 'type' field is actually always a fourcc like 'form'610 // FIXME which Newt object should we use here? Binary? Int32? Symbol?611 PkgWriteU32(&pkg, hdr+12, PkgGetSlotInt(part, NSSYM(type), 0x666f726d));612 // reserved1613 PkgWriteU32(&pkg, hdr+16, 0);614 // flags615 PkgWriteU32(&pkg, hdr+20, PkgGetSlotInt(part, NSSYM(flags), 0));616 // reserved2617 PkgWriteU32(&pkg, hdr+28, 0);618 619 pkg.part_offset += part_size;620 674 } 621 675 } … … 625 679 PkgWriteU32(&pkg, 28, pkg.size); 626 680 627 // convert pkg_stream_t into binary package 628 // return new object 629 630 { FILE *f = fopen("d:/home/matt/dev/Newton/ntk2/helloWRT.pkg", "wb"); 631 fwrite(pkg.data, 1, pkg.size, f); 632 fclose(f); 633 } 681 result = NewtMakeBinary(NSSYM(package), pkg.data, pkg.size, false); 682 683 // clean up our allocations 684 if (pkg.data) 685 free(pkg.data); 634 686 635 687 # ifdef HAVE_LIBICONV … … 637 689 # endif /* HAVE_LIBICONV */ 638 690 639 return kNewtRefNIL;691 return result; 640 692 } 641 693 … … 700 752 break; 701 753 case 2: // special 702 if (ref==kNewtRefTRUE) result = kNewtRefTRUE; 703 else if (ref==kNewtRefNIL) result = kNewtRefNIL; 704 else if (ref&0x0f==0x0a) result = NewtMakeCharacter(ref>>4); 705 else if (ref==kNewtSymbolClass) result = kNewtSymbolClass; 706 else { 707 # ifdef DEBUG_PKG 708 printf("*** PkgReader: PkgReadRef - unknown ref 0x%08x\n", ref); 709 # endif 710 result = ref; 711 } 754 // special refs are immedites, encoded in the same format in 755 // memory as in package files (at least for all instances I could find) 756 result = ref; 712 757 break; 713 758 case 3: // magic pointer 714 # ifdef __NAMED_MAGIC_POINTER__ 715 result = kNewtRefNIL; // not implemented 716 # else 717 result = ref; // already a correct magic pointer 718 # endif 759 // FIXME we must implement special code for name magic pointers here! 760 result = ref; // already a correct magic pointer 719 761 break; 720 762 } … … 748 790 char *buf = NewtIconv(pkg->from_utf16, src, sze, &buflen); 749 791 if (buf) { 750 result = NewtMakeString2(buf, buflen-1, false); // NewtMakeString2 appends another null792 result = NewtMakeString2(buf, buflen-1, true); // NewtMakeString2 appends another null 751 793 } 752 794 # endif /* HAVE_LIBICONV */ 753 795 if (result==kNewtRefNIL) 754 result = NewtMakeString2(src, sze, false);796 result = NewtMakeString2(src, sze, true); 755 797 } else if (klass==NSSYM0(int32)) { 756 798 uint32_t v = PkgReadU32(pkg->data + p_obj + 12); … … 760 802 result = NewtMakeReal(ntohd(*v)); 761 803 } else if (klass==NSSYM0(instructions)) { 762 result = NewtMakeBinary(klass, pkg->data + p_obj + 12, size-12, false);804 result = NewtMakeBinary(klass, pkg->data + p_obj + 12, size-12, true); 763 805 # ifdef DEBUG_PKG_DIS 764 806 printf("*** PkgReader: PkgReadBinaryObject - dumping byte code\n"); … … 766 808 # endif 767 809 } else { 768 // bits: the bits in the icon769 // mask: the transparency mask for the icon770 810 # ifdef DEBUG_PKG 811 // This output is helpful to find more binary classes that may need 812 // endianness fixes like the floating point class 771 813 if (klass) { 772 814 printf("*** PkgReader: PkgReadBinaryObject - unknown class "); … … 774 816 } 775 817 # endif 776 result = NewtMakeBinary(klass, pkg->data + p_obj + 12, size-12, false);818 result = NewtMakeBinary(klass, pkg->data + p_obj + 12, size-12, true); 777 819 } 778 820 … … 891 933 newtRefVar result; 892 934 893 // verify that we have a correct header935 // verify that we have a correct lead-in 894 936 if (PkgReadU32(pkg->part)!=0x00001041 || PkgReadU32(pkg->part+8)!=0x00000002) { 895 937 # ifdef DEBUG_PKG … … 900 942 } 901 943 902 // create an array that holds a ref to all creted objects, avoiding double instantiation 903 if (pkg->instances) 904 NewtSetLength(pkg->instances, ntohl(pkg->part_header->size)/4); 905 else 906 pkg->instances = NewtMakeArray(kNewtRefUnbind, ntohl(pkg->part_header->size)/4); 944 // create an array that holds a ref to all created objects, avoiding double instantiation 945 pkg->instances = NewtMakeArray(kNewtRefUnbind, ntohl(pkg->part_header->size)/4); 907 946 908 947 // now recursively load all objects … … 944 983 945 984 NcSetSlot(frame, NSSYM(flags), NewtMakeInt32(flags)); 946 NcSetSlot(frame, NSSYM(type), NewtMakeBinary(kNewtRefUnbind, 947 (uint8_t*)&pkg->part_header->type, 4, true)); 985 NcSetSlot(frame, NSSYM(type), NewtMakeInt32(ntohl(pkg->part_header->type))); 948 986 949 987 switch (flags&0x03) { … … 1001 1039 char *buf = NewtIconv(pkg->from_utf16, src, size, &buflen); 1002 1040 if (buf) { 1003 return NewtMakeString2(buf, buflen-1, false);1041 return NewtMakeString2(buf, buflen-1, true); 1004 1042 } 1005 1043 # endif /* HAVE_LIBICONV */ 1006 return NewtMakeString2(src, size, false);1044 return NewtMakeString2(src, size, true); 1007 1045 } 1008 1046 } … … 1019 1057 newtRefVar fnv[] = { 1020 1058 NS_CLASS, NSSYM(PackageHeader), 1059 NSSYM(type), kNewtRefNIL, 1060 NSSYM(pkg_version), kNewtRefNIL, 1021 1061 NSSYM(version), kNewtRefNIL, 1022 1062 NSSYM(copyright), kNewtRefNIL, … … 1028 1068 newtRefVar parts; 1029 1069 1030 NcSetSlot(frame, NSSYM(flags), NewtMakeInt32(ntohl(pkg->header->flags))); 1070 NcSetSlot(frame, NSSYM(type), NewtMakeInt32(ntohl(pkg->header->type))); 1071 NcSetSlot(frame, NSSYM(pkg_version), NewtMakeInteger(pkg->pkg_version)); 1031 1072 NcSetSlot(frame, NSSYM(version), NewtMakeInt32(ntohl(pkg->header->version))); 1032 1073 NcSetSlot(frame, NSSYM(copyright), PkgReadVardataString(pkg, &pkg->header->copyright)); 1033 1074 NcSetSlot(frame, NSSYM(name), PkgReadVardataString(pkg, &pkg->header->name)); 1034 // all other header values can be derived form the archive itself 1035 // or can be calculated at creation time 1075 NcSetSlot(frame, NSSYM(flags), NewtMakeInt32(ntohl(pkg->header->flags))); 1036 1076 1037 1077 parts = NewtMakeArray(kNewtRefNIL, pkg->num_parts); … … 1055 1095 /** Read a Package and create an array of parts 1056 1096 * 1097 * This function creates a hierarchy of Newt objects from a block of data 1098 * interpreted as Package data. Usually this data would be a verbatim 1099 * copy of a .pkg file. 1100 * 1101 * NewtReadPkg was tested on a random bunch of .pkg files containing Newton 1102 * Script applications. 1103 * 1104 * The iconv library is required at compile-time to read Newton-compatible 1105 * packages. 1106 * 1107 * @todo NewtReadPkg does not support a relocation table yet which may 1108 * be needed to load native function of a higher complexity. 1109 * @todo Error handling is not yet implemented. 1110 * @todo Named magic poiners are not supported yet. 1111 * @todo Only NOS parts are currently supported. We still must implement 1112 * Protocol parts and Raw parts. 1113 * @todo A function should be added that creates a working default 1114 * Package hierarchy. 1115 * 1057 1116 * @param data [in] Package data memory, can be read-only 1058 1117 * @param size [in] size of memory array 1059 1118 * 1060 * @retval Newt array containing all parts of the Package 1061 * 1062 * @todo There is no support for relocation data yet. 1119 * @retval Newt array containing some descriptions and all parts of the Package 1063 1120 */ 1064 1121 newtRef NewtReadPkg(uint8_t * data, size_t size) … … 1074 1131 1075 1132 memset(&pkg, 0, sizeof(pkg)); 1076 pkg. verno= data[7]-'0';1133 pkg.pkg_version = data[7]-'0'; 1077 1134 pkg.data = data; 1078 1135 pkg.size = size;
