Hi,
  Attached find the list of Xpress tokens, and what they mean.  Some of this
is figured out by taking there program apart, and others are from context.
I'll also include a very primitive program, for UNIX, that decodes the
headers in the datastream.  The packet boundary marker is a 0xFF.

  Karen and I are going to go to San Diago for a weekend sometime in the
Fall.  We have a couple of frequent flyer tickets that will expire if we
don't use them by about September.  Any interest in meeting us there?

See ya,
JIm

============================================================================


# MAIN MENU
N******* "News"
S******* "Sports"
W******* "Weather"
L******* "Lifestyles"
E******* "Entertainment"
T******* "Tech Talk"
M******* "Shopping"
I******* "Information on X*CHANGE"
X******* "Inside X*PRESS"
B******* "Business Wire"
F******* "Financial News"

# BUSINESS WIRE
B??AG*** "Canadian Press(CP): Business Report"
B??HS*** "McGraw-Hill News SNAPSHOT"
B??RB*** "BUSINESS-WIRE: Company PR W.R.T. Stock"
B??RP*** "PR Newswire"
B??SI*** "NYSE Standard and Poors Indices"

# ENTERTAINMENT
E??H**** "The Stars"
E??L**** "TV Schedules"
E??M**** "Movies, Books, and Music"
E??S**** "TV Scope"
E??W**** "What's happening"

# FINANCIAL NEWS
F??CC*** "Commodity Commentary"
F??CF*** "Weekly Farm Report"
F??CP*** "Commodity Prices"
F??F**** "Weekly Mutual Fund Commentary"
F??MC*** "Money Commentary"
F??ME*** "Foreign Exchange Rates"
F??MM*** "Interest and Money Rates"
F??MU*** "US Treasury Bills Rates"
F??O**** "Financial News Headlines"
F??Og*** "Selected Press Releases/Financial Reports"
F??Oi*** "Daily Insider Trading Report"
F??PMR** "Today's Interest Rates"
F??POC** "Market Statistics"
F??POM** "Just a Reminder!"
F??SA*** "Hourly Dow Jones Averages"
F??SC*** "New York Stock Market Commentary"
F??SD*** "Daily Dividends"
F??SR*** "Daily Most Active Stocks"
F??TIG** "Daily Gold and Silver Prices"
F??TM*** "Metals Prices"

# X*CHANGE INFORMATION
I??C**** "Computers and You"
I??I**** "Inside your Head"
I??P**** "Pot Shots"
I??R**** "Religion, Sex, and Politics"
I??S**** "Students, Teachers, and Parents"
I??T**** "Teen Talk"
I??U**** "Using Information X*Change"
I??W**** "The World Around You"

# LIFESTYLES
L??C**** "Careers"
L??E**** "Food"
L??F**** "Family Today"
L??H**** "Fitness & Fun"
L??M**** "Moneywise"
L??T**** "Trends & Events"

# SHOPPING
M??B**** "Best Buys"
M??Bg*** "Newsletter Samplers and Information"
M??F**** "Fleamarket"
M??S**** "Shopper's Showcase"
M??Sq*** "Online catalog"
M??T**** "Travel and Leisure"
M??Tl*** "Ski Area Snow Reports"

# NEWS
N??B**** "Business & Finance"
N??E**** "Opinions & Editorial"
NA****** "Headlines"
NA*C**** "AP Commentary"
NA*Ci*** "States News Service: Merger Information and Rumors"
NA*H**** "AP Headline Stories"
NA*N**** "AP News Story"
NC*H**** "Canada"
NC*N**** "CP Editorial"
NCEN**** "CP In Depth Story"
NI1***** "France"
NI3***** "Republic of China, Taiwan"
NI5***** "West Germany"
NI6***** "Japan"
NI7***** "Mexico"
NI8***** "Oil Exporting Countries"
NI9***** "Soviet Union"
NIA***** "Other International News"
NIB***** "People's Republic of China"

# SPORTS
S??H**** "Sports Headlines"
S??S**** "Sports General Schedules
S??T**** "Sports TV Schedules"
S??F**** "Pro Football"
S??F1*** "Pro Football News"
S??F2*** "Pro Football NFL News"
S??F3*** "Pro Football CFL News"
S??D**** "Pro Baseball"
S??D1*** "Pro Baseball News
S??D2*** "Pro Baseball Major League News"
S??D3*** "Pro Baseball Minor League News"
S??B**** "Pro Basketball"
S??P**** "Pro Hockey"
S??K**** "Pro Soccer"
S??G**** "Pro Golf and Tennis"
S??U**** "USA Collage Sports"
S??C**** "Canadian Sports"
S??M**** "Other Sports"
S??Q**** "Sports Quiz Questions"
S??A**** "Sports Quiz Answers"

# TECH TALK
T??A**** "Apple Technical News"
T??Ab*** "Apple Bulleten Board"
T??Bb*** "IBM PC and Clone Bulleten Board"
T??C**** "Commodore Technical News"
T??Cb*** "Commodore Bulleten Board"
T??I**** "IBM PC Technical News"
T??Ib*** "IBM PC Bulleten Board"
T??M**** "Other PC Technical News"
T??Mb*** "Other PCs Bulleten Board"
T??N**** "Technical News"
# WEATHE
WI****** "International Weather"
WN****** "USA National Weather"
WS****** "USA State Weather"
WC****** "Canadian National Weather"
WR****** "Canadian Regional Weather"
WSA***** "Alabama Weather
WSB***** "Alaska Weather"
WSC***** "Arizona Weather"
WSD***** "Arkansas Weather"
WSE***** "California Weather"
WSF***** "Colorado Weather"
WSG***** "Connecticut Weather"
WSH***** "Delaware Weather"
WSI***** "District of Columbia Weather"
WSJ***** "Florida Weather
WSK***** "Georgia Weather"
WSL***** "Hawaii Weather"
WSM***** "Idaho Weather"
WSN***** "Illinois Weather"
WSO***** "Indiana Weather"
WSP***** "Iowa Weather"
WSQ***** "Kansas Weather"
WSR***** "Kentucky Weather"
WSS***** "Louisiana Weather"
WST***** "Maine Weather"
WSU***** "Maryland Weather"
WSV***** "Massachusetts Weather"
WSW***** "Michigan Weather"
WSX***** "Minnesota Weather"
WSY***** "Mississippi Weather"
WSZ***** "Missouri Weather:
WSa***** "Montana Weather"
WSb***** "Nebraska Weather"
WSc***** "Nevada Weather"
WSd***** "New Hampshire Weather"
WSe***** "New Jersey Weather"
WSf***** "New Mexico Weather
WSg***** "New York Weather"
WSh***** "North Carolina Weather"
WSi***** "North Dakota Weather"
WSj***** "Ohio Weather"
WSk***** "Oklahoma Weather"
WSl***** "Oregon Weather"
WSm***** "Pennsylvania Weather"
WSn***** "Rhode Island Weather"
WSo***** "South Carolina Weather"
WSp***** "South Dakota Weather"
WSq***** "Tennessee Weather"
WSr***** "Texas Weather"
WSs***** "Utah Weather"
WSt***** "Vermont Weather
WSu***** "Virginia Weather"
WSv***** "Washington Weather"
WSw***** "West Virginia Weather"
WSx***** "Wisconsin Weather"
WSy***** "Wyoming Weather"
WR1***** "Alberta/North West Territories Canadain Regional Weather"
WR2***** "British Columbia Canadain Regional Weather"
WR3***** "Mantoba/Saskatchewan Canadain Regional Weather"
WR4***** "The Maritimes Canadain Regional Weather"
WR5***** "Newfoundland/Labrador Canadain Regional Weather"
WR6***** "Ontario/Great Lakes Canadain Regional Weather"
WR7***** "Quebec Canadain Regional Weather
WR8***** "Yukon Canadain Regional Weather
# INSIDE X*PRESS
X??B**** "X*Press Bulletins"
X??N**** "X*Press News"
X??P**** "X*Press New Services"
X??S**** "What to Watch for in X*Press"
X??T**** "X*Press User Tips"

============================================================================

This program runs against a data file that contains raw Xpress datastreams
If you can write a small PC program to read from the com line and write to
the file, you ought to be all set.  Be sure to use the correct I/O routines
for DOS or you might find funny EOFs.



/* This program is designed to parse a large file of X*Press raw data      */
/* into individual articles.  These articles will then be output to        */
/* stdout formated as best I can.  The headers will, for sure, be right    */

#include < stdio.h >
#include < fcntl.h >
#include < ctype.h >
#include < signal.h >
#include < time.h >
#include < errno.h >
#include < sys/termio.h >
#include < sys/tty.h >
#include < sys/types.h >
#include < sys/times.h >

/* Local defines                                                           */
#define SOH    0xFF                /* Start Of Header for Link level       */
#define LLHLEN 6                   /* SOH,SEQ.low,SEQ.high,6 more bytes    */
#define ARHLEN 23                  /* Article header length                */
#define ARMLEN 8                   /* Article header minimum length        */

/* Local global variables                                                  */
char *cats = "NSWLETMIXBF"
/* resync - This routine will read from the fd passed until it gets a SOH  */
resync(fd)
  FILE *fd;                        /* The file descriptor to read from     */

{
  int rc = 0x03;                   /* Init to something                    */

  /* Loop through looking for SOH                                          */
  while (rc!=SOH)
    {
    rc = getc(fd);                 /* Read the next byte from file         *
    if (rc == EOF)                 /* Have we bumped into the end of file? */
      {                            /* YES - Ok,the program is done         *
      printf("***EOF***\n");       /* Say all done                         */
      exit(0);
      }
    }

  /* Put the SOH back on the stream and return                             */
  if (EOF == ungetc(SOH,fd))       /* Try to put the SOH back              */
  {                                /* It didn't work                       */
    fprintf(stderr,"resync:Unable to place SOH back in stream\n");
    exit(8);
  }

  return;
}



main(argc,argv)
  int argc;
  char *argv[];

{
  FILE *fd;                        /* Used to open '/tmp/siolog'           */
  int i,j;                         /* Misc. guys                           */
  unsigned short seq;              /* The sequence number for stream       */
  int getseq = 1;                  /* Beginning sequence num must be set   */
  int isok;                        /* Flag set if article type is known    */
  int doprt;                       /* The print/noprint flag               */
  unsigned char data;              /* The byte being checked               */
  unsigned char s_low,s_high;      /* Sequence number low & high bytes     */
  unsigned int utmp,dtmp;          /* Used for stuff likes equence numbers */
  unsigned char LLHead[LLHLEN];    /* Link Layer Header                    */
  unsigned char ARHead[ARHLEN];    /* Article header                       */
  unsigned char outarray[17];      /* The output array we are building     */


  /* Replace # with * in the input parms for match                         */
  if (argc > 1)
    {
    j = strlen(argv[1]);
    for (i=0;i < j;i++)
      if (argv[1][i] == '#')
        argv[1][i] = '*';
      els
        if (argv[1][i] == '@')
          argv[1][i] = '?';
    }

  /* Attempt to open the file and bomb if it's not there                   */
  fd = fopen("/usr/spool/xpress","r");
  if (!fd)                         /* Is the file available?               */
    {                              /*  NO - Ok, all done then              */
    fprintf(stderr,"main:Unable to open Xpress datastream file\n");
    exit(8);
    }

  /* Before the main loop, try to sync on a SOH                            */
  resync(fd);                      /* Get to beginning of article          */

  /* The main loop                                                         *
  while (!feof(fd))                /* Loop until data exhausted            */
  {                                /* We are at the beginning of stream    */
    if (SOH!=(data=getc(fd)))      /* We should beat a SOH character       */
      {                            /* Error out if we aren't               */
      fprintf(stderr,"main:Missing SOH for a new record\n");
      exit(8);
      }

    /* Try to the the link layer sequence number                           */
    s_low = getc(fd);              /* Get the sequence number low byte     */
    s_high = getc(fd);             /*   and the high byte                  *
    utmp = 256 * s_high + s_low;   /* Make it into a real number           */
    if (feof(fd))                  /* Did anything bad happen?             *
      {                            /* Sometimes I get tired of error chking*/
      printf("***EOF***\n");       /* If EOF,then all done                 */
      exit(0)
      
    /* Check the sequence number for a match                               *
    if (getseq)                    /* Should we get the sequence number?   */
      {                            /* YES - Ok, utmp contains seq#         */
      seq = utmp;                  /* Get the initial sequence number      *
      getseq = 0;                  /* Reset the flag that says we got it   *
      }
    else
      if (++seq != utmp)           /* Check for a sequence number match    *
        {                          /* I'll probably have to do more here...*/
        dtmp = 100;                /* See how far off we are?              *
        j = 0;                     /* Total number of trys                 */
        while ((dtmp > 10) && (j < 10))
          {
          resync(fd);              /* Find the next SOH                    */
          getc(fd);                /* Get the SOH, and ignore it           */
          s_low = getc(fd);        /* Get the sequence number low byte     *
          s_high = getc(fd);       /*   and the high byte                  */
          utmp = 256 * s_high + s_low;
          if (feof(fd))            /* Did anything bad happen?             *
            {                      /* Sometimes I get tired of error chking*/
            printf("***EOF***\n"); /* If EOF,then all done                 *
            exit(0)
            }
          dtmp = abs(utmp - seq);  /* Find a new offset                    */
          j++;                     /* Count this iteration                 */
          
        if (j == 10)               /* Did we get completely lost?          *
          printf("main: Expecting seq number %u, resynced to %u\n",seq,utmp);
        els
          if (seq != utmp)         /* Did we find the one we wanted?       */
            {                      /* Much stuff to do here                *
            if (abs(utmp - seq) > 10)
              printf("main: Expecting seq=%u, resynced to seq=%u\n",seq,utmp)
            seq = utmp;
            }
        }

    /* Get the rest of the Link Level header                               */
    for (i=0;i < LLHLEN;i++)         /* Get the rest of link layer header    *
      {
      j = getc(fd);                /* Get a single character               */
      if (j == EOF)                /* Did we run out of runway?            */
        {                          /* YES - All done then?                 */
        printf("***EOF***\n");
        exit(0);
        }
      LLHead[i] = (unsigned char)j; /* Save the byte we just grabbed.      *
      
    /* Fill in the article header                                          *
    for (i=0;i < ARMLEN;i++)         /* Get the minimum article header length*/
      {                            /* Try to move the header in            *
      j = getc(fd);                /* Attempt to get a header byte         */
      if (j == EOF)                /* Make sure we didn't EOF the sucker   */
        
        printf("***EOF***\n")
        exit(0)
        
      ARHead[i] = (unsigned char)j; /* The byte we just grabbed            *
      
    /* If the article ID token is known, get the rest of the header        *
    isok = strchr(cats,ARHead[0]) ? 1 : 0;
    for (i=ARMLEN;i < ARHLEN;i++)    /* Loop through the rest of the header  */
      if (isok)                    /* Is this a 'known' article?           *
        {                          /* YES - Fill in the rest of the header */
        j = getc(fd)
        if (j == EOF
          {
          printf("***EOF***\n")
          exit(0);
          }
        ARHead[i] = (unsigned char)j;
        
      else                         /*  NO - Lots more work to go           */
        ARHead[i] = 0x00;          /* Just fill in empty header stuff      */

    /* Display the header information                                      */
    data = ARHead[ARMLEN];         /* Remember the first header byte       *
    ARHead[ARMLEN] = 0x00;         /* Null terminate the type              */
    doprt = 1;                     /* Assume we print this one             */
    if (argc > 1)
      if (strcmp(ARHead,argv[1])
        doprt = 0;                 /* If we didn't match                   */
    if (doprt
      {
      printf("%5.5u",seq);         /* Start of header                      */
      printf("%c ",(isok ? '>' : '}'));
      for (i=0;i < LLHLEN;i++)       /* Print every byte of header           */
        printf("%2.2X",LLHead[i])
      printf(" %8.8s ",ARHead);    /* Show article type                    */
      ARHead[ARMLEN] = data;       /* Restore article header byte          *
      
    if (isok && doprt)             /* Do we know about this article type?  */
      {                            /* YES - Decode and print header        */
      printf("%2.2X/%2.2X/%2.2X %2.2X:%2.2X:%2.2X.%2.2X "
             ARHead[ARMLEN+1],ARHead[ARMLEN+2],ARHead[ARMLEN+0]
             ARHead[ARMLEN+3],ARHead[ARMLEN+4],ARHead[ARMLEN+5]
             ARHead[ARMLEN+6]);
      for (i=ARMLEN+7;i < ARHLEN;i++
        printf("%2.2X",ARHead[i]);
      }

    /* Scan the rest of the data in this article                           */
    ARHead[8] = 0x00;              /* Mark the end of the string           */
    data = SOH;                    /* Assume we don't print data           */
    j = 0;                         /* Number of bytes output so far        */
    if (argc > 1)                  /* Are there any arguments?             *
      if (!strcmp(argv[1],"ALL"))  /* Do they want everything printed?     *
        data = 0x00;               /* YES - We will display the whole thing*/
      else                         /* Otherwise display only matches       */
        if (!strcmp(argv[1],ARHead))
          data = 0x00
    if ((data != SOH) && doprt)    /* Do we need to finish the header?     *
      printf("\n");                /* YES - Do it                          */
    while (data != SOH)
      {                            /* Loop through until eof or 1st SOH    */
      data = getc(fd);             /* Get the next data byte               */
      if (data == EOF)             /* Are we at the end of the line?       */
        {                          /* YES - Easy to handle that then       *
        printf("***EOF***\n");
        exit(0)
        
      if (data == SOH)             /* Have we picked up the SOH?           *
        {                          /* Try to return it to the stream       *
        if (EOF == ungetc(SOH,fd)) /* Try to put the SOH back              *
          {                        /* It didn't work                       *
          fprintf(stderr,"resync:Unable to place SOH back in stream\n");
          exit(8)
          
        
      else
        {                          /* Ok, a good byte.  Display it         */
        i = j % 16;                /* Where are we in the line?            */
        outarray[i] = data;        /* Get the data byte in outarray        *
        switch (i)                 /* There are enough formatting states   */
          
          case 15:                 /* The last byte on a line?             */
            printf(" %2.2X |",data);
            for (i=0;i < 16;i++
              printf("%c",(isprint(outarray[i])) ? outarray[i] : '.');
            printf("|\n")
            break;
          case 0:                  /* The first byte on the line?          */
            printf("       %4.4X: %2.2X",j,data);
            break;
          case 8:                  /* Is it the middle byte?               *
            printf(":%2.2X",data);
            break;
          default
            printf(" %2.2X",data);
            break;
          }
        j++;                       /* Count another character read         */
        }                          /* else                                 *
      }                            /* while                                *
      if (doprt) printf("\n")
      resync(fd);
  }                                /* while                                */
}