ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/io/parse_tree.c
Revision: 2187
Committed: Wed Apr 13 18:41:17 2005 UTC (19 years, 2 months ago) by tim
Content type: text/plain
File size: 13505 byte(s)
Log Message:
more memory leak are fixed

File Contents

# Content
1 /*
2 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3 *
4 * The University of Notre Dame grants you ("Licensee") a
5 * non-exclusive, royalty free, license to use, modify and
6 * redistribute this software in source and binary code form, provided
7 * that the following conditions are met:
8 *
9 * 1. Acknowledgement of the program authors must be made in any
10 * publication of scientific results based in part on use of the
11 * program. An acceptable form of acknowledgement is citation of
12 * the article in which the program was described (Matthew
13 * A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14 * J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15 * Parallel Simulation Engine for Molecular Dynamics,"
16 * J. Comput. Chem. 26, pp. 252-271 (2005))
17 *
18 * 2. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * 3. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the
24 * distribution.
25 *
26 * This software is provided "AS IS," without a warranty of any
27 * kind. All express or implied conditions, representations and
28 * warranties, including any implied warranty of merchantability,
29 * fitness for a particular purpose or non-infringement, are hereby
30 * excluded. The University of Notre Dame and its licensors shall not
31 * be liable for any damages suffered by licensee as a result of
32 * using, modifying or distributing the software or its
33 * derivatives. In no event will the University of Notre Dame or its
34 * licensors be liable for any lost revenue, profit or data, or for
35 * direct, indirect, special, consequential, incidental or punitive
36 * damages, however caused and regardless of the theory of liability,
37 * arising out of the use of or inability to use software, even if the
38 * University of Notre Dame has been advised of the possibility of
39 * such damages.
40 */
41
42 #include <stdlib.h>
43 #include <stdio.h>
44
45 #include "io/parse_tree.h"
46 #include "utils/simError.h"
47
48 #ifdef IS_MPI
49 #define __is_lex__
50 #include "io/mpiBASS.h"
51 #endif
52
53 void walk_down( struct node_tag* the_node, struct namespc the_namespc );
54 int mol_index; // keeps track of the number of molecules
55 int comp_index; // keeps track of the number of components.
56
57 /*
58 * This is the parse tree function that is called by the yacc
59 * routine. It passes the global node and namespace to the recursive
60 * walk_down routine to explore the node tree.
61 */
62
63 void pt_me( struct node_tag* head_node ){
64
65 struct namespc global_namespc;
66
67 if( head_node->type != GLOBAL_HEAD ){
68 sprintf( painCave.errMsg,
69 "Parse tree error: The head node was not the global node.\n" );
70 painCave.isFatal = 1;
71 simError();
72 #ifdef IS_MPI
73 mpiInterfaceExit();
74 #endif //is_mpi
75 }
76
77 global_namespc.index = 0;
78 global_namespc.type = GLOBAL_HEAD;
79
80 mol_index = 0;
81 comp_index = 0;
82 walk_down( head_node->next_stmt, global_namespc );
83 // closed global namespace and exit
84
85 }
86
87 /*
88 * This is the main logic workhorse routine for the node tree
89 * parser. It recursively walks down the node list and calls the
90 * appropriate interface functions acording to the node types. It will
91 * also set the appropriate namespace for the nodes.
92 *
93 * Note: the nodes only know about the namespace of their
94 * current level, the namespace above themselves is hidden.
95 */
96
97 void walk_down( struct node_tag* the_node, struct namespc the_namespc ){
98
99 struct namespc current_namespc;
100
101 if( the_node != NULL ){
102
103 if( the_node->type == GLOBAL_HEAD ){
104 print_tree_error( the_node, "Too many global regions" );
105 }
106
107 if( the_node->stmt_list != NULL ){
108
109 // the statement is a block node of some sort
110
111 switch( the_node->type ){
112
113 case COMPONENT_HEAD:
114 if( the_namespc.type != GLOBAL_HEAD ){
115 print_tree_error( the_node,
116 "component block is not in the global namespace" );
117 }
118 else{
119 init_component( comp_index );
120 current_namespc.index = comp_index;
121 current_namespc.type = COMPONENT_HEAD;
122 walk_down( the_node->stmt_list, current_namespc );
123 comp_index++;
124 }
125 break;
126
127 case MOLECULE_HEAD:
128 if( the_namespc.type != GLOBAL_HEAD ){
129 print_tree_error( the_node,
130 "Molecule block is not in the global namespace" );
131 }
132 else{
133 init_molecule( mol_index );
134 current_namespc.index = mol_index;
135 current_namespc.type = MOLECULE_HEAD;
136 walk_down( the_node->stmt_list, current_namespc );
137 mol_index++;
138 }
139 break;
140
141 case ATOM_HEAD:
142 if( the_namespc.type != MOLECULE_HEAD ){
143 print_tree_error( the_node,
144 "The atom block is not in a molecule namespace" );
145 }
146 else{
147 init_atom( the_node->index );
148 current_namespc.index = the_node->index;
149 current_namespc.type = the_node->type;
150 walk_down( the_node->stmt_list, current_namespc );
151 }
152 break;
153
154 case RIGIDBODY_HEAD:
155 if( the_namespc.type != MOLECULE_HEAD ){
156 print_tree_error( the_node,
157 "The RigidBody block is not in a Molecule namespace" );
158 }
159 else{
160 init_rigidbody( the_node->index );
161 current_namespc.index = the_node->index;
162 current_namespc.type = the_node->type;
163 walk_down( the_node->stmt_list, current_namespc );
164 }
165 break;
166
167 case CUTOFFGROUP_HEAD:
168 if( the_namespc.type != MOLECULE_HEAD ){
169 print_tree_error( the_node,
170 "The CutoffGroup block is not in a Molecule namespace" );
171 }
172 else{
173 init_cutoffgroup( the_node->index );
174 current_namespc.index = the_node->index;
175 current_namespc.type = the_node->type;
176 walk_down( the_node->stmt_list, current_namespc );
177 }
178 break;
179
180 case BOND_HEAD:
181 if( the_namespc.type != MOLECULE_HEAD ){
182 print_tree_error( the_node,
183 "The bond block is not in a molecule namespace" );
184 }
185 else{
186 init_bond( the_node->index );
187 current_namespc.index = the_node->index;
188 current_namespc.type = the_node->type;
189 walk_down( the_node->stmt_list, current_namespc );
190 }
191 break;
192
193 case BEND_HEAD:
194 if( the_namespc.type != MOLECULE_HEAD ){
195 print_tree_error( the_node,
196 "The bend block is not in a molecule namespace" );
197 }
198 else{
199 init_bend( the_node->index );
200 current_namespc.index = the_node->index;
201 current_namespc.type = the_node->type;
202 walk_down( the_node->stmt_list, current_namespc );
203 }
204 break;
205
206 case TORSION_HEAD:
207 if( the_namespc.type != MOLECULE_HEAD ){
208 print_tree_error( the_node,
209 "The torsion block is not in "
210 "a molecule namespace" );
211 }
212 else{
213 init_torsion( the_node->index );
214 current_namespc.index = the_node->index;
215 current_namespc.type = the_node->type;
216 walk_down( the_node->stmt_list, current_namespc );
217 }
218 break;
219
220 case ZCONSTRAINT_HEAD:
221 if( the_namespc.type != GLOBAL_HEAD ){
222 print_tree_error( the_node,
223 "The Zconstraint block is not in "
224 "the global namespace" );
225 }
226 else{
227 init_zconstraint( the_node->index );
228 current_namespc.index = the_node->index;
229 current_namespc.type = the_node->type;
230 walk_down( the_node->stmt_list, current_namespc );
231 }
232 break;
233
234 default:
235 print_tree_error( the_node, "Not a valid code block" );
236 }
237 }
238
239 else{
240
241 // the node is a statement
242
243 switch( the_node->type ){
244
245 case MEMBERS_STMT:
246 switch( the_namespc.type ){
247 case BOND_HEAD: // fall through
248 case BEND_HEAD: // fall through
249 case TORSION_HEAD:
250 case RIGIDBODY_HEAD:
251 case CUTOFFGROUP_HEAD: // same for the first four
252 init_members( the_node, the_namespc );
253 break;
254
255 default:
256 print_tree_error( the_node,
257 "Members statement not in a bond, bend, "
258 "torsion, RigidBody, or CutoffGroup" );
259 break;
260 }
261 break;
262
263 case CONSTRAINT_STMT:
264 switch( the_namespc.type ){
265 case BOND_HEAD: // fall through
266 case BEND_HEAD: // fall through
267 case TORSION_HEAD: // same for the first three
268 init_constraint( the_node, the_namespc );
269 break;
270
271 default:
272 print_tree_error( the_node,
273 "Constraint statement not in a bond, bend, "
274 "or torsion" );
275 break;
276 }
277 break;
278
279 case ASSIGNMENT_STMT:
280 init_assignment( the_node, the_namespc );
281 break;
282
283 case POSITION_STMT:
284 if( the_namespc.type != ATOM_HEAD ){
285 print_tree_error( the_node,
286 "position statement is not located in an "
287 "atom block" );
288 }
289
290 init_position( the_node, the_namespc );
291 break;
292
293 case ORIENTATION_STMT:
294 if( the_namespc.type != ATOM_HEAD ){
295 print_tree_error( the_node,
296 "orientation statement is not located in an "
297 "atom block" );
298 }
299
300 init_orientation( the_node, the_namespc );
301 break;
302
303 default:
304 print_tree_error( the_node, "unrecognized statement" );
305 break;
306 }
307 }
308
309 // recurse down to the next node
310
311 walk_down( the_node->next_stmt, the_namespc );
312 }
313
314 // send an end of block signal
315 else end_of_block();
316
317 // we're done
318 }
319
320
321
322 /*
323 * This is a routine utilized by the node parsers to make printing
324 * error messages easy.
325 */
326
327 void print_tree_error( struct node_tag* err_node, char* err_msg ){
328
329 switch( err_node->type ){
330
331 case GLOBAL_HEAD:
332 sprintf( painCave.errMsg,
333 "Parse tree error: global head node error -> %s\n",
334 err_msg );
335 break;
336
337 case COMPONENT_HEAD:
338 sprintf( painCave.errMsg,
339 "Parse tree error: component head node error -> %s\n",
340 err_msg );
341 break;
342
343 case MOLECULE_HEAD:
344 sprintf( painCave.errMsg,
345 "Parse tree error: molecule head node error -> %s\n",
346 err_msg );
347 break;
348
349 case RIGIDBODY_HEAD:
350 sprintf( painCave.errMsg,
351 "Parse tree error: rigidBody head node error -> %s\n",
352 err_msg );
353 break;
354
355 case CUTOFFGROUP_HEAD:
356 sprintf( painCave.errMsg,
357 "Parse tree error: CutoffGroup head node error -> %s\n",
358 err_msg );
359 break;
360
361 case ATOM_HEAD:
362 sprintf( painCave.errMsg,
363 "Parse tree error: atom head node error [%d] -> %s\n",
364 err_node->index,
365 err_msg );
366 break;
367
368 case BOND_HEAD:
369 sprintf( painCave.errMsg,
370 "Parse tree error: bond head node error [%d] -> %s\n",
371 err_node->index,
372 err_msg );
373 break;
374
375 case BEND_HEAD:
376 sprintf( painCave.errMsg,
377 "Parse tree error: bend head node error [%d] -> %s\n",
378 err_node->index,
379 err_msg );
380 break;
381
382 case ZCONSTRAINT_HEAD:
383 sprintf( painCave.errMsg,
384 "Parse tree error: Zconstraint head node error [%d] -> %s\n",
385 err_node->index,
386 err_msg );
387 break;
388
389 case MEMBERS_STMT:
390 sprintf( painCave.errMsg,
391 "Parse tree error: members node error (nMembers = %d)\n"
392 " -> %s\n",
393 err_node->the_data.mbrs.nMembers,
394 err_msg );
395 break;
396
397 case CONSTRAINT_STMT:
398 sprintf( painCave.errMsg,
399 "Parse tree error: constraint node error => ( %lf )\n"
400 " -> %s\n",
401 err_node->the_data.cnstr.constraint_val,
402 err_msg );
403 break;
404
405 case ASSIGNMENT_STMT:
406 sprintf( painCave.errMsg,
407 "Parse tree error: assignment node error\n"
408 " => %s = ",
409 err_node->the_data.asmt.identifier );
410
411 switch( err_node->the_data.asmt.type ){
412
413 case STR_ASSN:
414 sprintf( painCave.errMsg,
415 "%s",
416 err_node->the_data.asmt.rhs.str_ptr );
417 break;
418
419 case INT_ASSN:
420 sprintf( painCave.errMsg,
421 "%d",
422 err_node->the_data.asmt.rhs.i_val );
423 break;
424
425 case DOUBLE_ASSN:
426 sprintf( painCave.errMsg,
427 "%lf",
428 err_node->the_data.asmt.rhs.d_val );
429 break;
430 }
431
432 sprintf( painCave.errMsg,
433 "\n"
434 " -> %s\n",
435 err_msg );
436 break;
437
438 case POSITION_STMT:
439 sprintf( painCave.errMsg,
440 "Parse tree error: position node error => ( %lf, %lf, %lf )\n"
441 " -> %s\n",
442 err_node->the_data.pos.x,
443 err_node->the_data.pos.y,
444 err_node->the_data.pos.z,
445 err_msg );
446 break;
447
448 case ORIENTATION_STMT:
449 sprintf( painCave.errMsg,
450 "Parse tree error: orientation node error => ( %lf, %lf, %lf )\n"
451 " -> %s\n",
452 err_node->the_data.ort.phi,
453 err_node->the_data.ort.theta,
454 err_node->the_data.ort.psi,
455 err_msg );
456 break;
457
458 default:
459 sprintf( painCave.errMsg,
460 "Parse tree error: unknown node type -> %s\n",
461 err_msg );
462 }
463
464 painCave.isFatal = 1;
465 simError();
466 #ifdef IS_MPI
467 mpiInterfaceExit();
468 #endif //is_mpi
469
470 }
471
472
473 /*
474 * recursive walkdown and kill of the node tree
475 * note: looks mighty similar to the walkdown routine.
476 */
477
478 void kill_tree( struct node_tag* the_node ){
479
480
481 if( the_node != NULL ){
482
483 if( the_node->stmt_list != NULL ){
484
485 // the statement is a block node of some sort
486
487 kill_tree( the_node->stmt_list );
488 }
489
490 else{
491
492 // the node is a statement
493
494 switch( the_node->type ){
495
496 case ASSIGNMENT_STMT:
497
498 if( the_node->the_data.asmt.type == STR_ASSN )
499 free( the_node->the_data.asmt.rhs.str_ptr );
500
501 free( the_node->the_data.asmt.identifier );
502 break;
503
504 case MEMBERS_STMT:
505
506 if (the_node->the_data.mbrs.nMembers >0 ){
507 free(the_node->the_data.mbrs.memberList);
508 }
509 break;
510
511 default:
512 // nothing to do here, everyone else can be freed normally.
513 break;
514 }
515 }
516
517 // recurse down to the next node
518
519 kill_tree( the_node->next_stmt );
520 free( the_node );
521 }
522
523 // we're done
524 }