Merged changes in the trunk up to revision 34996.
[blender.git] / source / blender / makesdna / intern / dna_genfile.c
1 /* dna_genfile.c
2  *
3  * Functions for struct-dna, the genetic file dot c!
4  *
5  * $Id$
6  *
7  * ***** BEGIN GPL LICENSE BLOCK *****
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL LICENSE BLOCK *****
31  * DNA handling
32  */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include "MEM_guardedalloc.h" // for MEM_freeN MEM_mallocN MEM_callocN
39
40 #include "DNA_genfile.h"
41 #include "DNA_sdna_types.h" // for SDNA ;-)
42
43
44 /* gcc 4.1 on mingw was complaining that __int64 was already defined
45 actually is saw the line below as typedef long long long long... 
46 Anyhow, since its already defined, its safe to do an ifndef here- Campbell */
47 #ifdef FREE_WINDOWS
48 #ifndef __int64
49 typedef long long __int64;
50 #endif
51 #endif
52
53 /*
54  * - please note: no builtin security to detect input of double structs
55  * - if you want a struct not to be in DNA file: add two hash marks above it (#<enter>#<enter>)
56
57 Structure DNA data is added to each blender file and to each executable, this to detect
58 in .blend files new veriables in structs, changed array sizes, etc. It's also used for
59 converting endian and pointer size (32-64 bits)
60 As an extra, Python uses a call to detect run-time the contents of a blender struct.
61
62 Create a structDNA: only needed when one of the input include (.h) files change.
63 File Syntax:
64         SDNA (4 bytes) (magic number)
65         NAME (4 bytes)
66         <nr> (4 bytes) amount of names (int)
67         <string> 
68         <string>
69         ...
70         ...
71         TYPE (4 bytes)
72         <nr> amount of types (int)
73         <string>
74         <string>
75         ...
76         ...
77         TLEN (4 bytes)
78         <len> (short) the lengths of types
79         <len>
80         ...
81         ...
82         STRC (4 bytes)
83         <nr> amount of structs (int)
84         <typenr><nr_of_elems> <typenr><namenr> <typenr><namenr> ...
85         
86 !!Remember to read/write integer and short aligned!!
87
88  While writing a file, the names of a struct is indicated with a type number,
89  to be found with: type= findstruct_nr(SDNA *, char *)
90  The value of 'type' corresponds with the the index within the structs array
91
92  For the moment: the complete DNA file is included in a .blend file. For
93  the future we can think of smarter methods, like only included the used
94  structs. Only needed to keep a file short though...
95
96 ALLOWED AND TESTED CHANGES IN STRUCTS:
97  - type change (a char to float will be divided by 255)
98  - location within a struct (everthing can be randomly mixed up)
99  - struct within struct (within struct etc), this is recursive
100  - adding new elements, will be default initialized zero
101  - remving elements
102  - change of array sizes
103  - change of a pointer type: when the name doesn't change the contents is copied
104
105 NOT YET:
106  - array (vec[3]) to float struct (vec3f)
107
108 DONE:
109  - endian compatibility
110  - pointer conversion (32-64 bits)
111
112 IMPORTANT:
113  - do not use #defines in structs for array lengths, this cannot be read by the dna functions
114  - do not use uint, but unsigned int instead, ushort and ulong are allowed
115  - only use a long in Blender if you want this to be the size of a pointer. so it is
116    32 bits or 64 bits, dependant at the cpu architecture
117  - chars are always unsigned
118  - aligment of variables has to be done in such a way, that any system does
119    not create 'padding' (gaps) in structures. So make sure that:
120    - short: 2 aligned
121    - int: 4 aligned
122    - float: 4 aligned
123    - double: 8 aligned
124    - long: 8 aligned
125    - struct: 8 aligned
126  - the sdna functions have several error prints builtin, always check blender running from a console.
127  
128 */
129
130 /* local */
131 static int le_int(int temp);
132 static short le_short(short temp);
133
134 /* ************************* ENDIAN STUFF ********************** */
135
136 static short le_short(short temp)
137 {
138         short new;
139         char *rt=(char *)&temp, *rtn=(char *)&new;
140
141         rtn[0]= rt[1];
142         rtn[1]= rt[0];
143
144         return new;
145 }
146
147
148 static int le_int(int temp)
149 {
150         int new;
151         char *rt=(char *)&temp, *rtn=(char *)&new;
152
153         rtn[0]= rt[3];
154         rtn[1]= rt[2];
155         rtn[2]= rt[1];
156         rtn[3]= rt[0];
157
158         return new;
159 }
160
161
162 /* ************************* MAKE DNA ********************** */
163
164 /* allowed duplicate code from makesdna.c */
165 int DNA_elem_array_size(const char *astr, int len)
166 {
167         int a, mul=1;
168         char str[100], *cp=0;
169
170         memcpy(str, astr, len+1);
171
172         for(a=0; a<len; a++) {
173                 if( str[a]== '[' ) {
174                         cp= &(str[a+1]);
175                 }
176                 else if( str[a]==']' && cp) {
177                         str[a]= 0;
178                         mul*= atoi(cp);
179                 }
180         }
181
182         return mul;
183 }
184
185 /* ************************* END MAKE DNA ********************** */
186
187 /* ************************* DIV ********************** */
188
189 void DNA_sdna_free(SDNA *sdna)
190 {
191         MEM_freeN(sdna->data);
192         MEM_freeN(sdna->names);
193         MEM_freeN(sdna->types);
194         MEM_freeN(sdna->structs);
195         
196         MEM_freeN(sdna);
197 }
198
199 static int ispointer(const char *name)
200 {
201         /* check if pointer or function pointer */
202         return (name[0]=='*' || (name[0]=='(' && name[1]=='*'));
203 }
204
205 static int elementsize(SDNA *sdna, short type, short name)
206 /* call with numbers from struct-array */
207 {
208         int mul, namelen, len;
209         const char *cp;
210         
211         cp= sdna->names[name];
212         len= 0;
213         
214         namelen= strlen(cp);
215         /* is it a pointer or function pointer? */
216         if(ispointer(cp)) {
217                 /* has the naam an extra length? (array) */
218                 mul= 1;
219                 if( cp[namelen-1]==']') mul= DNA_elem_array_size(cp, namelen);
220                 
221                 len= sdna->pointerlen*mul;
222         }
223         else if( sdna->typelens[type] ) {
224                 /* has the naam an extra length? (array) */
225                 mul= 1;
226                 if( cp[namelen-1]==']') mul= DNA_elem_array_size(cp, namelen);
227                 
228                 len= mul*sdna->typelens[type];
229                 
230         }
231         
232         return len;
233 }
234
235 #if 0
236 static void printstruct(SDNA *sdna, short strnr)
237 {
238         /* is for debug */
239         int b, nr;
240         short *sp;
241         
242         sp= sdna->structs[strnr];
243         
244         printf("struct %s\n", sdna->types[ sp[0] ]);
245         nr= sp[1];
246         sp+= 2;
247         
248         for(b=0; b< nr; b++, sp+= 2) {
249                 printf("   %s %s\n", sdna->types[sp[0]], sdna->names[sp[1]]);
250         }
251 }
252 #endif
253
254 static short *findstruct_name(SDNA *sdna, const char *str)
255 {
256         int a;
257         short *sp=0;
258
259
260         for(a=0; a<sdna->nr_structs; a++) {
261
262                 sp= sdna->structs[a];
263                 
264                 if(strcmp( sdna->types[ sp[0] ], str )==0) return sp;
265         }
266         
267         return 0;
268 }
269
270 int DNA_struct_find_nr(SDNA *sdna, const char *str)
271 {
272         short *sp=0;
273         int a;
274
275         if(sdna->lastfind<sdna->nr_structs) {
276                 sp= sdna->structs[sdna->lastfind];
277                 if(strcmp( sdna->types[ sp[0] ], str )==0) return sdna->lastfind;
278         }
279
280         for(a=0; a<sdna->nr_structs; a++) {
281
282                 sp= sdna->structs[a];
283                 
284                 if(strcmp( sdna->types[ sp[0] ], str )==0) {
285                         sdna->lastfind= a;
286                         return a;
287                 }
288         }
289         
290         return -1;
291 }
292
293 /* ************************* END DIV ********************** */
294
295 /* ************************* READ DNA ********************** */
296
297 static void init_structDNA(SDNA *sdna, int do_endian_swap)
298 /* in sdna->data the data, now we convert that to something understandable */
299 {
300         int *data, *verg, gravity_fix= -1;
301         intptr_t nr;
302         short *sp;
303         char str[8], *cp;
304         
305         verg= (int *)str;
306         data= (int *)sdna->data;
307
308         strcpy(str, "SDNA");
309         if( *data == *verg ) {
310         
311                 data++;
312                 
313                 /* load names array */
314                 strcpy(str, "NAME");
315                 if( *data == *verg ) {
316                         data++;
317                         
318                         if(do_endian_swap) sdna->nr_names= le_int(*data);
319                         else sdna->nr_names= *data;
320                         
321                         data++;
322                         sdna->names= MEM_callocN( sizeof(void *)*sdna->nr_names, "sdnanames");
323                 }
324                 else {
325                         printf("NAME error in SDNA file\n");
326                         return;
327                 }
328                 
329                 nr= 0;
330                 cp= (char *)data;
331                 while(nr<sdna->nr_names) {
332                         sdna->names[nr]= cp;
333
334                         /* "float gravity [3]" was parsed wrong giving both "gravity" and
335                            "[3]"  members. we rename "[3]", and later set the type of
336                            "gravity" to "void" so the offsets work out correct */
337                         if(*cp == '[' && strcmp(cp, "[3]")==0) {
338                                 if(nr && strcmp(sdna->names[nr-1], "Cvi") == 0) {
339                                         sdna->names[nr]= "gravity[3]";
340                                         gravity_fix= nr;
341                                 }
342                         }
343
344                         while( *cp) cp++;
345                         cp++;
346                         nr++;
347                 }
348                 nr= (intptr_t)cp;               /* prevent BUS error */
349                 nr= (nr+3) & ~3;
350                 cp= (char *)nr;
351                 
352                 /* load type names array */
353                 data= (int *)cp;
354                 strcpy(str, "TYPE");
355                 if( *data == *verg ) {
356                         data++;
357                         
358                         if(do_endian_swap) sdna->nr_types= le_int(*data);
359                         else sdna->nr_types= *data;
360                         
361                         data++;
362                         sdna->types= MEM_callocN( sizeof(void *)*sdna->nr_types, "sdnatypes");
363                 }
364                 else {
365                         printf("TYPE error in SDNA file\n");
366                         return;
367                 }
368                 
369                 nr= 0;
370                 cp= (char *)data;
371                 while(nr<sdna->nr_types) {
372                         sdna->types[nr]= cp;
373                         
374                         /* this is a patch, to change struct names without a confict with SDNA */
375                         /* be careful to use it, in this case for a system-struct (opengl/X) */
376                         
377                         if( *cp == 'b') {
378                                 /* struct Screen was already used by X, 'bScreen' replaces the old IrisGL 'Screen' struct */
379                                 if( strcmp("bScreen", cp)==0 ) sdna->types[nr]= cp+1;
380                         }
381                         
382                         while( *cp) cp++;
383                         cp++;
384                         nr++;
385                 }
386                 nr= (intptr_t)cp;               /* prevent BUS error */
387                 nr= (nr+3) & ~3;
388                 cp= (char *)nr;
389                 
390                 /* load typelen array */
391                 data= (int *)cp;
392                 strcpy(str, "TLEN");
393                 if( *data == *verg ) {
394                         data++;
395                         sp= (short *)data;
396                         sdna->typelens= sp;
397                         
398                         if(do_endian_swap) {
399                                 short a, *spo= sp;
400                                 
401                                 a= sdna->nr_types;
402                                 while(a--) {
403                                         spo[0]= le_short(spo[0]);
404                                         spo++;
405                                 }
406                         }
407                         
408                         sp+= sdna->nr_types;
409                 }
410                 else {
411                         printf("TLEN error in SDNA file\n");
412                         return;
413                 }
414                 if(sdna->nr_types & 1) sp++;    /* prevent BUS error */
415
416                 /* load struct array */
417                 data= (int *)sp;
418                 strcpy(str, "STRC");
419                 if( *data == *verg ) {
420                         data++;
421                         
422                         if(do_endian_swap) sdna->nr_structs= le_int(*data);
423                         else sdna->nr_structs= *data;
424                         
425                         data++;
426                         sdna->structs= MEM_callocN( sizeof(void *)*sdna->nr_structs, "sdnastrcs");
427                 }
428                 else {
429                         printf("STRC error in SDNA file\n");
430                         return;
431                 }
432                 
433                 nr= 0;
434                 sp= (short *)data;
435                 while(nr<sdna->nr_structs) {
436                         sdna->structs[nr]= sp;
437                         
438                         if(do_endian_swap) {
439                                 short a;
440                                 
441                                 sp[0]= le_short(sp[0]);
442                                 sp[1]= le_short(sp[1]);
443                                 
444                                 a= sp[1];
445                                 sp+= 2;
446                                 while(a--) {
447                                         sp[0]= le_short(sp[0]);
448                                         sp[1]= le_short(sp[1]);
449                                         sp+= 2;
450                                 }
451                         }
452                         else {
453                                 sp+= 2*sp[1]+2;
454                         }
455                         
456                         nr++;
457                 }
458
459                 /* finally pointerlen: use struct ListBase to test it, never change the size of it! */
460                 sp= findstruct_name(sdna, "ListBase");
461                 /* weird; i have no memory of that... I think I used sizeof(void *) before... (ton) */
462                 
463                 sdna->pointerlen= sdna->typelens[ sp[0] ]/2;
464
465                 if(sp[1]!=2 || (sdna->pointerlen!=4 && sdna->pointerlen!=8)) {
466                         printf("ListBase struct error! Needs it to calculate pointerize.\n");
467                         exit(0);
468                         /* well, at least sizeof(ListBase) is error proof! (ton) */
469                 }
470                 
471                 /* second part of gravity problem, setting "gravity" type to void */
472                 if(gravity_fix > -1) {
473                         for(nr=0; nr<sdna->nr_structs; nr++) {
474                                 sp= sdna->structs[nr];
475                                 if(strcmp(sdna->types[sp[0]], "ClothSimSettings") == 0)
476                                         sp[10]= 9;
477                         }
478                 }
479         }
480 }
481
482 SDNA *DNA_sdna_from_data(void *data, int datalen, int do_endian_swap)
483 {
484         SDNA *sdna= MEM_mallocN(sizeof(*sdna), "sdna");
485         
486         sdna->lastfind= 0;
487
488         sdna->datalen= datalen;
489         sdna->data= MEM_mallocN(datalen, "sdna_data");
490         memcpy(sdna->data, data, datalen);
491         
492         init_structDNA(sdna, do_endian_swap);
493         
494         return sdna;
495 }
496
497 /* ******************** END READ DNA ********************** */
498
499 /* ******************* HANDLE DNA ***************** */
500
501 static void recurs_test_compflags(SDNA *sdna, char *compflags, int structnr)
502 {
503         int a, b, typenr, elems;
504         short *sp;
505         const char *cp;
506         
507         /* check all structs, test if it's inside another struct */
508         sp= sdna->structs[structnr];
509         typenr= sp[0];
510         
511         for(a=0; a<sdna->nr_structs; a++) {
512                 if(a!=structnr && compflags[a]==1) {
513                         sp= sdna->structs[a];
514                         elems= sp[1];
515                         sp+= 2;
516                         for(b=0; b<elems; b++, sp+=2) {
517                                 if(sp[0]==typenr) {
518                                         cp= sdna->names[ sp[1] ];
519                                         if(!ispointer(cp)) {
520                                                 compflags[a]= 2;
521                                                 recurs_test_compflags(sdna, compflags, a);
522                                         }
523                                 }
524                         }
525                 }
526         }
527         
528 }
529
530         /* Unsure of exact function - compares the sdna argument to
531          * newsdna and sets up the information necessary to convert
532          * data written with a dna of oldsdna to inmemory data with a
533          * structure defined by the newsdna sdna (I think). -zr
534          */
535
536 /* well, the function below is just a lookup table to speed
537  * up reading files. doh! -ton
538  */
539
540
541 char *DNA_struct_get_compareflags(SDNA *sdna, SDNA *newsdna)
542 {
543         /* flag: 0: doesn't exist anymore (or not yet)
544          *       1: is equal
545          *       2: is different
546          */
547         int a, b;
548         short *spold, *spcur;
549         const char *str1, *str2;
550         char *compflags;
551         
552         if(sdna->nr_structs==0) {
553                 printf("error: file without SDNA\n");
554                 return NULL;
555         }
556                 
557         compflags= MEM_callocN(sdna->nr_structs, "compflags");
558
559         /* we check all structs in 'sdna' and compare them with 
560          * the structs in 'newsdna'
561          */
562         
563         for(a=0; a<sdna->nr_structs; a++) {
564                 spold= sdna->structs[a];
565                 
566                 /* search for type in cur */
567                 spcur= findstruct_name(newsdna, sdna->types[spold[0]]);
568                 
569                 if(spcur) {
570                         compflags[a]= 2;
571                         
572                         /* compare length and amount of elems */
573                         if( spcur[1] == spold[1]) {
574                                  if( newsdna->typelens[spcur[0]] == sdna->typelens[spold[0]] ) {
575                                          
576                                          /* same length, same amount of elems, now per type and name */
577                                          b= spold[1];
578                                          spold+= 2;
579                                          spcur+= 2;
580                                          while(b > 0) {
581                                                  str1= newsdna->types[spcur[0]];
582                                                  str2= sdna->types[spold[0]];
583                                                  if(strcmp(str1, str2)!=0) break;
584
585                                                  str1= newsdna->names[spcur[1]];
586                                                  str2= sdna->names[spold[1]];
587                                                  if(strcmp(str1, str2)!=0) break;
588                                                  
589                                                  /* same type and same name, now pointersize */
590                                                  if(ispointer(str1)) {
591                                                          if(sdna->pointerlen!=newsdna->pointerlen) break;
592                                                  }
593                                                  
594                                                  b--;
595                                                  spold+= 2;
596                                                  spcur+= 2;
597                                          }
598                                          if(b==0) compflags[a]= 1;
599
600                                  }
601                         }
602                         
603                 }
604         }
605
606         /* first struct in util.h is struct Link, this is skipped in compflags (als # 0).
607          * was a bug, and this way dirty patched! Solve this later....
608          */
609         compflags[0]= 1;
610
611         /* Because structs can be inside structs, we recursively
612          * set flags when a struct is altered
613          */
614         for(a=0; a<sdna->nr_structs; a++) {
615                 if(compflags[a]==2) recurs_test_compflags(sdna, compflags, a);
616         }
617         
618 /*
619         for(a=0; a<sdna->nr_structs; a++) {
620                 if(compflags[a]==2) {
621                         spold= sdna->structs[a];
622                         printf("changed: %s\n", sdna->types[ spold[0] ]);
623                 }
624         }
625 */
626
627         return compflags;
628 }
629
630 static void cast_elem(char *ctype, char *otype, const char *name, char *curdata, char *olddata)
631 {
632         double val = 0.0;
633         int arrlen, curlen=1, oldlen=1, ctypenr, otypenr;
634         
635         arrlen= DNA_elem_array_size(name, strlen(name));
636         
637         /* define otypenr */
638         if(strcmp(otype, "char")==0 || (strcmp(otype, "const char")==0)) otypenr= 0; 
639         else if((strcmp(otype, "uchar")==0) || (strcmp(otype, "unsigned char")==0)) otypenr= 1;
640         else if(strcmp(otype, "short")==0) otypenr= 2; 
641         else if((strcmp(otype, "ushort")==0)||(strcmp(otype, "unsigned short")==0)) otypenr= 3;
642         else if(strcmp(otype, "int")==0) otypenr= 4;
643         else if(strcmp(otype, "long")==0) otypenr= 5;
644         else if((strcmp(otype, "ulong")==0)||(strcmp(otype, "unsigned long")==0)) otypenr= 6;
645         else if(strcmp(otype, "float")==0) otypenr= 7;
646         else if(strcmp(otype, "double")==0) otypenr= 8;
647         else return;
648         
649         /* define ctypenr */
650         if(strcmp(ctype, "char")==0) ctypenr= 0; 
651         else if(strcmp(ctype, "const char")==0) ctypenr= 0; 
652         else if((strcmp(ctype, "uchar")==0)||(strcmp(ctype, "unsigned char")==0)) ctypenr= 1;
653         else if(strcmp(ctype, "short")==0) ctypenr= 2; 
654         else if((strcmp(ctype, "ushort")==0)||(strcmp(ctype, "unsigned short")==0)) ctypenr= 3;
655         else if(strcmp(ctype, "int")==0) ctypenr= 4;
656         else if(strcmp(ctype, "long")==0) ctypenr= 5;
657         else if((strcmp(ctype, "ulong")==0)||(strcmp(ctype, "unsigned long")==0)) ctypenr= 6;
658         else if(strcmp(ctype, "float")==0) ctypenr= 7;
659         else if(strcmp(ctype, "double")==0) ctypenr= 8;
660         else return;
661
662         /* define lengths */
663         if(otypenr < 2) oldlen= 1;
664         else if(otypenr < 4) oldlen= 2;
665         else if(otypenr < 8) oldlen= 4;
666         else oldlen= 8;
667
668         if(ctypenr < 2) curlen= 1;
669         else if(ctypenr < 4) curlen= 2;
670         else if(ctypenr < 8) curlen= 4;
671         else curlen= 8;
672         
673         while(arrlen>0) {
674                 switch(otypenr) {
675                 case 0:
676                         val= *olddata; break;
677                 case 1:
678                         val= *( (unsigned char *)olddata); break;
679                 case 2:
680                         val= *( (short *)olddata); break;
681                 case 3:
682                         val= *( (unsigned short *)olddata); break;
683                 case 4:
684                         val= *( (int *)olddata); break;
685                 case 5:
686                         val= *( (int *)olddata); break;
687                 case 6:
688                         val= *( (unsigned int *)olddata); break;
689                 case 7:
690                         val= *( (float *)olddata); break;
691                 case 8:
692                         val= *( (double *)olddata); break;
693                 }
694                 
695                 switch(ctypenr) {
696                 case 0:
697                         *curdata= val; break;
698                 case 1:
699                         *( (unsigned char *)curdata)= val; break;
700                 case 2:
701                         *( (short *)curdata)= val; break;
702                 case 3:
703                         *( (unsigned short *)curdata)= val; break;
704                 case 4:
705                         *( (int *)curdata)= val; break;
706                 case 5:
707                         *( (int *)curdata)= val; break;
708                 case 6:
709                         *( (unsigned int *)curdata)= val; break;
710                 case 7:
711                         if(otypenr<2) val/= 255;
712                         *( (float *)curdata)= val; break;
713                 case 8:
714                         if(otypenr<2) val/= 255;
715                         *( (double *)curdata)= val; break;
716                 }
717
718                 olddata+= oldlen;
719                 curdata+= curlen;
720                 arrlen--;
721         }
722 }
723
724 static void cast_pointer(int curlen, int oldlen, const char *name, char *curdata, char *olddata)
725 {
726 #ifdef WIN32
727         __int64 lval;
728 #else
729         long long lval;
730 #endif
731         int arrlen;
732         
733         arrlen= DNA_elem_array_size(name, strlen(name));
734         
735         while(arrlen>0) {
736         
737                 if(curlen==oldlen) {
738                         memcpy(curdata, olddata, curlen);
739                 }
740                 else if(curlen==4 && oldlen==8) {
741 #ifdef WIN32                    
742                         lval= *( (__int64 *)olddata );
743 #else
744                         lval= *( (long long *)olddata );
745 #endif
746                         *((int *)curdata) = lval>>3;            /* is of course gambling! */
747                 }
748                 else if(curlen==8 && oldlen==4) {
749 #ifdef WIN32
750                          *( (__int64 *)curdata ) = *((int *)olddata);
751 #else
752                          *( (long long *)curdata ) = *((int *)olddata);
753 #endif
754                 }
755                 else {
756                         /* for debug */
757                         printf("errpr: illegal pointersize! \n");
758                 }
759                 
760                 olddata+= oldlen;
761                 curdata+= curlen;
762                 arrlen--;
763
764         }
765 }
766
767 static int elem_strcmp(const char *name, const char *oname)
768 {
769         int a=0;
770         
771         /* strcmp without array part */
772         
773         while(1) {
774                 if(name[a] != oname[a]) return 1;
775                 if(name[a]=='[') break;
776                 if(name[a]==0) break;
777                 a++;
778         }
779         if(name[a] != oname[a]) return 1;
780         return 0;
781 }
782
783 static char *find_elem(SDNA *sdna, const char *type, const char *name, short *old, char *olddata, short **sppo)
784 {
785         int a, elemcount, len;
786         const char *otype, *oname;
787         
788         /* without arraypart, so names can differ: return old namenr and type */
789         
790         /* in old is the old struct */
791         elemcount= old[1];
792         old+= 2;
793         for(a=0; a<elemcount; a++, old+=2) {
794         
795                 otype= sdna->types[old[0]];
796                 oname= sdna->names[old[1]];
797                 
798                 len= elementsize(sdna, old[0], old[1]);
799                 
800                 if( elem_strcmp(name, oname)==0 ) {     /* naam equal */
801                         if( strcmp(type, otype)==0 ) {  /* type equal */
802                                 if(sppo) *sppo= old;
803                                 return olddata;
804                         }
805                         
806                         return 0;
807                 }
808                 
809                 olddata+= len;
810         }
811         return 0;
812 }
813
814 static void reconstruct_elem(SDNA *newsdna, SDNA *oldsdna, char *type, const char *name, char *curdata, short *old, char *olddata)
815 {
816         /* rules: test for NAME:
817                         - name equal:
818                                 - cast type
819                         - name partially equal (array differs)
820                                 - type equal: memcpy
821                                 - types casten
822            (nzc 2-4-2001 I want the 'unsigned' bit to be parsed as well. Where
823            can I force this?)
824         */      
825         int a, elemcount, len, array, oldsize, cursize, mul;
826         char *otype;
827         const char *oname, *cp;
828         
829         /* is 'name' an array? */
830         cp= name;
831         array= 0;
832         while( *cp && *cp!='[') {
833                 cp++; array++;
834         }
835         if( *cp!= '[' ) array= 0;
836         
837         /* in old is the old struct */
838         elemcount= old[1];
839         old+= 2;
840         for(a=0; a<elemcount; a++, old+=2) {
841                 otype= oldsdna->types[old[0]];
842                 oname= oldsdna->names[old[1]];
843                 len= elementsize(oldsdna, old[0], old[1]);
844                 
845                 if( strcmp(name, oname)==0 ) {  /* name equal */
846                         
847                         if(ispointer(name)) {   /* pointer of functionpointer afhandelen */
848                                 cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata);
849                         }
850                         else if( strcmp(type, otype)==0 ) {     /* type equal */
851                                 memcpy(curdata, olddata, len);
852                         }
853                         else cast_elem(type, otype, name, curdata, olddata);
854
855                         return;
856                 }
857                 else if(array) {                /* name is an array */
858
859                         if(oname[array]=='[' && strncmp(name, oname, array)==0 ) {                      /* basis equal */
860                                 
861                                 cursize= DNA_elem_array_size(name, strlen(name));
862                                 oldsize= DNA_elem_array_size(oname, strlen(oname));
863
864                                 if(ispointer(name)) {           /* handle pointer or functionpointer */
865                                         if(cursize>oldsize) cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, oname, curdata, olddata);
866                                         else cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata);
867                                 }
868                                 else if(name[0]=='*' || strcmp(type, otype)==0 ) {      /* type equal */
869                                         mul= len/oldsize;
870                                         mul*= (cursize < oldsize)? cursize: oldsize;
871                                         memcpy(curdata, olddata, mul);
872                                         
873                                         /* terminate strings */
874                                         if(oldsize > cursize && strcmp(type, "char")==0)
875                                                 curdata[mul-1]= 0;
876                                 }
877                                 else {
878                                         if(cursize>oldsize) cast_elem(type, otype, oname, curdata, olddata);
879                                         else cast_elem(type, otype, name, curdata, olddata);
880                                 }
881                                 return;
882                         }
883                 }
884                 olddata+= len;
885         }
886 }
887
888 static void reconstruct_struct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int oldSDNAnr, char *data, int curSDNAnr, char *cur)
889 {
890         /* Recursive!
891          * Per element from cur_struct, read data from old_struct.
892          * If element is a struct, call recursive.
893          */
894         int a, elemcount, elen, eleno, mul, mulo, firststructtypenr;
895         short *spo, *spc, *sppo;
896         char *type, *cpo, *cpc;
897         const char *name, *nameo;
898
899         if(oldSDNAnr== -1) return;
900         if(curSDNAnr== -1) return;
901
902         if( compflags[oldSDNAnr]==1 ) {         /* if recursive: test for equal */
903         
904                 spo= oldsdna->structs[oldSDNAnr];
905                 elen= oldsdna->typelens[ spo[0] ];
906                 memcpy( cur, data, elen);
907                 
908                 return;
909         }
910
911         firststructtypenr= *(newsdna->structs[0]);
912
913         spo= oldsdna->structs[oldSDNAnr];
914         spc= newsdna->structs[curSDNAnr];
915
916         elemcount= spc[1];
917
918         spc+= 2;
919         cpc= cur;
920         for(a=0; a<elemcount; a++, spc+=2) {
921                 type= newsdna->types[spc[0]];
922                 name= newsdna->names[spc[1]];
923                 
924                 elen= elementsize(newsdna, spc[0], spc[1]);
925
926                 /* test: is type a struct? */
927                 if(spc[0]>=firststructtypenr  &&  !ispointer(name)) {
928                 
929                         /* where does the old struct data start (and is there an old one?) */
930                         cpo= find_elem(oldsdna, type, name, spo, data, &sppo);
931                         
932                         if(cpo) {
933                                 oldSDNAnr= DNA_struct_find_nr(oldsdna, type);
934                                 curSDNAnr= DNA_struct_find_nr(newsdna, type);
935                                 
936                                 /* array! */
937                                 mul= DNA_elem_array_size(name, strlen(name));
938                                 nameo= oldsdna->names[sppo[1]];
939                                 mulo= DNA_elem_array_size(nameo, strlen(nameo));
940                                 
941                                 eleno= elementsize(oldsdna, sppo[0], sppo[1]);
942                                 
943                                 elen/= mul;
944                                 eleno/= mulo;
945                                 
946                                 while(mul--) {
947                                         reconstruct_struct(newsdna, oldsdna, compflags, oldSDNAnr, cpo, curSDNAnr, cpc);
948                                         cpo+= eleno;
949                                         cpc+= elen;
950                                         
951                                         /* new struct array larger than old */
952                                         mulo--;
953                                         if(mulo<=0) break;
954                                 }
955                         }
956                         else cpc+= elen;
957                 }
958                 else {
959
960                         reconstruct_elem(newsdna, oldsdna, type, name, cpc, spo, data);
961                         cpc+= elen;
962
963                 }
964         }
965 }
966
967 void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
968 {
969         /* Recursive!
970          * If element is a struct, call recursive.
971          */
972         int a, mul, elemcount, elen, elena, firststructtypenr;
973         short *spo, *spc, skip;
974         char *type, *cpo, *cur, cval;
975         const char *name;
976
977         if(oldSDNAnr== -1) return;
978         firststructtypenr= *(oldsdna->structs[0]);
979         
980         spo= spc= oldsdna->structs[oldSDNAnr];
981
982         elemcount= spo[1];
983
984         spc+= 2;
985         cur= data;
986         
987         for(a=0; a<elemcount; a++, spc+=2) {
988                 type= oldsdna->types[spc[0]];
989                 name= oldsdna->names[spc[1]];
990                 
991                 /* elementsize = including arraysize */
992                 elen= elementsize(oldsdna, spc[0], spc[1]);
993
994                 /* test: is type a struct? */
995                 if(spc[0]>=firststructtypenr  &&  !ispointer(name)) {
996                         /* where does the old data start (is there one?) */
997                         cpo= find_elem(oldsdna, type, name, spo, data, 0);
998                         if(cpo) {
999                                 oldSDNAnr= DNA_struct_find_nr(oldsdna, type);
1000                                 
1001                                 mul= DNA_elem_array_size(name, strlen(name));
1002                                 elena= elen/mul;
1003
1004                                 while(mul--) {
1005                                         DNA_struct_switch_endian(oldsdna, oldSDNAnr, cpo);
1006                                         cpo += elena;
1007                                 }
1008                         }
1009                 }
1010                 else {
1011                         
1012                         if(ispointer(name)) {
1013                                 if(oldsdna->pointerlen==8) {
1014                                         
1015                                         mul= DNA_elem_array_size(name, strlen(name));
1016                                         cpo= cur;
1017                                         while(mul--) {
1018                                                 cval= cpo[0]; cpo[0]= cpo[7]; cpo[7]= cval;
1019                                                 cval= cpo[1]; cpo[1]= cpo[6]; cpo[6]= cval;
1020                                                 cval= cpo[2]; cpo[2]= cpo[5]; cpo[5]= cval;
1021                                                 cval= cpo[3]; cpo[3]= cpo[4]; cpo[4]= cval;
1022                                                 
1023                                                 cpo+= 8;
1024                                         }
1025                                         
1026                                 }
1027                         }
1028                         else {
1029                                 
1030                                 if( spc[0]==2 || spc[0]==3 ) {  /* short-ushort */
1031                                         
1032                                         /* exception: variable called blocktype/ipowin: derived from ID_  */
1033                                         skip= 0;
1034                                         if(name[0]=='b' && name[1]=='l') {
1035                                                 if(strcmp(name, "blocktype")==0) skip= 1;
1036                                         }
1037                                         else if(name[0]=='i' && name[1]=='p') {
1038                                                 if(strcmp(name, "ipowin")==0) skip= 1;
1039                                         }
1040                                         
1041                                         if(skip==0) {
1042                                                 mul= DNA_elem_array_size(name, strlen(name));
1043                                                 cpo= cur;
1044                                                 while(mul--) {
1045                                                         cval= cpo[0];
1046                                                         cpo[0]= cpo[1];
1047                                                         cpo[1]= cval;
1048                                                         cpo+= 2;
1049                                                 }
1050                                         }
1051                                 }
1052                                 else if(spc[0]>3 && spc[0]<8) { /* int-long-ulong-float */
1053
1054                                         mul= DNA_elem_array_size(name, strlen(name));
1055                                         cpo= cur;
1056                                         while(mul--) {
1057                                                 cval= cpo[0];
1058                                                 cpo[0]= cpo[3];
1059                                                 cpo[3]= cval;
1060                                                 cval= cpo[1];
1061                                                 cpo[1]= cpo[2];
1062                                                 cpo[2]= cval;
1063                                                 cpo+= 4;
1064                                         }
1065                                 }
1066                         }
1067                 }
1068                 cur+= elen;
1069         }
1070 }
1071
1072 void *DNA_struct_reconstruct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int oldSDNAnr, int blocks, void *data)
1073 {
1074         int a, curSDNAnr, curlen=0, oldlen;
1075         short *spo, *spc;
1076         char *cur, *type, *cpc, *cpo;
1077         
1078         /* oldSDNAnr == structnr, we're looking for the corresponding 'cur' number */
1079         spo= oldsdna->structs[oldSDNAnr];
1080         type= oldsdna->types[ spo[0] ];
1081         oldlen= oldsdna->typelens[ spo[0] ];
1082         curSDNAnr= DNA_struct_find_nr(newsdna, type);
1083
1084         /* init data and alloc */
1085         if(curSDNAnr >= 0) {
1086                 spc= newsdna->structs[curSDNAnr];
1087                 curlen= newsdna->typelens[ spc[0] ];
1088         }
1089         if(curlen==0) {
1090                 return NULL;
1091         }
1092
1093         cur= MEM_callocN( blocks*curlen, "reconstruct");
1094         cpc= cur;
1095         cpo= data;
1096         for(a=0; a<blocks; a++) {
1097                 reconstruct_struct(newsdna, oldsdna, compflags, oldSDNAnr, cpo, curSDNAnr, cpc);
1098                 cpc+= curlen;
1099                 cpo+= oldlen;
1100         }
1101
1102         return cur;
1103 }
1104
1105 int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const char *name)
1106 {
1107         
1108         int SDNAnr= DNA_struct_find_nr(sdna, stype);
1109         short *spo= sdna->structs[SDNAnr];
1110         char *cp= find_elem(sdna, vartype, name, spo, NULL, NULL);
1111         return (int)((intptr_t)cp);
1112 }
1113