source: trunk/gsdl/lib/display.cpp@ 1310

Last change on this file since 1310 was 1310, checked in by sjboddie, 24 years ago

Removed CVS logging information from source files

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 44.9 KB
Line 
1/**********************************************************************
2 *
3 * display.cpp -- Context sensitive macro language
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26#include "display.h"
27#include "gsdlunicode.h"
28#include "unitool.h"
29#include <assert.h>
30
31// include to get NULL
32#include <stdlib.h>
33
34
35
36/////////////////////////////////////
37// misc classes
38/////////////////////////////////////
39
40
41// precedencetype defines a 'precedence value' for each parameter
42typedef map<text_t, double, lttext_t> precedencetype;
43
44
45// macro value structure
46struct mvalue
47{
48 text_t filename;
49 text_t value;
50};
51
52inline bool operator==(const mvalue &x, const mvalue &y) {
53 return (x.filename==y.filename && x.value==y.value);
54}
55
56inline bool operator<(const mvalue &x, const mvalue &y) {
57 return (x.filename<y.filename ||
58 (x.filename==y.filename && x.filename<y.filename));
59}
60
61
62
63/////////////////////////////////////
64// stuff for defaultmacros_t
65/////////////////////////////////////
66
67typedef map<text_t, mvalue, lttext_t> defparammap;
68typedef map<text_t, defparammap, lttext_t> defmacromap;
69typedef map<text_t, defmacromap, lttext_t> defpackagemap;
70
71// all methods in defaultmacros_t assume the parameters
72// and packages in a standard form and not empty
73class defaultmacros_t
74{
75protected:
76 defpackagemap macros;
77
78public:
79 typedef defpackagemap::const_iterator const_package_iterator;
80 typedef defpackagemap::size_type package_size_type;
81
82 // setmacro returns 0 if there was no error,
83 // -1 if it redefined a macro
84 // -2 if it hid a Global macro
85 // -3 if it redefined a macro and hid a Global macro
86 // -4 if either a package, macroname, or params were not supplied
87 int setmacro(const text_t &package,
88 const text_t &macroname,
89 const text_t &params,
90 const text_t &filename,
91 const text_t &macrovalue);
92
93 void delmacro(const text_t &package,
94 const text_t &macroname,
95 const text_t &params);
96
97 void clear () {macros.erase(macros.begin(), macros.end());}
98
99 // top level stuff
100 const_package_iterator package_begin () const {return macros.begin();}
101 const_package_iterator package_end () const {return macros.end();}
102 bool package_empty () const {return macros.empty();}
103 package_size_type package_size() const {return macros.size();}
104
105 // methods to find things
106 defmacromap *package_find (const text_t &packagename);
107 defparammap *macro_find (const text_t &packagename,
108 const text_t &macroname);
109 mvalue *parameter_find (const text_t &packagename,
110 const text_t &macroname,
111 const text_t &parametername);
112};
113
114
115// setmacro returns 0 if there was no error,
116// -1 if it redefined a macro
117// -2 if it hid a Global macro
118// -3 if it redefined a macro and hid a Global macro
119// -4 if either a package, macroname, or params were not supplied
120int defaultmacros_t::setmacro(const text_t &package,
121 const text_t &macroname,
122 const text_t &params,
123 const text_t &filename,
124 const text_t &macrovalue)
125{
126 paramhashtype paramhash;
127
128 defmacromap *macromapptr;
129 defparammap *parammapptr;
130 mvalue *mvalueptr;
131
132 int warning = 0;
133
134 // check to see if we would be hiding a Global macro with the
135 // same name. Note: it doesn't matter what parameters are used
136 // a Global macro will still be hid by a non-Global one with
137 // the same name.
138 if ((package != "Global") &&
139 (macro_find ("Global", macroname) != NULL))
140 {
141 warning -= 2; // found the macroname
142 }
143
144 // define this macro
145 macromapptr = &(macros[package]); // -- package
146 parammapptr = &((*macromapptr)[macroname]); // -- macro name
147 // -- parameters
148 if ((*parammapptr).find(params) != (*parammapptr).end()) {
149 warning -= 1; // found the parameters
150 }
151 mvalueptr = &((*parammapptr)[params]);
152
153 // -- value
154 (*mvalueptr).filename = filename;
155 (*mvalueptr).value = macrovalue;
156
157 return warning;
158}
159
160void defaultmacros_t::delmacro(const text_t &package,
161 const text_t &macroname,
162 const text_t &params)
163{
164 // make sure everything was supplied
165 if (package.empty() || macroname.empty() || params.empty()) return;
166
167 // find the package and macroname
168 defparammap *parammapptr = macro_find(package, macroname);
169 if (parammapptr == NULL) return;
170
171 // find the parameters
172 defparammap::iterator parammapit = parammapptr->find(params);
173 if (parammapit == parammapptr->end()) return;
174
175 // finally delete this element
176 parammapptr->erase(parammapit);
177}
178
179defmacromap *defaultmacros_t::package_find (const text_t &packagename)
180{
181 if (packagename.empty()) return NULL;
182
183 defpackagemap::iterator it = macros.find(packagename);
184 if (it == macros.end()) return NULL;
185
186 return &((*it).second);
187}
188
189defparammap *defaultmacros_t::macro_find (const text_t &packagename,
190 const text_t &macroname)
191{
192 defmacromap *macromapptr = package_find(packagename);
193 if (macromapptr == NULL || macroname.empty()) return NULL;
194
195 defmacromap::iterator it = (*macromapptr).find(macroname);
196 if (it == (*macromapptr).end()) return NULL;
197
198 return &((*it).second);
199}
200
201mvalue *defaultmacros_t::parameter_find (const text_t &packagename,
202 const text_t &macroname,
203 const text_t &parametername)
204{
205 defparammap *parammapptr = macro_find(packagename, macroname);
206 if (parammapptr == NULL || parametername.empty()) return NULL;
207
208 defparammap::iterator it = (*parammapptr).find(parametername);
209 if (it == (*parammapptr).end()) return NULL;
210
211 return &((*it).second);
212}
213
214
215
216/////////////////////////////////////
217// stuff for currentmacros_t
218/////////////////////////////////////
219
220typedef map<text_t, mvalue, lttext_t> curmacromap;
221typedef map<text_t, curmacromap, lttext_t> curpackagemap;
222
223// all methods in currentmacros_t assume the parameters
224// and packages in a standard form and not empty
225class currentmacros_t
226{
227protected:
228 curpackagemap macros;
229
230public:
231 typedef curpackagemap::const_iterator const_package_iterator;
232 typedef curpackagemap::size_type package_size_type;
233
234 // setmacro returns 0 if there was no error,
235 // -1 if it redefined a macro
236 // -4 if either a package, or macroname were not supplied
237 int setmacro(const text_t &package,
238 const text_t &macroname,
239 const text_t &filename,
240 const text_t &macrovalue);
241
242 void delmacro(const text_t &package,
243 const text_t &macroname);
244
245 void clear () {macros.erase(macros.begin(), macros.end());}
246
247 // top level stuff
248 const_package_iterator package_begin () const {return macros.begin();}
249 const_package_iterator package_end () const {return macros.end();}
250 bool package_empty () const {return macros.empty();}
251 package_size_type package_size() const {return macros.size();}
252
253 // methods to find things
254 curmacromap *package_find (const text_t &packagename);
255 mvalue *macro_find (const text_t &packagename,
256 const text_t &macroname);
257};
258
259
260// setmacro returns 0 if there was no error,
261// -1 if it redefined a macro
262// -4 if either a package, or macroname were not supplied
263int currentmacros_t::setmacro(const text_t &package,
264 const text_t &macroname,
265 const text_t &filename,
266 const text_t &macrovalue)
267{
268 int warning = 0;
269
270 // make sure everything was supplied
271 if (package.empty() || macroname.empty()) return -4;
272
273 // define this macro
274 curmacromap *macromapptr = &(macros[package]);
275 if ((*macromapptr).find(macroname) != (*macromapptr).end())
276 {
277 warning -= 1; // found the macroname
278 }
279 mvalue *mvalueptr = &((*macromapptr)[macroname]);
280
281 // -- value
282 (*mvalueptr).filename = filename;
283 (*mvalueptr).value = macrovalue;
284
285 return warning;
286}
287
288void currentmacros_t::delmacro(const text_t &package,
289 const text_t &macroname)
290{
291 // make sure everything was supplied
292 if (package.empty() || macroname.empty()) return;
293
294 // find the package
295 curmacromap *macromapptr = package_find(package);
296 if (macromapptr == NULL) return;
297
298 // find the macroname
299 curmacromap::iterator macromapit = macromapptr->find(macroname);
300 if (macromapit == macromapptr->end()) return;
301
302 // finally delete this element
303 macromapptr->erase(macromapit);
304}
305
306curmacromap *currentmacros_t::package_find (const text_t &packagename)
307{
308 if (packagename.empty()) return NULL;
309
310 curpackagemap::iterator it = macros.find(packagename);
311 if (it == macros.end()) return NULL;
312
313 return &((*it).second);
314}
315
316mvalue *currentmacros_t::macro_find (const text_t &packagename,
317 const text_t &macroname)
318{
319 curmacromap *macromapptr = package_find(packagename);
320 if (macromapptr == NULL || macroname.empty()) return NULL;
321
322 curmacromap::iterator it = (*macromapptr).find(macroname);
323 if (it == (*macromapptr).end()) return NULL;
324
325 return &((*it).second);
326}
327
328
329
330
331/////////////////////////////////////
332// support functions
333/////////////////////////////////////
334
335// this calculation of precedence will make one occurance of a high
336// precedence item override many occurances of lower precedence items
337void calcprecedence (const text_t &precedstr, precedencetype &precedhash)
338{
339 text_t param;
340 double multiple = 5.0;
341 double nextprec = multiple;
342
343 text_t::const_iterator here, end;
344
345 // set precedhash to an empty hash
346 precedhash.erase(precedhash.begin(), precedhash.end());
347
348 // iterate through paramstring ignoring space and extracting
349 // out key value pairs.
350 here = precedstr.begin();
351 end = precedstr.end();
352 while (here != end)
353 {
354 // get the next parameter
355 param.clear(); // set param to an empty string
356
357 while (here != end)
358 {
359 if (*here == ',')
360 {
361 // found the end of the parameter
362 here++;
363 break;
364 }
365 else if (*here == ' ')
366 {
367 // do nothing (ignore spaces)
368 }
369 else
370 {
371 // character in parameter
372 param.push_back (*here); // copy this character
373 }
374
375 here++;
376 }
377
378 // if a parameter was found insert its value
379 if (!param.empty())
380 {
381 precedhash[param] = nextprec;
382 nextprec *= multiple;
383 }
384 }
385}
386
387
388// decides how specific any given parameter is to the page parameters. Returns
389// negative if any options are different or else the sum of the precedence for
390// the options which match.
391double getspecificness(const paramhashtype &pageparams,
392 const paramhashtype &theseparams,
393 const precedencetype &precedhash)
394{
395 double specificness = 0.0;
396 paramhashtype::const_iterator here, pagevalueit;
397 precedencetype::const_iterator precedit;
398 text_t thesekey, thesevalue, constignore("ignore");
399
400 here = theseparams.begin();
401 while (here != theseparams.end())
402 {
403 thesekey = (*here).first;
404 thesevalue = (*here).second;
405
406 if (thesekey == constignore)
407 {
408 // do nothing, this is a placeholder
409 }
410 else
411 {
412 pagevalueit = pageparams.find(thesekey);
413 if ((pagevalueit != pageparams.end()) &&
414 ((*pagevalueit).second == thesevalue))
415 {
416 // this parameter fits, add its precedence value
417 precedit = precedhash.find(thesekey);
418 if (precedit == precedhash.end())
419 specificness += 1.0; // no precedence defined
420 else
421 specificness += (*precedit).second;
422 }
423 else
424 {
425 return -1.0; // did not match
426 }
427 }
428
429 here++;
430 }
431
432 return specificness;
433}
434
435
436void splitparams (const text_t &paramstring, paramhashtype &paramhash)
437{
438 text_t key;
439 text_t value;
440
441 text_t::const_iterator here, end;
442
443 // set paramhash to an empty hash
444 paramhash.erase(paramhash.begin(), paramhash.end());
445
446 // iterate through paramstring ignoring space and extracting
447 // out key value pairs.
448 here = paramstring.begin();
449 end = paramstring.end();
450 while (here != end)
451 {
452 // reset key and value
453 key.clear();
454 value.clear();
455
456 // get key
457 while (here != end)
458 {
459 if (*here == ',')
460 {
461 // have a key with no value
462 break;
463 }
464 else if (*here == '=')
465 {
466 // found the end of the key
467 here ++;
468 break;
469 }
470 else if (*here == ' ')
471 {
472 // do nothing (ignore spaces)
473 }
474 else
475 {
476 // character in key
477 key.push_back (*here); // copy this character
478 }
479 here ++;
480 }
481
482 // get value
483 while (here != end)
484 {
485 if (*here == '=')
486 {
487 // multiple values for one key, ignore previous
488 // values
489 value.clear();
490 }
491 else if (*here == ',')
492 {
493 // found the end of the value
494 here ++;
495 break;
496 }
497 else if (*here == ' ')
498 {
499 // do nothing (ignore spaces)
500 }
501 else
502 {
503 // character in value
504 value.push_back (*here); // copy this character
505 }
506 here ++;
507 }
508
509 // if a key was found insert the key/value pair in
510 // the map
511 if (!key.empty())
512 {
513 paramhash[key] = value;
514 }
515 }
516}
517
518
519void joinparams (const paramhashtype &paramhash, text_t &paramstring)
520{
521 //set paramstring to an empty string
522 paramstring.clear();
523
524 //iterate through the paramhash
525 paramhashtype::const_iterator thepair;
526 int firstparam = 1;
527
528 for (thepair=paramhash.begin();thepair!=paramhash.end(); thepair++)
529 {
530 if (!firstparam) paramstring.push_back(',');
531 firstparam = 0;
532
533 // insert pairs of "key=value"
534 text_t thevalue;
535 paramstring.append((*thepair).first);
536 paramstring.push_back('=');
537 paramstring.append((*thepair).second);
538 }
539}
540
541
542
543/////////////////////////////////////
544// parsing support functions
545/////////////////////////////////////
546
547inline int my_isalpha (unsigned short c)
548{
549 return ((c >= 'A' && c <= 'Z') ||
550 (c >= 'a' && c <= 'z'));
551}
552
553
554
555inline unsigned short my_ttnextchar (text_t::const_iterator &here,
556 text_t::const_iterator &end)
557{
558 if (here != end)
559 {
560 here++;
561 if (here != end) return (*here);
562 }
563 return '\0';
564}
565
566
567
568/////////////////////////////////////
569// methods for display
570/////////////////////////////////////
571
572// public methods for display
573
574displayclass::displayclass ()
575{
576 defaultmacros = new defaultmacros_t;
577 defaultfiles = new fileinfomap;
578
579 orderparamlist = new paramspeclist;
580 currentmacros = new currentmacros_t;
581
582 outc = NULL;
583
584 logout = &cerr;
585}
586
587
588displayclass::~displayclass ()
589{
590 delete defaultmacros;
591 delete defaultfiles;
592
593 delete orderparamlist;
594 delete currentmacros;
595}
596
597// setdefaultmacro adds an entry to the list of default macros
598// returns 0 if there was no error,
599// -1 if it redefined a macro
600// -2 if it hid a Global macro
601// -3 if it redefined a macro and hid a Global macro
602// -4 if no macroname was supplied
603int displayclass::setdefaultmacro (text_t package, const text_t &macroname,
604 text_t params, const text_t &macrovalue)
605{
606 return setdefaultmacro (macroname, package, params, macrovalue, "memory");
607}
608
609
610
611// as we are using one character lookahead the
612// value of line might be off by one.
613// the input file must be in the utf-8 or unicode format
614// initially for each file isunicode should be set to 0 and
615// bigendian should be set to 1
616// 0 will be returned when the end of the file has been found
617unsigned short my_uni_get (unistream &fin, int &line,
618 int &isunicode, int &bigendian) {
619 unsigned short c = 0;
620
621 if (isunicode) {
622 // unicode text
623 // get the next two characters
624 unsigned char c1 = 0, c2 = 0;
625
626 if (!fin.eof()) fin.get(c1);
627 if (!fin.eof()) fin.get(c2);
628 else c1 = 0;
629
630 // if they indicate the order get the next character
631 // otherwise just get these characters
632 if (c1 == 0xff && c2 == 0xfe) {
633 bigendian = 0;
634 c = my_uni_get (fin, line, isunicode, bigendian);
635 } else if (c1 == 0xfe && c2 == 0xff) {
636 bigendian = 1;
637 c = my_uni_get (fin, line, isunicode, bigendian);
638 } else c = (bigendian) ? (c1*256+c2) : (c2*256+c1);
639
640 } else {
641 // utf-8 text
642 // how many characters we get depends on what we find
643 unsigned char c1 = 0, c2 = 0, c3 = 0;
644 while (!fin.eof()) {
645 fin.get(c1);
646 if (c1 == 0xfe || c1 == 0xff) {
647 // switch to unicode
648 isunicode = 1;
649 if (!fin.eof()) fin.get(c2);
650
651 if (c1 == 0xff && c2 == 0xfe) bigendian = 0;
652 else bigendian = 1;
653
654 c = my_uni_get (fin, line, isunicode, bigendian);
655 break;
656
657 } else if (c1 <= 0x7f) {
658 // one byte character
659 c = c1;
660 break;
661
662 } else if (c1 >= 0xc0 && c1 <= 0xdf) {
663 // two byte character
664 if (!fin.eof()) fin.get(c2);
665 c = ((c1 & 0x1f) << 6) + (c2 & 0x3f);
666 break;
667
668 } else if (c1 >= 0xe0 && c1 <= 0xef) {
669 // three byte character
670 if (!fin.eof()) fin.get(c2);
671 if (!fin.eof()) fin.get(c3);
672 c = ((c1 & 0xf) << 12) + ((c2 & 0x3f) << 6) + (c3 & 0x3f);
673 break;
674 }
675
676 // if we get here there was an error in the file, we should
677 // be able to recover from it however, maybe the file is in
678 // another encoding
679 }
680 }
681
682 if (c == '\n') line++;
683 return c;
684}
685
686
687
688// loads a default macro file (if it isn't already loaded)
689// returns 0 if didn't need to load the file (it was already loaded)
690// 1 if was (re)loaded
691// -1 an error occurred while trying to load the file
692int displayclass::loaddefaultmacros (text_t thisfilename) {
693 // convert the filename to a C string
694 char *filenamestr = thisfilename.getcstr();
695 outconvertclass text_t2ascii;
696
697 // see if we need to open this file -- this isn't implemented yet
698
699 // open the file
700 unistream fin (filenamestr);
701
702 if (fin.fail()) return -1; // read failed
703
704 text_t package = "Global";
705 int line = 1;
706 int isunicode = 0, bigendian = 1;
707
708 // pre-fetch the next character
709 unsigned short c = my_uni_get(fin, line, isunicode, bigendian);
710
711 text_t macropackage, macroname, macroparameters, macrovalue;
712 int err; // for keeping track of whether an error occurred somewhere
713
714 while (!fin.eof()) {
715 // expect: white space, comment, "package", or macroname
716 if (is_unicode_space(c)) {
717 // found some white-space
718 c = my_uni_get(fin, line, isunicode, bigendian);
719
720 } else if (c == '#') {
721 // found the start of a comment
722 // skip all characters up to the end of the line
723 c = my_uni_get(fin, line, isunicode, bigendian); // skip the '#'
724 while (!fin.eof ()) {
725 if (c == '\n') break;
726 c = my_uni_get(fin, line, isunicode, bigendian);
727 }
728
729 } else if (c == 'p') {
730 // found the start of 'package' (hopefully)
731 // get everything up to the next space
732 text_t tmp;
733 while (!fin.eof() && my_isalpha(c)) {
734 tmp.push_back(c);
735 c = my_uni_get(fin, line, isunicode, bigendian);
736 }
737 // see if we have a package name
738 if (tmp == "package") {
739 // skip all white space
740 while (!fin.eof() && is_unicode_space(c))
741 c = my_uni_get(fin, line, isunicode, bigendian);
742
743 // get the package name
744 tmp.clear(); // init tmp
745 while (!fin.eof() && my_isalpha(c)) {
746 tmp.push_back(c);
747 c = my_uni_get(fin, line, isunicode, bigendian);
748 }
749 package = tmp;
750 if (package.empty()) package = "Global";
751
752 } else {
753 // error
754 if (logout != NULL) {
755 (*logout) << text_t2ascii << "Expected 'package' on line " << line
756 << " of " << thisfilename << "\n";
757 }
758 }
759
760 } else if (c == '_') {
761 // found the start of a macro (hopefully)
762 c = my_uni_get(fin, line, isunicode, bigendian); // skip the _
763
764 // init variables
765 err = 0;
766 macropackage = package;
767 macroname.clear(); // init macroname
768 macroparameters.clear(); // init macroname
769 macrovalue.clear(); // init macroname
770
771 // get the macro name
772 while ((!fin.eof()) && (!is_unicode_space(c)) &&
773 (c != '\\') && (c != '_') &&(c != ':') &&
774 (macroname.size() < 80)) {
775 macroname.push_back(c);
776 c = my_uni_get(fin, line, isunicode, bigendian);
777 }
778
779 if (c == ':') {
780 // we actually had the macro package
781 c = my_uni_get(fin, line, isunicode, bigendian); // skip :
782 macropackage = macroname;
783 macroname.clear ();
784
785 // get the macro name (honest!)
786 while ((!fin.eof()) && (!is_unicode_space(c)) &&
787 (c != '\\') && (c != '_') &&(c != ':') &&
788 (macroname.size() < 80)) {
789 macroname.push_back(c);
790 c = my_uni_get(fin, line, isunicode, bigendian);
791 }
792 }
793
794 if (!err && c == '_') {
795 c = my_uni_get(fin, line, isunicode, bigendian); // skip the _
796
797 // skip all white space
798 while (!fin.eof() && is_unicode_space(c)) c = my_uni_get(fin, line, isunicode, bigendian);
799 } else if (!err) err = 1;
800
801 // get the macro parameters (optional)
802 if (!err && c == '[') {
803 c = my_uni_get(fin, line, isunicode, bigendian); // skip the [
804 while ((!fin.eof()) && (c != '\n') && (c != '\\') && (c != ']')) {
805 macroparameters.push_back(c);
806 c = my_uni_get(fin, line, isunicode, bigendian);
807 }
808
809 if (c == ']') {
810 c = my_uni_get(fin, line, isunicode, bigendian); // skip the ]
811
812 // skip all white space
813 while (!fin.eof() && is_unicode_space(c)) c = my_uni_get(fin, line, isunicode, bigendian);
814 }
815 else if (!err) err = 2;
816 }
817
818 // get the macro value
819 if (!err && c == '{') {
820 c = my_uni_get(fin, line, isunicode, bigendian); // skip the {
821 while ((!fin.eof()) && (c != '}')) {
822 if (c == '\\') {
823 macrovalue.push_back(c); // keep the '\'
824 c = my_uni_get(fin, line, isunicode, bigendian); // store the *next* value regardless
825 if (!fin.eof()) macrovalue.push_back(c);
826 c = my_uni_get(fin, line, isunicode, bigendian);
827 }
828 macrovalue.push_back(c);
829 c = my_uni_get(fin, line, isunicode, bigendian);
830 }
831
832 if (c == '}') {
833 c = my_uni_get(fin, line, isunicode, bigendian); // skip the }
834
835 // define the macro
836 err = setdefaultmacro (macropackage, macroname, macroparameters,
837 thisfilename, macrovalue);
838 if ((err == -1 || err == -3) && logout != NULL) {
839 (*logout) << text_t2ascii << "Warning: redefinition of _" <<
840 package << ":" << macroname << "_[" << macroparameters <<
841 "] on line ";
842 (*logout) << line;
843 (*logout) << text_t2ascii << " of " << thisfilename << "\n";
844
845 } else if (err == -2 && logout != NULL) {
846 (*logout) << text_t2ascii << "Warning: _" <<
847 package << ":" << macroname << "_[" << macroparameters <<
848 "] on line ";
849 (*logout) << line;
850 (*logout) << text_t2ascii << " of " <<
851 thisfilename << " hides a Global macro with the same name\n";
852
853 } else if (err == -4 && logout != NULL) {
854 (*logout) << text_t2ascii << "Error: macro name expected on line ";
855 (*logout) << line ;
856 (*logout) << text_t2ascii << " of " << thisfilename << "\n";
857 }
858
859 err = 0; // for the test below
860 }
861 else if (!err) err = 3;
862 }
863 else if (!err) err = 4;
864
865 if (err) {
866 // found an error, skip to the end of the line
867 if (logout != NULL) {
868 (*logout) << text_t2ascii << "Error: ";
869 if (err == 1) (*logout) << text_t2ascii << "'_'";
870 else if (err == 2) (*logout) << text_t2ascii << "']'";
871 else if (err == 3) (*logout) << text_t2ascii << "'}'";
872 else if (err == 4) (*logout) << text_t2ascii << "'{'";
873 (*logout) << text_t2ascii << " expected on line ";
874 (*logout) << line ;
875 (*logout) << text_t2ascii << " of " << thisfilename << "\n";
876 }
877 while (!fin.eof ()) {
878 if (c == '\n') break;
879 c = my_uni_get(fin, line, isunicode, bigendian);
880 }
881 }
882
883 } else {
884 // found an error, skip to the end of the line
885 if (logout != NULL) {
886 (*logout) << text_t2ascii << "Error: Unexpected input on line " << line
887 << " of " << thisfilename << "\n";
888 }
889 while (!fin.eof ()) {
890 if (c == '\n') break;
891 c = my_uni_get(fin, line, isunicode, bigendian);
892 }
893
894 }
895 }
896
897 fin.close ();
898
899 // free up memory
900 delete filenamestr;
901 return 0;
902}
903
904
905// prepares to create a page.
906void displayclass::openpage (const text_t &thispageparams,
907 const text_t &thisprecedence)
908{
909 // init variables
910 currentmacros->clear();
911
912 // reload any default macro files which have changed.
913 if (checkdefaultmacrofiles() < 0)
914 {
915 // print error message
916 }
917
918 setpageparams (thispageparams, thisprecedence);
919}
920
921
922// changes the parameters for the current page.
923void displayclass::setpageparams (text_t thispageparams,
924 text_t thisprecedence)
925{
926 paramhashtype thissplitparams, splittheseparams;
927 precedencetype precedhash;
928 text_tset::iterator text_tsetit;
929 paramspec tmpps;
930
931 precedence = thisprecedence;
932 calcprecedence(thisprecedence, precedhash);
933
934 splitparams(thispageparams, thissplitparams);
935 joinparams(thissplitparams, thispageparams);
936 params = thispageparams;
937
938 // get a list of parameters with their specificness
939 orderparamlist->erase(orderparamlist->begin(), orderparamlist->end());
940 for (text_tsetit=allparams.begin();
941 text_tsetit!=allparams.end();
942 text_tsetit++)
943 {
944 tmpps.param = (*text_tsetit);
945 splitparams(tmpps.param, splittheseparams);
946 tmpps.spec = getspecificness(thissplitparams, splittheseparams, precedhash);
947 if (tmpps.spec >= 0)
948 {
949 orderparamlist->push_back (tmpps);
950 }
951 }
952
953 // sort the list
954 sort(orderparamlist->begin(), orderparamlist->end());
955
956// paramspeclist::iterator pshere = orderparamlist->begin();
957// paramspeclist::iterator psend = orderparamlist->end();
958// while (pshere != psend)
959// {
960// cerr << text_t2ascii << "param=" << (*pshere).param;
961// cerr << " spec=" << (int)((*pshere).spec) << "\n";
962// pshere++;
963// }
964}
965
966
967// overrides (or sets) a macro for the current page.
968// returns 0 if there was no error,
969// -1 if it redefined a macro
970// -4 if no macroname was supplied
971int displayclass::setmacro (const text_t &macroname,
972 text_t package,
973 const text_t &macrovalue)
974{
975 // make sure a macroname was supplied
976 if (macroname.empty()) return -4;
977
978 // make package "Global" if it doesn't point to anything yet
979 if (package.empty()) package = "Global";
980
981 // set the macro
982 return currentmacros->setmacro(package, macroname, "memory", macrovalue);
983}
984
985
986void displayclass::expandstring (const text_t &inputtext, text_t &outputtext)
987{
988 expandstring("", inputtext, outputtext);
989}
990
991
992void displayclass::expandstring (text_t package, const text_t &inputtext,
993 text_t &outputtext, int recursiondepth)
994{
995 text_t macroname, macropackage, macroargs;
996 text_t::const_iterator tthere = inputtext.begin();
997 text_t::const_iterator ttend = inputtext.end();
998 unsigned short c = '\0';
999
1000 if (package.empty()) package = "Global";
1001
1002 outputtext.clear();
1003
1004 // use one-character lookahead
1005 if (tthere != ttend) c = (*tthere);
1006 while (tthere != ttend)
1007 {
1008 if (c == '\\')
1009 {
1010 // found an escape character
1011 c = my_ttnextchar (tthere, ttend); // skip the escape character
1012 if (tthere != ttend)
1013 {
1014 if (c == 'n') outputtext.push_back('\n');
1015 else if (c == 't') outputtext.push_back('\t');
1016 else outputtext.push_back(c);
1017 }
1018 c = my_ttnextchar (tthere, ttend);
1019
1020 }
1021 else if (c == '_')
1022 {
1023 // might have found the start of a macro
1024
1025 // embedded macros (macros within the names
1026 // of other macros) are no longer supported -- Rodger.
1027
1028 // save the current state (in case we need to back out)
1029 text_t::const_iterator savedtthere = tthere;
1030 unsigned short savedc = c;
1031
1032 macroname.clear();
1033 macropackage = package;
1034 macroargs.clear();
1035
1036 c = my_ttnextchar (tthere, ttend); // skip the '_'
1037
1038 // get the macroname
1039 while (tthere != ttend && (!is_unicode_space(c)) &&
1040 (c != '\\') && (c != '_') &&(c != ':') &&
1041 (macroname.size() < 80))
1042 {
1043 macroname.push_back((unsigned char)c);
1044 c = my_ttnextchar (tthere, ttend);
1045 }
1046
1047 if (c == ':')
1048 {
1049 // we actually had the macro package
1050 c = my_ttnextchar (tthere, ttend);
1051 macropackage = macroname;
1052 macroname.clear ();
1053
1054 // get the macro name (honest!)
1055 while ((tthere != ttend) && (!is_unicode_space(c)) &&
1056 (c != '\\') && (c != '_') &&(c != ':') &&
1057 (macroname.size() < 80))
1058 {
1059 macroname.push_back((unsigned char)c);
1060 c = my_ttnextchar (tthere, ttend);
1061 }
1062 }
1063
1064 if ((tthere != ttend) && (c == '_') &&
1065 (macroname.size() > 0))
1066 {
1067 // found a macro!!!! (maybe)
1068
1069 c = my_ttnextchar (tthere, ttend); // skip the '_'
1070
1071 // get the parameters (if there are any)
1072 if ((tthere != ttend) && (c == '('))
1073 {
1074 c = my_ttnextchar (tthere, ttend); // skip '('
1075
1076 // have to be careful of quotes
1077 unsigned short quote = '\0';
1078 while (tthere != ttend)
1079 {
1080 if (c == '\\')
1081 {
1082 // have an escape character, save escape
1083 // character and next character as well
1084 macroargs.push_back (c);
1085 c = my_ttnextchar (tthere, ttend);
1086
1087 }
1088 else if (quote == '\0')
1089 {
1090 // not in a quote at the moment
1091 if (c == ')')
1092 {
1093 // found end of the arguments
1094 c = my_ttnextchar (tthere, ttend); // skip ')'
1095 break;
1096
1097 }
1098 else if (c == '\'' || c == '\"')
1099 {
1100 // found a quote
1101 quote = c;
1102 }
1103
1104 }
1105 else
1106 {
1107 // we are in a quote
1108 if (c == quote) quote = '\0';
1109 }
1110
1111 // save this character
1112 if (tthere != ttend) macroargs.push_back (c);
1113 c = my_ttnextchar (tthere, ttend);
1114 }
1115 }
1116
1117 //
1118 // we now have the macropackage, macroname, and macroargs
1119 //
1120
1121 // try to expand out this macro
1122 text_t expandedmacro;
1123 if (macro (macroname, macropackage, macroargs, expandedmacro, recursiondepth))
1124 {
1125 // append the expanded macro
1126 outputtext += expandedmacro;
1127 }
1128 else
1129 {
1130 // wasn't a macro
1131 tthere = savedtthere;
1132 c = savedc;
1133 outputtext.push_back(c); // the '_'
1134 c = my_ttnextchar (tthere, ttend);
1135 }
1136
1137
1138 }
1139 else
1140 {
1141 // wasn't a macro
1142 tthere = savedtthere;
1143 c = savedc;
1144 outputtext.push_back(c); // the '_'
1145 c = my_ttnextchar (tthere, ttend);
1146 }
1147
1148 }
1149 else
1150 {
1151 // nothing of interest
1152 outputtext.push_back(c); // the '_'
1153 c = my_ttnextchar (tthere, ttend);
1154 }
1155 }
1156}
1157
1158ostream *displayclass::setlogout (ostream *thelogout) {
1159
1160 ostream *oldlogout = logout;
1161 logout = thelogout;
1162 return oldlogout;
1163}
1164
1165// protected methods for display
1166
1167// reloads any default macro files which have changed
1168// returns 0 no errors occurred
1169// -1 an error occurred while trying to load one of the files
1170int displayclass::checkdefaultmacrofiles ()
1171{
1172 // this isn't implemented yet
1173 return 0;
1174}
1175
1176// isdefaultmacro sees if there is an entry in the list of
1177// default macros with the given package and macro name
1178// returns 0 if no macros in the package or in the global package
1179// were found
1180// 1 if no macros in the package were found but a macro
1181// in the global package was found
1182// 2 if a macro in the given package was found
1183int displayclass::isdefaultmacro (text_t package, const text_t &macroname) {
1184 // make sure a macroname was supplied
1185 if (macroname.empty()) return 0;
1186
1187 // make package "Global" if it doesn't point to anything yet
1188 if (package.empty()) package = "Global";
1189
1190 // check the given package
1191 if (defaultmacros->macro_find(package, macroname) != NULL) return 2;
1192
1193 // check the Global package
1194 if (defaultmacros->macro_find("Global", macroname) != NULL) return 1;
1195
1196 return 0;
1197}
1198
1199
1200// setdefaultmacro adds an entry to the list of default macros
1201// returns 0 if there was no error,
1202// -1 if it redefined a macro
1203// -2 if it hid a Global macro
1204// -3 if it redefined a macro and hid a Global macro
1205// -4 if no macroname was supplied
1206int displayclass::setdefaultmacro (text_t package, const text_t &macroname,
1207 text_t params, const text_t &filename,
1208 const text_t &macrovalue)
1209{
1210 // make sure a macroname was supplied
1211 if (macroname.empty()) return -4;
1212
1213 // put the parameters in a standard form
1214 paramhashtype paramhash;
1215 if (params.empty()) params = "ignore=yes";
1216 splitparams (params, paramhash);
1217 joinparams (paramhash, params);
1218
1219 // make package "Global" if it doesn't point to anything yet
1220 if (package.empty()) package = "Global";
1221
1222 // remember these parameters
1223 allparams.insert (params);
1224
1225 // remember this filename (this part isn't finished yet -- Rodger).
1226
1227 // set the macro
1228 return defaultmacros->setmacro(package, macroname, params, filename, macrovalue);
1229}
1230
1231
1232// evaluates a boolean expression
1233// returns false if expr equals "" or "0".
1234// otherwise returns true *unless* expr is
1235// format "XXXX" eq/ne "dddd" in which case
1236// the two quoted strings are compared
1237bool displayclass::boolexpr (text_t package, const text_t &expr, int recursiondepth) {
1238
1239 if (expr.empty()) return false;
1240
1241 text_t expexpr;
1242 if (package.empty()) package = "Global";
1243 expandstring (package, expr, expexpr, recursiondepth);
1244
1245 if (expexpr.empty() || expexpr == "0") return false;
1246 if (expr[0] != '\"') return true;
1247
1248 // don't use expexpr while separating quoted parts of
1249 // expression just in case expanded out macros contain
1250 // quotes
1251 text_t::const_iterator here = expr.begin();
1252 text_t::const_iterator end = expr.end();
1253
1254 int quotecount = 0;
1255 text_t string1, expstring1;
1256 text_t string2, expstring2;
1257 text_t op;
1258 text_t combineop;
1259 bool result = false; // an empty string is false
1260 bool result2 = false;
1261
1262 while (here != end) {
1263 // get a comparison
1264 quotecount = 0;
1265 string1.clear();
1266 string2.clear();
1267 op.clear();
1268 while (here != end) {
1269 if (*here == '"') quotecount++;
1270 else if (quotecount == 1) string1.push_back(*here);
1271 else if ((quotecount == 2) && !is_unicode_space (*here))
1272 op.push_back(*here);
1273 else if (quotecount == 3) string2.push_back(*here);
1274 else if (quotecount >= 4) break;
1275 here ++;
1276 }
1277
1278 expandstring (package, string1, expstring1, recursiondepth);
1279 expandstring (package, string2, expstring2, recursiondepth);
1280
1281 // get next result
1282 result2 = true; // any badly formatted string will return true
1283 if (op == "eq") result2 = (expstring1 == expstring2);
1284 else if (op == "ne") result2 = (expstring1 != expstring2);
1285 else if (op == "gt") result2 = (expstring1 > expstring2);
1286 else if (op == "ge") result2 = (expstring1 >= expstring2);
1287 else if (op == "lt") result2 = (expstring1 < expstring2);
1288 else if (op == "le") result2 = (expstring1 <= expstring2);
1289 else if (op == "==") result2 = (expstring1.getint() == expstring2.getint());
1290 else if (op == "!=") result2 = (expstring1.getint() != expstring2.getint());
1291 else if (op == ">") result2 = (expstring1.getint() > expstring2.getint());
1292 else if (op == ">=") result2 = (expstring1.getint() >= expstring2.getint());
1293 else if (op == "<") result2 = (expstring1.getint() < expstring2.getint());
1294 else if (op == "<=") result2 = (expstring1.getint() <= expstring2.getint());
1295
1296 // combine the results
1297 if (combineop == "&&") result = (result && result2);
1298 else if (combineop == "||") result = (result || result2);
1299 else result = result2;
1300
1301 // get next combination operator
1302 combineop.clear();
1303 while (here != end && *here != '"') {
1304 if (!is_unicode_space(*here)) combineop.push_back(*here);
1305 here++;
1306 }
1307 }
1308
1309 return result;
1310}
1311
1312
1313// (recursively) expand out a macro
1314// returns true if the macro was found
1315// false if the macro was not found
1316bool displayclass::macro (const text_t &macroname, text_t macropackage,
1317 const text_t &macroparam, text_t &outputtext,
1318 int recursiondepth)
1319{
1320 outconvertclass text_t2ascii;
1321 text_tlist splitmacroparam;
1322 text_t::const_iterator hereit, endit;
1323 text_t aparam;
1324 unsigned short c = '\0', quote = '\0';
1325
1326 // cerr << "r: " << recursiondepth << "\n";
1327
1328 // check for deep recursion
1329 if (recursiondepth >= MAXRECURSIONDEPTH)
1330 {
1331 if (logout != NULL)
1332 (*logout) << "Warning: deep recursion, limiting macro expansion\n";
1333 return false;
1334 }
1335
1336 // check the macropackage
1337 if (macropackage.empty()) macropackage = "Global";
1338
1339 // get the parameters (but don't expand them)
1340 if (macroparam.size() > 0) {
1341 // set up for loop
1342 hereit = macroparam.begin();
1343 endit = macroparam.end();
1344 if (hereit != endit) c = (*hereit);
1345
1346 while (hereit != endit) {
1347 // get the next parameter
1348 aparam.clear();
1349 quote = '\0'; // not-quoted unless proven quoted
1350
1351 // ignore initial whitespace
1352 while ((hereit!=endit)&&is_unicode_space(c)) c=my_ttnextchar(hereit,endit);
1353
1354 // look for the end of the parameter
1355 while (hereit != endit) {
1356 if (c == '\\') {
1357 // found escape character, also get next character
1358 aparam.push_back(c);
1359 c = my_ttnextchar (hereit, endit);
1360 if (hereit != endit) aparam.push_back(c);
1361
1362 } else if (quote=='\0' && (c=='\'' /*|| c=='"'*/)) {
1363 // found a quoted section
1364 quote = c;
1365 // aparam.push_back(c);
1366
1367 } else if (quote!='\0' && c==quote) {
1368 // found the end of a quote
1369 quote = '\0';
1370 // aparam.push_back(c);
1371
1372 } else if (quote=='\0' && c==',') {
1373 // found the end of a parameter
1374 c = my_ttnextchar (hereit, endit);
1375 break;
1376
1377 } else {
1378 // ordinary character
1379 aparam.push_back(c);
1380 }
1381
1382 c = my_ttnextchar (hereit, endit);
1383 }
1384
1385 // add this parameter to the list
1386 splitmacroparam.push_back(aparam);
1387 }
1388 }
1389
1390 if (macroname == "If") {
1391 // get the condition, then clause and else clause
1392 text_tlist::iterator paramcond = splitmacroparam.begin();
1393 text_tlist::iterator paramend = splitmacroparam.end();
1394 text_tlist::iterator paramthen = paramend;
1395 text_tlist::iterator paramelse = paramend;
1396
1397 if (paramcond != paramend) {
1398 paramthen = paramcond;
1399 paramthen++;
1400 }
1401 if (paramthen != paramend) {
1402 paramelse = paramthen;
1403 paramelse++;
1404 }
1405
1406 // will always output something
1407 outputtext.clear();
1408
1409 // expand out the first parameter
1410 if (paramcond != paramend) {
1411 text_t tmpoutput;
1412 expandstring (macropackage, *paramcond, tmpoutput, recursiondepth+1);
1413 lc (tmpoutput);
1414
1415 // test the expanded string
1416 if (boolexpr (macropackage, *paramcond, recursiondepth+1)) {
1417 //(tmpoutput.size()) && (tmpoutput != "false") && (tmpoutput != "0")) {
1418 // true
1419 if (paramthen != paramend)
1420 expandstring (macropackage, *paramthen, outputtext, recursiondepth+1);
1421
1422 } else {
1423 // false
1424 if (paramelse != paramend)
1425 expandstring (macropackage, *paramelse, outputtext, recursiondepth+1);
1426 }
1427 }
1428
1429 return true;
1430 }
1431
1432 // try and find this macro
1433
1434 // this list might be replaced by something a little more
1435 // sophisticated in the future.
1436 text_tlist packagelist;
1437 packagelist.push_back (macropackage);
1438 packagelist.push_back ("Global");
1439
1440 paramspeclist::iterator paramhere, paramend;
1441 text_tlist::iterator packagehere = packagelist.begin();
1442 text_tlist::iterator packageend = packagelist.end();
1443 mvalue *macrovalue = NULL;
1444 while ((macrovalue == NULL) && (packagehere != packageend))
1445 {
1446 // first look in the currentmacros
1447 macrovalue = currentmacros->macro_find(*packagehere, macroname);
1448 if (macrovalue == NULL)
1449 macrovalue = currentmacros->macro_find("Style", macroname);
1450
1451 // look in the default macros
1452 if (macrovalue == NULL)
1453 {
1454 // next look in the defaultmacros
1455 if (defaultmacros->macro_find (*packagehere, macroname) != NULL)
1456 {
1457 paramhere = orderparamlist->begin(); paramend = orderparamlist->end();
1458 while ((macrovalue == NULL) && (paramhere != paramend))
1459 {
1460// cerr << text_t2ascii << "\npackage: " << *packagehere << "\n";
1461// cerr << text_t2ascii << "macroname: " << macroname << "\n";
1462// cerr << text_t2ascii << "param: " << (*paramhere).param << "\n";
1463// cerr << "spec: " << (int)((*paramhere).spec) << "\n";
1464 macrovalue = defaultmacros->parameter_find(*packagehere, macroname,
1465 (*paramhere).param);
1466 paramhere++;
1467 }
1468 }
1469 }
1470
1471 // and again in the package "Style"
1472 if (macrovalue == NULL)
1473 {
1474 // next look in the defaultmacros
1475 if (defaultmacros->macro_find ("Style", macroname) != NULL)
1476 {
1477 paramhere = orderparamlist->begin(); paramend = orderparamlist->end();
1478 while ((macrovalue == NULL) && (paramhere != paramend))
1479 {
1480 macrovalue = defaultmacros->parameter_find("Style", macroname,
1481 (*paramhere).param);
1482 paramhere++;
1483 }
1484 }
1485 }
1486 if (macrovalue == NULL) packagehere++;
1487 }
1488
1489 if (macrovalue != NULL)
1490 {
1491 // we found a macro
1492
1493 // replace all the option macros (_1_, _2_, ...) in the value of this macro
1494 // and decide if we need to expand the value of this macro
1495 bool needsexpansion = false;
1496 text_t tempmacrovalue;
1497 tempmacrovalue.clear();
1498 hereit = macrovalue->value.begin();
1499 endit = macrovalue->value.end();
1500 if (hereit != endit) c = (*hereit);
1501 while (hereit != endit)
1502 {
1503 if (c == '\\')
1504 {
1505 // found an escape character
1506 needsexpansion = true;
1507 tempmacrovalue.push_back(c);
1508 c = my_ttnextchar (hereit, endit);
1509 if (hereit != endit) tempmacrovalue.push_back(c);
1510 c = my_ttnextchar (hereit, endit);
1511 }
1512 else if (c == '_')
1513 {
1514 text_t::const_iterator savedhereit = hereit;
1515
1516 // attempt to get a number
1517 int argnum = 0;
1518 unsigned short digc = my_ttnextchar (hereit, endit);
1519 while (digc >= '0' && digc <= '9') {
1520 argnum = argnum*10 + digc - '0';
1521 digc = my_ttnextchar (hereit, endit);
1522 }
1523 if (digc == '_' && argnum > 0) {
1524 // found an option macro, append the appropriate text
1525 text_tlist::iterator ttlisthere = splitmacroparam.begin();
1526 text_tlist::iterator ttlistend = splitmacroparam.end();
1527 while ((argnum > 1) && (ttlisthere != ttlistend)) {
1528 argnum--;
1529 ttlisthere++;
1530 }
1531 if (ttlisthere != ttlistend) {
1532 tempmacrovalue.append(*ttlisthere);
1533 if (findchar((*ttlisthere).begin(), (*ttlisthere).end(), '_') != (*ttlisthere).end())
1534 needsexpansion = true;
1535 }
1536
1537 c = my_ttnextchar (hereit, endit);
1538
1539 } else {
1540 // wasn't a option macro
1541 needsexpansion = true;
1542 tempmacrovalue.push_back(c);
1543 hereit = savedhereit;
1544 c = my_ttnextchar (hereit, endit);
1545 }
1546 }
1547 else
1548 {
1549 tempmacrovalue.push_back(c);
1550 c = my_ttnextchar (hereit, endit);
1551 }
1552 }
1553
1554 // recursively replace this macro (if we need to)
1555 if (needsexpansion) {
1556 expandstring (*packagehere, tempmacrovalue, outputtext, recursiondepth+1);
1557 } else {
1558 outputtext += tempmacrovalue;
1559 }
1560
1561 return true;
1562 }
1563
1564 if (logout != NULL) {
1565 (*logout) << text_t2ascii << "Warning: _" <<
1566 macropackage << ":" << macroname << "_ not found\n";
1567 }
1568
1569 return false; // didn't find the macro
1570}
1571
1572
1573void displayclass::printdefaultmacros ()
1574{
1575 defpackagemap::const_iterator packagemapit;
1576 defmacromap::const_iterator macromapit;
1577 defparammap::const_iterator parammapit;
1578 const mvalue *mvalueptr;
1579 outconvertclass text_t2ascii;
1580
1581 text_t packagename, macroname, macroparam;
1582
1583 for (packagemapit = defaultmacros->package_begin();
1584 packagemapit != defaultmacros->package_end();
1585 packagemapit++)
1586 {
1587 packagename = (*packagemapit).first;
1588 // cerr << "***package : \"" << packagename << "\"\n";
1589
1590 for (macromapit = (*packagemapit).second.begin();
1591 macromapit != (*packagemapit).second.end();
1592 macromapit++)
1593 {
1594 macroname = (*macromapit).first;
1595 // cerr << "***macroname : \"" << macroname << "\"\n";
1596
1597 for (parammapit = (*macromapit).second.begin();
1598 parammapit != (*macromapit).second.end();
1599 parammapit++)
1600 {
1601 macroparam = (*parammapit).first;
1602 mvalueptr = &((*parammapit).second);
1603 cerr << text_t2ascii << "package : \"" << packagename << "\"\n";
1604 cerr << text_t2ascii << "macroname : \"" << macroname << "\"\n";
1605 cerr << text_t2ascii << "parameters: [" << macroparam << "]\n";
1606 cerr << text_t2ascii << "filename : \"" << mvalueptr->filename << "\"\n";
1607 cerr << text_t2ascii << "value : {" << mvalueptr->value << "}\n\n";
1608 }
1609 }
1610 }
1611}
1612
1613void displayclass::printallparams ()
1614{
1615 text_tset::iterator text_tsetit;
1616 outconvertclass text_t2ascii;
1617
1618 cerr << text_t2ascii << "** allparams\n";
1619 for (text_tsetit=allparams.begin();
1620 text_tsetit!=allparams.end();
1621 text_tsetit++) {
1622 cerr << text_t2ascii << (*text_tsetit) << "\n";
1623 }
1624 cerr << text_t2ascii << "\n";
1625}
1626
1627
1628
1629/////////////////////////////////////
1630// stuff to do tricky output
1631/////////////////////////////////////
1632
1633displayclass &operator<< (outconvertclass &theoutc, displayclass &display)
1634{
1635 display.setconvertclass (&theoutc);
1636 return display;
1637}
1638
1639displayclass &operator<< (displayclass &display, const text_t &t)
1640{
1641 outconvertclass *theoutc = display.getconvertclass();
1642
1643 if (theoutc == NULL) return display;
1644
1645 text_t output;
1646 display.expandstring (t, output);
1647 (*theoutc) << output;
1648
1649 return display;
1650}
Note: See TracBrowser for help on using the repository browser.