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

# User Rev Content
1 gezelter 1930 /*
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 gezelter 1490 #include <stdlib.h>
43     #include <stdio.h>
44    
45 tim 1492 #include "io/parse_tree.h"
46     #include "utils/simError.h"
47 gezelter 1490
48     #ifdef IS_MPI
49     #define __is_lex__
50 tim 1492 #include "io/mpiBASS.h"
51 gezelter 1490 #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 tim 2187 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 gezelter 1490 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     }