From 12315f4d0e0ae993805f141f64cb8c73c5297311 Mon Sep 17 00:00:00 2001 From: Hans Lambermont Date: Sat, 12 Oct 2002 11:37:38 +0000 Subject: Initial revision --- source/blender/makesdna/intern/makesdna.c | 1121 +++++++++++++++++++++++++++++ 1 file changed, 1121 insertions(+) create mode 100644 source/blender/makesdna/intern/makesdna.c (limited to 'source/blender/makesdna/intern/makesdna.c') diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c new file mode 100644 index 00000000000..98a23472a9c --- /dev/null +++ b/source/blender/makesdna/intern/makesdna.c @@ -0,0 +1,1121 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + * Struct muncher for making SDNA + * + * Originally by Ton, some mods by Frank, and some cleaning and + * extension by Nzc. + * + * Makesdna creates a .c file with a long string of numbers that + * encode the Blender file format. It is fast, because it is basically + * a binary dump. There are some details to mind when reconstructing + * the file (endianness and byte-alignment). + * + * This little program scans all structs that need to be serialized, + * and determined the names and types of all members. It calculates + * how much memory (on disk or in ram) is needed to store that struct, + * and the offsets for reaching a particular one. + * + * There is a facility to get verbose output from sdna. Search for + * debugSDNA. This int can be set to 0 (no output) to some int. Higher + * numbers give more output. + * */ + +#define DNA_VERSION_DATE "$Id$" + +#include +#include +#include + +#include "MEM_guardedalloc.h" + +#include "DNA_sdna_types.h" + +#define SDNA_MAX_FILENAME_LENGTH 255 + + +/* Included the path relative from /source/blender/ here, so we can move */ +/* headers around with more freedom. */ +char *includefiles[] = { + + // if you add files here, please add them at the end + // of makesdna.c (this file) as well + + "DNA_listBase.h", + "DNA_vec_types.h", + "DNA_ID.h", + "DNA_ipo_types.h", + "DNA_key_types.h", + "DNA_scriptlink_types.h", + "DNA_text_types.h", + "DNA_packedFile_types.h", + "DNA_camera_types.h", + "DNA_image_types.h", + "DNA_texture_types.h", + "DNA_lamp_types.h", + "DNA_wave_types.h", + "DNA_material_types.h", + "DNA_vfont_types.h", + // if you add files here, please add them at the end + // of makesdna.c (this file) as well + "DNA_meta_types.h", + "DNA_curve_types.h", + "DNA_mesh_types.h", + "DNA_lattice_types.h", + "DNA_object_types.h", + "DNA_world_types.h", + "DNA_radio_types.h", + "DNA_scene_types.h", + "DNA_view3d_types.h", + "DNA_view2d_types.h", + "DNA_space_types.h", + "DNA_userdef_types.h", + "DNA_screen_types.h", + "DNA_sdna_types.h", + // if you add files here, please add them at the end + // of makesdna.c (this file) as well + "DNA_fileglobal_types.h", + "DNA_sequence_types.h", + "DNA_effect_types.h", + "DNA_ika_types.h", + "DNA_oops_types.h", + "DNA_property_types.h", + "DNA_sensor_types.h", + "DNA_controller_types.h", + "DNA_actuator_types.h", + "DNA_sound_types.h", + "DNA_group_types.h", + "DNA_armature_types.h", + "DNA_action_types.h", + "DNA_constraint_types.h", + "DNA_nla_types.h", + // if you add files here, please add them at the end + // of makesdna.c (this file) as well + + // empty string to indicate end of includefiles + "" +}; + +int maxdata= 500000, maxnr= 50000; +int nr_names=0; +int nr_types=0; +int nr_structs=0; +char **names, *namedata; /* op adres names[a] staat string a */ +char **types, *typedata; /* op adres types[a] staat string a */ +short *typelens; /* op typelens[a] staat de lengte van type a */ +short *alphalens; /* contains sizes as they are calculated on the alpha */ +short **structs, *structdata; /* op sp= structs[a] staat eerste adres structdefinitie + sp[0] is typenummer + sp[1] is aantal elementen + sp[2] sp[3] is typenr, namenr (enz) */ +/* + * debugSDNA: + * - 0 = no output, except errors + * - 1 = detail actions + * - 2 = full trace, tell which names and types were found + * - 4 = full trace, plus all gritty details + */ +int debugSDNA = 0; +int additional_slen_offset; + +/* ************************************************************************** */ +/* Functions */ +/* ************************************************************************** */ + +/** + * Add type to struct indexed by , if it was not yet found. + */ +int add_type(char *str, int len); + +/** + * Add variable to + */ +int add_name(char *str); + +/** + * Search whether this structure type was already found, and if not, + * add it. + */ +short *add_struct(int namecode); + +/** + * Remove comments from this buffer. Assumes that the buffer refers to + * ascii-code text. + */ +int preprocess_include(char *maindata, int len); + +/** + * Scan this file for serializable types. + */ +int convert_include(char *filename); + +/** + * Determine how many bytes are needed for an array. + */ +int arraysize(char *astr, int len); + +/** + * Determine how many bytes are needed for each struct. + */ +int calculate_structlens(void); + +/** + * Construct the DNA.c file + */ +void dna_write(FILE *file, void *pntr, int size); + +/** + * Report all structures found so far, and print their lenghts. + */ +void printStructLenghts(void); + +/** + * + */ +int make_structDNA(FILE *file); + +/** + * + */ +int main(int argc, char ** argv); + + + +/* ************************************************************************** */ +/* Implementation */ +/* ************************************************************************** */ + +/* ************************* MAKEN DNA ********************** */ + +int add_type(char *str, int len) +{ + int nr; + char *cp; + + if(str[0]==0) return -1; + + /* zoek typearray door */ + for(nr=0; nr=maxnr) { + printf("too many types\n"); + return nr_types-1;; + } + nr_types++; + + return nr_types-1; +} + + +/** + * + * Because of the weird way of tokenizing, we have to 'cast' function + * pointers to ... (*f)(), whatever the original signature. In fact, + * we add name and type at the same time... There are two special + * cases, unfortunately. These are explicitly checked. + * + * */ +int add_name(char *str) +{ + int nr, i, j, k; + char *cp; + char buf[255]; /* stupid limit, change it :) */ + char *name; + + additional_slen_offset = 0; + + if((str[0]==0) /* || (str[1]==0) */) return -1; + + if (str[0] == '(' && str[1] == '*') { + if (debugSDNA > 3) printf("\t\t\t\t*** Function pointer found\n"); + /* functionpointer: transform the type (sometimes) */ + i = 0; + j = 0; + + while (str[i] != ')') { + buf[i] = str[i]; + i++; + } + + /* Another number we need is the extra slen offset. This extra + * offset is the overshoot after a space. If there is no + * space, no overshoot should be calculated. */ + j = i; /* j at first closing brace */ + + if (debugSDNA > 3) printf("first brace after offset %d\n", i); + + j++; /* j beyond closing brace ? */ + while ((str[j] != 0) && (str[j] != ')' )) { + if (debugSDNA > 3) printf("seen %c ( %d) \n", str[j], str[j]); + j++; + } + if (debugSDNA > 3) printf("seen %c ( %d) \n", str[j], str[j]); + if (debugSDNA > 3) printf("special after offset %d\n", j); + + if (str[j] == 0 ) { + if (debugSDNA > 3) printf("offsetting for space\n"); + /* get additional offset */ + k = 0; + while (str[j] != ')') { + j++; + k++; + } + if (debugSDNA > 3) printf("extra offset %d\n", k); + additional_slen_offset = k; + } else if (str[j] == ')' ) { + if (debugSDNA > 3) printf("offsetting for brace\n"); + ; /* don't get extra offset */ + } else { + printf("Error during tokening function pointer argument list\n"); + } + + /* + * Put )(void) at the end? Maybe )(). Should check this with + * old sdna. Actually, sometimes )(), sometimes )(void...) + * Alas.. such is the nature of braindamage :( + * + * Sorted it out: always do )(), except for headdraw and + * windraw, part of ScrArea. This is important, because some + * linkers will treat different fp's differently when called + * !!! This has to do with interference in byte-alignment and + * the way args are pushed on the stack. + * + * */ + buf[i] = 0; + if (debugSDNA > 3) printf("Name before chomping: %s\n", buf); + if ( (strncmp(buf,"(*headdraw", 10) == 0) + || (strncmp(buf,"(*windraw", 9) == 0) ) { + buf[i] = ')'; + buf[i+1] = '('; + buf[i+2] = 'v'; + buf[i+3] = 'o'; + buf[i+4] = 'i'; + buf[i+5] = 'd'; + buf[i+6] = ')'; + buf[i+7] = 0; + } else { + buf[i] = ')'; + buf[i+1] = '('; + buf[i+2] = ')'; + buf[i+3] = 0; + } + /* now precede with buf*/ + if (debugSDNA > 3) printf("\t\t\t\t\tProposing fp name %s\n", buf); + name = buf; + } else { + /* normal field: old code */ + name = str; + } + + /* zoek name array door */ + for(nr=0; nr=maxnr) { + printf("too many names\n"); + return nr_names-1; + } + nr_names++; + + return nr_names-1; +} + +short *add_struct(int namecode) +{ + int len; + short *sp; + + if(nr_structs==0) { + structs[0]= structdata; + } + else { + sp= structs[nr_structs-1]; + len= sp[1]; + structs[nr_structs]= sp+ 2*len+2; + } + + sp= structs[nr_structs]; + sp[0]= namecode; + + if(nr_structs>=maxnr) { + printf("too many structs\n"); + return sp; + } + nr_structs++; + + return sp; +} + +int preprocess_include(char *maindata, int len) +{ + int a, newlen, comment = 0; + char *cp, *temp, *md; + + temp= MEM_mallocN(len, "preprocess_include"); + memcpy(temp, maindata, len); + + // remove all c++ comments + /* alle enters/tabs/etc vervangen door spaties */ + cp= temp; + a= len; + comment = 0; + while(a--) { + if(cp[0]=='/' && cp[1]=='/') { + comment = 1; + } else if (*cp<32) { + comment = 0; + } + if (comment || *cp<32 || *cp>128 ) *cp= 32; + cp++; + } + + + /* data uit temp naar maindata kopieeren, verwijder commentaar en dubbele spaties */ + cp= temp; + md= maindata; + newlen= 0; + comment= 0; + a= len; + while(a--) { + + if(cp[0]=='/' && cp[1]=='*') { + comment= 1; + cp[0]=cp[1]= 32; + } + if(cp[0]=='*' && cp[1]=='/') { + comment= 0; + cp[0]=cp[1]= 32; + } + + /* niet kopieeren als: */ + if(comment); + else if( cp[0]==' ' && cp[1]==' ' ); + else if( cp[-1]=='*' && cp[0]==' ' ); /* pointers met spatie */ + else { + md[0]= cp[0]; + md++; + newlen++; + } + cp++; + } + + MEM_freeN(temp); + return newlen; +} + +void *read_file_data(char *filename, int *len_r) +{ +#ifdef WIN32 + FILE *fp= fopen(filename, "rb"); +#else + FILE *fp= fopen(filename, "r"); +#endif + void *data; + + if (!fp) { + *len_r= -1; + return NULL; + } + + fseek(fp, 0L, SEEK_END); + *len_r= ftell(fp); + fseek(fp, 0L, SEEK_SET); + + data= MEM_mallocN(*len_r, "read_file_data"); + if (!data) { + *len_r= -1; + return NULL; + } + + if (fread(data, *len_r, 1, fp)!=1) { + *len_r= -1; + MEM_freeN(data); + return NULL; + } + + return data; +} + +int convert_include(char *filename) +{ + /* lees includefile, sla structen over die op regel ervoor '#' hebben. + sla alle data op in tijdelijke arrays. + */ + int filelen, count, overslaan, slen, type, name, strct; + short *structpoin, *sp; + char *maindata, *mainend, *md, *md1; + + md= maindata= read_file_data(filename, &filelen); + if (filelen==-1) { + printf("Can't read file %s\n", filename); + return 1; + } + + filelen= preprocess_include(maindata, filelen); + mainend= maindata+filelen-1; + + /* we zoeken naar '{' en dan terug naar 'struct' */ + count= 0; + overslaan= 0; + while(count 1) printf("\t|\t|-- detected struct %s\n", types[strct]); + + /* eerst overal keurige strings van maken */ + md1= md+1; + while(*md1 != '}') { + if( ((long)md1) > ((long)mainend) ) break; + + if(*md1==',' || *md1==' ') *md1= 0; + md1++; + } + + /* types en namen lezen tot eerste karakter niet '}' */ + md1= md+1; + while( *md1 != '}' ) { + if( ((long)md1) > ((long)mainend) ) break; + + /* als er 'struct' of 'unsigned' staat, overslaan */ + if(*md1) { + if( strncmp(md1, "struct", 6)==0 ) md1+= 7; + if( strncmp(md1, "unsigned", 6)==0 ) md1+= 9; + + /* type te pakken! */ + type= add_type(md1, 0); + + if (debugSDNA > 1) printf("\t|\t|\tfound type %s (", md1); + + md1+= strlen(md1); + + + /* doorlezen tot ';' */ + while( *md1 != ';' ) { + if( ((long)md1) > ((long)mainend) ) break; + + if(*md1) { + /* Name te pakken. slen needs + * correction for function + * pointers! */ + slen= strlen(md1); + if( md1[slen-1]==';' ) { + md1[slen-1]= 0; + + + name= add_name(md1); + slen += additional_slen_offset; + sp[0]= type; + sp[1]= name; + + if ((debugSDNA>1) && (names[name] != 0 )) printf("%s |", names[name]); + + structpoin[1]++; + sp+= 2; + + md1+= slen; + break; + } + + + name= add_name(md1); + slen += additional_slen_offset; + + sp[0]= type; + sp[1]= name; + if ((debugSDNA > 1) && (names[name] != 0 )) printf("%s ||", names[name]); + + structpoin[1]++; + sp+= 2; + + md1+= slen; + } + md1++; + } + + if (debugSDNA > 1) printf(")\n"); + + } + md1++; + } + } + } + } + count++; + md++; + } + + MEM_freeN(maindata); + + return 0; +} + +int arraysize(char *astr, int len) +{ + int a, mul=1; + char str[100], *cp=0; + + memcpy(str, astr, len+1); + + for(a=0; a3 && (len % 4) ) { + printf("Align 4 error in struct: %s %s\n", types[structtype], cp); + } + else if(typelens[type]==2 && (len % 2) ) { + printf("Align 2 error in struct: %s %s\n", types[structtype], cp); + } + + len += mul*typelens[type]; + alphalen += mul * alphalens[type]; + + } else { + len= 0; + alphalen = 0; + break; + } + } + + if (len==0) { + unknown++; + } else { + typelens[structtype]= len; + alphalens[structtype]= alphalen; + // two ways to detect if a struct contains a pointer: + // has_pointer is set or alphalen != len + if (has_pointer || alphalen != len) { + if (alphalen % 8) { + printf("Sizeerror in struct: %s\n", types[structtype]); + dna_error = 1; + } + } + } + } + } + + if(unknown==lastunknown) break; + } + + if(unknown) { + printf("ERROR: still %d structs unknown\n", unknown); + + if (debugSDNA) { + printf("*** Known structs : \n"); + + for(a=0; a= MAX_DNA_LINE_LENGTH) { + fprintf(file, "\n"); + linelength = 0; + } + } +} + +void printStructLenghts(void) +{ + int a, unknown= nr_structs, lastunknown, structtype; + short *structpoin; + printf("\n\n*** All detected structs:\n"); + + while(unknown) { + lastunknown= unknown; + unknown= 0; + + /* loop alle structen af... */ + for(a=0; a -1) { + fflush(stdout); + printf("Running makesdna at debug level %d\n", debugSDNA); + printf("\tProgram version: %s\n", DNA_VERSION_DATE); + } + + /* de allerlangst bekende struct is 50k, 100k is ruimte genoeg! */ + namedata= MEM_callocN(maxdata, "namedata"); + typedata= MEM_callocN(maxdata, "typedata"); + structdata= MEM_callocN(maxdata, "structdata"); + + /* maximaal 5000 variablen, vast voldoende? */ + names= MEM_callocN(sizeof(char *)*maxnr, "names"); + types= MEM_callocN(sizeof(char *)*maxnr, "types"); + typelens= MEM_callocN(sizeof(short)*maxnr, "typelens"); + alphalens= MEM_callocN(sizeof(short)*maxnr, "alphalens"); + structs= MEM_callocN(sizeof(short)*maxnr, "structs"); + + /* inserten alle bekende types */ + /* let op: uint komt niet voor! gebruik in structen unsigned int */ + add_type("char", 1); /* 0 */ + add_type("uchar", 1); /* 1 */ + add_type("short", 2); /* 2 */ + add_type("ushort", 2); /* 3 */ + add_type("int", 4); /* 4 */ + add_type("long", 4); /* 5 */ + add_type("ulong", 4); /* 6 */ + add_type("float", 4); /* 7 */ + add_type("double", 8); /* 8 */ + add_type("void", 0); /* 9 */ + + // the defines above shouldn't be output in the padding file... + firststruct = nr_types; + +#define BASE_HEADER "../" + + /* add all include files defined in the global array */ + /* Since the internal file+path name buffer has limited length, I do a */ + /* little test first... */ + /* Mind the breaking condition here! */ + if (debugSDNA) printf("\tStart of header scan:\n"); + for (i = 0; strlen(includefiles[i]); i++) { + if (debugSDNA) printf("\t|-- Converting %s%s\n", BASE_HEADER, includefiles[i]); + if (strlen(includefiles[i]) > SDNA_MAX_FILENAME_LENGTH) { + /* this would cause coredumps*/ + printf("*** \tError in makesdna: the specified filenames is too long " + "for parsing.\n\tFile: %s%s\n", BASE_HEADER, includefiles[i]); + } else { + sprintf(str, "%s%s", BASE_HEADER, includefiles[i]); + if (convert_include(str)) { + return (1); + } + } + } + if (debugSDNA) printf("\tFinished scanning %d headers.\n", i); + + if (calculate_structlens()) { + // error + return(1); + } + + /* DIT DEEL VOOR DEBUG */ + if (debugSDNA > 1) + { + int a,b; +/* short *elem; */ + short num_types; + + printf("nr_names %d nr_types %d nr_structs %d\n", nr_names, nr_types, nr_structs); + for(a=0; a -1) printf("Writing file ... "); + + if(nr_names==0 || nr_structs==0); + else { + strcpy(str, "SDNA"); + dna_write(file, str, 4); + + /* SCHRIJF NAMEN */ + strcpy(str, "NAME"); + dna_write(file, str, 4); + len= nr_names; + dna_write(file, &len, 4); + + /* lengte berekenen datablok met strings */ + cp= names[nr_names-1]; + cp+= strlen(names[nr_names-1]) + 1; /* +1: nul-terminator */ + len= (long)cp - (long)(names[0]); + len= (len+3) & ~3; + dna_write(file, names[0], len); + + /* SCHRIJF TYPES */ + strcpy(str, "TYPE"); + dna_write(file, str, 4); + len= nr_types; + dna_write(file, &len, 4); + + /* lengte berekenen datablok */ + cp= types[nr_types-1]; + cp+= strlen(types[nr_types-1]) + 1; /* +1: nul-terminator */ + len= (long)cp - (long)(types[0]); + len= (len+3) & ~3; + + dna_write(file, types[0], len); + + /* SCHRIJF TYPELENGTES */ + strcpy(str, "TLEN"); + dna_write(file, str, 4); + + len= 2*nr_types; + if(nr_types & 1) len+= 2; + dna_write(file, typelens, len); + + /* SCHRIJF STRUCTEN */ + strcpy(str, "STRC"); + dna_write(file, str, 4); + len= nr_structs; + dna_write(file, &len, 4); + + /* lengte berekenen datablok */ + sp= structs[nr_structs-1]; + sp+= 2+ 2*( sp[1] ); + len= (long)sp - (long)(structs[0]); + len= (len+3) & ~3; + + dna_write(file, structs[0], len); + + /* dna padding test */ + + if (0) { + FILE *fp; + int a; + + fp= fopen("padding.c", "w"); + if(fp==NULL); + else { + + // add all include files defined in the global array + for (i = 0; strlen(includefiles[i]); i++) { + fprintf(fp, "#include \"%s\"\n", includefiles[i]); + } + + fprintf(fp, "main(){\n"); + sp = typelens; + sp += firststruct; + for(a=firststruct; a -1) printf("done.\n"); + + return(0); +} + +/* ************************* END MAKEN DNA ********************** */ + +void make_bad_file(char *file) +{ + FILE *fp= fopen(file, "w"); + fprintf(fp, "NO NO NO! YOUR STUPID STUPID STUPID!\n"); + fclose(fp); +} + +int main(int argc, char ** argv) +{ + FILE *file; + int return_status = 0; + + if (argc != 2) { + printf("Usage: %s outfile.c\n", argv[0]); + return_status = 1; + } else { + file = fopen(argv[1], "w"); + if (!file) { + printf ("Unable to open file: %s\n", argv[1]); + return_status = 1; + } else { + fprintf (file, "unsigned char DNAstr[]= {\n"); + if (make_structDNA(file)) { + // error + fclose(file); + make_bad_file(argv[1]); + return_status = 1; + } else { + fprintf(file, "};\n"); + fprintf(file, "int DNAlen= sizeof(DNAstr);\n"); + + fclose(file); + } + } + } + + + return(return_status); +} + +// include files for automatic dependancies +#include "DNA_listBase.h" +#include "DNA_vec_types.h" +#include "DNA_ID.h" +#include "DNA_ipo_types.h" +#include "DNA_key_types.h" +#include "DNA_scriptlink_types.h" +#include "DNA_text_types.h" +#include "DNA_packedFile_types.h" +#include "DNA_camera_types.h" +#include "DNA_image_types.h" +#include "DNA_texture_types.h" +#include "DNA_lamp_types.h" +#include "DNA_wave_types.h" +#include "DNA_material_types.h" +#include "DNA_vfont_types.h" +#include "DNA_meta_types.h" +#include "DNA_curve_types.h" +#include "DNA_mesh_types.h" +#include "DNA_lattice_types.h" +#include "DNA_object_types.h" +#include "DNA_world_types.h" +#include "DNA_radio_types.h" +#include "DNA_scene_types.h" +#include "DNA_view3d_types.h" +#include "DNA_view2d_types.h" +#include "DNA_space_types.h" +#include "DNA_userdef_types.h" +#include "DNA_screen_types.h" +#include "DNA_sdna_types.h" +#include "DNA_fileglobal_types.h" +#include "DNA_sequence_types.h" +#include "DNA_effect_types.h" +#include "DNA_ika_types.h" +#include "DNA_oops_types.h" +#include "DNA_property_types.h" +#include "DNA_sensor_types.h" +#include "DNA_controller_types.h" +#include "DNA_actuator_types.h" +#include "DNA_sound_types.h" +#include "DNA_group_types.h" +#include "DNA_armature_types.h" +#include "DNA_action_types.h" +#include "DNA_constraint_types.h" +#include "DNA_nla_types.h" +/* end of list */ -- cgit v1.2.3