Coverage Report - com.ccg.macros.at.Core
 
Classes in this File Line Coverage Branch Coverage Complexity
Core
62% 
67% 
5.95
 
 1  
 /*----------------------------------------------------------------
 2  
  * $Id: Core.java,v 1.1.1.1 2004/01/26 20:46:18 pkb Exp $
 3  
  * 
 4  
  * (c)2001 - Paul Blankenbaker */
 5  
 //----------------------------------------------------------------
 6  
 
 7  
 package com.ccg.macros.at;
 8  
 
 9  
 import com.ccg.util.Log;
 10  
 import com.ccg.util.Debug;
 11  
 import com.ccg.macros.*;
 12  
 
 13  
 import java.io.*;
 14  
 import java.util.*;
 15  
 
 16  
 import java.text.*;
 17  
 
 18  
 //----------------------------------------------------------------
 19  
 /** Set of core macros which provide some standard basic features.
 20  
  * 
 21  
  * <code><pre>
 22  
  * class Example {
 23  
  *   public void main(String[] args) {
 24  
  *     com.ccg.macros.at.Core o = new com.ccg.macros.at.Core();
 25  
  *           System.out.println(o);
 26  
  *   }
 27  
  * }
 28  
  * </pre></code>
 29  
  * 
 30  
  * @version $Revision: 1.1.1.1 $
 31  
  * 
 32  
  * @since 1.0
 33  
  * 
 34  
  * @author $Author: pkb $ */
 35  
 //----------------------------------------------------------------
 36  
 
 37  
 public class Core extends Base {
 38  
 
 39  
   //----------------------------------------------------------------
 40  
   /** Constructs the object and readies it for {@link #install installation}.
 41  
    * 
 42  
    * @since        1.0
 43  
    * 
 44  
    * @see #install */
 45  
   //----------------------------------------------------------------
 46  
 
 47  
   public Core() {
 48  26
     super(true);
 49  26
     _Includes = new Hashtable();
 50  26
     setLineSeparator(null);
 51  26
   }
 52  
 
 53  
 
 54  
 
 55  
   //----------------------------------------------------------------
 56  
   /** Holds the string used to separate lines on the current platform
 57  
    * 
 58  
    * @serial        
 59  
    * 
 60  
    * @since        1.0  */
 61  
   //----------------------------------------------------------------
 62  
 
 63  
   private String _LineSeparator;
 64  
 
 65  
 
 66  
   //----------------------------------------------------------------
 67  
   /** Set the string used to separate lines on the current platform
 68  
    * 
 69  
    * @param        val
 70  
    * 
 71  
    *         New String value to assign - note, if you pass null, we will
 72  
    *         attempt to reset it based on the "line.separator" system
 73  
    *         property.
 74  
    * 
 75  
    * @see #getLineSeparator  */
 76  
   //----------------------------------------------------------------
 77  
 
 78  
   public void setLineSeparator(String val) {
 79  36
     if (val == null) {
 80  28
       val = System.getProperty("line.separator");
 81  28
       if (val == null) val = "\n";
 82  
     }
 83  36
     _LineSeparator = val;
 84  36
   }
 85  
 
 86  
 
 87  
   //----------------------------------------------------------------
 88  
   /** Get the string used to separate lines on the current platform
 89  
    * 
 90  
    * @return
 91  
    * 
 92  
    *         Current String value assigned.
 93  
    * 
 94  
    * @see #setLineSeparator  */
 95  
   //----------------------------------------------------------------
 96  
 
 97  
   public String getLineSeparator() {
 98  14
     return _LineSeparator;
 99  
   }
 100  
 
 101  
 
 102  
   //----------------------------------------------------------------
 103  
   /** &#064;ifEqual(V1,V2,E,NE) macro - branching macro.
 104  
    * 
 105  
    * <p>This macro is used to compare two values (V1 and V2). If the
 106  
    * evaluation of the two values results in identical values, then
 107  
    * the equal statement (E) is evaluated, else the false statement
 108  
    * "NE" is evaluated.
 109  
    *
 110  
    * <pre>
 111  
    * &#064;define(name,fred)&#064;ifEqual("&#064name","barney","betty","wilma")
 112  
    * </pre>
 113  
    *
 114  
    * <p>The above should result in the output of "wilma".
 115  
    * 
 116  
    * @param        out
 117  
    * 
 118  
    *         The {@link Output output device} to write the results of
 119  
    *         processing the argument to.
 120  
    * 
 121  
    * @param        args
 122  
    * 
 123  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 124  
    * 
 125  
    * @throws        IOException
 126  
    * 
 127  
    *         If there is a problem writing to the {@link Output output device}
 128  
    * 
 129  
    * @throws        InterpretException
 130  
    * 
 131  
    *         If a problem is encountered interpretting the arguments passed.
 132  
    * 
 133  
    * @since        1.0 */
 134  
   //----------------------------------------------------------------
 135  
 
 136  
   public void ifEqual(Output out, Vector args)
 137  
     throws IOException, InterpretException {
 138  
 
 139  40
     AtMacros am = getAtMacros();
 140  
 
 141  40
     if ((args != null) && (args.size() >= 3)) {
 142  40
       Object o1 = args.elementAt(0);
 143  40
       Object o2 = args.elementAt(1);
 144  
 
 145  40
       String v1 = null;
 146  40
       String v2 = null;
 147  40
       if (o1 != null) v1 = am.interpretCheck(o1.toString());
 148  40
       if (o2 != null) v2 = am.interpretCheck(o2.toString());
 149  40
       if (v1 == null) v1 = "";
 150  40
       if (v2 == null) v2 = "";
 151  
 
 152  40
       if (v1.equals(v2)) {        // if equal, do equal output if possible
 153  20
         Object e = args.elementAt(2);
 154  20
         if (e != null) out.write(am.interpretCheck(e.toString()));
 155  20
       }
 156  
                                 // otherwise do not equal output if possible
 157  20
       else if (args.size() >= 4) {
 158  20
         Object ne = args.elementAt(3);
 159  20
         if (ne != null) out.write(am.interpretCheck(ne.toString()));
 160  
       }
 161  
     }
 162  40
   }
 163  
 
 164  
 
 165  
   //----------------------------------------------------------------
 166  
   /** &#064;increment(NAME) increments value of integer macro by 1.
 167  
    * 
 168  
    * <p>This macro is used to increment the value of the macro "NAME"
 169  
    * by 1. If the macro does not exist or has a non numeric value, it
 170  
    * is created and initialized with a value of '1'.
 171  
    *
 172  
    * <pre>
 173  
    * &#064;increment(cnt)&#064;cnt,&#064increment(cnt)&#064cnt
 174  
    * </pre>
 175  
    *
 176  
    * <p>The above should result in the output of "1,2".
 177  
    * 
 178  
    * @param        out
 179  
    * 
 180  
    *         The {@link Output output device} to write the results of
 181  
    *         processing the argument to.
 182  
    * 
 183  
    * @param        args
 184  
    * 
 185  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 186  
    * 
 187  
    * @throws        IOException
 188  
    * 
 189  
    *         If there is a problem writing to the {@link Output output device}
 190  
    * 
 191  
    * @throws        InterpretException
 192  
    * 
 193  
    *         If a problem is encountered interpretting the arguments passed.
 194  
    * 
 195  
    * @since        1.0 */
 196  
   //----------------------------------------------------------------
 197  
 
 198  
   public void increment(Output out, Vector args)
 199  
     throws IOException, InterpretException {
 200  
 
 201  0
     AtMacros am = getAtMacros();
 202  
 
 203  0
     if ((args != null) && (args.size() >= 1)) {
 204  0
       Object o1 = args.elementAt(0);
 205  
 
 206  0
       if (o1 != null) {
 207  0
         String mname = o1.toString();
 208  0
         Object macro = am.getMacro(mname);
 209  0
         if (macro == null) {
 210  0
           am.addMacro(mname,"1");
 211  0
         } else {
 212  0
           String nstr = am.interpretCheck(""+am.getStartMacroChar()+mname);
 213  
           try {
 214  0
             am.addMacro(mname,Integer.toString(Integer.parseInt(nstr)+1));
 215  0
           } catch (Exception e) {
 216  0
             am.addMacro(mname,"1");
 217  0
           }
 218  
         }
 219  
       }
 220  
     }
 221  0
   }
 222  
 
 223  
 
 224  
   //----------------------------------------------------------------
 225  
   /** &#064;decrement(NAME) decrements value of integer macro by 1.
 226  
    * 
 227  
    * <p>This macro is used to decrement the value of the macro "NAME"
 228  
    * by 1. If the macro does not exist or has a non numeric value, it
 229  
    * is created and initialized with a value of '1'.
 230  
    *
 231  
    * <pre>
 232  
    * &#064;define(cnt,4)&#064;decrement(cnt)&#064;cnt,&#064decrement(cnt)&#064cnt
 233  
    * </pre>
 234  
    *
 235  
    * <p>The above should result in the output of "3,2".
 236  
    * 
 237  
    * @param        out
 238  
    * 
 239  
    *         The {@link Output output device} to write the results of
 240  
    *         processing the argument to.
 241  
    * 
 242  
    * @param        args
 243  
    * 
 244  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 245  
    * 
 246  
    * @throws        IOException
 247  
    * 
 248  
    *         If there is a problem writing to the {@link Output output device}
 249  
    * 
 250  
    * @throws        InterpretException
 251  
    * 
 252  
    *         If a problem is encountered interpretting the arguments passed.
 253  
    * 
 254  
    * @since        1.0 */
 255  
   //----------------------------------------------------------------
 256  
 
 257  
   public void decrement(Output out, Vector args)
 258  
     throws IOException, InterpretException {
 259  
 
 260  0
     AtMacros am = getAtMacros();
 261  
 
 262  0
     if ((args != null) && (args.size() >= 1)) {
 263  0
       Object o1 = args.elementAt(0);
 264  
 
 265  0
       if (o1 != null) {
 266  0
         String mname = o1.toString();
 267  0
         Object macro = am.getMacro(mname);
 268  0
         if (macro == null) {
 269  0
           am.addMacro(mname,"-1");
 270  0
         } else {
 271  0
           String nstr = am.interpretCheck(""+am.getStartMacroChar()+mname);
 272  
           try {
 273  0
             am.addMacro(mname,Integer.toString(Integer.parseInt(nstr)-1));
 274  0
           } catch (Exception e) {
 275  0
             am.addMacro(mname,"-1");
 276  0
           }
 277  
         }
 278  
       }
 279  
     }
 280  0
   }
 281  
 
 282  
 
 283  
   //----------------------------------------------------------------
 284  
   /** &#064;ifDefined(MACRO,YES,NO) macro - branch if macro is defined.
 285  
    * 
 286  
    * <p>This macro is evaluates the <b>MACRO</b> name passed. If the
 287  
    * evaluated value of the <b>MACRO</b> is a defined macro, then the
 288  
    * <b>YES</b> clause is evaluated. Otherwise the <b>NO</b> clause is
 289  
    * evaluated.</p>
 290  
    *
 291  
    * <p>The following determines if the <b>&#064;name()</b> macro is
 292  
    * defined. If not, it defines it to "fred".
 293  
    *
 294  
    * <pre>
 295  
    * &#064;ifDefined("name",,"&#064;define("name","fred")")
 296  
    * </pre>
 297  
    * 
 298  
    * @param        out
 299  
    * 
 300  
    *         The {@link Output output device} to write the results of
 301  
    *         processing the argument to.
 302  
    * 
 303  
    * @param        args
 304  
    * 
 305  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 306  
    * 
 307  
    * @throws        IOException
 308  
    * 
 309  
    *         If there is a problem writing to the {@link Output output device}
 310  
    * 
 311  
    * @throws        InterpretException
 312  
    * 
 313  
    *         If a problem is encountered interpretting the arguments passed.
 314  
    * 
 315  
    * @since        1.0 */
 316  
   //----------------------------------------------------------------
 317  
 
 318  
   public void ifDefined(Output out, Vector args)
 319  
     throws IOException, InterpretException {
 320  
 
 321  0
     AtMacros am = getAtMacros();
 322  
 
 323  0
     if ((args != null) && ((args.size() == 2) || args.size() == 3)) {
 324  0
       Object o1 = args.elementAt(0);
 325  
 
 326  0
       String v1 = null;
 327  0
       if (o1 != null) v1 = am.interpretCheck(o1.toString());
 328  0
       if (v1 == null) v1 = "";
 329  
 
 330  
                                 // if macro is defined
 331  0
       if (am.getMacro(v1) != null) {
 332  0
         Object e = args.elementAt(1);
 333  0
         if (e != null) out.write(am.interpretCheck(e.toString()));
 334  0
       }
 335  
                                 // handle the undefined case
 336  0
       else if (args.size() == 3) {
 337  0
         Object e = args.elementAt(2);
 338  0
         if (e != null) out.write(am.interpretCheck(e.toString()));
 339  
       }
 340  
     }
 341  0
   }
 342  
 
 343  
 
 344  
   //----------------------------------------------------------------
 345  
   /** &#064;fnb(V0[,V1[,V2[,...]) macro - find first "non-blank" value.
 346  
    * 
 347  
    * <p>This macro returns the first parameter that evaluates to
 348  
    * something other than white space (or no space). It is
 349  
    * particularily useful when defining macros where you want to
 350  
    * provide a default value if the user omits one. Here's an example
 351  
    * that defines "pkb" to print "Paul Blankenbaker (574-7964)" unless
 352  
    * a alternate phone number is passed:
 353  
    *
 354  
    * <pre>
 355  
    * &#064;define("pkb","Paul Blankenbaker (&#064fnb("&#064param(0)","574-7964"))")
 356  
    * </pre>
 357  
    * 
 358  
    * @param        out
 359  
    * 
 360  
    *         The {@link Output output device} to write the results of
 361  
    *         processing the argument to.
 362  
    * 
 363  
    * @param        args
 364  
    * 
 365  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 366  
    * 
 367  
    * @throws        IOException
 368  
    * 
 369  
    *         If there is a problem writing to the {@link Output output device}
 370  
    * 
 371  
    * @throws        InterpretException
 372  
    * 
 373  
    *         If a problem is encountered interpretting the arguments passed.
 374  
    * 
 375  
    * @since        1.0 */
 376  
   //----------------------------------------------------------------
 377  
 
 378  
   public void fnb(Output out, Vector args)
 379  
     throws IOException, InterpretException {
 380  
 
 381  28
     if (args != null) {
 382  28
       int n = args.size();
 383  58
       for (int i = 0; i < n; i++) {
 384  54
         Object f = args.elementAt(i);
 385  54
         if (f == null) continue;
 386  
                                 // as soon as we find a parameter that
 387  
                                 // isn't white space, append it and
 388  
                                 // exit
 389  54
         String text = getAtMacros().interpretCheck(f.toString());
 390  54
         if ((text != null) && (text.length() != 0) &&
 391  
             (text.trim().length() != 0)) {
 392  24
           out.write(text);
 393  24
           return;
 394  
         }
 395  
       }
 396  
     }
 397  4
   }
 398  
 
 399  
 
 400  
   //----------------------------------------------------------------
 401  
   /** &#064;param(N[,t|f]) macro - get parameter value
 402  
    * 
 403  
    * This macro is typically used in the definition of run time macros
 404  
    * (in the VAL parameter of "&#064;define(NAME,VAL)". It allows a user
 405  
    * defined macro (run time defined) to reference the parameter
 406  
    * passed to its invocation. Take a look at the following:
 407  
    *
 408  
    * <pre>
 409  
    * &#064;define(email,"&lt;a href=\"mailto:&#064;param(0)\"&gt;&#064;param(0)&lt;/a&gt;")
 410  
    * &#064;email("paul&#064;mekwin.com")
 411  
    * </pre>
 412  
    *
 413  
    * <p>The above defines a new run time macro "&#064;email", the new
 414  
    * "&#064;email" macro allows the user to pass an argument which is
 415  
    * subsitutes in two places. This provides a means to make some
 416  
    * pretty powerful run time macros.
 417  
    *
 418  
    * <p>Note, the second parameter indicates whether you want the
 419  
    * value of the parameter to be interpretted or not. You can get the
 420  
    * exact value passed (instead of the default interrpretted
 421  
    * results), by passing "f".
 422  
    * 
 423  
    * @param        out
 424  
    * 
 425  
    *         The {@link Output output device} to write the results of
 426  
    *         processing the argument to.
 427  
    * 
 428  
    * @param        args
 429  
    * 
 430  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 431  
    * 
 432  
    * @throws        IOException
 433  
    * 
 434  
    *         If there is a problem writing to the {@link Output output device}
 435  
    * 
 436  
    * @throws        InterpretException
 437  
    * 
 438  
    *         If a problem is encountered interpretting the arguments passed.
 439  
    * 
 440  
    * @since        1.0 */
 441  
   //----------------------------------------------------------------
 442  
 
 443  
   public void param(Output out, Vector args)
 444  
     throws IOException, InterpretException {
 445  
 
 446  374
     AtMacros am = getAtMacros();
 447  
 
 448  374
     int size = args.size();
 449  
 
 450  374
     if ((args != null) && (size >= 1)) {
 451  374
       Object o = args.elementAt(0);
 452  374
       int idx = -1;
 453  
       try {
 454  374
         idx = Integer.parseInt(am.interpretCheck(o.toString()));
 455  0
       } catch (Throwable t) {
 456  0
         throw new InterpretException("@param("+o+") - "+t.getMessage());
 457  374
       }
 458  
       
 459  
                                 // determine if parameter's value
 460  
                                 // should be evaluated
 461  374
       boolean eval = true;
 462  374
       if (size >= 2) {
 463  0
         Object eo = args.elementAt(1);
 464  0
         if (eo != null) {
 465  0
           String estr = am.interpretCheck(eo.toString());
 466  0
           if ((estr.length() > 0) && (estr.charAt(0) == 'f')) eval = false;
 467  
         }
 468  
       }
 469  
       //      out.write("eval:"+eval+"  param:"+am.getParameter(idx,false));
 470  374
       out.write(am.getParameter(idx,eval));
 471  
     }
 472  374
   }
 473  
 
 474  
 
 475  
   //----------------------------------------------------------------
 476  
   /** &#064;quote(TEXT) macro - output text verbatim
 477  
    * 
 478  
    * This macro is invoked in the form "&#064;quote(TEXT)". This macro only
 479  
    * looks at the first argument (additional arguments are
 480  
    * ignored). The text of the first argument is written verbatim to
 481  
    * the output device. This allows one to output macro names. For
 482  
    * example: <b>&#064;quote("&#064;quote(TEXT)")</b> would result in
 483  
    * <b>&#064;quote(TEXT)</b> in the output stream.
 484  
    * 
 485  
    * @param        out
 486  
    * 
 487  
    *         The {@link Output output device} to write the results of
 488  
    *         processing the argument to.
 489  
    * 
 490  
    * @param        args
 491  
    * 
 492  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 493  
    * 
 494  
    * @throws        IOException
 495  
    * 
 496  
    *         If there is a problem writing to the {@link Output output device}
 497  
    * 
 498  
    * @throws        InterpretException
 499  
    * 
 500  
    *         If a problem is encountered interpretting the arguments passed.
 501  
    * 
 502  
    * @since        1.0 */
 503  
   //----------------------------------------------------------------
 504  
 
 505  
   public void quote(Output out, Vector args)
 506  
     throws IOException, InterpretException {
 507  
 
 508  58
     if ((args != null) && (args.size() >= 1)) {
 509  58
       Object o = args.elementAt(0);
 510  58
       if (o != null) out.write(o.toString());
 511  
     }
 512  58
   }
 513  
 
 514  
 
 515  
   //----------------------------------------------------------------
 516  
   /** &#064;setDocumentInfo(TYPE,INFO,yyyy-MM-dd) set information
 517  
    * about the document.
 518  
    *
 519  
    * <p>Often it is desirable to have a consistent set of macros to
 520  
    * retrieve information about the document being processed (such as
 521  
    * its last revision date, copyright, etc). This macro is used to
 522  
    * generate these values.
 523  
    *
 524  
    * <p>You typically use this macro at the start of your document in
 525  
    * the following form:
 526  
    *
 527  
    * <pre>
 528  
    * &#064;setDocumentInfo("cvsId","$Id: Core.java,v 1.1.1.1 2004/01/26 20:46:18 pkb Exp $","2001-12-25")
 529  
    * </pre>
 530  
    *
 531  
    * <p>The following parameters are recognized:
 532  
    *
 533  
    * <dl>
 534  
    *
 535  
    * <dt>TYPE</dt><dd>This is the type of information from which we
 536  
    * are to get the document info from. This describes the format of
 537  
    * the INFO field. Currently, the only recognized type is "cvsId"
 538  
    * which means the info corresponds to the CVS Id value.</dd>
 539  
    *
 540  
    * <dt>INFO</dt><dd>This is the text string which provides
 541  
    * information about the document.</dd>
 542  
    *
 543  
    * <dt>yyyy-MM-dd</dt><dd>This is the copyright date associated with
 544  
    * the document. It must be in the format shown.</dd>
 545  
    *
 546  
    * </dl>
 547  
    * 
 548  
    * <p>This takes the information passed to it and then defines the
 549  
    * following macros:
 550  
    *
 551  
    * <dl>
 552  
    *
 553  
    * <dt>&#064;docLastModifiedMillis()</dt><dd>Will be the Java
 554  
    * millisecond count that the document was last modified - if unable
 555  
    * to determine from the information passed, the current time will
 556  
    * be used.</dd>
 557  
    *
 558  
    * <dt>&#064;docVersion()</dt><dd>Will be the version number
 559  
    * associated with the document, if unable to determine, this will
 560  
    * default to "0.0.1".</dd>
 561  
    *
 562  
    * <dt>&#064;copyRightYear()</dt><dd>Will be the year field from the
 563  
    * copy right.</dd>
 564  
    *
 565  
    * <dt>&#064;copyRightDate()</dt><dd>Will be the copy right date.</dd>
 566  
    *
 567  
    * <dt>&#064;copyRightMillis()</dt><dd>Will be the copy right date
 568  
    * as a Java millisecond time value.</dd>
 569  
    *
 570  
    * </dl>
 571  
    * 
 572  
    * @param        out
 573  
    * 
 574  
    *         The {@link Output output device} to write the results of
 575  
    *         processing the argument to.
 576  
    * 
 577  
    * @param        args
 578  
    * 
 579  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 580  
    * 
 581  
    * @throws        IOException
 582  
    * 
 583  
    *         If there is a problem writing to the {@link Output output device}
 584  
    * 
 585  
    * @throws        InterpretException
 586  
    * 
 587  
    *         If a problem is encountered interpretting the arguments passed.
 588  
    * 
 589  
    * @since        1.0 */
 590  
   //----------------------------------------------------------------
 591  
 
 592  
   public void setDocumentInfo(Output out, Vector args) 
 593  
     throws IOException, InterpretException {
 594  
 
 595  2
     AtMacros am = getAtMacros();
 596  
 
 597  
                                 // set copyright info
 598  2
     String cr = getStringParameter(args,2);
 599  2
     SimpleDateFormat ymd = new SimpleDateFormat("y-M-d");
 600  2
     ymd.setLenient(true);
 601  
     try {
 602  2
       Date crDate = ymd.parse(cr);
 603  2
       am.addMacro("copyRightDate",cr);
 604  2
       am.addMacro("copyRightMillis",""+crDate.getTime());
 605  2
       int dpos = cr.indexOf('-');
 606  2
       am.addMacro("copyRightYear",cr.substring(0,dpos));
 607  0
     } catch (ParseException pe) {
 608  0
       throw new InterpretException("missing/bad copyright parameter "+
 609  
                                    "to setDocumentInfoMacro");
 610  2
     }
 611  
 
 612  2
     long lastMod = System.currentTimeMillis();
 613  2
     String ver = "0.0.1";
 614  
 
 615  2
     if (getStringParameter(args,0).equals("cvsId")) {
 616  2
       String cvsId = getStringParameter(args,1);
 617  2
       int vpos = cvsId.indexOf(",v ");
 618  2
       if (vpos > 0) {
 619  2
         vpos += 3;
 620  2
         int spos = cvsId.indexOf(' ',vpos);
 621  2
         if (spos > vpos) {
 622  2
           ver = cvsId.substring(vpos,spos);
 623  
           try {
 624  2
             SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
 625  2
             Date lastModDate = df.parse(cvsId.substring(spos+1));
 626  2
             lastMod = lastModDate.getTime();
 627  0
           } catch (Exception e) {
 628  0
             throw new InterpretException("CVS modification date not in "+
 629  
                                          "yyyy/MM/dd HH:mm:ss format");
 630  2
           }
 631  
         }
 632  
       }
 633  
     }
 634  
 
 635  2
     am.addMacro("docLastModifiedMillis",""+lastMod);
 636  2
     am.addMacro("docVersion",ver);
 637  2
   }
 638  
 
 639  
 
 640  
   //----------------------------------------------------------------
 641  
   /** &#064;formatMillis([MILLIS][,DATE_FMT[,TIME_FMT]],[TZ]) macro -
 642  
    * format a Java millisecond count.
 643  
    * 
 644  
    * <p>This macro is invoked in the form "&#064;millis(MILLIS)". This
 645  
    * macro accepts up to four arguments (how to format the date/time
 646  
    * and the time zone). Refer to the {@link SimpleDateFormat} class
 647  
    * if you want to specify your own custom format (like:
 648  
    * "yyyy-MM-dd").</p>
 649  
    *
 650  
    * <p>The four optional parameters to this macro accepts include:</p>
 651  
    *
 652  
    * <dl>
 653  
    *
 654  
    * <dt>MILLIS</dt><dd>This value can be the Java millisecond count
 655  
    * of the time to be formatted. If omitted, the current system time
 656  
    * is used.</dd>
 657  
    *
 658  
    * <dt>DATE_FMT</dt><dd>This parameter can be one of the Java
 659  
    * specific formats (like: "long", "short", etc - described
 660  
    * below). Or, it can be a full date/time format using the
 661  
    * characters recognized by the {@link java.text.SimpleDateFormat}
 662  
    * class (like "yyyy-MMM-dd hh:mm:ss").</dd>
 663  
    *
 664  
    * <dt>TIME_FMT</dt><dd>This parameter is only used if you want to
 665  
    * specify the locale specific formats supported by the Java run
 666  
    * time.</dd>
 667  
    *
 668  
    * <dt>TZ</dt><dd>You only need to pass this parameter if you want
 669  
    * to force a particular time zone. It may be any string value (it
 670  
    * will be interpretted first) recognized as a valid parameter to
 671  
    * {@link TimeZone#getTimeZone(String)}. For example: "UTC",
 672  
    * "America/Los_Angeles", or "GMT+10". If you pass a unrecognized
 673  
    * timezone, we will ignore your request (we will log a debug
 674  
    * message) and use the default time zone for the JVM.</dd>
 675  
    *
 676  
    * </dl>
 677  
    *
 678  
    * <p>If you want to use one of the built in local formats, pass use
 679  
    * one of the following keywords for the <b>DATE_FMT</b> and/or
 680  
    * <b>TIME_FMT</b> parameters:</p>
 681  
    *
 682  
    * <dl>
 683  
    *
 684  
    * <dt>none</dt><dd>Don't include (only one of the parameters should
 685  
    * be set to this value).</dd>
 686  
    *
 687  
    * <dt>short</dt><dd>Use the {@link DateFormat#SHORT} format for
 688  
    * this portion.
 689  
    *
 690  
    * <dt>medium</dt><dd>Use the {@link DateFormat#MEDIUM} format for
 691  
    * this portion.
 692  
    *
 693  
    * <dt>long</dt><dd>Use the {@link DateFormat#LONG} format for
 694  
    * this portion.
 695  
    *
 696  
    * <dt>full</dt><dd>Use the {@link DateFormat#FULL} format for
 697  
    * this portion.
 698  
    *
 699  
    * </dl>
 700  
    * 
 701  
    * @param        out
 702  
    * 
 703  
    *         The {@link Output output device} to write the results of
 704  
    *         processing the argument to.
 705  
    * 
 706  
    * @param        args
 707  
    * 
 708  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 709  
    * 
 710  
    * @throws        IOException
 711  
    * 
 712  
    *         If there is a problem writing to the {@link Output output device}
 713  
    * 
 714  
    * @throws        InterpretException
 715  
    * 
 716  
    *         If a problem is encountered interpretting the arguments passed.
 717  
    * 
 718  
    * @since        1.0 */
 719  
   //----------------------------------------------------------------
 720  
 
 721  
   public void formatMillis(Output out, Vector args) 
 722  
     throws IOException, InterpretException {
 723  
 
 724  20
     String fmt = getStringParameter(args,1);
 725  20
     String fmt2 = getStringParameter(args,2);
 726  20
     String tz = getStringParameter(args,3);
 727  
 
 728  20
     DateFormat df = null;
 729  
 
 730  
                                 // if we have the two argument form
 731  20
     if (fmt2.length() > 0) {
 732  16
       int dfmt = getDateTimeFormat(fmt);
 733  16
       int tfmt = getDateTimeFormat(fmt2);
 734  16
       if (dfmt != -1) {
 735  12
         if (tfmt != -1) {
 736  8
           df = DateFormat.getDateTimeInstance(dfmt,tfmt);
 737  8
         }
 738  
         else {
 739  4
           df = DateFormat.getDateInstance(dfmt);
 740  
         }
 741  4
       }
 742  4
       else if (tfmt != -1) {
 743  4
         df = DateFormat.getTimeInstance(tfmt);
 744  
       }
 745  16
     }
 746  4
     else if (fmt.length() > 0) {
 747  4
       df = new SimpleDateFormat(fmt);
 748  
     }
 749  
 
 750  20
     if (df == null) df = DateFormat.getDateTimeInstance();
 751  
 
 752  20
     String text = null;
 753  20
     long now = getLongParameter(args,0,System.currentTimeMillis());
 754  20
     Date curTime = new Date(now);
 755  
 
 756  20
     if (tz.length() > 0) {
 757  
       try {
 758  10
         df.setTimeZone(TimeZone.getTimeZone(tz));
 759  0
       } catch (Throwable tze) {
 760  0
         if (Debug.ENABLED && Debug.isEnabledFor(3)) {
 761  0
           Debug.out("problem with time zone \""+tz+"\" - ignoring",tze);
 762  
         }
 763  10
       }
 764  
     }
 765  
 
 766  
     try {
 767  20
       text = df.format(curTime);
 768  0
     } catch (Throwable t) {
 769  0
       if (Debug.ENABLED && Debug.isEnabledFor(3)) {
 770  0
         Debug.out("problem with date format:"+df,t);
 771  
       }
 772  0
       text = DateFormat.getDateTimeInstance().format(curTime);
 773  20
     }
 774  
 
 775  20
     out.write(text);
 776  20
   }
 777  
 
 778  
 
 779  
   //----------------------------------------------------------------
 780  
   /** &#064;now() macro - dumps current time
 781  
    * 
 782  
    * <p>This macro is invoked in the form "&#064;now()". This macro
 783  
    * accepts one argument (how to format the date/time). Refer to the
 784  
    * {@link SimpleDateFormat} class if you want to specify your own
 785  
    * custom format (like: "yyyy-MM-dd").
 786  
    *
 787  
    * <p>If you want to use one of the built in local formats, pass two
 788  
    * arguments in the form "&#064;now(DATE_FMT,TIME_FMT)", where the
 789  
    * first parameter corresponds to the format to use for the date
 790  
    * portion and the second parameter corresponds to what to use for
 791  
    * the time portion. The following formats are recognized:
 792  
    *
 793  
    * <dl>
 794  
    *
 795  
    * <dt>none</dt><dd>Don't include (only one of the parameters should
 796  
    * be set to this value).</dd>
 797  
    *
 798  
    * <dt>short</dt><dd>Use the {@link DateFormat#SHORT} format for
 799  
    * this portion.
 800  
    *
 801  
    * <dt>medium</dt><dd>Use the {@link DateFormat#MEDIUM} format for
 802  
    * this portion.
 803  
    *
 804  
    * <dt>long</dt><dd>Use the {@link DateFormat#LONG} format for
 805  
    * this portion.
 806  
    *
 807  
    * <dt>full</dt><dd>Use the {@link DateFormat#FULL} format for
 808  
    * this portion.
 809  
    *
 810  
    * </dl>
 811  
    * 
 812  
    * @param        out
 813  
    * 
 814  
    *         The {@link Output output device} to write the results of
 815  
    *         processing the argument to.
 816  
    * 
 817  
    * @param        args
 818  
    * 
 819  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 820  
    * 
 821  
    * @throws        IOException
 822  
    * 
 823  
    *         If there is a problem writing to the {@link Output output device}
 824  
    * 
 825  
    * @throws        InterpretException
 826  
    * 
 827  
    *         If a problem is encountered interpretting the arguments passed.
 828  
    * 
 829  
    * @since        1.0 */
 830  
   //----------------------------------------------------------------
 831  
   /*
 832  
   public void now(Output out, Vector args) 
 833  
     throws IOException, InterpretException {
 834  
 
 835  
     String fmt = getStringParameter(args,0);
 836  
     String fmt2 = getStringParameter(args,1);
 837  
 
 838  
     DateFormat df = null;
 839  
 
 840  
                                 // if we have the two argument form
 841  
     if (fmt2.length() > 0) {
 842  
       int dfmt = getDateTimeFormat(fmt);
 843  
       int tfmt = getDateTimeFormat(fmt2);
 844  
       if (dfmt != -1) {
 845  
         if (tfmt != -1) {
 846  
           df = DateFormat.getDateTimeInstance(dfmt,tfmt);
 847  
         }
 848  
         else {
 849  
           df = DateFormat.getDateInstance(dfmt);
 850  
         }
 851  
       }
 852  
       else if (tfmt != -1) {
 853  
         df = DateFormat.getTimeInstance(tfmt);
 854  
       }
 855  
     }
 856  
     else if (fmt.length() > 0) {
 857  
       df = new SimpleDateFormat(fmt);
 858  
     }
 859  
 
 860  
     if (df == null) df = DateFormat.getDateTimeInstance();
 861  
 
 862  
     String text = null;
 863  
     Date curTime = new Date();
 864  
     try {
 865  
       text = df.format(curTime);
 866  
     } catch (Throwable t) {
 867  
       if (Debug.ENABLED && Debug.isEnabledFor(3)) {
 868  
         Debug.out("problem with date format:"+df,t);
 869  
       }
 870  
       text = DateFormat.getDateTimeInstance().format(curTime);
 871  
     }
 872  
 
 873  
     out.write(text);
 874  
   }
 875  
   */
 876  
 
 877  
   //----------------------------------------------------------------
 878  
   /** &#064;debug(LEVEL,TEXT) macro - debug output.
 879  
    * 
 880  
    * This macro is invoked in the form "&#064;debug(LEVEL,TEXT)". If
 881  
    * the current {@link Debug#isEnabledFor debug level} is enabled for
 882  
    * the LEVEL specified, the text is interpretted and debug output is
 883  
    * generated. This can be VERY useful when tracking down problems in
 884  
    * your source file.
 885  
    * 
 886  
    * @param        out
 887  
    * 
 888  
    *         The {@link Output output device} to write the results of
 889  
    *         processing the argument to.
 890  
    * 
 891  
    * @param        args
 892  
    * 
 893  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 894  
    * 
 895  
    * @throws        IOException
 896  
    * 
 897  
    *         If there is a problem writing to the {@link Output output device}
 898  
    * 
 899  
    * @throws        InterpretException
 900  
    * 
 901  
    *         If a problem is encountered interpretting the arguments passed.
 902  
    * 
 903  
    * @since        1.0 */
 904  
   //----------------------------------------------------------------
 905  
 
 906  
   public void debug(Output out, Vector args)
 907  
     throws IOException, InterpretException {
 908  
 
 909  
                                 // get debug level
 910  76
     int dlevel = getIntParameter(args,0,-1);
 911  
                                 // if we should output debug info, do so now
 912  76
     if (dlevel >= 0 && Debug.ENABLED && Debug.isEnabledFor(dlevel)) {
 913  
                                 // use second argument as output to
 914  
                                 // debug message
 915  0
       Debug.out(getStringParameter(args,1));
 916  
     }
 917  
 
 918  76
   }
 919  
 
 920  
 
 921  
   //----------------------------------------------------------------
 922  
   /** &#064;define(NAME,VAL[,OPT]) macro - define a new macro.
 923  
    * 
 924  
    * This macro is invoked in the form
 925  
    * "&#064;define(NAME,VAL[,OPT])". This macro is used to define new
 926  
    * text replacement macros. The first argument NAME is the name of
 927  
    * the new macro to define (do not include the leading "&#064;"
 928  
    * sign). The second argument VAL is the text which is to be
 929  
    * subsituted. The third arguments allows for some specialized
 930  
    * options during the definition. For example:
 931  
    *
 932  
    * <pre>
 933  
    * &#064;define(pkb_email,"&#064;quote(paul&#064;mekwin.com)")
 934  
    * </pre>
 935  
    *
 936  
    * <p>After interpretting the above, one could then use
 937  
    * "&#064;pkb_email()" in the document and have "paul&#064;mekwin.com"
 938  
    * appear. It should be noted, that the "VAL" area can contain
 939  
    * references to other macros. For example:
 940  
    *
 941  
    * <pre>
 942  
    * &#064;define(pkb,"Paul Blankenbaker (&#064;pkb_email)")
 943  
    * </pre>
 944  
    *
 945  
    * <p>There are two important concepts to understand with the
 946  
    * above. One is that the &#064;pkb macro just defined contains a
 947  
    * reference to another macro. This is handled properly and the
 948  
    * contained &#064;pkb_email reference will be expanded each time the
 949  
    * &#064;pkb macro is used. The second concept is that the expansion
 950  
    * occurs at the time the &#064;pkb macro is used, not at the time it is
 951  
    * defined. In other words, if someone changed the definition of the
 952  
    * &#064;pkb_email macro, then it would affect subsequent invocations of
 953  
    * the &#064;pkb macro.
 954  
    *
 955  
    * <p>The third parameter to this macro is optional, and can be
 956  
    * extremely useful in some circumstances. The third parameter can
 957  
    * be one of the following:
 958  
    *
 959  
    * <dl>
 960  
    *
 961  
    * <dt><b>ifnew</b></dt><dd>The "ifnew" option means that the
 962  
    * definition should only be accepted if a definition does not
 963  
    * already exist. This can be a very handy way to provide default
 964  
    * values.</dd>
 965  
    *
 966  
    * <dt><b>now</b></dt><dd>The "now" option means that the value
 967  
    * should be interpretted immediately (right now). This can be more
 968  
    * efficient and prevents future changes from having affects.</dd>
 969  
    *
 970  
    * </dl>
 971  
    *
 972  
    * <p>To get an idea of how these behave, try running the the
 973  
    * following through to see what comes out:
 974  
    *
 975  
    * <pre>
 976  
    * &#064;define("name","Joe Schmoe")
 977  
    * &#064;define("phone","333-333-3333")
 978  
    * &#064;define("pname","&#064;name &#064;phone")
 979  
    * &#064;define("nname","&#064;name &#064;phone","now")
 980  
    * &#064;define("phone","444-444-4444")
 981  
    * &#064;define("phone","555-555-5555","ifnew")
 982  
    * &#064;quote("&#064;pname=")&#064;pname
 983  
    * &#064;quote("&#064;nname=")&#064;nname
 984  
    * </pre>
 985  
    * 
 986  
    * @param        out
 987  
    * 
 988  
    *         The {@link Output output device} to write the results of
 989  
    *         processing the argument to.
 990  
    * 
 991  
    * @param        args
 992  
    * 
 993  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 994  
    * 
 995  
    * @throws        IOException
 996  
    * 
 997  
    *         If there is a problem writing to the {@link Output output device}
 998  
    * 
 999  
    * @throws        InterpretException
 1000  
    * 
 1001  
    *         If a problem is encountered interpretting the arguments passed.
 1002  
    * 
 1003  
    * @since        1.0 */
 1004  
   //----------------------------------------------------------------
 1005  
 
 1006  
   public void define(Output out, Vector args) 
 1007  
     throws IOException, InterpretException {
 1008  
 
 1009  662
     AtMacros am = getAtMacros();
 1010  
 
 1011  662
     if ((args != null) && (args.size() >= 2)) {
 1012  
                                 // allow interpretation of name
 1013  662
       String name = getStringParameter(args,0);
 1014  662
       Object v = args.elementAt(1);
 1015  662
       if ((name != null) && (v != null)) {
 1016  662
         String val = v.toString();
 1017  
 
 1018  
                                 // see if any special options specified
 1019  662
         if (args.size() > 2) {
 1020  216
           Object op = args.elementAt(2);
 1021  216
           String opStr = null;
 1022  216
           if (op != null) opStr = op.toString();
 1023  
 
 1024  216
           if (opStr != null) {
 1025  
                                 // "now" option requires us to evaluate now
 1026  216
             if (opStr.equals("now")) { val = am.interpretCheck(val); }
 1027  
                                 // "ifnew" option means to skip
 1028  
                                 // definition if already defined
 1029  24
             else if (opStr.equals("ifnew")) {
 1030  24
               if (am.getMacro(name) != null) return;
 1031  
             }
 1032  
           }
 1033  
         }
 1034  646
         am.addMacro(name,val);
 1035  
       }
 1036  
     }
 1037  646
   }
 1038  
 
 1039  
 
 1040  
   //----------------------------------------------------------------
 1041  
   /** &#064;definition(NAME) macro - fetch definition of a macro.
 1042  
    * 
 1043  
    * This macro is mainly used for debugging purposes, it returns the
 1044  
    * current definition of a macro. You pass the NAME of the macro
 1045  
    * (without the leading "&#064;" symbol) which you want to retrieve the
 1046  
    * definition for. The current definition of the macro is returned
 1047  
    * as a text string. If the macro was created with the
 1048  
    * "&#064;define(NAME,VAL)" macro, then the returned text will be
 1049  
    * "VAL". If the macro is a built-in macro (such as
 1050  
    * "&#064;definition(NAME)", then the returned value will be the name of
 1051  
    * the Java class/method used to handle the macro.
 1052  
    * 
 1053  
    * @param        out
 1054  
    * 
 1055  
    *         The {@link Output output device} to write the results of
 1056  
    *         processing the argument to.
 1057  
    * 
 1058  
    * @param        args
 1059  
    * 
 1060  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 1061  
    * 
 1062  
    * @throws        IOException
 1063  
    * 
 1064  
    *         If there is a problem writing to the {@link Output output device}
 1065  
    * 
 1066  
    * @throws        InterpretException
 1067  
    * 
 1068  
    *         If a problem is encountered interpretting the arguments passed.
 1069  
    * 
 1070  
    * @since        1.0 */
 1071  
   //----------------------------------------------------------------
 1072  
 
 1073  
   public void definition(Output out, Vector args) 
 1074  
     throws IOException, InterpretException {
 1075  
 
 1076  2
     AtMacros am = getAtMacros();
 1077  
 
 1078  2
     if ((args != null) && (args.size() >= 1)) {
 1079  2
       Object n = args.elementAt(0);
 1080  2
       if (n != null) {
 1081  2
         Object o = am.getMacro(n.toString());
 1082  2
         out.write(o);
 1083  
       }
 1084  
     }
 1085  2
   }
 1086  
 
 1087  
 
 1088  
   //----------------------------------------------------------------
 1089  
   /** &#064;systemProperty(NAME[,DEF]) macro - fetch a specific system
 1090  
    * property.
 1091  
    * 
 1092  
    * This macro is evaluates the "NAME" parameter and then tries to
 1093  
    * fetch the "system property" it identifies. If the system property
 1094  
    * is successfully retrieved, it is returned. Otherwise, if the
 1095  
    * system property is not available (or attempts to retrieve it
 1096  
    * result in some sort of error), the optional DEF parameter is
 1097  
    * evaluated and returned.
 1098  
    *
 1099  
    * <p>Here are some sample (and useful definitions) out of "Core.At"
 1100  
    * which area available and make use of this:
 1101  
    *
 1102  
    * <pre>
 1103  
    * &#064;define("userName","&#064;systemProperty("user.name","unknown")","now")
 1104  
    * &#064;define("userHome","&#064;systemProperty("user.home",".")","now")
 1105  
    * </pre>
 1106  
    * 
 1107  
    * @param        out
 1108  
    * 
 1109  
    *         The {@link Output output device} to write the results of
 1110  
    *         processing the argument to.
 1111  
    * 
 1112  
    * @param        args
 1113  
    * 
 1114  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 1115  
    * 
 1116  
    * @throws        IOException
 1117  
    * 
 1118  
    *         If there is a problem writing to the {@link Output output device}
 1119  
    * 
 1120  
    * @throws        InterpretException
 1121  
    * 
 1122  
    *         If a problem is encountered interpretting the arguments passed.
 1123  
    * 
 1124  
    * @since        1.0 */
 1125  
   //----------------------------------------------------------------
 1126  
 
 1127  
   public void systemProperty(Output out, Vector args) 
 1128  
     throws IOException, InterpretException {
 1129  
 
 1130  156
     String key = getStringParameter(args,0);
 1131  156
     String text = null;
 1132  
 
 1133  
     try {
 1134  156
       text = System.getProperty(key);
 1135  4
     } catch (Throwable t) { 
 1136  4
       if (Debug.ENABLED && Debug.isEnabledFor(3)) {
 1137  0
         Debug.out("problem retrieving system property for \""+key+"\":"+t);
 1138  
       }
 1139  152
     }
 1140  
 
 1141  156
     if (text == null) text = getStringParameter(args,1);
 1142  156
     if (text.length() > 0) out.write(text);
 1143  
 
 1144  156
   }
 1145  
 
 1146  
 
 1147  
   //----------------------------------------------------------------
 1148  
   /** &#064;dumpDefinitions() macro - dump definition of all macros.
 1149  
    * 
 1150  
    * <p>This macro is mainly used for debugging purposes. It dumps the
 1151  
    * definition of ALL defined macros.
 1152  
    *
 1153  
    * <p>NOTE: You may optionally pass a single argument to this
 1154  
    * method. If passed, the argument will be expanded for each
 1155  
    * definition in our macro dictionary. The following macros will be
 1156  
    * available:
 1157  
    *
 1158  
    * <dl> 
 1159  
    *
 1160  
    * <dt>&#064;dumpDefName()</dt><dd>The name of the macro the
 1161  
    * definition refers to.
 1162  
    *
 1163  
    * <dt>&#064;dumpDefValue()</dt><dd>The string value of the macro
 1164  
    * (this may be the name of the Java method used to evaluate
 1165  
    * it.</dd>
 1166  
    *
 1167  
    * </dl>
 1168  
    *
 1169  
    * <p>Here is an example which produces the same results as the
 1170  
    * default output:
 1171  
    *
 1172  
    * <pre>
 1173  
    * &#064;dumpDefinitions("&#064;dumpDefName()=&#064;dumpDefValue()
 1174  
    * ")
 1175  
    * </pre>
 1176  
    *
 1177  
    * <p>Here's an example which provides a little fancier output in
 1178  
    * HTML:
 1179  
    *
 1180  
    * <pre>
 1181  
    * &#064;dumpDefinitions("&lt;h2&gt;&#064;quote(&#064;)&#064;dumpDefName()&lt;/h2&gt;
 1182  
    * &lt;pre&gt;
 1183  
    * &#064;htmlEscape("&#064;dumpDefValue()")
 1184  
    * &lt;/pre&gt;
 1185  
    * ")
 1186  
    * </pre>
 1187  
    * 
 1188  
    * @param        out
 1189  
    * 
 1190  
    *         The {@link Output output device} to write the results of
 1191  
    *         processing the argument to.
 1192  
    * 
 1193  
    * @param        args
 1194  
    * 
 1195  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 1196  
    * 
 1197  
    * @throws        IOException
 1198  
    * 
 1199  
    *         If there is a problem writing to the {@link Output output device}
 1200  
    * 
 1201  
    * @throws        InterpretException
 1202  
    * 
 1203  
    *         If a problem is encountered interpretting the arguments passed.
 1204  
    * 
 1205  
    * @since        1.0 */
 1206  
   //----------------------------------------------------------------
 1207  
 
 1208  
   public void dumpDefinitions(Output out, Vector args) 
 1209  
     throws IOException, InterpretException {
 1210  
 
 1211  0
     AtMacros am = getAtMacros();
 1212  
 
 1213  
                                 // default dump ouput
 1214  0
     String format = "@dumpDefName()=@dumpDefValue()"+_LineSeparator;
 1215  
                                 // see if user overrode format
 1216  0
     if ((args != null) && (args.size() > 0)) {
 1217  0
       Object o = args.elementAt(0);
 1218  0
       if (o != null) format = o.toString();
 1219  
     }
 1220  
                                 // get and sort macro names that are defined
 1221  0
     Vector allNames = new Vector(500);
 1222  0
     Enumeration keys = am.getMacroNames();
 1223  0
     while (keys.hasMoreElements()) {
 1224  0
       String name = keys.nextElement().toString();
 1225  0
       allNames.addElement(name);
 1226  0
     }
 1227  
 
 1228  0
     String[] mnames = new String[allNames.size()];
 1229  0
     for (int i = 0; i < mnames.length; i++) {
 1230  0
       mnames[i] = (String) allNames.elementAt(i);
 1231  
     }
 1232  0
     Arrays.sort(mnames,new com.ccg.util.CompareStrings());
 1233  
 
 1234  0
     class Verbatim implements MacroHandler {
 1235  
       String _Text;
 1236  
       public void process(Output ov, Vector av)
 1237  
         throws IOException, InterpretException {
 1238  0
         ov.write(_Text);
 1239  0
       }
 1240  
     }
 1241  
 
 1242  0
     Verbatim v = new Verbatim();
 1243  
 
 1244  0
     am.addMacro("dumpDefValue",v);
 1245  
 
 1246  
                                 // now, go process each macro definition
 1247  0
     for (int i = 0; i < mnames.length; i++) {
 1248  0
       am.addMacro("dumpDefName",mnames[i]);
 1249  0
       v._Text = am.getMacro(mnames[i]).toString();
 1250  0
       out.write(am.interpretCheck(format));
 1251  
     }
 1252  
 
 1253  
                                 // reset to blank definitions - not
 1254  
                                 // sure if we need to do this
 1255  
     //    am.addMacro("dumpDefName",null);
 1256  
     //    am.addMacro("dumpDefValue",null);
 1257  
     /*
 1258  
     String beforeAll = null;
 1259  
     //    String beforeEach = ""+am.getStartMacroChar()+"define(\"";
 1260  
     //    String betweenEach = "\",\"";
 1261  
     //    String afterEach = "\")\n";
 1262  
     String beforeEach = null;
 1263  
     String betweenEach = "=";
 1264  
     String afterEach = "\n";
 1265  
     String afterAll = null;
 1266  
 
 1267  
     Enumeration keys = am.getMacroNames();
 1268  
     while (keys.hasMoreElements()) {
 1269  
       String name = keys.nextElement().toString();
 1270  
       Object o = am.getMacro(name);
 1271  
 
 1272  
       if (beforeEach != null) out.write(beforeEach);
 1273  
       out.write(name);
 1274  
       out.write(betweenEach);
 1275  
       out.write(o);
 1276  
       out.write(afterEach);
 1277  
     }
 1278  
     */
 1279  0
   }
 1280  
 
 1281  
 
 1282  
   //----------------------------------------------------------------
 1283  
   /** &#064;include(SOURCE,[IGNERR],[NOOUT]) insert and process other file(s).
 1284  
    * 
 1285  
    * <p>This macro is used to load and process the contents of another
 1286  
    * file. Currently the full or relative path to the source must be
 1287  
    * specified (in the future, path searching may be added).
 1288  
    *
 1289  
    * <p>It should be noted however, that the CLASSPATH and/or JAR
 1290  
    * files are searched. For example, the file
 1291  
    * "/com/ccg/macros/at/Jnlp.At" would be found as its included with
 1292  
    * the distribution. Check the "/com/ccg/macros/at" directory for
 1293  
    * "*.At" files which are available.
 1294  
    *
 1295  
    * <p>For example, to include the file
 1296  
    * "/opt/include/atmacros/companies.atmacros", one could use the
 1297  
    * following command:
 1298  
    *
 1299  
 <pre>
 1300  
 &#064;include("/etc/hosts")
 1301  
 </pre>
 1302  
    *
 1303  
    * <p>The second parameter IGNERR is optional. It may be set to
 1304  
    * either "true" or "false" (only first letter is checked). If
 1305  
    * omitted, it defaults to a value of "false". When set to "true",
 1306  
    * then no error will be thrown if the file is not found. If set to
 1307  
    * "false" (or omitted), then an error will be thrown if the desired
 1308  
    * SOURCE could not be found.
 1309  
    *
 1310  
    * <p>The third parameter DISOUT is optional. It may be set to
 1311  
    * either "true", "false", "cdata" or "definitions" (only first letter is
 1312  
    * checked). If omitted, it defaults to a value of "false". When set
 1313  
    * to "true", then no output will be produced while interpretting
 1314  
    * the file included (this allows one to load definition
 1315  
    * files). When set to "false" (or omitted), any output produced as
 1316  
    * a result of interpretting the file will be written to the current
 1317  
    * output device. When set to "definition" (or "d"), no output will
 1318  
    * be generated, AND the file will only be included if it has not be
 1319  
    * included in the past (this is useful when you don't want to
 1320  
    * bother processing macro definition files more than once).</p>
 1321  
    *
 1322  
    * <p>When the third parameter is set to "cdata" (or "c"), the
 1323  
    * contents of the file are treated as character data (similar to
 1324  
    * XML) and placed in the output verbatim.</p>
 1325  
    *
 1326  
    * <p>When using this directive to include definition files, it is
 1327  
    * often handy to set the DISOUT value to "definition" (or "d") to
 1328  
    * disable any output as a result of interpretting the definition
 1329  
    * file (this allows one to enter comments in their definition
 1330  
    * files). It also prevents the same definitions from being loaded
 1331  
    * more than once during a run.</p>
 1332  
    * 
 1333  
    * @param        out
 1334  
    * 
 1335  
    *         The {@link Output output device} to write the results of
 1336  
    *         processing the argument to.
 1337  
    * 
 1338  
    * @param        args
 1339  
    * 
 1340  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 1341  
    * 
 1342  
    * @throws        IOException
 1343  
    * 
 1344  
    *         If there is a problem writing to the {@link Output output device}
 1345  
    * 
 1346  
    * @throws        InterpretException
 1347  
    * 
 1348  
    *         If a problem is encountered interpretting the arguments passed.
 1349  
    * 
 1350  
    * @since        1.0 */
 1351  
   //----------------------------------------------------------------
 1352  
 
 1353  
   public void include(Output out, Vector args) 
 1354  
     throws IOException, InterpretException {
 1355  
 
 1356  46
     int argc = args.size();
 1357  46
     if (argc < 1) return;
 1358  
 
 1359  46
     AtMacros am = getAtMacros();
 1360  
 
 1361  46
     String source = am.interpretCheck(args.elementAt(0).toString());
 1362  
 
 1363  
     try {
 1364  
                                 // check for "true"/"definition" in
 1365  
                                 // second argument
 1366  46
       String disout = getStringParameter(args,2);
 1367  46
       char type = 'f';                // assume not
 1368  46
       if (disout.length() > 0) type = Character.toLowerCase(disout.charAt(0));
 1369  
 
 1370  46
       if (type == 't') {
 1371  0
         out = OutputNull.getInstance();
 1372  0
       } 
 1373  
                                 // if definition file that's already
 1374  
                                 // been loaded, then don't bother with
 1375  
                                 // it
 1376  46
       else if (type == 'd') {
 1377  42
         if (_Includes.contains(source)) return;
 1378  38
         out = OutputNull.getInstance();
 1379  
       }
 1380  
 
 1381  
                                 // update that we've "included" this
 1382  
                                 // source - assume it will error
 1383  42
       _Includes.put(source,source);
 1384  
 
 1385  
                                 // get source file to process
 1386  42
       Reader in = com.ccg.io.Utility.getReader(source);
 1387  
 
 1388  
                                 // go interpret the contents of the file
 1389  42
       if (type != 'c') {
 1390  42
         am.interpretCheck(new InputReader(in),out);
 1391  42
       } else {
 1392  0
         char[] buf = new char[8096];
 1393  0
         int len = -1;
 1394  0
         while ((len = in.read(buf)) > 0) {
 1395  0
           out.write(buf,0,len);
 1396  0
         }
 1397  
       }
 1398  
 
 1399  
                                 // indicate the included source file
 1400  
                                 // had no errors
 1401  42
       _Includes.put(source,source);
 1402  
 
 1403  0
     } catch (IOException ioe) {
 1404  0
       if (argc > 1) {
 1405  0
         String cont = am.interpretCheck(args.elementAt(1).toString());
 1406  0
         if (cont.length() > 0 && 
 1407  
             Character.toLowerCase(cont.charAt(0)) == 't') {
 1408  0
           Log.warning("Warning: source \""+source+
 1409  
                       "\" skipped:"+ioe.toString());
 1410  0
           ioe = null;                // OK to continue
 1411  
         }
 1412  
       }
 1413  0
       if (ioe != null) throw ioe;
 1414  42
     }
 1415  
 
 1416  42
   }
 1417  
 
 1418  
 
 1419  
   //----------------------------------------------------------------  
 1420  
   // private data
 1421  
   //----------------------------------------------------------------
 1422  
 
 1423  
   private int getDateTimeFormat(String s) {
 1424  32
     s = s.toLowerCase();
 1425  32
     if (s.equals("short")) return DateFormat.SHORT;
 1426  28
     if (s.equals("medium")) return DateFormat.MEDIUM;
 1427  20
     if (s.equals("long")) return DateFormat.LONG;
 1428  16
     if (s.equals("full")) return DateFormat.FULL;
 1429  8
     return -1;
 1430  
   }
 1431  
 
 1432  
                                 // what source(s) have been included
 1433  
   private Hashtable _Includes;
 1434  
 
 1435  
 }