runini
Now we try to automate the EXE files created using the ge2exe program, which is integrated into the compiler. This lesson describes the procedure mentioned above, making it easier for users to create the EXE files.
Example 1
. Let INI-file be a file, which contains the information about programs in the Gentee language. We have to help users choose a program from the given list, compile it and create the EXE file, if necessary.
We start with the description of the INI-file format. Each section denotes a program and consists of the following fields:
Name is the name of a program.
Src is the .g file of a program.
Exe - to create the EXE file or not (If the field contains a 1 or a 0).
Run - to run the program after successful compilation or not.
Output - If you want to change the last file name or store it in the other directory, you should enter the specified file name and its path here.
Note that the Src is a required field.
[ID2]
Name = Square
Src = ..\square\square.1.g
Exe = 0
The INI-file can be changed; it`s up to you. Moreover, you can add elements. Take a look at the runini.ini file used as an example in the samples\runini subdirectory.
The ini.g library is required to deal with the INI-file. So, let`s include the library by using the include command. To illustrate this, assume that these examples are located in the subdirectory samples, so we use the relative path. If you would like to carry this example to another directory, you should enter the absolute path.
include : $"..\..\lib\ini\ini.g"
The string with the initial dollar sign '$' does not contain any command characters, however it may contain macros. It is interesting to note that the use of such strings makes it easier to define the path to the files, because there is no need to double the '\' sign.
Let's write two auxiliary functions.
func uint openini( ini retini )
The openini function reads data from the runini.ini - file; but if the file is not available, the error message is displayed. If you want to get the error code, take a look at the source program.
func uint idaction( ini retini, str section )
This function is considered to be significant. It calls the program that can compile and create the exe-file. The first argument is the file object ini, the second one is the name of the section that should be launched.
The following statements read the field values.
retini.getvalue( section, "Src", src, "" )
if !*src
{
congetch("ID '\(section)' is not valid. Press any key...\n")
return 0
}
run = retini.getnum( section, "Run", 1 )
exe = retini.getnum( section, "Exe", 0 )
retini.getvalue( section, "Output", outname, "" )
Note that the last argument of the getvalue and the getnum functions defines the value, if this field isn't defined in the INI-file.
Using the options from the INI-file, the following code generates command lines in order to start up the compiler and ge2exe. The process function makes the programs start up. The "." directive, as the second argument of the process function, indicates that gentee.exe and ge2exe.exe will use the current directory as their working directory.
if exe
{
process( "..\\..\\exe\\gentee.exe -p samples \(src)", ".", &result )
src.fsetext( src, "ge" )
process( "..\\..\\exe\\ge2exe.exe \(src)", ".", &result )
deletefile( src )
src.fsetext( src, "exe" )
if run : process( src, ".", &result )
}
else : shell( src )
Let us jump into an example that illustrates the function body, which displays a list of possible programs and receives the program name chosen by a user:
ini tini
arrstr sections
str name src section
openini( tini )
tini.sections( sections )
while 1
{
print( "-----------\n" )
foreach cur, sections
{
tini.getvalue( cur, "Src", src, "" )
if !*src : continue
tini.getvalue( cur, "Name", name, src )
print( "\(cur)".fillspacer( 20 ) + name + "\n" )
}
print( "-----------\n" )
congetstr("Enter ID name (enter 0 to exit): ", section )
if section[0] == '0' : break
idaction( tini, section )
}
First, we read the INI-file and get the section list contained in a string array. After the program list is displayed in a window, a user should choose a program name. Then, we call the idaction function with the required program name.
Here, the following string is described in detail.
print( "\(cur)".fillspacer( 20 ) + name + "\n" )
The fillspacer method appends a specified number of space characters onto the end of the string. As you can see, we call the method on the string enclosed in double quote marks. Note, that in Gentee a string enclosed in double quote marks is the same object as a variable of type str. Furthermore, we can call methods on functions and other methods, which return strings.
For example, the expression given below appends ten space characters onto the end of the string, thus increasing the string's length to 30 characters.
"ID: \(cur)".fillspacer( 20 ).fillspacel( 30 )
Exercise 2
Write a program using runini.1.g, that gets a program-section name from a command line and runs it. If no command-line argument is specified, this program must work like the program discussed above.Tip: my program consists of 14 lines. For more details about this, read runini.2.g.