Annotation of OpenXM_contrib/pari-2.2/src/language/anal.c, Revision 1.1
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);
! 609: #define match(c) ({match2(analyseur, c); analyseur++;})
! 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>