home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / alt / sources / 2610 < prev    next >
Encoding:
Text File  |  1992-11-23  |  81.0 KB  |  3,183 lines

  1. Newsgroups: alt.sources
  2. Path: sparky!uunet!elroy.jpl.nasa.gov!swrinde!sgiblab!pacbell.com!tlhouns
  3. From: tlhouns@srv.PacBell.COM (Lee Hounshell)
  4. Subject: C++ class library "var" (version 1.1) and "VarMap" (associateive arrays)
  5. Message-ID: <1992Nov24.030101.6844@PacBell.COM>
  6. Sender: news@PacBell.COM (Pacific Bell Netnews)
  7. Organization: Pacific * Bell
  8. Date: Tue, 24 Nov 1992 03:01:01 GMT
  9. Lines: 3172
  10.  
  11. This is the latest release of "var", and "VarMap".
  12. This is a C++ object library that provides a "super-string" class with
  13. "associative array" capabilities.
  14.  
  15. The var class does a pretty good job of offering a data object that assumes
  16. its "type" at run time, based on context of use.  Rarely will you need to
  17. declare int's, or longs, or doubles or char[] or even string objects!
  18. "Var" does it all (or at least tries to).
  19.  
  20.     + var will do base data types (eg: int, long, char *, float, string ...)
  21.     + var will do arithmetic
  22.     + var will do strings and operations on strings
  23.     + var will do sub-strings and operations on sub-strings
  24.     + var will intelligently "mix" operations between mixed types
  25.     + var will do formatted output using the stream library
  26.     + individual vars can be "staticly" typed, or they can assume
  27.       type at runtime, based on context.
  28.     + VarMap will do associative arrays of vars indexed by vars.
  29.  
  30. To use this class, simply type make and a library file "libvar.a" will be
  31. created.  This class has been used extensively here at Pacific Bell as a
  32. base class in development of our own internal C++ class libraries. I've
  33. even used "var" as the YYSTYPE type inside yacc/lex programs!!
  34.  
  35. To try out the enclosed demo programs, type "make demo".
  36.  
  37. Both var and VarMap have been tested and used on the following architectures:
  38.  
  39.     - Sun C++ versions 2.0 and 2.1
  40.     - AT&T C++ versions 2.0 and 2.1
  41.     - g++ (yes, I now support GNU C++!!)
  42.  
  43. If you like (or dislike) var and/or VarMap, please drop me a line.
  44. Mail bug reports and comments to:
  45. tlhouns@srv.pacbell.com
  46.  
  47. -Lee
  48.  
  49. #----------------------------------cut here-------------------------------------
  50.  
  51. # This is a shell archive.  Remove anything before this line,
  52. # then unpack it by saving it in a file and typing "sh file".
  53. #
  54. # Wrapped by pbpal!tlhouns on Mon Nov 23 18:48:43 PST 1992
  55. # Contents:  README LEGAL_NOTICE var.3++ VarMap.3++ Makefile var.H var.C
  56. #    VarMap.H VarMap.C demo.C demo2.C
  57.  
  58. echo x - README
  59. sed 's/^@//' > "README" <<'@//E*O*F README//'
  60.  
  61. This is the latest release of "var", and "VarMap".
  62. This is a C++ object library that provides a "super-string" class with
  63. "associative array" capabilities.
  64.  
  65. The var class does a pretty good job of offering a data object that assumes
  66. its "type" at run time, based on context of use.  Rarely will you need to
  67. declare int's, or longs, or doubles or char[] or even string objects!
  68. "Var" does it all (or at least tries to).
  69.  
  70.     + var will do base data types (eg: int, long, char *, float, string ...)
  71.     + var will do arithmetic
  72.     + var will do strings and operations on strings
  73.     + var will do sub-strings and operations on sub-strings
  74.     + var will intelligently "mix" operations between mixed types
  75.     + var will do formatted output using the stream library
  76.     + individual vars can be "staticly" typed, or they can assume
  77.       type at runtime, based on context.
  78.     + VarMap will do associative arrays of vars indexed by vars.
  79.  
  80. To use this class, simply type make and a library file "libvar.a" will be
  81. created.  This class has been used extensively here at Pacific Bell as a
  82. base class in development of our own internal C++ class libraries. I've
  83. even used "var" as the YYSTYPE type inside yacc/lex programs!!
  84.  
  85. To try out the enclosed demo programs, type "make demo".
  86.  
  87. Both var and VarMap have been tested and used on the following architectures:
  88.  
  89.     - Sun C++ versions 2.0 and 2.1
  90.     - AT&T C++ versions 2.0 and 2.1
  91.     - g++ (yes, I now support GNU C++!!)
  92.  
  93. If you like (or dislike) var and/or VarMap, please drop me a line.
  94. Mail bug reports and comments to:
  95. tlhouns@srv.pacbell.com
  96.  
  97. -Lee
  98. @//E*O*F README//
  99. chmod u=rw,g=r,o=r README
  100.  
  101. echo x - LEGAL_NOTICE
  102. sed 's/^@//' > "LEGAL_NOTICE" <<'@//E*O*F LEGAL_NOTICE//'
  103.  
  104.         Any use of this source code must include, in the user documentation
  105.         and internal comments to the code, and notices to the end user as
  106.         follows:
  107.  
  108.     Copyright (c) 1992 Lee Hounshell
  109.  
  110.     LEE HOUNSHELL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF
  111.         THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS"
  112.         WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  LEE HOUNSHELL
  113.     SEVERALLY AND INDIVIDUALLY, DISCLAIM ALL WARRANTIES WITH REGARD
  114.     TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF
  115.     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO
  116.     EVENT SHALL LEE HOUNSHELL BE LIABLE FOR ANY SPECIAL, INDIRECT,
  117.     INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
  118.     RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  119.     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  120.     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.
  121.  
  122.     Permission to use, copy, modify, and distribute this software
  123.     and its documentation for any purpose and without fee is hereby
  124.     granted, provided that the above copyright notice appear in all
  125.     copies and that both that copyright notice and this permission
  126.     notice appear in supporting documentation, and that the name of
  127.     Lee Hounshell not be used in advertising in publicity pertaining
  128.     to distribution of the software without specific, written prior
  129.     permission.
  130.  
  131. @//E*O*F LEGAL_NOTICE//
  132. chmod u=rw,g=r,o=r LEGAL_NOTICE
  133.  
  134. echo x - var.3++
  135. sed 's/^@//' > "var.3++" <<'@//E*O*F var.3++//'
  136. @.po 6
  137. @.TH VAR 3++ "1/92" "Version 1.1" "Variable Base Type String Class Library"
  138.  
  139. @.SH CLASS
  140. VAR    \- Variable Base Type String Class Library
  141. @.SH SYNOPSIS
  142. @.B #include     <var.H>
  143. @.PP
  144. @.nf
  145. @.ta.5i 1.0i 4.0i
  146. \fB
  147. class var {
  148.  
  149.   public:
  150.     // Constructors & Destructors
  151.     var(void);                    // constructor
  152.     var(const varsize &);            // constructor
  153.     var(const char *);                // constructor
  154.     var(const char);                // constructor
  155.     var(const short);                // constructor
  156.     var(const unsigned short);            // constructor
  157.     var(const int);                // constructor
  158.     var(const unsigned int);            // constructor
  159.     var(const long);                // constructor
  160.     var(const unsigned long);            // constructor
  161.     var(const double);                // constructor
  162.     var(const var &);                // copy constructor
  163.     ~var(void);                    // destructor
  164.  
  165.     // Operators
  166.     var & operator = (const char *);        // assignment
  167.     var & operator = (const var &);        // assignment
  168.     char & operator [] (const int);        // indexing
  169.     subvar & operator () (int, int) const;    // substring
  170.     subvar & operator () (const int) const;    // substring
  171.     friend ostream & operator << (ostream &, const var &); // output
  172.     friend class subvar;            // substring
  173.  
  174.     // More Operators (used for arithmetic type extension)
  175.     var & operator = (const char);        // assignment
  176.     var & operator = (const short);        // assignment
  177.     var & operator = (const unsigned short);    // assignment
  178.     var & operator = (const int);        // assignment
  179.     var & operator = (const unsigned int);    // assignment
  180.     var & operator = (const long);        // assignment
  181.     var & operator = (const unsigned long);    // assignment
  182.     var & operator = (const double);        // assignment
  183.  
  184.     // Casting Operators
  185.     operator char * (void) const;        // type conversion
  186.     operator double (void) const;        // type conversion
  187.  
  188.     // Assignment Operators
  189.     var & operator ++ (void);            // increment (pre-index only)
  190.     var & operator -- (void);            // decrement (pre-index only)
  191.     var operator ! (void) const;        // not
  192.  
  193.     var operator + (const var &) const;        // addition OR concatenation
  194.     var operator - (const var &) const;        // subtraction
  195.     var operator * (const var &) const;        // multiplication
  196.     var operator / (const var &) const;        // division
  197.     var operator % (const var &) const;        // remainder
  198.  
  199.     var & operator += (const var &);        // addition OR concatenation
  200.     var & operator -= (const var &);        // subtraction
  201.     var & operator *= (const var &);        // multiplication
  202.     var & operator /= (const var &);        // division
  203.     var & operator %= (const var &);        // remainder
  204.  
  205.     var & operator += (const char &);        // addition OR concatenation
  206.     var & operator += (const char *);        // addition OR concatenation
  207.     var & operator -= (const char *);        // subtraction
  208.     var & operator *= (const char *);        // multiplication
  209.     var & operator /= (const char *);        // division
  210.     var & operator %= (const char *);        // remainder
  211.  
  212.     var & operator += (const double);        // addition OR concatenation
  213.     var & operator -= (const double);        // subtraction
  214.     var & operator *= (const double);        // multiplication
  215.     var & operator /= (const double);        // division
  216.     var & operator %= (const double);        // remainder
  217.  
  218.     friend var operator + (const char *, const var &); // addition OR concatenation
  219.     friend var operator - (const char *, const var &); // subtraction
  220.     friend var operator * (const char *, const var &); // multiplication
  221.     friend var operator / (const char *, const var &); // division
  222.     friend var operator % (const char *, const var &); // remainder
  223.     friend var operator + (const var &, const char *); // addition OR concatenation
  224.     friend var operator - (const var &, const char *); // subtraction
  225.     friend var operator * (const var &, const char *); // multiplication
  226.     friend var operator / (const var &, const char *); // division
  227.     friend var operator % (const var &, const char *); // remainder
  228.  
  229.     friend var operator + (const var &, const double); // addition OR concatenation
  230.     friend var operator - (const var &, const double); // subtraction
  231.     friend var operator * (const var &, const double); // multiplication
  232.     friend var operator / (const var &, const double); // division
  233.     friend var operator % (const var &, const double); // remainder
  234.     friend var operator + (const double, const var &); // addition OR concatenation
  235.     friend var operator - (const double, const var &); // subtraction
  236.     friend var operator * (const double, const var &); // multiplication
  237.     friend var operator / (const double, const var &); // division
  238.     friend var operator % (const double, const var &); // remainder
  239.  
  240.     // Equality Operators
  241.     int operator == (const var &) const;    // equality
  242.     int operator != (const var &) const;    // inequality
  243.     int operator < (const var &) const;        // less than
  244.     int operator > (const var &) const;        // greater than
  245.     int operator <= (const var &) const;    // less than or equal
  246.     int operator >= (const var &) const;    // greater than or equal
  247.  
  248.     friend int operator == (const var &, const char *); // equality
  249.     friend int operator != (const var &, const char *); // inequality
  250.     friend int operator < (const var &, const char *);  // less than
  251.     friend int operator > (const var &, const char *);  // greater than
  252.     friend int operator <= (const var &, const char *); // less than or equal
  253.     friend int operator >= (const var &, const char *); // greater than or equal
  254.     friend int operator == (const char *, const var &); // equality
  255.     friend int operator != (const char *, const var &); // inequality
  256.     friend int operator < (const char *, const var &);  // less than
  257.     friend int operator > (const char *, const var &);  // greater than
  258.     friend int operator <= (const char *, const var &); // less than or equal
  259.     friend int operator >= (const char *, const var &); // greater than or equal
  260.  
  261.     friend int operator == (const var &, const double); // equality
  262.     friend int operator != (const var &, const double); // inequality
  263.     friend int operator < (const var &, const double);  // less than
  264.     friend int operator > (const var &, const double);  // greater than
  265.     friend int operator <= (const var &, const double); // less than or equal
  266.     friend int operator >= (const var &, const double); // greater than or equal
  267.     friend int operator == (const double, const var &); // equality
  268.     friend int operator != (const double, const var &); // inequality
  269.     friend int operator < (const double, const var &);  // less than
  270.     friend int operator > (const double, const var &);  // greater than
  271.     friend int operator <= (const double, const var &); // less than or equal
  272.     friend int operator >= (const double, const var &); // greater than or equal
  273.  
  274.     // Custom Interface
  275.     void null(int);                // "null" out string
  276.     void changesize(int);            // change allocated memory
  277.     int length(void) const;            // length of string
  278.     const char * vartype(void) const;        // name of this var type
  279.     void change_type(const char *);        // change var type
  280.     int is_string(void) const;            // test var type
  281.     int is_double(void) const;            // test var type
  282.     int is_long(void) const;            // test var type
  283.     int strchr(const char) const;        // strchr(char) index
  284.     int strrchr(const char) const;        // strrchr(char) index
  285.     var & concat(const var &);            // concatenation
  286.     var & format(const char *);            // set output format
  287. };
  288. @.fi
  289. \fP
  290.  
  291. @.SH DESCRIPTION
  292. Class \fBvar\fP represents a \fBstring\fP object class that also provides all
  293. the traditional functionality of the C base types: char, int, long, float, double, and char*.
  294. \fBVar\fP, is in many ways a "super-string" class.
  295. The var class does a pretty good job of offering a base data "container" object that can either
  296. assume its "type" at run time, based on context or remain a "fixed" type, always.
  297.  
  298. @.SS var will do
  299. @.TP 2
  300. +
  301. all the base data types (eg: short, int, long, char *, float, double ...)
  302. @.TP 2
  303. +
  304. string types
  305. @.TP 2
  306. +
  307. arithmetic
  308. @.TP 2
  309. +
  310. strings and operations on strings
  311. @.TP 2
  312. +
  313. sub-strings and operations on sub-strings
  314. @.TP 2
  315. +
  316. intelligent "mixing" of operations between mixed types
  317. @.TP 2
  318. +
  319. formatted output using the stream library
  320.  
  321. @.SH PUBLIC CONSTRUCTORS
  322. @.SS var(void);
  323. This constructor is used to declare an "untyped" var object.  Type is determined
  324. at run-time, based on context of use.
  325.  
  326. @.SS var(const varsize &);
  327. This constructor is used to declare an "string" var object, with preallocated memory.
  328. The object's type can change at run-time, based on context.
  329.  
  330. @.SS var(const char *);
  331. This constructor is used to declare a "string" object initialize from a "char *".
  332. The object's type can change at run-time, based on context.
  333.  
  334. @.SS var(const char);
  335. This constructor is used to declare an "numeric" var object, initialized from a char.
  336. The object's type can change at run-time, based on context.
  337.  
  338. @.SS var(const short);
  339. This constructor is used to declare an "numeric" var object, initialized from a short.
  340. The object's type is fixed and will not change at run-time.
  341.  
  342. @.SS var(const unsigned short);
  343. This constructor is used to declare an "numeric" var object, initialized from an unsigned short.
  344. The object's type is fixed and will not change at run-time.
  345.  
  346. @.SS var(const int);
  347. This constructor is used to declare an "numeric" var object, initialized from an int.
  348. The object's type is fixed and will not change at run-time.
  349.  
  350. @.SS var(const unsigned int);
  351. This constructor is used to declare an "numeric" var object, initialized from an unsigned int.
  352. The object's type is fixed and will not change at run-time.
  353.  
  354. @.SS var(const long);
  355. This constructor is used to declare an "numeric" var object, initialized from a long.
  356. The object's type is fixed and will not change at run-time.
  357.  
  358. @.SS var(const unsigned long);
  359. This constructor is used to declare an "numeric" var object, initialized from an unsigned long.
  360. The object's type is fixed and will not change at run-time.
  361.  
  362. @.SS var(const double);
  363. This constructor is used to declare an "numeric" var object, initialized from a double or float.
  364. The object's type is fixed and will not change at run-time.
  365.  
  366. @.SS var(const var &);
  367. This constructor is used to declare a var object, which is a copy of another var.
  368. The object assumes the characteristics of the initializing object.
  369.  
  370. @.SS ~var(void);
  371. The destructor returns all memory allocated by the object back to the OS.
  372.  
  373.  
  374. @.SH PUBLIC OPERATORS
  375. @.SS Arithmetic and Concatenation Operators
  376. Most operators (+, -, /, *, %, +=, etc..) will operate as expected.
  377. The "+" and "+=" operators will either do addition or concatenation, as appropriate.
  378. if concatenation is required, then the \fB"var.concat(var)"\fP member function should
  379. be used.
  380.  
  381. @.SS Relational Operators
  382. These also operate as expected.  If "string" objects are compared, the comparison
  383. will be as performed by \fBstrcmp(3)\fP.
  384.  
  385. @.SS The Indexing Operator []
  386. You can index a character from inside a \fBvar\fP by using
  387. the \fB"char & operator [] (const int);"\fP operator.
  388. If you attempt to index \fBbeyond\fP a \fBvar\fP object's current end, then
  389. the referenced object will be automatically extended (padded with spaces)
  390. to the desired length.
  391. A reference to the character is returned, which can be assigned to.
  392. Do not assign the NULL character using this operator.
  393. Instead call the member function \fB"null(index)"\fP.
  394.  
  395. @.SS Sub-strings
  396. Two operators are provide for substring operation.  The
  397. first, \fB"subvar & operator () (int start, int length) const;"\fP
  398. will extract a string starting at "start" for "length" characters.
  399. The second, \fB"subvar & operator () (const int start) const;"\fP will
  400. extract a string starting at "start" to the end of the string.
  401.  
  402. @.SS Type Casting
  403. Only two type casts are required by \fBvar\fP. The first converts
  404. the object into a "char *".  The second converts the object into a
  405. double.  Implicit conversion between "char *" and "double" types
  406. will be performed by your C++ compiler.
  407.  
  408. @.SS Formatted Output
  409. You can use \fBvar\fP with the io stream library.  Objects can be
  410. output using the ">>" operator.
  411. For formatted output, be sure to set the object's "format template"
  412. prior to calling the ">>" operator.  (see \fB"var & format(const char *);"\fP)
  413.  
  414. @.SH PUBLIC MEMBER FUNCTIONS
  415.  
  416. @.SS Truncating a string 
  417. The \fB"void null(int index);"\fP function will truncate a \fBvar\fP
  418. object, starting from the specified index postion.
  419.  
  420. @.SS Memory Allocation
  421. The \fB"void changesize(int newsize);"\fP can be used to increase
  422. allocated memory for a var.  Memory can NOT be decreased.  Allocated
  423. memory is returned to the heap when an object goes out of scope.
  424.  
  425. @.SS Determining Var's Length
  426. The \fB"int length(void) const;"\fP function returns the "size" of a \fBvar\fP.
  427.  
  428. @.SS Determining Var's Type
  429. The \fB"const char * vartype(void) const;"\fP function returns the "type" of a \fBvar\fP.
  430. Possible types are: "VAR_STRING", "VAR_LONG" and "VAR_DOUBLE".
  431.  
  432. @.SS Explititly Changing a Var's Type
  433. The \fB"void change_type(const char *newtype);"\fP function can be used
  434. to set an exact type.  Valid values for "newtype" are "string", "short",
  435. "unsigned short", "int", "unsigned int", "long", "unsigned long",
  436. "float", and "double".
  437.  
  438. @.SS Testing a Var's Type
  439. Three functions are provided that allow testing a \fBvar\fP type.
  440. They are as follows: \fB"int is_string(void) const;"\fP,
  441. \fB"int is_double(void) const;"\fP, and \fB"int is_long(void) const;"\fP
  442.  
  443. @.SS Searching for a Character
  444. Two functions are provided that search a \fBvar\fP for a specified
  445. character.  Both return an offset.  The first \fB"int strchr(const char) const;"\fP
  446. searches forward.  The second, \fB"int strrchr(const char) const;"\fP
  447. searches backward.
  448.  
  449. @.SS Concatenation
  450. Concatenation can be forced, regardless of type with the \fB"var & concat(const var &);"\fP
  451. function.
  452.  
  453. @.SS Setting the Output Format
  454. The \fB"var & format(const char *fmt);"\fP function will allow you to specify an
  455. output format.  This format will remain in effect until changed.  Printf()
  456. style output formats can be introduced anywhere in the format statment.
  457. Multiple formateed output directives can appear in the same "fmt".  Each
  458. directive will receive a copy of the object.  Automatic type conversion will
  459. occur.
  460.  
  461.  
  462. @.SH AUTHOR
  463. Lee Hounshell - 1/92
  464.  
  465. @.SH EXAMPLE
  466. @.nf
  467. #include    <var.H>
  468.  
  469. main ()
  470. {
  471.     var value;                // declare an "untyped" var
  472.     value = "hello world";        // initialize it
  473.     cout << value << "\n";        // output "hello world"
  474.     value = value(3, value.length() - 6); // substring example
  475.     cout << value << "\n";        // output "lo wo"
  476.     value = 34;                // assignment of int
  477.     value++;                // increment
  478.     value += 42.375;            // add 42.375 to present value
  479.     cout << value << "\n";        // output "77.375"
  480.     cout << value.format("formatted output example %05d of value\n");
  481.     cout << value.format("multiple outputs #1=%d, #2=%9.2f of value\n");
  482.     value.null(2);            // truncate string
  483.     value += " sunset strip";        // concatenate a string
  484.     cout << value.format("%s\n");    // output "77 sunset strip"
  485.     cout << value[3] << value[4] << value[5] << "\n"; // output "sun"
  486. }
  487. @.fi
  488.  
  489. @.SH SUPERCLASSES
  490. none.
  491.  
  492. @.SH SUBCLASSES
  493. none
  494.  
  495. @.SH BUGS
  496. Assignment of an array of vars to another array of vars
  497. must currently be done one element at a time.
  498. Var now works with g++. (version 1.1)
  499. String contatenation problem fixed. (version 1.1)
  500. Memory leak fixed. (version 1.1)
  501.  
  502. @//E*O*F var.3++//
  503. chmod u=rw,g=r,o=r var.3++
  504.  
  505. echo x - VarMap.3++
  506. sed 's/^@//' > "VarMap.3++" <<'@//E*O*F VarMap.3++//'
  507. @.po 6
  508. @.TH VARMAP 3++ "1/92" "Version 1.0" "VAR Associative Array Class Library"
  509.  
  510. @.SH CLASS
  511. VARMAP    \- Variable Base Type Associative Array Class Library
  512. @.SH SYNOPSIS
  513. @.B #include     <VarMap.H>
  514. @.PP
  515. @.nf
  516. @.ta.5i 1.0i 4.0i
  517. \fB
  518. class VarMap {
  519.  
  520.   public:
  521.     // Standard Interface
  522.     const var & type(void) const;        // who am i
  523.  
  524.     // Constructors & Destructor
  525.     VarMap(int type = VARMAP_FIFO);
  526.     ~VarMap(void) {remove();}
  527.  
  528.     // Operators
  529.     VarMap & operator = (const VarMap &);    // assign VarMaps
  530.     int operator == (VarMap &) const;        // equality
  531.     int operator != (VarMap &) const;        // inequality
  532.     var & operator [] (const var index);    // index/create entry
  533.  
  534.     friend ostream & operator << (ostream &, const VarMap &); // output
  535.     friend TraceStream & operator << (TraceStream &, const VarMap &);
  536.  
  537.     // Standard Member Functions
  538.     void print(ostream &) const;        // output
  539.  
  540.     // Custom Interface - see VarMap man pages for use
  541.     int    append(var newkey, var newvalue);    // append to map
  542.     int    push(var newkey, var newvalue);        // push a var
  543.     var    pop(void);                // pop a var
  544.     int    empty(void) const;            // is map empty
  545.     int    at_start(void) const;            // at head of map
  546.     int    at_end(void) const;            // at end of map
  547.     int    position(void);                // index within map
  548.     int    size(void) const;            // length of map
  549.     void remove(void);                // remove all items
  550.     void delete_here(void);            // remove this item
  551.     int    element(const var & index);        // test for element
  552.     var & key(void);                // current key
  553.     var & value(void);                // current value
  554.     void display(ostream & out = cerr);        // print the map
  555.     void first(void);                // point to first node
  556.     void next(void);                // point to next node
  557.     void last(void);                // point to last node
  558. };
  559. @.fi
  560. \fP
  561.  
  562. @.SH DESCRIPTION
  563. Class \fBVarMap\fP represents an \fBassociative array\fP object class that allows dynamic
  564. arrays of \fBvar\fP objects to be indexed by another \fBvar\fP object.
  565. \fBVarMap\fP, is in many ways a "super-associative-array" class.
  566. The VarMap class does a pretty good job of offering an associative array object with an
  567. index of virtually \fBany base type\fP.  It also provides a base data "container" object
  568. that can assume its "type" at run time, based on context.  VarMap can also function as a "stack"
  569. object, with both FIFO (first-in-first-out) and LIFO (last-in-last-out) capabilities.
  570.  
  571. @.SH PUBLIC CONSTRUCTORS
  572. @.SS VarMap(int type = VARMAP_FIFO);
  573. This constructor is used to declare a VarMap object.  The newly created object will
  574. initially contain NO data elements.  If the paramater \fBVARMAP_LIFO\fP is specified,
  575. then this object will use LIFO (last-in-first-out) stack operations.  If either no
  576. parameter or \fBVARMAP_FIFO\fP is specified, then FIFO (first-in-first-out) stack
  577. operations will occur on this object.  Type of the indexed object
  578. is determined at run-time, based on context of use.
  579.  
  580. @.SS ~VarMap(void);
  581. The destructor returns all memory allocated by the object back to the OS.
  582.  
  583. @.SH PUBLIC OPERATORS
  584. @.SS The Assignment Operator
  585. The assignment operator (=) will operate as expected.
  586. As no \fBcopy constructor\fP exists at present for \fBVarMap\fP, you will need
  587. to use this operator to initialize copies of other VarMaps.
  588.  
  589. @.SS Relational Operators
  590. Only the \fBequality\fP (==) and \fBinequality\fP (!=) operators are currently implemented.
  591. These operate as expected.  The objects must be \fBexactly\fP the same to match.
  592.  
  593. @.SS The Indexing Operator []
  594. You can index any \fBvar\fP object inside a \fBVarMap\fP object by using
  595. the \fB"var & operator [] (const var);"\fP operator.  WARNING!! If you attempt
  596. to index an object that does not yet exist, then it will be created automatically.
  597. To test whether or not an object exists without creating it, use the \fBelement(const var)\fP
  598. member function.  A reference to the indexed \fBvar\fP is returned, which can be assigned to.
  599.  
  600. @.SS Type Casting
  601. There are no cast operators for \fBVarMap\fP objects; however, you may cast the
  602. indexed \fBvar\fP object to any base type.
  603.  
  604. @.SS Output
  605. You can output the contents of an entire \fBVarMap\fP object using the io stream library.
  606. Objects can be output using the ">>" operator.
  607. For formatted output, be sure to index and set each \fBvar\fP element's "format template"
  608. prior to calling the ">>" operator.  (see \fB"var & format(const char *);"\fP)
  609.  
  610. @.SH PUBLIC MEMBER FUNCTIONS
  611.  
  612. @.SS Appending a New Element and Key to a VarMap
  613. The \fB"int append(var newkey, var newvalue);\fP function will append a new element
  614. to the VarMap with the index \fBnewkey\fP and the value \fBnewvalue\fP.  The size of
  615. the VarMap is increased by one.
  616.  
  617. @.SS Pushing a New Element (and Key) onto a VarMap
  618. The \fB"int push(var newkey, var newvalue);\fP function will push a new element
  619. to the \fBVarMap\fP stack with the index \fBnewkey\fP and the value \fBnewvalue\fP.
  620. The size of the \fBVarMap\fP is increased by one. The order that this element will be
  621. later \fBpopped\fP is determined by the \fBVarmap\fP object's initial VARMAP_FIFO
  622. or VARMAP_LIFO constructor argument.
  623.  
  624. @.SS Poping an Element from a VarMap
  625. The \fB"int pop(void);\fP function will pop the next appropriate element
  626. from the \fBVarMap\fP stack.  The size of the \fBVarMap\fP is decreased by one.
  627. The order that each element is popped is determined by the \fBVarmap\fP object's
  628. initial VARMAP_FIFO or VARMAP_LIFO constructor argument.
  629.  
  630. @.SS Testing a VarMap Index
  631. The \fB"int element(const var & index) const;"\fP function returns 1 if a \fBVarMap\fP entry
  632. exists for the passed index value, 0 otherwise.
  633.  
  634. @.SS Determining if a VarMap is Empty
  635. The \fB"int empty(void) const;"\fP function returns 1 if a \fBVarMap\fP is empty, 0 otherwise.
  636.  
  637. @.SS Determining VarMap's Size
  638. The \fB"int size(void) const;"\fP function returns the "size" of a \fBVarMap\fP.
  639.  
  640. @.SS Relative "Positions" Inside a VarMap Object
  641. Six member functions exist to allow user to "walk" through a \fBVarMap's\fP elements and/or test
  642. where (relatively speaking) you are currently positioned within the map.  The first two are used
  643. to test if you are at the \fBhead\fP or \fBtail\fP of the \fBVarMap\fP.
  644. The \fB"int at_start(void) const;"\fP function returns 1 if you are at the head of a \fBVarMap\fP, 0 otherwise.
  645. The \fB"int at_end(void) const;"\fP function returns 1 if you are at the tail of a \fBVarMap\fP, 0 otherwise.
  646. The \fB"int position(void) const;"\fP function returns relative \fBnumerical position\fP of the current
  647. node in a \fBVarMap\fP. Three memeber functions allow you to change the current position.
  648. The \fB"void first(void) const;"\fP function moves the current \fBVarMap\fP pointer to the head of the map.
  649. The \fB"void last(void) const;"\fP function moves the current \fBVarMap\fP pointer to the tail of the map.
  650. The \fB"void next(void) const;"\fP function moves the current \fBVarMap\fP pointer to the next entry of the map.
  651.  
  652. @.SS Deleting the current VarMap Entry
  653. The \fB"void delete_here(void) const;"\fP function will destroy the currently \fBpointed to\fP entry.
  654. This is often used in conjunction with the \fBfirst()\fP and \fBnext()\fP function to traverse a
  655. \fBVarMap\fP and remove nodes at random.  After a \fBdelete_here()\fP call, the \fBVarMap\fP will be
  656. pointing to the \fBnext\fP node (just as if a \fBnext()\fP call had been made).
  657.  
  658. @.SS Deleting all VarMap Entries
  659. The \fB"void remove(void) const;"\fP function will destroy every entry in the \fBVarMap\fP.  After this
  660. call, the \fBVarMap's\fP size will be zero.
  661.  
  662. @.SS Extracting the Current Entry's Key Value
  663. The \fB"var & key(void);"\fP function will return a reference to the current \fBVarMap\fP element's key.
  664.  
  665. @.SS Extracting the Current Entry's Data Value
  666. The \fB"var & value(void);"\fP function will return a reference to the current \fBVarMap\fP element.
  667.  
  668. @.SS Displaying a VarMap
  669. The \fB"void display(ostream & out = cerr);"\fP function will output all elements and keys of a \fBVarMap\fP
  670. to the passed ostream.  By default, output is sent to \fBcerr\fP.
  671.  
  672. @.SH AUTHOR
  673. Lee Hounshell - 1/92
  674.  
  675. @.SH EXAMPLE
  676. @.nf
  677. #include    <VarMap.H>
  678.  
  679. main ()
  680. {
  681.     VarMap aa;                // declare a VarMap
  682.     var lee = "foobar";
  683.     if (!aa.element(lee)) {
  684.     aa[lee] = "hello world";    // create/assign using index "foobar"
  685.     }
  686.     aa[42] = "testing 123";        // create/assign using index "42"
  687.     aa[5] = 123.45;            // create/assign using index "5"
  688.     aa.display();            // display this map to stderr
  689. }
  690. @.fi
  691.  
  692. @.SH SUPERCLASSES
  693. none.
  694.  
  695. @.SH SUBCLASSES
  696. var
  697.  
  698. @.SH BUGS
  699.  
  700. @//E*O*F VarMap.3++//
  701. chmod u=rw,g=r,o=r VarMap.3++
  702.  
  703. echo x - Makefile
  704. sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
  705. ############################################################################
  706. #       make - compiles the C++ library (libvar.a) 
  707. #       make clean - removes all .o files generated in these procedures
  708. #       make clobber - removes all libraries, cleans up .o's
  709. ############################################################################
  710.  
  711.  
  712. # from the two below, pick the operating system closest to yours:
  713.  
  714. # If you're using g++, define CC and INCDIRS as appropriate for you
  715. CC    = g++
  716. INCDIRS = -I. -I/usr/local/lib/g++-include
  717.  
  718. # If you're using Sun or AT&T C++ version 2.0 or 2.1 use these..
  719. #CC    = CC
  720. #INCDIRS = -I.
  721.  
  722. #SYS    = HP
  723. SYS    = SUN
  724.  
  725. #-----don't change anything after this line-----
  726.  
  727. CFLAGS    = -O $(INCDIRS)
  728. ARFLAGS    = rv
  729.  
  730.  
  731. is_bsd    = test $(SYS) = SUN
  732.  
  733. all:    libvar.a
  734.  
  735. C++FILES    = var.C VarMap.C
  736. INS_HFILES    = var.H VarMap.H
  737. HFILES        = $(INS_HFILES)
  738.  
  739. OBJECTS = ${C++FILES:.C=.o}
  740.  
  741. libvar.a:    $(OBJECTS)
  742.         ar $(ARFLAGS) $@ $?
  743.         if $(is_bsd) ; then ranlib $@; fi
  744.  
  745. $(OBJECTS):    $(HFILES)
  746.  
  747. demo:        libvar.a demo.C demo2.C
  748.         $(CC) $(INCDIRS) demo.C -L. -lvar -o demo
  749.         $(CC) $(INCDIRS) demo2.C -L. -lvar -o demo2
  750.  
  751. clean:    
  752.         rm -f *.o a.out core $(OBJECTS)
  753.         cd demo; $(MAKE) clean
  754.  
  755. clobber:    clean
  756.         rm -fr $(DOTAS)
  757.         cd demo; $(MAKE) clobber
  758.  
  759. #####
  760. #####
  761. #.SUFFIXES: .o .C .C~ .c .c~
  762. @.SUFFIXES: .o .C .C~
  763. @.C~.C:
  764.     -cd $(<D); $(GET) $(GFLAGS) $(<F)
  765. @.C.c:
  766.     $(CC) $(CFLAGS) -Fc $*.C > $*.c
  767. @.C.o:
  768.     $(CC) $(CFLAGS) -c $*.C
  769. @.C~.o:
  770.     -cd $(<D); $(GET) $(GFLAGS) $(<F)
  771.     $(CC) $(CFLAGS) -c $*.C
  772.  
  773. @//E*O*F Makefile//
  774. chmod u=rw,g=r,o=r Makefile
  775.  
  776. echo x - var.H
  777. sed 's/^@//' > "var.H" <<'@//E*O*F var.H//'
  778. //
  779. // NAME:    var.H
  780. //
  781. // PURPOSE:    C++ Generic "Universal Variable" Class Library Header File
  782. // VERSION:    1.1
  783. // AUTHOR:    Lee Hounshell
  784. // LAST MOD:    Mon Nov 23 08:56:24 PST 1992
  785. //
  786.  
  787. #ifndef VAR_H
  788. #define VAR_H
  789.  
  790. #include    <stream.h>
  791. #include    "string.h"
  792.  
  793. // -----------------------------------------------------------------------------
  794. //
  795. class varsize {
  796.     // dummy class needed for var constructor of specific size that
  797.     // doesn't conflict with the var integer type constructor
  798.     public:
  799.     // Constructors & Destructors
  800.     varsize(int sz);                // constructor
  801.     int size;                    // size of var
  802. };
  803.  
  804. class subvar;
  805.  
  806. // -----------------------------------------------------------------------------
  807. //
  808. class var {
  809.  
  810.     public:
  811.     // Standard Interface
  812.     const var & type(void) const;            // who am i
  813.  
  814.     // Constructors & Destructors
  815.     var(void);                    // constructor
  816.     var(const varsize &);                // constructor
  817.     var(const char *);                // constructor
  818.     var(const char);                // constructor
  819.     var(const short);                // constructor
  820.     var(const unsigned short);            // constructor
  821.     var(const int);                    // constructor
  822.     var(const unsigned int);            // constructor
  823.     var(const long);                // constructor
  824.     var(const unsigned long);            // constructor
  825.     var(const double);                // constructor
  826.     var(const var &);                // copy constructor
  827.     ~var(void);                    // destructor
  828.  
  829.     // Operators
  830.     var & operator = (const char *);        // assignment
  831.         var & operator = (const var &);            // assignment
  832.         char & operator [] (const int);            // indexing
  833.         subvar & operator () (int, int) const;        // substring
  834.         subvar & operator () (const int) const;        // substring
  835.         friend ostream & operator << (ostream &, const var &); // output
  836.     friend class subvar;                // substring
  837.  
  838.     // More Operators (used for arithmetic type extension)
  839.     var & operator = (const char);            // assignment
  840.     var & operator = (const short);            // assignment
  841.     var & operator = (const unsigned short);    // assignment
  842.     var & operator = (const int);            // assignment
  843.     var & operator = (const unsigned int);        // assignment
  844.     var & operator = (const long);            // assignment
  845.     var & operator = (const unsigned long);        // assignment
  846.     var & operator = (const double);        // assignment
  847.  
  848.     // Casting Operators
  849.     operator char * (void) const;            // type conversion
  850.     operator double (void) const;            // type conversion
  851.  
  852.     // Assignment Operators
  853.         var & operator ++ (void);            // increment (pre-index only)
  854.         var & operator -- (void);            // decrement (pre-index only)
  855.         var operator ! (void) const;            // not
  856.  
  857.         var operator + (const var &) const;        // addition OR concatenation
  858.         var operator - (const var &) const;        // subtraction
  859.         var operator * (const var &) const;        // multiplication
  860.         var operator / (const var &) const;        // division
  861.         var operator % (const var &) const;        // remainder
  862.  
  863.         var & operator += (const var &);        // addition OR concatenation
  864.         var & operator -= (const var &);        // subtraction
  865.         var & operator *= (const var &);        // multiplication
  866.         var & operator /= (const var &);        // division
  867.         var & operator %= (const var &);        // remainder
  868.  
  869.         var & operator += (const char &);        // addition OR concatenation
  870.         var & operator += (const char *);        // addition OR concatenation
  871.         var & operator -= (const char *);        // subtraction
  872.         var & operator *= (const char *);        // multiplication
  873.         var & operator /= (const char *);        // division
  874.         var & operator %= (const char *);        // remainder
  875.  
  876.         var & operator += (const double);        // addition OR concatenation
  877.         var & operator -= (const double);        // subtraction
  878.         var & operator *= (const double);        // multiplication
  879.         var & operator /= (const double);        // division
  880.         var & operator %= (const double);        // remainder
  881.  
  882.     friend var operator + (const char *, const var &); // addition OR concatenation
  883.     friend var operator - (const char *, const var &); // subtraction
  884.     friend var operator * (const char *, const var &); // multiplication
  885.     friend var operator / (const char *, const var &); // division
  886.     friend var operator % (const char *, const var &); // remainder
  887.     friend var operator + (const var &, const char *); // addition OR concatenation
  888.     friend var operator - (const var &, const char *); // subtraction
  889.     friend var operator * (const var &, const char *); // multiplication
  890.     friend var operator / (const var &, const char *); // division
  891.     friend var operator % (const var &, const char *); // remainder
  892.  
  893.     friend var operator + (const var &, const double); // addition OR concatenation
  894.     friend var operator - (const var &, const double); // subtraction
  895.     friend var operator * (const var &, const double); // multiplication
  896.     friend var operator / (const var &, const double); // division
  897.     friend var operator % (const var &, const double); // remainder
  898.     friend var operator + (const double, const var &); // addition OR concatenation
  899.     friend var operator - (const double, const var &); // subtraction
  900.     friend var operator * (const double, const var &); // multiplication
  901.     friend var operator / (const double, const var &); // division
  902.     friend var operator % (const double, const var &); // remainder
  903.  
  904.     // Equality Operators
  905.         int operator == (const var &) const;        // equality
  906.         int operator != (const var &) const;        // inequality
  907.         int operator < (const var &) const;        // less than
  908.         int operator > (const var &) const;        // greater than
  909.         int operator <= (const var &) const;        // less than or equal
  910.         int operator >= (const var &) const;        // greater than or equal
  911.  
  912.     friend int operator == (const var &, const char *); // equality
  913.     friend int operator != (const var &, const char *); // inequality
  914.     friend int operator < (const var &, const char *);  // less than
  915.     friend int operator > (const var &, const char *);  // greater than
  916.     friend int operator <= (const var &, const char *); // less than or equal
  917.     friend int operator >= (const var &, const char *); // greater than or equal
  918.     friend int operator == (const char *, const var &); // equality
  919.     friend int operator != (const char *, const var &); // inequality
  920.     friend int operator < (const char *, const var &);  // less than
  921.     friend int operator > (const char *, const var &);  // greater than
  922.     friend int operator <= (const char *, const var &); // less than or equal
  923.     friend int operator >= (const char *, const var &); // greater than or equal
  924.  
  925.     friend int operator == (const var &, const double); // equality
  926.     friend int operator != (const var &, const double); // inequality
  927.     friend int operator < (const var &, const double);  // less than
  928.     friend int operator > (const var &, const double);  // greater than
  929.     friend int operator <= (const var &, const double); // less than or equal
  930.     friend int operator >= (const var &, const double); // greater than or equal
  931.     friend int operator == (const double, const var &); // equality
  932.     friend int operator != (const double, const var &); // inequality
  933.     friend int operator < (const double, const var &);  // less than
  934.     friend int operator > (const double, const var &);  // greater than
  935.     friend int operator <= (const double, const var &); // less than or equal
  936.     friend int operator >= (const double, const var &); // greater than or equal
  937.  
  938.     // Custom Interface
  939.     void null(int);                    // "null" out string
  940.     void changesize(int);                // change allocated memory
  941.     int length(void) const;                // length of string
  942.     const char * vartype(void) const;        // name of this var type
  943.     void change_type(const char *);            // change var type
  944.     int is_string(void) const;            // test var type
  945.     int is_double(void) const;            // test var type
  946.     int is_long(void) const;            // test var type
  947.     int strchr(const char) const;            // strchr(char) index
  948.     int strrchr(const char) const;            // strrchr(char) index
  949.     var & concat(const var &);            // concatenation
  950.     var & format(const char *);            // set output format
  951.     void print(ostream &) const;            // output
  952.  
  953.     protected:
  954.  
  955.     private:
  956.     int    numcheck(const char *) const;        // determine is_numeric value
  957.  
  958.     short    fixed;                    // 1=fixed data type
  959.     short    is_numeric;                // 0=string, 1=short/int/long, 2=float/double
  960.     int    data_str_len;                // length of allocated "string"
  961.     int    data_str_end;                // index to current "end" of string
  962.     char    *data_str;                // for "string" data
  963.     char    *format_str;                // the output format string
  964.  
  965. };
  966.  
  967.  
  968. class subvar : public var {
  969.     public:
  970.         var & operator = (const var &);            // substring replacement
  971.     var        *varptr;
  972.     unsigned    offset;
  973.     unsigned    length;
  974. };
  975.  
  976.  
  977. // global conversion functions
  978. char *itoa(const int foo);
  979. char *uitoa(const unsigned int foo);
  980. char *dtoa(const double foo);
  981. double atod(char * foo);
  982.  
  983. #ifdef HP
  984.     char *ltoa(long foo);
  985.     char *ultoa(unsigned long foo);
  986. #else
  987.     char *ltoa(const long foo);
  988.     char *ultoa(const unsigned long foo);
  989. #endif
  990.  
  991.  
  992. #endif
  993.  
  994. @//E*O*F var.H//
  995. chmod u=rw,g=r,o=r var.H
  996.  
  997. echo x - var.C
  998. sed 's/^@//' > "var.C" <<'@//E*O*F var.C//'
  999. //
  1000. // NAME:    var.C
  1001. //
  1002. // PURPOSE:    C++ Generic "Universal Variable" library class
  1003. // VERSION:    1.1
  1004. // AUTHOR:    Lee Hounshell
  1005. // LAST MOD:    Mon Nov 23 08:56:24 PST 1992
  1006. //
  1007.  
  1008. #include    <stddef.h>
  1009. #include    <stream.h>
  1010. #include    <stdlib.h>
  1011. #include    <ctype.h>
  1012. #include    <string.h>
  1013. #include    <memory.h>
  1014. #include    "var.H"
  1015.  
  1016. const int    VAR_PAD_SIZE        = 128;
  1017. const int    VAR_DEF_SIZE        = 16;
  1018.  
  1019. const short    VAR_STRING        = 0;
  1020. const short    VAR_LONG        = 1;
  1021. const short    VAR_DOUBLE        = 2;
  1022.  
  1023. char *    DEFAULT_STRING_FORMAT        = "'%s'";
  1024. char *    DEFAULT_INT_FORMAT        = "%d";
  1025. char *    DEFAULT_UINT_FORMAT        = "%u";
  1026. char *    DEFAULT_LONG_FORMAT        = "%ld";
  1027. char *    DEFAULT_ULONG_FORMAT        = "%lu";
  1028. char *    DEFAULT_DOUBLE_FORMAT        = "%9.2f";
  1029.  
  1030. // -----------------------------------------------------------------------------
  1031.  
  1032.  
  1033. const var & var::type(void) const
  1034. {
  1035.     static const var objtype = "var";
  1036.     return objtype;
  1037. }
  1038.  
  1039.  
  1040. varsize::varsize(int sz)
  1041. {
  1042.     size = sz;
  1043. }
  1044.  
  1045.  
  1046. var::var(void)
  1047. {
  1048.     fixed = 0;
  1049.     is_numeric = VAR_STRING;
  1050.     data_str_len = VAR_DEF_SIZE;
  1051.     data_str_end = 0;
  1052.     data_str = new char[data_str_len];
  1053.     data_str[0] = 0;
  1054.     format_str = DEFAULT_STRING_FORMAT;
  1055. }
  1056.  
  1057.  
  1058. var::var(const char *str)
  1059. {
  1060.     fixed = 1;
  1061.     is_numeric = VAR_STRING;
  1062.     data_str_end = strlen(str);
  1063.     data_str_len = data_str_end + VAR_DEF_SIZE;
  1064.     data_str = new char[data_str_len];
  1065.     strcpy(data_str, str);
  1066.     format_str = DEFAULT_STRING_FORMAT;
  1067. }
  1068.  
  1069.  
  1070. var::var(const varsize &vsz)
  1071. {
  1072.     fixed = 0;
  1073.     is_numeric = VAR_STRING;
  1074.     data_str_len = vsz.size + VAR_DEF_SIZE;
  1075.     data_str_end = 0;
  1076.     data_str = new char[data_str_len];
  1077.     data_str[0] = 0;
  1078.     format_str = DEFAULT_STRING_FORMAT;
  1079. }
  1080.  
  1081.  
  1082. var::var(const char ch)
  1083. {
  1084.     fixed = 0;
  1085.     is_numeric = VAR_STRING;
  1086.     data_str_len = VAR_DEF_SIZE;
  1087.     data_str_end = 1;
  1088.     data_str = new char[data_str_len];
  1089.     data_str[0] = ch;
  1090.     data_str[1] = 0;
  1091.     format_str = DEFAULT_STRING_FORMAT;
  1092. }
  1093.  
  1094.  
  1095. var::var(const short int_num)
  1096. {
  1097.     fixed = 1;
  1098.     is_numeric = VAR_LONG;
  1099.     data_str_len = VAR_DEF_SIZE;
  1100.     data_str = new char[data_str_len];
  1101.     strcpy(data_str, itoa((const int) int_num));
  1102.     data_str_end = strlen(data_str);
  1103.     format_str = DEFAULT_INT_FORMAT;
  1104. }
  1105.  
  1106.  
  1107. var::var(const unsigned short int_num)
  1108. {
  1109.     fixed = 1;
  1110.     is_numeric = VAR_LONG;
  1111.     data_str_len = VAR_DEF_SIZE;
  1112.     data_str = new char[data_str_len];
  1113.     strcpy(data_str, itoa((const int) int_num));
  1114.     data_str_end = strlen(data_str);
  1115.     format_str = DEFAULT_UINT_FORMAT;
  1116. }
  1117.  
  1118.  
  1119. var::var(const int int_num)
  1120. {
  1121.     fixed = 1;
  1122.     is_numeric = VAR_LONG;
  1123.     data_str_len = VAR_DEF_SIZE;
  1124.     data_str = new char[data_str_len];
  1125.     strcpy(data_str, itoa(int_num));
  1126.     data_str_end = strlen(data_str);
  1127.     format_str = DEFAULT_INT_FORMAT;
  1128. }
  1129.  
  1130.  
  1131. var::var(const unsigned int int_num)
  1132. {
  1133.     fixed = 1;
  1134.     is_numeric = VAR_LONG;
  1135.     data_str_len = VAR_DEF_SIZE;
  1136.     data_str = new char[data_str_len];
  1137.     strcpy(data_str, itoa((const int) int_num));
  1138.     data_str_end = strlen(data_str);
  1139.     format_str = DEFAULT_UINT_FORMAT;
  1140. }
  1141.  
  1142.  
  1143. var::var(const long long_num)
  1144. {
  1145.     fixed = 1;
  1146.     is_numeric = VAR_LONG;
  1147.     data_str_len = VAR_DEF_SIZE;
  1148.     data_str = new char[data_str_len];
  1149.     strcpy(data_str, ltoa(long_num));
  1150.     data_str_end = strlen(data_str);
  1151.     format_str = DEFAULT_LONG_FORMAT;
  1152. }
  1153.  
  1154.  
  1155. var::var(const unsigned long long_num)
  1156. {
  1157.     fixed = 1;
  1158.     is_numeric = VAR_LONG;
  1159.     data_str_len = VAR_DEF_SIZE;
  1160.     data_str = new char[data_str_len];
  1161.     strcpy(data_str, ltoa(long_num));
  1162.     data_str_end = strlen(data_str);
  1163.     format_str = DEFAULT_ULONG_FORMAT;
  1164. }
  1165.  
  1166.  
  1167. var::var(const double double_num)
  1168. {
  1169.     fixed = 1;
  1170.     is_numeric = VAR_DOUBLE;
  1171.     data_str_len = VAR_DEF_SIZE;
  1172.     data_str = new char[data_str_len];
  1173.     strcpy(data_str, dtoa(double_num));
  1174.     data_str_end = strlen(data_str);
  1175.     format_str = DEFAULT_DOUBLE_FORMAT;
  1176. }
  1177.  
  1178.  
  1179. var::var(const var &v)
  1180. {
  1181.     fixed = v.fixed;
  1182.     is_numeric = v.is_numeric;
  1183.     if (v.data_str && v.data_str_end) {
  1184.     data_str_len = v.data_str_end + VAR_DEF_SIZE;
  1185.     data_str_end = v.data_str_end;
  1186.     data_str = new char[data_str_len];
  1187.     strcpy(data_str, v.data_str);
  1188.     }
  1189.     else {
  1190.     data_str_len = VAR_DEF_SIZE;
  1191.     data_str_end = 0;
  1192.     data_str = new char[data_str_len];
  1193.     data_str[0] = 0;
  1194.     }
  1195.     format_str = DEFAULT_STRING_FORMAT;
  1196. }
  1197.  
  1198.  
  1199. var::~var(void)
  1200. {
  1201.     if (data_str) {
  1202.     delete data_str;
  1203.     }
  1204.     if (format_str
  1205.     && format_str != DEFAULT_STRING_FORMAT
  1206.     && format_str != DEFAULT_INT_FORMAT
  1207.     && format_str != DEFAULT_UINT_FORMAT
  1208.     && format_str != DEFAULT_LONG_FORMAT
  1209.     && format_str != DEFAULT_ULONG_FORMAT
  1210.     && format_str != DEFAULT_DOUBLE_FORMAT) {
  1211.         delete format_str;
  1212.     }
  1213. }
  1214.  
  1215. // -----------------------------------------------------------------------------
  1216.  
  1217. var & var::operator = (const char *str)
  1218. {
  1219.     //
  1220.     if (fixed && is_numeric) {
  1221.     if (is_numeric == VAR_DOUBLE) {
  1222.         double d = atod((char *) str);
  1223.         *this = d;
  1224.     }
  1225.     else {
  1226.         long l = atol(str);
  1227.         *this = l;
  1228.     }
  1229.     }
  1230.     else {
  1231.     int len = strlen(str) + 1;
  1232.     if (data_str_len < len) {
  1233.         delete data_str;
  1234.         data_str_len = len;
  1235.         data_str = new char[data_str_len];
  1236.     }
  1237.     data_str_end = len - 1;
  1238.     strcpy(data_str, str);
  1239.     if (!fixed) {
  1240.         int str_is_numeric = numcheck(data_str);
  1241.         is_numeric = str_is_numeric;
  1242.     }
  1243.     }
  1244.     return *this;
  1245. }
  1246.  
  1247.  
  1248. var & var::operator = (const var &l)
  1249. {
  1250.     //
  1251.     if (this != &l) {
  1252.     if (data_str_len <= l.data_str_end) {
  1253.         delete data_str;
  1254.         data_str_len = l.data_str_end + VAR_DEF_SIZE;
  1255.         data_str = new char[data_str_len];
  1256.     }
  1257.     data_str_end = l.data_str_end;
  1258.     strncpy(data_str, l.data_str, l.data_str_end);
  1259.     data_str[data_str_end] = 0;
  1260.     if (!fixed) {
  1261.         is_numeric = numcheck(data_str);
  1262.     }
  1263.     //
  1264.     // Note: the output "format" of a var variable is preserved
  1265.     //
  1266.     }
  1267.     return *this;
  1268. }
  1269.  
  1270.  
  1271. char & var::operator [] (const int index)
  1272. {
  1273.     static char error_ch;
  1274.     if (index < 0) {
  1275.     cerr << "ERROR: " << " - var[" << index << "] negative index used.\n";
  1276.     error_ch = 0;
  1277.     return error_ch;
  1278.     }
  1279.     if (data_str_len <= index) {
  1280.     // this is technically a program error, but I'll be nice and extend the string's length
  1281.     data_str_len = index + VAR_PAD_SIZE;
  1282.     data_str_end = index + 1;
  1283.     char *buf = new char[data_str_len];
  1284.     sprintf(buf, "%-*.*s", data_str_end, data_str_end, data_str);
  1285.     delete data_str;
  1286.     data_str = buf;
  1287.     data_str[index] = 0;
  1288.     // cerr << "WARNING: " << " - var index '" << index << "' beyond current string boundary.\n";
  1289.     }
  1290.     while (data_str_end < index) {
  1291.     data_str[data_str_end++] = ' ';        // pad to index with spaces if necessary
  1292.     }
  1293.     if (data_str_end == index) {
  1294.     data_str[data_str_end] = 0;        // the end of a string is ALWAYS 0
  1295.     if ((data_str_end + 1) < data_str_len) {
  1296.         data_str[++data_str_end] = 0;    // the new end of string is also 0
  1297.     }
  1298.     }
  1299.     return data_str[index];
  1300. }
  1301.  
  1302.  
  1303. // for substrings
  1304. subvar & var::operator () (const int offset) const
  1305. {
  1306.     return operator () (offset, -1);
  1307. }
  1308.  
  1309.  
  1310. // for substrings
  1311. subvar & var::operator () (int offset, int length) const
  1312. {
  1313.     static subvar _esi_subvar;
  1314.     if (length < 0) {
  1315.     length = data_str_end - offset;
  1316.     }
  1317.     char *substr = new char[length + 1];
  1318.     strncpy(substr, data_str + offset, (int) length);
  1319.     substr[length] = 0;
  1320.     _esi_subvar.var::operator = (substr);
  1321.     _esi_subvar.varptr = (var *) this;
  1322.     _esi_subvar.offset = offset;
  1323.     _esi_subvar.length = length;
  1324.     delete substr;
  1325.     return _esi_subvar;
  1326. }
  1327.  
  1328.  
  1329. // for syntax: var(offset, length) = var
  1330. var & subvar::operator = (const var &substr)
  1331. {
  1332.     char *srcstr = varptr->data_str;
  1333.     char *repstr = substr.data_str;
  1334.     int replen = length;
  1335.     if (substr.data_str_end < length) {
  1336.     replen = substr.data_str_end;
  1337.     }
  1338.     int len = varptr->data_str_len;
  1339.     char *newstr = new char[len];
  1340.     strncpy(newstr, srcstr, offset);        // data from string being replaced up to "offset"
  1341.     if (replen) {
  1342.     strncpy(newstr + offset, repstr, replen);    // replacement string data
  1343.     }
  1344.     int newoffset = offset + replen;
  1345.     if (newoffset < varptr->data_str_end) {
  1346.     strcpy(newstr + newoffset, srcstr + offset + length);
  1347.     }
  1348.     else {
  1349.     newstr[newoffset] = 0;
  1350.     }
  1351.     if (varptr->data_str) {
  1352.     delete varptr->data_str;
  1353.     }
  1354.     varptr->data_str = newstr;
  1355.     varptr->data_str_len = len;
  1356.     varptr->data_str_end = strlen(newstr);
  1357.     if (!varptr->fixed) {
  1358.     varptr->is_numeric = numcheck(newstr);
  1359.     }
  1360.     return *varptr;
  1361. }
  1362.  
  1363. // -----------------------------------------------------------------------------
  1364.  
  1365. var & var::operator = (const char ch)
  1366. {
  1367.     char buf[2];
  1368.     buf[0] = ch;
  1369.     buf[1] = 0;
  1370.     *this = buf;
  1371.     return *this;
  1372. }
  1373.  
  1374.  
  1375. var & var::operator = (const short int_num)
  1376. {
  1377.     char *str = itoa((const int) int_num);
  1378.     int len = strlen(str);
  1379.     if (data_str_len < len) {
  1380.     delete data_str;
  1381.     data_str_len = len + 1;
  1382.     data_str = new char[data_str_len];
  1383.     }
  1384.     data_str_end = len;
  1385.     strcpy(data_str, str);
  1386.     if (!fixed) {
  1387.     is_numeric = VAR_LONG;
  1388.     }
  1389.     return *this;
  1390. }
  1391.  
  1392.  
  1393. var & var::operator = (const unsigned short int_num)
  1394. {
  1395.     char *str = itoa((const int) int_num);
  1396.     int len = strlen(str);
  1397.     if (data_str_len < len) {
  1398.     delete data_str;
  1399.     data_str_len = len + 1;
  1400.     data_str = new char[data_str_len];
  1401.     }
  1402.     data_str_end = len;
  1403.     strcpy(data_str, str);
  1404.     is_numeric = VAR_LONG;
  1405.     return *this;
  1406. }
  1407.  
  1408.  
  1409. var & var::operator = (const int int_num)
  1410. {
  1411.     char *str = itoa(int_num);
  1412.     int len = strlen(str);
  1413.     if (data_str_len < len) {
  1414.     delete data_str;
  1415.     data_str_len = len + 1;
  1416.     data_str = new char[data_str_len];
  1417.     }
  1418.     data_str_end = len;
  1419.     strcpy(data_str, str);
  1420.     if (!fixed) {
  1421.     is_numeric = VAR_LONG;
  1422.     }
  1423.     return *this;
  1424. }
  1425.  
  1426.  
  1427. var & var::operator = (const unsigned int int_num)
  1428. {
  1429.     char *str = itoa((const int) int_num);
  1430.     int len = strlen(str);
  1431.     if (data_str_len < len) {
  1432.     delete data_str;
  1433.     data_str_len = len + 1;
  1434.     data_str = new char[data_str_len];
  1435.     }
  1436.     data_str_end = len;
  1437.     strcpy(data_str, str);
  1438.     if (!fixed) {
  1439.     is_numeric = VAR_LONG;
  1440.     }
  1441.     return *this;
  1442. }
  1443.  
  1444.  
  1445. var & var::operator = (const long long_num)
  1446. {
  1447.     char *str = ltoa(long_num);
  1448.     int len = strlen(str);
  1449.     if (data_str_len < len) {
  1450.     delete data_str;
  1451.     data_str_len = len + 1;
  1452.     data_str = new char[data_str_len];
  1453.     }
  1454.     data_str_end = len;
  1455.     strcpy(data_str, str);
  1456.     if (!fixed) {
  1457.     is_numeric = VAR_LONG;
  1458.     }
  1459.     return *this;
  1460. }
  1461.  
  1462.  
  1463. var & var::operator = (const unsigned long long_num)
  1464. {
  1465.     char *str = ltoa(long_num);
  1466.     int len = strlen(str);
  1467.     if (data_str_len < len) {
  1468.     delete data_str;
  1469.     data_str_len = len + 1;
  1470.     data_str = new char[data_str_len];
  1471.     }
  1472.     data_str_end = len;
  1473.     strcpy(data_str, str);
  1474.     if (!fixed) {
  1475.     is_numeric = VAR_LONG;
  1476.     }
  1477.     return *this;
  1478. }
  1479.  
  1480.  
  1481. var & var::operator = (const double dbl_num)
  1482. {
  1483.     char *str = dtoa(dbl_num);
  1484.     int len = strlen(str);
  1485.     if (data_str_len < len) {
  1486.     delete data_str;
  1487.     data_str_len = len + 1;
  1488.     data_str = new char[data_str_len];
  1489.     }
  1490.     data_str_end = len;
  1491.     strcpy(data_str, str);
  1492.     if (!fixed) {
  1493.     is_numeric = VAR_DOUBLE;
  1494.     }
  1495.     return *this;
  1496. }
  1497.  
  1498. // -----------------------------------------------------------------------------
  1499.  
  1500. var::operator char * (void) const
  1501. {
  1502.     return data_str;
  1503. }
  1504.  
  1505.  
  1506. var::operator double (void) const
  1507. {
  1508.     return atod(data_str);
  1509. }
  1510.  
  1511. // -----------------------------------------------------------------------------
  1512.  
  1513. var & var::operator ++ (void)        // increment (pre-index only)
  1514. {
  1515.     *this -= (-1);            // because of bug in g++
  1516.     return *this;
  1517. }
  1518.  
  1519.  
  1520. var & var::operator -- (void)        // decrement (pre-index only)
  1521. {
  1522.     *this -= 1;
  1523.     return *this;
  1524. }
  1525.  
  1526.  
  1527. var var::operator ! (void) const    // not
  1528. {
  1529.     var not(1);
  1530.     if ((int) *this) {
  1531.     not = 0;
  1532.     }
  1533.     return not;
  1534. }
  1535.  
  1536. // -----------------------------------------------------------------------------
  1537.  
  1538. var var::operator + (const var & v) const    // addition OR concatenation
  1539. {
  1540.     var add;
  1541.     if (is_numeric && v.is_numeric) {
  1542.     // do math in the highest precision specified
  1543.     int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1544.     switch (n_type) {
  1545.         case VAR_LONG:
  1546.         add = (long) *this + (long) v;
  1547.         break;
  1548.         default:
  1549.         // should be VAR_DOUBLE
  1550.         add = (double) *this + (double) v;
  1551.         break;
  1552.     }
  1553.     }
  1554.     else {
  1555.     // concatenate strings
  1556.     add = (*this);
  1557.     add.concat(v);
  1558.     add.is_numeric = VAR_STRING;
  1559.     }
  1560.     return add;
  1561. }
  1562.  
  1563.  
  1564. var var::operator - (const var & v) const    // subtraction
  1565. {
  1566.     var sub;
  1567.     // do math in the highest precision specified
  1568.     int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1569.     switch (n_type) {
  1570.     case VAR_LONG:
  1571.         sub = (long) *this - (long) v;
  1572.         sub.is_numeric = VAR_LONG;
  1573.         break;
  1574.     default:
  1575.         // should be VAR_DOUBLE
  1576.         sub = (double) *this - (double) v;
  1577.         break;
  1578.     }
  1579.     return sub;
  1580. }
  1581.  
  1582.  
  1583. var var::operator * (const var & v) const    // multiplication
  1584. {
  1585.     var times;
  1586.     // do math in the highest precision specified
  1587.     int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1588.     switch (n_type) {
  1589.     case VAR_LONG:
  1590.         times = (long) *this * (long) v;
  1591.         break;
  1592.     default:
  1593.         // should be VAR_DOUBLE
  1594.         times = (double) *this * (double) v;
  1595.         break;
  1596.     }
  1597.     return times;
  1598. }
  1599.  
  1600.  
  1601. var var::operator / (const var & v) const    // division
  1602. {
  1603.     var div;
  1604.     // do math in the highest precision specified
  1605.     int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1606.     switch (n_type) {
  1607.     case VAR_LONG:
  1608.         div = (long) *this / (long) v;
  1609.         break;
  1610.     default:
  1611.         // should be VAR_DOUBLE
  1612.         div = (double) *this / (double) v;
  1613.         break;
  1614.     }
  1615.     return div;
  1616. }
  1617.  
  1618.  
  1619. var var::operator % (const var & v) const    // remainder
  1620. {
  1621.     var mod;
  1622.     // do math in the highest precision specified
  1623.     int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1624.     switch (n_type) {
  1625.     case VAR_LONG:
  1626.         mod = (long) *this % (long) v;
  1627.         break;
  1628.     default:
  1629.         // should be VAR_DOUBLE
  1630.         // really, I shouldn't allow this..
  1631.         mod = (double) ((long) *this % (long) v);
  1632.         break;
  1633.     }
  1634.     return mod;
  1635. }
  1636.  
  1637. // -----------------------------------------------------------------------------
  1638.  
  1639. var & var::operator += (const var & v)
  1640. {
  1641.     if ((is_numeric == VAR_STRING) || (v.is_numeric == VAR_STRING)) {
  1642.     concat(v);
  1643.     }
  1644.     else {
  1645.     *this = (*this) + v;
  1646.     }
  1647.     return *this;
  1648. }
  1649.  
  1650.  
  1651. var & var::operator -= (const var & v)
  1652. {
  1653.     *this = (*this) - v;
  1654.     return *this;
  1655. }
  1656.  
  1657.  
  1658. var & var::operator *= (const var & v)
  1659. {
  1660.     *this = (*this) * v;
  1661.     return *this;
  1662. }
  1663.  
  1664.  
  1665. var & var::operator /= (const var & v)
  1666. {
  1667.     *this = (*this) / v;
  1668.     return *this;
  1669. }
  1670.  
  1671.  
  1672. var & var::operator %= (const var & v)
  1673. {
  1674.     *this = (*this) % v;
  1675.     return *this;
  1676. }
  1677.  
  1678. // -----------------------------------------------------------------------------
  1679.  
  1680. var & var::operator += (const char & ch)
  1681. {
  1682.     var foo = ch;
  1683.     *this += foo;
  1684.     return *this;
  1685. }
  1686.  
  1687. var & var::operator += (const char * v)
  1688. {
  1689.     var foo = v;
  1690.     *this += foo;
  1691.     return *this;
  1692. }
  1693.  
  1694.  
  1695. var & var::operator -= (const char * v)
  1696. {
  1697.     var foo = v;
  1698.     *this -= foo;
  1699.     return *this;
  1700. }
  1701.  
  1702.  
  1703. var & var::operator *= (const char * v)
  1704. {
  1705.     var foo = v;
  1706.     *this *= foo;
  1707.     return *this;
  1708. }
  1709.  
  1710.  
  1711. var & var::operator /= (const char * v)
  1712. {
  1713.     var foo = v;
  1714.     *this /= foo;
  1715.     return *this;
  1716. }
  1717.  
  1718.  
  1719. var & var::operator %= (const char * v)
  1720. {
  1721.     var foo = v;
  1722.     *this %= foo;
  1723.     return *this;
  1724. }
  1725.  
  1726. // -----------------------------------------------------------------------------
  1727.  
  1728. var & var::operator += (const double v)
  1729. {
  1730.     var foo = v;
  1731.     *this += foo;
  1732.     return *this;
  1733. }
  1734.  
  1735.  
  1736. var & var::operator -= (const double v)
  1737. {
  1738.     var foo = v;
  1739.     *this -= foo;
  1740.     return *this;
  1741. }
  1742.  
  1743.  
  1744. var & var::operator *= (const double v)
  1745. {
  1746.     var foo = v;
  1747.     *this *= foo;
  1748.     return *this;
  1749. }
  1750.  
  1751.  
  1752. var & var::operator /= (const double v)
  1753. {
  1754.     var foo = v;
  1755.     *this /= foo;
  1756.     return *this;
  1757. }
  1758.  
  1759.  
  1760. var & var::operator %= (const double v)
  1761. {
  1762.     var foo = v;
  1763.     *this %= foo;
  1764.     return *this;
  1765. }
  1766.  
  1767. // -----------------------------------------------------------------------------
  1768.  
  1769. var operator + (const char * s, const var & v)
  1770. {
  1771.     var foo = s;
  1772.     return foo + v;
  1773. }
  1774.  
  1775.  
  1776. var operator - (const char * s, const var & v)
  1777. {
  1778.     var foo = s;
  1779.     return foo - v;
  1780. }
  1781.  
  1782.  
  1783. var operator * (const char * s, const var & v)
  1784. {
  1785.     var foo = s;
  1786.     return foo * v;
  1787. }
  1788.  
  1789.  
  1790. var operator / (const char * s, const var & v)
  1791. {
  1792.     var foo = s;
  1793.     return foo / v;
  1794. }
  1795.  
  1796.  
  1797. var operator % (const char * s, const var & v)
  1798. {
  1799.     var foo = s;
  1800.     return foo % v;
  1801. }
  1802.  
  1803.  
  1804. var operator + (const var & v, const char * s)
  1805. {
  1806.     var foo = s;
  1807.     return v + foo;
  1808. }
  1809.  
  1810.  
  1811. var operator - (const var & v, const char * s)
  1812. {
  1813.     var foo = s;
  1814.     return v - foo;
  1815. }
  1816.  
  1817.  
  1818. var operator * (const var & v, const char * s)
  1819. {
  1820.     var foo = s;
  1821.     return v * foo;
  1822. }
  1823.  
  1824.  
  1825. var operator / (const var & v, const char * s)
  1826. {
  1827.     var foo = s;
  1828.     return v / foo;
  1829. }
  1830.  
  1831.  
  1832. var operator % (const var & v, const char * s)
  1833. {
  1834.     var foo = s;
  1835.     return v % foo;
  1836. }
  1837.  
  1838. // -----------------------------------------------------------------------------
  1839.  
  1840. var operator + (const var & v, const double d)
  1841. {
  1842.     var foo = d;
  1843.     return v + foo;
  1844. }
  1845.  
  1846.  
  1847. var operator - (const var & v, const double d)
  1848. {
  1849.     var foo = d;
  1850.     return v - foo;
  1851. }
  1852.  
  1853.  
  1854. var operator * (const var & v, const double d)
  1855. {
  1856.     var foo = d;
  1857.     return v * foo;
  1858. }
  1859.  
  1860.  
  1861. var operator / (const var & v, const double d)
  1862. {
  1863.     var foo = d;
  1864.     return v / foo;
  1865. }
  1866.  
  1867.  
  1868. var operator % (const var & v, const double d)
  1869. {
  1870.     var foo = d;
  1871.     return v % foo;
  1872. }
  1873.  
  1874.  
  1875. var operator + (const double d, const var & v)
  1876. {
  1877.     var foo = d;
  1878.     return foo + v;
  1879. }
  1880.  
  1881.  
  1882. var operator - (const double d, const var & v)
  1883. {
  1884.     var foo = d;
  1885.     return foo - v;
  1886. }
  1887.  
  1888.  
  1889. var operator * (const double d, const var & v)
  1890. {
  1891.     var foo = d;
  1892.     return foo * v;
  1893. }
  1894.  
  1895.  
  1896. var operator / (const double d, const var & v)
  1897. {
  1898.     var foo = d;
  1899.     return foo / v;
  1900. }
  1901.  
  1902.  
  1903. var operator % (const double d, const var & v)
  1904. {
  1905.     var foo = d;
  1906.     return foo % v;
  1907. }
  1908.  
  1909. // -----------------------------------------------------------------------------
  1910.  
  1911. int var::operator == (const var & t) const        // equality
  1912. {
  1913.     if (is_numeric && t.is_numeric) {
  1914.     if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1915.         return (long) (*this) == (long) t;
  1916.     }
  1917.     return (double) (*this) == (double) t;
  1918.     }
  1919.     else {
  1920.     if (data_str_end && t.data_str_end) {
  1921.         return !strcmp(data_str, t.data_str);
  1922.     }
  1923.     else {
  1924.         return data_str_end == t.data_str_end;
  1925.     }
  1926.     }
  1927. }
  1928.  
  1929.  
  1930. int var::operator != (const var & t) const        // inequality
  1931. {
  1932.     if (is_numeric && t.is_numeric) {
  1933.     if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1934.         return (long) (*this) != (long) t;
  1935.     }
  1936.     return (double) (*this) != (double) t;
  1937.     }
  1938.     else {
  1939.     if (data_str_end && t.data_str_end) {
  1940.         return strcmp(data_str, t.data_str);
  1941.     }
  1942.     else {
  1943.         return data_str_end != t.data_str_end;
  1944.     }
  1945.     }
  1946. }
  1947.  
  1948.  
  1949. int var::operator < (const var & t) const        // less than
  1950. {
  1951.     if (is_numeric && t.is_numeric) {
  1952.     if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1953.         return (long) (*this) < (long) t;
  1954.     }
  1955.     return (double) (*this) < (double) t;
  1956.     }
  1957.     else {
  1958.     if (data_str_end && t.data_str_end) {
  1959.         return (strcmp(data_str, t.data_str) < 0);
  1960.     }
  1961.     else {
  1962.         return data_str_end < t.data_str_end;
  1963.     }
  1964.     }
  1965. }
  1966.  
  1967.  
  1968. int var::operator > (const var & t) const        // greater than
  1969. {
  1970.     if (is_numeric && t.is_numeric) {
  1971.     if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1972.         return (long) (*this) > (long) t;
  1973.     }
  1974.     return (double) (*this) > (double) t;
  1975.     }
  1976.     else {
  1977.     if (data_str_end && t.data_str_end) {
  1978.         return (strcmp(data_str, t.data_str) > 0);
  1979.     }
  1980.     else {
  1981.         return data_str_end > t.data_str_end;
  1982.     }
  1983.     }
  1984. }
  1985.  
  1986.  
  1987. int var::operator <= (const var & t) const        // less than or equal
  1988. {
  1989.     if (is_numeric && t.is_numeric) {
  1990.     if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1991.         return (long) (*this) <= (long) t;
  1992.     }
  1993.     return (double) (*this) <= (double) t;
  1994.     }
  1995.     else {
  1996.     if (data_str_end && t.data_str_end) {
  1997.         return (strcmp(data_str, t.data_str) <= 0);
  1998.     }
  1999.     else {
  2000.         return data_str_end <= t.data_str_end;
  2001.     }
  2002.     }
  2003. }
  2004.  
  2005.  
  2006. int var::operator >= (const var & t) const        // greater than or equal
  2007. {
  2008.     if (is_numeric && t.is_numeric) {
  2009.     if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  2010.         return (long) (*this) >= (long) t;
  2011.     }
  2012.     return (double) (*this) >= (double) t;
  2013.     }
  2014.     else {
  2015.     if (data_str_end && t.data_str_end) {
  2016.         return (strcmp(data_str, t.data_str) >= 0);
  2017.     }
  2018.     else {
  2019.         return data_str_end >= t.data_str_end;
  2020.     }
  2021.     }
  2022. }
  2023.  
  2024. // -----------------------------------------------------------------------------
  2025.  
  2026. int operator == (const var & t, const char * s)
  2027. {
  2028.     var foo = s;
  2029.     return t == foo;
  2030. }
  2031.  
  2032.  
  2033. int operator != (const var & t, const char * s)
  2034. {
  2035.     var foo = s;
  2036.     return t != foo;
  2037. }
  2038.  
  2039.  
  2040. int operator < (const var & t, const char * s)
  2041. {
  2042.     var foo = s;
  2043.     return t < foo;
  2044. }
  2045.  
  2046.  
  2047. int operator > (const var & t, const char * s)
  2048. {
  2049.     var foo = s;
  2050.     return t > foo;
  2051. }
  2052.  
  2053.  
  2054. int operator <= (const var & t, const char * s)
  2055. {
  2056.     var foo = s;
  2057.     return t <= foo;
  2058. }
  2059.  
  2060.  
  2061. int operator >= (const var & t, const char * s)
  2062. {
  2063.     var foo = s;
  2064.     return t >= foo;
  2065. }
  2066.  
  2067.  
  2068. int operator == (const char * s, const var & t)
  2069. {
  2070.     var foo = s;
  2071.     return foo == t;
  2072. }
  2073.  
  2074.  
  2075. int operator != (const char * s, const var & t)
  2076. {
  2077.     var foo = s;
  2078.     return foo != t;
  2079. }
  2080.  
  2081.  
  2082. int operator < (const char * s, const var & t)
  2083. {
  2084.     var foo = s;
  2085.     return foo < t;
  2086. }
  2087.  
  2088.  
  2089. int operator > (const char * s, const var & t)
  2090. {
  2091.     var foo = s;
  2092.     return foo > t;
  2093. }
  2094.  
  2095.  
  2096. int operator <= (const char * s, const var & t)
  2097. {
  2098.     var foo = s;
  2099.     return foo <= t;
  2100. }
  2101.  
  2102.  
  2103. int operator >= (const char * s, const var & t)
  2104. {
  2105.     var foo = s;
  2106.     return foo >= t;
  2107. }
  2108.  
  2109. // -----------------------------------------------------------------------------
  2110.  
  2111. int operator == (const var & t, const double d)
  2112. {
  2113.     return (double) t == d;
  2114. }
  2115.  
  2116.  
  2117. int operator != (const var & t, const double d)
  2118. {
  2119.     return (double) t != d;
  2120. }
  2121.  
  2122.  
  2123. int operator < (const var & t, const double d)
  2124. {
  2125.     return (double) t < d;
  2126. }
  2127.  
  2128.  
  2129. int operator > (const var & t, const double d)
  2130. {
  2131.     return (double) t > d;
  2132. }
  2133.  
  2134.  
  2135. int operator <= (const var & t, const double d)
  2136. {
  2137.     return (double) t <= d;
  2138. }
  2139.  
  2140.  
  2141. int operator >= (const var & t, const double d)
  2142. {
  2143.     return (double) t >= d;
  2144. }
  2145.  
  2146.  
  2147. int operator == (const double d, const var & t)
  2148. {
  2149.     return d == (double) t;
  2150. }
  2151.  
  2152.  
  2153. int operator != (const double d, const var & t)
  2154. {
  2155.     return d != (double) t;
  2156. }
  2157.  
  2158.  
  2159. int operator < (const double d, const var & t)
  2160. {
  2161.     return d < (double) t;
  2162. }
  2163.  
  2164.  
  2165. int operator > (const double d, const var & t)
  2166. {
  2167.     return d > (double) t;
  2168. }
  2169.  
  2170.  
  2171. int operator <= (const double d, const var & t)
  2172. {
  2173.     return d <= (double) t;
  2174. }
  2175.  
  2176.  
  2177. int operator >= (const double d, const var & t)
  2178. {
  2179.     return d >= (double) t;
  2180. }
  2181.  
  2182. // -----------------------------------------------------------------------------
  2183.  
  2184. void var::null(int index)
  2185. {
  2186.     if (index >= data_str_len) {
  2187.     cerr << "WARNING: " << " - var::null(" << index << ") - the index out of range.\n";
  2188.     (*this)[index] = 0;
  2189.     data_str_end = index;
  2190.     }
  2191.     else {
  2192.     data_str[index] = 0;
  2193.     data_str_end = index;
  2194.     }
  2195. }
  2196.  
  2197.  
  2198. void var::changesize(int newsize)
  2199. {
  2200.     if (newsize > data_str_len) {
  2201.     char *buf = new char[newsize];
  2202.     if (data_str) {
  2203.         strncpy(buf, data_str, data_str_end);
  2204.         buf[data_str_end] = 0;
  2205.         delete data_str;
  2206.     }
  2207.     else {
  2208.         *buf = 0;
  2209.         data_str_end = 0;
  2210.     }
  2211.     data_str_len = newsize;
  2212.     data_str = buf;
  2213.     }
  2214. }
  2215.  
  2216.  
  2217. int var::length(void) const
  2218. {
  2219.     return data_str_end;
  2220. }
  2221.  
  2222.  
  2223. const char * var::vartype(void) const
  2224. {
  2225.     switch (is_numeric) {
  2226.     case VAR_STRING:
  2227.         return "VAR_STRING";
  2228.     case VAR_LONG:
  2229.         return "VAR_LONG";
  2230.     case VAR_DOUBLE:
  2231.         return "VAR_DOUBLE";
  2232.     }
  2233.     return "var type unknown";
  2234. }
  2235.  
  2236.  
  2237. void var::change_type(const char *ntype)
  2238. {
  2239.     if (ntype == NULL) {
  2240.     return;
  2241.     }
  2242.     int index = strlen(ntype);
  2243.     if (!index) {
  2244.     return;
  2245.     }
  2246.     char *new_type = new char[index + 1];
  2247.     if (ntype[0] == '(' && ntype[index - 1] == ')') {
  2248.     strcpy(new_type, &ntype[1]);
  2249.     index = strlen(new_type) - 1;
  2250.     if (index <= 0) {
  2251.         delete new_type;
  2252.         return;
  2253.     }
  2254.     new_type[index] = 0;            // drop parens
  2255.     }
  2256.     else {
  2257.     strcpy(new_type, ntype);
  2258.     }
  2259.     if (new_type[index - 1] == ' ') {
  2260.     new_type[index - 1] = 0;
  2261.     }
  2262.     fixed = 1;
  2263.     if (!strcmp(new_type, "var")) {
  2264.     is_numeric = numcheck((const char *) *this);
  2265.     }
  2266.     else if (!strcmp(new_type, "string")) {
  2267.     is_numeric = VAR_STRING;
  2268.     }
  2269.     else if (!strcmp(new_type, "short")) {
  2270.     is_numeric = VAR_LONG;
  2271.     }
  2272.     else if (!strcmp(new_type, "unsigned short")) {
  2273.     is_numeric = VAR_LONG;
  2274.     }
  2275.     else if (!strcmp(new_type, "int")) {
  2276.     is_numeric = VAR_LONG;
  2277.     }
  2278.     else if (!strcmp(new_type, "unsigned int")) {
  2279.     is_numeric = VAR_LONG;
  2280.     }
  2281.     else if (!strcmp(new_type, "long")) {
  2282.     is_numeric = VAR_LONG;
  2283.     }
  2284.     else if (!strcmp(new_type, "unsigned long")) {
  2285.     is_numeric = VAR_LONG;
  2286.     }
  2287.     else if (!strcmp(new_type, "float")) {
  2288.     is_numeric = VAR_DOUBLE;
  2289.     }
  2290.     else if (!strcmp(new_type, "double")) {
  2291.     is_numeric = VAR_DOUBLE;
  2292.     }
  2293.     else {
  2294.     cerr << "WARNING: " << " - change_type(" << new_type << ") - unrecognized type name.\n";
  2295.     }
  2296.     delete new_type;
  2297. }
  2298.  
  2299.  
  2300. int var::is_string(void) const
  2301. {
  2302.     return is_numeric == VAR_STRING;
  2303. }
  2304.  
  2305.  
  2306. int var::is_double(void) const
  2307. {
  2308.     return is_numeric == VAR_DOUBLE;
  2309. }
  2310.  
  2311.  
  2312. int var::is_long(void) const
  2313. {
  2314.     return is_numeric == VAR_LONG;
  2315. }
  2316.  
  2317.  
  2318. int var::strchr(const char ch) const
  2319. {
  2320.     for (int i = 0; i < data_str_end; ++i) {
  2321.     if (data_str[i] == ch) {
  2322.         return i;
  2323.     }
  2324.     }
  2325.     return -1;
  2326. }
  2327.  
  2328.  
  2329. int var::strrchr(const char ch) const
  2330. {
  2331.     for (int i = data_str_end - 1; i >= 0; --i) {
  2332.     if (data_str[i] == ch) {
  2333.         return i;
  2334.     }
  2335.     }
  2336.     return -1;
  2337. }
  2338.  
  2339.  
  2340. var & var::concat(const var & str)
  2341. {
  2342.     // concatenate strings
  2343.     char *this_str = (char *) (*this);
  2344.     char *strs_str = (char *) (str);
  2345.     int this_len = strlen(this_str);
  2346.     int strs_len = strlen(strs_str);
  2347.     int new_data_str_end = data_str_end + str.data_str_end;
  2348.     // will it fit in this var's memory?
  2349.     if (new_data_str_end >= (this_len + strs_len)) {
  2350.     var add;
  2351.     add.data_str_len = this_len + strs_len + VAR_PAD_SIZE;
  2352.     add.data_str_end = this_len + strs_len;
  2353.     delete add.data_str;
  2354.     add.data_str = new char[add.data_str_len];
  2355.     strcpy(add.data_str, this_str);
  2356.     strcpy((add.data_str) + this_len, strs_str);
  2357.     *this = add;
  2358.     }
  2359.     else {
  2360.     strcpy(data_str + this_len, strs_str);
  2361.     data_str_end = this_len + strs_len;
  2362.     }
  2363.     return *this;
  2364. }
  2365.  
  2366.  
  2367. var & var::format(const char * fmt)
  2368. {
  2369.     if (format_str
  2370.     && format_str != DEFAULT_STRING_FORMAT
  2371.     && format_str != DEFAULT_INT_FORMAT
  2372.     && format_str != DEFAULT_UINT_FORMAT
  2373.     && format_str != DEFAULT_LONG_FORMAT
  2374.     && format_str != DEFAULT_ULONG_FORMAT
  2375.     && format_str != DEFAULT_DOUBLE_FORMAT) {
  2376.         delete format_str;
  2377.     }
  2378.     if (fmt) {
  2379.     format_str = new char[strlen(fmt) + 1];
  2380.     strcpy(format_str, fmt);
  2381.     }
  2382.     else {
  2383.     format_str = NULL;
  2384.     }
  2385.     return *this;
  2386. }
  2387.  
  2388.  
  2389. int var::numcheck(const char * str) const
  2390. {
  2391.     if (!str || !*str) {
  2392.     return VAR_STRING;        // assume a string
  2393.     }
  2394.     char *ptr = (char *) str;
  2395.     int nc = VAR_LONG;            // assume a signed long
  2396.     int decimal_yet = 0;
  2397.     if (*ptr == '.' && *(ptr + 1)) {
  2398.     nc = VAR_DOUBLE;        // floating point number
  2399.     decimal_yet = 1;
  2400.     ++ptr;
  2401.     }
  2402.     else if (*ptr == '-' && *(ptr + 1)) {
  2403.     // skip optional sign char
  2404.     ++ptr;
  2405.     }
  2406.     while (*ptr) {
  2407.     if (*ptr == '.' && !decimal_yet) {
  2408.         decimal_yet = 1;
  2409.         nc = VAR_DOUBLE;        // assume a double
  2410.     }
  2411.     else if (!isdigit(*ptr)) {
  2412.         return VAR_STRING;        // nope.. got a string
  2413.     }
  2414.     ++ptr;
  2415.     }
  2416.     return nc;
  2417. }
  2418.  
  2419. // -----------------------------------------------------------------------------
  2420.  
  2421. ostream & operator << (ostream &out, const var &d)
  2422. {
  2423.     d.print(out);
  2424.     return out;
  2425. }
  2426.  
  2427.  
  2428. void var::print(ostream &out) const
  2429. {
  2430.     // NOTE: the "read()" function requires a newline to appear after the last quote.
  2431.     // I assume that this newline was appropriately output by the var class user.
  2432.     if (!format_str || (format_str && *format_str == 0)) {
  2433.     out << "var OBJECT: {"
  2434.         << "\n\tfixed        = " << fixed
  2435.         << "\n\tis_numeric   = " << is_numeric
  2436.         << "\n\tdata_str_len = " << data_str_len
  2437.         << "\n\tdata_str_end = " << data_str_end
  2438.         << "\n\tdata_str     = '" << data_str << "'"
  2439.         << "\n\tformat_str   = '" << format_str << "'"
  2440.         << "\n}\n";
  2441.     }
  2442.     else {
  2443.     // we need to use the specified format string for output
  2444.     int len = length() + 1;
  2445.     char *outbuf = new char[2048];
  2446.     char *fptr = format_str;
  2447.     while (*fptr) {
  2448.         if (*fptr != '%' && *fptr != '\\') {
  2449.         out << *fptr;
  2450.         ++fptr;
  2451.         }
  2452.         else if (*fptr == '\\') {
  2453.         switch (*(fptr + 1)) {
  2454.             case 'n':
  2455.             cout << '\n';
  2456.             break;
  2457.             case 't':
  2458.             cout << '\t';
  2459.             break;
  2460.             case 'v':
  2461.             cout << '\v';
  2462.             break;
  2463.             case 'b':
  2464.             cout << '\b';
  2465.             break;
  2466.             case 'r':
  2467.             cout << '\r';
  2468.             break;
  2469.             case 'f':
  2470.             cout << '\f';
  2471.             break;
  2472.             case 'a':
  2473.             cout << '\007';
  2474.             break;
  2475.             case '\\':
  2476.             cout << '\\';
  2477.             break;
  2478.             case '?':
  2479.             cout << '\?';
  2480.             break;
  2481.             case '\'':
  2482.             cout << '\'';
  2483.             break;
  2484.             case '\"':
  2485.             cout << '\"';
  2486.             break;
  2487.             default:
  2488.             cout << *(fptr + 1);
  2489.         }
  2490.         fptr += 2;
  2491.         }
  2492.         else {
  2493.         // Hmmm.. we need to do some special formatting
  2494.         // first extract this printf-style format string
  2495.         char smallfmtstr[128];
  2496.         char *smptr = smallfmtstr;
  2497.         *smptr = 0;
  2498.         if (*(fptr + 1) == '%') {
  2499.             strcpy(outbuf, "%");
  2500.             fptr += 2;
  2501.         }
  2502.         else {
  2503.             while (*fptr) {
  2504.             *smptr = *fptr++;
  2505.             *(smptr + 1) = 0;
  2506.             // integer
  2507.             if (*smptr == 'd') {
  2508.                 sprintf(outbuf, smallfmtstr, (int) *this);
  2509.                 break;
  2510.             }
  2511.             // unsigned integer
  2512.             if (*smptr == 'o' || *smptr == 'u' || *smptr == 'x' || *smptr == 'X') {
  2513.                 sprintf(outbuf, smallfmtstr, (unsigned int) *this);
  2514.                 break;
  2515.             }
  2516.             // float or double
  2517.             if (*smptr == 'f' || *smptr == 'e' || *smptr == 'E' || *smptr == 'g' || *smptr == 'G') {
  2518.                 sprintf(outbuf, smallfmtstr, (double) *this);
  2519.                 break;
  2520.             }
  2521.             // character
  2522.             if (*smptr == 'c') {
  2523.                 if (!strcmp(vartype(), "VAR_STRING")) {
  2524.                 const char *tmp = (const char *) (*this);
  2525.                 sprintf(outbuf, smallfmtstr, tmp[0]);
  2526.                 }
  2527.                 else {
  2528.                 sprintf(outbuf, smallfmtstr, (char) ((int) *this));
  2529.                 }
  2530.                 break;
  2531.             }
  2532.             // string
  2533.             if (*smptr == 's') {
  2534.                 sprintf(outbuf, smallfmtstr, (const char *) *this);
  2535.                 break;
  2536.             }
  2537.             ++smptr;
  2538.             }
  2539.         }
  2540.         out << outbuf;
  2541.         }
  2542.     }
  2543.     //out << flush;
  2544.     delete outbuf;
  2545.     }
  2546. }
  2547.  
  2548. // -----------------------------------------------------------------------------
  2549.  
  2550. // convert an integer into an ascii string.  return a pointer to that string.
  2551. //
  2552. char *itoa(const int foo)
  2553. {
  2554.     static char int_buf[28];
  2555.     sprintf(int_buf, "%d", foo);
  2556.     return int_buf;
  2557. }
  2558.  
  2559.  
  2560. // convert an unsigned integer into an ascii string.  return a pointer to that string.
  2561. //
  2562. char *uitoa(const unsigned int foo)
  2563. {
  2564.     static char int_buf[28];
  2565.     sprintf(int_buf, "%u", foo);
  2566.     return int_buf;
  2567. }
  2568.  
  2569.  
  2570. // convert a long into an ascii string.  return a pointer to that string.
  2571. //
  2572. #ifdef HP
  2573. char *ltoa(long foo)
  2574. #else
  2575. char *ltoa(const long foo)
  2576. #endif
  2577. {
  2578.     static char long_buf[28];
  2579.     sprintf(long_buf, "%ld", foo);
  2580.     return long_buf;
  2581. }
  2582.  
  2583.  
  2584. // convert an unsigned long into an ascii string.  return a pointer to that string.
  2585. //
  2586. #ifdef HP
  2587. char *ultoa(unsigned long foo)
  2588. #else
  2589. char *ultoa(const unsigned long foo)
  2590. #endif
  2591. {
  2592.     static char long_buf[28];
  2593.     sprintf(long_buf, "%lu", foo);
  2594.     return long_buf;
  2595. }
  2596.  
  2597.  
  2598. // convert a double into an ascii string.  return a pointer to that string.
  2599. // truncate any extra zeros after the decimal point.
  2600. //
  2601. char *dtoa(const double foo)
  2602. {
  2603.     static char double_buf[28];
  2604.     sprintf(double_buf, "%lf", foo);
  2605.     char *ptr;
  2606.     for (ptr = double_buf; *ptr; ++ptr) {
  2607.     if (*ptr == '.') {
  2608.         // we may need to truncate zeroes
  2609.         ptr = double_buf + (strlen(double_buf) - 1);
  2610.         while (*ptr == '0') {
  2611.         *ptr-- = 0;
  2612.         }
  2613.         if (*ptr == '.') {
  2614.         *ptr = 0;
  2615.         }
  2616.         break;
  2617.     }
  2618.     }
  2619.     return double_buf;
  2620. }
  2621.  
  2622.  
  2623. // convert an ascii string to a double
  2624. //
  2625. double atod(char * foo)
  2626. {
  2627.     double d = 0;
  2628.     if (!foo || !*foo) {
  2629.     return d;
  2630.     }
  2631.     if (!isdigit(*foo)) {
  2632.     if (*foo != '-' && *foo != '+') {
  2633.         return d;
  2634.     }
  2635.     if (!isdigit(*(foo + 1))) {
  2636.         return d;
  2637.     }
  2638.     }
  2639.     sscanf(foo, "%lf", &d);
  2640.     return d;
  2641. }
  2642.  
  2643. @//E*O*F var.C//
  2644. chmod u=rw,g=r,o=r var.C
  2645.  
  2646. echo x - VarMap.H
  2647. sed 's/^@//' > "VarMap.H" <<'@//E*O*F VarMap.H//'
  2648. //
  2649. // NAME:        VarMap.H
  2650. //
  2651. // PURPOSE:     C++ "Map of Vars" Class Library Header File
  2652. // VERSION:     1.0
  2653. // AUTHOR:      Lee Hounshell
  2654. // LAST MOD:    Mon Nov 23 13:50:56 PST 1992
  2655. //
  2656.  
  2657. #ifndef VARMAP_H
  2658. #define VARMAP_H
  2659.  
  2660. #include    <stream.h>
  2661. #include    "var.H"
  2662.  
  2663. enum {VARMAP_FIFO, VARMAP_LIFO};
  2664.  
  2665. class VarMapNode
  2666. {
  2667.    public:
  2668.         // Standard Interface
  2669.         const var & type(void) const;                   // who am i
  2670.  
  2671.         // Operators
  2672.     friend ostream & operator << (ostream &, const VarMapNode &); // output
  2673.  
  2674.     friend class VarMap;
  2675.  
  2676.         // Standard Member Functions
  2677.         void print(ostream &) const;            // output
  2678.  
  2679.         int             errno;                          // primitive error control
  2680.  
  2681.    protected:
  2682.  
  2683.    private:
  2684.     VarMapNode(var newkey, var newvalue);
  2685.     var        key;
  2686.     var        value;
  2687.     VarMapNode    *prev;
  2688.     VarMapNode    *next;
  2689. };
  2690.  
  2691.  
  2692. class VarMap
  2693. {
  2694.    public:
  2695.         // Standard Interface
  2696.         const var & type(void) const;                   // who am i
  2697.  
  2698.         // Constructors & Destructor
  2699.     VarMap(int type = VARMAP_FIFO);
  2700.     ~VarMap(void)    {remove();}
  2701.  
  2702.         // Operators
  2703.     VarMap &    operator = (const VarMap &);    // assign VarMaps
  2704.     int operator == (VarMap &) const;        // equality
  2705.     int operator != (VarMap &) const;        // inequality
  2706.     var &        operator [] (const var index);    // index/create entry
  2707.  
  2708.     friend ostream & operator << (ostream &, const VarMap &); // output
  2709.  
  2710.         // Standard Member Functions
  2711.         void print(ostream &) const;            // output
  2712.  
  2713.         // Custom Interface - see VarMap man pages for use
  2714.     int         append(var newkey, var newvalue); // append to map
  2715.     int        push(var newkey, var newvalue);    // push a var
  2716.     var        pop(void);            // pop a var
  2717.     int        empty(void) const;        // is map empty
  2718.     int        at_start(void) const;        // at head of map
  2719.     int        at_end(void) const;        // at end of map
  2720.     int        position(void);            // index within map
  2721.     int        size(void) const;        // length of map
  2722.     void        remove(void);            // remove all items
  2723.     void        delete_here(void);        // remove this item
  2724.     int        element(const var & index);    // test for element
  2725.     var &        key(void);            // current key
  2726.     var &        value(void);            // current value
  2727.     void        display(ostream & out = cerr);    // print the map
  2728.     void        first(void);            // point to first node
  2729.     void        next(void);            // point to next node
  2730.     void        last(void);            // point to last node
  2731.  
  2732.         int             errno;                          // primitive error control
  2733.  
  2734.    protected:
  2735.  
  2736.    private:
  2737.     int        typeofmap;            // VARMAP_FIFO or VARMAP_LIFO
  2738.     VarMapNode    *head;                // first node
  2739.     VarMapNode    *tail;                // last node
  2740.     VarMapNode    *here;                // current node
  2741.     int        _size;                // size of Map
  2742. };
  2743.  
  2744. #endif
  2745.  
  2746. @//E*O*F VarMap.H//
  2747. chmod u=rw,g=r,o=r VarMap.H
  2748.  
  2749. echo x - VarMap.C
  2750. sed 's/^@//' > "VarMap.C" <<'@//E*O*F VarMap.C//'
  2751. //
  2752. // NAME:    VarMap.C
  2753. //
  2754. // PURPOSE:    C++ "Map of Vars" Class Library Source File
  2755. // VERSION:     1.0
  2756. // AUTHOR:      Lee Hounshell
  2757. // LAST MOD:    Mon Nov 23 13:55:39 PST 1992
  2758. //
  2759.  
  2760. #include <stream.h>
  2761. #include "VarMap.H"
  2762.  
  2763. // -----------------------------------------------------------------------------
  2764.  
  2765. const var & VarMapNode::type(void) const
  2766. {
  2767.     static const var objtype = "VarMapNode";
  2768.     return objtype;
  2769. }
  2770.  
  2771.  
  2772. const var & VarMap::type(void) const
  2773. {
  2774.     static const var objtype = "VarMap";
  2775.     return objtype;
  2776. }
  2777.  
  2778.  
  2779. VarMapNode::VarMapNode(var newkey, var newvalue)
  2780. {
  2781.     errno = 0;
  2782.     key = newkey;
  2783.     value = newvalue;
  2784.     prev = next = NULL;
  2785. }
  2786.  
  2787.  
  2788. VarMap::VarMap(int type)
  2789. {
  2790.     errno = 0;
  2791.     typeofmap = type;
  2792.     here = head = tail = NULL;
  2793.     _size = 0;
  2794. }
  2795.  
  2796. // -----------------------------------------------------------------------------
  2797.  
  2798. VarMap & VarMap::operator = (const VarMap & map)
  2799. {
  2800.     if (this != &map) {
  2801.     VarMapNode *vptr;
  2802.     remove();
  2803.     typeofmap = map.typeofmap;
  2804.     for (vptr = map.head; vptr; vptr = vptr->next) {
  2805.         append(vptr->key, vptr->value);
  2806.     }
  2807.     here = map.here;
  2808.     }
  2809.     return *this;
  2810. }
  2811.  
  2812.  
  2813. int VarMap::operator == (VarMap & map) const
  2814. {
  2815.     if (size() != map.size()) {
  2816.     return 0;
  2817.     }
  2818.     if (empty() && map.empty()) {
  2819.     return 1;
  2820.     }
  2821.     int rc = 1;
  2822.     VarMapNode *tmp1 = head;
  2823.     VarMapNode *tmp2 = map.head;
  2824.     int done = 0;
  2825.     do {
  2826.     if (tmp1 == tail) {
  2827.         done = 1;
  2828.     }
  2829.     if (tmp1->key != tmp2->key) {
  2830.         rc = 0;
  2831.         break;
  2832.     }
  2833.     if (tmp1->value != tmp2->value) {
  2834.         rc = 0;
  2835.         break;
  2836.     }
  2837.     if ((tmp2 == map.tail) && (tmp1 != tail)) {
  2838.         rc = 0;
  2839.         break;
  2840.     }
  2841.     tmp1 = tmp1->next;
  2842.     tmp2 = tmp2->next;
  2843.     } while (!done);
  2844.     return rc;
  2845. }
  2846.  
  2847.  
  2848. int VarMap::operator != (VarMap & map) const
  2849. {
  2850.     return (!(*this == map));
  2851. }
  2852.  
  2853.  
  2854. var & VarMap::operator [] (const var index)
  2855. {
  2856.     for (VarMapNode *vptr = head; vptr; vptr = vptr->next) {
  2857.     if (vptr->key == index) {
  2858.         here = vptr;
  2859.         return vptr->value;
  2860.     }
  2861.     }
  2862.     append(index, "");
  2863.     return here->value;
  2864. }
  2865.  
  2866. // -----------------------------------------------------------------------------
  2867.  
  2868. int VarMap::append(var newkey, var newvalue)
  2869. {
  2870.     VarMapNode *newnode = new VarMapNode(newkey, newvalue);
  2871.     if (newnode == NULL) {
  2872.     cerr << "Out of memory.\n";
  2873.     return 0;
  2874.     }
  2875.     if (head == NULL) {
  2876.     // empty map
  2877.     head = newnode;
  2878.     tail = newnode;
  2879.     }
  2880.     else {
  2881.     tail->next = newnode;
  2882.     newnode->prev = tail;
  2883.     tail = newnode;
  2884.     }
  2885.     here = newnode;
  2886.     _size++;
  2887.     return 1;
  2888. }
  2889.  
  2890.  
  2891. int VarMap::push(var newkey, var newvalue)
  2892. {
  2893.     if (typeofmap == VARMAP_FIFO) {
  2894.     return append(newkey, newvalue);
  2895.     }
  2896.     else if (typeofmap == VARMAP_LIFO) {
  2897.     VarMapNode *newnode = new VarMapNode(newkey, newvalue);
  2898.     if (newnode == NULL) {
  2899.         cerr << "Out of memory.\n";
  2900.         return 0;
  2901.     }
  2902.     if (head == NULL) {
  2903.         // empty map
  2904.         head = newnode;
  2905.         tail = newnode;
  2906.     }
  2907.     else {
  2908.         head->prev = newnode;
  2909.         newnode->next = head;
  2910.         newnode->prev = NULL;
  2911.         head = newnode;
  2912.     }
  2913.     here = newnode;
  2914.     }
  2915.     return 1;
  2916. }
  2917.  
  2918.  
  2919. var VarMap::pop(void)
  2920. {
  2921.     var        data;
  2922.     VarMapNode    *vptr;
  2923.     if (head == NULL) {
  2924.     // empty map
  2925.     return 0;
  2926.     }
  2927.     data = head->value;
  2928.     vptr = head;
  2929.     here = head = head->next;
  2930.     if (head) {
  2931.     head->prev = NULL;
  2932.     }
  2933.     else {
  2934.     tail = NULL;
  2935.     }
  2936.     delete vptr;
  2937.     _size--;
  2938.     return data;
  2939. }
  2940.  
  2941.  
  2942. int VarMap::empty(void) const
  2943. {
  2944.     return head == NULL;
  2945. }
  2946.  
  2947.  
  2948. int VarMap::at_start(void) const
  2949. {
  2950.     return here == head;
  2951. }
  2952.  
  2953.  
  2954. int VarMap::at_end(void) const
  2955. {
  2956.     return here == tail;
  2957. }
  2958.  
  2959.  
  2960. int VarMap::position(void)
  2961. {
  2962.     int index = 0;
  2963.     VarMapNode *vptr = head;
  2964.     while (vptr && vptr != here) {
  2965.     vptr = vptr->next;
  2966.     ++index;
  2967.     }
  2968.     return index;
  2969. }
  2970.  
  2971.  
  2972. int VarMap::size(void) const
  2973. {
  2974.     return _size;
  2975. }
  2976.  
  2977.  
  2978. void VarMap::remove(void)
  2979. {
  2980.     VarMapNode *vptr = head;
  2981.     while (vptr) {
  2982.     VarMapNode *tmp = vptr;
  2983.     vptr = vptr->next;
  2984.     delete tmp;
  2985.     }
  2986.     here = head = tail = NULL;
  2987.     _size = 0;
  2988. }
  2989.  
  2990.  
  2991. void VarMap::delete_here(void)
  2992. {
  2993.     if (here) {
  2994.     VarMapNode *vptr = here;
  2995.     if (here->next) {
  2996.         here->next->prev = here->prev;
  2997.     }
  2998.     if (here->prev) {
  2999.         here->prev->next = here->next;
  3000.     }
  3001.     if (here == head && head == tail) {
  3002.         here = head = tail = NULL;
  3003.     }
  3004.     else if (here == head) {
  3005.         head = here->next;
  3006.         here = head;
  3007.     }
  3008.     else if (here == tail) {
  3009.         tail = here->prev;
  3010.         here = tail;
  3011.     }
  3012.     else {
  3013.         here = here->next;
  3014.     }
  3015.     delete vptr;
  3016.     --_size;
  3017.     }
  3018. }
  3019.  
  3020.  
  3021. int VarMap::element(const var & index)
  3022. {
  3023.     for (VarMapNode *vptr = head; vptr; vptr = vptr->next) {
  3024.     if (vptr->key == index) {
  3025.         return 1;                // found it
  3026.     }
  3027.     }
  3028.     return 0;                    // this index doesn't exist
  3029. }
  3030.  
  3031.  
  3032. var & VarMap::key(void)
  3033. {
  3034.     static var vkey = "";
  3035.     if (!here) {
  3036.     return vkey;
  3037.     }
  3038.     return here->key;
  3039. }
  3040.  
  3041.  
  3042. var & VarMap::value(void)
  3043. {
  3044.     static var vvalue = "";
  3045.     if (!here) {
  3046.     return vvalue;
  3047.     }
  3048.     return here->value;
  3049. }
  3050.  
  3051.  
  3052. void VarMap::display(ostream & out)
  3053. {
  3054.     out << "Display VarMap\n";
  3055.     for (VarMapNode *vptr = head; vptr; vptr = vptr->next) {
  3056.     out << "\tKey: " << vptr->key << " Value: " << vptr->value << "\n";
  3057.     }
  3058. }
  3059.  
  3060.  
  3061. // return value of first node - NULL if invalid
  3062. void VarMap::first(void)
  3063. {
  3064.     here = head;
  3065. }
  3066.  
  3067.  
  3068. // return value of next node
  3069. void VarMap::next(void)
  3070. {
  3071.     if (here == tail) {
  3072.     return;
  3073.     }
  3074.     here = here->next;
  3075. }
  3076.  
  3077.  
  3078. // return value of last node
  3079. void VarMap::last(void)
  3080. {
  3081.     here = tail;
  3082. }
  3083.  
  3084. // -----------------------------------------------------------------------------
  3085.  
  3086. ostream & operator << (ostream &out, const VarMapNode &d)
  3087. {
  3088.     d.print(out);
  3089.     return out;
  3090. }
  3091.  
  3092.  
  3093. ostream & operator << (ostream &out, const VarMap &d)
  3094. {
  3095.     d.print(out);
  3096.     return out;
  3097. }
  3098.  
  3099.  
  3100. void VarMapNode::print(ostream &out) const
  3101. {
  3102.     out << "VarMapNode OBJECT: {"
  3103.     << "\n\t<this>           = " << (void *) this
  3104.     << "\n\tvar key          = " << key
  3105.     << "\n\tvar value        = " << value
  3106.     << "\n\tVarMapNode *prev = " << prev
  3107.     << "\n\tVarMapNode *next = " << next
  3108.     << "\n}\n";
  3109. }
  3110.  
  3111.  
  3112. void VarMap::print(ostream &out) const
  3113. {
  3114.     out << "VarMap OBJECT: {"
  3115.     << "\n\tint typeofmap    = " << typeofmap
  3116.     << "\n\tVarMapNode *head = " << head
  3117.     << "\n\tVarMapNode *tail = " << tail
  3118.     << "\n\tVarMapNode *here = " << here
  3119.     << "\n\tint _size        = '" << _size << "'";
  3120.     int i = 0;
  3121.     for (VarMapNode *ptr = head; ptr; ptr = ptr->next) {
  3122.     ++i;
  3123.     out << "\n\tVarMapNode #" << i << "    = " << *ptr;
  3124.     }
  3125.     out << "\n}\n";
  3126. }
  3127.  
  3128. @//E*O*F VarMap.C//
  3129. chmod u=rw,g=r,o=r VarMap.C
  3130.  
  3131. echo x - demo.C
  3132. sed 's/^@//' > "demo.C" <<'@//E*O*F demo.C//'
  3133. #include    <stdlib.h>
  3134. #include    <stream.h>
  3135. #include    <var.H>
  3136.  
  3137. main ()
  3138. {
  3139.     var value;                // declare an "untyped" var
  3140.     value = "hello world";            // initialize it
  3141.     cout << value << "\n";            // output "hello world"
  3142.     value = value(3, value.length() - 6);    // substring example
  3143.     cout << value << "\n";            // output "lo wo"
  3144.     value = 34;                // assignment of int
  3145.     value++;                // increment
  3146.     value += 42.375;            // add 42.375 to present value
  3147.     cout << value << "\n";            // output "77.375"
  3148.     cout << value.format("formatted output example %05d of value\n");
  3149.     cout << value.format("multiple outputs #1=%d, #2=%9.2f of value\n");
  3150.     value.null(2);                // truncate string
  3151.     value += " sunset strip";        // concatenate a string
  3152.     cout << value.format("%s\n");        // output "77 sunset strip"
  3153.     cout << value[3] << value[4] << value[5] << "\n"; // output "sun"
  3154. }
  3155.  
  3156. @//E*O*F demo.C//
  3157. chmod u=rw,g=r,o=r demo.C
  3158.  
  3159. echo x - demo2.C
  3160. sed 's/^@//' > "demo2.C" <<'@//E*O*F demo2.C//'
  3161. #include    <VarMap.H>
  3162.  
  3163. main ()
  3164. {
  3165.     VarMap aa;                // declare a VarMap
  3166.     var lee = "foobar";
  3167.     if (!aa.element(lee)) {
  3168.     aa[lee] = "hello world";    // create/assign using index "foobar"
  3169.     }
  3170.     aa[42] = "testing 123";        // create/assign using index "42"
  3171.     aa[5] = 123.45;            // create/assign using index "5"
  3172.     aa.display();            // display this map to stderr
  3173. }
  3174.  
  3175. @//E*O*F demo2.C//
  3176. chmod u=rw,g=r,o=r demo2.C
  3177.  
  3178. exit 0
  3179. -- 
  3180. Lee Hounshell - (510) 823-2432
  3181. tlhouns@srv.pacbell.com
  3182. Alchemical Engineer and Virtual Realist
  3183.