RFC 138

Status report on proposed Data Reconfiguration Service

๐Ÿ“… published April 1971, from ietf

STATUS REPORT ON PROPOSED DATA RECONFIGURATION SERVICE ๐Ÿฆ‹

okay bestie, so this is RFC 138 ๐ŸŽ€ It came out of the Network Working Group and is dated 28 April 1971. The header has the NIC 6715 number, and it's a status report on a proposed Network experiment. There's no category, obsoletes, or updates line in the header, so I'm not inventing one ๐Ÿ™ˆ

The authors are Bob Anderson (Rand), Vint Cerf (UCLA), Eric Harslem (Rand), John Heafner (Rand), Jim Madden (U. of Illinois), Bob Metcalfe (MIT), Arie Shoshani (SDC), Jim White (UCSB), and David Wood (Mitre). That's a whole squad ๐Ÿ’…โœจ

Contents

                                 CONTENTS
     I.  INTRODUCTION .................................    2

         Purpose of this RFC ..........................    2
         Motivation ...................................    2

    II.  OVERVIEW OF DATA RECONFIGURATION SERVICE .....    3

         Elements of Data Reconfiguration Service .....    3
         Conceptual Network Connections ...............    3
         Connection Protocols and Message Formats .....    4
         Example Connection Configurations ............    6

   III.  THE FORM MACHINE .............................    7

         Input/Output Stream and Forms ................    7
         Form Machine BNF Syntax ......................    7
         Alternate Specification of Form Machine Syntax    8
         Forms ........................................    9
         Rules ........................................   10
         Terms ........................................   10

           Term Format 1 ..............................   11
           Term Format 2 ..............................   11
           Term Format 3 ..............................   13
           Term Format 4 ..............................   13
           Application of a Term ......................   14
           Restrictions and Interpretations of
             Term Functions ...........................   14
         Term and Rule Sequencing .....................   16

    IV.  EXAMPLES .....................................   16

         Remarks ......................................   16
         Field Insertion ..............................   17
         Deletion .....................................   17
         Variable Length Records ......................   17
         String Length Computation ....................   18
         Transposition ................................   18
         Character Packing and Unpacking ..............   18

     V.  PROPOSED USES OF DATA RECONFIGURATION SERVICE    19

    VI.  IMPLEMENTATION PLANS .........................   20

   Appendix A .........................................   21

         Note 1 to the DRS Working Group ..............   21
         Note 2 to the DRS Working Group ..............   22

I. INTRODUCTION ๐ŸŒธ

PURPOSE OF THIS RFC ๐Ÿ’–

okay so the whole point of this RFC is to describe, in part, a proposed Network experiment ๐Ÿงš and to ask everyone for comments on literally any aspect of it. The experiment is a software mechanism that reformats Network data streams, and it can be adapted to loads of Network application programs โœจ The big hope is that the results lead to a further standard service that embodies the principles in this RFC ๐ŸŽ€ We'd love comments on whether this work is appropriate as a Network experiment, and also on any particular Network data reformatting needs that these techniques couldn't easily handle ๐Ÿ™ˆ

MOTIVATION ๐Ÿซถ

application programs need specific data I/O formats, and those formats are different from program to program ๐Ÿ˜ค our position is that the Network should adapt to each program's requirements instead of making every program change to match a standard. this doesn't rule out standards that describe the formats of regular message contents. it's just a way of reading a standard as a desirable mode of operation, but not a necessary one ๐Ÿ’…

there's also a format mismatch problem when users want to hook lots of different kinds of consoles up to one service program ๐Ÿ“Ÿ it's way better for the Network to adapt to each console configuration than to need a unique software package for every console transformation ๐Ÿ’€

one approach is for sites with substantial computing power to offer a data reconfiguration service, and a proposed example of one is described here ๐ŸŒˆ

the envisioned modus operandi is that an applications programmer defines forms that describe data reconfigurations. the service stores the forms by name. later on, a user (maybe not a programmer!) uses the service to do a particular transformation of a Network data stream, simply by calling the form by name ๐Ÿ‘‘

we tried to make a notation tailored to some specifically needed instances of data reformatting. we kept the notation and its underlying implementation inside a utility range. on the lower end, it's expressive enough to make the experimental service useful. on the upper end, it stays short of a general-purpose programming language ๐Ÿ“


II. OVERVIEW OF THE DATA RECONFIGURATION SERVICE โœจ

ELEMENTS OF THE DATA RECONFIGURATION SERVICE ๐Ÿฆ‹

an implementation of the Data Reconfiguration Service (DRS) includes modules for connection protocols, a handler for some requests that can be made of the service, a compiler and/or interpreter (called the Form Machine) to act on those requests, and a file storage module for saving and retrieving definitions of data reconfigurations (forms) ๐Ÿ—‚๏ธ

this section highlights connection protocols and requests. the next section covers the Form Machine language in some detail. file storage isn't described in this document, because it's transparent to the use of the service and its implementation is different at each DRS host ๐Ÿ™ˆ

CONCEPTUAL NETWORK CONNECTIONS ๐ŸŒ

okay so there are three conceptual Network connections to the DRS, see Fig. 1 ๐Ÿ’–

  1. The control connection (CC) is between an originating user and the DRS. a form specifying data reconfiguration is defined over this connection, and it's applied to data passing over the two connections below.
  2. The user connection (UC) is between a user process and the DRS.
  3. The server connection (SC) is between the DRS and the serving process.

since the goal is to adapt the Network to user and server processes, a minimum of requirements are imposed on the UC and SC ๐Ÿซถ

      +-------------+   CC   +-----------+   SC   +-----------+
      | ORIGINATING +--------+    DRS    +--------+ SERVER    |
      |    USER     |   ^    |           |    ^   | PROCESS   |
      +-------------+   |    +------+----+    |   +-----------+
                        |          /          |
                     Telnet       / <------ Simplex or Duplex
                    Protocol   UC/            Connections
                   Connection   /
                               /
                        +-----+-----+
                        | USER      |
                        | PROCESS   |
                        +-----------+

Figure 1. DRS Network Connections

CONNECTION PROTOCOLS AND MESSAGE FORMATS ๐Ÿ”ฅ

over a control connection, the dialog is directly between an originating user and the DRS. here, the user is defining forms or assigning forms to connections for reformatting ๐Ÿ’…

the user connects to the DRS via the initial connection protocol (ICP) specified in NWG/RFC #80, version 1. rather than going through a logger, the user calls on a particular socket that the DRS always listens on. DRS switches the user to another socket pair โœจ

messages sent over a control connection are of the types and formats to be specified for TELNET. so a user at a terminal should be able to connect to a DRS via their local TELNET, for example, as shown in Fig. 2 ๐Ÿงš

                                          +--------------+
                         +--------+  CC   |              |
                 +-------+ TELNET +-------+     DRS      |
                 |       +--------+       |              |
                 |                        +--------------+
      +----------+---------+
      |      USER          |
      |(TERMINAL OR PROGRAM|
      +--------------------+

Figure 2. A TELNET Connection to DRS

when a user connects to DRS, he supplies a six-character user ID (UID) as a qualifier, which guarantees the uniqueness of his form names. he'll have (at least) the following commands ๐Ÿ‘‘

  1. DEFFORM (name)
  2. ENDFORM (name)

these two commands define a form, whose text is chronologically entered between them. the (name) is six characters. the form is stored in the DRS local file system ๐Ÿ—‚๏ธ

  1. PURGE (name)

the named form, as qualified by the current UID, is purged from the DRS file system ๐Ÿ—‘๏ธ

  1. LISTNAMES (UID)

the unqualified names of all forms assigned to UID are returned ๐Ÿ“‹

  1. LISTFORM (name)

the source text of a named form is returned ๐Ÿ“œ

  1. DUPLEXCONNECT (user site, user send, user receive, user method, server site, server send, server receive, server method, user-to-server form, server-to-user form)
  2. SIMPLEXCONNECT (send site, send socket, send method, receive site, receive socket, receive method, form)

either one, both, or neither of the two parties specified in 6 or 7 may be at the same host as the party issuing the request ๐ŸŒธ sites and sockets specify user and server for the connection. method indicates the way in which the connection is established. three options are provided:

  1. site/socket already connected to DRS as a dummy control connection. (a dummy control connection should not also be the real control connection.)
  2. connect via standard ICP. (Only for command no. 6.)
  3. connect directly via STR, RTS. ๐Ÿ’œ

EXAMPLE CONNECTION CONFIGURATIONS ๐ŸŽ€

okay so there are basically two modes of DRS operation, and they're both giving main character energy ๐Ÿ’…โœจ

  1. the user wants a DRS UC/SC connection (or connections) between two programs
  2. the user wants to set up those same connections where they (their terminal) sit at one end of the UC or the SC ๐Ÿฆ‹

The second one is perfect when you want to chat with the serving process straight from your terminal, like a logger ๐Ÿชต๐Ÿ’œ

For the first case (Fig. 1, where the originating user is either a terminal or a program), the user just issues the right CONNECT command ๐Ÿ”ฅ The UC/SC can be simplex or duplex, so you pick what fits.

The second case has two possible setups, shown in Figs. 3 and 4 ๐Ÿ‘‘

               +--------+  CC  +--------+      +------+
               |        +------+        |  SC  |      |
     +------+ /| TELNET |  UC  |  DRS   +------+  SP  |
     |      |/ |        +------+        |      |      |
     | USER | /+--------+      +--------+      +------+
     |      |/
     +------+

            Figure 3.  Use of Dummy Control Connection

               +--------+
     +------+ /|  USER  |  CC  +--------+      +------+
     |      |/ |  SIDE  +------+        |  SC  |      |
     | USER |  +--------+  UC  |  DRS   +------+  SP  |
     |      |\ | SERVING+------+        |      |      |
     +------+ \|  SIDE  |      +--------+      +------+
               +--------+

            Figure 4.  Use of Server TELNET

In Fig. 3 the user tells their TELNET to make two duplex connections to DRS ๐Ÿงš One is for control info (the CC) and the other is a dummy. When they issue the CONNECT, they reference the dummy duplex connection (UC) using the "already connected" option. bestie, that's so clever ๐Ÿ˜ญ

In Fig. 4 the user has their TELNET (user side) call the DRS. When they issue the CONNECT, the DRS calls the TELNET (server side), which accepts the call on behalf of the console ๐Ÿ’… Here's the tea: this distinction is only known to the user. To the DRS, the Fig. 4 setup looks exactly like Fig. 1 ๐Ÿซถ Two things to note:

  1. TELNET protocol is needed only to define forms and direct connections. It is not required for the using and serving processes.
  2. The using and serving processes need only a minimum of modification for Network use, i.e., an NCP interface.

III. THE FORM MACHINE โœจ

INPUT/OUTPUT STREAMS AND FORMS ๐ŸŒธ

okay so this section explains the syntax and semantics of the forms that describe the data reconfigurations ๐Ÿ’– The Form Machine takes in an input stream, reformats it according to a form describing the reconfiguration, and emits the reformatted data as an output stream. iconic behavior tbh ๐Ÿ“

When you're reading this, it helps to picture a form getting applied to the data stream, like in Fig. 5 ๐Ÿฆ‹ There are two pointers to keep track of. An input stream pointer marks where the data being analyzed right now sits in the input stream, and an output stream pointer marks where data is being emitted in the output stream ๐Ÿ’œ

       /\/\                                                  /\/\
  ^    |  |                     FORM                         |  |   ^
  |    |  |                -----------------                 |  |   |
  |    |  |            +-  -----------------  -+             |  |   |
  |    |  |            |   CURRENT PART OF     |             |  |   |
INPUT  |  |<= CURRENT <    -----------------    > CURRENT => |  | OUTPUT
STREAM |  |   POINTER  |   FORM BEING APPLIED  |  POINTER    |  | STREAM
       |  |            +-  -----------------  -+             |  |
       |  |                -----------------                 |  |
       |  |                -----------------                 |  |
       |  |                -----------------                 |  |
       \/\/                                                  \/\/
              Figure 5.  Application of Form to Data Streams

FORM MACHINE BNF SYNTAX ๐Ÿง

Here's the grammar, bestie. Read it carefully because every piece matters ๐Ÿ”ฅ

form           ::=  rule | rule form

rule           ;;=  label  inputstream  outputstream ;

label          ::=  INTEGER | <null>

inputstream    ::=  terms | <null>

terms          ::=  term | terms , term

outputstream   ::=  : terms | <null>

term           ::=  identifier | identifier  descriptor |
                    descriptor | comparator

identifier     ::=  an alpha character followed by 0 to 3
                    alphamerics

descriptor     ::=  (replicationexpression , datatype ,
                    valueexpression , lengthexpression  control)

comparator     ::=  (value  connective  value  control)  |
                    (identifier .<=>. control)

replicationexpression  ::=  arithmeticexpression | <null>

datatype       ::=  B | O | X | E | A

valueexpression  ::=  value | <null>

lengthexpression  ::=  # | arithmeticexpression | <null>

connective     ::=  .LE. | .LT. | .GE. | .GT. | .EQ. | .NE.

value          ::=  literal | arithmeticexpression

arithmeticexpression  ::=  primary | primary operator
                           arithmeticexpression

primary        ::=  identifier | L(identifier) | V(identifier) |
                    INTEGER

operator       ::=  + | - | * | /

literal        ::=  literaltype "string"
literaltype    ::=  B | O | X | E | A

string         ::=  from 0 to 256 characters

control        ::=  :  options | <null>

options        ::=  S(where) | F(where) | U(where) |
                    S(where) , F(where) |
                    F(where) , S(where)

where          ::=  arithmeticexpression | R(arithmeticexpression)

ALTERNATE SPECIFICATION OF FORM MACHINE SYNTAX ๐Ÿฆ„

same grammar, just written in a different notation, so you can pick whichever one clicks for you โœจ

                                   infinity
form                    ::=  {rule}
                                   1
                                      1         1          1
rule                    ::=  {INTEGER}   {terms}   {:terms} ;
                                      0         0          0
                                         infinity
terms                   ::=  term {,term}
                                         0
                                                      1
term                    ::=  identifier | {identifier}   descriptor
                                                      0
                             | comparator
                                                    1
descriptor              ::=  ({arithmeticexpression}  , datatype ,
                                                    0
                                    1                     1           1
                             {value} ,  {lengthexpression}  {:options}
                                    0                     0           0
                                                                 1
comparator              ::=  (value  connective  value {:options} ) |
                                                                 0
                                                              1
                             (identifier .<=. value {:options} )
                                                              0
connective              ::=  .LE. | .LT. | .GE. | .GT. | .EQ. | .NE.

lengthexpression        ::=  # | arithmeticexpression

datatype                ::=  B | O | X | E | A

value                   ::=  literal | arithmeticexpression

                                                         infinity
arithmeticexpression    ::=  primary  {operator  primary}
                                                         0
operator                ::= + | - | * | /

primary                 ::=  identifier | L(identifier) |
                             V(identifier) | INTEGER
                                                      256
literal                 ::=  literaltype  "{CHARACTER}   "
                                                      0
literaltype             ::=  B | O | X | A | E
                                                 1
options                 ::=  S(where) {,F(where)}  |
                                                 0
                                                 1
                             F(where) {,S(where)}  | U(where)
                                                 0

where                   ::=  arithmeticexpression |
                             R(arithmeticexpression)
                                                     3
identifier              ::=  ALPHABETIC  {ALPHAMERIC}
                                                     0

FORMS ๐Ÿ’…

a form is an ordered set of rules ๐Ÿ’–

form ::=  rule | rule form

the current rule gets applied at the current spot in the input stream. if the input-stream part of a rule fails to correctly describe the current input, then another rule becomes current and gets applied at that same spot. which rule comes next is either spelled out explicitly by the current term in the current rule, or it's just the next sequential rule by default. the flow of control is explained more fully under TERM AND RULE SEQUENCING ๐Ÿง 

if the input-stream part of a rule succeeds in correctly describing the current input, then some data may be emitted at the current spot in the output stream, according to the rule. both pointers then move forward past the described and emitted data, and the next rule gets applied to the new current spot in the input stream ๐Ÿ”ฅ

the application of the form ends when an explicit return, R(arithmeticexpression), shows up in a rule. the user and server connections get closed, and the return code (arithmeticexpression) is sent to the originating user ๐Ÿ‘‘

RULES ๐ŸŒˆ

a rule is a replacement, comparison, and/or assignment operation, shaped like this ๐ŸŽ€

rule ::= label  inputstream  outputstream ;

a label is the name of a rule. it exists so the rule can be referenced elsewhere in the form for explicit transfer of control. labels look like this ๐Ÿ’œ

label ::=  INTEGER | <null>

the optional integer labels are in the range 0 >= INTEGER >= 9999. the rules don't need to be labeled in ascending numerical order, so you do you ๐Ÿฆ‹

TERMS ๐Ÿงš

the inputstream (describing the input stream to be matched) and the outputstream (describing data to be emitted in the output stream) each consist of zero or more terms, and they look like this โœจ

inputstream   ::=  terms | <null>
outputstream  ::=  :terms | <null>
terms         ::=  term | terms , term

terms come in one of four formats, as shown below ๐Ÿ’–

term ::=  identifier | identifier  descriptor |
          descriptor | comparator

Term Format 1 ๐ŸŒธ

the first term format looks like this ๐Ÿ“

identifier

the identifier is a symbolic reference to a previously identified term (term format 2) in the form. it takes on the same attributes (value, length, type) as the term with that name. term format 1 is normally used to emit data in the output stream ๐Ÿซถ

identifiers are formed by an alpha character followed by 0 to 3 alphameric characters ๐Ÿ’…

Term Format 2 ๐Ÿ’–

Okay bestie, term format 2 is the one with an identifier sitting right in front of the descriptor ๐ŸŽ€

         identifier descriptor

It's mostly used as an input stream term, but it can totally be used as an output stream term too ๐Ÿฆ‹

Here's how a descriptor is defined โœจ

         descriptor ::= (replicationexpression, datatype,
                        valueexpression, lengthexpression
                        control)

The identifier is the term's symbolic name, like in any programming language ๐Ÿ’… It picks up the type, length, and value attributes of the term, and it can be referenced somewhere else in the form ๐ŸŒธ

The replication expression is defined below ๐Ÿ”ฅ

         replicationexpression ::= arithmeticexpression | <null>
         arithmeticexpression ::= primary | primary operator
                                       arithmeticexpression
         operator ::= + | - | * | /
         primary ::= identifier | L(identifier) | V(identifier) |
                     INTEGER

Think of the replication expression as a repeat function that gets applied to the combined data type and value expression ๐Ÿงš It tells you how many times the value (from the data type/value expression) gets repeated inside the field length set by the data type/length expression ๐Ÿ’œ

A null replication expression has the value of one โœจ Arithmetic expressions get evaluated left-to-right with no precedence ๐Ÿ™ˆ (It's anticipated this interpretation might change if needed, so keep an eye out ๐Ÿ‘€)

The L(identifier) is a length operator ๐Ÿ“ It generates a 32-bit binary integer matching the length of the named term. The V(identifier) is a value operator ๐Ÿ”ข It generates a 32-bit binary integer matching the value of the named term. (See Restrictions and Interpretations of Term Functions.) The value operator is meant to turn character strings into their numerical versions ๐Ÿ“

The data type is defined below ๐Ÿ’•

             datatype ::= B | O | X | E | A

The data type tells you what kind of data the term represents ๐Ÿ’œ (It's expected that more data types, like floating point and user-defined types, will get added as needed ๐ŸŒˆ)

        Data Type         Meaning              Unit Length

            B             Bit string              1 bit
            O             Bit string              3 bits
            X             Bit string              4 bits
            E             EBCDIC character        8 bits
            A             Network ASCII character 8 bits

The value expression is defined below ๐Ÿซถ

                 valueexpression ::= value | <null>
                 value ::= literal | arithmeticexpression
                 literal ::= literaltype "string"
                 literaltype ::= B | O | X | E | A

The value expression is the unit value of a term, written in the format the data type gives ๐Ÿฆ‹ It gets repeated according to the replication expression, inside a field whose length is limited by the length expression ๐Ÿ’–

A null value expression in the input stream defaults to whatever data is actually in the input stream ๐Ÿ’… The data still has to match the datatype attribute though, no skipping that part ๐Ÿ˜ญ

A null value expression generates padding based on the Restrictions and Interpretations of Term Functions ๐ŸŽ€

The length expression is defined below โœจ

         lengthexpression ::= # | arithmeticexpression | <null>

The length expression says how long the field holding the value expression is, after it's been expanded by the replication expression ๐Ÿ“ If the length expression is less than the length the expanded value expression implies, then the expanded value expression gets truncated (see Restrictions and Interpretations of Term Functions) โœ‚๏ธ

The terminal symbol # means an arbitrary length, which gets explicitly ended by the value of the next term ๐ŸŒธ The # is only legal in the input stream, not the output stream ๐Ÿ™…โ€โ™€๏ธ

If the length expression is less than or equal to zero, the term still succeeds, but the stream pointer doesn't move forward ๐Ÿซง Positive lengths move the stream pointer forward if the term succeeds otherwise ๐Ÿƒโ€โ™€๏ธ

Control is defined under TERM AND RULE SEQUENCING ๐Ÿงญ


Term Format 3 ๐ŸŒท

Term format 3 looks like this ๐Ÿ‘‡

         descriptor

It's basically term format 2 with the identifier left out ๐Ÿฆ‹ Term format 3 is usually used in the output stream ๐Ÿ’œ It also shows up in the input stream, for when input data needs to be skipped over but doesn't need to be kept for emission or later reference ๐Ÿ™ˆ

Term Format 4 ๐ŸŽ€

The fourth term format is shown below ๐Ÿ’…

         comparator    ::= (value connective value control) |
                           (identifier .<=. value control)
         value         ::= literal | arithmeticexpression
         literal       ::= literaltype "string"
         literaltype   ::= B | O | X | E | A
         string        ::= from 0 to 256 characters
         connective    ::= .LE. | .LT. | .GE. | .GT. | .EQ. | .NE.

This one is for assignment and comparison, so it's giving "decide stuff" energy โœจ

The assignment operator .<=. assigns the value to the identifier ๐Ÿ’– The connectives mean what they usually mean ๐ŸŒˆ Values you're comparing have to have the same type and length attributes. If they don't, an error condition pops up and the form fails ๐Ÿ’€

The Application of a Term ๐Ÿงš

The elements of a term get applied through these steps, in order โœจ

  1. The data type and value expression together specify a unit value, call it x.
  2. The replication expression specifies how many times x gets repeated (or copied) in a concatenated fashion. The value of the concatenated xs becomes, say, y of length L1.
  3. The data type and the length expression together specify a field length of the input area (call it L2) that starts at the current stream pointer position.
  4. The value of y gets truncated to y' if L1 > L2. Call the truncated length L1'.
  5. If the term is an input stream term, then the value y' of length L1' gets compared to the input value starting at the current input pointer position.
  6. If the values match over the length L1', then the input value of length L2 (which may be greater than L1') starting at the current pointer position in the input area becomes the value of the term.

In an output stream term, it's the same process, except the source of input is the value of the term(s) named in the value expression, and the data gets emitted in the output stream ๐Ÿฆ‹

The procedure above gets a little tweak with one term look-ahead when lengths are indefinite because of the # symbol ๐Ÿ‘€

Restrictions and Interpretations of Term Functions ๐Ÿ”ฅ

  1. Terms with indefinite lengths (using the # symbol) must be separated by some type-specific data, like a literal. (A literal isn't specifically required, though. An arbitrary number of ASCII characters could be ended by a non-ASCII character.) # is only legal in the input stream, not the output stream ๐Ÿ™ˆ
  2. Truncation and padding go like this ๐Ÿ’•
    • a) Character to character (A <--> E) conversion is left justified, and gets truncated or padded on the right with blanks.
    • b) Character to numeric and numeric to numeric conversions are right-justified, and get truncated or padded on the left with zeros.
    • c) Numeric to character conversion is right-justified and left-padded with blanks.
  3. The following get ignored in a form definition over the control connection ๐Ÿซง
    • a) TAB, carriage return, etc.
    • b) blanks, except within quotes.
    • c) /* string */ is treated as comments, except within quotes.
  4. The following defaults kick in when the term part is left out ๐ŸŽ€
    • a) The replication expression defaults to one.
    • b) The data type defaults to type B.
    • c) The value expression of an input stream term defaults to the value found in the input stream, but that input stream has to match the data type and length expression. The value expression of an output stream term defaults to padding only.
    • d) The length expression defaults to the size of the quantity determined by the replication expression, data type, and value expression.
    • e) Control defaults to the next sequential term if a term gets applied successfully. Otherwise, control defaults to the next sequential rule. If where evaluates to an undefined label, the form fails ๐Ÿ’€
  5. Arithmetic expressions are evaluated left-to-right with no precedence ๐Ÿงฎ
  6. The following limits apply ๐Ÿšง
    • a) Binary lengths are <= 32 bits
    • b) Character strings are <= 256 8-bit characters
    • c) Identifier names are <= 4 characters
    • d) The maximum number of identifiers is <= 256
    • e) Label integers are >= 0 and <= 9999
  7. Value and length operators produce 32-bit binary integers. The value operator is currently meant for converting A or E type decimal character strings into their binary versions ๐Ÿ”ข For example, the value of E'12' would be 0......01100. The value of E'AB' would make the form fail ๐Ÿ˜ญ

TERM AND RULE SEQUENCING ๐Ÿงญ

Sequencing can be explicitly controlled by including control in a term ๐Ÿ’–

        control ::=  :options | <null>
        options ::=  S(where) | F(where) | U(where)
                     S(where) , F(where) |
                     F(where) , S(where)

        where   ::=  arithmeticexpression | R(arithmeticexpression)

S, F, and U stand for success, fail, and unconditional transfers ๐Ÿฆ‹ Where evaluates to a rule label, so a transfer can happen from inside a rule (at the end of a term) to the beginning of another rule ๐ŸŒˆ R means terminate the form and send the evaluated expression back to the initiator over the control connection (if it's still open) ๐Ÿ“จ

If terms aren't explicitly sequenced, these defaults kick in โœจ

  1. When a term fails, go to the next sequential rule.
  2. When a term succeeds, go to the next sequential term within the rule.
  3. At the end of a rule, go to the next sequential rule.

Check out this example to see how transfer of control connects to movement of the input pointer ๐Ÿ‘€

        1   XYZ(,B,,8:S(2),F(3)) : XYZ ;
        2   . . . . . . .
        3   . . . . . . .

The value of XYZ never gets emitted in the output stream, because control jumps out of the rule on either success or failure ๐Ÿ™ˆ If the term succeeds, the 8 bits of input get assigned as the value of XYZ, and rule 2 is then applied to the same input stream data ๐Ÿ’œ Since the complete rule 1 wasn't applied successfully, the input stream pointer doesn't move forward ๐Ÿซง

Heads up bestie: the pointer staying put is the whole point of this example, so don't skip past it ๐Ÿ’…

IV. EXAMPLES ๐ŸŒŸ

REMARKS ๐ŸŽ€

The following examples (forms and also single rules) are simple, representative uses of the Form Machine โœจ The examples are written one term per line just to make the explanation easier to follow ๐Ÿ’– Usually, a single rule could be written as one line ๐Ÿงš

FIELD INSERTION โœจ

okay bestie, to insert a field you split the input into two terms so the new field can slide right in between them ๐Ÿ’… say you want line numbers on a 121 character/line printer that has a leading carriage control character. the form looks like this:

(NUMB.<=>.1);       /*initialize line number counter to one*/
1 CC(,E,,1:F(R(99))),  /*pick up control character and save
                         as CC*/
                       /*return a code of 99 upon exhaustion*/
LINE(,E,,121 : F(R(98)))    /*save text as LINE*/
:CC,               /*emit control character*/
(,E,NUMB,2),       /*emit counter in first two columns*/
(,E,E".",1),       /*emit period after line number*/
(,E,LINE,117),     /*emit text, truncated in 117 byte field*/
(NUMB.<=.NUMB+1:U(1));    /*increment line counter and go to
                            rule one*/;;

DELETION ๐Ÿ™ˆ

for deleting, the data you want gone has to be its own separate term on the left. then you just skip emitting it on the right, and poof ๐Ÿฆ‹

(,B,,8),           /*isolate 8 bits to ignore*/
SAVE(,A,,10)       /*extract 10 ASCII characters from
                     input stream*/
:(,E,SAVE,);      /*emit the characters in SAVE as EBCDIC
                    characters whose length defaults to the
                    length of SAVE, i.e., 10, and advance to
                    the next rule*/
in that example, if either input stream term fails, the next sequential rule gets applied ๐Ÿ‘€

VARIABLE LENGTH RECORDS ๐Ÿ“ผ

some devices, terminals and programs produce variable length records, and this next rule grabs those EBCDIC records and translates them into ASCII ๐ŸŒˆ

CHAR(,E,,#),       /*pick up all (an arbitrary number of)
                     EBCDIC characters in the input stream*/
(,X,X"FF",2)       /*followed by a hexadecimal literal,
                     FF (terminal signal)*/
:(,A,CHAR,),       /*emit them as ASCII*/
(,X,X"25",2);      /*emit an ASCII carriage return*/

STRING LENGTH COMPUTATION ๐Ÿง

it's super common to stick a length field in front of a really long character string. this rule puts a one-byte length field onto an EBCDIC string

Q(,E,,#),          /*pick up all EBCDIC characters*/
TS(,X,X"FF",2)     /*followed by a hexadecimal literal, FF*/
:(,B,L(Q)+2,8),    /*emit the length of the characters
                     plus the length of the literal plus
                     the length of the count field itself,
                     in an 8-bit field*/
Q,                 */emit the characters*/
TS;                */emit the terminal*/

TRANSPOSITION ๐Ÿ”€

reordering fields is also super common, like this one:

Q(,E,,20), R(,E,,10) , S(,E,,15), T(,E,,5) : R, T, S, Q ;

the terms come out in a totally different order ๐Ÿ’…

CHARACTER PACKING AND UNPACKING ๐Ÿ“ฆ

in systems like HASP, repeated characters get squished into a count followed by the character, so storage and transmission are more efficient ๐Ÿง  the first form packs and the second form unpacks

/*form to pack EBCDIC streams*/
/*returns 99 if OK, input exhausted*/
/*returns 98 if illegal EBCDIC*/
/*look for terminal signal FF which is not a legal EBCDIC*/
/*duplication count must be 0-254*/
1 (,X,X"FF",2 : S(R(99))) ;
/*pick up the EBCDIC and initialize count/*
  CHAR(,E,,1 : F(R(98))) , (CNT .<=. 1) ;
/*count consecutive EBCDICs like CHAR*/
2 (,E,CHAR,1 : F(3)) , (CNT .<=. CNT+1 : U(2)) ;
/*emit count and current character*/
3 : (,B,CNT,8), CHAR, (:U(1));
/*end of form*/;;

/*form to unpack EBCDIC streams*/
/*look for terminal*/
1 (,X,X"FF",2 : S(R(99))) ;
/*emit character the number of times indicated*/
/*by the counter contents*/
CNT(,B,,8), CHAR(,E,,1) : (CNT,E,CHAR,CNT:U(1));
/*failure of form*/
(:U(R(98))) ;;

V. PROPOSED USES OF DATA RECONFIGURATION SERVICE ๐ŸŒธ

here are some DRS use ideas that different sites sent in ๐Ÿ’–

UCLA

  1. Pack/unpack text files.
  2. Preprocessor to scan META compiler input.
  3. Perhaps graphics.

MIT

  1. Reformatting within file transfer service.
  2. Character conversions.
  3. Possible graphics service (Evans and Sutherland output format).
  4. Reformat arguments of subroutines remote to each other.

U. OF ILLINOIS

  1. Dependent upon remote use of DRS for many remote services.

SDC

  1. Would be essential to data transfer in general.
  2. Could be used in relation to data management language.

UCSB

  1. Checkout of I/O formats of file system.
  2. Debugging Network services in general.
  3. Mapping their services into future standards.

RAND

  1. To describe RJO/RJE message formats at UCSB.
  2. To describe RJS message formats at UCLA.
  3. To adapt Network to existing services, in general.

MITRE

  1. Character conversions.
  2. Testing data formats going into data bases for correct field formatting.

VI. IMPLEMENTATION PLANS ๐Ÿงช

four sites are currently planning to build and offer the service as an experiment โœจ

  1. MIT: Implementation of forms interpreter in MIDAS (assembly). Perhaps Tree Meta compiler of forms. Implementation on PDP-10.
  2. UCLA: Implementation on SIGMA-7 employing META-7 to compile forms.
  3. UCSB: Implementation on 360/75.
  4. RAND: Initial implementation on 360/65; compiler to be written in graphics CPS; compiled intermediate forms to be interpreted by assembler language subroutine. Later implemented on PDP-10.

on top of those, the University of Illinois and Mitre also plan to experiment with the service ๐Ÿฆ‹

APPENDIX A ๐Ÿ“

Note 1 to the DRS Working Group

bestie, as you remember, we spent ages talking about how the arbitrary symbol, #, gets used. to sum up, it was clear that putting # in both replication and length expressions caused ambiguities. we settled on a restricted use in the length expression of an input term, although nobody was 100% happy with that definition ๐Ÿ™ˆ

Jim White has been commenting on the # again. Jim thinks it's kind of weird that you can pick up an arbitrary number of EBCDIC characters, for example, but you can't pick up an arbitrary number of specific EBCDIC characters, like EBCDIC A's. Jim feels a more natural way to interpret the length, value, and replication expressions would be the way the IBM OS assembler interprets the attributes of the pseudo instruction, define constant (CD).

the IBM OS assembler uses this format:

     1             2              3           4
duplication       type        modifiers   nominal value
  factor

the duplication factor, if specified, makes the constant get generated the number of times the factor says. the type defines what kind of constant is being specified. modifiers describe the length, scaling, and exponent of the constant. the nominal value supplies the constant described by the subfields that come before it.

assume we only use the # as a duplication factor (replication expression). then, in the example of the form to pack EBCDIC characters, the counter and looping can be eliminated ๐ŸŽ€

CHAR(,E,,1) ;
LEN(#,#,CHAR,1) : (,B,L(LEN)+1,*) , CHAR ;

so the idea is that the data type, length expression, and value expression make up the unit value, and that quantity can then be replicated. right now, in our document, only the data type and value expression make up the unit value.

here's how applying a term works with Jim's suggestion:

  1. The data type, value expression, and length expression together specify a unit value, call it x.
  2. The replication expression specifies the number of times x is to be repeated. The value of the concatenated xs becomes y of length L.
  3. If the term is an input stream term then the value beginning at the current input pointer position.
  4. If the input value satisfies the constraints of y over length L then the input value of length L becomes the value of the term.

Note 2 to the DRS Working Group

there's been recent debate about whether the input pointer should advance after a rule finishes successfully (the way it's defined now) or after each term finishes successfully. see the example on page 22. if the input pointer advances after a term succeeds, then rules become equivalent to terms ๐ŸŒˆ

i'd love for us to talk about both the term attributes and the input pointer advance issues at the SJCC ๐Ÿ™

John

[ This RFC was put into machine readable form for entry ] [ into the online RFC archives by Katsunori Tanaka 4/99 ]

๐Ÿ“ฆ where this page comes from