From: Michael Meskes <meskes@topsystem.de>

And the next update. Now you can use only parts of a struct like this:

exec sql select a into :struct.string from foo;
This commit is contained in:
Marc G. Fournier 1998-04-27 14:35:58 +00:00
parent 3e3477f5a4
commit 718430ea40
9 changed files with 177 additions and 97 deletions

View File

@ -142,3 +142,10 @@ Fri Apr 24 13:50:15 CEST 1998
- Fixed some bugs.
- Set version to 2.1.1
Mon Apr 27 14:26:55 CEST 1998
- Parser now able to understand and process syntax like :foo->bar
and :foo.bar as variables.
- Set version to 2.2.0

View File

@ -53,6 +53,3 @@ exec sql disconnect {current|default|all|connectionname|connection_hostvar};
commit release|commit work release auch disconnect
It is not neccessary to check for "not found" after all commands.
It would be nice to be able to specify parts of a structure like :foo.bar or
:foo->bar.

View File

@ -18,7 +18,7 @@
* Complex types:
* VARCHAR, VARCHAR2 - Strings with length (maxlen is given in the declaration)
* Arrays of simple types and of VARCHAR, VARCHAR2 (size given in declaration)
* Records build of simple types, arrays and other records.
* Records build of simple types, arrays and other structs.
*
* Complicating things:
* typedefs and struct names!
@ -41,7 +41,7 @@ enum ECPGttype
ECPGt_float, ECPGt_double,
ECPGt_varchar, ECPGt_varchar2,
ECPGt_array,
ECPGt_record,
ECPGt_struct,
ECPGt_EOIT, /* End of insert types. */
ECPGt_EORT, /* End of result types. */
ECPGt_NO_INDICATOR /* no indicator */

View File

@ -2,8 +2,8 @@ SRCDIR= ../../..
include $(SRCDIR)/Makefile.global
MAJOR_VERSION=2
MINOR_VERSION=1
PATCHLEVEL=1
MINOR_VERSION=2
PATCHLEVEL=0
CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
-DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \

View File

@ -306,6 +306,7 @@ sql [sS][qQ][lL]
return (yytext[0]);
}
<SQL>{self} { return (yytext[0]); }
<SQL>"->" { return S_STRUCTPOINTER; }
<SQL>{operator}/-[\.0-9] {
yylval.str = strdup((char*)yytext);
return (Op);

View File

@ -17,8 +17,8 @@ static int QueryIsRule = 0;
static enum ECPGttype actual_type[128];
static char *actual_storage[128];
/* temporarily store record members while creating the data structure */
struct ECPGrecord_member *record_member_list[128] = { NULL };
/* temporarily store struct members while creating the data structure */
struct ECPGstruct_member *struct_member_list[128] = { NULL };
/* keep a list of cursors */
struct cursor *cur = NULL;
@ -89,26 +89,6 @@ int braces_open;
static struct variable * allvariables = NULL;
static struct variable *
find_variable(char * name)
{
struct variable * p;
char * errorstring = (char *) mm_alloc(strlen(name) + 100);
for (p = allvariables; p; p = p->next)
{
if (strcmp(p->name, name) == 0)
return p;
}
sprintf(errorstring, "The variable %s is not declared", name);
yyerror(errorstring);
free (errorstring);
return NULL;
}
static void
new_variable(const char * name, struct ECPGtype * type)
{
struct variable * p = (struct variable*) mm_alloc(sizeof(struct variable));
@ -119,6 +99,97 @@ new_variable(const char * name, struct ECPGtype * type)
p->next = allvariables;
allvariables = p;
return(p);
}
static struct variable * find_variable(char * name);
static struct variable *
find_struct_member(char *name, char *str, struct ECPGstruct_member *members)
{
char *next = strpbrk(++str, ".-"), c = '\0';
if (next != NULL)
{
c = *next;
*next = '\0';
}
for (; members; members = members->next)
{
if (strcmp(members->name, str) == 0)
{
if (c == '\0')
{
/* found the end */
switch (members->typ->typ)
{
case ECPGt_struct:
return(new_variable(name, ECPGmake_struct_type(members->typ->u.members)));
case ECPGt_varchar:
return(new_variable(name, ECPGmake_varchar_type(members->typ->typ, members->typ->size)));
default:
return(new_variable(name, ECPGmake_simple_type(members->typ->typ, members->typ->size)));
}
}
else
{
*next = c;
if (c == '-') next++;
return(find_struct_member(name, next, members->typ->u.members));
}
}
}
return(NULL);
}
static struct variable *
find_struct(char * name, char *next)
{
struct variable * p;
char c = *next;
/* first get the mother structure entry */
*next = '\0';
p = find_variable(name);
/* restore the name, we will need it later on */
*next = c;
if (*next == '-') next++;
return (find_struct_member(name, next, p->type->u.members));
}
static struct variable *
find_simple(char * name)
{
struct variable * p;
for (p = allvariables; p; p = p->next)
{
if (strcmp(p->name, name) == 0)
return p;
}
return(NULL);
}
static struct variable *
find_variable(char * name)
{
char * next;
struct variable * p =
((next = strpbrk(name, ".-")) != NULL) ? find_struct(name, next) : find_simple(name);
if (p == NULL)
{
sprintf(errortext, "The variable %s is not declared", name);
yyerror(errortext);
}
return(p);
}
static void
@ -215,7 +286,7 @@ check_indicator(struct ECPGtype *var)
/* make sure this is a valid indicator variable */
switch (var->typ)
{
struct ECPGrecord_member *p;
struct ECPGstruct_member *p;
case ECPGt_short:
case ECPGt_int:
@ -225,7 +296,7 @@ check_indicator(struct ECPGtype *var)
case ECPGt_unsigned_long:
break;
case ECPGt_record:
case ECPGt_struct:
for (p = var->u.members; p; p = p->next)
check_indicator(p->typ);
break;
@ -392,8 +463,8 @@ output_statement(const char * stmt)
/* C token */
%token S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_EXTERN
%token S_FLOAT S_INT
%token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT S_UNSIGNED
%token S_VARCHAR
%token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT
%token S_STRUCTPOINTER S_UNSIGNED S_VARCHAR
/* I need this and don't know where it is defined inside the backend */
%token TYPECAST
@ -3704,7 +3775,7 @@ declaration: storage_clause type
{
actual_storage[struct_level] = $1;
actual_type[struct_level] = $2;
if ($2 != ECPGt_varchar && $2 != ECPGt_record)
if ($2 != ECPGt_varchar && $2 != ECPGt_struct)
fprintf(yyout, "%s %s", $1, ECPGtype_name($2));
}
variable_list ';' { fputc(';', yyout); }
@ -3723,11 +3794,13 @@ type: simple_type
struct_type: s_struct '{' variable_declarations '}'
{
struct_level--;
$$ = actual_type[struct_level] = ECPGt_record;
fputs("} ", yyout);
$$ = ECPGt_struct;
}
s_struct : S_STRUCT symbol
{
struct_member_list[struct_level] = NULL;
struct_level++;
fprintf(yyout, "struct %s {", $2);
}
@ -3764,14 +3837,13 @@ variable: opt_pointer symbol opt_index opt_initializer
switch (actual_type[struct_level])
{
case ECPGt_record:
case ECPGt_struct:
if (struct_level == 0)
new_variable($2, ECPGmake_record_type(record_member_list[struct_level]));
new_variable($2, ECPGmake_struct_type(struct_member_list[struct_level]));
else
ECPGmake_record_member($2, ECPGmake_record_type(record_member_list[struct_level]), &(record_member_list[struct_level-1]));
ECPGmake_struct_member($2, ECPGmake_struct_type(struct_member_list[struct_level]), &(struct_member_list[struct_level-1]));
record_member_list[struct_level] = NULL;
fprintf(yyout, "} %s%s%s%s", $1, $2, $3.str, $4);
fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4);
break;
case ECPGt_varchar:
@ -3781,7 +3853,7 @@ variable: opt_pointer symbol opt_index opt_initializer
if (struct_level == 0)
new_variable($2, ECPGmake_varchar_type(actual_type[struct_level], length));
else
ECPGmake_record_member($2, ECPGmake_varchar_type(actual_type[struct_level], length), &(record_member_list[struct_level-1]));
ECPGmake_struct_member($2, ECPGmake_varchar_type(actual_type[struct_level], length), &(struct_member_list[struct_level-1]));
if (length > 0)
fprintf(yyout, "%s struct varchar_%s { int len; char arr[%d]; } %s", actual_storage[struct_level], $2, length, $2);
@ -3794,7 +3866,7 @@ variable: opt_pointer symbol opt_index opt_initializer
if (struct_level == 0)
new_variable($2, ECPGmake_simple_type(actual_type[struct_level], length));
else
ECPGmake_record_member($2, ECPGmake_simple_type(actual_type[struct_level], length), &(record_member_list[struct_level-1]));
ECPGmake_struct_member($2, ECPGmake_simple_type(actual_type[struct_level], length), &(struct_member_list[struct_level-1]));
fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4);
@ -4230,15 +4302,15 @@ civariableonly : cvariable name {
}
cvariable: CVARIABLE { $$ = $1; }
| CVARIABLE '.' identlist { $$ = $1; }
| CVARIABLE '-' '>' identlist { $$ = $1; }
| CVARIABLE '.' identlist { $$ = cat3_str($1, ".", $3); }
| CVARIABLE S_STRUCTPOINTER identlist { $$ = cat3_str($1, "->", $3); }
identlist: IDENT { $$ = $1; }
| IDENT '.' identlist { $$ = $1; }
| IDENT '-' '>' identlist { $$ = $1; }
| IDENT '.' identlist { $$ = cat3_str($1, ".", $3); }
| IDENT S_STRUCTPOINTER identlist { $$ = cat3_str($1, "->", $3); }
indicator: /* empty */ { $$ = NULL; }
| cvariable { check_indicator((find_variable($1))->type); $$ = $1; }
| cvariable { printf("## %s\n", $1); check_indicator((find_variable($1))->type); $$ = $1; }
| SQL_INDICATOR cvariable { check_indicator((find_variable($2))->type); $$ = $2; }
| SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; }

View File

@ -40,12 +40,12 @@ mm_realloc(void *ptr, size_t size)
*/
/* The NAME argument is copied. The type argument is preserved as a pointer. */
struct ECPGrecord_member *
ECPGmake_record_member(char *name, struct ECPGtype * type, struct ECPGrecord_member ** start)
struct ECPGstruct_member *
ECPGmake_struct_member(char *name, struct ECPGtype * type, struct ECPGstruct_member ** start)
{
struct ECPGrecord_member *ptr,
struct ECPGstruct_member *ptr,
*ne =
(struct ECPGrecord_member *) mm_alloc(sizeof(struct ECPGrecord_member));
(struct ECPGstruct_member *) mm_alloc(sizeof(struct ECPGstruct_member));
ne->name = strdup(name);
ne->typ = type;
@ -94,9 +94,9 @@ ECPGmake_array_type(struct ECPGtype * typ, long siz)
}
struct ECPGtype *
ECPGmake_record_type(struct ECPGrecord_member * rm)
ECPGmake_struct_type(struct ECPGstruct_member * rm)
{
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_record, 1);
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_struct, 1);
ne->u.members = rm;
@ -116,14 +116,14 @@ ECPGmake_record_type(struct ECPGrecord_member * rm)
reference-to-variable can be a reference to a struct element.
arrsize is the size of the array in case of array fetches. Otherwise 0.
size is the maxsize in case it is a varchar. Otherwise it is the size of
the variable (required to do array fetches of records).
the variable (required to do array fetches of structs).
*/
void
ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
long varcharsize,
long arrsiz, const char *siz, const char *prefix);
void
ECPGdump_a_record(FILE *o, const char *name, const char *ind_name, long arrsiz,
ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, long arrsiz,
struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offset, const char *prefix, const char * ind_prefix);
@ -154,19 +154,19 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in
{
abort(); /* Array of array, */
}
else if (typ->u.element->typ == ECPGt_record)
else if (typ->u.element->typ == ECPGt_struct)
{
/* Array of records. */
ECPGdump_a_record(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, 0, prefix, ind_prefix);
/* Array of structs. */
ECPGdump_a_struct(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, 0, prefix, ind_prefix);
}
else
{
abort();
}
}
else if (typ->typ == ECPGt_record)
else if (typ->typ == ECPGt_struct)
{
ECPGdump_a_record(o, name, ind_name, 0, typ, ind_typ, 0, prefix, ind_prefix);
ECPGdump_a_struct(o, name, ind_name, 0, typ, ind_typ, 0, prefix, ind_prefix);
}
else
{
@ -176,7 +176,7 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in
/* If siz is NULL, then the offset is 0, if not use siz as a
string, it represents the offset needed if we are in an array of records. */
string, it represents the offset needed if we are in an array of structs. */
void
ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
long varcharsize,
@ -189,66 +189,66 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
{
case ECPGt_char:
if (varcharsize == 0) /* pointer */
fprintf(o, "\n\tECPGt_char,%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
fprintf(o, "\n\tECPGt_char,(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
siz == NULL ? "sizeof(char)" : siz);
else
fprintf(o, "\n\tECPGt_char,&%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
fprintf(o, "\n\tECPGt_char,&(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
siz == NULL ? "sizeof(char)" : siz);
break;
case ECPGt_unsigned_char:
if (varcharsize == 0) /* pointer */
fprintf(o, "\n\tECPGt_unsigned_char,%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
fprintf(o, "\n\tECPGt_unsigned_char,(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
siz == NULL ? "sizeof(char)" : siz);
else
fprintf(o, "\n\tECPGt_unsigned_char,&%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
fprintf(o, "\n\tECPGt_unsigned_char,&(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
siz == NULL ? "sizeof(unsigned char)" : siz);
break;
case ECPGt_short:
fprintf(o, "\n\tECPGt_short,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
fprintf(o, "\n\tECPGt_short,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(short)" : siz);
break;
case ECPGt_unsigned_short:
fprintf(o,
"\n\tECPGt_unsigned_short,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
"\n\tECPGt_unsigned_short,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(unsigned short)" : siz);
break;
case ECPGt_int:
fprintf(o, "\n\tECPGt_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
fprintf(o, "\n\tECPGt_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(int)" : siz);
break;
case ECPGt_unsigned_int:
fprintf(o, "\n\tECPGt_unsigned_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
fprintf(o, "\n\tECPGt_unsigned_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(unsigned int)" : siz);
break;
case ECPGt_long:
fprintf(o, "\n\tECPGt_long,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
fprintf(o, "\n\tECPGt_long,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(long)" : siz);
break;
case ECPGt_unsigned_long:
fprintf(o, "\n\tECPGt_unsigned_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
fprintf(o, "\n\tECPGt_unsigned_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(unsigned int)" : siz);
break;
case ECPGt_float:
fprintf(o, "\n\tECPGt_float,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
fprintf(o, "\n\tECPGt_float,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(float)" : siz);
break;
case ECPGt_double:
fprintf(o, "\n\tECPGt_double,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
fprintf(o, "\n\tECPGt_double,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(double)" : siz);
break;
case ECPGt_bool:
fprintf(o, "\n\tECPGt_bool,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
fprintf(o, "\n\tECPGt_bool,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(bool)" : siz);
break;
case ECPGt_varchar:
case ECPGt_varchar2:
if (siz == NULL)
fprintf(o, "\n\tECPGt_varchar,&%s%s,%ldL,%ldL,sizeof(struct varchar_%s), ",
fprintf(o, "\n\tECPGt_varchar,&(%s%s),%ldL,%ldL,sizeof(struct varchar_%s), ",
prefix ? prefix : "", name,
varcharsize,
arrsiz, name);
else
fprintf(o, "\n\tECPGt_varchar,&%s%s,%ldL,%ldL,%s, ",
fprintf(o, "\n\tECPGt_varchar,&(%s%s),%ldL,%ldL,%s, ",
prefix ? prefix : "", name,
varcharsize,
arrsiz, siz);
@ -263,17 +263,17 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
}
/* Penetrate a record and dump the contents. */
/* Penetrate a struct and dump the contents. */
void
ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz, struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offsetarg, const char *prefix, const char *ind_prefix)
ECPGdump_a_struct(FILE *o, const char *name, const char * ind_name, long arrsiz, struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offsetarg, const char *prefix, const char *ind_prefix)
{
/*
* If offset is NULL, then this is the first recursive level. If not
* then we are in a record in a record and the offset is used as
* then we are in a struct in a struct and the offset is used as
* offset.
*/
struct ECPGrecord_member *p, *ind_p = NULL;
struct ECPGstruct_member *p, *ind_p = NULL;
char obuf[BUFSIZ];
char pbuf[BUFSIZ], ind_pbuf[BUFSIZ];
const char *offset;
@ -306,18 +306,19 @@ ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz,
/* Freeing is not really that important. Since we throw away the process
anyway. Lets implement that last! */
void
ECPGfree_record_member(struct ECPGrecord_member * rm)
/* won't work anymore because a list of members may appear in several locations */
/*void
ECPGfree_struct_member(struct ECPGstruct_member * rm)
{
while (rm)
{
struct ECPGrecord_member *p = rm;
struct ECPGstruct_member *p = rm;
rm = rm->next;
free(p->name);
free(p);
}
}
}*/
void
ECPGfree_type(struct ECPGtype * typ)
@ -330,15 +331,17 @@ ECPGfree_type(struct ECPGtype * typ)
free(typ->u.element);
else if (typ->u.element->typ == ECPGt_array)
abort(); /* Array of array, */
else if (typ->u.element->typ == ECPGt_record)
/* Array of records. */
ECPGfree_record_member(typ->u.members);
else if (typ->u.element->typ == ECPGt_struct)
/* Array of structs. */
free(typ->u.members);
/* ECPGfree_struct_member(typ->u.members);*/
else
abort();
}
else if (typ->typ == ECPGt_record)
else if (typ->typ == ECPGt_struct)
{
ECPGfree_record_member(typ->u.members);
free(typ->u.members);
/* ECPGfree_struct_member(typ->u.members);*/
}
else
{

View File

@ -1,11 +1,11 @@
#include <ecpgtype.h>
struct ECPGtype;
struct ECPGrecord_member
struct ECPGstruct_member
{
char *name;
struct ECPGtype *typ;
struct ECPGrecord_member *next;
struct ECPGstruct_member *next;
};
struct ECPGtype
@ -19,20 +19,20 @@ struct ECPGtype
struct ECPGtype *element; /* For an array this is the type
* of the element */
struct ECPGrecord_member *members;
struct ECPGstruct_member *members;
/* A pointer to a list of members. */
} u;
};
/* Everything is malloced. */
struct ECPGrecord_member *ECPGmake_record_member(char *, struct ECPGtype *, struct ECPGrecord_member **);
struct ECPGstruct_member *ECPGmake_struct_member(char *, struct ECPGtype *, struct ECPGstruct_member **);
struct ECPGtype *ECPGmake_simple_type(enum ECPGttype, long);
struct ECPGtype *ECPGmake_varchar_type(enum ECPGttype, long);
struct ECPGtype *ECPGmake_array_type(struct ECPGtype *, long);
struct ECPGtype *ECPGmake_record_type(struct ECPGrecord_member *);
struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *);
/* Frees a type. */
void ECPGfree_record_member(struct ECPGrecord_member *);
void ECPGfree_struct_member(struct ECPGstruct_member *);
void ECPGfree_type(struct ECPGtype *);
/* Dump a type.
@ -43,7 +43,7 @@ void ECPGfree_type(struct ECPGtype *);
reference-to-variable can be a reference to a struct element.
arrsize is the size of the array in case of array fetches. Otherwise 0.
size is the maxsize in case it is a varchar. Otherwise it is the size of
the variable (required to do array fetches of records).
the variable (required to do array fetches of structs).
*/
void ECPGdump_a_type(FILE *, const char *, struct ECPGtype *, const char *, struct ECPGtype *, const char *, const char *);

View File

@ -60,7 +60,7 @@ exec sql end declare section;
while (not_found == 0) {
strcpy(msg, "fetch");
exec sql fetch cur into :personal:ind_personal, :married:ind_married, :personal.birth.born;
exec sql fetch cur into :personal:ind_personal, :married:ind_married;
if (not_found == 0)
printf ("%8.8s was born %d (age = %d) %s%s\n", personal.name.arr, personal.birth.born, personal.birth.age, ind_married ? "" : "and married ", ind_married ? "" : married);
}