McIDAS Programmer's Manual

Chapter 7 - Writing ADDE Servers

This chapter describes the procedures that you will use to build data servers for McIDAS-X ADDE applications. You'll learn:

This chapter is organized into the following sections:

Overview

ADDE (Abstract Data Distribution Environment) is the client/server mechanism for distributing data in McIDAS-X. In ADDE, an application sends a request for data through an API routine to a server. The server is the software running on a machine in a distributed system that stores data and supplies it to the client upon request.

What does a server do?

The server's job is to:

When the application reads the data sent from the server, the physical location of the original data and its stored format are transparent.

How many server categories does McIDAS-X have?

McIDAS-X has two server categories: primary and secondary.

In short, a user enters a data request based on the ADDE group and descriptor name. mcserv starts the appropriate primary server based on the request type. The primary server extracts information about the requested dataset from the server mapping table, including the stored format of the data. If the stored data format is different from the standard McIDAS-X stored formats, the primary server starts a secondary server to convert the data to the format the client expects.

Getting started

Before writing an ADDE server, you should understand some basic concepts about servers in McIDAS-X. This section describes the following:

Client and server communication

The ADDE design is stream-oriented, so both the client and server can work simultaneously. An ADDE server reads a data request sent from the client via stdin (standard input) and sends data back to the client using stdout (standard output) through a pipe.

Although the size of the data sent from the server may be many megabytes, intermediate data storage on the server or client is not needed. Since the pipe is a finite size, the server will wait to write if the pipe is full. The client will wait for up to two minutes if the pipe is empty. If no activity takes place on the pipe after two minutes, the process stops. This is important for requests that take a long time to fulfill due to extensive searching. An environment variable, ADDETIMEOUT, can be set on the server to change this timeout length.

Rules for transmitting data

The rules below apply to all data transmissions between the server and client.

Primary servers

Primary servers, along with the client APIs, define the client selection syntax and the transmission format between the server and the client. The selection syntax and transmission format are different for the various data types in McIDAS-X. The table below lists the current primary servers provided in McIDAS-X.

Client APIs

Client request type

Data type

Server name

Description

Secondary
server suffix

mcadel

ADEL

image

adelserv

deletes images from a dataset

 

mcadir
mcadrd

ADIR

image

adirserv

retrieves image header information

ADIR

mcaget
mcalin
mcapfx
mcanav
mcacal
mcacrd

AGET

image

agetserv

retrieves the image header, navigation, calibration and data; data is returned line by line

AGET

mcaput
mcaout
mcacou

APUT

image

aputserv

writes an image object to a dataset

 

mcaput

ATOK

image

atokserv

checks file permissions for writing image objects

 

mcgdir
mcgfdrd
mcgdrd

GDIR

grid

gdirserv

retrieves grid header information

GDIR

mcgget
mcgridf
mcgridc

GGET

grid

ggetserv

retrieves the grid header and entire grid

GGET

mcgput
mcgoutf
mcgoutc

GPUT

grid

gputserv

writes a grid object to a dataset

 

mcgput

GTOK

grid

gtokserv

checks file permissions for writing grid objects

 

m0pthdr
m0ptrdhdr
m0pthdrd

MDFH

point

mdfhserv

retrieves point file header information

 

ptcopy command

MDHD

point

mdhdserv

retrieves point header information

 

m0ptget
m0ptrd

MDKS

point

mdksserv

retrieves the point header and data

KS

m0navget
M0ReadNavBlock

NAVG

nav

navgserv

retrieves satellite navigation

 

M0obtxget
M0obtxread

OBTG

text

obtgserv

retrieves observational weather text

OBTG

M0textget
M0txtread

TXTG

text

txtgserv

retrieves an ASCII text file

 

M0wtxget
M0wtxread

WTXG

text

wtxgserv

retrieves textual weather information

WTXG

The ADDE communications module, mcserv , starts the primary servers based on the server's IP address, which tells mcserv if the request will be fulfilled locally or remotely. If the request is handled locally, mcserv finds the ADDE request type and runs the appropriate server process. The server process reads the body of the client request, acquires the data requested and sends the data back to the client.

If the request is handled remotely, mcserv opens a connection to the remote server and acts as a TCP-to-pipe bridge, sending out the request. On the server machine, inetd receives the connection and creates a child process running the same mcserv module with slightly different command arguments. Like local requests, this version reads the beginning of the client request, determines which server process is needed and runs it. The server processes the request and sends the data requested back to the client.

Secondary servers

In ADDE, the client requesting data doesn't care about the file format of the stored data. It only cares that the data is delivered in a well-known, predefined format. For example, if you have gridded data stored in a flat ASCII file, the McIDAS-X GRDDISP command can contour that data as long as the server delivers the gridded data to the client in the appropriate format. To accomplish this, you need a secondary server.

The secondary server's job is to:

Sample data request

The example below shows the steps that a primary and secondary server will use to fulfill a data request. You should assume that the server administrator inserted the two commands below into the server mapping table:

DSSERVE ADD ETA/00 GRID 101 110 TYPE=GRID "00Z ETA Model Run
DSSERVE ADD LOCAL/MODEL FLAT TYPE=GRID "Local Model Grids

The first entry created the grid dataset ETA/00, which is stored in the standard McIDAS-X grid format in grid file numbers 101 to 110. The second entry created the grid dataset LOCAL/MODEL. The grids for this dataset aren't stored in the McIDAS-X grid format, but in a format called FLAT. If a user enters a GRDDISP command to display a grid from each of these datasets, the steps taken by the server to fulfill these requests are different.

Using a primary server

If the user enters the GRDDISP command below, the steps that follow are performed once the appropriate machine is identified.

Type: GRDDISP ETA/00

  1. mcserv starts the primary server ggetserv .
  2. ggetserv reads the server mapping table entry for the dataset ETA/00.
  3. Because the grids from ETA/00 are in the standard McIDAS-X format, ggetserv processes the data request and sends the data to the client.

Using a secondary server

If the user enters the command below, the steps that follow are performed.

Type: GRDDISP LOCAL/MODEL

  1. mcserv starts the primary server ggetserv .
  2. ggetserv reads the server mapping table entry for the dataset LOCAL/MODEL.
  3. Because the grids are stored in a non-standard McIDAS-X format called FLAT, ggetserv starts the secondary server flatgget .
  4. flatgget processes the data request and sends the data to the client.

Building your ADDE server

Whether you're creating primary or secondary ADDE servers, they must perform these seven steps:

  1. Initialize the McIDAS-X file system to recognize MCPATH and file redirection.
  2. Read the ADDE client request.
  3. Read the server mapping table.
  4. Interpret the client request.
  5. Retrieve the requested data from disk.
  6. Send the data to the client.
  7. End the transaction.

Steps 1, 2, 3 and 7 are the same for all data types; steps 4, 5 and 6 are different among the data types. All seven steps are described in this section, along with the function calls required to perform them.

This section is organized into these parts:

McIDAS library functions

The McIDAS-X library functions that you will use when creating an ADDE server are listed alphabetically in the table below.

C function

Fortran function

Description

 

initblok

initializes the McIDAS-X environment for the server

M0isrtdataset

m0isrtdataset

determines if the dataset requested was flagged as a real-time dataset

M0IsTraceSet

m0istraceset

given a client request, activates tracing if TRACE=nonzero value

M0swbyt4

swbyt4

conditionally flips 4-byte data buffers

 

swbyt2

conditionally flips 2-byte data buffers

M0sxdatasetinfo

m0sxdatasetinfo

extracts the server mapping table information

M0sxdone

m0sxdone

ends the ADDE transaction

M0sxGetClientRequest

m0sxgetclientrequest

reads the request header and request string sent from the client

M0sxread

m0sxread

reads data sent from the client to the server

 

m0sxresolv

appends information from the server mapping table to the client request

M0sxsend

m0sxsend

sends data from the server to the client

M0sxSetTraceOff

m0sxsettraceoff

turns tracing off

M0sxSetTraceOn

m0sxsettraceon

turns tracing on

M0sxtrce

m0sxtrce

writes tracing information to a trace file

M0InitLocalServer

 

initializes the environment for secondary servers

Mctrace

mctrace

writes tracing information to a trace file

Initializing the McIDAS-X file system

Your server must be able to access McIDAS-X disk files, since most servers are built using disk file utilities. Use the initblok function to initialize the McIDAS-X disk file system so the server can recognize MCPATH and the redirection table, as shown below. Note that the parameter passed into initblok must be a 2-byte integer.

In Fortran:

integer*2 init_stat
:
ok = initblok (init_stat)

In C:

short     init_stat;
:
ok = initblok_ (&init_stat);

 

 

For more information about disk files, see the section titled McIDAS disk files in Chapter 5, Accessing Data . For more information about file redirection and MCPATH, see the section titled McIDAS user applications in Chapter 2, Learning the Basics .

Reading the ADDE client request

Each ADDE client request received by the server contains a 160-byte request header , which contains system-level information built for the server.

The table below shows the input components included in the request header. The third column contains the starting word locations if the server is written in Fortran; the fourth column contains the variable names for the C structure, servacct , if the server is written in C.

 

Request header components

Length, in bytes

Word number
in Fortran

servacct structure names in C

server IP address

4

1

server_address

server port

4

2

server_port

client IP address

4

3

client_address

user initials

4 (ASCII)

4

user

project number

4

5

project

password

12 (ASCII)

6 - 8

password

service name

4 (ASCII)

9

transaction

input data length

4

10

input_length in excess of 160 bytes

request string

120 (ASCII)

11 - 40

text

The last 120 characters of the request header is a buffer that may hold the client request string. The request string contains the group and descriptor names, and any selection conditions the server may need to fulfill the client request. If the request string is too long to fit in this buffer, the request string variable will contain a value of zero in bytes 4-7; bytes 0-3 will contain the actual length of the request string, which the server then must read from stdin .

The process for reading the ADDE client request is performed with one of two functions, depending on whether the server reading the request is a primary or secondary server.

Words 41 to 64 are for sending a return packet. The section Ending the transaction in this chapter provides more information.

Using a primary server

To read the client request from a primary server, call M0sxGetClientRequest or m0sxgetclientrequest , as shown in the code fragments below.

In Fortran:

include 'fileparm.inc'
character*(MAXPATHLENGTH) request
integer                   request_block(64)
:
:
ok = m0sxgetclientrequest(request_block, request)

In C:

#include "mcidas.h"
:
servacct request_block;
char     *request;
int       ok;

ok = M0sxGetClientRequest (&request_block, &request);

Upon successful completion, request_block contains the request header information sent to the server, and request contains the request string, including the group and descriptor names and selection conditions specified.

Using a secondary server

To read the client request from a secondary server, call the function M0InitLocalServer, as shown in the code fragment below.

const char Server[] = {"TESTSERV"};
servacct   request_block;
char      *request;
:
:
ok = M0InitLocalServer (Server, &request_block, &request);

Upon successful completion, request_block contains the request header information sent to the server, and request contains the request string, including the group and descriptor names and selection conditions specified.

If the dataset requested by the client is stored in a non-standard McIDAS-X format on the server, the primary server starts the secondary server with a call to m0subserv . m0subserv builds an argument list for the secondary server and starts it with a call to execlp . The argument list contains both information from the client request block and the actual client request string. The M0InitLocalServer function extracts values from the secondary server's argument list and puts them in the client request block.

Reading the server mapping table

Once the server successfully receives the client's request, it must extract information from the server mapping table, which is a database that provides the server with information needed to fulfill a user request. The server mapping table is manipulated by the DSSERVE command and contains information about the location and format of the data on the server machine. This information is accessed by the server based on the group and descriptor names included in the client request.

The function M0sxdatasetinfo or m0sxdatasetinfo extracts information that the server needs from the server mapping table, including:

The code fragment below demonstrates the use of M0sxdatasetinfo . It assumes that the server administrator entered the following DSSERVE command, which created the ADDE dataset GMS/IR:

Type: DSSERVE ADD GMS /IR AUST 3 8 TYPE =IMAGE INFO=east_ir.cfg "GMS Infrared Imagery

char *request;
char *group;
char *dataset;
char *type;
char *format;
char *info;
char *comment;
int   min_range;
int   max_range;
int   real_time;

...
...
...

ok = M0sxdatasetinfo (request, &group, &dataset, &type, &format,
                 &info, &comment, &min_range, &max_range, &real_time);

Upon successful completion, the output variables will contain the following values:

Variable

Value

group

GMS

dataset

IR

type

IMAGE

format

AUST

info

east_ir.cfg

comment

GMS Infrared Imagery

min_range

3

max_range

8

real_time

0 (default)

Interpreting the client request

After the server reads the client request and extracts the dataset information from the server mapping table, it parses the client request so the data can be located and the request fulfilled.

Since client requests are similar in form to a McIDAS-X command, it is easiest to use the McIDAS-X command line parsing routines to extract information from the request. To use common command line data retrievers, such as Mccmdstr and Mccmdint , you must initialize the command line subsystem. You only need to do this for primary servers. The M0InitLocalServer function automatically performs these steps for secondary servers.

The code fragments below demonstrate how to initialize the command line subsystem in both Fortran and C.

In Fortran:

    character*256    request
    integer          len_req
    :

c---    request already contains the request string to be parsed

    call m0cmdput (m0cmdparse (request, len_req))

In C:

char *request;
int   len_req;
int   stat;
:

/* request already contains the request string to be parsed */

stat = M0cmdput (M0cmdparse (request, &len_req)) ;

Once the request string is parsed by the command line subsystem, it is your job, as the server developer, to find the data matching the request. The section titled Request syntax and data transmission formats later in this chapter explains the request syntax for each of the McIDAS-X data types.

Retrieving the requested data from disk

The method of retrieving data matching the client request will vary from file format to file format.

When determining the location of data files, you should be aware that the server mapping table may not have enough entries available for an individual dataset to fully explain the filing format. If this happens, use a configuration file and store the name of that file in the INFO field of the server mapping table. Then the server can get additional file location information there.

Sending the data to the client

When the request is parsed and the appropriate data is located, it can be sent back to the client. All data transactions are done in pairs (count + data) using the function M0sxsend or m0sxsend. First, a 4-byte value containing the length of the data being sent to the client is transmitted. Then that many bytes of data are transmitted.

To ensure that data sent between the server and the client is in network-byte-order (big-endian), include calls to M0swbyt4 or swbyt4 for all integer values. This function flips 4-byte memory segments on little-endian machines; it has no effect on big-endian machines.

The first value sent from the server to the client is read internally by the client function M0cxreq or m0cxreq before any API-level reading routines are called. For example, when serving image data, this value is the total number of bytes the server will send to completely transmit the data object. Some ADDE clients expect a dummy, nonzero value in this location. If a zero is sent back, M0cxreq or m0cxreq assumes the server was unable to fulfill the request. The complete transmission format for each McIDAS-X data type is described later in this chapter in the section titled Request syntax and data transmission formats.

The code fragment below demonstrates the appropriate way to send data from the server to the client. It assumes the client wants to receive a 4-byte dummy value of one, which will be read by m0cxreq, followed by two 40-byte records. Words 2 through 4 in the record are character values; the remainder of the record contains integer values.

   integer n_bytes      ! number of bytes to send  
    integer n_bytes_nbo  ! number of bytes in network byte order
    integer dum_val
    integer buffer(10)

c---    send the value 4 to the client indicating that it is to read an 
c---    additional 4 bytes; the additional 4 bytes will contain the 
c---    value 1; this pair is read on the client in m0cxreq.

    n_bytes     = 4
    n_bytes_nbo = n_bytes
    call swbyt4(n_bytes_nbo, 1)
       call m0sxsend (4, n_bytes_nbo)

       dum_val = 1
       call swbyt4(dum_val, 1)
       call m0sxsend (n_bytes, dum_val)


c---    now we will loop 2 times, getting new data and sending it
c---    back to the client; remember that words 2 through 4 are
c---    character strings.

    do 10 I = 1 , 2

c---    get the data

    ok = datareader (buffer)   ! fictitious function

c---    send the record length back
    
        n_bytes     = 40
        n_bytes_nbo = n_bytes
        call swbyt4(n_bytes_nbo, 1)
        call m0sxsend (4, n_bytes_nbo)

c---    convert the appropriate locations in the buffer to
c---    network byte order

        call swbyt4(buffer(1), 1)
          call swbyt4(buffer(5), 6) 

c---    send the data back to the client

        call m0sxsend (n_bytes, buffer) 

10  continue

Ending the transaction

After the data is transmitted to the client, the server ends the transaction by calling M0sxdone or m0sxdone . This function sends a 96-byte trailer, which is filled on the server and sent to the client at the end of the transaction. Its contents are described in the table below.

Trailer description

Length,
in bytes

Word number
in Fortran

servacct structure names in C

total reply length

4

41

reply_length

cpu used

4

42

cpu

return status code

4

43

returncode

error messages

72

44 - 61

errormsg

date

4

62

date

start time

4

63

start_time

end time

4

64

end_time

Before the transaction ends, you must set the return status code and any error messages that may have voided the transaction. The only successful return code is zero, which appears in word 43 of the client request block. If you send a nonzero value to the client, also put an error string in words 44-61 so the client API will print a message telling the user why the request couldn't be fulfilled. If your site uses the ADDE accounting software, also fill word 41 with the total number of bytes transmitted to the client.

The code fragment below shows the calling sequence that a server should include for a request that can't be fulfilled.

    integer       request_block(64)
    logical       syntax_error
    :
    :

c---there is a syntax error in the client request

    if (syntax_error)then
       comm_block(43) = -1001
        call movcw (request_block(44),'Syntax error in the user
          request')
    endif

    call m0sxdone (request_block)

Using this example, the message below is printed by the function m0cxreq if the server encounters a syntax error.

COMMAND: Syntax error in the user request -1001

Debugging servers

Because ADDE servers read from stdin and write to stdout , you can't call the sdest or Mcprintf function to trace the progress of a server for two reasons:

The solution is to dump messages needed for tracing errors to a file. If errors are reported and tracing is activated, the function M0sxtrce or m0sxtrce will write trace messages to a file named trce . If tracing is not activated, M0sxtrce or m0sxtrce does nothing.

The keyword TRACE is appended to each client request. If TRACE=0, which is the default, tracing is not performed. If TRACE=nonzero value, tracing is activated. The function M0IsTraceSet or m0istraceset automatically activates tracing on the server if the value for TRACE in the client request string is a nonzero number. If you write secondary servers, a call to M0IsTraceSet is made within the function M0InitLocalServer . To activate tracing within a server on your own, call M0sxSetTraceOn or m0sxsettraceon . To turn it off, call M0sxSetTraceOff or m0sxsettraceoff .

Since each account has only one trace file, prefix each line of your tracing strings with the name of the server generating that string. When you look through the contents of the trace file, you can easily find the trace information generated by the problem server.

You can also use the Mctrace or mctrace function to automatically append the server name to the trace message and set a flag for each message. The flag restricts tracing to only selected values of the keyword TRACE.

The sample code fragment below is from the server TOMGSERV.

const char    Server[] = {"TOMGSERV"};
char         *request;
servacct      request_block;
char          trace_string[500];
short         init_stat;

initblok_ (&init_stat);

/* get the client request and set tracing */

ok = M0sxGetClientRequest (&request_block, &request);
ok = M0IsTraceSet (request); 

/* print a trace message containing the entire user request */

sprintf (trace_string, "%s: %s", Server, request);
M0sxtrce (trace_string)
;

/* continue processing */

If the user enters the following client request:

Type: GMS AUST TIME=12 DAY=1996352 ID=YSSY TRACE=1

Upon completion, the file trace will contain this line:

TOMGSERV: GMS AUST TIME=12 DAY=1996352 ID=YSSY TRACE=1

Request syntax and data transmission formats

This section is organized into the following topics:

In ADDE, the client will manipulate data regardless of the format in which it is stored on the server. For this to happen, however, you must follow a specified set of rules for processing data and delivering it to the client. This section describes the client request syntax and data transmission formats for each data type supported in McIDAS-X. The table below provides a summary of the necessary components for each request type, in alphabetical order.

Request type

Data type

Description

Client requester

Client reader

Sample McIDAS-X command

ADIR

image

image header information

mcadir

mcadrd

 

AGET

image

image header, navigation, calibration and data; data is returned line by line; comments

mcaget

mcalin

mcapfx

mcacrd

mcacal

mcanav

 

 

GDIR

grid

grid header information

mcgdir

mcgfdrd

mcgdrd

 

GGET

grid

grid header and entire grid

mcgget

mcgridf

 

 

MDFH

point

point file header information

m0pthdr

m0ptrdhdr

FORM=FILE

MDHD

point

point header information

 

 

PTLIST FORM=PARAM

MDKS

point

point header and data

m0ptget

m0ptrd

PTLIST

NAVG

nav

satellite navigation

m0navget

m0snlist

m0nvblk

 

OBTG

text

observational weather text

M0obtxget

M0obtxread

 

TXTG

text

ASCII text file

M0textgt

M0txtread

 

WTXG

text

textual weather information

M0wtxget

M0wtxread

 

All secondary servers must perform the four basic tasks below to deliver the appropriate data to the client.

  1. Read the client request based on the syntax described for the data type.
  2. Verify that the client request adheres to any special rules which apply to that data type.
  3. Convert the data to the format the client expects.
  4. Transmit the data to the client in the appropriate format.

Since ADDE client requests are sent as character strings with a format similar to McIDAS-X commands, it is easiest to use the McIDAS-X command line retrieving routines to extract information from the client request. The request syntax description for each data type described in this section uses the McIDAS-X command line notation.

Additionally, remember that transactions of integer values between the client and the server are performed in network-byte-order (big-endian). Unless otherwise noted, assume that all strings sent back to the client are blank padded.

Serving image data

The ADDE server, agetserv , processes a client request and returns a complete image object to the client. An image object includes an image header and the image lines, and may also contain a line prefix for each line, calibration, navigation and comment cards. Due to the volume of data associated with image objects, the server delivers the data portion of the object to the client one line at a time. The McIDAS-X command IMGDISP accesses image objects.

Image object request syntax

The table below lists the client request syntax options for an image object. Note that keywords 1 through 9 are placed in the request block as positional parameters.

Keywords

Description

Remarks

' ' 1

group name

 

' ' 2

dataset name

 

' ' 3

position in the dataset

relative position in the dataset; negative means Nth most recent

' ' 4

coordinate type and position

(E)arth, (I)mage, (A)rea; (C)entered or (U)pper; no default; this field is used with the next two parameters; for example, to return an image centered at latitude 43.5 and longitude 90.0, the client request will contain EC 43.5 90.0

' ' 5

latitude or line number

latitude of the Earth (dd:mm:ss) or line number

' ' 6

longitude or element number

longitude of the Earth (dd:mm:ss) or element number

' ' 7

image resolution

default=1

' ' 8

number of lines to transmit

default=480

' ' 9

number of elements to transmit

default=640

VERSION=

transmission version number

value as of 11/96 is 1

TIME=btime etime

time of day selection range

the format is hh:mm:ss (no default)

DAY=

the day that data is valid

not a range of days; format must be yyddd or ccyyddd (no default)

UNITS=

calibration type requested

not all calibration types are valid for a data type (default=stored units)

SPAC=

number of bytes per data point

be careful when reducing data point resolution, if the data can be sent back in lower resolution (default=stored format)

CAL=

set to QTIR to return TIROS in quick calibration

 

STYPE=VISR

sets calibration to UNITS of BRIT and type of VISR

converts data type to 1-byte data

BAND=band

BAND=ALL

specific band number to send or ALL bands

 

LMAG=

line magnification factor

blow ups are done on the client to conserve transmission bandwidth (default=1); values must be integers; negative numbers mean a blowdown must be performed

EMAG=

element magnification factor

blow ups are done on the client to conserve transmission bandwidth (default=1) values must be integers; negative numbers mean a blowdown must be performed

DOC=

if YES, include the line documentation block

default=NO

AUX=

if YES, additional calibration information is sent

 

Server-specific keywords

Description

ID=

NEXRAD station ID (NEXRAD server)

TIME=btime etime C

Coverage; accesses data for specified time range (realtime POES server)

WL=

wavelength (AIRS server)

WN=

wavenumber (AIRS server)

Special rules for transmitting an image object

You must adhere to the rules below when transmitting an image object. The first five are specific to the client request; the last three are specific to the transmission format sent back to the client.

Converting the image object's format

The image object contains the image header and the image lines. It may also contain line prefixes, navigation, calibration and comment cards. Each of these components is created by the server. Their formats are described in Chapter 6 of this manual in the AREAnnnn data file documentation. Below are the common modifications needed for the image header.

Word

Description

Reason for modification

1

ADDE dataset relative position number

always modified

6

upper-left image line number

1) if client does not specify SIZE=ALL

2) if client requests coordinate base transfer

7

upper-left image element number

1) if client does not specify SIZE=ALL

2) if client requests coordinate base transfer

9

number of lines in the image

1) if client does not specify SIZE=ALL

2) instead of sending lines containing all zeros at the bottom of the image

10

number of elements in the image; must be divisible by 4

1) if client does not specify SIZE=ALL

2) instead of sending lines containing all zeros at the bottom of the image

11

number of bytes per band

1) if SPAC≠source value

2) if client requests STYPE=VISR

12

line resolution

if LMAG≠1

13

element resolution

if EMAG≠1

14

number of spectral bands

if BAND≠ALL

15

length of line prefix

1) if BAND=ALL is not specified

2) if SIZE=ALL is not specified

3) if DOC=YES is specified

4) if STYPE=VISR

19

spectral band map

if BAND=ALL is not specified

34

byte offset to the start of the data block

always modified (256+navlength+callength)

35

byte offset to the start of the navigation block

always modified (usually 256)

36

validity code

1) if request contains DOC=NO, set to 0

2) if SIZE=ALL is not specified, set to 0

3) if DOC=YES, must be set

49

length of the prefix documentation

1) if DOC=NO is specified, set to 0

2) if SIZE=ALL is not specified, set to 0

50

length of prefix calibration

if STYPE=VISR, set to 0

51

length of prefix band length

1) if STYPE=VISR, set to 0

2) if BAND≠ ALL

52

source type; satellite-specific (ASCII)

if STYPE=VISR, set to VISR

53

calibration type; satellite-specific (ASCII)

if STYPE=VISR, set to BRIT

54

sampling/averaging flag

set to 1 if blow down is performed by sampling

57

source's original satellite type (ASCII)

if STYPE=VISR, set to original satellite type

58

units of values returned

if AUX=YES and UNIT is specified

59

scaling of values returned

1) if UNIT is specified

2) if AUX=YES, set to 1

63

byte offset to the start of the calibration block

if calibration is sent
(usually 256+navlength)

64

number of comment cards

if comment cards exist

Transmitting the image object to the client

Once the data is formatted correctly, the image object can be sent to the client. Because the transmission protocol is count+data, the server will send the following information to the client:

The sample code below shows you how to set up your server to transmit image objects.

   integer image_header(64)
    integer nav_block(1024)
    integer cal_block(1024)
    integer line(2000)
    integer prefix(100)
    integer comment(20)
    integer total_bytes
    integer nav_size
    integer cal_size
    integer pre_size
    integer n_comments
    integer n_lines
    integer n_elements
    integer data_size
    integer n_send
    integer n_send_nbo

c---    assume the image_header, nav_block, cal_block have already been loaded

    n_lines    = image_header(9)
    n_elements = image_header(10)
    data_size  = image_header(11)
    nav_size   = image_header(63) - image_header(35)
    cal_size   = image_header(34) - image_header(63)
    pre_size   = image_header(15)
    n_comments = image_header(64)

    total_bytes= (n_lines * n_elements * data_size) +
    &             (n_rows * pre_size) +
    &             (n_comments * 80)
    &             (nav_size + cal_size)

c---    send the total number of bytes in the image object

    n_send_nbo = total_bytes
    call swbyt4(n_send_nbo, 1)
    call m0sxsend(4, n_send_nbo) 

c---    send the image header; assume imageheadernbo converts the header
c---    to network-byte-order

    call imageheadernbo(image_header)
    call m0sxsend(256, image_header) 

c---    send the nav block; assume navnbo converts the nav block to
c---    network-byte order

    if (nav_size .gt. 0)then
       call navnbo(nav_block)
       call m0sxsend(nav_size, nav_block) 
    endif

c---    send the cal block; assume calnbo converts the cal block to
c---    network-byte order

    if (cal_size .gt. 0)then
       call calnbo(cal_block)
       call m0sxsend(cal_size, cal_block) 
    endif

c---    now we will send the image data lines, one line at a time;
c---    assume getoneline retrieves one line of data as packed bytes

    do 10 i = 1 , n_lines
       ok = getoneline(i, line, prefix)
       if (pre_size .gt. 0)then
          call m0sxsend(pre_size, prefix) 
       endif
       call m0sxsend(n_elements, line) 
10  continue

c---    send the comments; assume readcomment reads one comment card

    if (n_comment .gt. 0)then
       do 20 i = 1 , n_comments
          call readcomment(i, comment)
          call m0sxsend(80, comment) 
20     continue
    endif

Serving image directory data

The ADDE server, adirserv , processes a client request and returns image directories and comment cards to the client. The McIDAS-X command IMGLIST accesses image directories.

Image directory request syntax

The table below lists the client request syntax options for image directories. Note that keywords 1 through 4 are placed in the request block as positional parameters

Keywords

Description

Remarks

' ' 1

group name

 

' ' 2

descriptor name

 

' ' 3

beginning file position number

can be the value ALL; positive numbers represent absolute locations; negative numbers are time-relative offsets (no default)

' ' 4

ending file position number

default=beginning file number

AUX=

when YES, sends the center lat/lon, latitude resolution in km, longitude resolution in km, and valid calibration types as comment cards

default=NO

BAND=

spectral band, if the image has multiple bands

DAY=bday eday

day range to search

ccyyddd or yyddd format (no default)

ID=

NEXRAD station ID

NEXRAD server only

SS=ss1 ss2

satellite sensor number

no default

TIME=btime etime

time range to search

hh:mm:ss format (no default)

WL=

wavelength

AIRS server only

WN=

wavenumber

AIRS server only

Special rules for transmitting the image directory

If the server has problems fulfilling the request, use the following standard error values and messages found in ~mcidas/src/adderror.doc . The range -12000 to -12999 lists error codes specific to image directories. Use enumerated error codes and messages when applicable and create new error codes and messages for error conditions that are unique to your site.

Converting the image directory's format

The image directory sent to the client is a 65-word directory. Word 1 contains the AREA number from the server. Words 2 through 65 are the same as words 1 through 64 in the image directory described in the AREAnnnn data file documentation in Chapter 6.

Transmitting image directory objects to the client

Once the data is formatted correctly, the image directory can be transmitted. Because the transmission protocol is count+data, the server will send the following information to the client:

The information is repeated until there are no new image directories to send. The sample code on the facing page shows you how to set up your server to transmit an image directory.

 

   integer image_header(64)
    integer n_comments
    integer comment(20)
    integer n_send_nbo
    integer total_bytes

c---    loop through all image objects matching selection conditions
c---    assume readimagedirectory reads a 64-word image in area format

    do 10 i = 1 , n_files

       ok = readimagedirectory (i, image_header)

       n_comments = image_header(64)

c---    calculate the number of bytes to be sent for this directory

       total_bytes = 260 + (n_comments * 80)
       n_send_nbo  = total_bytes
       call swbyt4(n_send_nbo, 1)
       call m0sxsend(4, total_bytes) 

c---    send the file number

       file = i
       call swbyt4(file, 1)
       call m0sxsend(4, file) 

c---    send the image directory; assume imageheadernbo converts
c---    the header to network-byte-order

       call imageheadernbo(image_header)
       call m0sxsend(256, image_header) 

c---    send comment cards backlashes readcomment reads once 
c---    comment card

       if (n_comments .gt. 0)then
          do 20 j = 1 , n_comments
             call readcomment(i,j,comment)
             call m0sxsend(80,comment) 
20     continue 
        endif
10  continue

Serving grid data

The ADDE server, ggetserv , processes a client request and returns complete grid objects to the client. The grid object contains the grid header and the data. Unlike the image server, which can only send one image object to the client, grid requests may include as many grid objects as desired. The McIDAS-X GRDDISP command accesses grid objects.

Grid object request syntax

The table below lists the client request syntax options for grid objects. The table below lists the client request syntax options for image directories. Note that keywords 1 through 3 are placed in the request block as positional parameters

Keywords

Description

Remarks

' ' 1

group name

 

' ' 2

descriptor name

 

' ' 3

maximum number of bytes that can be stored in the destination grid buffer on the client

 

DAY=day1 .. dayn

list of model-run days

ccyyddd format (no default)

DERIVE=

derived parameters

 

DRANGE=bday eday dinc

range of model-run Julian days

ccyyddd format

FDAY=

model-forecast valid day

ccyyddd format

FRANGE=fhr1 .. fhrn

range of model-forecast hours

 

FTIME=

model-forecast valid time

hhmmss format

GRIB=sgrib egrib

range of grib numbers to get from a McIDAS-X grid file

 

GRID=sgrid egrid

range of grid numbers to get from a McIDAS-X grid file

 

LEV=lev1 .. levn

list of data levels to retrieve

can be a number, SFC, MSL or TRO

NUM=

number of grids to retrieve

can be a number or ALL

PARM=p1 .. pn

list of parameters to retrieve

 

PARSE=select1 .. selectn

list of grid selection conditions for multiple grid parsing

format is a subset of other selection conditions specified; each selection is isolated by single quotes

PNUM=

number of parseable grids specified in the selection

 

POS=

relative file position number in the dataset

 

PRO=

model-projection type

 

SRC=src1 .. srcn

list of model grid sources

 

TIME=time1 .. timen

model run times to retrieve

hhmmss format

TRANGE=btime etime tinc

range of model-run times

hhmmss format for time

VERSION=

grid transmission version

value is A as of 11/96

VT=vt1 .. vt2

valid hour offsets

hhmmss format

Special rules for transmitting a grid object

You must adhere to the rules below when transmitting a grid object. The first two are specific to the client request. The last three are specific to the transmission format sent back to the client.

Converting the grid object's format

The grid object contains a grid header and gridded data. The grid header format is described in Chapter 6 of this manual in the GRIDnnnn data file documentation.

Transmitting grid objects to the client

As the server sends data to the client, TCP may timeout during periods of no data transmission. To avoid timeouts, the server can send a heartbeat value (11223344) periodically to the client to keep the connection active. The heartbeat values are sent at the beginning of the transmission only. Once all the data is found and formatted, the grid object can be sent to the client.

The server sends the client the following information:

The grid header, grid object, and 4-byte value containing zero are repeated until all the grid objects are sent.

The sample code below shows you how to set up your server to transmit a grid object.

   include 'gridparm.inc'
    integer grid_header(64)
    integer grid(MAXGRIDPT)
    integer total_bytes
    integer grid_size

c---    read the grid; assume readgrid reads a grid header's grid
c---    into McIDAS format

    ok = readgrid(grid_header, grid)
    grid_size = grid_header(1)

c---    send the total number of bytes

    total_bytes = 256 + (grid_size * 4) + 8
    temp_int    = total_bytes
    call swbyt4(temp_int, 1)
    call m0sxsend(4, temp_int)
    call M0sxsend (4 temp_int)

c---    send the number of grids

    temp_int = 1
    call swbyt4(temp_int, 1)
    call m0sxsend(4, temp_int)

c---    send the grid header; assume gridheadernbo switches integer
c---    values in the header to network byte order

    call gridheadernbo(grid_header)
    call m0sxsend(256, grid_header)

c---    send the data

    call swbyt4(grid_data,grid_size)
    call m0sxsend(grid_size*4, grid)

c---send 0 separate

    temp = 0
    call swbyt4(temp_int, 1)
    call M0sxsend (4,temp_int)

Serving grid directories

The ADDE server, gdirserv , processes a client request and returns grid directories to the client. The grid directory contains information about the contents of the grid. The McIDAS-X command GRDLIST is one that accesses grid directories.

Grid directory request syntax

The table below lists the client request syntax options for grid directories. Keywords 1 and 2 are placed in the request block as positional parameters.

Keywords

Description

Remarks

' ' 1

group name

 

' ' 2

descriptor name

 

DAY=day1 .. dayn

list of model-run days

ccyyddd format

DERIVE=

derived parameters

 

DRANGE=bday eday dinc

range of model-run Julian days

ccyyddd format

FDAY=

model forecast valid day

ccyyddd format

FRANGE=fhr1 .. fhrn

range of model-forecast hours

 

FTIME=

model-forecast valid time

hhmmss format

GRIB=sgrib egrib

range of grib numbers to get from a McIDAS-X grid file

 

GRID=sgrid egrid

range of grid numbers to get from a McIDAS-X grid file

 

LEV=lev1 .. levn

list of data levels to retrieve

can be a number, SFC, MSL or TRO

NUM=

number of grids to retrieve

can be a number or ALL

OUT=

output format

default=ALL

PARM=p1 .. pn

list of parameters to retrieve

 

PARSE=select1 .. selectn

list of grid selection conditions for multiple grid parsing

format will be a subset of other selection conditions specified; each selection is isolated by single quotes

PNUM=

number of parseable grids specified in the selection

 

POS=

relative file position number in the dataset

 

PRO=

model-projection type to retrieve

 

SRC=src1 .. srcn

list of model grid sources

 

TIME=time1 .. timen

list of model-run times to retrieve

hhmmss format

TRANGE=btime etime tinc

range of model-run times

hhmmss format for time

VERSION=

ADDE grid transmission version

value is 1 as of 11/96

VT=vt1 .. vt2

list of valid hour offsets

hhmmss format

Special rules for transmitting the grid directory

If PAR=STREAML, WINDB or WINDV, you must send the u- and v- component wind.

If DERIVE=TTIN, VOR, DVG, SPD, DIR, ABV, DSH, DST, TD, KINX, COR, BETA or ADV, you must calculate the appropriate grid before sending the results back to the client.

Converting the grid directory's format

The grid directory's format is defined in Chapter 6 of this manual in the GRIDnnnn data file documentation.

Transmitting the grid directory to the client

As the server sends data to the client, TCP may timeout during periods of no data transmission. To avoid timeouts, the server can send a heartbeat value (11223344) to the client periodically to maintain an active connection. The heartbeat values are sent at the beginning of the transmission only. Once all the data is found and formatted, the grid directory can be sent to the client.

The server sends the client the following information. Except the first item, all the items listed below are repeated for each grid file. Within each grid file, the grid file header and the two 4-byte values are repeated for each grid in the grid file.

A 4-byte value of 2, indicating no more grid files, is sent to end the transaction.

If the server has problems fulfilling the request, use the standard error values/messages found in ~mcidas/src/adderror.doc . The range -22001 to
-22999 lists error codes specific to grid directories. Use enumerated error codes and messages when applicable and create new error codes and messages for error conditions that are unique to your site.

The sample code below shows you how to set up your server to transmit a grid directory.

 

   integer grid_header(64)
    integer grid_file_header(64)

c---    send total byte count

    temp_int = (260* n_grids) + (n_files * 260)
    call m0sxsend(4, temp_int)

c---    loop through the grid file headers

    do 10 file = 1 , n_files

c---        read the grid file header; assume readfileheader reads
c---        a grid file header in McIDAS grid file format

        call readfileheader(file, grid_file_header, n_grids)

c---        send the value 0 indicating that a grid file was found

        temp_int = 0
        call m0sxsend (4, temp_int)

c---    send the grid file header; assume gridfileheadernbo
c---    switches integer words to network byte order

    nbytes = 256
    call gridfileheadernbo(grid_file_header)
    call m0sxsend(nbytes, grid_file_header)

    do 20 i = 1 , n_grids

c---        read the grid header; assume readgridheader reads a 
c---        grid in McIDAS grid format

        call readgridheader(file,i,grid_header)

c---        send the value 0 indicating that a grid file was found

        temp_int = 0
        call m0sxsend (4, temp_int)

c---        send the grid header; assume gridheadernbo switches
c---        integer words to network byte order

        nbytes = 256
        call gridheadernbo (grid_header)
        call m0sxsend(nbytes, grid_header)
20  continue

c---    no more data from this grid file

    temp_int = 1
    call swbyt4(temp_int, 1)
    call m0sxsend (4, temp_int)
10  continue

c---    no more data

    temp_int = 2
    call swbyt4(temp_int, 1)
    call m0sxsend (4, temp_int)

Serving point data

The ADDE server, mdksserv , processes a request and returns point data to the client. In addition to the data values, the server also sends information about the units, scaling factor, and name of each parameter returned to the client. The McIDAS-X command PTLIST accesses point data.

Point data request syntax

The table below lists the client request syntax options for point data. The table below lists the client request syntax options for image directories. Note that keywords 1 through 2 are placed in the request block as positional parameters

Keywords

Descriptions

Remarks

' ' 1

group name

 

' ' 2

descriptor name

 

MAX=

maximum number of matches to find given the selection conditions

 

POS=

file position number in a dataset

 

SELECT=

data selection clause

see comments below

TRACE=

trace file activation

set to 1 to activate tracing

VERSION=

transmission version number

value is 1 as of 11/96

Special rules for transmitting point data

The client can request point data either by specifying no specific parameter names, which sends all the parameters to the client, or by specifying only the parameter names of interest. Because the user may ask for an unlimited number of individual parameters, the parameter list is sent after the client request string. Thus, a server must make additional calls to M0sxread to get the list of 4-byte, blank-padded parameter names. You can also call the McExtractPointRequest function to extract the client request and put it in the C structure PTREQUEST.

The SELECT clause contains the entire data selection clause format. You can use as many selection clauses as needed for each request. The selection clause format is described in the section titled Reading point objects: Defining selection conditions in Chapter 5, Accessing Data.

Transmitting point data to the client

When the point data is formatted correctly, it can be sent to the client. The server sends the following information:

The last two pieces of information are repeated until there is no more data to be transmitted. Then the 4-byte value containing the number of bytes of data to be sent will be zero.

If the server has problems fulfilling the request, use the standard error values and messages found in ~mcidas/src/adderror.doc . The range
-31000 to -31999 lists error codes specific to point data. Use enumerated error codes and messages when applicable and create new error codes and messages for error conditions that are unique to your site.

The sample below shows how to set up your server to transmit point data.

   parameter (N_KEYS = 4)
    integer buffer(N_KEYS)
    character*256 keys
    character*256 keys
    integer scales(N_KEYS)
    integer length
    character*1 NULL
    data NULL=/'0'/
    integer temp

c---    send four parameters to the client: station ID, temperature
c---    in Celsius, dew point in Kelvin and wind direction

    keys='ID'//NULL//'T'//NULL//'TD'//NULL//'DIR'
    units='CHAR'//NULL//'C'//NULL//'K'//NULL//'DEG'

    scales(1)  = 0
    scales(2)  = 2
    scales(3)  = 2
    scales(4)  = 0

c---    send the key names

    length = lentrim(keys)
    temp=length
    call swbyt4(length, 1)
    call m0sxsend(4, length)
    call m0sxsend(temp * 4, keys)

c---    send the units

    length = lentrim(units)         
    temp=length
    call m0sxsend(4, length)
    call m0sxsend(temp * 4, units)

c---    send the scalings

    call swbyt4(n_vals, 1)
    call m0sxsend(4, n_vals)
    call m0sxsend(N_KEYS, scales)

10  continue

c---    read the new data; assume readnewdata reads a record of 
c---    data values

    ok = readnewdata(buffer)
    if (ok .eq. 0)then
c---      flip the temp, dewpt and direction
      call swbyt4(buffer(2), 3)
      call m0sxsend(4, n_vals)
      call m0sxsend(N_KEYS * 4, buffer)
      goto 10
    endif

Serving weather text data

The ADDE server, wtxgserv , processes a client request and sends back the text header containing information about the data and the actual weather text data. The McIDAS-X command WXTLIST is one command that accesses weather text data.

This server is delivered with the McIDAS-XCD package.

Weather text request syntax

The table below lists the client request syntax options for weather text data.

Keywords

Description

Remarks

APRO=

AFOS/AWIPS product headers to match

three characters; don't use APRO with the WMO keyword

ASTN=

AFOS/AWIPS stations to match

two or three characters

DAY=

most recent day to begin the search

ccyyddd format (default=current day)

DTIME=

maximum number of hours back in time to search

no default

MATCH=

list of character match strings to find from the text

 

NUM=

number of matches to find

default=1

PROD=

predefined product name

 

SOURCE=

circuit source

default=ALL

WMO=

WMO product headers to match

at least two characters; wildcard characters are allowed; don't use WMO with the APRO keyword

WSTN=

WMO stations to match

four characters

Special rules for transmitting weather text

If the day specified does not equal the current day, the search begins from the end of the day instead of the current time.

Text data is sent to the client as a blank-padded buffer.

The valid standard error values and messages for weather text are located in the range -45000 to -46999. See the wtxgserv source code for error message descriptions.

Converting the text header's format

The information in the table below must be included with each text header sent to the client.

Bytes

Description

Remarks

0 - 3

circuit source

blank-padded character string

4 - 7

number of bytes in the data section

 

8 - 11

file address where the data is located

usually not important to the client

12 - 15

time the data was ingested

hhmmss format

16 - 19

four-character WMO header

product code and country code

20 - 23

WMO product number

integer value

24 - 27

WMO station origin

four-character ICAO ID

28 - 31

AFOS product header

three characters

32 - 35

AFOS product location

two or three characters

36 - 39

AFOS product issuing station

three characters

40 - 43

Julian day of the data

ccyyddd format

44 - 47

number of bytes per line

usually 80

60 - 63

FAA catalog number

 

Transmitting weather text data to the client

Once all the data is found and formatted, the weather text can be sent to the client. Because TCP may timeout during periods of no data transmission, a heartbeat value (11223344) can be sent to the client periodically client maintain an active connection.

The server sends the client the following information:

The last three pieces of information are repeated until no more data is found.

The sample code below shows you how to set up your server to transmit weather text data.

 

char       *actual_request;
int         text_header[16];
char       *text;
int         req_length;
int         temp_int;

/* send back the client request */

req_length = strlen (actual_request);
temp_int   = req_length;
M0swbyt4 (&temp_int, 1);
M0sxsend (4, &temp_int);

length = 1;
while (length > 0)
{
  int total_bytes;

  /* read the length of the next text block */

  length = ReadNewTextBlock (text_header, &text);

  if (length > 0)
  {
    total_bytes = sizeof (text_header) + length;

    /* send the total data block length */

    M0swbyt4 (&total_bytes, 1);
    M0sxsend (4, &total_bytes);

    /* send the text header */

    M0sxsend (sizeof (text_header), text_header);

    /* send the text */

    M0sxsend (length, text);
    free (text);
  }
  else
  {
    temp_int=length;
    M0swbyt4 (&temp_int,1);
    M0sxsend (4, &temp_int);
    
  }
}

Serving observational weather-text data

The ADDE server, obtgserv , processes a client request and returns the text header containing information about the retrieved data, along with the observational weather-text data. The McIDAS-X command OBSRPT is one that accesses observational weather-text data.

This server is delivered with the McIDAS-XCD package.

Observational weather-text request syntax

The table below lists the client request syntax options for observational weather-text data.

Keywords

Description

Remarks

CO=co1 .. con

list of countries

2- character country IDs are read from COUNTRY.DAT, which is provided with McIDAS-XCD

ID=id1 .. idn

list of stations

 

IDREQ=

ID request type

must be set to LIST if CO, REG, or ID is specified; if a LATLON option is added to this server, specify GEO

NEWEST=day hour

most recent observation time to allow in the request

default=most recent observation filed

NHOURS=

maximum number of hours back in time to search from the value in NEWEST

no default

NPERIOD=

number of time periods to list

varies among data types

NUM=

number of matches to find for each station

default=1

OLDEST=day hour

oldest observation time to allow in the request

 

REG=reg1 .. regn

list of station regions

the regions list is stored in GROUPS.DAT, which contains the stations for a particular state/province

TYPE=

numeric value for the type of observation

varies among data types

Special rules for transmitting observational weather text

Don't specify both NUM and NPERIOD, or NPERIOD and NHOURS in the same request. If you specify NHOURS, you must specify NEWEST.

The valid standard error values and messages for observational weather text are located in the range -48000 to -48999. See the obgtserv source code for error message descriptions.

Converting the text header's format

The information in the table below must be included with each text header sent to the client.

Bytes

Description

Remarks

0 - 3

version number

currently zero

4 - 7

observation type number

varies among data types

8 - 11

active observation flag

0=inactive, 1=active

12 - 15

starting observation day

ccyyddd format

16 - 19

starting observation time

hhmmss format

20 - 23

starting observation hour

hhmmss format

24 - 27

ending observation day

ccyyddd format

28 - 31

ending observation time

hhmmss format

32 - 35

ending observation hour

hhmmss format

36 - 39

ID type flag

1 if ICAO ID

40 - 47

station ID

ccyyddd format

48 - 51

number of bytes of data

 

52 - 55

number of lines of data

 

56 - 95

reserved for future use

 

Transmitting observational weather-text data
to the client

Once the data is formatted, the text data can be sent to the client. The server sends the client the following information:

This information should be repeated until no more data is found.

The sample code below shows you how to set up your server to transmit observational weather text data to the client.

   integer       header(24)
    integer       n_bytes
    integer       n_bytes_nbo
    character*80  line(1000)

100 continue

       ok = readnewdata(header, line)
       if (ok .eq. 0)then
          n_bytes = 96
          n_bytes_nbo = n_bytes
          call swbyt4(nbyte_nbo, 1)
          call m0sxsend(4, n_bytes_nbo)
          call m0sxsend(n_bytes, header)
          n_bytes = header(13)
          n_bytes_nbo = n_bytes
          call swbyt4(n_bytes_nbo, 1)
          call m0sxsend(4, n_bytes_nbo)
          call m0sxsend(n_bytes, line)
          goto 100
       else
          n_bytes = 4
          n_bytes_nbo = n_bytes
          call swbyt4(n_bytes_nbo, 1)
          call m0sxsend(4, n_bytes_nbo)
          call m0sxsend(4,0)
         endif

 

 

Appendices

The Programmer's Manual contains the following appendices: