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

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

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

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