📄 dvgenerate.c
字号:
/* * Copyright(C) 2006 Bill Cox * * 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. * * 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 USA */#include "dv.h"/*-------------------------------------------------------------------------------------------------- Create new classes that are just useful for holding dynamic arrays of objects.--------------------------------------------------------------------------------------------------*/static void createClassDynamicArrayClasses( dvModule module){ dvClass theClass, dynarrayClass; dvClass lastClass = dvModuleGetLastClass(module); dvRelationship rel; utSym sym; dvForeachModuleClass(module, theClass) { if(dvClassGenerateArrayClass(theClass)) { sym = utSymCreateFormatted("%sArray", utCopyString(dvClassGetName(theClass))); dynarrayClass = dvClassCreate(module, dvSchemaNull, sym, dvClassNull); rel = dvRelationshipCreate(dynarrayClass, theClass, REL_ARRAY, utSymNull, utSymNull); dvRelationshipSetAccessParent(rel, false); } if(theClass == lastClass) { return; /* Don't build array classes for themselves! */ } } dvEndForeachModuleClass;}/*-------------------------------------------------------------------------------------------------- Create fields used by the relationship. Note that we copy the label strings because we are creating new symbols in this fuction, which could cause them to move in memory.--------------------------------------------------------------------------------------------------*/static void generateRelationshipFields( dvRelationship relationship){ dvClass parent = dvRelationshipGetParentClass(relationship); dvClass child = dvRelationshipGetChildClass(relationship); dvProperty prop; utSym sym; char *parentName = utCopyString(dvClassGetName(parent)); char *childName = utCopyString(dvClassGetName(child)); char *parentLabel = utCopyString(dvRelationshipGetParentLabel(relationship)); char *childLabel = utCopyString(dvRelationshipGetChildLabel(relationship)); dvRelationshipType type = dvRelationshipGetType(relationship); if(dvRelationshipAccessParent(relationship)) { /* Owner pointer */ sym = utSymCreateFormatted("%s%s", parentLabel, parentName); prop = dvClassFindProperty(child, sym); if(prop != dvPropertyNull) { if(dvPropertyGetClass(prop) != child || dvPropertyGetUnion(prop) != dvUnionNull || dvPropertyGetType(prop) != PROP_POINTER) { utExit("Property %s defined differently the second time", utSymGetName(sym)); } /* Must be a duplicated relationship */ dvRelationshipSetSharedParent(relationship, true); } else { prop = dvPropertyCreate(child, dvUnionNull, PROP_POINTER, sym); dvPropertySetClassProp(prop, parent); } } if(!dvRelationshipAccessChild(relationship)) { return; } if(type == REL_POINTER) { /* Child pointer */ sym = utSymCreateFormatted("%s%s", childLabel, childName); prop = dvPropertyCreate(parent, dvUnionNull, PROP_POINTER, sym); dvPropertySetClassProp(prop, child); } if(type == REL_LINKED_LIST || type == REL_TAIL_LINKED || type == REL_DOUBLY_LINKED || type == REL_HASHED) { /* First pointer */ sym = utSymCreateFormatted("First%s%s", childLabel, childName); prop = dvPropertyCreate(parent, dvUnionNull, PROP_POINTER, sym); dvPropertySetClassProp(prop, child); /* Next child pointer */ sym = utSymCreateFormatted("Next%s%s%s", parentName, childLabel, childName); prop = dvPropertyCreate(child, dvUnionNull, PROP_POINTER, sym); dvPropertySetClassProp(prop, child); } if(type == REL_TAIL_LINKED || type == REL_DOUBLY_LINKED || type == REL_HASHED) { /* Last pointer */ sym = utSymCreateFormatted("Last%s%s", childLabel, childName); prop = dvPropertyCreate(parent, dvUnionNull, PROP_POINTER, sym); dvPropertySetClassProp(prop, child); } if(type == REL_DOUBLY_LINKED || type == REL_HASHED) { /* Previous child pointer */ sym = utSymCreateFormatted("Prev%s%s%s", parentName, childLabel, childName); prop = dvPropertyCreate(child, dvUnionNull, PROP_POINTER, sym); dvPropertySetClassProp(prop, child); } if(type == REL_ARRAY) { /* Array of children */ sym = utSymCreateFormatted("%s%s", childLabel, childName); prop = dvPropertyCreate(parent, dvUnionNull, PROP_POINTER, sym); dvPropertySetClassProp(prop, child); dvPropertySetArray(prop, true); /* Index on parent */ sym = utSymCreateFormatted("%s%sIndex", parentName, childLabel); prop = dvPropertyCreate(child, dvUnionNull, PROP_UINT, sym); dvPropertySetWidth(prop, 32); /* Used children on parent */ sym = utSymCreateFormatted("Used%s%s", childLabel, childName); prop = dvPropertyCreate(parent, dvUnionNull, PROP_UINT, sym); dvPropertySetWidth(prop, 32); } if(type == REL_HASHED) { /* Hash table */ sym = utSymCreateFormatted("%s%sTable", childLabel, childName); prop = dvPropertyCreate(parent, dvUnionNull, PROP_POINTER, sym); dvPropertySetClassProp(prop, child); dvPropertySetArray(prop, true); /* Number of entries in table */ sym = utSymCreateFormatted("Num%s%s", childLabel, childName); prop = dvPropertyCreate(parent, dvUnionNull, PROP_UINT, sym); dvPropertySetWidth(prop, 32); /* Symbol on child */ sym = utSymCreateFormatted("%sSym", childLabel); prop = dvPropertyCreate(child, dvUnionNull, PROP_SYM, sym); /* Move symbol to front, just to improve reading fields */ dvClassRemoveProperty(child, prop); dvClassInsertProperty(child, prop); /* Next child in table */ sym = utSymCreateFormatted("NextTable%s%s%s", parentName, childLabel, childName); prop = dvPropertyCreate(child, dvUnionNull, PROP_POINTER, sym); dvPropertySetClassProp(prop, child); }}/*-------------------------------------------------------------------------------------------------- Create all the module's fields used by relationships.--------------------------------------------------------------------------------------------------*/static void createModuleRelationshipFields( dvModule module){ dvRelationship relationship; dvClass theClass; dvForeachModuleClass(module, theClass) { dvForeachClassChildRelationship(theClass, relationship) { generateRelationshipFields(relationship); } dvEndForeachClassChildRelationship; } dvEndForeachModuleClass;}/*-------------------------------------------------------------------------------------------------- Move the new property in front of the old property in the list of properties on a class.--------------------------------------------------------------------------------------------------*/static void movePropInFront( dvProperty newProp, dvProperty oldProp){ dvClass theClass = dvPropertyGetClass(newProp); dvClassRemoveProperty(theClass, newProp); if(dvClassGetFirstProperty(theClass) == oldProp) { dvClassInsertProperty(theClass, newProp); } else { dvClassInsertAfterProperty(theClass, dvPropertyGetPrevClassProperty(oldProp), newProp); }}/*-------------------------------------------------------------------------------------------------- Generate array fields. Move them in front of their array properties so when we read them from a backup file, they already have been defined.--------------------------------------------------------------------------------------------------*/static void createArrayFields( dvModule module){ dvClass theClass; dvProperty property, newProp; utSym sym; dvForeachModuleClass(module, theClass) { dvForeachClassProperty(theClass, property) { if(dvPropertyArray(property)) { /* Index into heap for first element */ sym = utSymCreateFormatted("%sIndex", utCopyString(dvPropertyGetName(property))); newProp = dvPropertyCreate(theClass, dvUnionNull, PROP_UINT, sym); dvPropertySetWidth(newProp, 32); dvPropertySetFirstElementProp(property, newProp); movePropInFront(newProp, property); dvPropertySetHidden(newProp, true); /* Number of elements allocated in array */ sym = utSymCreateFormatted("Num%s", utCopyString(dvPropertyGetName(property))); newProp = dvPropertyCreate(theClass, dvUnionNull, PROP_UINT, sym); dvPropertySetWidth(newProp, 32); dvPropertySetNumElementsProp(property, newProp); movePropInFront(newProp, property); dvPropertySetHidden(newProp, true); } } dvEndForeachClassProperty; } dvEndForeachModuleClass;}/*-------------------------------------------------------------------------------------------------- Find the size of a property element in bits. For typedef properties, we return 0.--------------------------------------------------------------------------------------------------*/uint8 dvFindPropertySize( dvProperty property){ switch(dvPropertyGetType(property)) { case PROP_INT: case PROP_UINT: return dvPropertyGetWidth(property); case PROP_FLOAT: return sizeof(float) << 3; case PROP_DOUBLE: return sizeof(double) << 3; case PROP_BOOL: return sizeof(bool) << 3; case PROP_CHAR: return sizeof(char) << 3; case PROP_ENUM: return sizeof(int) << 3; case PROP_TYPEDEF: return 0; /* We don't really know */ case PROP_POINTER: return dvClassGetReferenceSize(dvPropertyGetClassProp(property)); case PROP_SYM: return sizeof(utSym) << 3; case PROP_BIT: return 1; default: utExit("Unknown property type"); } return 0; /* Dummy return */}/*-------------------------------------------------------------------------------------------------- Find a field on the class for use as a next pointer on a free list.--------------------------------------------------------------------------------------------------*/static dvProperty findFieldForNextFreePointer( dvClass theClass){ dvProperty property; uint32 refSize = dvClassGetReferenceSize(theClass); dvForeachClassProperty(theClass, property) { if(dvFindPropertySize(property) == refSize && dvPropertyGetUnion(property) == dvUnionNull) { return property; } } dvEndForeachClassProperty; return dvPropertyNull;}/*-------------------------------------------------------------------------------------------------- Find a field on the class large enough to hold the next pointer. If none exist, allocate it.--------------------------------------------------------------------------------------------------*/static void setFreeListFields( dvModule module){ dvClass theClass; dvProperty property; utSym sym; dvForeachModuleClass(module, theClass) { property = findFieldForNextFreePointer(theClass); if(property == dvPropertyNull) { sym = utSymCreate("FreeList"); property = dvPropertyCreate(theClass, dvUnionNull, PROP_POINTER, sym); dvPropertySetClassProp(property, theClass); dvPropertySetHidden(property, true); } dvClassSetFreeListProperty(theClass, property); } dvEndForeachModuleClass;}/*-------------------------------------------------------------------------------------------------- Just count the number fields that we will need to track. Set the total number of fields on dvTheRoot.--------------------------------------------------------------------------------------------------*/static void setPropertyFieldNumbers( dvModule module){ dvClass theClass; dvUnion theUnion; dvCase theCase; dvEnum theEnum; dvEntry entry; dvProperty property; uint16 classNumber = 0; uint16 fieldNumber = 0; uint16 enumNumber = 0; uint16 entryNumber; uint16 unionCaseNumber; uint16 xField; dvForeachModuleClass(module, theClass) { xField = 0; dvForeachClassProperty(theClass, property) { if(dvPropertyGetUnion(property) == dvUnionNull) { dvPropertySetFieldNumber(property, fieldNumber); fieldNumber++; xField++; } } dvEndForeachClassProperty; dvForeachClassUnion(theClass, theUnion) { dvUnionSetFieldNumber(theUnion, fieldNumber); unionCaseNumber = 0; dvForeachUnionProperty(theUnion, property) { dvForeachPropertyCase(property, theCase) { unionCaseNumber++; } dvEndForeachPropertyCase; } dvEndForeachUnionProperty; dvUnionSetNumCases(theUnion, unionCaseNumber); fieldNumber++; xField++; } dvEndForeachClassUnion; dvClassSetNumFields(theClass, xField); classNumber++; } dvEndForeachModuleClass; dvModuleSetNumFields(module, fieldNumber); dvModuleSetNumClasses(module, classNumber); dvForeachModuleEnum(module, theEnum) { enumNumber++; entryNumber = 0; dvForeachEnumEntry(theEnum, entry) { entryNumber++; } dvEndForeachEnumEntry; dvEnumSetNumEntries(theEnum, entryNumber); } dvEndForeachModuleEnum; dvModuleSetNumEnums(module, enumNumber);}/*-------------------------------------------------------------------------------------------------- Generate code from the file.--------------------------------------------------------------------------------------------------*/bool dvGenerateCode( dvModule module, char *includeFile, char *sourceFile){ createClassDynamicArrayClasses(module); createModuleRelationshipFields(module); createArrayFields(module); setFreeListFields(module); setPropertyFieldNumbers(module); dvWriteHeaderFile(module, includeFile); dvWriteCFile(module, sourceFile); return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -