IBM
Contents Index Previous Next



Abstract Data Type for File Manipulations and I/O


The ADT TextFile

In this section an SDL abstract data type, TextFile, is discussed where file manipulations and I/O operations are implemented as operations on the abstract data type. This ADT can be used also in OS integrations and in Cmicro if the target system has support for files in C.

This data type, which you may include in any SDL system, makes it possible to access, at the SDL level, a subset of the file and I/O operations provided by C.

The implementation of the operators are harmonized with the I/O in the monitor, including the Simulator Graphical User interface. All terminal I/O, for example, will be logged on the interaction log file if the monitor command Log-On is given.

The data type defines a "file" type and contains three groups of operations:

  1. Operations to open and close files
  2. Operations to write information onto a file
  3. Operations to read information from a file.

The operations may handle I/O operations both on files and on the terminal (file stdin and stdout in C).

Note:

This data type is not intended to be used in the SDL Explorer!

Purpose

The TextFile data type supplies basic file and I/O operations as abstract data type operations in SDL, whereby I/O may be performed within the SDL language. The operations may handle I/O both on the terminal and on files and are harmonized with the I/O from the monitor, from the trace functions, and from the functions handling dynamic errors.

To make the data type available you include the file containing the definition with an analyzer include in an appropriate text symbol:

Example 534 : Including an ADT File

/*#include 'file.pr' */

Remember that all file systems are operating system specific. Any rules in your file system apply.

Summary of Operators

The following literals are available in the data type FileName:

SYNTYPE FileName = Charstring 
ENDSYNTYPE;

SYNONYM NULL    FileName = `NULL';
SYNONYM stdin   FileName = `stdin';
SYNONYM stdout  FileName = `stdout';
SYNONYM stderr  FileName = `stderr';

The following literals and operators are available in the data type TextFile:

NEWTYPE TextFile
  LITERALS 
    NULL, stdin, stdout, stderr;

  OPERATORS
    GetAndOpenR   : FileName -> TextFile;
    GetAndOpenW   : FileName -> TextFile;
    OpenR         : FileName -> TextFile; 
    OpenW         : FileName -> TextFile; 
    OpenA         : FileName -> TextFile;
    Close         : TextFile -> TextFile;
    Flush         : TextFile -> TextFile; 
    IsOpened      : TextFile -> Boolean; 
    AtEOF         : TextFile -> Boolean; 
    AtLastChar    : TextFile -> Boolean;

    PutReal       : TextFile, Real -> TextFile; 
    PutTime       : TextFile, Time -> TextFile; 
    PutDuration   : TextFile, Duration -> TextFile; 
    PutPId        : TextFile, PId -> TextFile; 
    PutInteger    : TextFile, Integer -> TextFile;
    PutBoolean    : TextFile, Boolean -> TextFile;
    PutCharacter  : TextFile, Character -> TextFile;
    PutCharstring : TextFile, Charstring -> TextFile;
    PutString     : TextFile, Charstring -> TextFile;
    PutLine       : TextFile, Charstring -> TextFile;
    PutNewLine    : TextFile -> TextFile;
    "//"          : TextFile, Real -> TextFile;
    "//"          : TextFile, Time -> TextFile;
    "//"          : TextFile, Duration -> TextFile;
    "//"          : TextFile, Integer -> TextFile;
    "//"          : TextFile, Charstring -> TextFile;
    "//"          : TextFile, Boolean -> TextFile;
    "//"          : TextFile, PId -> TextFile;
    "+"           : TextFile, Character -> TextFile;

    GetReal       : TextFile, Charstring -> Real; 
    GetTime       : TextFile, Charstring -> Time; 
    GetDuration   : TextFile, Charstring -> Duration; 
    GetPId        : TextFile, Charstring -> PId; 
    GetInteger    : TextFile, Charstring -> Integer;
    GetBoolean    : TextFile, Charstring -> Boolean;
    GetCharacter  : TextFile, Charstring -> Character;
    GetCharstring : TextFile, Charstring -> Charstring;
    GetString     : TextFile, Charstring -> Charstring;
    GetLine       : TextFile, Charstring -> Charstring;
    GetSeed       : TextFile, Charstring -> Integer;
 
    GetReal       : TextFile -> Real; 
    GetTime       : TextFile -> Time; 
    GetDuration   : TextFile -> Duration; 
    GetPId        : TextFile -> PId; 
    GetInteger    : TextFile -> Integer; 
    GetBoolean    : TextFile -> Boolean; 
    GetCharacter  : TextFile -> Character; 
    GetCharstring : TextFile -> Charstring;
    GetString     : TextFile -> Charstring; 
    GetLine       : TextFile -> Charstring;
    GetSeed       : TextFile -> Integer;
ENDNEWTYPE TextFile;

The operators may be divided into three groups with different purpose:

  1. Operators that, together with the literals, are used for handling files.
  2. Operators suited for writing information to files.
  3. Operators intended for reading information from files.

The next three subsections provide the necessary information for using these operators. The data type itself will be discussed together with the operators for handling files.

File Handling Operators

First in this subsection each operator and literal will be discussed in detail and then some typical applications of the operators will be presented.

Caution!

The operators GetAndOpenR and GetAndOpenW do not work with the Application library. The operators GetPId and PutPId (and the // operator to write PIds) can be used with the Application library, but they will use a different output format.

Operator Behavior

The type TextFile is implemented using the ordinary C file type FILE. A TextFile is a pointer to a FILE.

typedef FILE * TextFile;

The literal NULL represents a null value for files. This literal is translated to TextFileNull() in the generated C code by an appropriate #NAME directive and is then implemented using the macro:

#define TextFileNull() (TextFile)0

All variables of the type TextFile will have this value as default value.

The literals stdin and stdout represent the standard files stdin and stdout in C, which are the files used in C for I/O to the terminal. The file stdin is used for reading information from the keyboard, while stdout is used for writing information on the screen.

The standard operators assignment and test for equality is implemented in such a way that A:=B means that now A refers to the same file as B, while A=B tests if A and B refer to the same file.

FileName

The data type FileName is used to represent file names in the operators GetAndOpenR, GetAndOpenW, OpenR, OpenW, and OpenA. It has all Charstring literals and the special synonyms NULL, stdin (input from the keyboard), stdout (output to the screen), and stderr (output to the screen from which the SDL Suite was started). As FileName is a syntype of Charstring, the usual Charstring operators are defined for this type.

Caution!

The synonyms stdin, stdout, stderr in some circumstances hide the literals with the same names according to SDL scope rules. If that is the case, please insert a qualifier <<type textfile>> before the literal name.

GetAndOpenR - GetAndOpenW

The operators GetAndOpenR and GetAndOpenW are used to open a file with a name prompted for on the terminal. GetAndOpenR opens the file for read, while GetAndOpenW opens the file for write. The operators take the prompt as parameter (type charstring), print the prompt on the screen (on stdout), and read a file name from the keyboard (from stdin). An attempt is then made to open a file with that name. If the open operation was successful, a reference to the file is returned by the GetAndOpenR or GetAndOpenW operator, otherwise NULL is returned. After a successful open operation you may use the file for reading or writing.

If you type <Return>, - or the file name stdin at the prompt in GetAndOpenR a reference to stdin is returned by the operator. GetAndOpenW will, in the same way, return a reference to stdout if the prompt is answered by <Return>, - or the file name stdout.

Note:

To work properly in the Simulator Graphical User Interface, the prompt string should be terminated with: ": ", i.e. colon space.

OpenR - OpenW - OpenA

The operators OpenR, OpenW, and OpenA are used to open a file with a file name passed as parameter. OpenR opens the file for read, while OpenW opens the file for write and OpenA opens the file for append. An attempt is made to open a file with the name given as a parameter. If the open operation was successful, a reference to the file is returned by the OpenR, OpenW, or OpenA operator, otherwise NULL is returned. After a successful open operation you may read, write or append on the file.

Close

The operator Close is used to close the file passed as parameter. Close always returns the value NULL. This operator should be used on each file opened for write after all information is written to the file to ensure that any possibly buffered data is flushed.

Note:

Always close a file variable before assigning it to a new file, otherwise data may be lost.

Flush

Output to files is usually buffered, and is therefore not immediately written on the physical output device. The operator Flush forces the output buffer of the file that is passed as parameter to be written on the physical output device. It is equivalent to C function fflush.

IsOpened

The operator IsOpened may be used to determine if a TextFile is open or not. It may, for example, be used to test the result of the Open operation discussed above. The test IsOpened(F) is equivalent to
F /= NULL.

AtEOF

The operator AtEof may be used to determine if a TextFile has reached the end of file or not. This operator could be used in order to determine when to stop reading input from a file. The test AtEof(F) is equivalent to feof(F).

Note:

AtEof first becomes true when attempts are made to read behind the
end-of-file. Operator AtLastChar becomes true when the last character of the file has been read, and is usually more useful than AtEof.

AtLastChar

The operator AtLastChar may be used to determine if a TextFile has reached the end of file or not. This operator is useful in order to determine when to stop reading input from a file. The test AtLastChar(F) returns true if there are no more characters to be read from the file.

Examples of Use

Three typical situations when you want to write information are easily identified:

  1. The information is to be printed on the screen.
  2. The information is to be printed on a file with a given name.
  3. You want to determine at run-time where the information is to be printed.

Example 535 : ADT for File I/O, Print to Screen

If the information is to be printed on the screen, you may use the following structure:

DCL F TextFile;
TASK F := stdout // 'example';

Declare a variable of type TextFile and assign it the value stdout. You may then use it in the write operators discussed under Write Operators.

Example 536 : ADT for File I/O, Print to File

If the information is to be printed on a file with a given name, you may use the following structure:

DCL F TextFile;
TASK F := OpenW('filename');
TASK F := F // 'example';

The difference from the above is that the operator OpenW is used to open a file with the specified name. This outline may be complemented with a test if the OpenW operation was successful or not.

Example 537 : ADT for File I/O, Accessing Text File

If you want to be able to determine at run-time where the information should be printed, you should define a TextFile as in the examples above, and then use the following structure.

Figure 562 : Accessing a TextFile

If you answer the question by hitting <Return> or by typing stdout, the information will be printed on screen (stdout). If you type the name of a file, the information will be printed on that file.

If you want to open the file for read instead of write, you may use almost identical structures.

Write Operators

Operator Behavior

The write operators PutReal, PutTime, PutDuration, PutInteger, PutBoolean, PutCharacter, and PutCharstring all take a TextFile and a value of the appropriate type as parameters. The operators print the value passed as parameter on the file referenced by the TextFile parameter and then return the TextFile. The Put* operators will print the values in the same format as the monitor uses for the command Examine-Variable, and will append a space after each printed value.

The operator PutString takes a TextFile and a Charstring parameter and prints the string on the TextFile. PutString prints the string as a C string, not using the format for SDL Charstring. This means that no ' is printed. PutString returns the TextFile given as parameter as result.

The infix write operator "//" takes as parameters a TextFile and a value of type Boolean, Charstring, Integer, PId, Real, Time, or Duration. TextF // Val prints the value `Val' to the TextFile referenced by `TextF', and returns value `TextF'. Character strings are printed without enclosing `''. All // operators except the one for Charstring append a space to the file, after the value is written.

The infix write operator "+" takes as parameters a TextFile and a Character. "+" behaves just as "//", but it has its special name in order to avoid type conflicts with Charstring.

The operator PutNewLine takes a TextFile as parameter, prints a carriage return (actually a "\n") on this file, and returns the TextFile as operator result.

The different Put operators are equivalent to the // operators, and they are mainly present for backward compatibility reasons.

There is a function named xPutValue in the implementation of the data type TextFile. This function may print a value of any type that may be handled by the monitor system, but may only be accessed from in-line C code and not from SDL. A detailed description of the xPutValue function may be found under Accessing the Operators from C.

Example 538 : ADT for File I/O, Print to File

To print a line according to the following example, where 137 is the value of the variable NoOfJobs:

Number of jobs: 137 Current time: 137.0000

You could use the following statements, assuming that the TextFile F is already opened:

TASK 
  F := F // `Number of jobs: ` // NoOfJobs;
TASK 
  F := F // `current time: ` // Now;
TASK
  F := PutNewLine(F);

Read Operators

Operator Behavior

The read operators GetReal, GetTime, GetDuration, GetInteger, GetBoolean, GetCharacter, GetCharstring, and GetSeed are used to read values of the various sorts.

The operator GetSeed is used to read appropriate values to initialize random number generators (odd integers in the range 1 to 32767).

There are two versions of each Get operator: one that only takes as parameters a TextFile, and the other that takes as parameters a TextFile and a Charstring which is used as prompt. All Get operators behave differently depending on if the value should be read from the terminal (stdin) or from a file.

If the value should be read from the terminal, the Get operators with the prompt parameter may be used. This prompt is printed on the screen, and then an attempt to read a value of the current type is made. If a Get operator with only the TextFile parameter is used, a default prompt is used, that depends on the type that is to be input. If the operation is successful, the read value is returned as a result, otherwise the message "Illegal value" is printed and the user is given a new chance to type a value.

Note:

To work properly in the Simulator Graphical User Interface, the prompt string should be terminated with: ": ", i.e. colon space.

If the value should be read from a file, it is recommended to use the Get operators without the prompt parameter, as it is not used. It is assumed that a value of the correct type will be found.

There are several Get operators for reading character strings:

GetString reads a sequence of characters until the first white space character, and is equivalent to fscanf (f, "%s").

GetLine reads a sequence of characters until the end of line is reached. It is equivalent to fgets, but the end-of-line character will not be part of the string.

GetCharstring reads a sequence of characters on a single line that is enclosed by single quotes (`). This operator is mainly present for backward compatibility reasons.

There is a function named xGetValue in the implementation of the data type TextFile, which may read a value of any type that may be handled by the monitor system. This function can only be accessed from in-line C code and not from SDL. A detailed description of the xGetValue function may be found under Accessing the Operators from C.

Example 539 : ADT for File I/O, Read from File

TASK
  Mean := GetReal (F),
  A(1) := GetReal (F),
  A(2) := GetReal (F),
  A(3) := GetReal (F);

Accessing the Operators from C

In some circumstances it may be easier to use C code (in #CODE directives) rather than SDL to implement an algorithm. SDL implementations for linear algorithms sometimes become unnecessarily large and complex, as SDL for example lacks a loop concept. Consider the SDL graph in Figure 562. This graph could be replaced by a TASK with the following contents:

'Open file F' /*#CODE
#(F) = GetAndOpenW("LFile : ");
while ( ! IsOpened(#(F)) )
  #(F) = GetAndOpenW("LIllegal name. File : "); */

which is more compact and gives a better overview at the SDL level.

#(F) is an SDL directive telling the SDL to C compiler to translate the SDL variable F to the name it will receive in the generated C code.

To simplify the use of in-line C code, #NAME directives are introduced on all identifiers defined in this data type. The same names are used in C as in SDL.

Note:

Upper and lower case letters are significant in C (but not in SDL).

Note also the additional L in the Charstring literals, for example "LIllegal name. File : ". This first character is used in the implementation of the SDL sort Charstring and should always be L in a charstring literal.

From in-line C, two functions xGetValue and xPutValue are also available to read and write values of any type. These functions have the following prototypes:

extern void xGetValue(
  TextFile       F,
  SDL_Charstring Prompt, 
  xSortIdNode    SortId,
  void         * Result,
  char         * FunctionName );

extern void xPutValue(
  TextFile    F,
  xSortIdNode SortId,
  void      * Value,
  char      * FunctionName ); 

Parameter Interpretation
TextFile F

The file to read from or to print to.

In xGetValue:
SDL_Charstring Prompt

Is used as prompt in exactly the same way as for the ordinary Get operators.

xSortIdNode SortId 

A reference to the xIdNode that represents the SDL sort to be read or printed

For the predefined SDL sorts you may use variables named xSrtN_SDL_Real, xSrtN_SDL_Integer, and so on, as parameter.

For user-defined sorts, you may use similar variables named ySrtN_#(SortName), where SortName should be replaced by the sort name.

void * Result
void * Value

The address to the variable where the result should be stored, or the address to the variable that should be printed.

char * FunctionName

A string specifying the name of an appropriate function. This name will be given if an error is detected during reading or printing.

Note:

xGetValue and xPutValue will not work together with the Application library.

To handle, for example, I/O of an SDL struct, the ideas presented below may be used.

Example 540 : ADT for File I/O of an SDL Struct

NEWTYPE SName STRUCT
  a, b Integer;
ENDNEWTYPE;

DCL
  FIn, FOut TextFile,
  SVar SName;

TASK 'Put SVar on FOut' /*#CODE
  xPutValue( #(FOut), ySrtN_#(SName),
  &(#(SVar)), "PutSName" ); */;

TASK 'Get SVar from FIn' /*#CODE
  xGetValue( #(FIn), "Value : ",
  ySrtN_#(SName),&(#(SVar)), "LGetSName"); */;


http://www.ibm.com/rational
Contents Index Previous Next