|
LCS-2016-006c |
|
1 {18-Jan-2017} 2 {11-Feb-2017} 3 {17-Feb-2017} 4 {21-Feb-2017} 5 {22-Feb-2017} 6 {xx-Feb-2017} 7 {24-Feb-2017} 8 {15-Mar-2017} |
|
15-Mar-2017 |
|
Voting |
|
Patrick Lehmann |
|
Main.PatrickLehmann |
|
File IO / TextIO updates |
|
TextIO additions. See LCS-2016-006a for file I/O additions. |
DIRECTORY.Childs
to DIRECTORY.Items
.
DIR_CREATE_STATUS
, changed STATUS_NO_DIRECTORY
to STATUS_ITEM_EXISTS
.
DIR_DELETE_STATUS
, added STATUS_NOT_EMPTY
.
out
parameter Dir
to match the LRM style.
impure function DIR_OPEN
as dependent on LCS 002.
FILE_OPEN
as requested.
type FT is file of TM;where type mark TM denotes a scalar type, a record type, or a fully constrained array subtype, the following operations are
procedure FILE_OPEN (file F: FT; External_Name: in STRING; Open_Kind: in FILE_OPEN_KIND := READ_MODE);
procedure FILE_OPEN (Status: out FILE_OPEN_STATUS; file F: FT; External_Name: in STRING; Open_Kind: in FILE_OPEN_KIND := READ_MODE);
procedure FILE_OPEN (file F: FT; External_Name: in STRING; Status: out FILE_OPEN_STATUS);
procedure FILE_OPEN (file F: FT; External_Name: in STRING; Open_Kind: in FILE_OPEN_KIND; Status: out FILE_OPEN_STATUS);
impure function FILE_OPEN (file F: FT; External_Name: in STRING; Open_Kind: in FILE_OPEN_KIND := READ_MODE) return FILE_OPEN_STATUS;
procedure FILE_CLOSE (file F: FT);
procedure READ (file F: FT; VALUE: out TM);
procedure WRITE (file F: FT; VALUE: in TM);
procedure FLUSH (file F: FT);
function ENDFILE (file F: FT) return BOOLEAN;
[...]
The first form of FILE_OPEN causes an error to occur if the second form of FILE_OPEN, when called under identical conditions, package TEXTIO is -- Type definitions for text I/O: type LINE is access STRING; -- A LINE is a pointer to a STRING value. -- The predefined operations for this type are as follows: -- function"=" (anonymous, anonymous: LINE) return BOOLEAN; -- function"/=" (anonymous, anonymous: LINE) return BOOLEAN; -- procedure DEALLOCATE (P: inout LINE); [Editor note: Move LINE_VECTOR to std.STANDARD if LINE moves their.] type LINE_VECTOR is array(NATURAL range <>) of LINE; -- The predefined operations for this type are as follows: -- function "="(anonymous, anonymous: LINE_VECTOR) return BOOLEAN; -- function "/="(anonymous, anonymous: LINE_VECTOR) return BOOLEAN; -- function "&"(anonymous: LINE_VECTOR; anonymous: LINE_VECTOR) return LINE_VECTOR; -- function "&"(anonymous: LINE_VECTOR; anonymous: LINE) return LINE_VECTOR; -- function "&"(anonymous: LINE; anonymous: LINE_VECTOR) return LINE_VECTOR; -- function "&"(anonymous: LINE; anonymous: LINE) return LINE_VECTOR; type TEXT is file of STRING; -- A file of variable-length ASCII records. -- The predefined operations for this type are as follows: -- procedure FILE_OPEN (file F: TEXT; External_Name; in STRING; Open_Kind: in FILE_OPEN_KIND := READ_MODE); -- procedure FILE_OPEN (Status: out FILE_OPEN_STATUS; file F: TEXT; External_Name: in STRING; Open_Kind: in FILE_OPEN_KIND := READ_MODE); -- procedure FILE_CLOSE (file F: TEXT); -- procedure READ (file F: TEXT; VALUE: out STRING); -- procedure WRITE (file F: TEXT; VALUE: in STRING); -- procedure FLUSH (file F: TEXT); -- function ENDFILE (file F: TEXT) return BOOLEAN; end package TEXTIO;
use work.textio.all; package ENV is procedure STOP (STATUS: INTEGER); procedure STOP; procedure FINISH (STATUS: INTEGER); procedure FINISH; function RESOLUTION_LIMIT return DELAY_LENGTH; [... LCS-2016-011 ...] type DIRECTORY_ITEMS is access LINE_VECTOR; -- The predefined operations for this type are as follows: -- function"=" (anonymous, anonymous: DIRECTORY_ITEMS) return BOOLEAN; -- function"/=" (anonymous, anonymous: DIRECTORY_ITEMS) return BOOLEAN; -- procedure DEALLOCATE (P: inout DIRECTORY_ITEMS); type DIRECTORY is record Name : LINE; -- current directory name; resolved to its canonical form Items : DIRECTORY_ITEMS; -- list of pointers to directory item names end record; -- The predefined operations for this type are as follows: -- function "="(anonymous, anonymous: DIRECTORY) return BOOLEAN; -- function "/="(anonymous, anonymous: DIRECTORY) return BOOLEAN; type DIR_OPEN_STATUS is ( STATUS_OK, STATUS_NOT_FOUND, STATUS_NO_DIRECTORY, STATUS_ACCESS_DENIED, STATUS_ERROR ); -- The predefined operations for this type are as follows: -- function "="(anonymous, anonymous: DIR_OPEN_STATUS) return BOOLEAN; -- function "/="(anonymous, anonymous: DIR_OPEN_STATUS) return BOOLEAN; -- function "<"(anonymous, anonymous: DIR_OPEN_STATUS) return BOOLEAN; -- function "<="(anonymous, anonymous: DIR_OPEN_STATUS) return BOOLEAN; -- function ">"(anonymous, anonymous: DIR_OPEN_STATUS) return BOOLEAN; -- function ">="(anonymous, anonymous: DIR_OPEN_STATUS) return BOOLEAN; -- function MINIMUM (L, R: DIR_OPEN_STATUS) return DIR_OPEN_STATUS; -- function MAXIMUM (L, R: DIR_OPEN_STATUS) return DIR_OPEN_STATUS; type DIR_CREATE_STATUS is ( STATUS_OK, STATUS_ITEM_EXISTS, STATUS_ACCESS_DENIED, STATUS_ERROR ); -- The predefined operations for this type are as follows: -- function "="(anonymous, anonymous: DIR_CREATE_STATUS) return BOOLEAN; -- function "/="(anonymous, anonymous: DIR_CREATE_STATUS) return BOOLEAN; -- function "<"(anonymous, anonymous: DIR_CREATE_STATUS) return BOOLEAN; -- function "<="(anonymous, anonymous: DIR_CREATE_STATUS) return BOOLEAN; -- function ">"(anonymous, anonymous: DIR_CREATE_STATUS) return BOOLEAN; -- function ">="(anonymous, anonymous: DIR_CREATE_STATUS) return BOOLEAN; -- function MINIMUM (L, R: DIR_CREATE_STATUS) return DIR_CREATE_STATUS; -- function MAXIMUM (L, R: DIR_CREATE_STATUS) return DIR_CREATE_STATUS; type DIR_DELETE_STATUS is ( STATUS_OK, STATUS_NO_DIRECTORY, STATUS_NOT_EMPTY, STATUS_ACCESS_DENIED, STATUS_ERROR ); -- The predefined operations for this type are as follows: -- function "="(anonymous, anonymous: DIR_DELETE_STATUS) return BOOLEAN; -- function "/="(anonymous, anonymous: DIR_DELETE_STATUS) return BOOLEAN; -- function "<"(anonymous, anonymous: DIR_DELETE_STATUS) return BOOLEAN; -- function "<="(anonymous, anonymous: DIR_DELETE_STATUS) return BOOLEAN; -- function ">"(anonymous, anonymous: DIR_DELETE_STATUS) return BOOLEAN; -- function ">="(anonymous, anonymous: DIR_DELETE_STATUS) return BOOLEAN; -- function MINIMUM (L, R: DIR_DELETE_STATUS) return DIR_DELETE_STATUS; -- function MAXIMUM (L, R: DIR_DELETE_STATUS) return DIR_DELETE_STATUS; type FILE_DELETE_STATUS is ( STATUS_OK, STATUS_NO_FILE, STATUS_ACCESS_DENIED, STATUS_ERROR ); -- The predefined operations for this type are as follows: -- function "="(anonymous, anonymous: FILE_DELETE_STATUS) return BOOLEAN; -- function "/="(anonymous, anonymous: FILE_DELETE_STATUS) return BOOLEAN; -- function "<"(anonymous, anonymous: FILE_DELETE_STATUS) return BOOLEAN; -- function "<="(anonymous, anonymous: FILE_DELETE_STATUS) return BOOLEAN; -- function ">"(anonymous, anonymous: FILE_DELETE_STATUS) return BOOLEAN; -- function ">="(anonymous, anonymous: FILE_DELETE_STATUS) return BOOLEAN; -- function MINIMUM (L, R: FILE_DELETE_STATUS) return FILE_DELETE_STATUS; -- function MAXIMUM (L, R: FILE_DELETE_STATUS) return FILE_DELETE_STATUS; procedure DIR_OPEN(Dir : out DIRECTORY; Path : in STRING; Status : out DIR_OPEN_STATUS); impure function DIR_OPEN(Dir : out DIRECTORY; Path : in STRING;) return DIR_OPEN_STATUS; [Requires out parameters in impure functions: LCS 002 ??] procedure DIR_CLOSE(Dir : in DIRECTORY); -- used to deallocate internal values impure function DIR_ITEMEXISTS(Path : in STRING) return BOOLEAN; impure function DIR_ITEMISDIR(Path : in STRING) return BOOLEAN; impure function DIR_ITEMISFILE(Path : in STRING) return BOOLEAN; procedure DIR_WORKINGDIR(Path : in STRING; Status : out DIR_OPEN_STATUS); impure function DIR_WORKINGDIR(Path : in STRING) return DIR_OPEN_STATUS; impure function DIR_WORKINGDIR return STRING; procedure DIR_CREATEDIR(Path : in STRING; Status : out DIR_CREATE_STATUS); procedure DIR_CREATEDIR(Path : in STRING; Parents : in BOOLEAN; Status : out DIR_CREATE_STATUS); impure function DIR_CREATEDIR(Path : in STRING; Parents : in BOOLEAN := FALSE) return DIR_CREATE_STATUS; procedure DIR_DELETEDIR(Path : in STRING; Status : out DIR_DELETE_STATUS); procedure DIR_DELETEDIR(Path : in STRING; Recursive : in BOOLEAN; Status : out DIR_DELETE_STATUS); impure function DIR_DELETEDIR(Path : in STRING; Recursive : in BOOLEAN := FALSE) return DIR_DELETE_STATUS; procedure DIR_DELETEFILE(Path : in STRING; Status : out FILE_DELETE_STATUS); impure function DIR_DELETEFILE(Path : in STRING) return FILE_DELETE_STATUS; constant DIR_SEPARATOR : STRING; end package ENV;[Editor note: Three notes ...]
vhpi_control
function called with the argument vhpiStop
(see 23.5). Execution of the FINISH procedures causes the same action by the host simulator as that caused by the vhpi_control
function vhpiFinish
(see 23.5). Execution shall not return to the VHDL description after a call to the FINISH procedure. For the vhpi_control
function with no additional arguments beyond the vhpiStop
vhpiFinish
argument.
The function RESOLUTION_LIMIT returns the value of the resolution limit (see 5.2.4.2).
DIRECTOTY_CHILDS
-- Hendrik Eeckhaut - 2017-01-23
Title is incorrect : "Language Change Specification for Hierarchical Libraries"
-- Hendrik Eeckhaut - 2017-01-23
Fixed typo and title. No version increment due to minor changes.
-- Patrick Lehmann - 2017-01-23
Would suggest changing "CHILD" to "ITEM" throughout.
-- Kevin Jennings - 2017-02-09
record
Directory needs to contain an explicit ItemCount. Wouldn't this be equivalent to Items.all'length
?
Also doing away with repeating the name of the queried directory would eliminate the need for the DIRECTORY record
altogether. Without this record
, even an API using a comprehensive list of entries can be based on returning a line_vector
instead of inventing this other access
type
DirectoryItems.
-- Thomas Preusser - 2017-02-14
At first VHDL shall not provide a high level API for directories and files. This can be solved in an open source package.
At second, not all the world is build of old POSIX. There are other implementations available giving an abstract view to a
directory. The directory name itself is included in my DIRECTORY structure because VHDL offers no way to get a handle to a
parent directory. If can now be extracted by searching for the last delimiter sign. Not all directory APIs are iterator based.
Most implementations of iterators on top of static information.
That brings me to third: POSIX internally works on a block structure which is returned by opendir
! readdir
is an iterator on top of that basic data structure. DIRECTORY.Name
does not repeat the Path
argument passed to DIR_OPEN
. If Path
is a relative path, the returned Name
value returns a resolved value.
ItemCount
is now removed.
-- Patrick Lehmann - 2017-02-17
1) There is small inconsistency. 16.5.1 defines procedures for DIR_CREATEDIR(...), DIR_DELETEDIR(...), and DIR_DELETEFILE(...) whereas 16.5.4 talks about functions with this name.
2) What is the rationale for having procedures instead of impure functions for DIR_WORKINGDIR(Path), DIR_CREATEDIR(...), DIR_DELETEDIR(...) and DIR_DELETEFILE(...)? All these
subprograms have only one output parameter which can be a return value instead. This would also simplify the usage of these subprograms, e.g.
if DIR_CREATEDIR("test") /= STATUS_OK then report "Could not create directory." severity error; end if;instead of
variable status : DIR_CREATE_STATUS; ... DIR_CREATEDIR("test", status); if status /= STATUS_OK then report "Could not create directory." severity error; end if;-- Martin Zabel - 2017-02-17 Please, consider specifying
DIRECTORY.Name
as canonical path of the directory LINE
but instead talks about access types referencing STRING
objects?
The statement If the parameter Recursive is set to TRUE, all subdirectories and files are deleted, even if the directory is not empty. is not sufficient. It should
probably be stated that DIR_DELETEDIR
will not delete a directory that is not empty unless the parameter Recursive is asserted, in which case all existing subitems will be
deleted as well.
PS: Fixed some grammar.
-- Thomas Preusser - 2017-02-19
MZ: 1) DIRECTORY.Name
as canonical path of the directory LINE
... function PATH_CANONIZE(Path : STRING; Base : STRING :!
".") returns LINE= to canonize arbitrary paths, optionally relative to a specified base
directory. This would also allow to drop the implied canonization of DIR_OPEN
and help other file-related LCSs.
-- Thomas Preusser - 2017-02-21
TBP: I think a mutable global working directory is problematic as it jeopardizes the isolation of modules. DIR_WORKINGDIR
only affects the file and directory API (FILE_*
/ DIR_*
), nothing else.
TBP: I suggest to introduce a function PATH_CANONIZE(...) returns LINE
[...]PATH_CANONIZE
subprogram would require knowledge about symbolic links, mount points and junction points in the file system.
-- Patrick Lehmann - 2017-02-22
AlertIfNot(DIR_OPEN(...) = STATUS_OK or DIR_OPEN(...) = STATUS_OK or DIR_OPEN(...) = STATUS_OK, "Directory did not open", FAILURE) ;Is this really what you what? Keep in mind that each one can potentially update MyDir. -- Jim Lewis - 2017-02-24 To_string is also implicitly defined for all scalar values. -- Jim Lewis - 2017-02-24 Why status should be first: WRT:
procedure DIR_CREATEDIR(Path : in STRING; Status : out DIR_CREATE_STATUS; Parents : in BOOLEAN := FALSE);My preference is:
procedure DIR_CREATEDIR(Status : out DIR_CREATE_STATUS; Path : in STRING; Parents : in BOOLEAN := FALSE);This follows the pattern of, acknowledging that out designates a target of an operation. Also acknowledging that when the line parameter is second the value is an input and when it is first it appends to the target:
procedure WRITE (file F: TEXT; VALUE: in STRING); procedure FILE_OPEN (Status: out FILE_OPEN_STATUS; file F: TEXT;External_Name: in STRING;Open_Kind: in FILE_OPEN_KIND := READ_MODE); procedure READLINE (file F: TEXT; L: inout LINE); procedure WRITE (L: inout LINE; VALUE: in BIT;JUSTIFIED: in SIDE:= RIGHT; FIELD: in WIDTH := 0);That leaves all versions of READ as the odd duck in the situation. What I see is that the READ was made consistent with WRITE, which also makes sense:
procedure READ (file F: TEXT; VALUE: out STRING); procedure READ (L: inout LINE; VALUE: out BIT); procedure READ (L: inout LINE; VALUE: out BIT_VECTOR;GOOD: out BOOLEAN);OTOH, in a private conversation, you indicated that status could not be last, like read, due to the optional parameter. I disagree. One simply has to work harder on the authoring side, but it can be done, and I consider consistency of the use model most important:
procedure DIR_CREATEDIR(Path : in STRING; Parents : in BOOLEAN; Status : out DIR_CREATE_STATUS ); procedure DIR_CREATEDIR(Path : in STRING; Status : out DIR_CREATE_STATUS );Back to functions, I don't feel great about them have generalized outputs, but I do like the use model of DIR_OPEN that I gave previously. -- Jim Lewis - 2017-02-27 All the procedures and functions follow these rules:
Status
is the last parameter
Status
being the first parameter. Moreover I consider FILE_OPEN(Status ...)
a design fault. And I don't
want to redo a design fault just for consistency. If we look for other subprograms in VHDL, we'll see that status information is
provided as the last parameter if no optional parameters are present.
-- Patrick Lehmann - 2017-02-28
Implemented optional parameters as procedure overloads to fulfill Jim's demands for coding style.
-- Patrick Lehmann - 2017-03-02
READ
subprograms, we see that the Good
parameter is listed at the end of each subprogram,
if present. This strengths my point of view. In addition, 6 reviewers of this LCS have no problem with my proposed interface.
There is no issue with the FILE_OPEN
procedure except for that it does not apply to common rules how to order parameters in an interface
as described in various books. Of cause these rules are not graved in stone, but I don't like to redo a design fault from VHDL-1993. I also
like consistency, that's why I propose this interface. But, consistency is no excuse to redo design faults!
If you like, I can propose similar overloads for the existing file API. But this would require another LCS ...
-- Patrick Lehmann - 2017-03-06