1 /*
2     CCCC - C and C++ Code Counter
3     Copyright (C) 1994-2005 Tim Littlefair (tim_littlefair@hotmail.com)
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18 */
19 // cccc_use.cc
20 
21 // implementation of CCCC_UseRelationship class
22 
23 #include "cccc.h"
24 
25 #include "cccc_itm.h"
26 #include "cccc_use.h"
27 #include "cccc_db.h"
28 
29 
CCCC_UseRelationship(CCCC_Item & is)30 CCCC_UseRelationship::CCCC_UseRelationship(CCCC_Item& is)
31 {
32   is.Extract(client);
33   is.Extract(member);
34   is.Extract(supplier);
35   visible=abDONTKNOW;
36   concrete=abDONTKNOW;
37   ut=utDONTKNOW;
38 }
39 
name(int name_level) const40 string CCCC_UseRelationship::name(int name_level) const
41 {
42   string namestr;
43 
44   switch(name_level)
45     {
46     case nlRANK:
47     case nlSIMPLE:
48       namestr.append(client);
49       namestr.append(" uses ");
50       namestr.append(supplier);
51       break;
52 
53     case nlSUPPLIER:
54       namestr=supplier;
55       break;
56 
57     case nlCLIENT:
58       namestr=client;
59       break;
60 
61     default:
62       cerr << "unexpected name level" << endl;
63     }
64 
65   return namestr.c_str();
66 }
67 
add_extent(CCCC_Item & is)68 void CCCC_UseRelationship::add_extent(CCCC_Item& is)
69 {
70   // processing is similar to the CCCC_Record method, except that we update
71   // the visibility and concreteness data members
72   // but do not do merge_flags
73   CCCC_Extent *new_extent=new CCCC_Extent(is);
74   CCCC_Extent *inserted_extent=extent_table.find_or_insert(new_extent);
75 
76   switch(new_extent->get_visibility())
77     {
78     case vPUBLIC:
79     case vPROTECTED:
80       visible=abTRUE;
81       break;
82     case vPRIVATE:
83     case vIMPLEMENTATION:
84       visible=abFALSE;
85       break;
86 
87     default:
88       // nothing required
89       ;;
90     }
91 
92   // a single relationship record represents all connections between two
93   // modules, hence it may have multiple extents which are of different use
94   // types
95   // the use type attached to the relationship record is used only to identify
96   // inheritance relationships
97   UseType new_ut=new_extent->get_usetype();
98   if(new_ut==utINHERITS)
99     {
100       ut=utINHERITS;
101     }
102 
103   switch(new_ut)
104     {
105     case utINHERITS:
106     case utHASBYVAL:
107     case utPARBYVAL:
108     case utVARBYVAL:
109       concrete=abTRUE;
110       break;
111     default:
112       // no change required
113       ;;
114     }
115 
116   if(new_extent != inserted_extent)
117     {
118       delete new_extent;
119     }
120 }
121 
get_count(const char * count_tag)122 int CCCC_UseRelationship::get_count(const char* count_tag)
123 {
124   int retval=0;
125 
126   if( (strncmp(count_tag,"FI",2)==0) || (strncmp(count_tag,"FO",2)==0) )
127     {
128       char suffix=count_tag[2];
129       switch(suffix)
130 	{
131 	case 0:
132 	  retval=1;
133 	  break;
134 
135 	case 'v':
136 	  if(visible!=abFALSE)
137 	    {
138 	      retval=1;
139 	    }
140 	  break;
141 
142 	case 'c':
143 	  if(concrete!=abFALSE)
144 	    {
145 	      retval=1;
146 	    }
147 	  break;
148 
149 	default:
150 	  cerr << "Unexpected count tag suffix" << count_tag << endl;
151 	}
152     }
153   else
154     {
155       cerr << "Unexpected count tag " << count_tag << endl;
156     }
157 
158 
159   return retval;
160 }
161 
162 
163 
supplier_module_ptr(CCCC_Project * prj)164 CCCC_Module* CCCC_UseRelationship::supplier_module_ptr(CCCC_Project *prj)
165 {
166   return prj->module_table.find(supplier.c_str());
167 }
168 
client_module_ptr(CCCC_Project * prj)169 CCCC_Module* CCCC_UseRelationship::client_module_ptr(CCCC_Project *prj)
170 {
171   return prj->module_table.find(client.c_str());
172 }
173 
174 
ToFile(ofstream & ofstr)175 int CCCC_UseRelationship::ToFile(ofstream& ofstr)
176 {
177   int retval=FALSE;
178 
179   CCCC_Item line;
180   line.Insert(USEREL_PREFIX);
181   line.Insert(supplier);
182   line.Insert(client);
183   line.ToFile(ofstr);
184 
185   CCCC_Extent *extent_ptr=extent_table.first_item();
186   while(extent_ptr!=NULL)
187     {
188       CCCC_Item extent_line;
189       extent_line.Insert(USEEXT_PREFIX);
190       extent_line.Insert(supplier);
191       extent_line.Insert(client);
192       extent_ptr->AddToItem(extent_line);
193       extent_line.ToFile(ofstr);
194 
195       extent_ptr=extent_table.next_item();
196     }
197 
198   if(ofstr.good())
199     {
200       retval=TRUE;
201     }
202 
203   return retval;
204 }
205 
FromFile(ifstream & ifstr)206 int CCCC_UseRelationship::FromFile(ifstream& ifstr)
207 {
208   int retval;
209   CCCC_Item next_line;
210   next_line.FromFile(ifstr);
211   ifstr_line++;
212 
213   string line_keyword_dummy;
214 
215   CCCC_UseRelationship *found_uptr=NULL;
216 
217   if(
218      next_line.Extract(line_keyword_dummy) &&
219      next_line.Extract(this->supplier) &&
220      next_line.Extract(this->client)
221      )
222     {
223       found_uptr=
224 	current_loading_project->userel_table.find_or_insert(this);
225       if(found_uptr==this)
226 	{
227 	  // the newly created instance of the module is the first
228 	  // and has taken its place in the database, so we protect
229 	  // it from deletion
230 	  retval=RECORD_ADDED;
231 	}
232       else
233 	{
234 	  retval=RECORD_TRANSCRIBED;
235 	}
236 
237       // process extent records
238       while(PeekAtNextLinePrefix(ifstr,USEEXT_PREFIX))
239 	{
240 	  CCCC_Extent *new_extent=new CCCC_Extent;
241 	  next_line.FromFile(ifstr);
242 	  ifstr_line++;
243 	  string supplier_dummy, client_dummy;
244 
245 	  if(
246 	     next_line.Extract(line_keyword_dummy) &&
247 	     next_line.Extract(supplier_dummy) &&
248 	     next_line.Extract(client_dummy) &&
249 	     new_extent->GetFromItem(next_line)
250 	     )
251 	    {
252 	      // We don't ever expect to find duplicated extent records
253 	      // but just in case...
254 	      CCCC_Extent *found_eptr=
255 		found_uptr->extent_table.find_or_insert(new_extent);
256 	      if(found_eptr!=new_extent)
257 		{
258 		  cerr << "Failed to add extent for relationship "
259 		       << found_uptr->key() << " at line " << ifstr_line
260 		       << endl;
261 		  delete new_extent;
262 		}
263 	    }
264 	}
265 
266     }
267   else // extraction of module intial line failed
268     {
269       // unexpected problem with the input
270       retval=RECORD_ERROR;
271     }
272 
273   // If the import was successful, we will also have imported all dependent
274   // extent records following the main record.
275   // If not, we must skip them.
276   while(PeekAtNextLinePrefix(ifstr,USEEXT_PREFIX))
277     {
278       CCCC_Item next_line;
279       next_line.FromFile(ifstr);
280       ifstr_line++;
281       cerr << "Ignoring userel extent on line " << ifstr_line << endl;
282     }
283 
284   return retval;
285 }
286 
287 
288 
289 
290