diff -dcrpN pgsql85dev.3describe/doc/src/sgml/ecpg.sgml pgsql85dev.4string/doc/src/sgml/ecpg.sgml
*** pgsql85dev.3describe/doc/src/sgml/ecpg.sgml	2009-07-13 15:16:28.469424632 +0200
--- pgsql85dev.4string/doc/src/sgml/ecpg.sgml	2009-07-14 22:30:24.345801171 +0200
*************** void PGTYPESdecimal_free(decimal *var);
*** 2418,2423 ****
--- 2418,2428 ----
     know about ranges like for example <literal>YEAR TO MINUTE</> so you won't
     find support in ecpg for that either.
    </para>
+   <para>
+    The Informix-special "string" data type for storing right-trimmed character string data is now
+    supported in Informix-mode without using <literal>typedef</literal>. In fact, in Informix-mode,
+    ECPG refuses to process source files that contain <literal>typedef sometype string;</literal>
+   </para>
  
    <sect2>
     <title>Additional embedded SQL statements</title>
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/data.c pgsql85dev.4string/src/interfaces/ecpg/ecpglib/data.c
*** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/data.c	2009-01-16 11:45:04.000000000 +0100
--- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/data.c	2009-07-14 21:36:58.576800146 +0200
*************** ecpg_get_data(const PGresult *results, i
*** 138,143 ****
--- 138,144 ----
  			case ECPGt_char:
  			case ECPGt_unsigned_char:
  			case ECPGt_varchar:
+ 			case ECPGt_string:
  				break;
  
  			default:
*************** ecpg_get_data(const PGresult *results, i
*** 389,394 ****
--- 390,396 ----
  
  				case ECPGt_char:
  				case ECPGt_unsigned_char:
+ 				case ECPGt_string:
  					if (pval)
  					{
  						if (varcharsize == 0 || varcharsize > size)
*************** ecpg_get_data(const PGresult *results, i
*** 426,431 ****
--- 428,454 ----
  								sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
  							}
  						}
+ 						/* Do the rtrim() */
+ 						if (type == ECPGt_string)
+ 						{
+ 							char	*str = (char *) ((long) var + offset * act_tuple);
+ 							char	*last;
+ 							int	len = strlen(str);
+ 
+ 							last = str + len;
+ 							while (last > str)
+ 							{
+ 								if (*last == '\0')
+ 									last--;
+ 								else if (*last == ' ')
+ 								{
+ 									*last = '\0';
+ 									last--;
+ 								}
+ 								else
+ 									break;
+ 							}
+ 						}
  						pval += size;
  					}
  					break;
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/descriptor.c pgsql85dev.4string/src/interfaces/ecpg/ecpglib/descriptor.c
*** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/descriptor.c	2009-07-14 21:21:46.526800064 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/descriptor.c	2009-07-14 21:36:58.577803765 +0200
*************** get_char_item(int lineno, void *var, enu
*** 201,206 ****
--- 201,207 ----
  	{
  		case ECPGt_char:
  		case ECPGt_unsigned_char:
+ 		case ECPGt_string:
  			strncpy((char *) var, value, varcharsize);
  			break;
  		case ECPGt_varchar:
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/execute.c pgsql85dev.4string/src/interfaces/ecpg/ecpglib/execute.c
*** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/execute.c	2009-07-14 21:25:02.120803120 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/execute.c	2009-07-14 21:36:58.582803006 +0200
*************** ecpg_store_result(const PGresult *result
*** 360,365 ****
--- 360,366 ----
  			{
  				case ECPGt_char:
  				case ECPGt_unsigned_char:
+ 				case ECPGt_string:
  					if (!var->varcharsize && !var->arrsize)
  					{
  						/* special mode for handling char**foo=0 */
*************** ecpg_store_result(const PGresult *result
*** 419,425 ****
  
  	/* fill the variable with the tuple(s) */
  	if (!var->varcharsize && !var->arrsize &&
! 		(var->type == ECPGt_char || var->type == ECPGt_unsigned_char))
  	{
  		/* special mode for handling char**foo=0 */
  
--- 420,426 ----
  
  	/* fill the variable with the tuple(s) */
  	if (!var->varcharsize && !var->arrsize &&
! 		(var->type == ECPGt_char || var->type == ECPGt_unsigned_char || var->type == ECPGt_string))
  	{
  		/* special mode for handling char**foo=0 */
  
*************** ecpg_store_input(const int lineno, const
*** 758,763 ****
--- 759,765 ----
  
  			case ECPGt_char:
  			case ECPGt_unsigned_char:
+ 			case ECPGt_string:
  				{
  					/* set slen to string length if type is char * */
  					int			slen = (var->varcharsize == 0) ? strlen((char *) var->value) : (unsigned int) var->varcharsize;
*************** ecpg_execute(struct statement * stmt)
*** 1196,1201 ****
--- 1198,1204 ----
  					{
  						case ECPGt_char:
  						case ECPGt_varchar:
+ 						case ECPGt_string:
  							desc_inlist.varcharsize = strlen(sqlda->sqlvar[i].sqldata);
  							break;
  						default:
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/misc.c pgsql85dev.4string/src/interfaces/ecpg/ecpglib/misc.c
*** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/misc.c	2009-06-13 18:25:05.000000000 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/misc.c	2009-07-14 21:36:58.583801667 +0200
*************** ECPGset_noind_null(enum ECPGttype type, 
*** 295,300 ****
--- 295,301 ----
  	{
  		case ECPGt_char:
  		case ECPGt_unsigned_char:
+ 		case ECPGt_string:
  			*((char *) ptr) = '\0';
  			break;
  		case ECPGt_short:
*************** ECPGis_noind_null(enum ECPGttype type, v
*** 361,366 ****
--- 362,368 ----
  	{
  		case ECPGt_char:
  		case ECPGt_unsigned_char:
+ 		case ECPGt_string:
  			if (*((char *) ptr) == '\0')
  				return true;
  			break;
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/typename.c pgsql85dev.4string/src/interfaces/ecpg/ecpglib/typename.c
*** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/typename.c	2009-07-14 21:25:45.229800483 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/typename.c	2009-07-14 21:36:58.584800118 +0200
*************** ecpg_type_name(enum ECPGttype typ)
*** 20,25 ****
--- 20,26 ----
  	switch (typ)
  	{
  		case ECPGt_char:
+ 		case ECPGt_string:
  			return "char";
  		case ECPGt_unsigned_char:
  			return "unsigned char";
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/include/ecpgtype.h pgsql85dev.4string/src/interfaces/ecpg/include/ecpgtype.h
*** pgsql85dev.3describe/src/interfaces/ecpg/include/ecpgtype.h	2009-07-14 20:28:50.644801933 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/include/ecpgtype.h	2009-07-14 21:36:58.584800118 +0200
*************** enum ECPGttype
*** 62,68 ****
  	ECPGt_EOIT,					/* End of insert types. */
  	ECPGt_EORT,					/* End of result types. */
  	ECPGt_NO_INDICATOR,			/* no indicator */
! 	ECPGt_sqlda				/* INFORMIX-compatible sqlda_t descriptor */
  };
  
   /* descriptor items */
--- 62,69 ----
  	ECPGt_EOIT,					/* End of insert types. */
  	ECPGt_EORT,					/* End of result types. */
  	ECPGt_NO_INDICATOR,			/* no indicator */
! 	ECPGt_sqlda,				/* INFORMIX-compatible sqlda_t descriptor */
! 	ECPGt_string				/* trimmed (char *) type */
  };
  
   /* descriptor items */
*************** enum ECPGdtype
*** 87,93 ****
  	ECPGd_cardinality
  };
  
! #define IS_SIMPLE_TYPE(type) ((type) >= ECPGt_char && (type) <= ECPGt_interval)
  
  /* we also have to handle different statement types */
  enum ECPG_statement_type
--- 88,94 ----
  	ECPGd_cardinality
  };
  
! #define IS_SIMPLE_TYPE(type) (((type) >= ECPGt_char && (type) <= ECPGt_interval) || ((type) == ECPGt_string))
  
  /* we also have to handle different statement types */
  enum ECPG_statement_type
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.addons pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.addons
*** pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.addons	2009-07-14 21:26:31.594800717 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.addons	2009-07-14 21:36:58.585801153 +0200
*************** ECPG: ColIdcol_name_keyword rule
*** 331,336 ****
--- 331,344 ----
  	| ECPGKeywords                  { $$ = $1; }
  	| ECPGCKeywords                 { $$ = $1; }
  	| CHAR_P                        { $$ = make_str("char"); }
+ 	| STRING_P
+ 	{
+ 		struct typedefs *this = get_typedef("string", FALSE);
+ 		if (this)
+ 			$$ = make_str("string");
+ 		else
+ 			$$ = make_str("char");
+ 	}
  	| VALUES                        { $$ = make_str("values"); }
  ECPG: type_function_nametype_func_name_keyword rule
  	| ECPGKeywords                          { $$ = $1; }
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.header pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.header
*** pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.header	2009-06-13 18:25:05.000000000 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.header	2009-07-15 11:19:06.423546668 +0200
*************** adjust_informix(struct arguments *list)
*** 256,267 ****
  		original_var = ptr->variable->name;
  		sprintf(temp, "%d))", ecpg_informix_var);
  
! 		if ((ptr->variable->type->type != ECPGt_varchar && ptr->variable->type->type != ECPGt_char && ptr->variable->type->type != ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
  		{
  			ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, make_str("1"), ptr->variable->type->u.element->lineno), ptr->variable->type->size), 0);
  			sprintf(temp, "%d, (", ecpg_informix_var++);
  		}
! 		else if ((ptr->variable->type->type == ECPGt_varchar || ptr->variable->type->type == ECPGt_char || ptr->variable->type->type == ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
  		{
  			ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0);
  			sprintf(temp, "%d, (", ecpg_informix_var++);
--- 256,267 ----
  		original_var = ptr->variable->name;
  		sprintf(temp, "%d))", ecpg_informix_var);
  
! 		if ((ptr->variable->type->type != ECPGt_varchar && ptr->variable->type->type != ECPGt_char && ptr->variable->type->type != ECPGt_unsigned_char && ptr->variable->type->type != ECPGt_string) && atoi(ptr->variable->type->size) > 1)
  		{
  			ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, make_str("1"), ptr->variable->type->u.element->lineno), ptr->variable->type->size), 0);
  			sprintf(temp, "%d, (", ecpg_informix_var++);
  		}
! 		else if ((ptr->variable->type->type == ECPGt_varchar || ptr->variable->type->type == ECPGt_char || ptr->variable->type->type == ECPGt_unsigned_char || ptr->variable->type->type == ECPGt_string) && atoi(ptr->variable->type->size) > 1)
  		{
  			ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0);
  			sprintf(temp, "%d, (", ecpg_informix_var++);
*************** add_typedef(char *name, char * dimension
*** 343,348 ****
--- 343,350 ----
  	     type_enum == ECPGt_union) &&
  	    initializer == 1)
  		mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in type definition");
+ 	else if (INFORMIX_MODE && strcmp(name, "string") == 0)
+ 		mmerror(PARSE_ERROR, ET_ERROR, "type name \"string\" is reserved in Informix mode");
  	else
  	{
  		for (ptr = types; ptr != NULL; ptr = ptr->next)
*************** add_typedef(char *name, char * dimension
*** 371,376 ****
--- 373,379 ----
  		if (type_enum != ECPGt_varchar &&
  			type_enum != ECPGt_char &&
  			type_enum != ECPGt_unsigned_char &&
+ 			type_enum != ECPGt_string &&
  			atoi(this->type->type_index) >= 0)
  			mmerror(PARSE_ERROR, ET_ERROR, "multidimensional arrays for simple data types are not supported");
  
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.tokens pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.tokens
*** pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.tokens	2008-11-14 11:03:33.000000000 +0100
--- pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.tokens	2009-07-14 21:36:58.596799901 +0200
***************
*** 25,28 ****
  %token TYPECAST
  %token CSTRING CVARIABLE CPP_LINE IP 
  %token DOLCONST ECONST NCONST UCONST UIDENT
! 
--- 25,28 ----
  %token TYPECAST
  %token CSTRING CVARIABLE CPP_LINE IP 
  %token DOLCONST ECONST NCONST UCONST UIDENT
! %token STRING_P
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.trailer pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.trailer
*** pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.trailer	2009-07-14 21:27:26.131801570 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.trailer	2009-07-14 21:36:58.598800505 +0200
*************** char_variable: cvariable
*** 213,218 ****
--- 213,219 ----
  				{
  					case ECPGt_char:
  					case ECPGt_unsigned_char:
+ 					case ECPGt_string:
  						$$ = $1;
  						break;
  					case ECPGt_varchar:
*************** var_type:	simple_type
*** 596,613 ****
  			else
  			{
  				/* this is for typedef'ed types */
! 				struct typedefs *this = get_typedef($1);
  
! 				$$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
! 				$$.type_enum = this->type->type_enum;
! 				$$.type_dimension = this->type->type_dimension;
! 				$$.type_index = this->type->type_index;
! 				if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
! 					$$.type_sizeof = this->type->type_sizeof;
! 				else 
! 					$$.type_sizeof = cat_str(3, make_str("sizeof("), mm_strdup(this->name), make_str(")"));
  
! 				struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
  			}
  		}
  		| s_struct_union_symbol
--- 597,630 ----
  			else
  			{
  				/* this is for typedef'ed types */
! 				struct typedefs *this = get_typedef($1, FALSE);
  
! 				if (this == NULL)
! 				{
! 					if ((strcmp($1, "string") == 0) && INFORMIX_MODE)
! 					{
! 						$$.type_enum = ECPGt_string;
! 						$$.type_str = make_str("char");
! 						$$.type_dimension = make_str("-1");
! 						$$.type_index = make_str("-1");
! 						$$.type_sizeof = NULL;
! 					}
! 					else
! 						mmerror(PARSE_ERROR, ET_FATAL, "type \"%s\" is not defined", $1);
! 				}
! 				else
! 				{
! 					$$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
! 					$$.type_enum = this->type->type_enum;
! 					$$.type_dimension = this->type->type_dimension;
! 					$$.type_index = this->type->type_index;
! 					if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
! 						$$.type_sizeof = this->type->type_sizeof;
! 					else 
! 						$$.type_sizeof = cat_str(3, make_str("sizeof("), mm_strdup(this->name), make_str(")"));
  
! 					struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
! 				}
  			}
  		}
  		| s_struct_union_symbol
*************** var_type:	simple_type
*** 623,629 ****
  			{
  				/* No */
  
! 				this = get_typedef(name);
  				$$.type_str = mm_strdup(this->name);
  				$$.type_enum = this->type->type_enum;
  				$$.type_dimension = this->type->type_dimension;
--- 640,646 ----
  			{
  				/* No */
  
! 				this = get_typedef(name, TRUE);
  				$$.type_str = mm_strdup(this->name);
  				$$.type_enum = this->type->type_enum;
  				$$.type_dimension = this->type->type_dimension;
*************** signed_type: SQL_SHORT				{ $$ = ECPGt_s
*** 795,800 ****
--- 812,818 ----
  		}
  		| SQL_BOOL					{ $$ = ECPGt_bool; }
  		| CHAR_P					{ $$ = ECPGt_char; }
+ 		| STRING_P					{ $$ = ECPGt_string; }
  		| DOUBLE_P					{ $$ = ECPGt_double; }
  		;
  
*************** variable: opt_pointer ECPGColLabel opt_a
*** 855,860 ****
--- 873,879 ----
  
  				case ECPGt_char:
  				case ECPGt_unsigned_char:
+ 				case ECPGt_string:
  					if (atoi(dimension) == -1)
  					{
  						int i = strlen($5);
*************** ECPGVar: SQL_VAR
*** 1332,1337 ****
--- 1351,1357 ----
  
  					case ECPGt_char:
  					case ECPGt_unsigned_char:
+ 					case ECPGt_string:
  						if (atoi(dimension) == -1)
  							type = ECPGmake_simple_type($5.type_enum, length, 0);
  						else
*************** c_anything:  ecpg_ident				{ $$ = $1; }
*** 2018,2023 ****
--- 2038,2044 ----
  		| SQL_UNSIGNED			{ $$ = make_str("unsigned"); }
  		| YEAR_P			{ $$ = make_str("year"); }
  		| CHAR_P			{ $$ = make_str("char"); }
+ 		| STRING_P			{ $$ = make_str("string"); }
  		| FLOAT_P			{ $$ = make_str("float"); }
  		| TO				{ $$ = make_str("to"); }
  		| UNION				{ $$ = make_str("union"); }
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/preproc/extern.h pgsql85dev.4string/src/interfaces/ecpg/preproc/extern.h
*** pgsql85dev.3describe/src/interfaces/ecpg/preproc/extern.h	2009-07-14 20:59:04.846801587 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/preproc/extern.h	2009-07-14 21:36:58.598800505 +0200
*************** extern void add_variable_to_head(struct 
*** 94,100 ****
  extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *);
  extern void remove_variable_from_list(struct arguments ** list, struct variable * var);
  extern void dump_variables(struct arguments *, int);
! extern struct typedefs *get_typedef(char *);
  extern void adjust_array(enum ECPGttype, char **, char **, char *, char *, int, bool);
  extern void reset_variables(void);
  extern void check_indicator(struct ECPGtype *);
--- 94,100 ----
  extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *);
  extern void remove_variable_from_list(struct arguments ** list, struct variable * var);
  extern void dump_variables(struct arguments *, int);
! extern struct typedefs *get_typedef(char *, int);
  extern void adjust_array(enum ECPGttype, char **, char **, char *, char *, int, bool);
  extern void reset_variables(void);
  extern void check_indicator(struct ECPGtype *);
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/preproc/type.c pgsql85dev.4string/src/interfaces/ecpg/preproc/type.c
*** pgsql85dev.3describe/src/interfaces/ecpg/preproc/type.c	2009-07-14 20:59:41.644799341 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/preproc/type.c	2009-07-14 21:36:58.599800842 +0200
*************** get_type(enum ECPGttype type)
*** 200,205 ****
--- 200,208 ----
  		case ECPGt_timestamp:
  			return ("ECPGt_timestamp");
  			break;
+ 		case ECPGt_string:
+ 			return ("ECPGt_string");
+ 			break;
  		default:
  			mmerror(PARSE_ERROR, ET_ERROR, "unrecognized variable type code %d", type);
  	}
*************** ECPGdump_a_simple(FILE *o, const char *n
*** 368,373 ****
--- 371,377 ----
  			case ECPGt_char:
  			case ECPGt_unsigned_char:
  			case ECPGt_char_variable:
+ 			case ECPGt_string:
  
  				/*
  				 * we have to use the pointer except for arrays with given
diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/preproc/variable.c pgsql85dev.4string/src/interfaces/ecpg/preproc/variable.c
*** pgsql85dev.3describe/src/interfaces/ecpg/preproc/variable.c	2009-07-14 16:40:53.576682685 +0200
--- pgsql85dev.4string/src/interfaces/ecpg/preproc/variable.c	2009-07-14 21:36:58.600799922 +0200
*************** check_indicator(struct ECPGtype * var)
*** 486,497 ****
  }
  
  struct typedefs *
! get_typedef(char *name)
  {
  	struct typedefs *this;
  
  	for (this = types; this && strcmp(this->name, name); this = this->next);
! 	if (!this)
  		mmerror(PARSE_ERROR, ET_FATAL, "unrecognized data type name \"%s\"", name);
  
  	return (this);
--- 486,497 ----
  }
  
  struct typedefs *
! get_typedef(char *name, int error)
  {
  	struct typedefs *this;
  
  	for (this = types; this && strcmp(this->name, name); this = this->next);
! 	if (!this && error)
  		mmerror(PARSE_ERROR, ET_FATAL, "unrecognized data type name \"%s\"", name);
  
  	return (this);
*************** adjust_array(enum ECPGttype type_enum, c
*** 524,530 ****
  												"multilevel pointers (more than 2 levels) are not supported; found %d levels", pointer_len),
  				pointer_len);
  
! 	if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char)
  		mmerror(PARSE_ERROR, ET_FATAL, "pointer to pointer is not supported for this data type");
  
  	if (pointer_len > 1 && (atoi(*length) >= 0 || atoi(*dimension) >= 0))
--- 524,530 ----
  												"multilevel pointers (more than 2 levels) are not supported; found %d levels", pointer_len),
  				pointer_len);
  
! 	if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char && type_enum != ECPGt_string)
  		mmerror(PARSE_ERROR, ET_FATAL, "pointer to pointer is not supported for this data type");
  
  	if (pointer_len > 1 && (atoi(*length) >= 0 || atoi(*dimension) >= 0))
*************** adjust_array(enum ECPGttype type_enum, c
*** 563,568 ****
--- 563,569 ----
  			break;
  		case ECPGt_char:
  		case ECPGt_unsigned_char:
+ 		case ECPGt_string:
  			/* char ** */
  			if (pointer_len == 2)
  			{
