next up previous contents index
Next: Destruction of structures Up: Objects and structures Previous: Structures   Contents   Index


How to create and access structures

Structure types are created in the initialization file (cf. 3.6). This allows structures to be created when the interpreter is running.

The structure types that are available when the interpreter is running are contained in the array

struc_typ *Struc_typ;

If the section !struct of the initialization file contains for example the following :

!struct
; Structures of the first type (comment line)
defstruc1
3
member_1
defobj1
member_2
defobj2
member_3
X
Structures 1 : 
-1
nb1
; Structures of the second type (comment line)
defstruc2
3
member_1b
defobj1
member_2b
defobj2
member_3b
defstruc1
Structures 1 : 
0
nb2
.

2 structure types will be created, Struc_typ[0] and Struc_typ[1]. If the object types defobj1, defobj2 have been created previously, but no object or structure type called X, the structures defstruc1 have 3 members : an object of type defobj1, an object of type defobj2 and a variable of the expression evaluator. The structures defstruc2 have 3 members : an object of type defobj1, an object of type defobj2 and a structure of type defstruc1.


The structures are contained in the array

strucb **Struc;

Struc[i][j] will contain the j-th structure of type i. The type 0 corresponds to the first type of structures created in the initialization file, the type 1 to the second type of structures created in the initialization file, and so on.

When the interpreter is running, structures are created using the corresponding command. For instance, in the preceeding example, the command

- interpcom -> defstruc1 xxx

will create a structure of the first type, whose name is xxx. It is also possible to create arrays of structures. For example, the command

- interpcom -> defstruc1 zz[3]

will create the structures zz[1],zz[2] and zz[3]. Note that it is now possible to use the name zz for another structure or object. The command assign can be used to fix the members of the structure. The command desassign can be used to free them. With the command desc it is possible to have the description of a structure.


Example :

- interpcom -> defstruc1 xxx
- interpcom -> desc xxx
 member_1 (object defobj1) : (null)
 member_2 (object defobj2) : (null)
 member_3 (variable xxx_member_3) : 0
- interpcom -> defobj1 xxx1
- interpcom -> defobj2 xxx2
- interpcom -> assign xxx member_1 xxx1
- interpcom -> assign xxx member_2 xxx2
- interpcom -> desc xxx
 member_1 (object defobj1) : xxx1
 member_2 (object defobj2) : xxx2
 member_3 (variable xxx_member_3) : 0
- interpcom -> desassign xxx member_1
- interpcom -> assign xxx member_3 2.5
- interpcom -> desc xxx
 member_1 (object defobj1) : (null)
 member_2 (object defobj2) : xxx2
 member_3 (variable xxx_member_3) : 2.5


In this example the third member of the structure xxx is a hidden variable of the expression evaluator (cf. 7), called xxx_member_3 (so its name is the name of the structure, followed by a _ and by the name of the member). The command assign is also used here to fix the value of the member. Its value will be the last argument of the command assign. If a member of a structure which is a variable of the expression evaluator is not assigned any value, the corresponding variable remains undefined. In the previous example the function

int struc_create(int argc, char *argv[]);

is the one that is called to create structures. This is the function that implements the command strucdef. In the above example, defstruc1 is in fact the following program

:defstruc1
3
0
0
strucdef 0 #1

The 0 after objdef means that the command defstruc1 will create structures of type 0 (which is the first type of structures defined in the initialization file). When the initialization file is read, a program of this type is created for each structure type. So the command

- interpcom -> defstruc1 xxx

is equivalent to this one :

- interpcom -> strucdef 0 xxx

but the first one is more explicit.

Suppose we want to define the members of a structure together with the structure itself. For instance, we want a command called Def_Struc1 such that

- interpcom -> Def_Struc1 xxx

would create the structure xxx, the objects xxx.memb1, xxx.memb2, of type defobj1, defobj2 respectively, and assign these objects to the members of xxx. The function that implements this comment could be :

int 
Def_struc1_cmd(int argc, char *argv[])
{ 
    char   *k[5], h[100]; 
    flow_data  *flow_interp;

    flow_interp = (flow_data *) argv[-1];
    /* we create the structure */ 
    k[0] = (char *) flow_interp;
    k[1] = ch_copy("strucdef"); 
    k[2] = ch_copy("0"); 
    k[3] = argv[1]; 
    if (struc_create(3, k + 1)== -1) {   /* creation of the structure */ 
        error_mess(5, flow_interp); 
        return 1; 
    }

    free(k[0]); 
/*--------------------------------------*/ 

    /* we create the members of the structure */ 
    memset(h, 0, 100); 
    sprintf(h, "%s.memb1", argv[1]); 
    k[1] = ch_copy("objdef"); 
    k[3] = h; 
    if (obj_create(3, k + 1) == -1) {   /* creation of member 1 */ 
        error_mess(5, flow_interp); 
        return 1; 
    }
    memset(h, 0, 100); 
    sprintf(h, "%s.memb2", argv[1]); 
    k[2][0]= '1'; 
    k[3] = h; 
    if (obj_create(3, k + 1) == -1) {   /* creation of member 2 */ 
        error_mess(5, flow_interp); 
        return 1; 
    }
/*--------------------------------------*/ 

/* we assign the objects to the members of the structure */ 
    free(k[1]); 
    k[1] = ch_copy("assign"); 
    free(k[2]); 
    k[2] = argv[1]; 
    k[3] = ch_copy("member_1"); 
    sprintf(h, "%s.memb1", argv[1]); 
    k[4] = h; 
    assign_membre(4, k + 1); 
    k[3][7] = '2'; 
    assign_membre(4, k + 1); 
    free(k[1]);
    free(k[3]); 
/*--------------------------------------*/ 
    return 0; 
}

Here the function assign_membre (which corresponds to the command assign) is used to assign objects to members of a structure (we make a simulation of the command assign...). The function struc_create (which creates structures) returns -1 if it fails (as obj_create does). The preceeding function could be improved : for example, if it is impossible to create a member of the structure, the structure (and already created members) could be destroyed.


Now we show how to access structures which have been created, and their members. Suppose that we have a command, called Xcom1b, that uses a structure of type defstr1. So the command should be used as follows :

- interpcom -> Xcom1b xxx

where the argument xxx is supposed to be the name of a structure of type defstr1. The function that implements this command could be as follows :

int
Xcom1b_cmd(int argc, char *argv[])
{ 
    int i0, i1, i2, **I; 
    double ***A;
    flow_data  *flow_interp;

/* we test if the structure exists */
    if (sketch_obj_restr(argv[1], &i0, -1, flow_interp) != -1) { 
        error_mess(5, flow_interp);
        return 1;
    }
/*-------------------------------------*/ 

/* we extract the members of the structure */ 
    if (sketch_struc(0, i0, "member1", &i1, flow_interp) == 0) { 
        error_mess(6, flow_interp);
        return 1;
    }
    I = (int **) Obj[0][i1].adresse;}
    if (sketch_struc(0, i0, "member2", &i2, flow_interp) == 0) { 
        error_mess(6, flow_interp);
        return 1;
    }
    A = (double ***) Obj[1][i2].adresse;
/*-------------------------------------*/ 

/*  Here should follow the useful part of the function */
    return 0;
}

Here the error message 6 could be unassigned member !. The function

int sketch_obj_restr(char *str, int *i0, int j, flow_data *flow_interp);

is used as for objects to find a structure with a given name. If j is a negative number, sketch_obj_restr(str, &i0, j, flow_interp) will return j if str is the name of a structure of type -j-1 with name str. In this case, i0 will contain the number of the structure. So this structure will be Struc[-j-1][i0].

To know the members of a structure it is possible to use it itself, or to use the function

int sketch_struc(int i, int i0, char *memb, int *j, flow_data *flow_interp);

Here sketch_struc(i, i0, memb, &j, flow_interp) will return 0 if memb is not the name of a member of the structure number i0 of type i, or if this structure is not defined. If memb is the name of a member of this structure, and if this member is not assigned, it returns also 0. In the remaining case, if the member is an object of type k, the function returns k+1, j will contain the number of the object, and if it is a structure of type k, the function returns -k-1, j will contain the number of the structure. So the member will be Obj[k][j] or Struc[k][j]. The parameter flow_interp is the address of the flow_data structure corresponding to the running thread (cf. 10.4, 5.2).


next up previous contents index
Next: Destruction of structures Up: Objects and structures Previous: Structures   Contents   Index
2009-11-12