UPD Mail Archive: Re: UPD> completeness: commands generation

Re: UPD> completeness: commands generation (xpdo)

From: Jim Lo (Jim.Lo@eng.sun.com)
Date: Fri Dec 01 2000 - 15:21:14 EST

  • Next message: Jim Lo: "Re: UPD> completeness: Printer error/status monitoring (Responses framework)"

    <<My apology for resending this email due to the lack of an attached document in a hurry for lunch>>

    Hi,

    Per Norbert Schade's request, I am trying to exchange what many of us
    working for Sun Microsystem think in many areas of printer description
    in terms of what may be a must and the possible solutions from the perspectives
    of looking for a "long term" solution for universal (raster-based) printing services
    (framework and drivers) under Unix and other platforms.

    As a new late comer, I am not sure it is a good way or a good timing now but I am doing it anyway ...

    The first thing I'd like to discuss is the requirement in printer description for run-time evaluation
    to generate raster data and printer setup commands. I have an impression that it had been brought up
    to UPDF's attention in the past (by Don Wright of Lexmark?) for the "completeness" of any page description file
    or otherwise those commands would need to be "hard-coded" somewhere else in C code for which
    the programming interface needs to be defined (and therefore must be covered as part of UPDF?).

    Attached (xpdo.nov01.html) for your reference please find the extensible printer description object model
    based on XML technologies. It is a very simple virtual machine for XML-based printer description language
    in an attempt to address those command generation issues in addition to custom declaration, modulization and
    binary encoding etc.

    My appology that GPD teminologies are used in the document for a demonstration because GPD is
    the only printer description format I know of that generates raster data for low-cost printers.

    Table of Content:
    -----------------

       Introduction
       Data Types: string, name, int, float, boolean, array, dictionary
       File Modulization for Printer Model Family Hierarchies
       Executable Objects and Execution Context
       The load Executable Object and Paramter Dictionaries
       The switch Executable Object
       The Math Executable Objects: idiv, add, sub, expr
       The Formatter Executable Objects: tostring, numformat, maxrepeat

    Samples in the document:
    ------------------------

    - for raster data commands generation:

      <CmdSendBlockData> <!-- pre-definded parameter: NumOfDataBytes -->
           <maxrepeat> <!-- an executable object that describes how a CmdSendBlockData is
                            generated with a value-range encoding limit -->
                <int>5100</int> <!-- limit -->
                <load name="NumOfDataBytes"> <!-- total -->
                <tostring> <!-- 3rd executable object to be repeatedly evaluated -->
                   <str>{1B}*{03}</str>
                   <expr str="numformat(MaxRepeatInstance,'l')"/>
                </tostring>
           </maxrepeat>
       </CmdSendBlockData>

       <CmdYMoveRelUp> <!-- pre-definded parameter: DestYRel -->
           <maxrepeat> <!-- an executable object that describes how a CmdSendBlockData is
                            generated with a value-range encoding limit -->
                <int>12600</str> <!-- limit -->
                <load name="DestYRel"/> <!-- total -->
                <tostring> <!-- 3th executable object to be repeatedly evaluated -->
                    <str>{1B}(*p-</str>
                    <load name="MaxRepeatInstance"/>
                </tostring>
           </maxrepeat>
       </CmdYMoveRelUp>

    - for multiple-way runtime dependency (e.g., a printable area depends on the paper size and perhaps the orientation
    chosen at runtime):

    <PaperSize>
       <Name str="Paper Size"/>
       <Options>
          <A4>
             <Name str="A4, 210 x 297 mm"/>
             <PrintableOrigin>
                <switch name="Orientation"> <!-- returning an integer object as the
                                               associated with the Orientation key
                                               in the system setup dictionary
                                            -->
                   <case name="PORTRAIT" intary="300 300"/>
                   <case name="LANDSCAPE_CC90" intary="200 180"/>
                   <default intary="180 200"/>
                </switch>
             </PrintableOrigin>
             <!-- ... -->
          </A4>
          <!-- ... -->
       </Options>
       <!-- ... -->
    </PaperSize>

    - for Custom feature/option (e.g. paper size):

    <PaperSize>
       <Options>
          <A4>
             <Name str="A4, 210 x 297 mm"/> <!-- Display name is optional for predefined paper size -->
             <PrintableOrigin intary="..."/> <!-- required for any paper size -->
             <!-- ... -->
          </A4>
          <entry name="MyCustomPaperSize">
             <Name str="My Custom Paper Size: x by y"/> <!-- Display name is required only for custom paper size -->
             <PrintableOrigin intary="..."/> <!-- required for any paper size -->
             <PageDimensions intary="..."/> <!-- required only for unknown custom paper size -->
             <!-- ... -->
          </entry>
          <!-- ... -->
       </Options>
       <!-- ... -->
    </PaperSize>

    Best regards,

    Jim Lo (jim.lo@eng.sun.com)
    Internet Appliance Group
    Sun Microsystems, Inc.
    Menlo Park, California


    XPDO (Extensible Printer Description Object Model) Virtual Machine

    Introduction
    XPDO Data Types: string, name, int, float, boolean, array, dictionary
    XPDO File Modulization for Printer Model Family Hierarchies
    Executable Objects and Execution Context
    The load Executable Object and Paramter Dictionaries
    The switch Executable Object
    The Math Executable Objects: idiv, add, sub, expr
    The Formatter Executable Objects: tostring, numformat, maxrepeat
    Introduction

    This document describes a very simple virtual machine based on an extensible object model for printer description as a XML application. Many requirements in printer description such as run-time evaluation for raster data and printer setup command generation, custom declaration, modulization and binary encoding are addressed.

    1. Everything is described as an object.
    2. Every object is strongly typed.
    3. The type information is available not only at compile time but also at runtime.
    4. The compile-time type checking can perfectly fit into the strutural validation feature of a XML parser.
    5. The run-time type checking can be optionally performed by so-called executable objects.
    6. The number of pre-defined object types is limited. Custom data can be aggregated in either of two pre-defined compound data types: dictionary and array.
    7. An enumeration (the most frequently-used "custom type") can be realized by simply iterating all keys of a dictionary.
    8. A printer description file can be simply extended by a dictionary deep-merge operation.
    9. A binary format of a XML-encoded printer description file can be simply realized by a serialization process from an object map in a memory created by a XML processor.
    10. Tools based on printer description data in an strongly-typed object form can provide many services such as context-sensitive validation, product family/peer views and display string except for localization.
    XPDO Data Types

    XPDO provides a object-based system which is strongly typed.

    There are several primitive types. They are for string, name, integer, float and boolean objects which are encoded as below:

       <int>77</int>             
       <float>-1.2</float>       
       <bool>TRUE</bool>         
       <str>a string</str>          
       <name>aName</name>        
    
    A XPDO numbers can be signed integer objects such as 12, -98, 0, +650 and floating point objects such as -0.01 2.3 -4.56 -7. 0.0

    A XPDO boolean object is for use in logical expression or returned as status information. The names true and false are associated with the two values of this type. The <TRUE/> and <FALSE/> are introduced for a short hand form of a boolean object with true and false value, respectively.

    A XPDO name object is of XML NMTOKEN type.

    A XPDO string object is of XML CDATA type with one exception in favor of hexadecimal encoding which is useful for arbitrary binary data which is often mixed in a printer command string. The ASCII '{' character and the '}' are used to enter and exit the hexadecimal encoding mode respectively. A string is initially in the normal ASCII encoding mode. For example, the selection command for Letter size on Canon BJC-600 is the hexadecimal byte stream 1B 28:'(' 67:'g' 03 00 6E:'n' 01 72:'r' where all printable ASCII characters are shown after a colon for the ease of reference. It can be specificed as below:

       {1B}(g{0300}n{01}r    
    
    Note that the only way to encode '{' and '}' themselves is in the hexadecimal mode.

    To be more precise, a hexadecimal encoded data enclosed within '<' and '>' consists of a sequence of hex characters (the digits 0 through 9 and the letters A through F or a through f) . Each pair of hex digits defines a byte. White-space characters are ignored. If there is an odd number of digits, the final digit that is missing is assumed to be zero. For example, { 1B 28a } will be treated as {1b28a0}.

    There is also a short-hand form which takes advantage of XML attribute syntax when a primitive object is associated with other object in the context of XPDO dictionary key/value pairing or XPDO run-time operator operand. For example,

       <XMoveUnit int="60"/>   
    
    As shown in the example, the XMoveUnit is an empty-element tag with a single attribute to explicitly declare its type and value.

    There are several XPDO compound types. They include array, dictionary and all executable objects for flow control, math and formatting operations etc.

    An array object is enclosed in the <ary> start-tag and </ary> end-tag. The nested elements of an array can be any XPDO primitive and compound types. When all nested elements are of the same primitive type except the string type, a short-hand form is provided. Consider the the following example:

       <MasterUnit>
          <ary>
             <int>720</int>
             <int>432</int>
          </ary>
       </MasterUnit>
    
    It can be also specified in a more concise manner. As shown below, the nested element values are delimited by XML white spaces and they must be all integer type which can be further reinforced via the new <intary> start-tag and </intary> end-tag.

       <MasterUnit>
          <intary>720 432</intary>
       </MasterUnit>
    
    When the integer array short form is combined with the attributed short-form mentioned earlier, it can be specified as simple as shown below:

       <MasterUnit intary="720 432"/>
    
    Similarly to the name array, float array and boolean array except the new <nameary>, <floatary> and <boolary> tags are used respectively.

    A dictionary object is enclosed in the <dict> start-tag and </dict> end-tag. The nested elements of a dictionary are nothing but key/value pairs (also referred to as entries). Those entries are specified via the <entry> start-tag and </entry> end-tag as below:

       <Declarations>
          <dict> 
             <entry name="MasterUnit"><intary>720 432</intary></entry>
             <!-- ... -->
          </dict> 
       </Declarations>
    
    As shown, there is an attribute to specify an entry key which can be of any primitive type and array type. An entry value can be of any primitive and compound type including dictionary itself.

    Note that when a dictionary entry key is a pre-definded XPDO name such as MasterUnit in the previous example, the general <entry> tag which is provided for printer vendor defined custom printer properties can be replaced by the predefinded tag for that pre-definded name. Note also that when an entry value of an pre-definded entry key name is allowed to be an dictionary only, the <dict> tag can be removed. It is demonstrated below as a more concise version of the previous example.

       <Declarations>
          <MasterUnit intary="720 432"/>
          <!-- ... -->
       </Declarations>
    
    The conciseness due to the short-hand form is much preferred since such a construct is so typical to appear almost everywhere in a XPDOdocument.

    Finally, An example that deals with a variety of object types is shown below:

    <CmdSelect> <!-- pre-definded CmdSelect is an dictionary with three entries: two pre-definded Order, Cmd entries and a custom MyNotPredefined entry --> <dict> <Order> <!-- pre-definded Order is an array with two elements: a pre-definded name JOB_SETUP and an integer 10 --> <ary> <name>JOB_SETU;</name> <int>10</int> </ary> </Order> <Cmd str="printer control commands"/> <entry name="MyNotPredefined"><int>9</int></entry> </dict> </CmdSelect>
    which can be abbreviated as below:

    <CmdSelect> <Order name="JOB_SETUP" int="10"> <Cmd str="printer control commands"/> <entry name="MyNotPredefined"> <int>9</int> </entry> </CmdSelect>
    In addition to the three general short-hand forms which are attributed short-hand form, array short-hand form and dictionary short-hand form, there are also short-hand forms that are specific to particular pre-definded tags such as <Order> as shown in the previous example.

    A name object as the typical data type of a dicitonary key is much faster to match (as opposed to string type) in that it is the internal representation (usually the address where the name is stored) rather than the character string for the name that gets involved for the key matching process.

    Note that the generic <entry> tag is for a custom entry whose key name is defined by printer vendors. For another example,

    <PaperSize> <Options> <A4> <Name str="A4, 210 x 297 mm"/> <!-- optional for predefined paper size --> <PrintableOrigin intary="..."/> <!-- required for any paper size --> <!-- ... --> </A4> <entry name="MyCustomPaperSize"> <Name str="My Custom Paper Size: x by y"/> <!-- required only for custom paper size --> <PrintableOrigin intary="..."/> <!-- required for any paper size --> <PageDimensions intary="..."/> <!-- required only for custom paper size --> <!-- ... --> </entry> <!-- ... --> </Options> <!-- ... --> </PaperSize>
    A XPDO document is encoded as a single dictionary object which contains some key/value pairs whose value may be of dictionary type. A XPDO object hierarchy formed in that manner can then serve as a base for the XPDO modulization (file merging for printer description inheritance) mechanism.

    XPDO File Modulization for Printer Model Family Hierarchies

    Printer models in a same product family share a lot in common. A bunch of related XPDO files can be grouped together in a hierarchy via the xpdo extend processing instruction in order to reflect the model structure of a printer product family in a nature way.

    Consider the following two XPDO files to be merged,

    <!-- base.xpdo file -->
    <?xml version="1.0">
    <XPDO>
       <Dictionary>
          <Base str="BASE"/>
          <Untouched str="SAME"/>
       </Dictionary>
       <Base>
          <!-- Base... -->
       </Base>
       <Untouched str="SAME"/>
    </XPDO>
    
    <!-- derived.xpdo file -->
    <?xml version="1.0">
    <?xpdo extend="base.xpdo"/>
    <XPDO>
       <Dictionary>
          <Derived str="DERIVED"/>
          <Base str="DERIVED"/>
       </Dictionary> 
       <Derived str="DERIVED"/>
       <Base str="DERIVED"/>
    </XPDO>
    
    Loading the derived.xpdo file would collect the following single XPDO dictionary object in memory as a result of merging its extended base.xpdo file:

    <?xml version="1.0">
    <XPDO>
       <Dictionary>
          <Base str="DERIVED"/> <!-- overridden from the old value: (Base) -->
          <Untouched str="SAME"/>
          <Derived str="DERIVED"/> <!-- new entry -->
       </Dictionary> 
       <Base str="DERIVED"/> <!-- overridden from the old value: Base dictionary -->
       <Untouched str="SAME"/>
       <Derived str="DERIVED"/> <!-- new entry -->
    </XPDO>
    
    The XPDO files merging based on the xpdo extend processing instruction can therefore work in such a simple way that is described in the following rules based on dictionary deep (recursively) merge:

    1. Collect base dictionary and derived dictionary from the base XPDO file and derived XPDO file respectively.

    2. Enumerate all entries in the derived dictionary and apply each of them with the following rules.

    3. If an entry doesn't exist in its base xpdo file, it is simply added to the base dictionary.

    4. If an entry does exist in its base xpdo file and the base value and the derived value are neither dictionary, the base value is overridden by the derived value.

    5. Otherwise, apply rule 2 to rule 5 recursivley with the base dictionary value and derived dictionary value.

    Note that the iteration order of a dictionary defaults to what the dictionary entries are checked in. It is usually the order specified lexically during loading time. However, when dictionaries are merged the iteration order for new entries may not be what is appropriate for GUI presentation). An optional <EntryOrder> entry can be added to explicitly specify the iteration order. The value is an array consist of key names for all dictionary entries.

    A XPDO hierarchy can be as deep as needed.

    The following hierarchy demonstrates a possible real-life printer product family would look like in their entirety:

    HP_Raster
        HP_DeskJet_600_Monochrome
        HP_DeskJet_540_Monochrome
        HP_PaintJet
        HP_DeskJet_Plus
        HP_DeskJet_400_Monochrome
        HP_DeskJet_6xx 
            HP_DeskJet_67x 
                HP_DeskJet_660Cse
                HP_DeskJet_660C
                HP_DeskJet_670C
                HP_DeskJet_672C
            
            HP_DeskJet_69x 
                HP_DeskJet_680C
                HP_DeskJet_682C
                HP_DeskJet_690C
                HP_DeskJet_692C
                HP_DeskJet_693C
                HP_DeskJet_694C
                HP_DeskJet_695C
                HP_DeskJet_697C
        
        HP_DeskJet_600
        HP_QuietJet
        HP_DeskJet_400
        HP_DeskJet_85x 
            HP_DeskJet_850C
            HP_DeskJet_855Cse
            HP_DeskJet_855Cxi
        
        HP_DeskJet_420
        HP_DeskJet_87x 
            HP_DeskJet_870C
            HP_DeskJet_870Cse
            HP_DeskJet_870Cxi
        
        HP_DeskJet_89x 
            HP_DeskJet_895Cse
            HP_DeskJet_895Cxi
        
        HP_DeskJet_560C
        HP_DeskJet_82x 
            HP_DeskJet_820Cse
            HP_DeskJet_820Cxi
        
        HP_DeskJet_540
        HP_OfficeJet
        HP_DeskJet_510
        HP_DeskJet_7xx 
            HP_DeskJet_710C
            HP_DeskJet_712C
            HP_DeskJet_720C
            HP_DeskJet_722C
        
        HP_OfficeJet_LX
        HP_DeskJet_500
        HP_DeskJet_520
        HP_ThinkJet
        HP_DeskJet_340_Monochrome
        HP_DeskJet_320
        HP_DeskJet_340
        HP_OfficeJet_3xx 
            HP_OfficeJet_300
            HP_OfficeJet_330
            HP_OfficeJet_350
        
        HP_QuietJet_Plus
        HP_DeskJet_550C
        HP_DeskJet_500C
        HP_DeskJet_Portable
        HP_DeskJet_310
        HP_DeskJet
    
    Executable Objects and Execution Context

    In the process of printer description, there are cases where a printing property is dependent on a user selection in runtime or actual printing data based on a raster scheme needs to be generated from actual parameters passed by printing system which does the actual graphics rendering to produce raster data.

    An executable object is a XPDO object that is evaluated at run time. An executable object can consist of one or more nested elements of any object type as is the case with an array. The result of the evaluation is a single XPDO object of any type. An input value is associated with a key name which is referred in the body Of an executable object.

    There can be as many dictionary objects as needed for such an input parameter loading. A system level stack is introduced as a collection of those dictionaries and the key mapping order is defined to be from the top all way down to the bottom of the stack.

    The first dictionary object automatically pushed is the so-called setup dictionary which contains typically selected option (entry value) for all features (entry key).

       |                            | Top
       |                            |
       |          .                 |
       |          .                 |
       |          .                 |
       |                            |
       | +------------------------+ |
       | | parameter dictionary   | | 
       | | for a nested executable| | (Only during the evaluation of the nested executable object for the parameters)
       | | objects, if any        | | 
       | +------------------------+ |
       |                            |
       | +----------------------+   |
       | | parameter dictionary |   |
       | | containing one or    |   | (Only during the evaluation of an executable object for the parameters)
       | | more entries         |   |
       | +----------------------+   |
       |                            |
       | +----------------------+   |
       | | setup dictionary     |   | (Always available)
       | +----------------------+   |
       +----------------------------+ Bottom 
          System dictionary stack
          (Execution Context)
    
    The load Executable Object and Parameter Dictionaries

    The <load> executable object is introduced to explicitly load an object from the system dictionary stack.

    For example, the following load object will load the currently selected paper size from the system setup dictionary:

       <load name="PaperSize">    <!-- returning a A4 name object, for example -->
    
    Take another example shown below regarding a parametric executable object evaluation:
    <CmdYMoveAbsolute>
       <!-- ... -->
          <load name="DestY"/>
       <!-- ... -->
    </CmdYMoveAbsolute>
    
    Note that the pre-definded parameter DestY is specific to the pre-definded CmdYMoveAbsolute entry. Mechanically, a parameter dictionary containing the entry with the name DestY as its key and the current DestY as its integer value will be pushed to the system dictionary stack before the evaluation takes place. It is shown as below:

       |                          | Top
       | +----------------------+ |
       | | parameter dictionary | |
       | | containing the       | | (Only during the evaluation of CmdYMoveAbsolute)
       | | DestY entry          | |
       | +----------------------+ |
       |                          |
       | +----------------------+ |
       | | setup dictionary     | | (Always available)
       | +----------------------+ |
       +--------------------------+ Bottom 
          System Dictionary Stack
    
    The switch Executable Object

    The switch executable object provide a flow control at runtime. The following example demonstrates how the origin of a printable area for a particular paper size will depend on the paper orientation a user will select.

    <PaperSize>
       <Name str="Paper Size"/>
       <Options>
          <A4>
             <Name str="A4, 210 x 297 mm"/>
             <PrintableOrigin>
                <switch name="Orientation"> <!-- returning an integer object as the
                                               associated with the Orientation key
                                               in the system setup dictionary 
                                            -->
                   <case name="PORTRAIT" intary="300 300"/>
                   <case name="LANDSCAPE_CC90" intary="200 180"/>
                   <default intary="180 200"/>
                </switch>
             </PrintableOrigin>
             <!-- ... -->
          </A4>
          <!-- ... -->
       </Options>
       <!-- ... -->
    </PaperSize>
    
    The printable origin of A4 size in case of portrait printing requested by a user is (300,300), (200,180) in case of LANDSCAPE (counter clockwise by 90 degree) or (180, 200) in other cases.

    The <switch> construct shown in the previous example actually is an abbreviation of a general form of how a switch object Can be instantiated in memory or encoded in a binary stream. The most general form of the previous example is shown as below:

    <switch>
       <load name="Resolution">
       <dict>
          <entry name="PORTRAIT" intary="300 300"/>
          <entry name="LANDSCAPE_CC90" intary="200 180"/>
          <entry name="-default-" intary="180 200"/>
       </dict>
    </switch>
    
    The <case> tag is only a more readable alias of <entry> tag and the <default> tag is an abbreviation of a dictionary entry whose key is a reserved name called "-default-".

    Just consider a switch object as yet another compound object. The first object It contains can be of any type that is qualified as a dictionary key as a runtime condition. As a control flow language construct, the object is typically evaluated at runtime as a retuned value of a <load> tag. The second object is a dictionary object whose entries serve a case pool. An entry key is used to match the first condition object and when matched its associated value is used for a returned value of a switch construct. The default entry provided a default case if present or otherwise a null object is returned to indicate an exceptional situation may arise. However, an warning message can also be issued by a validating tool at loading time for pre-definded names in the Switch construct.

    The Math Executable Objects: idiv, add, sub, expr

    There are cases where a parameter needs to be subject to mathematics operations such as addition, subtraction and division.

    The idiv executable object must contain two integer objects. The first integer will be divided by the second integer. Take the following as an example:

       <idiv>
          <load name="DestY"/>
          <int>2</int>
       </idiv>
    
    The returned value will be 3 given that the current value of DestY is 7.

    For many frequently used expression, the expr executable object is introduced to provide an optimized short form by the expr executable object. The previous example can then also be specified as below:

       <expr str="idiv(DestX,2)"/>
    
    There are many other pre-definded expression such as "idiv(DestY,2)", "numformat(NumOfDataBytes+1,'l')".

    Similarly to other math executable objects such as add and sub except that the two nested elements they contains can be either integer or floating-point number type.

    The Formatter Executable Objects

    The value of the CmdYMoveAbsolute entry of the following example will be (1B)*p7Y given that the current value of DestY is 7. This is because a string object will be resulted from a concatenation of all nested elements enclosed in the tostring executable object.

    <CmdYMoveAbsolute>
       <tostring>
          <str>(1B)*p</str>
          <load name="DestY"/>
          <str>Y</str>
       </tostring>
    </CmdYMoveAbsolute>
    
    The tostring executable object is evaluated in such a way that:

    1. In case that a nested element is an executable object, it will be evaluated first as discussed earlier and the executable object will be replaced by any object returned.
    2. All elements will be converted to their textual representation as a string object.
    3. All string object will then be concatenated into a single string object.
    The <numformat> executable object is introduced in case where a special integer formatting is needed. For example, the '+' sign is not printed for signed integer if it is greater than 0 by the <tostring>. The numformat executable object consists of one integer object followed by a string object indicating its pre-definded formatting code.

    
       <numformat int="12" str='d'/>        <!-- returning "12" which consists of two ASCII characters '1' and '2'
                                                     as what the tostring formatting does
                                                -->
    
       <numformat><int>12</int><str>D</str></numformat>   <!-- returning "+12" which is the same as above except that
                                                                    the + sign is included if the integer is greater than 0.
                                                                -->
    
       <expr str="numformat(DestX,'l')">   <!-- returning "(0201)" which is a two-byte string with low-order byte (LSB) first     
                                                    given DestX = 0x0102 (16-bit integer)
                                               -->
       <expr str="numformat(DestX,'m')">   <!-- returning "(0102)" which is a two-byte string with high-order byte (MSB) first    
                                                    given DestX = 0x0102 (16-bit integer)
                                               -->
    
    In cases where a printer command is forced to be emitted more than once due to its allowable maximum value range in the command encoding, the <maxrepeat> executable object can be very useful.

    The first and second object contained are both integer. The third object is an executable object which is evaluated repeatedly using a maximum allowed value as the first integer object) until the accumulated value is equal to a total value as the second integer object.

    For the input of each executable object evaluation, a share value will be associated automatically in the <MaxRepeatInstance as is the case with any other pre-definded parameters handled in the system dictionary stack. For each returned object as a result of the third executable object evaluation, it will be automatically converted to a textual representation and concatenated with the accumulation of all previous repeated evaluation outputs. In other words, the final returned object of the <maxrepeat> executable object as a whole is the same as the returned object of an <tostring> evaluation with all those repeatedly returned objects as its nested elements.

    Considering the following simple example:

       <maxrepeat>
          <int>2</str>   <!-- 1st object: limit -->
          <int>5</str>   <!-- 2nd object: total -->
          <load name="MaxRepeatInstance"/>      <!-- 3rd executable object to be repeatedly evaluated
                                                 to collect all share values stored in the 
                                                 pre-definded MaxRepeatInstance -->
       </maxrepeat>
    
    which will return a string object which is the same as the object encoded below:

       <str>221</str>  <!-- i.e., there are three shares, non of which exceeds the limit (2). 
                            The sum of  all shares (2+2+1) is the total (5) -->
    
    For two more real-life examples:

       <CmdSendBlockData>   <!-- pre-definded parameter: NumOfDataBytes --> 
           <maxrepeat> <!-- an executable object that describes how a CmdSendBlockData is
                            generated with a value-range encoding limit --> 
                <int>5100</int>   <!-- limit --> 
                <load name="NumOfDataBytes">  <!-- total --> 
                <tostring>   <!-- 3rd executable object to be repeatedly evaluated -->
                   <str>{1B}*{03}</str>
                   <expr str="numformat(MaxRepeatInstance,'l')"/>
                </tostring>
           </maxrepeat>
       </CmdSendBlockData>
    
       <CmdYMoveRelUp> <!-- pre-definded parameter: DestYRel --> 
           <maxrepeat> <!-- an executable object that describes how a CmdSendBlockData is 
                            generated with a value-range encoding limit --> 
                <int>12600</str>     <!-- limit --> 
                <load name="DestYRel"/>  <!-- total --> 
                <tostring>   <!-- 3rd executable object to be repeatedly evaluated -->
                    <str>{1B}(*p-</str>
                    <load name="MaxRepeatInstance"/>
                </tostring>
           </maxrepeat>
       </CmdYMoveRelUp>
    
    The following shows what the system dictionary stack looks like for the evaluation of <CmdSendBlockData> in the example (similar to the <CmdYMoveRelUp>).

       |                             | Top
       | +-------------------------+ |
       | | parameter dictionary    | |
       | | containing the          | | (Pushed and poped for each evaluation of 3rd executable object of maxrepeat)
       | | MaxRepeatInstance entry | |
       | +-------------------------+ |
       |                             |
       | +-------------------------+ |
       | | parameter dictionary    | |
       | | containing the          | | (Only during the evaluation of CmdSendBLockData)
       | | NumOfDataBytes entry    | |
       | +-------------------------+ |
       |                             |
       | +-------------------------+ |
       | | setup dictionary        | | (Always available)
       | +-------------------------+ |
       +-----------------------------+ Bottom 
           System Dictionary Stack
    



    This archive was generated by hypermail 2b29 : Fri Dec 01 2000 - 15:22:29 EST