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 // ////////////////////////////////////////////////////////////////////////// //
31 type
33 public
38 private
41 public
44 public
53 // process one byte, return `true` if codepoint is ready
59 // ////////////////////////////////////////////////////////////////////////// //
64 // strips out name from `fn`, leaving trailing slash
67 // ends with '/' or '\'?
70 // strips extra trailing slashes in `path, and extra leading slashes in `fn`
71 // will add slash to `path`, even if `fn` is empty!
74 // does filename have one of ".wad", ".pk3", ".zip" extensions?
77 // does filepath have ".XXX:\" in it?
80 // adds ".wad" extension if filename doesn't have one of ".wad", ".pk3", ".zip"
83 // convert number to strig with nice commas
91 // `true` if strings are equal; ignoring case for cp1251
98 // `pathname` will be modified if path is valid
99 // `lastIsDir` should be `true` if we are searching for directory
100 // nobody cares about shitdoze, so i'll use the same code path for it
103 // return fixed AnsiString or empty AnsiString
106 // they throws
110 // little endian
138 // big endian
168 {$IF DEFINED(CPU386) OR DEFINED(CPUAMD64)}
170 {$ENDIF}
182 {$IF DEFINED(CPU386) OR DEFINED(CPUAMD64)}
184 {$ENDIF}
195 {$IF DEFINED(CPU386) OR DEFINED(CPUAMD64)}
197 {$ENDIF}
199 type
202 // returns formatted string if `writerCB` is `nil`, empty string otherwise
203 function formatstrf (const fmt: AnsiString; const args: array of const; writerCB: TFormatStrFCallback=nil): AnsiString;
210 // returns string in single or double quotes
211 // single quotes supports only pascal-style '' for single quote char
212 // double quotes supports c-style escapes
213 // function will select quote mode automatically
217 type
219 private
220 //type PItemT = ^ItemT;
223 public
224 type
226 private
230 public
237 private
241 private
248 public
252 //WARNING! don't change list contents in `for ... in`!
262 public
274 implementation
276 uses
277 xstreams;
280 // ////////////////////////////////////////////////////////////////////////// //
282 begin
287 begin
292 begin
297 // ////////////////////////////////////////////////////////////////////////// //
299 begin
306 begin
312 begin
317 // ////////////////////////////////////////////////////////////////////////// //
319 begin
327 begin
334 begin
340 begin
347 begin
354 begin
360 begin
367 begin
373 begin
379 var
381 begin
383 begin
393 var
395 begin
397 begin
404 var
406 begin
408 begin
411 end
412 else
413 begin
419 // ////////////////////////////////////////////////////////////////////////// //
420 var
425 // ////////////////////////////////////////////////////////////////////////// //
426 const
428 $0402,$0403,$201A,$0453,$201E,$2026,$2020,$2021,$20AC,$2030,$0409,$2039,$040A,$040C,$040B,$040F,
429 $0452,$2018,$2019,$201C,$201D,$2022,$2013,$2014,$003F,$2122,$0459,$203A,$045A,$045C,$045B,$045F,
430 $00A0,$040E,$045E,$0408,$00A4,$0490,$00A6,$00A7,$0401,$00A9,$0404,$00AB,$00AC,$00AD,$00AE,$0407,
431 $00B0,$00B1,$0406,$0456,$0491,$00B5,$00B6,$00B7,$0451,$2116,$0454,$00BB,$0458,$0405,$0455,$0457,
432 $0410,$0411,$0412,$0413,$0414,$0415,$0416,$0417,$0418,$0419,$041A,$041B,$041C,$041D,$041E,$041F,
433 $0420,$0421,$0422,$0423,$0424,$0425,$0426,$0427,$0428,$0429,$042A,$042B,$042C,$042D,$042E,$042F,
434 $0430,$0431,$0432,$0433,$0434,$0435,$0436,$0437,$0438,$0439,$043A,$043B,$043C,$043D,$043E,$043F,
436 );
440 var
442 begin
450 // ////////////////////////////////////////////////////////////////////////// //
451 // fast state-machine based UTF-8 decoder; using 8 bytes of memory
452 // code points from invalid range will never be valid, this is the property of the state machine
453 const
454 // see http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
456 // maps bytes to character classes
473 // maps a combination of a state of the automaton and a character class to a state
483 // ////////////////////////////////////////////////////////////////////////// //
484 constructor TUtf8DecoderFast.Create (v: Boolean{fuck you, fpc}); begin state := Accept; codepoint := 0; end;
490 function TUtf8DecoderFast.completeOrInvalid (): Boolean; inline; begin result := (state = Accept) or (state = Reject); end;
492 function TUtf8DecoderFast.decode (c: AnsiChar): Boolean; inline; overload; begin result := decode(Byte(c)); end;
495 var
497 begin
500 if (state <> Accept) then codepoint := (b and $3f) or (codepoint shl 6) else codepoint := ($ff shr tp) and b;
507 // ////////////////////////////////////////////////////////////////////////// //
509 begin
515 // ////////////////////////////////////////////////////////////////////////// //
517 var
520 begin
522 begin
524 begin
528 begin
531 exit;
539 var
543 begin
546 begin
548 end
550 begin
553 end
555 begin
559 end
561 begin
566 end
567 else
568 begin
573 begin
575 begin
577 begin
580 begin
582 begin
584 end
585 else
586 begin
590 exit;
597 // ////////////////////////////////////////////////////////////////////////// //
599 begin
604 begin
607 end
608 else
609 begin
618 // ////////////////////////////////////////////////////////////////////////// //
622 var
624 begin
627 begin
635 var
638 begin
641 begin
649 begin
652 end
654 begin
657 end
658 else
659 begin
666 var
669 begin
671 begin
679 // ////////////////////////////////////////////////////////////////////////// //
681 var
684 begin
687 begin
690 begin
692 exit;
702 var
705 begin
710 begin
722 var
725 begin
729 begin
732 begin
734 begin
736 end
737 else
738 begin
741 exit;
748 begin
755 // strips out name from `fn`, leaving trailing slash
757 var
760 begin
765 begin
774 // ends with '/' or '\'?
776 begin
778 begin
780 end
781 else
782 begin
788 // strips extra trailing slashes in `path, and extra leading slashes in `fn`
789 // will add slash to `path`, even if `fn` is empty!
791 var
793 begin
797 if (Length(result) > 0) and ((result[Length(result)] <> '/') and (result[Length(result)] <> '\')) then result += '/';
799 begin
801 //FIXME: make this faster!
802 while (Length(result) > 0) and ((result[Length(result)] = '/') or (result[Length(result)] = '\')) do
803 begin
812 var
814 begin
816 result := StrEquCI1251(ext, '.wad') or StrEquCI1251(ext, '.pk3') or StrEquCI1251(ext, '.zip') or StrEquCI1251(ext, '.dfz');
821 begin
828 var
831 begin
835 begin
837 begin
840 begin
842 if StrEquCI1251(s, '.wad') or StrEquCI1251(s, '.pk3') or StrEquCI1251(s, '.zip') or StrEquCI1251(s, '.dfz') then
843 begin
845 exit;
855 var
857 begin
861 begin
868 begin
870 begin
872 end
873 else
874 begin
876 begin
878 end
879 else
880 begin
892 begin
894 begin
896 end
897 else
898 begin
900 begin
902 end
903 else
904 begin
916 var
918 begin
927 var
930 begin
932 begin
934 begin
938 exit;
941 // nothing to do
946 // ////////////////////////////////////////////////////////////////////////// //
947 // utils
948 // `ch`: utf8 start
949 // -1: invalid utf8
951 begin
963 var
965 begin
969 begin
975 // check other sequence bytes
977 begin
987 // ////////////////////////////////////////////////////////////////////////// //
988 const
990 $0402,$0403,$201A,$0453,$201E,$2026,$2020,$2021,$20AC,$2030,$0409,$2039,$040A,$040C,$040B,$040F,
991 $0452,$2018,$2019,$201C,$201D,$2022,$2013,$2014,$003F,$2122,$0459,$203A,$045A,$045C,$045B,$045F,
992 $00A0,$040E,$045E,$0408,$00A4,$0490,$00A6,$00A7,$0401,$00A9,$0404,$00AB,$00AC,$00AD,$00AE,$0407,
993 $00B0,$00B1,$0406,$0456,$0491,$00B5,$00B6,$00B7,$0451,$2116,$0454,$00BB,$0458,$0405,$0455,$0457,
994 $0410,$0411,$0412,$0413,$0414,$0415,$0416,$0417,$0418,$0419,$041A,$041B,$041C,$041D,$041E,$041F,
995 $0420,$0421,$0422,$0423,$0424,$0425,$0426,$0427,$0428,$0429,$042A,$042B,$042C,$042D,$042E,$042F,
996 $0430,$0431,$0432,$0433,$0434,$0435,$0436,$0437,$0438,$0439,$043A,$043B,$043C,$043D,$043E,$043F,
998 );
1002 var
1004 begin
1005 (* The following encodings are valid, except for the 5 and 6 byte
1006 * combinations:
1007 * 0xxxxxxx
1008 * 110xxxxx 10xxxxxx
1009 * 1110xxxx 10xxxxxx 10xxxxxx
1010 * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
1011 * 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
1012 * 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
1013 *)
1021 // mask out unused bits
1029 // now continue
1031 begin
1039 // done, try 1251
1041 // alas
1046 var
1048 begin
1052 begin
1063 // ////////////////////////////////////////////////////////////////////////// //
1064 // `pathname` will be modified if path is valid
1065 // `lastIsDir` should be `true` if we are searching for directory
1066 // nobody cares about shitdoze, so i'll use the same code path for it
1068 var
1076 begin
1081 begin
1082 // remove trailing slashes
1085 // extract name
1088 begin
1092 // remove trailing slashes again
1095 //writeln(Format('npt=[%s]; newname=[%s]; curname=[%s]; wantdir=%d', [npt, newname, curname, Integer(wantdir)]));
1096 // try the easiest case first
1099 begin
1101 begin
1102 // i found her!
1105 continue;
1108 //writeln(Format('npt=[%s]; newname=[%s]; curname=[%s]; wantdir=%d', [npt, newname, curname, Integer(wantdir)]));
1109 // alas, either not found, or invalid attributes
1111 try
1113 repeat
1115 begin
1116 // i found her!
1120 break;
1123 finally
1132 const fileExtensions: array [0..6] of AnsiString = ('.wad', '.dfzip', '.dfwad', '.pk3', '.pak', '.zip', '.dfz');
1135 var
1138 begin
1140 //writeln('findDiskWad00: fname=<', fname, '>');
1144 //writeln(' findDiskWad01: fname=<', fname, '>; origExt=<', origExt, '>');
1146 begin
1147 //writeln(' findDiskWad02: fname=<', fname, '>; origExt=<', origExt, '>; newExt=<', newExt, '>');
1149 begin
1150 //writeln(' SKIP');
1151 continue;
1161 begin
1167 var
1169 begin
1172 begin
1173 if not findFileCI(path, true) then raise Exception.Create('can''t create file "'+pathname+'"');
1180 {$IFDEF ENDIAN_LITTLE}
1181 begin
1184 {$ELSE}
1185 var
1187 begin
1190 begin
1196 {$ENDIF}
1199 {$IFDEF ENDIAN_LITTLE}
1200 var
1202 begin
1205 begin
1211 {$ELSE}
1212 begin
1215 {$ENDIF}
1218 begin
1223 var
1226 begin
1229 begin
1231 begin
1234 end
1235 else
1236 begin
1238 begin
1257 procedure writeIntBE (st: TStream; v: ShortInt); overload; begin writeIntegerBE(st, @v, 1); end;
1259 procedure writeIntBE (st: TStream; v: SmallInt); overload; begin writeIntegerBE(st, @v, 2); end;
1260 procedure writeIntBE (st: TStream; v: LongWord); overload; begin writeIntegerBE(st, @v, 4); end;
1261 procedure writeIntBE (st: TStream; v: LongInt); overload; begin writeIntegerBE(st, @v, 4); end;
1270 begin
1272 if (maxlen <= 65535) then writeInt(st, Word(Length(str))) else writeInt(st, LongWord(Length(str)));
1277 var
1279 begin
1284 begin
1292 {$IFDEF ENDIAN_LITTLE}
1293 begin
1296 {$ELSE}
1297 var
1299 begin
1302 begin
1308 {$ENDIF}
1311 {$IFDEF ENDIAN_LITTLE}
1312 var
1314 begin
1317 begin
1323 {$ELSE}
1324 begin
1327 {$ENDIF}
1348 // ////////////////////////////////////////////////////////////////////////// //
1349 function nmin (a, b: Byte): Byte; inline; overload; begin if (a < b) then result := a else result := b; end;
1350 function nmin (a, b: ShortInt): ShortInt; inline; overload; begin if (a < b) then result := a else result := b; end;
1351 function nmin (a, b: Word): Word; inline; overload; begin if (a < b) then result := a else result := b; end;
1352 function nmin (a, b: SmallInt): SmallInt; inline; overload; begin if (a < b) then result := a else result := b; end;
1353 function nmin (a, b: LongWord): LongWord; inline; overload; begin if (a < b) then result := a else result := b; end;
1354 function nmin (a, b: LongInt): LongInt; inline; overload; begin if (a < b) then result := a else result := b; end;
1355 function nmin (a, b: Int64): Int64; inline; overload; begin if (a < b) then result := a else result := b; end;
1356 function nmin (a, b: UInt64): UInt64; inline; overload; begin if (a < b) then result := a else result := b; end;
1357 function nmin (a, b: Single): Single; inline; overload; begin if (a < b) then result := a else result := b; end;
1358 function nmin (a, b: Double): Double; inline; overload; begin if (a < b) then result := a else result := b; end;
1359 {$IF DEFINED(CPU386) OR DEFINED(CPUAMD64)}
1360 function nmin (a, b: Extended): Extended; inline; overload; begin if (a < b) then result := a else result := b; end;
1361 {$ENDIF}
1363 function nmax (a, b: Byte): Byte; inline; overload; begin if (a > b) then result := a else result := b; end;
1364 function nmax (a, b: ShortInt): ShortInt; inline; overload; begin if (a > b) then result := a else result := b; end;
1365 function nmax (a, b: Word): Word; inline; overload; begin if (a > b) then result := a else result := b; end;
1366 function nmax (a, b: SmallInt): SmallInt; inline; overload; begin if (a > b) then result := a else result := b; end;
1367 function nmax (a, b: LongWord): LongWord; inline; overload; begin if (a > b) then result := a else result := b; end;
1368 function nmax (a, b: LongInt): LongInt; inline; overload; begin if (a > b) then result := a else result := b; end;
1369 function nmax (a, b: Int64): Int64; inline; overload; begin if (a > b) then result := a else result := b; end;
1370 function nmax (a, b: UInt64): UInt64; inline; overload; begin if (a > b) then result := a else result := b; end;
1371 function nmax (a, b: Single): Single; inline; overload; begin if (a > b) then result := a else result := b; end;
1372 function nmax (a, b: Double): Double; inline; overload; begin if (a > b) then result := a else result := b; end;
1373 {$IF DEFINED(CPU386) OR DEFINED(CPUAMD64)}
1374 function nmax (a, b: Extended): Extended; inline; overload; begin if (a > b) then result := a else result := b; end;
1375 {$ENDIF}
1377 function nclamp (v, a, b: Byte): Byte; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
1378 function nclamp (v, a, b: ShortInt): ShortInt; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
1379 function nclamp (v, a, b: Word): Word; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
1380 function nclamp (v, a, b: SmallInt): SmallInt; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
1381 function nclamp (v, a, b: LongWord): LongWord; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
1382 function nclamp (v, a, b: LongInt): LongInt; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
1383 function nclamp (v, a, b: Int64): Int64; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
1384 function nclamp (v, a, b: UInt64): UInt64; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
1385 function nclamp (v, a, b: Single): Single; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
1386 function nclamp (v, a, b: Double): Double; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
1387 {$IF DEFINED(CPU386) OR DEFINED(CPUAMD64)}
1388 function nclamp (v, a, b: Extended): Extended; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
1389 {$ENDIF}
1391 // ////////////////////////////////////////////////////////////////////////// //
1392 {$IFDEF WINDOWS}
1393 function snprintf (buf: PAnsiChar; bufsize: SizeUInt; const fmt: PAnsiChar): SizeUInt; cdecl; varargs; external 'msvcrt.dll' name '_snprintf';
1394 {$ELSE}
1395 {$IFDEF GO32V2}
1398 begin
1399 {$WARNING snprintf not implemented!}
1404 function snprintf (buf: PAnsiChar; bufsize: SizeUInt; const fmt: PAnsiChar; x: LongInt): SizeUInt; overload;
1405 begin
1406 {$WARNING snprintf+longint not implemented!}
1411 function snprintf (buf: PAnsiChar; bufsize: SizeUInt; const fmt: PAnsiChar; x: PAnsiChar): SizeUInt; overload;
1412 begin
1413 {$WARNING snprintf+string not implemented!}
1418 function snprintf (buf: PAnsiChar; bufsize: SizeUInt; const fmt: PAnsiChar; x: Char): SizeUInt; overload;
1419 begin
1420 {$WARNING snprintf+char not implemented!}
1425 function snprintf (buf: PAnsiChar; bufsize: SizeUInt; const fmt: PAnsiChar; x: Double): SizeUInt; overload;
1426 begin
1427 {$WARNING snprintf+double not implemented!}
1432 {$ELSE}
1433 function snprintf (buf: PAnsiChar; bufsize: SizeUInt; const fmt: PAnsiChar): SizeUInt; cdecl; varargs; external 'libc' name 'snprintf';
1434 {$ENDIF}
1435 {$ENDIF}
1438 (*
1439 procedure conwriter (constref buf; len: SizeUInt);
1440 var
1441 ss: ShortString;
1442 slen: Integer;
1443 b: PByte;
1444 begin
1445 if (len < 1) then exit;
1446 b := PByte(@buf);
1447 while (len > 0) do
1448 begin
1449 if (len > 255) then slen := 255 else slen := Integer(len);
1450 Move(b^, ss[1], len);
1451 ss[0] := AnsiChar(slen);
1452 write(ss);
1453 b += slen;
1454 len -= slen;
1455 end;
1456 end;
1457 *)
1460 function formatstrf (const fmt: AnsiString; const args: array of const; writerCB: TFormatStrFCallback=nil): AnsiString;
1461 const
1463 PadZeroes: AnsiString = '00000000000000000000000000000000000000000000000000000000000000000000000';
1464 var
1480 var
1484 begin
1488 begin
1490 end
1491 else
1492 begin
1494 begin
1506 begin
1511 begin
1517 var
1519 begin
1525 var
1527 begin
1533 begin
1537 begin
1547 begin
1552 var
1555 begin
1557 begin
1561 end
1562 else
1563 begin
1568 repeat
1570 begin
1574 end
1575 else
1576 begin
1578 begin
1581 end
1593 var
1595 begin
1598 repeat
1600 begin
1604 end
1605 else
1606 begin
1608 begin
1611 end
1621 var
1623 begin
1625 begin
1633 var
1635 begin
1637 begin
1644 begin
1648 begin
1649 // print literal part
1652 // output literal part
1654 begin
1656 begin
1658 break;
1662 begin
1666 end
1667 else
1668 begin
1672 continue;
1674 // check if we have argument for this format string
1676 begin
1679 break;
1681 // skip percent
1685 // parse format; check for sign
1689 // parse width
1692 begin
1693 if (fmt[spos] < '0') or (fmt[spos] > '9') then begin xwrite('<INVALID FORMAT>'); writer((PAnsiChar(fmt)+spos-1)^, Length(fmt)-spos+1); break; end;
1697 begin
1703 end
1704 else
1705 begin
1709 // parse precision
1712 begin
1715 if (fmt[spos] < '0') or (fmt[spos] > '9') then begin xwrite('<INVALID FORMAT>'); writer((PAnsiChar(fmt)+spos-1)^, Length(fmt)-spos+1); break; end;
1718 begin
1725 // get format char
1729 // done parsing format, check for valid format chars
1730 if not (fmtch in ['s','u','d','x','X','p','f','g','c']) then begin xwrite('<INVALID FORMAT CHAR>'); writer((PAnsiChar(fmt)+spos-1)^, Length(fmt)-spos+1); break; end;
1731 // now write formatted string
1734 begin
1735 if not (fmtch in ['s','u','d','x','X']) then begin xwrite('<INVALID FORMAT CHAR>'); writer((PAnsiChar(fmt)+spos-1)^, Length(fmt)-spos+1); break; end;
1744 begin
1746 if args[curarg].VBoolean then strblen := snprintf(@strbuf[0], Length(strbuf), @fmtbuf[0], 'true')
1751 begin
1753 if args[curarg].VBoolean then strblen := snprintf(@strbuf[0], Length(strbuf), @fmtbuf[0], AnsiChar('t'))
1758 begin
1763 else
1764 begin
1767 break;
1773 begin
1780 begin
1785 else
1786 begin
1789 break;
1792 //vtWideChar: begin end; // args[curarg].VWideChar (WideChar)
1796 begin
1803 begin
1809 begin
1811 strblen := snprintf(@strbuf[0], Length(strbuf), @fmtbuf[0], Integer(trunc(args[curarg].VExtended^)));
1815 begin
1817 strblen := snprintf(@strbuf[0], Length(strbuf), @fmtbuf[0], LongWord(trunc(args[curarg].VExtended^)));
1820 else
1821 begin
1824 break;
1828 begin
1836 begin
1845 begin
1853 else
1854 begin
1857 break;
1862 begin
1866 end
1867 else
1868 begin
1876 begin
1877 if (args[curarg].VObject <> nil) then ccname := args[curarg].VObject.Classname else ccname := '<nil>';
1883 begin
1884 if (args[curarg].VClass <> nil) then ccname := args[curarg].VClass.Classname else ccname := '<nil>';
1889 //vtPWideChar: begin end; // args[curarg].VPWideChar (PWideChar)
1891 begin
1896 //vtCurrency: begin end; // args[curarg].VCurrency (PCurrency)
1897 //vtVariant: begin end; // args[curarg].VVariant^ (PVariant)
1898 //vtInterface: begin end; // args[curarg].VInterface (Pointer);
1899 //vtWideString: begin end; // args[curarg].VWideString (Pointer);
1901 begin
1906 else begin xwrite('<INVALID FORMAT CHAR>'); writer((PAnsiChar(fmt)+spos-1)^, Length(fmt)-spos+1); break; end;
1911 begin
1913 begin
1915 begin
1920 end
1921 else
1922 begin
1925 end
1926 else
1927 begin
1935 begin
1940 else begin xwrite('<INVALID FORMAT CHAR>'); writer((PAnsiChar(fmt)+spos-1)^, Length(fmt)-spos+1); break; end;
1944 if (sign <> '-') then begin if zeropad then indent0(width-pclen) else indent(width-pclen); end;
1948 else
1949 begin
1952 break;
1960 (*
1961 var
1962 ss: ShortString;
1963 ls: AnsiString;
1964 i64: Int64 = -$A000000000;
1965 ui64: UInt64 = $A000000000;
1966 begin
1967 writef(conwriter, 'test int:<%s> bool:<%s:%02d:%c> bool:<%s:%02d:%c>; char:<%2s;%c;%d>!'#10, [42, true, true, true, false, false, false, 'A', 'A', 'A']);
1968 writef(conwriter, 'test float:<%s;%u;%f;%g>'#10, [666.6942, 666.6942, 666.6942, 666.6942]);
1969 ss := 'fuckit';
1970 ls := 'FUCKIT';
1971 writef(conwriter, 'test ss:<%5s;%040s>'#10, [ss, ss]);
1972 writef(conwriter, 'test ls:<%5s;%040s>'#10, [ls, ls]);
1973 writef(conwriter, 'test pointer:<%s;%x;%p>'#10, [@ss, @ss, @ss]);
1974 writef(conwriter, 'test i64:<%s;%x;%015d;%u;%X>'#10, [i64, i64, i64, i64, i64]);
1975 writef(conwriter, 'test ui64:<%s;%x;%15d;%015u;%X>'#10, [ui64, ui64, ui64, ui64, ui64]);
1976 *)