[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

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>