home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / saoimage / sao1_07.tar / rgntoken.c < prev    next >
C/C++ Source or Header  |  1991-01-08  |  7KB  |  245 lines

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /* Module:    rgntoken.c (Region Token)
  6.  * Purpose:    Parse tokens from a region descriptor file
  7.  * Subroutine:    check_parens()        returns: int
  8.  * Subroutine:    burst_line()        returns: int
  9.  * Subroutine:    next_token()        returns: *char
  10.  * Xlib calls:    none
  11.  * Copyright:    1989 Smithsonian Astrophysical Observatory
  12.  *        You may do anything you like with this file except remove
  13.  *        this copyright.  The Smithsonian Astrophysical Observatory
  14.  *        makes no representations about the suitability of this
  15.  *        software for any purpose.  It is provided "as is" without
  16.  *        express or implied warranty.
  17.  * Modified:    {0} Michael VanHilst    initial version        9 August 1989
  18.  *        {n} <who> -- <does what> -- <when>
  19.  */
  20.  
  21. #include <stdio.h>        /* stderr, NULL, etc. */
  22. #include <ctype.h>        /* toupper, isalpha, etc. */
  23. #include <X11/Xlib.h>        /* X window stuff */
  24. #include <X11/Xutil.h>        /* X window manager stuff */
  25. #include "hfiles/constant.h"    /* define codes */
  26. #include "hfiles/region.h"    /* region parsing record (reg_param) */
  27.  
  28. #define TYPECNT 9
  29. struct reg_types {
  30.   int code;
  31.   char name[16];
  32. };
  33. static struct reg_types types[TYPECNT] = {
  34.   COP_Annuli, "ANNULUS",
  35.   COP_Arrow, "ARROW",
  36.   COP_Box, "BOX",
  37.   COP_Circle, "CIRCLE",
  38.   COP_Ellipse, "ELLIPSE",
  39.   COP_PieSlice, "PIE",
  40.   COP_Point, "POINT",
  41.   COP_Polygon, "POLYGON",
  42.   COP_Text, "TEXT"
  43. };
  44.  
  45.  
  46. /*  Subroutine:    check_parens
  47.  *  Purpose:    Check nesting of parentheses.  Also, turn all token
  48.  *        separators into ascii spaces
  49.  *  Returns:    length of parsable line up to EOL or # (comment), else -1
  50.  */
  51. #ifdef ANSIC
  52. int check_parens ( char *orig, char *line )
  53. #else
  54. int check_parens ( orig, line )
  55.      char *orig;    /* original line */
  56.      char *line;    /* workspace with line copy */
  57. #endif
  58. {
  59.   int i;
  60.   int error = 0;
  61.   int paren = 0;
  62.   char space = ' ';
  63.   /* check nesting of parentheses and strip all parens, tabs, and commas */
  64.   for( i=0; (line[i] != '\0') && (line[i] != '#'); i++ ) {
  65.     if( line[i] == ')' ) {
  66.       paren--;
  67.       if( paren < 0 )
  68.     error++;
  69.       line[i] = space;
  70.     } else if( line[i] == '(' ) {
  71.       paren++;
  72.       line[i] = space;
  73.     } else if( line[i] == '\n' ) {
  74.       if( paren > 0 )
  75.     line[i] = space;
  76.       else
  77.     break;
  78.     } else if( (line[i] == ',') || (line[i] == '\t') ) {
  79.       line[i] = space;
  80.     } else if( ((line[i] == ';') || (line[i] == '&') ||
  81.         (line[i] == '|')) && (paren != 0) )
  82.       /* also check region separators */
  83.       error++;
  84.   }
  85.   /* make termination a null (removes comments and \n) */
  86.   line[i] = '\0';
  87.   if( error || (paren != 0) ) {
  88.     (void)fprintf(stderr,"WARNING: unbalanced parens:\n%s\n",orig);
  89.     return( -1 );
  90.   } else {
  91.     return( i );
  92.   }
  93. }
  94.  
  95. /*
  96.  * Subroutine:    burst_line
  97.  * Purpose:    Find each region descriptor and its identifying token
  98.  * Returns:    Number of regions found
  99.  */
  100. int burst_line ( orig, line, len, records )
  101.      char *orig;        /* original line */
  102.      char *line;        /* workspace with line copy */
  103.      int len;            /* length of meaningful part of line */
  104.      struct reg_param *records;    /* region parse note pad */
  105. {
  106.   int i;
  107.   int starting;        /* 1=fresh line, 2=fresh & must find region, 0=found */
  108.   int count, no_error;
  109.   int set_region_type();
  110.  
  111.   /* clear error flag, set count to 0, clear first record */
  112.   no_error = 1;
  113.   count = 0;
  114.   bzero((char *)&records[0], sizeof(struct reg_param));
  115.   /* initial state is looking for beginning of a region descriptor */
  116.   starting = 1;
  117.   for( i=0; (no_error) && (i<len); i++ ) {
  118.     /* if looking for beginning of a region description */
  119.     if( starting ) {
  120.       if( line[i] == '-' ) {
  121.     /* found an exclude indicator */
  122.     starting = 2;
  123.     records[count].exclude = 1;
  124.       } else if( line[i] == '!' ) {
  125.     /* found a 'not' indicator */
  126.     records[count].not = 1;
  127.     starting = 2;
  128.       } else if( line[i] != ' ' ) {
  129.     /* found first token */
  130.     starting = 0;
  131.     if( set_region_type(&records[count], &line[i]) == -1 ) {
  132.       (void)fprintf(stderr,"%s\n",orig);
  133.       return(-1);
  134.     }
  135.     count++;
  136.     /* clear next record */
  137.     if( count < REG_LIMIT )
  138.       bzero((char *)&records[count], sizeof(struct reg_param));
  139.     else
  140.       no_error = 0;
  141.       }
  142.     }
  143.     /* check for region separators to restart process */
  144.     if( (line[i] == '&') || (line[i] == '|') ) {
  145.       if( starting )
  146.     no_error = 0;
  147.       starting = 2;
  148.       records[count].connector = line[i];
  149.       /* terminate line of parameters for first record */
  150.       line[i] = '\0';
  151.     } else if( line[i] == ';' ) {
  152.       if( starting > 1 )
  153.     no_error = 0;
  154.       starting = 1;
  155.       /* terminate line of parameters for first record */
  156.       line[i] = '\0';
  157.     }
  158.   }
  159.   if( no_error && (starting <= 1) ) {
  160.     return( count );
  161.   } else {
  162.     (void)fprintf(stderr,"WARNING: improper region separation:\n%s\n",orig);
  163.     return( -1 );
  164.   }
  165. }
  166.  
  167. /*
  168.  * Subroutine:    next_token
  169.  * Purpose:    Advance the line position beyond the first cnt tokens
  170.  * Note:    All token separators are ascii spaces (see check_parens)
  171.  * Note:    line termination is a null ('\0') or new_line ('\n')
  172.  * Returns:    NULL if insufficient or no more tokens, else ptr to line
  173.  */
  174. char *next_token ( line, cnt )
  175.      char *line;
  176.      int cnt;
  177. {
  178.   int i, j;
  179.  
  180.   i = 0;
  181.   for( j = 0; j < cnt; j++ ) {
  182.     /* check for premature end */
  183.     if( (line[i] == '\0') || (line[i] == '\n') )
  184.       return( NULL );
  185.     /* advance to token */
  186.     while( line[i] == ' ' ) i++;
  187.     /* advance to end of token */
  188.     while( (line[i] != ' ') && (line[i] != '\0') && (line[i] != '\n') ) i++;
  189.   }
  190.   /* advance to next token */
  191.   while( line[i] == ' ' ) i++;
  192.   if( line[i] == '\0' )
  193.     /* report no more tokens */
  194.     return( NULL );
  195.   else
  196.     /* report location of next token */
  197.     return( &line[i] );
  198. }
  199.  
  200. /*
  201.  * Subroutine:    set_region_type
  202.  * Purpose:    Check the name for a unique match with a known region type
  203.  * Called by:    burst_line() in RegionParse.c
  204.  */
  205. int set_region_type ( record, line )
  206.      struct reg_param *record;
  207.      char *line;
  208. {
  209.   int i, j;
  210.   int match = 0;
  211.   for( i=0; line[i] != ' '; i++ ) {
  212.     /* convert all lower case characters to uppercase */
  213.     if( islower(line[i]) )
  214.       line[i] = toupper(line[i]);
  215.     /* check for line end overrun */
  216.     if( line[i] == '\0' ) {
  217.       (void)fprintf(stderr,"WARNING: missing region specification: %s\n",line);
  218.       return( -1 );
  219.     }
  220.   }
  221.   /* null terminate name token */
  222.   line[i] = '\0';
  223.   /* point record at parameter field */
  224.   record->line = &line[i+1];
  225.   for( i=0; i<TYPECNT; i++ ) {
  226.     /* do match on all input chars (for unique abbreviation check) */
  227.     for( j=0; (line[j] != '\0') && (line[j] == types[i].name[j]); j++ );
  228.     if( (j > 0) && (line[j] == '\0') ) {
  229.       record->line = &line[j+1];
  230.       record->type = types[i].code;
  231.       match++;
  232.     }
  233.   }
  234.   /* possible outcomes: match == 1, match > 1, match < 1 */
  235.   if( match == 1 ) {
  236.     return( 0 );
  237.   } else if( match > 1 ) {
  238.     (void)fprintf(stderr,
  239.           "WARNING: non-unique region abbreviation: %s\n",line);
  240.   } else {
  241.     (void)fprintf(stderr,"WARNING: unknown region type: %s\n",line);
  242.   }
  243.   return( -1 );
  244. }
  245.