[BACK]Return to command.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot

Annotation of OpenXM_contrib/gnuplot/command.c, Revision 1.1.1.2

1.1       maekawa     1: #ifndef lint
1.1.1.2 ! maekawa     2: static char *RCSid = "$Id: command.c,v 1.20.2.1 1999/08/19 14:42:21 lhecking Exp $";
1.1       maekawa     3: #endif
                      4:
                      5: /* GNUPLOT - command.c */
                      6:
                      7: /*[
                      8:  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
                      9:  *
                     10:  * Permission to use, copy, and distribute this software and its
                     11:  * documentation for any purpose with or without fee is hereby granted,
                     12:  * provided that the above copyright notice appear in all copies and
                     13:  * that both that copyright notice and this permission notice appear
                     14:  * in supporting documentation.
                     15:  *
                     16:  * Permission to modify the software is granted, but not the right to
                     17:  * distribute the complete modified source code.  Modifications are to
                     18:  * be distributed as patches to the released version.  Permission to
                     19:  * distribute binaries produced by compiling modified sources is granted,
                     20:  * provided you
                     21:  *   1. distribute the corresponding source modifications from the
                     22:  *    released version in the form of a patch file along with the binaries,
                     23:  *   2. add special version identification to distinguish your version
                     24:  *    in addition to the base release version number,
                     25:  *   3. provide your name and address as the primary contact for the
                     26:  *    support of your modified version, and
                     27:  *   4. retain our contact information in regard to use of the base
                     28:  *    software.
                     29:  * Permission to distribute the released version of the source code along
                     30:  * with corresponding source modifications in the form of a patch file is
                     31:  * granted with same provisions 2 through 4 for binary distributions.
                     32:  *
                     33:  * This software is provided "as is" without express or implied warranty
                     34:  * to the extent permitted by applicable law.
                     35: ]*/
                     36:
                     37: /*
                     38:  * Changes:
                     39:  *
                     40:  * Feb 5, 1992  Jack Veenstra   (veenstra@cs.rochester.edu) Added support to
                     41:  * filter data values read from a file through a user-defined function before
                     42:  * plotting. The keyword "thru" was added to the "plot" command. Example
                     43:  * syntax: f(x) = x / 100 plot "test.data" thru f(x) This example divides all
                     44:  * the y values by 100 before plotting. The filter function processes the
                     45:  * data before any log-scaling occurs. This capability should be generalized
                     46:  * to filter x values as well and a similar feature should be added to the
                     47:  * "splot" command.
                     48:  *
                     49:  * 19 September 1992  Lawrence Crowl  (crowl@cs.orst.edu)
                     50:  * Added user-specified bases for log scaling.
                     51:  */
                     52:
                     53: #include "plot.h"
                     54: #include "setshow.h"
                     55: #include "fit.h"
                     56: #include "binary.h"
                     57:
                     58: #if defined(MSDOS) || defined(DOS386)
                     59: # ifdef DJGPP
                     60: extern char HelpFile[];                /* patch for do_help  - AP */
                     61: # endif                                /* DJGPP */
                     62: # ifdef __TURBOC__
                     63: #  ifndef _Windows
                     64: extern unsigned _stklen = 16394;       /* increase stack size */
                     65: extern char HelpFile[];                /* patch for do_help  - DJL */
                     66: #  endif /* _Windows */
                     67: # endif /* TURBOC */
                     68: #endif /* MSDOS */
                     69:
                     70: #ifndef _Windows
                     71: # include "help.h"
                     72: #else
                     73: static int winsystem __PROTO((char *));
                     74: #endif /* _Windows */
                     75:
                     76: #ifndef STDOUT
                     77: # define STDOUT 1
                     78: #endif
                     79:
                     80: #ifdef _Windows
                     81: # include <windows.h>
                     82: # ifdef __MSC__
                     83: #  include <malloc.h>
                     84: # else
                     85: #  include <alloc.h>
                     86: #  include <dir.h>             /* setdisk() */
                     87: # endif                                /* !MSC */
                     88: # include "win/wgnuplib.h"
                     89: extern TW textwin;
                     90: extern LPSTR winhelpname;
                     91: extern void screen_dump(void); /* in term/win.trm */
                     92: extern int Pause(LPSTR mess);  /* in winmain.c */
                     93: #endif /* _Windows */
                     94:
                     95: #ifdef _Windows
                     96: # define SET_CURSOR_WAIT SetCursor(LoadCursor((HINSTANCE) NULL, IDC_WAIT))
                     97: # define SET_CURSOR_ARROW SetCursor(LoadCursor((HINSTANCE) NULL, IDC_ARROW))
                     98: #else
                     99: # define SET_CURSOR_WAIT /* nought, zilch */
                    100: # define SET_CURSOR_ARROW /* nought, zilch */
                    101: #endif
                    102:
                    103: #ifdef OS2
                    104:  /* emx has getcwd, chdir that can handle drive names */
                    105: # define chdir  _chdir2
                    106: extern int PM_pause(char *);  /* term/pm.trm */
                    107: extern int ExecuteMacro(char *, int); /* plot.c */
                    108: #endif /* OS2 */
                    109:
                    110: #ifdef VMS
                    111: int vms_vkid;                  /* Virtual keyboard id */
                    112: int vms_ktid;                  /* key table id, for translating keystrokes */
                    113: #endif /* VMS */
                    114:
                    115: /* Used by vws.trm */
                    116: void replotrequest __PROTO((void));
                    117:
                    118:
                    119: /* static prototypes */
                    120: static int command __PROTO((void));
                    121: static int read_line __PROTO((char *prompt));
                    122: static void do_shell __PROTO((void));
                    123: static void do_help __PROTO((int toplevel));
                    124: static void do_system __PROTO((void));
                    125: static int changedir __PROTO((char *path));
                    126:
                    127: /* input data, parsing variables */
                    128: #ifdef AMIGA_SC_6_1
                    129: __far int num_tokens, c_token;
                    130: #else
                    131: int num_tokens, c_token;
                    132: #endif
                    133:
                    134: struct lexical_unit *token;
                    135: int token_table_size;
                    136:
                    137: char *input_line;
                    138: int input_line_len;
                    139: int inline_num;                        /* input line number */
                    140:
                    141: struct udft_entry *dummy_func; /* NULL means no dummy vars active */
                    142:
                    143: char c_dummy_var[MAX_NUM_VAR][MAX_ID_LEN+1];   /* current dummy vars */
                    144:
                    145:
                    146: /* support for replot command */
                    147: char *replot_line;
                    148: int plot_token;                        /* start of 'plot' command */
                    149:
                    150: /* If last plot was a 3d one. */
                    151: TBOOLEAN is_3d_plot = FALSE;
                    152:
                    153: #define Inc_c_token if (++c_token >= num_tokens)       \
                    154:                         int_error ("Syntax error", c_token);
                    155:
                    156: /* support for dynamic size of input line */
                    157: void extend_input_line()
                    158: {
                    159:     if (input_line_len == 0) {
                    160:        /* first time */
                    161:        input_line = gp_alloc(MAX_LINE_LEN, "input_line");
                    162:        input_line_len = MAX_LINE_LEN;
                    163:        input_line[0] = NUL;
                    164:     } else {
                    165:        input_line = gp_realloc(input_line, input_line_len + MAX_LINE_LEN, "extend input line");
                    166:        input_line_len += MAX_LINE_LEN;
                    167:        FPRINTF((stderr, "extending input line to %d chars\n", input_line_len));
                    168:     }
                    169: }
                    170:
                    171:
                    172: void extend_token_table()
                    173: {
                    174:     if (token_table_size == 0) {
                    175:        /* first time */
                    176:        token = (struct lexical_unit *) gp_alloc(MAX_TOKENS * sizeof(struct lexical_unit), "token table");
                    177:        token_table_size = MAX_TOKENS;
                    178:     } else {
                    179:        token = gp_realloc(token, (token_table_size + MAX_TOKENS) * sizeof(struct lexical_unit), "extend token table");
                    180:        token_table_size += MAX_TOKENS;
                    181:        FPRINTF((stderr, "extending token table to %d elements\n", token_table_size));
                    182:     }
                    183: }
                    184:
                    185:
                    186: void init_memory()
                    187: {
                    188:     extend_input_line();
                    189:     extend_token_table();
                    190:     replot_line = gp_alloc(1, "string");
                    191:     *replot_line = NUL;
                    192: }
                    193:
                    194:
                    195: int com_line()
                    196: {
                    197:     if (multiplot) {
                    198:        /* calls int_error() if it is not happy */
                    199:        term_check_multiplot_okay(interactive);
                    200:
                    201:        if (read_line("multiplot> "))
                    202:            return (1);
                    203:     } else {
                    204:        if (read_line(PROMPT))
                    205:            return (1);
                    206:     }
                    207:
                    208:     /* So we can flag any new output: if false at time of error,
                    209:      * we reprint the command line before printing caret.
                    210:      * TRUE for interactive terminals, since the command line is typed.
                    211:      * FALSE for non-terminal stdin, so command line is printed anyway.
                    212:      * (DFK 11/89)
                    213:      */
                    214:     screen_ok = interactive;
                    215:
                    216:     if (do_line())
                    217:        return (1);
                    218:     else
                    219:        return (0);
                    220: }
                    221:
                    222:
                    223: int do_line()
                    224: {
                    225:     /* Line continuation has already been handled
                    226:      * by read_line() */
                    227:     char *inlptr = input_line;
                    228:
                    229:     /* Skip leading whitespace */
                    230:     while (isspace((int)*inlptr))
                    231:        inlptr++;
                    232:
                    233:     if (inlptr != input_line) {
                    234:        /* If there was leading whitespace, copy the actual
                    235:         * command string to the front. use memmove() because
                    236:         * source and target overlap */
                    237:        memmove(input_line,inlptr,strlen(inlptr));
                    238:        /* Terminate resulting string */
                    239:        input_line[strlen(inlptr)] = NUL;
                    240:     }
                    241:
                    242:     FPRINTF((stderr, "Input line: \"%s\"\n",input_line));
                    243:
                    244:     /* also used in load_file */
                    245:     if (is_system(input_line[0])) {
                    246:        do_system();
                    247:        if (interactive)        /* 3.5 did it unconditionally */
                    248:            (void) fputs("!\n", stderr);        /* why do we need this ? */
                    249:        return (0);
                    250:     }
                    251:     num_tokens = scanner(input_line);
                    252:     c_token = 0;
                    253:     while (c_token < num_tokens) {
                    254:        if (command())
                    255:            return (1);
                    256:        if (c_token < num_tokens) {     /* something after command */
                    257:            if (equals(c_token, ";"))
                    258:                c_token++;
                    259:            else
                    260:                int_error("';' expected", c_token);
                    261:        }
                    262:     }
                    263:     return (0);
                    264: }
                    265:
                    266:
                    267: void define()
                    268: {
                    269:     register int start_token;  /* the 1st token in the function definition */
                    270:     register struct udvt_entry *udv;
                    271:     register struct udft_entry *udf;
                    272:
                    273:     if (equals(c_token + 1, "(")) {
                    274:        /* function ! */
                    275:        int dummy_num = 0;
                    276:        struct at_type *at_tmp;
                    277:        char save_dummy[MAX_NUM_VAR][MAX_ID_LEN + 1];
                    278:        memcpy(save_dummy, c_dummy_var, sizeof(save_dummy));
                    279:        start_token = c_token;
                    280:        do {
                    281:            c_token += 2;       /* skip to the next dummy */
                    282:            copy_str(c_dummy_var[dummy_num++], c_token, MAX_ID_LEN);
                    283:        } while (equals(c_token + 1, ",") && (dummy_num < MAX_NUM_VAR));
                    284:        if (equals(c_token + 1, ","))
                    285:            int_error("function contains too many parameters", c_token + 2);
                    286:        c_token += 3;           /* skip (, dummy, ) and = */
                    287:        if (END_OF_COMMAND)
                    288:            int_error("function definition expected", c_token);
                    289:        udf = dummy_func = add_udf(start_token);
                    290:        if ((at_tmp = perm_at()) == (struct at_type *) NULL)
                    291:            int_error("not enough memory for function", start_token);
                    292:        if (udf->at)            /* already a dynamic a.t. there */
                    293:            free((char *) udf->at);     /* so free it first */
                    294:        udf->at = at_tmp;       /* before re-assigning it. */
                    295:        memcpy(c_dummy_var, save_dummy, sizeof(save_dummy));
                    296:        m_capture(&(udf->definition), start_token, c_token - 1);
                    297:        dummy_func = NULL;      /* dont let anyone else use our workspace */
                    298:     } else {
                    299:        /* variable ! */
                    300:        start_token = c_token;
                    301:        c_token += 2;
                    302:        udv = add_udv(start_token);
                    303:        (void) const_express(&(udv->udv_value));
                    304:        udv->udv_undef = FALSE;
                    305:     }
                    306: }
                    307:
                    308:
                    309: static int command()
                    310: {
                    311:     FILE *fp;
                    312:     int i;
                    313:     /* string holding name of save or load file */
                    314:     char sv_file[MAX_LINE_LEN + 1];
                    315:
                    316:     for (i = 0; i < MAX_NUM_VAR; i++)
                    317:        c_dummy_var[i][0] = NUL;        /* no dummy variables */
                    318:
                    319:     if (is_definition(c_token))
                    320:        define();
                    321:     else if (almost_equals(c_token, "h$elp") || equals(c_token, "?")) {
                    322:        c_token++;
                    323:        do_help(1);
                    324:     } else if (equals(c_token, "testtime")) {
                    325:        /* given a format and a time string, exercise the time code */
                    326:        char format[160], string[160];
                    327:        struct tm tm;
                    328:        double secs;
                    329:        if (isstring(++c_token)) {
                    330:            quote_str(format, c_token, 159);
                    331:            if (isstring(++c_token)) {
                    332:                quote_str(string, c_token++, 159);
                    333:                memset(&tm, 0, sizeof(tm));
                    334:                gstrptime(string, format, &tm);
                    335:                secs = gtimegm(&tm);
                    336:                fprintf(stderr, "internal = %f - %d/%d/%d::%d:%d:%d , wday=%d, yday=%d\n",
1.1.1.2 ! maekawa   337:                        secs, tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 100, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_wday, tm.tm_yday);
1.1       maekawa   338:                memset(&tm, 0, sizeof(tm));
                    339:                ggmtime(&tm, secs);
                    340:                gstrftime(string, 159, format, secs);
                    341:                fprintf(stderr, "convert back \"%s\" - %d/%d/%d::%d:%d:%d , wday=%d, yday=%d\n",
1.1.1.2 ! maekawa   342:                        string, tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 100, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_wday, tm.tm_yday);
1.1       maekawa   343:            }
                    344:        }
                    345:     } else if (almost_equals(c_token, "test")) {
                    346:        c_token++;
                    347:        test_term();
                    348:     } else if (almost_equals(c_token, "scr$eendump")) {
                    349:        c_token++;
                    350: #ifdef _Windows
                    351:        screen_dump();
                    352: #else
                    353:        fputs("screendump not implemented\n", stderr);
                    354: #endif
                    355:     } else if (almost_equals(c_token, "pa$use")) {
                    356:        struct value a;
                    357:        int sleep_time, text = 0;
                    358:        char buf[MAX_LINE_LEN + 1];
                    359:
                    360:        c_token++;
                    361:        sleep_time = (int) real(const_express(&a));
                    362:        buf[0] = NUL;
                    363:        if (!(END_OF_COMMAND)) {
                    364:            if (!isstring(c_token))
                    365:                int_error("expecting string", c_token);
                    366:            else {
                    367:                quote_str(buf, c_token, MAX_LINE_LEN);
                    368:                ++c_token;
                    369: #ifdef _Windows
                    370:                if (sleep_time >= 0)
                    371: #else
                    372: # ifdef OS2
                    373:                if (strcmp(term->name, "pm") != 0 || sleep_time >= 0)
                    374: # else
                    375: #  ifdef MTOS
                    376:                if (strcmp(term->name, "mtos") != 0 || sleep_time >= 0)
                    377: #  endif /* MTOS */
                    378: # endif /* OS2 */
                    379: #endif /* _Windows */
                    380:                        fputs(buf, stderr);
                    381:                text = 1;
                    382:            }
                    383:        }
                    384:        if (sleep_time < 0) {
                    385: #ifdef _Windows
                    386:            if (!Pause(buf))
                    387:                bail_to_command_line();
                    388: #else
                    389: # ifdef OS2
                    390:            if (strcmp(term->name, "pm") == 0 && sleep_time < 0) {
                    391:                int rc;
                    392:                if ((rc = PM_pause(buf)) == 0)
                    393:                    bail_to_command_line();
                    394:                else if (rc == 2) {
                    395:                    fputs(buf, stderr);
                    396:                    text = 1;
                    397:                    (void) fgets(buf, MAX_LINE_LEN, stdin);
                    398:                }
                    399:            }
                    400: # else                         /* !OS2 */
                    401: #  ifdef _Macintosh
                    402:            if (strcmp(term->name, "macintosh") == 0 && sleep_time < 0)
                    403:                Pause(sleep_time);
                    404: #  else                                /* !_Macintosh */
                    405: #   ifdef MTOS
                    406:            if (strcmp(term->name, "mtos") == 0) {
                    407:                int MTOS_pause(char *buf);
                    408:                int rc;
                    409:                if ((rc = MTOS_pause(buf)) == 0)
                    410:                    bail_to_command_line();
                    411:                else if (rc == 2) {
                    412:                    fputs(buf, stderr);
                    413:                    text = 1;
                    414:                    (void) fgets(buf, MAX_LINE_LEN, stdin);
                    415:                }
                    416:            } else if (strcmp(term->name, "atari") == 0) {
                    417:                char *readline(char *);
                    418:                char *line = readline("");
                    419:                if (line)
                    420:                    free(line);
                    421:            } else
                    422:                (void) fgets(buf, MAX_LINE_LEN, stdin);
                    423: #   else                       /* !MTOS */
                    424: #    ifdef ATARI
                    425:            if (strcmp(term->name, "atari") == 0) {
                    426:                char *readline(char *);
                    427:                char *line = readline("");
                    428:                if (line)
                    429:                    free(line);
                    430:            } else
                    431:                (void) fgets(buf, MAX_LINE_LEN, stdin);
                    432: #    else                      /* !ATARI */
                    433:            (void) fgets(buf, MAX_LINE_LEN, stdin);
                    434:            /* Hold until CR hit. */
                    435: #    endif                     /* !ATARI */
                    436: #   endif                      /* !MTOS */
                    437: #  endif                       /* !_Macintosh */
                    438: # endif                                /* !OS2 */
                    439: #endif
                    440:        }
                    441:        if (sleep_time > 0)
                    442:            GP_SLEEP(sleep_time);
                    443:
                    444:        if (text != 0 && sleep_time >= 0)
                    445:            fputc('\n', stderr);
                    446:        screen_ok = FALSE;
                    447:     } else if (almost_equals(c_token, "pr$int")) {
                    448:        int need_space = 0;     /* space printed between two expressions only */
                    449:        screen_ok = FALSE;
                    450:        do {
                    451:            ++c_token;
                    452:            if (isstring(c_token)) {
                    453:                char s[MAX_LINE_LEN];
                    454:                quote_str(s, c_token, MAX_LINE_LEN);
                    455:                fputs(s, stderr);
                    456:                need_space = 0;
                    457:                ++c_token;
                    458:            } else {
                    459:                struct value a;
                    460:                (void) const_express(&a);
                    461:                if (need_space)
                    462:                    putc(' ', stderr);
                    463:                need_space = 1;
                    464:                disp_value(stderr, &a);
                    465:            }
                    466:        } while (!END_OF_COMMAND && equals(c_token, ","));
                    467:
                    468:        (void) putc('\n', stderr);
                    469:     } else if (almost_equals(c_token, "fit")) {
                    470:        ++c_token;
                    471:        do_fit();
                    472:     } else if (almost_equals(c_token, "up$date")) {
                    473:        char tmps[80];
                    474:        char tmps2[80];
                    475:        /* Have to initialise tmps2, otherwise
                    476:         * update() cannot decide whether a valid
                    477:         * filename was given. lh
                    478:         */
                    479:        tmps2[0] = NUL;
                    480:        if (!isstring(++c_token))
                    481:            int_error("Parameter filename expected", c_token);
                    482:        quote_str(tmps, c_token++, 80);
                    483:        if (!(END_OF_COMMAND)) {
                    484:            if (!isstring(c_token))
                    485:                int_error("New parameter filename expected", c_token);
                    486:            else
                    487:                quote_str(tmps2, c_token++, 80);
                    488:        }
                    489:        update(tmps, tmps2);
                    490:     } else if (almost_equals(c_token, "p$lot")) {
                    491:        plot_token = c_token++;
                    492:        SET_CURSOR_WAIT;
                    493:        plotrequest();
                    494:        SET_CURSOR_ARROW;
                    495:     } else if (almost_equals(c_token, "sp$lot")) {
                    496:        plot_token = c_token++;
                    497:        SET_CURSOR_WAIT;
                    498:        plot3drequest();
                    499:        SET_CURSOR_ARROW;
                    500:     } else if (almost_equals(c_token, "rep$lot")) {
                    501:        if (replot_line[0] == NUL)
                    502:            int_error("no previous plot", c_token);
                    503:        c_token++;
                    504:        SET_CURSOR_WAIT;
                    505:        replotrequest();
                    506:        SET_CURSOR_ARROW;
                    507:     } else if (almost_equals(c_token, "se$t"))
                    508:        set_command();
                    509:     else if (almost_equals(c_token, "res$et"))
                    510:        reset_command();
                    511:     else if (almost_equals(c_token, "sh$ow"))
                    512:        show_command();
                    513:     else if (almost_equals(c_token, "cl$ear")) {
                    514:        term_start_plot();
                    515:
                    516:        if (multiplot && term->fillbox) {
                    517:            unsigned int x1 = (unsigned int) (xoffset * term->xmax);
                    518:            unsigned int y1 = (unsigned int) (yoffset * term->ymax);
                    519:            unsigned int width = (unsigned int) (xsize * term->xmax);
                    520:            unsigned int height = (unsigned int) (ysize * term->ymax);
                    521:            (*term->fillbox) (0, x1, y1, width, height);
                    522:        }
                    523:        term_end_plot();
                    524:
                    525:        screen_ok = FALSE;
                    526:        c_token++;
                    527:     } else if (almost_equals(c_token, "she$ll")) {
                    528:        do_shell();
                    529:        screen_ok = FALSE;
                    530:        c_token++;
                    531:     } else if (almost_equals(c_token, "sa$ve")) {
                    532:        if (almost_equals(++c_token, "f$unctions")) {
                    533:            if (!isstring(++c_token))
                    534:                int_error("expecting filename", c_token);
                    535:            else {
                    536:                quote_str(sv_file, c_token, MAX_LINE_LEN);
                    537:                save_functions(fopen(sv_file, "w"));
                    538:            }
                    539:        } else if (almost_equals(c_token, "v$ariables")) {
                    540:            if (!isstring(++c_token))
                    541:                int_error("expecting filename", c_token);
                    542:            else {
                    543:                quote_str(sv_file, c_token, MAX_LINE_LEN);
                    544:                save_variables(fopen(sv_file, "w"));
                    545:            }
                    546:        } else if (almost_equals(c_token, "s$et")) {
                    547:            if (!isstring(++c_token))
                    548:                int_error("expecting filename", c_token);
                    549:            else {
                    550:                quote_str(sv_file, c_token, MAX_LINE_LEN);
                    551:                save_set(fopen(sv_file, "w"));
                    552:            }
                    553:        } else if (isstring(c_token)) {
                    554:            quote_str(sv_file, c_token, MAX_LINE_LEN);
                    555:            save_all(fopen(sv_file, "w"));
                    556:        } else {
                    557:            int_error("filename or keyword 'functions', 'variables', or 'set' expected", c_token);
                    558:        }
                    559:        c_token++;
                    560:     } else if (almost_equals(c_token, "l$oad")) {
                    561:        if (!isstring(++c_token))
                    562:            int_error("expecting filename", c_token);
                    563:        else {
                    564:            quote_str(sv_file, c_token, MAX_LINE_LEN);
                    565:            /* load_file(fp=fopen(sv_file, "r"), sv_file, FALSE); OLD
                    566:             * DBT 10/6/98 handle stdin as special case
                    567:             * passes it on to load_file() so that it gets
                    568:             * pushed on the stack and recusion will work, etc
                    569:             */
                    570:            fp = strcmp(sv_file, "-") ? fopen(sv_file, "r") : stdin;
                    571:            load_file(fp, sv_file, FALSE);
                    572:            /* input_line[] and token[] now destroyed! */
                    573:            c_token = num_tokens = 0;
                    574:        }
                    575:     } else if (almost_equals(c_token, "ca$ll")) {
                    576:        if (!isstring(++c_token))
                    577:            int_error("expecting filename", c_token);
                    578:        else {
                    579:            quote_str(sv_file, c_token, MAX_LINE_LEN);
                    580:            load_file(fopen(sv_file, "r"), sv_file, TRUE);      /* Argument list follows filename */
                    581:            /* input_line[] and token[] now destroyed! */
                    582:            c_token = num_tokens = 0;
                    583:        }
                    584:     } else if (almost_equals(c_token, "if")) {
                    585:        double exprval;
                    586:        struct value t;
                    587:        if (!equals(++c_token, "("))    /* no expression */
                    588:            int_error("expecting (expression)", c_token);
                    589:        exprval = real(const_express(&t));
                    590:        if (exprval != 0.0) {
                    591:            /* fake the condition of a ';' between commands */
                    592:            int eolpos = token[num_tokens - 1].start_index + token[num_tokens - 1].length;
                    593:            --c_token;
                    594:            token[c_token].length = 1;
                    595:            token[c_token].start_index = eolpos + 2;
                    596:            input_line[eolpos + 2] = ';';
                    597:            input_line[eolpos + 3] = NUL;
                    598:        } else
                    599:            c_token = num_tokens = 0;
                    600:     } else if (almost_equals(c_token, "rer$ead")) {
                    601:        fp = lf_top();
                    602:        if (fp != (FILE *) NULL)
                    603:            rewind(fp);
                    604:        c_token++;
                    605:     } else if (almost_equals(c_token, "cd")) {
                    606:        if (!isstring(++c_token))
                    607:            int_error("expecting directory name", c_token);
                    608:        else {
                    609:            quote_str(sv_file, c_token, MAX_LINE_LEN);
                    610:            if (changedir(sv_file)) {
                    611:                int_error("Can't change to this directory", c_token);
                    612:            }
                    613:            c_token++;
                    614:        }
                    615:     } else if (almost_equals(c_token, "pwd")) {
                    616:        GP_GETCWD(sv_file, sizeof(sv_file));
                    617:        fprintf(stderr, "%s\n", sv_file);
                    618:        c_token++;
                    619:     } else if (almost_equals(c_token, "ex$it") ||
                    620:               almost_equals(c_token, "q$uit")) {
                    621:        /* graphics will be tidied up in main */
                    622:        return (1);
                    623:     } else if (!equals(c_token, ";")) {                /* null statement */
                    624: #ifdef OS2
                    625:        if (_osmode == OS2_MODE) {
                    626:            if (token[c_token].is_token) {
                    627:                int rc;
                    628:                rc = ExecuteMacro(input_line + token[c_token].start_index,
                    629:                                  token[c_token].length);
                    630:                if (rc == 0) {
                    631:                    c_token = num_tokens = 0;
                    632:                    return (0);
                    633:                }
                    634:            }
                    635:        }
                    636: #endif
                    637:        int_error("invalid command", c_token);
                    638:     }
                    639:     return (0);
                    640: }
                    641:
                    642:
                    643: void done(status)
                    644: int status;
                    645: {
                    646:     term_reset();
                    647:     exit(status);
                    648: }
                    649:
                    650: static int changedir(path)
                    651: char *path;
                    652: {
                    653: #if defined(MSDOS) || defined(WIN16) || defined(ATARI) || defined(DOS386)
                    654: # if defined(__ZTC__)
                    655:     unsigned dummy;            /* it's a parameter needed for dos_setdrive */
                    656: # endif
                    657:
                    658:     /* first deal with drive letter */
                    659:
                    660:     if (isalpha(path[0]) && (path[1] == ':')) {
                    661:        int driveno = toupper(path[0]) - 'A';   /* 0=A, 1=B, ... */
                    662:
                    663: # if defined(ATARI)
                    664:        (void) Dsetdrv(driveno);
                    665: # endif
                    666:
                    667: # if defined(__ZTC__)
                    668:        (void) dos_setdrive(driveno + 1, &dummy);
                    669: # endif
                    670:
                    671: # if (defined(MSDOS) && defined(__EMX__)) || defined(__MSC__)
                    672:        (void) _chdrive(driveno + 1);
                    673: # endif
                    674:
                    675:
                    676: /* HBB: recent versions of DJGPP also have setdisk():,
                    677:  * so I del'ed the special code */
                    678: # if ((defined(MSDOS) || defined(_Windows)) && defined(__TURBOC__)) || defined(DJGPP)
                    679:        (void) setdisk(driveno);
                    680: # endif
                    681:        path += 2;              /* move past drive letter */
                    682:     }
                    683:     /* then change to actual directory */
                    684:     if (*path)
                    685:        if (chdir(path))
                    686:            return 1;
                    687:
                    688:     return 0;                  /* should report error with setdrive also */
                    689:
                    690: #elif defined(WIN32)
                    691:     return !(SetCurrentDirectory(path));
                    692: #else
                    693:     return chdir(path);
                    694: #endif /* MSDOS, ATARI etc. */
                    695: }
                    696:
                    697:
                    698: void replotrequest()
                    699: {
                    700:     if (equals(c_token, "["))
                    701:        int_error("cannot set range with replot", c_token);
                    702:
                    703:     /* do not store directly into the replot_line string, until the
                    704:      * new plot line has been successfully plotted. This way,
                    705:      * if user makes a typo in a replot line, they do not have
                    706:      * to start from scratch. The replot_line will be committed
                    707:      * after do_plot has returned, whence we know all is well
                    708:      */
                    709:     if (END_OF_COMMAND) {
                    710:        /* it must already be long enough, but lets make sure */
                    711:        int len = strlen(replot_line) + 1;
                    712:        while (input_line_len < len)
                    713:            extend_input_line();
                    714:        strcpy(input_line, replot_line);
                    715:     } else {
                    716:        char *replot_args = NULL;       /* else m_capture will free it */
                    717:        int last_token = num_tokens - 1;
                    718:        /* length = length of old part + length of new part + ',' + \0 */
                    719:        int newlen = strlen(replot_line) + token[last_token].start_index + token[last_token].length - token[c_token].start_index + 2;
                    720:        m_capture(&replot_args, c_token, last_token);   /* might be empty */
                    721:        while (input_line_len < newlen)
                    722:            extend_input_line();
                    723:        strcpy(input_line, replot_line);
                    724:        strcat(input_line, ",");
                    725:        strcat(input_line, replot_args);
                    726:        free(replot_args);
                    727:     }
                    728:     plot_token = 0;            /* whole line to be saved as replot line */
                    729:
                    730:     screen_ok = FALSE;
                    731:     num_tokens = scanner(input_line);
                    732:     c_token = 1;               /* skip the 'plot' part */
                    733:     if (is_3d_plot)
                    734:        plot3drequest();
                    735:     else
                    736:        plotrequest();
                    737: }
                    738:
                    739:
                    740: /* Support for input, shell, and help for various systems */
                    741:
                    742: #ifdef VMS
                    743:
                    744: # include <descrip.h>
                    745: # include <rmsdef.h>
                    746: # include <smgdef.h>
                    747: # include <smgmsg.h>
                    748:
                    749: extern lib$get_input(), lib$put_output();
                    750: extern smg$read_composed_line();
                    751: extern sys$putmsg();
                    752: extern lbr$output_help();
                    753: extern lib$spawn();
                    754:
                    755: int vms_len;
                    756:
                    757: unsigned int status[2] = {1, 0};
                    758:
                    759: static char Help[MAX_LINE_LEN+1] = "gnuplot";
                    760:
                    761: $DESCRIPTOR(prompt_desc, PROMPT);
                    762: /* temporary fix until change to variable length */
                    763: struct dsc$descriptor_s line_desc =
                    764: {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
                    765:
                    766: $DESCRIPTOR(help_desc, Help);
                    767: $DESCRIPTOR(helpfile_desc, "GNUPLOT$HELP");
                    768:
                    769: /* please note that the vms version of read_line doesn't support variable line
                    770:    length (yet) */
                    771:
                    772: static int read_line(prompt)
                    773: char *prompt;
                    774: {
                    775:     int more, start = 0;
                    776:     char expand_prompt[40];
                    777:
                    778:     prompt_desc.dsc$w_length = strlen(prompt);
                    779:     prompt_desc.dsc$a_pointer = prompt;
                    780:     (void) strcpy(expand_prompt, "_");
                    781:     (void) strncat(expand_prompt, prompt, 38);
                    782:     do {
                    783:        line_desc.dsc$w_length = MAX_LINE_LEN - start;
                    784:        line_desc.dsc$a_pointer = &input_line[start];
                    785:        switch (status[1] = smg$read_composed_line(&vms_vkid, &vms_ktid, &line_desc, &prompt_desc, &vms_len)) {
                    786:        case SMG$_EOF:
                    787:            done(IO_SUCCESS);   /* ^Z isn't really an error */
                    788:            break;
                    789:        case RMS$_TNS:          /* didn't press return in time */
                    790:            vms_len--;          /* skip the last character */
                    791:            break;              /* and parse anyway */
                    792:        case RMS$_BES:          /* Bad Escape Sequence */
                    793:        case RMS$_PES:          /* Partial Escape Sequence */
                    794:            sys$putmsg(status);
                    795:            vms_len = 0;        /* ignore the line */
                    796:            break;
                    797:        case SS$_NORMAL:
                    798:            break;              /* everything's fine */
                    799:        default:
                    800:            done(status[1]);    /* give the error message */
                    801:        }
                    802:        start += vms_len;
                    803:        input_line[start] = NUL;
                    804:        inline_num++;
                    805:        if (input_line[start - 1] == '\\') {
                    806:            /* Allow for a continuation line. */
                    807:            prompt_desc.dsc$w_length = strlen(expand_prompt);
                    808:            prompt_desc.dsc$a_pointer = expand_prompt;
                    809:            more = 1;
                    810:            --start;
                    811:        } else {
                    812:            line_desc.dsc$w_length = strlen(input_line);
                    813:            line_desc.dsc$a_pointer = input_line;
                    814:            more = 0;
                    815:        }
                    816:     } while (more);
                    817:     return 0;
                    818: }
                    819:
                    820:
                    821: # ifdef NO_GIH
                    822: static void do_help(toplevel)
                    823: int toplevel;                  /* not used for VMS version */
                    824: {
                    825:     int first = c_token;
                    826:     while (!END_OF_COMMAND)
                    827:        ++c_token;
                    828:
                    829:     strcpy(Help, "GNUPLOT ");
                    830:     capture(Help + 8, first, c_token - 1, sizeof(Help) - 9);
                    831:     help_desc.dsc$w_length = strlen(Help);
                    832:     if ((vaxc$errno = lbr$output_help(lib$put_output, 0, &help_desc,
                    833:                        &helpfile_desc, 0, lib$get_input)) != SS$_NORMAL)
                    834:        os_error("can't open GNUPLOT$HELP", NO_CARET);
                    835: }
                    836:
                    837: # endif /* NO_GIH */
                    838:
                    839: static void do_shell()
                    840: {
                    841:     if ((vaxc$errno = lib$spawn()) != SS$_NORMAL) {
                    842:        os_error("spawn error", NO_CARET);
                    843:     }
                    844: }
                    845:
                    846:
                    847: static void do_system()
                    848: {
                    849: /*    input_line[0] = ' ';     an embarrassment, but... */
                    850:
                    851: /* input_line is filled by read_line or load_file, but
                    852:  * line_desc length is set only by read_line; adjust now
                    853:  */
                    854:     line_desc.dsc$w_length = strlen(input_line) - 1;
                    855:     line_desc.dsc$a_pointer = &input_line[1];
                    856:
                    857:     if ((vaxc$errno = lib$spawn(&line_desc)) != SS$_NORMAL)
                    858:        os_error("spawn error", NO_CARET);
                    859:
                    860:     (void) putc('\n', stderr);
                    861: }
                    862:
                    863: #endif /* VMS */
                    864:
                    865:
                    866: #ifdef _Windows
                    867:
                    868: # ifdef NO_GIH
                    869: static void do_help(toplevel)
                    870: int toplevel;                  /* not used for windows */
                    871: {
                    872:     if (END_OF_COMMAND)
                    873:        WinHelp(textwin.hWndParent, (LPSTR) winhelpname, HELP_INDEX, (DWORD) NULL);
                    874:     else {
                    875:        char buf[128];
                    876:        int start = c_token++;
                    877:        while (!(END_OF_COMMAND))
                    878:            c_token++;
                    879:        capture(buf, start, c_token - 1, 128);
                    880:        WinHelp(textwin.hWndParent, (LPSTR) winhelpname, HELP_PARTIALKEY, (DWORD) buf);
                    881:     }
                    882: }
                    883: # endif /* NO_GIH */
                    884: #endif /* _Windows */
                    885:
                    886: /*
                    887:  * do_help: (not VMS, although it would work) Give help to the user. It
                    888:  * parses the command line into helpbuf and supplies help for that string.
                    889:  * Then, if there are subtopics available for that key, it prompts the user
                    890:  * with this string. If more input is given, do_help is called recursively,
                    891:  * with argument 0.  Thus a more specific help can be supplied. This can be
                    892:  * done repeatedly.  If null input is given, the function returns, effecting
                    893:  * a backward climb up the tree.
                    894:  * David Kotz (David.Kotz@Dartmouth.edu) 10/89
                    895:  * drd - The help buffer is first cleared when called with toplevel=1.
                    896:  * This is to fix a bug where help is broken if ^C is pressed whilst in the
                    897:  * help.
                    898:  */
                    899:
                    900: #ifndef NO_GIH
                    901: static void do_help(toplevel)
                    902: int toplevel;
                    903: {
                    904:     static char *helpbuf = NULL;
                    905:     static char *prompt = NULL;
                    906:     int base;                  /* index of first char AFTER help string */
                    907:     int len;                   /* length of current help string */
                    908:     TBOOLEAN more_help;
                    909:     TBOOLEAN only;             /* TRUE if only printing subtopics */
                    910:     int subtopics;             /* 0 if no subtopics for this topic */
                    911:     int start;                 /* starting token of help string */
                    912:     char *help_ptr;            /* name of help file */
                    913: # if defined(SHELFIND)
                    914:     static char help_fname[256] = ""; /* keep helpfilename across calls */
                    915: # endif
                    916:
                    917: # if defined(MTOS) || defined(ATARI)
                    918:     char const *const ext[] = {NULL};
                    919: # endif
                    920:
                    921:     if ((help_ptr = getenv("GNUHELP")) == (char *) NULL)
                    922: # ifndef SHELFIND
                    923:        /* if can't find environment variable then just use HELPFILE */
                    924:
                    925: /* patch by David J. Liu for getting GNUHELP from home directory */
                    926: #  if (defined(__TURBOC__) && (defined(MSDOS) || defined(DOS386))) || defined(__DJGPP__)
                    927:        help_ptr = HelpFile;
                    928: #  else
                    929: #   if defined(MTOS) || defined(ATARI)
                    930:     {
                    931:        if ((help_ptr = findfile(HELPFILE, getenv("GNUPLOTPATH"), ext)) == NULL)
                    932:            help_ptr = findfile(HELPFILE, getenv("PATH"), ext);
                    933:        if (!help_ptr)
                    934:            help_ptr = HELPFILE;
                    935:     }
                    936: #   else
                    937:        help_ptr = HELPFILE;
                    938: #   endif /* MTOS || ATARI */
                    939: #  endif /* __TURBOC__ */
                    940: /* end of patch  - DJL */
                    941:
                    942: # else /* !SHELFIND */
                    943:        /* try whether we can find the helpfile via shell_find. If not, just
                    944:           use the default. (tnx Andreas) */
                    945:
                    946:        if (!strchr(HELPFILE, ':') && !strchr(HELPFILE, '/') &&
                    947:            !strchr(HELPFILE, '\\')) {
                    948:            if (strlen(help_fname) == 0) {
                    949:                strcpy(help_fname, HELPFILE);
                    950:                if (shel_find(help_fname) == 0) {
                    951:                    strcpy(help_fname, HELPFILE);
                    952:                }
                    953:            }
                    954:            help_ptr = help_fname;
                    955:        } else {
                    956:            help_ptr = HELPFILE;
                    957:        }
                    958: # endif /* !SHELFIND */
                    959:
                    960:     /* Since MSDOS DGROUP segment is being overflowed we can not allow such  */
                    961:     /* huge static variables (1k each). Instead we dynamically allocate them */
                    962:     /* on the first call to this function...                                 */
                    963:     if (helpbuf == NULL) {
                    964:        helpbuf = gp_alloc((unsigned long) MAX_LINE_LEN, "help buffer");
                    965:        prompt = gp_alloc((unsigned long) MAX_LINE_LEN, "help prompt");
                    966:        helpbuf[0] = prompt[0] = 0;
                    967:     }
                    968:     if (toplevel)
                    969:        helpbuf[0] = prompt[0] = 0;     /* in case user hit ^c last time */
                    970:
                    971:     len = base = strlen(helpbuf);
                    972:
                    973:     /* find the end of the help command */
                    974:     for (start = c_token; !(END_OF_COMMAND); c_token++);
                    975:     /* copy new help input into helpbuf */
                    976:     if (len > 0)
                    977:        helpbuf[len++] = ' ';   /* add a space */
                    978:     capture(helpbuf + len, start, c_token - 1, MAX_LINE_LEN - len);
                    979:     squash_spaces(helpbuf + base);     /* only bother with new stuff */
                    980:     lower_case(helpbuf + base);        /* only bother with new stuff */
                    981:     len = strlen(helpbuf);
                    982:
                    983:     /* now, a lone ? will print subtopics only */
                    984:     if (strcmp(helpbuf + (base ? base + 1 : 0), "?") == 0) {
                    985:        /* subtopics only */
                    986:        subtopics = 1;
                    987:        only = TRUE;
                    988:        helpbuf[base] = NUL;    /* cut off question mark */
                    989:     } else {
                    990:        /* normal help request */
                    991:        subtopics = 0;
                    992:        only = FALSE;
                    993:     }
                    994:
                    995:     switch (help(helpbuf, help_ptr, &subtopics)) {
                    996:     case H_FOUND:{
                    997:            /* already printed the help info */
                    998:            /* subtopics now is true if there were any subtopics */
                    999:            screen_ok = FALSE;
                   1000:
                   1001:            do {
                   1002:                if (subtopics && !only) {
                   1003:                    /* prompt for subtopic with current help string */
                   1004:                    if (len > 0)
                   1005:                        (void) sprintf(prompt, "Subtopic of %s: ", helpbuf);
                   1006:                    else
                   1007:                        (void) strcpy(prompt, "Help topic: ");
                   1008:                    read_line(prompt);
                   1009:                    num_tokens = scanner(input_line);
                   1010:                    c_token = 0;
                   1011:                    more_help = !(END_OF_COMMAND);
                   1012:                    if (more_help)
                   1013:                        /* base for next level is all of current helpbuf */
                   1014:                        do_help(0);
                   1015:                } else
                   1016:                    more_help = FALSE;
                   1017:            } while (more_help);
                   1018:
                   1019:            break;
                   1020:        }
                   1021:     case H_NOTFOUND:{
                   1022:            printf("Sorry, no help for '%s'\n", helpbuf);
                   1023:            break;
                   1024:        }
                   1025:     case H_ERROR:{
                   1026:            perror(help_ptr);
                   1027:            break;
                   1028:        }
                   1029:     default:{                  /* defensive programming */
                   1030:            int_error("Impossible case in switch", NO_CARET);
                   1031:            /* NOTREACHED */
                   1032:        }
                   1033:     }
                   1034:
                   1035:     helpbuf[base] = NUL;       /* cut it off where we started */
                   1036: }
                   1037: #endif /* !NO_GIH */
                   1038:
                   1039:
                   1040: #ifndef VMS
                   1041:
                   1042: # ifdef AMIGA_AC_5
                   1043: static char *parms[80];
                   1044: static char strg0[256];
                   1045: static void getparms __PROTO((char *, char**));
                   1046: # endif
                   1047:
                   1048: static void do_system()
                   1049: {
                   1050: # ifdef AMIGA_AC_5
                   1051:     getparms(input_line + 1, parms);
                   1052:     fexecv(parms[0], parms);
                   1053: # elif (defined(ATARI) && defined(__GNUC__))
                   1054: /* || (defined(MTOS) && defined(__GNUC__)) */
                   1055:     /* use preloaded shell, if available */
                   1056:     short (*shell_p) (char *command);
                   1057:     void *ssp;
                   1058:
                   1059:     ssp = (void *) Super(NULL);
                   1060:     shell_p = *(short (**)(char *)) 0x4f6;
                   1061:     Super(ssp);
                   1062:
                   1063:     /* this is a bit strange, but we have to have a single if */
                   1064:     if (shell_p)
                   1065:        (*shell_p) (input_line + 1);
                   1066:     else
                   1067:        system(input_line + 1);
                   1068: # elif defined(_Windows)
                   1069:     winsystem(input_line + 1);
                   1070: # else /* !(AMIGA_AC_5 || ATARI && __GNUC__ || _Windows) */
                   1071: /* (am, 19980929)
                   1072:  * OS/2 related note: cmd.exe returns 255 if called w/o argument.
                   1073:  * i.e. calling a shell by "!" will always end with an error message.
                   1074:  * A workaround has to include checking for EMX,OS/2, two environment
                   1075:  *  variables,...
                   1076:  */
                   1077:     system(input_line + 1);
                   1078: # endif /* !(AMIGA_AC_5 || ATARI&&__GNUC__ || _Windows) */
                   1079: }
                   1080:
                   1081:
                   1082: # ifdef AMIGA_AC_5
                   1083: /******************************************************************************
                   1084:  * Parses the command string (for fexecv use) and  converts the first token
                   1085:  * to lower case
                   1086:  *****************************************************************************/
                   1087: static void getparms(command, parms)
                   1088: char *command;
                   1089: char **parms;
                   1090: {
                   1091:     register int i = 0;                /* A bunch of indices */
                   1092:     register int j = 0;
                   1093:     register int k = 0;
                   1094:
                   1095:     while (*(command + j) != NUL) {    /* Loop on string characters */
                   1096:        parms[k++] = strg0 + i;
                   1097:        while (*(command + j) == ' ')
                   1098:            ++j;
                   1099:        while (*(command + j) != ' ' && *(command + j) != NUL) {
                   1100:            if (*(command + j) == '"')  /* Get quoted string */
                   1101:                for (*(strg0 + (i++)) = *(command + (j++));
                   1102:                     *(command + j) != '"';
                   1103:                     *(strg0 + (i++)) = *(command + (j++)));
                   1104:            *(strg0 + (i++)) = *(command + (j++));
                   1105:        }
                   1106:        *(strg0 + (i++)) = NUL; /* NUL terminate every token */
                   1107:     }
                   1108:     parms[k] = NUL;
                   1109:
                   1110:     for (k = strlen(strg0) - 1; k >= 0; --k)   /* Convert to lower case */
                   1111:        *(strg0 + k) >= 'A' && *(strg0 + k) <= 'Z' ? *(strg0 + k) |= 32 : *(strg0 + k);
                   1112: }
                   1113:
                   1114: # endif /* AMIGA_AC_5 */
                   1115:
                   1116:
1.1.1.2 ! maekawa  1117: # if defined(READLINE) || defined(HAVE_LIBREADLINE)
1.1       maekawa  1118: /* keep some compilers happy */
                   1119: static char *rlgets __PROTO((char *s, int n, char *prompt));
                   1120:
                   1121: static char * rlgets(s, n, prompt)
                   1122: char *s;
                   1123: int n;
                   1124: char *prompt;
                   1125: {
                   1126:     static char *line = (char *) NULL;
                   1127:     static int leftover = -1;  /* index of 1st char leftover from last call */
                   1128:
                   1129:     if (leftover == -1) {
                   1130:        /* If we already have a line, first free it */
                   1131:        if (line != (char *) NULL) {
                   1132:            free(line);
                   1133:            line = NULL;
                   1134:            /* so that ^C or int_error during readline() does
                   1135:             * not result in line being free-ed twice */
                   1136:        }
                   1137:        line = readline((interactive) ? prompt : "");
                   1138:        leftover = 0;
                   1139:        /* If it's not an EOF */
                   1140:        if (line && *line)
                   1141:            add_history(line);
                   1142:     }
                   1143:     if (line) {
                   1144:        safe_strncpy(s, line + leftover, n);
                   1145:        leftover += strlen(s);
                   1146:        if (line[leftover] == NUL)
                   1147:            leftover = -1;
                   1148:        return s;
                   1149:     }
                   1150:     return NULL;
                   1151: }
1.1.1.2 ! maekawa  1152: # endif /* READLINE || HAVE_LIBREADLINE */
1.1       maekawa  1153:
                   1154:
                   1155: # if defined(MSDOS) || defined(_Windows) || defined(DOS386)
                   1156: static void do_shell()
                   1157: {
                   1158:     register char *comspec;
                   1159:     if ((comspec = getenv("COMSPEC")) == (char *) NULL)
                   1160:        comspec = "\\command.com";
                   1161: #  ifdef _Windows
                   1162:     if (WinExec(comspec, SW_SHOWNORMAL) <= 32)
                   1163: #  else
                   1164: #   ifdef DJGPP
                   1165:     if (system(comspec) == -1)
                   1166: #   else
                   1167:     if (spawnl(P_WAIT, comspec, NULL) == -1)
                   1168: #   endif /* !DJGPP */
                   1169: #  endif /* !_Windows */
                   1170:        os_error("unable to spawn shell", NO_CARET);
                   1171: }
                   1172:
                   1173: # else /* !MSDOS */
                   1174:
                   1175: /* plain old Unix */
                   1176:
                   1177: #  ifdef AMIGA_SC_6_1
                   1178: static void do_shell()
                   1179: {
                   1180:     register char *shell;
                   1181:     if (!(shell = getenv("SHELL")))
                   1182:        shell = SHELL;
                   1183:
                   1184:     if (system(shell))
                   1185:        os_error("system() failed", NO_CARET);
                   1186:
                   1187:     (void) putc('\n', stderr);
                   1188: }
                   1189:
                   1190: #  else /* !AMIGA_SC_6_1 */
                   1191:
                   1192: #   ifdef OS2
                   1193: static void do_shell()
                   1194: {
                   1195:     register char *shell;
                   1196:     if (!(shell = getenv("SHELL")) && !(shell = getenv("COMSPEC")))
                   1197:        shell = SHELL;
                   1198:
                   1199:     if (system(shell) == -1)
                   1200:        os_error("system() failed", NO_CARET);
                   1201:
                   1202:     (void) putc('\n', stderr);
                   1203: }
                   1204: #   else /* !OS2 */
                   1205:
                   1206: #define EXEC "exec "
                   1207: static void do_shell()
                   1208: {
                   1209:     static char exec[100] = EXEC;
                   1210:     register char *shell;
                   1211:     if (!(shell = getenv("SHELL")))
                   1212:        shell = SHELL;
                   1213:
                   1214:     if (system(safe_strncpy(&exec[sizeof(EXEC) - 1], shell,
                   1215:                       sizeof(exec) - sizeof(EXEC) - 1)))
                   1216:        os_error("system() failed", NO_CARET);
                   1217:
                   1218:     (void) putc('\n', stderr);
                   1219: }
                   1220:
                   1221: #   endif /* !OS2 */
                   1222: #  endif /* !AMIGA_SC_6_1 */
                   1223: # endif /* !MSDOS */
                   1224:
                   1225: /* read from stdin, everything except VMS */
                   1226:
1.1.1.2 ! maekawa  1227: # if !defined(READLINE) && !defined(HAVE_LIBREADLINE)
1.1       maekawa  1228: #  if (defined(MSDOS) || defined(DOS386)) && !defined(_Windows) && !defined(__EMX__) && !defined(DJGPP)
                   1229:
                   1230: /* if interactive use console IO so CED will work */
                   1231:
                   1232: #define PUT_STRING(s) cputs(s)
                   1233: #define GET_STRING(s,l) ((interactive) ? cgets_emu(s,l) : fgets(s,l,stdin))
                   1234:
                   1235: #   ifdef __TURBOC__
                   1236: /* cgets implemented using dos functions */
                   1237: /* Maurice Castro 22/5/91 */
                   1238: static char *doscgets __PROTO((char *));
                   1239:
                   1240: static char *doscgets(s)
                   1241: char *s;
                   1242: {
                   1243:     long datseg;
                   1244:
                   1245:     /* protect and preserve segments - call dos to do the dirty work */
                   1246:     datseg = _DS;
                   1247:
                   1248:     _DX = FP_OFF(s);
                   1249:     _DS = FP_SEG(s);
                   1250:     _AH = 0x0A;
                   1251:     geninterrupt(33);
                   1252:     _DS = datseg;
                   1253:
                   1254:     /* check for a carriage return and then clobber it with a null */
                   1255:     if (s[s[1] + 2] == '\r')
                   1256:        s[s[1] + 2] = 0;
                   1257:
                   1258:     /* return the input string */
                   1259:     return (&(s[2]));
                   1260: }
                   1261: #   endif /* __TURBOC__ */
                   1262:
                   1263: #   ifdef __ZTC__
                   1264: void cputs(char *s)
                   1265: {
                   1266:     register int i = 0;
                   1267:     while (s[i] != NUL)
                   1268:        bdos(0x02, s[i++], NULL);
                   1269: }
                   1270:
                   1271: char *cgets(char *s)
                   1272: {
                   1273:     bdosx(0x0A, s, NULL);
                   1274:
                   1275:     if (s[s[1] + 2] == '\r')
                   1276:        s[s[1] + 2] = 0;
                   1277:
                   1278:     /* return the input string */
                   1279:     return (&(s[2]));
                   1280: }
                   1281: #   endif /* __ZTC__ */
                   1282:
                   1283: /* emulate a fgets like input function with DOS cgets */
                   1284: char *cgets_emu(str, len)
                   1285: char *str;
                   1286: int len;
                   1287: {
                   1288:     static char buffer[128] = "";
                   1289:     static int leftover = 0;
                   1290:
                   1291:     if (buffer[leftover] == NUL) {
                   1292:        buffer[0] = 126;
                   1293: #   ifdef __TURBOC__
                   1294:        doscgets(buffer);
                   1295: #   else
                   1296:        cgets(buffer);
                   1297: #   endif
                   1298:        fputc('\n', stderr);
                   1299:        if (buffer[2] == 26)
                   1300:            return NULL;
                   1301:        leftover = 2;
                   1302:     }
                   1303:     safe_strncpy(str, buffer + leftover, len);
                   1304:     leftover += strlen(str);
                   1305:     return str;
                   1306: }
                   1307: #  else /* !plain DOS */
                   1308:
                   1309: #   define PUT_STRING(s) fputs(s, stderr)
                   1310: #   define GET_STRING(s,l) fgets(s, l, stdin)
                   1311:
                   1312: #  endif /* !plain DOS */
1.1.1.2 ! maekawa  1313: # endif /* !READLINE && !HAVE_LIBREADLINE) */
1.1       maekawa  1314:
                   1315: /* Non-VMS version */
                   1316: static int read_line(prompt)
                   1317: char *prompt;
                   1318: {
                   1319:     int start = 0;
                   1320:     TBOOLEAN more = FALSE;
                   1321:     int last = 0;
                   1322:
1.1.1.2 ! maekawa  1323: # if !defined(READLINE) && !defined(HAVE_LIBREADLINE)
1.1       maekawa  1324:     if (interactive)
                   1325:        PUT_STRING(prompt);
                   1326: # endif /* READLINE */
                   1327:     do {
                   1328:        /* grab some input */
1.1.1.2 ! maekawa  1329: # if defined(READLINE) || defined(HAVE_LIBREADLINE)
1.1       maekawa  1330:        if (((interactive)
                   1331:             ? rlgets(&(input_line[start]), input_line_len - start,
                   1332:                      ((more) ? "> " : prompt))
                   1333:             : fgets(&(input_line[start]), input_line_len - start, stdin))
                   1334:            == (char *) NULL) {
1.1.1.2 ! maekawa  1335: # else /* !(READLINE || HAVE_LIBREADLINE) */
1.1       maekawa  1336:        if (GET_STRING(&(input_line[start]), input_line_len - start)
                   1337:            == (char *) NULL) {
1.1.1.2 ! maekawa  1338: # endif /* !(READLINE || HAVE_LIBREADLINE) */
1.1       maekawa  1339:            /* end-of-file */
                   1340:            if (interactive)
                   1341:                (void) putc('\n', stderr);
                   1342:            input_line[start] = NUL;
                   1343:            inline_num++;
                   1344:            if (start > 0)      /* don't quit yet - process what we have */
                   1345:                more = FALSE;
                   1346:            else
                   1347:                return (1);     /* exit gnuplot */
                   1348:        } else {
                   1349:            /* normal line input */
                   1350:            last = strlen(input_line) - 1;
                   1351:            if (last >= 0) {
                   1352:                if (input_line[last] == '\n') {         /* remove any newline */
                   1353:                    input_line[last] = NUL;
                   1354:                    /* Watch out that we don't backup beyond 0 (1-1-1) */
                   1355:                    if (last > 0)
                   1356:                        --last;
                   1357:                } else if (last + 2 >= input_line_len) {
                   1358:                    extend_input_line();
                   1359:                    start = last + 1;
                   1360:                    more = TRUE;
                   1361:                    continue;   /* read rest of line, don't print "> " */
                   1362:                }
                   1363:                if (input_line[last] == '\\') {         /* line continuation */
                   1364:                    start = last;
                   1365:                    more = TRUE;
                   1366:                } else
                   1367:                    more = FALSE;
                   1368:            } else
                   1369:                more = FALSE;
                   1370:        }
1.1.1.2 ! maekawa  1371: # if !defined(READLINE) && !defined(HAVE_LIBREADLINE)
1.1       maekawa  1372:        if (more && interactive)
                   1373:            PUT_STRING("> ");
                   1374: # endif
                   1375:     } while (more);
                   1376:     return (0);
                   1377: }
                   1378: #endif /* !VMS */
                   1379:
                   1380: #ifdef _Windows
                   1381: /* there is a system like call on MS Windows but it is a bit difficult to
                   1382:    use, so we will invoke the command interpreter and use it to execute the
                   1383:    commands */
                   1384: static int winsystem(char *s)
                   1385: {
                   1386:     LPSTR comspec;
                   1387:     LPSTR execstr;
                   1388:     LPSTR p;
                   1389:
                   1390:     /* get COMSPEC environment variable */
                   1391: # ifdef WIN32
                   1392:     char envbuf[81];
                   1393:     GetEnvironmentVariable("COMSPEC", envbuf, 80);
                   1394:     if (*envbuf == NUL)
                   1395:        comspec = "\\command.com";
                   1396:     else
                   1397:        comspec = envbuf;
                   1398: # else
                   1399:     p = GetDOSEnvironment();
                   1400:     comspec = "\\command.com";
                   1401:     while (*p) {
                   1402:        if (!strncmp(p, "COMSPEC=", 8)) {
                   1403:            comspec = p + 8;
                   1404:            break;
                   1405:        }
                   1406:        p += strlen(p) + 1;
                   1407:     }
                   1408: # endif
                   1409:     /* if the command is blank we must use command.com */
                   1410:     p = s;
                   1411:     while ((*p == ' ') || (*p == '\n') || (*p == '\r'))
                   1412:        p++;
                   1413:     if (*p == NUL) {
                   1414:        WinExec(comspec, SW_SHOWNORMAL);
                   1415:     } else {
                   1416:        /* attempt to run the windows/dos program via windows */
                   1417:        if (WinExec(s, SW_SHOWNORMAL) <= 32) {
                   1418:            /* attempt to run it as a dos program from command line */
                   1419:            execstr = (char *) malloc(strlen(s) + strlen(comspec) + 6);
                   1420:            strcpy(execstr, comspec);
                   1421:            strcat(execstr, " /c ");
                   1422:            strcat(execstr, s);
                   1423:            WinExec(execstr, SW_SHOWNORMAL);
                   1424:            free(execstr);
                   1425:        }
                   1426:     }
                   1427:
                   1428:     /* regardless of the reality return OK - the consequences of */
                   1429:     /* failure include shutting down Windows */
                   1430:     return (0);                        /* success */
                   1431: }
                   1432: #endif /* _Windows */
                   1433:

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