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}
19 interface
21 uses
25 // ////////////////////////////////////////////////////////////////////////// //
26 type
30 // this is base type for all scalars (and arrays)
32 public
33 type
34 TType = (TBool, TChar, TByte, TUByte, TShort, TUShort, TInt, TUInt, TString, TPoint, TSize, TList, TTrigData);
35 // TPoint: pair of Shorts
36 // TSize: pair of UShorts
37 // TList: actually, array of records
38 // TTrigData: array of bytes
39 // arrays of chars are pascal shortstrings (with counter in the first byte)
41 type
45 private
46 type
49 private
70 // default values
77 // temp
80 private
91 public
106 // won't work for lists
109 public
134 private
145 private
155 public
168 public
182 private
191 private
200 public
206 public
215 private
218 private
221 public
226 private
231 public
241 public
246 implementation
248 uses
249 SysUtils;
252 // ////////////////////////////////////////////////////////////////////////// //
254 begin
265 begin
272 begin
279 begin
309 var
311 begin
324 begin
326 end
327 else
328 begin
351 procedure TDynField.setSVal (const v: AnsiString); inline; begin mSVal := v; mDefined := true; end;
354 // won't work for lists
356 begin
380 var
383 begin
385 begin
387 begin
389 raise Exception.Create(Format('field ''%s'' in record ''%s'' of record type ''%s'' is not set', [mName, mOwner.mId, mOwner.mName]));
392 begin
393 if (CompareText(mDefSVal, 'null') <> 0) then raise Exception.Create(Format('field ''%s'' in record ''%s'' of record type ''%s'' has non-null default value ''%s''', [mName, mOwner.mId, mOwner.mName, mDefSVal]));
397 exit;
405 //mDefined := true;
406 //writeln('DEFAULT for <', mName, '>: <', s, '>');
408 try
410 finally
420 var
424 begin
426 //result := mDefaultValueSet;
431 TType.TPoint, TType.TSize: begin result := false; exit; end; // no default values for these types yet
435 try
439 finally
447 begin
468 begin
477 TEBS.TBitSet: begin result += ' bitset '; if mBitSetUnique then result += 'unique '; result += mEBSName; end;
480 begin
481 if (mType = TType.TChar) or (mType = TType.TString) then result += ' default '+TTextParser.quote(mDefSVal)
483 {
484 else
485 begin
486 if (mType = TType.TBool) then
487 begin
488 result += ' default ';
489 if (mDefIVal <> 0) then result += 'true' else result += 'false';
490 end
491 else
492 begin
493 result += Format(' default %d', [mDefIVal]);
494 end;
495 end;
496 }
499 begin
500 if (mType = TType.TPoint) then begin if (mAsT) then result += ' as txy' else result += ' as xy'; end
501 else if (mType = TType.TSize) then begin if (mAsT) then result += ' as twh' else result += ' as wh'; end;
509 var
526 begin
547 // field name
550 // field type
554 // fixed-size array?
556 begin
558 if (lmaxdim < 1) then raise Exception.Create(Format('invali field ''%s'' array size', [fldname]));
563 begin
565 begin
566 if (fldofs >= 0) then raise Exception.Create(Format('duplicate field ''%s'' offset', [fldname]));
569 continue;
573 begin
579 continue;
583 begin
585 if (Length(fldrecname) <> 0) then raise Exception.Create(Format('field ''%s'' already typed as ''%s''', [fldname, fldrecname]));
587 continue;
591 begin
593 if (Length(fldrecname) <> 0) then raise Exception.Create(Format('field ''%s'' already typed as ''%s''', [fldname, fldrecname]));
596 continue;
600 begin
601 if hasdefStr or hasdefInt or hasdefId then raise Exception.Create(Format('field ''%s'' has duplicate default', [fldname]));
604 begin
609 begin
614 begin
618 else
621 continue;
625 begin
627 continue;
631 begin
633 continue;
636 if (pr.tokType <> pr.TTId) then raise Exception.Create(Format('field ''%s'' has something unexpected in definition', [fldname]));
638 if (Length(fldrecname) <> 0) then raise Exception.Create(Format('field ''%s'' already typed as ''%s''', [fldname, fldrecname]));
645 // create field
660 else raise Exception.Create(Format('field ''%s'' has invalid type ''%s''', [fldname, fldtype]));
662 {if hasdefId and (self.baseType = self.TType.TBool) then
663 begin
664 if (defstr = 'true') or (defstr = 'tan') or (defstr = 'yes') then self.mDefIVal := 1
665 else if (defstr = 'false') or (defstr = 'ona') or (defstr = 'no') then self.mDefIVal := 0
666 else raise Exception.Create(Format('field ''%s'' has invalid boolean default ''%s''', [fldname, defstr]));
667 end
668 else}
669 begin
691 var
696 begin
699 // if this field should contain struct, convert type and parse struct
703 begin
705 begin
707 end
709 begin
711 end
712 else
713 begin
717 exit;
720 begin
723 if (es = nil) then raise Exception.Create(Format('record enum type ''%s'' for field ''%s'' not found', [mEBSName, mName]));
725 begin
727 begin
730 exit;
733 raise Exception.Create(Format('value %d in record enum type ''%s'' for field ''%s'' not found', [mIVal, mEBSName, mName]));
736 begin
739 if (es = nil) then raise Exception.Create(Format('record bitset type ''%s'' for field ''%s'' not found', [mEBSName, mName]));
740 // none?
742 begin
744 begin
746 begin
749 exit;
752 raise Exception.Create(Format('value %d in record bitset type ''%s'' for field ''%s'' not found', [0, mEBSName, mName]));
754 // not none
758 begin
760 begin
763 begin
765 begin
769 break;
772 if not found then raise Exception.Create(Format('value %d in record bitset type ''%s'' for field ''%s'' not found', [mask, mEBSName, mName]));
777 exit;
784 begin
786 exit;
789 begin
790 if (mMaxDim = 0) then raise Exception.Create(Format('invalid string size definition for field ''%s''', [mName]));
793 exit;
801 begin
803 exit;
806 begin
809 exit;
813 begin
815 exit;
818 begin
820 exit;
823 begin
825 exit;
836 begin
838 if (mIVal < min) or (mIVal > max) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
842 var
848 begin
849 // if this field should contain struct, convert type and parse struct
853 begin
855 // ugly hack. sorry.
857 begin
859 // find trigger definition
861 if (tfld = nil) then raise Exception.Create(Format('triggerdata value for field ''%s'' in record ''%s'' without ''type'' field', [mName, rec.mName]));
862 if (tfld.mEBS <> TEBS.TEnum) then raise Exception.Create(Format('triggerdata value for field ''%s'' in record ''%s'' with bad ''type'' field', [mName, rec.mName]));
864 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]));
871 exit;
873 // other record types
875 begin
877 if (rec = nil) then raise Exception.Create(Format('record ''%s'' (%s) value for field ''%s'' not found', [pr.tokStr, mEBSName, mName]));
884 exit;
885 end
887 begin
889 if (rec = nil) then raise Exception.Create(Format('record type ''%s'' for field ''%s'' not found', [mEBSName, mName]));
896 exit;
901 begin
904 if (es = nil) then raise Exception.Create(Format('record enum type ''%s'' for field ''%s'' not found', [mEBSName, mName]));
906 if not es.has[tk] then raise Exception.Create(Format('record enum value ''%s'' of type ''%s'' for field ''%s'' not found', [tk, mEBSName, mName]));
909 //writeln('ENUM ', mEBSName, '; element <', mSVal, '> with value ', mIVal);
912 exit;
915 begin
918 if (es = nil) then raise Exception.Create(Format('record bitset type ''%s'' for field ''%s'' not found', [mEBSName, mName]));
921 begin
923 if not es.has[tk] then raise Exception.Create(Format('record bitset value ''%s'' of type ''%s'' for field ''%s'' not found', [tk, mEBSName, mName]));
927 if mBitSetUnique then raise Exception.Create(Format('record bitset of type ''%s'' for field ''%s'' expects only one value', [tk, mEBSName, mName]));
928 //pr.expectDelim('|');
933 exit;
940 begin
946 exit;
949 begin
950 if (mMaxDim = 0) then raise Exception.Create(Format('invalid string size definition for field ''%s''', [mName]));
953 begin
954 // single char
955 if (Length(mSVal) <> 1) then raise Exception.Create(Format('invalid string size for field ''%s''', [mName]));
958 end
959 else
960 begin
961 // string
962 if (Length(mSVal) > mMaxDim) then raise Exception.Create(Format('invalid string size for field ''%s''', [mName]));
966 exit;
969 begin
972 exit;
975 begin
978 exit;
981 begin
984 exit;
987 begin
990 exit;
993 begin
996 exit;
999 begin
1002 exit;
1005 begin
1009 exit;
1013 begin
1017 begin
1018 if (mIVal < -32768) or (mIVal > 32767) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1019 end
1020 else
1021 begin
1022 if (mIVal < 0) or (mIVal > 32767) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1026 begin
1027 if (mIVal2 < -32768) or (mIVal2 > 32767) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1028 end
1029 else
1030 begin
1031 if (mIVal2 < 0) or (mIVal2 > 32767) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1036 exit;
1039 begin
1041 exit;
1044 begin
1046 exit;
1054 // ////////////////////////////////////////////////////////////////////////// //
1056 begin
1057 if (pr = nil) then raise Exception.Create('cannot create record type without type definition');
1070 begin
1080 begin
1089 begin
1092 begin
1101 begin
1107 var
1109 begin
1116 begin
1122 var
1124 begin
1132 var
1134 begin
1144 begin
1154 var
1157 begin
1159 begin
1162 begin
1164 begin
1168 if isForTrig[tdn] then raise Exception.Create(Format('duplicate trigdata ''%s'' trigtype ''%s''', [mName, tdn]));
1172 end
1173 else
1174 begin
1179 end
1180 else
1181 begin
1186 begin
1189 begin
1190 if (mSize > 0) then raise Exception.Create(Format('duplicate `size` in record ''%s''', [mName]));
1192 if (mSize < 1) then raise Exception.Create(Format('invalid record ''%s'' size: %d', [mName, mSize]));
1194 continue;
1197 begin
1198 if (mBinBlock >= 0) then raise Exception.Create(Format('duplicate `binblock` in record ''%s''', [mName]));
1200 if (mBinBlock < 1) then raise Exception.Create(Format('invalid record ''%s'' binblock: %d', [mName, mBinBlock]));
1201 continue;
1207 // load fields
1209 begin
1211 if hasByName(fld.name) then begin fld.Free(); raise Exception.Create(Format('duplicate field ''%s''', [fld.name])); end;
1212 // append
1216 // done with field
1217 //writeln('DEF: ', fld.definition);
1224 var
1226 begin
1228 begin
1229 // trigger data
1232 begin
1235 begin
1240 end
1241 else
1242 begin
1245 end
1246 else
1247 begin
1248 // record
1255 begin
1265 var
1268 begin
1270 begin
1277 try
1279 begin
1281 // record list?
1283 begin
1286 begin
1290 continue;
1297 finally
1306 var
1311 begin
1312 if (mOwner = nil) then raise Exception.Create(Format('can''t parse record ''%s'' value without owner', [mName]));
1315 begin
1316 // id?
1323 begin
1328 // records
1330 begin
1334 begin
1336 begin
1337 // find (or create) list of records with this type
1340 begin
1341 // first record
1347 if (fld.mType <> TDynField.TType.TList) then raise Exception.Create(Format('thing ''%s'' in record ''%s'' must be record', [fld.mName, mName]));
1349 try
1353 begin
1355 begin
1356 if (Length(fld.mRVal[c].mId) > 0) and (CompareText(fld.mRVal[c].mId, rec.mId) = 0) then raise Exception.Create(Format('duplicate thing ''%s'' in record ''%s''', [fld.mName, mName]));
1361 writeln('added ''', mOwner.records[f].mName, ''' with id ''', rec.mId, ''' (total:', Length(fld.mRVal), ')');
1362 //assert(mOwner.findRecordById(mOwner.records[f].mName, rec.mId) <> nil);
1364 finally
1368 break;
1374 // fields
1377 begin
1378 if fld.defined then raise Exception.Create(Format('duplicate field ''%s'' in record ''%s''', [fld.mName, mName]));
1379 if fld.internal then raise Exception.Create(Format('internal field ''%s'' in record ''%s''', [fld.mName, mName]));
1382 continue;
1385 // something is wrong
1389 // fix field defaults
1395 // ////////////////////////////////////////////////////////////////////////// //
1397 begin
1404 begin
1411 begin
1422 begin
1425 begin
1434 begin
1440 var
1442 begin
1449 var
1451 begin
1455 // fields
1458 begin
1462 begin
1466 end
1467 else
1468 begin
1473 // max field
1480 var
1486 begin
1495 begin
1498 begin
1499 if (CompareText(mIds[f], idname) = 0) then raise Exception.Create(Format('duplicate field ''%s'' in enum/bitset ''%s''', [idname, mName]));
1501 if (CompareText(mMaxName, idname) = 0) then raise Exception.Create(Format('duplicate field ''%s'' in enum/bitset ''%s''', [idname, mName]));
1505 // has value?
1507 begin
1509 begin
1510 if (Length(mMaxName) > 0) then raise Exception.Create(Format('duplicate max field ''%s'' in enum/bitset ''%s''', [idname, mName]));
1513 end
1514 else
1515 begin
1521 // append it?
1523 begin
1524 // fix maxvalue
1526 begin
1533 // next cv
1535 begin
1544 // add max field
1546 begin
1555 // ////////////////////////////////////////////////////////////////////////// //
1557 begin
1567 var
1569 begin
1581 begin
1588 var
1590 begin
1592 begin
1600 var
1602 begin
1604 begin
1612 var
1614 begin
1616 begin
1624 var
1628 begin
1631 // find record type
1632 //writeln('searching for type <', atypename, '>');
1635 // find record data
1636 //writeln('searching for data of type <', atypename, '>');
1640 // find by id
1641 //writeln('searching for data of type <', atypename, '> with id <', aid, '> (', Length(fld.mRVal), ')');
1643 begin
1645 begin
1646 //writeln(' FOUND!');
1648 exit;
1651 // alas
1656 var
1660 begin
1663 begin
1668 begin
1671 begin
1678 //writeln(eb.definition); writeln;
1679 continue;
1683 begin
1686 begin
1688 begin
1696 //writeln(dr.definition); writeln;
1697 continue;
1701 //writeln(dr.definition); writeln;
1702 if (findRec(dr.name) <> nil) then begin dr.Free(); raise Exception.Create(Format('duplicate record ''%s''', [dr.name])); end;
1703 if (hdr <> nil) and (CompareText(dr.name, hdr.name) = 0) then begin dr.Free(); raise Exception.Create(Format('duplicate record ''%s''', [dr.name])); end;
1706 begin
1707 if (hdr <> nil) then begin dr.Free(); raise Exception.Create(Format('duplicate header record ''%s'' (previous is ''%s'')', [dr.name, hdr.name])); end;
1709 end
1710 else
1711 begin
1724 // ////////////////////////////////////////////////////////////////////////// //
1726 var
1728 begin
1729 if (curheader <> nil) then raise Exception.Create('cannot call `parseMap()` recursively, sorry');
1731 try
1738 finally