Blender V2.61 - r43446

makesdna.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00051 #define DNA_VERSION_DATE "FIXME-DNA_VERSION_DATE"
00052 
00053 #include <string.h>
00054 #include <stdlib.h>
00055 #include <stdio.h>
00056 
00057 #include "MEM_guardedalloc.h"
00058 #include "DNA_sdna_types.h"
00059 
00060 #include "BLO_sys_types.h" // for intptr_t support
00061 
00062 #define SDNA_MAX_FILENAME_LENGTH 255
00063 
00064 
00065 /* Included the path relative from /source/blender/ here, so we can move     */
00066 /* headers around with more freedom.                                         */
00067 static const char *includefiles[] = {
00068 
00069     // if you add files here, please add them at the end
00070     // of makesdna.c (this file) as well
00071 
00072     "DNA_listBase.h",
00073     "DNA_vec_types.h",
00074     "DNA_ID.h",
00075     "DNA_ipo_types.h",
00076     "DNA_key_types.h",
00077     "DNA_text_types.h",
00078     "DNA_packedFile_types.h",
00079     "DNA_camera_types.h",
00080     "DNA_image_types.h",
00081     "DNA_texture_types.h",
00082     "DNA_lamp_types.h",
00083     "DNA_material_types.h",
00084     "DNA_vfont_types.h",
00085     // if you add files here, please add them at the end
00086     // of makesdna.c (this file) as well
00087     "DNA_meta_types.h",
00088     "DNA_curve_types.h",
00089     "DNA_mesh_types.h",
00090     "DNA_meshdata_types.h",
00091     "DNA_modifier_types.h",
00092     "DNA_lattice_types.h",  
00093     "DNA_object_types.h",
00094     "DNA_object_force.h",
00095     "DNA_object_fluidsim.h",
00096     "DNA_world_types.h",
00097     "DNA_scene_types.h",
00098     "DNA_view3d_types.h",
00099     "DNA_view2d_types.h",   
00100     "DNA_space_types.h",
00101     "DNA_userdef_types.h",
00102     "DNA_screen_types.h",
00103     "DNA_sdna_types.h",
00104     // if you add files here, please add them at the end
00105     // of makesdna.c (this file) as well
00106     "DNA_fileglobal_types.h",
00107     "DNA_sequence_types.h",
00108     "DNA_effect_types.h",
00109     "DNA_outliner_types.h",
00110     "DNA_property_types.h",
00111     "DNA_sensor_types.h",
00112     "DNA_controller_types.h",
00113     "DNA_actuator_types.h",
00114     "DNA_sound_types.h",
00115     "DNA_group_types.h",
00116     "DNA_armature_types.h",
00117     "DNA_action_types.h",
00118     "DNA_constraint_types.h",
00119     "DNA_nla_types.h",
00120     "DNA_node_types.h",
00121     "DNA_color_types.h",
00122     "DNA_brush_types.h",
00123     "DNA_customdata_types.h",
00124     "DNA_particle_types.h",
00125     "DNA_cloth_types.h",
00126     "DNA_gpencil_types.h",
00127     // if you add files here, please add them at the end
00128     // of makesdna.c (this file) as well
00129     "DNA_windowmanager_types.h",
00130     "DNA_anim_types.h",
00131     "DNA_boid_types.h",
00132     "DNA_smoke_types.h",
00133     "DNA_speaker_types.h",
00134     "DNA_movieclip_types.h",
00135     "DNA_tracking_types.h",
00136     "DNA_dynamicpaint_types.h",
00137 
00138     // empty string to indicate end of includefiles
00139     ""
00140 };
00141 
00142 static int maxdata= 500000, maxnr= 50000;
00143 static int nr_names=0;
00144 static int nr_types=0;
00145 static int nr_structs=0;
00146 static char **names, *namedata;     /* at address names[a] is string a */
00147 static char **types, *typedata;     /* at address types[a] is string a */
00148 static short *typelens;             /* at typelens[a] is de length of type a */
00149 static short *alphalens;            /* contains sizes as they are calculated on the DEC Alpha (64 bits), infact any 64bit system */
00150 static short **structs, *structdata;/* at sp= structs[a] is the first address of a struct definition
00151                                        sp[0] is type number
00152                                        sp[1] is amount of elements
00153                                        sp[2] sp[3] is typenr,  namenr (etc) */
00162 static int debugSDNA = 0;
00163 static int additional_slen_offset;
00164 
00165 /* ************************************************************************** */
00166 /* Functions                                                                  */
00167 /* ************************************************************************** */
00168 
00174 static int add_type(const char *str, int len);
00175 
00180 static int add_name(const char *str);
00181 
00186 static short *add_struct(int namecode);
00187 
00192 static int preprocess_include(char *maindata, int len);
00193 
00197 static int convert_include(char *filename);
00198 
00202 static int arraysize(char *astr, int len);
00203 
00207 static int calculate_structlens(int);
00208 
00212 void dna_write(FILE *file, void *pntr, int size);
00213 
00217 void printStructLenghts(void);
00218 
00219 
00220 
00221 /* ************************************************************************** */
00222 /* Implementation                                                             */
00223 /* ************************************************************************** */
00224 
00225 /* ************************* MAKEN DNA ********************** */
00226 
00227 static int add_type(const char *str, int len)
00228 {
00229     int nr;
00230     char *cp;
00231     
00232     if(str[0]==0) return -1;
00233     
00234     /* search through type array */
00235     for(nr=0; nr<nr_types; nr++) {
00236         if(strcmp(str, types[nr])==0) {
00237             if (len) {
00238                 typelens[nr]= len;
00239                 alphalens[nr] = len;
00240             }
00241             return nr;
00242         }
00243     }
00244     
00245     /* append new type */
00246     if(nr_types==0) cp= typedata;
00247     else {
00248         cp= types[nr_types-1]+strlen(types[nr_types-1])+1;
00249     }
00250     strcpy(cp, str);
00251     types[nr_types]= cp;
00252     typelens[nr_types]= len;
00253     alphalens[nr_types]= len;
00254     
00255     if(nr_types>=maxnr) {
00256         printf("too many types\n");
00257         return nr_types-1;
00258     }
00259     nr_types++;
00260     
00261     return nr_types-1;
00262 }
00263 
00264 
00273 static int add_name(const char *str)
00274 {
00275     int nr, i, j, k;
00276     char *cp;
00277     char buf[255]; /* stupid limit, change it :) */
00278     const char *name;
00279 
00280     additional_slen_offset = 0;
00281     
00282     if(str[0]==0 /*  || (str[1]==0) */) return -1;
00283 
00284     if (str[0] == '(' && str[1] == '*') {
00285         /* we handle function pointer and special array cases here, e.g.
00286            void (*function)(...) and float (*array)[..]. the array case
00287            name is still converted to (array*)() though because it is that
00288            way in old dna too, and works correct with elementsize() */
00289         int isfuncptr = (strchr(str+1, '(')) != NULL;
00290 
00291         if (debugSDNA > 3) printf("\t\t\t\t*** Function pointer or multidim array pointer found\n");
00292         /* functionpointer: transform the type (sometimes) */
00293         i = 0;
00294 
00295         while (str[i] != ')') {
00296             buf[i] = str[i];
00297             i++;
00298         }
00299         
00300         /* Another number we need is the extra slen offset. This extra
00301          * offset is the overshoot after a space. If there is no
00302          * space, no overshoot should be calculated. */
00303         j = i; /* j at first closing brace */
00304 
00305         if (debugSDNA > 3) printf("first brace after offset %d\n", i);
00306 
00307         j++; /* j beyond closing brace ? */
00308         while ((str[j] != 0) && (str[j] != ')' )) {
00309             if (debugSDNA > 3) printf("seen %c ( %d) \n", str[j], str[j]);
00310             j++;
00311         }
00312         if (debugSDNA > 3) printf("seen %c ( %d) \n"
00313                                   "special after offset%d\n",
00314                                   str[j], str[j], j);
00315                 
00316         if (!isfuncptr) {
00317             /* multidimensional array pointer case */
00318             if(str[j] == 0) {
00319                 if (debugSDNA > 3) printf("offsetting for multidim array pointer\n");
00320             }
00321             else
00322                 printf("Error during tokening multidim array pointer\n");
00323         }
00324         else if (str[j] == 0 ) {
00325             if (debugSDNA > 3) printf("offsetting for space\n"); 
00326             /* get additional offset */
00327             k = 0;
00328             while (str[j] != ')') {
00329                 j++;
00330                 k++;
00331             }
00332             if (debugSDNA > 3) printf("extra offset %d\n", k);
00333             additional_slen_offset = k;
00334         } else if (str[j] == ')' ) {
00335             if (debugSDNA > 3) printf("offsetting for brace\n");
00336             ; /* don't get extra offset */
00337         } else {
00338             printf("Error during tokening function pointer argument list\n");
00339         }
00340                 
00341         /*
00342          * Put )(void) at the end? Maybe )(). Should check this with
00343          * old sdna. Actually, sometimes )(), sometimes )(void...)
00344          * Alas.. such is the nature of braindamage :(
00345          *
00346          * Sorted it out: always do )(), except for headdraw and
00347          * windraw, part of ScrArea. This is important, because some
00348          * linkers will treat different fp's differently when called
00349          * !!! This has to do with interference in byte-alignment and
00350          * the way args are pushed on the stack.
00351          *
00352          * */
00353         buf[i] = 0;
00354         if (debugSDNA > 3) printf("Name before chomping: %s\n", buf); 
00355         if ( (strncmp(buf,"(*headdraw", 10) == 0)
00356             || (strncmp(buf,"(*windraw", 9) == 0) ) {
00357             buf[i] = ')';
00358             buf[i+1] = '(';
00359             buf[i+2] = 'v'; 
00360             buf[i+3] = 'o';
00361             buf[i+4] = 'i';
00362             buf[i+5] = 'd';
00363             buf[i+6] = ')';
00364             buf[i+7] = 0;
00365         } else {
00366             buf[i] = ')';
00367             buf[i+1] = '(';
00368             buf[i+2] = ')';
00369             buf[i+3] = 0;
00370         }
00371         /* now precede with buf*/
00372         if (debugSDNA > 3)  printf("\t\t\t\t\tProposing fp name %s\n", buf);
00373         name = buf;
00374     } else {
00375         /* normal field: old code */
00376         name = str;
00377     }
00378     
00379     /* search name array */
00380     for(nr=0; nr<nr_names; nr++) {
00381         if(strcmp(name, names[nr])==0) {
00382             return nr;
00383         }
00384     }
00385     
00386     /* append new type */
00387     if(nr_names==0) cp= namedata;
00388     else {
00389         cp= names[nr_names-1]+strlen(names[nr_names-1])+1;
00390     }
00391     strcpy(cp, name);
00392     names[nr_names]= cp;
00393     
00394     if(nr_names>=maxnr) {
00395         printf("too many names\n");
00396         return nr_names-1;
00397     }
00398     nr_names++;
00399     
00400     return nr_names-1;
00401 }
00402 
00403 static short *add_struct(int namecode)
00404 {
00405     int len;
00406     short *sp;
00407 
00408     if(nr_structs==0) {
00409         structs[0]= structdata;
00410     }
00411     else {
00412         sp= structs[nr_structs-1];
00413         len= sp[1];
00414         structs[nr_structs]= sp+ 2*len+2;
00415     }
00416     
00417     sp= structs[nr_structs];
00418     sp[0]= namecode;
00419     
00420     if(nr_structs>=maxnr) {
00421         printf("too many structs\n");
00422         return sp;
00423     }
00424     nr_structs++;
00425     
00426     return sp;
00427 }
00428 
00429 static int preprocess_include(char *maindata, int len)
00430 {
00431     int a, newlen, comment = 0;
00432     char *cp, *temp, *md;
00433     
00434     /* note: len + 1, last character is a dummy to prevent
00435      * comparisons using uninitialized memory */
00436     temp= MEM_mallocN(len + 1, "preprocess_include");
00437     temp[len]= ' ';
00438 
00439     memcpy(temp, maindata, len);
00440     
00441     // remove all c++ comments
00442     /* replace all enters/tabs/etc with spaces */
00443     cp= temp;
00444     a= len;
00445     comment = 0;
00446     while(a--) {
00447         if(cp[0]=='/' && cp[1]=='/') {
00448             comment = 1;
00449         } else if (*cp<32) {
00450             comment = 0;
00451         }
00452         if (comment || *cp<32 || *cp>128 ) *cp= 32;
00453         cp++;
00454     }
00455     
00456 
00457     /* data from temp copy to maindata, remove comments and double spaces */
00458     cp= temp;
00459     md= maindata;
00460     newlen= 0;
00461     comment= 0;
00462     a= len;
00463     while(a--) {
00464         
00465         if(cp[0]=='/' && cp[1]=='*') {
00466             comment= 1;
00467             cp[0]=cp[1]= 32;
00468         }
00469         if(cp[0]=='*' && cp[1]=='/') {
00470             comment= 0;
00471             cp[0]=cp[1]= 32;
00472         }
00473 
00474         /* do not copy when: */
00475         if(comment);
00476         else if( cp[0]==' ' && cp[1]==' ' );
00477         else if( cp[-1]=='*' && cp[0]==' ' );   /* pointers with a space */
00478 
00479         /* skip special keywords */
00480         else if (strncmp("DNA_DEPRECATED", cp, 14)==0) {
00481             /* single values are skipped already, so decrement 1 less */
00482             a -= 13;
00483             cp += 13;
00484         }
00485         else {
00486             md[0]= cp[0];
00487             md++;
00488             newlen++;
00489         }
00490         cp++;
00491     }
00492     
00493     MEM_freeN(temp);
00494     return newlen;
00495 }
00496 
00497 static void *read_file_data(char *filename, int *len_r)
00498 {
00499 #ifdef WIN32
00500     FILE *fp= fopen(filename, "rb");
00501 #else
00502     FILE *fp= fopen(filename, "r");
00503 #endif
00504     void *data;
00505 
00506     if (!fp) {
00507         *len_r= -1;
00508         return NULL;
00509     }
00510 
00511     fseek(fp, 0L, SEEK_END);
00512     *len_r= ftell(fp);
00513     fseek(fp, 0L, SEEK_SET);
00514 
00515     data= MEM_mallocN(*len_r, "read_file_data");
00516     if (!data) {
00517         *len_r= -1;
00518         fclose(fp);
00519         return NULL;
00520     }
00521 
00522     if (fread(data, *len_r, 1, fp)!=1) {
00523         *len_r= -1;
00524         MEM_freeN(data);
00525         fclose(fp);
00526         return NULL;
00527     }
00528     
00529     fclose(fp);
00530     return data;
00531 }
00532 
00533 static int convert_include(char *filename)
00534 {
00535     /* read include file, skip structs with a '#' before it.
00536        store all data in temporal arrays.
00537     */
00538     int filelen, count, overslaan, slen, type, name, strct;
00539     short *structpoin, *sp;
00540     char *maindata, *mainend, *md, *md1;
00541     
00542     md= maindata= read_file_data(filename, &filelen);
00543     if (filelen==-1) {
00544         printf("Can't read file %s\n", filename);
00545         return 1;
00546     }
00547 
00548     filelen= preprocess_include(maindata, filelen);
00549     mainend= maindata+filelen-1;
00550 
00551     /* we look for '{' and then back to 'struct' */
00552     count= 0;
00553     overslaan= 0;
00554     while(count<filelen) {
00555         
00556         /* code for skipping a struct: two hashes on 2 lines. (preprocess added a space) */
00557         if(md[0]=='#' && md[1]==' ' && md[2]=='#') {
00558             overslaan= 1;
00559         }
00560         
00561         if(md[0]=='{') {
00562             md[0]= 0;
00563             if(overslaan) {
00564                 overslaan= 0;
00565             }
00566             else {
00567                 if(md[-1]==' ') md[-1]= 0;
00568                 md1= md-2;
00569                 while( *md1!=32) md1--;     /* to beginning of word */
00570                 md1++;
00571                 
00572                 /* we've got a struct name when... */
00573                 if( strncmp(md1-7, "struct", 6)==0 ) {
00574 
00575                     
00576                     strct= add_type(md1, 0);
00577                     structpoin= add_struct(strct);
00578                     sp= structpoin+2;
00579 
00580                     if (debugSDNA > 1) printf("\t|\t|-- detected struct %s\n", types[strct]);
00581 
00582                     /* first lets make it all nice strings */
00583                     md1= md+1;
00584                     while(*md1 != '}') {
00585                         if(md1>mainend) break;
00586                         
00587                         if(*md1==',' || *md1==' ') *md1= 0;
00588                         md1++;
00589                     }
00590                     
00591                     /* read types and names until first character that is not '}' */
00592                     md1= md+1;
00593                     while( *md1 != '}' ) {
00594                         if(md1>mainend) break;
00595                         
00596                         /* skip when it says 'struct' or 'unsigned' or 'const' */
00597                         if(*md1) {
00598                             if( strncmp(md1, "struct", 6)==0 ) md1+= 7;
00599                             if( strncmp(md1, "unsigned", 8)==0 ) md1+= 9;
00600                             if( strncmp(md1, "const", 5)==0 ) md1+= 6;
00601                             
00602                             /* we've got a type! */
00603                             type= add_type(md1, 0);
00604 
00605                             if (debugSDNA > 1) printf("\t|\t|\tfound type %s (", md1);
00606 
00607                             md1+= strlen(md1);
00608 
00609                             
00610                             /* read until ';' */
00611                             while( *md1 != ';' ) {
00612                                 if(md1>mainend) break;
00613                                 
00614                                 if(*md1) {
00615                                     /* We've got a name. slen needs
00616                                      * correction for function
00617                                      * pointers! */
00618                                     slen= (int) strlen(md1);
00619                                     if( md1[slen-1]==';' ) {
00620                                         md1[slen-1]= 0;
00621 
00622 
00623                                         name= add_name(md1);
00624                                         slen += additional_slen_offset;
00625                                         sp[0]= type;
00626                                         sp[1]= name;
00627 
00628                                         if ((debugSDNA>1) && (names[name] != NULL)) printf("%s |", names[name]);
00629 
00630                                         structpoin[1]++;
00631                                         sp+= 2;
00632                                                                                     
00633                                         md1+= slen;
00634                                         break;
00635                                     }
00636                                     
00637 
00638                                     name= add_name(md1);
00639                                     slen += additional_slen_offset;
00640 
00641                                     sp[0]= type;
00642                                     sp[1]= name;
00643                                     if ((debugSDNA > 1) && (names[name] != NULL)) printf("%s ||", names[name]);
00644 
00645                                     structpoin[1]++;
00646                                     sp+= 2;
00647                                     
00648                                     md1+= slen;
00649                                 }
00650                                 md1++;
00651                             }
00652 
00653                             if (debugSDNA > 1) printf(")\n");
00654 
00655                         }
00656                         md1++;
00657                     }
00658                 }
00659             }
00660         }
00661         count++;
00662         md++;
00663     }
00664     
00665     MEM_freeN(maindata);
00666 
00667     return 0;
00668 }
00669 
00670 static int arraysize(char *astr, int len)
00671 {
00672     int a, mul=1;
00673     char str[100], *cp=NULL;
00674 
00675     memcpy(str, astr, len+1);
00676     
00677     for(a=0; a<len; a++) {
00678         if( str[a]== '[' ) {
00679             cp= &(str[a+1]);
00680         }
00681         else if( str[a]==']' && cp) {
00682             str[a]= 0;
00683             /* if 'cp' is a preprocessor definition, it will evaluate to 0,
00684              * the caller needs to check for this case and throw an error */
00685             mul*= atoi(cp);
00686         }
00687     }
00688     
00689     return mul;
00690 }
00691 
00692 static int calculate_structlens(int firststruct)
00693 {
00694     int a, b, len, alphalen, unknown= nr_structs, lastunknown, structtype, type, mul, namelen;
00695     short *sp, *structpoin;
00696     char *cp;
00697     int has_pointer, dna_error = 0;
00698         
00699     while(unknown) {
00700         lastunknown= unknown;
00701         unknown= 0;
00702         
00703         /* check all structs... */
00704         for(a=0; a<nr_structs; a++) {
00705             structpoin= structs[a];
00706             structtype= structpoin[0];
00707 
00708             /* when length is not known... */
00709             if(typelens[structtype]==0) {
00710                 
00711                 sp= structpoin+2;
00712                 len= 0;
00713                 alphalen = 0;
00714                 has_pointer = 0;
00715                 
00716                 /* check all elements in struct */
00717                 for(b=0; b<structpoin[1]; b++, sp+=2) {
00718                     type= sp[0];
00719                     cp= names[sp[1]];
00720 
00721                     namelen= (int) strlen(cp);
00722                     /* is it a pointer or function pointer? */
00723                     if(cp[0]=='*' || cp[1]=='*') {
00724                         has_pointer = 1;
00725                         /* has the name an extra length? (array) */
00726                         mul= 1;
00727                         if( cp[namelen-1]==']') mul= arraysize(cp, namelen);
00728 
00729                         if (mul == 0) {
00730                             printf("Zero array size found or could not parse %s: '%.*s'\n", types[structtype], namelen + 1, cp);
00731                             dna_error = 1;
00732                         }
00733 
00734                         /* 4-8 aligned/ */
00735                         if(sizeof(void *) == 4) {
00736                             if (len % 4) {
00737                                 printf("Align pointer error in struct (len4): %s %s\n", types[structtype], cp);
00738                                 dna_error = 1;
00739                             }
00740                         } else {
00741                             if (len % 8) {
00742                                 printf("Align pointer error in struct (len8): %s %s\n", types[structtype], cp);
00743                                 dna_error = 1;
00744                             }
00745                         }
00746 
00747                         if (alphalen % 8) {
00748                             printf("Align pointer error in struct (alphalen8): %s %s\n", types[structtype],cp);
00749                             dna_error = 1;
00750                         }
00751 
00752                         len += sizeof(void *) * mul;
00753                         alphalen += 8 * mul;
00754 
00755                     } else if(cp[0]=='[') {
00756                         /* parsing can cause names "var" and "[3]" to be found for "float var [3]" ... */
00757                         printf("Parse error in struct, invalid member name: %s %s\n", types[structtype], cp);
00758                         dna_error = 1;
00759                     } else if( typelens[type] ) {
00760                         /* has the name an extra length? (array) */
00761                         mul= 1;
00762                         if( cp[namelen-1]==']') mul= arraysize(cp, namelen);
00763 
00764                         if (mul == 0) {
00765                             printf("Zero array size found or could not parse %s: '%.*s'\n", types[structtype], namelen + 1, cp);
00766                             dna_error = 1;
00767                         }
00768 
00769                         /* struct alignment */
00770                         if(type >= firststruct) {
00771                             if(sizeof(void *)==8 && (len % 8) ) {
00772                                 printf("Align struct error: %s %s\n", types[structtype],cp);
00773                                 dna_error = 1;
00774                             }
00775                         }
00776                         
00777                         /* 2-4 aligned/ */
00778                         if(typelens[type]>3 && (len % 4) ) {
00779                             printf("Align 4 error in struct: %s %s (add %d padding bytes)\n", types[structtype], cp, len%4);
00780                             dna_error = 1;
00781                         }
00782                         else if(typelens[type]==2 && (len % 2) ) {
00783                             printf("Align 2 error in struct: %s %s (add %d padding bytes)\n", types[structtype], cp, len%2);
00784                             dna_error = 1;
00785                         }
00786 
00787                         len += mul*typelens[type];
00788                         alphalen += mul * alphalens[type];
00789                         
00790                     } else {
00791                         len= 0;
00792                         alphalen = 0;
00793                         break;
00794                     }
00795                 }
00796                 
00797                 if (len==0) {
00798                     unknown++;
00799                 } else {
00800                     typelens[structtype]= len;
00801                     alphalens[structtype]= alphalen;
00802                     // two ways to detect if a struct contains a pointer:
00803                     // has_pointer is set or alphalen != len
00804                     if (has_pointer || alphalen != len) {
00805                         if (alphalen % 8) {
00806                             printf("Sizeerror 8 in struct: %s (add %d bytes)\n", types[structtype], alphalen%8);
00807                             dna_error = 1;
00808                         }
00809                     }
00810                     
00811                     if(len % 4) {
00812                         printf("Sizeerror 4 in struct: %s (add %d bytes)\n", types[structtype], len%4);
00813                         dna_error = 1;
00814                     }
00815                     
00816                 }
00817             }
00818         }
00819         
00820         if(unknown==lastunknown) break;
00821     }
00822     
00823     if(unknown) {
00824         printf("ERROR: still %d structs unknown\n", unknown);
00825 
00826         if (debugSDNA) {
00827             printf("*** Known structs : \n");
00828             
00829             for(a=0; a<nr_structs; a++) {
00830                 structpoin= structs[a];
00831                 structtype= structpoin[0];
00832                 
00833                 /* length unknown */
00834                 if(typelens[structtype]!=0) {
00835                     printf("  %s\n", types[structtype]);
00836                 }
00837             }
00838         }
00839 
00840             
00841         printf("*** Unknown structs : \n");
00842             
00843         for(a=0; a<nr_structs; a++) {
00844             structpoin= structs[a];
00845             structtype= structpoin[0];
00846 
00847             /* length unkown yet */
00848             if(typelens[structtype]==0) {
00849                 printf("  %s\n", types[structtype]);
00850             }
00851         }
00852     }
00853 
00854     return(dna_error);
00855 }
00856 
00857 #define MAX_DNA_LINE_LENGTH 20
00858 
00859 void dna_write(FILE *file, void *pntr, int size)
00860 {
00861     static int linelength = 0;
00862     int i;
00863     char *data;
00864 
00865     data = (char *) pntr;
00866     
00867     for (i = 0 ; i < size ; i++)
00868     {
00869         fprintf(file, "%d,", data[i]);
00870         linelength++;
00871         if (linelength >= MAX_DNA_LINE_LENGTH) {
00872             fprintf(file, "\n");
00873             linelength = 0;
00874         }
00875     }
00876 }
00877 
00878 void printStructLenghts(void)
00879 {
00880     int a, unknown= nr_structs, structtype;
00881     /*int lastunknown;*/ /*UNUSED*/
00882     short *structpoin;
00883     printf("\n\n*** All detected structs:\n");
00884 
00885     while(unknown) {
00886         /*lastunknown= unknown;*/ /*UNUSED*/
00887         unknown= 0;
00888         
00889         /* check all structs... */
00890         for(a=0; a<nr_structs; a++) {
00891             structpoin= structs[a];
00892             structtype= structpoin[0];
00893             printf("\t%s\t:%d\n", types[structtype], typelens[structtype]);
00894         }
00895     }
00896 
00897     printf("*** End of list\n");
00898 
00899 }
00900 
00901 
00902 static int make_structDNA(char *baseDirectory, FILE *file)
00903 {
00904     int len, i;
00905     short *sp;
00906     /* str contains filenames. Since we now include paths, I stretched       */
00907     /* it a bit. Hope this is enough :) -nzc-                                */
00908     char str[SDNA_MAX_FILENAME_LENGTH], *cp;
00909     int firststruct;
00910     
00911     if (debugSDNA > -1) {
00912         fflush(stdout);
00913         printf("Running makesdna at debug level %d\n", debugSDNA);
00914         printf("\tProgram version: %s\n", DNA_VERSION_DATE);
00915     }
00916         
00917     /* the longest known struct is 50k, so we assume 100k is sufficent! */
00918     namedata= MEM_callocN(maxdata, "namedata");
00919     typedata= MEM_callocN(maxdata, "typedata");
00920     structdata= MEM_callocN(maxdata, "structdata");
00921     
00922     /* a maximum of 5000 variables, must be sufficient? */
00923     names= MEM_callocN(sizeof(char *)*maxnr, "names");
00924     types= MEM_callocN(sizeof(char *)*maxnr, "types");
00925     typelens= MEM_callocN(sizeof(short)*maxnr, "typelens");
00926     alphalens= MEM_callocN(sizeof(short)*maxnr, "alphalens");
00927     structs= MEM_callocN(sizeof(short)*maxnr, "structs");
00928 
00929     /* insertion of all known types */
00930     /* watch it: uint is not allowed! use in structs an unsigned int */
00931     /* watch it: sizes must match DNA_elem_type_size() */
00932     add_type("char", 1);    /* SDNA_TYPE_CHAR */
00933     add_type("uchar", 1);   /* SDNA_TYPE_UCHAR */
00934     add_type("short", 2);   /* SDNA_TYPE_SHORT */
00935     add_type("ushort", 2);  /* SDNA_TYPE_USHORT */
00936     add_type("int", 4);     /* SDNA_TYPE_INT */
00937     add_type("long", 4);    /* SDNA_TYPE_LONG */        /* should it be 8 on 64 bits? */
00938     add_type("ulong", 4);   /* SDNA_TYPE_ULONG */
00939     add_type("float", 4);   /* SDNA_TYPE_FLOAT */
00940     add_type("double", 8);  /* SDNA_TYPE_DOUBLE */
00941     add_type("int64_t", 8); /* SDNA_TYPE_INT64 */
00942     add_type("uint64_t", 8); /* SDNA_TYPE_UINT64 */
00943     add_type("void", 0);    /* SDNA_TYPE_VOID */
00944 
00945     // the defines above shouldn't be output in the padding file...
00946     firststruct = nr_types;
00947     
00948     /* add all include files defined in the global array                     */
00949     /* Since the internal file+path name buffer has limited length, I do a   */
00950     /* little test first...                                                  */
00951     /* Mind the breaking condition here!                                     */
00952     if (debugSDNA) printf("\tStart of header scan:\n"); 
00953     for (i = 0; strlen(includefiles[i]); i++) {
00954         sprintf(str, "%s%s", baseDirectory, includefiles[i]);
00955           if (debugSDNA) printf("\t|-- Converting %s\n", str); 
00956         if (convert_include(str)) {
00957             return (1);
00958         }
00959     }
00960     if (debugSDNA) printf("\tFinished scanning %d headers.\n", i); 
00961 
00962     if (calculate_structlens(firststruct)) {
00963         // error
00964         return(1);
00965     }
00966 
00967     /* FOR DEBUG */
00968     if (debugSDNA > 1)
00969     {
00970         int a,b;
00971 /*          short *elem; */
00972         short num_types;
00973 
00974         printf("nr_names %d nr_types %d nr_structs %d\n", nr_names, nr_types, nr_structs);
00975         for(a=0; a<nr_names; a++) { 
00976             printf(" %s \n", names[a]);
00977         }
00978         printf("\n");
00979         
00980         sp= typelens;
00981         for(a=0; a<nr_types; a++, sp++) { 
00982             printf(" %s %d\n", types[a], *sp);
00983         }
00984         printf("\n");
00985         
00986         for(a=0; a<nr_structs; a++) {
00987             sp= structs[a];
00988             printf(" struct %s elems: %d size: %d\n", types[sp[0]], sp[1],typelens[sp[0]]);
00989             num_types  = sp[1];
00990             sp+= 2;
00991             /* ? num_types was elem? */
00992             for(b=0; b< num_types; b++, sp+= 2) {
00993                 printf("   %s %s\n", types[sp[0]], names[sp[1]]);
00994             }
00995         }
00996     }
00997 
00998     /* file writing */
00999 
01000     if (debugSDNA > -1) printf("Writing file ... ");
01001         
01002     if(nr_names==0 || nr_structs==0);
01003     else {
01004         strcpy(str, "SDNA");
01005         dna_write(file, str, 4);
01006         
01007         /* write names */
01008         strcpy(str, "NAME");
01009         dna_write(file, str, 4);
01010         len= nr_names;
01011         dna_write(file, &len, 4);
01012         
01013         /* calculate size of datablock with strings */
01014         cp= names[nr_names-1];
01015         cp+= strlen(names[nr_names-1]) + 1;         /* +1: null-terminator */
01016         len= (intptr_t) (cp - (char*) names[0]);
01017         len= (len+3) & ~3;
01018         dna_write(file, names[0], len);
01019         
01020         /* write TYPES */
01021         strcpy(str, "TYPE");
01022         dna_write(file, str, 4);
01023         len= nr_types;
01024         dna_write(file, &len, 4);
01025     
01026         /* calculate datablock size */
01027         cp= types[nr_types-1];
01028         cp+= strlen(types[nr_types-1]) + 1;     /* +1: null-terminator */
01029         len= (intptr_t) (cp - (char*) types[0]);
01030         len= (len+3) & ~3;
01031         
01032         dna_write(file, types[0], len);
01033         
01034         /* WRITE TYPELENGTHS */
01035         strcpy(str, "TLEN");
01036         dna_write(file, str, 4);
01037         
01038         len= 2*nr_types;
01039         if(nr_types & 1) len+= 2;
01040         dna_write(file, typelens, len);
01041         
01042         /* WRITE STRUCTS */
01043         strcpy(str, "STRC");
01044         dna_write(file, str, 4);
01045         len= nr_structs;
01046         dna_write(file, &len, 4);
01047     
01048         /* calc datablock size */
01049         sp= structs[nr_structs-1];
01050         sp+= 2+ 2*( sp[1] );
01051         len= (intptr_t) ((char*) sp - (char*) structs[0]);
01052         len= (len+3) & ~3;
01053         
01054         dna_write(file, structs[0], len);
01055     
01056         /* a simple dna padding test */
01057         if (0) {
01058             FILE *fp;
01059             int a;
01060             
01061             fp= fopen("padding.c", "w");
01062             if(fp==NULL);
01063             else {
01064 
01065                 // add all include files defined in the global array
01066                 for (i = 0; strlen(includefiles[i]); i++) {
01067                     fprintf(fp, "#include \"%s%s\"\n", baseDirectory, includefiles[i]);
01068                 }
01069 
01070                 fprintf(fp, "main(){\n");
01071                 sp = typelens;
01072                 sp += firststruct;
01073                 for(a=firststruct; a<nr_types; a++, sp++) { 
01074                     if(*sp) {
01075                         fprintf(fp, "\tif(sizeof(struct %s) - %d) printf(\"ALIGN ERROR:", types[a], *sp);
01076                         fprintf(fp, "%%d %s %d ", types[a], *sp);
01077                         fprintf(fp, "\\n\",  sizeof(struct %s) - %d);\n", types[a], *sp);
01078                     }
01079                 }
01080                 fprintf(fp, "}\n");
01081                 fclose(fp);
01082             }
01083         }
01084         /*  end end padding test */
01085     }
01086     
01087     
01088     MEM_freeN(namedata);
01089     MEM_freeN(typedata);
01090     MEM_freeN(structdata);
01091     MEM_freeN(names);
01092     MEM_freeN(types);
01093     MEM_freeN(typelens);
01094     MEM_freeN(alphalens);
01095     MEM_freeN(structs);
01096 
01097     if (debugSDNA > -1) printf("done.\n");
01098     
01099     return(0);
01100 }
01101 
01102 /* ************************* END MAKE DNA ********************** */
01103 
01104 static void make_bad_file(const char *file, int line)
01105 {
01106     FILE *fp= fopen(file, "w");
01107     fprintf(fp, "#error \"Error! can't make correct DNA.c file from %s:%d, STUPID!\"\n", __FILE__, line);
01108     fclose(fp);
01109 }
01110 
01111 #ifndef BASE_HEADER
01112 #define BASE_HEADER "../"
01113 #endif
01114 
01115 int main(int argc, char ** argv)
01116 {
01117     FILE *file;
01118     int return_status = 0;
01119 
01120     if (argc!=2 && argc!=3) {
01121         printf("Usage: %s outfile.c [base directory]\n", argv[0]);
01122         return_status = 1;
01123     } else {
01124         file = fopen(argv[1], "w");
01125         if (!file) {
01126             printf ("Unable to open file: %s\n", argv[1]);
01127             return_status = 1;
01128         } else {
01129             char baseDirectory[256];
01130 
01131             if (argc==3) {
01132                 strcpy(baseDirectory, argv[2]);
01133             } else {
01134                 strcpy(baseDirectory, BASE_HEADER);
01135             }
01136 
01137             fprintf (file, "unsigned char DNAstr[]= {\n");
01138             if (make_structDNA(baseDirectory, file)) {
01139                 // error
01140                 fclose(file);
01141                 make_bad_file(argv[1], __LINE__);
01142                 return_status = 1;
01143             } else {
01144                 fprintf(file, "};\n");
01145                 fprintf(file, "int DNAlen= sizeof(DNAstr);\n");
01146     
01147                 fclose(file);
01148             }
01149         }
01150     }
01151 
01152         
01153     return(return_status);
01154 }
01155 
01156 // include files for automatic dependancies
01157 #include "DNA_listBase.h"
01158 #include "DNA_vec_types.h"
01159 #include "DNA_ID.h"
01160 #include "DNA_ipo_types.h"
01161 #include "DNA_key_types.h"
01162 #include "DNA_text_types.h"
01163 #include "DNA_packedFile_types.h"
01164 #include "DNA_camera_types.h"
01165 #include "DNA_image_types.h"
01166 #include "DNA_texture_types.h"
01167 #include "DNA_lamp_types.h"
01168 #include "DNA_material_types.h"
01169 #include "DNA_vfont_types.h"
01170 #include "DNA_meta_types.h"
01171 #include "DNA_curve_types.h"
01172 #include "DNA_mesh_types.h"
01173 #include "DNA_meshdata_types.h"
01174 #include "DNA_modifier_types.h"
01175 #include "DNA_lattice_types.h"  
01176 #include "DNA_object_types.h"
01177 #include "DNA_object_force.h"
01178 #include "DNA_object_fluidsim.h"
01179 #include "DNA_world_types.h"
01180 #include "DNA_scene_types.h"
01181 #include "DNA_view3d_types.h"
01182 #include "DNA_view2d_types.h"   
01183 #include "DNA_space_types.h"
01184 #include "DNA_userdef_types.h"
01185 #include "DNA_screen_types.h"
01186 #include "DNA_sdna_types.h"
01187 #include "DNA_fileglobal_types.h"
01188 #include "DNA_sequence_types.h"
01189 #include "DNA_effect_types.h"
01190 #include "DNA_outliner_types.h"
01191 #include "DNA_property_types.h"
01192 #include "DNA_sensor_types.h"
01193 #include "DNA_controller_types.h"
01194 #include "DNA_actuator_types.h"
01195 #include "DNA_sound_types.h"
01196 #include "DNA_group_types.h"
01197 #include "DNA_armature_types.h"
01198 #include "DNA_action_types.h"
01199 #include "DNA_constraint_types.h"
01200 #include "DNA_nla_types.h"
01201 #include "DNA_node_types.h"
01202 #include "DNA_color_types.h"
01203 #include "DNA_brush_types.h"
01204 #include "DNA_customdata_types.h"
01205 #include "DNA_particle_types.h"
01206 #include "DNA_cloth_types.h"
01207 #include "DNA_gpencil_types.h"
01208 #include "DNA_windowmanager_types.h"
01209 #include "DNA_anim_types.h"
01210 #include "DNA_boid_types.h"
01211 #include "DNA_smoke_types.h"
01212 #include "DNA_speaker_types.h"
01213 #include "DNA_movieclip_types.h"
01214 #include "DNA_tracking_types.h"
01215 #include "DNA_dynamicpaint_types.h"
01216 /* end of list */