[BACK]Return to anal.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / src / language

Annotation of OpenXM_contrib/pari-2.2/src/language/anal.c, Revision 1.1.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=&gne; 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=&geq; goto L2; }
                    540:       goto L1;
                    541:
                    542:     case '!':
                    543:       if (analyseur[1] == '=') { analyseur+=2; F1=&gne; 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 0­terminated] */
                   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>