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

Annotation of OpenXM_contrib/pari-2.2/src/language/es.c, Revision 1.1.1.1

1.1       noro        1: /* $Id: es.c,v 1.59 2001/09/29 12:58:10 karim Exp $
                      2:
                      3: Copyright (C) 2000  The PARI group.
                      4:
                      5: This file is part of the PARI/GP package.
                      6:
                      7: PARI/GP is free software; you can redistribute it and/or modify it under the
                      8: terms of the GNU General Public License as published by the Free Software
                      9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
                     10: ANY WARRANTY WHATSOEVER.
                     11:
                     12: Check the License for details. You should have received a copy of it, along
                     13: with the package; see the file 'COPYING'. If not, write to the Free Software
                     14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
                     15:
                     16: /*******************************************************************/
                     17: /**                                                               **/
                     18: /**                 INPUT/OUTPUT SUBROUTINES                      **/
                     19: /**                                                               **/
                     20: /*******************************************************************/
                     21: #include "pari.h"
                     22: #include "anal.h"
                     23: extern GEN confrac(GEN x); /* should be static here, but use hiremainder */
                     24: extern GEN convi(GEN x);
                     25: static void bruti(GEN g, long n);
                     26: static void texi(GEN g, long nosign);
                     27: static void sori(GEN g);
                     28: char * type_name(long t);
                     29: static char format;
                     30: static long decimals, chmp, initial;
                     31:
                     32: /* output a space or do nothing depending on original caller */
                     33: static void (*sp)();
                     34:
                     35: void
                     36: hit_return()
                     37: {
                     38:   int c;
                     39:   if (under_texmacs || under_emacs) return;
                     40:   pariputs("---- (type RETURN to continue) ----");
                     41:   /* if called from a readline callback, may be in a funny TTY mode,  */
                     42:   do c = fgetc(stdin); while (c >= 0 && c != '\n' && c != '\r' && c != ' ');
                     43:   pariputc('\n');
                     44: }
                     45:
                     46: /********************************************************************/
                     47: /**                                                                **/
                     48: /**                        INPUT FILTER                            **/
                     49: /**                                                                **/
                     50: /********************************************************************/
                     51:
                     52: #define ONE_LINE_COMMENT   2
                     53: #define MULTI_LINE_COMMENT 1
                     54: /* Filter s into t. If flag is a query, return s (yes) / NULL (no)
                     55:  * Otherwise, if t == NULL, allocate enough room, filter then return t.
                     56:  *            if not return pointer to ending '\0' in t.
                     57:  */
                     58: char *
                     59: filtre(char *s0, char *t0, int flag)
                     60: {
                     61:   static int in_string, in_comment = 0;
                     62:   char c, *s, *t;
                     63:   int downcase, return_end;
                     64:
                     65:   if (flag & f_INIT) in_string = 0;
                     66:   switch(flag)
                     67:   {
                     68:     case f_ENDFILE:
                     69:       if (in_string)
                     70:       {
                     71:         err(warner,"run-away string. Closing it");
                     72:         in_string = 0;
                     73:       }
                     74:       if (in_comment)
                     75:       {
                     76:         err(warner,"run-away comment. Closing it");
                     77:         in_comment = 0;
                     78:       } /* fall through */
                     79:     case f_INIT: case f_COMMENT:
                     80:       return in_comment? s0: NULL;
                     81:   }
                     82:
                     83:   downcase = ((flag & f_KEEPCASE) == 0 && compatible == OLDALL);
                     84:   s = s0; return_end = (t0 != NULL);
                     85:   if (!t0) t0 = gpmalloc(strlen(s)+1);
                     86:   t = t0;
                     87:
                     88:   while ((c = *s++))
                     89:   {
                     90:     if (in_string) *t++ = c; /* copy verbatim */
                     91:     else if (in_comment)
                     92:     {
                     93:       if (in_comment == MULTI_LINE_COMMENT)
                     94:       {
                     95:         while (c != '*' || *s != '/')
                     96:         {
                     97:           if (!*s) goto END;
                     98:           c = *s++;
                     99:         }
                    100:         s++;
                    101:       }
                    102:       else
                    103:         while (c != '\n')
                    104:         {
                    105:           if (!*s) { in_comment=0; goto END; }
                    106:           c = *s++;
                    107:         }
                    108:       in_comment=0; continue;
                    109:     }
                    110:     else
                    111:     { /* weed out comments and spaces */
                    112:       if (c=='\\' && *s=='\\') { in_comment = ONE_LINE_COMMENT; continue; }
                    113:       if (isspace((int)c)) continue;
                    114:       *t++ = downcase? tolower(c): c;
                    115:     }
                    116:     switch(c)
                    117:     {
                    118:       case '/':
                    119:         if (*s != '*' || in_string) break;
                    120:         /* start multi-line comment */
                    121:         t--; in_comment = MULTI_LINE_COMMENT; break;
                    122:
                    123:       case '\\':
                    124:         if (!in_string) break;
                    125:         if (!*s) goto END;     /* this will result in an error */
                    126:         *t++ = *s++; break; /* in strings, \ is the escape character */
                    127:         /*  \" does not end a string. But \\" does */
                    128:
                    129:       case '"':
                    130:         in_string = !in_string;
                    131:     }
                    132:   }
                    133: END:
                    134:   *t = 0; return return_end? t: t0;
                    135: }
                    136: #undef ONE_LINE_COMMENT
                    137: #undef MULTI_LINE_COMMENT
                    138:
                    139: GEN
                    140: lisGEN(FILE *fi)
                    141: {
                    142:   long size = 512, n = size;
                    143:   char *buf = gpmalloc(n), *s = buf;
                    144:
                    145:   while (fgets(s, n, fi))
                    146:   {
                    147:     if (s[strlen(s)-1] == '\n')
                    148:     {
                    149:       GEN x = flisexpr(buf);
                    150:       free(buf); return x;
                    151:     }
                    152:     buf = gprealloc(buf, size<<1, size);
                    153:     s = buf + (size-1); n = size+1; size <<= 1;
                    154:   }
                    155: #if defined(UNIX) || defined(__EMX__)
                    156:   if (!feof(fi))
                    157: #endif
                    158:     err(talker, "failed read from file");
                    159:   return NULL;
                    160: }
                    161:
                    162: /********************************************************************/
                    163: /**                                                                **/
                    164: /**                  GENERAL PURPOSE PRINTING                      **/
                    165: /**                                                                **/
                    166: /********************************************************************/
                    167: PariOUT *pariOut, *pariErr;
                    168:
                    169: static void
                    170: normalOutC(char c)
                    171: {
                    172:   putc(c, pari_outfile);
                    173:   if (logfile) putc(c, logfile);
                    174: }
                    175: static void
                    176: normalOutS(char *s)
                    177: {
                    178:   fputs(s, pari_outfile);
                    179:   if (logfile) { fputs(s, logfile); }
                    180: }
                    181: static void
                    182: normalOutF(void)
                    183: {
                    184:   fflush(pari_outfile);
                    185:   if (logfile) fflush(logfile);
                    186: }
                    187: PariOUT defaultOut = {normalOutC, normalOutS, normalOutF, NULL};
                    188:
                    189: static void
                    190: normalErrC(char c)
                    191: {
                    192:   putc(c, errfile);
                    193:   if (logfile) putc(c, logfile);
                    194: }
                    195: static void
                    196: normalErrS(char *s)
                    197: {
                    198:   fputs(s, errfile);
                    199:   if (logfile) fputs(s, logfile);
                    200: }
                    201: static void
                    202: normalErrF(void)
                    203: {
                    204:   fflush(errfile);
                    205:   if (logfile) fflush(logfile);
                    206: }
                    207: PariOUT defaultErr = {normalErrC, normalErrS, normalErrF, NULL};
                    208:
                    209: /**                         GENERIC PRINTING                       **/
                    210: void
                    211: initout(int initerr)
                    212: {
                    213:   infile = stdin; pari_outfile = stdout; errfile = stderr;
                    214:   pariOut = &defaultOut;
                    215:   if (initerr) pariErr = &defaultErr;
                    216: }
                    217:
                    218: void
                    219: pariputc(char c) { pariOut->putch(c); }
                    220:
                    221: void
                    222: pariputs(char *s) { pariOut->puts(s); }
                    223:
                    224: void
                    225: pariflush(void) { pariOut->flush(); }
                    226:
                    227: void
                    228: flusherr(void) { pariErr->flush(); }
                    229:
                    230: /* format is standard printf format, except %Z is a GEN (cast to long) */
                    231: void
                    232: vpariputs(char* format, va_list args)
                    233: {
                    234:   char buf[1024], str[1024], *f = format, *s = str;
                    235:   long nb = 0;
                    236:
                    237:   while (*f)
                    238:   {
                    239:     if (*f != '%') *s++ = *f++;
                    240:     else
                    241:     {
                    242:       if (f[1] != 'Z') { *s++ = *f++; *s++ = *f++; }
                    243:       else
                    244:       {
                    245:         strcpy(s,"\003%020ld\003"); /* brace with unprobable characters */
                    246:         nb++; s += 8; f += 2; /* skip %Z */
                    247:       }
                    248:     }
                    249:   }
                    250:   *s = 0; vsprintf(buf,str,args); s = buf;
                    251:   if (nb)
                    252:     for (f=s; *f; f++)
                    253:       if (*f == '\003' && f[21] == '\003')
                    254:       {
                    255:         *f = 0; f[21] = 0; /* remove the bracing chars */
                    256:         pariOut->puts(s); bruteall((GEN)atol(f+1),'g',-1,1);
                    257:         f += 22; s = f;
                    258:         nb--; if (!nb) break;
                    259:       }
                    260:   pariOut->puts(s);
                    261: }
                    262:
                    263: void
                    264: pariputsf(char *format, ...)
                    265: {
                    266:   va_list args;
                    267:
                    268:   va_start(args,format); vpariputs(format,args);
                    269:   va_end(args);
                    270: }
                    271:
                    272: /* start printing in "color" c */
                    273: /* terminal has to support ANSI color escape sequences */
                    274: #ifdef ESC
                    275: #  undef ESC
                    276: #endif
                    277: #define ESC  (0x1f & '[') /* C-[ = escape */
                    278:
                    279: void
                    280: term_color(int c)
                    281: {
                    282:   pariputs(term_get_color(c));
                    283: }
                    284:
                    285: void
                    286: decode_color(int n, int *c)
                    287: {
                    288:   c[1] = n & 0xf; n >>= 4; /* foreground */
                    289:   c[2] = n & 0xf; n >>= 4; /* background */
                    290:   c[0] = n & 0xf; /* attribute */
                    291: }
                    292:
                    293: char *
                    294: term_get_color(int n)
                    295: {
                    296:   static char s[16];
                    297:   int c[3], a;
                    298:
                    299:   if (disable_color) return "";
                    300:   if (n == c_NONE || (a = gp_colors[n]) == c_NONE)
                    301:     sprintf(s, "%c[0m",ESC); /* reset */
                    302:   else
                    303:   {
                    304:     decode_color(a,c);
                    305:     if (c[1]<8) c[1] += 30; else c[1] += 82;
                    306:     if (a & (1<<12)) /* transparent background */
                    307:       sprintf(s, "%c[%d;%dm", ESC, c[0], c[1]);
                    308:     else
                    309:     {
                    310:       if (c[2]<8) c[2] += 40; else c[2] += 92;
                    311:       sprintf(s, "%c[%d;%d;%dm", ESC, c[0], c[1], c[2]);
                    312:     }
                    313:   }
                    314:   return s;
                    315: }
                    316:
                    317: /********************************************************************/
                    318: /**                                                                **/
                    319: /**                  PRINTING BASED ON SCREEN WIDTH                **/
                    320: /**                                                                **/
                    321: /********************************************************************/
                    322: static int col_index, lin_index, max_width, max_lin;
                    323: #ifdef HAS_TIOCGWINSZ
                    324: #  include <sys/termios.h>
                    325: #  include <sys/ioctl.h>
                    326: #endif
                    327:
                    328: static int
                    329: term_width_intern()
                    330: {
                    331: #ifdef HAS_TIOCGWINSZ
                    332:   {
                    333:     struct winsize s;
                    334:     if (!under_emacs && !under_texmacs && !ioctl(0, TIOCGWINSZ, &s))
                    335:       return s.ws_col;
                    336:   }
                    337: #endif
                    338: #ifdef UNIX
                    339:   {
                    340:     char *str;
                    341:     if ((str = getenv("COLUMNS"))) return atoi(str);
                    342:   }
                    343: #endif
                    344: #ifdef __EMX__
                    345:   {
                    346:     int scrsize[2];
                    347:     _scrsize(scrsize); return scrsize[0];
                    348:   }
                    349: #endif
                    350:   return 0;
                    351: }
                    352:
                    353: static int
                    354: term_height_intern()
                    355: {
                    356: #ifdef HAS_TIOCGWINSZ
                    357:   {
                    358:     struct winsize s;
                    359:     if (!under_emacs && !under_texmacs && !ioctl(0, TIOCGWINSZ, &s))
                    360:       return s.ws_row;
                    361:   }
                    362: #endif
                    363: #ifdef UNIX
                    364:   {
                    365:     char *str;
                    366:     if ((str = getenv("LINES"))) return atoi(str);
                    367:   }
                    368: #endif
                    369: #ifdef __EMX__
                    370:   {
                    371:     int scrsize[2];
                    372:     _scrsize(scrsize); return scrsize[1];
                    373:   }
                    374: #endif
                    375:   return 0;
                    376: }
                    377:
                    378: #define DFT_TERM_WIDTH  80
                    379: #define DFT_TERM_HEIGHT 20
                    380:
                    381: int
                    382: term_width()
                    383: {
                    384:   int n = term_width_intern();
                    385:   return (n>1)? n: DFT_TERM_WIDTH;
                    386: }
                    387:
                    388: int
                    389: term_height()
                    390: {
                    391:   int n = term_height_intern();
                    392:   return (n>1)? n: DFT_TERM_HEIGHT;
                    393: }
                    394:
                    395: #define MAX_WIDTH 76
                    396: /* output string wrapped after MAX_WIDTH characters (for gp -test) */
                    397: static void
                    398: putc80(char c)
                    399: {
                    400:   if (c == '\n') col_index = -1;
                    401:   else if (col_index == MAX_WIDTH)
                    402:     { putc('\n',pari_outfile); col_index = 0; }
                    403:   putc(c, pari_outfile); col_index++;
                    404: }
                    405: #undef MAX_WIDTH
                    406: static void
                    407: puts80(char *s)
                    408: {
                    409:   while (*s) putc80(*s++);
                    410: }
                    411: PariOUT pariOut80= {putc80, puts80, normalOutF, NULL};
                    412:
                    413: void
                    414: init80(long n)
                    415: {
                    416:   col_index = n; pariOut = &pariOut80;
                    417: }
                    418:
                    419: /* output stopped after max_line have been printed (for default(lines,)) */
                    420: static void
                    421: putc_lim_lines(char c)
                    422: {
                    423:   if (lin_index > max_lin) return;
                    424:   if (lin_index == max_lin)
                    425:     if (c == '\n' || col_index >= max_width-5)
                    426:     {
                    427:       normalOutS(term_get_color(c_ERR));
                    428:       normalOutS("[+++]"); lin_index++; return;
                    429:     }
                    430:   if (c == '\n')
                    431:   {
                    432:     col_index = -1; lin_index++;
                    433:   }
                    434:   else if (col_index == max_width)
                    435:   {
                    436:     col_index =  0; lin_index++;
                    437:   }
                    438:   col_index++; normalOutC(c);
                    439: }
                    440: static void
                    441: puts_lim_lines(char *s)
                    442: {
                    443:   long i,len;
                    444:   if (lin_index > max_lin) return;
                    445:   len = strlen(s);
                    446:   for(i=0; i<len; i++) putc_lim_lines(s[i]);
                    447: }
                    448:
                    449: PariOUT pariOut_lim_lines= {putc_lim_lines, puts_lim_lines, normalOutF, NULL};
                    450:
                    451: /* s = prefix already printed (print up to max lines) */
                    452: void
                    453: init_lim_lines(char *s, long max)
                    454: {
                    455:   if (!max) return;
                    456:   if (!s) { pariOut = &defaultOut; return; }
                    457:   max_width = term_width();
                    458:   max_lin = max;
                    459:   lin_index = 1; col_index = strlen(s);
                    460:   pariOut = &pariOut_lim_lines;
                    461: }
                    462:
                    463: #define is_blank_or_null(c) (!(c) || is_blank(c))
                    464: #define is_blank(c) ((c) == ' ' || (c) == '\n')
                    465: #define MAX_WORD_LEN 255
                    466:
                    467: static void
                    468: _new_line(char *prefix)
                    469: {
                    470:   pariputc('\n'); if (prefix) pariputs(prefix);
                    471: }
                    472:
                    473: static long
                    474: strlen_real(char *s)
                    475: {
                    476:   char *t = s, *t0;
                    477:   long ctrl_len = 0;
                    478:   while (*t)
                    479:   {
                    480:     t0 = t;
                    481:     if (*t++ == ESC && *t++ == '[')
                    482:     {
                    483:       while (*t && *t++ != 'm') /* empty */;
                    484:       ctrl_len += t - t0;
                    485:     }
                    486:   }
                    487:   return strlen(s) - ctrl_len;
                    488: }
                    489:
                    490: /* output: <prefix>< s wrapped at EOL >
                    491:  *         <prefix>< ... > <str>
                    492:  *                         ^---  (no \n at the end)
                    493:  * If str is NULL, omit the arrow, assume the text doesn't contain ASCII
                    494:  * escape sequences and end the text with '\n'. If prefix is NULL, use ""
                    495:  */
                    496: void
                    497: print_prefixed_text(char *s, char *prefix, char *str)
                    498: {
                    499:   long prelen = prefix? strlen_real(prefix): 0;
                    500:   long oldwlen=0, linelen=prelen, w = term_width();
                    501:   char word[MAX_WORD_LEN+1], oldword[MAX_WORD_LEN+1], *u=word;
                    502:
                    503:   if (prefix) pariputs(prefix);
                    504:   oldword[0]='\0';
                    505:   while ((*u++ = *s++))
                    506:   {
                    507:     if (is_blank_or_null(*s))
                    508:     {
                    509:       while (is_blank(*s)) s++;
                    510:       linelen += oldwlen;
                    511:       if (linelen >= w)
                    512:       {
                    513:         _new_line(prefix);
                    514:         linelen = oldwlen + prelen;
                    515:       }
                    516:       pariputs(oldword); *u++ = ' '; *u = 0;
                    517:       /* u-word = strlen(word) */
                    518:       oldwlen = str ? strlen_real(word): u - word;
                    519:       if (*s) { strcpy(oldword,word);  u = word; }
                    520:     }
                    521:   }
                    522:   if (!str)
                    523:   { /* add final period if needed */
                    524:     u--; while (u > word && is_blank_or_null(*u)) u--;
                    525:     if (u >= word && isalnum((int)*u)) { u[1] = '.'; u[2] = 0; }
                    526:   }
                    527:   else
                    528:     { *(u-2) = 0; oldwlen--; }
                    529:   linelen += oldwlen;
                    530:   if (linelen >= w) { _new_line(prefix); linelen = prelen + oldwlen; }
                    531:   pariputs(word);
                    532:   if (str)
                    533:   {
                    534:     long i,len = strlen_real(str);
                    535:     int space = (*str == ' ' && str[1]);
                    536:     if (linelen + len >= w)
                    537:     {
                    538:       _new_line(prefix); linelen = prelen;
                    539:       if (space) { str++; len--; space = 0; }
                    540:     }
                    541:     term_color(c_OUTPUT);
                    542:     pariputs(str); if (!len || str[len-1] != '\n') pariputc('\n');
                    543:     if (space) { linelen++; len--; }
                    544:     term_color(c_ERR);
                    545:     for (i=0; i<linelen; i++) pariputc(' ');
                    546:     pariputc('^');
                    547:     for (i=0; i<len; i++) pariputc('-');
                    548:   }
                    549:   else
                    550:     pariputc('\n');
                    551: }
                    552:
                    553: /********************************************************************/
                    554: /**                                                                **/
                    555: /**                    GEN <---> CHARACTER STRINGS                 **/
                    556: /**                                                                **/
                    557: /********************************************************************/
                    558:
                    559: typedef struct outString {
                    560:   char *string;
                    561:   ulong len,size;
                    562: } outString;
                    563: static outString *OutStr, *ErrStr = NULL;
                    564:
                    565: #define STEPSIZE 1024
                    566: #define check_output_length(str,l) { \
                    567:   const ulong s = str->size; \
                    568:   if (str->len + l >= s) { \
                    569:     ulong t = s + l + STEPSIZE; \
                    570:     str->string = gprealloc(str->string, t, s); \
                    571:     str->size = t; \
                    572:   } \
                    573: }
                    574:
                    575: #define str_putc(str, c) { \
                    576:   check_output_length(str,1); \
                    577:   str->string[str->len++] = c; \
                    578: }
                    579: static void
                    580: outstr_putc(char c) { str_putc(OutStr, c); }
                    581: static void
                    582: errstr_putc(char c) { str_putc(ErrStr, c); }
                    583:
                    584: #define str_puts(str, s) {\
                    585:   const long len=strlen(s); \
                    586:   check_output_length(str,len); \
                    587:   strcpy(str->string+str->len,s); \
                    588:   str->len += len; \
                    589: }
                    590: static void
                    591: outstr_puts(char *s) { str_puts(OutStr, s); }
                    592: static void
                    593: errstr_puts(char *s) { str_puts(ErrStr, s); }
                    594:
                    595: static void
                    596: outstr_flush(void) { /* empty */ }
                    597: PariOUT pariOut2Str = {outstr_putc, outstr_puts, outstr_flush, NULL};
                    598: PariOUT pariErr2Str = {errstr_putc, errstr_puts, outstr_flush, NULL};
                    599: #undef STEPSIZE
                    600:
                    601: char *
                    602: pari_strdup(char *s)
                    603: {
                    604:   int n = strlen(s)+1;
                    605:   char *t = gpmalloc(n);
                    606:   memcpy(t,s,n); return t;
                    607: }
                    608:
                    609: /* returns a malloc-ed string, which should be freed after usage */
                    610: char *
                    611: GENtostr0(GEN x, void(*do_out)(GEN))
                    612: {
                    613:   PariOUT *tmp = pariOut;
                    614:   outString *tmps = OutStr, newStr;
                    615:
                    616:   if (typ(x) == t_STR) return pari_strdup(GSTR(x));
                    617:   pariOut = &pariOut2Str; OutStr = &newStr;
                    618:   OutStr->len = 0; OutStr->size=0; OutStr->string=NULL;
                    619:   do_out(x); OutStr->string[OutStr->len] = 0;
                    620:
                    621:   pariOut = tmp; OutStr = tmps; return newStr.string;
                    622: }
                    623:
                    624: char *
                    625: GENtostr(GEN x) { return GENtostr0(x,outbrute); }
                    626:
                    627: /********************************************************************/
                    628: /**                                                                **/
                    629: /**                         WRITE AN INTEGER                       **/
                    630: /**                                                                **/
                    631: /********************************************************************/
                    632: #define putsigne(x) pariputs((x>0)? " + " : " - ")
                    633: #define sp_sign_sp(x) sp(), pariputc(x>0? '+': '-'), sp()
                    634: #define sp_plus_sp() sp(), pariputc('+'), sp()
                    635: #define comma_sp() pariputc(','), sp()
                    636:
                    637: static void wr_space() {pariputc(' ');}
                    638: static void no_space() {}
                    639:
                    640: static void
                    641: blancs(long nb) { while (nb-- > 0) pariputc(' '); }
                    642:
                    643: static void
                    644: zeros(long nb)  { while (nb-- > 0) pariputc('0'); }
                    645:
                    646: static long
                    647: coinit(long x)
                    648: {
                    649:   char cha[10], *p = cha + 9;
                    650:
                    651:   *p = 0;
                    652:   do { *--p = x%10 + '0'; x /= 10; } while (x);
                    653:   pariputs(p); return 9 - (p - cha);
                    654: }
                    655:
                    656: /* as above, printing leading 0s, return # significant digits printed */
                    657: static long
                    658: coinit2(long x)
                    659: {
                    660:   char cha[10], *p = cha + 9;
                    661:   int i = 0;
                    662:
                    663:   for (*p = 0; p > cha; x /= 10) *--p = x%10 + '0';
                    664:   while (cha[i] == '0') i++;
                    665:   pariputs(cha); return 9 - i;
                    666: }
                    667:
                    668:
                    669: static void
                    670: comilieu(long x)
                    671: {
                    672:   char cha[10], *p = cha + 9;
                    673:
                    674:   for (*p = 0; p > cha; x /= 10) *--p = x%10 + '0';
                    675:   pariputs(cha);
                    676: }
                    677:
                    678: static void
                    679: cofin(long x, long decim)
                    680: {
                    681:   char cha[10], *p = cha + 9;
                    682:
                    683:   for (; p > cha; x /= 10) *--p = x%10 + '0';
                    684:   cha[decim] = 0; pariputs(cha);
                    685: }
                    686:
                    687: static long
                    688: nbdch(long l)
                    689: {
                    690:   if (l<100000)
                    691:   {
                    692:     if (l<10) return 1;
                    693:     if (l<100) return 2;
                    694:     if (l<1000) return 3;
                    695:     if (l<10000) return 4;
                    696:     return 5;
                    697:   }
                    698:   if (l<1000000) return 6;
                    699:   if (l<10000000) return 7;
                    700:   if (l<100000000) return 8;
                    701:   if (l<1000000000) return 9;
                    702:   return 10; /* not reached */
                    703: }
                    704:
                    705: /* write an int. fw = field width (pad with ' ') */
                    706: static void
                    707: wr_int(GEN x, long fw, long nosign)
                    708: {
                    709:   long *res,*re,i, sx=signe(x);
                    710:
                    711:   if (!sx) { blancs(fw-1); pariputc('0'); return; }
                    712:   setsigne(x,1); re = res = convi(x);
                    713:   setsigne(x,sx);
                    714:   i = nbdch(*--re); while (*--re >= 0) i+=9;
                    715:   if (nosign || sx>0) blancs(fw-i);
                    716:   else
                    717:      { i++; blancs(fw-i); pariputc('-'); }
                    718:   coinit(*--res); while (*--res >= 0) comilieu(*res);
                    719: }
                    720:
                    721: static void
                    722: wr_vecsmall(GEN g)
                    723: {
                    724:   long i,l;
                    725:   pariputc('['); l = lg(g);
                    726:   for (i=1; i<l; i++)
                    727:   {
                    728:     pariputsf("%ld", g[i]);
                    729:     if (i<l-1) comma_sp();
                    730:   }
                    731:   pariputc(']');
                    732: }
                    733: /********************************************************************/
                    734: /**                                                                **/
                    735: /**                        WRITE A REAL NUMBER                     **/
                    736: /**                                                                **/
                    737: /********************************************************************/
                    738: static void wr_exp(GEN x);
                    739:
                    740: /* assume x != 0 and print |x| in floating point format */
                    741: static void
                    742: wr_float(GEN x)
                    743: {
                    744:   long *res, ex,s,d,e,decmax, dec = decimals;
                    745:   GEN p1;
                    746:
                    747:   if (dec>0) /* round if needed */
                    748:   {
                    749:     GEN arrondi = cgetr(3);
                    750:     arrondi[1] = (long) (x[1]-((double)BITS_IN_LONG/pariK)*dec-2);
                    751:     arrondi[2] = x[2]; x = addrr(x,arrondi);
                    752:   }
                    753:   ex = expo(x); e = bit_accuracy(lg(x)); /* significant bits */
                    754:   if (ex >= e) { wr_exp(x); return; }
                    755:   decmax = (long) (e * L2SL10); /* significant digits */
                    756:   if ((ulong)decmax < (ulong)dec) dec = decmax; /* Hack: includes dec < 0 */
                    757:
                    758: /* integer part */
                    759:   p1 = gcvtoi(x,&e); s = signe(p1);
                    760:   if (e > 0) err(bugparier,"wr_float");
                    761:   if (!s) { pariputc('0'); d=0; }
                    762:   else
                    763:   {
                    764:     x = subri(x,p1); setsigne(p1,1);
                    765:     res = convi(p1); d = coinit(*--res);
                    766:     while (*(--res) >= 0) { d += 9; comilieu(*res); }
                    767:   }
                    768:   pariputc('.');
                    769:
                    770: /* fractional part: 0 < x < 1 */
                    771:   if (!signe(x))
                    772:   {
                    773:     dec -= d; if (dec>0) zeros(dec);
                    774:     return;
                    775:   }
                    776:
                    777:   res = confrac(x);
                    778:   if (!s)
                    779:   {
                    780:     while (!*res) { res++; pariputs("000000000"); }
                    781:     d = coinit2(*res++);
                    782:   }
                    783:
                    784:   /* d = # significant digits already printed */
                    785:   dec -= d;
                    786:   while (dec>8) { comilieu(*res++); dec -= 9; }
                    787:   if (dec>0) cofin(*res,dec);
                    788: }
                    789:
                    790: /* as above in exponential format */
                    791: static void
                    792: wr_exp(GEN x)
                    793: {
                    794:   GEN dix = cgetr(lg(x)+1);
                    795:   long ex = expo(x);
                    796:
                    797:   ex = (ex>=0)? (long)(ex*L2SL10): (long)(-(-ex*L2SL10)-1);
                    798:   affsr(10,dix); if (ex) x = mulrr(x,gpuigs(dix,-ex));
                    799:   if (absr_cmp(x, dix) >= 0) { x=divrr(x,dix); ex++; }
                    800:   wr_float(x); sp(); pariputsf("E%ld",ex);
                    801: }
                    802:
                    803: /* Write real number x.
                    804:  * format: e (exponential), f (floating point), g (as f unless x too small)
                    805:  *   if format isn't correct (one of the above) act as e.
                    806:  * decimals: number of decimals to print (all if <0).
                    807:  */
                    808: static void
                    809: wr_real(GEN x, long nosign)
                    810: {
                    811:   long ltop, sx = signe(x), ex = expo(x);
                    812:
                    813:   if (!sx) /* real 0 */
                    814:   {
                    815:     if (format == 'f')
                    816:     {
                    817:       if (decimals<0)
                    818:       {
                    819:         long d = 1+((-ex)>>TWOPOTBITS_IN_LONG);
                    820:         if (d < 0) d = 0;
                    821:         decimals=(long)(pariK*d);
                    822:       }
                    823:       pariputs("0."); zeros(decimals);
                    824:     }
                    825:     else
                    826:     {
                    827:       ex = (ex>=0)? (long)(ex*L2SL10): (long)(-(-ex*L2SL10)-1);
                    828:       pariputsf("0.E%ld", ex+1);
                    829:     }
                    830:     return;
                    831:   }
                    832:   if (!nosign && sx < 0) pariputc('-'); /* print sign if needed */
                    833:   ltop = avma;
                    834:   if ((format == 'g' && ex>=-32) || format == 'f') wr_float(x); else wr_exp(x);
                    835:   avma = ltop;
                    836: }
                    837:
                    838: void
                    839: ecrire(GEN x, char f, long d, long fw)
                    840: {
                    841:   if (typ(x)==t_INT)
                    842:     wr_int(x,fw,0);
                    843:   else
                    844:   {
                    845:     sp = &wr_space; format = f; decimals = d;
                    846:     wr_real(x,0);
                    847:   }
                    848: }
                    849:
                    850: /********************************************************************/
                    851: /**                                                                **/
                    852: /**                       HEXADECIMAL OUTPUT                       **/
                    853: /**                                                                **/
                    854: /********************************************************************/
                    855:
                    856: static void
                    857: sorstring(char* b, long x)
                    858: {
                    859: #ifdef LONG_IS_64BIT
                    860:   pariputsf(b,(ulong)x>>32,x & MAXHALFULONG);
                    861: #else
                    862:   pariputsf(b,x);
                    863: #endif
                    864: }
                    865:
                    866: /* English ordinal numbers -- GN1998Apr17 */
                    867: static const char *ordsuff[4] = {"st","nd","rd","th"};
                    868:
                    869: const char*
                    870: eng_ord(long i)                        /* i > 0 assumed */
                    871: {
                    872:   switch (i%10)
                    873:   {
                    874:     case 1:
                    875:       if (i%100==11) return ordsuff[3]; /* xxx11-th */
                    876:       return ordsuff[0];         /* xxx01-st, xxx21-st,... */
                    877:     case 2:
                    878:       if (i%100==12) return ordsuff[3]; /* xxx12-th */
                    879:       return ordsuff[1];         /* xxx02-nd, xxx22-nd,... */
                    880:     case 3:
                    881:       if (i%100==13) return ordsuff[3]; /* xxx13-th */
                    882:       return ordsuff[2];         /* xxx03-rd, xxx23-rd,... */
                    883:     default:
                    884:       return ordsuff[3];         /* xxxx4-th,... */
                    885:   }
                    886: }
                    887:
                    888: static char
                    889: vsigne(GEN x)
                    890: {
                    891:   long s = signe(x);
                    892:   if (!s) return '0';
                    893:   return (s > 0) ? '+' : '-';
                    894: }
                    895:
                    896: static void
                    897: voir2(GEN x, long nb, long bl)
                    898: {
                    899:   long tx=typ(x),i,j,e,dx,lx=lg(x);
                    900:
                    901:   if (tx == t_INT && x == gzero) { pariputs("gzero\n"); return; }
                    902:   if (tx == t_SMALL) {
                    903:     pariputs("[SMALL ");
                    904:     sorstring(VOIR_STRING2,(long)x);
                    905:     pariputs("]\n"); return;
                    906:   }
                    907:   sorstring(VOIR_STRING1,(ulong)x);
                    908:
                    909:   pariputsf("%s(lg=%ld%s):",type_name(tx)+2,lx,isclone(x)? ",CLONE" : "");
                    910:   sorstring(VOIR_STRING2,x[0]);
                    911:   if (! is_recursive_t(tx)) /* t_SMALL, t_INT, t_REAL, t_STR, t_VECSMALL */
                    912:   {
                    913:     if (tx == t_STR)
                    914:        pariputs("chars:");
                    915:     else if (tx == t_INT)
                    916:        pariputsf("(%c,lgef=%ld):", vsigne(x), lgefint(x));
                    917:     else if (tx == t_REAL)
                    918:        pariputsf("(%c,expo=%ld):", vsigne(x), expo(x));
                    919:     if (nb<0) nb = (tx==t_INT)? lgefint(x): lx;
                    920:     if (tx == t_VECSMALL) nb = lx;
                    921:     for (i=1; i < nb; i++) sorstring(VOIR_STRING2,x[i]);
                    922:     pariputc('\n'); return;
                    923:   }
                    924:
                    925:   if (tx == t_PADIC)
                    926:     pariputsf("(precp=%ld,valp=%ld):", precp(x), valp(x));
                    927:   else if (tx == t_POL)
                    928:     pariputsf("(%c,varn=%ld,lgef=%ld):", vsigne(x), varn(x), lgef(x));
                    929:   else if (tx == t_SER)
                    930:     pariputsf("(%c,varn=%ld,prec=%ld,valp=%ld):",
                    931:                vsigne(x), varn(x),lg(x)-2, valp(x));
                    932:   else if (tx == t_LIST)
                    933:     pariputsf("(lgef=%ld):", lgef(x));
                    934:
                    935:   if (tx == t_POL || tx == t_LIST) lx = lgef(x);
                    936:   for (i=1; i<lx; i++) sorstring(VOIR_STRING2,x[i]);
                    937:   bl+=2; pariputc('\n');
                    938:   switch(tx)
                    939:   {
                    940:     case t_INTMOD: case t_POLMOD:
                    941:     {
                    942:       char *s = (tx==t_INTMOD)? "int = ": "pol = ";
                    943:       if (isonstack(x[1])) blancs(bl); else { blancs(bl-2); pariputs("* "); }
                    944:       pariputs("mod = "); voir2((GEN)x[1],nb,bl);
                    945:       blancs(bl); pariputs(s);        voir2((GEN)x[2],nb,bl);
                    946:       break;
                    947:     }
                    948:     case t_FRAC: case t_FRACN: case t_RFRAC: case t_RFRACN:
                    949:       blancs(bl); pariputs("num = "); voir2((GEN)x[1],nb,bl);
                    950:       blancs(bl); pariputs("den = "); voir2((GEN)x[2],nb,bl);
                    951:       break;
                    952:
                    953:     case t_COMPLEX:
                    954:       blancs(bl); pariputs("real = "); voir2((GEN)x[1],nb,bl);
                    955:       blancs(bl); pariputs("imag = "); voir2((GEN)x[2],nb,bl);
                    956:       break;
                    957:
                    958:     case t_PADIC:
                    959:       if (isonstack(x[2])) blancs(bl); else { blancs(bl-2); pariputs("* "); }
                    960:                   pariputs("  p : "); voir2((GEN)x[2],nb,bl);
                    961:       blancs(bl); pariputs("p^l : "); voir2((GEN)x[3],nb,bl);
                    962:       blancs(bl); pariputs("  I : "); voir2((GEN)x[4],nb,bl);
                    963:       break;
                    964:
                    965:     case t_QUAD:
                    966:       blancs(bl); pariputs("pol = ");  voir2((GEN)x[1],nb,bl);
                    967:       blancs(bl); pariputs("real = "); voir2((GEN)x[2],nb,bl);
                    968:       blancs(bl); pariputs("imag = "); voir2((GEN)x[3],nb,bl);
                    969:       break;
                    970:
                    971:     case t_POL: case t_SER:
                    972:       e = (tx==t_SER)? valp(x): 0;
                    973:       for (i=2; i<lx; i++)
                    974:       {
                    975:        blancs(bl); pariputsf("coef of degree %ld = ",e);
                    976:        e++; voir2((GEN)x[i],nb,bl);
                    977:       }
                    978:       break;
                    979:
                    980:     case t_LIST: case t_QFR: case t_QFI: case t_VEC: case t_COL:
                    981:       i = (tx==t_LIST)? 2: 1;
                    982:       for (   ; i<lx; i++)
                    983:       {
                    984:         blancs(bl); pariputsf("%ld%s component = ",i,eng_ord(i));
                    985:        voir2((GEN)x[i],nb,bl);
                    986:       }
                    987:       break;
                    988:
                    989:     case t_MAT:
                    990:       if (lx==1) return;
                    991:       dx=lg((GEN)x[1]);
                    992:       for (i=1; i<dx; i++)
                    993:        for (j=1; j<lx; j++)
                    994:        {
                    995:          blancs(bl); pariputsf("mat(%ld,%ld) = ",i,j);
                    996:          voir2(gcoeff(x,i,j),nb,bl);
                    997:        }
                    998:   }
                    999: }
                   1000:
                   1001: void
                   1002: voir(GEN x, long nb)
                   1003: {
                   1004:   voir2(x,nb,0);
                   1005: }
                   1006:
                   1007: char *
                   1008: type_name(long t)
                   1009: {
                   1010:   char *s;
                   1011:   switch(t)
                   1012:   {
                   1013:     case t_SMALL  : s="t_SMALL";   break;
                   1014:     case t_INT    : s="t_INT";     break;
                   1015:     case t_REAL   : s="t_REAL";    break;
                   1016:     case t_INTMOD : s="t_INTMOD";  break;
                   1017:     case t_FRAC   : s="t_FRAC";    break;
                   1018:     case t_FRACN  : s="t_FRACN";   break;
                   1019:     case t_COMPLEX: s="t_COMPLEX"; break;
                   1020:     case t_PADIC  : s="t_PADIC";   break;
                   1021:     case t_QUAD   : s="t_QUAD";    break;
                   1022:     case t_POLMOD : s="t_POLMOD";  break;
                   1023:     case t_POL    : s="t_POL";     break;
                   1024:     case t_SER    : s="t_SER";     break;
                   1025:     case t_RFRAC  : s="t_RFRAC";   break;
                   1026:     case t_RFRACN : s="t_RFRACN";  break;
                   1027:     case t_QFR    : s="t_QFR";     break;
                   1028:     case t_QFI    : s="t_QFI";     break;
                   1029:     case t_VEC    : s="t_VEC";     break;
                   1030:     case t_COL    : s="t_COL";     break;
                   1031:     case t_MAT    : s="t_MAT";     break;
                   1032:     case t_LIST   : s="t_LIST";    break;
                   1033:     case t_STR    : s="t_STR";     break;
                   1034:     case t_VECSMALL:s="t_VECSMALL";break;
                   1035:     default: err(talker,"unknown type %ld",t);
                   1036:       s = NULL; /* not reached */
                   1037:   }
                   1038:   return s;
                   1039: }
                   1040:
                   1041: /********************************************************************/
                   1042: /**                                                                **/
                   1043: /**                        FORMATTED OUTPUT                        **/
                   1044: /**                                                                **/
                   1045: /********************************************************************/
                   1046: static char *
                   1047: get_var(long v, char *buf)
                   1048: {
                   1049:   entree *ep = varentries[v];
                   1050:
                   1051:   if (ep) return ep->name;
                   1052:   if (v==MAXVARN) return "#";
                   1053:   sprintf(buf,"#<%d>",(int)v); return buf;
                   1054: }
                   1055:
                   1056: static char *
                   1057: get_texvar(long v, char *buf)
                   1058: {
                   1059:   entree *ep = varentries[v];
                   1060:   char *s, *t = buf;
                   1061:
                   1062:   if (!ep) err(talker, "this object uses debugging variables");
                   1063:   s = ep->name;
                   1064:   if (strlen(s)>=64) err(talker, "TeX variable name too long");
                   1065:   while(isalpha((int)*s)) *t++ = *s++;
                   1066:   *t = 0; if (isdigit((int)*s) || *s++ == '_') sprintf(t,"_{%s}",s);
                   1067:   return buf;
                   1068: }
                   1069:
                   1070: static void
                   1071: monome(char *v, long deg)
                   1072: {
                   1073:   if (deg)
                   1074:   {
                   1075:     pariputs(v);
                   1076:     if (deg!=1) pariputsf("^%ld",deg);
                   1077:   }
                   1078:   else pariputc('1');
                   1079: }
                   1080:
                   1081: static void
                   1082: texnome(char *v, long deg)
                   1083: {
                   1084:   if (deg)
                   1085:   {
                   1086:     pariputs(v);
                   1087:     if (deg!=1) pariputsf("^{%ld}",deg);
                   1088:   }
                   1089:   else pariputc('1');
                   1090: }
                   1091:
                   1092: #define padic_nome(p,e) {pariputs(p); if (e != 1) pariputsf("^%ld",e);}
                   1093: #define padic_texnome(p,e) {pariputs(p); if (e != 1) pariputsf("^{%ld}",e);}
                   1094:
                   1095: void
                   1096: etatpile(unsigned int n)
                   1097: {
                   1098:   long av=avma,nu,i,l,m;
                   1099:   GEN adr,adr1;
                   1100:   double r;
                   1101:
                   1102:   nu = (top-avma)/BYTES_IN_LONG;
                   1103:   l = (top-bot)/BYTES_IN_LONG;
                   1104:   r = 100.0*nu/l;
                   1105:   pariputsf("\n Top : %lx   Bottom : %lx   Current stack : %lx\n",
                   1106:           top, bot, avma);
                   1107:
                   1108:   pariputsf(" Used :                         %ld  long words  (%ld K)\n",
                   1109:            nu, nu/1024*BYTES_IN_LONG);
                   1110:
                   1111:   pariputsf(" Available :                    %ld  long words  (%ld K)\n",
                   1112:            (l-nu), (l-nu)/1024*BYTES_IN_LONG);
                   1113:
                   1114:   pariputsf(" Occupation of the PARI stack : %6.2f percent\n",r);
                   1115:
                   1116:   adr=getheap();
                   1117:   pariputsf(" %ld objects on heap occupy %ld long words\n\n",
                   1118:                  itos((GEN)adr[1]), itos((GEN)adr[2]));
                   1119:   avma=av;
                   1120:
                   1121:   pariputsf(" %ld variable names used out of %d\n\n",manage_var(3,NULL),MAXVARN);
                   1122:   if (!n) return;
                   1123:
                   1124:   if (n > (ulong)nu) n = nu;
                   1125:   adr = (GEN)avma; adr1 = adr+n;
                   1126:   while (adr<adr1)
                   1127:   {
                   1128:     sorstring(VOIR_STRING3,(ulong)adr);
                   1129:     l=lg(adr); m = (adr==polvar) ? MAXVARN : 0;
                   1130:     for (i=0; i<l && adr<adr1; i++,adr++) sorstring(VOIR_STRING2,*adr);
                   1131:     pariputc('\n'); adr=polvar+m;
                   1132:   }
                   1133:   pariputc('\n');
                   1134: }
                   1135:
                   1136: /********************************************************************/
                   1137: /**                                                                **/
                   1138: /**                           RAW OUTPUT                           **/
                   1139: /**                                                                **/
                   1140: /********************************************************************/
                   1141: #define isnull_for_pol(g)  ((typ(g)==t_INTMOD)? !signe(g[2]): isnull(g))
                   1142:
                   1143: /* is to be printed as '0' */
                   1144: static long
                   1145: isnull(GEN g)
                   1146: {
                   1147:   long i;
                   1148:   switch (typ(g))
                   1149:   {
                   1150:     case t_SMALL:
                   1151:       return !smalltos(g);
                   1152:     case t_INT:
                   1153:       return !signe(g);
                   1154:     case t_COMPLEX:
                   1155:       return isnull((GEN)g[1]) && isnull((GEN)g[2]);
                   1156:     case t_QUAD:
                   1157:       return isnull((GEN)g[2]) && isnull((GEN)g[3]);
                   1158:     case t_FRAC: case t_FRACN: case t_RFRAC: case t_RFRACN:
                   1159:       return isnull((GEN)g[1]);
                   1160:     case t_POLMOD:
                   1161:       return isnull((GEN)g[2]);
                   1162:     case t_POL:
                   1163:       for (i=lgef(g)-1; i>1; i--)
                   1164:        if (!isnull((GEN)g[i])) return 0;
                   1165:       return 1;
                   1166:   }
                   1167:   return 0;
                   1168: }
                   1169:
                   1170: /* return 1 or -1 if g is 1 or -1, 0 otherwise*/
                   1171: static long
                   1172: isone(GEN g)
                   1173: {
                   1174:   long i;
                   1175:   switch (typ(g))
                   1176:   {
                   1177:     case t_SMALL:
                   1178:       switch(smalltos(g))
                   1179:       {
                   1180:         case  1: return  1;
                   1181:         case -1: return -1;
                   1182:       }
                   1183:       break;
                   1184:     case t_INT:
                   1185:       return (signe(g) && is_pm1(g))? signe(g): 0;
                   1186:     case t_COMPLEX:
                   1187:       return isnull((GEN)g[2])? isone((GEN)g[1]): 0;
                   1188:     case t_QUAD:
                   1189:       return isnull((GEN)g[3])? isone((GEN)g[2]): 0;
                   1190:     case t_FRAC: case t_FRACN: case t_RFRAC: case t_RFRACN:
                   1191:       return isone((GEN)g[1]) * isone((GEN)g[2]);
                   1192:     case t_POL:
                   1193:       if (!signe(g)) return 0;
                   1194:       for (i=lgef(g)-1; i>2; i--)
                   1195:        if (!isnull((GEN)g[i])) return 0;
                   1196:       return isone((GEN)g[2]);
                   1197:   }
                   1198:   return 0;
                   1199: }
                   1200:
                   1201: /* if g is a "monomial", return its sign, 0 otherwise */
                   1202: static long
                   1203: isfactor(GEN g)
                   1204: {
                   1205:   long i,deja,sig;
                   1206:   switch(typ(g))
                   1207:   {
                   1208:     case t_INT: case t_REAL:
                   1209:       return (signe(g)<0)? -1: 1;
                   1210:     case t_FRAC: case t_FRACN: case t_RFRAC: case t_RFRACN:
                   1211:       return isfactor((GEN)g[1]);
                   1212:     case t_COMPLEX:
                   1213:       if (isnull((GEN)g[1])) return isfactor((GEN)g[2]);
                   1214:       if (isnull((GEN)g[2])) return isfactor((GEN)g[1]);
                   1215:       return 0;
                   1216:     case t_PADIC:
                   1217:       return !signe((GEN)g[4]);
                   1218:     case t_QUAD:
                   1219:       if (isnull((GEN)g[2])) return isfactor((GEN)g[3]);
                   1220:       if (isnull((GEN)g[3])) return isfactor((GEN)g[2]);
                   1221:       return 0;
                   1222:     case t_POL: deja = 0; sig = 1;
                   1223:       for (i=lgef(g)-1; i>1; i--)
                   1224:         if (!isnull((GEN)g[i]))
                   1225:        {
                   1226:          if (deja) return 0;
                   1227:          sig=isfactor((GEN)g[i]); deja=1;
                   1228:        }
                   1229:       return sig? sig: 1;
                   1230:     case t_SER:
                   1231:       for (i=lg(g)-1; i>1; i--)
                   1232:         if (!isnull((GEN)g[i])) return 0;
                   1233:   }
                   1234:   return 1;
                   1235: }
                   1236:
                   1237: /* return 1 if g is a "truc" (see anal.c) */
                   1238: static long
                   1239: isdenom(GEN g)
                   1240: {
                   1241:   long i,deja;
                   1242:   switch(typ(g))
                   1243:   {
                   1244:     case t_FRAC: case t_FRACN: case t_RFRAC: case t_RFRACN:
                   1245:       return 0;
                   1246:     case t_COMPLEX: return isnull((GEN)g[2]);
                   1247:     case t_PADIC: return !signe((GEN)g[4]);
                   1248:     case t_QUAD: return isnull((GEN)g[3]);
                   1249:
                   1250:     case t_POL: deja = 0;
                   1251:       for (i=lgef(g)-1; i>1; i--)
                   1252:         if (!isnull((GEN)g[i]))
                   1253:        {
                   1254:          if (deja) return 0;
                   1255:          if (i==2) return isdenom((GEN)g[2]);
                   1256:          if (!isone((GEN)g[i])) return 0;
                   1257:          deja=1;
                   1258:        }
                   1259:       return 1;
                   1260:     case t_SER:
                   1261:       for (i=lg(g)-1; i>1; i--)
                   1262:        if (!isnull((GEN)g[i])) return 0;
                   1263:   }
                   1264:   return 1;
                   1265: }
                   1266:
                   1267: /* write a * v^d */
                   1268: static void
                   1269: wr_monome(GEN a, char *v, long d)
                   1270: {
                   1271:   long sig = isone(a);
                   1272:
                   1273:   if (sig) { sp_sign_sp(sig); monome(v,d); }
                   1274:   else
                   1275:   {
                   1276:     sig = isfactor(a);
                   1277:     if (sig) { sp_sign_sp(sig); bruti(a,sig); }
                   1278:     else
                   1279:     {
                   1280:       sp_plus_sp(); pariputc('('); bruti(a,sig); pariputc(')');
                   1281:     }
                   1282:     if (d) { pariputc('*'); monome(v,d); }
                   1283:   }
                   1284: }
                   1285:
                   1286: static void
                   1287: wr_texnome(GEN a, char *v, long d)
                   1288: {
                   1289:   long sig = isone(a);
                   1290:
                   1291:   if (sig) { putsigne(sig); texnome(v,d); }
                   1292:   else
                   1293:   {
                   1294:     sig = isfactor(a);
                   1295:     if (sig) { putsigne(sig); texi(a,sig); }
                   1296:     else
                   1297:     {
                   1298:       pariputs(" + \\left("); texi(a,sig); pariputs("\\right) ");
                   1299:     }
                   1300:     if (d)
                   1301:     {
                   1302:       if (under_texmacs) pariputs("\\*");
                   1303:       texnome(v,d);
                   1304:     }
                   1305:   }
                   1306: }
                   1307:
                   1308: static void
                   1309: wr_lead_monome(GEN a, char *v, long d, long nosign)
                   1310: {
                   1311:   long sig = isone(a);
                   1312:   if (sig)
                   1313:   {
                   1314:     if (!nosign && sig<0) pariputc('-');
                   1315:     monome(v,d);
                   1316:   }
                   1317:   else
                   1318:   {
                   1319:     if (isfactor(a)) bruti(a,nosign);
                   1320:     else
                   1321:     {
                   1322:       pariputc('('); bruti(a,0); pariputc(')');
                   1323:     }
                   1324:     if (d) { pariputc('*'); monome(v,d); }
                   1325:   }
                   1326: }
                   1327:
                   1328: static void
                   1329: wr_lead_texnome(GEN a, char *v, long d, long nosign)
                   1330: {
                   1331:   long sig = isone(a);
                   1332:   if (sig)
                   1333:   {
                   1334:     if (!nosign && sig<0) pariputc('-');
                   1335:     texnome(v,d);
                   1336:   }
                   1337:   else
                   1338:   {
                   1339:     if (isfactor(a)) texi(a,nosign);
                   1340:     else
                   1341:     {
                   1342:       pariputs(" \\left("); texi(a,0); pariputs("\\right) ");
                   1343:     }
                   1344:     if (d)
                   1345:     {
                   1346:       if (under_texmacs) pariputs("\\*");
                   1347:       texnome(v,d);
                   1348:     }
                   1349:   }
                   1350: }
                   1351:
                   1352: static void
                   1353: bruti(GEN g, long nosign)
                   1354: {
                   1355:   long tg,l,i,j,r;
                   1356:   GEN a,b;
                   1357:   char *v, buf[32];
                   1358:
                   1359:   if (!g) { pariputs("NULL"); return; }
                   1360:   if (isnull(g)) { pariputc('0'); return; }
                   1361:   r = isone(g);
                   1362:   if (r)
                   1363:   {
                   1364:     if (!nosign && r<0) pariputc('-');
                   1365:     pariputc('1'); return;
                   1366:   }
                   1367:
                   1368:   tg = typ(g);
                   1369:   switch(tg)
                   1370:   {
                   1371:     case t_SMALL: pariputsf("%ld",smalltos(g)); break;
                   1372:     case t_INT: wr_int(g,0,nosign); break;
                   1373:     case t_REAL: wr_real(g,nosign); break;
                   1374:
                   1375:     case t_INTMOD: case t_POLMOD:
                   1376:       pariputs(new_fun_set? "Mod(": "mod(");
                   1377:       bruti((GEN)g[2],0); comma_sp();
                   1378:       bruti((GEN)g[1],0); pariputc(')'); break;
                   1379:
                   1380:     case t_FRAC: case t_FRACN: case t_RFRAC: case t_RFRACN:
                   1381:       r = isfactor((GEN)g[1]); if (!r) pariputc('(');
                   1382:       bruti((GEN)g[1],nosign);
                   1383:       if (!r) pariputc(')');
                   1384:       pariputc('/');
                   1385:       r = isdenom((GEN)g[2]); if (!r) pariputc('(');
                   1386:       bruti((GEN)g[2],0);
                   1387:       if (!r) pariputc(')');
                   1388:       break;
                   1389:
                   1390:     case t_COMPLEX: case t_QUAD: r = (tg==t_QUAD);
                   1391:       a = (GEN)g[r+1]; b = (GEN)g[r+2]; v = r? "w": "I";
                   1392:       if (isnull(a))
                   1393:       {
                   1394:         wr_lead_monome(b,v,1,nosign);
                   1395:         return;
                   1396:       }
                   1397:       bruti(a,nosign);
                   1398:       if (!isnull(b)) wr_monome(b,v,1);
                   1399:       break;
                   1400:
                   1401:     case t_POL: v = get_var(ordvar[varn(g)], buf);
                   1402:       /* hack: we want g[i] = coeff of degree i. */
                   1403:       i = degpol(g); g += 2; while (isnull((GEN)g[i])) i--;
                   1404:       wr_lead_monome((GEN)g[i],v,i,nosign);
                   1405:       while (i--)
                   1406:       {
                   1407:         a = (GEN)g[i];
                   1408:         if (!isnull_for_pol(a)) wr_monome(a,v,i);
                   1409:       }
                   1410:       break;
                   1411:
                   1412:     case t_SER: v = get_var(ordvar[varn(g)], buf);
                   1413:       i = valp(g);
                   1414:       if (signe(g))
                   1415:       { /* hack: we want g[i] = coeff of degree i. */
                   1416:         l = i + lg(g)-2; g += (2-i);
                   1417:         wr_lead_monome((GEN)g[i],v,i,nosign);
                   1418:         while (++i < l)
                   1419:         {
                   1420:           a = (GEN)g[i];
                   1421:           if (!isnull_for_pol(a)) wr_monome(a,v,i);
                   1422:         }
                   1423:         sp_plus_sp();
                   1424:       }
                   1425:       pariputs("O("); monome(v,i); pariputc(')'); break;
                   1426:
                   1427:     case t_PADIC:
                   1428:     {
                   1429:       GEN p = (GEN)g[2];
                   1430:       i = valp(g); l = precp(g)+i;
                   1431:       g = (GEN)g[4]; v = GENtostr(p);
                   1432:       for (; i<l; i++)
                   1433:       {
                   1434:        g = dvmdii(g,p,&a);
                   1435:        if (signe(a))
                   1436:        {
                   1437:          if (!i || !is_pm1(a))
                   1438:          {
                   1439:            wr_int(a,0,1); if (i) pariputc('*');
                   1440:          }
                   1441:          if (i) padic_nome(v,i);
                   1442:           sp_plus_sp();
                   1443:        }
                   1444:       }
                   1445:       pariputs("O("); padic_nome(v,i); pariputc(')');
                   1446:       free(v); break;
                   1447:     }
                   1448:
                   1449:     case t_QFR: case t_QFI: r = (tg == t_QFR);
                   1450:       if (new_fun_set) pariputs("Qfb("); else pariputs(r? "qfr(": "qfi(");
                   1451:       bruti((GEN)g[1],0); comma_sp();
                   1452:       bruti((GEN)g[2],0); comma_sp();
                   1453:       bruti((GEN)g[3],0);
                   1454:       if (r) { comma_sp(); bruti((GEN)g[4],0); }
                   1455:       pariputc(')'); break;
                   1456:
                   1457:     case t_VEC: case t_COL:
                   1458:       pariputc('['); l = lg(g);
                   1459:       for (i=1; i<l; i++)
                   1460:       {
                   1461:         bruti((GEN)g[i],0);
                   1462:         if (i<l-1) comma_sp();
                   1463:       }
                   1464:       pariputc(']'); if (tg==t_COL) pariputc('~');
                   1465:       break;
                   1466:     case t_VECSMALL: wr_vecsmall(g); break;
                   1467:
                   1468:     case t_LIST:
                   1469:       pariputs("List(["); l = lgef(g);
                   1470:       for (i=2; i<l; i++)
                   1471:       {
                   1472:         bruti((GEN)g[i],0);
                   1473:         if (i<l-1) comma_sp();
                   1474:       }
                   1475:       pariputs("])"); break;
                   1476:
                   1477:     case t_STR:
                   1478:       pariputc('"'); pariputs(GSTR(g)); pariputc('"');
                   1479:       return;
                   1480:
                   1481:     case t_MAT:
                   1482:       r = lg(g); if (r==1) { pariputs("[;]"); return; }
                   1483:       l = lg(g[1]);
                   1484:       if (l==1)
                   1485:       {
                   1486:         pariputsf(new_fun_set? "matrix(0,%ld)":"matrix(0,%ld,j,k,0)", r-1);
                   1487:         return;
                   1488:       }
                   1489:       if (l==2)
                   1490:       {
                   1491:         pariputs(new_fun_set? "Mat(": "mat(");
                   1492:         if (r == 2) { bruti(gcoeff(g,1,1),0); pariputc(')'); return; }
                   1493:       }
                   1494:       pariputc('[');
                   1495:       for (i=1; i<l; i++)
                   1496:       {
                   1497:        for (j=1; j<r; j++)
                   1498:        {
                   1499:          bruti(gcoeff(g,i,j),0);
                   1500:           if (j<r-1) comma_sp();
                   1501:        }
                   1502:        if (i<l-1) { pariputc(';'); sp(); }
                   1503:       }
                   1504:       pariputc(']'); if (l==2) pariputc(')');
                   1505:       break;
                   1506:
                   1507:     default: sorstring(VOIR_STRING2,*g);
                   1508:   }
                   1509: }
                   1510:
                   1511: static void
                   1512: matbruti(GEN g, long flag)
                   1513: {
                   1514:   long i,j,r,l;
                   1515:
                   1516:   if (typ(g) != t_MAT) { bruti(g,flag); return; }
                   1517:
                   1518:   r=lg(g); if (r==1 || lg(g[1])==1) { pariputs("[;]\n"); return; }
                   1519:   pariputc('\n'); l = lg(g[1]);
                   1520:   for (i=1; i<l; i++)
                   1521:   {
                   1522:     pariputc('[');
                   1523:     for (j=1; j<r; j++)
                   1524:     {
                   1525:       bruti(gcoeff(g,i,j),0); if (j<r-1) pariputc(' ');
                   1526:     }
                   1527:     if (i<l-1) pariputs("]\n\n"); else pariputs("]\n");
                   1528:   }
                   1529: }
                   1530:
                   1531: static void
                   1532: sor_monome(GEN a, char *v, long d)
                   1533: {
                   1534:   long sig = isone(a);
                   1535:   if (sig) { putsigne(sig); monome(v,d); }
                   1536:   else
                   1537:   {
                   1538:     sig = isfactor(a);
                   1539:     if (sig) { putsigne(sig); if (sig < 0) a = gneg(a); }
                   1540:     else pariputs(" + ");
                   1541:     sori(a); if (d) { pariputc(' '); monome(v,d);}
                   1542:   }
                   1543: }
                   1544:
                   1545: static void
                   1546: sor_lead_monome(GEN a, char *v, long d)
                   1547: {
                   1548:   long sig = isone(a);
                   1549:   if (sig)
                   1550:   {
                   1551:     if (sig < 0) pariputc('-');
                   1552:     monome(v,d);
                   1553:   }
                   1554:   else
                   1555:   {
                   1556:     sori(a);
                   1557:     if (d) { pariputc(' '); monome(v,d); }
                   1558:   }
                   1559: }
                   1560:
                   1561: static void
                   1562: sori(GEN g)
                   1563: {
                   1564:   long tg=typ(g), i,j,r,l,close_paren;
                   1565:   GEN a,b;
                   1566:   char *v, buf[32];
                   1567:
                   1568:   switch (tg)
                   1569:   {
                   1570:     case t_SMALL: pariputsf("%ld",smalltos(g)); return;
                   1571:     case t_INT: wr_int(g,chmp,0); return;
                   1572:     case t_REAL: wr_real(g,0); return;
                   1573:     case t_STR:
                   1574:       pariputc('"'); pariputs(GSTR(g)); pariputc('"'); return;
                   1575:     case t_LIST:
                   1576:       chmp=0; pariputs("List(");
                   1577:       for (i=2; i<lgef(g); i++)
                   1578:       {
                   1579:        sori((GEN)g[i]); if (i<lgef(g)-1) pariputs(", ");
                   1580:       }
                   1581:       pariputs(")\n"); return;
                   1582:   }
                   1583:   close_paren=0;
                   1584:   if (!is_matvec_t(tg)) chmp = 0;
                   1585:   if (!is_graphicvec_t(tg))
                   1586:   {
                   1587:     if (is_frac_t(tg) && gsigne(g) < 0) pariputc('-');
                   1588:     if (! is_rfrac_t(tg)) { pariputc('('); close_paren=1; }
                   1589:   }
                   1590:   switch(tg)
                   1591:   {
                   1592:     case t_INTMOD: case t_POLMOD:
                   1593:       a = (GEN)g[2]; b = (GEN)g[1];
                   1594:       if (tg == t_INTMOD && signe(a) < 0) a = addii(a,b);
                   1595:       sori(a); pariputs(" mod "); sori(b); break;
                   1596:
                   1597:     case t_FRAC: case t_FRACN:
                   1598:       a=(GEN)g[1]; wr_int(a,chmp,1); pariputs(" /");
                   1599:       b=(GEN)g[2]; wr_int(b,chmp,1); break;
                   1600:
                   1601:     case t_COMPLEX: case t_QUAD: r = (tg==t_QUAD);
                   1602:       a = (GEN)g[r+1]; b = (GEN)g[r+2]; v = r? "w": "I";
                   1603:       if (isnull(a)) { sor_lead_monome(b,v,1); break; }
                   1604:       sori(a); if (!isnull(b)) sor_monome(b,v,1);
                   1605:       break;
                   1606:
                   1607:     case t_PADIC:
                   1608:     {
                   1609:       GEN p = (GEN)g[2];
                   1610:       i = valp(g); l = precp(g)+i;
                   1611:       g = (GEN)g[4]; v = GENtostr(p);
                   1612:       for (; i<l; i++)
                   1613:       {
                   1614:        g = dvmdii(g,p,&a);
                   1615:        if (signe(a))
                   1616:        {
                   1617:          if (!i || !is_pm1(a))
                   1618:          {
                   1619:            wr_int(a,chmp,1); pariputc(i? '*': ' ');
                   1620:          }
                   1621:          if (i) { padic_nome(v,i); pariputc(' '); }
                   1622:           pariputs("+ ");
                   1623:        }
                   1624:       }
                   1625:       pariputs("O(");
                   1626:       if (!i) pariputs(" 1)"); else padic_nome(v,i);
                   1627:       pariputc(')'); free(v); break;
                   1628:     }
                   1629:
                   1630:     case t_POL:
                   1631:       if (!signe(g)) { pariputc('0'); break; }
                   1632:       v = get_var(ordvar[varn(g)],buf);
                   1633:       i = degpol(g); g += 2; while (isnull((GEN)g[i])) i--;
                   1634:       sor_lead_monome((GEN)g[i],v,i);
                   1635:       while (i--)
                   1636:       {
                   1637:         a = (GEN)g[i]; if (!isnull_for_pol(a)) sor_monome(a,v,i);
                   1638:       }
                   1639:       break;
                   1640:
                   1641:     case t_SER: v = get_var(ordvar[varn(g)],buf);
                   1642:       i = valp(g);
                   1643:       if (signe(g))
                   1644:       { /* hack: we want g[i] = coeff of degree i. */
                   1645:         l = i + lg(g)-2; g += (2-i);
                   1646:         sor_lead_monome((GEN)g[i],v,i);
                   1647:         while (++i < l)
                   1648:         {
                   1649:           a = (GEN)g[i]; if (!isnull_for_pol(a)) sor_monome(a,v,i);
                   1650:         }
                   1651:         pariputs(" + ");
                   1652:       }
                   1653:       pariputs("O(");
                   1654:       if (!i) pariputs(" 1)"); else monome(v,i);
                   1655:       pariputc(')'); break;
                   1656:
                   1657:     case t_RFRAC: case t_RFRACN:
                   1658:     if (initial)
                   1659:     {
                   1660:       char *v1, *v2;
                   1661:       long sd = 0, sn = 0, d,n;
                   1662:       long wd = term_width();
                   1663:
                   1664:       initial = 0;
                   1665:       v1 = GENtostr0((GEN)g[1], &sori); n = strlen(v1);
                   1666:       v2 = GENtostr0((GEN)g[2], &sori); d = strlen(v2);
                   1667:
                   1668:       pariputc('\n');
                   1669:       i = max(n,d)+2;
                   1670:       if (i > wd)
                   1671:       {
                   1672:         pariputs(v1); pariputs("\n\n");
                   1673:         for (j=0; j<wd; j++) pariputc('-');
                   1674:         pariputs("\n\n");
                   1675:         pariputs(v2);
                   1676:         pariputc('\n'); return;
                   1677:       }
                   1678:       if (n < d) sn = (d-n) >> 1; else sd = (n-d) >> 1;
                   1679:       blancs(sn+1); pariputs(v1);
                   1680:       pariputs("\n\n"); for (j=0; j<i; j++) pariputc('-');
                   1681:       pariputs("\n\n");
                   1682:       blancs(sd+1); pariputs(v2);
                   1683:       pariputc('\n'); return;
                   1684:     }
                   1685:     pariputc('('); sori((GEN)g[1]); pariputs(" / "); sori((GEN)g[2]);
                   1686:     pariputc(')'); return;
                   1687:
                   1688:     case t_QFR: case t_QFI: pariputc('{');
                   1689:       sori((GEN)g[1]); pariputs(", ");
                   1690:       sori((GEN)g[2]); pariputs(", ");
                   1691:       sori((GEN)g[3]);
                   1692:       if (tg == t_QFR) { pariputs(", "); sori((GEN)g[4]); }
                   1693:       pariputs("}\n"); break;
                   1694:
                   1695:     case t_VEC:
                   1696:       chmp=0; pariputc('[');
                   1697:       for (i=1; i<lg(g); i++)
                   1698:       {
                   1699:        sori((GEN)g[i]); if (i<lg(g)-1) pariputs(", ");
                   1700:       }
                   1701:       pariputc(']'); break;
                   1702:     case t_VECSMALL: wr_vecsmall(g); break;
                   1703:
                   1704:     case t_COL:
                   1705:       if (lg(g)==1) { pariputs("[]\n"); return; }
                   1706:       pariputc('\n');
                   1707:       for (i=1; i<lg(g); i++)
                   1708:       {
                   1709:         pariputc('['); sori((GEN)g[i]); pariputs("]\n");
                   1710:       }
                   1711:       break;
                   1712:
                   1713:     case t_MAT:
                   1714:     {
                   1715:       long lx = lg(g);
                   1716:
                   1717:       if (lx==1) { pariputs("[;]\n"); return; }
                   1718:       pariputc('\n'); l=lg((GEN)g[1]);
                   1719:       for (i=1; i<l; i++)
                   1720:       {
                   1721:        pariputc('[');
                   1722:        for (j=1; j<lx; j++)
                   1723:        {
                   1724:          sori(gcoeff(g,i,j)); if (j<lx-1) pariputc(' ');
                   1725:        }
                   1726:        pariputs("]\n"); if (i<l-1) pariputc('\n');
                   1727:       }
                   1728:       break;
                   1729:     }
                   1730:     default: sorstring(VOIR_STRING2,*g);
                   1731:   }
                   1732:   if (close_paren) pariputc(')');
                   1733: }
                   1734:
                   1735: /********************************************************************/
                   1736: /**                                                                **/
                   1737: /**                           TeX OUTPUT                           **/
                   1738: /**                                                                **/
                   1739: /********************************************************************/
                   1740:
                   1741: /* this follows bruti exactly */
                   1742: static void
                   1743: texi(GEN g, long nosign)
                   1744: {
                   1745:   long tg,i,j,l,r;
                   1746:   GEN a,b;
                   1747:   char *v, buf[67];
                   1748:
                   1749:   if (isnull(g)) { pariputs("{0}"); return; }
                   1750:   r = isone(g); pariputc('{');
                   1751:   if (r)
                   1752:   {
                   1753:     if (!nosign && r<0) pariputc('-');
                   1754:     pariputs("1}"); return;
                   1755:   }
                   1756:
                   1757:   tg = typ(g);
                   1758:   switch(tg)
                   1759:   {
                   1760:     case t_INT: wr_int(g,0,nosign); break;
                   1761:     case t_REAL: wr_real(g,nosign); break;
                   1762:
                   1763:     case t_INTMOD: case t_POLMOD:
                   1764:       texi((GEN)g[2],0); pariputs(" mod ");
                   1765:       texi((GEN)g[1],0); break;
                   1766:
                   1767:     case t_FRAC: case t_FRACN: case t_RFRAC: case t_RFRACN:
                   1768:       texi((GEN)g[1],nosign); pariputs("\\over");
                   1769:       texi((GEN)g[2],0); break;
                   1770:
                   1771:     case t_COMPLEX: case t_QUAD: r = (tg==t_QUAD);
                   1772:       a = (GEN)g[r+1]; b = (GEN)g[r+2]; v = r? "w": "I";
                   1773:       if (isnull(a))
                   1774:       {
                   1775:         wr_lead_texnome(b,v,1,nosign);
                   1776:         break;
                   1777:       }
                   1778:       texi(a,nosign);
                   1779:       if (!isnull(b)) wr_texnome(b,v,1);
                   1780:       break;
                   1781:
                   1782:     case t_POL: v = get_texvar(ordvar[varn(g)],buf);
                   1783:       /* hack: we want g[i] = coeff of degree i. */
                   1784:       i = degpol(g); g += 2; while (isnull((GEN)g[i])) i--;
                   1785:       wr_lead_texnome((GEN)g[i],v,i,nosign);
                   1786:       while (i--)
                   1787:       {
                   1788:         a = (GEN)g[i];
                   1789:         if (!isnull_for_pol(a)) wr_texnome(a,v,i);
                   1790:       }
                   1791:       break;
                   1792:
                   1793:     case t_SER: v = get_texvar(ordvar[varn(g)],buf);
                   1794:       i = valp(g);
                   1795:       if (signe(g))
                   1796:       { /* hack: we want g[i] = coeff of degree i. */
                   1797:         l = i + lg(g)-2; g += (2-i);
                   1798:         wr_lead_texnome((GEN)g[i],v,i,nosign);
                   1799:         while (++i < l)
                   1800:         {
                   1801:           a = (GEN)g[i];
                   1802:           if (!isnull_for_pol(a)) wr_texnome(a,v,i);
                   1803:         }
                   1804:         pariputs("+ ");
                   1805:       }
                   1806:       pariputs("O("); texnome(v,i); pariputc(')'); break;
                   1807:
                   1808:     case t_PADIC:
                   1809:     {
                   1810:       GEN p = (GEN)g[2];
                   1811:       i = valp(g); l = precp(g)+i;
                   1812:       g = (GEN)g[4]; v = GENtostr(p);
                   1813:       for (; i<l; i++)
                   1814:       {
                   1815:        g = dvmdii(g,p,&a);
                   1816:        if (signe(a))
                   1817:        {
                   1818:          if (!i || !is_pm1(a))
                   1819:          {
                   1820:            wr_int(a,0,1); if (i) pariputs("\\cdot");
                   1821:          }
                   1822:          if (i) padic_texnome(v,i);
                   1823:          pariputc('+');
                   1824:        }
                   1825:       }
                   1826:       pariputs("O("); padic_texnome(v,i); pariputc(')');
                   1827:       free(v); break;
                   1828:     }
                   1829:     case t_QFR: case t_QFI: r = (tg == t_QFR);
                   1830:       if (new_fun_set) pariputs("Qfb("); else pariputs(r? "qfr(": "qfi(");
                   1831:       texi((GEN)g[1],0); pariputs(", ");
                   1832:       texi((GEN)g[2],0); pariputs(", ");
                   1833:       texi((GEN)g[3],0);
                   1834:       if (r) { pariputs(", "); texi((GEN)g[4],0); }
                   1835:       pariputc(')'); break;
                   1836:
                   1837:     case t_VEC:
                   1838:       pariputs("\\pmatrix{ "); l = lg(g);
                   1839:       for (i=1; i<l; i++)
                   1840:       {
                   1841:        texi((GEN)g[i],0); if (i<lg(g)-1) pariputc('&');
                   1842:       }
                   1843:       pariputs("\\cr}\n"); break;
                   1844:
                   1845:     case t_LIST:
                   1846:       pariputs("\\pmatrix{ "); l = lgef(g);
                   1847:       for (i=2; i<l; i++)
                   1848:       {
                   1849:        texi((GEN)g[i],0); if (i<lgef(g)-1) pariputc('&');
                   1850:       }
                   1851:       pariputs("\\cr}\n"); break;
                   1852:
                   1853:     case t_COL:
                   1854:       pariputs("\\pmatrix{ "); l = lg(g);
                   1855:       for (i=1; i<l; i++)
                   1856:       {
                   1857:        texi((GEN)g[i],0); pariputs("\\cr\n");
                   1858:       }
                   1859:       pariputc('}'); break;
                   1860:
                   1861:     case t_STR:
                   1862:       pariputs("\\mbox{"); pariputs(GSTR(g));
                   1863:       pariputc('}'); break;
                   1864:
                   1865:     case t_MAT:
                   1866:       pariputs("\\pmatrix{\n "); r = lg(g);
                   1867:       if (r>1)
                   1868:       {
                   1869:         l = lg(g[1]);
                   1870:         for (i=1; i<l; i++)
                   1871:         {
                   1872:           for (j=1; j<r; j++)
                   1873:           {
                   1874:             texi(gcoeff(g,i,j),0); if (j<r-1) pariputc('&');
                   1875:           }
                   1876:           pariputs("\\cr\n ");
                   1877:         }
                   1878:       }
                   1879:       pariputc('}'); break;
                   1880:   }
                   1881:   pariputc('}');
                   1882: }
                   1883:
                   1884: /*******************************************************************/
                   1885: /**                                                               **/
                   1886: /**                        USER OUTPUT FUNCTIONS                  **/
                   1887: /**                                                               **/
                   1888: /*******************************************************************/
                   1889:
                   1890: void
                   1891: bruteall(GEN g, char f, long d, long flag)
                   1892: {
                   1893:   long av = avma;
                   1894:   void (*oldsp)() = sp;
                   1895:
                   1896:   sp = flag? &wr_space: &no_space;
                   1897:   format = f; decimals = d;
                   1898:   bruti(changevar(g,polvar),0);
                   1899:   sp = oldsp; avma = av;
                   1900: }
                   1901:
                   1902: void
                   1903: matbrute(GEN g, char f, long d)
                   1904: {
                   1905:   long av=avma; sp = &wr_space;
                   1906:   format = f; decimals = d;
                   1907:   matbruti(changevar(g,polvar),0); avma=av;
                   1908: }
                   1909:
                   1910: void
                   1911: sor(GEN g, char f, long d, long c)
                   1912: {
                   1913:   long av=avma; sp = &wr_space;
                   1914:   format = f; decimals = d; chmp = c; initial = 1;
                   1915:   sori(changevar(g,polvar)); avma = av;
                   1916: }
                   1917:
                   1918: void
                   1919: texe(GEN g, char f, long d)
                   1920: {
                   1921:   long av=avma; sp = &no_space;
                   1922:   format = f; decimals = d;
                   1923:   texi(changevar(g,polvar),0); avma=av;
                   1924: }
                   1925:
                   1926: void
                   1927: brute(GEN g, char format, long decimals) { bruteall(g,format,decimals,1); }
                   1928:
                   1929: void
                   1930: outbrute(GEN g) { bruteall(g,'g',-1,1); }
                   1931:
                   1932: void
                   1933: outsor(GEN g) { sor(g,'g',-1,1); }
                   1934:
                   1935: void
                   1936: outtex(GEN g) { texe(g,'g',-1); }
                   1937:
                   1938: void
                   1939: output(GEN x)
                   1940: {
                   1941:   outbrute(x); pariputc('\n'); pariflush();
                   1942: }
                   1943:
                   1944: void
                   1945: outmat(GEN x)
                   1946: {
                   1947:   matbrute(x,'g',-1); pariputc('\n'); pariflush();
                   1948: }
                   1949:
                   1950: void
                   1951: outbeaut(GEN x)
                   1952: {
                   1953:   outsor(x); pariputc('\n'); pariflush();
                   1954: }
                   1955:
                   1956: void
                   1957: outerr(GEN x)
                   1958: {
                   1959:   PariOUT *out = pariOut; pariOut = pariErr;
                   1960:   output(x); pariOut = out;
                   1961: }
                   1962:
                   1963: void
                   1964: outbeauterr(GEN x)
                   1965: {
                   1966:   PariOUT *out = pariOut; pariOut = pariErr;
                   1967:   outbeaut(x); pariOut = out;
                   1968: }
                   1969:
                   1970: void
                   1971: bruterr(GEN x,char format,long decimals)
                   1972: {
                   1973:   PariOUT *out = pariOut; pariOut = pariErr;
                   1974:   bruteall(x,format,decimals,1); pariOut = out;
                   1975: }
                   1976:
                   1977: void
                   1978: fprintferr(char* format, ...)
                   1979: {
                   1980:   va_list args;
                   1981:   PariOUT *out = pariOut; pariOut = pariErr;
                   1982:
                   1983:   va_start(args, format); vpariputs(format,args);
                   1984:   va_end(args); pariOut = out;
                   1985: }
                   1986:
                   1987: /*******************************************************************/
                   1988: /**                            FILES                              **/
                   1989: /*******************************************************************/
                   1990: /* stack of temporary files (includes all infiles + some output) */
                   1991: static pariFILE *last_tmp_file = NULL;
                   1992: /* stack of "permanent" (output) files */
                   1993: static pariFILE *last_file = NULL;
                   1994: #if defined(UNIX) || defined(__EMX__)
                   1995: #  include <fcntl.h>
                   1996: #  include <sys/stat.h>
                   1997: #  include <pwd.h>
                   1998: #  ifdef __EMX__
                   1999: #    include <process.h>
                   2000: #  endif
                   2001: #  define HAVE_PIPES
                   2002: #endif
                   2003: #ifndef O_RDONLY
                   2004: #  define O_RDONLY 0
                   2005: #endif
                   2006:
                   2007: pariFILE *
                   2008: newfile(FILE *f, char *name, int type)
                   2009: {
                   2010:   pariFILE *file = (pariFILE*) gpmalloc(strlen(name) + 1 + sizeof(pariFILE));
                   2011:   file->type = type;
                   2012:   file->name = strcpy((char*)(file+1), name);
                   2013:   file->file = f;
                   2014:   file->next = NULL;
                   2015:   if (type & mf_PERM)
                   2016:   {
                   2017:     file->prev = last_file;
                   2018:     last_file = file;
                   2019:   }
                   2020:   else
                   2021:   {
                   2022:     file->prev = last_tmp_file;
                   2023:     last_tmp_file = file;
                   2024:   }
                   2025:   if (file->prev) (file->prev)->next = file;
                   2026:   if (DEBUGFILES)
                   2027:     fprintferr("I/O: opening file %s (code %d) \n",name,type);
                   2028:   return file;
                   2029: }
                   2030:
                   2031: static void
                   2032: pari_kill_file(pariFILE *f)
                   2033: {
                   2034:   if ((f->type & mf_PIPE) == 0)
                   2035:   {
                   2036:     if (fclose(f->file)) err(warnfile, "close", f->name);
                   2037:   }
                   2038: #ifdef HAVE_PIPES
                   2039:   else
                   2040:   {
                   2041:     if (f->type & mf_FALSE)
                   2042:     {
                   2043:       if (fclose(f->file)) err(warnfile, "close", f->name);
                   2044:       if (unlink(f->name)) err(warnfile, "delete", f->name);
                   2045:     }
                   2046:     else
                   2047:       if (pclose(f->file) < 0) err(warnfile, "close pipe", f->name);
                   2048:   }
                   2049: #endif
                   2050:   if (DEBUGFILES)
                   2051:     fprintferr("I/O: closing file %s (code %d) \n",f->name,f->type);
                   2052:   free(f);
                   2053: }
                   2054:
                   2055: void
                   2056: pari_fclose(pariFILE *f)
                   2057: {
                   2058:   if (f->next) (f->next)->prev = f->prev;
                   2059:   else if (f == last_tmp_file) last_tmp_file = f->prev;
                   2060:   else if (f == last_file) last_file = f->prev;
                   2061:   if (f->prev) (f->prev)->next = f->next;
                   2062:   pari_kill_file(f);
                   2063: }
                   2064:
                   2065: static pariFILE *
                   2066: pari_open_file(FILE *f, char *s, char *mode)
                   2067: {
                   2068:   if (!f) err(talker, "could not open requested file %s", s);
                   2069:   if (DEBUGFILES)
                   2070:     fprintferr("I/O: opening file %s (mode %s)\n", s, mode);
                   2071:   return newfile(f,s,0);
                   2072: }
                   2073:
                   2074: pariFILE *
                   2075: pari_fopen(char *s, char *mode)
                   2076: {
                   2077:   return pari_open_file(fopen(s, mode), s, mode);
                   2078: }
                   2079:
                   2080: #ifdef UNIX
                   2081: /* open tmpfile s (a priori for writing) avoiding symlink attacks */
                   2082: pariFILE *
                   2083: pari_safefopen(char *s, char *mode)
                   2084: {
                   2085:   long fd = open(s, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
                   2086:
                   2087:   if (fd == -1) err(talker,"tempfile %s already exists",s);
                   2088:   return pari_open_file(fdopen(fd, mode), s, mode);
                   2089: }
                   2090: #else
                   2091: pariFILE *
                   2092: pari_safefopen(char *s, char *mode)
                   2093: {
                   2094:   return pari_fopen(s, mode);
                   2095: }
                   2096: #endif
                   2097:
                   2098: void
                   2099: pari_unlink(char *s)
                   2100: {
                   2101:   if (unlink(s)) err(warner, "I/O: can\'t remove file %s", s);
                   2102:   else if (DEBUGFILES)
                   2103:     fprintferr("I/O: removed file %s\n", s);
                   2104: }
                   2105:
                   2106: /* Remove one INFILE from the stack. Reset infile (to the most recent infile)
                   2107:  * Return -1, if we're trying to pop out stdin itself; 0 otherwise
                   2108:  * Check for leaked file handlers (temporary files)
                   2109:  */
                   2110: int
                   2111: popinfile()
                   2112: {
                   2113:   pariFILE *f;
                   2114:
                   2115:   filtre(NULL,NULL, f_ENDFILE);
                   2116:   for (f = last_tmp_file; f; f = f->prev)
                   2117:   {
                   2118:     if (f->type & mf_IN) break;
                   2119:     err(warner, "I/O: leaked file descriptor (%d): %s",
                   2120:                f->type, f->name);
                   2121:     pari_fclose(f);
                   2122:   }
                   2123:   last_tmp_file = f; if (!last_tmp_file) return -1;
                   2124:   pari_fclose(last_tmp_file);
                   2125:   for (f = last_tmp_file; f; f = f->prev)
                   2126:     if (f->type & mf_IN) { infile = f->file; return 0; }
                   2127:   infile = stdin; return 0;
                   2128: }
                   2129:
                   2130: static void
                   2131: kill_file_stack(pariFILE **s)
                   2132: {
                   2133:   pariFILE *f = *s;
                   2134:   while (f)
                   2135:   {
                   2136:     pariFILE *t = f->prev;
                   2137:     pari_kill_file(f);
                   2138:     *s = f = t; /* have to update *s in case of ^C */
                   2139:   }
                   2140: }
                   2141:
                   2142: void
                   2143: killallfiles(int leaving)
                   2144: {
                   2145:   if (leaving)
                   2146:   {
                   2147:     popinfile(); /* look for leaks */
                   2148:     kill_file_stack(&last_file);
                   2149:   }
                   2150:   kill_file_stack(&last_tmp_file);
                   2151:   infile = stdin;
                   2152: }
                   2153:
                   2154: pariFILE *
                   2155: try_pipe(char *cmd, int fl)
                   2156: {
                   2157: #ifndef HAVE_PIPES
                   2158:   err(archer); return NULL;
                   2159: #else
                   2160:   FILE *file;
                   2161:   char *f;
                   2162:   VOLATILE int flag = fl;
                   2163:
                   2164: #  ifdef __EMX__
                   2165:   if (_osmode == DOS_MODE) /* no pipes under DOS */
                   2166:   {
                   2167:     char *s;
                   2168:     if (flag & mf_OUT) err(archer);
                   2169:     f = pari_unique_filename("pipe");
                   2170:     s = gpmalloc(strlen(cmd)+strlen(f)+4);
                   2171:     sprintf(s,"%s > %s",cmd,f);
                   2172:     file = system(s)? NULL: (FILE *) fopen(f,"r");
                   2173:     flag |= mf_FALSE; free(s);
                   2174:   }
                   2175:   else
                   2176: #  endif
                   2177:   {
                   2178:     file = (FILE *) popen(cmd, (flag & mf_OUT)? "w": "r");
                   2179:     if (flag & mf_OUT) flag |= mf_PERM;
                   2180:     if (flag & (mf_TEST | mf_OUT))
                   2181:     {
                   2182:       jmp_buf env;
                   2183:       void *c;
                   2184:       int i;
                   2185:       if (DEBUGFILES) fprintferr("I/O: checking output pipe...\n");
                   2186:       if (setjmp(env)) return NULL;
                   2187:
                   2188:       c = err_catch(-1, env, NULL);
                   2189:       fprintf(file,"\n\n"); fflush(file);
                   2190:       for (i=1; i<1000; i++) fprintf(file,"                  \n");
                   2191:       fprintf(file,"\n"); fflush(file);
                   2192:       err_leave(&c);
                   2193:     }
                   2194:     f = cmd;
                   2195:   }
                   2196:   if (!file) err(talker,"[pipe:] '%s' failed",cmd);
                   2197:   return newfile(file, f, mf_PIPE|flag);
                   2198: #endif
                   2199: }
                   2200:
                   2201: void
                   2202: os_close(long fd)
                   2203: {
                   2204: #ifdef WINCE
                   2205:   CloseHandle((HANDLE)fd);
                   2206: #else
                   2207:   close(fd);
                   2208: #endif
                   2209: }
                   2210:
                   2211: void
                   2212: (*os_signal(int sig, void (*f)(int)))(int)
                   2213: {
                   2214: #ifdef WINCE
                   2215:   return SIG_IGN;
                   2216: #else
                   2217:   return signal(sig,f);
                   2218: #endif
                   2219: }
                   2220:
                   2221: void
                   2222: os_read(long fd, char ch[], long s)
                   2223: {
                   2224: #ifdef WINCE
                   2225:   DWORD chRead;
                   2226:   ReadFile((HANDLE)fd, ch, s, &chRead, NULL);
                   2227: #else
                   2228:   read(fd,ch,s);
                   2229: #endif
                   2230: }
                   2231:
                   2232: long
                   2233: os_open(char *s, int mode)
                   2234: {
                   2235:   long fd;
                   2236: #ifdef WINCE
                   2237:   HANDLE h;
                   2238:   short ws[256];
                   2239:   if (mode != O_RDONLY) err(impl,"generic open for Windows");
                   2240:   MultiByteToWideChar(CP_ACP, 0, s, strlen(s)+1, ws, 256);
                   2241:   h = CreateFile(ws,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
                   2242:   fd = (h == INVALID_HANDLE_VALUE)? (long)-1: (long)h;
                   2243: #else
                   2244:   fd = open(s,mode);
                   2245: #endif
                   2246:   return fd;
                   2247: }
                   2248:
                   2249: char *
                   2250: os_getenv(char *s)
                   2251: {
                   2252: #if defined(WINCE) || defined(macintosh)
                   2253:   return NULL;
                   2254: #else
                   2255:   return getenv(s);
                   2256: #endif
                   2257: }
                   2258:
                   2259: /*******************************************************************/
                   2260: /**                                                               **/
                   2261: /**                   GP STANDARD INPUT AND OUTPUT                **/
                   2262: /**                                                               **/
                   2263: /*******************************************************************/
                   2264: static char *last_filename = NULL;
                   2265: static char **dir_list = NULL;
                   2266:
                   2267: #ifdef HAS_OPENDIR
                   2268: #  include <dirent.h>
                   2269: #endif
                   2270: /* slow, but more portable than stat + S_I[FS]DIR */
                   2271: int
                   2272: pari_is_dir(char *name)
                   2273: {
                   2274: #ifdef HAS_OPENDIR
                   2275:   DIR *d = opendir(name);
                   2276:   if (d) { (void)closedir(d); return 1; }
                   2277: #endif
                   2278:   return 0;
                   2279: }
                   2280:
                   2281: /* expand tildes in filenames, return a malloc'ed buffer */
                   2282: static char *
                   2283: _expand_tilde(char *s)
                   2284: {
                   2285: #if !defined(UNIX) && !defined(__EMX__)
                   2286:   return pari_strdup(s);
                   2287: #else
                   2288:   struct passwd *p;
                   2289:   char *u;
                   2290:   int len;
                   2291:
                   2292:   if (*s != '~') return pari_strdup(s);
                   2293:   s++; u = s; /* skip ~ */
                   2294:   if (!*s || *s == '/')
                   2295:   {
                   2296:     p = getpwuid(geteuid());
                   2297:     if (!p)
                   2298:     { /* host badly configured, don't kill session on startup
                   2299:        * (when expanding path) */
                   2300:       err(warner,"can't expand ~");
                   2301:       return pari_strdup(s);
                   2302:     }
                   2303:   }
                   2304:   else
                   2305:   {
                   2306:     char *tmp;
                   2307:     while (*u && *u != '/') u++;
                   2308:     len = u-s;
                   2309:     tmp = strncpy(gpmalloc(len+1),s,len);
                   2310:     tmp[len] = 0;
                   2311:     p = getpwnam(tmp); free(tmp);
                   2312:   }
                   2313:   if (!p) err(talker2,"unknown user ",s,s-1);
                   2314:   s = gpmalloc(strlen(p->pw_dir) + strlen(u) + 1);
                   2315:   sprintf(s,"%s%s",p->pw_dir,u); return s;
                   2316: #endif
                   2317: }
                   2318:
                   2319: /* expand environment variables in str, return a malloc'ed buffer
                   2320:  * assume no \ remain and str can be freed */
                   2321: static char *
                   2322: _expand_env(char *str)
                   2323: {
                   2324: #if defined(WINCE) || defined(macintosh)
                   2325:   return str;
                   2326: #else
                   2327:   long i, l, len = 0, xlen = 16, xnum = 0;
                   2328:   char *s = str, *s0 = s, *env;
                   2329:   char **x = (char **)gpmalloc(xlen * sizeof(char*));
                   2330:
                   2331:   while (*s)
                   2332:   {
                   2333:     if (*s != '$') { s++; continue; }
                   2334:     l = s - s0;
                   2335:     if (l)
                   2336:     {
                   2337:       s0 = strncpy(gpmalloc(l+1), s0, l); s0[l] = 0;
                   2338:       x[xnum++] = s0; len += l;
                   2339:     }
                   2340:     if (xnum > xlen - 3) /* need room for possibly two more elts */
                   2341:     {
                   2342:       long xnew = xlen << 1;
                   2343:       x = (char **)gprealloc((void*)x, xlen * sizeof(char*),
                   2344:                                        xnew * sizeof(char*));
                   2345:       xlen = xnew;
                   2346:     }
                   2347:
                   2348:     s0 = ++s; /* skip $ */
                   2349:     while (is_keyword_char(*s)) s++;
                   2350:     l = s - s0;
                   2351:     env = strncpy(gpmalloc(l+1), s0, l); env[l] = 0;
                   2352:     s0 = getenv(env);
                   2353:     if (!s0)
                   2354:     {
                   2355:       err(warner,"undefined environment variable: %s",env);
                   2356:       s0 = "";
                   2357:     }
                   2358:     l = strlen(s0);
                   2359:     if (l)
                   2360:     {
                   2361:       s0 = strncpy(gpmalloc(l+1), s0, l); s0[l] = 0;
                   2362:       x[xnum++] = s0; len += l;
                   2363:     }
                   2364:     free(env); s0 = s;
                   2365:   }
                   2366:   l = s - s0;
                   2367:   if (l)
                   2368:   {
                   2369:     s0 = strncpy(gpmalloc(l+1), s0, l); s0[l] = 0;
                   2370:     x[xnum++] = s0; len += l;
                   2371:   }
                   2372:
                   2373:   s = gpmalloc(len+1); *s = 0;
                   2374:   for (i = 0; i < xnum; i++) { (void)strcat(s, x[i]); free(x[i]); }
                   2375:   free(str); free(x); return s;
                   2376: #endif
                   2377: }
                   2378:
                   2379: char *
                   2380: expand_tilde(char *s)
                   2381: {
                   2382:   return _expand_env(_expand_tilde(s));
                   2383: }
                   2384:
                   2385: #if defined __EMX__ || defined _WIN32
                   2386: #  define PATH_SEPARATOR ';'
                   2387: #else
                   2388: #  define PATH_SEPARATOR ':'
                   2389: #endif
                   2390:
                   2391: void
                   2392: gp_expand_path(char *v)
                   2393: {
                   2394:   char **path, **old, *s;
                   2395:   int i, n = 0;
                   2396:
                   2397:   v = pari_strdup(v);
                   2398:   for (s=v; *s; s++)
                   2399:     if (*s == PATH_SEPARATOR) { *s = 0; n++; }
                   2400:   path = (char**) gpmalloc((n + 2)*sizeof(char *));
                   2401:
                   2402:   for (s=v, i=0; i<=n; i++)
                   2403:   {
                   2404:     char *end = s + strlen(s), *f = end;
                   2405:     while (f > s && *--f == '/') *f = 0;
                   2406:     path[i] = expand_tilde(s);
                   2407:     s = end + 1; /* next path component */
                   2408:   }
                   2409:   path[i] = NULL; old = dir_list; dir_list = path;
                   2410:   if (old)
                   2411:   {
                   2412:     for (path=old; *path; path++) free(*path);
                   2413:     free(old);
                   2414:   }
                   2415: }
                   2416:
                   2417: /* name is a malloc'ed (existing) filename. Accept it as new infile
                   2418:  * (unzip if needed). */
                   2419: static FILE *
                   2420: accept_file(char *name, FILE *file)
                   2421: {
                   2422:   if (pari_is_dir(name))
                   2423:   {
                   2424:     err(warner,"skipping directory %s",name);
                   2425:     return NULL;
                   2426:   }
                   2427:   if (! last_tmp_file)
                   2428:   {  /* empty file stack, record this name */
                   2429:     if (last_filename) free(last_filename);
                   2430:     last_filename = pari_strdup(name);
                   2431:   }
                   2432: #ifdef ZCAT
                   2433:   {
                   2434:     long l = strlen(name);
                   2435:     char *end = name + l-1;
                   2436:
                   2437:     if (l > 2 && (!strncmp(end-1,".Z",2)
                   2438: #ifdef GNUZCAT
                   2439:                || !strncmp(end-2,".gz",3)
                   2440: #endif
                   2441:     ))
                   2442:     { /* compressed file (compress or gzip) */
                   2443:       char *cmd = gpmalloc(strlen(ZCAT) + l + 2);
                   2444:       sprintf(cmd,"%s %s",ZCAT,name);
                   2445:       fclose(file); infile = try_pipe(cmd, mf_IN)->file;
                   2446:       free(cmd); return infile;
                   2447:     }
                   2448:   }
                   2449: #endif
                   2450:   return infile = newfile(file, name, mf_IN)->file;
                   2451: }
                   2452:
                   2453: /* If a file called "name" exists (possibly after appending ".gp")
                   2454:  * record it in the file_stack (as a pipe if compressed).
                   2455:  * name is malloc'ed, we free it before returning
                   2456:  */
                   2457: static FILE *
                   2458: try_name(char *name)
                   2459: {
                   2460:   FILE *file = fopen(name, "r");
                   2461:   if (file) file = accept_file(name,file);
                   2462:   if (!file)
                   2463:   { /* try appending ".gp" to name */
                   2464:     char *s = gpmalloc(strlen(name)+4);
                   2465:     sprintf(s, "%s.gp", name);
                   2466:     file = fopen(s, "r");
                   2467:     if (file) file = accept_file(s,file);
                   2468:     free(s);
                   2469:   }
                   2470:   free(name); return file;
                   2471: }
                   2472:
                   2473: /* If name = "", re-read last file */
                   2474: void
                   2475: switchin(char *name0)
                   2476: {
                   2477:   char *s, *name;
                   2478:
                   2479:   if (*name0)
                   2480:     name = expand_tilde(name0);
                   2481:   else
                   2482:   {
                   2483:     if (last_filename == NULL)
                   2484:       err(talker,"You never gave me anything to read!");
                   2485:     name0 = last_filename;
                   2486:     name = pari_strdup(name0);
                   2487:   }
                   2488:   /* if name contains '/',  don't use dir_list */
                   2489:   s=name; while (*s && *s != '/' && *s != '\\') s++;
                   2490:   if (*s) { if (try_name(name)) return; }
                   2491:   else
                   2492:   {
                   2493:     char **tmp = dir_list;
                   2494:     for ( ; *tmp; tmp++)
                   2495:     { /* make room for '/' and '\0', try_name frees it */
                   2496:       s = gpmalloc(2 + strlen(*tmp) + strlen(name));
                   2497:       sprintf(s,"%s/%s",*tmp,name);
                   2498:       if (try_name(s)) return;
                   2499:     }
                   2500:   }
                   2501:   err(openfiler,"input",name0);
                   2502: }
                   2503:
                   2504: void
                   2505: switchout(char *name)
                   2506: {
                   2507:   if (name)
                   2508:   {
                   2509:     FILE *f = fopen(name, "a");
                   2510:     if (!f) err(openfiler,"output",name);
                   2511:     pari_outfile = f;
                   2512:   }
                   2513:   else if (pari_outfile != stdout)
                   2514:   {
                   2515:     fclose(pari_outfile);
                   2516:     pari_outfile = stdout;
                   2517:   }
                   2518: }
                   2519:
                   2520: /*******************************************************************/
                   2521: /**                                                               **/
                   2522: /**                    I/O IN BINARY FORM                         **/
                   2523: /**                                                               **/
                   2524: /*******************************************************************/
                   2525: #define _fwrite(a,b,c,d) \
                   2526:   if (fwrite((a),(b),(c),(d)) < (c)) err(talker,"write failed")
                   2527: #define _fread(a,b,c,d) \
                   2528:   if (fread((a),(b),(c),(d)) < (c)) err(talker,"read failed")
                   2529: #define _lfread(a,b,c) _fread((a),sizeof(long),(b),(c))
                   2530: #define _cfread(a,b,c) _fread((a),sizeof(char),(b),(c))
                   2531: #define _lfwrite(a,b,c) _fwrite((a),sizeof(long),(b),(c))
                   2532: #define _cfwrite(a,b,c) _fwrite((a),sizeof(char),(b),(c))
                   2533:
                   2534: #define BIN_GEN 0
                   2535: #define NAM_GEN  1
                   2536:
                   2537: static long
                   2538: rd_long(FILE *f)
                   2539: {
                   2540:   long L;
                   2541:   _lfread(&L, 1, f); return L;
                   2542: }
                   2543: static void
                   2544: wr_long(long L, FILE *f)
                   2545: {
                   2546:   _lfwrite(&L, 1, f);
                   2547: }
                   2548:
                   2549: /* append x to file f */
                   2550: static void
                   2551: wrGEN(GEN x, FILE *f)
                   2552: {
                   2553:   GENbin *p = copy_bin(x);
                   2554:   long L = p->len;
                   2555:
                   2556:   wr_long(L,f);
                   2557:   wr_long((long)p->x,f);
                   2558:   wr_long((long)p->base,f);
                   2559:   _lfwrite(GENbase(p), L,f);
                   2560:   free((void*)p);
                   2561: }
                   2562:
                   2563: static void
                   2564: wrstr(char *s, FILE *f)
                   2565: {
                   2566:   long L = strlen(s)+1;
                   2567:   wr_long(L,f);
                   2568:   _cfwrite(s, L, f);
                   2569: }
                   2570:
                   2571: static char *
                   2572: rdstr(FILE *f)
                   2573: {
                   2574:   long L = rd_long(f);
                   2575:   char *s;
                   2576:   if (!L) return NULL;
                   2577:   s = gpmalloc(L);
                   2578:   _cfread(s, L, f); return s;
                   2579: }
                   2580:
                   2581: void
                   2582: writeGEN(GEN x, FILE *f)
                   2583: {
                   2584:   fputc(BIN_GEN,f);
                   2585:   wrGEN(x, f);
                   2586: }
                   2587:
                   2588: void
                   2589: writenamedGEN(GEN x, char *s, FILE *f)
                   2590: {
                   2591:   fputc(NAM_GEN,f);
                   2592:   wrstr(s, f);
                   2593:   wrGEN(x, f);
                   2594: }
                   2595:
                   2596: /* read a GEN from file f */
                   2597: static GEN
                   2598: rdGEN(FILE *f)
                   2599: {
                   2600:   long L = rd_long(f);
                   2601:   GENbin *p;
                   2602:
                   2603:   if (!L) return NULL;
                   2604:   p = (GENbin*)gpmalloc(sizeof(GENbin) + L*sizeof(long));
                   2605:   p->len  = L;
                   2606:   p->x    = (GEN)rd_long(f);
                   2607:   p->base = (GEN)rd_long(f);
                   2608:   _lfread(GENbase(p), L,f);
                   2609:   return bin_copy(p);
                   2610: }
                   2611:
                   2612: GEN
                   2613: readobj(FILE *f)
                   2614: {
                   2615:   int c = fgetc(f);
                   2616:   GEN x = NULL;
                   2617:   switch(c)
                   2618:   {
                   2619:     case BIN_GEN:
                   2620:       x = rdGEN(f);
                   2621:       if (!x) err(talker,"malformed binary file (no GEN)");
                   2622:       break;
                   2623:     case NAM_GEN:
                   2624:     {
                   2625:       char *s = rdstr(f);
                   2626:       if (!s) err(talker,"malformed binary file (no name)");
                   2627:       x = rdGEN(f);
                   2628:       if (!x) err(talker,"malformed binary file (no GEN)");
                   2629:       fprintferr("setting %s\n",s);
                   2630:       changevalue(fetch_named_var(s,0), x);
                   2631:       break;
                   2632:     }
                   2633:     case EOF: break;
                   2634:     default: err(talker,"unknown code in readobj");
                   2635:   }
                   2636:   return x;
                   2637: }
                   2638:
                   2639: #define MAGIC "\020\001\022\011-\007\020" /* ^P^A^R^I-^G^P */
                   2640: #ifdef LONG_IS_64BIT
                   2641: #  define ENDIAN_CHECK 0x0102030405060708L
                   2642: #else
                   2643: #  define ENDIAN_CHECK 0x01020304L
                   2644: #endif
                   2645: const long BINARY_VERSION = 0;
                   2646:
                   2647: static int
                   2648: is_magic_ok(FILE *f)
                   2649: {
                   2650:   int L = strlen(MAGIC);
                   2651:   char *s = gpmalloc(L);
                   2652:   int r = (fread(s,1,L, f) == L && strncmp(s,MAGIC,L) == 0);
                   2653:   free(s); return r;
                   2654: }
                   2655:
                   2656: static int
                   2657: is_sizeoflong_ok(FILE *f)
                   2658: {
                   2659:   char c;
                   2660:   return (fread(&c,1,1, f) == 1 && c == sizeof(long));
                   2661: }
                   2662:
                   2663: static int
                   2664: is_long_ok(FILE *f, long L)
                   2665: {
                   2666:   long c;
                   2667:   return (fread(&c,sizeof(long),1, f) == 1 && c == L);
                   2668: }
                   2669:
                   2670: static void
                   2671: check_magic(char *name, FILE *f)
                   2672: {
                   2673:   if (!is_magic_ok(f))
                   2674:     err(talker, "%s is not a GP binary file",name);
                   2675:   if (!is_sizeoflong_ok(f))
                   2676:     err(talker, "%s not written for a %ld bit architecture",
                   2677:                name, sizeof(long)*8);
                   2678:   if (!is_long_ok(f, ENDIAN_CHECK))
                   2679:     err(talker, "unexpected endianness in %s",name);
                   2680:   if (!is_long_ok(f, BINARY_VERSION))
                   2681:     err(talker, "%s written by an incompatible version of GP",name);
                   2682: }
                   2683:
                   2684: static void
                   2685: write_magic(FILE *f)
                   2686: {
                   2687:   fprintf(f, MAGIC);
                   2688:   fprintf(f, "%c", sizeof(long));
                   2689:   wr_long(ENDIAN_CHECK, f);
                   2690:   wr_long(BINARY_VERSION, f);
                   2691: }
                   2692:
                   2693: int
                   2694: file_is_binary(FILE *f)
                   2695: {
                   2696:   int c = fgetc(f), r = isprint(c);
                   2697:   ungetc(c,f); return (r == 0);
                   2698: }
                   2699:
                   2700: void
                   2701: writebin(char *name, GEN x)
                   2702: {
                   2703:   FILE *f = fopen(name,"r");
                   2704:   int already = f? 1: 0;
                   2705:
                   2706:   if (f) { check_magic(name,f); fclose(f); }
                   2707:   f = fopen(name,"a");
                   2708:   if (!f) err(openfiler,"binary output",name);
                   2709:   if (!already) write_magic(f);
                   2710:
                   2711:   if (x) writeGEN(x,f);
                   2712:   else
                   2713:   {
                   2714:     long v, maxv = manage_var(3,NULL);
                   2715:     for (v=0; v<maxv; v++)
                   2716:     {
                   2717:       entree *ep = varentries[v];
                   2718:       if (!ep) continue;
                   2719:       writenamedGEN(ep->value,ep->name,f);
                   2720:     }
                   2721:   }
                   2722:   fclose(f);
                   2723: }
                   2724:
                   2725: /* read all objects in file and return last one */
                   2726: GEN
                   2727: readbin(char *name, FILE *f)
                   2728: {
                   2729:   GEN y, x = NULL;
                   2730:   check_magic(name,f);
                   2731:   while ((y = readobj(f))) x = y;
                   2732:   return x;
                   2733: }
                   2734:
                   2735: /*******************************************************************/
                   2736: /**                                                               **/
                   2737: /**                       TEMPORARY FILES                         **/
                   2738: /**                                                               **/
                   2739: /*******************************************************************/
                   2740: #ifdef __WIN32
                   2741: #  include <process.h> /* for getpid */
                   2742: #endif
                   2743:
                   2744: #ifndef R_OK
                   2745: #  define R_OK 4
                   2746: #  define W_OK 2
                   2747: #  define X_OK 1
                   2748: #  define F_OK 0
                   2749: #endif
                   2750:
                   2751: #ifdef __EMX__
                   2752: #include <io.h>
                   2753: static int
                   2754: unix_shell()
                   2755: {
                   2756:   char *base, *sh = getenv("EMXSHELL");
                   2757:   if (sh == NULL) sh = getenv("COMSPEC");
                   2758:   if (sh == NULL) return 0;
                   2759:   base = _getname (sh);
                   2760:   if (stricmp (base, "cmd.exe") == 0 || stricmp (base, "4os2.exe") == 0
                   2761:       || stricmp (base, "command.com") == 0
                   2762:       || stricmp (base, "4dos.com") == 0)
                   2763:     return 0;
                   2764:   return 1;
                   2765: }
                   2766: #endif
                   2767:
                   2768: /* check if s has rwx permissions for us */
                   2769: static int
                   2770: pari_is_rwx(char *s)
                   2771: {
                   2772: #if defined(UNIX) || defined (__EMX__) /* TODO: ok for macintosh? */
                   2773:   return access(s, R_OK | W_OK | X_OK) == 0;
                   2774: #else
                   2775:   return 1;
                   2776: #endif
                   2777: }
                   2778:
                   2779: static int
                   2780: pari_file_exists(char *s)
                   2781: {
                   2782: #if defined(UNIX) || defined (__EMX__)
                   2783:   return access(s, F_OK) == 0;
                   2784: #else
                   2785:   return 0;
                   2786: #endif
                   2787: }
                   2788:
                   2789: char *
                   2790: env_ok(char *s)
                   2791: {
                   2792:   char *t = os_getenv(s);
                   2793:   if (t && !pari_is_rwx(t))
                   2794:   {
                   2795:     err(warner,"%s is set (%s), but is not writeable", s,t);
                   2796:     t = NULL;
                   2797:   }
                   2798:   if (t && !pari_is_dir(t))
                   2799:   {
                   2800:     err(warner,"%s is set (%s), but is not a directory", s,t);
                   2801:     t = NULL;
                   2802:   }
                   2803:   return t;
                   2804: }
                   2805:
                   2806: static char*
                   2807: pari_tmp_dir()
                   2808: {
                   2809:   char *s;
                   2810: #ifdef WINCE
                   2811:   s = env_ok("TEMP"); if (s) return s;
                   2812:   return "\\temp";
                   2813: #endif
                   2814:   s = env_ok("GPTMPDIR"); if (s) return s;
                   2815:   s = env_ok("TMPDIR"); if (s) return s;
                   2816: #ifdef __EMX__
                   2817:   s = env_ok("TMP"); if (s) return s;
                   2818:   s = env_ok("TEMP"); if (s) return s;
                   2819: #endif
                   2820: #if defined(UNIX) || defined(__EMX__)
                   2821:   if (pari_is_rwx("/tmp")) return "/tmp";
                   2822:   if (pari_is_rwx("/var/tmp")) return "/var/tmp";
                   2823: #endif
                   2824:   return ".";
                   2825: }
                   2826:
                   2827: /* Return a "unique filename" built from the string s, possibly the user id
                   2828:  * and the process pid (on Unix systems). A "temporary" directory name is
                   2829:  * prepended. The name returned is stored in a static buffer (gpmalloc'ed
                   2830:  * permanently). It is DOS-safe (s truncated to 8 chars)
                   2831:  */
                   2832: char*
                   2833: pari_unique_filename(char *s)
                   2834: {
                   2835:   static char *buf, *pre, *post = NULL;
                   2836:
                   2837:   if (!post || !s) /* initialize */
                   2838:   {
                   2839:     char suf[64];
                   2840:     int lpre, lsuf;
                   2841:
                   2842:     if (post) free(post);
                   2843:     pre = pari_tmp_dir();
                   2844: #ifdef UNIX
                   2845:     sprintf(suf,".%ld.%ld", (long)getuid(), (long)getpid());
                   2846: #else
                   2847:     sprintf(suf,".gpa");
                   2848: #endif
                   2849:     lsuf = strlen(suf);
                   2850:     lpre = strlen(pre);
                   2851:     /* room for suffix + '\0 + prefix + '/' + s + suffix '\0' */
                   2852:     /*          ^- post        ^- buf         ^- pre          */
                   2853:     post = (char*) gpmalloc(lpre + 1 + 8 + 2*(lsuf + 1));
                   2854:     strcpy(post, suf);
                   2855:     buf = post + lsuf; *buf = 0; buf++;
                   2856:     strcpy(buf, pre);
                   2857:     if (buf[lpre-1] != '/') { (void)strcat(buf, "/"); lpre++; }
                   2858: #ifdef __EMX__
                   2859:     if (!unix_shell())
                   2860: #endif
                   2861: #if defined(__EMX__) || defined(WINCE)
                   2862:       for (pre=buf; *pre; pre++)
                   2863:        if (*pre == '/') *pre = '\\';
                   2864: #endif
                   2865:     pre = buf + lpre; if (!s) return s;
                   2866:   }
                   2867:   sprintf(pre, "%.8s%s", s, post);
                   2868:   if (pari_file_exists(buf))
                   2869:   {
                   2870:     char c, *end = buf + strlen(buf) - 1;
                   2871:     for (c='a'; c<='z'; c++)
                   2872:     {
                   2873:       *end = c;
                   2874:       if (! pari_file_exists(buf)) break;
                   2875:     }
                   2876:     if (c > 'z')
                   2877:       err(talker,"couldn't find a suitable name for a tempfile (%s)",s);
                   2878:   }
                   2879:   return buf;
                   2880: }

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