root/test/manual/etags/y-src/parse.y

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. FUN1
  2. FUN2
  3. FUN0
  4. FUN2
  5. FUN1

     1 %{
     2 /*      Copyright (C) 1990, 1992-1993, 2016-2023 Free Software Foundation,
     3  *      Inc.
     4 
     5 This file is part of Oleo, the GNU Spreadsheet.
     6 
     7 Oleo is free software; you can redistribute it and/or modify
     8 it under the terms of the GNU General Public License as published by
     9 the Free Software Foundation; either version 2, or (at your option)
    10 any later version.
    11 
    12 Oleo is distributed in the hope that it will be useful,
    13 but WITHOUT ANY WARRANTY; without even the implied warranty of
    14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15 GNU General Public License for more details.
    16 
    17 You should have received a copy of the GNU General Public License
    18 along with Oleo; see the file COPYING.  If not, write to
    19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
    20 %}
    21 
    22 
    23 %right '?' ':'
    24 /* %left '|' */
    25 %left '&'
    26 %nonassoc '=' NE
    27 %nonassoc '<' LE '>' GE
    28 %left '+' '-'
    29 %left '*' '/' '%'
    30 %right '^'
    31 %left NEG '!'
    32 
    33 %token  L_CELL L_RANGE
    34 %token  L_VAR
    35 
    36 %token  L_CONST
    37 %token  L_FN0   L_FN1   L_FN2   L_FN3   L_FN4   L_FNN
    38 %token  L_FN1R  L_FN2R  L_FN3R  L_FN4R  L_FNNR
    39 
    40 %token  L_LE    L_NE    L_GE
    41 
    42 %{
    43 #include "funcdef.h"
    44 
    45 #include <ctype.h>
    46 
    47 #define obstack_chunk_alloc ck_malloc
    48 #define obstack_chunk_free free
    49 #include "obstack.h"
    50 #include "sysdef.h"
    51 
    52 #include "global.h"
    53 #include "errors.h"
    54 #include "node.h"
    55 #include "eval.h"
    56 #include "ref.h"
    57 
    58 int yylex ();
    59 #ifdef __STDC__
    60 void yyerror (char *);
    61 #else
    62 void yyerror ();
    63 #endif
    64 VOIDSTAR parse_hash;
    65 extern VOIDSTAR hash_find();
    66 
    67 /* This table contains a list of the infix single-char functions */
    68 unsigned char fnin[] = {
    69         SUM, DIFF, DIV, PROD, MOD, /* AND, OR, */ POW, EQUAL, IF, CONCAT, 0
    70 };
    71 
    72 #define YYSTYPE _y_y_s_t_y_p_e
    73 typedef struct node *YYSTYPE;
    74 YYSTYPE parse_return;
    75 #ifdef __STDC__
    76 YYSTYPE make_list (YYSTYPE, YYSTYPE);
    77 #else
    78 YYSTYPE make_list ();
    79 #endif
    80 
    81 char *instr;
    82 int parse_error = 0;
    83 extern struct obstack tmp_mem;
    84 
    85 %}
    86 %%
    87 line:   exp
    88                 { parse_return=$1; }
    89         | error {
    90                 if(!parse_error)
    91                         parse_error=PARSE_ERR;
    92                 parse_return=0; }
    93         ;
    94 
    95 exp:      L_CONST
    96         | cell
    97         | L_FN0 '(' ')' {
    98                 $$=$1; }
    99         | L_FN1 '(' exp ')' {
   100                 ($1)->n_x.v_subs[0]=$3;
   101                 ($1)->n_x.v_subs[1]=(struct node *)0;
   102                 $$=$1; }
   103         | L_FN2 '(' exp ',' exp ')' {
   104                 ($1)->n_x.v_subs[0]=$3;
   105                 ($1)->n_x.v_subs[1]=$5;
   106                 $$=$1; }
   107         | L_FN3 '(' exp ',' exp ',' exp ')' {
   108                 ($1)->n_x.v_subs[0]=make_list($3,$5);
   109                 ($1)->n_x.v_subs[1]=$7;
   110                 $$=$1;}
   111         | L_FN4 '(' exp ',' exp ',' exp ',' exp ')' {
   112                 ($1)->n_x.v_subs[0]=make_list($3,$5);
   113                 ($1)->n_x.v_subs[1]=make_list($7,$9);
   114                 $$=$1;}
   115         | L_FNN '(' exp_list ')' {
   116                 ($1)->n_x.v_subs[0]=(struct node *)0;
   117                 ($1)->n_x.v_subs[1]=$3;
   118                 $$=$1; }
   119         | L_FN1R '(' L_RANGE ')' {
   120                 $1->n_x.v_subs[0]=$3;
   121                 $$=$1; }
   122         | L_FN1R '(' L_VAR ')' {
   123                 $1->n_x.v_subs[0]=$3;
   124                 $$=$1; }
   125 
   126         | L_FN2R '(' L_RANGE ',' exp ')' {
   127                 $1->n_x.v_subs[0]=$3;
   128                 $1->n_x.v_subs[1]=$5;
   129                 $$=$1; }
   130         | L_FN2R '(' L_VAR ',' exp ')' {
   131                 $1->n_x.v_subs[0]=$3;
   132                 $1->n_x.v_subs[1]=$5;
   133                 $$=$1; }
   134 
   135         /* JF:  These should be FN2R, but I'm hacking this for SYLNK */
   136         | L_FN2R '(' L_RANGE ',' exp ',' exp ')' {
   137                 if($1->comp_value!=F_INDEX)
   138                         parse_error=PARSE_ERR;
   139                 $1->comp_value=F_INDEX2;
   140                 $1->n_x.v_subs[0]=make_list($3,$5);
   141                 $1->n_x.v_subs[1]=$7;
   142                 $$=$1; }
   143         | L_FN2R '(' L_VAR ',' exp ',' exp ')' {
   144                 if($1->comp_value!=F_INDEX)
   145                         parse_error=PARSE_ERR;
   146                 $1->comp_value=F_INDEX2;
   147                 $1->n_x.v_subs[0]=make_list($3,$5);
   148                 $1->n_x.v_subs[1]=$7;
   149                 $$=$1; }
   150 
   151         | L_FN3R '(' L_RANGE ',' exp ',' exp ')' {
   152                 ($1)->n_x.v_subs[0]=make_list($3,$5);
   153                 ($1)->n_x.v_subs[1]=$7;
   154                 $$=$1;}
   155         | L_FN3R '(' L_VAR ',' exp ',' exp ')' {
   156                 ($1)->n_x.v_subs[0]=make_list($3,$5);
   157                 ($1)->n_x.v_subs[1]=$7;
   158                 $$=$1;}
   159 
   160         | L_FNNR '(' range_exp_list ')' {
   161                 ($1)->n_x.v_subs[0]=(struct node *)0;
   162                 ($1)->n_x.v_subs[1]=$3;
   163                 $$=$1; }
   164         | exp '?' exp ':' exp {
   165                 $2->comp_value=IF;
   166                 $2->n_x.v_subs[0]=$4;
   167                 $2->n_x.v_subs[1]=$5;
   168                 $4->n_x.v_subs[0]=$1;
   169                 $4->n_x.v_subs[1]=$3;
   170                 $$=$2; }
   171         /* | exp '|' exp {
   172                 $2->n_x.v_subs[0]=$1;
   173                 $2->n_x.v_subs[1]=$3;
   174                 $$ = $2; } */
   175         | exp '&' exp {
   176                 $2->n_x.v_subs[0]=$1;
   177                 $2->n_x.v_subs[1]=$3;
   178                 $$ = $2; }
   179         | exp '<' exp {
   180                 $2->n_x.v_subs[0]=$1;
   181                 $2->n_x.v_subs[1]=$3;
   182                 $$ = $2; }
   183         | exp LE exp {
   184                 $2->n_x.v_subs[0]=$1;
   185                 $2->n_x.v_subs[1]=$3;
   186                 $$ = $2; }
   187         | exp '=' exp {
   188                 $2->n_x.v_subs[0]=$1;
   189                 $2->n_x.v_subs[1]=$3;
   190                 $$ = $2; }
   191         | exp NE exp {
   192                 $2->n_x.v_subs[0]=$1;
   193                 $2->n_x.v_subs[1]=$3;
   194                 $$ = $2; }
   195         | exp '>' exp {
   196                 $2->n_x.v_subs[0]=$1;
   197                 $2->n_x.v_subs[1]=$3;
   198                 $$ = $2; }
   199         | exp GE exp {
   200                 $2->n_x.v_subs[0]=$1;
   201                 $2->n_x.v_subs[1]=$3;
   202                 $$ = $2; }
   203         | exp '+' exp {
   204                 $2->n_x.v_subs[0]=$1;
   205                 $2->n_x.v_subs[1]=$3;
   206                 $$ = $2; }
   207         | exp '-' exp {
   208                 $2->n_x.v_subs[0]=$1;
   209                 $2->n_x.v_subs[1]=$3;
   210                 $$ = $2; }
   211         | exp '*' exp {
   212                 $2->n_x.v_subs[0]=$1;
   213                 $2->n_x.v_subs[1]=$3;
   214                 $$ = $2; }
   215         | exp '/' exp {
   216                 $2->n_x.v_subs[0]=$1;
   217                 $2->n_x.v_subs[1]=$3;
   218                 $$ = $2; }
   219         | exp '%' exp {
   220                 $2->n_x.v_subs[0]=$1;
   221                 $2->n_x.v_subs[1]=$3;
   222                 $$ = $2; }
   223         | exp '^' exp {
   224                 $2->n_x.v_subs[0]=$1;
   225                 $2->n_x.v_subs[1]=$3;
   226                 $$ = $2; }
   227         | '-' exp %prec NEG {
   228                 if($2->comp_value==CONST_FLT) {
   229                         $2->n_x.v_float= -($2->n_x.v_float);
   230                         /* free($1); */
   231                         $$=$2;
   232                 } else if($2->comp_value==CONST_INT) {
   233                         $2->n_x.v_int= -($2->n_x.v_int);
   234                         /* free($1); */
   235                         $$=$2;
   236                 } else {
   237                         $1->comp_value = NEGATE;
   238                         $1->n_x.v_subs[0]=$2;
   239                         $1->n_x.v_subs[1]=(struct node *)0;
   240                         $$ = $1;
   241                 } }
   242         | '!' exp {
   243                 $1->n_x.v_subs[0]=$2;
   244                 $1->n_x.v_subs[1]=(struct node *)0;
   245                 $$ = $1; }
   246         | '(' exp ')'
   247                 { $$ = $2; }
   248         | '(' exp error {
   249                 if(!parse_error)
   250                         parse_error=NO_CLOSE;
   251                 }
   252         /* | exp ')' error {
   253                 if(!parse_error)
   254                         parse_error=NO_OPEN;
   255                 } */
   256         | '(' error {
   257                 if(!parse_error)
   258                         parse_error=NO_CLOSE;
   259                 }
   260         ;
   261 
   262 
   263 exp_list: exp
   264                 { $$ = make_list($1, 0); }
   265         | exp_list ',' exp
   266                 { $$ = make_list($3, $1); }
   267         ;
   268 
   269 range_exp: L_RANGE
   270         | exp
   271         ;
   272 
   273 range_exp_list: range_exp
   274                 { $$=make_list($1, 0); }
   275         |   range_exp_list ',' range_exp
   276                 { $$=make_list($3,$1); }
   277         ;
   278 
   279 cell:   L_CELL
   280                 { $$=$1; }
   281         | L_VAR
   282         ;
   283 %%
   284 
   285 void
   286 yyerror FUN1(char *, s)
   287 {
   288         if(!parse_error)
   289                 parse_error=PARSE_ERR;
   290 }
   291 
   292 YYSTYPE
   293 make_list FUN2(YYSTYPE, car, YYSTYPE, cdr)
   294 {
   295         YYSTYPE ret;
   296 
   297         ret=(YYSTYPE)obstack_alloc(&tmp_mem,sizeof(*ret));
   298         ret->comp_value = 0;
   299         ret->n_x.v_subs[0]=car;
   300         ret->n_x.v_subs[1]=cdr;
   301         return ret;
   302 }
   303 
   304 #define ERROR -1
   305 
   306 extern struct node *yylval;
   307 
   308 #ifdef __STDC__
   309 unsigned char parse_cell_or_range (char **,struct rng *);
   310 #else
   311 unsigned char parse_cell_or_range ();
   312 #endif
   313 
   314 int
   315 yylex FUN0()
   316 {
   317         int ch;
   318         struct node *new;
   319         int isflt;
   320         char *begin;
   321         char *tmp_str;
   322         unsigned char byte_value;
   323         int n;
   324 
   325         /* unsigned char *ptr; */
   326         int nn;
   327         struct function *fp;
   328         int tmp_ch;
   329 
   330 #ifdef TEST
   331         if(!instr)
   332                 return ERROR;
   333 #endif
   334         while(isspace(*instr))
   335                 instr++;
   336         ch = *instr++;
   337         if(ch=='(' || ch==',' || ch==')')
   338                 return ch;
   339 
   340         new=(struct node *)obstack_alloc(&tmp_mem,sizeof(struct node));
   341         new->add_byte=0;
   342         new->sub_value=0;
   343         switch(ch) {
   344         case 0:
   345                 return 0;
   346 
   347         case '0': case '1': case '2': case '3': case '4': case '5': case '6':
   348         case '7': case '8': case '9': case '.':
   349                 isflt = (ch=='.');
   350 
   351                 begin=instr-1;
   352                 tmp_str=instr;
   353 
   354                 while(isdigit(*tmp_str) || (!isflt && *tmp_str=='.' && ++isflt))
   355                         tmp_str++;
   356                 if(*tmp_str=='e' || *tmp_str=='E') {
   357                         isflt=1;
   358                         tmp_str++;
   359                         if(*tmp_str=='-' || *tmp_str=='+')
   360                                 tmp_str++;
   361                         while(isdigit(*tmp_str))
   362                                 tmp_str++;
   363                 }
   364                 if(isflt) {
   365                         new->n_x.v_float=astof((char **)(&begin));
   366                         byte_value=CONST_FLT;
   367                 } else {
   368                         new->n_x.v_int=astol((char **)(&begin));
   369                         if(begin!=tmp_str) {
   370                                 begin=instr-1;
   371                                 new->n_x.v_float=astof((char **)(&begin));
   372                                 byte_value=CONST_FLT;
   373                         } else
   374                                 byte_value=CONST_INT;
   375                 }
   376                 ch=L_CONST;
   377                 instr=begin;
   378                 break;
   379 
   380         case '"':
   381                 begin=instr;
   382                 while(*instr && *instr!='"') {
   383                         if(*instr=='\\' && instr[1])
   384                                 instr++;
   385                         instr++;
   386                 }
   387                 if(!*instr) {
   388                         parse_error=NO_QUOTE;
   389                         return ERROR;
   390                 }
   391                 tmp_str=new->n_x.v_string=(char *)ck_malloc(1+instr-begin);
   392                 while(begin!=instr) {
   393                         unsigned char n;
   394 
   395                         if(*begin=='\\') {
   396                                 begin++;
   397                                 if(begin[0]>='0' && begin[0]<='7') {
   398                                         if(begin[1]>='0' && begin[1]<='7') {
   399                                                 if(begin[2]>='0' && begin[2]<='7') {
   400                                                         n=(begin[2]-'0') + (010 * (begin[1]-'0')) + ( 0100 * (begin[0]-'0'));
   401                                                         begin+=3;
   402                                                 } else {
   403                                                         n=(begin[1]-'0') + (010 * (begin[0]-'0'));
   404                                                         begin+=2;
   405                                                 }
   406                                         } else {
   407                                                 n=begin[0]-'0';
   408                                                 begin++;
   409                                         }
   410                                 } else
   411                                         n= *begin++;
   412                                 *tmp_str++= n;
   413                         } else
   414                                 *tmp_str++= *begin++;
   415                 }
   416                 *tmp_str='\0';
   417                 instr++;
   418                 byte_value=CONST_STR;
   419                 ch=L_CONST;
   420                 break;
   421 
   422         case '+':       case '-':
   423 
   424         case '*':       case '/':       case '%':       case '&':
   425         /* case '|': */ case '^':       case '=':
   426 
   427         case '?':
   428         {
   429                 unsigned char *ptr;
   430 
   431                 for(ptr= fnin;*ptr;ptr++)
   432                         if(the_funs[*ptr].fn_str[0]==ch)
   433                                 break;
   434 #ifdef TEST
   435                 if(!*ptr)
   436                         panic("Can't find fnin[] entry for '%c'",ch);
   437 #endif
   438                 byte_value= *ptr;
   439         }
   440                 break;
   441 
   442         case ':':
   443                 byte_value=IF;
   444                 break;
   445 
   446         case '!':
   447         case '<':
   448         case '>':
   449                 if(*instr!='=') {
   450                         byte_value = (ch=='<') ? LESS : (ch=='>') ? GREATER : NOT;
   451                         break;
   452                 }
   453                 instr++;
   454                 byte_value = (ch=='<') ? LESSEQ : (ch=='>') ? GREATEQ : NOTEQUAL;
   455                 ch = (ch=='<') ? LE : (ch=='>') ? GE : NE;
   456                 break;
   457 
   458         case '\'':
   459         case ';':
   460         case '[':
   461         case '\\':
   462         case ']':
   463         case '`':
   464         case '{':
   465         case '}':
   466         case '~':
   467         bad_chr:
   468                 parse_error=BAD_CHAR;
   469                 return ERROR;
   470 
   471         case '#':
   472                 begin=instr-1;
   473                 while(*instr && (isalnum(*instr) || *instr=='_'))
   474                         instr++;
   475                 ch= *instr;
   476                 *instr=0;
   477                 if(!stricmp(begin,tname))
   478                         byte_value=F_TRUE;
   479                 else if(!stricmp(begin,fname))
   480                         byte_value=F_FALSE;
   481                 else if(!stricmp(begin,iname) && (begin[4]==0 || !stricmp(begin+4,"inity")))
   482                         byte_value=CONST_INF;
   483                 else if(!stricmp(begin,mname) ||
   484                         !stricmp(begin,"#ninf"))
   485                         byte_value=CONST_NINF;
   486                 else if(!stricmp(begin,nname) ||
   487                         !stricmp(begin,"#nan"))
   488                         byte_value=CONST_NAN;
   489                 else {
   490                         for(n=1;n<=ERR_MAX;n++)
   491                                 if(!stricmp(begin,ename[n]))
   492                                         break;
   493                         if(n>ERR_MAX)
   494                                 n=BAD_CHAR;
   495                         new->n_x.v_int=n;
   496                         byte_value=CONST_ERR;
   497                 }
   498                 *instr=ch;
   499                 ch=L_CONST;
   500                 break;
   501 
   502         default:
   503                 if(!a0 && (ch=='@' || ch=='$'))
   504                    goto bad_chr;
   505 
   506                 if(a0 && ch=='@') {
   507                         begin=instr;
   508                         while(*instr && (isalpha(*instr) || isdigit(*instr) || *instr=='_'))
   509                                 instr++;
   510                         n=instr-begin;
   511                 } else {
   512                         begin=instr-1;
   513                         byte_value=parse_cell_or_range(&begin,&(new->n_x.v_rng));
   514                         if(byte_value) {
   515                                 if((byte_value& ~0x3)==R_CELL)
   516                                         ch=L_CELL;
   517                                 else
   518                                         ch=L_RANGE;
   519                                 instr=begin;
   520                                 break;
   521                         }
   522 
   523                         while(*instr && (isalpha(*instr) || isdigit(*instr) || *instr=='_'))
   524                                 instr++;
   525 
   526                         n=instr-begin;
   527                         while(isspace(*instr))
   528                                 instr++;
   529 
   530                         if(*instr!='(') {
   531                                 ch=L_VAR;
   532                                 byte_value=VAR;
   533                                 new->n_x.v_var=find_or_make_var(begin,n);
   534                                 break;
   535                         }
   536                 }
   537                 tmp_ch=begin[n];
   538                 begin[n]='\0';
   539                 fp=hash_find(parse_hash,begin);
   540                 begin[n]=tmp_ch;
   541                 byte_value= ERROR;
   542                 if(!fp) {
   543                         parse_error=BAD_FUNC;
   544                         return ERROR;
   545                 }
   546 
   547                 if(fp>=the_funs && fp<=&the_funs[USR1])
   548                         byte_value=fp-the_funs;
   549                 else {
   550                         for(nn=0;nn<n_usr_funs;nn++) {
   551                                 if(fp>=&usr_funs[nn][0] && fp<=&usr_funs[nn][usr_n_funs[nn]]) {
   552                                         byte_value=USR1+nn;
   553                                         new->sub_value=fp-&usr_funs[nn][0];
   554                                         break;
   555                                 }
   556                         }
   557 #ifdef TEST
   558                         if(nn==n_usr_funs) {
   559                                 io_error_msg("Couldn't turn fp into a ##");
   560                                 parse_error=BAD_FUNC;
   561                                 return ERROR;
   562                         }
   563 #endif
   564                 }
   565 
   566                 if(fp->fn_argn&X_J)
   567                         ch= byte_value==F_IF ? L_FN3 : L_FN2;
   568                 else if(fp->fn_argt[0]=='R' || fp->fn_argt[0]=='E')
   569                         ch=L_FN1R-1+fp->fn_argn-X_A0;
   570                 else
   571                         ch=L_FN0 + fp->fn_argn-X_A0;
   572 
   573                 break;
   574         }
   575         /* new->node_type=ch; */
   576         new->comp_value=byte_value;
   577         yylval=new;
   578         return ch;
   579 }
   580 
   581 /* Return value is
   582         0 if it doesn't look like a cell or a range,
   583         R_CELL if it is a cell (ptr now points past the characters, lr and lc hold the row and col of the cell)
   584         RANGE if it is a range (ptr points past the chars)
   585  */
   586 unsigned char
   587 parse_cell_or_range FUN2(char **,ptr, struct rng *,retp)
   588 {
   589         if(a0) {
   590                 unsigned tmpc,tmpr;
   591                 char *p;
   592                 int abz = ROWREL|COLREL;
   593 
   594                 p= *ptr;
   595                 tmpc=0;
   596                 if(*p=='$') {
   597                         abz-=COLREL;
   598                         p++;
   599                 }
   600                 if(!isalpha(*p))
   601                         return 0;
   602                 tmpc=str_to_col(&p);
   603                 if(tmpc<MIN_COL || tmpc>MAX_COL)
   604                         return 0;
   605                 if(*p=='$') {
   606                         abz-=ROWREL;
   607                         p++;
   608                 }
   609                 if(!isdigit(*p))
   610                         return 0;
   611                 for(tmpr=0;isdigit(*p);p++)
   612                         tmpr=tmpr*10 + *p - '0';
   613 
   614                 if(tmpr<MIN_ROW || tmpr>MAX_ROW)
   615                         return 0;
   616 
   617                 if(*p==':' || *p=='.') {
   618                         unsigned tmpc1,tmpr1;
   619 
   620                         abz = ((abz&COLREL) ? LCREL : 0)|((abz&ROWREL) ? LRREL : 0)|HRREL|HCREL;
   621                         p++;
   622                         if(*p=='$') {
   623                                 abz-=HCREL;
   624                                 p++;
   625                         }
   626                         if(!isalpha(*p))
   627                                 return 0;
   628                         tmpc1=str_to_col(&p);
   629                         if(tmpc1<MIN_COL || tmpc1>MAX_COL)
   630                                 return 0;
   631                         if(*p=='$') {
   632                                 abz-=HRREL;
   633                                 p++;
   634                         }
   635                         if(!isdigit(*p))
   636                                 return 0;
   637                         for(tmpr1=0;isdigit(*p);p++)
   638                                 tmpr1=tmpr1*10 + *p - '0';
   639                         if(tmpr1<MIN_ROW || tmpr1>MAX_ROW)
   640                                 return 0;
   641 
   642                         if(tmpr<tmpr1) {
   643                                 retp->lr=tmpr;
   644                                 retp->hr=tmpr1;
   645                         } else {
   646                                 retp->lr=tmpr1;
   647                                 retp->hr=tmpr;
   648                         }
   649                         if(tmpc<tmpc1) {
   650                                 retp->lc=tmpc;
   651                                 retp->hc=tmpc1;
   652                         } else {
   653                                 retp->lc=tmpc1;
   654                                 retp->hc=tmpc;
   655                         }
   656                         *ptr= p;
   657                         return RANGE | abz;
   658                 }
   659                 retp->lr = retp->hr = tmpr;
   660                 retp->lc = retp->hc = tmpc;
   661                 *ptr=p;
   662                 return R_CELL | abz;
   663         } else {
   664                 char *p;
   665                 unsigned char retr;
   666                 unsigned char retc;
   667                 int ended;
   668                 long num;
   669                 CELLREF tmp;
   670 
   671 #define CK_ABS_R(x)     if((x)<MIN_ROW || (x)>MAX_ROW)  \
   672                                 return 0;               \
   673                         else
   674 
   675 #define CK_REL_R(x)     if(   ((x)>0 && MAX_ROW-(x)<cur_row)    \
   676                            || ((x)<0 && MIN_ROW-(x)>cur_row))   \
   677                                 return 0;                       \
   678                         else
   679 
   680 #define CK_ABS_C(x)     if((x)<MIN_COL || (x)>MAX_COL)  \
   681                                 return 0;               \
   682                         else
   683 
   684 #define CK_REL_C(x)     if(   ((x)>0 && MAX_COL-(x)<cur_col)    \
   685                            || ((x)<0 && MIN_COL-(x)>cur_col))   \
   686                                 return 0;                       \
   687                         else
   688 
   689 #define MAYBEREL(p) (*(p)=='[' && (isdigit((p)[1]) || (((p)[1]=='+' || (p)[1]=='-') && isdigit((p)[2]))))
   690 
   691                 p= *ptr;
   692                 retr=0;
   693                 retc=0;
   694                 ended=0;
   695                 while(ended==0) {
   696                         switch(*p) {
   697                         case 'r':
   698                         case 'R':
   699                                 if(retr) {
   700                                         ended++;
   701                                         break;
   702                                 }
   703                                 p++;
   704                                 retr=R_CELL;
   705                                 if(isdigit(*p)) {
   706                                         num=astol(&p);
   707                                         CK_ABS_R(num);
   708                                         retp->lr= retp->hr=num;
   709                                 } else if(MAYBEREL(p)) {
   710                                         p++;
   711                                         num=astol(&p);
   712                                         CK_REL_R(num);
   713                                         retp->lr= retp->hr=num+cur_row;
   714                                         retr|=ROWREL;
   715                                         if(*p==':') {
   716                                                 retr=RANGE|LRREL|HRREL;
   717                                                 p++;
   718                                                 num=astol(&p);
   719                                                 CK_REL_R(num);
   720                                                 retp->hr=num+cur_row;
   721                                         }
   722                                         if(*p++!=']')
   723                                                 return 0;
   724                                 } else if(retc || *p=='c' || *p=='C') {
   725                                         retr|=ROWREL;
   726                                         retp->lr= retp->hr=cur_row;
   727                                 } else
   728                                         return 0;
   729                                 if(*p==':' && retr!=(RANGE|LRREL|HRREL)) {
   730                                         retr= (retr&ROWREL) ? RANGE|LRREL : RANGE;
   731                                         p++;
   732                                         if(isdigit(*p)) {
   733                                                 num=astol(&p);
   734                                                 CK_ABS_R(num);
   735                                                 retp->hr=num;
   736                                         } else if(MAYBEREL(p)) {
   737                                                 p++;
   738                                                 num=astol(&p);
   739                                                 CK_REL_R(num);
   740                                                 retp->hr=num+cur_row;
   741                                                 retr|=HRREL;
   742                                                 if(*p++!=']')
   743                                                         return 0;
   744                                         } else
   745                                                 return 0;
   746                                 }
   747 
   748                                 if(retc)
   749                                         ended++;
   750                                 break;
   751 
   752                         case 'c':
   753                         case 'C':
   754                                 if(retc) {
   755                                         ended++;
   756                                         break;
   757                                 }
   758                                 p++;
   759                                 retc=R_CELL;
   760                                 if(isdigit(*p)) {
   761                                         num=astol(&p);
   762                                         CK_ABS_C(num);
   763                                         retp->lc= retp->hc=num;
   764                                 } else if(MAYBEREL(p)) {
   765                                         p++;
   766                                         num=astol(&p);
   767                                         CK_REL_C(num);
   768                                         retp->lc= retp->hc=num+cur_col;
   769                                         retc|=COLREL;
   770                                         if(*p==':') {
   771                                                 retc=RANGE|LCREL|HCREL;
   772                                                 p++;
   773                                                 num=astol(&p);
   774                                                 CK_REL_C(num);
   775                                                 retp->hc=num+cur_col;
   776                                         }
   777                                         if(*p++!=']')
   778                                                 return 0;
   779                                 } else if(retr || *p=='r' || *p=='R') {
   780                                         retc|=COLREL;
   781                                         retp->lc= retp->hc=cur_col;
   782                                 } else
   783                                         return 0;
   784                                 if(*p==':' && retc!=(RANGE|LCREL|HCREL)) {
   785                                         retc= (retc&COLREL) ? RANGE|LCREL : RANGE;
   786                                         p++;
   787                                         if(isdigit(*p)) {
   788                                                 num=astol(&p);
   789                                                 CK_ABS_C(num);
   790                                                 retp->hc=num;
   791                                         } else if(MAYBEREL(p)) {
   792                                                 p++;
   793                                                 num=astol(&p);
   794                                                 CK_REL_C(num);
   795                                                 retp->hc=num+cur_col;
   796                                                 retc|=HCREL;
   797                                                 if(*p++!=']')
   798                                                         return 0;
   799                                         } else
   800                                                 return 0;
   801                                 }
   802 
   803                                 if(retr)
   804                                         ended++;
   805                                 break;
   806                         default:
   807                                 if(retr) {
   808                                         *ptr=p;
   809                                         retp->lc=MIN_COL;
   810                                         retp->hc=MAX_COL;
   811                                         if((retr|ROWREL)==(R_CELL|ROWREL))
   812                                                 return (retr&ROWREL) ? (RANGE|LRREL|HRREL) : RANGE;
   813                                         else
   814                                                 return retr;
   815                                 } else if(retc) {
   816                                         *ptr=p;
   817                                         retp->lr=MIN_ROW;
   818                                         retp->hr=MAX_COL;
   819                                         if((retc|COLREL)==(R_CELL|COLREL))
   820                                                 return (retc&COLREL) ? (RANGE|LCREL|HCREL) : RANGE;
   821                                         else
   822                                                 return retc;
   823                                 }
   824                                 return 0;
   825                         }
   826                 }
   827                 if(!retr || !retc)
   828                         return 0;
   829                 *ptr=p;
   830                 if(retp->lr>retp->hr)
   831                         tmp=retp->lr,retp->lr=retp->hr,retp->hr=tmp;
   832                 if(retp->lc>retp->hc)
   833                         tmp=retp->lc,retp->lc=retp->hc,retp->hc=tmp;
   834 
   835                 if((retr|ROWREL)==(R_CELL|ROWREL)) {
   836                         if((retc|COLREL)==(R_CELL|COLREL))
   837                                 return retr|retc;
   838                         return (retr&ROWREL) ? (retc|LRREL|HRREL) : retc;
   839                 }
   840                 if((retc|COLREL)==(R_CELL|COLREL))
   841                         return (retc&COLREL) ? (retr|LCREL|HCREL) : retr;
   842                 return retr|retc;
   843         }
   844 }
   845 
   846 int
   847 str_to_col FUN1(char **,str)
   848 {
   849         int ret;
   850         char c,cc,ccc;
   851 #if MAX_COL>702
   852         char cccc;
   853 #endif
   854 
   855         ret=0;
   856         c=str[0][0];
   857         if(!isalpha((cc=str[0][1]))) {
   858                 (*str)++;
   859                 return MIN_COL + (isupper(c) ? c-'A' : c-'a');
   860         }
   861         if(!isalpha((ccc=str[0][2]))) {
   862                 (*str)+=2;
   863                 return MIN_COL+26 + (isupper(c) ? c-'A' : c-'a')*26 + (isupper(cc) ? cc-'A' : cc-'a');
   864         }
   865 #if MAX_COL>702
   866         if(!isalpha((cccc=str[0][3]))) {
   867                 (*str)+=3;
   868                 return MIN_COL+702 + (isupper(c) ? c-'A' : c-'a')*26*26 + (isupper(cc) ? cc-'A' : cc-'a')*26 + (isupper(ccc) ? ccc-'A' : ccc-'a');
   869         }
   870         if(!isalpha(str[0][4])) {
   871                 (*str)+=4;
   872                 return MIN_COL+18278 + (isupper(c) ? c-'A' : c-'a')*26*26*26 + (isupper(cc) ? cc-'A' : cc-'a')*26*26 + (isupper(ccc) ? ccc-'A' : ccc-'a')*26 + (isupper(cccc) ? cccc-'A' : cccc-'a');
   873         }
   874 #endif
   875         return 0;
   876 }

/* [<][>][^][v][top][bottom][index][help] */