| | 119 | /** Duplicate of same function in NSOF. |
| | 120 | * Maybe we could make the original file publicly accessible |
| | 121 | */ |
| | 122 | int32_t PkgArraySearch(newtRefArg array, newtRefArg r) |
| | 123 | { |
| | 124 | newtRef * slots; |
| | 125 | uint32_t len; |
| | 126 | uint32_t i; |
| | 127 | |
| | 128 | len = NewtArrayLength(array); |
| | 129 | slots = NewtRefToSlots(array); |
| | 130 | |
| | 131 | for (i = 0; i < len; i++) |
| | 132 | { |
| | 133 | if (slots[i] == r) |
| | 134 | return i; |
| | 135 | } |
| | 136 | |
| | 137 | return -1; |
| | 138 | } |
| | 139 | |
| | 140 | /*------------------------------------------------------------------------*/ |
| | 141 | /** Verify if the give reference was already written to the package. |
| | 142 | * |
| | 143 | * @param pkg [inout] the package |
| | 144 | * @param ref [in] the reference that we try to find |
| | 145 | * |
| | 146 | * @retval ref to the previously written object |
| | 147 | * @retval or kNewtRefUnbind if the object still needs to be written |
| | 148 | */ |
| | 149 | newtRef PkgPartGetPrecedent(pkg_stream_t *pkg, newtRefArg ref) |
| | 150 | { |
| | 151 | int32_t ix = PkgArraySearch(pkg->precedents, ref); |
| | 152 | if (ix>=0) { |
| | 153 | printf("*** Multiple: "); |
| | 154 | NewtPrintObject(stdout, ref); |
| | 155 | return NewtGetArraySlot(pkg->instances, ix); |
| | 156 | } else { |
| | 157 | return kNewtRefUnbind; |
| | 158 | } |
| | 159 | } |
| | 160 | |
| | 161 | /*------------------------------------------------------------------------*/ |
| | 162 | /** Remember that a specific reference was already written. |
| | 163 | * |
| | 164 | * @param pkg [inout] the package |
| | 165 | * @param ref [in] the original reference in memory |
| | 166 | * @param val [in] the reference needed to find this object in the package |
| | 167 | */ |
| | 168 | void PkgPartSetPrecedent(pkg_stream_t *pkg, newtRefArg ref, newtRefArg val) |
| | 169 | { |
| | 170 | uint32_t n = NewtArrayLength(pkg->instances); |
| | 171 | NewtInsertArraySlot(pkg->instances, n, val); |
| | 172 | NewtInsertArraySlot(pkg->precedents, n, ref); |
| | 173 | } |
| | 174 | |
| | 175 | /*------------------------------------------------------------------------*/ |
| | 176 | /** Align the given value to 8 or 4 bytes. |
| | 177 | * |
| | 178 | * @param pkg [inout] the package |
| | 179 | * @param offset [in] offset to be aligned |
| | 180 | * |
| | 181 | * @retval new offset aligned to 8 bytes, or 4 bytes for the advance format |
| | 182 | * |
| | 183 | * @todo We shoudld add 4-byte alignment support at some point, so the |
| | 184 | * generated package is a bit smaller |
| | 185 | */ |
| | 186 | uint32_t PkgAlign(pkg_stream_t *pkg, uint32_t offset) |
| | 187 | { |
| | 188 | return (offset+7)&(~7); |
| | 189 | } |
| | 190 | |
| | 191 | /*------------------------------------------------------------------------*/ |
| | 192 | /** Convenience function to get the integer value of a slot. |
| | 193 | * |
| | 194 | * @param frame [in] find the slot in this frame |
| | 195 | * @param name [in] name of slot |
| | 196 | * @param def [in] default value if slot was not found |
| | 197 | * |
| | 198 | * @retval value read if found, or default value if not found |
| | 199 | */ |
| | 200 | uint32_t PkgGetSlotInt(newtRefArg frame, newtRefArg name, uint32_t def) |
| | 201 | { |
| | 202 | newtRef slot; |
| | 203 | int32_t ix; |
| | 204 | |
| | 205 | ix = NewtFindSlotIndex(frame, name); |
| | 206 | if (ix<0) |
| | 207 | return def; |
| | 208 | slot = NewtGetArraySlot(frame, ix); |
| | 209 | if (NewtRefIsInteger(slot)) { |
| | 210 | return NewtRefToInteger(slot); |
| | 211 | } else { |
| | 212 | return def; |
| | 213 | } |
| | 214 | } |
| | 215 | |
| | 216 | /*------------------------------------------------------------------------*/ |
| | 217 | /** Make some room for more data in the package |
| | 218 | * |
| | 219 | * @param pkg [inout] the package |
| | 220 | * @param offset [in] offset where we will need room |
| | 221 | * @param size [in] number of bytes that we will need |
| | 222 | */ |
| | 223 | void PkgMakeRoom(pkg_stream_t *pkg, uint32_t offset, uint32_t size) |
| | 224 | { |
| | 225 | uint32_t new_size = offset+size; |
| | 226 | |
| | 227 | if (pkg->data_size<new_size) { |
| | 228 | uint32_t os = pkg->data_size; |
| | 229 | uint32_t ns = (new_size+16383) & (~16383); // alocate ein 16k blocks |
| | 230 | pkg->data = realloc(pkg->data, ns); |
| | 231 | memset(pkg->data+os, 0xbf, ns-os); // filler byte |
| | 232 | pkg->data_size = ns; |
| | 233 | } |
| | 234 | |
| | 235 | if (pkg->size<new_size) |
| | 236 | pkg->size = new_size; |
| | 237 | } |
| | 238 | |
| | 239 | /*------------------------------------------------------------------------*/ |
| | 240 | /** Write arbitrary data into the package at any position |
| | 241 | * |
| | 242 | * @param pkg [inout] the package |
| | 243 | * @param offset [in] offset to the beginning of data |
| | 244 | * @param data [in] data to be copied to package |
| | 245 | * @param size [in] size of data block |
| | 246 | */ |
| | 247 | void PkgWriteData(pkg_stream_t *pkg, uint32_t offset, void *data, uint32_t size) |
| | 248 | { |
| | 249 | if (pkg->data_size<offset+size) |
| | 250 | PkgMakeRoom(pkg, offset, size); |
| | 251 | if (pkg->size<offset+size) |
| | 252 | pkg->size = offset+size; |
| | 253 | memcpy(pkg->data+offset, data, size); |
| | 254 | } |
| | 255 | |
| | 256 | /*------------------------------------------------------------------------*/ |
| | 257 | /** Write a 32 bit integer into the package at any position |
| | 258 | * |
| | 259 | * @param pkg [inout] the package |
| | 260 | * @param offset [in] offset to the beginning of data |
| | 261 | * @param v [in] value to be written |
| | 262 | */ |
| | 263 | void PkgWriteU32(pkg_stream_t *pkg, uint32_t offset, uint32_t v) |
| | 264 | { |
| | 265 | v = htonl(v); |
| | 266 | PkgWriteData(pkg, offset, &v, 4); |
| | 267 | } |
| | 268 | |
| | 269 | /*------------------------------------------------------------------------*/ |
| | 270 | /** Write the data in the object into the vardata section and generate the info ref |
| | 271 | * |
| | 272 | * @param pkg [inout] the package |
| | 273 | * @param offset [in] whgere to write the info ref |
| | 274 | * @param frame [in] frame containing the data |
| | 275 | * @param sym [in] symbol of slot containing the data |
| | 276 | */ |
| | 277 | void PgkWriteVarData(pkg_stream_t *pkg, uint32_t offset, newtRefVar frame, newtRefVar sym) |
| | 278 | { |
| | 279 | newtRef info; |
| | 280 | uint32_t ix; |
| | 281 | |
| | 282 | PkgWriteU32(pkg, offset, 0); |
| | 283 | |
| | 284 | ix = NewtFindSlotIndex(frame, sym); |
| | 285 | if (ix<0) |
| | 286 | return; |
| | 287 | info = NewtGetFrameSlot(frame, ix); |
| | 288 | if (NewtRefIsBinary(info)) { |
| | 289 | uint32_t size = NewtBinaryLength(info); |
| | 290 | uint8_t *data = NewtRefToBinary(info); |
| | 291 | pkg_info_ref_t info_ref; |
| | 292 | |
| | 293 | # ifdef HAVE_LIBICONV |
| | 294 | if (NewtRefIsString(info)) { |
| | 295 | size_t buflen; |
| | 296 | char *buf = NewtIconv(pkg->to_utf16, data, size, &buflen); |
| | 297 | if (buf) { |
| | 298 | size = buflen; |
| | 299 | data = buf; |
| | 300 | } |
| | 301 | } |
| | 302 | # endif /* HAVE_LIBICONV */ |
| | 303 | |
| | 304 | info_ref.offset = htons(pkg->var_data_size); |
| | 305 | info_ref.size = htons(size); |
| | 306 | |
| | 307 | PkgWriteData(pkg, pkg->header_size + pkg->var_data_size, data, size); |
| | 308 | PkgWriteData(pkg, offset, &info_ref, 4); |
| | 309 | |
| | 310 | pkg->var_data_size += size; |
| | 311 | } |
| | 312 | } |
| | 313 | |
| | 314 | /*------------------------------------------------------------------------*/ |
| | 315 | /** Append a frame object to the end of the Package |
| | 316 | * |
| | 317 | * @param pkg [inout] the package |
| | 318 | * @param frame [in] the frame that we will write |
| | 319 | * |
| | 320 | * @retval offset to the beginning of the object in the package file |
| | 321 | */ |
| | 322 | newtRef PkgWriteFrame(pkg_stream_t *pkg, newtRefArg frame) |
| | 323 | { |
| | 324 | uint32_t dst, size, i, n; |
| | 325 | newtRef map, map_pos; |
| | 326 | newtRef slot, slot_pos; |
| | 327 | |
| | 328 | // calculate the size of this chunk |
| | 329 | dst = PkgAlign(pkg, pkg->size); |
| | 330 | n = NewtFrameLength(frame); |
| | 331 | size = (n+3)*4; |
| | 332 | |
| | 333 | // make room for the entire chunk and write the header |
| | 334 | PkgMakeRoom(pkg, dst, size); |
| | 335 | PkgWriteU32(pkg, dst, (size<<8) | 0x40 | kObjSlotted | kObjFrame); |
| | 336 | PkgWriteU32(pkg, dst+4, 0); |
| | 337 | |
| | 338 | // recursively add all arrays making up the map |
| | 339 | map = NewtFrameMap(frame); |
| | 340 | map_pos = PkgWriteObject(pkg, map); |
| | 341 | PkgWriteU32(pkg, dst+8, map_pos); |
| | 342 | |
| | 343 | // now add all slots and fill in the rest of our chunk |
| | 344 | for (i=0; i<n; i++) { |
| | 345 | slot = NewtGetFrameSlot(frame, i); |
| | 346 | slot_pos = PkgWriteObject(pkg, slot); |
| | 347 | PkgWriteU32(pkg, dst+12+4*i, slot_pos); |
| | 348 | } |
| | 349 | |
| | 350 | return NewtMakePointer(dst); |
| | 351 | } |
| | 352 | |
| | 353 | /*------------------------------------------------------------------------*/ |
| | 354 | /** Append an array object to the end of the Package |
| | 355 | * |
| | 356 | * @param pkg [inout] the package |
| | 357 | * @param array [in] the array that we will write |
| | 358 | * |
| | 359 | * @retval offset to the beginning of the object in the package file |
| | 360 | */ |
| | 361 | newtRef PkgWriteArray(pkg_stream_t *pkg, newtRefArg array) |
| | 362 | { |
| | 363 | uint32_t dst, size, i, n; |
| | 364 | newtRef klass, klass_pos; |
| | 365 | newtRef slot, slot_pos; |
| | 366 | |
| | 367 | // calculate the size of this chunk |
| | 368 | dst = PkgAlign(pkg, pkg->size); |
| | 369 | n = NewtArrayLength(array); |
| | 370 | size = (n+3)*4; |
| | 371 | |
| | 372 | // make room for the entire chunk and write the header |
| | 373 | PkgMakeRoom(pkg, dst, size); |
| | 374 | PkgWriteU32(pkg, dst, (size<<8) | 0x40 | kObjSlotted); |
| | 375 | PkgWriteU32(pkg, dst+4, 0); |
| | 376 | |
| | 377 | // add the class information |
| | 378 | klass = NcClassOf(array); |
| | 379 | klass_pos = PkgWriteObject(pkg, klass); |
| | 380 | PkgWriteU32(pkg, dst+8, klass_pos); |
| | 381 | |
| | 382 | // now add all slots and fill in the rest of our chunk |
| | 383 | for (i=0; i<n; i++) { |
| | 384 | slot = NewtGetArraySlot(array, i); |
| | 385 | slot_pos = PkgWriteObject(pkg, slot); |
| | 386 | PkgWriteU32(pkg, dst+12+4*i, slot_pos); |
| | 387 | } |
| | 388 | |
| | 389 | return NewtMakePointer(dst); |
| | 390 | } |
| | 391 | |
| | 392 | /*------------------------------------------------------------------------*/ |
| | 393 | /** Append a binary object to the end of the Package |
| | 394 | * |
| | 395 | * @param pkg [inout] the package |
| | 396 | * @param obj [in] the binary object that we will write |
| | 397 | * |
| | 398 | * @retval offset to the beginning of the object in the package file |
| | 399 | */ |
| | 400 | newtRef PkgWriteBinary(pkg_stream_t *pkg, newtRefArg obj) |
| | 401 | { |
| | 402 | uint32_t dst, size; |
| | 403 | uint8_t *data; |
| | 404 | newtRef klass, klass_ref = kNewtRefUnbind; |
| | 405 | |
| | 406 | // calculate the size of this chunk |
| | 407 | dst = PkgAlign(pkg, pkg->size); |
| | 408 | size = NewtBinaryLength(obj); |
| | 409 | data = NewtRefToBinary(obj); |
| | 410 | |
| | 411 | // make room for the binary chunk and write the header |
| | 412 | if (NewtRefIsSymbol(obj)) { |
| | 413 | size = NewtSymbolLength(obj)+5; // remember the trailing zero! |
| | 414 | } else if (NewtRefIsString(obj)) { |
| | 415 | # ifdef HAVE_LIBICONV |
| | 416 | size_t buflen; |
| | 417 | char *buf = NewtIconv(pkg->to_utf16, data, size, &buflen); |
| | 418 | if (buf) { |
| | 419 | size = buflen; |
| | 420 | data = buf; |
| | 421 | } |
| | 422 | # endif /* HAVE_LIBICONV */ |
| | 423 | } |
| | 424 | size += 12; |
| | 425 | |
| | 426 | // make room for the binary chunk and write the header |
| | 427 | PkgMakeRoom(pkg, dst, size); |
| | 428 | PkgWriteU32(pkg, dst, (size<<8) | 0x40); |
| | 429 | PkgWriteU32(pkg, dst+4, 0); |
| | 430 | |
| | 431 | // symbols have special handling to avoid recursion |
| | 432 | if (NewtRefIsSymbol(obj)) { |
| | 433 | PkgWriteU32(pkg, dst+8, kNewtSymbolClass); |
| | 434 | PkgWriteU32(pkg, dst+12, NewtRefToHash(obj)); // make sure the hash has the right endianness |
| | 435 | PkgWriteData(pkg, dst+16, (uint8_t*)NewtSymbolGetName(obj), size-16); |
| | 436 | return NewtMakePointer(dst); |
| | 437 | } |
| | 438 | |
| | 439 | // add the class information |
| | 440 | klass = NcClassOf(obj); |
| | 441 | klass_ref = PkgWriteObject(pkg, klass); |
| | 442 | PkgWriteU32(pkg, dst+8, klass_ref); |
| | 443 | |
| | 444 | // add a verbose copy of the binary data |
| | 445 | PkgWriteData(pkg, dst+12, data, size-12); |
| | 446 | |
| | 447 | return NewtMakePointer(dst); |
| | 448 | } |
| | 449 | |
| | 450 | /*------------------------------------------------------------------------*/ |
| | 451 | /** Append the object to the end of the Package |
| | 452 | * |
| | 453 | * @param pkg [inout] the package |
| | 454 | * @param obj [in] the object that we will write |
| | 455 | * |
| | 456 | * @retval offset to the beginning of the object in the package file |
| | 457 | */ |
| | 458 | newtRef PkgWriteObject(pkg_stream_t *pkg, newtRefArg obj) |
| | 459 | { |
| | 460 | uint32_t dst = pkg->size; |
| | 461 | newtRef prec; |
| | 462 | |
| | 463 | if (NewtRefIsImmediate(obj)) { |
| | 464 | printf("*** immediate: "); |
| | 465 | NewtPrintObject(stdout, obj); |
| | 466 | return obj; |
| | 467 | } |
| | 468 | |
| | 469 | prec = PkgPartGetPrecedent(pkg, obj); |
| | 470 | if (prec!=kNewtRefUnbind) { |
| | 471 | return prec; |
| | 472 | } |
| | 473 | |
| | 474 | if (NewtRefIsFrame(obj)) { |
| | 475 | dst = PkgWriteFrame(pkg, obj); |
| | 476 | } else if (NewtRefIsArray(obj)) { |
| | 477 | dst = PkgWriteArray(pkg, obj); |
| | 478 | } else if (NewtRefIsBinary(obj)) { |
| | 479 | dst = PkgWriteBinary(pkg, obj); |
| | 480 | } 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... |
| | 486 | } |
| | 487 | |
| | 488 | // make this ref available for later incarnations of the same object |
| | 489 | PkgPartSetPrecedent(pkg, obj, dst); |
| | 490 | |
| | 491 | return dst; |
| | 492 | } |
| | 493 | |
| | 494 | /*------------------------------------------------------------------------*/ |
| | 495 | /** Create a part in package format based on this object. |
| | 496 | * |
| | 497 | * @param pkg [inout] the package |
| | 498 | * @param part [in] object containing part data |
| | 499 | * |
| | 500 | * @retval ref to binary part data |
| | 501 | */ |
| | 502 | newtRef PkgWritePart(pkg_stream_t *pkg, newtRefArg part) |
| | 503 | { |
| | 504 | uint32_t dst = pkg->part_offset; |
| | 505 | int32_t ix; |
| | 506 | newtRef data; |
| | 507 | |
| | 508 | ix = NewtFindSlotIndex(part, NSSYM(data)); |
| | 509 | if (ix<0) |
| | 510 | return kNewtRefNIL; |
| | 511 | data = NewtGetFrameSlot(part, ix); |
| | 512 | |
| | 513 | pkg->instances = NewtMakeArray(kNewtRefUnbind, 0); |
| | 514 | pkg->precedents = NewtMakeArray(kNewtRefUnbind, 0); |
| | 515 | |
| | 516 | PkgMakeRoom(pkg, dst, 16); |
| | 517 | PkgWriteU32(pkg, dst, 0x00001041); |
| | 518 | PkgWriteU32(pkg, dst+4, 0x00000000); |
| | 519 | PkgWriteU32(pkg, dst+8, 0x00000002); |
| | 520 | PkgWriteU32(pkg, dst+12, PkgWriteObject(pkg, data)); |
| | 521 | |
| | 522 | NewtSetLength(pkg->precedents, 0); |
| | 523 | NewtSetLength(pkg->instances, 0); |
| | 524 | |
| | 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 |
| | 532 | * |
| | 533 | * @retval binary object with package |
| | 534 | */ |
| | 535 | newtRef NewtWritePkg(newtRefArg package) |
| | 536 | { |
| | 537 | pkg_stream_t pkg; |
| | 538 | int32_t num_parts, i, ix, directory_size; |
| | 539 | newtRef parts; |
| | 540 | |
| | 541 | // setup pkg_stream_t |
| | 542 | memset(&pkg, 0, sizeof(pkg)); |
| | 543 | |
| | 544 | # ifdef HAVE_LIBICONV |
| | 545 | { char *encoding = NewtDefaultEncoding(); |
| | 546 | pkg.to_utf16 = iconv_open("UTF-16BE", encoding); |
| | 547 | } |
| | 548 | # endif /* HAVE_LIBICONV */ |
| | 549 | |
| | 550 | ix = NewtFindSlotIndex(package, NSSYM(parts)); |
| | 551 | if (ix>=0) { |
| | 552 | parts = NewtGetFrameSlot(package, ix); |
| | 553 | num_parts = NewtFrameLength(parts); |
| | 554 | pkg.header_size = sizeof(pkg_header_t) + num_parts * sizeof(pkg_part_t); |
| | 555 | |
| | 556 | // start setting up the header with whatever we know |
| | 557 | // sig |
| | 558 | PkgWriteData(&pkg, 0, "package0", 8); |
| | 559 | // type |
| | 560 | PkgWriteData(&pkg, 8, "xxxx", 4); |
| | 561 | // flags |
| | 562 | PkgWriteU32(&pkg, 12, PkgGetSlotInt(package, NSSYM(flags), 0)); |
| | 563 | // version |
| | 564 | PkgWriteU32(&pkg, 16, PkgGetSlotInt(package, NSSYM(version), 0)); |
| | 565 | // copyright |
| | 566 | PgkWriteVarData(&pkg, 20, package, NSSYM(copyright)); |
| | 567 | // name |
| | 568 | PgkWriteVarData(&pkg, 24, package, NSSYM(name)); |
| | 569 | // date |
| | 570 | PkgWriteU32(&pkg, 32, 0xc2296aa5); // FIXME some fake creation date |
| | 571 | // reserved2 |
| | 572 | PkgWriteU32(&pkg, 36, 0); |
| | 573 | // reserved3 |
| | 574 | PkgWriteU32(&pkg, 40, 0); |
| | 575 | // numParts |
| | 576 | PkgWriteU32(&pkg, 48, num_parts); |
| | 577 | |
| | 578 | // calculate the size of the header so we can correctly set our refs in the parts |
| | 579 | for (i=0; i<num_parts; i++) { |
| | 580 | newtRef part = NewtGetArraySlot(parts, i); |
| | 581 | PgkWriteVarData(&pkg, sizeof(pkg_header_t) + i*sizeof(pkg_part_t) + 24, part, NSSYM(info)); |
| | 582 | } |
| | 583 | |
| | 584 | // the original file has this (c) message embedded |
| | 585 | { char msg[] = "Newton� ToolKit Package � 1992-1997, Apple Computer, Inc."; |
| | 586 | PkgWriteData(&pkg, pkg.header_size + pkg.var_data_size, msg, sizeof(msg)); |
| | 587 | pkg.var_data_size += sizeof(msg); |
| | 588 | } |
| | 589 | |
| | 590 | pkg.part_offset = directory_size = PkgAlign(&pkg, pkg.header_size + pkg.var_data_size); |
| | 591 | // directorySize |
| | 592 | PkgWriteU32(&pkg, 44, directory_size); |
| | 593 | |
| | 594 | // create all parts |
| | 595 | 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 | newtRef part = NewtGetArraySlot(parts, i); |
| | 599 | |
| | 600 | PkgWritePart(&pkg, part); |
| | 601 | PkgMakeRoom(&pkg, PkgAlign(&pkg, pkg.size), 0); |
| | 602 | part_size = pkg.size - pkg.part_offset; |
| | 603 | // offset |
| | 604 | PkgWriteU32(&pkg, hdr, pkg.part_offset - directory_size); |
| | 605 | // size & size2 |
| | 606 | PkgWriteU32(&pkg, hdr+4, part_size); |
| | 607 | PkgWriteU32(&pkg, hdr+8, part_size); |
| | 608 | // type |
| | 609 | // 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 | // reserved1 |
| | 613 | PkgWriteU32(&pkg, hdr+16, 0); |
| | 614 | // flags |
| | 615 | PkgWriteU32(&pkg, hdr+20, PkgGetSlotInt(part, NSSYM(flags), 0)); |
| | 616 | // reserved2 |
| | 617 | PkgWriteU32(&pkg, hdr+28, 0); |
| | 618 | |
| | 619 | pkg.part_offset += part_size; |
| | 620 | } |
| | 621 | } |
| | 622 | |
| | 623 | // finish filling in the header |
| | 624 | // size |
| | 625 | PkgWriteU32(&pkg, 28, pkg.size); |
| | 626 | |
| | 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 | } |
| | 634 | |
| | 635 | # ifdef HAVE_LIBICONV |
| | 636 | iconv_close(pkg.to_utf16); |
| | 637 | # endif /* HAVE_LIBICONV */ |
| | 638 | |
| | 639 | return kNewtRefNIL; |
| | 640 | } |