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