diff mbox

[fortran] PR55117 Programs fails to read namelist (contains derived types objects)

Message ID 5381520C.1060904@charter.net
State New
Headers show

Commit Message

Jerry DeLisle May 25, 2014, 2:14 a.m. UTC
Hi folks,

This patch combines Tobias front-end patch with my libgfortran patch to resolve
this PR.

To denote extended derived types (classes) we use a '+' rather than '%' in
certain parts of the namelist name internally to identify that an extended type
is being dealt with.  The runtime is modified to look for this '+' and when it
is seen, scan ahead for the varname match.

For inherited types, a match could be found in two different ways.

parent%cousin%child

parent%child

This would be internally represented as:

parent+cousin%child

So the '+' sign is used to signal that we have to do a special matching check
for both possible cases depending on how the user chose to represent it, usually
as the shorter version of the name.

Admittedly, I do not have very many examples of code that use this feature yet.

Regression tested on x86-64.  Test case attached with patch.

OK for trunk?

Regards,

Jerry

2014-05-24  Tobias Burnus  <burnus@net-b.de>

	PR fortran/55117
	* trans-io.c (nml_full_name, transfer_namelist_element): Insert
	a '+' rather then '%' to differentiate namelist variable names
	that are based on extended derived types.
	
2014-05-24  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libgfortran/55117
	* io/list_read.c (extended_look_ahead): New helper function to
	scan the namelist name and look for matches with the new '+'
	extended type parent indicator.  (str_comp_extended): New
	helper function to compare the namelist name with the varname
	namelist. (find_nml_name): Use the new helper functions to match
	the extended type varnames.

Comments

Jerry DeLisle May 25, 2014, 3:44 a.m. UTC | #1
I attached the wrong test case.

use the one attached.

On 05/24/2014 07:14 PM, Jerry DeLisle wrote:
> Hi folks,
> 
> This patch combines Tobias front-end patch with my libgfortran patch to resolve
> this PR.
> 
> To denote extended derived types (classes) we use a '+' rather than '%' in
> certain parts of the namelist name internally to identify that an extended type
> is being dealt with.  The runtime is modified to look for this '+' and when it
> is seen, scan ahead for the varname match.
> 
> For inherited types, a match could be found in two different ways.
> 
> parent%cousin%child
> 
> parent%child
> 
> This would be internally represented as:
> 
> parent+cousin%child
> 
> So the '+' sign is used to signal that we have to do a special matching check
> for both possible cases depending on how the user chose to represent it, usually
> as the shorter version of the name.
> 
> Admittedly, I do not have very many examples of code that use this feature yet.
> 
> Regression tested on x86-64.  Test case attached with patch.
> 
> OK for trunk?
> 
> Regards,
> 
> Jerry
> 
> 2014-05-24  Tobias Burnus  <burnus@net-b.de>
> 
> 	PR fortran/55117
> 	* trans-io.c (nml_full_name, transfer_namelist_element): Insert
> 	a '+' rather then '%' to differentiate namelist variable names
> 	that are based on extended derived types.
> 	
> 2014-05-24  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
> 
> 	PR libgfortran/55117
> 	* io/list_read.c (extended_look_ahead): New helper function to
> 	scan the namelist name and look for matches with the new '+'
> 	extended type parent indicator.  (str_comp_extended): New
> 	helper function to compare the namelist name with the varname
> 	namelist. (find_nml_name): Use the new helper functions to match
> 	the extended type varnames.
>
Tobias Burnus May 26, 2014, 6:01 a.m. UTC | #2
Jerry DeLisle wrote:
> Regression tested on x86-64.  Test case attached with patch.
> OK for trunk?

Looks good to me. Thanks for the patch.

Tobias

> 2014-05-24  Tobias Burnus  <burnus@net-b.de>
>
> 	PR fortran/55117
> 	* trans-io.c (nml_full_name, transfer_namelist_element): Insert
> 	a '+' rather then '%' to differentiate namelist variable names
> 	that are based on extended derived types.
> 	
> 2014-05-24  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
>
> 	PR libgfortran/55117
> 	* io/list_read.c (extended_look_ahead): New helper function to
> 	scan the namelist name and look for matches with the new '+'
> 	extended type parent indicator.  (str_comp_extended): New
> 	helper function to compare the namelist name with the varname
> 	namelist. (find_nml_name): Use the new helper functions to match
> 	the extended type varnames.
>
diff mbox

Patch

Index: gcc/fortran/trans-io.c
===================================================================
--- gcc/fortran/trans-io.c	(revision 210573)
+++ 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 210898)
+++ libgfortran/io/list_read.c	(working copy)
@@ -2557,6 +2557,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)
 {
@@ -2568,6 +2600,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;