37d27dfca414f09c812edf9af38aa0ed6c9a31be
1 (* Copyright (C) DooM 2D:Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$INCLUDE a_modes.inc}
20 interface
22 uses
23 Classes,
27 // ////////////////////////////////////////////////////////////////////////// //
28 type
38 // this is base type for all scalars (and arrays)
40 public
41 type
42 TType = (TBool, TChar, TByte, TUByte, TShort, TUShort, TInt, TUInt, TString, TPoint, TSize, TList, TTrigData);
43 // TPoint: pair of Integers
44 // TSize: pair of UShorts
45 // TList: actually, array of records
46 // TTrigData: array of mMaxDim bytes, but internally a record (mRecRef)
47 // arrays of chars are pascal shortstrings (with counter in the first byte)
49 private
50 type
53 private
75 mAsMonsterId: Boolean; // special hack for triggers: monster record number+1 in binary (so 0 means "none")
76 // default value
83 mEBSType: TObject; // either TDynRecord or TDynEBS; nil means "simple type"; nil for `TTrigData` too
85 // for binary parser
88 private
93 procedure parseDefaultValue (); // parse `mDefUnparsed` to `mDefSVal`, `mDefIVal`, `mDefIVal2`, `mDefRecRef`
101 protected
102 // returns `true` for duplicate record id
105 public
123 // won't work for lists
128 public
141 // for lists
144 property items[const aname: AnsiString]: TDynRecord read getListItem; default; // alas, FPC 3+ lost property overloading feature
153 // "value" header record contains TList fields, with name equal to record type
155 private
162 {$IF DEFINED(XDYNREC_USE_FIELDHASH)}
164 {$ENDIF}
168 mHeaderRec: TDynRecord; // for "value" records this is header record with data, for "type" records this is header type record
170 private
180 protected
183 function addRecordByType (const atypename: AnsiString; rc: TDynRecord): Boolean; // `true`: duplicate record id
188 public
206 // find field with `TriggerType` type
209 // number of records of the given instance
212 public
217 //property fields: TDynFieldList read mFields;
227 private
236 private
245 public
252 // return empty string if not found
255 public
264 public
269 private
274 public
284 // creates new header record
287 // creates new header record
290 public
295 {$IF DEFINED(D2D_DYNREC_PROFILER)}
297 {$ENDIF}
300 implementation
302 uses
303 SysUtils, e_log
307 // ////////////////////////////////////////////////////////////////////////// //
311 // ////////////////////////////////////////////////////////////////////////// //
313 begin
321 begin
329 begin
336 begin
343 begin
379 var
381 begin
392 begin
422 // won't work for lists
424 begin
442 begin
452 var
454 begin
456 try
458 finally
465 var
471 begin
473 begin
478 end
479 else
480 begin
486 try
493 finally
505 // default value should be parsed
507 begin
510 begin
512 raise Exception.Create(Format('field ''%s'' in record ''%s'' of record type ''%s'' is not set', [mName, mOwner.mId, mOwner.mName]));
522 // default value should be parsed
524 begin
537 begin
543 begin
544 if (mRVal <> nil) and (idx >= 0) and (idx < mRVal.count) then result := mRVal[idx] else result := nil;
549 var
551 begin
557 begin
560 begin
568 begin
589 begin
598 TEBS.TBitSet: begin result += ' bitset '; if mBitSetUnique then result += 'unique '; result += mEBSTypeName; end;
603 begin
604 if (mType = TType.TPoint) then begin if (mAsT) then result += ' as txy' else result += ' as xy'; end
605 else if (mType = TType.TSize) then begin if (mAsT) then result += ' as twh' else result += ' as wh'; end;
613 begin
617 TType.TChar: if (mMaxDim > 0) then result += formatstrf('Char%d;', [mMaxDim]) else result += 'Char;';
641 var
659 begin
690 begin
692 if (lmaxdim < 1) then raise Exception.Create(Format('invalid field ''%s'' array size', [fldname]));
694 end;
697 begin
699 begin
700 if (fldofs >= 0) then raise Exception.Create(Format('duplicate field ''%s'' offset', [fldname]));
703 continue;
707 begin
714 continue;
715 end;
718 begin
720 if (Length(fldrecname) <> 0) then raise Exception.Create(Format('field ''%s'' already typed as ''%s''', [fldname, fldrecname]));
722 continue;
726 begin
728 if (Length(fldrecname) <> 0) then raise Exception.Create(Format('field ''%s'' already typed as ''%s''', [fldname, fldrecname]));
731 continue;
735 begin
736 if hasdefStr or hasdefInt or hasdefId then raise Exception.Create(Format('field ''%s'' has duplicate default', [fldname]));
739 begin
744 begin
749 begin
753 else
756 continue;
760 begin
762 continue;
766 begin
768 continue;
771 if (pr.tokType <> pr.TTId) then raise Exception.Create(Format('field ''%s'' has something unexpected in definition', [fldname]));
773 if (Length(fldrecname) <> 0) then raise Exception.Create(Format('field ''%s'' already typed as ''%s''', [fldname, fldrecname]));
780 // create field
795 else raise Exception.Create(Format('field ''%s'' has invalid type ''%s''', [fldname, fldtype]));
797 if (lmaxdim > 0) and (mType <> TType.TChar) and (mType <> TType.TTrigData) then raise Exception.Create(Format('field ''%s'' of type ''%s'' cannot be array', [fldname, fldtype]));
799 begin
800 if (lmaxdim < 1) then raise Exception.Create(Format('field ''%s'' of type ''%s'' cannot be array', [fldname, fldtype]));
801 if (Length(fldrecname) > 0) then raise Exception.Create(Format('field ''%s'' of type ''%s'' cannot have another type', [fldname, fldtype]));
822 end;
826 var
832 begin
836 begin
838 begin
839 // this must be triggerdata
841 begin
842 raise Exception.Create(Format('record reference type ''%s'' in field ''%s'' cannot be written', [mEBSTypeName, mName]));
844 // write triggerdata
846 if (buf = nil) then raise Exception.Create(Format('record reference type ''%s'' in field ''%s'' cannot be written', [mEBSTypeName, mName]));
847 try
850 begin
855 finally
859 exit;
861 // record reference
869 else raise Exception.Create(Format('record reference type ''%s'' in field ''%s'' cannot be written', [mEBSTypeName, mName]));
871 // find record number
873 begin
875 if (f < 0) then raise Exception.Create(Format('record reference type ''%s'' in field ''%s'' not found in record list', [mEBSTypeName, mName]));
877 if (f > maxv) then raise Exception.Create(Format('record reference type ''%s'' in field ''%s'' has too big index', [mEBSTypeName, mName]));
878 end
879 else
880 begin
887 else raise Exception.Create(Format('record reference type ''%s'' in field ''%s'' cannot be written', [mEBSTypeName, mName]));
889 exit;
898 begin
900 begin
902 end
903 else
904 begin
907 exit;
910 begin
911 if (mMaxDim = 0) then raise Exception.Create(Format('invalid string size definition for field ''%s''', [mName]));
913 begin
914 if (Length(mSVal) <> 1) then raise Exception.Create(Format('invalid string size definition for field ''%s''', [mName]));
916 end
917 else
918 begin
919 if (Length(mSVal) > mMaxDim) then raise Exception.Create(Format('invalid string size definition for field ''%s''', [mName]));
924 exit;
928 begin
929 // triggerdata array was processed earlier
930 if (mMaxDim >= 0) then Exception.Create(Format('byte array in field ''%s'' cannot be written', [mName]));
932 exit;
936 begin
937 if (mMaxDim >= 0) then raise Exception.Create(Format('short array in field ''%s'' cannot be written', [mName]));
939 exit;
943 begin
944 if (mMaxDim >= 0) then raise Exception.Create(Format('int array in field ''%s'' cannot be written', [mName]));
946 exit;
949 begin
953 begin
954 if (mMaxDim >= 0) then raise Exception.Create(Format('pos/size array in field ''%s'' cannot be written', [mName]));
957 exit;
960 begin
961 if (mMaxDim >= 0) then raise Exception.Create(Format('pos/size array in field ''%s'' cannot be written', [mName]));
964 exit;
967 begin
969 exit;
972 begin
974 exit;
982 var
986 begin
992 begin
994 begin
996 end
998 begin
1000 end
1001 else
1002 begin
1006 exit;
1009 begin
1010 //def := mOwner.mOwner;
1011 //es := def.findEBSType(mEBSTypeName);
1014 if (es = nil) or (not es.mIsEnum) then raise Exception.Create(Format('record enum type ''%s'' for field ''%s'' not found', [mEBSTypeName, mName]));
1016 begin
1018 begin
1021 exit;
1024 raise Exception.Create(Format('value %d in record enum type ''%s'' for field ''%s'' not found', [mIVal, mEBSTypeName, mName]));
1027 begin
1028 //def := mOwner.mOwner;
1029 //es := def.findEBSType(mEBSTypeName);
1032 if (es = nil) or es.mIsEnum then raise Exception.Create(Format('record bitset type ''%s'' for field ''%s'' not found', [mEBSTypeName, mName]));
1033 // none?
1035 begin
1037 begin
1039 begin
1042 exit;
1045 raise Exception.Create(Format('value %d in record bitset type ''%s'' for field ''%s'' not found', [0, mEBSTypeName, mName]));
1047 // not none
1051 begin
1053 begin
1056 begin
1058 begin
1062 break;
1065 if not found then raise Exception.Create(Format('value %d in record bitset type ''%s'' for field ''%s'' not found', [mask, mEBSTypeName, mName]));
1070 exit;
1077 begin
1079 exit;
1082 begin
1083 if (mMaxDim = 0) then raise Exception.Create(Format('invalid string size definition for field ''%s''', [mName]));
1086 exit;
1094 begin
1096 exit;
1099 begin
1102 exit;
1106 begin
1108 exit;
1111 begin
1113 exit;
1116 begin
1118 exit;
1126 var
1133 begin
1137 begin
1138 // this must be triggerdata
1140 begin
1143 // find trigger definition
1145 if (tfld = nil) then raise Exception.Create(Format('triggerdata value for field ''%s'' in record ''%s'' without TriggerType field', [mName, rec.mName]));
1147 if (rc = nil) then raise Exception.Create(Format('triggerdata definition for field ''%s'' in record ''%s'' with type ''%s'' not found', [mName, rec.mName, tfld.mSVal]));
1150 try
1154 finally
1158 exit;
1159 end
1160 else
1161 begin
1162 // not a trigger data
1170 else raise Exception.Create(Format('invalid non-numeric type ''%s'' for field ''%s'' of record ''%s''', [getTypeName(mType), mName, mEBSTypeName]));
1176 exit;
1180 begin
1189 else raise Exception.Create(Format('invalid non-numeric type ''%s'' for field ''%s'' of record ''%s''', [getTypeName(mType), mName, mEBSTypeName]));
1193 if (es = nil) or (es.mIsEnum <> (mEBS = TEBS.TEnum)) then raise Exception.Create(Format('record enum type ''%s'' for field ''%s'' not found', [mEBSTypeName, mName]));
1195 // build enum/bitfield values
1197 begin
1199 if (Length(mSVal) = 0) then raise Exception.Create(Format('record enum type ''%s'' for field ''%s'' has invalid value %d', [mEBSTypeName, mName, mIVal]));
1200 end
1201 else
1202 begin
1203 // special for 'none'
1205 begin
1207 if (Length(mSVal) = 0) then raise Exception.Create(Format('record bitset type ''%s'' for field ''%s'' has invalid value %d', [mEBSTypeName, mName, mIVal]));
1208 end
1209 else
1210 begin
1214 begin
1216 begin
1218 if (Length(s) = 0) then raise Exception.Create(Format('record bitset type ''%s'' for field ''%s'' has invalid value %d', [mEBSTypeName, mName, mask]));
1226 //writeln('ebs <', es.mName, '>: ', mSVal);
1228 exit;
1235 begin
1241 exit;
1244 begin
1246 begin
1248 end
1249 else
1250 begin
1253 try
1258 begin
1263 finally
1268 exit;
1277 begin
1279 exit;
1282 begin
1286 exit;
1289 begin
1293 exit;
1296 begin
1298 exit;
1301 begin
1303 exit;
1314 begin
1316 if (mIVal < min) or (mIVal > max) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1320 var
1326 begin
1327 // if this field should contain struct, convert type and parse struct
1331 begin
1332 // ugly hack. sorry.
1334 begin
1337 begin
1338 // '{}'
1341 end
1342 else
1343 begin
1345 // find trigger definition
1347 if (tfld = nil) then raise Exception.Create(Format('triggerdata value for field ''%s'' in record ''%s'' without ''type'' field', [mName, rec.mName]));
1349 if (rc = nil) then raise Exception.Create(Format('triggerdata definition for field ''%s'' in record ''%s'' with type ''%s'' not found', [mName, rec.mName, tfld.mSVal]));
1352 //writeln(rc.definition);
1353 try
1357 finally
1363 exit;
1365 // other record types
1367 begin
1369 begin
1371 end
1372 else
1373 begin
1375 if (rec = nil) then raise Exception.Create(Format('record ''%s'' (%s) value for field ''%s'' not found', [pr.tokStr, mEBSTypeName, mName]));
1381 exit;
1382 end
1384 begin
1385 //rec := mOwner.mOwner.findRecType(mEBSTypeName); // find in mapdef
1388 if (rec = nil) then raise Exception.Create(Format('record type ''%s'' for field ''%s'' not found', [mEBSTypeName, mName]));
1395 begin
1396 //raise Exception.Create(Format('record type ''%s'' for field ''%s'' not found', [mEBSTypeName, mName]));
1397 e_LogWritefln('duplicate record with id ''%s'' for field ''%s'' in record ''%s''', [rc.mId, mName, mOwner.mName]);
1400 exit;
1405 begin
1406 //es := mOwner.mOwner.findEBSType(mEBSTypeName); // find in mapdef
1409 if (es = nil) or (not es.mIsEnum) then raise Exception.Create(Format('record enum type ''%s'' for field ''%s'' not found', [mEBSTypeName, mName]));
1411 if not es.has[tk] then raise Exception.Create(Format('record enum value ''%s'' of type ''%s'' for field ''%s'' not found', [tk, mEBSTypeName, mName]));
1414 //writeln('ENUM ', mEBSName, '; element <', mSVal, '> with value ', mIVal);
1417 exit;
1420 begin
1421 //es := mOwner.mOwner.findEBSType(mEBSTypeName); // find in mapdef
1424 if (es = nil) or es.mIsEnum then raise Exception.Create(Format('record bitset type ''%s'' for field ''%s'' not found', [mEBSTypeName, mName]));
1427 begin
1429 if not es.has[tk] then raise Exception.Create(Format('record bitset value ''%s'' of type ''%s'' for field ''%s'' not found', [tk, mEBSTypeName, mName]));
1433 if mBitSetUnique then raise Exception.Create(Format('record bitset of type ''%s'' for field ''%s'' expects only one value', [tk, mEBSTypeName, mName]));
1434 //pr.expectDelim('|');
1439 exit;
1446 begin
1452 exit;
1455 begin
1456 if (mMaxDim = 0) then raise Exception.Create(Format('invalid string size definition for field ''%s''', [mName]));
1459 begin
1460 // single char
1461 if (Length(mSVal) <> 1) then raise Exception.Create(Format('invalid string size for field ''%s''', [mName]));
1464 end
1465 else
1466 begin
1467 // string
1468 if (Length(mSVal) > mMaxDim) then raise Exception.Create(Format('invalid string size for field ''%s''', [mName]));
1472 exit;
1475 begin
1478 exit;
1481 begin
1484 exit;
1487 begin
1490 exit;
1493 begin
1496 exit;
1499 begin
1502 exit;
1505 begin
1508 exit;
1511 begin
1515 exit;
1519 begin
1523 begin
1524 if (mIVal < 0) or (mIVal > 32767) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1528 begin
1529 if (mIVal2 < 0) or (mIVal2 > 32767) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1534 exit;
1537 begin
1539 exit;
1542 begin
1544 exit;
1552 // ////////////////////////////////////////////////////////////////////////// //
1554 begin
1555 if (pr = nil) then raise Exception.Create('cannot create record type without type definition');
1560 {$IF DEFINED(XDYNREC_USE_FIELDHASH)}
1562 {$ENDIF}
1572 begin
1576 {$IF DEFINED(XDYNREC_USE_FIELDHASH)}
1578 {$ENDIF}
1586 begin
1590 {$IF DEFINED(XDYNREC_USE_FIELDHASH)}
1593 {$ENDIF}
1601 begin
1604 {$IF DEFINED(XDYNREC_USE_FIELDHASH)}
1606 {$ENDIF}
1610 function TDynRecord.addFieldChecked (fld: TDynField): Boolean; inline; // `true`: duplicate name
1611 begin
1614 {$IF not DEFINED(XDYNREC_USE_FIELDHASH)}
1616 {$ENDIF}
1618 {$IF DEFINED(XDYNREC_USE_FIELDHASH)}
1620 {$ENDIF}
1625 begin
1626 {$IF DEFINED(XDYNREC_USE_FIELDHASH)}
1628 {$ELSE}
1631 begin
1636 {$ENDIF}
1641 begin
1647 var
1649 begin
1656 begin
1662 var
1664 begin
1672 var
1675 begin
1683 begin
1696 var
1699 begin
1702 // find record data
1705 if (fld.mType <> fld.TType.TList) then raise Exception.Create(Format('cannot get record of type ''%s'' due to name conflict with ordinary field', [atypename]));
1706 // find by id
1708 begin
1711 // alas
1715 function TDynRecord.findRecordNumByType (const atypename: AnsiString; rc: TDynRecord): Integer;
1716 var
1719 begin
1721 // find record data
1724 if (fld.mType <> fld.TType.TList) then raise Exception.Create(Format('cannot get record of type ''%s'' due to name conflict with ordinary field', [atypename]));
1725 // find by ref
1727 begin
1729 begin
1733 // alas
1738 var
1740 begin
1741 // find record data
1744 begin
1745 // first record
1750 if (fld.mType <> fld.TType.TList) then raise Exception.Create(Format('cannot append record of type ''%s'' due to name conflict with ordinary field', [atypename]));
1751 // append
1753 begin
1762 var
1764 begin
1770 begin
1778 var
1781 begin
1783 begin
1794 // number of records of the given instance
1796 var
1798 begin
1806 var
1809 begin
1811 begin
1814 begin
1816 begin
1820 if isForTrig[tdn] then raise Exception.Create(Format('duplicate trigdata ''%s'' trigtype ''%s''', [mName, tdn]));
1824 end
1825 else
1826 begin
1832 end
1833 else
1834 begin
1839 begin
1842 begin
1843 if (mSize > 0) then raise Exception.Create(Format('duplicate `size` in record ''%s''', [mName]));
1845 if (mSize < 1) then raise Exception.Create(Format('invalid record ''%s'' size: %d', [mName, mSize]));
1847 continue;
1850 begin
1851 if (mBinBlock >= 0) then raise Exception.Create(Format('duplicate `binblock` in record ''%s''', [mName]));
1853 if (mBinBlock < 1) then raise Exception.Create(Format('invalid record ''%s'' binblock: %d', [mName, mBinBlock]));
1854 continue;
1860 // load fields
1862 begin
1864 //if hasByName(fld.name) then begin fld.Free(); raise Exception.Create(Format('duplicate field ''%s''', [fld.name])); end;
1865 // append
1868 begin
1872 // done with field
1879 var
1881 begin
1883 begin
1886 end
1887 else
1888 begin
1889 // record
1893 begin
1903 var
1905 begin
1907 begin
1908 // trigger data
1911 begin
1914 begin
1919 end
1920 else
1921 begin
1924 end
1925 else
1926 begin
1927 // record
1934 begin
1944 var
1956 var
1959 begin
1960 //writeln('*** rec: ', rec.mName, '.', rec.mId, ' (', rec.mFields.count, ')');
1962 begin
1964 begin
1966 continue;
1972 begin
1973 e_LogWritefln('record of type ''%s'' with id ''%s'' links to inexistant record of type ''%s'' with id ''%s''', [rec.mName, rec.mId, fld.mEBSTypeName, fld.mRecRefId], MSG_WARNING);
1974 //raise Exception.Create(Format('record of type ''%s'' with id ''%s'' links to inexistant record of type ''%s'' with id ''%s''', [rec.mName, rec.mId, fld.mEBSTypeName, fld.mRecRefId]));
1976 //writeln(' ', rec.mName, '.', rec.mId, ':', fld.mName, ' -> ', rt.mName, '.', rt.mId, ' (', fld.mEBSTypeName, '.', fld.mRecRefId, ')');
1982 begin
1983 //writeln(' ', fld.mName);
1988 begin
1991 try
1993 begin
1994 // parse map file as sequence of blocks
1998 // parse blocks
2000 begin
2006 if (bsize < 0) or (bsize > $1fffffff) then raise Exception.Create(Format('block of type %d has invalid size %d', [btype, bsize]));
2007 if loaded[btype] then raise Exception.Create(Format('block of type %d already loaded', [btype]));
2009 // find record type for this block
2012 if (rect = nil) then raise Exception.Create(Format('block of type %d has no corresponding record', [btype]));
2013 //writeln('found type ''', rec.mName, ''' for block type ', btype);
2014 if (rec.mSize = 0) or ((bsize mod rec.mSize) <> 0) then raise Exception.Create(Format('block of type %d has invalid number of records', [btype]));
2015 // header?
2017 begin
2018 if (bsize <> mSize) then raise Exception.Create(Format('header block of type %d has invalid number of records', [btype]));
2023 end
2024 else
2025 begin
2026 // create list for this type
2031 begin
2035 begin
2042 //writeln('parsed ''', rec.mId, '''...');
2048 //st.position := st.position+bsize;
2050 // link fields
2052 begin
2056 exit;
2059 // read fields
2061 if (mSize < 1) then raise Exception.Create(Format('cannot read record of type ''%s'' with unknown size', [mName]));
2065 begin
2068 if (fld.mBinOfs >= st.size) then raise Exception.Create(Format('record of type ''%s'' has invalid field ''%s''', [fld.mName]));
2070 //writeln('parsing ''', mName, '.', fld.mName, '''...');
2073 finally
2080 procedure TDynRecord.writeBinTo (st: TStream; trigbufsz: Integer=-1; onlyFields: Boolean=false);
2081 var
2087 //f, c: Integer;
2090 begin
2092 begin
2093 if (mBinBlock < 1) then raise Exception.Create('cannot write binary record without block number');
2096 end
2097 else
2098 begin
2101 try
2106 // write normal fields
2108 begin
2109 // record list?
2113 if (fld.mBinOfs >= bufsz) then raise Exception.Create('binary value offset is outside of the buffer');
2115 //writeln('writing field <', fld.mName, '>');
2119 // write block with normal fields
2121 begin
2122 //writeln('writing header...');
2123 // signature and version
2134 // write other blocks, if any
2136 begin
2137 // calculate blkmax
2140 begin
2141 // record list?
2143 begin
2151 // write blocks
2153 begin
2157 begin
2158 // record list?
2160 begin
2169 // flush block
2171 begin
2182 // write end marker
2187 finally
2195 var
2198 begin
2200 begin
2207 try
2209 begin
2210 // record list?
2212 begin
2215 begin
2217 begin
2223 continue;
2230 finally
2238 {$IF DEFINED(D2D_DYNREC_PROFILER)}
2239 var
2250 begin
2252 writeln('record cloning: ', profCloneRec div 1000, '.', profCloneRec mod 1000, ' milliseconds');
2253 writeln('findRecType : ', profFindRecType div 1000, '.', profFindRecType mod 1000, ' milliseconds');
2254 writeln('field[] : ', profFieldSearching div 1000, '.', profFieldSearching mod 1000, ' milliseconds');
2255 writeln('list dup check: ', profListDupChecking div 1000, '.', profListDupChecking mod 1000, ' milliseconds');
2256 writeln('addRecByType : ', profAddRecByType div 1000, '.', profAddRecByType mod 1000, ' milliseconds');
2257 writeln('field valparse: ', profFieldValParsing div 1000, '.', profFieldValParsing mod 1000, ' milliseconds');
2258 writeln('fix defaults : ', profFixDefaults div 1000, '.', profFixDefaults mod 1000, ' milliseconds');
2259 writeln('recvalparse : ', profRecValParse div 1000, '.', profRecValParse mod 1000, ' milliseconds');
2261 {$ENDIF}
2265 var
2269 {$IF DEFINED(D2D_DYNREC_PROFILER)}
2271 {$ENDIF}
2272 begin
2273 if (mOwner = nil) then raise Exception.Create(Format('can''t parse record ''%s'' value without owner', [mName]));
2277 // not a header?
2279 begin
2280 // id?
2282 end
2283 else
2284 begin
2288 //writeln('parsing record <', mName, '>');
2291 begin
2293 //writeln('<', mName, '.', pr.tokStr, '>');
2295 // records
2297 begin
2298 // add records with this type (if any)
2303 begin
2308 try
2311 (*
2312 if (Length(rec.mId) > 0) then
2313 begin
2314 {$IF DEFINED(D2D_DYNREC_PROFILER)}stt := curTimeMicro();{$ENDIF}
2315 fld := field[pr.tokStr];
2316 {$IF DEFINED(D2D_DYNREC_PROFILER)}profFieldSearching := curTimeMicro()-stt;{$ENDIF}
2317 (*
2318 if (fld <> nil) and (fld.mRVal <> nil) then
2319 begin
2320 {$IF DEFINED(D2D_DYNREC_PROFILER)}stt := curTimeMicro();{$ENDIF}
2321 //idtmp := trc.mName+':'+rec.mId;
2322 //if ids.put(idtmp, 1) then raise Exception.Create(Format('duplicate thing ''%s'' in record ''%s''', [fld.mName, mName]));
2323 if fld.mRHash.has(rec.mId) then raise Exception.Create(Format('duplicate thing ''%s'' in record ''%s''', [fld.mName, mName]));
2324 {$IF DEFINED(D2D_DYNREC_PROFILER)}profListDupChecking := curTimeMicro()-stt;{$ENDIF}
2325 end;
2326 end;
2327 *)
2332 finally
2335 continue;
2339 // fields
2344 begin
2345 if fld.defined then raise Exception.Create(Format('duplicate field ''%s'' in record ''%s''', [fld.mName, mName]));
2346 if fld.internal then raise Exception.Create(Format('internal field ''%s'' in record ''%s''', [fld.mName, mName]));
2351 continue;
2354 // something is wrong
2358 // fix field defaults
2362 //writeln('done parsing record <', mName, '>');
2363 //{$IF DEFINED(D2D_DYNREC_PROFILER)}writeln('stall: ', curTimeMicro()-stall);{$ENDIF}
2368 // ////////////////////////////////////////////////////////////////////////// //
2370 begin
2377 begin
2384 begin
2395 begin
2398 begin
2407 begin
2413 var
2415 begin
2422 var
2424 begin
2428 // fields
2431 begin
2435 begin
2439 end
2440 else
2441 begin
2446 // max field
2453 var
2455 begin
2457 // fields
2459 begin
2466 var
2468 begin
2470 begin
2478 var
2484 begin
2493 begin
2496 begin
2497 if StrEqu(mIds[f], idname) then raise Exception.Create(Format('duplicate field ''%s'' in enum/bitset ''%s''', [idname, mName]));
2499 if StrEqu(mMaxName, idname) then raise Exception.Create(Format('duplicate field ''%s'' in enum/bitset ''%s''', [idname, mName]));
2503 // has value?
2505 begin
2507 begin
2508 if (Length(mMaxName) > 0) then raise Exception.Create(Format('duplicate max field ''%s'' in enum/bitset ''%s''', [idname, mName]));
2511 end
2512 else
2513 begin
2519 // append it?
2521 begin
2522 // fix maxvalue
2524 begin
2531 // next cv
2533 begin
2542 // add max field
2544 begin
2553 // ////////////////////////////////////////////////////////////////////////// //
2555 begin
2564 var
2567 begin
2582 begin
2589 var
2591 begin
2593 begin
2601 var
2603 begin
2605 begin
2613 var
2615 begin
2617 begin
2625 var
2630 // setup header links and type links
2632 var
2634 begin
2637 begin
2642 begin
2644 if (fld.mEBSType = nil) then raise Exception.Create(Format('field ''%s'' of type ''%s'' has no correcponding record definition', [fld.mName, fld.mEBSTypeName]));
2648 begin
2650 if (fld.mEBSType = nil) then raise Exception.Create(Format('field ''%s'' of type ''%s'' has no correcponding enum/bitset', [fld.mName, fld.mEBSTypeName]));
2651 if ((fld.mEBS = TDynField.TEBS.TEnum) <> (fld.mEBSType as TDynEBS).mIsEnum) then raise Exception.Create(Format('field ''%s'' of type ''%s'' enum/bitset type conflict', [fld.mName, fld.mEBSTypeName]));
2657 // setup default values
2659 var
2661 begin
2665 begin
2668 begin
2673 begin
2676 begin
2682 //writeln(eb.definition); writeln;
2683 continue;
2687 begin
2690 begin
2692 begin
2699 //writeln(dr.definition); writeln;
2700 continue;
2704 //writeln(dr.definition); writeln;
2705 if (findRecType(rec.name) <> nil) then begin rec.Free(); raise Exception.Create(Format('duplicate record ''%s''', [rec.name])); end;
2706 if (hdr <> nil) and StrEqu(rec.name, hdr.name) then begin rec.Free(); raise Exception.Create(Format('duplicate record ''%s''', [rec.name])); end;
2709 begin
2710 if (hdr <> nil) then begin rec.Free(); raise Exception.Create(Format('duplicate header record ''%s'' (previous is ''%s'')', [rec.name, hdr.name])); end;
2712 end
2713 else
2714 begin
2719 // put header record to top
2725 // setup header links and type links
2729 // setup default values
2735 // ////////////////////////////////////////////////////////////////////////// //
2737 var
2739 begin
2741 try
2748 finally
2755 var
2757 begin
2759 try
2765 finally
2772 var
2778 begin
2780 result += '// ////////////////////////////////////////////////////////////////////////// //'#10;
2783 result += #10#10'// ////////////////////////////////////////////////////////////////////////// //'#10;
2786 begin
2791 result += #10#10'// ////////////////////////////////////////////////////////////////////////// //'#10;
2797 begin
2801 begin
2807 begin