source: ThirdParty/mpqc_open/src/lib/util/keyval/ipv2_read.cc

Candidate_v1.6.1
Last change on this file was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 13.2 KB
Line 
1//
2// ipv2_read.cc
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Curtis Janssen <cljanss@limitpt.com>
7// Maintainer: LPS
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28/* This file provides the routines to do the initial parse of the input
29 * file. */
30
31#include <util/misc/string.h>
32#ifdef DEC
33#include <math.h>
34#else
35#include <stdlib.h>
36#endif
37#include <util/keyval/ipv2.h>
38
39#include <stdio.h>
40#include <iostream>
41#include <fstream>
42
43using namespace std;
44using namespace sc;
45
46/* Initialize the ip routines. This involves parsing the entire file and
47 * converting it into an internal representation. */
48/* in = the input file. */
49/* out = the output file. */
50void
51IPV2::ip_initialize(istream&in,ostream&out)
52{
53 ip_initialized = 1;
54
55 ip_in = &in;
56 ip_out = &out;
57
58 /* Just in case a scanner has already been running. */
59 lexer->switch_streams(ip_in, ip_out);
60
61 /* If ip_tree is not NULL, then ip_initialize has been called twice,
62 * with a done inbetween. Call done now. */
63 if (ip_tree) {
64 warn("ip_initialize has been called twice without an IPV2::done");
65 done();
66 }
67
68 sub_tree = ip_tree;
69
70 yparse();
71
72 /* The initial cwk list is nothing. */
73 cwk_clear();
74
75 ip_internal_values();
76}
77
78/* Continue adding to the ip_tree with, presumably, another input file.
79 * This should be called after ip_initialize has been called with different
80 * input file. Multiple calls to ip_append, with different input files,
81 * are allowed. */
82/* in = the input file. */
83/* out = the output file. */
84void
85IPV2::ip_append(istream&in,ostream&out)
86{
87
88 ip_in = &in;
89 ip_out = &out;
90
91 lexer->switch_streams(ip_in, ip_out);
92
93 if (sub_tree != NULL) {
94 error("ip_append: sub_tree != NULL - impossible");
95 }
96
97 yparse();
98
99 ip_internal_values();
100}
101
102/* This routine can be called by the user after the ip routines have been
103 * initialized. It look for a prefix"dir" in the cwk list and a prefix"files"
104 * array. If prefix"dir" is found this concatenated with each of the
105 * prefix"files" that does not begin with a '/'. Each of these files is
106 * ip_append'ed to the set of inputs. */
107void
108IPV2::append_from_input(const char*prefix,ostream&outfile)
109{
110 char keyword[KEYWORD_LENGTH];
111 const char *dir;
112 const char *file;
113 char dirfile[512];
114 int i,nfile;
115
116 /* Get the prefix. */
117 strcpy(keyword,prefix);
118 strcat(keyword,"dir");
119 if (value(keyword,&dir,0) != OK) dir = NULL;
120
121 strcpy(keyword,prefix);
122 strcat(keyword,"files");
123 if (count(keyword,&nfile,0)!=OK) return;
124 for (i=0; i<nfile; i++) {
125 if (value_v(keyword,&file,1,&i) == OK) {
126 if (dir && (file[0] != '/')) strcpy(dirfile,dir);
127 else dirfile[0] = '\0';
128 strcat(dirfile,file);
129 ifstream infile(dirfile, ios::in);
130 if (infile.bad()) {
131 ExEnv::errn() << "WARNING: IPV2::append_from_input: "
132 << "couldn't open the file "
133 << dirfile
134 << endl;
135 }
136 else {
137 outfile << "appending " << dirfile << " to input" << endl;
138 ip_append(infile,outfile);
139 }
140 }
141 }
142}
143
144
145/* Set up internal ip variables based on the input that has been read in. */
146void
147IPV2::ip_internal_values()
148{
149 int errcod;
150
151 errcod = boolean(":ip:keyword",&ip_keyword,0);
152 if (errcod) ip_keyword = 0;
153
154}
155
156/* Free all of the data. */
157void
158IPV2::done()
159{
160 ip_free_keyword_tree(ip_tree);
161 ip_tree = NULL;
162 sub_tree = NULL;
163 ip_in = NULL;
164 ip_out = NULL;
165}
166
167void
168IPV2::ip_push_keyword(char*keyword)
169{
170 ip_push_keyclass(keyword,0,0);
171}
172
173void
174IPV2::ip_push_keyclass(char*keyword,char*classname,ip_string_list_t*parentlist)
175{
176 ip_keyword_tree_t *I, *new_keyword;
177
178 // if there is no keyword, then set the classname of the current
179 // sub_tree
180 if (!keyword) {
181 if (classname && sub_tree && sub_tree->keyword && !sub_tree->classname) {
182 sub_tree->classname = classname;
183 return;
184 }
185 else if (!sub_tree) {
186 keyword = strdup("TOP");
187 }
188 else {
189 if (classname) error("got a classname only in invalid context: %k");
190 else error("no classname, no keyword");
191 }
192 }
193
194 /* Make the parentlist a part of the keyword. */
195 if (parentlist) {
196 int newkeysize = strlen(keyword) + 4 + 1;
197 ip_string_list_t *pl;
198 char* newkey;
199
200 for (pl=parentlist; pl != NULL; pl=pl->p) {
201 newkeysize += strlen(pl->string);
202 if (pl->p) newkeysize++;
203 }
204
205 newkey = (char*)malloc(newkeysize);
206 strcpy(newkey,keyword);
207 strcat(newkey,"<<");
208
209 for (pl=parentlist; pl != NULL; pl=pl->p) {
210 strcat(newkey,pl->string);
211 if (pl->p) strcat(newkey,",");
212 }
213 strcat(newkey,">>");
214
215 free(keyword);
216 keyword = newkey;
217 }
218
219 /* If this is the first keyword, then create the tree. */
220 if (!ip_tree) {
221 sub_tree = ip_tree = ip_alloc_keyword_tree();
222 sub_tree->across = sub_tree;
223 sub_tree->keyword = keyword;
224 sub_tree->classname = classname;
225 return;
226 }
227
228 /* This is not the first keyword, so descend the tree. */
229
230 /* If sub_tree is at the top (NULL), then move to ip_tree. */
231 if (!sub_tree) {
232 sub_tree = ip_tree;
233 }
234 /* If there is not already a sub_tree->down, then create it. */
235 else if (!sub_tree->down) {
236 sub_tree->down = ip_alloc_keyword_tree();
237 sub_tree->down->across = sub_tree->down;
238 sub_tree->down->up = sub_tree;
239
240 sub_tree = sub_tree->down;
241 sub_tree->keyword = keyword;
242 sub_tree->classname = classname;
243 return;
244 }
245 /* Descend the tree, but keep track of where we were. */
246 else {
247 sub_tree = sub_tree->down;
248 }
249
250 /* Does the keyword exist in the current sub tree? */
251 I=sub_tree;
252 do {
253
254 if (!strcmp(I->keyword,keyword)) {
255 /* We found it. */
256 sub_tree = I;
257 if (classname && I->classname) {
258 if (strcmp(classname,I->classname)) {
259 error("Class specifications differ for keyword %k\n");
260 }
261 free(classname);
262 }
263 else if (classname) I->classname = classname;
264 free(keyword);
265 return;
266 }
267
268 } while ((I = I->across) != sub_tree);
269
270 /* We could not find it -- create a new entry. */
271
272 new_keyword = ip_alloc_keyword_tree();
273 new_keyword->across = sub_tree->across;
274 new_keyword->keyword = keyword;
275 new_keyword->classname = classname;
276 sub_tree->across = new_keyword;
277
278 new_keyword->up = sub_tree->up;
279
280 /* Move us down to the new keyword. */
281 sub_tree = new_keyword;
282}
283
284void
285IPV2::ip_pop_keyword()
286{
287 /* Make sure we aren\'t already on top. */
288 if (!sub_tree) {
289 error("ip_pop_keyword: tried to pop above top");
290 }
291 sub_tree = sub_tree->up;
292}
293
294void
295IPV2::ip_begin_table(ip_string_list_t*keywords)
296{
297 current_table_keyword = table_keywords = keywords;
298 table_sub_tree = sub_tree;
299 table_row_number = 0;
300}
301
302/* Given a string containing keywords separated by ':', push the
303 * keywords. */
304void
305IPV2::ip_push_table_col(char*keys)
306{
307 char cindex[10];
308 char * tmp = dup_string(keys);
309 char * keyword = strtok(tmp,":");
310 int n = 0;
311 do {
312 ip_push_keyword(dup_string(keyword));
313 n++;
314 } while((keyword = strtok(NULL,":")) != NULL);
315 free(tmp);
316 sprintf(cindex,"%d",table_row_number);
317 ip_push_keyword(dup_string(cindex));
318}
319
320void
321IPV2::ip_next_table_entry()
322{
323 if (table_array_depth>0) return;
324
325 sub_tree = table_sub_tree;
326 ip_push_table_col(current_table_keyword->string);
327
328 /* Advance the current_table_keyword pointer */
329 if (current_table_keyword->p == NULL) {
330 current_table_keyword = table_keywords;
331 table_row_number++;
332 }
333 else {
334 current_table_keyword = current_table_keyword->p;
335 }
336}
337
338void
339IPV2::ip_done_table()
340{
341 ip_string_list_t *I,*J;
342
343 /* Free the keywords strings and string list */
344 for (I=table_keywords; I!=NULL; ) {
345 free(I->string);
346 J = I->p;
347 free(I);
348 I = J;
349 }
350 table_keywords = NULL;
351 current_table_keyword = NULL;
352 sub_tree = table_sub_tree;
353 table_sub_tree = NULL;
354 }
355
356/* This adds the string, s, to the string list linked list, sl. */
357ip_string_list_t *
358IPV2::ip_add_string_list(ip_string_list_t*sl,char*s)
359{
360 ip_string_list_t *I;
361
362 if (!sl) return ip_string_to_string_list(s);
363
364 for (I=sl; I->p!=NULL; I=I->p);
365 I->p = ip_string_to_string_list(s);
366 return sl;
367}
368
369ip_string_list_t *
370IPV2::ip_string_to_string_list(char*s)
371{
372 ip_string_list_t *r;
373 r = (ip_string_list_t *) malloc(sizeof(ip_string_list_t));
374 r->string = s;
375 r->p = NULL;
376 return r;
377}
378
379char *
380IPV2::dup_string(const char*s)
381{
382 char *r;
383 r = (char *) malloc(strlen(s)+1);
384 strcpy(r,s);
385 return r;
386}
387
388ip_keyword_tree_t *
389IPV2::ip_get_variable_kt(char* variable)
390{
391 char* passed_variable = variable;
392 ip_keyword_tree_t *kt;
393 ip_keyword_tree_t *top;
394
395 top = sub_tree;
396
397 /* One or more occurrences of "..:" at the beginning of the keyword
398 * move us up the keyword tree */
399 while(top && !strncmp(variable,"..:",3)) {
400 variable = &variable[3];
401 top = top->up;
402 }
403
404 /* If top is still then we have a problem. */
405 if (!top) {
406 error("tried to get a variable above the top level - impossible");
407 }
408
409 /* Descend the keyword tree, creating nodes if needed. */
410 if (variable[0] == ':') {
411 kt = ip_descend_tree(ip_tree,variable);
412 }
413 else {
414 kt = ip_descend_tree(top,variable);
415 }
416
417 /* This should never be the case since variable keyword trees are
418 * created as needed. */
419 if (!kt) {
420 ExEnv::errn() << "WARNING: couldn't find the variable "
421 << variable
422 << endl;
423 return NULL;
424 }
425
426 /* Release storage for the variable. */
427 free(passed_variable);
428
429 return(kt);
430}
431
432void
433IPV2::ip_assign_variable(char* variable)
434{
435 if (table_keywords) ip_next_table_entry();
436
437 /* Note that the subtree is really a reference to another subtree. */
438 sub_tree->variable = variable;
439}
440
441char *
442IPV2::ip_get_variable_value(char*variable)
443{
444 ip_keyword_tree_t *kt;
445
446 /* Get the keyword tree associated with the variable. */
447 kt = ip_get_variable_kt(variable);
448
449 /* Return the value associated with the keyword. */
450 if (kt) return(kt->value);
451 else return NULL;
452}
453
454double
455IPV2::ip_get_variable_double(char*variable)
456{
457 char *value;
458
459 value = ip_get_variable_value(variable);
460
461 if (value == NULL) return 0.0;
462 else return atof(value);
463}
464
465char *
466IPV2::ip_double_to_string(double val)
467{
468 char *result;
469
470 result = (char *) malloc(64);
471
472 sprintf(result,"%22.15e",val);
473
474 return result;
475}
476
477void
478IPV2::ip_assign_value(char*value)
479{
480
481 if (table_keywords) ip_next_table_entry();
482
483 /* If sub_tree is still NULL then we have a problem. */
484 if (!sub_tree) {
485 error("tried to put a keyword at the top level - impossible");
486 }
487
488 /* Check for duplicate definitions. */
489 if (sub_tree->value) {
490# ifdef DUP_WARN
491 /* Warn the user about duplicate definitions. */
492 warn("duplicate definition of the following keyword:");
493 ip_print_keyword(ip_out,sub_tree);
494 fprintf(ip_out,"\n");
495 warn("the new value will be ignored");
496# endif /* DUP_WARN */
497 free(value);
498 }
499 else sub_tree->value = value;
500 }
501
502void
503IPV2::ip_start_karray()
504{
505 if (table_keywords && table_array_depth == 0) ip_next_table_entry();
506 if (table_keywords) table_array_depth++;
507 if (!karray_indices) {
508 karray_indices = (intlist_t *) malloc(sizeof(intlist_t));
509 karray_indices->p = NULL;
510 }
511 else {
512 intlist_t *tmp;
513 tmp = (intlist_t *) malloc(sizeof(intlist_t));
514 tmp->p = karray_indices;
515 karray_indices = tmp;
516 }
517 }
518
519void
520IPV2::ip_init_karray()
521{
522 init_karray = 1;
523 karray_indices->i = 0;
524}
525
526void
527IPV2::ip_incr_karray()
528{
529 char *key;
530
531 if (init_karray) {
532 init_karray = 0;
533 }
534 else {
535 ip_pop_keyword();
536 }
537
538 /* Construct a keyword to push. */
539 /* A cheap, yet inaccurate estimate of the string size needed. */
540 key = (char *) malloc(karray_indices->i/1000 + 4);
541 sprintf(key,"%d",karray_indices->i);
542
543 ip_push_keyword(key);
544
545 /* Increment the current karray index. */
546 karray_indices->i++;
547}
548
549void
550IPV2::ip_pop_karray()
551{
552 intlist_t *tmp;
553 if (table_keywords) table_array_depth--;
554 if (!init_karray) ip_pop_keyword();
555 tmp = karray_indices;
556 karray_indices = karray_indices->p;
557 if (tmp) free(tmp);
558}
559
560char *
561IPV2::ip_append_keystrings(char*s1,char*s2)
562{
563 char *r;
564
565 if (s1) r = (char *) malloc(strlen(s1)+strlen(s2)+2);
566 else r = (char *) malloc(strlen(s2)+2);
567 r[0] = '\0';
568 if (s1) strcat(r,s1);
569 strcat(r,":");
570 strcat(r,s2);
571 if (s1) free(s1);
572 free(s2);
573 return r;
574}
575
576/////////////////////////////////////////////////////////////////////////////
577
578// Local Variables:
579// mode: c++
580// c-file-style: "CLJ"
581// End:
Note: See TracBrowser for help on using the repository browser.