mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
updated for version 7.0001
This commit is contained in:
37
runtime/tools/README.txt
Normal file
37
runtime/tools/README.txt
Normal file
@@ -0,0 +1,37 @@
|
||||
Some tools that can be used with Vim:
|
||||
|
||||
blink.c: C program to make the cursor blink in an xterm.
|
||||
|
||||
ccfilter*: C program to filter the output of a few compilers to a common
|
||||
QuickFix format.
|
||||
|
||||
efm_filter.*: Perl script to filter compiler messages to QuickFix format.
|
||||
|
||||
efm_perl.pl: Perl script to filter error messages from the Perl interpreter
|
||||
for use with Vim quickfix mode.
|
||||
|
||||
mve.* Awk script to filter error messages to QuickFix format.
|
||||
|
||||
pltags.pl: Perl script to create a tags file from Perl scripts.
|
||||
|
||||
ref: Shell script for the K command.
|
||||
|
||||
shtags.*: Perl script to create a tags file from a shell script.
|
||||
|
||||
tcltags: Shell + Awk script to create a tags file from a TCL file.
|
||||
|
||||
vim132: Shell script to edit in 132 column mode on vt100 compatible
|
||||
terminals.
|
||||
|
||||
vimm: Shell script to start Vim on a DEC terminal with mouse
|
||||
enabled.
|
||||
|
||||
vimspell.*: Shell script for highlighting spelling mistakes.
|
||||
|
||||
vim_vs_net.cmd: MS-Windows command file to use Vim with MS Visual Studio 7 and
|
||||
later.
|
||||
|
||||
xcmdsrv_client.c: Example for a client program that communicates with a Vim
|
||||
server through the X-Windows interface.
|
||||
|
||||
[xxd (and tee for OS/2) can be found in the src directory]
|
21
runtime/tools/blink.c
Normal file
21
runtime/tools/blink.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* An extremely simple program to make the cursor blink in an xterm.
|
||||
* This is useful when the cursor is hard to spot in a highlighted file.
|
||||
* Start in the background: "blink&" Stop by killing it.
|
||||
* Bram Moolenaar 980109 (based on an idea from John Lange).
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
main()
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
printf("\e[?25h");
|
||||
fflush(stdout);
|
||||
usleep(400000); /* on time */
|
||||
printf("\e[?25l");
|
||||
fflush(stdout);
|
||||
usleep(250000); /* off time */
|
||||
}
|
||||
}
|
93
runtime/tools/ccfilter.1
Normal file
93
runtime/tools/ccfilter.1
Normal file
@@ -0,0 +1,93 @@
|
||||
.TH ccfilter 1 "01-Apr-97"
|
||||
.SH NAME
|
||||
ccfilter \- a compiler's output filter for vim quickfix
|
||||
.SH SYNOPSIS
|
||||
ccfilter [
|
||||
.B <options>
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
The ccfilter utility "filters" the output of several compilers
|
||||
and makers (make/gmake) from several platforms (see NOTES below)
|
||||
to a standardized format which easily fits in vim's quickfix
|
||||
feature. For further details, see in vim ":help quickfix".
|
||||
.PP
|
||||
ccfilter reads
|
||||
.B 'stdin'
|
||||
and outputs to
|
||||
.B 'stdout'
|
||||
\.
|
||||
.PP
|
||||
The need for ccfilter is clear, as some compilers have irregular
|
||||
and/or multiple line error messages (with the relevant information on
|
||||
line 2), which makes it impossible for the errorformat to correctly
|
||||
display them !
|
||||
|
||||
When working on different platforms, and with different compilers,
|
||||
ccfilter eases the utilization of quickfix, due to it's standardized
|
||||
output, allowing to have in .vimrc a plain
|
||||
.br
|
||||
.B \ \ \ \ :set\ errorformat=%f:%l:%c:%t:%m
|
||||
|
||||
.SH USAGE
|
||||
When using ccfilter, one would include the following lines in .vimrc:
|
||||
.br
|
||||
.B \ \ \ \ :set shellpipe=\\\\|&ccfilter\\\\>
|
||||
.br
|
||||
.B \ \ \ \ :set errorformat=%f:%l:%c:%t:%m
|
||||
|
||||
.SH OPTIONS
|
||||
.TP 16
|
||||
-c
|
||||
Decrement column by one. This may be needed, depending on
|
||||
the compiler being used.
|
||||
.TP
|
||||
-r
|
||||
Decrement row by one. This may be needed, depending on
|
||||
the compiler being used.
|
||||
.TP
|
||||
-v
|
||||
Verbose (Outputs also invalid lines).
|
||||
This option makes ccfilter output also the lines that
|
||||
couldn't be correctly parsed. This is used mostly for
|
||||
ccfilter debugging.
|
||||
.TP
|
||||
-o <COMPILER>
|
||||
Treat input as <COMPILER>'s output.
|
||||
Even when configuring ccfilter to assume a default
|
||||
COMPILER, sometimes it's helpful to be able to specify
|
||||
the COMPILER used to generate ccfilter's input.
|
||||
For example, when cross-compiling on a network from a
|
||||
single machine.
|
||||
.TP
|
||||
-h
|
||||
Shows a brief help, describing the configured default COMPILER
|
||||
and the valid parameters for COMPILER.
|
||||
|
||||
.SH NOTES
|
||||
Currently, ccfilter accepts output from several compilers, as
|
||||
described below:
|
||||
.TP 10
|
||||
GCC
|
||||
GCC compiler
|
||||
.TP
|
||||
AIX
|
||||
AIX's C compiler
|
||||
.TP
|
||||
ATT
|
||||
AT&T/NCR's High Performance C Compiler
|
||||
.TP
|
||||
IRIX
|
||||
IRIX's MIPS/MIPSpro C compiler
|
||||
.TP
|
||||
SOLARIS
|
||||
SOLARIS's SparcWorks C compiler
|
||||
.TP
|
||||
HPUX
|
||||
HPUX's C compiler
|
||||
|
||||
.SH AUTHOR
|
||||
.B ccfilter
|
||||
was developed by
|
||||
.B Pablo Ariel Kohan
|
||||
.BR
|
||||
.B mailto:pablo@memco.co.il
|
326
runtime/tools/ccfilter.c
Normal file
326
runtime/tools/ccfilter.c
Normal file
@@ -0,0 +1,326 @@
|
||||
/* ======================================================================= */
|
||||
/* Project : VIM */
|
||||
/* Module : ccfilter Version: 02.01.01 */
|
||||
/* File : ccfilter.c */
|
||||
/* Purpose : Filter gmake/cc output into a standardized form */
|
||||
/* ======================================================================= */
|
||||
/* Created On: 12-Sep-95 20:32 */
|
||||
/* Last modification: 03-Feb-98 */
|
||||
/* -e option added by Bernd Feige */
|
||||
/* ======================================================================= */
|
||||
/* Copyright : */
|
||||
/* This source file is copyright (c) to Pablo Ariel Kohan */
|
||||
/* ======================================================================= */
|
||||
#define __CCFILTER_C__
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define LINELENGTH 2048
|
||||
|
||||
/* Collector(s) */
|
||||
char Line[LINELENGTH];
|
||||
char Line2[LINELENGTH];
|
||||
/* Components */
|
||||
char FileName[1024];
|
||||
char BasePath[1024];
|
||||
char CWD[1024];
|
||||
unsigned long Row;
|
||||
unsigned long Col;
|
||||
char Severity;
|
||||
char Reason[LINELENGTH];
|
||||
|
||||
#define COMPILER_UNKNOWN 0
|
||||
#define COMPILER_GCC 1
|
||||
#define COMPILER_AIX 2
|
||||
#define COMPILER_ATT 3
|
||||
#define COMPILER_IRIX 4
|
||||
#define COMPILER_SOLARIS 5
|
||||
#define COMPILER_HPUX 6
|
||||
|
||||
char *COMPILER_Names[][2] =
|
||||
{
|
||||
/* Name Description */
|
||||
{ "N/A", "" },
|
||||
{ "GCC", "GCC compiler" },
|
||||
{ "AIX", "AIX's C compiler" },
|
||||
{ "ATT", "AT&T/NCR's High Performance C Compiler" },
|
||||
{ "IRIX", "IRIX's MIPS/MIPSpro C compiler" },
|
||||
{ "SOLARIS", "SOLARIS's SparcWorks C compiler" },
|
||||
{ "HPUX", "HPUX's C compiler" }
|
||||
};
|
||||
#define COMPILER_QTY (sizeof(COMPILER_Names)/sizeof(COMPILER_Names[0]))
|
||||
|
||||
#if defined(_GCC)
|
||||
# define COMPILER_DEFAULT COMPILER_GCC
|
||||
#elif defined(_AIX)
|
||||
# define COMPILER_DEFAULT COMPILER_AIX
|
||||
#elif defined(_ATT)
|
||||
# define COMPILER_DEFAULT COMPILER_ATT
|
||||
#elif defined(_IRIX)
|
||||
# define COMPILER_DEFAULT COMPILER_IRIX
|
||||
#elif defined(_SOLARIS)
|
||||
# define COMPILER_DEFAULT COMPILER_SOLARIS
|
||||
#elif defined(_HPUX)
|
||||
# define COMPILER_DEFAULT COMPILER_HPUX
|
||||
#else
|
||||
# define COMPILER_DEFAULT COMPILER_UNKNOWN
|
||||
#endif
|
||||
|
||||
const char USAGE[] =
|
||||
"ccfilter v2.1 (c)1994-1997 by Pablo Ariel Kohan\n"
|
||||
"Filter Out compiler's output, and converts it to fit VIM\n\n"
|
||||
"Usage:\n"
|
||||
" ccfilter [<options>]\n"
|
||||
"Where: <options> is one or more of:\n"
|
||||
" -c Decrement column by one\n"
|
||||
" -r Decrement row by one\n"
|
||||
" -e Echo stdin to stderr\n"
|
||||
" -v Verbose (Outputs also invalid lines)\n"
|
||||
" -o <COMPILER> Treat input as <COMPILER>'s output\n"
|
||||
" Note: COMPILER may be preceded by an _\n"
|
||||
" -h This usage.\n";
|
||||
|
||||
|
||||
int ShowUsage( char *szError )
|
||||
{ int i;
|
||||
|
||||
fprintf( stderr, USAGE );
|
||||
|
||||
fprintf( stderr, "Current default <COMPILER>: %s\n",
|
||||
COMPILER_Names[COMPILER_DEFAULT][0] );
|
||||
|
||||
fprintf( stderr, "Acceptable parameters for <COMPILER> are:\n" );
|
||||
for (i=1; i < COMPILER_QTY; i++)
|
||||
fprintf( stderr, " %-15.15s %s\n",
|
||||
COMPILER_Names[i][0],
|
||||
COMPILER_Names[i][1] );
|
||||
fprintf(stderr, szError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *echogets(char *s, int echo) {
|
||||
char * const retval=fgets(s, LINELENGTH, stdin);
|
||||
if (echo!=0 && retval!=NULL) {
|
||||
fputs(retval, stderr);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{ int rv, i, j, ok;
|
||||
int stay;
|
||||
int prefetch;
|
||||
char *p;
|
||||
int dec_col = 0; /* Decrement column value by 1 */
|
||||
int dec_row = 0; /* Decrement row value by 1 */
|
||||
int echo = 0; /* Echo stdin to stderr */
|
||||
int verbose = 0; /* Include Bad Formatted Lines */
|
||||
int CWDlen;
|
||||
int COMPILER = COMPILER_DEFAULT;
|
||||
|
||||
getcwd( CWD, sizeof(CWD) );
|
||||
CWDlen = strlen(CWD);
|
||||
|
||||
for (i=1; i<argc; i++)
|
||||
{
|
||||
if (argv[i][0] != '-')
|
||||
return ShowUsage("");
|
||||
switch ( argv[i][1] )
|
||||
{
|
||||
case 'c':
|
||||
dec_col = 1;
|
||||
break;
|
||||
case 'r':
|
||||
dec_row = 1;
|
||||
break;
|
||||
case 'e':
|
||||
echo = 1;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'o':
|
||||
{
|
||||
if (i+1 >= argc)
|
||||
return ShowUsage("Error: Missing parameter for -o\n");
|
||||
i++;
|
||||
COMPILER = -1;
|
||||
for (j=1; j<COMPILER_QTY; j++)
|
||||
if ( (strcmp(argv[i], COMPILER_Names[j][0]) == 0) ||
|
||||
( (argv[i][0] == '_') &&
|
||||
(strcmp(&argv[i][1], COMPILER_Names[j][0]) == 0) ) )
|
||||
COMPILER = j;
|
||||
if (COMPILER == -1)
|
||||
return ShowUsage("Error: Invalid COMPILER specified\n");
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
return ShowUsage("");
|
||||
default:
|
||||
return ShowUsage("Error: Invalid option\n");
|
||||
}
|
||||
}
|
||||
if (COMPILER == 0)
|
||||
return ShowUsage("Error: COMPILER must be specified in this system\n");
|
||||
|
||||
stay = ( echogets(Line, echo) != NULL );
|
||||
prefetch = 0;
|
||||
|
||||
while( stay )
|
||||
{
|
||||
*FileName = 0;
|
||||
Row = 0;
|
||||
Col = 0;
|
||||
Severity = ' ';
|
||||
*Reason = 0;
|
||||
ok = 0;
|
||||
switch (COMPILER)
|
||||
{
|
||||
case COMPILER_GCC:
|
||||
Severity = 'e';
|
||||
#ifdef GOTO_FROM_WHERE_INCLUDED
|
||||
rv = sscanf( Line, "In file included from %[^:]:%u:",
|
||||
FileName, &Row );
|
||||
if ( rv == 2 )
|
||||
{
|
||||
ok = (echogets(Reason, echo) != NULL);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if ((rv = sscanf( Line, "%[^:]:%u: warning: %[^\n]",
|
||||
FileName, &Row, Reason ))==3) {
|
||||
Severity = 'w';
|
||||
} else {
|
||||
rv = sscanf( Line, "%[^:]:%u: %[^\n]",
|
||||
FileName, &Row, Reason );
|
||||
}
|
||||
ok = ( rv == 3 );
|
||||
}
|
||||
Col = (dec_col ? 1 : 0 );
|
||||
break;
|
||||
case COMPILER_AIX:
|
||||
rv = sscanf( Line, "\"%[^\"]\", line %u.%u: %*s (%c) %[^\n]",
|
||||
FileName, &Row, &Col, &Severity, Reason );
|
||||
ok = ( rv == 5 );
|
||||
break;
|
||||
case COMPILER_HPUX:
|
||||
rv = sscanf( Line, "cc: \"%[^\"]\", line %u: %c%*[^:]: %[^\n]",
|
||||
FileName, &Row, &Severity, Reason );
|
||||
ok = ( rv == 4 );
|
||||
Col = (dec_col ? 1 : 0 );
|
||||
break;
|
||||
case COMPILER_SOLARIS:
|
||||
rv = sscanf( Line, "\"%[^\"]\", line %u: warning: %[^\n]",
|
||||
FileName, &Row, Reason );
|
||||
Severity = 'w';
|
||||
ok = ( rv == 3 );
|
||||
if ( rv != 3 )
|
||||
{
|
||||
rv = sscanf( Line, "\"%[^\"]\", line %u: %[^\n]",
|
||||
FileName, &Row, Reason );
|
||||
Severity = 'e';
|
||||
ok = ( rv == 3 );
|
||||
}
|
||||
Col = (dec_col ? 1 : 0 );
|
||||
break;
|
||||
case COMPILER_ATT:
|
||||
rv = sscanf( Line, "%c \"%[^\"]\",L%u/C%u%*[^:]:%[^\n]",
|
||||
&Severity, FileName, &Row, &Col, Reason );
|
||||
ok = ( rv == 5 );
|
||||
|
||||
if (rv != 5)
|
||||
{ rv = sscanf( Line, "%c \"%[^\"]\",L%u/C%u: %[^\n]",
|
||||
&Severity, FileName, &Row, &Col, Reason );
|
||||
ok = ( rv == 5 );
|
||||
}
|
||||
|
||||
if (rv != 5)
|
||||
{ rv = sscanf( Line, "%c \"%[^\"]\",L%u: %[^\n]",
|
||||
&Severity, FileName, &Row, Reason );
|
||||
ok = ( rv == 4 );
|
||||
Col = (dec_col ? 1 : 0 );
|
||||
}
|
||||
|
||||
stay = (echogets(Line2, echo) != NULL);
|
||||
while ( stay && (Line2[0] == '|') )
|
||||
{ for (p=&Line2[2]; (*p) && (isspace(*p)); p++);
|
||||
strcat( Reason, ": " );
|
||||
strcat( Reason, p );
|
||||
Line2[0] = 0;
|
||||
stay = (echogets(Line2, echo) != NULL);
|
||||
}
|
||||
prefetch = 1;
|
||||
strcpy( Line, Line2 );
|
||||
break;
|
||||
case COMPILER_IRIX:
|
||||
Col = 1;
|
||||
prefetch = 0;
|
||||
rv = 0;
|
||||
ok = 0;
|
||||
if ( !strncmp(Line, "cfe: ", 5) )
|
||||
{ p = &Line[5];
|
||||
Severity = tolower(*p);
|
||||
p = strchr( &Line[5], ':' );
|
||||
if (p == NULL)
|
||||
{ ok = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = sscanf( p+2, "%[^:]: %u: %[^\n]",
|
||||
FileName, &Row, Reason );
|
||||
if (rv != 3)
|
||||
rv = sscanf( p+2, "%[^,], line %u: %[^\n]",
|
||||
FileName, &Row, Reason );
|
||||
ok = ( rv == 3 );
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{ prefetch = 1;
|
||||
stay = (echogets(Line, echo) != NULL);
|
||||
if (Line[0] == ' ')
|
||||
stay = (echogets(Line2, echo) != NULL);
|
||||
if ( (Line2[0] == ' ') &&
|
||||
( (Line2[1] == '-') || (Line2[1] == '^') ) )
|
||||
{ Col = strlen(Line2)-1;
|
||||
prefetch = 0;
|
||||
}
|
||||
else
|
||||
{ strcat( Line, "\n" );
|
||||
strcat( Line, Line2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (dec_col) Col--;
|
||||
if (dec_row) Row--;
|
||||
if (!ok)
|
||||
{
|
||||
if ( Line[0] == 'g' )
|
||||
p = &Line[1];
|
||||
else
|
||||
p = &Line[0];
|
||||
ok = sscanf( p, "make[%*d]: Entering directory `%[^']",
|
||||
BasePath );
|
||||
if (verbose)
|
||||
printf( "[%u]?%s\n", ok, Line );
|
||||
}
|
||||
else
|
||||
{
|
||||
for (p=Reason; (*p) && (isspace(*p)); p++);
|
||||
if ( BasePath[CWDlen] == 0 )
|
||||
printf( "%s:%u:%u:%c:%s\n", FileName, Row, Col, Severity, p );
|
||||
else
|
||||
{
|
||||
printf( "%s/%s:%u:%u:%c:%s\n", &BasePath[CWDlen+1], FileName, Row, Col, Severity, p );
|
||||
}
|
||||
}
|
||||
if (!prefetch)
|
||||
stay = ( echogets(Line, echo) != NULL );
|
||||
}
|
||||
return 0;
|
||||
}
|
91
runtime/tools/ccfilter_README.txt
Normal file
91
runtime/tools/ccfilter_README.txt
Normal file
@@ -0,0 +1,91 @@
|
||||
COMPILING AND INSTALLING:
|
||||
=========================
|
||||
|
||||
To compile ccfilter, you can just do a plain:
|
||||
cc ccfilter.c -o ccfilter
|
||||
Though, it may be wise to have your default compiler defined,
|
||||
so you would normally compile it with one of the following:
|
||||
cc -D_GCC ccfilter.c -o ccfilter
|
||||
cc -D_AIX ccfilter.c -o ccfilter
|
||||
cc -D_ATT ccfilter.c -o ccfilter
|
||||
cc -D_IRIX ccfilter.c -o ccfilter
|
||||
cc -D_SOLARIS ccfilter.c -o ccfilter
|
||||
cc -D_HPUX ccfilter.c -o ccfilter
|
||||
You can then copy ccfilter to it's target destination (i.e: /usr/local/bin).
|
||||
The man page ccfilter.1 has to be copied to somewhere in your MANPATH,
|
||||
under a man1 directory (i.e: /usr/local/man/man1).
|
||||
|
||||
|
||||
SUPPORTED COMPILERS/PORTING NOTES:
|
||||
==================================
|
||||
|
||||
The supported formats for the different compilers are described below:
|
||||
In this section, meta-names are used as place-holders in the line
|
||||
formats: <FILE> <ROW> <COL> <SEVERITY> <REASON> <>
|
||||
The <> denotes ignored text.
|
||||
Line formats are delimited by the ^ (caret) symbol.
|
||||
|
||||
0) Special case: "gmake directory change" lines:
|
||||
Lines with a format like:
|
||||
^gmake[<NUM>]: Entering directory `<DIR>'^
|
||||
are used to follow the directory changes during the make process,
|
||||
providing in the <FILE> part, a relative (if possible) directory
|
||||
path to the erroneous file.
|
||||
|
||||
|
||||
1) GCC:
|
||||
Recognized lines are of the format:
|
||||
- ^In file included from <FILE>:<ROW>:^
|
||||
Line following this one is used as <REASON>
|
||||
<SEVERITY> is always 'e' (error)
|
||||
<COL> is always '0'
|
||||
|
||||
- ^<FILE>:<ROW>:<REASON>^
|
||||
<SEVERITY> is always 'e' (error)
|
||||
<COL> is always '0'
|
||||
|
||||
|
||||
2) AIX:
|
||||
Recognized lines are of the format:
|
||||
- ^"<FILE>", line <ROW>.<COL>: <> (<SEVERITY>) <REASON>",
|
||||
|
||||
|
||||
3) HPUX:
|
||||
Recognized lines are of the format:
|
||||
- ^cc: "<FILE>", line <ROW>: <SEVERITY>: <REASON>^
|
||||
<COL> is always '0'
|
||||
|
||||
|
||||
4) SOLARIS:
|
||||
Recognized lines are of the format:
|
||||
- ^"<FILE>", line <ROW>: warning: <REASON>^
|
||||
This assumes <SEVERITY> is "W"
|
||||
<COL> is always '0'
|
||||
|
||||
- ^"<FILE>", line <ROW>: <REASON>^
|
||||
This assumes <SEVERITY> is "E"
|
||||
<COL> is always '0'
|
||||
|
||||
|
||||
5) ATT / NCR:
|
||||
Recognized lines are of the format:
|
||||
- ^<SEVERITY> "<FILE>",L<ROW>/C<COL><>:<REASON>^
|
||||
or
|
||||
- ^<SEVERITY> "<FILE>",L<ROW>/C<COL>:<REASON>^
|
||||
Following lines beginning with a pipe (|) are continuation
|
||||
lines, and are therefore appended to the <REASON>
|
||||
|
||||
- ^<SEVERITY> "<FILE>",L<ROW>:<REASON>^
|
||||
<COL> is '0'
|
||||
Following lines beginning with a pipe (|) are continuation
|
||||
lines, and are therefore appended to the <REASON>
|
||||
|
||||
|
||||
6) SGI-IRIX:
|
||||
Recognized lines are of the format:
|
||||
- ^cfe: <SEVERITY>: <FILE>: <ROW>: <REASON>^
|
||||
or
|
||||
^cfe: <SEVERITY>: <FILE>, line <ROW>: <REASON>^
|
||||
Following lines beginning with a dash (-) are "column-bar"
|
||||
that end with a caret in the column of the error. These lines
|
||||
are analyzed to generate the <COL>.
|
39
runtime/tools/efm_filter.pl
Executable file
39
runtime/tools/efm_filter.pl
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env perl
|
||||
#
|
||||
# This program works as a filter that reads from stdin, copies to
|
||||
# stdout *and* creates an error file that can be read by vim.
|
||||
#
|
||||
# This program has only been tested on SGI, Irix5.3.
|
||||
#
|
||||
# Written by Ives Aerts in 1996. This little program is not guaranteed
|
||||
# to do (or not do) anything at all and can be freely used for
|
||||
# whatever purpose you can think of.
|
||||
|
||||
$args = @ARGV;
|
||||
|
||||
unless ($args == 1) {
|
||||
die("Usage: vimccparse <output filename>\n");
|
||||
}
|
||||
|
||||
$filename = @ARGV[0];
|
||||
open (OUT, ">$filename") || die ("Can't open file: \"$filename\"");
|
||||
|
||||
while (<STDIN>) {
|
||||
print;
|
||||
if ( (/"(.*)", line (\d+): (e)rror\((\d+)\):/)
|
||||
|| (/"(.*)", line (\d+): (w)arning\((\d+)\):/) ) {
|
||||
$file=$1;
|
||||
$line=$2;
|
||||
$errortype="\u$3";
|
||||
$errornr=$4;
|
||||
chop($errormsg=<STDIN>);
|
||||
$errormsg =~ s/^\s*//;
|
||||
$sourceline=<STDIN>;
|
||||
$column=index(<STDIN>, "^") - 1;
|
||||
|
||||
print OUT "$file>$line:$column:$errortype:$errornr:$errormsg\n";
|
||||
}
|
||||
}
|
||||
|
||||
close(OUT);
|
||||
exit(0);
|
31
runtime/tools/efm_filter.txt
Normal file
31
runtime/tools/efm_filter.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
[adopted from a message that Ives posted in the Vim mailing list]
|
||||
|
||||
Some compilers produce an error message that cannot be handled with
|
||||
'errorformat' in Vim. Following is an example of a Perl script that
|
||||
translates one error message into something that Vim understands.
|
||||
|
||||
|
||||
The compiler that generates this kind of error messages (4 lines):
|
||||
|
||||
"/tmp_mnt/cm/src/apertos/MoU/MetaCore/MetaCore/common/src/MetaCoreImp_M.cc",
|
||||
line 50: error(3114):
|
||||
identifier "PRIMITIVE_M" is undefined
|
||||
return(ExecuteCore(PRIMITIVE_M,
|
||||
|
||||
You can find a small perl program at the end.
|
||||
The way I use it is:
|
||||
|
||||
:set errorformat=%f>%l:%c:%t:%n:%m
|
||||
:set makeprg=clearmake\ -C\ gnu
|
||||
:set shellpipe=2>&1\|\ vimccparse
|
||||
|
||||
If somebody thinks this is useful: feel free to do whatever you can think
|
||||
of with this code.
|
||||
|
||||
-Ives
|
||||
____________________________________________________________
|
||||
Ives Aerts (SW Developer) Sony Telecom Europe
|
||||
ives@sonytel.be St.Stevens Woluwestr. 55
|
||||
`Death could create most things, B-1130 Brussels, Belgium
|
||||
except for plumbing.' PHONE : +32 2 724 19 67
|
||||
(Soul Music - T.Pratchett) FAX : +32 2 726 26 86
|
153
runtime/tools/efm_perl.pl
Executable file
153
runtime/tools/efm_perl.pl
Executable file
@@ -0,0 +1,153 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
# vimparse.pl - Reformats the error messages of the Perl interpreter for use
|
||||
# with the quickfix mode of Vim
|
||||
#
|
||||
# Copyright (<28>) 2001 by J<>rg Ziefle <joerg.ziefle@gmx.de>
|
||||
# You may use and distribute this software under the same terms as Perl itself.
|
||||
#
|
||||
# Usage: put one of the two configurations below in your ~/.vimrc (without the
|
||||
# description and '# ') and enjoy (be sure to adjust the paths to vimparse.pl
|
||||
# before):
|
||||
#
|
||||
# Program is run interactively with 'perl -w':
|
||||
#
|
||||
# set makeprg=$HOME/bin/vimparse.pl\ %\ $*
|
||||
# set errorformat=%f:%l:%m
|
||||
#
|
||||
# Program is only compiled with 'perl -wc':
|
||||
#
|
||||
# set makeprg=$HOME/bin/vimparse.pl\ -c\ %\ $*
|
||||
# set errorformat=%f:%l:%m
|
||||
#
|
||||
# Usage:
|
||||
# vimparse.pl [-c] [-f <errorfile>] <programfile> [programargs]
|
||||
#
|
||||
# -c compile only, don't run (perl -wc)
|
||||
# -f write errors to <errorfile>
|
||||
#
|
||||
# Example usages:
|
||||
# * From the command line:
|
||||
# vimparse.pl program.pl
|
||||
#
|
||||
# vimparse.pl -c -f errorfile program.pl
|
||||
# Then run vim -q errorfile to edit the errors with Vim.
|
||||
#
|
||||
# * From Vim:
|
||||
# Edit in Vim (and save, if you don't have autowrite on), then
|
||||
# type ':mak' or ':mak args' (args being the program arguments)
|
||||
# to error check.
|
||||
#
|
||||
# Version history:
|
||||
# 0.2 (04/12/2001):
|
||||
# * First public version (sent to Bram)
|
||||
# * -c command line option for compiling only
|
||||
# * grammatical fix: 'There was 1 error.'
|
||||
# * bug fix for multiple arguments
|
||||
# * more error checks
|
||||
# * documentation (top of file, &usage)
|
||||
# * minor code clean ups
|
||||
# 0.1 (02/02/2001):
|
||||
# * Initial version
|
||||
# * Basic functionality
|
||||
#
|
||||
# Todo:
|
||||
# * test on more systems
|
||||
# * use portable way to determine the location of perl ('use Config')
|
||||
# * include option that shows perldiag messages for each error
|
||||
# * allow to pass in program by STDIN
|
||||
# * more intuitive behaviour if no error is found (show message)
|
||||
#
|
||||
# Tested under SunOS 5.7 with Perl 5.6.0. Let me know if it's not working for
|
||||
# you.
|
||||
|
||||
use strict;
|
||||
use Getopt::Std;
|
||||
|
||||
use vars qw/$opt_c $opt_f $opt_h/; # needed for Getopt in combination with use strict 'vars'
|
||||
|
||||
use constant VERSION => 0.2;
|
||||
|
||||
getopts('cf:h');
|
||||
|
||||
&usage if $opt_h; # not necessarily needed, but good for further extension
|
||||
|
||||
if (defined $opt_f) {
|
||||
|
||||
open FILE, "> $opt_f" or do {
|
||||
warn "Couldn't open $opt_f: $!. Using STDOUT instead.\n";
|
||||
undef $opt_f;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
my $handle = (defined $opt_f ? \*FILE : \*STDOUT);
|
||||
|
||||
(my $file = shift) or &usage; # display usage if no filename is supplied
|
||||
my $args = (@ARGV ? ' ' . join ' ', @ARGV : '');
|
||||
|
||||
my @lines = `perl @{[defined $opt_c ? '-c ' : '' ]} -w "$file$args" 2>&1`;
|
||||
|
||||
my $errors = 0;
|
||||
foreach my $line (@lines) {
|
||||
|
||||
chomp($line);
|
||||
my ($file, $lineno, $message, $rest);
|
||||
|
||||
if ($line =~ /^(.*)\sat\s(.*)\sline\s(\d+)(\.|,\snear\s\".*\")$/) {
|
||||
|
||||
($message, $file, $lineno, $rest) = ($1, $2, $3, $4);
|
||||
$errors++;
|
||||
$message .= $rest if ($rest =~ s/^,//);
|
||||
print $handle "$file:$lineno:$message\n";
|
||||
|
||||
} else { next };
|
||||
|
||||
}
|
||||
|
||||
if (defined $opt_f) {
|
||||
|
||||
my $msg;
|
||||
if ($errors == 1) {
|
||||
|
||||
$msg = "There was 1 error.\n";
|
||||
|
||||
} else {
|
||||
|
||||
$msg = "There were $errors errors.\n";
|
||||
|
||||
};
|
||||
|
||||
print STDOUT $msg;
|
||||
close FILE;
|
||||
unlink $opt_f unless $errors;
|
||||
|
||||
};
|
||||
|
||||
sub usage {
|
||||
|
||||
(local $0 = $0) =~ s/^.*\/([^\/]+)$/$1/; # remove path from name of program
|
||||
print<<EOT;
|
||||
Usage:
|
||||
$0 [-c] [-f <errorfile>] <programfile> [programargs]
|
||||
|
||||
-c compile only, don't run (executes 'perl -wc')
|
||||
-f write errors to <errorfile>
|
||||
|
||||
Examples:
|
||||
* At the command line:
|
||||
$0 program.pl
|
||||
Displays output on STDOUT.
|
||||
|
||||
$0 -c -f errorfile program.pl
|
||||
Then run 'vim -q errorfile' to edit the errors with Vim.
|
||||
|
||||
* In Vim:
|
||||
Edit in Vim (and save, if you don't have autowrite on), then
|
||||
type ':mak' or ':mak args' (args being the program arguments)
|
||||
to error check.
|
||||
EOT
|
||||
|
||||
exit 0;
|
||||
|
||||
};
|
23
runtime/tools/mve.awk
Executable file
23
runtime/tools/mve.awk
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/nawk -f
|
||||
#
|
||||
# Change "nawk" to "awk" or "gawk" if you get errors.
|
||||
#
|
||||
# Make Vim Errors
|
||||
# Processes errors from cc for use by Vim's quick fix tools
|
||||
# specifically it translates the ---------^ notation to a
|
||||
# column number
|
||||
#
|
||||
BEGIN { FS="[:,]" }
|
||||
|
||||
/^cfe/ { file=$3
|
||||
msg=$5
|
||||
split($4,s," ")
|
||||
line=s[2]
|
||||
}
|
||||
|
||||
# You may have to substitute a tab character for the \t here:
|
||||
/^[\t-]*\^/ {
|
||||
p=match($0, ".*\\^" )
|
||||
col=RLENGTH-2
|
||||
printf("%s, line %d, col %d : %s\n", file,line,col,msg)
|
||||
}
|
20
runtime/tools/mve.txt
Normal file
20
runtime/tools/mve.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
[ The mve awk script was posted on the vimdev mailing list ]
|
||||
|
||||
From: jimmer@barney.mdhc.mdc.com (J. McGlasson)
|
||||
Date: Mon, 31 Mar 1997 13:16:49 -0700 (Mar)
|
||||
|
||||
My compiler (SGI MIPSpro C compiler - IRIX 6.4) works like this.
|
||||
I have written a script mve (make vim errors), through which I pipe my make
|
||||
output, which translates output of the following form:
|
||||
|
||||
cfe: Error: syntax.c, line 4: Syntax Error
|
||||
int i[12;
|
||||
------------^
|
||||
|
||||
into:
|
||||
|
||||
cl.c, line 4, col 12 : Syntax Error
|
||||
|
||||
(in vim notation: %f, line %l, col %c : %m)
|
||||
|
||||
You might be able to tailor this for your compiler's output.
|
300
runtime/tools/pltags.pl
Executable file
300
runtime/tools/pltags.pl
Executable file
@@ -0,0 +1,300 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
# pltags - create a tags file for Perl code, for use by vi(m)
|
||||
#
|
||||
# Distributed with Vim <http://www.vim.org/>, latest version always available
|
||||
# at <http://www.mscha.com/mscha.html?pltags#tools>
|
||||
#
|
||||
# Version 2.3, 28 February 2002
|
||||
#
|
||||
# Written by Michael Schaap <pltags@mscha.com>. Suggestions for improvement
|
||||
# are very welcome!
|
||||
#
|
||||
# This script will not work with Perl 4 or below!
|
||||
#
|
||||
# Revision history:
|
||||
# 1.0 1997? Original version, quickly hacked together
|
||||
# 2.0 1999? Completely rewritten, better structured and documented,
|
||||
# support for variables, packages, Exuberant Ctags extensions
|
||||
# 2.1 Jun 2000 Fixed critical bug (typo in comment) ;-)
|
||||
# Support multiple level packages (e.g. Archive::Zip::Member)
|
||||
# 2.2 Jul 2001 'Glob' wildcards - especially useful under Windows
|
||||
# (thanks to Serge Sivkov and Jason King)
|
||||
# Bug fix: reset package name for each file
|
||||
# 2.21 Jul 2001 Oops... bug in variable detection (/local../ -> /^local.../)
|
||||
# 2.3 Feb 2002 Support variables declared with "our"
|
||||
# (thanks to Lutz Mende)
|
||||
|
||||
# Complain about undeclared variables
|
||||
use strict;
|
||||
|
||||
# Used modules
|
||||
use Getopt::Long;
|
||||
|
||||
# Options with their defaults
|
||||
my $do_subs = 1; # --subs, --nosubs include subs in tags file?
|
||||
my $do_vars = 1; # --vars, --novars include variables in tags file?
|
||||
my $do_pkgs = 1; # --pkgs, --nopkgs include packages in tags file?
|
||||
my $do_exts = 1; # --extensions, --noextensions
|
||||
# include Exuberant Ctags extensions
|
||||
|
||||
# Global variables
|
||||
my $VERSION = "2.21"; # pltags version
|
||||
my $status = 0; # GetOptions return value
|
||||
my $file = ""; # File being processed
|
||||
my @tags = (); # List of produced tags
|
||||
my $is_pkg = 0; # Are we tagging a package?
|
||||
my $has_subs = 0; # Has this file any subs yet?
|
||||
my $package_name = ""; # Name of current package
|
||||
my $var_continues = 0; # Variable declaration continues on last line
|
||||
my $line = ""; # Current line in file
|
||||
my $stmt = ""; # Current Perl statement
|
||||
my @vars = (); # List of variables in declaration
|
||||
my $var = ""; # Variable in declaration
|
||||
my $tagline = ""; # Tag file line
|
||||
|
||||
# Create a tag file line and push it on the list of found tags
|
||||
sub MakeTag($$$$$)
|
||||
{
|
||||
my ($tag, # Tag name
|
||||
$type, # Type of tag
|
||||
$is_static, # Is this a static tag?
|
||||
$file, # File in which tag appears
|
||||
$line) = @_; # Line in which tag appears
|
||||
|
||||
my $tagline = ""; # Created tag line
|
||||
|
||||
# Only process tag if not empty
|
||||
if ($tag)
|
||||
{
|
||||
# Get rid of \n, and escape / and \ in line
|
||||
chomp $line;
|
||||
$line =~ s/\\/\\\\/g;
|
||||
$line =~ s/\//\\\//g;
|
||||
|
||||
# Create a tag line
|
||||
$tagline = "$tag\t$file\t/^$line\$/";
|
||||
|
||||
# If we're told to do so, add extensions
|
||||
if ($do_exts)
|
||||
{
|
||||
$tagline .= ";\"\t$type"
|
||||
. ($is_static ? "\tfile:" : "")
|
||||
. ($package_name ? "\tclass:$package_name" : "");
|
||||
}
|
||||
|
||||
# Push it on the stack
|
||||
push (@tags, $tagline);
|
||||
}
|
||||
}
|
||||
|
||||
# Parse package name from statement
|
||||
sub PackageName($)
|
||||
{
|
||||
my ($stmt) = @_; # Statement
|
||||
|
||||
# Look for the argument to "package". Return it if found, else return ""
|
||||
if ($stmt =~ /^package\s+([\w:]+)/)
|
||||
{
|
||||
my $pkgname = $1;
|
||||
|
||||
# Remove any parent package name(s)
|
||||
$pkgname =~ s/.*://;
|
||||
return $pkgname;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
# Parse sub name from statement
|
||||
sub SubName($)
|
||||
{
|
||||
my ($stmt) = @_; # Statement
|
||||
|
||||
# Look for the argument to "sub". Return it if found, else return ""
|
||||
if ($stmt =~ /^sub\s+([\w:]+)/)
|
||||
{
|
||||
my $subname = $1;
|
||||
|
||||
# Remove any parent package name(s)
|
||||
$subname =~ s/.*://;
|
||||
return $subname;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
# Parse all variable names from statement
|
||||
sub VarNames($)
|
||||
{
|
||||
my ($stmt) = @_;
|
||||
|
||||
# Remove my or local from statement, if present
|
||||
$stmt =~ s/^(my|our|local)\s+//;
|
||||
|
||||
# Remove any assignment piece
|
||||
$stmt =~ s/\s*=.*//;
|
||||
|
||||
# Now find all variable names, i.e. "words" preceded by $, @ or %
|
||||
@vars = ($stmt =~ /[\$\@\%]([\w:]+)\b/g);
|
||||
|
||||
# Remove any parent package name(s)
|
||||
map(s/.*://, @vars);
|
||||
|
||||
return (@vars);
|
||||
}
|
||||
|
||||
############### Start ###############
|
||||
|
||||
print "\npltags $VERSION by Michael Schaap <mscha\@mscha.com>\n\n";
|
||||
|
||||
# Get options
|
||||
$status = GetOptions("subs!" => \$do_subs,
|
||||
"vars!" => \$do_vars,
|
||||
"pkgs!" => \$do_pkgs,
|
||||
"extensions!" => \$do_exts);
|
||||
|
||||
# Usage if error in options or no arguments given
|
||||
unless ($status && @ARGV)
|
||||
{
|
||||
print "\n" unless ($status);
|
||||
print " Usage: $0 [options] filename ...\n\n";
|
||||
print " Where options can be:\n";
|
||||
print " --subs (--nosubs) (don't) include sub declarations in tag file\n";
|
||||
print " --vars (--novars) (don't) include variable declarations in tag file\n";
|
||||
print " --pkgs (--nopkgs) (don't) include package declarations in tag file\n";
|
||||
print " --extensions (--noextensions)\n";
|
||||
print " (don't) include Exuberant Ctags / Vim style\n";
|
||||
print " extensions in tag file\n\n";
|
||||
print " Default options: ";
|
||||
print ($do_subs ? "--subs " : "--nosubs ");
|
||||
print ($do_vars ? "--vars " : "--novars ");
|
||||
print ($do_pkgs ? "--pkgs " : "--nopkgs ");
|
||||
print ($do_exts ? "--extensions\n\n" : "--noextensions\n\n");
|
||||
print " Example: $0 *.pl *.pm ../shared/*.pm\n\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
# Loop through files on command line - 'glob' any wildcards, since Windows
|
||||
# doesn't do this for us
|
||||
foreach $file (map { glob } @ARGV)
|
||||
{
|
||||
# Skip if this is not a file we can open. Also skip tags files and backup
|
||||
# files
|
||||
next unless ((-f $file) && (-r $file) && ($file !~ /tags$/)
|
||||
&& ($file !~ /~$/));
|
||||
|
||||
print "Tagging file $file...\n";
|
||||
|
||||
$is_pkg = 0;
|
||||
$package_name = "";
|
||||
$has_subs = 0;
|
||||
$var_continues = 0;
|
||||
|
||||
open (IN, $file) or die "Can't open file '$file': $!";
|
||||
|
||||
# Loop through file
|
||||
foreach $line (<IN>)
|
||||
{
|
||||
# Statement is line with comments and whitespace trimmed
|
||||
($stmt = $line) =~ s/#.*//;
|
||||
$stmt =~ s/^\s*//;
|
||||
$stmt =~ s/\s*$//;
|
||||
|
||||
# Nothing left? Never mind.
|
||||
next unless ($stmt);
|
||||
|
||||
# This is a variable declaration if one was started on the previous
|
||||
# line, or if this line starts with my or local
|
||||
if ($var_continues or ($stmt =~/^my\b/)
|
||||
or ($stmt =~/^our\b/) or ($stmt =~/^local\b/))
|
||||
{
|
||||
# The declaration continues if the line does not end with ;
|
||||
$var_continues = ($stmt !~ /;$/);
|
||||
|
||||
# Loop through all variable names in the declaration
|
||||
foreach $var (VarNames($stmt))
|
||||
{
|
||||
# Make a tag for this variable unless we're told not to. We
|
||||
# assume that a variable is always static, unless it appears
|
||||
# in a package before any sub. (Not necessarily true, but
|
||||
# it's ok for most purposes and Vim works fine even if it is
|
||||
# incorrect)
|
||||
if ($do_vars)
|
||||
{
|
||||
MakeTag($var, "v", (!$is_pkg or $has_subs), $file, $line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# This is a package declaration if the line starts with package
|
||||
elsif ($stmt =~/^package\b/)
|
||||
{
|
||||
# Get name of the package
|
||||
$package_name = PackageName($stmt);
|
||||
|
||||
if ($package_name)
|
||||
{
|
||||
# Remember that we're doing a package
|
||||
$is_pkg = 1;
|
||||
|
||||
# Make a tag for this package unless we're told not to. A
|
||||
# package is never static.
|
||||
if ($do_pkgs)
|
||||
{
|
||||
MakeTag($package_name, "p", 0, $file, $line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# This is a sub declaration if the line starts with sub
|
||||
elsif ($stmt =~/^sub\b/)
|
||||
{
|
||||
# Remember that this file has subs
|
||||
$has_subs = 1;
|
||||
|
||||
# Make a tag for this sub unless we're told not to. We assume
|
||||
# that a sub is static, unless it appears in a package. (Not
|
||||
# necessarily true, but it's ok for most purposes and Vim works
|
||||
# fine even if it is incorrect)
|
||||
if ($do_subs)
|
||||
{
|
||||
MakeTag(SubName($stmt), "s", (!$is_pkg), $file, $line);
|
||||
}
|
||||
}
|
||||
}
|
||||
close (IN);
|
||||
}
|
||||
|
||||
# Do we have any tags? If so, write them to the tags file
|
||||
if (@tags)
|
||||
{
|
||||
# Add some tag file extensions if we're told to
|
||||
if ($do_exts)
|
||||
{
|
||||
push (@tags, "!_TAG_FILE_FORMAT\t2\t/extended format/");
|
||||
push (@tags, "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted/");
|
||||
push (@tags, "!_TAG_PROGRAM_AUTHOR\tMichael Schaap\t/mscha\@mscha.com/");
|
||||
push (@tags, "!_TAG_PROGRAM_NAME\tpltags\t//");
|
||||
push (@tags, "!_TAG_PROGRAM_VERSION\t$VERSION\t/supports multiple tags and extended format/");
|
||||
}
|
||||
|
||||
print "\nWriting tags file.\n";
|
||||
|
||||
open (OUT, ">tags") or die "Can't open tags file: $!";
|
||||
|
||||
foreach $tagline (sort @tags)
|
||||
{
|
||||
print OUT "$tagline\n";
|
||||
}
|
||||
|
||||
close (OUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
print "\nNo tags found.\n";
|
||||
}
|
11
runtime/tools/ref
Executable file
11
runtime/tools/ref
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# ref - Check spelling of the arguments
|
||||
#
|
||||
# Usage: ref word ..
|
||||
#
|
||||
# can be used for the K command of Vim
|
||||
#
|
||||
spell <<EOF
|
||||
$*
|
||||
EOF
|
61
runtime/tools/shtags.1
Normal file
61
runtime/tools/shtags.1
Normal file
@@ -0,0 +1,61 @@
|
||||
.TH shtags 1 "local Utilities"
|
||||
.SH NAME
|
||||
shtags \- Create tags for shell scripts
|
||||
.SH SYNOPSIS
|
||||
.B shtags
|
||||
[\fI-mvw\fP] [\fI-t <file>\fP] [\fI-s <shell>\fP] <files>
|
||||
.SH DESCRIPTION
|
||||
\fBshtags\fP creates a \fBvi(1)\fP tags file for shell scripts - which
|
||||
essentially turns your code into a hypertext document. \fBshtags\fP
|
||||
attempts to create tags for all function and variable definitions,
|
||||
although this is a little difficult, because in most shell languages,
|
||||
variables don't need to be explicitly defined, and as such there is
|
||||
often no distinct "variable definition". If this is the case,
|
||||
\fBshtags\fP simply creates a tag for the first instance of a variable
|
||||
which is being set in a simple way, ie: \fIset x = 5\fP.
|
||||
.SH OPTIONS
|
||||
.IP "\fB-t <file>\fP"
|
||||
Name of tags file to create. (default is 'tags')
|
||||
.IP "\fB-s <shell>\fP"
|
||||
The name of the shell used by the script(s). By default,
|
||||
\fBshtags\fP tries to work out which is the appropriate shell for each
|
||||
file individually by looking at the first line of each file. This wont
|
||||
work however, if the script starts as a bourne shell script and tries
|
||||
to be clever about starting the shell it really wants.
|
||||
.b
|
||||
Currently supported shells are:
|
||||
.RS
|
||||
.IP \fBsh\fP
|
||||
Bourne Shell
|
||||
.IP \fBperl\fP
|
||||
Perl (versions 4 and 5)
|
||||
.IP \fBksh\fP
|
||||
Korn Shell
|
||||
.IP \fBtclsh\fP
|
||||
The TCL shell
|
||||
.IP \fBwish\fP
|
||||
The TK Windowing shell (same as tclsh)
|
||||
.RE
|
||||
|
||||
.IP \fB-v\fP
|
||||
Include variable definitions (variables mentioned at the start of a line)
|
||||
.IP \fB-V\fP
|
||||
Print version information.
|
||||
.IP \fB-w\fP
|
||||
Suppress "duplicate tag" warning messages.
|
||||
.IP \fB-x\fP
|
||||
Explicitly create a new tags file. Normally new tags are merged with
|
||||
the old tags file.
|
||||
.PP
|
||||
\fBshtags\fP scans the specified files for subroutines and possibly
|
||||
variable definitions, and creates a \fBvi\fP style tags file.
|
||||
.SH FILES
|
||||
.IP \fBtags\fP
|
||||
A tags file contains a sorted list of tags, one tag per line. The
|
||||
format is the same as that used by \fBvi\fP(1)
|
||||
.SH AUTHOR
|
||||
Stephen Riehm
|
||||
.br
|
||||
sr@pc-plus.de
|
||||
.SH "SEE ALSO"
|
||||
ctags(1), etags(1), perl(1), tclsh(1), wish(1), sh(1), ksh(1).
|
144
runtime/tools/shtags.pl
Executable file
144
runtime/tools/shtags.pl
Executable file
@@ -0,0 +1,144 @@
|
||||
#!/usr/bin/env perl
|
||||
#
|
||||
# shtags: create a tags file for perl scripts
|
||||
#
|
||||
# Author: Stephen Riehm
|
||||
# Last Changed: 96/11/27 19:46:06
|
||||
#
|
||||
# "@(#) shtags 1.1 by S. Riehm"
|
||||
#
|
||||
|
||||
# obvious... :-)
|
||||
sub usage
|
||||
{
|
||||
print <<_EOUSAGE_ ;
|
||||
USAGE: $program [-kvwVx] [-t <file>] <files>
|
||||
-t <file> Name of tags file to create. (default is 'tags')
|
||||
-s <shell> Name of the shell language in the script
|
||||
-v Include variable definitions.
|
||||
(variables mentioned at the start of a line)
|
||||
-V Print version information.
|
||||
-w Suppress "duplicate tag" warnings.
|
||||
-x Explicitly create a new tags file. Normally tags are merged.
|
||||
<files> List of files to scan for tags.
|
||||
_EOUSAGE_
|
||||
exit 0
|
||||
}
|
||||
|
||||
sub version
|
||||
{
|
||||
#
|
||||
# Version information
|
||||
#
|
||||
@id = split( ', ', 'scripts/bin/shtags, /usr/local/, LOCAL_SCRIPTS, 1.1, 96/11/27, 19:46:06' );
|
||||
$id[0] =~ s,.*/,,;
|
||||
print <<_EOVERS;
|
||||
$id[0]: $id[3]
|
||||
Last Modified: @id[4,5]
|
||||
Component: $id[1]
|
||||
Release: $id[2]
|
||||
_EOVERS
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
#
|
||||
# initialisations
|
||||
#
|
||||
($program = $0) =~ s,.*/,,;
|
||||
require 'getopts.pl';
|
||||
|
||||
#
|
||||
# parse command line
|
||||
#
|
||||
&Getopts( "t:s:vVwx" ) || &usage();
|
||||
$tags_file = $opt_t || 'tags';
|
||||
$explicit = $opt_x;
|
||||
$variable_tags = $opt_v;
|
||||
$allow_warnings = ! $opt_w;
|
||||
&version if $opt_V;
|
||||
&usage() unless @ARGV != 0;
|
||||
|
||||
# slurp up the existing tags. Some will be replaced, the ones that aren't
|
||||
# will be re-written exactly as they were read
|
||||
if( ! $explicit && open( TAGS, "< $tags_file" ) )
|
||||
{
|
||||
while( <TAGS> )
|
||||
{
|
||||
/^\S+/;
|
||||
$tags{$&} = $_;
|
||||
}
|
||||
close( TAGS );
|
||||
}
|
||||
|
||||
#
|
||||
# for each line of every file listed on the command line, look for a
|
||||
# 'sub' definition, or, if variables are wanted aswell, look for a
|
||||
# variable definition at the start of a line
|
||||
#
|
||||
while( <> )
|
||||
{
|
||||
&check_shell($_), ( $old_file = $ARGV ) if $ARGV ne $old_file;
|
||||
next unless $shell;
|
||||
if( $shell eq "sh" )
|
||||
{
|
||||
next unless /^\s*(((\w+)))\s*\(\s*\)/
|
||||
|| ( $variable_tags && /^(((\w+)=))/ );
|
||||
$match = $3;
|
||||
}
|
||||
if( $shell eq "ksh" )
|
||||
{
|
||||
# ksh
|
||||
next unless /^\s*function\s+(((\w+)))/
|
||||
|| ( $variable_tags && /^(((\w+)=))/ );
|
||||
$match = $3;
|
||||
}
|
||||
if( $shell eq "perl" )
|
||||
{
|
||||
# perl
|
||||
next unless /^\s*sub\s+(\w+('|::))?(\w+)/
|
||||
|| /^\s*(((\w+))):/
|
||||
|| ( $variable_tags && /^(([(\s]*[\$\@\%]{1}(\w+).*=))/ );
|
||||
$match = $3;
|
||||
}
|
||||
if( $shell eq "tcl" )
|
||||
{
|
||||
next unless /^\s*proc\s+(((\S+)))/
|
||||
|| ( $variable_tags && /^\s*set\s+(((\w+)\s))/ );
|
||||
$match = $3;
|
||||
}
|
||||
chop;
|
||||
warn "$match - duplicate ignored\n"
|
||||
if ( $new{$match}++
|
||||
|| !( $tags{$match} = sprintf( "%s\t%s\t?^%s\$?\n", $match, $ARGV, $_ ) ) )
|
||||
&& $allow_warnings;
|
||||
}
|
||||
|
||||
# write the new tags to the tags file - note that the whole file is rewritten
|
||||
open( TAGS, "> $tags_file" );
|
||||
foreach( sort( keys %tags ) )
|
||||
{
|
||||
print TAGS "$tags{$_}";
|
||||
}
|
||||
close( TAGS );
|
||||
|
||||
sub check_shell
|
||||
{
|
||||
local( $_ ) = @_;
|
||||
# read the first line of a script, and work out which shell it is,
|
||||
# unless a shell was specified on the command line
|
||||
#
|
||||
# This routine can't handle clever scripts which start sh and then
|
||||
# use sh to start the shell they really wanted.
|
||||
if( $opt_s )
|
||||
{
|
||||
$shell = $opt_s;
|
||||
}
|
||||
else
|
||||
{
|
||||
$shell = "sh" if /^:$/ || /^#!.*\/bin\/sh/;
|
||||
$shell = "ksh" if /^#!.*\/ksh/;
|
||||
$shell = "perl" if /^#!.*\/perl/;
|
||||
$shell = "tcl" if /^#!.*\/wish/;
|
||||
printf "Using $shell for $ARGV\n";
|
||||
}
|
||||
}
|
159
runtime/tools/tcltags
Executable file
159
runtime/tools/tcltags
Executable file
@@ -0,0 +1,159 @@
|
||||
#!/bin/sh
|
||||
# vim:ts=4:
|
||||
# Generates a tag file for TCL code. Slow, but gets the job done.
|
||||
#
|
||||
# Written by Darren Hiebert <darren@hiebert.com>
|
||||
|
||||
program_name=`basename $0`
|
||||
program_version="0.3"
|
||||
program_author="Darren Hiebert"
|
||||
author_email="darren@hiebert.com"
|
||||
tmp_tagfile=/tmp/${program_name}.$$
|
||||
|
||||
usage="\
|
||||
Usage: $program_name [-au] [-{f|o} tagfile] [--format=n] file(s)
|
||||
-a append to current tag file
|
||||
-f tagfile specify output tag file name (default=tags)
|
||||
-o alternative for -f
|
||||
-u unsorted
|
||||
--format=n specify tag file format (default=2)
|
||||
--help print this help message
|
||||
"
|
||||
|
||||
# defaults
|
||||
#
|
||||
append=0
|
||||
format=2
|
||||
sorted=1
|
||||
tagfile=tags
|
||||
filelist=
|
||||
|
||||
# read options
|
||||
#
|
||||
getparam()
|
||||
{
|
||||
if [ -n "$1" ]; then
|
||||
# set variable to word passed in
|
||||
echo "$2='$1'; opt="
|
||||
else
|
||||
# set variable to next word on command line
|
||||
echo "$2="'$1'"; shift"
|
||||
fi
|
||||
}
|
||||
|
||||
finished=0
|
||||
while [ $# -gt 0 -a $finished -eq 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
--*)
|
||||
opt=`echo "$1" | cut -c 3-`
|
||||
shift
|
||||
opt_name=`echo "$opt" | awk -F= '{print $1}'`
|
||||
opt_value=`echo "$opt" | awk -F= '{print $2}'`
|
||||
case "$opt_name" in
|
||||
format) case "$opt_value" in
|
||||
1|2) format=$opt_value;;
|
||||
*) echo "--$opt: unsupported value" >&2; exit 1;;
|
||||
esac
|
||||
;;
|
||||
help) echo "$usage"; exit 0;;
|
||||
*) echo "$opt_name: unsupported option" >&2; exit 1;;
|
||||
esac
|
||||
;;
|
||||
-*)
|
||||
# chop off leading '-'
|
||||
opt=`echo "$1" | cut -c 2-`
|
||||
shift
|
||||
while [ -n "$opt" ]
|
||||
do
|
||||
opt_char=`echo "$opt" | cut -c 1`
|
||||
opt=`echo "$opt" | cut -c 2-`
|
||||
case "$opt_char" in
|
||||
a) append=1;;
|
||||
u) sorted=0;;
|
||||
o|f) eval `getparam "$opt" tagfile`;;
|
||||
*) echo "$opt: unsupported option" >&2; exit 1;;
|
||||
esac
|
||||
done
|
||||
;;
|
||||
*) filelist="$*"; break;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$filelist" ] ;then
|
||||
echo "$usage" >&2; exit 1
|
||||
fi
|
||||
|
||||
# awk program for generating tags
|
||||
#
|
||||
ext_flags=""
|
||||
ttype=""
|
||||
if [ $format -eq 2 ] ;then
|
||||
ext_flags=';\" %s'
|
||||
ttype=", type"
|
||||
fi
|
||||
awkprg='
|
||||
function trim_comment(string) {
|
||||
comment = index(string, "#")
|
||||
if (comment != 0)
|
||||
string = substr(string, 0, comment-1)
|
||||
return string
|
||||
}
|
||||
function maketag(tagname, pattern, type, line_end) {
|
||||
gsub(/\\/, "\\\\", pattern)
|
||||
gsub(/\//, "\\/", pattern)
|
||||
if (line_end)
|
||||
terminator="$"
|
||||
else
|
||||
terminator=""
|
||||
printf("%s\t%s\t/^%s%s/'"$ext_flags"'\n", \
|
||||
tagname, FILENAME, pattern, terminator'"$ttype"')
|
||||
}
|
||||
$1 == "proc" && $3 ~ /^{/ {
|
||||
pattern = substr($0, 0, index($0, "{"))
|
||||
maketag($2, pattern, "f", 0)
|
||||
}
|
||||
/^set[ \t]/ && $2 !~ /\(/ {
|
||||
pattern = substr($0, 0, index($0, $2) + length($2))
|
||||
maketag($2, pattern, "v", 0)
|
||||
}
|
||||
/^array[ \t]*set[ \t]/ && $3 !~ /\(/ {
|
||||
pattern = substr($0, 0, index($0, $3) + length($3))
|
||||
maketag($3, pattern, "v", 0)
|
||||
}'
|
||||
|
||||
# add or correct the pseudo tags
|
||||
#
|
||||
if [ "$tagfile" != "-" ] ;then
|
||||
if [ $append -eq 1 ]; then
|
||||
# ensure existing sort flag is correct
|
||||
sed -e "/^!_TAG_FILE_SORTED/s/ [01] / $sorted /" \
|
||||
-e "/^!_TAG_FILE_FORMAT/s/ 1 / $format /" \
|
||||
$tagfile > $tmp_tagfile
|
||||
else
|
||||
echo -ne "\
|
||||
!_TAG_FILE_FORMAT $format /extended format; --format=1 will not append ;\" to lines/
|
||||
!_TAG_FILE_SORTED $sorted /0=unsorted, 1=sorted/
|
||||
!_TAG_PROGRAM_AUTHOR $program_author /$author_email/
|
||||
!_TAG_PROGRAM_NAME $program_name //
|
||||
!_TAG_PROGRAM_VERSION $program_version //
|
||||
" > $tmp_tagfile
|
||||
fi
|
||||
fi
|
||||
|
||||
# generate tags
|
||||
#
|
||||
awk "$awkprg" $filelist >> $tmp_tagfile
|
||||
|
||||
if [ $sorted -eq 1 ] ;then
|
||||
sort -u -o $tmp_tagfile $tmp_tagfile
|
||||
fi
|
||||
|
||||
if [ "$tagfile" = '-' ] ;then
|
||||
cat $tmp_tagfile
|
||||
else
|
||||
cp $tmp_tagfile $tagfile
|
||||
fi
|
||||
rm $tmp_tagfile
|
||||
|
||||
exit 0
|
13
runtime/tools/vim132
Executable file
13
runtime/tools/vim132
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/csh
|
||||
#
|
||||
# Shell script for use with UNIX
|
||||
# Starts up Vim with the terminal in 132 column mode
|
||||
# Only works on VT-100 terminals and lookalikes
|
||||
# You need to have a termcap entry "vt100-w". Same as vt100 but 132 columns.
|
||||
#
|
||||
set oldterm=$term
|
||||
echo "[?3h"
|
||||
setenv TERM vt100-w
|
||||
vim $*
|
||||
set term=$oldterm
|
||||
echo "[?3l"
|
24
runtime/tools/vim_vs_net.cmd
Normal file
24
runtime/tools/vim_vs_net.cmd
Normal file
@@ -0,0 +1,24 @@
|
||||
@rem
|
||||
@rem To use this with Visual Studio .Net
|
||||
@rem Tools->External Tools...
|
||||
@rem Add
|
||||
@rem Title - Vim
|
||||
@rem Command - d:\files\util\vim_vs_net.cmd
|
||||
@rem Arguments - +$(CurLine) $(ItemPath)
|
||||
@rem Init Dir - Empty
|
||||
@rem
|
||||
@rem Coutesy of Brian Sturk
|
||||
@rem
|
||||
@rem --remote-silent +%1 is a command +954, move ahead 954 lines
|
||||
@rem --remote-silent %2 full path to file
|
||||
@rem In Vim
|
||||
@rem :h --remote-silent for mor details
|
||||
@rem
|
||||
@rem --servername VS_NET
|
||||
@rem This will create a new instance of vim called VS_NET. So if you
|
||||
open
|
||||
@rem multiple files from VS, they will use the same instance of Vim.
|
||||
@rem This allows you to have multiple copies of Vim running, but you can
|
||||
@rem control which one has VS files in it.
|
||||
@rem
|
||||
start /b gvim.exe --servername VS_NET --remote-silent "%1" "%2"
|
6
runtime/tools/vimm
Executable file
6
runtime/tools/vimm
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
# enable DEC locator input model on remote terminal
|
||||
echo "\033[1;2'z\033[1;3'{\c"
|
||||
vim "$@"
|
||||
# disable DEC locator input model on remote terminal
|
||||
echo "\033[2;4'{\033[0'z\c"
|
41
runtime/tools/vimspell.sh
Executable file
41
runtime/tools/vimspell.sh
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Spell a file & generate the syntax statements necessary to
|
||||
# highlight in vim. Based on a program from Krishna Gadepalli
|
||||
# <krishna@stdavids.picker.com>.
|
||||
#
|
||||
# I use the following mappings (in .vimrc):
|
||||
#
|
||||
# noremap <F8> :so `vimspell.sh %`<CR><CR>
|
||||
# noremap <F7> :syntax clear SpellErrors<CR>
|
||||
#
|
||||
# Neil Schemenauer <nascheme@ucalgary.ca>
|
||||
# March 1999
|
||||
|
||||
INFILE=$1
|
||||
OUTFILE=/tmp/vimspell.$$
|
||||
# if you have "tempfile", use the following line
|
||||
#OUTFILE=`tempfile`
|
||||
|
||||
#
|
||||
# local spellings
|
||||
#
|
||||
LOCAL_DICT=${LOCAL_DICT-$HOME/local/lib/local_dict}
|
||||
|
||||
if [ -f $LOCAL_DICT ]
|
||||
then
|
||||
SPELL_ARGS="+$LOCAL_DICT"
|
||||
fi
|
||||
|
||||
spell $SPELL_ARGS $INFILE | sort -u |
|
||||
awk '
|
||||
{
|
||||
printf "syntax match SpellErrors \"\\<%s\\>\"\n", $0 ;
|
||||
}
|
||||
|
||||
END {
|
||||
printf "highlight link SpellErrors ErrorMsg\n\n" ;
|
||||
}
|
||||
' > $OUTFILE
|
||||
echo "!rm $OUTFILE" >> $OUTFILE
|
||||
echo $OUTFILE
|
22
runtime/tools/vimspell.txt
Normal file
22
runtime/tools/vimspell.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
vimspell.sh
|
||||
===========
|
||||
|
||||
This is a simple script to spell check a file and generate the syntax
|
||||
statements necessary to highlight the errors in vim. It is based on a
|
||||
similar program by Krishna Gadepalli <krishna@stdavids.picker.com>.
|
||||
|
||||
To use this script, first place it in a directory in your path. Next,
|
||||
you should add some convenient key mappings. I use the following (in
|
||||
.vimrc):
|
||||
|
||||
noremap <F8> :so `vimspell.sh %`<CR><CR>
|
||||
noremap <F7> :syntax clear SpellErrors<CR>
|
||||
|
||||
This program requires the old Unix "spell" command. On my Debian
|
||||
system, "spell" is a wrapper around "ispell". For better security,
|
||||
you should uncomment the line in the script that uses "tempfile" to
|
||||
create a temporary file. As all systems don't have "tempfile" the
|
||||
insecure "pid method" is used.
|
||||
|
||||
|
||||
Neil Schemenauer <nascheme@ucalgary.ca>
|
584
runtime/tools/xcmdsrv_client.c
Normal file
584
runtime/tools/xcmdsrv_client.c
Normal file
@@ -0,0 +1,584 @@
|
||||
/* vi:set ts=8 sts=4 sw=4:
|
||||
*
|
||||
* VIM - Vi IMproved by Bram Moolenaar
|
||||
* X-Windows communication by Flemming Madsen
|
||||
*
|
||||
* Do ":help uganda" in Vim to read copying and usage conditions.
|
||||
* Do ":help credits" in Vim to see a list of people who contributed.
|
||||
* See README.txt for an overview of the Vim source code.
|
||||
*
|
||||
* Client for sending commands to an '+xcmdsrv' enabled vim.
|
||||
* This is mostly a de-Vimified version of if_xcmdsrv.c in vim.
|
||||
* See that file for a protocol specification.
|
||||
*
|
||||
* You can make a test program with a Makefile like:
|
||||
* xcmdsrv_client: xcmdsrv_client.c
|
||||
* cc -o $@ -g -DMAIN -I/usr/X11R6/include -L/usr/X11R6/lib $< -lX11
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_SELECT
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <sys/poll.h>
|
||||
#endif
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#define __ARGS(x) x
|
||||
|
||||
/* Client API */
|
||||
char * sendToVim __ARGS((Display *dpy, char *name, char *cmd, int asKeys, int *code));
|
||||
|
||||
#ifdef MAIN
|
||||
/* A sample program */
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *res;
|
||||
int code;
|
||||
|
||||
if (argc == 4)
|
||||
{
|
||||
if ((res = sendToVim(XOpenDisplay(NULL), argv[2], argv[3],
|
||||
argv[1][0] != 'e', &code)) != NULL)
|
||||
{
|
||||
if (code)
|
||||
printf("Error code returned: %d\n", code);
|
||||
puts(res);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "Usage: %s {k|e} <server> <command>", argv[0]);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Maximum size property that can be read at one time by
|
||||
* this module:
|
||||
*/
|
||||
|
||||
#define MAX_PROP_WORDS 100000
|
||||
|
||||
/*
|
||||
* Forward declarations for procedures defined later in this file:
|
||||
*/
|
||||
|
||||
static int x_error_check __ARGS((Display *dpy, XErrorEvent *error_event));
|
||||
static int AppendPropCarefully __ARGS((Display *display,
|
||||
Window window, Atom property, char *value, int length));
|
||||
static Window LookupName __ARGS((Display *dpy, char *name,
|
||||
int delete, char **loose));
|
||||
static int SendInit __ARGS((Display *dpy));
|
||||
static char *SendEventProc __ARGS((Display *dpy, XEvent *eventPtr,
|
||||
int expect, int *code));
|
||||
static int IsSerialName __ARGS((char *name));
|
||||
|
||||
/* Private variables */
|
||||
static Atom registryProperty = None;
|
||||
static Atom commProperty = None;
|
||||
static Window commWindow = None;
|
||||
static int got_x_error = FALSE;
|
||||
|
||||
|
||||
/*
|
||||
* sendToVim --
|
||||
* Send to an instance of Vim via the X display.
|
||||
*
|
||||
* Results:
|
||||
* A string with the result or NULL. Caller must free if non-NULL
|
||||
*/
|
||||
|
||||
char *
|
||||
sendToVim(dpy, name, cmd, asKeys, code)
|
||||
Display *dpy; /* Where to send. */
|
||||
char *name; /* Where to send. */
|
||||
char *cmd; /* What to send. */
|
||||
int asKeys; /* Interpret as keystrokes or expr ? */
|
||||
int *code; /* Return code. 0 => OK */
|
||||
{
|
||||
Window w;
|
||||
Atom *plist;
|
||||
XErrorHandler old_handler;
|
||||
#define STATIC_SPACE 500
|
||||
char *property, staticSpace[STATIC_SPACE];
|
||||
int length;
|
||||
int res;
|
||||
static int serial = 0; /* Running count of sent commands.
|
||||
* Used to give each command a
|
||||
* different serial number. */
|
||||
XEvent event;
|
||||
XPropertyEvent *e = (XPropertyEvent *)&event;
|
||||
time_t start;
|
||||
char *result;
|
||||
char *loosename = NULL;
|
||||
|
||||
if (commProperty == None && dpy != NULL)
|
||||
{
|
||||
if (SendInit(dpy) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bind the server name to a communication window.
|
||||
*
|
||||
* Find any survivor with a serialno attached to the name if the
|
||||
* original registrant of the wanted name is no longer present.
|
||||
*
|
||||
* Delete any lingering names from dead editors.
|
||||
*/
|
||||
|
||||
old_handler = XSetErrorHandler(x_error_check);
|
||||
while (TRUE)
|
||||
{
|
||||
got_x_error = FALSE;
|
||||
w = LookupName(dpy, name, 0, &loosename);
|
||||
/* Check that the window is hot */
|
||||
if (w != None)
|
||||
{
|
||||
plist = XListProperties(dpy, w, &res);
|
||||
XSync(dpy, False);
|
||||
if (plist != NULL)
|
||||
XFree(plist);
|
||||
if (got_x_error)
|
||||
{
|
||||
LookupName(dpy, loosename ? loosename : name,
|
||||
/*DELETE=*/TRUE, NULL);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (w == None)
|
||||
{
|
||||
fprintf(stderr, "no registered server named %s\n", name);
|
||||
return NULL;
|
||||
}
|
||||
else if (loosename != NULL)
|
||||
name = loosename;
|
||||
|
||||
/*
|
||||
* Send the command to target interpreter by appending it to the
|
||||
* comm window in the communication window.
|
||||
*/
|
||||
|
||||
length = strlen(name) + strlen(cmd) + 10;
|
||||
if (length <= STATIC_SPACE)
|
||||
property = staticSpace;
|
||||
else
|
||||
property = (char *) malloc((unsigned) length);
|
||||
|
||||
serial++;
|
||||
sprintf(property, "%c%c%c-n %s%c-s %s",
|
||||
0, asKeys ? 'k' : 'c', 0, name, 0, cmd);
|
||||
if (name == loosename)
|
||||
free(loosename);
|
||||
if (!asKeys)
|
||||
{
|
||||
/* Add a back reference to our comm window */
|
||||
sprintf(property + length, "%c-r %x %d", 0, (uint) commWindow, serial);
|
||||
length += strlen(property + length + 1) + 1;
|
||||
}
|
||||
|
||||
res = AppendPropCarefully(dpy, w, commProperty, property, length + 1);
|
||||
if (length > STATIC_SPACE)
|
||||
free(property);
|
||||
if (res < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to send command to the destination program\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (asKeys) /* There is no answer for this - Keys are sent async */
|
||||
return NULL;
|
||||
|
||||
|
||||
/*
|
||||
* Enter a loop processing X events & pooling chars until we see the result
|
||||
*/
|
||||
|
||||
#define SEND_MSEC_POLL 50
|
||||
|
||||
time(&start);
|
||||
while ((time((time_t *) 0) - start) < 60)
|
||||
{
|
||||
/* Look out for the answer */
|
||||
#ifndef HAVE_SELECT
|
||||
struct pollfd fds;
|
||||
|
||||
fds.fd = ConnectionNumber(dpy);
|
||||
fds.events = POLLIN;
|
||||
if (poll(&fds, 1, SEND_MSEC_POLL) < 0)
|
||||
break;
|
||||
#else
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = SEND_MSEC_POLL * 1000;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(ConnectionNumber(dpy), &fds);
|
||||
if (select(ConnectionNumber(dpy) + 1, &fds, NULL, NULL, &tv) < 0)
|
||||
break;
|
||||
#endif
|
||||
while (XEventsQueued(dpy, QueuedAfterReading) > 0)
|
||||
{
|
||||
XNextEvent(dpy, &event);
|
||||
if (event.type == PropertyNotify && e->window == commWindow)
|
||||
if ((result = SendEventProc(dpy, &event, serial, code)) != NULL)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SendInit --
|
||||
* This procedure is called to initialize the
|
||||
* communication channels for sending commands and
|
||||
* receiving results.
|
||||
*/
|
||||
|
||||
static int
|
||||
SendInit(dpy)
|
||||
Display *dpy;
|
||||
{
|
||||
XErrorHandler old_handler;
|
||||
|
||||
/*
|
||||
* Create the window used for communication, and set up an
|
||||
* event handler for it.
|
||||
*/
|
||||
old_handler = XSetErrorHandler(x_error_check);
|
||||
got_x_error = FALSE;
|
||||
|
||||
commProperty = XInternAtom(dpy, "Comm", False);
|
||||
/* Change this back to "InterpRegistry" to talk to tk processes */
|
||||
registryProperty = XInternAtom(dpy, "VimRegistry", False);
|
||||
|
||||
if (commWindow == None)
|
||||
{
|
||||
commWindow =
|
||||
XCreateSimpleWindow(dpy, XDefaultRootWindow(dpy),
|
||||
getpid(), 0, 10, 10, 0,
|
||||
WhitePixel(dpy, DefaultScreen(dpy)),
|
||||
WhitePixel(dpy, DefaultScreen(dpy)));
|
||||
XSelectInput(dpy, commWindow, PropertyChangeMask);
|
||||
}
|
||||
|
||||
XSync(dpy, False);
|
||||
(void) XSetErrorHandler(old_handler);
|
||||
|
||||
return got_x_error ? -1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* LookupName --
|
||||
* Given an interpreter name, see if the name exists in
|
||||
* the interpreter registry for a particular display.
|
||||
*
|
||||
* Results:
|
||||
* If the given name is registered, return the ID of
|
||||
* the window associated with the name. If the name
|
||||
* isn't registered, then return 0.
|
||||
*/
|
||||
|
||||
static Window
|
||||
LookupName(dpy, name, delete, loose)
|
||||
Display *dpy; /* Display whose registry to check. */
|
||||
char *name; /* Name of an interpreter. */
|
||||
int delete; /* If non-zero, delete info about name. */
|
||||
char **loose; /* Do another search matching -999 if not found
|
||||
Return result here if a match is found */
|
||||
{
|
||||
unsigned char *regProp, *entry;
|
||||
unsigned char *p;
|
||||
int result, actualFormat;
|
||||
unsigned long numItems, bytesAfter;
|
||||
Atom actualType;
|
||||
Window returnValue;
|
||||
|
||||
/*
|
||||
* Read the registry property.
|
||||
*/
|
||||
|
||||
regProp = NULL;
|
||||
result = XGetWindowProperty(dpy, RootWindow(dpy, 0), registryProperty, 0,
|
||||
MAX_PROP_WORDS, False, XA_STRING, &actualType,
|
||||
&actualFormat, &numItems, &bytesAfter,
|
||||
®Prop);
|
||||
|
||||
if (actualType == None)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If the property is improperly formed, then delete it.
|
||||
*/
|
||||
|
||||
if ((result != Success) || (actualFormat != 8) || (actualType != XA_STRING))
|
||||
{
|
||||
if (regProp != NULL)
|
||||
XFree(regProp);
|
||||
XDeleteProperty(dpy, RootWindow(dpy, 0), registryProperty);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the property for the desired name.
|
||||
*/
|
||||
|
||||
returnValue = None;
|
||||
entry = NULL; /* Not needed, but eliminates compiler warning. */
|
||||
for (p = regProp; (p - regProp) < numItems; )
|
||||
{
|
||||
entry = p;
|
||||
while ((*p != 0) && (!isspace(*p)))
|
||||
p++;
|
||||
if ((*p != 0) && (strcasecmp(name, p + 1) == 0))
|
||||
{
|
||||
sscanf(entry, "%x", (uint*) &returnValue);
|
||||
break;
|
||||
}
|
||||
while (*p != 0)
|
||||
p++;
|
||||
p++;
|
||||
}
|
||||
|
||||
if (loose != NULL && returnValue == None && !IsSerialName(name))
|
||||
{
|
||||
for (p = regProp; (p - regProp) < numItems; )
|
||||
{
|
||||
entry = p;
|
||||
while ((*p != 0) && (!isspace(*p)))
|
||||
p++;
|
||||
if ((*p != 0) && IsSerialName(p + 1)
|
||||
&& (strncmp(name, p + 1, strlen(name)) == 0))
|
||||
{
|
||||
sscanf(entry, "%x", (uint*) &returnValue);
|
||||
*loose = strdup(p + 1);
|
||||
break;
|
||||
}
|
||||
while (*p != 0)
|
||||
p++;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete the property, if that is desired (copy down the
|
||||
* remainder of the registry property to overlay the deleted
|
||||
* info, then rewrite the property).
|
||||
*/
|
||||
|
||||
if ((delete) && (returnValue != None))
|
||||
{
|
||||
int count;
|
||||
|
||||
while (*p != 0)
|
||||
p++;
|
||||
p++;
|
||||
count = numItems - (p-regProp);
|
||||
if (count > 0)
|
||||
memcpy(entry, p, count);
|
||||
XChangeProperty(dpy, RootWindow(dpy, 0), registryProperty, XA_STRING,
|
||||
8, PropModeReplace, regProp,
|
||||
(int) (numItems - (p-entry)));
|
||||
XSync(dpy, False);
|
||||
}
|
||||
|
||||
XFree(regProp);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
static char *
|
||||
SendEventProc(dpy, eventPtr, expected, code)
|
||||
Display *dpy;
|
||||
XEvent *eventPtr; /* Information about event. */
|
||||
int expected; /* The one were waiting for */
|
||||
int *code; /* Return code. 0 => OK */
|
||||
{
|
||||
unsigned char *propInfo;
|
||||
unsigned char *p;
|
||||
int result, actualFormat;
|
||||
int retCode;
|
||||
unsigned long numItems, bytesAfter;
|
||||
Atom actualType;
|
||||
|
||||
if ((eventPtr->xproperty.atom != commProperty)
|
||||
|| (eventPtr->xproperty.state != PropertyNewValue))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the comm property and delete it.
|
||||
*/
|
||||
|
||||
propInfo = NULL;
|
||||
result = XGetWindowProperty(dpy, commWindow, commProperty, 0,
|
||||
MAX_PROP_WORDS, True, XA_STRING, &actualType,
|
||||
&actualFormat, &numItems, &bytesAfter,
|
||||
&propInfo);
|
||||
|
||||
/*
|
||||
* If the property doesn't exist or is improperly formed
|
||||
* then ignore it.
|
||||
*/
|
||||
|
||||
if ((result != Success) || (actualType != XA_STRING)
|
||||
|| (actualFormat != 8))
|
||||
{
|
||||
if (propInfo != NULL)
|
||||
{
|
||||
XFree(propInfo);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Several commands and results could arrive in the property at
|
||||
* one time; each iteration through the outer loop handles a
|
||||
* single command or result.
|
||||
*/
|
||||
|
||||
for (p = propInfo; (p - propInfo) < numItems; )
|
||||
{
|
||||
/*
|
||||
* Ignore leading NULs; each command or result starts with a
|
||||
* NUL so that no matter how badly formed a preceding command
|
||||
* is, we'll be able to tell that a new command/result is
|
||||
* starting.
|
||||
*/
|
||||
|
||||
if (*p == 0)
|
||||
{
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((*p == 'r') && (p[1] == 0))
|
||||
{
|
||||
int serial, gotSerial;
|
||||
char *res;
|
||||
|
||||
/*
|
||||
* This is a reply to some command that we sent out. Iterate
|
||||
* over all of its options. Stop when we reach the end of the
|
||||
* property or something that doesn't look like an option.
|
||||
*/
|
||||
|
||||
p += 2;
|
||||
gotSerial = 0;
|
||||
res = "";
|
||||
retCode = 0;
|
||||
while (((p-propInfo) < numItems) && (*p == '-'))
|
||||
{
|
||||
switch (p[1])
|
||||
{
|
||||
case 'r':
|
||||
if (p[2] == ' ')
|
||||
res = p + 3;
|
||||
break;
|
||||
case 's':
|
||||
if (sscanf(p + 2, " %d", &serial) == 1)
|
||||
gotSerial = 1;
|
||||
break;
|
||||
case 'c':
|
||||
if (sscanf(p + 2, " %d", &retCode) != 1)
|
||||
retCode = 0;
|
||||
break;
|
||||
}
|
||||
while (*p != 0)
|
||||
p++;
|
||||
p++;
|
||||
}
|
||||
|
||||
if (!gotSerial)
|
||||
continue;
|
||||
|
||||
if (code != NULL)
|
||||
*code = retCode;
|
||||
return serial == expected ? strdup(res) : NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Didn't recognize this thing. Just skip through the next
|
||||
* null character and try again.
|
||||
* Also, throw away commands that we cant process anyway.
|
||||
*/
|
||||
|
||||
while (*p != 0)
|
||||
p++;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
XFree(propInfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* AppendPropCarefully --
|
||||
*
|
||||
* Append a given property to a given window, but set up
|
||||
* an X error handler so that if the append fails this
|
||||
* procedure can return an error code rather than having
|
||||
* Xlib panic.
|
||||
*
|
||||
* Return:
|
||||
* 0 on OK - -1 on error
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
AppendPropCarefully(dpy, window, property, value, length)
|
||||
Display *dpy; /* Display on which to operate. */
|
||||
Window window; /* Window whose property is to
|
||||
* be modified. */
|
||||
Atom property; /* Name of property. */
|
||||
char *value; /* Characters to append to property. */
|
||||
int length; /* How much to append */
|
||||
{
|
||||
XErrorHandler old_handler;
|
||||
|
||||
old_handler = XSetErrorHandler(x_error_check);
|
||||
got_x_error = FALSE;
|
||||
XChangeProperty(dpy, window, property, XA_STRING, 8,
|
||||
PropModeAppend, value, length);
|
||||
XSync(dpy, False);
|
||||
(void) XSetErrorHandler(old_handler);
|
||||
return got_x_error ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Another X Error handler, just used to check for errors.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
x_error_check(dpy, error_event)
|
||||
Display *dpy;
|
||||
XErrorEvent *error_event;
|
||||
{
|
||||
got_x_error = TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if "str" looks like it had a serial number appended.
|
||||
* Actually just checks if the name ends in a digit.
|
||||
*/
|
||||
static int
|
||||
IsSerialName(str)
|
||||
char *str;
|
||||
{
|
||||
int len = strlen(str);
|
||||
|
||||
return (len > 1 && isdigit(str[len - 1]));
|
||||
}
|
Reference in New Issue
Block a user