[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.3

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>