Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
MariaDB and MySQL Packaging Team
mariadb-10.0
Commits
28192e02
Commit
28192e02
authored
Mar 01, 2014
by
Otto Kekäläinen
Browse files
Imported Upstream version 10.0.8
parent
aa038a23
Changes
185
Hide whitespace changes
Inline
Side-by-side
Too many changes to show.
To preserve performance only
5 of 185+
files are displayed.
Plain diff
Email patch
cmd-line-utils/libedit/history.c
0 → 100644
View file @
28192e02
/* $NetBSD: history.c,v 1.45 2011/07/29 23:44:44 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include
"config.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
#else
#endif
#endif
/* not lint && not SCCSID */
/*
* hist.c: TYPE(History) access functions
*/
#include
<string.h>
#include
<stdlib.h>
#include
<stdarg.h>
#ifdef HAVE_VIS_H
#include
<vis.h>
#else
#include
"np/vis.h"
#endif
#include
<sys/stat.h>
static
const
char
hist_cookie
[]
=
"_HiStOrY_V2_
\n
"
;
#include
"histedit.h"
#include
"chartype.h"
typedef
int
(
*
history_gfun_t
)(
void
*
,
TYPE
(
HistEvent
)
*
);
typedef
int
(
*
history_efun_t
)(
void
*
,
TYPE
(
HistEvent
)
*
,
const
Char
*
);
typedef
void
(
*
history_vfun_t
)(
void
*
,
TYPE
(
HistEvent
)
*
);
typedef
int
(
*
history_sfun_t
)(
void
*
,
TYPE
(
HistEvent
)
*
,
const
int
);
struct
TYPE
(
history
)
{
void
*
h_ref
;
/* Argument for history fcns */
int
h_ent
;
/* Last entry point for history */
history_gfun_t
h_first
;
/* Get the first element */
history_gfun_t
h_next
;
/* Get the next element */
history_gfun_t
h_last
;
/* Get the last element */
history_gfun_t
h_prev
;
/* Get the previous element */
history_gfun_t
h_curr
;
/* Get the current element */
history_sfun_t
h_set
;
/* Set the current element */
history_sfun_t
h_del
;
/* Set the given element */
history_vfun_t
h_clear
;
/* Clear the history list */
history_efun_t
h_enter
;
/* Add an element */
history_efun_t
h_add
;
/* Append to an element */
};
#define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev)
#define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev)
#define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev)
#define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev)
#define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev)
#define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n)
#define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev)
#define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str)
#define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str)
#define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n)
#define h_strdup(a) Strdup(a)
#define h_malloc(a) malloc(a)
#define h_realloc(a, b) realloc((a), (b))
#define h_free(a) free(a)
typedef
struct
{
int
num
;
Char
*
str
;
}
HistEventPrivate
;
private
int
history_setsize
(
TYPE
(
History
)
*
,
TYPE
(
HistEvent
)
*
,
int
);
private
int
history_getsize
(
TYPE
(
History
)
*
,
TYPE
(
HistEvent
)
*
);
private
int
history_setunique
(
TYPE
(
History
)
*
,
TYPE
(
HistEvent
)
*
,
int
);
private
int
history_getunique
(
TYPE
(
History
)
*
,
TYPE
(
HistEvent
)
*
);
private
int
history_set_fun
(
TYPE
(
History
)
*
,
TYPE
(
History
)
*
);
private
int
history_load
(
TYPE
(
History
)
*
,
const
char
*
);
private
int
history_save
(
TYPE
(
History
)
*
,
const
char
*
);
private
int
history_prev_event
(
TYPE
(
History
)
*
,
TYPE
(
HistEvent
)
*
,
int
);
private
int
history_next_event
(
TYPE
(
History
)
*
,
TYPE
(
HistEvent
)
*
,
int
);
private
int
history_next_string
(
TYPE
(
History
)
*
,
TYPE
(
HistEvent
)
*
,
const
Char
*
);
private
int
history_prev_string
(
TYPE
(
History
)
*
,
TYPE
(
HistEvent
)
*
,
const
Char
*
);
/***********************************************************************/
/*
* Builtin- history implementation
*/
typedef
struct
hentry_t
{
TYPE
(
HistEvent
)
ev
;
/* What we return */
void
*
data
;
/* data */
struct
hentry_t
*
next
;
/* Next entry */
struct
hentry_t
*
prev
;
/* Previous entry */
}
hentry_t
;
typedef
struct
history_t
{
hentry_t
list
;
/* Fake list header element */
hentry_t
*
cursor
;
/* Current element in the list */
int
max
;
/* Maximum number of events */
int
cur
;
/* Current number of events */
int
eventid
;
/* For generation of unique event id */
int
flags
;
/* TYPE(History) flags */
#define H_UNIQUE 1
/* Store only unique elements */
}
history_t
;
private
int
history_def_next
(
void
*
,
TYPE
(
HistEvent
)
*
);
private
int
history_def_first
(
void
*
,
TYPE
(
HistEvent
)
*
);
private
int
history_def_prev
(
void
*
,
TYPE
(
HistEvent
)
*
);
private
int
history_def_last
(
void
*
,
TYPE
(
HistEvent
)
*
);
private
int
history_def_curr
(
void
*
,
TYPE
(
HistEvent
)
*
);
private
int
history_def_set
(
void
*
,
TYPE
(
HistEvent
)
*
,
const
int
);
private
void
history_def_clear
(
void
*
,
TYPE
(
HistEvent
)
*
);
private
int
history_def_enter
(
void
*
,
TYPE
(
HistEvent
)
*
,
const
Char
*
);
private
int
history_def_add
(
void
*
,
TYPE
(
HistEvent
)
*
,
const
Char
*
);
private
int
history_def_del
(
void
*
,
TYPE
(
HistEvent
)
*
,
const
int
);
private
int
history_def_init
(
void
**
,
TYPE
(
HistEvent
)
*
,
int
);
private
int
history_def_insert
(
history_t
*
,
TYPE
(
HistEvent
)
*
,
const
Char
*
);
private
void
history_def_delete
(
history_t
*
,
TYPE
(
HistEvent
)
*
,
hentry_t
*
);
private
int
history_deldata_nth
(
history_t
*
,
TYPE
(
HistEvent
)
*
,
int
,
void
**
);
private
int
history_set_nth
(
void
*
,
TYPE
(
HistEvent
)
*
,
int
);
#define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
#define history_def_getsize(p) (((history_t *)p)->cur)
#define history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0)
#define history_def_setunique(p, uni) \
if (uni) \
(((history_t *)p)->flags) |= H_UNIQUE; \
else \
(((history_t *)p)->flags) &= ~H_UNIQUE
#define he_strerror(code) he_errlist[code]
#define he_seterrev(evp, code) {\
evp->num = code;\
evp->str = he_strerror(code);\
}
/* error messages */
static
const
Char
*
const
he_errlist
[]
=
{
STR
(
"OK"
),
STR
(
"unknown error"
),
STR
(
"malloc() failed"
),
STR
(
"first event not found"
),
STR
(
"last event not found"
),
STR
(
"empty list"
),
STR
(
"no next event"
),
STR
(
"no previous event"
),
STR
(
"current event is invalid"
),
STR
(
"event not found"
),
STR
(
"can't read history from file"
),
STR
(
"can't write history"
),
STR
(
"required parameter(s) not supplied"
),
STR
(
"history size negative"
),
STR
(
"function not allowed with other history-functions-set the default"
),
STR
(
"bad parameters"
)
};
/* error codes */
#define _HE_OK 0
#define _HE_UNKNOWN 1
#define _HE_MALLOC_FAILED 2
#define _HE_FIRST_NOTFOUND 3
#define _HE_LAST_NOTFOUND 4
#define _HE_EMPTY_LIST 5
#define _HE_END_REACHED 6
#define _HE_START_REACHED 7
#define _HE_CURR_INVALID 8
#define _HE_NOT_FOUND 9
#define _HE_HIST_READ 10
#define _HE_HIST_WRITE 11
#define _HE_PARAM_MISSING 12
#define _HE_SIZE_NEGATIVE 13
#define _HE_NOT_ALLOWED 14
#define _HE_BAD_PARAM 15
/* history_def_first():
* Default function to return the first event in the history.
*/
private
int
history_def_first
(
void
*
p
,
TYPE
(
HistEvent
)
*
ev
)
{
history_t
*
h
=
(
history_t
*
)
p
;
h
->
cursor
=
h
->
list
.
next
;
if
(
h
->
cursor
!=
&
h
->
list
)
*
ev
=
h
->
cursor
->
ev
;
else
{
he_seterrev
(
ev
,
_HE_FIRST_NOTFOUND
);
return
-
1
;
}
return
0
;
}
/* history_def_last():
* Default function to return the last event in the history.
*/
private
int
history_def_last
(
void
*
p
,
TYPE
(
HistEvent
)
*
ev
)
{
history_t
*
h
=
(
history_t
*
)
p
;
h
->
cursor
=
h
->
list
.
prev
;
if
(
h
->
cursor
!=
&
h
->
list
)
*
ev
=
h
->
cursor
->
ev
;
else
{
he_seterrev
(
ev
,
_HE_LAST_NOTFOUND
);
return
-
1
;
}
return
0
;
}
/* history_def_next():
* Default function to return the next event in the history.
*/
private
int
history_def_next
(
void
*
p
,
TYPE
(
HistEvent
)
*
ev
)
{
history_t
*
h
=
(
history_t
*
)
p
;
if
(
h
->
cursor
==
&
h
->
list
)
{
he_seterrev
(
ev
,
_HE_EMPTY_LIST
);
return
-
1
;
}
if
(
h
->
cursor
->
next
==
&
h
->
list
)
{
he_seterrev
(
ev
,
_HE_END_REACHED
);
return
-
1
;
}
h
->
cursor
=
h
->
cursor
->
next
;
*
ev
=
h
->
cursor
->
ev
;
return
0
;
}
/* history_def_prev():
* Default function to return the previous event in the history.
*/
private
int
history_def_prev
(
void
*
p
,
TYPE
(
HistEvent
)
*
ev
)
{
history_t
*
h
=
(
history_t
*
)
p
;
if
(
h
->
cursor
==
&
h
->
list
)
{
he_seterrev
(
ev
,
(
h
->
cur
>
0
)
?
_HE_END_REACHED
:
_HE_EMPTY_LIST
);
return
-
1
;
}
if
(
h
->
cursor
->
prev
==
&
h
->
list
)
{
he_seterrev
(
ev
,
_HE_START_REACHED
);
return
-
1
;
}
h
->
cursor
=
h
->
cursor
->
prev
;
*
ev
=
h
->
cursor
->
ev
;
return
0
;
}
/* history_def_curr():
* Default function to return the current event in the history.
*/
private
int
history_def_curr
(
void
*
p
,
TYPE
(
HistEvent
)
*
ev
)
{
history_t
*
h
=
(
history_t
*
)
p
;
if
(
h
->
cursor
!=
&
h
->
list
)
*
ev
=
h
->
cursor
->
ev
;
else
{
he_seterrev
(
ev
,
(
h
->
cur
>
0
)
?
_HE_CURR_INVALID
:
_HE_EMPTY_LIST
);
return
-
1
;
}
return
0
;
}
/* history_def_set():
* Default function to set the current event in the history to the
* given one.
*/
private
int
history_def_set
(
void
*
p
,
TYPE
(
HistEvent
)
*
ev
,
const
int
n
)
{
history_t
*
h
=
(
history_t
*
)
p
;
if
(
h
->
cur
==
0
)
{
he_seterrev
(
ev
,
_HE_EMPTY_LIST
);
return
-
1
;
}
if
(
h
->
cursor
==
&
h
->
list
||
h
->
cursor
->
ev
.
num
!=
n
)
{
for
(
h
->
cursor
=
h
->
list
.
next
;
h
->
cursor
!=
&
h
->
list
;
h
->
cursor
=
h
->
cursor
->
next
)
if
(
h
->
cursor
->
ev
.
num
==
n
)
break
;
}
if
(
h
->
cursor
==
&
h
->
list
)
{
he_seterrev
(
ev
,
_HE_NOT_FOUND
);
return
-
1
;
}
return
0
;
}
/* history_set_nth():
* Default function to set the current event in the history to the
* n-th one.
*/
private
int
history_set_nth
(
void
*
p
,
TYPE
(
HistEvent
)
*
ev
,
int
n
)
{
history_t
*
h
=
(
history_t
*
)
p
;
if
(
h
->
cur
==
0
)
{
he_seterrev
(
ev
,
_HE_EMPTY_LIST
);
return
-
1
;
}
for
(
h
->
cursor
=
h
->
list
.
prev
;
h
->
cursor
!=
&
h
->
list
;
h
->
cursor
=
h
->
cursor
->
prev
)
if
(
n
--
<=
0
)
break
;
if
(
h
->
cursor
==
&
h
->
list
)
{
he_seterrev
(
ev
,
_HE_NOT_FOUND
);
return
-
1
;
}
return
0
;
}
/* history_def_add():
* Append string to element
*/
private
int
history_def_add
(
void
*
p
,
TYPE
(
HistEvent
)
*
ev
,
const
Char
*
str
)
{
history_t
*
h
=
(
history_t
*
)
p
;
size_t
len
;
Char
*
s
;
HistEventPrivate
*
evp
=
(
void
*
)
&
h
->
cursor
->
ev
;
if
(
h
->
cursor
==
&
h
->
list
)
return
history_def_enter
(
p
,
ev
,
str
);
len
=
Strlen
(
evp
->
str
)
+
Strlen
(
str
)
+
1
;
s
=
h_malloc
(
len
*
sizeof
(
*
s
));
if
(
s
==
NULL
)
{
he_seterrev
(
ev
,
_HE_MALLOC_FAILED
);
return
-
1
;
}
(
void
)
Strncpy
(
s
,
h
->
cursor
->
ev
.
str
,
len
);
s
[
len
-
1
]
=
'\0'
;
(
void
)
Strncat
(
s
,
str
,
len
-
Strlen
(
s
)
-
1
);
h_free
(
evp
->
str
);
evp
->
str
=
s
;
*
ev
=
h
->
cursor
->
ev
;
return
0
;
}
private
int
history_deldata_nth
(
history_t
*
h
,
TYPE
(
HistEvent
)
*
ev
,
int
num
,
void
**
data
)
{
if
(
history_set_nth
(
h
,
ev
,
num
)
!=
0
)
return
-
1
;
/* magic value to skip delete (just set to n-th history) */
if
(
data
==
(
void
**
)
-
1
)
return
0
;
ev
->
str
=
Strdup
(
h
->
cursor
->
ev
.
str
);
ev
->
num
=
h
->
cursor
->
ev
.
num
;
if
(
data
)
*
data
=
h
->
cursor
->
data
;
history_def_delete
(
h
,
ev
,
h
->
cursor
);
return
0
;
}
/* history_def_del():
* Delete element hp of the h list
*/
/* ARGSUSED */
private
int
history_def_del
(
void
*
p
,
TYPE
(
HistEvent
)
*
ev
__attribute__
((
__unused__
)),
const
int
num
)
{
history_t
*
h
=
(
history_t
*
)
p
;
if
(
history_def_set
(
h
,
ev
,
num
)
!=
0
)
return
-
1
;
ev
->
str
=
Strdup
(
h
->
cursor
->
ev
.
str
);
ev
->
num
=
h
->
cursor
->
ev
.
num
;
history_def_delete
(
h
,
ev
,
h
->
cursor
);
return
0
;
}
/* history_def_delete():
* Delete element hp of the h list
*/
/* ARGSUSED */
private
void
history_def_delete
(
history_t
*
h
,
TYPE
(
HistEvent
)
*
ev
__attribute__
((
__unused__
)),
hentry_t
*
hp
)
{
HistEventPrivate
*
evp
=
(
void
*
)
&
hp
->
ev
;
if
(
hp
==
&
h
->
list
)
abort
();
if
(
h
->
cursor
==
hp
)
{
h
->
cursor
=
hp
->
prev
;
if
(
h
->
cursor
==
&
h
->
list
)
h
->
cursor
=
hp
->
next
;
}
hp
->
prev
->
next
=
hp
->
next
;
hp
->
next
->
prev
=
hp
->
prev
;
h_free
(
evp
->
str
);
h_free
(
hp
);
h
->
cur
--
;
}
/* history_def_insert():
* Insert element with string str in the h list
*/
private
int
history_def_insert
(
history_t
*
h
,
TYPE
(
HistEvent
)
*
ev
,
const
Char
*
str
)
{
hentry_t
*
c
;
c
=
h_malloc
(
sizeof
(
*
c
));
if
(
c
==
NULL
)
goto
oomem
;
if
((
c
->
ev
.
str
=
h_strdup
(
str
))
==
NULL
)
{
h_free
(
c
);
goto
oomem
;
}
c
->
data
=
NULL
;
c
->
ev
.
num
=
++
h
->
eventid
;
c
->
next
=
h
->
list
.
next
;
c
->
prev
=
&
h
->
list
;
h
->
list
.
next
->
prev
=
c
;
h
->
list
.
next
=
c
;
h
->
cur
++
;
h
->
cursor
=
c
;
*
ev
=
c
->
ev
;
return
0
;
oomem:
he_seterrev
(
ev
,
_HE_MALLOC_FAILED
);
return
-
1
;
}
/* history_def_enter():
* Default function to enter an item in the history
*/
private
int
history_def_enter
(
void
*
p
,
TYPE
(
HistEvent
)
*
ev
,
const
Char
*
str
)
{
history_t
*
h
=
(
history_t
*
)
p
;
if
((
h
->
flags
&
H_UNIQUE
)
!=
0
&&
h
->
list
.
next
!=
&
h
->
list
&&
Strcmp
(
h
->
list
.
next
->
ev
.
str
,
str
)
==
0
)
return
0
;
if
(
history_def_insert
(
h
,
ev
,
str
)
==
-
1
)
return
-
1
;
/* error, keep error message */
/*
* Always keep at least one entry.
* This way we don't have to check for the empty list.
*/
while
(
h
->
cur
>
h
->
max
&&
h
->
cur
>
0
)
history_def_delete
(
h
,
ev
,
h
->
list
.
prev
);
return
1
;
}
/* history_def_init():
* Default history initialization function
*/
/* ARGSUSED */
private
int
history_def_init
(
void
**
p
,
TYPE
(
HistEvent
)
*
ev
__attribute__
((
__unused__
)),
int
n
)
{
history_t
*
h
=
(
history_t
*
)
h_malloc
(
sizeof
(
*
h
));
if
(
h
==
NULL
)
return
-
1
;
if
(
n
<=
0
)
n
=
0
;
h
->
eventid
=
0
;
h
->
cur
=
0
;
h
->
max
=
n
;
h
->
list
.
next
=
h
->
list
.
prev
=
&
h
->
list
;
h
->
list
.
ev
.
str
=
NULL
;
h
->
list
.
ev
.
num
=
0
;
h
->
cursor
=
&
h
->
list
;
h
->
flags
=
0
;
*
p
=
h
;
return
0
;
}
/* history_def_clear():
* Default history cleanup function
*/
private
void
history_def_clear
(
void
*
p
,
TYPE
(
HistEvent
)
*
ev
)
{
history_t
*
h
=
(
history_t
*
)
p
;
while
(
h
->
list
.
prev
!=
&
h
->
list
)
history_def_delete
(
h
,
ev
,
h
->
list
.
prev
);
h
->
cursor
=
&
h
->
list
;
h
->
eventid
=
0
;
h
->
cur
=
0
;
}
/************************************************************************/
/* history_init():
* Initialization function.
*/
public
TYPE
(
History
)
*
FUN
(
history
,
init
)(
void
)
{
TYPE
(
HistEvent
)
ev
;
TYPE
(
History
)
*
h
=
(
TYPE
(
History
)
*
)
h_malloc
(
sizeof
(
*
h
));
if
(
h
==
NULL
)
return
NULL
;
if
(
history_def_init
(
&
h
->
h_ref
,
&
ev
,
0
)
==
-
1
)
{
h_free
(
h
);
return
NULL
;
}
h
->
h_ent
=
-
1
;
h
->
h_next
=
history_def_next
;
h
->
h_first
=
history_def_first
;
h
->
h_last
=
history_def_last
;
h
->
h_prev
=
history_def_prev
;
h
->
h_curr
=
history_def_curr
;
h
->
h_set
=
history_def_set
;
h
->
h_clear
=
history_def_clear
;
h
->
h_enter
=
history_def_enter
;
h
->
h_add
=
history_def_add
;
h
->
h_del
=
history_def_del
;
return
h
;
}
/* history_end():
* clean up history;
*/
public
void
FUN
(
history
,
end
)(
TYPE
(
History
)
*
h
)
{
TYPE
(
HistEvent
)
ev
;
if
(
h
->
h_next
==
history_def_next
)
history_def_clear
(
h
->
h_ref
,
&
ev
);
h_free
(
h
->
h_ref
);
h_free
(
h
);
}
/* history_setsize():
* Set history number of events
*/
private
int
history_setsize
(
TYPE
(
History
)
*
h
,
TYPE
(
HistEvent
)
*
ev
,
int
num
)
{
if
(
h
->
h_next
!=
history_def_next
)
{
he_seterrev
(
ev
,
_HE_NOT_ALLOWED
);
return
-
1
;
}
if
(
num
<
0
)
{
he_seterrev
(
ev
,
_HE_BAD_PARAM
);
return
-
1
;
}
history_def_setsize
(
h
->
h_ref
,
num
);
return
0
;
}
/* history_getsize():
* Get number of events currently in history
*/
private
int
history_getsize
(
TYPE
(
History
)
*
h
,
TYPE
(
HistEvent
)
*
ev
)
{
if
(
h
->
h_next
!=
history_def_next
)
{
he_seterrev
(
ev
,
_HE_NOT_ALLOWED
);
return
-
1
;
}
ev
->
num
=
history_def_getsize
(
h
->
h_ref
);
if
(
ev
->
num
<
-
1
)
{
he_seterrev
(
ev
,
_HE_SIZE_NEGATIVE
);
return
-
1
;
}
return
0
;
}
/* history_setunique():
* Set if adjacent equal events should not be entered in history.
*/
private
int
history_setunique
(
TYPE
(
History
)
*
h
,
TYPE
(
HistEvent
)
*
ev
,
int
uni
)
{
if
(
h
->
h_next
!=
history_def_next
)
{
he_seterrev
(
ev
,
_HE_NOT_ALLOWED
);
return
-
1
;
}
history_def_setunique
(
h
->
h_ref
,
uni
);
return
0
;
}
/* history_getunique():
* Get if adjacent equal events should not be entered in history.
*/
private
int
history_getunique
(
TYPE
(
History
)
*
h
,
TYPE
(
HistEvent
)
*
ev
)
{
if
(
h
->
h_next
!=
history_def_next
)
{
he_seterrev
(
ev
,
_HE_NOT_ALLOWED
);
return
-
1
;
}
ev
->
num
=
history_def_getunique
(
h
->
h_ref
);
return
0
;
}
/* history_set_fun():
* Set history functions
*/
private
int
history_set_fun
(
TYPE
(
History
)
*
h
,
TYPE
(
History
)
*
nh
)
{
TYPE
(
HistEvent
)
ev
;
if
(
nh
->
h_first
==
NULL
||
nh
->
h_next
==
NULL
||
nh
->
h_last
==
NULL
||
nh
->
h_prev
==
NULL
||
nh
->
h_curr
==
NULL
||
nh
->
h_set
==
NULL
||
nh
->
h_enter
==
NULL
||
nh
->
h_add
==
NULL
||
nh
->
h_clear
==
NULL
||
nh
->
h_del
==
NULL
||
nh
->
h_ref
==
NULL
)
{
if
(
h
->
h_next
!=
history_def_next
)
{
history_def_init
(
&
h
->
h_ref
,
&
ev
,
0
);
h
->
h_first
=
history_def_first
;
h
->
h_next
=
history_def_next
;
h
->
h_last
=
history_def_last
;
h
->
h_prev
=
history_def_prev
;
h
->
h_curr
=
history_def_curr
;
h
->
h_set
=
history_def_set
;
h
->
h_clear
=
history_def_clear
;
h
->
h_enter
=
history_def_enter
;
h
->
h_add
=
history_def_add
;
h
->
h_del
=
history_def_del
;
}
return
-
1
;
}
if
(
h
->
h_next
==
history_def_next
)
history_def_clear
(
h
->
h_ref
,
&
ev
);
h
->
h_ent
=
-
1
;
h
->
h_first
=
nh
->
h_first
;
h
->
h_next
=
nh
->
h_next
;
h
->
h_last
=
nh
->
h_last
;
h
->
h_prev
=
nh
->
h_prev
;
h
->
h_curr
=
nh
->
h_curr
;
h
->
h_set
=
nh
->
h_set
;
h
->
h_clear
=
nh
->
h_clear
;
h
->
h_enter
=
nh
->
h_enter
;
h
->
h_add
=
nh
->
h_add
;
h
->
h_del
=
nh
->
h_del
;
return
0
;
}
/* history_load():
* TYPE(History) load function
*/
private
int
history_load
(
TYPE
(
History
)
*
h
,
const
char
*
fname
)
{
FILE
*
fp
;
char
*
line
;
size_t
sz
,
max_size
;
char
*
ptr
;
int
i
=
-
1
;
TYPE
(
HistEvent
)
ev
;
#ifdef WIDECHAR
static
ct_buffer_t
conv
;
#endif
if
((
fp
=
fopen
(
fname
,
"r"
))
==
NULL
)
return
i
;
if
((
line
=
fgetln
(
fp
,
&
sz
))
==
NULL
)
goto
done
;
if
(
strncmp
(
line
,
hist_cookie
,
sz
)
!=
0
)
goto
done
;
ptr
=
h_malloc
((
max_size
=
1024
)
*
sizeof
(
*
ptr
));
if
(
ptr
==
NULL
)
goto
done
;
for
(
i
=
0
;
(
line
=
fgetln
(
fp
,
&
sz
))
!=
NULL
;
i
++
)
{
char
c
=
line
[
sz
];
if
(
sz
!=
0
&&
line
[
sz
-
1
]
==
'\n'
)
line
[
--
sz
]
=
'\0'
;
else
line
[
sz
]
=
'\0'
;
if
(
max_size
<
sz
)
{
char
*
nptr
;
max_size
=
(
sz
+
1024
)
&
(
size_t
)
~
1023
;
nptr
=
h_realloc
(
ptr
,
max_size
*
sizeof
(
*
ptr
));
if
(
nptr
==
NULL
)
{
i
=
-
1
;
goto
oomem
;
}
ptr
=
nptr
;
}
(
void
)
strunvis
(
ptr
,
line
);
line
[
sz
]
=
c
;
if
(
HENTER
(
h
,
&
ev
,
ct_decode_string
(
ptr
,
&
conv
))
==
-
1
)
{
i
=
-
1
;
goto
oomem
;
}
}
oomem:
h_free
(
ptr
);
done:
(
void
)
fclose
(
fp
);
return
i
;
}
/* history_save():
* TYPE(History) save function
*/
private
int
history_save
(
TYPE
(
History
)
*
h
,
const
char
*
fname
)
{
FILE
*
fp
;
TYPE
(
HistEvent
)
ev
;
int
i
=
-
1
,
retval
;
size_t
len
,
max_size
;
char
*
ptr
;
const
char
*
str
;
#ifdef WIDECHAR
static
ct_buffer_t
conv
;
#endif
if
((
fp
=
fopen
(
fname
,
"w"
))
==
NULL
)
return
-
1
;
if
(
fchmod
(
fileno
(
fp
),
S_IRUSR
|
S_IWUSR
)
==
-
1
)
goto
done
;
if
(
fputs
(
hist_cookie
,
fp
)
==
EOF
)
goto
done
;
ptr
=
h_malloc
((
max_size
=
1024
)
*
sizeof
(
*
ptr
));
if
(
ptr
==
NULL
)
goto
done
;
for
(
i
=
0
,
retval
=
HLAST
(
h
,
&
ev
);
retval
!=
-
1
;
retval
=
HPREV
(
h
,
&
ev
),
i
++
)
{
str
=
ct_encode_string
(
ev
.
str
,
&
conv
);
len
=
strlen
(
str
)
*
4
;
if
(
len
>=
max_size
)
{
char
*
nptr
;
max_size
=
(
len
+
1024
)
&
(
size_t
)
~
1023
;
nptr
=
h_realloc
(
ptr
,
max_size
*
sizeof
(
*
ptr
));
if
(
nptr
==
NULL
)
{
i
=
-
1
;
goto
oomem
;
}
ptr
=
nptr
;
}
(
void
)
strvis
(
ptr
,
str
,
VIS_WHITE
);
(
void
)
fprintf
(
fp
,
"%s
\n
"
,
ptr
);
}
oomem:
h_free
(
ptr
);
done:
(
void
)
fclose
(
fp
);
return
i
;
}
/* history_prev_event():
* Find the previous event, with number given
*/
private
int
history_prev_event
(
TYPE
(
History
)
*
h
,
TYPE
(
HistEvent
)
*
ev
,
int
num
)
{
int
retval
;
for
(
retval
=
HCURR
(
h
,
ev
);
retval
!=
-
1
;
retval
=
HPREV
(
h
,
ev
))
if
(
ev
->
num
==
num
)
return
0
;
he_seterrev
(
ev
,
_HE_NOT_FOUND
);
return
-
1
;
}
private
int
history_next_evdata
(
TYPE
(
History
)
*
h
,
TYPE
(
HistEvent
)
*
ev
,
int
num
,
void
**
d
)
{
int
retval
;
for
(
retval
=
HCURR
(
h
,
ev
);
retval
!=
-
1
;
retval
=
HPREV
(
h
,
ev
))
if
(
ev
->
num
==
num
)
{
if
(
d
)
*
d
=
((
history_t
*
)
h
->
h_ref
)
->
cursor
->
data
;
return
0
;
}
he_seterrev
(
ev
,
_HE_NOT_FOUND
);
return
-
1
;
}
/* history_next_event():
* Find the next event, with number given
*/
private
int
history_next_event
(
TYPE
(
History
)
*
h
,
TYPE
(
HistEvent
)
*
ev
,
int
num
)
{
int
retval
;
for
(
retval
=
HCURR
(
h
,
ev
);
retval
!=
-
1
;
retval
=
HNEXT
(
h
,
ev
))
if
(
ev
->
num
==
num
)
return
0
;
he_seterrev
(
ev
,
_HE_NOT_FOUND
);
return
-
1
;
}
/* history_prev_string():
* Find the previous event beginning with string
*/
private
int
history_prev_string
(
TYPE
(
History
)
*
h
,
TYPE
(
HistEvent
)
*
ev
,
const
Char
*
str
)
{
size_t
len
=
Strlen
(
str
);
int
retval
;
for
(
retval
=
HCURR
(
h
,
ev
);
retval
!=
-
1
;
retval
=
HNEXT
(
h
,
ev
))
if
(
Strncmp
(
str
,
ev
->
str
,
len
)
==
0
)
return
0
;
he_seterrev
(
ev
,
_HE_NOT_FOUND
);
return
-
1
;
}
/* history_next_string():
* Find the next event beginning with string
*/
private
int
history_next_string
(
TYPE
(
History
)
*
h
,
TYPE
(
HistEvent
)
*
ev
,
const
Char
*
str
)
{
size_t
len
=
Strlen
(
str
);
int
retval
;
for
(
retval
=
HCURR
(
h
,
ev
);
retval
!=
-
1
;
retval
=
HPREV
(
h
,
ev
))
if
(
Strncmp
(
str
,
ev
->
str
,
len
)
==
0
)
return
0
;
he_seterrev
(
ev
,
_HE_NOT_FOUND
);
return
-
1
;
}
/* history():
* User interface to history functions.
*/
int
FUNW
(
history
)(
TYPE
(
History
)
*
h
,
TYPE
(
HistEvent
)
*
ev
,
int
fun
,
...)
{
va_list
va
;
const
Char
*
str
;
int
retval
;
va_start
(
va
,
fun
);
he_seterrev
(
ev
,
_HE_OK
);
switch
(
fun
)
{
case
H_GETSIZE
:
retval
=
history_getsize
(
h
,
ev
);
break
;
case
H_SETSIZE
:
retval
=
history_setsize
(
h
,
ev
,
va_arg
(
va
,
int
));
break
;
case
H_GETUNIQUE
:
retval
=
history_getunique
(
h
,
ev
);
break
;
case
H_SETUNIQUE
:
retval
=
history_setunique
(
h
,
ev
,
va_arg
(
va
,
int
));
break
;
case
H_ADD
:
str
=
va_arg
(
va
,
const
Char
*
);
retval
=
HADD
(
h
,
ev
,
str
);
break
;
case
H_DEL
:
retval
=
HDEL
(
h
,
ev
,
va_arg
(
va
,
const
int
));
break
;
case
H_ENTER
:
str
=
va_arg
(
va
,
const
Char
*
);
if
((
retval
=
HENTER
(
h
,
ev
,
str
))
!=
-
1
)
h
->
h_ent
=
ev
->
num
;
break
;
case
H_APPEND
:
str
=
va_arg
(
va
,
const
Char
*
);
if
((
retval
=
HSET
(
h
,
ev
,
h
->
h_ent
))
!=
-
1
)
retval
=
HADD
(
h
,
ev
,
str
);
break
;
case
H_FIRST
:
retval
=
HFIRST
(
h
,
ev
);
break
;
case
H_NEXT
:
retval
=
HNEXT
(
h
,
ev
);
break
;
case
H_LAST
:
retval
=
HLAST
(
h
,
ev
);
break
;
case
H_PREV
:
retval
=
HPREV
(
h
,
ev
);
break
;
case
H_CURR
:
retval
=
HCURR
(
h
,
ev
);
break
;
case
H_SET
:
retval
=
HSET
(
h
,
ev
,
va_arg
(
va
,
const
int
));
break
;
case
H_CLEAR
:
HCLEAR
(
h
,
ev
);
retval
=
0
;
break
;
case
H_LOAD
:
retval
=
history_load
(
h
,
va_arg
(
va
,
const
char
*
));
if
(
retval
==
-
1
)
he_seterrev
(
ev
,
_HE_HIST_READ
);
break
;
case
H_SAVE
:
retval
=
history_save
(
h
,
va_arg
(
va
,
const
char
*
));
if
(
retval
==
-
1
)
he_seterrev
(
ev
,
_HE_HIST_WRITE
);
break
;
case
H_PREV_EVENT
:
retval
=
history_prev_event
(
h
,
ev
,
va_arg
(
va
,
int
));
break
;
case
H_NEXT_EVENT
:
retval
=
history_next_event
(
h
,
ev
,
va_arg
(
va
,
int
));
break
;
case
H_PREV_STR
:
retval
=
history_prev_string
(
h
,
ev
,
va_arg
(
va
,
const
Char
*
));
break
;
case
H_NEXT_STR
:
retval
=
history_next_string
(
h
,
ev
,
va_arg
(
va
,
const
Char
*
));
break
;
case
H_FUNC
:
{
TYPE
(
History
)
hf
;
hf
.
h_ref
=
va_arg
(
va
,
void
*
);
h
->
h_ent
=
-
1
;
hf
.
h_first
=
va_arg
(
va
,
history_gfun_t
);
hf
.
h_next
=
va_arg
(
va
,
history_gfun_t
);
hf
.
h_last
=
va_arg
(
va
,
history_gfun_t
);
hf
.
h_prev
=
va_arg
(
va
,
history_gfun_t
);
hf
.
h_curr
=
va_arg
(
va
,
history_gfun_t
);
hf
.
h_set
=
va_arg
(
va
,
history_sfun_t
);
hf
.
h_clear
=
va_arg
(
va
,
history_vfun_t
);
hf
.
h_enter
=
va_arg
(
va
,
history_efun_t
);
hf
.
h_add
=
va_arg
(
va
,
history_efun_t
);
hf
.
h_del
=
va_arg
(
va
,
history_sfun_t
);
if
((
retval
=
history_set_fun
(
h
,
&
hf
))
==
-
1
)
he_seterrev
(
ev
,
_HE_PARAM_MISSING
);
break
;
}
case
H_END
:
FUN
(
history
,
end
)(
h
);
retval
=
0
;
break
;
case
H_NEXT_EVDATA
:
{
int
num
=
va_arg
(
va
,
int
);
void
**
d
=
va_arg
(
va
,
void
**
);
retval
=
history_next_evdata
(
h
,
ev
,
num
,
d
);
break
;
}
case
H_DELDATA
:
{
int
num
=
va_arg
(
va
,
int
);
void
**
d
=
va_arg
(
va
,
void
**
);
retval
=
history_deldata_nth
((
history_t
*
)
h
->
h_ref
,
ev
,
num
,
d
);
break
;
}
case
H_REPLACE
:
/* only use after H_NEXT_EVDATA */
{
const
Char
*
line
=
va_arg
(
va
,
const
Char
*
);
void
*
d
=
va_arg
(
va
,
void
*
);
const
Char
*
s
;
if
(
!
line
||
!
(
s
=
Strdup
(
line
)))
{
retval
=
-
1
;
break
;
}
((
history_t
*
)
h
->
h_ref
)
->
cursor
->
ev
.
str
=
s
;
((
history_t
*
)
h
->
h_ref
)
->
cursor
->
data
=
d
;
retval
=
0
;
break
;
}
default:
retval
=
-
1
;
he_seterrev
(
ev
,
_HE_UNKNOWN
);
break
;
}
va_end
(
va
);
return
retval
;
}
cmd-line-utils/libedit/historyn.c
0 → 100644
View file @
28192e02
#define NARROW_WRAPPER
#include
"config.h"
#undef WIDECHAR
#define NARROWCHAR
#include
"./history.c"
cmd-line-utils/libedit/keymacro.c
0 → 100644
View file @
28192e02
/* $NetBSD: keymacro.c,v 1.7 2011/08/16 16:25:15 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include
"config.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93";
#else
#endif
#endif
/* not lint && not SCCSID */
/*
* keymacro.c: This module contains the procedures for maintaining
* the extended-key map.
*
* An extended-key (key) is a sequence of keystrokes introduced
* with a sequence introducer and consisting of an arbitrary
* number of characters. This module maintains a map (the
* el->el_keymacro.map)
* to convert these extended-key sequences into input strs
* (XK_STR), editor functions (XK_CMD), or unix commands (XK_EXE).
*
* Warning:
* If key is a substr of some other keys, then the longer
* keys are lost!! That is, if the keys "abcd" and "abcef"
* are in el->el_keymacro.map, adding the key "abc" will cause
* the first two definitions to be lost.
*
* Restrictions:
* -------------
* 1) It is not possible to have one key that is a
* substr of another.
*/
#include
<string.h>
#include
<stdlib.h>
#include
"el.h"
/*
* The Nodes of the el->el_keymacro.map. The el->el_keymacro.map is a
* linked list of these node elements
*/
struct
keymacro_node_t
{
Char
ch
;
/* single character of key */
int
type
;
/* node type */
keymacro_value_t
val
;
/* command code or pointer to str, */
/* if this is a leaf */
struct
keymacro_node_t
*
next
;
/* ptr to next char of this key */
struct
keymacro_node_t
*
sibling
;
/* ptr to another key with same prefix*/
};
private
int
node_trav
(
EditLine
*
,
keymacro_node_t
*
,
Char
*
,
keymacro_value_t
*
);
private
int
node__try
(
EditLine
*
,
keymacro_node_t
*
,
const
Char
*
,
keymacro_value_t
*
,
int
);
private
keymacro_node_t
*
node__get
(
Int
);
private
void
node__free
(
keymacro_node_t
*
);
private
void
node__put
(
EditLine
*
,
keymacro_node_t
*
);
private
int
node__delete
(
EditLine
*
,
keymacro_node_t
**
,
const
Char
*
);
private
int
node_lookup
(
EditLine
*
,
const
Char
*
,
keymacro_node_t
*
,
size_t
);
private
int
node_enum
(
EditLine
*
,
keymacro_node_t
*
,
size_t
);
#define KEY_BUFSIZ EL_BUFSIZ
/* keymacro_init():
* Initialize the key maps
*/
protected
int
keymacro_init
(
EditLine
*
el
)
{
el
->
el_keymacro
.
buf
=
el_malloc
(
KEY_BUFSIZ
*
sizeof
(
*
el
->
el_keymacro
.
buf
));
if
(
el
->
el_keymacro
.
buf
==
NULL
)
return
-
1
;
el
->
el_keymacro
.
map
=
NULL
;
keymacro_reset
(
el
);
return
0
;
}
/* keymacro_end():
* Free the key maps
*/
protected
void
keymacro_end
(
EditLine
*
el
)
{
el_free
(
el
->
el_keymacro
.
buf
);
el
->
el_keymacro
.
buf
=
NULL
;
node__free
(
el
->
el_keymacro
.
map
);
}
/* keymacro_map_cmd():
* Associate cmd with a key value
*/
protected
keymacro_value_t
*
keymacro_map_cmd
(
EditLine
*
el
,
int
cmd
)
{
el
->
el_keymacro
.
val
.
cmd
=
(
el_action_t
)
cmd
;
return
&
el
->
el_keymacro
.
val
;
}
/* keymacro_map_str():
* Associate str with a key value
*/
protected
keymacro_value_t
*
keymacro_map_str
(
EditLine
*
el
,
Char
*
str
)
{
el
->
el_keymacro
.
val
.
str
=
str
;
return
&
el
->
el_keymacro
.
val
;
}
/* keymacro_reset():
* Takes all nodes on el->el_keymacro.map and puts them on free list.
* Then initializes el->el_keymacro.map with arrow keys
* [Always bind the ansi arrow keys?]
*/
protected
void
keymacro_reset
(
EditLine
*
el
)
{
node__put
(
el
,
el
->
el_keymacro
.
map
);
el
->
el_keymacro
.
map
=
NULL
;
return
;
}
/* keymacro_get():
* Calls the recursive function with entry point el->el_keymacro.map
* Looks up *ch in map and then reads characters until a
* complete match is found or a mismatch occurs. Returns the
* type of the match found (XK_STR, XK_CMD, or XK_EXE).
* Returns NULL in val.str and XK_STR for no match.
* The last character read is returned in *ch.
*/
protected
int
keymacro_get
(
EditLine
*
el
,
Char
*
ch
,
keymacro_value_t
*
val
)
{
return
node_trav
(
el
,
el
->
el_keymacro
.
map
,
ch
,
val
);
}
/* keymacro_add():
* Adds key to the el->el_keymacro.map and associates the value in
* val with it. If key is already is in el->el_keymacro.map, the new
* code is applied to the existing key. Ntype specifies if code is a
* command, an out str or a unix command.
*/
protected
void
keymacro_add
(
EditLine
*
el
,
const
Char
*
key
,
keymacro_value_t
*
val
,
int
ntype
)
{
if
(
key
[
0
]
==
'\0'
)
{
(
void
)
fprintf
(
el
->
el_errfile
,
"keymacro_add: Null extended-key not allowed.
\n
"
);
return
;
}
if
(
ntype
==
XK_CMD
&&
val
->
cmd
==
ED_SEQUENCE_LEAD_IN
)
{
(
void
)
fprintf
(
el
->
el_errfile
,
"keymacro_add: sequence-lead-in command not allowed
\n
"
);
return
;
}
if
(
el
->
el_keymacro
.
map
==
NULL
)
/* tree is initially empty. Set up new node to match key[0] */
el
->
el_keymacro
.
map
=
node__get
(
key
[
0
]);
/* it is properly initialized */
/* Now recurse through el->el_keymacro.map */
(
void
)
node__try
(
el
,
el
->
el_keymacro
.
map
,
key
,
val
,
ntype
);
return
;
}
/* keymacro_clear():
*
*/
protected
void
keymacro_clear
(
EditLine
*
el
,
el_action_t
*
map
,
const
Char
*
in
)
{
#ifdef WIDECHAR
if
(
*
in
>
N_KEYS
)
/* can't be in the map */
return
;
#endif
if
((
map
[(
unsigned
char
)
*
in
]
==
ED_SEQUENCE_LEAD_IN
)
&&
((
map
==
el
->
el_map
.
key
&&
el
->
el_map
.
alt
[(
unsigned
char
)
*
in
]
!=
ED_SEQUENCE_LEAD_IN
)
||
(
map
==
el
->
el_map
.
alt
&&
el
->
el_map
.
key
[(
unsigned
char
)
*
in
]
!=
ED_SEQUENCE_LEAD_IN
)))
(
void
)
keymacro_delete
(
el
,
in
);
}
/* keymacro_delete():
* Delete the key and all longer keys staring with key, if
* they exists.
*/
protected
int
keymacro_delete
(
EditLine
*
el
,
const
Char
*
key
)
{
if
(
key
[
0
]
==
'\0'
)
{
(
void
)
fprintf
(
el
->
el_errfile
,
"keymacro_delete: Null extended-key not allowed.
\n
"
);
return
-
1
;
}
if
(
el
->
el_keymacro
.
map
==
NULL
)
return
0
;
(
void
)
node__delete
(
el
,
&
el
->
el_keymacro
.
map
,
key
);
return
0
;
}
/* keymacro_print():
* Print the binding associated with key key.
* Print entire el->el_keymacro.map if null
*/
protected
void
keymacro_print
(
EditLine
*
el
,
const
Char
*
key
)
{
/* do nothing if el->el_keymacro.map is empty and null key specified */
if
(
el
->
el_keymacro
.
map
==
NULL
&&
*
key
==
0
)
return
;
el
->
el_keymacro
.
buf
[
0
]
=
'"'
;
if
(
node_lookup
(
el
,
key
,
el
->
el_keymacro
.
map
,
(
size_t
)
1
)
<=
-
1
)
/* key is not bound */
(
void
)
fprintf
(
el
->
el_errfile
,
"Unbound extended key
\"
"
FSTR
"
\"\n
"
,
key
);
return
;
}
/* node_trav():
* recursively traverses node in tree until match or mismatch is
* found. May read in more characters.
*/
private
int
node_trav
(
EditLine
*
el
,
keymacro_node_t
*
ptr
,
Char
*
ch
,
keymacro_value_t
*
val
)
{
if
(
ptr
->
ch
==
*
ch
)
{
/* match found */
if
(
ptr
->
next
)
{
/* key not complete so get next char */
if
(
FUN
(
el
,
getc
)(
el
,
ch
)
!=
1
)
{
/* if EOF or error */
val
->
cmd
=
ED_END_OF_FILE
;
return
XK_CMD
;
/* PWP: Pretend we just read an end-of-file */
}
return
node_trav
(
el
,
ptr
->
next
,
ch
,
val
);
}
else
{
*
val
=
ptr
->
val
;
if
(
ptr
->
type
!=
XK_CMD
)
*
ch
=
'\0'
;
return
ptr
->
type
;
}
}
else
{
/* no match found here */
if
(
ptr
->
sibling
)
{
/* try next sibling */
return
node_trav
(
el
,
ptr
->
sibling
,
ch
,
val
);
}
else
{
/* no next sibling -- mismatch */
val
->
str
=
NULL
;
return
XK_STR
;
}
}
}
/* node__try():
* Find a node that matches *str or allocate a new one
*/
private
int
node__try
(
EditLine
*
el
,
keymacro_node_t
*
ptr
,
const
Char
*
str
,
keymacro_value_t
*
val
,
int
ntype
)
{
if
(
ptr
->
ch
!=
*
str
)
{
keymacro_node_t
*
xm
;
for
(
xm
=
ptr
;
xm
->
sibling
!=
NULL
;
xm
=
xm
->
sibling
)
if
(
xm
->
sibling
->
ch
==
*
str
)
break
;
if
(
xm
->
sibling
==
NULL
)
xm
->
sibling
=
node__get
(
*
str
);
/* setup new node */
ptr
=
xm
->
sibling
;
}
if
(
*++
str
==
'\0'
)
{
/* we're there */
if
(
ptr
->
next
!=
NULL
)
{
node__put
(
el
,
ptr
->
next
);
/* lose longer keys with this prefix */
ptr
->
next
=
NULL
;
}
switch
(
ptr
->
type
)
{
case
XK_CMD
:
case
XK_NOD
:
break
;
case
XK_STR
:
case
XK_EXE
:
if
(
ptr
->
val
.
str
)
el_free
(
ptr
->
val
.
str
);
break
;
default:
EL_ABORT
((
el
->
el_errfile
,
"Bad XK_ type %d
\n
"
,
ptr
->
type
));
break
;
}
switch
(
ptr
->
type
=
ntype
)
{
case
XK_CMD
:
ptr
->
val
=
*
val
;
break
;
case
XK_STR
:
case
XK_EXE
:
if
((
ptr
->
val
.
str
=
Strdup
(
val
->
str
))
==
NULL
)
return
-
1
;
break
;
default:
EL_ABORT
((
el
->
el_errfile
,
"Bad XK_ type %d
\n
"
,
ntype
));
break
;
}
}
else
{
/* still more chars to go */
if
(
ptr
->
next
==
NULL
)
ptr
->
next
=
node__get
(
*
str
);
/* setup new node */
(
void
)
node__try
(
el
,
ptr
->
next
,
str
,
val
,
ntype
);
}
return
0
;
}
/* node__delete():
* Delete node that matches str
*/
private
int
node__delete
(
EditLine
*
el
,
keymacro_node_t
**
inptr
,
const
Char
*
str
)
{
keymacro_node_t
*
ptr
;
keymacro_node_t
*
prev_ptr
=
NULL
;
ptr
=
*
inptr
;
if
(
ptr
->
ch
!=
*
str
)
{
keymacro_node_t
*
xm
;
for
(
xm
=
ptr
;
xm
->
sibling
!=
NULL
;
xm
=
xm
->
sibling
)
if
(
xm
->
sibling
->
ch
==
*
str
)
break
;
if
(
xm
->
sibling
==
NULL
)
return
0
;
prev_ptr
=
xm
;
ptr
=
xm
->
sibling
;
}
if
(
*++
str
==
'\0'
)
{
/* we're there */
if
(
prev_ptr
==
NULL
)
*
inptr
=
ptr
->
sibling
;
else
prev_ptr
->
sibling
=
ptr
->
sibling
;
ptr
->
sibling
=
NULL
;
node__put
(
el
,
ptr
);
return
1
;
}
else
if
(
ptr
->
next
!=
NULL
&&
node__delete
(
el
,
&
ptr
->
next
,
str
)
==
1
)
{
if
(
ptr
->
next
!=
NULL
)
return
0
;
if
(
prev_ptr
==
NULL
)
*
inptr
=
ptr
->
sibling
;
else
prev_ptr
->
sibling
=
ptr
->
sibling
;
ptr
->
sibling
=
NULL
;
node__put
(
el
,
ptr
);
return
1
;
}
else
{
return
0
;
}
}
/* node__put():
* Puts a tree of nodes onto free list using free(3).
*/
private
void
node__put
(
EditLine
*
el
,
keymacro_node_t
*
ptr
)
{
if
(
ptr
==
NULL
)
return
;
if
(
ptr
->
next
!=
NULL
)
{
node__put
(
el
,
ptr
->
next
);
ptr
->
next
=
NULL
;
}
node__put
(
el
,
ptr
->
sibling
);
switch
(
ptr
->
type
)
{
case
XK_CMD
:
case
XK_NOD
:
break
;
case
XK_EXE
:
case
XK_STR
:
if
(
ptr
->
val
.
str
!=
NULL
)
el_free
(
ptr
->
val
.
str
);
break
;
default:
EL_ABORT
((
el
->
el_errfile
,
"Bad XK_ type %d
\n
"
,
ptr
->
type
));
break
;
}
el_free
(
ptr
);
}
/* node__get():
* Returns pointer to a keymacro_node_t for ch.
*/
private
keymacro_node_t
*
node__get
(
Int
ch
)
{
keymacro_node_t
*
ptr
;
ptr
=
el_malloc
(
sizeof
(
*
ptr
));
if
(
ptr
==
NULL
)
return
NULL
;
ptr
->
ch
=
ch
;
ptr
->
type
=
XK_NOD
;
ptr
->
val
.
str
=
NULL
;
ptr
->
next
=
NULL
;
ptr
->
sibling
=
NULL
;
return
ptr
;
}
private
void
node__free
(
keymacro_node_t
*
k
)
{
if
(
k
==
NULL
)
return
;
node__free
(
k
->
sibling
);
node__free
(
k
->
next
);
el_free
(
k
);
}
/* node_lookup():
* look for the str starting at node ptr.
* Print if last node
*/
private
int
node_lookup
(
EditLine
*
el
,
const
Char
*
str
,
keymacro_node_t
*
ptr
,
size_t
cnt
)
{
ssize_t
used
;
if
(
ptr
==
NULL
)
return
-
1
;
/* cannot have null ptr */
if
(
!
str
||
*
str
==
0
)
{
/* no more chars in str. node_enum from here. */
(
void
)
node_enum
(
el
,
ptr
,
cnt
);
return
0
;
}
else
{
/* If match put this char into el->el_keymacro.buf. Recurse */
if
(
ptr
->
ch
==
*
str
)
{
/* match found */
used
=
ct_visual_char
(
el
->
el_keymacro
.
buf
+
cnt
,
KEY_BUFSIZ
-
cnt
,
ptr
->
ch
);
if
(
used
==
-
1
)
return
-
1
;
/* ran out of buffer space */
if
(
ptr
->
next
!=
NULL
)
/* not yet at leaf */
return
(
node_lookup
(
el
,
str
+
1
,
ptr
->
next
,
(
size_t
)
used
+
cnt
));
else
{
/* next node is null so key should be complete */
if
(
str
[
1
]
==
0
)
{
size_t
px
=
cnt
+
(
size_t
)
used
;
el
->
el_keymacro
.
buf
[
px
]
=
'"'
;
el
->
el_keymacro
.
buf
[
px
+
1
]
=
'\0'
;
keymacro_kprint
(
el
,
el
->
el_keymacro
.
buf
,
&
ptr
->
val
,
ptr
->
type
);
return
0
;
}
else
return
-
1
;
/* mismatch -- str still has chars */
}
}
else
{
/* no match found try sibling */
if
(
ptr
->
sibling
)
return
(
node_lookup
(
el
,
str
,
ptr
->
sibling
,
cnt
));
else
return
-
1
;
}
}
}
/* node_enum():
* Traverse the node printing the characters it is bound in buffer
*/
private
int
node_enum
(
EditLine
*
el
,
keymacro_node_t
*
ptr
,
size_t
cnt
)
{
ssize_t
used
;
if
(
cnt
>=
KEY_BUFSIZ
-
5
)
{
/* buffer too small */
el
->
el_keymacro
.
buf
[
++
cnt
]
=
'"'
;
el
->
el_keymacro
.
buf
[
++
cnt
]
=
'\0'
;
(
void
)
fprintf
(
el
->
el_errfile
,
"Some extended keys too long for internal print buffer"
);
(
void
)
fprintf
(
el
->
el_errfile
,
"
\"
"
FSTR
"...
\"\n
"
,
el
->
el_keymacro
.
buf
);
return
0
;
}
if
(
ptr
==
NULL
)
{
#ifdef DEBUG_EDIT
(
void
)
fprintf
(
el
->
el_errfile
,
"node_enum: BUG!! Null ptr passed
\n
!"
);
#endif
return
-
1
;
}
/* put this char at end of str */
used
=
ct_visual_char
(
el
->
el_keymacro
.
buf
+
cnt
,
KEY_BUFSIZ
-
cnt
,
ptr
->
ch
);
if
(
ptr
->
next
==
NULL
)
{
/* print this key and function */
el
->
el_keymacro
.
buf
[
cnt
+
(
size_t
)
used
]
=
'"'
;
el
->
el_keymacro
.
buf
[
cnt
+
(
size_t
)
used
+
1
]
=
'\0'
;
keymacro_kprint
(
el
,
el
->
el_keymacro
.
buf
,
&
ptr
->
val
,
ptr
->
type
);
}
else
(
void
)
node_enum
(
el
,
ptr
->
next
,
cnt
+
(
size_t
)
used
);
/* go to sibling if there is one */
if
(
ptr
->
sibling
)
(
void
)
node_enum
(
el
,
ptr
->
sibling
,
cnt
);
return
0
;
}
/* keymacro_kprint():
* Print the specified key and its associated
* function specified by val
*/
protected
void
keymacro_kprint
(
EditLine
*
el
,
const
Char
*
key
,
keymacro_value_t
*
val
,
int
ntype
)
{
el_bindings_t
*
fp
;
char
unparsbuf
[
EL_BUFSIZ
];
static
const
char
fmt
[]
=
"%-15s-> %s
\n
"
;
mbstate_t
state
;
memset
(
&
state
,
0
,
sizeof
(
mbstate_t
));
if
(
val
!=
NULL
)
switch
(
ntype
)
{
case
XK_STR
:
case
XK_EXE
:
(
void
)
keymacro__decode_str
(
val
->
str
,
unparsbuf
,
sizeof
(
unparsbuf
),
ntype
==
XK_STR
?
"
\"\"
"
:
"[]"
);
(
void
)
fprintf
(
el
->
el_outfile
,
fmt
,
ct_encode_string
(
key
,
&
el
->
el_scratch
),
unparsbuf
);
break
;
case
XK_CMD
:
for
(
fp
=
el
->
el_map
.
help
;
fp
->
name
;
fp
++
)
if
(
val
->
cmd
==
fp
->
func
)
{
memset
(
&
state
,
0
,
sizeof
(
mbstate_t
));
wcsrtombs
(
unparsbuf
,
(
const
wchar_t
**
)
&
fp
->
name
,
sizeof
(
unparsbuf
),
&
state
);
unparsbuf
[
sizeof
(
unparsbuf
)
-
1
]
=
'\0'
;
(
void
)
fprintf
(
el
->
el_outfile
,
fmt
,
ct_encode_string
(
key
,
&
el
->
el_scratch
),
unparsbuf
);
break
;
}
#ifdef DEBUG_KEY
if
(
fp
->
name
==
NULL
)
(
void
)
fprintf
(
el
->
el_outfile
,
"BUG! Command not found.
\n
"
);
#endif
break
;
default:
EL_ABORT
((
el
->
el_errfile
,
"Bad XK_ type %d
\n
"
,
ntype
));
break
;
}
else
(
void
)
fprintf
(
el
->
el_outfile
,
fmt
,
ct_encode_string
(
key
,
&
el
->
el_scratch
),
"no input"
);
}
#define ADDC(c) \
if (b < eb) \
*b++ = c; \
else \
b++
/* keymacro__decode_str():
* Make a printable version of the ey
*/
protected
size_t
keymacro__decode_str
(
const
Char
*
str
,
char
*
buf
,
size_t
len
,
const
char
*
sep
)
{
char
*
b
=
buf
,
*
eb
=
b
+
len
;
const
Char
*
p
;
mbstate_t
state
;
memset
(
&
state
,
0
,
sizeof
(
mbstate_t
));
b
=
buf
;
if
(
sep
[
0
]
!=
'\0'
)
{
ADDC
(
sep
[
0
]);
}
if
(
*
str
==
'\0'
)
{
ADDC
(
'^'
);
ADDC
(
'@'
);
goto
add_endsep
;
}
for
(
p
=
str
;
*
p
!=
0
;
p
++
)
{
Char
dbuf
[
VISUAL_WIDTH_MAX
];
Char
*
p2
=
dbuf
;
ssize_t
l
=
ct_visual_char
(
dbuf
,
VISUAL_WIDTH_MAX
,
*
p
);
while
(
l
--
>
0
)
{
ssize_t
n
=
ct_encode_char
(
b
,
(
size_t
)(
eb
-
b
),
*
p2
++
,
&
state
);
if
(
n
==
-
1
)
/* ran out of space */
goto
add_endsep
;
else
b
+=
n
;
}
}
add_endsep:
if
(
sep
[
0
]
!=
'\0'
&&
sep
[
1
]
!=
'\0'
)
{
ADDC
(
sep
[
1
]);
}
ADDC
(
'\0'
);
if
((
size_t
)(
b
-
buf
)
>=
len
)
buf
[
len
-
1
]
=
'\0'
;
return
(
size_t
)(
b
-
buf
);
}
cmd-line-utils/libedit/keymacro.h
0 → 100644
View file @
28192e02
/* $NetBSD: keymacro.h,v 1.2 2011/07/28 03:44:36 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)key.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.keymacro.h: Key macro header
*/
#ifndef _h_el_keymacro
#define _h_el_keymacro
typedef
union
keymacro_value_t
{
el_action_t
cmd
;
/* If it is a command the # */
Char
*
str
;
/* If it is a string... */
}
keymacro_value_t
;
typedef
struct
keymacro_node_t
keymacro_node_t
;
typedef
struct
el_keymacromacro_t
{
Char
*
buf
;
/* Key print buffer */
keymacro_node_t
*
map
;
/* Key map */
keymacro_value_t
val
;
/* Local conversion buffer */
}
el_keymacro_t
;
#define XK_CMD 0
#define XK_STR 1
#define XK_NOD 2
#define XK_EXE 3
protected
int
keymacro_init
(
EditLine
*
);
protected
void
keymacro_end
(
EditLine
*
);
protected
keymacro_value_t
*
keymacro_map_cmd
(
EditLine
*
,
int
);
protected
keymacro_value_t
*
keymacro_map_str
(
EditLine
*
,
Char
*
);
protected
void
keymacro_reset
(
EditLine
*
);
protected
int
keymacro_get
(
EditLine
*
,
Char
*
,
keymacro_value_t
*
);
protected
void
keymacro_add
(
EditLine
*
,
const
Char
*
,
keymacro_value_t
*
,
int
);
protected
void
keymacro_clear
(
EditLine
*
,
el_action_t
*
,
const
Char
*
);
protected
int
keymacro_delete
(
EditLine
*
,
const
Char
*
);
protected
void
keymacro_print
(
EditLine
*
,
const
Char
*
);
protected
void
keymacro_kprint
(
EditLine
*
,
const
Char
*
,
keymacro_value_t
*
,
int
);
protected
size_t
keymacro__decode_str
(
const
Char
*
,
char
*
,
size_t
,
const
char
*
);
#endif
/* _h_el_keymacro */
cmd-line-utils/libedit/makelist.sh
0 → 100644
View file @
28192e02
#!/bin/sh -
# $NetBSD: makelist,v 1.16 2010/04/18 21:17:05 christos Exp $
#
# Copyright (c) 1992, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Christos Zoulas of Cornell University.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)makelist 5.3 (Berkeley) 6/4/93
# makelist.sh: Automatically generate header files...
AWK
=
@AWK@
USAGE
=
"Usage:
$0
-n|-h|-e|-fc|-fh|-bc|-bh|-m <filenames>"
if
[
"x
$1
"
=
"x"
]
then
echo
$USAGE
1>&2
exit
1
fi
FLAG
=
"
$1
"
shift
FILES
=
"
$@
"
case
$FLAG
in
# generate foo.h file from foo.c
#
-n
)
cat
<<
_EOF
#undef WIDECHAR
#define NARROWCHAR
#include "
${
FILES
}
"
_EOF
;;
-h
)
set
-
`
echo
$FILES
|
sed
-e
's/\\./_/g'
`
hdr
=
"_h_
`
basename
$1
`
"
cat
$FILES
|
$AWK
'
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#ifndef %s\n#define %s\n", "'
$hdr
'", "'
$hdr
'");
}
/\(\):/ {
pr = substr($2, 1, 2);
if (pr == "vi" || pr == "em" || pr == "ed") {
# XXXMYSQL: support CRLF
name = substr($2, 1, index($2,"(") - 1);
#
# XXX: need a space between name and prototype so that -fc and -fh
# parsing is much easier
#
printf("protected el_action_t\t%s (EditLine *, Int);\n", name);
}
}
END {
printf("#endif /* %s */\n", "'
$hdr
'");
}'
;;
# generate help.c from various .c files
#
-bc
)
cat
$FILES
|
$AWK
'
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#include \"config.h\"\n#include \"el.h\"\n");
printf("#include \"chartype.h\"\n");
printf("private const struct el_bindings_t el_func_help[] = {\n");
low = "abcdefghijklmnopqrstuvwxyz_";
high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
for (i = 1; i <= length(low); i++)
tr[substr(low, i, 1)] = substr(high, i, 1);
}
/\(\):/ {
pr = substr($2, 1, 2);
if (pr == "vi" || pr == "em" || pr == "ed") {
# XXXMYSQL: support CRLF
name = substr($2, 1, index($2,"(") - 1);
uname = "";
fname = "";
for (i = 1; i <= length(name); i++) {
s = substr(name, i, 1);
uname = uname tr[s];
if (s == "_")
s = "-";
fname = fname s;
}
printf(" { %-30.30s %-30.30s\n","STR(\"" fname "\"),", uname ",");
ok = 1;
}
}
/^ \*/ {
if (ok) {
printf(" STR(\"");
for (i = 2; i < NF; i++)
printf("%s ", $i);
# XXXMYSQL: support CRLF
sub("\r", "", $i);
printf("%s\") },\n", $i);
ok = 0;
}
}
END {
printf("};\n");
printf("\nprotected const el_bindings_t* help__get()");
printf("{ return el_func_help; }\n");
}'
;;
# generate help.h from various .c files
#
-bh
)
$AWK
'
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#ifndef _h_help_c\n#define _h_help_c\n");
printf("protected const el_bindings_t *help__get(void);\n");
printf("#endif /* _h_help_c */\n");
}'
/dev/null
;;
# generate fcns.h from various .h files
#
# XXXMYSQL: use portable tr syntax
-fh
)
cat
$FILES
|
$AWK
'/el_action_t/ { print $3 }'
|
\
sort
|
tr
abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ |
$AWK
'
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#ifndef _h_fcns_c\n#define _h_fcns_c\n");
count = 0;
}
{
printf("#define\t%-30.30s\t%3d\n", $1, count++);
}
END {
printf("#define\t%-30.30s\t%3d\n", "EL_NUM_FCNS", count);
printf("typedef el_action_t (*el_func_t)(EditLine *, Int);");
printf("\nprotected const el_func_t* func__get(void);\n");
printf("#endif /* _h_fcns_c */\n");
}'
;;
# generate fcns.c from various .h files
#
-fc
)
cat
$FILES
|
$AWK
'/el_action_t/ { print $3 }'
|
sort
|
$AWK
'
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#include \"config.h\"\n#include \"el.h\"\n");
printf("private const el_func_t el_func[] = {");
maxlen = 80;
needn = 1;
len = 0;
}
{
clen = 25 + 2;
len += clen;
if (len >= maxlen)
needn = 1;
if (needn) {
printf("\n ");
needn = 0;
len = 4 + clen;
}
s = $1 ",";
printf("%-26.26s ", s);
}
END {
printf("\n};\n");
printf("\nprotected const el_func_t* func__get() { return el_func; }\n");
}'
;;
# generate editline.c from various .c files
#
-e
)
echo
"
$FILES
"
|
tr
' '
'\012'
|
$AWK
'
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#define protected static\n");
printf("#define SCCSID\n");
}
{
printf("#include \"%s\"\n", $1);
}'
;;
# generate man page fragment from various .c files
#
-m
)
cat
$FILES
|
$AWK
'
BEGIN {
printf(".\\\" Section automatically generated with makelist\n");
printf(".Bl -tag -width 4n\n");
}
/\(\):/ {
pr = substr($2, 1, 2);
if (pr == "vi" || pr == "em" || pr == "ed") {
# XXXMYSQL: support CRLF
name = substr($2, 1, index($2, "(") - 1);
fname = "";
for (i = 1; i <= length(name); i++) {
s = substr(name, i, 1);
if (s == "_")
s = "-";
fname = fname s;
}
printf(".It Ic %s\n", fname);
ok = 1;
}
}
/^ \*/ {
if (ok) {
for (i = 2; i < NF; i++)
printf("%s ", $i);
printf("%s.\n", $i);
ok = 0;
}
}
END {
printf(".El\n");
printf(".\\\" End of section automatically generated with makelist\n");
}'
;;
*
)
echo
$USAGE
1>&2
exit
1
;;
esac
Prev
1
…
6
7
8
9
10
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment