ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/arch.C
(Generate patch)

Comparing deliantra/server/common/arch.C (file contents):
Revision 1.13 by pippijn, Thu Sep 7 09:37:11 2006 UTC vs.
Revision 1.20 by root, Thu Sep 14 21:16:11 2006 UTC

1/*
2 * static char *rcsid_arch_c =
3 * "$Id: arch.C,v 1.13 2006/09/07 09:37:11 pippijn Exp $";
4 */
5
6/* 1/*
7 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
8 3
9 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
36#include <loader.h> 31#include <loader.h>
37 32
38/* IF set, does a little timing on the archetype load. */ 33/* IF set, does a little timing on the archetype load. */
39#define TIME_ARCH_LOAD 0 34#define TIME_ARCH_LOAD 0
40 35
41static void add_arch (archetype * at); 36static void add_arch (archetype *at);
42 37
43static archetype *arch_table[ARCHTABLE]; 38static archetype *arch_table[ARCHTABLE];
44int arch_cmp = 0; /* How many strcmp's */ 39int arch_cmp = 0; /* How many strcmp's */
45int arch_search = 0; /* How many searches */ 40int arch_search = 0; /* How many searches */
46int arch_init; /* True if doing arch initialization */ 41int arch_init; /* True if doing arch initialization */
53 * MSW 2003-04-29 48 * MSW 2003-04-29
54 */ 49 */
55 50
56#if USE_UNORDERED_MAP 51#if USE_UNORDERED_MAP
57// the hashtable 52// the hashtable
58typedef std::tr1::unordered_map<size_t, archetype *> HT; 53typedef std::tr1::unordered_map
54 <
55 std::size_t,
56 archetype *,
57 std::hash<size_t>,
58 std::equal_to<size_t>,
59 slice_allocator< std::pair<const std::size_t, archetype *> >
60 true,
61 > HT;
59 62
60static HT ht; 63static HT ht;
61#endif 64#endif
62 65
63/** 66/**
165 * but it otherwise had a big memory leak. 168 * but it otherwise had a big memory leak.
166 */ 169 */
167object * 170object *
168get_archetype_by_object_name (const char *name) 171get_archetype_by_object_name (const char *name)
169{ 172{
170 archetype * 173 archetype *at;
171 at;
172 char
173 tmpname[MAX_BUF]; 174 char tmpname[MAX_BUF];
174 int 175 int i;
175 i;
176 176
177 strncpy (tmpname, name, MAX_BUF - 1); 177 assign (tmpname, name);
178 tmpname[MAX_BUF - 1] = 0; 178
179 for (i = strlen (tmpname); i > 0; i--) 179 for (i = strlen (tmpname); i > 0; i--)
180 { 180 {
181 tmpname[i] = 0; 181 tmpname[i] = 0;
182 at = find_archetype_by_object_name (tmpname); 182 at = find_archetype_by_object_name (tmpname);
183
183 if (at != NULL) 184 if (at != NULL)
184 {
185 return arch_to_object (at); 185 return arch_to_object (at);
186 }
187 } 186 }
187
188 return create_singularity (name); 188 return create_singularity (name);
189} 189}
190 190
191 /* This is a subset of the parse_id command. Basically, name can be 191 /* This is a subset of the parse_id command. Basically, name can be
192 * a string seperated lists of things to match, with certain keywords. 192 * a string seperated lists of things to match, with certain keywords.
204 * If count is 1, make a quick check on the name. 204 * If count is 1, make a quick check on the name.
205 * IF count is >1, we need to make plural name. Return if match. 205 * IF count is >1, we need to make plural name. Return if match.
206 * Last, make a check on the full name. 206 * Last, make a check on the full name.
207 */ 207 */
208int 208int
209item_matched_string (object * pl, object * op, const char *name) 209item_matched_string (object *pl, object *op, const char *name)
210{ 210{
211 char * 211 char *
212 cp, 212 cp,
213 local_name[MAX_BUF]; 213 local_name[MAX_BUF];
214 int 214 int
215 count, 215 count,
216 retval = 0; 216 retval = 0;
217
217 strcpy (local_name, name); /* strtok is destructive to name */ 218 strcpy (local_name, name); /* strtok is destructive to name */
218 219
219 for (cp = strtok (local_name, ","); cp; cp = strtok (NULL, ",")) 220 for (cp = strtok (local_name, ","); cp; cp = strtok (NULL, ","))
220 { 221 {
221 while (cp[0] == ' ') 222 while (cp[0] == ' ')
322void 323void
323init_archetypes (void) 324init_archetypes (void)
324{ /* called from add_player() and edit() */ 325{ /* called from add_player() and edit() */
325 if (first_archetype != NULL) /* Only do this once */ 326 if (first_archetype != NULL) /* Only do this once */
326 return; 327 return;
328
327 arch_init = 1; 329 arch_init = 1;
328 load_archetypes (); 330 load_archetypes ();
329 arch_init = 0; 331 arch_init = 0;
330 empty_archetype = find_archetype ("empty_archetype"); 332 empty_archetype = archetype::find ("empty_archetype");
333
331/* init_blocksview();*/ 334/* init_blocksview();*/
332} 335}
333 336
334/* 337/*
335 * Stores debug-information about how efficient the hashtable 338 * Stores debug-information about how efficient the hashtable
336 * used for archetypes has been in the static errmsg array. 339 * used for archetypes has been in the static errmsg array.
337 */ 340 */
338 341
339void 342void
340arch_info (object * op) 343arch_info (object *op)
341{ 344{
342 sprintf (errmsg, "%d searches and %d strcmp()'s", arch_search, arch_cmp); 345 sprintf (errmsg, "%d searches and %d strcmp()'s", arch_search, arch_cmp);
343 new_draw_info (NDI_BLACK, 0, op, errmsg); 346 new_draw_info (NDI_BLACK, 0, op, errmsg);
344} 347}
345 348
358 */ 361 */
359 362
360void 363void
361init_archetable (void) 364init_archetable (void)
362{ 365{
363 archetype *at; 366 archetype *
367 at;
364 368
365 LOG (llevDebug, " Setting up archetable...\n"); 369 LOG (llevDebug, " Setting up archetable...\n");
366 370
367 for (at = first_archetype; at != NULL; at = (at->more == NULL) ? at->next : at->more) 371 for (at = first_archetype; at != NULL; at = (at->more == NULL) ? at->next : at->more)
368 add_arch (at); 372 add_arch (at);
373/* 377/*
374 * Dumps an archetype to debug-level output. 378 * Dumps an archetype to debug-level output.
375 */ 379 */
376 380
377void 381void
378dump_arch (archetype * at) 382dump_arch (archetype *at)
379{ 383{
380 dump_object (&at->clone); 384 dump_object (&at->clone);
381} 385}
382 386
383/* 387/*
389void 393void
390dump_all_archetypes (void) 394dump_all_archetypes (void)
391{ 395{
392 archetype * 396 archetype *
393 at; 397 at;
398
394 for (at = first_archetype; at != NULL; at = (at->more == NULL) ? at->next : at->more) 399 for (at = first_archetype; at != NULL; at = (at->more == NULL) ? at->next : at->more)
395 { 400 {
396 dump_arch (at); 401 dump_arch (at);
397 fprintf (logfile, "%s\n", errmsg); 402 fprintf (logfile, "%s\n", errmsg);
398 } 403 }
414 else 419 else
415 next = at->next; 420 next = at->next;
416 421
417 delete 422 delete
418 at; 423 at;
424
419 i++; 425 i++;
420 } 426 }
421 LOG (llevDebug, "Freed %d archetypes, %d faces\n", i, f); 427 LOG (llevDebug, "Freed %d archetypes, %d faces\n", i, f);
422} 428}
423 429
424/* 430archetype::archetype ()
425 * Allocates, initialises and returns the pointer to an archetype structure.
426 */
427// TODO: should become constructor
428archetype *
429get_archetype_struct (void)
430{ 431{
431 archetype *
432 arch;
433
434 arch = new archetype;
435
436 clear_object (&arch->clone); /* to initial state other also */ 432 clear_object (&clone); /* to initial state other also */
437 CLEAR_FLAG (&arch->clone, FLAG_FREED); /* This shouldn't matter, since copy_object() */ 433 CLEAR_FLAG (&clone, FLAG_FREED); /* This shouldn't matter, since copy_object() */
438 SET_FLAG (&arch->clone, FLAG_REMOVED); /* doesn't copy these flags... */ 434 SET_FLAG (&clone, FLAG_REMOVED); /* doesn't copy these flags... */
435}
439 436
440 return arch; 437archetype::~archetype ()
438{
441} 439}
442 440
443/* 441/*
444 * Reads/parses the archetype-file, and copies into a linked list 442 * Reads/parses the archetype-file, and copies into a linked list
445 * of archetype-structures. 443 * of archetype-structures.
446 */ 444 */
447void 445void
448first_arch_pass (object_thawer & fp) 446first_arch_pass (object_thawer & fp)
449{ 447{
450 object *
451 op;
452 archetype * 448 archetype *
453 at, * 449 at, *
454 head = NULL, *last_more = NULL; 450 head = NULL, *last_more = NULL;
455 int
456 i;
457 451
458 op = get_object ();
459 op->arch = first_archetype = at = get_archetype_struct (); 452 at->clone.arch = first_archetype = at = new archetype;
460 453
461 while ((i = load_object (fp, op, 0))) 454 while (int i = load_object (fp, &at->clone, 0))
462 { 455 {
463 copy_object (op, &at->clone);
464 at->clone.speed_left = (float) (-0.1); 456 at->clone.speed_left = (float) (-0.1);
465 /* copy the body_info to the body_used - this is only really 457 /* copy the body_info to the body_used - this is only really
466 * need for monsters, but doesn't hurt to do it for everything. 458 * need for monsters, but doesn't hurt to do it for everything.
467 * by doing so, when a monster is created, it has good starting 459 * by doing so, when a monster is created, it has good starting
468 * values for the body_used info, so when items are created 460 * values for the body_used info, so when items are created
469 * for it, they can be properly equipped. 461 * for it, they can be properly equipped.
470 */ 462 */
471 memcpy (&at->clone.body_used, &op->body_info, sizeof (op->body_info)); 463 memcpy (&at->clone.body_used, &at->clone.body_info, sizeof (at->clone.body_info));
472 464
473 switch (i) 465 switch (i)
474 { 466 {
475 case LL_NORMAL: /* A new archetype, just link it with the previous */ 467 case LL_NORMAL: /* A new archetype, just link it with the previous */
476 if (last_more != NULL) 468 if (last_more != NULL)
477 last_more->next = at; 469 last_more->next = at;
478 if (head != NULL) 470 if (head != NULL)
479 head->next = at; 471 head->next = at;
480 head = last_more = at; 472 head = last_more = at;
481#if 0 473#if 0
482 if (!op->type) 474 if (!op->type)
483 LOG (llevDebug, " WARNING: Archetype %s has no type info!\n", op->arch->name); 475 LOG (llevDebug, " WARNING: Archetype %s has no type info!\n", op->arch->name);
484#endif 476#endif
485 at->tail_x = 0; 477 at->tail_x = 0;
486 at->tail_y = 0; 478 at->tail_y = 0;
487 break; 479 break;
488 480
489 case LL_MORE: /* Another part of the previous archetype, link it correctly */ 481 case LL_MORE: /* Another part of the previous archetype, link it correctly */
490 482
491 at->head = head; 483 at->head = head;
492 at->clone.head = &head->clone; 484 at->clone.head = &head->clone;
493 if (last_more != NULL) 485 if (last_more != NULL)
494 { 486 {
495 last_more->more = at; 487 last_more->more = at;
496 last_more->clone.more = &at->clone; 488 last_more->clone.more = &at->clone;
497 } 489 }
498 last_more = at; 490 last_more = at;
499 491
500 /* If this multipart image is still composed of individual small 492 /* If this multipart image is still composed of individual small
501 * images, don't set the tail_.. values. We can't use them anyways, 493 * images, don't set the tail_.. values. We can't use them anyways,
502 * and setting these to zero makes the map sending to the client much 494 * and setting these to zero makes the map sending to the client much
503 * easier as just looking at the head, we know what to do. 495 * easier as just looking at the head, we know what to do.
504 */ 496 */
505 if (at->clone.face != head->clone.face) 497 if (at->clone.face != head->clone.face)
506 { 498 {
507 head->tail_x = 0; 499 head->tail_x = 0;
508 head->tail_y = 0; 500 head->tail_y = 0;
509 } 501 }
510 else 502 else
511 { 503 {
512 if (at->clone.x > head->tail_x) 504 if (at->clone.x > head->tail_x)
513 head->tail_x = at->clone.x; 505 head->tail_x = at->clone.x;
514 if (at->clone.y > head->tail_y) 506 if (at->clone.y > head->tail_y)
515 head->tail_y = at->clone.y; 507 head->tail_y = at->clone.y;
516 } 508 }
517 break; 509 break;
518 510
519 } 511 }
520 512
521 at = get_archetype_struct (); 513 at = new archetype;
522 clear_object (op); 514
523 op->arch = at; 515 at->clone.arch = at;
524 } 516 }
525 517
526 delete 518 delete at;
527 at;
528 free_object (op);
529} 519}
530 520
531/* 521/*
532 * Reads the archetype file once more, and links all pointers between 522 * Reads the archetype file once more, and links all pointers between
533 * archetypes. 523 * archetypes.
556 cp--; 546 cp--;
557 } 547 }
558 } 548 }
559 if (!strcmp ("Object", variable)) 549 if (!strcmp ("Object", variable))
560 { 550 {
561 if ((at = find_archetype (argument)) == NULL) 551 if ((at = archetype::find (argument)) == NULL)
562 LOG (llevError, "Warning: failed to find arch %s\n", argument); 552 LOG (llevError, "Warning: failed to find arch %s\n", argument);
563 } 553 }
564 else if (!strcmp ("other_arch", variable)) 554 else if (!strcmp ("other_arch", variable))
565 { 555 {
566 if (at != NULL && at->clone.other_arch == NULL) 556 if (at != NULL && at->clone.other_arch == NULL)
567 { 557 {
568 if ((other = find_archetype (argument)) == NULL) 558 if ((other = archetype::find (argument)) == NULL)
569 LOG (llevError, "Warning: failed to find other_arch %s\n", argument); 559 LOG (llevError, "Warning: failed to find other_arch %s\n", argument);
570 else if (at != NULL) 560 else if (at != NULL)
571 at->clone.other_arch = other; 561 at->clone.other_arch = other;
572 } 562 }
573 } 563 }
575 { 565 {
576 if (at != NULL) 566 if (at != NULL)
577 { 567 {
578 treasurelist * 568 treasurelist *
579 tl = find_treasurelist (argument); 569 tl = find_treasurelist (argument);
570
580 if (tl == NULL) 571 if (tl == NULL)
581 LOG (llevError, "Failed to link treasure to arch (%s): %s\n", &at->name, argument); 572 LOG (llevError, "Failed to link treasure to arch (%s): %s\n", &at->name, argument);
582 else 573 else
583 at->clone.randomitems = tl; 574 at->clone.randomitems = tl;
584 } 575 }
590void 581void
591check_generators (void) 582check_generators (void)
592{ 583{
593 archetype * 584 archetype *
594 at; 585 at;
586
595 for (at = first_archetype; at != NULL; at = at->next) 587 for (at = first_archetype; at != NULL; at = at->next)
596 if (QUERY_FLAG (&at->clone, FLAG_GENERATOR) && at->clone.other_arch == NULL) 588 if (QUERY_FLAG (&at->clone, FLAG_GENERATOR) && at->clone.other_arch == NULL)
597 LOG (llevError, "Warning: %s is generator but lacks other_arch.\n", &at->name); 589 LOG (llevError, "Warning: %s is generator but lacks other_arch.\n", &at->name);
598} 590}
599#endif 591#endif
608void 600void
609load_archetypes (void) 601load_archetypes (void)
610{ 602{
611 char 603 char
612 filename[MAX_BUF]; 604 filename[MAX_BUF];
605
613#if TIME_ARCH_LOAD 606#if TIME_ARCH_LOAD
614 struct timeval 607 struct timeval
615 tv1, 608 tv1,
616 tv2; 609 tv2;
617#endif 610#endif
652 * Creates and returns a new object which is a copy of the given archetype. 645 * Creates and returns a new object which is a copy of the given archetype.
653 * This function returns NULL on failure. 646 * This function returns NULL on failure.
654 */ 647 */
655 648
656object * 649object *
657arch_to_object (archetype * at) 650arch_to_object (archetype *at)
658{ 651{
659 object * 652 object *
660 op; 653 op;
654
661 if (at == NULL) 655 if (at == NULL)
662 { 656 {
663 if (warn_archetypes) 657 if (warn_archetypes)
664 LOG (llevError, "Couldn't find archetype.\n"); 658 LOG (llevError, "Couldn't find archetype.\n");
659
665 return NULL; 660 return NULL;
666 } 661 }
662
667 op = get_object (); 663 op = get_object ();
668 copy_object (&at->clone, op); 664 copy_object (&at->clone, op);
665 op->arch = at;
669 op->instantiate (); 666 op->instantiate ();
670 op->arch = at;
671 return op; 667 return op;
672} 668}
673 669
674/* 670/*
675 * Creates an object. This function is called by get_archetype() 671 * Creates an object. This function is called by get_archetype()
679 */ 675 */
680 676
681object * 677object *
682create_singularity (const char *name) 678create_singularity (const char *name)
683{ 679{
684 object * 680 object * op;
685 op;
686 char
687 buf[MAX_BUF]; 681 char buf[MAX_BUF];
682
688 sprintf (buf, "%s (%s)", ARCH_SINGULARITY, name); 683 sprintf (buf, "%s (%s)", ARCH_SINGULARITY, name);
689 op = get_object (); 684 op = get_object ();
690 op->name = op->name_pl = buf; 685 op->name = op->name_pl = buf;
691 SET_FLAG (op, FLAG_NO_PICK); 686 SET_FLAG (op, FLAG_NO_PICK);
692 return op; 687 return op;
698 */ 693 */
699 694
700object * 695object *
701get_archetype (const char *name) 696get_archetype (const char *name)
702{ 697{
703 archetype * 698 archetype *at = archetype::find (name);
704 at; 699
705 at = find_archetype (name); 700 if (!at)
706 if (at == NULL)
707 return create_singularity (name); 701 return create_singularity (name);
702
708 return arch_to_object (at); 703 return arch_to_object (at);
709} 704}
710 705
711/* 706/*
712 * Hash-function used by the arch-hashtable. 707 * Hash-function used by the arch-hashtable.
713 */ 708 */
714 709
715unsigned long 710unsigned long
716hasharch (const char *str, int tablesize) 711hasharch (const char *str, int tablesize)
717{ 712{
718 unsigned long 713 unsigned long hash = 0;
719 hash = 0;
720 unsigned int 714 unsigned int i = 0;
721 i = 0;
722 const char * 715 const char *p;
723 p;
724 716
725 /* use the one-at-a-time hash function, which supposedly is 717 /* use the one-at-a-time hash function, which supposedly is
726 * better than the djb2-like one used by perl5.005, but 718 * better than the djb2-like one used by perl5.005, but
727 * certainly is better then the bug used here before. 719 * certainly is better then the bug used here before.
728 * see http://burtleburtle.net/bob/hash/doobs.html 720 * see http://burtleburtle.net/bob/hash/doobs.html
745 * Finds, using the hashtable, which archetype matches the given name. 737 * Finds, using the hashtable, which archetype matches the given name.
746 * returns a pointer to the found archetype, otherwise NULL. 738 * returns a pointer to the found archetype, otherwise NULL.
747 */ 739 */
748 740
749archetype * 741archetype *
750find_archetype (const char *name) 742archetype::find (const char *name)
751{ 743{
752#if USE_UNORDERED_MAP
753 name = shstr::find (name);
754
755 if (!name) 744 if (!name)
756 return 0; 745 return 0;
757 746
758 HT::const_iterator i = ht.find ((size_t)name); 747#if USE_UNORDERED_MAP
748 AUTODECL (i, ht.find ((size_t) name));
759 749
760 if (i == ht.end ()) 750 if (i == ht.end ())
761 return 0; 751 return 0;
762 else 752 else
763 return i->second; 753 return i->second;
764#endif 754#endif
765 755
766 archetype *at; 756 archetype *at;
767 unsigned long index; 757 unsigned long index;
768 758
769 if (name == NULL)
770 return (archetype *) NULL;
771
772 index = hasharch (name, ARCHTABLE); 759 index = hasharch (name, ARCHTABLE);
773 arch_search++; 760 arch_search++;
774 for (;;) 761 for (;;)
775 { 762 {
776 at = arch_table[index]; 763 at = arch_table[index];
764
777 if (at == NULL) 765 if (at == NULL)
778 { 766 {
779 if (warn_archetypes) 767 if (warn_archetypes)
780 LOG (llevError, "Couldn't find archetype %s\n", name); 768 LOG (llevError, "Couldn't find archetype %s\n", name);
769
781 return NULL; 770 return NULL;
782 } 771 }
772
783 arch_cmp++; 773 arch_cmp++;
774
784 if (!strcmp ((const char *) at->name, name)) 775 if (!strcmp ((const char *) at->name, name))
785 return at; 776 return at;
777
786 if (++index >= ARCHTABLE) 778 if (++index >= ARCHTABLE)
787 index = 0; 779 index = 0;
788 } 780 }
789} 781}
790 782
794 786
795static void 787static void
796add_arch (archetype *at) 788add_arch (archetype *at)
797{ 789{
798#if USE_UNORDERED_MAP 790#if USE_UNORDERED_MAP
799 ht.insert (std::make_pair ((size_t)(const char *)at->name, at)); 791 ht.insert (std::make_pair ((size_t) (const char *) at->name, at));
800#endif 792#endif
801 793
802 int index = hasharch ((const char *) at->name, ARCHTABLE), org_index = index; 794 int index = hasharch ((const char *) at->name, ARCHTABLE), org_index = index;
803 795
804 for (;;) 796 for (;;)
823 */ 815 */
824 816
825archetype * 817archetype *
826type_to_archetype (int type) 818type_to_archetype (int type)
827{ 819{
828 archetype * 820 archetype *at;
829 at;
830 821
831 for (at = first_archetype; at != NULL; at = (at->more == NULL) ? at->next : at->more) 822 for (at = first_archetype; at; at = at->more == 0 ? at->next : at->more)
832 if (at->clone.type == type) 823 if (at->clone.type == type)
833 return at; 824 return at;
825
834 return NULL; 826 return 0;
835} 827}
836 828
837/* 829/*
838 * Returns a new object copied from the first archetype matching 830 * Returns a new object copied from the first archetype matching
839 * the given type. 831 * the given type.
841 */ 833 */
842 834
843object * 835object *
844clone_arch (int type) 836clone_arch (int type)
845{ 837{
846 archetype * 838 archetype *at;
847 at;
848 object *
849 op = get_object (); 839 object *op = get_object ();
850 840
851 if ((at = type_to_archetype (type)) == NULL) 841 if ((at = type_to_archetype (type)) == NULL)
852 { 842 {
853 LOG (llevError, "Can't clone archetype %d\n", type); 843 LOG (llevError, "Can't clone archetype %d\n", type);
854 free_object (op); 844 free_object (op);
855 return NULL; 845 return NULL;
856 } 846 }
847
857 copy_object (&at->clone, op); 848 copy_object (&at->clone, op);
858 op->instantiate (); 849 op->instantiate ();
859 return op; 850 return op;
860} 851}
861 852
862/* 853/*
863 * member: make instance from class 854 * member: make instance from class
864 */ 855 */
865 856
866object * 857object *
867object_create_arch (archetype * at) 858object_create_arch (archetype *at)
868{ 859{
869 object * 860 object *op, *prev = 0, *head = 0;
870 op, *
871 prev = NULL, *head = NULL;
872 861
873 while (at) 862 while (at)
874 { 863 {
875 op = arch_to_object (at); 864 op = arch_to_object (at);
876 op->x = at->clone.x; 865 op->x = at->clone.x;
877 op->y = at->clone.y; 866 op->y = at->clone.y;
867
878 if (head) 868 if (head)
879 op->head = head, prev->more = op; 869 op->head = head, prev->more = op;
870
880 if (!head) 871 if (!head)
881 head = op; 872 head = op;
873
882 prev = op; 874 prev = op;
883 at = at->more; 875 at = at->more;
884 } 876 }
877
885 return (head); 878 return (head);
886} 879}
887 880
888/*** end of arch.c ***/

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines