Annotation of OpenXM_contrib/pari/src/language/anal.c, Revision 1.1.1.1
1.1 maekawa 1: /*******************************************************************/
2: /* */
3: /* SYNTACTICAL ANALYZER FOR GP */
4: /* */
5: /*******************************************************************/
6: /* $Id: anal.c,v 1.1.1.1 1999/09/16 13:48:02 karim Exp $ */
7: #include "pari.h"
8: #include "anal.h"
9: #include "parinf.h"
10:
11: typedef struct var_cell {
12: struct var_cell *prev;
13: GEN value;
14: char flag;
15: } var_cell;
16: #define PUSH_VAL 0
17: #define COPY_VAL 1
18: #define copyvalue(v,x) new_val_cell(get_ep(v), gclone(x), COPY_VAL)
19: #define pushvalue(v,x) new_val_cell(get_ep(v), x, PUSH_VAL)
20: #define killvalue(v) pop_val(get_ep(v))
21:
22: #define separe(c) ((c)==';' || (c)==':')
23: typedef GEN (*PFGEN)(ANYARG);
24:
25: static GEN constante(void);
26: static GEN expr(void);
27: static GEN facteur(void);
28: static GEN identifier(void);
29: static GEN matrix_block(GEN p, entree *ep);
30: static GEN read_member(GEN x);
31: static GEN seq(void);
32: static GEN truc(void);
33: static long number(long *nb);
34: static void doskipseq(char *s, int strict);
35: static void skipconstante(void);
36: static void skipexpr(void);
37: static void skipfacteur(void);
38: static void skipidentifier(void);
39: static void skipseq(void);
40: static void skipstring(void);
41: static long skiptruc(void);
42: static GEN strtoGENstr_t();
43: static entree *entry(void);
44: static entree *installep(void *f,char *name,int l,int v,int add,entree **table);
45: static entree *skipentry(void);
46:
47: void killbloc0(GEN x, int inspect);
48:
49: /* last time we began parsing an object of specified type */
50: static struct
51: {
52: char *identifier, *symbol, *raw, *member, *start;
53: } mark;
54:
55: /* when skipidentifier() detects that user function f() is being redefined,
56: * (f()= ... ) this is set pointing to the opening parenthesis. Checked in
57: * identifier(). Otherwise definition like f(x=1)= would change the value of
58: * global variable x
59: */
60: static char *redefine_fun = NULL;
61:
62: /* points to the part of the string that remains to be parsed */
63: static char *analyseur;
64:
65: /* when non-0, we are checking the syntax of a new function body */
66: static long skipping_fun_def;
67:
68: /* when non-NULL, points to the entree of a new user function (currently
69: * being checked). Used by the compatibility engine in the following way:
70: * when user types in a function whose name has changed, it is understood
71: * as EpNEW; first syntax error (missing = after function definition
72: * usually) triggers err_new_fun() if check_new_fun is set.
73: */
74: static entree *check_new_fun;
75:
76: /* for control statements (check_break) */
77: static long br_status, br_count;
78: static GEN br_res = NULL;
79:
80: /* Special characters:
81: * ' ', '\t', '\n', '\\' are forbidden internally (suppressed by filtre).
82: * { } are forbidden everywhere and will be used to denote optional
83: * lexemes in the sequel.
84: *
85: * Definitions: The sequence
86: * { a }* means any number (possibly 0) of object a.
87: * { x|y } means an optional x or y.
88: *
89: * seq : only this one can be empty.
90: * sequence of { expr{ :|; } }*
91: *
92: * expr :
93: * expression = sequence of "facteurs" separated by binary operators
94: * whose priority are:
95: * 1: *, /, \, \/, %, >>, << (highest)
96: * 2: +, -
97: * 3: <, <=, >, >=, !=, ==, <>
98: * 4: &, &&, |, || (lowest)
99: * read from left to right.
100: *
101: * facteur :
102: * Optional leading sign (meaningfull only when "facteur" is enclosed
103: * in parentheses), followed by a "truc", then by any succession of the
104: * following:
105: *
106: * ~, _, ', !
107: * or ^ facteur
108: * or matrix_block
109: * or .member (see gp_member_list)
110: *
111: * truc:
112: * identifier
113: * or constante
114: * or ! truc
115: * or ' identifier
116: * or matrix_block (no_affect=1)
117: * or (expr)
118: * or %{ ` }* or %number
119: *
120: * identifier:
121: * entry ( { expr } { ,expr }* )
122: * The () are optional when arg list is void.
123: *
124: * matrix_block :
125: * [ A { { ; }A }*] where A = { expr } { { , }{ expr } }*
126: * All A must share the same length.
127: * If (no_affect=0 || ep !=NULL): follows an optional "= expr"
128: * or ++, --, op= where op is one of the operators in expr 1: and 2:
129: *
130: * entry :
131: * any succesion of alphanumeric characters, the first of which is not
132: * a digit.
133: *
134: * constante:
135: * number { . } { number } { e|E } { +|- } { number }.
136: *
137: * number:
138: * any non-negative integer.
139: */
140: char*
141: _analyseur(void)
142: {
143: return analyseur;
144: }
145:
146: /* Do not modify (analyseur,mark.start) */
147: static GEN
148: lisseq0(char *t, GEN (*f)(void))
149: {
150: const long av = avma;
151: char *olds = analyseur, *olde = mark.start;
152: GEN res;
153:
154: if (foreignExprHandler && *t == foreignExprSwitch)
155: return (*foreignExprHandler)(t);
156:
157: check_new_fun=NULL; skipping_fun_def=0;
158: mark.start = analyseur = t;
159:
160: br_status = br_NONE;
161: if (br_res) { killbloc(br_res); br_res = NULL; }
162: res = f();
163: analyseur = olds; mark.start = olde;
164:
165: if (br_status)
166: {
167: if (!br_res) { avma = av; return gnil; }
168: res = forcecopy(br_res);
169: }
170: return gerepileupto(av, res);
171: }
172:
173: GEN
174: lisseq(char *t)
175: {
176: return lisseq0(t, seq);
177: }
178:
179: GEN
180: lisexpr(char *t)
181: {
182: return lisseq0(t, expr);
183: }
184:
185: /* filtered lisexpr = remove blanks and comments */
186: GEN
187: flisexpr(char *t)
188: {
189: char *tmp = pari_strdup(t);
190: GEN x;
191:
192: filtre(tmp, f_INIT | f_REG);
193: x = lisseq0(tmp, expr);
194: free(tmp); return x;
195: }
196:
197: /* check syntax, then execute */
198: GEN
199: readseq(char *c, int strict)
200: {
201: check_new_fun=NULL; skipping_fun_def=0;
202: doskipseq(c, strict); return lisseq(c);
203: }
204:
205: entree *
206: install(void *f, char *name, char *code)
207: {
208: long hash;
209: entree *ep = is_entry_intern(name, functions_hash, &hash);
210:
211: if (ep) err(warner,"[install] '%s' already there. Not replaced", name);
212: else
213: {
214: ep = installep(f, name, strlen(name), EpINSTALL, 0, functions_hash + hash);
215: ep->code = pari_strdup(code);
216: }
217: return ep;
218: }
219:
220: static void
221: free_args(gp_args *f)
222: {
223: long i;
224: GEN *y = f->arg;
225: for (i = f->narg + f->nloc - 1; i>=0; i--)
226: if (isclone(y[i])) gunclone(y[i]);
227: }
228:
229: void
230: freeep(entree *ep)
231: {
232: if (foreignFuncFree && ep->code && (*ep->code == 'x'))
233: (*foreignFuncFree)(ep); /* function created by foreign interpreter */
234:
235: if (EpSTATIC(ep)) return; /* gp function loaded at init time */
236: if (ep->help) free(ep->help);
237: if (ep->code) free(ep->code);
238: if (ep->args)
239: {
240: switch(EpVALENCE(ep))
241: {
242: case EpVAR: case EpGVAR: break;
243: default: free_args((gp_args*)ep->args);
244: }
245: free((void*)ep->args);
246: }
247: free(ep);
248: }
249:
250: /*******************************************************************/
251: /* */
252: /* VARIABLES */
253: /* */
254: /*******************************************************************/
255: /* push_val and pop_val are private functions for use in sumiter and bibli2:
256: * we want a temporary value for ep, which is NOT a clone, to avoid
257: * unnecessary gaffect calls.
258: *
259: * Assumptions:
260: * EpVALENCE(ep) = EpVAR or EpGVAR
261: * ep->args initilized to NULL in installep()
262: */
263: static void
264: new_val_cell(entree *ep, GEN a, char flag)
265: {
266: var_cell *v = (var_cell*) gpmalloc(sizeof(var_cell));
267: v->value = (GEN)ep->value;
268: v->prev = (var_cell*) ep->args;
269: v->flag = flag;
270:
271: ep->args = (void*) v;
272: ep->value = a;
273: }
274:
275: void
276: push_val(entree *ep, GEN a)
277: {
278: new_val_cell(ep,a,PUSH_VAL);
279: }
280:
281: void
282: pop_val(entree *ep)
283: {
284: var_cell *v = (var_cell*) ep->args;
285:
286: if (!v) return; /* initial value */
287: if (v->flag == COPY_VAL) killbloc((GEN)ep->value);
288: ep->value = v->value;
289: ep->args = (void*) v->prev;
290: free((void*)v);
291: }
292:
293: int
294: pop_val_if_newer(entree *ep, long loc)
295: {
296: var_cell *v = (var_cell*) ep->args;
297:
298: if (!v) return 0; /* initial value */
299: if (v->flag == COPY_VAL)
300: {
301: GEN x = (GEN)ep->value;
302: if (bl_num(x) < loc) return 0; /* older */
303: killbloc((GEN)ep->value);
304: }
305: ep->value = v->value;
306: ep->args = (void*) v->prev;
307: free((void*)v); return 1;
308: }
309:
310: static void
311: changevalue(entree *ep, GEN val)
312: {
313: GEN x = gclone(val);
314: var_cell *v = (var_cell*) ep->args;
315:
316: if (!v) new_val_cell(ep,x, COPY_VAL);
317: else
318: {
319: if (v->flag == COPY_VAL) killbloc((GEN)ep->value); else v->flag = COPY_VAL;
320: ep->value = x;
321: }
322: }
323:
324: void
325: kill_from_hashlist(entree *ep)
326: {
327: long hash = hashvalue(ep->name);
328: entree *ep1;
329:
330: if (functions_hash[hash] == ep)
331: {
332: functions_hash[hash] = ep->next;
333: freeep(ep); return;
334: }
335: for (ep1 = functions_hash[hash]; ep1; ep1 = ep1->next)
336: if (ep1->next == ep)
337: {
338: ep1->next = ep->next;
339: freeep(ep); return;
340: }
341: }
342:
343: static entree*
344: get_ep(long v)
345: {
346: entree *ep = varentries[v];
347: if (!ep) err(talker2,"this function uses a killed variable",
348: mark.identifier, mark.start);
349: return ep;
350: }
351:
352: /* Kill entree ep, i.e free all memory it occupies, remove it from hashtable.
353: * If it's a variable set a "black hole" in polx[v], etc. x = 0-th variable
354: * can NOT be killed (only the value). That's because we use explicitly
355: * polx[0] at many places.
356: */
357: void
358: kill0(entree *ep)
359: {
360: long v;
361:
362: if (EpSTATIC(ep))
363: err(talker2,"can't kill that",mark.symbol,mark.start);
364: switch(EpVALENCE(ep))
365: {
366: case EpVAR:
367: case EpGVAR:
368: v = varn(initial_value(ep)); killvalue(v);
369: if (!v) return; /* never kill x */
370: polx[v] = polun[v] = gnil;
371: polvar[v+1] = (long)gnil;
372: varentries[v] = NULL; break;
373: case EpUSER:
374: gunclone((GEN)ep->value); break;
375: }
376: kill_from_hashlist(ep);
377: }
378:
379: /*******************************************************************/
380: /* */
381: /* PARSER */
382: /* */
383: /*******************************************************************/
384:
385: static GEN
386: seq(void)
387: {
388: const long av=avma, lim=stack_lim(av,1);
389: GEN res=gnil;
390:
391: for(;;)
392: {
393: while (separe(*analyseur)) analyseur++;
394: if (!*analyseur || *analyseur == ')' || *analyseur == ',') return res;
395: res = expr();
396: if (br_status || !separe(*analyseur)) return res;
397:
398: if (low_stack(lim, stack_lim(av,1)))
399: {
400: if(DEBUGMEM>1) err(warnmem,"seq");
401: if (is_universal_constant(res)) avma = av;
402: else
403: res = gerepileupto(av, gcopy(res));
404: }
405: }
406: }
407:
408: static GEN
409: gshift_l(GEN x, GEN n) { return gshift(x, itos(n)); }
410:
411: static GEN
412: gshift_r(GEN x, GEN n) { return gshift(x,-itos(n)); }
413:
414: static GEN
415: expr(void)
416: {
417: PFGEN f[] = { NULL,NULL,NULL,NULL };
418: GEN aux,e,e1,e2,e3;
419: long av = avma, lim = stack_lim(av,2);
420:
421: e1 = e2 = e3 = NULL;
422:
423: L3:
424: aux = facteur();
425: if (br_status) return NULL;
426: e3 = f[3]? f[3](e3,aux): aux;
427: switch(*analyseur)
428: {
429: case '*': analyseur++; f[3] = (PFGEN)&gmul; goto L3;
430: case '/': analyseur++; f[3] = (PFGEN)&gdiv; goto L3;
431: case '%': analyseur++; f[3] = (PFGEN)&gmod; goto L3;
432: case '\\':
433: if (*++analyseur == '/') { analyseur++; f[3]=(PFGEN)&gdivround; goto L3; }
434: f[3] = (PFGEN)&gdivent; goto L3;
435:
436: case '<': case '>':
437: if (analyseur[1] == *analyseur)
438: {
439: f[3] = (*analyseur == '<')? (PFGEN)&gshift_l
440: : (PFGEN)&gshift_r;
441: analyseur += 2; goto L3;
442: }
443: }
444: f[3] = NULL;
445:
446: L2:
447: if (!e3) goto L3;
448: e2 = f[2]? f[2](e2,e3): e3;
449: e3 = NULL;
450: if (low_stack(lim, stack_lim(av,2)))
451: {
452: GEN *gptr[2];
453: int n = 1; gptr[0]=&e2;
454: if (e1) gptr[n++]=&e1;
455: if(DEBUGMEM>1) err(warnmem,"expr");
456: gerepilemany(av,gptr,n);
457: }
458:
459: switch(*analyseur)
460: {
461: case '+': analyseur++; f[2]=(PFGEN)&gadd; goto L3;
462: case '-': analyseur++; f[2]=(PFGEN)&gsub; goto L3;
463: }
464: f[2] = NULL;
465:
466: L1:
467: if (!e2) goto L2;
468: e1 = f[1]? f[1](e1,e2): e2;
469: e2 = NULL;
470: switch(*analyseur)
471: {
472: case '<':
473: switch(*++analyseur)
474: {
475: case '=': analyseur++; f[1]=(PFGEN)&gle; goto L2;
476: case '>': analyseur++; f[1]=(PFGEN)⪈ goto L2;
477: }
478: f[1]=(PFGEN)&glt; goto L2;
479:
480: case '>':
481: if (*++analyseur == '=') { analyseur++; f[1]=(PFGEN)&gge; goto L2; }
482: f[1]=(PFGEN)&ggt; goto L2;
483:
484: case '=':
485: if (analyseur[1] == '=') { analyseur+=2; f[1]=(PFGEN)≥ goto L2; }
486: goto L1;
487:
488: case '!':
489: if (analyseur[1] == '=') { analyseur+=2; f[1]=(PFGEN)⪈ goto L2; }
490: goto L1;
491: }
492: f[1] = NULL;
493:
494: /* L0: */
495: if (!e1) goto L1;
496: e = f[0]? (gcmp0(e1)? gzero: gun): e1;
497: e1 = NULL;
498: switch(*analyseur)
499: {
500: case '&':
501: if (*++analyseur == '&') analyseur++;
502: if (gcmp0(e)) { skipexpr(); return gzero; }
503: f[0]=(PFGEN)1; goto L1;
504:
505: case '|':
506: if (*++analyseur == '|') analyseur++;
507: if (!gcmp0(e)) { skipexpr(); return gun; }
508: f[0]=(PFGEN)1; goto L1;
509: }
510: return e;
511: }
512:
513: /********************************************************************/
514: /** **/
515: /** CHECK FUNCTIONS **/
516: /** **/
517: /********************************************************************/
518:
519: /* if current identifier was a function in 1.39.15, raise "obsolete" error */
520: static void
521: err_new_fun()
522: {
523: char *s = NULL, str[128];
524:
525: if (check_new_fun)
526: {
527: if (check_new_fun != NOT_CREATED_YET)
528: {
529: s = strcpy(str,check_new_fun->name);
530: kill0(check_new_fun);
531: }
532: check_new_fun=NULL;
533: }
534: if (compatible == NONE)
535: {
536: char *v, *u = str, *lim = str + 127;
537: int n;
538:
539: if (!s)
540: { /* guess that the offending function was last identifier */
541: v = mark.identifier;
542: while (is_keyword_char(*v) && u < lim) *u++ = *v++;
543: *u = 0; s = str;
544: }
545: if (whatnow_fun)
546: n = whatnow_fun(s,1);
547: else
548: n = is_entry_intern(s,funct_old_hash,NULL)? 1: 0;
549: if (n) err(obsoler,mark.identifier,mark.start, s,n);
550: }
551: }
552:
553: #ifdef INLINE
554: INLINE
555: #endif
556: void
557: match2(char *s, char c)
558: {
559: if (*s != c)
560: {
561: char str[64];
562: if (check_new_fun && (c == '(' || c == '=' || c == ',')) err_new_fun();
563: sprintf(str,"expected character: '%c' instead of",c);
564: err(talker2,str,s,mark.start);
565: }
566: }
567:
568: #define match(c) match2(analyseur++, (c))
569:
570: static long
571: readlong()
572: {
573: const long av = avma;
574: const char *old = analyseur;
575: long m;
576: GEN arg = expr();
577:
578: if (br_status) err(breaker,"here (reading long)");
579: if (typ(arg) != t_INT) err(caseer,old,mark.start);
580: m = itos(arg); avma=av; return m;
581: }
582:
583: static long
584: check_array_index(long max)
585: {
586: const char *old = analyseur;
587: const long c = readlong();
588:
589: if (c < 1 || c >= max)
590: {
591: char s[80];
592: sprintf(s,"array index (%ld) out of allowed range ",c);
593: if (max == 1) strcat(s, "[none]");
594: else if (max == 2) strcat(s, "[1]");
595: else sprintf(s,"%s[1-%ld]",s,max-1);
596: err(talker2,s,old,mark.start);
597: }
598: return c;
599: }
600:
601: static long
602: readvar()
603: {
604: const char *old = analyseur;
605: const GEN x = expr();
606:
607: if (typ(x) != t_POL || lgef(x) != 4 ||
608: !gcmp0((GEN)x[2]) || !gcmp1((GEN)x[3])) err(varer1,old,mark.start);
609: return varn(x);
610: }
611:
612: /* alright !=0 means function was called without () */
613: static int
614: do_switch(int alright, int matchcomma)
615: {
616: if (alright || !*analyseur || *analyseur == ')' || separe(*analyseur))
617: return 1;
618: if (*analyseur == ',') /* we just read an arg, or first arg */
619: {
620: if (!matchcomma && analyseur[-1] == '(') return 1; /* first arg */
621: if (analyseur[1] == ',' || analyseur[1] == ')')
622: { analyseur++; return 1; }
623: }
624: return 0;
625: }
626:
627: /********************************************************************/
628: /** **/
629: /** READ FUNCTIONS **/
630: /** **/
631: /********************************************************************/
632:
633: static GEN
634: facteur(void)
635: {
636: const char *old = analyseur;
637: GEN x,p1;
638: int plus=1;
639:
640: switch(*analyseur)
641: {
642: case '-': plus=0; /* fall through */
643: case '+': analyseur++; break;
644: }
645: x = truc();
646: if (br_status) return NULL;
647:
648: for(;;)
649: switch(*analyseur)
650: {
651: case '.':
652: analyseur++; x = read_member(x);
653: if (!x) err(talker2, "not a proper member definition",
654: mark.member, mark.start);
655: break;
656: case '^':
657: analyseur++; p1 = facteur();
658: if (br_status) err(breaker,"here (after ^)");
659: x = gpui(x,p1,prec); break;
660: case '\'':
661: analyseur++; x = deriv(x,gvar9(x)); break;
662: case '~':
663: analyseur++; x = gtrans(x); break;
664: case '[':
665: x = matrix_block(x,NULL); break;
666: case '!':
667: if (analyseur[1] != '=')
668: {
669: if (typ(x) != t_INT) err(caseer,old,mark.start);
670: analyseur++; x=mpfact(itos(x)); break;
671: } /* Fall through */
672:
673: default:
674: return (plus || x==gnil)? x: gneg(x);
675: }
676: }
677:
678: #define check_var_name() \
679: if (!isalpha((int)*analyseur)) err(varer1,analyseur,mark.start);
680:
681: static GEN
682: truc(void)
683: {
684: long i,j, n=0, p=0, m=1, sizetab;
685: GEN *table,p1;
686: char *old;
687:
688: if (*analyseur == '!')
689: {
690: analyseur++; p1 = truc();
691: if (br_status) err(breaker,"here (after !)");
692: return gcmp0(p1)? gun: gzero;
693: }
694: if (*analyseur == '\'')
695: {
696: const char* old;
697: entree *ep;
698: analyseur++; check_var_name();
699: old = analyseur; ep = entry();
700: switch(EpVALENCE(ep))
701: {
702: case EpVAR: case EpGVAR:
703: return (GEN)initial_value(ep);
704: default: err(varer1,old,mark.start);
705: }
706: }
707: if (isalpha((int)*analyseur)) return identifier();
708:
709: if (*analyseur == '"') return strtoGENstr_t();
710: if (isdigit((int)*analyseur) || *analyseur == '.') return constante();
711: switch(*analyseur++)
712: {
713: case '(': p1=expr(); match(')'); return p1;
714:
715: case '[':
716: if (*analyseur == ';' && analyseur[1] == ']')
717: { analyseur+=2; return cgetg(1,t_MAT); }
718:
719: old=analyseur; analyseur--; sizetab=skiptruc(); analyseur=old;
720: table = (GEN*) gpmalloc((sizetab+1)*sizeof(GEN));
721:
722: if (*analyseur != ']')
723: {
724: table[++n] = expr();
725: if (br_status) err(breaker,"array context");
726: }
727: while (*analyseur == ',')
728: {
729: analyseur++;
730: table[++n] = expr();
731: if (br_status) err(breaker,"array context");
732: }
733: switch (*analyseur++)
734: {
735: case ']':
736: p1=cgetg(n+1,t_VEC);
737: for (i=1; i<=n; i++)
738: p1[i] = lcopy(table[i]);
739: break;
740:
741: case ';':
742: m = n;
743: do
744: {
745: table[++n] = expr();
746: if (br_status) err(breaker,"array context");
747: }
748: while (*analyseur++ != ']');
749: p = n/m + 1;
750: p1 = cgetg(m+1,t_MAT);
751: for (j=1; j<=m; j++)
752: {
753: p1[j] = lgetg(p,t_COL);
754: for (i=1; i<p; i++)
755: coeff(p1,i,j) = lcopy(table[(i-1)*m+j]);
756: }
757: break;
758:
759: default:
760: /* can only occur in library mode */
761: err(talker,"incorrect vector or matrix");
762: return NULL; /* not reached */
763: }
764: free(table); return p1;
765:
766: case '%':
767: old=analyseur-1; p=0;
768: if (! gp_history_fun)
769: err(talker2,"history not available in library mode",old,mark.start);
770: while (*analyseur == '`') { analyseur++; p++; }
771: return p ? gp_history_fun(p ,1,old,mark.start)
772: : gp_history_fun(number(&n),0,old,mark.start);
773: }
774: err(caracer1,analyseur-1,mark.start);
775: return NULL; /* not reached */
776: }
777:
778: /* valid x opop, e.g x++ */
779: #ifdef INLINE
780: INLINE
781: #endif
782: int
783: repeated_op()
784: {
785: char c = *analyseur;
786: return c == analyseur[1] && (c == '+' || c == '-');
787: }
788:
789: static GEN
790: matrix_block(GEN p, entree *ep)
791: {
792: long tx,full_col,full_row,c,r;
793: char *old;
794: GEN res, *pt, cpt;
795:
796: tx = full_col = full_row = 0; pt = &p;
797: while (*analyseur == '[')
798: {
799: analyseur++; p = *pt; tx = typ(p);
800: switch(tx)
801: {
802: case t_LIST:
803: c = check_array_index(lgef(p)-1) + 1;
804: pt = (GEN*)(p + c); match(']'); break;
805:
806: case t_VEC: case t_COL:
807: c = check_array_index(lg(p));
808: pt = (GEN*)(p + c); match(']'); break;
809:
810: case t_MAT:
811: if (lg(p)==1) err(talker2,"a 0x0 matrix has no elements",
812: analyseur,mark.start);
813: full_col = full_row = 0;
814: if (*analyseur==',') /* whole column */
815: {
816: analyseur++;
817: if (*analyseur != '[') full_col = 1;
818: c = check_array_index(lg(p));
819: pt = (GEN*)(p + c); match(']'); break;
820: }
821:
822: r = check_array_index(lg(p[1]));
823: match(',');
824: if (*analyseur == ']') /* whole row */
825: {
826: GEN p2 = cgetg(lg(p),t_VEC);
827: analyseur++;
828: if (*analyseur != '[') full_row = 1;
829: for (c=1; c<lg(p); c++) p2[c] = coeff(p,r,c);
830: pt = &p2;
831: }
832: else
833: {
834: c = check_array_index(lg(p));
835: pt = (GEN*)(((GEN)p[c]) + r); /* &coeff(p,r,c) */
836: match(']');
837: }
838: break;
839:
840: default:
841: err(caracer1,analyseur-1,mark.start);
842: }
843: }
844: old = analyseur;
845: cpt = *pt;
846:
847: if (*analyseur == '=') /* assignment or equality test */
848: {
849: if (analyseur[1] == '=') return cpt; /* test */
850:
851: analyseur++; old = analyseur; res = expr();
852: if (br_status) err(breaker,"assignment");
853: }
854: else if (repeated_op())
855: { /* a++, a-- */
856: res = gadd(cpt, (*analyseur == '+')? gun: negi(gun));
857: analyseur += 2;
858: }
859: else
860: {
861: GEN (*f)(GEN,GEN) = NULL;
862:
863: if (!*analyseur)
864: return (ep && !full_row)? cpt: gcopy(cpt);
865:
866: /* op= constructs ? */
867: if (analyseur[1] == '=')
868: {
869: switch(*analyseur)
870: {
871: case '+' : f = &gadd ; break;
872: case '-' : f = &gsub ; break;
873: case '*' : f = &gmul ; break;
874: case '/' : f = &gdiv ; break;
875: case '\\': f = &gdivent; break;
876: case '%' : f = &gmod ; break;
877: default:
878: return (ep && !full_row)? cpt: gcopy(cpt);
879: }
880: analyseur += 2;
881: }
882: else
883: {
884: if (analyseur[2] == '=')
885: switch(*analyseur)
886: {
887: case '>' :
888: if (analyseur[1]=='>') f = &gshift_r;
889: break;
890: case '<' :
891: if (analyseur[1]=='<') f = &gshift_l;
892: break;
893: case '\\':
894: if (analyseur[1]=='/') f = &gdivround;
895: break;
896: }
897: if (!f)
898: return (ep && !full_row)? cpt: gcopy(cpt);
899: analyseur += 3;
900: }
901: old = analyseur; res = expr();
902: if (br_status) err(breaker,"assignment");
903: res = f(cpt, res);
904: }
905:
906: /* assignment */
907: if (!ep) err(caracer1,analyseur,mark.start);
908:
909: if (!tx) /* simple variable */
910: {
911: changevalue(ep,res);
912: return (GEN) ep->value;
913: }
914:
915: if (full_row) /* whole row (index r) */
916: {
917: if (typ(res) != t_VEC || lg(res) != lg(p))
918: err(caseer2,old,mark.start);
919:
920: for (c=1; c<lg(p); c++)
921: {
922: GEN p2 = gcoeff(p,r,c); if (isclone(p2)) killbloc(p2);
923: coeff(p,r,c) = lclone((GEN)res[c]);
924: }
925: return res;
926: }
927:
928: res = gclone(res);
929: /* sanity check in case v[i] = f(), where f destroys v */
930: if (cpt != *pt)
931: err(talker2,"variable on the left-hand side was affected during this function call. Check whether it is modified as a side effect there", old, mark.start);
932:
933: if (full_col) /* whole col */
934: {
935: if (typ(res) != t_COL || lg(res) != lg(cpt))
936: err(caseer2,old,mark.start);
937:
938: for (r=1; r<lg(cpt); r++)
939: if (isclone(cpt[r])) killbloc((GEN)cpt[r]);
940: }
941: /* no need to inspect if full_col (done above) */
942: if (isclone(cpt)) killbloc0(cpt, !full_col);
943: return *pt = res;
944: }
945:
946: static char*
947: init_buf(long len, char **ptbuf, char **ptlim)
948: {
949: char *buf = (char *)new_chunk(2 + len / sizeof(long));
950: *ptbuf = buf; *ptlim = buf + len; return buf;
951: }
952:
953: static char*
954: realloc_buf(char *bp, long len, char **ptbuf,char **ptlimit)
955: {
956: char *buf = *ptbuf;
957: long newlen = ((*ptlimit - buf) + len) << 1;
958: long oldlen = bp - buf;
959:
960: (void)init_buf(newlen, ptbuf, ptlimit);
961: memcpy(*ptbuf, buf, oldlen);
962: return *ptbuf + oldlen;
963: }
964:
965: static char *
966: expand_string(char *bp, char **ptbuf, char **ptlimit)
967: {
968: char *tmp, *s = analyseur;
969: long len, alloc = 1;
970:
971: while (is_keyword_char(*s)) s++;
972: if (*s == '"' || *s == ',' || *s == ')')
973: { /* Do not create new user variables */
974: entree *ep = is_entry_intern(analyseur, functions_hash,0);
975: if (!ep)
976: { /* consider as a literal */
977: tmp = analyseur;
978: len = s - analyseur;
979: analyseur = s; alloc = 0;
980: }
981: }
982: if (alloc)
983: {
984: long av = avma;
985: GEN p1 = expr();
986: if (br_status) err(breaker,"here (expanding string)");
987: tmp = GENtostr(p1);
988: len = strlen(tmp); avma = av;
989: }
990: if (ptlimit && bp + len > *ptlimit)
991: bp = realloc_buf(bp, len, ptbuf,ptlimit);
992: memcpy(bp,tmp,len); /* ignore trailing \0 */
993: if (alloc) free(tmp);
994: return bp + len;
995: }
996:
997: static char *
998: translate(char **src, char *s, char **ptbuf, char **ptlim)
999: {
1000: char *t = *src;
1001: while (*t)
1002: {
1003: while (*t == '\\')
1004: {
1005: switch(*++t)
1006: {
1007: case 'e': *s='\033'; break; /* escape */
1008: case 'n': *s='\n'; break;
1009: case 't': *s='\t'; break;
1010: default: *s=*t; if (!*t) err(talker,"unfinished string");
1011: }
1012: t++; s++;
1013: }
1014: if (*t == '"') break;
1015: if (ptlim && s >= *ptlim)
1016: s = realloc_buf(s,1, ptbuf,ptlim);
1017: *s++ = *t++;
1018: }
1019: *s=0; *src=t; return s;
1020: }
1021:
1022: static char *
1023: readstring_i(char *s, char **ptbuf, char **ptlim)
1024: {
1025: match('"'); s = translate(&analyseur,s, ptbuf,ptlim); match('"');
1026: return s;
1027: }
1028:
1029: static GEN
1030: any_string()
1031: {
1032: long n = 0, len = 16;
1033: GEN p1, res = new_chunk(len + 1);
1034:
1035: while (*analyseur)
1036: {
1037: if (*analyseur == '"')
1038: {
1039: res[n++] = (long) strtoGENstr_t();
1040: continue;
1041: }
1042: if (*analyseur == ')' || *analyseur == ';') break;
1043: if (*analyseur == ',')
1044: analyseur++;
1045: else
1046: {
1047: p1 = expr();
1048: if (br_status) err(breaker,"here (print)");
1049: res[n++] = (long) p1;
1050: }
1051: if (n == len)
1052: {
1053: long newlen = len << 1;
1054: p1 = new_chunk(newlen + 1);
1055: for (n = 0; n < len; n++) p1[n] = res[n];
1056: res = p1; len = newlen;
1057: }
1058: }
1059: res[n] = 0; /* end the sequence with NULL */
1060: return res;
1061: }
1062:
1063: /* Read a "string" from src. Format then copy it, starting at s. Return
1064: * pointer to the \0 which terminates the string.
1065: */
1066: char *
1067: readstring(char *src, char *s)
1068: {
1069: match2(src++, '"'); s = translate(&src, s, NULL,NULL);
1070: match2(src, '"'); return s;
1071: }
1072:
1073: static GEN
1074: strtoGENstr_t()
1075: {
1076: char *old = analyseur;
1077: long n;
1078: GEN x;
1079:
1080: skipstring(); n = analyseur-old - 1; /* don't count the enclosing '"' */
1081: old++; /* skip '"' */
1082: n = (n+BYTES_IN_LONG) >> TWOPOTBYTES_IN_LONG;
1083: x = cgetg(n+1, t_STR);
1084: translate(&old, GSTR(x), NULL,NULL);
1085: return x;
1086: }
1087:
1088: GEN
1089: strtoGENstr(char *s, long flag)
1090: {
1091: long n;
1092: GEN x;
1093:
1094: if (flag) s = expand_tilde(s);
1095: n = strlen(s)+1;
1096: n = (n+BYTES_IN_LONG) >> TWOPOTBYTES_IN_LONG;
1097: x = cgetg(n+1, t_STR);
1098: strcpy(GSTR(x), s);
1099: if (flag) free(s);
1100: return x;
1101: }
1102:
1103: /* p = NULL + array of variable numbers (longs) + function text */
1104: static GEN
1105: call_fun(GEN p, GEN *arg, GEN *loc, int narg, int nloc)
1106: {
1107: GEN res;
1108: long i;
1109:
1110: p++; /* skip NULL */
1111: /* push new values for formal parameters */
1112: for (i=0; i<narg; i++) copyvalue(*p++, *arg++);
1113: for (i=0; i<nloc; i++) pushvalue(*p++, *loc++);
1114: /* dumps the false GEN arglist from identifier() to the garbage zone */
1115: res = lisseq((char *)p);
1116: if (br_status != br_NONE)
1117: br_status = br_NONE;
1118: else
1119: if (! is_universal_constant(res)) /* important for gnil */
1120: res = forcecopy(res); /* make result safe */
1121:
1122: /* pop ancient values for formal parameters */
1123: for (i=0; i<nloc; i++) killvalue(*--p);
1124: for (i=0; i<narg; i++) killvalue(*--p);
1125: return res;
1126: }
1127:
1128: entree *
1129: do_alias(entree *ep)
1130: {
1131: while (ep->valence == EpALIAS) ep = (entree *) ((GEN)ep->value)[1];
1132: return ep;
1133: }
1134:
1135: static GEN
1136: global0()
1137: {
1138: GEN res = gnil;
1139: long i,n;
1140:
1141: for (i=0,n=lg(polvar)-1; n>=0; n--)
1142: {
1143: entree *ep = varentries[n];
1144: if (ep && EpVALENCE(ep) == EpGVAR)
1145: {
1146: res=new_chunk(1);
1147: res[0]=(long)polx[n]; i++;
1148: }
1149: }
1150: if (i) { res = cgetg(1,t_VEC); setlg(res, i+1); }
1151: return res;
1152: }
1153:
1154: static void
1155: check_pointer(unsigned int ptrs, GEN argvec[])
1156: {
1157: unsigned int i;
1158: for (i=0; ptrs; i++,ptrs>>=1)
1159: if (ptrs & 1) *((GEN*)argvec[i]) = gclone(*((GEN*)argvec[i]));
1160: }
1161:
1162: #define match_comma() if (matchcomma) match(','); else matchcomma = 1
1163:
1164: long
1165: check_args()
1166: {
1167: long nparam = 0, matchcomma = 0;
1168: entree *ep;
1169: char *old;
1170: GEN cell;
1171:
1172: while (*analyseur != ')')
1173: {
1174: old=analyseur; nparam++; match_comma();
1175: cell = new_chunk(2);
1176: if (!isalpha((int)*analyseur))
1177: {
1178: err_new_fun();
1179: err(paramer1, mark.identifier, mark.start);
1180: }
1181: ep = entry();
1182: if (EpVALENCE(ep) != EpVAR)
1183: {
1184: err_new_fun();
1185: if (EpVALENCE(ep) == EpGVAR)
1186: err(talker2,"global variable: ",old , mark.start);
1187: err(paramer1, old, mark.start);
1188: }
1189: cell[0] = varn(initial_value(ep));
1190: if (*analyseur == '=')
1191: {
1192: long av = avma;
1193: GEN p1;
1194: analyseur++; p1 = expr();
1195: if (br_status) err(breaker,"here (default args)");
1196: cell[1] = lclone(p1);
1197: avma = av;
1198: }
1199: else cell[1] = zero;
1200: }
1201: return nparam;
1202: }
1203:
1204: #define DFT_VAR (GEN)-1
1205: #define DFT_GEN (GEN)NULL
1206:
1207: static GEN
1208: identifier(void)
1209: {
1210: long m,i,av,matchcomma;
1211: char *ch1;
1212: entree *ep;
1213: GEN res, newfun, ptr;
1214:
1215: mark.identifier = analyseur; ep = entry();
1216: if (EpVALENCE(ep)==EpVAR || EpVALENCE(ep)==EpGVAR)
1217: { /* optimized for simple variables */
1218: switch (*analyseur)
1219: {
1220: case ')': case ',': return (GEN)ep->value;
1221: case '.':
1222: {
1223: long len, v;
1224:
1225: analyseur++; ch1 = analyseur;
1226: if ((res = read_member((GEN)ep->value))) return res;
1227:
1228: /* define a new member function */
1229: v = varn(initial_value(ep));
1230: len = analyseur - ch1;
1231: analyseur++; /* skip = */
1232: ep = installep(NULL,ch1,len,EpMEMBER,0, members_hash + hashvalue(ch1));
1233: ch1 = analyseur; skipseq(); len = analyseur-ch1;
1234:
1235: newfun=ptr= (GEN) newbloc(1 + (len>>TWOPOTBYTES_IN_LONG) + 4);
1236: newfun++; /* this bloc is no GEN, leave the first cell alone ( = 0) */
1237: *newfun++ = v;
1238:
1239: /* record text */
1240: strncpy((char *)newfun, ch1, len);
1241: ((char *) newfun)[len] = 0;
1242: ep->value = (void *)ptr; return gnil;
1243: }
1244: }
1245: return matrix_block((GEN) ep->value,ep);
1246: }
1247: ep = do_alias(ep); matchcomma = 0;
1248: if (ep->code)
1249: {
1250: char *s = ep->code, *oldanalyseur = NULL, *buf, *limit, *bp;
1251: unsigned int ret = RET_GEN, alright=0, has_pointer=0;
1252: long fake;
1253: void *call = ep->value;
1254: GEN argvec[9];
1255:
1256: if (*analyseur == '(') analyseur++;
1257: else
1258: { /* if no mandatory argument, no () needed */
1259: if (EpVALENCE(ep)) match('('); /* error */
1260:
1261: if (!*s || (!s[1] && *s == 'p'))
1262: return ((GEN (*)(long))ep->value)(prec);
1263: alright=1; /* no arg was given, but valence is ok */
1264: }
1265: i = 0;
1266: /* Optimized for G and p. */
1267: while (*s == 'G')
1268: {
1269: match_comma(); s++;
1270: argvec[i++] = expr();
1271: if (br_status) err(breaker,"here (argument reading)");
1272: }
1273: if (*s == 'p') { argvec[i++] = (GEN) prec; s++; }
1274:
1275: while (*s)
1276: switch (*s++)
1277: {
1278: case 'G': /* GEN */
1279: match_comma(); argvec[i++] = expr();
1280: if (br_status) err(breaker,"here (argument reading)");
1281: break;
1282:
1283: case 'L': /* long */
1284: match_comma(); argvec[i++] = (GEN) readlong(); break;
1285:
1286: case 'n': /* var number */
1287: match_comma(); argvec[i++] = (GEN) readvar(); break;
1288:
1289: case 'V': case 'S': /* variable or symbol */
1290: match_comma(); mark.symbol=analyseur;
1291: argvec[i++] = (GEN)entry(); break;
1292: case '&': /* *GEN */
1293: match_comma(); match('&'); mark.symbol=analyseur;
1294: {
1295: entree *e = entry();
1296: if (e->value == (void*)initial_value(e))
1297: changevalue(e, gzero); /* don't overwrite initial value */
1298: has_pointer |= (1 << i);
1299: argvec[i++] = (GEN) &(e->value); break;
1300: }
1301: case 'I': /* Input position */
1302: match_comma();
1303: argvec[i++] = (GEN) analyseur;
1304: skipseq(); break;
1305:
1306: case 'r': /* raw */
1307: match_comma(); mark.raw = analyseur;
1308: bp = init_buf(256, &buf,&limit);
1309: while (*analyseur)
1310: {
1311: if (*analyseur == ',' || *analyseur == ')') break;
1312: if (*analyseur == '"')
1313: bp = readstring_i(bp, &buf,&limit);
1314: else
1315: {
1316: if (bp > limit)
1317: bp = realloc_buf(bp,1, &buf,&limit);
1318: *bp++ = *analyseur++;
1319: }
1320: }
1321: *bp++ = 0; argvec[i++] = (GEN) buf;
1322: break;
1323:
1324: case 's': /* expanded string; empty arg yields "" */
1325: match_comma();
1326: if (*s == '*') /* any number of string objects */
1327: {
1328: argvec[i++] = any_string();
1329: s++; break;
1330: }
1331:
1332: bp = init_buf(256, &buf,&limit);
1333: while (*analyseur)
1334: {
1335: if (*analyseur == ',' || *analyseur == ')') break;
1336: if (*analyseur == '"')
1337: bp = readstring_i(bp, &buf,&limit);
1338: else
1339: bp = expand_string(bp, &buf,&limit);
1340: }
1341: *bp++ = 0; argvec[i++] = (GEN)buf;
1342: break;
1343:
1344: case 'p': /* precision */
1345: argvec[i++] = (GEN) prec; break;
1346:
1347: case '=':
1348: match('='); matchcomma = 0; break;
1349:
1350: case 'D': /* Has a default value */
1351: if (do_switch(alright,matchcomma))
1352: switch (*s)
1353: {
1354: case 'G':
1355: case '&':
1356: case 'I':
1357: case 'V': argvec[i++]=DFT_GEN; s++; break;
1358: case 'n': argvec[i++]=DFT_VAR; s++; break;
1359: default:
1360: oldanalyseur = analyseur;
1361: analyseur = s; matchcomma = 0;
1362: while (*s++ != ',');
1363: }
1364: else
1365: switch (*s)
1366: {
1367: case 'G':
1368: case '&':
1369: case 'I':
1370: case 'V':
1371: case 'n': break;
1372: default:
1373: while (*s++ != ',');
1374: }
1375: break;
1376:
1377: case 'P': /* series precision */
1378: argvec[i++] = (GEN) precdl; break;
1379:
1380: case 'f': /* Fake *long argument */
1381: argvec[i++] = (GEN) &fake; break;
1382:
1383: case 'x': /* Foreign function */
1384: argvec[i++] = (GEN) ep; call = foreignHandler; break;
1385:
1386: case 'l': /* Return long */
1387: ret = RET_INT; break;
1388:
1389: case 'v': /* Return void */
1390: ret = RET_VOID; break;
1391:
1392: case ',': /* Clean up default */
1393: if (oldanalyseur)
1394: {
1395: analyseur = oldanalyseur;
1396: oldanalyseur = NULL; matchcomma=1;
1397: }
1398: break;
1399: default: err(bugparier,"identifier (unknown code)");
1400: }
1401: #if 0 /* uncomment if using purify: unitialized read otherwise */
1402: for ( ; i<9; i++) argvec[i]=NULL;
1403: #endif
1404: switch (ret)
1405: {
1406: case RET_GEN:
1407: res = ((PFGEN)call)(argvec[0], argvec[1], argvec[2], argvec[3],
1408: argvec[4], argvec[5], argvec[6], argvec[7], argvec[8]);
1409: break;
1410:
1411: case RET_INT:
1412: m = ((long (*)(ANYARG))call)(argvec[0], argvec[1], argvec[2], argvec[3],
1413: argvec[4], argvec[5], argvec[6], argvec[7], argvec[8]);
1414: res = stoi(m); break;
1415:
1416: case RET_VOID:
1417: ((void (*)(ANYARG))call)(argvec[0], argvec[1], argvec[2], argvec[3],
1418: argvec[4], argvec[5], argvec[6], argvec[7], argvec[8]);
1419: res = gnil; break;
1420: }
1421: if (has_pointer) check_pointer(has_pointer,argvec);
1422: if (!alright) match(')');
1423: return res;
1424: }
1425:
1426: if (EpPREDEFINED(ep))
1427: {
1428: if (*analyseur != '(')
1429: {
1430: if (EpVALENCE(ep) == 88) return global0();
1431: match('('); /* error */
1432: }
1433: analyseur++;
1434: switch(EpVALENCE(ep))
1435: {
1436: case 50: /* O */
1437: res = truc();
1438: if (br_status) err(breaker,"here (in O()))");
1439: if (*analyseur=='^') { analyseur++; m = readlong(); } else m = 1;
1440: res = ggrando(res,m); break;
1441:
1442: case 80: /* if then else */
1443: av = avma; res = expr();
1444: if (br_status) err(breaker,"test expressions");
1445: m = gcmp0(res); avma = av; match(',');
1446: if (m) /* false */
1447: {
1448: skipseq();
1449: if (*analyseur == ')') res = gnil;
1450: else
1451: {
1452: match(',');
1453: res = seq(); if (br_status) { res = NULL; skipseq(); }
1454: }
1455: }
1456: else /* true */
1457: {
1458: res = seq(); if (br_status) { res = NULL; skipseq(); }
1459: if (*analyseur != ')') { match(','); skipseq(); }
1460: }
1461: break;
1462:
1463: case 81: /* while do */
1464: av = avma; ch1 = analyseur;
1465: for(;;)
1466: {
1467: res = expr();
1468: if (br_status) err(breaker,"test expressions");
1469: if (gcmp0(res)) { match(','); break; }
1470:
1471: avma = av; match(','); (void)seq();
1472: if (loop_break()) break;
1473: analyseur = ch1;
1474: }
1475: avma = av; skipseq(); res = gnil; break;
1476:
1477: case 82: /* repeat until */
1478: av = avma; ch1 = analyseur; skipexpr();
1479: for(;;)
1480: {
1481: avma = av; match(','); (void)seq();
1482: if (loop_break()) break;
1483: analyseur = ch1;
1484: res = expr();
1485: if (br_status) err(breaker,"test expressions");
1486: if (!gcmp0(res)) { match(','); break; }
1487: }
1488: avma = av; skipseq(); res = gnil; break;
1489:
1490: case 88: /* global */
1491: if (*analyseur == ')') return global0();
1492: while (*analyseur != ')')
1493: {
1494: match_comma(); ch1=analyseur;
1495: ep = skipentry();
1496: switch(EpVALENCE(ep))
1497: {
1498: case EpGVAR:
1499: err(warner,"%s already declared global", ep->name);
1500: /* fall through */
1501: case EpVAR: break;
1502: default: err(talker2,"symbol already in use",ch1,mark.start);
1503: }
1504: analyseur=ch1; ep = entry();
1505: if (*analyseur == '=')
1506: {
1507: long av=avma; analyseur++;
1508: res = expr();
1509: if (br_status) err(breaker,"here (defining global var)");
1510: changevalue(ep, res); avma=av;
1511: }
1512: ep->valence = EpGVAR;
1513: }
1514: res = gnil; break;
1515:
1516: default: err(valencer1);
1517: }
1518: match(')'); return res;
1519: }
1520:
1521: switch (EpVALENCE(ep))
1522: {
1523: GEN *defarg; /* = default args, and values for local variables */
1524: int narg, nloc;
1525: gp_args *f;
1526:
1527: case EpUSER: /* user-defined functions */
1528: f = (gp_args*)ep->args;
1529: defarg = f->arg;
1530: narg = f->narg;
1531: nloc = f->nloc;
1532: if (*analyseur != '(') /* no args */
1533: {
1534: if (*analyseur != '=' || analyseur[1] == '=')
1535: return call_fun((GEN)ep->value, defarg, defarg+narg, narg, nloc);
1536: match('('); /* ==> error */
1537: }
1538: if (analyseur != redefine_fun)
1539: {
1540: GEN *arglist = (GEN*) new_chunk(narg);
1541: ch1 = analyseur; analyseur++;
1542: for (i=0; i<narg; i++)
1543: {
1544: if (do_switch(0,matchcomma))
1545: { matchcomma=1 ; arglist[i] = defarg[i]; } /* default arg */
1546: else
1547: { /* user supplied */
1548: match_comma(); res = expr();
1549: if (br_status) err(breaker,"here (reading function args)");
1550: arglist[i] = res;
1551: }
1552: }
1553: if (*analyseur++ == ')' && (*analyseur != '=' || analyseur[1] == '='))
1554: return call_fun((GEN)ep->value, arglist, defarg+narg, narg, nloc);
1555:
1556: /* should happen only in cases like (f()= f()=); f (!!!) */
1557: analyseur--;
1558: if (*analyseur != ',' && *analyseur != ')') skipexpr();
1559: while (*analyseur == ',') { analyseur++; skipexpr(); }
1560: match(')');
1561: if (*analyseur != '=' || analyseur[1] == '=')
1562: err(nparamer1,mark.identifier,mark.start);
1563: matchcomma=0; analyseur = ch1;
1564: }
1565: redefine_fun = NULL;
1566: free_args((gp_args*)ep->args);
1567: /* Fall through */
1568:
1569: case EpNEW: /* new function */
1570: {
1571: GEN tmpargs = (GEN)avma;
1572: char *start;
1573: long len;
1574:
1575: check_new_fun = ep;
1576:
1577: /* checking arguments */
1578: match('('); ch1 = analyseur;
1579: narg = check_args(); nloc = 0;
1580: match(')'); match('=');
1581: while (strncmp(analyseur,"local(",6) == 0)
1582: {
1583: analyseur += 6;
1584: nloc += check_args();
1585: match(')'); while(separe(*analyseur)) analyseur++;
1586: }
1587: { /* checking function definition */
1588: char *oldredef = redefine_fun;
1589: skipping_fun_def++;
1590: start = analyseur; skipseq(); len = analyseur-start;
1591: skipping_fun_def--; redefine_fun = oldredef;
1592: }
1593: /* function is ok. record it */
1594: newfun = ptr = (GEN) newbloc(narg+nloc + (len>>TWOPOTBYTES_IN_LONG) + 4);
1595: newfun++; /* this bloc is no GEN, leave the first cell alone ( = 0) */
1596:
1597: /* record default args */
1598: f = (gp_args*) gpmalloc((narg+nloc)*sizeof(GEN) + sizeof(gp_args));
1599: ep->args = (void*) f;
1600: f->nloc = nloc;
1601: f->narg = narg;
1602: f->arg = defarg = (GEN*)(f + 1);
1603: narg += nloc; /* record default args and local variables */
1604: for (i = 1; i <= narg; i++)
1605: {
1606: GEN cell = tmpargs-(i<<1);
1607: *newfun++ = cell[0];
1608: *defarg++ = (GEN)cell[1];
1609: }
1610: if (narg > 1)
1611: { /* check for duplicates */
1612: GEN x = new_chunk(narg), v = ptr+1;
1613: long k;
1614: for (i=0; i<narg; i++) x[i] = v[i];
1615: qsort(x,narg,sizeof(long),(QSCOMP)pari_compare_long);
1616: for (k=x[0],i=1; i<narg; k=x[i],i++)
1617: if (x[i] == k)
1618: err(talker,"user function %s: variable %Z declared twice",
1619: ep->name, polx[k]);
1620: }
1621:
1622: /* record text */
1623: strncpy((char *)newfun, start, len);
1624: ((char *) newfun)[len] = 0;
1625: if (EpVALENCE(ep) == EpUSER) gunclone((GEN)ep->value);
1626: /* have to wait till here because of the above line. (f()=f()=x). Text
1627: * of new fun is given by value of the old one, which had to be kept
1628: */
1629: ep->value = (void *)ptr;
1630: ep->valence = EpUSER;
1631: check_new_fun=NULL;
1632: avma = (long)tmpargs; return gnil;
1633: }
1634: }
1635: err(valencer1); return NULL; /* not reached */
1636: }
1637:
1638: static long
1639: number(long *nb)
1640: {
1641: long m = 0;
1642: for (*nb = 0; *nb < 9 && isdigit((int)*analyseur); (*nb)++)
1643: m = 10*m + (*analyseur++ - '0');
1644: return m;
1645: }
1646:
1647: static GEN
1648: constante()
1649: {
1650: static long pw10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000,
1651: 10000000, 100000000, 1000000000 };
1652: long l,m,n = 0,nb, av = avma, limite = stack_lim(av,1);
1653: GEN z,y;
1654:
1655: y = stoi(number(&nb));
1656: while (isdigit((int)*analyseur))
1657: {
1658: m = number(&nb);
1659: y = addsi(m, mulsi(pw10[nb],y));
1660: if (low_stack(limite, stack_lim(av,1))) y = gerepileupto(av,y);
1661: }
1662: switch(*analyseur)
1663: {
1664: default: return y; /* integer */
1665: case '.':
1666: analyseur++;
1667: while (isdigit((int)*analyseur))
1668: {
1669: m = number(&nb); n -= nb;
1670: y = addsi(m, mulsi(pw10[nb],y));
1671: if (low_stack(limite, stack_lim(av,1))) y = gerepileupto(av,y);
1672: }
1673: if (*analyseur != 'E' && *analyseur != 'e') break;
1674: /* Fall through */
1675: case 'E': case 'e':
1676: {
1677: char *old = analyseur;
1678: switch(*++analyseur)
1679: {
1680: case '-': analyseur++; n -= number(&nb); break;
1681: case '+': analyseur++; /* Fall through */
1682: default: n += number(&nb);
1683: }
1684: if (nb > 8) err(talker2,"exponent too large: ",old,mark.start);
1685: }
1686: }
1687: l=lgefint(y); if (l<prec) l=prec;
1688: if (n)
1689: {
1690: new_chunk(l); /* hack: mulrr and divrr need exactly l words */
1691: z=cgetr(l); affir(y,z);
1692: y=cgetr(l); affsr(10,y); y = gpuigs(y, labs(n));
1693: avma = av; /* hidden gerepile */
1694: return n > 0 ? mulrr(z,y) : divrr(z,y);
1695: }
1696: z=cgetr(l); affir(y,z); return z;
1697: }
1698:
1699: /********************************************************************/
1700: /** **/
1701: /** HASH TABLE MANIPULATIONS **/
1702: /** **/
1703: /********************************************************************/
1704: /* slighlty more efficient than is_keyword_char. Not worth a static array. */
1705: #define is_key(c) (isalnum((int)(c)) || (c)=='_')
1706:
1707: long
1708: is_keyword_char(char c) { return is_key(c); }
1709:
1710: /* return hashing value for identifier s (analyseur is s = NULL) */
1711: long
1712: hashvalue(char *s)
1713: {
1714: long update, n = 0;
1715:
1716: if (!s) { s = analyseur; update = 1; } else update = 0;
1717: while (is_key(*s)) { n = (n<<1) ^ *s; s++; }
1718: if (update) analyseur = s;
1719: if (n < 0) n = -n;
1720: return n % functions_tblsz;
1721: }
1722:
1723: /* Looking for entry in hashtable. ep1 is the cell's first element */
1724: static entree *
1725: findentry(char *name, long len, entree *ep1)
1726: {
1727: entree *ep;
1728:
1729: for (ep = ep1; ep; ep = ep->next)
1730: if (!strncmp(ep->name, name, len) && !(ep->name)[len]) return ep;
1731:
1732: if (foreignAutoload) /* Try to autoload. */
1733: return foreignAutoload(name, len);
1734: return NULL; /* not found */
1735: }
1736:
1737: entree *
1738: is_entry_intern(char *s, entree **table, long *pthash)
1739: {
1740: char *old = analyseur;
1741: long hash, len;
1742:
1743: analyseur = s; hash = hashvalue(NULL);
1744: len = analyseur - s; analyseur = old;
1745: if (pthash) *pthash = hash;
1746: return findentry(s,len,table[hash]);
1747: }
1748:
1749: int
1750: is_identifier(char *s)
1751: {
1752: while (*s && is_keyword_char(*s)) s++;
1753: return *s? 0: 1;
1754: }
1755:
1756: static entree *
1757: installep(void *f, char *name, int len, int valence, int add, entree **table)
1758: {
1759: entree *ep = (entree *) gpmalloc(sizeof(entree) + add + len+1);
1760: const entree *ep1 = initial_value(ep);
1761: char *u = (char *) ep1 + add;
1762:
1763: ep->name = u; strncpy(u, name,len); u[len]=0;
1764: ep->args = NULL; ep->help = NULL; ep->code = NULL;
1765: ep->value = f? f: (void *) ep1;
1766: ep->next = *table;
1767: ep->valence = valence;
1768: ep->menu = 0;
1769: return *table = ep;
1770: }
1771:
1772: long
1773: manage_var(long n, entree *ep)
1774: {
1775: static long max_avail = MAXVARN; /* first user variable not yet used */
1776: static long nvar; /* first GP free variable */
1777: long var;
1778: GEN p;
1779:
1780: if (n) /* special behaviour */
1781: {
1782: switch(n)
1783: {
1784: case 2: return nvar=0;
1785: case 3: return nvar;
1786: case 4: return max_avail;
1787: case 5:
1788: {
1789: long v = (long)ep;
1790: if (v != nvar-1) err(talker,"can't pop gp variable");
1791: setlg(polvar, nvar);
1792: return --nvar;
1793: }
1794: }
1795:
1796: /* user wants to delete one of his/her/its variables */
1797: if (max_avail == MAXVARN-1) return 0; /* nothing to delete */
1798: free(polx[++max_avail]); /* frees both polun and polx */
1799: return max_avail+1;
1800: }
1801:
1802: if (nvar == max_avail) err(talker2,"no more variables available",
1803: mark.identifier, mark.start);
1804: if (ep)
1805: {
1806: p = (GEN)ep->value;
1807: var=nvar++;
1808: }
1809: else
1810: {
1811: p = (GEN) gpmalloc(7*sizeof(long));
1812: var=max_avail--;
1813: }
1814:
1815: /* create polx[var] */
1816: p[0] = evaltyp(t_POL) | evallg(4);
1817: p[1] = evalsigne(1) | evallgef(4) | evalvarn(var);
1818: p[2] = zero; p[3] = un;
1819: polx[var] = p;
1820:
1821: /* create polun[nvar] */
1822: p += 4;
1823: p[0] = evaltyp(t_POL) | evallg(3);
1824: p[1] = evalsigne(1) | evallgef(3) | evalvarn(var);
1825: p[2] = un;
1826: polun[var] = p;
1827:
1828: varentries[var] = ep;
1829: if (ep) { polvar[nvar] = (long) ep->value; setlg(polvar, nvar+1); }
1830: return var;
1831: }
1832:
1833: long
1834: fetch_var()
1835: {
1836: return manage_var(0,NULL);
1837: }
1838:
1839: entree *
1840: fetch_named_var(char *s, int doerr)
1841: {
1842: entree *ep = is_entry(s);
1843: if (ep)
1844: {
1845: if (doerr) err(talker,"identifier already in use: %s", s);
1846: return ep;
1847: }
1848: ep = installep(NULL,s,strlen(s),EpVAR, 7*sizeof(long),
1849: functions_hash + hashvalue(s));
1850: manage_var(0,ep); return ep;
1851: }
1852:
1853: long
1854: fetch_user_var(char *s)
1855: {
1856: entree *ep = is_entry(s);
1857: long av;
1858: GEN p1;
1859:
1860: if (ep)
1861: {
1862: switch (EpVALENCE(ep))
1863: {
1864: case EpVAR: case EpGVAR:
1865: return varn(initial_value(ep));
1866: }
1867: err(talker, "%s already exists with incompatible valence", s);
1868: }
1869: av=avma; p1 = lisexpr(s); avma=av;
1870: return varn(p1);
1871: }
1872:
1873: void
1874: delete_named_var(entree *ep)
1875: {
1876: manage_var(5, (entree*)varn(initial_value(ep)));
1877: kill0(ep);
1878: }
1879:
1880: long
1881: delete_var()
1882: {
1883: return manage_var(1,NULL);
1884: }
1885:
1886: void
1887: name_var(long n, char *s)
1888: {
1889: entree *ep;
1890: char *u;
1891:
1892: if (n < manage_var(3,NULL))
1893: err(talker, "renaming a GP variable is forbidden");
1894: if (n > MAXVARN)
1895: err(talker, "variable number too big");
1896:
1897: ep = (entree*)gpmalloc(sizeof(entree) + strlen(s) + 1);
1898: u = (char *)initial_value(ep);
1899: ep->valence = EpVAR;
1900: ep->name = u; strcpy(u,s);
1901: ep->value = gzero; /* in case geval would be called */
1902: if (varentries[n]) free(varentries[n]);
1903: varentries[n] = ep;
1904: }
1905:
1906: /* Find entry or create it */
1907: static entree *
1908: entry(void)
1909: {
1910: char *old = analyseur;
1911: const long hash = hashvalue(NULL), len = analyseur - old;
1912: entree *ep = findentry(old,len,functions_hash[hash]);
1913: long val,n;
1914:
1915: if (ep) return ep;
1916: if (compatible == WARN)
1917: {
1918: ep = findentry(old,len,funct_old_hash[hash]);
1919: if (ep) return ep; /* the warning was done in skipentry() */
1920: }
1921: /* ep does not exist. Create it */
1922: if (*analyseur == '(')
1923: { n=0; val=EpNEW; }
1924: else
1925: { n=7*sizeof(long); val=EpVAR; }
1926: ep = installep(NULL,old,len,val,n, functions_hash + hash);
1927:
1928: if (n) manage_var(0,ep); /* Variable */
1929: return ep;
1930: }
1931:
1932: /********************************************************************/
1933: /** **/
1934: /** SKIP FUNCTIONS **/
1935: /** **/
1936: /********************************************************************/
1937:
1938: /* as skipseq without modifying analyseur && al */
1939: static void
1940: doskipseq(char *c, int strict)
1941: {
1942: char *olds = analyseur;
1943:
1944: mark.start = c; analyseur = c; skipseq();
1945: if (*analyseur)
1946: {
1947: if (strict) err(talker2,"unused characters", analyseur, c);
1948: err(warner, "unused characters: %s", analyseur);
1949: }
1950: analyseur = olds;
1951: }
1952:
1953: static void
1954: skipstring()
1955: {
1956: match('"');
1957: while (*analyseur)
1958: switch (*analyseur++)
1959: {
1960: case '"': return;
1961: case '\\': analyseur++;
1962: }
1963: match('"');
1964: }
1965:
1966: static void
1967: skip_matrix_block(int no_affect)
1968: {
1969: while (*analyseur == '[')
1970: {
1971: analyseur++;
1972: if (*analyseur == ',') { analyseur++; skipexpr(); }
1973: else
1974: {
1975: skipexpr();
1976: if (*analyseur == ',')
1977: if (*++analyseur != ']') skipexpr();
1978: }
1979: match(']');
1980: }
1981:
1982: if (*analyseur == '=' && analyseur[1] != '=')
1983: {
1984: if (no_affect) err(caracer1,analyseur,mark.start);
1985: analyseur++; skipexpr(); return;
1986: }
1987: if (repeated_op())
1988: {
1989: if (no_affect) err(caracer1,analyseur,mark.start);
1990: analyseur+=2; return;
1991: }
1992: if (!*analyseur) return;
1993: if (analyseur[1] != '=')
1994: {
1995: switch(*analyseur)
1996: {
1997: case '>': case '<':
1998: if (analyseur[1] != *analyseur || analyseur[2] != '=') return;
1999: if (no_affect) err(caracer1,analyseur,mark.start);
2000: analyseur+=3; skipexpr(); return;
2001: case '\\':
2002: if (analyseur[1] != '/' || analyseur[2] != '=') return;
2003: if (no_affect) err(caracer1,analyseur,mark.start);
2004: analyseur+=3; skipexpr(); return;
2005: }
2006: return;
2007: }
2008:
2009: switch(*analyseur)
2010: {
2011: case '+': case '-': case '*': case '/': case '\\': case '%':
2012: if (no_affect) err(caracer1,analyseur,mark.start);
2013: analyseur+=2; skipexpr(); return;
2014: }
2015: }
2016:
2017: static void
2018: skipseq(void)
2019: {
2020: for(;;)
2021: {
2022: while (separe(*analyseur)) analyseur++;
2023: if (*analyseur == ',' || *analyseur == ')' || !*analyseur) return;
2024: skipexpr(); if (!separe(*analyseur)) return;
2025: }
2026: }
2027:
2028: static void
2029: skipexpr(void)
2030: {
2031: int e1 = 0, e2 = 0, e3;
2032:
2033: L3:
2034: e3=1; skipfacteur();
2035: switch(*analyseur)
2036: {
2037: case '*': case '/': case '%':
2038: analyseur++; goto L3;
2039: case '\\':
2040: if (*++analyseur == '/') analyseur++;
2041: goto L3;
2042: case '<': case '>':
2043: if (analyseur[1]==*analyseur) { analyseur +=2; goto L3; }
2044: }
2045:
2046: L2:
2047: if (!e3) goto L3;
2048: e3=0; e2=1;
2049: switch(*analyseur)
2050: {
2051: case '+': case '-':
2052: analyseur++; goto L3;
2053: }
2054:
2055: L1:
2056: if (!e2) goto L2;
2057: e2=0; e1=1;
2058: switch(*analyseur)
2059: {
2060: case '<':
2061: switch(*++analyseur)
2062: {
2063: case '=': case '>': analyseur++;
2064: }
2065: goto L2;
2066:
2067: case '>':
2068: if (*++analyseur == '=') analyseur++;
2069: goto L2;
2070:
2071: case '=': case '!':
2072: if (analyseur[1] == '=') { analyseur+=2; goto L2; }
2073: goto L1;
2074: }
2075:
2076: /* L0: */
2077: if (!e1) goto L1;
2078: e1=0;
2079: switch(*analyseur)
2080: {
2081: case '&':
2082: if (*++analyseur == '&') analyseur++;
2083: goto L1;
2084: case '|':
2085: if (*++analyseur == '|') analyseur++;
2086: goto L1;
2087: }
2088: }
2089:
2090: static void
2091: skipfacteur(void)
2092: {
2093: if (*analyseur == '+' || *analyseur == '-') analyseur++;
2094: skiptruc();
2095: for(;;)
2096: switch(*analyseur)
2097: {
2098: case '.':
2099: analyseur++; while (isalnum((int)*analyseur)) analyseur++;
2100: if (*analyseur == '=' && analyseur[1] != '=')
2101: { analyseur++; skipseq(); }
2102: break;
2103: case '^':
2104: analyseur++; skipfacteur(); break;
2105: case '~': case '\'':
2106: analyseur++; break;
2107: case '[':
2108: skip_matrix_block(1); break;
2109: case '!':
2110: if (analyseur[1] != '=') { analyseur++; break; }
2111: default: return;
2112: }
2113: }
2114:
2115: /* return the number of elements we need to read if array/matrix */
2116: static long
2117: skiptruc(void)
2118: {
2119: long n=0;
2120: char *old;
2121:
2122: if (*analyseur == '"') { skipstring(); return 0; }
2123: if (*analyseur == '!') { analyseur++; skiptruc(); return 0; }
2124: if (*analyseur == '\'')
2125: {
2126: analyseur++; check_var_name();
2127: skipentry(); return 0;
2128: }
2129: if (isalpha((int)*analyseur))
2130: { skipidentifier(); return 0; }
2131: if (isdigit((int)*analyseur) || *analyseur== '.')
2132: { skipconstante(); return 0; }
2133: switch(*analyseur++)
2134: {
2135: case '(':
2136: skipexpr(); match(')'); return 0;
2137: case '[':
2138: old = analyseur-1;
2139: if (*analyseur == ';' && analyseur[1] == ']') /* 0 x 0 matrix */
2140: { analyseur+=2; return 0; }
2141: if (*analyseur != ']')
2142: {
2143: do { n++; skipexpr(); old=analyseur; }
2144: while (*analyseur++ == ',');
2145: analyseur--;
2146: }
2147: switch (*analyseur)
2148: {
2149: case ']': analyseur++; return n;
2150: case ';':
2151: {
2152: long m, norig=n; /* number of elts in first line */
2153: old=analyseur;
2154: do {
2155: m=n;
2156: do { n++; analyseur++; skipexpr(); }
2157: while (*analyseur != ';' && *analyseur != ']');
2158: if (n-m != norig)
2159: err(talker2,"non rectangular matrix",old,mark.start);
2160: } while (*analyseur != ']');
2161: analyseur++; return n;
2162: }
2163: default:
2164: err(talker2,"; or ] expected",old,mark.start);
2165: return 0; /* not reached */
2166: }
2167: case '%':
2168: if (*analyseur == '`') { while (*++analyseur == '`'); return 0; }
2169: number(&n); return 0;
2170: }
2171: err(caracer1,analyseur-1,mark.start);
2172: return 0; /* not reached */
2173: }
2174:
2175: static void
2176: check_var()
2177: {
2178: char *old = analyseur;
2179: check_var_name();
2180: switch(EpVALENCE(skipentry()))
2181: {
2182: case EpVAR: break;
2183: case EpGVAR:
2184: err(talker2,"global variable not allowed", old,mark.start);
2185: default: err(varer1,old,mark.start);
2186: }
2187: }
2188:
2189: static void
2190: skipidentifier(void)
2191: {
2192: int matchcomma=0;
2193: entree *ep;
2194: char *old;
2195:
2196: mark.identifier = analyseur; ep = do_alias(skipentry());
2197: if (ep->code)
2198: {
2199: char *s = ep->code;
2200:
2201: if (*analyseur != '(')
2202: {
2203: if (EpVALENCE(ep) == 0) return; /* no mandatory argument */
2204: match('('); /* ==> error */
2205: }
2206: analyseur++;
2207:
2208: /* Optimized for G and p. */
2209: while (*s == 'G') { match_comma(); skipexpr(); s++; }
2210: if (*s == 'p') s++;
2211: while (*s) switch (*s++)
2212: {
2213: case 'G': case 'n': case 'L':
2214: match_comma();
2215: if (*analyseur == ',' || *analyseur == ')') break;
2216: skipexpr(); break;
2217: case 'I':
2218: match_comma(); skipseq(); break;
2219: case 'r':
2220: match_comma();
2221: while (*analyseur)
2222: {
2223: while (*analyseur == '"') skipstring();
2224: if (*analyseur == ',' || *analyseur == ')') break;
2225: analyseur++;
2226: }
2227: break;
2228: case 's':
2229: match_comma();
2230: if (*s == '*')
2231: {
2232: while (*analyseur)
2233: {
2234: while (*analyseur == '"') skipstring();
2235: if (*analyseur == ')') break;
2236: if (*analyseur == ',') analyseur++;
2237: else skipexpr();
2238: }
2239: s++; if (*s == 'p' || *s == 't') s++;
2240: break;
2241: }
2242:
2243: while (*analyseur)
2244: {
2245: while (*analyseur == '"') skipstring();
2246: if (*analyseur == ')' || *analyseur == ',') break;
2247: skipexpr();
2248: }
2249: break;
2250:
2251: case 'S': match_comma();
2252: check_var_name(); skipentry(); break;
2253: case '&': match_comma(); match('&'); check_var(); break;
2254: case 'V': match_comma(); check_var(); break;
2255:
2256: case 'p': case 'P': case 'l': case 'v': case 'f': case 'x':
2257: break;
2258:
2259: case 'D':
2260: if ( *analyseur == ')' ) { analyseur++; return; }
2261: if (*s == 'G' || *s == '&' || *s == 'n' || *s == 'I' || *s == 'V')
2262: break;
2263: while (*s++ != ',');
2264: break;
2265: case '=':
2266: match('='); matchcomma = 0; break;
2267: case ',':
2268: matchcomma=1; break;
2269: default:
2270: err(bugparier,"skipidentifier (unknown code)");
2271: }
2272: match(')');
2273: return;
2274: }
2275: if (EpPREDEFINED(ep))
2276: {
2277: if (*analyseur != '(')
2278: {
2279: switch(EpVALENCE(ep))
2280: {
2281: case 0:
2282: case 88: return;
2283: }
2284: match('('); /* error */
2285: }
2286: analyseur++;
2287: switch(EpVALENCE(ep))
2288: {
2289: case 50: skiptruc();
2290: if (*analyseur == '^') { analyseur++; skipfacteur(); };
2291: break;
2292: case 80: skipexpr(); match(','); skipseq();
2293: if (*analyseur != ')') { match(','); skipseq(); }
2294: break;
2295: case 81: case 82: skipexpr(); match(','); skipseq(); break;
2296: case 88:
2297: while (*analyseur != ')') { match_comma(); skipexpr(); };
2298: break;
2299: default: err(valencer1);
2300: }
2301: match(')'); return;
2302: }
2303: switch (EpVALENCE(ep))
2304: {
2305: case EpGVAR:
2306: case EpVAR: /* variables */
2307: skip_matrix_block(0); return;
2308:
2309: case EpUSER: /* fonctions utilisateur */
2310: {
2311: char *ch1 = analyseur;
2312: gp_args *f;
2313: int i;
2314:
2315: if (*analyseur != '(')
2316: {
2317: if ( *analyseur != '=' || analyseur[1] == '=' ) return;
2318: match('('); /* error */
2319: }
2320: f = (gp_args*)ep->args;
2321: analyseur++; /* skip '(' */
2322: for (i = f->nloc + f->narg; i; i--)
2323: {
2324: if (do_switch(0,matchcomma)) matchcomma=1;
2325: else { match_comma(); skipexpr(); }
2326: }
2327:
2328: if (*analyseur == ')')
2329: if ( analyseur[1] != '=' || analyseur[2] == '=' )
2330: { analyseur++; return; }
2331:
2332: /* here we are redefining a user function */
2333: old = analyseur;
2334: if (*analyseur != ',' && *analyseur != ')') skipexpr();
2335: while (*analyseur == ',') { analyseur++; skipexpr(); }
2336: match(')');
2337:
2338: if (*analyseur != '=' || analyseur[1] == '=')
2339: {
2340: if (skipping_fun_def) return;
2341: err(nparamer1,old,mark.start);
2342: }
2343: analyseur = ch1; matchcomma = 0;
2344: if (!redefine_fun) redefine_fun = analyseur;
2345: } /* fall through */
2346:
2347: case EpNEW: /* new function */
2348: if (check_new_fun && ! skipping_fun_def)
2349: {
2350: err_new_fun(); /* ep not created yet: no need to kill it */
2351: err(paramer1, mark.identifier, mark.start);
2352: }
2353: check_new_fun = NOT_CREATED_YET; match('(');
2354: while (*analyseur != ')') { match_comma(); skipexpr(); };
2355: match(')');
2356: if (*analyseur == '=')
2357: {
2358: skipping_fun_def++;
2359: analyseur++; skipseq();
2360: skipping_fun_def--;
2361: }
2362: check_new_fun=NULL; return;
2363:
2364: default: err(valencer1);
2365: }
2366: }
2367:
2368: static void
2369: skipconstante(void)
2370: {
2371: while (isdigit((int)*analyseur)) analyseur++;
2372: if ( *analyseur!='.' && *analyseur!='e' && *analyseur!='E' ) return;
2373: if (*analyseur=='.') analyseur++;
2374: while (isdigit((int)*analyseur)) analyseur++;
2375: if ( *analyseur=='e' || *analyseur=='E' )
2376: {
2377: analyseur++;
2378: if ( *analyseur=='+' || *analyseur=='-' ) analyseur++;
2379: while (isdigit((int)*analyseur)) analyseur++;
2380: }
2381: }
2382:
2383: static entree *
2384: skipentry(void)
2385: {
2386: static entree fakeEpNEW = { "",EpNEW };
2387: static entree fakeEpVAR = { "",EpVAR };
2388: char *old = analyseur;
2389: const long hash = hashvalue(NULL), len = analyseur - old;
2390: entree *ep = findentry(old,len,functions_hash[hash]);
2391:
2392: if (ep) return ep;
2393: if (compatible == WARN)
2394: {
2395: ep = findentry(old,len,funct_old_hash[hash]);
2396: if (ep)
2397: {
2398: err(warner,"using obsolete function %s",ep->name);
2399: return ep;
2400: }
2401: }
2402: return (*analyseur == '(') ? &fakeEpNEW : &fakeEpVAR;
2403: }
2404:
2405: /********************************************************************/
2406: /** **/
2407: /** MEMBER FUNCTIONS **/
2408: /** **/
2409: /********************************************************************/
2410: static GEN
2411: e(GEN x)
2412: {
2413: x = get_primeid(x);
2414: if (!x) err(member,"e",mark.member,mark.start);
2415: return (GEN)x[3];
2416: }
2417:
2418: static GEN
2419: f(GEN x)
2420: {
2421: x = get_primeid(x);
2422: if (!x) err(member,"f",mark.member,mark.start);
2423: return (GEN)x[4];
2424: }
2425:
2426: static GEN
2427: p(GEN x)
2428: {
2429: x = get_primeid(x);
2430: if (!x) err(member,"p",mark.member,mark.start);
2431: return (GEN)x[1];
2432: }
2433:
2434: static GEN
2435: bnf(GEN x)
2436: {
2437: int t; x = get_bnf(x,&t);
2438: if (!x) err(member,"bnf",mark.member,mark.start);
2439: return x;
2440: }
2441:
2442: static GEN
2443: nf(GEN x)
2444: {
2445: int t; x = get_nf(x,&t);
2446: if (!x) err(member,"nf",mark.member,mark.start);
2447: return x;
2448: }
2449:
2450: /* integral basis */
2451: static GEN
2452: zk(GEN x)
2453: {
2454: int t; GEN y = get_nf(x,&t);
2455: if (!y)
2456: {
2457: switch(t)
2458: {
2459: case typ_CLA: return gmael(x,1,4);
2460: case typ_Q: y = cgetg(3,t_VEC);
2461: y[1]=un; y[2]=lpolx[varn(x[1])]; return y;
2462: }
2463: err(member,"zk",mark.member,mark.start);
2464: }
2465: return (GEN)y[7];
2466: }
2467:
2468: static GEN
2469: disc(GEN x) /* discriminant */
2470: {
2471: int t; GEN y = get_nf(x,&t);
2472: if (!y)
2473: {
2474: switch(t)
2475: {
2476: case typ_Q : return discsr((GEN)x[1]);
2477: case typ_CLA: return gmael3(x,1,3,1);
2478: case typ_ELL: return (GEN)x[12];
2479: }
2480: err(member,"disc",mark.member,mark.start);
2481: }
2482: return (GEN)y[3];
2483: }
2484:
2485: static GEN
2486: pol(GEN x) /* polynomial */
2487: {
2488: int t; GEN y = get_nf(x,&t);
2489: if (!y)
2490: {
2491: switch(t)
2492: {
2493: case typ_CLA: return gmael(x,1,1);
2494: case typ_POL: return x;
2495: case typ_Q : return (GEN)x[1];
2496: }
2497: if (typ(x)==t_POLMOD) return (GEN)x[2];
2498: err(member,"pol",mark.member,mark.start);
2499: }
2500: return (GEN)y[1];
2501: }
2502:
2503: static GEN
2504: mod(GEN x) /* modulus */
2505: {
2506: switch(typ(x))
2507: {
2508: case t_INTMOD: case t_POLMOD: case t_QUAD: break;
2509: default: err(member,"mod",mark.member,mark.start);
2510: }
2511: return (GEN)x[1];
2512: }
2513:
2514: static GEN
2515: sign(GEN x) /* signature */
2516: {
2517: int t; GEN y = get_nf(x,&t);
2518: if (!y)
2519: {
2520: if (t == typ_CLA) return gmael(x,1,2);
2521: err(member,"sign",mark.member,mark.start);
2522: }
2523: return (GEN)y[2];
2524: }
2525:
2526: static GEN
2527: t2(GEN x) /* T2 matrix */
2528: {
2529: int t; x = get_nf(x,&t);
2530: if (!x) err(member,"t2",mark.member,mark.start);
2531: return gmael(x,5,3);
2532: }
2533:
2534: static GEN
2535: diff(GEN x) /* different */
2536: {
2537: int t; x = get_nf(x,&t);
2538: if (!x) err(member,"diff",mark.member,mark.start);
2539: return gmael(x,5,5);
2540: }
2541:
2542: static GEN
2543: codiff(GEN x) /* codifferent */
2544: {
2545: int t; x = get_nf(x,&t);
2546: if (!x) err(member,"codiff",mark.member,mark.start);
2547: return gdiv(gmael(x,5,7), absi((GEN) x[3]));
2548: }
2549:
2550: static GEN
2551: mroots(GEN x) /* roots */
2552: {
2553: int t; GEN y = get_nf(x,&t);
2554: if (!y)
2555: {
2556: if (t == typ_ELL) return (GEN)x[14];
2557: err(member,"roots",mark.member,mark.start);
2558: }
2559: return (GEN)y[6];
2560: }
2561:
2562: static GEN
2563: clgp(GEN x) /* class group (3-component row vector) */
2564: {
2565: int t; GEN y = get_bnf(x,&t);
2566: if (!y)
2567: {
2568: switch(t)
2569: {
2570: case typ_QUA:
2571: y = cgetg(4,t_VEC);
2572: for(t=1; t<4; t++) y[t] = x[t];
2573: return y;
2574: case typ_CLA: return gmael(x,1,5);
2575: }
2576: if (typ(x)==t_VEC)
2577: switch(lg(x))
2578: {
2579: case 3: /* no gen */
2580: case 4: return x;
2581: }
2582: err(member,"clgp",mark.member,mark.start);
2583: }
2584: if (t==typ_BNR) return (GEN)x[5];
2585: return gmael(y,8,1);
2586: }
2587:
2588: static GEN
2589: reg(GEN x) /* regulator */
2590: {
2591: int t; GEN y = get_bnf(x,&t);
2592: if (!y)
2593: {
2594: switch(t)
2595: {
2596: case typ_CLA: return gmael(x,1,6);
2597: case typ_QUA: return (GEN)x[4];
2598: }
2599: err(member,"reg",mark.member,mark.start);
2600: }
2601: if (t == typ_BNR) err(impl,"ray regulator");
2602: return gmael(x,8,2);
2603: }
2604:
2605: static GEN
2606: fu(GEN x) /* fundamental units */
2607: {
2608: int t; GEN y = get_bnf(x,&t);
2609: if (!y)
2610: {
2611: switch(t)
2612: {
2613: case typ_CLA: x = (GEN)x[1]; if (lg(x)<11) break;
2614: return (GEN)x[9];
2615: case typ_Q:
2616: x = discsr((GEN)x[1]);
2617: return (signe(x)<0)? cgetg(1,t_VEC): fundunit(x);
2618: }
2619: err(member,"fu",mark.member,mark.start);
2620: }
2621: if (t == typ_BNR) err(impl,"ray units");
2622: return check_units(y,".fu");
2623: }
2624:
2625: /* torsion units. return [w,e] where w is the number of roots of 1, and e a
2626: * polymod generator */
2627: static GEN
2628: tu(GEN x)
2629: {
2630: int t; GEN y = get_bnf(x,&t), res = cgetg(3,t_VEC);
2631: if (!y)
2632: {
2633: switch(t)
2634: {
2635: case typ_Q:
2636: y = discsr((GEN)x[1]);
2637: if (signe(y)<0 && cmpis(y,-4)>=0)
2638: y = stoi((itos(y) == -4)? 4: 6);
2639: else
2640: { y = gdeux; x=negi(gun); }
2641: res[1] = (long)y;
2642: res[2] = (long)x; return res;
2643: case typ_CLA:
2644: if (lg(x[1])==11) break;
2645: default: err(member,"tu",mark.member,mark.start);
2646: }
2647: x = (GEN) x[1]; y=(GEN)x[8];
2648: }
2649: else
2650: {
2651: if (t == typ_BNR) err(impl,"ray torsion units");
2652: x = (GEN)y[7]; y=(GEN)y[8];
2653: if (lg(y) > 5) y = (GEN)y[4];
2654: else
2655: {
2656: y = rootsof1(x);
2657: y[2] = lmul((GEN)x[7], (GEN)y[2]);
2658: }
2659: }
2660: res[2] = y[2];
2661: res[1] = y[1]; return res;
2662: }
2663:
2664: static GEN
2665: futu(GEN x) /* concatenation of fu and tu, w is lost */
2666: {
2667: GEN fuc = fu(x);
2668: return concat(fuc, (GEN)tu(x)[2]);
2669: }
2670:
2671: static GEN
2672: tufu(GEN x) /* concatenation of tu and fu, w is lost */
2673: {
2674: GEN fuc = fu(x);
2675: return concat((GEN) tu(x)[2], fuc);
2676: }
2677:
2678: static GEN
2679: zkst(GEN bid)
2680: /* structure of (Z_K/m)^*, where bid is an idealstarinit (with or without gen)
2681: or a bnrinit (with or without gen) */
2682: {
2683: if (typ(bid)==t_VEC)
2684: switch(lg(bid))
2685: {
2686: case 6: return (GEN) bid[2]; /* idealstarinit */
2687: case 7: return gmael(bid,2,2); /* bnrinit */
2688: }
2689: err(member,"zkst",mark.member,mark.start);
2690: return NULL; /* not reached */
2691: }
2692:
2693: static GEN
2694: no(GEN clg) /* number of elements of a group (of type clgp) */
2695: {
2696: clg = clgp(clg);
2697: if (typ(clg)!=t_VEC || (lg(clg)!=3 && lg(clg)!=4))
2698: err(member,"no",mark.member,mark.start);
2699: return (GEN) clg[1];
2700: }
2701:
2702: static GEN
2703: cyc(GEN clg) /* cyclic decomposition (SNF) of a group (of type clgp) */
2704: {
2705: clg = clgp(clg);
2706: if (typ(clg)!=t_VEC || (lg(clg)!=3 && lg(clg)!=4))
2707: err(member,"cyc",mark.member,mark.start);
2708: return (GEN) clg[2];
2709: }
2710:
2711: /* SNF generators of a group (of type clgp), or generators of a prime
2712: * ideal
2713: */
2714: static GEN
2715: gen(GEN x)
2716: {
2717: GEN y = get_primeid(x);
2718: if (y)
2719: {
2720: x = cgetg(3,t_VEC);
2721: x[1] = lcopy((GEN)y[1]);
2722: x[2] = lcopy((GEN)y[2]);
2723: return x;
2724: }
2725: x = clgp(x);
2726: if (typ(x)!=t_VEC || lg(x)!=4)
2727: err(member,"gen",mark.member,mark.start);
2728: if (typ(x[1]) == t_COL) return (GEN)x[2]; /* from bnfisprincipal */
2729: return (GEN) x[3];
2730: }
2731:
2732: #define is_ell(x) (typ(x) == t_VEC && lg(x)>=14)
2733: #define is_bigell(x) (typ(x) == t_VEC && lg(x)>=20)
2734:
2735: static GEN
2736: a1(GEN x)
2737: {
2738: if (!is_ell(x)) err(member,"a1",mark.member,mark.start);
2739: return (GEN)x[1];
2740: }
2741:
2742: static GEN
2743: a2(GEN x)
2744: {
2745: if (!is_ell(x)) err(member,"a2",mark.member,mark.start);
2746: return (GEN)x[2];
2747: }
2748:
2749: static GEN
2750: a3(GEN x)
2751: {
2752: if (!is_ell(x)) err(member,"a3",mark.member,mark.start);
2753: return (GEN)x[3];
2754: }
2755:
2756: static GEN
2757: a4(GEN x)
2758: {
2759: if (!is_ell(x)) err(member,"a4",mark.member,mark.start);
2760: return (GEN)x[4];
2761: }
2762:
2763: static GEN
2764: a6(GEN x)
2765: {
2766: if (!is_ell(x)) err(member,"a6",mark.member,mark.start);
2767: return (GEN)x[5];
2768: }
2769:
2770: static GEN
2771: b2(GEN x)
2772: {
2773: if (!is_ell(x)) err(member,"b2",mark.member,mark.start);
2774: return (GEN)x[6];
2775: }
2776:
2777: static GEN
2778: b4(GEN x)
2779: {
2780: if (!is_ell(x)) err(member,"b4",mark.member,mark.start);
2781: return (GEN)x[7];
2782: }
2783:
2784: static GEN
2785: b6(GEN x)
2786: {
2787: if (!is_ell(x)) err(member,"b6",mark.member,mark.start);
2788: return (GEN)x[8];
2789: }
2790:
2791: static GEN
2792: b8(GEN x)
2793: {
2794: if (!is_ell(x)) err(member,"b8",mark.member,mark.start);
2795: return (GEN)x[9];
2796: }
2797:
2798: static GEN
2799: c4(GEN x)
2800: {
2801: if (!is_ell(x)) err(member,"c4",mark.member,mark.start);
2802: return (GEN)x[10];
2803: }
2804:
2805: static GEN
2806: c6(GEN x)
2807: {
2808: if (!is_ell(x)) err(member,"c6",mark.member,mark.start);
2809: return (GEN)x[11];
2810: }
2811:
2812: static GEN
2813: j(GEN x)
2814: {
2815: if (!is_ell(x)) err(member,"j",mark.member,mark.start);
2816: return (GEN)x[13];
2817: }
2818:
2819: static GEN
2820: momega(GEN x)
2821: {
2822: GEN y;
2823:
2824: if (!is_bigell(x)) err(member,"omega",mark.member,mark.start);
2825: if (gcmp0((GEN)x[19])) err(talker,"curve not defined over R");
2826: y=cgetg(3,t_VEC); y[1]=x[15]; y[2]=x[16];
2827: return y;
2828: }
2829:
2830: static GEN
2831: meta(GEN x)
2832: {
2833: GEN y;
2834:
2835: if (!is_bigell(x)) err(member,"eta",mark.member,mark.start);
2836: if (gcmp0((GEN)x[19])) err(talker,"curve not defined over R");
2837: y=cgetg(3,t_VEC); y[1]=x[17]; y[2]=x[18];
2838: return y;
2839: }
2840:
2841: static GEN
2842: area(GEN x)
2843: {
2844: if (!is_bigell(x)) err(member,"area",mark.member,mark.start);
2845: if (gcmp0((GEN)x[19])) err(talker,"curve not defined over R");
2846: return (GEN)x[19];
2847: }
2848:
2849: static GEN
2850: tate(GEN x)
2851: {
2852: GEN z = cgetg(3,t_VEC);
2853: if (!is_bigell(x)) err(member,"tate",mark.member,mark.start);
2854: if (!gcmp0((GEN)x[19])) err(talker,"curve not defined over a p-adic field");
2855: z[1]=x[15];
2856: z[2]=x[16];
2857: z[3]=x[17]; return z;
2858: }
2859:
2860: static GEN
2861: w(GEN x)
2862: {
2863: if (!is_bigell(x)) err(member,"tate",mark.member,mark.start);
2864: if (!gcmp0((GEN)x[19])) err(talker,"curve not defined over a p-adic field");
2865: return (GEN)x[18];
2866: }
2867:
2868: /*
2869: * Only letters and digits in member names. AT MOST 8 of THEM
2870: * (or modify gp_rl.c::pari_completion)
2871: */
2872: entree gp_member_list[] = {
2873: {"a1",0,(void*)a1},
2874: {"a2",0,(void*)a2},
2875: {"a3",0,(void*)a3},
2876: {"a4",0,(void*)a4},
2877: {"a6",0,(void*)a6},
2878: {"area",0,(void*)area},
2879: {"b2",0,(void*)b2},
2880: {"b4",0,(void*)b4},
2881: {"b6",0,(void*)b6},
2882: {"b8",0,(void*)b8},
2883: {"bnf",0,(void*)bnf},
2884: {"c4",0,(void*)c4},
2885: {"c6",0,(void*)c6},
2886: {"clgp",0,(void*)clgp},
2887: {"codiff",0,(void*)codiff},
2888: {"cyc",0,(void*)cyc},
2889: {"diff",0,(void*)diff},
2890: {"disc",0,(void*)disc},
2891: {"e",0,(void*)e},
2892: {"eta",0,(void*)meta},
2893: {"f",0,(void*)f},
2894: {"fu",0,(void*)fu},
2895: {"futu",0,(void*)futu},
2896: {"gen",0,(void*)gen},
2897: {"j",0,(void*)j},
2898: {"mod",0,(void*)mod},
2899: {"nf",0,(void*)nf},
2900: {"no",0,(void*)no},
2901: {"omega",0,(void*)momega},
2902: {"p",0,(void*)p},
2903: {"pol",0,(void*)pol},
2904: {"reg",0,(void*)reg},
2905: {"roots",0,(void*)mroots},
2906: {"sign",0,(void*)sign},
2907: {"tate",0,(void*)tate},
2908: {"t2",0,(void*)t2},
2909: {"tu",0,(void*)tu},
2910: {"tufu",0,(void*)tufu},
2911: {"w",0,(void*)w},
2912: {"zk",0,(void*)zk},
2913: {"zkst",0,(void*)zkst},
2914: {NULL,0,NULL}
2915: };
2916:
2917: static entree*
2918: find_member()
2919: {
2920: char *old = analyseur;
2921: const long hash = hashvalue(NULL), len = analyseur - old;
2922: return findentry(old,len,members_hash[hash]);
2923: }
2924:
2925: static GEN
2926: read_member(GEN x)
2927: {
2928: entree *ep;
2929:
2930: mark.member = analyseur;
2931: ep = find_member();
2932: if (ep)
2933: {
2934: if (*analyseur == '=' && analyseur[1] != '=')
2935: {
2936: if (EpPREDEFINED(ep))
2937: err(talker2,"can't modify a pre-defined member: ",
2938: mark.member,mark.start);
2939: gunclone((GEN)ep->value); return NULL;
2940: }
2941: if (EpVALENCE(ep) == EpMEMBER)
2942: return call_fun((GEN)ep->value, NULL, &x, 0, 1);
2943: else
2944: return ((GEN (*)(ANYARG))ep->value)(x);
2945: }
2946: if (*analyseur != '=' || analyseur[1] == '=')
2947: err(talker2,"unknown member function",mark.member,mark.start);
2948: return NULL; /* to be redefined */
2949: }
2950:
2951: /********************************************************************/
2952: /** **/
2953: /** SIMPLE GP FUNCTIONS **/
2954: /** **/
2955: /********************************************************************/
2956:
2957: long
2958: loop_break()
2959: {
2960: switch(br_status)
2961: {
2962: case br_BREAK : if (! --br_count) br_status = br_NONE; /* fall through */
2963: case br_RETURN: return 1;
2964:
2965: case br_NEXT: br_status = br_NONE; /* fall through */
2966: }
2967: return 0;
2968: }
2969:
2970: long
2971: did_break() { return br_status; }
2972:
2973: GEN
2974: return0(GEN x)
2975: {
2976: br_res = x? gclone(x): NULL;
2977: br_status = br_RETURN; return NULL;
2978: }
2979:
2980: GEN
2981: next0(long n)
2982: {
2983: if (n < 1)
2984: err(talker2,"positive integer expected",mark.identifier,mark.start);
2985: if (n == 1) br_status = br_NEXT;
2986: else
2987: {
2988: br_count = n-1;
2989: br_status = br_BREAK;
2990: }
2991: return NULL;
2992: }
2993:
2994: GEN
2995: break0(long n)
2996: {
2997: if (n < 1)
2998: err(talker2,"positive integer expected",mark.identifier,mark.start);
2999: br_count = n;
3000: br_status = br_BREAK; return NULL;
3001: }
3002:
3003: void
3004: alias0(char *s, char *old)
3005: {
3006: entree *ep, *e;
3007: long hash;
3008: GEN x;
3009:
3010: ep = is_entry(old);
3011: if (!ep) err(talker2,"unknown function",mark.raw,mark.start);
3012: switch(EpVALENCE(ep))
3013: {
3014: case EpVAR: case EpGVAR:
3015: err(talker2,"only functions can be aliased",mark.raw,mark.start);
3016: }
3017:
3018: if ( (e = is_entry_intern(s, functions_hash, &hash)) )
3019: {
3020: if (EpVALENCE(e) != EpALIAS)
3021: err(talker2,"can't replace an existing symbol by an alias",
3022: mark.raw, mark.start);
3023: kill0(e);
3024: }
3025: ep = do_alias(ep); x = newbloc(2);
3026: x[0] = evaltyp(t_STR)|evallg(2); /* for getheap */
3027: x[1] = (long)ep;
3028: installep(x, s, strlen(s), EpALIAS, 0, functions_hash + hash);
3029: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>