VPDF compiles and links but exits early after start.
[AROS-Contrib.git] / rexx / src / nextsymb.c
blobe8a546fbfe5aa4c9772124101b8939716a82d757
1 /*
2 * $Header$
3 * $Log$
4 * Revision 1.1 2001/04/04 05:43:39 wang
5 * First commit: compiles on Linux, Amiga, Windows, Windows CE, generic gcc
7 * Revision 1.2 1999/11/26 13:13:47 bnv
8 * Changed: Some spaces to tabs.
10 * Revision 1.1 1998/07/02 17:34:50 bnv
11 * Initial revision
15 #define __NEXTSYMB_C__
17 #include <bmem.h>
19 #include <lerror.h>
20 #include <lstring.h>
21 #include <nextsymb.h>
23 static PLstr ProgStr; /* pointer that holds the program string*/
24 static int InitNextch; /* NextChar initialised? */
25 static bool NextBlank; /* Next char is blank */
26 static bool commentfound; /* if comment found in nextchar */
28 bool _in_nextsymbol; /* Used only to track error inside nextsymb*/
30 /* ------------------- function prototypes ----------------------- */
31 static void literal(void);
32 static void identifier(int isnumber);
34 /* --------------------------------------------------------------- */
35 /* return the next character and advance the input stream by one */
36 /* also it searches for comments */
37 /* --------------------------------------------------------------- */
38 static void
39 nextchar(int instring)
41 int level=0;
43 commentfound = FALSE;
45 getnextchar:
46 if (instring!=-1) {
47 if (*symbolptr=='\n') symboline++;
48 symbolptr++;
49 } else
50 instring=FALSE;
52 if (!instring && *symbolptr=='/' && *(symbolptr+1)=='*') {
53 /* search for comment */
54 commentfound = TRUE;
55 symbolptr += 2;
56 level++;
57 for (;;) {
58 while ((*symbolptr!='*') && (*symbolptr!='/')) {
59 if (*symbolptr=='\n') symboline++;
60 symbolptr++;
61 if (*symbolptr == 0)
62 Lerror(ERR_UNMATCHED_QUOTE,1);
64 symbolptr++;
65 if ((*(symbolptr-1)=='/') && (*symbolptr=='*')) {
66 level++;
67 symbolptr++;
68 } else
69 if ((*(symbolptr-1)=='*') && (*symbolptr=='/')) {
70 --level;
71 if (!level) goto getnextchar;
72 symbolptr++;
76 } /* nextchar */
78 /* --------------- InitNextsymbol -------------------- */
79 void
80 InitNextsymbol( PLstr str )
82 Lcat(str,"\n"); /* We must have a least one new line at the end */
84 ProgStr = str;
85 LASCIIZ(*ProgStr); /* Put a zero at the end */
86 symbol = semicolon_sy;
87 symbolptr = LSTR(*ProgStr);
88 symboline = 1;
90 /* Skip first line, '#!/bin/rexx' */
91 if (symbolptr[0]=='#' && symbolptr[1]=='!') {
92 while (*symbolptr!='\n') symbolptr++;
93 symboline++;
96 InitNextch = FALSE;
97 NextBlank = FALSE;
98 symbolstat = normal_st;
99 } /* InitNextsymbol */
101 /* --------------------------------------------------------------- */
102 /* P A R S E next B A S I C S Y M B O L */
103 /* Return the next basic symbol and advance the input stream */
104 /* --------------------------------------------------------------- */
105 void
106 nextsymbol(void)
108 #define NEXTCHAR {*(ns++)=*symbolptr; LLEN(symbolstr)++; nextchar(FALSE);}
110 char *Psymbolptr, *ns;
111 int _lineno;
113 if (!InitNextch) {
114 /* call nextchar to search for comments */
115 nextchar(-1); /* initialise */
116 commentfound = FALSE;
117 InitNextch = TRUE;
119 /* make the type always to be LSTRING */
120 LTYPE(symbolstr) = LSTRING_TY;
121 LLEN(symbolstr) = 0;
123 _in_nextsymbol = TRUE;
124 symbolPrevBlank = NextBlank;
125 NextBlank = FALSE;
126 _NEXTSYMBOL:
128 while (*symbolptr==' ' || *symbolptr=='\t')
129 nextchar(FALSE);
131 ns = LSTR(symbolstr);
133 symbolprevptr = symbolptr;
135 switch (l2u[(byte)*symbolptr]) {
136 case '0': case '1': case '2':
137 case '3': case '4': case '5':
138 case '6': case '7': case '8':
139 case '9':
140 symbol = literal_sy;
141 identifier(TRUE);
142 break;
144 case 'A': case 'B': case 'C':
145 case 'D': case 'E': case 'F':
146 case 'G': case 'H': case 'I':
147 case 'J': case 'K': case 'L':
148 case 'M': case 'N': case 'O':
149 case 'P': case 'Q': case 'R':
150 case 'S': case 'T': case 'U':
151 case 'V': case 'W': case 'X':
152 case 'Y': case 'Z':
154 case '@':
155 case '#':
156 case '$':
157 case '_':
158 case '?':
159 case '!':
160 symbol = ident_sy;
161 identifier(FALSE);
162 break;
164 case '/':
165 NEXTCHAR;
166 if (*symbolptr=='/') {
167 symbol = mod_sy;
168 NEXTCHAR;
169 } else
170 if (*symbolptr=='=') {
171 NEXTCHAR;
172 if (*symbolptr=='=') {
173 symbol = dne_sy;
174 NEXTCHAR;
175 } else
176 symbol = ne_sy;
177 } else
178 symbol = div_sy;
179 break;
181 case '-':
182 symbol = minus_sy;
183 NEXTCHAR;
184 break;
186 case '*':
187 NEXTCHAR;
188 if (*symbolptr=='/')
189 Lerror(ERR_INVALID_EXPRESSION,0);
190 if (*symbolptr=='*') {
191 symbol = power_sy;
192 NEXTCHAR;
193 } else
194 symbol = times_sy;
195 break;
197 case '~':
198 case '^':
199 case '\\':
200 NEXTCHAR;
201 switch (*symbolptr) {
202 case '=':
203 NEXTCHAR;
204 if (*symbolptr=='=') {
205 symbol = dne_sy;
206 NEXTCHAR;
207 } else
208 symbol = ne_sy;
209 break;
211 case '>':
212 NEXTCHAR;
213 if (*symbolptr=='>') {
214 symbol = dle_sy;
215 NEXTCHAR;
216 } else
217 symbol = le_sy;
218 break;
220 case '<':
221 NEXTCHAR;
222 if (*symbolptr=='<') {
223 symbol = dge_sy;
224 NEXTCHAR;
225 } else
226 symbol = ge_sy;
227 break;
229 default:
230 symbol = not_sy;
232 break;
234 case '%':
235 symbol = intdiv_sy;
236 NEXTCHAR;
237 break;
239 case '(':
240 symbol = le_parent;
241 NEXTCHAR;
242 break;
244 case ')':
245 symbol = ri_parent;
246 NEXTCHAR;
247 break;
249 #ifndef MSDOS
250 /* Only for UNIX where \r is not recognised as \n */
251 case '\r':
252 NEXTCHAR;
253 #endif
254 case '\n':
255 case ';':
256 symbol = semicolon_sy;
257 NEXTCHAR;
258 break;
260 case ',':
261 NEXTCHAR;
262 Psymbolptr = symbolptr;
263 _lineno = symboline;
264 nextsymbol();
265 NextBlank = FALSE;
266 symbolPrevBlank = TRUE;
267 if (symbol==semicolon_sy &&
268 _lineno!=symboline) goto _NEXTSYMBOL;
269 symbolptr = Psymbolptr;
270 symbol = comma_sy;
271 NextBlank = FALSE;
272 symbolPrevBlank = TRUE;
273 break;
275 case '.':
276 Psymbolptr = symbolptr+1;
277 if ( *Psymbolptr !=' ' &&
278 *Psymbolptr !=',' &&
279 *Psymbolptr !='\n' &&
280 *Psymbolptr !='\r' &&
281 *Psymbolptr !='\t' &&
282 *Psymbolptr !=';' ) {
283 symbol = literal_sy;
284 identifier(TRUE);
285 } else {
286 symbol = dot_sy;
287 NEXTCHAR;
289 break;
291 case '|':
292 NEXTCHAR;
293 if (*symbolptr=='|') {
294 symbol = concat_sy;
295 NEXTCHAR;
296 } else
297 symbol = or_sy;
298 break;
300 case '&':
301 NEXTCHAR;
302 if (*symbolptr=='&') {
303 symbol = xor_sy;
304 NEXTCHAR;
305 } else
306 symbol = and_sy;
307 break;
309 case '+':
310 symbol = plus_sy;
311 NEXTCHAR;
312 break;
314 case '=':
315 NEXTCHAR;
316 switch (*symbolptr) {
317 case '=':
318 NEXTCHAR;
319 symbol = deq_sy;
320 break;
322 case '>':
323 NEXTCHAR;
324 if (*symbolptr=='>') {
325 NEXTCHAR;
326 symbol = dge_sy;
327 } else
328 symbol = ge_sy;
329 break;
331 case '<':
332 NEXTCHAR;
333 if (*symbolptr=='<') {
334 NEXTCHAR;
335 symbol = dle_sy;
336 } else
337 symbol = le_sy;
338 break;
340 default:
341 symbol = eq_sy;
343 break;
345 case '<':
346 NEXTCHAR;
347 switch (*symbolptr) {
348 case '<':
349 NEXTCHAR;
350 if (*symbolptr=='=') {
351 symbol = dle_sy;
352 NEXTCHAR;
353 } else
354 symbol = dlt_sy;
355 break;
357 case '=':
358 symbol = le_sy;
359 NEXTCHAR;
360 break;
362 case '>':
363 symbol = ne_sy;
364 NEXTCHAR;
365 break;
367 default:
368 symbol = lt_sy;
370 break;
372 case '>':
373 NEXTCHAR;
374 switch (*symbolptr) {
375 case '>':
376 NEXTCHAR;
377 if (*symbolptr=='=') {
378 symbol = dge_sy;
379 NEXTCHAR;
380 } else
381 symbol = dgt_sy;
382 break;
384 case '=':
385 symbol = ge_sy;
386 NEXTCHAR;
387 break;
389 case '<':
390 symbol = ne_sy;
391 NEXTCHAR;
392 break;
394 default:
395 symbol = gt_sy;
397 break;
399 case '\'':
400 case '\"':
401 literal();
402 break;
404 case ':':
405 Lerror(ERR_SYMBOL_EXPECTED,0);
406 break;
408 case 0:
409 _in_nextsymbol = FALSE;
410 if ((symbolstat == in_do_st) ||
411 (symbolstat == in_if_st))
412 Lerror(ERR_INCOMPLETE_STRUCT,0);
413 else
414 if (symbolstat == in_if_init_st)
415 Lerror(ERR_THEN_EXPECTED,0);
416 else
417 if (symbolstat != normal_st)
418 Lerror(ERR_SYMBOL_EXPECTED,0);
419 symbol = exit_sy;
420 break;
422 default:
423 Lerror(ERR_INVALID_CHAR,0);
425 if ( *symbolptr== ' ' ||
426 *symbolptr=='\t' ||
427 *symbolptr== ',' )
428 NextBlank = TRUE;
429 _in_nextsymbol = FALSE;
430 } /* nextsymbol */
432 /* --------------------------------------------------------------- */
433 /* find the identifier */
434 /* --------------------------------------------------------------- */
435 static void
436 identifier(int isnumber)
438 char *s;
439 int l; /* length */ /* -+- l > maxlen ? */
440 int hasDot=FALSE, hasExp=FALSE;
442 symbolisstr = FALSE;
443 symbolhasdot = 0;
444 s = LSTR(symbolstr);
445 l = 0;
447 for (;;) {
448 if (l>LMAXLEN(symbolstr))
449 Lerror(ERR_TOO_LONG_STRING,0);
451 if (commentfound &&
452 *symbolptr!='(' && *symbolptr!=':') {
453 commentfound = FALSE;
454 *s='\0';
455 LLEN(symbolstr) = l;
456 goto Nleave;
459 switch (l2u[(byte)*symbolptr]) {
460 case '0': case '1': case '2':
461 case '3': case '4': case '5':
462 case '6': case '7': case '8':
463 case '9':
464 *s++ = *symbolptr;
465 l++;
466 nextchar(FALSE);
467 break;
469 case 'A': case 'B': case 'C':
470 case 'D': case 'E': case 'F':
471 case 'G': case 'H': case 'I':
472 case 'J': case 'K': case 'L':
473 case 'M': case 'N': case 'O':
474 case 'P': case 'Q': case 'R':
475 case 'S': case 'T': case 'U':
476 case 'V': case 'W': case 'X':
477 case 'Y': case 'Z':
479 case '@':
480 case '#':
481 case '$':
482 case '_':
483 case '?':
484 case '!':
485 *s = l2u[(byte)*symbolptr];
486 if (isnumber) {
487 if (*s=='E') {
488 if (hasExp)
489 isnumber = FALSE;
490 hasExp = TRUE;
491 } else
492 isnumber = FALSE;
494 s++; l++;
495 nextchar(FALSE);
496 break;
498 case '+':
499 case '-':
500 if (isnumber) {
501 if (*(s-1)=='E') {
502 *s++ = *symbolptr; l++;
503 nextchar(FALSE);
504 } else {
505 *s='\0';
506 LLEN(symbolstr) = l;
507 goto Nleave;
509 } else {
510 *s='\0';
511 LLEN(symbolstr) = l;
512 goto Nleave;
514 break;
516 case '.':
517 *s++ = *symbolptr; l++;
518 if (!symbolhasdot) /* position of first */
519 symbolhasdot = l; /* dot */
520 nextchar(FALSE);
521 if (isnumber) {
522 if (hasDot)
523 isnumber = FALSE;
524 hasDot = TRUE;
525 symbolhasdot = 0;
527 break;
529 case '(':
530 nextchar(FALSE);
531 *s='\0';
532 LLEN(symbolstr) = l;
533 symbol = function_sy;
534 return;
536 case ':':
537 nextchar(FALSE);
538 *s='\0';
539 LLEN(symbolstr) = l;
540 symbol = label_sy;
541 return;
543 case '\t':
544 case ' ':
545 NextBlank = TRUE;
546 *s='\0';
547 LLEN(symbolstr)=l;
548 while (*symbolptr==' '||*symbolptr=='\t')
549 nextchar(FALSE);
551 /* literal finished and it is not a label? */
552 if (*symbolptr!=':')
553 goto Nleave;
555 /* literal is label */
556 symbol = label_sy;
557 nextchar(FALSE);
558 return;
560 default:
561 *s='\0';
562 LLEN(symbolstr) = l;
563 goto Nleave;
564 } /* end of switch */
565 } /* end of for */
566 Nleave:
567 if (symbol!=ident_sy) return ;
569 if (symbolhasdot == LLEN(symbolstr))
570 symbolhasdot = 0; /* treat is as a variable */
572 if (symbolstat == in_do_init_st) {
573 if (!Lcmp(&symbolstr,"BY" )) symbol = by_sy;
574 else if (!Lcmp(&symbolstr,"FOR" )) symbol = for_sy;
575 else if (!Lcmp(&symbolstr,"TO" )) symbol = to_sy;
576 else if (!Lcmp(&symbolstr,"UNTIL")) symbol = until_sy;
577 else if (!Lcmp(&symbolstr,"WHILE")) symbol = while_sy;
578 } else
579 if (symbolstat == in_parse_value_st) {
580 if (!Lcmp(&symbolstr,"WITH" )) symbol = with_sy;
581 } else
582 if (symbolstat == in_if_init_st) {
583 if (!Lcmp(&symbolstr,"THEN" )) symbol = then_sy;
585 } /* identifier */
587 /* --------------------------------------------------------------- */
588 /* extract a literal symbol */
589 /* --------------------------------------------------------------- */
590 static void
591 literal(void)
593 char quote;
594 char *s;
595 int l; /* length of symbolstr */
596 Lstr A;
598 symbolhasdot = 0;
599 symbol = literal_sy;
600 quote = *symbolptr;
601 s = LSTR(symbolstr);
602 l = 0;
603 symbolisstr = TRUE;
605 for (;;) { /* -+- l > maxlen ? */
606 nextchar(TRUE);
607 if (l>=LMAXLEN(symbolstr))
608 Lerror(ERR_TOO_LONG_STRING,0);
609 if (*symbolptr==quote) {
610 nextchar(FALSE); /* quote ended?? */
611 if (*symbolptr == '(') {
612 *s = '\0';
613 LLEN(symbolstr) = l;
614 symbol = function_sy;
615 nextchar(FALSE);
616 return;
617 } else
618 if (commentfound) { /* a comment was inside */
619 commentfound = FALSE;
620 *s = '\0';
621 LLEN(symbolstr) = l;
622 return;
623 } else
624 if (STRCHR("bBxXhH",*symbolptr)) {
625 /* check next char */
626 char nc=l2u[(byte)*(symbolptr+1)];
628 *s = '\0';
629 LLEN(symbolstr) = l;
631 if (IN_RANGE('0',nc,'9') ||
632 IN_RANGE('A',nc,'Z') ||
633 nc=='@' || nc=='#' || nc=='$' ||
634 nc=='_' || nc=='?' || nc=='!' ||
635 nc=='.')
636 return;
638 LINITSTR(A);
640 switch (l2u[(byte)*symbolptr]) {
641 case 'B':
642 if (!Ldatatype(&symbolstr,'B'))
643 Lerror(ERR_INVALID_HEX_CONST,0);
644 Lb2x(&A,&symbolstr);
645 Lx2c(&symbolstr,&A);
646 break;
647 case 'H':
648 if (!Ldatatype(&symbolstr,'X'))
649 Lerror(ERR_INVALID_HEX_CONST,0);
650 Lx2d(&A,&symbolstr,0);
651 Lstrcpy(&symbolstr,&A);
652 break;
653 case 'X':
654 if (!Ldatatype(&symbolstr,'X'))
655 Lerror(ERR_INVALID_HEX_CONST,0);
656 Lx2c(&A,&symbolstr);
657 Lstrcpy(&symbolstr,&A);
658 break;
660 nextchar(FALSE);
661 LFREESTR(A);
662 return;
663 } else
664 if (*symbolptr==quote) {
665 *s++ = *symbolptr; l++;
666 } else {
667 *s = '\0';
668 LLEN(symbolstr) = l;
669 return;
671 } else
672 if (*symbolptr == '\n') {
673 *s++ = ' '; l++;
674 } else
675 if (*symbolptr == 0)
676 Lerror(ERR_UNMATCHED_QUOTE,
677 (quote=='\'')?2:3);
678 else {
679 *s++ = *symbolptr;
680 l++;
683 } /* literal */