mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-24 06:17:57 +02:00
commit bash-20090416 snapshot
This commit is contained in:
@@ -7934,3 +7934,34 @@ parse.y
|
||||
character can change to a state where a reserved word is legal,
|
||||
since it is not a shell meta character. Fixes bug reported by
|
||||
Bernd Eggink <monoped@sudrala.de>.
|
||||
|
||||
4/17
|
||||
----
|
||||
jobs.c
|
||||
- new functions to save and restore the pgrp_pipe (since there's only
|
||||
one): save_pgrp_pipe and restore_pgrp_pipe
|
||||
|
||||
trap.c
|
||||
- run_debug_trap now saves and restores the pgrp_pipe before and
|
||||
after calling the debug trap
|
||||
- run_debug_trap now makes sure the terminal is owned by the pipeline
|
||||
pgrp after the debug trap runs. Rest of fix for bug reported by
|
||||
Oleksly Melnyk <o.melnyk@upc.ua> (lex@upc.ca)
|
||||
|
||||
4/19
|
||||
----
|
||||
include/posixselect.h
|
||||
- new include file, encapsulates select(2) includes and defines for
|
||||
bash and readline. Inspired by patch from Mike Frysinger
|
||||
<vapier@gentoo.org>
|
||||
|
||||
lib/sh/input_avail.c
|
||||
- include "posixselect.h"
|
||||
|
||||
lib/readline/{input,parens}.c
|
||||
- include "posixselect.h" instead of using inline includes
|
||||
- use new USEC_TO_TIMEVAL define to make sure that values for timeouts
|
||||
greater than one second are handled properly
|
||||
|
||||
lib/sh/fpurge.c
|
||||
- updated implementation, taken from gnulib
|
||||
|
||||
@@ -7926,3 +7926,39 @@ lib/readline/terminal.c
|
||||
- in rl_resize_terminal, don't call rl_redisplay_after_sigwinch() if
|
||||
we're already in the middle of redisplay (RL_STATE_REDISPLAYING).
|
||||
Fix for bug reported by Nicolai Lissner <nlissne@linux01.org>
|
||||
|
||||
4/15
|
||||
----
|
||||
parse.y
|
||||
- fix parse_comsub to add check for \n when seeing whether the current
|
||||
character can change to a state where a reserved word is legal,
|
||||
since it is not a shell meta character. Fixes bug reported by
|
||||
Bernd Eggink <monoped@sudrala.de>.
|
||||
|
||||
4/17
|
||||
----
|
||||
jobs.c
|
||||
- new functions to save and restore the pgrp_pipe (since there's only
|
||||
one): save_pgrp_pipe and restore_pgrp_pipe
|
||||
|
||||
trap.c
|
||||
- run_debug_trap now saves and restores the pgrp_pipe before and
|
||||
after calling the debug trap
|
||||
- run_debug_trap now makes sure the terminal is owned by the pipeline
|
||||
pgrp after the debug trap runs. Rest of fix for bug reported by
|
||||
Oleksly Melnyk <o.melnyk@upc.ua> (lex@upc.ca)
|
||||
|
||||
4/19
|
||||
----
|
||||
include/posixselect.h
|
||||
- new include file, encapsulates select(2) includes and defines for
|
||||
bash and readline. Inspired by patch from Mike Frysinger
|
||||
<vapier@gentoo.org>
|
||||
|
||||
lib/sh/input_avail.c
|
||||
- include "posixselect.h"
|
||||
|
||||
lib/readline/{input,parens}.c
|
||||
- include "posixselect.h" instead of using inline includes
|
||||
- use new USEC_TO_TIMEVAL define to make sure that values for timeouts
|
||||
greater than one second are handled properly
|
||||
|
||||
@@ -215,6 +215,7 @@ include/memalloc.h f
|
||||
include/ocache.h f
|
||||
include/posixdir.h f
|
||||
include/posixjmp.h f
|
||||
include/posixselect.h f
|
||||
include/posixstat.h f
|
||||
include/posixtime.h f
|
||||
include/posixwait.h f
|
||||
|
||||
@@ -1036,6 +1036,7 @@ tests/trap.right f
|
||||
tests/trap1.sub f 755
|
||||
tests/trap2.sub f 755
|
||||
tests/trap2a.sub f 755
|
||||
tests/trap3.sub f
|
||||
tests/type.tests f
|
||||
tests/type.right f
|
||||
tests/type1.sub f
|
||||
|
||||
+1
-1
@@ -7323,7 +7323,7 @@ But first, you should
|
||||
make sure that it really is a bug, and that it appears in the latest
|
||||
version of Bash.
|
||||
The latest version of Bash is always available for FTP from
|
||||
@uref{ftp://ftp.gnu.org/pub/bash/}.
|
||||
@uref{ftp://ftp.gnu.org/pub/gnu/bash/}.
|
||||
|
||||
Once you have determined that a bug actually exists, use the
|
||||
@code{bashbug} command to submit a bug report.
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/* posixselect.h -- wrapper for select(2) includes and definitions */
|
||||
|
||||
/* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _POSIXSELECT_H_
|
||||
#define _POSIXSELECT_H_
|
||||
|
||||
#if defined (FD_SET) && !defined (HAVE_SELECT)
|
||||
# define HAVE_SELECT 1
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_SELECT)
|
||||
# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX)
|
||||
# include <sys/time.h>
|
||||
# endif
|
||||
#endif /* HAVE_SELECT */
|
||||
#if defined (HAVE_SYS_SELECT_H)
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#ifndef USEC_PER_SEC
|
||||
# define USEC_PER_SEC 1000000
|
||||
#endif
|
||||
|
||||
#define USEC_TO_TIMEVAL(us, tv) \
|
||||
do { \
|
||||
(tv).tv_sec = (us) / USEC_PER_SEC; \
|
||||
(tv).tv_usec = (us) % USEC_PER_SEC; \
|
||||
} while (0)
|
||||
|
||||
#endif /* _POSIXSELECT_H_ */
|
||||
@@ -0,0 +1,24 @@
|
||||
/* posixselect.h -- wrapper for select(2) includes and definitions */
|
||||
|
||||
/* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _POSIXSELECT_H_
|
||||
#define _POSIXSELECT_H_
|
||||
|
||||
#endif /* _POSIXSELECT_H_ */
|
||||
@@ -4203,4 +4203,23 @@ close_pgrp_pipe ()
|
||||
sh_closepipe (pgrp_pipe);
|
||||
}
|
||||
|
||||
void
|
||||
save_pgrp_pipe (p, clear)
|
||||
int *p;
|
||||
int clear;
|
||||
{
|
||||
p[0] = pgrp_pipe[0];
|
||||
p[1] = pgrp_pipe[1];
|
||||
if (clear)
|
||||
pgrp_pipe[0] = pgrp_pipe[1] = -1;
|
||||
}
|
||||
|
||||
void
|
||||
restore_pgrp_pipe (p)
|
||||
int *p;
|
||||
{
|
||||
pgrp_pipe[0] = p[0];
|
||||
pgrp_pipe[1] = p[1];
|
||||
}
|
||||
|
||||
#endif /* PGRP_PIPE */
|
||||
|
||||
@@ -427,7 +427,6 @@ void
|
||||
save_pipeline (clear)
|
||||
int clear;
|
||||
{
|
||||
itrace("save_pipeline (%d)", clear);
|
||||
saved_pipeline = the_pipeline;
|
||||
if (clear)
|
||||
the_pipeline = (PROCESS *)NULL;
|
||||
@@ -440,7 +439,6 @@ restore_pipeline (discard)
|
||||
{
|
||||
PROCESS *old_pipeline;
|
||||
|
||||
itrace("restore_pipeline (%d)", discard);
|
||||
old_pipeline = the_pipeline;
|
||||
the_pipeline = saved_pipeline;
|
||||
already_making_children = saved_already_making_children;
|
||||
@@ -457,6 +455,7 @@ start_pipeline ()
|
||||
cleanup_the_pipeline ();
|
||||
pipeline_pgrp = 0;
|
||||
#if defined (PGRP_PIPE)
|
||||
itrace("start_pipeline: cleaning up existing pipeline: closing %d %d", pgrp_pipe[0], pgrp_pipe[1]);
|
||||
sh_closepipe (pgrp_pipe);
|
||||
#endif
|
||||
}
|
||||
@@ -466,6 +465,7 @@ start_pipeline ()
|
||||
{
|
||||
if (pipe (pgrp_pipe) == -1)
|
||||
sys_error (_("start_pipeline: pgrp pipe"));
|
||||
itrace("start_pipeline: pgrp_pipe: %d %d", pgrp_pipe[0], pgrp_pipe[1]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -487,6 +487,7 @@ stop_pipeline (async, deferred)
|
||||
|
||||
#if defined (PGRP_PIPE)
|
||||
/* The parent closes the process group synchronization pipe. */
|
||||
itrace("stop_pipeline: close pgrp_pipe %d %d", pgrp_pipe[0], pgrp_pipe[1]);
|
||||
sh_closepipe (pgrp_pipe);
|
||||
#endif
|
||||
|
||||
@@ -594,7 +595,6 @@ stop_pipeline (async, deferred)
|
||||
newjob->j_cleanup = (sh_vptrfunc_t *)NULL;
|
||||
newjob->cleanarg = (PTR_T) NULL;
|
||||
|
||||
itrace("adding the_pipeline (%s) as job index %d", newjob->pipe->command, i);
|
||||
jobs[i] = newjob;
|
||||
if (newjob->state == JDEAD && (newjob->flags & J_FOREGROUND))
|
||||
setjstatus (i);
|
||||
@@ -4206,4 +4206,23 @@ close_pgrp_pipe ()
|
||||
sh_closepipe (pgrp_pipe);
|
||||
}
|
||||
|
||||
void
|
||||
save_pgrp_pipe (p, clear)
|
||||
int *p;
|
||||
int clear;
|
||||
{
|
||||
p[0] = pgrp_pipe[0];
|
||||
p[1] = pgrp_pipe[1];
|
||||
if (clear)
|
||||
pgrp_pipe[0] = pgrp_pipe[1] = -1;
|
||||
}
|
||||
|
||||
void
|
||||
restore_pgrp_pipe (p)
|
||||
int *p;
|
||||
{
|
||||
pgrp_pipe[0] = p[0];
|
||||
pgrp_pipe[1] = p[1];
|
||||
}
|
||||
|
||||
#endif /* PGRP_PIPE */
|
||||
|
||||
@@ -235,6 +235,8 @@ extern void default_tty_job_signals __P((void));
|
||||
extern void init_job_stats __P((void));
|
||||
|
||||
extern void close_pgrp_pipe __P((void));
|
||||
extern void save_pgrp_pipe __P((int *, int));
|
||||
extern void restore_pgrp_pipe __P((int *));
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
extern int job_control;
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
/* jobs.h -- structures and definitions used by the jobs.c file. */
|
||||
|
||||
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (_JOBS_H_)
|
||||
# define _JOBS_H_
|
||||
|
||||
#include "quit.h"
|
||||
#include "siglist.h"
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
#include "posixwait.h"
|
||||
|
||||
/* Defines controlling the fashion in which jobs are listed. */
|
||||
#define JLIST_STANDARD 0
|
||||
#define JLIST_LONG 1
|
||||
#define JLIST_PID_ONLY 2
|
||||
#define JLIST_CHANGED_ONLY 3
|
||||
#define JLIST_NONINTERACTIVE 4
|
||||
|
||||
/* I looked it up. For pretty_print_job (). The real answer is 24. */
|
||||
#define LONGEST_SIGNAL_DESC 24
|
||||
|
||||
/* The max time to sleep while retrying fork() on EAGAIN failure */
|
||||
#define FORKSLEEP_MAX 16
|
||||
|
||||
/* We keep an array of jobs. Each entry in the array is a linked list
|
||||
of processes that are piped together. The first process encountered is
|
||||
the group leader. */
|
||||
|
||||
/* Values for the `running' field of a struct process. */
|
||||
#define PS_DONE 0
|
||||
#define PS_RUNNING 1
|
||||
#define PS_STOPPED 2
|
||||
#define PS_RECYCLED 4
|
||||
|
||||
/* Each child of the shell is remembered in a STRUCT PROCESS. A circular
|
||||
chain of such structures is a pipeline. */
|
||||
typedef struct process {
|
||||
struct process *next; /* Next process in the pipeline. A circular chain. */
|
||||
pid_t pid; /* Process ID. */
|
||||
WAIT status; /* The status of this command as returned by wait. */
|
||||
int running; /* Non-zero if this process is running. */
|
||||
char *command; /* The particular program that is running. */
|
||||
} PROCESS;
|
||||
|
||||
/* PALIVE really means `not exited' */
|
||||
#define PSTOPPED(p) (WIFSTOPPED((p)->status))
|
||||
#define PRUNNING(p) ((p)->running == PS_RUNNING)
|
||||
#define PALIVE(p) (PRUNNING(p) || PSTOPPED(p))
|
||||
|
||||
#define PEXITED(p) ((p)->running == PS_DONE)
|
||||
#if defined (RECYCLES_PIDS)
|
||||
# define PRECYCLED(p) ((p)->running == PS_RECYCLED)
|
||||
#else
|
||||
# define PRECYCLED(p) (0)
|
||||
#endif
|
||||
#define PDEADPROC(p) (PEXITED(p) || PRECYCLED(p))
|
||||
|
||||
#define get_job_by_jid(ind) (jobs[(ind)])
|
||||
|
||||
/* A description of a pipeline's state. */
|
||||
typedef enum { JNONE = -1, JRUNNING = 1, JSTOPPED = 2, JDEAD = 4, JMIXED = 8 } JOB_STATE;
|
||||
#define JOBSTATE(job) (jobs[(job)]->state)
|
||||
#define J_JOBSTATE(j) ((j)->state)
|
||||
|
||||
#define STOPPED(j) (jobs[(j)]->state == JSTOPPED)
|
||||
#define RUNNING(j) (jobs[(j)]->state == JRUNNING)
|
||||
#define DEADJOB(j) (jobs[(j)]->state == JDEAD)
|
||||
|
||||
#define INVALID_JOB(j) ((j) < 0 || (j) >= js.j_jobslots || get_job_by_jid(j) == 0)
|
||||
|
||||
/* Values for the FLAGS field in the JOB struct below. */
|
||||
#define J_FOREGROUND 0x01 /* Non-zero if this is running in the foreground. */
|
||||
#define J_NOTIFIED 0x02 /* Non-zero if already notified about job state. */
|
||||
#define J_JOBCONTROL 0x04 /* Non-zero if this job started under job control. */
|
||||
#define J_NOHUP 0x08 /* Don't send SIGHUP to job if shell gets SIGHUP. */
|
||||
#define J_STATSAVED 0x10 /* A process in this job had had status saved via $! */
|
||||
#define J_ASYNC 0x20 /* Job was started asynchronously */
|
||||
|
||||
#define IS_FOREGROUND(j) ((jobs[j]->flags & J_FOREGROUND) != 0)
|
||||
#define IS_NOTIFIED(j) ((jobs[j]->flags & J_NOTIFIED) != 0)
|
||||
#define IS_JOBCONTROL(j) ((jobs[j]->flags & J_JOBCONTROL) != 0)
|
||||
#define IS_ASYNC(j) ((jobs[j]->flags & J_ASYNC) != 0)
|
||||
|
||||
typedef struct job {
|
||||
char *wd; /* The working directory at time of invocation. */
|
||||
PROCESS *pipe; /* The pipeline of processes that make up this job. */
|
||||
pid_t pgrp; /* The process ID of the process group (necessary). */
|
||||
JOB_STATE state; /* The state that this job is in. */
|
||||
int flags; /* Flags word: J_NOTIFIED, J_FOREGROUND, or J_JOBCONTROL. */
|
||||
#if defined (JOB_CONTROL)
|
||||
COMMAND *deferred; /* Commands that will execute when this job is done. */
|
||||
sh_vptrfunc_t *j_cleanup; /* Cleanup function to call when job marked JDEAD */
|
||||
PTR_T cleanarg; /* Argument passed to (*j_cleanup)() */
|
||||
#endif /* JOB_CONTROL */
|
||||
} JOB;
|
||||
|
||||
struct jobstats {
|
||||
/* limits */
|
||||
long c_childmax;
|
||||
/* child process statistics */
|
||||
int c_living; /* running or stopped child processes */
|
||||
int c_reaped; /* exited child processes still in jobs list */
|
||||
int c_injobs; /* total number of child processes in jobs list */
|
||||
/* child process totals */
|
||||
int c_totforked; /* total number of children this shell has forked */
|
||||
int c_totreaped; /* total number of children this shell has reaped */
|
||||
/* job counters and indices */
|
||||
int j_jobslots; /* total size of jobs array */
|
||||
int j_lastj; /* last (newest) job allocated */
|
||||
int j_firstj; /* first (oldest) job allocated */
|
||||
int j_njobs; /* number of non-NULL jobs in jobs array */
|
||||
int j_ndead; /* number of JDEAD jobs in jobs array */
|
||||
/* */
|
||||
int j_current; /* current job */
|
||||
int j_previous; /* previous job */
|
||||
/* */
|
||||
JOB *j_lastmade; /* last job allocated by stop_pipeline */
|
||||
JOB *j_lastasync; /* last async job allocated by stop_pipeline */
|
||||
};
|
||||
|
||||
struct pidstat {
|
||||
struct pidstat *next;
|
||||
pid_t pid;
|
||||
int status;
|
||||
};
|
||||
|
||||
struct bgpids {
|
||||
struct pidstat *list;
|
||||
struct pidstat *end;
|
||||
int npid;
|
||||
};
|
||||
|
||||
#define NO_JOB -1 /* An impossible job array index. */
|
||||
#define DUP_JOB -2 /* A possible return value for get_job_spec (). */
|
||||
#define BAD_JOBSPEC -3 /* Bad syntax for job spec. */
|
||||
|
||||
/* A value which cannot be a process ID. */
|
||||
#define NO_PID (pid_t)-1
|
||||
|
||||
/* System calls. */
|
||||
#if !defined (HAVE_UNISTD_H)
|
||||
extern pid_t fork (), getpid (), getpgrp ();
|
||||
#endif /* !HAVE_UNISTD_H */
|
||||
|
||||
/* Stuff from the jobs.c file. */
|
||||
extern struct jobstats js;
|
||||
|
||||
extern pid_t original_pgrp, shell_pgrp, pipeline_pgrp;
|
||||
extern pid_t last_made_pid, last_asynchronous_pid;
|
||||
extern int asynchronous_notification;
|
||||
|
||||
extern JOB **jobs;
|
||||
|
||||
extern void making_children __P((void));
|
||||
extern void stop_making_children __P((void));
|
||||
extern void cleanup_the_pipeline __P((void));
|
||||
extern void save_pipeline __P((int));
|
||||
extern void restore_pipeline __P((int));
|
||||
extern void start_pipeline __P((void));
|
||||
extern int stop_pipeline __P((int, COMMAND *));
|
||||
|
||||
extern void delete_job __P((int, int));
|
||||
extern void nohup_job __P((int));
|
||||
extern void delete_all_jobs __P((int));
|
||||
extern void nohup_all_jobs __P((int));
|
||||
|
||||
extern int count_all_jobs __P((void));
|
||||
|
||||
extern void terminate_current_pipeline __P((void));
|
||||
extern void terminate_stopped_jobs __P((void));
|
||||
extern void hangup_all_jobs __P((void));
|
||||
extern void kill_current_pipeline __P((void));
|
||||
|
||||
#if defined (__STDC__) && defined (pid_t)
|
||||
extern int get_job_by_pid __P((int, int));
|
||||
extern void describe_pid __P((int));
|
||||
#else
|
||||
extern int get_job_by_pid __P((pid_t, int));
|
||||
extern void describe_pid __P((pid_t));
|
||||
#endif
|
||||
|
||||
extern void list_one_job __P((JOB *, int, int, int));
|
||||
extern void list_all_jobs __P((int));
|
||||
extern void list_stopped_jobs __P((int));
|
||||
extern void list_running_jobs __P((int));
|
||||
|
||||
extern pid_t make_child __P((char *, int));
|
||||
|
||||
extern int get_tty_state __P((void));
|
||||
extern int set_tty_state __P((void));
|
||||
|
||||
extern int wait_for_single_pid __P((pid_t));
|
||||
extern void wait_for_background_pids __P((void));
|
||||
extern int wait_for __P((pid_t));
|
||||
extern int wait_for_job __P((int));
|
||||
|
||||
extern void notify_and_cleanup __P((void));
|
||||
extern void reap_dead_jobs __P((void));
|
||||
extern int start_job __P((int, int));
|
||||
extern int kill_pid __P((pid_t, int, int));
|
||||
extern int initialize_job_control __P((int));
|
||||
extern void initialize_job_signals __P((void));
|
||||
extern int give_terminal_to __P((pid_t, int));
|
||||
|
||||
extern void run_sigchld_trap __P((int));
|
||||
|
||||
extern void unfreeze_jobs_list __P((void));
|
||||
extern int set_job_control __P((int));
|
||||
extern void without_job_control __P((void));
|
||||
extern void end_job_control __P((void));
|
||||
extern void restart_job_control __P((void));
|
||||
extern void set_sigchld_handler __P((void));
|
||||
extern void ignore_tty_job_signals __P((void));
|
||||
extern void default_tty_job_signals __P((void));
|
||||
|
||||
extern void init_job_stats __P((void));
|
||||
|
||||
extern void close_pgrp_pipe __P((void));
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
extern int job_control;
|
||||
#endif
|
||||
|
||||
#endif /* _JOBS_H_ */
|
||||
+2
-10
@@ -45,14 +45,7 @@
|
||||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#if defined (HAVE_SELECT)
|
||||
# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX)
|
||||
# include <sys/time.h>
|
||||
# endif
|
||||
#endif /* HAVE_SELECT */
|
||||
#if defined (HAVE_SYS_SELECT_H)
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
#include "posixselect.h"
|
||||
|
||||
#if defined (FIONREAD_IN_SYS_IOCTL)
|
||||
# include <sys/ioctl.h>
|
||||
@@ -190,8 +183,7 @@ rl_gather_tyi ()
|
||||
FD_ZERO (&exceptfds);
|
||||
FD_SET (tty, &readfds);
|
||||
FD_SET (tty, &exceptfds);
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = _keyboard_input_timeout;
|
||||
USEC_TO_TIMEVAL (_keyboard_input_timeout, timeout);
|
||||
result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
|
||||
if (result <= 0)
|
||||
return 0; /* Nothing to read. */
|
||||
|
||||
@@ -0,0 +1,595 @@
|
||||
/* input.c -- character input functions for readline. */
|
||||
|
||||
/* Copyright (C) 1994-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
|
||||
Readline is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Readline is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Readline. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define READLINE_LIBRARY
|
||||
|
||||
#if defined (__TANDEM)
|
||||
# include <floss.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#if defined (HAVE_SYS_FILE_H)
|
||||
# include <sys/file.h>
|
||||
#endif /* HAVE_SYS_FILE_H */
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#include "posixselect.h"
|
||||
|
||||
#if defined (FIONREAD_IN_SYS_IOCTL)
|
||||
# include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
/* System-specific feature definitions and include files. */
|
||||
#include "rldefs.h"
|
||||
#include "rlmbutil.h"
|
||||
|
||||
/* Some standard library routines. */
|
||||
#include "readline.h"
|
||||
|
||||
#include "rlprivate.h"
|
||||
#include "rlshell.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* What kind of non-blocking I/O do we have? */
|
||||
#if !defined (O_NDELAY) && defined (O_NONBLOCK)
|
||||
# define O_NDELAY O_NONBLOCK /* Posix style */
|
||||
#endif
|
||||
|
||||
/* Non-null means it is a pointer to a function to run while waiting for
|
||||
character input. */
|
||||
rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL;
|
||||
|
||||
rl_getc_func_t *rl_getc_function = rl_getc;
|
||||
|
||||
static int _keyboard_input_timeout = 100000; /* 0.1 seconds; it's in usec */
|
||||
|
||||
static int ibuffer_space PARAMS((void));
|
||||
static int rl_get_char PARAMS((int *));
|
||||
static int rl_gather_tyi PARAMS((void));
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Character Input Buffering */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
static int pop_index, push_index;
|
||||
static unsigned char ibuffer[512];
|
||||
static int ibuffer_len = sizeof (ibuffer) - 1;
|
||||
|
||||
#define any_typein (push_index != pop_index)
|
||||
|
||||
int
|
||||
_rl_any_typein ()
|
||||
{
|
||||
return any_typein;
|
||||
}
|
||||
|
||||
/* Return the amount of space available in the buffer for stuffing
|
||||
characters. */
|
||||
static int
|
||||
ibuffer_space ()
|
||||
{
|
||||
if (pop_index > push_index)
|
||||
return (pop_index - push_index - 1);
|
||||
else
|
||||
return (ibuffer_len - (push_index - pop_index));
|
||||
}
|
||||
|
||||
/* Get a key from the buffer of characters to be read.
|
||||
Return the key in KEY.
|
||||
Result is KEY if there was a key, or 0 if there wasn't. */
|
||||
static int
|
||||
rl_get_char (key)
|
||||
int *key;
|
||||
{
|
||||
if (push_index == pop_index)
|
||||
return (0);
|
||||
|
||||
*key = ibuffer[pop_index++];
|
||||
#if 0
|
||||
if (pop_index >= ibuffer_len)
|
||||
#else
|
||||
if (pop_index > ibuffer_len)
|
||||
#endif
|
||||
pop_index = 0;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Stuff KEY into the *front* of the input buffer.
|
||||
Returns non-zero if successful, zero if there is
|
||||
no space left in the buffer. */
|
||||
int
|
||||
_rl_unget_char (key)
|
||||
int key;
|
||||
{
|
||||
if (ibuffer_space ())
|
||||
{
|
||||
pop_index--;
|
||||
if (pop_index < 0)
|
||||
pop_index = ibuffer_len;
|
||||
ibuffer[pop_index] = key;
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
_rl_pushed_input_available ()
|
||||
{
|
||||
return (push_index != pop_index);
|
||||
}
|
||||
|
||||
/* If a character is available to be read, then read it and stuff it into
|
||||
IBUFFER. Otherwise, just return. Returns number of characters read
|
||||
(0 if none available) and -1 on error (EIO). */
|
||||
static int
|
||||
rl_gather_tyi ()
|
||||
{
|
||||
int tty;
|
||||
register int tem, result;
|
||||
int chars_avail, k;
|
||||
char input;
|
||||
#if defined(HAVE_SELECT)
|
||||
fd_set readfds, exceptfds;
|
||||
struct timeval timeout;
|
||||
#endif
|
||||
|
||||
chars_avail = 0;
|
||||
tty = fileno (rl_instream);
|
||||
|
||||
#if defined (HAVE_SELECT)
|
||||
FD_ZERO (&readfds);
|
||||
FD_ZERO (&exceptfds);
|
||||
FD_SET (tty, &readfds);
|
||||
FD_SET (tty, &exceptfds);
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = _keyboard_input_timeout;
|
||||
result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
|
||||
if (result <= 0)
|
||||
return 0; /* Nothing to read. */
|
||||
#endif
|
||||
|
||||
result = -1;
|
||||
#if defined (FIONREAD)
|
||||
errno = 0;
|
||||
result = ioctl (tty, FIONREAD, &chars_avail);
|
||||
if (result == -1 && errno == EIO)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
#if defined (O_NDELAY)
|
||||
if (result == -1)
|
||||
{
|
||||
tem = fcntl (tty, F_GETFL, 0);
|
||||
|
||||
fcntl (tty, F_SETFL, (tem | O_NDELAY));
|
||||
chars_avail = read (tty, &input, 1);
|
||||
|
||||
fcntl (tty, F_SETFL, tem);
|
||||
if (chars_avail == -1 && errno == EAGAIN)
|
||||
return 0;
|
||||
if (chars_avail == 0) /* EOF */
|
||||
{
|
||||
rl_stuff_char (EOF);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
#endif /* O_NDELAY */
|
||||
|
||||
#if defined (__MINGW32__)
|
||||
/* Use getch/_kbhit to check for available console input, in the same way
|
||||
that we read it normally. */
|
||||
chars_avail = isatty (tty) ? _kbhit () : 0;
|
||||
result = 0;
|
||||
#endif
|
||||
|
||||
/* If there's nothing available, don't waste time trying to read
|
||||
something. */
|
||||
if (chars_avail <= 0)
|
||||
return 0;
|
||||
|
||||
tem = ibuffer_space ();
|
||||
|
||||
if (chars_avail > tem)
|
||||
chars_avail = tem;
|
||||
|
||||
/* One cannot read all of the available input. I can only read a single
|
||||
character at a time, or else programs which require input can be
|
||||
thwarted. If the buffer is larger than one character, I lose.
|
||||
Damn! */
|
||||
if (tem < ibuffer_len)
|
||||
chars_avail = 0;
|
||||
|
||||
if (result != -1)
|
||||
{
|
||||
while (chars_avail--)
|
||||
{
|
||||
RL_CHECK_SIGNALS ();
|
||||
k = (*rl_getc_function) (rl_instream);
|
||||
if (rl_stuff_char (k) == 0)
|
||||
break; /* some problem; no more room */
|
||||
if (k == NEWLINE || k == RETURN)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (chars_avail)
|
||||
rl_stuff_char (input);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
rl_set_keyboard_input_timeout (u)
|
||||
int u;
|
||||
{
|
||||
int o;
|
||||
|
||||
o = _keyboard_input_timeout;
|
||||
if (u >= 0)
|
||||
_keyboard_input_timeout = u;
|
||||
return (o);
|
||||
}
|
||||
|
||||
/* Is there input available to be read on the readline input file
|
||||
descriptor? Only works if the system has select(2) or FIONREAD.
|
||||
Uses the value of _keyboard_input_timeout as the timeout; if another
|
||||
readline function wants to specify a timeout and not leave it up to
|
||||
the user, it should use _rl_input_queued(timeout_value_in_microseconds)
|
||||
instead. */
|
||||
int
|
||||
_rl_input_available ()
|
||||
{
|
||||
#if defined(HAVE_SELECT)
|
||||
fd_set readfds, exceptfds;
|
||||
struct timeval timeout;
|
||||
#endif
|
||||
#if !defined (HAVE_SELECT) && defined(FIONREAD)
|
||||
int chars_avail;
|
||||
#endif
|
||||
int tty;
|
||||
|
||||
tty = fileno (rl_instream);
|
||||
|
||||
#if defined (HAVE_SELECT)
|
||||
FD_ZERO (&readfds);
|
||||
FD_ZERO (&exceptfds);
|
||||
FD_SET (tty, &readfds);
|
||||
FD_SET (tty, &exceptfds);
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = _keyboard_input_timeout;
|
||||
return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0);
|
||||
#else
|
||||
|
||||
#if defined (FIONREAD)
|
||||
if (ioctl (tty, FIONREAD, &chars_avail) == 0)
|
||||
return (chars_avail);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (__MINGW32__)
|
||||
if (isatty (tty))
|
||||
return (_kbhit ());
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_rl_input_queued (t)
|
||||
int t;
|
||||
{
|
||||
int old_timeout, r;
|
||||
|
||||
old_timeout = rl_set_keyboard_input_timeout (t);
|
||||
r = _rl_input_available ();
|
||||
rl_set_keyboard_input_timeout (old_timeout);
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
_rl_insert_typein (c)
|
||||
int c;
|
||||
{
|
||||
int key, t, i;
|
||||
char *string;
|
||||
|
||||
i = key = 0;
|
||||
string = (char *)xmalloc (ibuffer_len + 1);
|
||||
string[i++] = (char) c;
|
||||
|
||||
while ((t = rl_get_char (&key)) &&
|
||||
_rl_keymap[key].type == ISFUNC &&
|
||||
_rl_keymap[key].function == rl_insert)
|
||||
string[i++] = key;
|
||||
|
||||
if (t)
|
||||
_rl_unget_char (key);
|
||||
|
||||
string[i] = '\0';
|
||||
rl_insert_text (string);
|
||||
xfree (string);
|
||||
}
|
||||
|
||||
/* Add KEY to the buffer of characters to be read. Returns 1 if the
|
||||
character was stuffed correctly; 0 otherwise. */
|
||||
int
|
||||
rl_stuff_char (key)
|
||||
int key;
|
||||
{
|
||||
if (ibuffer_space () == 0)
|
||||
return 0;
|
||||
|
||||
if (key == EOF)
|
||||
{
|
||||
key = NEWLINE;
|
||||
rl_pending_input = EOF;
|
||||
RL_SETSTATE (RL_STATE_INPUTPENDING);
|
||||
}
|
||||
ibuffer[push_index++] = key;
|
||||
#if 0
|
||||
if (push_index >= ibuffer_len)
|
||||
#else
|
||||
if (push_index > ibuffer_len)
|
||||
#endif
|
||||
push_index = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Make C be the next command to be executed. */
|
||||
int
|
||||
rl_execute_next (c)
|
||||
int c;
|
||||
{
|
||||
rl_pending_input = c;
|
||||
RL_SETSTATE (RL_STATE_INPUTPENDING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Clear any pending input pushed with rl_execute_next() */
|
||||
int
|
||||
rl_clear_pending_input ()
|
||||
{
|
||||
rl_pending_input = 0;
|
||||
RL_UNSETSTATE (RL_STATE_INPUTPENDING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Character Input */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Read a key, including pending input. */
|
||||
int
|
||||
rl_read_key ()
|
||||
{
|
||||
int c;
|
||||
|
||||
rl_key_sequence_length++;
|
||||
|
||||
if (rl_pending_input)
|
||||
{
|
||||
c = rl_pending_input;
|
||||
rl_clear_pending_input ();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If input is coming from a macro, then use that. */
|
||||
if (c = _rl_next_macro_key ())
|
||||
return (c);
|
||||
|
||||
/* If the user has an event function, then call it periodically. */
|
||||
if (rl_event_hook)
|
||||
{
|
||||
while (rl_event_hook && rl_get_char (&c) == 0)
|
||||
{
|
||||
(*rl_event_hook) ();
|
||||
RL_CHECK_SIGNALS ();
|
||||
if (rl_done) /* XXX - experimental */
|
||||
return ('\n');
|
||||
if (rl_gather_tyi () < 0) /* XXX - EIO */
|
||||
{
|
||||
rl_done = 1;
|
||||
return ('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rl_get_char (&c) == 0)
|
||||
c = (*rl_getc_function) (rl_instream);
|
||||
RL_CHECK_SIGNALS ();
|
||||
}
|
||||
}
|
||||
|
||||
return (c);
|
||||
}
|
||||
|
||||
int
|
||||
rl_getc (stream)
|
||||
FILE *stream;
|
||||
{
|
||||
int result;
|
||||
unsigned char c;
|
||||
|
||||
while (1)
|
||||
{
|
||||
RL_CHECK_SIGNALS ();
|
||||
|
||||
#if defined (__MINGW32__)
|
||||
if (isatty (fileno (stream)))
|
||||
return (getch ());
|
||||
#endif
|
||||
result = read (fileno (stream), &c, sizeof (unsigned char));
|
||||
|
||||
if (result == sizeof (unsigned char))
|
||||
return (c);
|
||||
|
||||
/* If zero characters are returned, then the file that we are
|
||||
reading from is empty! Return EOF in that case. */
|
||||
if (result == 0)
|
||||
return (EOF);
|
||||
|
||||
#if defined (__BEOS__)
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
#if defined (EWOULDBLOCK)
|
||||
# define X_EWOULDBLOCK EWOULDBLOCK
|
||||
#else
|
||||
# define X_EWOULDBLOCK -99
|
||||
#endif
|
||||
|
||||
#if defined (EAGAIN)
|
||||
# define X_EAGAIN EAGAIN
|
||||
#else
|
||||
# define X_EAGAIN -99
|
||||
#endif
|
||||
|
||||
if (errno == X_EWOULDBLOCK || errno == X_EAGAIN)
|
||||
{
|
||||
if (sh_unset_nodelay_mode (fileno (stream)) < 0)
|
||||
return (EOF);
|
||||
continue;
|
||||
}
|
||||
|
||||
#undef X_EWOULDBLOCK
|
||||
#undef X_EAGAIN
|
||||
|
||||
/* If the error that we received was SIGINT, then try again,
|
||||
this is simply an interrupted system call to read ().
|
||||
Otherwise, some error ocurred, also signifying EOF. */
|
||||
if (errno != EINTR)
|
||||
return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
/* read multibyte char */
|
||||
int
|
||||
_rl_read_mbchar (mbchar, size)
|
||||
char *mbchar;
|
||||
int size;
|
||||
{
|
||||
int mb_len, c;
|
||||
size_t mbchar_bytes_length;
|
||||
wchar_t wc;
|
||||
mbstate_t ps, ps_back;
|
||||
|
||||
memset(&ps, 0, sizeof (mbstate_t));
|
||||
memset(&ps_back, 0, sizeof (mbstate_t));
|
||||
|
||||
mb_len = 0;
|
||||
while (mb_len < size)
|
||||
{
|
||||
RL_SETSTATE(RL_STATE_MOREINPUT);
|
||||
c = rl_read_key ();
|
||||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
|
||||
if (c < 0)
|
||||
break;
|
||||
|
||||
mbchar[mb_len++] = c;
|
||||
|
||||
mbchar_bytes_length = mbrtowc (&wc, mbchar, mb_len, &ps);
|
||||
if (mbchar_bytes_length == (size_t)(-1))
|
||||
break; /* invalid byte sequence for the current locale */
|
||||
else if (mbchar_bytes_length == (size_t)(-2))
|
||||
{
|
||||
/* shorted bytes */
|
||||
ps = ps_back;
|
||||
continue;
|
||||
}
|
||||
else if (mbchar_bytes_length == 0)
|
||||
{
|
||||
mbchar[0] = '\0'; /* null wide character */
|
||||
mb_len = 1;
|
||||
break;
|
||||
}
|
||||
else if (mbchar_bytes_length > (size_t)(0))
|
||||
break;
|
||||
}
|
||||
|
||||
return mb_len;
|
||||
}
|
||||
|
||||
/* Read a multibyte-character string whose first character is FIRST into
|
||||
the buffer MB of length MLEN. Returns the last character read, which
|
||||
may be FIRST. Used by the search functions, among others. Very similar
|
||||
to _rl_read_mbchar. */
|
||||
int
|
||||
_rl_read_mbstring (first, mb, mlen)
|
||||
int first;
|
||||
char *mb;
|
||||
int mlen;
|
||||
{
|
||||
int i, c;
|
||||
mbstate_t ps;
|
||||
|
||||
c = first;
|
||||
memset (mb, 0, mlen);
|
||||
for (i = 0; c >= 0 && i < mlen; i++)
|
||||
{
|
||||
mb[i] = (char)c;
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
if (_rl_get_char_len (mb, &ps) == -2)
|
||||
{
|
||||
/* Read more for multibyte character */
|
||||
RL_SETSTATE (RL_STATE_MOREINPUT);
|
||||
c = rl_read_key ();
|
||||
RL_UNSETSTATE (RL_STATE_MOREINPUT);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
+2
-12
@@ -38,16 +38,7 @@
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined (FD_SET) && !defined (HAVE_SELECT)
|
||||
# define HAVE_SELECT
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_SELECT)
|
||||
# include <sys/time.h>
|
||||
#endif /* HAVE_SELECT */
|
||||
#if defined (HAVE_SYS_SELECT_H)
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
#include "posixselect.h"
|
||||
|
||||
#if defined (HAVE_STRING_H)
|
||||
# include <string.h>
|
||||
@@ -130,8 +121,7 @@ rl_insert_close (count, invoking_key)
|
||||
|
||||
FD_ZERO (&readfds);
|
||||
FD_SET (fileno (rl_instream), &readfds);
|
||||
timer.tv_sec = 0;
|
||||
timer.tv_usec = _paren_blink_usec;
|
||||
USEC_TO_TIMEVAL (_paren_blink_usec, timer);
|
||||
|
||||
orig_point = rl_point;
|
||||
rl_point = match_point;
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/* parens.c -- implementation of matching parentheses feature. */
|
||||
|
||||
/* Copyright (C) 1987, 1989, 1992-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
|
||||
Readline is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Readline is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Readline. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define READLINE_LIBRARY
|
||||
|
||||
#if defined (__TANDEM)
|
||||
# include <floss.h>
|
||||
#endif
|
||||
|
||||
#include "rlconf.h"
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "posixselect.h"
|
||||
|
||||
#if defined (HAVE_STRING_H)
|
||||
# include <string.h>
|
||||
#else /* !HAVE_STRING_H */
|
||||
# include <strings.h>
|
||||
#endif /* !HAVE_STRING_H */
|
||||
|
||||
#if !defined (strchr) && !defined (__STDC__)
|
||||
extern char *strchr (), *strrchr ();
|
||||
#endif /* !strchr && !__STDC__ */
|
||||
|
||||
#include "readline.h"
|
||||
#include "rlprivate.h"
|
||||
|
||||
static int find_matching_open PARAMS((char *, int, int));
|
||||
|
||||
/* Non-zero means try to blink the matching open parenthesis when the
|
||||
close parenthesis is inserted. */
|
||||
#if defined (HAVE_SELECT)
|
||||
int rl_blink_matching_paren = 1;
|
||||
#else /* !HAVE_SELECT */
|
||||
int rl_blink_matching_paren = 0;
|
||||
#endif /* !HAVE_SELECT */
|
||||
|
||||
static int _paren_blink_usec = 500000;
|
||||
|
||||
/* Change emacs_standard_keymap to have bindings for paren matching when
|
||||
ON_OR_OFF is 1, change them back to self_insert when ON_OR_OFF == 0. */
|
||||
void
|
||||
_rl_enable_paren_matching (on_or_off)
|
||||
int on_or_off;
|
||||
{
|
||||
if (on_or_off)
|
||||
{ /* ([{ */
|
||||
rl_bind_key_in_map (')', rl_insert_close, emacs_standard_keymap);
|
||||
rl_bind_key_in_map (']', rl_insert_close, emacs_standard_keymap);
|
||||
rl_bind_key_in_map ('}', rl_insert_close, emacs_standard_keymap);
|
||||
}
|
||||
else
|
||||
{ /* ([{ */
|
||||
rl_bind_key_in_map (')', rl_insert, emacs_standard_keymap);
|
||||
rl_bind_key_in_map (']', rl_insert, emacs_standard_keymap);
|
||||
rl_bind_key_in_map ('}', rl_insert, emacs_standard_keymap);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
rl_set_paren_blink_timeout (u)
|
||||
int u;
|
||||
{
|
||||
int o;
|
||||
|
||||
o = _paren_blink_usec;
|
||||
if (u > 0)
|
||||
_paren_blink_usec = u;
|
||||
return (o);
|
||||
}
|
||||
|
||||
int
|
||||
rl_insert_close (count, invoking_key)
|
||||
int count, invoking_key;
|
||||
{
|
||||
if (rl_explicit_arg || !rl_blink_matching_paren)
|
||||
_rl_insert_char (count, invoking_key);
|
||||
else
|
||||
{
|
||||
#if defined (HAVE_SELECT)
|
||||
int orig_point, match_point, ready;
|
||||
struct timeval timer;
|
||||
fd_set readfds;
|
||||
|
||||
_rl_insert_char (1, invoking_key);
|
||||
(*rl_redisplay_function) ();
|
||||
match_point =
|
||||
find_matching_open (rl_line_buffer, rl_point - 2, invoking_key);
|
||||
|
||||
/* Emacs might message or ring the bell here, but I don't. */
|
||||
if (match_point < 0)
|
||||
return -1;
|
||||
|
||||
FD_ZERO (&readfds);
|
||||
FD_SET (fileno (rl_instream), &readfds);
|
||||
timer.tv_sec = 0;
|
||||
timer.tv_usec = _paren_blink_usec;
|
||||
|
||||
orig_point = rl_point;
|
||||
rl_point = match_point;
|
||||
(*rl_redisplay_function) ();
|
||||
ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer);
|
||||
rl_point = orig_point;
|
||||
#else /* !HAVE_SELECT */
|
||||
_rl_insert_char (count, invoking_key);
|
||||
#endif /* !HAVE_SELECT */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
find_matching_open (string, from, closer)
|
||||
char *string;
|
||||
int from, closer;
|
||||
{
|
||||
register int i;
|
||||
int opener, level, delimiter;
|
||||
|
||||
switch (closer)
|
||||
{
|
||||
case ']': opener = '['; break;
|
||||
case '}': opener = '{'; break;
|
||||
case ')': opener = '('; break;
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
level = 1; /* The closer passed in counts as 1. */
|
||||
delimiter = 0; /* Delimited state unknown. */
|
||||
|
||||
for (i = from; i > -1; i--)
|
||||
{
|
||||
if (delimiter && (string[i] == delimiter))
|
||||
delimiter = 0;
|
||||
else if (rl_basic_quote_characters && strchr (rl_basic_quote_characters, string[i]))
|
||||
delimiter = string[i];
|
||||
else if (!delimiter && (string[i] == closer))
|
||||
level++;
|
||||
else if (!delimiter && (string[i] == opener))
|
||||
level--;
|
||||
|
||||
if (!level)
|
||||
break;
|
||||
}
|
||||
return (i);
|
||||
}
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../include/posixselect.h
|
||||
+46
-21
@@ -31,7 +31,7 @@
|
||||
#endif
|
||||
extern int fpurge __P((FILE *stream));
|
||||
|
||||
#if HAVE___FPURGE /* glibc >= 2.2, Solaris >= 7 */
|
||||
#if HAVE___FPURGE /* glibc >= 2.2, Haiku, Solaris >= 7 */
|
||||
# include <stdio_ext.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
@@ -39,13 +39,13 @@ extern int fpurge __P((FILE *stream));
|
||||
int
|
||||
fpurge (FILE *fp)
|
||||
{
|
||||
#if HAVE___FPURGE /* glibc >= 2.2, Solaris >= 7 */
|
||||
#if HAVE___FPURGE /* glibc >= 2.2, Haiku, Solaris >= 7 */
|
||||
|
||||
__fpurge (fp);
|
||||
/* The __fpurge function does not have a return value. */
|
||||
return 0;
|
||||
|
||||
#elif HAVE_FPURGE /* FreeBSD, NetBSD, OpenBSD, MacOS X */
|
||||
#elif HAVE_FPURGE /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X */
|
||||
|
||||
/* Call the system's fpurge function. */
|
||||
# undef fpurge
|
||||
@@ -53,7 +53,7 @@ fpurge (FILE *fp)
|
||||
extern int fpurge (FILE *);
|
||||
# endif
|
||||
int result = fpurge (fp);
|
||||
# if defined __sferror /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */
|
||||
# if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
|
||||
if (result == 0)
|
||||
/* Correct the invariants that fpurge broke.
|
||||
<stdio.h> on BSD systems says:
|
||||
@@ -71,7 +71,7 @@ fpurge (FILE *fp)
|
||||
/* Most systems provide FILE as a struct and the necessary bitmask in
|
||||
<stdio.h>, because they need it for implementing getc() and putc() as
|
||||
fast macros. */
|
||||
# if defined _IO_ferror_unlocked /* GNU libc, BeOS */
|
||||
# if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
|
||||
fp->_IO_read_end = fp->_IO_read_ptr;
|
||||
fp->_IO_write_ptr = fp->_IO_write_base;
|
||||
/* Avoid memory leak when there is an active ungetc buffer. */
|
||||
@@ -81,28 +81,27 @@ fpurge (FILE *fp)
|
||||
fp->_IO_save_base = NULL;
|
||||
}
|
||||
return 0;
|
||||
# elif defined __sferror /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */
|
||||
fp->_p = fp->_bf._base;
|
||||
fp->_r = 0;
|
||||
fp->_w = ((fp->_flags & (__SLBF | __SNBF | __SRD)) == 0 /* fully buffered and not currently reading? */
|
||||
? fp->_bf._size
|
||||
: 0);
|
||||
# elif defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
|
||||
fp_->_p = fp_->_bf._base;
|
||||
fp_->_r = 0;
|
||||
fp_->_w = ((fp_->_flags & (__SLBF | __SNBF | __SRD)) == 0 /* fully buffered and not currently reading? */
|
||||
? fp_->_bf._size
|
||||
: 0);
|
||||
/* Avoid memory leak when there is an active ungetc buffer. */
|
||||
# if defined __NetBSD__ || defined __OpenBSD__ /* NetBSD, OpenBSD */
|
||||
/* See <http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
|
||||
and <http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup> */
|
||||
# define fp_ub ((struct { struct __sbuf _ub; } *) fp->_ext._base)->_ub
|
||||
# else /* FreeBSD, MacOS X, Cygwin */
|
||||
# define fp_ub fp->_ub
|
||||
# endif
|
||||
if (fp_ub._base != NULL)
|
||||
{
|
||||
if (fp_ub._base != fp->_ubuf)
|
||||
if (fp_ub._base != fp_->_ubuf)
|
||||
free (fp_ub._base);
|
||||
fp_ub._base = NULL;
|
||||
}
|
||||
return 0;
|
||||
# elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, mingw */
|
||||
# elif defined __EMX__ /* emx+gcc */
|
||||
fp->_ptr = fp->_buffer;
|
||||
fp->_rcount = 0;
|
||||
fp->_wcount = 0;
|
||||
fp->_ungetc_count = 0;
|
||||
return 0;
|
||||
# elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw */
|
||||
fp->_ptr = fp->_base;
|
||||
if (fp->_ptr != NULL)
|
||||
fp->_cnt = 0;
|
||||
@@ -115,8 +114,34 @@ fpurge (FILE *fp)
|
||||
fp->__bufpos = fp->__bufread;
|
||||
# endif
|
||||
return 0;
|
||||
# elif defined __QNX__ /* QNX */
|
||||
fp->_Rback = fp->_Back + sizeof (fp->_Back);
|
||||
fp->_Rsave = NULL;
|
||||
if (fp->_Mode & 0x2000 /* _MWRITE */)
|
||||
/* fp->_Buf <= fp->_Next <= fp->_Wend */
|
||||
fp->_Next = fp->_Buf;
|
||||
else
|
||||
/* fp->_Buf <= fp->_Next <= fp->_Rend */
|
||||
fp->_Rend = fp->_Next;
|
||||
return 0;
|
||||
# elif defined __MINT__ /* Atari FreeMiNT */
|
||||
if (fp->__pushed_back)
|
||||
{
|
||||
fp->__bufp = fp->__pushback_bufp;
|
||||
fp->__pushed_back = 0;
|
||||
}
|
||||
/* Preserve the current file position. */
|
||||
if (fp->__target != -1)
|
||||
fp->__target += fp->__bufp - fp->__buffer;
|
||||
fp->__bufp = fp->__buffer;
|
||||
/* Nothing in the buffer, next getc is nontrivial. */
|
||||
fp->__get_limit = fp->__bufp;
|
||||
/* Nothing in the buffer, next putc is nontrivial. */
|
||||
fp->__put_limit = fp->__buffer;
|
||||
return 0;
|
||||
# else
|
||||
#error "Please port gnulib fpurge.c to your platform! Look at the definitions of fflush, setvbuf and ungetc on your system, then report this to bug-gnulib."
|
||||
# warning "Please port gnulib fpurge.c to your platform! Look at the definitions of fflush, setvbuf and ungetc on your system, then report this to bug-gnulib."
|
||||
return 0;
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/* fpurge - Flushing buffers of a FILE stream. */
|
||||
|
||||
/* Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Specification. Same as in ../../externs.h. */
|
||||
#define NEED_FPURGE_DECL
|
||||
#if HAVE_FPURGE
|
||||
# define fpurge _bash_fpurge
|
||||
#endif
|
||||
extern int fpurge __P((FILE *stream));
|
||||
|
||||
#if HAVE___FPURGE /* glibc >= 2.2, Solaris >= 7 */
|
||||
# include <stdio_ext.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
fpurge (FILE *fp)
|
||||
{
|
||||
#if HAVE___FPURGE /* glibc >= 2.2, Solaris >= 7 */
|
||||
|
||||
__fpurge (fp);
|
||||
/* The __fpurge function does not have a return value. */
|
||||
return 0;
|
||||
|
||||
#elif HAVE_FPURGE /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X */
|
||||
|
||||
/* Call the system's fpurge function. */
|
||||
# undef fpurge
|
||||
# if !HAVE_DECL_FPURGE
|
||||
extern int fpurge (FILE *);
|
||||
# endif
|
||||
int result = fpurge (fp);
|
||||
# if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
|
||||
if (result == 0)
|
||||
/* Correct the invariants that fpurge broke.
|
||||
<stdio.h> on BSD systems says:
|
||||
"The following always hold: if _flags & __SRD, _w is 0."
|
||||
If this invariant is not fulfilled and the stream is read-write but
|
||||
currently writing, subsequent putc or fputc calls will write directly
|
||||
into the buffer, although they shouldn't be allowed to. */
|
||||
if ((fp->_flags & __SRD) != 0)
|
||||
fp->_w = 0;
|
||||
# endif
|
||||
return result;
|
||||
|
||||
#else
|
||||
|
||||
/* Most systems provide FILE as a struct and the necessary bitmask in
|
||||
<stdio.h>, because they need it for implementing getc() and putc() as
|
||||
fast macros. */
|
||||
# if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Linux libc5 */
|
||||
fp->_IO_read_end = fp->_IO_read_ptr;
|
||||
fp->_IO_write_ptr = fp->_IO_write_base;
|
||||
/* Avoid memory leak when there is an active ungetc buffer. */
|
||||
if (fp->_IO_save_base != NULL)
|
||||
{
|
||||
free (fp->_IO_save_base);
|
||||
fp->_IO_save_base = NULL;
|
||||
}
|
||||
return 0;
|
||||
# elif defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
|
||||
fp->_p = fp->_bf._base;
|
||||
fp->_r = 0;
|
||||
fp->_w = ((fp->_flags & (__SLBF | __SNBF | __SRD)) == 0 /* fully buffered and not currently reading? */
|
||||
? fp->_bf._size
|
||||
: 0);
|
||||
/* Avoid memory leak when there is an active ungetc buffer. */
|
||||
# if defined __NetBSD__ || defined __OpenBSD__ /* NetBSD, OpenBSD */
|
||||
/* See <http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
|
||||
and <http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup> */
|
||||
# define fp_ub ((struct { struct __sbuf _ub; } *) fp->_ext._base)->_ub
|
||||
# else /* FreeBSD, MacOS X, Cygwin */
|
||||
# define fp_ub fp->_ub
|
||||
# endif
|
||||
if (fp_ub._base != NULL)
|
||||
{
|
||||
if (fp_ub._base != fp->_ubuf)
|
||||
free (fp_ub._base);
|
||||
fp_ub._base = NULL;
|
||||
}
|
||||
return 0;
|
||||
# elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, mingw */
|
||||
fp->_ptr = fp->_base;
|
||||
if (fp->_ptr != NULL)
|
||||
fp->_cnt = 0;
|
||||
return 0;
|
||||
# elif defined __UCLIBC__ /* uClibc */
|
||||
# ifdef __STDIO_BUFFERS
|
||||
if (fp->__modeflags & __FLAG_WRITING)
|
||||
fp->__bufpos = fp->__bufstart;
|
||||
else if (fp->__modeflags & (__FLAG_READONLY | __FLAG_READING))
|
||||
fp->__bufpos = fp->__bufread;
|
||||
# endif
|
||||
return 0;
|
||||
# else
|
||||
#error "Please port gnulib fpurge.c to your platform! Look at the definitions of fflush, setvbuf and ungetc on your system, then report this to bug-gnulib."
|
||||
# endif
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/* fpurge - Flushing buffers of a FILE stream. */
|
||||
|
||||
/* Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Specification. Same as in ../../externs.h. */
|
||||
#define NEED_FPURGE_DECL
|
||||
#if HAVE_FPURGE
|
||||
# define fpurge _bash_fpurge
|
||||
#endif
|
||||
extern int fpurge __P((FILE *stream));
|
||||
|
||||
#if HAVE___FPURGE /* glibc >= 2.2, Haiku, Solaris >= 7 */
|
||||
# include <stdio_ext.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
fpurge (FILE *fp)
|
||||
{
|
||||
#if HAVE___FPURGE /* glibc >= 2.2, Haiku, Solaris >= 7 */
|
||||
|
||||
__fpurge (fp);
|
||||
/* The __fpurge function does not have a return value. */
|
||||
return 0;
|
||||
|
||||
#elif HAVE_FPURGE /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X */
|
||||
|
||||
/* Call the system's fpurge function. */
|
||||
# undef fpurge
|
||||
# if !HAVE_DECL_FPURGE
|
||||
extern int fpurge (FILE *);
|
||||
# endif
|
||||
int result = fpurge (fp);
|
||||
# if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
|
||||
if (result == 0)
|
||||
/* Correct the invariants that fpurge broke.
|
||||
<stdio.h> on BSD systems says:
|
||||
"The following always hold: if _flags & __SRD, _w is 0."
|
||||
If this invariant is not fulfilled and the stream is read-write but
|
||||
currently writing, subsequent putc or fputc calls will write directly
|
||||
into the buffer, although they shouldn't be allowed to. */
|
||||
if ((fp->_flags & __SRD) != 0)
|
||||
fp->_w = 0;
|
||||
# endif
|
||||
return result;
|
||||
|
||||
#else
|
||||
|
||||
/* Most systems provide FILE as a struct and the necessary bitmask in
|
||||
<stdio.h>, because they need it for implementing getc() and putc() as
|
||||
fast macros. */
|
||||
# if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
|
||||
fp->_IO_read_end = fp->_IO_read_ptr;
|
||||
fp->_IO_write_ptr = fp->_IO_write_base;
|
||||
/* Avoid memory leak when there is an active ungetc buffer. */
|
||||
if (fp->_IO_save_base != NULL)
|
||||
{
|
||||
free (fp->_IO_save_base);
|
||||
fp->_IO_save_base = NULL;
|
||||
}
|
||||
return 0;
|
||||
# elif defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
|
||||
fp_->_p = fp_->_bf._base;
|
||||
fp_->_r = 0;
|
||||
fp_->_w = ((fp_->_flags & (__SLBF | __SNBF | __SRD)) == 0 /* fully buffered and not currently reading? */
|
||||
? fp_->_bf._size
|
||||
: 0);
|
||||
/* Avoid memory leak when there is an active ungetc buffer. */
|
||||
if (fp_ub._base != NULL)
|
||||
{
|
||||
if (fp_ub._base != fp_->_ubuf)
|
||||
free (fp_ub._base);
|
||||
fp_ub._base = NULL;
|
||||
}
|
||||
return 0;
|
||||
# elif defined __EMX__ /* emx+gcc */
|
||||
fp->_ptr = fp->_buffer;
|
||||
fp->_rcount = 0;
|
||||
fp->_wcount = 0;
|
||||
fp->_ungetc_count = 0;
|
||||
return 0;
|
||||
# elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw */
|
||||
fp->_ptr = fp->_base;
|
||||
if (fp->_ptr != NULL)
|
||||
fp->_cnt = 0;
|
||||
return 0;
|
||||
# elif defined __UCLIBC__ /* uClibc */
|
||||
# ifdef __STDIO_BUFFERS
|
||||
if (fp->__modeflags & __FLAG_WRITING)
|
||||
fp->__bufpos = fp->__bufstart;
|
||||
else if (fp->__modeflags & (__FLAG_READONLY | __FLAG_READING))
|
||||
fp->__bufpos = fp->__bufread;
|
||||
# endif
|
||||
return 0;
|
||||
# elif defined __QNX__ /* QNX */
|
||||
fp->_Rback = fp->_Back + sizeof (fp->_Back);
|
||||
fp->_Rsave = NULL;
|
||||
if (fp->_Mode & 0x2000 /* _MWRITE */)
|
||||
/* fp->_Buf <= fp->_Next <= fp->_Wend */
|
||||
fp->_Next = fp->_Buf;
|
||||
else
|
||||
/* fp->_Buf <= fp->_Next <= fp->_Rend */
|
||||
fp->_Rend = fp->_Next;
|
||||
return 0;
|
||||
# elif defined __MINT__ /* Atari FreeMiNT */
|
||||
if (fp->__pushed_back)
|
||||
{
|
||||
fp->__bufp = fp->__pushback_bufp;
|
||||
fp->__pushed_back = 0;
|
||||
}
|
||||
/* Preserve the current file position. */
|
||||
if (fp->__target != -1)
|
||||
fp->__target += fp->__bufp - fp->__buffer;
|
||||
fp->__bufp = fp->__buffer;
|
||||
/* Nothing in the buffer, next getc is nontrivial. */
|
||||
fp->__get_limit = fp->__bufp;
|
||||
/* Nothing in the buffer, next putc is nontrivial. */
|
||||
fp->__put_limit = fp->__buffer;
|
||||
return 0;
|
||||
# else
|
||||
#error "Please port gnulib fpurge.c to your platform! Look at the definitions of fflush, setvbuf and ungetc on your system, then report this to bug-gnulib."
|
||||
# endif
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -39,14 +39,7 @@
|
||||
|
||||
#include "bashansi.h"
|
||||
|
||||
#if defined (HAVE_SELECT)
|
||||
# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX)
|
||||
# include <sys/time.h>
|
||||
# endif
|
||||
#endif /* HAVE_SELECT */
|
||||
#if defined (HAVE_SYS_SELECT_H)
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
#include "posixselect.h"
|
||||
|
||||
#if defined (FIONREAD_IN_SYS_IOCTL)
|
||||
# include <sys/ioctl.h>
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/* input_avail.c -- check whether or not data is available for reading on a
|
||||
specified file descriptor. */
|
||||
|
||||
/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined (__TANDEM)
|
||||
# include <floss.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#if defined (HAVE_SYS_FILE_H)
|
||||
# include <sys/file.h>
|
||||
#endif /* HAVE_SYS_FILE_H */
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
|
||||
#include "bashansi.h"
|
||||
|
||||
#if defined (HAVE_SELECT)
|
||||
# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX)
|
||||
# include <sys/time.h>
|
||||
# endif
|
||||
#endif /* HAVE_SELECT */
|
||||
#if defined (HAVE_SYS_SELECT_H)
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#if defined (FIONREAD_IN_SYS_IOCTL)
|
||||
# include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
#if !defined (O_NDELAY) && defined (O_NONBLOCK)
|
||||
# define O_NDELAY O_NONBLOCK /* Posix style */
|
||||
#endif
|
||||
|
||||
/* Return >= 1 if select/FIONREAD indicates data available for reading on
|
||||
file descriptor FD; 0 if no data available. Return -1 on error. */
|
||||
int
|
||||
input_avail (fd)
|
||||
int fd;
|
||||
{
|
||||
int result, chars_avail;
|
||||
#if defined(HAVE_SELECT)
|
||||
fd_set readfds, exceptfds;
|
||||
struct timeval timeout;
|
||||
#endif
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
chars_avail = 0;
|
||||
|
||||
#if defined (HAVE_SELECT)
|
||||
FD_ZERO (&readfds);
|
||||
FD_ZERO (&exceptfds);
|
||||
FD_SET (fd, &readfds);
|
||||
FD_SET (fd, &exceptfds);
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
result = select (fd + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
|
||||
return ((result <= 0) ? 0 : 1);
|
||||
|
||||
#endif
|
||||
|
||||
result = -1;
|
||||
#if defined (FIONREAD)
|
||||
errno = 0;
|
||||
result = ioctl (fd, FIONREAD, &chars_avail);
|
||||
if (result == -1 && errno == EIO)
|
||||
return -1;
|
||||
return (chars_avail);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
BUILD_DIR=/usr/local/build/bash/bash-current
|
||||
BUILD_DIR=/usr/local/build/chet/bash/bash-current
|
||||
THIS_SH=$BUILD_DIR/bash
|
||||
PATH=$PATH:$BUILD_DIR
|
||||
|
||||
|
||||
@@ -799,6 +799,7 @@ run_debug_trap ()
|
||||
{
|
||||
int trap_exit_value;
|
||||
pid_t save_pgrp;
|
||||
int save_pipe[2];
|
||||
|
||||
/* XXX - question: should the DEBUG trap inherit the RETURN trap? */
|
||||
trap_exit_value = 0;
|
||||
@@ -806,14 +807,25 @@ run_debug_trap ()
|
||||
{
|
||||
#if defined (JOB_CONTROL)
|
||||
save_pgrp = pipeline_pgrp;
|
||||
pipeline_pgrp = shell_pgrp;
|
||||
pipeline_pgrp = 0;
|
||||
save_pipeline (1);
|
||||
# if defined (PGRP_PIPE)
|
||||
save_pgrp_pipe (save_pipe, 1);
|
||||
# endif
|
||||
stop_making_children ();
|
||||
#endif
|
||||
|
||||
trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
pipeline_pgrp = save_pgrp;
|
||||
restore_pipeline (1);
|
||||
# if defined (PGRP_PIPE)
|
||||
close_pgrp_pipe ();
|
||||
restore_pgrp_pipe (save_pipe);
|
||||
# endif
|
||||
if (pipeline_pgrp > 0)
|
||||
give_terminal_to (pipeline_pgrp, 1);
|
||||
notify_and_cleanup ();
|
||||
#endif
|
||||
|
||||
|
||||
+1042
File diff suppressed because it is too large
Load Diff
@@ -86,6 +86,10 @@ extern procenv_t wait_intr_buf;
|
||||
extern int return_catch_flag, return_catch_value;
|
||||
extern int subshell_level;
|
||||
|
||||
#if defined (PGRP_PIPE)
|
||||
extern int pgrp_pipe[2];
|
||||
#endif
|
||||
|
||||
/* The list of things to do originally, before we started trapping. */
|
||||
SigHandler *original_signals[NSIG];
|
||||
|
||||
@@ -799,6 +803,7 @@ run_debug_trap ()
|
||||
{
|
||||
int trap_exit_value;
|
||||
pid_t save_pgrp;
|
||||
int save_pipe[2];
|
||||
|
||||
/* XXX - question: should the DEBUG trap inherit the RETURN trap? */
|
||||
trap_exit_value = 0;
|
||||
@@ -806,14 +811,26 @@ run_debug_trap ()
|
||||
{
|
||||
#if defined (JOB_CONTROL)
|
||||
save_pgrp = pipeline_pgrp;
|
||||
pipeline_pgrp = shell_pgrp;
|
||||
pipeline_pgrp = 0;
|
||||
save_pipeline (1);
|
||||
# if defined (PGRP_PIPE)
|
||||
save_pgrp_pipe (save_pipe, 1);
|
||||
# endif
|
||||
stop_making_children ();
|
||||
#endif
|
||||
|
||||
trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
pipeline_pgrp = save_pgrp;
|
||||
restore_pipeline (1);
|
||||
# if defined (PGRP_PIPE)
|
||||
close_pgrp_pipe ();
|
||||
restore_pgrp_pipe (save_pipe);
|
||||
# endif
|
||||
if (pipeline_pgrp > 0)
|
||||
give_terminal_to (pipeline_pgrp, 1);
|
||||
notify_and_cleanup ();
|
||||
#endif
|
||||
|
||||
#if defined (DEBUGGER)
|
||||
|
||||
Reference in New Issue
Block a user