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
22 xparser;
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
144 private
154 public
167 public
181 private
190 private
199 public
205 public
214 private
217 private
220 public
225 private
230 public
240 public
245 implementation
247 uses
248 SysUtils;
251 // ////////////////////////////////////////////////////////////////////////// //
253 begin
264 begin
271 begin
278 begin
308 var
310 begin
323 begin
325 end
326 else
327 begin
350 procedure TDynField.setSVal (const v: AnsiString); inline; begin mSVal := v; mDefined := true; end;
353 // won't work for lists
355 begin
379 var
382 begin
384 begin
386 begin
388 raise Exception.Create(Format('field ''%s'' in record ''%s'' of record type ''%s'' is not set', [mName, mOwner.mId, mOwner.mName]));
391 begin
392 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]));
396 exit;
404 //mDefined := true;
405 //writeln('DEFAULT for <', mName, '>: <', s, '>');
407 try
409 finally
419 var
423 begin
425 //result := mDefaultValueSet;
430 TType.TPoint, TType.TSize: begin result := false; exit; end; // no default values for these types yet
434 try
438 finally
446 begin
467 begin
476 TEBS.TBitSet: begin result += ' bitset '; if mBitSetUnique then result += 'unique '; result += mEBSName; end;
479 begin
480 if (mType = TType.TChar) or (mType = TType.TString) then result += ' default '+TTextParser.quote(mDefSVal)
482 {
483 else
484 begin
485 if (mType = TType.TBool) then
486 begin
487 result += ' default ';
488 if (mDefIVal <> 0) then result += 'true' else result += 'false';
489 end
490 else
491 begin
492 result += Format(' default %d', [mDefIVal]);
493 end;
494 end;
495 }
498 begin
499 if (mType = TType.TPoint) then begin if (mAsT) then result += ' as txy' else result += ' as xy'; end
500 else if (mType = TType.TSize) then begin if (mAsT) then result += ' as twh' else result += ' as wh'; end;
508 var
525 begin
546 // field name
549 // field type
553 // fixed-size array?
555 begin
557 if (lmaxdim < 1) then raise Exception.Create(Format('invali field ''%s'' array size', [fldname]));
562 begin
564 begin
565 if (fldofs >= 0) then raise Exception.Create(Format('duplicate field ''%s'' offset', [fldname]));
568 continue;
572 begin
578 continue;
582 begin
584 if (Length(fldrecname) <> 0) then raise Exception.Create(Format('field ''%s'' already typed as ''%s''', [fldname, fldrecname]));
586 continue;
590 begin
592 if (Length(fldrecname) <> 0) then raise Exception.Create(Format('field ''%s'' already typed as ''%s''', [fldname, fldrecname]));
595 continue;
599 begin
600 if hasdefStr or hasdefInt or hasdefId then raise Exception.Create(Format('field ''%s'' has duplicate default', [fldname]));
603 begin
608 begin
613 begin
617 else
620 continue;
624 begin
626 continue;
630 begin
632 continue;
635 if (pr.tokType <> pr.TTId) then raise Exception.Create(Format('field ''%s'' has something unexpected in definition', [fldname]));
637 if (Length(fldrecname) <> 0) then raise Exception.Create(Format('field ''%s'' already typed as ''%s''', [fldname, fldrecname]));
644 // create field
659 else raise Exception.Create(Format('field ''%s'' has invalid type ''%s''', [fldname, fldtype]));
661 {if hasdefId and (self.baseType = self.TType.TBool) then
662 begin
663 if (defstr = 'true') or (defstr = 'tan') or (defstr = 'yes') then self.mDefIVal := 1
664 else if (defstr = 'false') or (defstr = 'ona') or (defstr = 'no') then self.mDefIVal := 0
665 else raise Exception.Create(Format('field ''%s'' has invalid boolean default ''%s''', [fldname, defstr]));
666 end
667 else}
668 begin
690 var
695 begin
698 // if this field should contain struct, convert type and parse struct
702 begin
704 begin
706 end
708 begin
710 end
711 else
712 begin
716 exit;
719 begin
722 if (es = nil) then raise Exception.Create(Format('record enum type ''%s'' for field ''%s'' not found', [mEBSName, mName]));
724 begin
726 begin
729 exit;
732 raise Exception.Create(Format('value %d in record enum type ''%s'' for field ''%s'' not found', [mIVal, mEBSName, mName]));
735 begin
738 if (es = nil) then raise Exception.Create(Format('record bitset type ''%s'' for field ''%s'' not found', [mEBSName, mName]));
739 // none?
741 begin
743 begin
745 begin
748 exit;
751 raise Exception.Create(Format('value %d in record bitset type ''%s'' for field ''%s'' not found', [0, mEBSName, mName]));
753 // not none
757 begin
759 begin
762 begin
764 begin
768 break;
771 if not found then raise Exception.Create(Format('value %d in record bitset type ''%s'' for field ''%s'' not found', [mask, mEBSName, mName]));
776 exit;
783 begin
785 exit;
788 begin
789 if (mMaxDim = 0) then raise Exception.Create(Format('invalid string size definition for field ''%s''', [mName]));
792 exit;
800 begin
802 exit;
805 begin
808 exit;
812 begin
814 exit;
817 begin
819 exit;
822 begin
824 exit;
835 begin
837 if (mIVal < min) or (mIVal > max) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
841 var
847 begin
848 // if this field should contain struct, convert type and parse struct
852 begin
854 // ugly hack. sorry.
856 begin
858 // find trigger definition
860 if (tfld = nil) then raise Exception.Create(Format('triggerdata value for field ''%s'' in record ''%s'' without ''type'' field', [mName, rec.mName]));
861 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]));
863 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]));
870 exit;
872 // other record types
874 begin
876 if (rec = nil) then raise Exception.Create(Format('record ''%s'' (%s) value for field ''%s'' not found', [pr.tokStr, mEBSName, mName]));
883 exit;
884 end
886 begin
888 if (rec = nil) then raise Exception.Create(Format('record type ''%s'' for field ''%s'' not found', [mEBSName, mName]));
895 exit;
900 begin
903 if (es = nil) then raise Exception.Create(Format('record enum type ''%s'' for field ''%s'' not found', [mEBSName, mName]));
905 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]));
908 //writeln('ENUM ', mEBSName, '; element <', mSVal, '> with value ', mIVal);
911 exit;
914 begin
917 if (es = nil) then raise Exception.Create(Format('record bitset type ''%s'' for field ''%s'' not found', [mEBSName, mName]));
920 begin
922 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]));
926 if mBitSetUnique then raise Exception.Create(Format('record bitset of type ''%s'' for field ''%s'' expects only one value', [tk, mEBSName, mName]));
927 //pr.expectDelim('|');
932 exit;
939 begin
945 exit;
948 begin
949 if (mMaxDim = 0) then raise Exception.Create(Format('invalid string size definition for field ''%s''', [mName]));
952 begin
953 // single char
954 if (Length(mSVal) <> 1) then raise Exception.Create(Format('invalid string size for field ''%s''', [mName]));
957 end
958 else
959 begin
960 // string
961 if (Length(mSVal) > mMaxDim) then raise Exception.Create(Format('invalid string size for field ''%s''', [mName]));
965 exit;
968 begin
971 exit;
974 begin
977 exit;
980 begin
983 exit;
986 begin
989 exit;
992 begin
995 exit;
998 begin
1001 exit;
1004 begin
1008 exit;
1012 begin
1016 begin
1017 if (mIVal < -32768) or (mIVal > 32767) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1018 end
1019 else
1020 begin
1021 if (mIVal < 0) or (mIVal > 32767) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1025 begin
1026 if (mIVal2 < -32768) or (mIVal2 > 32767) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1027 end
1028 else
1029 begin
1030 if (mIVal2 < 0) or (mIVal2 > 32767) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1035 exit;
1038 begin
1040 exit;
1043 begin
1045 exit;
1053 // ////////////////////////////////////////////////////////////////////////// //
1055 begin
1056 if (pr = nil) then raise Exception.Create('cannot create record type without type definition');
1068 begin
1078 begin
1087 begin
1090 begin
1099 begin
1105 var
1107 begin
1114 begin
1120 var
1122 begin
1130 var
1132 begin
1142 begin
1152 var
1155 begin
1157 begin
1160 begin
1162 begin
1166 if isForTrig[tdn] then raise Exception.Create(Format('duplicate trigdata ''%s'' trigtype ''%s''', [mName, tdn]));
1170 end
1171 else
1172 begin
1177 end
1178 else
1179 begin
1185 begin
1187 if (mSize < 1) then raise Exception.Create(Format('invalid record ''%s'' size: %d', [mName, mSize]));
1194 // load fields
1196 begin
1198 if hasByName(fld.name) then begin fld.Free(); raise Exception.Create(Format('duplicate field ''%s''', [fld.name])); end;
1199 // append
1203 // done with field
1204 //writeln('DEF: ', fld.definition);
1211 var
1213 begin
1215 begin
1216 // trigger data
1219 begin
1222 begin
1227 end
1228 else
1229 begin
1232 end
1233 else
1234 begin
1235 // record
1242 begin
1252 var
1255 begin
1257 begin
1264 try
1266 begin
1268 // record list?
1270 begin
1273 begin
1277 continue;
1284 finally
1293 var
1298 begin
1299 if (mOwner = nil) then raise Exception.Create(Format('can''t parse record ''%s'' value without owner', [mName]));
1302 begin
1303 // id?
1310 begin
1315 // records
1317 begin
1321 begin
1323 begin
1324 // find (or create) list of records with this type
1327 begin
1328 // first record
1334 if (fld.mType <> TDynField.TType.TList) then raise Exception.Create(Format('thing ''%s'' in record ''%s'' must be record', [fld.mName, mName]));
1336 try
1340 begin
1342 begin
1343 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]));
1348 writeln('added ''', mOwner.records[f].mName, ''' with id ''', rec.mId, ''' (total:', Length(fld.mRVal), ')');
1349 //assert(mOwner.findRecordById(mOwner.records[f].mName, rec.mId) <> nil);
1351 finally
1355 break;
1361 // fields
1364 begin
1365 if fld.defined then raise Exception.Create(Format('duplicate field ''%s'' in record ''%s''', [fld.mName, mName]));
1366 if fld.internal then raise Exception.Create(Format('internal field ''%s'' in record ''%s''', [fld.mName, mName]));
1369 continue;
1372 // something is wrong
1376 // fix field defaults
1382 // ////////////////////////////////////////////////////////////////////////// //
1384 begin
1391 begin
1398 begin
1409 begin
1412 begin
1421 begin
1427 var
1429 begin
1436 var
1438 begin
1442 // fields
1445 begin
1449 begin
1453 end
1454 else
1455 begin
1460 // max field
1467 var
1473 begin
1482 begin
1485 begin
1486 if (CompareText(mIds[f], idname) = 0) then raise Exception.Create(Format('duplicate field ''%s'' in enum/bitset ''%s''', [idname, mName]));
1488 if (CompareText(mMaxName, idname) = 0) then raise Exception.Create(Format('duplicate field ''%s'' in enum/bitset ''%s''', [idname, mName]));
1492 // has value?
1494 begin
1496 begin
1497 if (Length(mMaxName) > 0) then raise Exception.Create(Format('duplicate max field ''%s'' in enum/bitset ''%s''', [idname, mName]));
1500 end
1501 else
1502 begin
1508 // append it?
1510 begin
1511 // fix maxvalue
1513 begin
1520 // next cv
1522 begin
1531 // add max field
1533 begin
1542 // ////////////////////////////////////////////////////////////////////////// //
1544 begin
1554 var
1556 begin
1568 begin
1575 var
1577 begin
1579 begin
1587 var
1589 begin
1591 begin
1599 var
1601 begin
1603 begin
1611 var
1615 begin
1618 // find record type
1619 //writeln('searching for type <', atypename, '>');
1622 // find record data
1623 //writeln('searching for data of type <', atypename, '>');
1627 // find by id
1628 //writeln('searching for data of type <', atypename, '> with id <', aid, '> (', Length(fld.mRVal), ')');
1630 begin
1632 begin
1633 //writeln(' FOUND!');
1635 exit;
1638 // alas
1643 var
1647 begin
1650 begin
1655 begin
1658 begin
1665 //writeln(eb.definition); writeln;
1666 continue;
1670 begin
1673 begin
1675 begin
1683 //writeln(dr.definition); writeln;
1684 continue;
1688 //writeln(dr.definition); writeln;
1689 if (findRec(dr.name) <> nil) then begin dr.Free(); raise Exception.Create(Format('duplicate record ''%s''', [dr.name])); end;
1690 if (hdr <> nil) and (CompareText(dr.name, hdr.name) = 0) then begin dr.Free(); raise Exception.Create(Format('duplicate record ''%s''', [dr.name])); end;
1693 begin
1694 if (hdr <> nil) then begin dr.Free(); raise Exception.Create(Format('duplicate header record ''%s'' (previous is ''%s'')', [dr.name, hdr.name])); end;
1696 end
1697 else
1698 begin
1711 // ////////////////////////////////////////////////////////////////////////// //
1713 var
1715 begin
1716 if (curheader <> nil) then raise Exception.Create('cannot call `parseMap()` recursively, sorry');
1718 try
1725 finally