628 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			628 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| unit Hak;
 | |
| 
 | |
| {$mode objfpc}{$H+}
 | |
| {$macro on}
 | |
| {$linklib hak}
 | |
| {$linklib c}
 | |
| {$linklib dl}
 | |
| {$linklib gcc}
 | |
| 
 | |
| {$if defined(HAK_LIB_QUADMATH_REQUIRED)}
 | |
| {$linklib quadmath}
 | |
| {$endif}
 | |
| 
 | |
| interface
 | |
| 
 | |
| uses SysUtils;
 | |
| 
 | |
| type
 | |
| 	BitMask = longword; (* this must match hak_bitmask_t in hak.h *)
 | |
| 
 | |
| (*const
 | |
| 	TRAIT_LANG_ENABLE_EOL = (BitMask(1) shl 14); *)
 | |
| 
 | |
| type
 | |
| 	Bchar = System.AnsiChar;
 | |
| 	PBchar = System.PAnsiChar;
 | |
| 
 | |
| {$if defined(HAK_WIDE_CHAR_SIZE_IS_4)}
 | |
| 	Uchar = System.UCS4Char;
 | |
| 	PUchar = System.PUCS4Char;
 | |
| {$else}
 | |
| 	Uchar = System.WideChar;
 | |
| 	PUchar = System.PWideChar;
 | |
| {$endif}
 | |
| 
 | |
| 	TraitBit = ( (* this enum must follow hak_trait_t in hak.h *)
 | |
| 		LANG_ENABLE_EOL = (BitMask(1) shl 14)
 | |
| 	);
 | |
| 
 | |
| 	Option = ( (* this enum must follow hak_option_t in hak.h *)
 | |
| 		TRAIT,
 | |
| 		LOG_MASK,
 | |
| 		LOG_MAXCAPA
 | |
| 	);
 | |
| 
 | |
| 	IoCmd = ( (* this enum must follow hak_io_cmd_t in hak.h *)
 | |
| 		IO_OPEN,
 | |
| 		IO_CLOSE,
 | |
| 		IO_READ,
 | |
| 		IO_READ_BYTES,
 | |
| 		IO_WRITE,
 | |
| 		IO_WRITE_BYTES,
 | |
| 		IO_FLUSH
 | |
| 	);
 | |
| 
 | |
| 	LocationB = record
 | |
| 		line: System.SizeUint;
 | |
| 		colm: System.SizeUint;
 | |
| 		filp: PBchar;
 | |
| 	end;
 | |
| 
 | |
| 	LocationU = record
 | |
| 		line: System.SizeUint;
 | |
| 		colm: System.SizeUint;
 | |
| 		filp: PUchar;
 | |
| 	end;
 | |
| 
 | |
| 	ErrorException = class(SysUtils.Exception)
 | |
| 	private
 | |
| 		error_code: integer;
 | |
| 		error_file: string;
 | |
| 		error_line: System.SizeUint;
 | |
| 		error_colm: System.SizeUint;
 | |
| 
 | |
| 	public
 | |
| 		constructor Create(const msg: string); overload;
 | |
| 		constructor Create(const msg: string; cod: integer; const fil: string; lin: System.SizeUint; col: System.SizeUint); overload;
 | |
| 
 | |
| 		property Code: integer read error_code;
 | |
| 		property Line: System.SizeUint read error_line;
 | |
| 		property Column: System.SizeUint read error_colm;
 | |
| 		property FileName: string read error_file;
 | |
| 	end;
 | |
| 
 | |
| {$ifndef HAK_CCI_BUF_LEN}
 | |
| {$define HAK_CCI_BUF_LEN := 2048}
 | |
| {$endif}
 | |
| 
 | |
| //{$packrecords c}
 | |
| 	CciArgPtr = ^CciArg;
 | |
| 	CciArg = record (* this record must follow the public part of hak_io_cciarg_t in hak.h *)
 | |
| 		name: PUchar;
 | |
| 		handle: pointer;
 | |
| 		byte_oriented: integer;
 | |
| 		buf: array[0..(HAK_CCI_BUF_LEN - 1)] of Uchar;
 | |
| 		xlen: System.SizeUint;
 | |
| 		includer: CciArgPtr;
 | |
| 	end;
 | |
| //{$packrecords normal}
 | |
| 
 | |
| 	Interp = class
 | |
| 	protected
 | |
| 		handle: pointer;
 | |
| 		basefile: string;
 | |
| 
 | |
| 	public
 | |
| 		constructor Create(x: integer);
 | |
| 		destructor Destroy(); override;
 | |
| 		procedure Ignite(heapsize: System.SizeUint);
 | |
| 		procedure AddBuiltinPrims();
 | |
| 		procedure CompileFile(filename: System.PAnsiChar);
 | |
| 		procedure CompileText(text: System.PAnsiChar);
 | |
| 		procedure CompileText(text: System.PAnsiChar; len: System.SizeUint);
 | |
| 		procedure CompileText(text: PUchar);
 | |
| 		procedure CompileText(text: PUchar; len: System.SizeUint);
 | |
| {$if defined(HAK_WIDE_CHAR_SIZE_IS_4)}
 | |
| 		procedure CompileText(text: PWideChar);
 | |
| 		procedure CompileText(text: PWideChar; len: System.SizeUint);
 | |
| {$endif}
 | |
| 		procedure Execute();
 | |
| 
 | |
| 	protected
 | |
| 		function FetchException(const hdr: string): Exception;
 | |
| 	end;
 | |
| 
 | |
| 	InterpExt = record
 | |
| 		self: Interp;
 | |
| 	end;
 | |
| 
 | |
| 	InterpExtPtr = ^InterpExt;
 | |
| 
 | |
| 	IO = class
 | |
| 	public
 | |
| 		procedure Open(); virtual; abstract;
 | |
| 		procedure Close(); virtual; abstract;
 | |
| 		function Read(): System.SizeUint; virtual; abstract;
 | |
| 	end;
 | |
| 
 | |
| 	SynerrBPtr = ^SynerrB;
 | |
| 	SynerrB = record
 | |
| 		num: integer;
 | |
| 		loc: LocationB;
 | |
| 	end;
 | |
| 
 | |
| 	ErrbinfPtr = ^Errbinf;
 | |
| 	Errbinf = record
 | |
| 		num: integer;
 | |
| 		msg: array[0..2047] of Bchar;
 | |
| 		loc: LocationB;
 | |
| 	end;
 | |
| 
 | |
| 	ErruinfPtr = ^Errbinf;
 | |
| 	Erruinf = record
 | |
| 		num: integer;
 | |
| 		msg: array[0..2047] of Uchar;
 | |
| 		loc: LocationU;
 | |
| 	end;
 | |
| 
 | |
| 	Errinf = Erruinf;
 | |
| 	ErrinfPtr = ErruinfPtr;
 | |
| 
 | |
| 
 | |
| (*----- external hak function -----*)
 | |
| function hak_errnum_to_errbcstr(errnum: integer; errbuf: pointer; errbufsz: System.SizeUint): pointer; cdecl; external;
 | |
| function hak_errnum_is_synerr(errnum: integer): boolean; cdecl; external;
 | |
| 
 | |
| function hak_openstd(xtnsize: System.SizeUint; errinf: pointer): pointer; cdecl; external;
 | |
| procedure hak_close(handle: pointer); cdecl; external;
 | |
| function hak_getxtn(handle: pointer): InterpExtPtr; cdecl; external;
 | |
| 
 | |
| function hak_setoption(handle: pointer; option: Option; value: pointer): integer; cdecl; external;
 | |
| function hak_getoption(handle: pointer; option: Option; value: pointer): integer; cdecl; external;
 | |
| 
 | |
| procedure hak_seterrnum(handle: pointer; errnum: integer); cdecl; external;
 | |
| function hak_geterrnum(handle: pointer): integer; cdecl; external;
 | |
| 
 | |
| procedure hak_seterrbmsg(handle: pointer; errnum: integer; errmsg: PBchar); cdecl; external;
 | |
| function hak_geterrbmsg(handle: pointer): PBchar; cdecl; external;
 | |
| 
 | |
| procedure hak_geterrbinf(handle: pointer; errinf: pointer); cdecl; external;
 | |
| procedure hak_geterruinf(handle: pointer; errinf: pointer); cdecl; external;
 | |
| 
 | |
| function hak_ignite(handle: pointer; heapsize: System.SizeUint): integer; cdecl; external;
 | |
| function hak_addbuiltinprims(handle: pointer): integer; cdecl; external;
 | |
| function hak_beginfeed(handle: pointer; on_cnode: pointer): integer; cdecl; external;
 | |
| function hak_feedbchars(handle: pointer; data: PBchar; len: System.SizeUint): integer; cdecl; external;
 | |
| function hak_feeduchars(handle: pointer; data: PUchar; len: System.SizeUint): integer; cdecl; external; (* this is wrong in deed - hak_uchar_t may not been Uchar ..*)
 | |
| function hak_endfeed(handle: pointer): integer; cdecl; external;
 | |
| 
 | |
| function hak_attachccio(handle: pointer; cci: pointer): integer; cdecl; external;
 | |
| function hak_attachcciostdwithbcstr(handle: pointer; cci: PBchar): integer; cdecl; external;
 | |
| procedure hak_detachccio(handle: pointer); cdecl; external;
 | |
| function hak_attachudiostdwithbcstr(handle: pointer; udi: PBchar; udo: PBchar): integer; cdecl; external;
 | |
| procedure hak_detachudio(handle: pointer); cdecl; external;
 | |
| function hak_compile(handle: pointer; cnode: pointer; flags: integer): integer; cdecl; external;
 | |
| function hak_execute(handle: pointer): pointer; cdecl; external;
 | |
| procedure hak_abort(handle: pointer) cdecl; external;
 | |
| 
 | |
| procedure hak_getsynerrb(handle: pointer; synerr: SynerrBPtr) cdecl; external;
 | |
| function hak_syserrstrb(handle: pointer; syserr_type: integer; syserr_code: integer; buf: PBchar; len: System.SizeUint): integer; cdecl; external;
 | |
| function hak_count_ucstr(ptr: PUchar): System.SizeUint; cdecl; external;
 | |
| (*----- end external hak function -----*)
 | |
| 
 | |
| implementation
 | |
| 
 | |
| uses Math, Classes;
 | |
| 
 | |
| type
 | |
| 	NamedHandle = record
 | |
| 		handle: THandle;
 | |
| 		name: System.RawByteString;
 | |
| 	end;
 | |
| 
 | |
| 	NamedHandlePtr = ^NamedHandle;
 | |
| 
 | |
| 
 | |
| function PUCS4CharLength(p: PUCS4Char): System.SizeUint;
 | |
| var
 | |
| 	len: System.SizeUint;
 | |
| begin
 | |
| 	len := 0;
 | |
| 	while p[len] <> 0 do Inc(len);
 | |
| 	exit(len);
 | |
| end;
 | |
| 
 | |
| function PUCS4CharToWideString(p: PUCS4Char): System.WideString;
 | |
| var
 | |
| 	len: System.SizeUint;
 | |
| 	arr: System.UCS4String;
 | |
| begin
 | |
| 	len := PUCS4CharLength(p);
 | |
| 
 | |
| 	(* len + 1 for SetLength because UCS4StringToWideString() skips the last character in RTL.
 | |
| 	   https://gitlab.com/freepascal.org/fpc/source/-/blob/main/rtl/inc/ustrings.inc
 | |
|   function UCS4StringToUnicodeString(const s : UCS4String) : UnicodeString;
 | |
|   var
 | |
|     i        : SizeInt;
 | |
|     reslen   : SizeInt;
 | |
|   begin
 | |
|     reslen:=0;
 | |
|     for i:=0 to length(s)-2 do
 | |
|       Inc(reslen,1+ord((s[i]>$ffff) and (cardinal(s[i])<=$10ffff)));
 | |
|     SetLength(result,reslen);
 | |
|     UCS4Decode(s,pointer(result));
 | |
|   end;
 | |
| 	*)
 | |
| 
 | |
| 	SetLength(arr, len + 1);
 | |
| 	Move(p^, arr[0], len * SizeOf(UCS4Char));
 | |
| 
 | |
| 	exit(UCS4StringToWideString(arr));
 | |
| end;
 | |
| 
 | |
| constructor ErrorException.Create (const msg: string);
 | |
| begin
 | |
| 	inherited Create(msg);
 | |
| end;
 | |
| 
 | |
| constructor ErrorException.Create (const msg: string; cod: integer; const fil: string; lin: System.SizeUint; col: System.SizeUint);
 | |
| begin
 | |
| 	inherited Create(msg);
 | |
| 	self.error_code := cod;
 | |
| 	self.error_file := fil;
 | |
| 	self.error_line := lin;
 | |
| 	self.error_colm := col;
 | |
| end;
 | |
| 
 | |
| constructor Interp.Create (x: integer);
 | |
| var
 | |
| 	h: pointer;
 | |
| 	ei: Errinf;
 | |
| 	ebi: Errbinf;
 | |
| 	tb: BitMask;
 | |
| 	ext: InterpExtPtr;
 | |
| begin
 | |
| 	h := hak_openstd(System.SizeOf(Interp), @ei);
 | |
| 	if h = nil then begin
 | |
| {$if defined(HAK_WIDE_CHAR_SIZE_IS_4)}
 | |
| 		raise Exception.Create(System.UTF8Encode(PUCS4CharToWideString(ei.msg)));
 | |
| {$else}
 | |
| 		raise Exception.Create(System.UTF8Encode(ei.msg));
 | |
| {$endif}
 | |
| 	end;
 | |
| 
 | |
| 	if hak_getoption(h, Option.TRAIT, @tb) <= -1 then tb := 0;
 | |
| 
 | |
| 	tb := tb or BitMask(TraitBit.LANG_ENABLE_EOL);
 | |
| 	if hak_setoption(h, Option.TRAIT, @tb) <= -1 then begin
 | |
| 		hak_geterrbinf(h, @ebi);
 | |
| 		hak_close(h);
 | |
| 		raise Exception.Create(ebi.msg);
 | |
| 	end;
 | |
| 
 | |
| 	self.handle := h;
 | |
| 
 | |
| 	ext := hak_getxtn(h);
 | |
| 	ext^.self := self;
 | |
| end;
 | |
| 
 | |
| destructor Interp.Destroy;
 | |
| begin
 | |
| 	if self.handle <> nil then
 | |
| 	begin
 | |
| 		hak_close(self.handle);
 | |
| 		self.handle := nil;
 | |
| 	end;
 | |
| 	inherited;
 | |
| end;
 | |
| 
 | |
| function Interp.FetchException(const hdr: string): Exception;
 | |
| var
 | |
| 	ebi: Errbinf;
 | |
| 	serr: SynerrB;
 | |
| 	filp: PBchar;
 | |
| 	xmsg: string;
 | |
| begin
 | |
| 	hak_geterrbinf(self.handle, @ebi);
 | |
| 	if hak_errnum_is_synerr(ebi.num) then begin
 | |
| 		hak_getsynerrb(self.handle, @serr);
 | |
| 		filp := PBchar('');
 | |
| 		if serr.loc.filp <> nil then filp := serr.loc.filp;
 | |
| 		exit(ErrorException.Create(string(ebi.msg), ebi.num, string(filp), serr.loc.line, serr.loc.colm));
 | |
| 	end
 | |
| 	else if ebi.loc.line > 0 then begin
 | |
| 		exit(ErrorException.Create(string(ebi.msg), ebi.num, string(ebi.loc.filp), ebi.loc.line, ebi.loc.colm));
 | |
| 	end
 | |
| 	else begin
 | |
| 		if hdr = '' then
 | |
| 			xmsg := string(ebi.msg)
 | |
| 		else
 | |
| 			xmsg := SysUtils.Format('%s - %s', [hdr, string(ebi.msg)]);
 | |
| 		exit(Exception.Create(xmsg));
 | |
| 	end;
 | |
| end;
 | |
| 
 | |
| procedure Interp.Ignite(heapsize: System.SizeUint);
 | |
| begin
 | |
| 	if hak_ignite(self.handle, heapsize) <= -1 then
 | |
| 	begin
 | |
| 		raise self.FetchException('failed to ignite');
 | |
| 	end;
 | |
| end;
 | |
| 
 | |
| procedure Interp.AddBuiltinPrims();
 | |
| begin
 | |
| 	if hak_addbuiltinprims(self.handle) <= -1 then
 | |
| 	begin
 | |
| 		raise self.FetchException('failed to add builtin primitives');
 | |
| 	end;
 | |
| end;
 | |
| 
 | |
| function handle_to_self(handle: pointer): Interp;
 | |
| var
 | |
| 	ext: InterpExtPtr;
 | |
| begin
 | |
| 	ext := hak_getxtn(handle);
 | |
| 	exit(ext^.self);
 | |
| end;
 | |
| 
 | |
| function cci_handler(handle: pointer; cmd: IoCmd; arg: CciArgPtr): integer; cdecl;
 | |
| var
 | |
| 	nf: NamedHandlePtr;
 | |
| 	len: System.LongInt;
 | |
| 	err: System.Integer;
 | |
| 	name: System.RawByteString;
 | |
| 	basedir: System.RawByteString;
 | |
| 	self: Interp;
 | |
| begin
 | |
| 	case cmd of
 | |
| 		IO_OPEN: begin
 | |
| 			self := handle_to_self(handle);
 | |
| 
 | |
| 			if arg^.includer = nil then begin
 | |
| 				(* main stream *)
 | |
| 				name := self.basefile;
 | |
| 			end
 | |
| 			else begin
 | |
| 				(* included file *)
 | |
| 				nf := NamedHandlePtr(arg^.includer^.handle);
 | |
| 				basedir := SysUtils.ExtractFilePath(nf^.name);
 | |
| 				name := System.UTF8Encode(WideString(arg^.name));
 | |
| 				if SysUtils.CompareStr(basedir, '') <> 0 then
 | |
| 					name := SysUtils.ConcatPaths([basedir, name]);
 | |
| 			end;
 | |
| 
 | |
| 			System.New(nf);
 | |
| 			if nf = nil then begin
 | |
| 				err := SysUtils.GetLastOSError();
 | |
| 				hak_seterrbmsg(handle, hak_syserrstrb(handle, 0, err, nil, 0), PBchar(SysUtils.SysErrorMessage(err)));
 | |
| 				exit(-1);
 | |
| 			end;
 | |
| 
 | |
| 			if arg^.includer <> nil then begin
 | |
| 				(* included file *)
 | |
| 				nf^.handle := SysUtils.FileOpen(name, SysUtils.fmOpenRead);
 | |
| 				if nf^.handle = System.THandle(-1) then begin
 | |
| 					err := SysUtils.GetLastOSError();
 | |
| 					hak_seterrbmsg(handle, hak_syserrstrb(handle, 0, err, nil, 0), PBchar(SysUtils.SysErrorMessage(err)));
 | |
| 					System.Dispose(nf);
 | |
| 					exit(-1);
 | |
| 				end;
 | |
| 			end
 | |
| 			else begin
 | |
| 				nf^.handle := THandle(-1);
 | |
| 			end;
 | |
| 
 | |
| 			nf^.name := name;
 | |
| 			arg^.handle := pointer(nf);
 | |
| 			arg^.byte_oriented := 1;
 | |
| 		end;
 | |
| 
 | |
| 		IO_CLOSE: begin
 | |
| 			nf := NamedHandlePtr(arg^.handle);
 | |
| 			if nf^.handle <> System.THandle(-1) then SysUtils.FileClose(nf^.handle);
 | |
| 			System.Dispose(nf);
 | |
| 		end;
 | |
| 
 | |
| 		IO_READ_BYTES: begin
 | |
| 			nf := NamedHandlePtr(arg^.handle);
 | |
| 			len := SysUtils.FileRead(nf^.handle, arg^.buf, System.SizeOf(arg^.buf)); (* use SizeOf a Uchar buffer as it needs to fill it with bytes *)
 | |
| 			if len <= -1 then begin
 | |
| 				hak_seterrbmsg(handle, hak_syserrstrb(handle, 0, err, nil, 0), PBchar(SysUtils.SysErrorMessage(err)));
 | |
| 				exit(-1);
 | |
| 			end;
 | |
| 			arg^.xlen := len;
 | |
| 		end;
 | |
| 
 | |
| 		IO_FLUSH:
 | |
| 			(* no effect on an input stream *)
 | |
| 			;
 | |
| 
 | |
| 		(* the following operations are prohibited on the code input stream:
 | |
| 		IO_READ:
 | |
| 		IO_WRITE:
 | |
| 		IO_WRITE_BYTES:
 | |
| 		*)
 | |
| 		else begin
 | |
| 			hak_seterrnum(handle, 999); (* TODO: change error code *)
 | |
| 			exit(-1);
 | |
| 		end;
 | |
| 	end;
 | |
| 
 | |
| 	exit(0);
 | |
| end;
 | |
| 
 | |
| procedure Interp.CompileFile(filename: System.PAnsiChar);
 | |
| var
 | |
| 	f: System.THandle = -1;
 | |
| 	attached: boolean = false;
 | |
| 	feed_ongoing: boolean = false;
 | |
| 	buf: array[0..1023] of System.AnsiChar;
 | |
| 	len: System.LongInt;
 | |
| 	excpt: SysUtils.Exception;
 | |
| label
 | |
| 	oops;
 | |
| begin
 | |
| 	f := SysUtils.FileOpen(filename, SysUtils.fmOpenRead);
 | |
| 	if f = System.THandle(-1) then begin
 | |
| 		excpt := Exception.Create('failed to open ' + filename + ' - ' +  SysUtils.SysErrorMessage(SysUtils.GetLastOSError()));
 | |
| 		goto oops;
 | |
| 	end;
 | |
| 
 | |
| 	self.basefile := filename;
 | |
| 	if hak_attachccio(self.handle, @cci_handler) <= -1 then begin
 | |
| 		excpt := self.FetchException('failed to attach ccio handler');
 | |
| 		goto oops;
 | |
| 	end;
 | |
| 	attached := true;
 | |
| 
 | |
| 	if hak_beginfeed(self.handle, nil) <= -1 then begin
 | |
| 		excpt := self.FetchException('failed to begin feeding');
 | |
| 		goto oops;
 | |
| 	end;
 | |
| 	feed_ongoing := true;
 | |
| 
 | |
| 	while true do begin
 | |
| 		len := SysUtils.FileRead(f, buf, System.SizeOf(buf));
 | |
| 		if len <= -1 then begin
 | |
| 			excpt := Exception.Create('failed to read ' + filename + ' - ' +  SysUtils.SysErrorMessage(SysUtils.GetLastOSError()));
 | |
| 			goto oops;
 | |
| 		end;
 | |
| 		if len = 0 then break;
 | |
| 
 | |
| 		if hak_feedbchars(self.handle, buf, len) <= -1 then begin
 | |
| 			excpt := self.FetchException('failed to feed text');
 | |
| 			goto oops;
 | |
| 		end;
 | |
| 	end;
 | |
| 
 | |
| 	if hak_endfeed(self.handle) <= -1 then begin
 | |
| 		excpt := self.FetchException('failed to end feeding');
 | |
| 		goto oops;
 | |
| 	end;
 | |
| 	feed_ongoing := false;
 | |
| 
 | |
| 	hak_detachccio(self.handle);
 | |
| 	self.basefile := '';
 | |
| 	SysUtils.FileClose(f);
 | |
| 	exit();
 | |
| 
 | |
| oops:
 | |
| 	if feed_ongoing then hak_endfeed(self.handle);
 | |
| 	if attached then hak_detachccio(self.handle);
 | |
| 	self.basefile := '';
 | |
| 	if f <> System.THandle(-1) then SysUtils.FileClose(f);
 | |
| 	raise excpt;
 | |
| end;
 | |
| 
 | |
| procedure Interp.CompileText(text: System.PAnsiChar);
 | |
| begin
 | |
| 	self.CompileText(text, SysUtils.Strlen(text));
 | |
| end;
 | |
| 
 | |
| procedure Interp.CompileText(text: System.PAnsiChar; len: System.SizeUint);
 | |
| var
 | |
| 	excpt: Exception;
 | |
| begin
 | |
| 	if hak_attachcciostdwithbcstr(self.handle, nil) <= -1 then begin
 | |
| 		excpt := self.FetchException('failed to attach ccio handler');
 | |
| 		raise excpt;
 | |
| 	end;
 | |
| 
 | |
| 	if hak_beginfeed(self.handle, nil) <= -1 then begin
 | |
| 		excpt := self.FetchException('failed to begin feeding');
 | |
| 		hak_detachccio(self.handle);
 | |
| 		raise excpt;
 | |
| 	end;
 | |
| 
 | |
| 	if hak_feedbchars(self.handle, text, len) <= -1 then begin
 | |
| 		excpt := self.FetchException('failed to feed text');
 | |
| 		hak_endfeed(self.handle);
 | |
| 		hak_detachccio(self.handle);
 | |
| 		raise excpt;
 | |
| 	end;
 | |
| 
 | |
| 	if hak_endfeed(self.handle) <= -1 then begin
 | |
| 		excpt := self.FetchException('failed to end feeding');
 | |
| 		hak_detachccio(self.handle);
 | |
| 		raise excpt;
 | |
| 	end;
 | |
| 
 | |
| 	hak_detachccio(self.handle);
 | |
| end;
 | |
| 
 | |
| {$if defined(HAK_WIDE_CHAR_SIZE_IS_4)}
 | |
| procedure Interp.CompileText(text: PWideChar);
 | |
| var
 | |
| 	x: UCS4String;
 | |
| begin
 | |
| 	x := WideStringToUcs4String(text);
 | |
| 	self.CompileText(PUchar(x));
 | |
| end;
 | |
| 
 | |
| procedure Interp.CompileText(text: PWideChar; len: System.SizeUint);
 | |
| var
 | |
| 
 | |
| 	x_text: PBchar;
 | |
| 	x_capa: System.SizeUint;
 | |
| 	x_len: System.SizeUint;
 | |
| begin
 | |
| 	x_capa := len * 4 + 1; (* allocation sizing for the worst case *)
 | |
| 	System.GetMem(x_text, x_capa);
 | |
| 	try
 | |
| 		x_len := System.UnicodeToUtf8(x_text, x_capa, text, len);
 | |
| 		self.CompileText(x_text, x_len);
 | |
| 	finally
 | |
| 		FreeMem(x_text);
 | |
| 	end;
 | |
| end;
 | |
| {$endif}
 | |
| 
 | |
| procedure Interp.CompileText(text: PUchar);
 | |
| begin
 | |
| 	(*self.CompileText(text, SysUtils.Strlen(text));*)
 | |
| 	self.CompileText(text, hak_count_ucstr(text));
 | |
| end;
 | |
| 
 | |
| procedure Interp.CompileText(text: PUchar; len: System.SizeUint);
 | |
| var
 | |
| 	excpt: Exception;
 | |
| begin
 | |
| 	if hak_attachcciostdwithbcstr(self.handle, nil) <= -1 then begin
 | |
| 		excpt := self.FetchException('failed to attach ccio handler');
 | |
| 		raise excpt;
 | |
| 	end;
 | |
| 
 | |
| 	if hak_beginfeed(self.handle, nil) <= -1 then begin
 | |
| 		excpt := self.FetchException('failed to begin feeding');
 | |
| 		hak_detachccio(self.handle);
 | |
| 		raise excpt;
 | |
| 	end;
 | |
| 
 | |
| 	if hak_feeduchars(self.handle, text, len) <= -1 then begin
 | |
| 		excpt := self.FetchException('failed to feed text');
 | |
| 		hak_endfeed(self.handle);
 | |
| 		hak_detachccio(self.handle);
 | |
| 		raise excpt;
 | |
| 	end;
 | |
| 
 | |
| 	if hak_endfeed(self.handle) <= -1 then begin
 | |
| 		excpt := self.FetchException('failed to end feeding');
 | |
| 		hak_detachccio(self.handle);
 | |
| 		raise excpt;
 | |
| 	end;
 | |
| 
 | |
| 	hak_detachccio(self.handle);
 | |
| end;
 | |
| 
 | |
| 
 | |
| procedure Interp.Execute();
 | |
| var
 | |
| 	excpt: Exception;
 | |
| begin
 | |
| 	if hak_attachudiostdwithbcstr(self.handle, nil, nil) <= -1 then begin
 | |
| 		excpt := self.FetchException('failed to attach udio handlers');
 | |
| 		raise excpt;
 | |
| 	end;
 | |
| 	if hak_execute(self.handle) = nil then begin
 | |
| 		excpt := self.FetchException(''); (* no header message used to make the error format the same as bin/hak *)
 | |
| 		hak_detachudio(self.handle);
 | |
| 		raise excpt;
 | |
| 	end;
 | |
| 
 | |
| 	hak_detachudio(self.handle);
 | |
| end;
 | |
| 
 | |
| end. (* unit *)
 |