[prev in list] [next in list] [prev in thread] [next in thread]
List: gcc-fortran
Subject: [RFC, patch] Extended types in namelists
From: Jerry DeLisle <jvdelisle () charter ! net>
Date: 2014-03-23 22:57:59
Message-ID: 532F66F7.3000602 () charter ! net
[Download RAW message or body]
Hi all,
The attached patch will eventually resolve pr55117. It provides a way to
identify extended type variable names in namelists that use a parent%child
format, but internally these are represented as parent%extended%child. (Forgive
me if I have my nomenclature inaccurate).
The patch has two parts, front-end and library. The front-end patch was
provided by Tobias and substitutes a '+' symbol in the namelist variable name
strings so that we can tell if the variable being searched is an extended type.
The library part modifies the search for the variable names to first look for a
match to a non extended type and then if not found, looks for an extended type
match.
I have been running Tobias front-end patch for months without any failures so
that tells me we don't have too many code examples to exercise this, none in the
testsuite for sure.
The patch is preliminary in that I have tested with some test cases I have. I
am not convinced that a recursive approach is not needed depending on how the
variable names get nested. With that said, I would appreciate some examples that
are not handled yet by the patch. (I hate it when I ask for it because usually I
will then get a bundle of examples, ha ha)
Testing and comments much appreciated.
Regards,
Jerry
["extended_type_nml.diff" (text/x-patch)]
Index: gcc/fortran/trans-io.c
===================================================================
--- gcc/fortran/trans-io.c (revision 208755)
+++ gcc/fortran/trans-io.c (working copy)
@@ -1452,10 +1452,10 @@ gfc_trans_wait (gfc_code * code)
/* nml_full_name builds up the fully qualified name of a
- derived type component. */
+ derived type component. '+' is used to denote a type extension. */
static char*
-nml_full_name (const char* var_name, const char* cmp_name)
+nml_full_name (const char* var_name, const char* cmp_name, bool parent)
{
int full_name_length;
char * full_name;
@@ -1463,7 +1463,7 @@ static char*
full_name_length = strlen (var_name) + strlen (cmp_name) + 1;
full_name = XCNEWVEC (char, full_name_length + 1);
strcpy (full_name, var_name);
- full_name = strcat (full_name, "%");
+ full_name = strcat (full_name, parent ? "+" : "%");
full_name = strcat (full_name, cmp_name);
return full_name;
}
@@ -1634,7 +1634,8 @@ transfer_namelist_element (stmtblock_t * block, co
for (cmp = ts->u.derived->components; cmp; cmp = cmp->next)
{
- char *full_name = nml_full_name (var_name, cmp->name);
+ char *full_name = nml_full_name (var_name, cmp->name,
+ ts->u.derived->attr.extension);
transfer_namelist_element (block,
full_name,
NULL, cmp, expr);
Index: libgfortran/io/list_read.c
===================================================================
--- libgfortran/io/list_read.c (revision 208755)
+++ libgfortran/io/list_read.c (working copy)
@@ -2400,6 +2400,38 @@ err_ret:
return false;
}
+
+static bool
+extended_look_ahead (char *p, char *q)
+{
+ char *r, *s;
+
+ /* Scan ahead to find a '%' in the p string. */
+ for(r = p, s = q; *r && *s; s++)
+ if ((*s == '%' || *s == '+') && strcmp (r + 1, s + 1) == 0)
+ return true;
+ return false;
+}
+
+
+static bool
+strcmp_extended_type (char *p, char *q)
+{
+ char *r, *s;
+
+ for (r = p, s = q; *r && *s; r++, s++)
+ {
+ if (*r != *s)
+ {
+ if (*r == '%' && *s == '+' && extended_look_ahead (r, s))
+ return true;
+ break;
+ }
+ }
+ return false;
+}
+
+
static namelist_info *
find_nml_node (st_parameter_dt *dtp, char * var_name)
{
@@ -2411,6 +2443,11 @@ find_nml_node (st_parameter_dt *dtp, char * var_na
t->touched = 1;
return t;
}
+ if (strcmp_extended_type (var_name, t->var_name))
+ {
+ t->touched = 1;
+ return t;
+ }
t = t->next;
}
return NULL;
["deep.f90" (text/x-fortran)]
program test_type_extension
type tk_t
real :: x
end type tk_t
type, extends(tk_t) :: tke_t
character(8) :: string
end type tke_t
type, extends(tke_t) :: deep
integer :: int1
real :: y
character(10) :: the_name
end type deep
type other
integer :: one_oh
integer :: two_oh
end type other
type plain_type
integer :: var1
type(other) :: var2
real :: var3
end type plain_type
type some_other
complex :: varx
type(tke_t) :: tke
type (plain_type) :: varpy
real :: vary
end type some_other
type(deep) :: trouble
type(some_other) :: somethinelse
type(tke_t) :: tke
integer :: answer
namelist /test_NML/ trouble, somethinelse, tke, answer
tke%x = 0.0
tke%string = "xxxxxxxx"
answer = 5
trouble%x = 5.34
trouble%y = 4.25
trouble%string = "yyyy"
trouble%the_name = "mischief"
!write(*,*) tke%x, tke%string, answer
!write(*,*) "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
!write(*,*) trouble
!write(*,*) "======================================="
!write(6,nml=test_NML)
open(unit=10,file='good.inp')
read(10,NML=test_NML)
write(*,*) tke%x, tke%string, answer
end program test_type_extension
["good.inp" (text/plain)]
&TEST_NML
TKE%X= 3.14 ,
TKE%STRING="kf7rcc",
ANSWER= 42,
/
***** replace the above chunk with the following for no error*******
&TEST_NML
TKE%TK_T%X= 3.14 ,
TKE%STRING="kf7rcc54",
ANSWER= 42,
/
****************************
type tk_t
real :: x
end type tk_t
type, extends(tk_t) :: tke_t
character(8) :: string
end type tke_t
type, extends(tke_t) :: deep
integer :: int1
real :: y
character(10) :: the_name
end type deep
type(tke_t) :: tke
type(deep) :: trouble
integer :: answer
namelist /test_NML/ tke, answer, trouble
Note to self:
To fix this bug we need to modify the search algorythm in find_nml_node
Consider searching for matching first name and matching last name
Create a test case with multiple extended/nested types
Tobias patch is applied
var_name = tke%x << We have this
t.var_name = tke
t.next.var_name = tke%tk_t
t.next.next.var_name = tke%tk_t%x << The one we are looking for
t.next.next.next.var_name = tke%string
["tc55117-2.f90" (text/x-fortran)]
type i1
integer :: val
end type i1
type, extends(i1) :: i2
end type i2
type o1
type(i2) :: i2
end type o1
type,extends(o1) :: o2
end type o2
type(o2) :: var
namelist /nml/ var
var%i2%val = -42
write(*,nml=nml)
open (99, status='scratch')
write(99, '(A)') '&nml var%i2%val = 1 /'
rewind(99); read(99,nml=nml); close(99)
if (var%i2%val /= 1) call abort ()
!var%i2%i1%val = -43
!open (99, status='scratch')
!write(99, '(A)') '&nml var%i2%i1%val = 2 /'
!rewind(99); read(99,nml=nml); close(99)
!if (var%i2%val /= 2) call abort ()
!var%o1%i2%i1%val = -44
!open (99, status='scratch')
!write(99, '(A)') '&nml var%o1%i2%i1%val = 3 /'
!rewind(99); read(99,nml=nml); close(99)
!if (var%i2%val /= 3) call abort ()
!var%o1%i2%val = -45
!open (99, status='scratch')
!write(99, '(A)') '&nml var%o1%i2%val = 4 /'
!rewind(99); read(99,nml=nml); close(99)
!if (var%i2%val /= 4) call abort ()
end
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic