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