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

Annotation of OpenXM_contrib/pari/src/language/anal.c, Revision 1.1

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

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