Commit d95ff0b9 authored by rdubner's avatar rdubner

Significantly improved the logic and accuracy of the cross referencing

parent 4493aade
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
using namespace std; using namespace std;
#define DUMPING //#define DUMPING
void void
scan_test(const string &filename) scan_test(const string &filename)
...@@ -291,12 +291,6 @@ main(int argc, char *argv[]) ...@@ -291,12 +291,6 @@ main(int argc, char *argv[])
COB_DATA cob_data; COB_DATA cob_data;
COB_FIELD_ATTRIBUTES cob_field_attributes; COB_FIELD_ATTRIBUTES cob_field_attributes;
COB_FIELDS cob_fields; COB_FIELDS cob_fields;
DATA_DESCRIPTIONS data_description;
string source = params.basename;
const string GLOBAL = "GLOBAL";
const string LOCAL = "LOCAL";
const string MAIN = "MAIN";
// We embark on a multi-step process, where we scan a number of // We embark on a multi-step process, where we scan a number of
// different files separately. This is a bit like putting a jigsaw // different files separately. This is a bit like putting a jigsaw
...@@ -311,7 +305,7 @@ main(int argc, char *argv[]) ...@@ -311,7 +305,7 @@ main(int argc, char *argv[])
variable_tree.ReadFromFile(params.cbl_lst); variable_tree.ReadFromFile(params.cbl_lst);
variable_tree.BuildCanonicalName(); variable_tree.BuildCanonicalName();
#if defined(DUMPING) #if defined(DUMPING)
//variable_tree.Dump(); // variable_tree.Dump();
#endif #endif
// Scan the .h files for working storage and local storage locations // Scan the .h files for working storage and local storage locations
...@@ -322,7 +316,6 @@ main(int argc, char *argv[]) ...@@ -322,7 +316,6 @@ main(int argc, char *argv[])
cob_field_attributes, cob_field_attributes,
cob_fields cob_fields
); );
// Scan the .c file for program identification and linkage information. // Scan the .c file for program identification and linkage information.
ScanForLinkage(params.c_file, ScanForLinkage(params.c_file,
params.c_filename.GetFname(), params.c_filename.GetFname(),
...@@ -330,6 +323,11 @@ main(int argc, char *argv[]) ...@@ -330,6 +323,11 @@ main(int argc, char *argv[])
cob_data, cob_data,
cob_fields cob_fields
); );
// The f_/b_ cross reference is as complete as we know how to make it.
// Scan cob_fields, updating the parent variables and building the lookup map
cob_fields.FixLookup(cob_data);
#if defined(DUMPING) #if defined(DUMPING)
cout << endl; cout << endl;
//program_labels.Dump(); //program_labels.Dump();
...@@ -339,12 +337,6 @@ main(int argc, char *argv[]) ...@@ -339,12 +337,6 @@ main(int argc, char *argv[])
cob_fields.Dump(); cob_fields.Dump();
#endif #endif
// We now have a nice complete list of COB_DATA, COB_FIELD_ATTRIBUTES, COB_FIELDS // We now have a nice complete list of COB_DATA, COB_FIELD_ATTRIBUTES, COB_FIELDS
// Flatten them down into the composite table:
data_description.Flatten(cob_fields,cob_field_attributes,cob_pic_symbols,cob_data);
#if defined(DUMPING)
data_description.Dump();
#endif
// The most complete description of the COBOL variable identifiers is // The most complete description of the COBOL variable identifiers is
// found in variable_tree. But as of right now, it knows nothing about // found in variable_tree. But as of right now, it knows nothing about
...@@ -354,7 +346,7 @@ main(int argc, char *argv[]) ...@@ -354,7 +346,7 @@ main(int argc, char *argv[])
// The Consolidate() routine puts them together. // The Consolidate() routine puts them together.
variable_tree.Consolidate(data_description,cob_data); variable_tree.Consolidate(cob_fields);
#if defined(DUMPING) #if defined(DUMPING)
variable_tree.Dump(); variable_tree.Dump();
variable_tree.DumpFlatList(); variable_tree.DumpFlatList();
......
...@@ -309,25 +309,25 @@ ProcessDataStorage(ifstream &ifs, ...@@ -309,25 +309,25 @@ ProcessDataStorage(ifstream &ifs,
} }
} }
// Skip to the name_of_data // Skip to the name_of_data
string name_of_data; string b_name;
if( nfound < input.length() ) { if( nfound < input.length() ) {
// Pick up the b // Pick up the b
name_of_data += input[nfound++]; b_name += input[nfound++];
} }
if( nfound < input.length() ) { if( nfound < input.length() ) {
// Pick up the _ // Pick up the _
name_of_data += input[nfound++]; b_name += input[nfound++];
} }
while( nfound < input.length() ) { while( nfound < input.length() ) {
char ch = input[nfound++]; char ch = input[nfound++];
if( !isdigit(ch) ) { if( !isdigit(ch) ) {
break; break;
} }
name_of_data += ch; b_name += ch;
} }
if(name_of_data EQ "NU") { if(b_name EQ "NU") {
name_of_data = ""; b_name = "";
} }
// Skip past the ampersand: // Skip past the ampersand:
...@@ -339,21 +339,21 @@ ProcessDataStorage(ifstream &ifs, ...@@ -339,21 +339,21 @@ ProcessDataStorage(ifstream &ifs,
} }
// Pick up the pointer to the attribute // Pick up the pointer to the attribute
string name_of_attr; string a_name;
if( nfound < input.length() ) { if( nfound < input.length() ) {
// Pick up the a // Pick up the a
name_of_attr += input[nfound++]; a_name += input[nfound++];
} }
if( nfound < input.length() ) { if( nfound < input.length() ) {
// Pick up the _ // Pick up the _
name_of_attr += input[nfound++]; a_name += input[nfound++];
} }
while( nfound < input.length() ) { while( nfound < input.length() ) {
char ch = input[nfound++]; char ch = input[nfound++];
if( !isdigit(ch) ) { if( !isdigit(ch) ) {
break; break;
} }
name_of_attr += ch; a_name += ch;
} }
// See if there is an offset: // See if there is an offset:
...@@ -380,18 +380,25 @@ ProcessDataStorage(ifstream &ifs, ...@@ -380,18 +380,25 @@ ProcessDataStorage(ifstream &ifs,
// variables lined up with the .cbl.lst variable list. // variables lined up with the .cbl.lst variable list.
map<string,string>::const_iterator it = map<string,string>::const_iterator it =
b_symbol_to_program_id.find(name_of_data); b_symbol_to_program_id.find(b_name);
if(it != b_symbol_to_program_id.end()) { if(it != b_symbol_to_program_id.end()) {
mapped_program_id = it->second; mapped_program_id = it->second;
} }
string parent;
const COB_DATUM *pdatum = cob_data.GetCobDatum(b_name);
if( pdatum ) {
parent = pdatum->cbl_name;
}
cob_fields.Insert(f_name, cob_fields.Insert(f_name,
name_of_data, b_name,
offset, offset,
size, size,
name_of_attr, a_name,
mapped_program_id, mapped_program_id,
cbl_name); parent,
cbl_name); // And this the child
continue; continue;
} }
...@@ -674,7 +681,7 @@ ScanForLinkage(ifstream &ifs, ...@@ -674,7 +681,7 @@ ScanForLinkage(ifstream &ifs,
nfound = param2.find(" + ",nfound+3); nfound = param2.find(" + ",nfound+3);
} }
} }
cob_fields.Modify(f_symbol,"NULL",offset); cob_fields.Modify(f_symbol,"",offset);
} }
// Go see if there are more on this line // Go see if there are more on this line
...@@ -684,42 +691,6 @@ ScanForLinkage(ifstream &ifs, ...@@ -684,42 +691,6 @@ ScanForLinkage(ifstream &ifs,
return; return;
} }
void
DATA_DESCRIPTIONS::Flatten(const COB_FIELDS &cob_fields,
const COB_FIELD_ATTRIBUTES &cob_field_attributes,
const COB_PIC_SYMBOLS &cob_pic_symbols,
const COB_DATA &cob_data
)
{
// Run through the f_ fields first
for(V_COB_FIELDS::const_iterator it=cob_fields.v_cob_fields.begin();
it != cob_fields.v_cob_fields.end();
it++
) {
COB_FIELD field = *it;
DATA_DESCRIPTION ds;
ds.f_name = field.f_name ;
ds.size = field.size ;
ds.b_name = field.b_name;
ds.offset = field.offset ;
ds.program_id = field.program_id ;
ds.cobol_symbol = field.cbl_name ;
const COB_DATUM *cd = cob_data.GetCobDatum(ds.b_name);
if( cd ) {
ds.size = cd->size;
ds.storage_type = cd->storage_type;
}
if( ds.storage_type.empty() AND ds.b_name.empty() ) {
ds.storage_type = "Local";
}
DsInsert(ds);
}
}
void void
COB_PROGRAM_LABELS::FormatProgramInfo(stringstream &ss) const COB_PROGRAM_LABELS::FormatProgramInfo(stringstream &ss) const
{ {
...@@ -769,34 +740,3 @@ COB_PROGRAM_LABELS::FormatProgramInfo(stringstream &ss) const ...@@ -769,34 +740,3 @@ COB_PROGRAM_LABELS::FormatProgramInfo(stringstream &ss) const
} }
} }
} }
void
DATA_DESCRIPTIONS::Dump() const
{
cout << "DATA_DESCRIPTION:" << endl ;
cout << setw(20) << "program_id" ;
cout << setw(20) << "cobol_symbol" ;
cout << setw(13) << "storage_type" ;
cout << setw( 9) << "b_name" ;
cout << setw( 7) << "offset" ;
cout << setw( 6) << "size" ;
cout << setw( 9) << "f_symbol" ;
cout << setw(16) << "picture" ;
cout << endl;
for(VDATA_DESCRIPTION::const_iterator it=symbols.begin();
it!=symbols.end();
it++ ) {
DATA_DESCRIPTION symbol = *it;
cout << setw(20) << symbol.program_id ;
cout << setw(20) << symbol.cobol_symbol ;
cout << setw(13) << symbol.storage_type ;
cout << setw( 9) << symbol.b_name ;
cout << setw( 7) << symbol.offset ;
cout << setw( 6) << symbol.size ;
cout << setw( 9) << symbol.f_name ;
cout << setw(16) << symbol.picture_string ;
cout << endl;
}
cout << endl;
}
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#define nullptr NULL #define nullptr NULL
#endif #endif
#define NO_INDEX ((size_t)(-1))
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// These data structures are based on from GnuCOBOL3.1-dev/libcob/common.h // These data structures are based on from GnuCOBOL3.1-dev/libcob/common.h
...@@ -379,8 +380,9 @@ public: ...@@ -379,8 +380,9 @@ public:
int offset; /* any internal + offset */ int offset; /* any internal + offset */
int size; /* Field size */ int size; /* Field size */
std::string a_name; /* name of attribute */ std::string a_name; /* name of attribute */
std::string program_id; /* Where defined */ std::string program_id;
std::string cbl_name; /* From the comment in the .h code */ std::string parent;
std::string child; /* child of B of C of parent of program_id */
public: public:
COB_FIELD(std::string f_name_, COB_FIELD(std::string f_name_,
...@@ -389,7 +391,8 @@ public: ...@@ -389,7 +391,8 @@ public:
int size_, int size_,
std::string a_name_, std::string a_name_,
std::string program_id_, std::string program_id_,
std::string cbl_name_) std::string parent_,
std::string child_)
{ {
f_name = f_name_ ; f_name = f_name_ ;
b_name = b_name_ ; b_name = b_name_ ;
...@@ -397,7 +400,8 @@ public: ...@@ -397,7 +400,8 @@ public:
size = size_ ; size = size_ ;
a_name = a_name_ ; a_name = a_name_ ;
program_id = program_id_; program_id = program_id_;
cbl_name = cbl_name_ ; parent = parent_ ;
child = child_ ;
} }
friend COB_FIELDS; friend COB_FIELDS;
...@@ -409,10 +413,32 @@ class COB_FIELDS ...@@ -409,10 +413,32 @@ class COB_FIELDS
{ {
private: private:
M_COB_FIELDS m_cob_fields; M_COB_FIELDS m_cob_fields;
M_COB_FIELDS m_from_cobol;
public: public:
V_COB_FIELDS v_cob_fields; V_COB_FIELDS v_cob_fields;
private:
std::string
MakeKey(const std::string &prog,
const std::string &parent,
const std::string &child,
int offset
) const
{
char ach[32];
sprintf(ach,"%d",offset);
std::string retval;
retval += prog;
retval += "|";
retval += parent;
retval += "|";
retval += child;
retval += "|";
retval += ach;
return retval;
}
public: public:
void void
Insert(std::string f_name, Insert(std::string f_name,
...@@ -421,7 +447,8 @@ public: ...@@ -421,7 +447,8 @@ public:
int size, int size,
std::string a_name, std::string a_name,
std::string program_id, std::string program_id,
std::string cbl_name) std::string parent,
std::string child)
{ {
M_COB_FIELDS::const_iterator it = m_cob_fields.find(f_name); M_COB_FIELDS::const_iterator it = m_cob_fields.find(f_name);
if( it != m_cob_fields.end() ) { if( it != m_cob_fields.end() ) {
...@@ -434,11 +461,30 @@ public: ...@@ -434,11 +461,30 @@ public:
size, size,
a_name, a_name,
program_id, program_id,
cbl_name); parent,
child);
m_cob_fields[f_name] = v_cob_fields.size(); m_cob_fields[f_name] = v_cob_fields.size();
v_cob_fields.push_back(cf); v_cob_fields.push_back(cf);
} }
size_t
FetchByNameAndOffset(const std::string &program_id_,
const std::string &parent_,
const std::string &child_,
int offset
) const
{
size_t retval = NO_INDEX;
std::string key = MakeKey(program_id_,parent_,child_,offset);
M_COB_FIELDS::const_iterator it = m_from_cobol.find(key);
if( it != m_from_cobol.end() ) {
retval = it->second;
}
return retval;
}
void void
Modify(std::string f_name_, Modify(std::string f_name_,
std::string b_name_, std::string b_name_,
...@@ -454,6 +500,27 @@ public: ...@@ -454,6 +500,27 @@ public:
v_cob_fields[i].offset = offset_; v_cob_fields[i].offset = offset_;
} }
void
FixLookup(const COB_DATA &cob_data)
{
for( size_t i=0; i< v_cob_fields.size(); i++ ) {
if( !v_cob_fields[i].b_name.empty() && v_cob_fields[i].parent.empty() ) {
// The parent is empty, and b_name is not. It's possible that the linkage
// scan of the .c code populated the parent field. If so, we might be able
// to populate the parent field now:
const COB_DATUM *pdatum = cob_data.GetCobDatum(v_cob_fields[i].b_name);
if( pdatum ) {
v_cob_fields[i].parent = pdatum->cbl_name;
}
}
m_from_cobol[MakeKey(v_cob_fields[i].program_id,
v_cob_fields[i].parent,
v_cob_fields[i].child,
v_cob_fields[i].offset)] = i;
}
}
void void
Dump() const Dump() const
{ {
...@@ -464,7 +531,8 @@ public: ...@@ -464,7 +531,8 @@ public:
std::cout << std::setw(20) << "size"; std::cout << std::setw(20) << "size";
std::cout << std::setw(20) << "a_name"; std::cout << std::setw(20) << "a_name";
std::cout << std::setw(20) << "program_id"; std::cout << std::setw(20) << "program_id";
std::cout << std::setw(20) << "cbl_name"; std::cout << std::setw(20) << "parent";
std::cout << std::setw(20) << "child";
std::cout << std::endl; std::cout << std::endl;
for( V_COB_FIELDS::const_iterator it = v_cob_fields.begin(); for( V_COB_FIELDS::const_iterator it = v_cob_fields.begin();
...@@ -477,7 +545,8 @@ public: ...@@ -477,7 +545,8 @@ public:
std::cout << std::setw(20) << field.size; std::cout << std::setw(20) << field.size;
std::cout << std::setw(20) << field.a_name; std::cout << std::setw(20) << field.a_name;
std::cout << std::setw(20) << field.program_id; std::cout << std::setw(20) << field.program_id;
std::cout << std::setw(20) << field.cbl_name; std::cout << std::setw(20) << field.parent;
std::cout << std::setw(20) << field.child;
std::cout << std::endl; std::cout << std::endl;
} }
std::cout << std::endl; std::cout << std::endl;
...@@ -586,109 +655,6 @@ public: ...@@ -586,109 +655,6 @@ public:
} }
}; };
class DATA_DESCRIPTIONS;
class DATA_DESCRIPTION
{
public:
std::string program_id;
std::string cobol_symbol;
std::string storage_type;
std::string b_name;
int offset;
int size;
std::string f_name;
std::string picture_string;
public:
DATA_DESCRIPTION()
{
offset = 0;
size = 0;
}
friend DATA_DESCRIPTIONS;
};
typedef std::vector<DATA_DESCRIPTION> VDATA_DESCRIPTION;
typedef std::map<std::string,size_t> M_VKEY;
class DATA_DESCRIPTIONS
{
private:
VDATA_DESCRIPTION symbols;
// We are going to key that table by (program-id, cbl_symbol,offset)
M_VKEY symbols_key;
std::map<std::string,size_t>location_of_c_symbol;
public:
int
size() const
{
return static_cast<int>(symbols.size());
}
const DATA_DESCRIPTION &
operator[](size_t n) const
{
return symbols[n];
}
int
IndexOfSymbol(const std::string &symbol) const
{
std::map<std::string,size_t>::const_iterator it =
location_of_c_symbol.find(symbol);
if(it == location_of_c_symbol.end()) {
return -1;
}
return static_cast<int>(it->second);
}
std::string
MakeVKey(std::string const &program_id, std::string const &c_symbol,int offset) const
{
char ach[20];
sprintf(ach,"%d",offset);
return program_id + "|" + c_symbol + "|" + ach;
}
void
DsInsert(const DATA_DESCRIPTION &ds )
{
symbols_key[MakeVKey(ds.program_id,ds.cobol_symbol,ds.offset)] = symbols.size();
symbols.push_back(ds);
}
bool
IsInDs(std::string const &program_id, std::string const &cobol_symbol,int offset) const
{
std::string dskey=MakeVKey(program_id,cobol_symbol,offset);
M_VKEY::const_iterator it = symbols_key.find(dskey);
return it != symbols_key.end();
}
size_t
GetIndex(std::string const &program_id, std::string const &c_symbol,int offset) const
{
size_t retval = (size_t)(-1);
std::string dskey=MakeVKey(program_id,c_symbol,offset);
M_VKEY::const_iterator it = symbols_key.find(dskey);
if(it != symbols_key.end()) {
retval = it->second;
}
return retval;
}
void Dump() const;
void Flatten(const COB_FIELDS &cob_fields,
const COB_FIELD_ATTRIBUTES &cob_field_attributes,
const COB_PIC_SYMBOLS &cob_pic_symbols,
const COB_DATA &cob_data
);
};
void ScanAllDotHFiles(const std::string &path, void ScanAllDotHFiles(const std::string &path,
const std::string &fname, const std::string &fname,
COB_PIC_SYMBOLS &cob_pic_symbols, COB_PIC_SYMBOLS &cob_pic_symbols,
......
This diff is collapsed.
...@@ -103,15 +103,16 @@ private: ...@@ -103,15 +103,16 @@ private:
int size; // Size in bytes int size; // Size in bytes
std::string type; // GROUP, NUMERIC, ALPHABETIC std::string type; // GROUP, NUMERIC, ALPHABETIC
int level; // COBOL identifier level int level; // COBOL identifier level
// DATA section is level 00 // // DATA section is level 00
// The PROGRAM-ID is level -1 // // The PROGRAM-ID is level -1
// The ROOT is level -2 // // The ROOT is level -2
std::string name; // COBOL identifier std::string name; // COBOL identifier
std::string picture; // Reported PICTURE string std::string picture; // Reported PICTURE string
std::string usage; // Reported USAGE string std::string usage; // Reported USAGE string
std::string redefines; // Identifier this one REDEFINES
int occurs; // Non-zero means this is a table int occurs; // Non-zero means this is a table
std::string redefines; // Identifier this one REDEFINES
bool is_external; // Flagged as EXTERNAL bool is_external; // Flagged as EXTERNAL
bool is_global; // Flagged as global
// Here we keep track of the tree // Here we keep track of the tree
VAR_NODE *parent; VAR_NODE *parent;
...@@ -119,28 +120,11 @@ private: ...@@ -119,28 +120,11 @@ private:
VVAR_NODES renamed_by; // When somebody cites us as an 66/RENAMES, VVAR_NODES renamed_by; // When somebody cites us as an 66/RENAMES,
// // we save them here so we can update // // we save them here so we can update
// // them later // // them later
std::string canonical_name; // The full COBOL A in B in C identifier std::string canonical_name; // The full COBOL A in B in C identifier
std::string base_symbol; // The b_ base for this variable int offset; // The total offset to this identifier, as
int offset; // The total offset to this identifier // // calculated from the sizes.
std::string b_name; // b_name is imputed from the f_name