2006-01-31 02:51:50 +10:00
/** \file parse_util.c
2006-02-19 11:54:38 +10:00
Various mostly unrelated utility functions related to parsing ,
loading and evaluating fish code .
2006-10-29 02:41:22 +10:00
This library can be seen as a ' toolbox ' for functions that are
used in many places in fish and that are somehow related to
2011-12-26 19:18:46 -08:00
parsing the code .
2006-01-31 02:51:50 +10:00
*/
# include "config.h"
2006-02-28 23:17:16 +10:00
2006-01-31 02:51:50 +10:00
# include <stdlib.h>
# include <stdio.h>
# include <sys/types.h>
# include <unistd.h>
# include <wctype.h>
# include <wchar.h>
2012-01-04 17:40:36 -08:00
# include <map>
# include <set>
2012-01-05 11:44:57 -08:00
# include <algorithm>
2006-01-31 02:51:50 +10:00
2006-02-08 19:20:05 +10:00
# include <time.h>
2006-01-31 02:51:50 +10:00
# include <assert.h>
2006-02-28 23:17:16 +10:00
# include "fallback.h"
2006-01-31 02:51:50 +10:00
# include "util.h"
2006-02-28 23:17:16 +10:00
2006-01-31 02:51:50 +10:00
# include "wutil.h"
# include "common.h"
# include "tokenizer.h"
# include "parse_util.h"
2006-02-08 19:20:05 +10:00
# include "expand.h"
# include "intern.h"
# include "exec.h"
2006-02-15 05:56:36 +10:00
# include "env.h"
2006-11-01 20:54:12 +10:00
# include "signal.h"
2006-02-19 11:14:32 +10:00
# include "wildcard.h"
2006-02-08 19:20:05 +10:00
2006-10-11 08:45:46 +10:00
/**
Maximum number of autoloaded items opf a specific type to keep in
memory at a time .
*/
# define AUTOLOAD_MAX 10
/**
Minimum time , in seconds , before an autoloaded item will be
unloaded
*/
# define AUTOLOAD_MIN_AGE 60
2012-01-04 17:40:36 -08:00
2006-02-05 23:10:35 +10:00
int parse_util_lineno ( const wchar_t * str , int len )
{
2006-02-20 04:19:32 +10:00
/**
First cached state
*/
2006-06-14 23:22:40 +10:00
static wchar_t * prev_str = 0 ;
2006-02-20 04:19:32 +10:00
static int i = 0 ;
static int res = 1 ;
2006-02-05 23:10:35 +10:00
2006-02-20 04:19:32 +10:00
/**
Second cached state
*/
2006-06-14 23:22:40 +10:00
static wchar_t * prev_str2 = 0 ;
2006-02-05 23:10:35 +10:00
static int i2 = 0 ;
static int res2 = 1 ;
2006-06-21 10:48:36 +10:00
CHECK ( str , 0 ) ;
2006-02-05 23:10:35 +10:00
if ( str ! = prev_str | | i > len )
{
if ( prev_str2 = = str & & i2 < = len )
{
2006-06-14 23:22:40 +10:00
wchar_t * tmp_str = prev_str ;
2006-02-05 23:10:35 +10:00
int tmp_i = i ;
int tmp_res = res ;
prev_str = prev_str2 ;
i = i2 ;
res = res2 ;
2011-12-26 19:18:46 -08:00
2006-02-05 23:10:35 +10:00
prev_str2 = tmp_str ;
i2 = tmp_i ;
res2 = tmp_res ;
}
else
{
prev_str2 = prev_str ;
i2 = i ;
res2 = res ;
2011-12-26 19:18:46 -08:00
2006-06-14 23:22:40 +10:00
prev_str = ( wchar_t * ) str ;
2006-02-05 23:10:35 +10:00
i = 0 ;
res = 1 ;
}
}
2011-12-26 19:18:46 -08:00
2006-02-06 23:47:57 +10:00
for ( ; str [ i ] & & i < len ; i + + )
2006-02-05 23:10:35 +10:00
{
if ( str [ i ] = = L ' \n ' )
2007-01-16 03:51:44 +10:00
{
2006-02-05 23:10:35 +10:00
res + + ;
2007-01-16 03:51:44 +10:00
}
2006-02-05 23:10:35 +10:00
}
return res ;
}
2007-09-22 00:05:49 +10:00
2012-02-06 00:57:43 -08:00
int parse_util_get_line_from_offset ( const wcstring & str , int pos )
2007-09-22 00:05:49 +10:00
{
// return parse_util_lineno( buff, pos );
2012-02-06 00:57:43 -08:00
const wchar_t * buff = str . c_str ( ) ;
2007-09-22 00:05:49 +10:00
int i ;
int count = 0 ;
if ( pos < 0 )
{
return - 1 ;
}
2011-12-26 19:18:46 -08:00
2007-09-22 00:05:49 +10:00
for ( i = 0 ; i < pos ; i + + )
{
if ( ! buff [ i ] )
{
return - 1 ;
}
2011-12-26 19:18:46 -08:00
2007-09-22 00:05:49 +10:00
if ( buff [ i ] = = L ' \n ' )
{
count + + ;
}
}
return count ;
}
2012-08-01 16:32:52 -07:00
size_t parse_util_get_offset_from_line ( const wcstring & str , int line )
2007-09-22 00:05:49 +10:00
{
2012-02-06 00:57:43 -08:00
const wchar_t * buff = str . c_str ( ) ;
2012-08-01 16:32:52 -07:00
size_t i ;
2007-09-22 00:05:49 +10:00
int count = 0 ;
2011-12-26 19:18:46 -08:00
2007-09-22 00:05:49 +10:00
if ( line < 0 )
{
2012-08-01 16:32:52 -07:00
return ( size_t ) ( - 1 ) ;
2007-09-22 00:05:49 +10:00
}
if ( line = = 0 )
return 0 ;
2011-12-26 19:18:46 -08:00
2007-09-22 00:05:49 +10:00
for ( i = 0 ; ; i + + )
{
if ( ! buff [ i ] )
{
return - 1 ;
}
2011-12-26 19:18:46 -08:00
2007-09-22 00:05:49 +10:00
if ( buff [ i ] = = L ' \n ' )
{
count + + ;
if ( count = = line )
{
2012-06-21 21:05:14 +05:30
return ( i + 1 ) < str . size ( ) ? i + 1 : i ;
2007-09-22 00:05:49 +10:00
}
2011-12-26 19:18:46 -08:00
2007-09-22 00:05:49 +10:00
}
}
}
2012-08-01 16:32:52 -07:00
size_t parse_util_get_offset ( const wcstring & str , int line , long line_offset )
2007-09-22 00:05:49 +10:00
{
2012-02-06 00:57:43 -08:00
const wchar_t * buff = str . c_str ( ) ;
2012-08-01 16:32:52 -07:00
size_t off = parse_util_get_offset_from_line ( buff , line ) ;
size_t off2 = parse_util_get_offset_from_line ( buff , line + 1 ) ;
long line_offset2 = line_offset ;
2011-12-26 19:18:46 -08:00
2012-08-01 16:32:52 -07:00
if ( off = = ( size_t ) ( - 1 ) )
2007-09-22 00:05:49 +10:00
{
return - 1 ;
}
2011-12-26 19:18:46 -08:00
2012-08-01 16:32:52 -07:00
if ( off2 = = ( size_t ) ( - 1 ) )
2007-09-22 00:05:49 +10:00
{
2012-07-28 17:49:46 -07:00
off2 = ( int ) ( wcslen ( buff ) + 1 ) ;
2007-09-22 00:05:49 +10:00
}
2011-12-26 19:18:46 -08:00
2007-09-22 00:05:49 +10:00
if ( line_offset2 < 0 )
{
line_offset2 = 0 ;
}
2011-12-26 19:18:46 -08:00
2007-09-22 00:05:49 +10:00
if ( line_offset2 > = off2 - off - 1 )
{
line_offset2 = off2 - off - 1 ;
}
2011-12-26 19:18:46 -08:00
2007-09-22 00:05:49 +10:00
return off + line_offset2 ;
2011-12-26 19:18:46 -08:00
2007-09-22 00:05:49 +10:00
}
2011-12-26 19:18:46 -08:00
int parse_util_locate_cmdsubst ( const wchar_t * in ,
wchar_t * * begin ,
2006-06-14 23:22:40 +10:00
wchar_t * * end ,
2006-01-31 02:51:50 +10:00
int allow_incomplete )
{
2006-06-14 23:22:40 +10:00
wchar_t * pos ;
2006-01-31 02:51:50 +10:00
wchar_t prev = 0 ;
int syntax_error = 0 ;
2011-12-26 19:18:46 -08:00
int paran_count = 0 ;
2006-01-31 02:51:50 +10:00
2006-06-14 23:22:40 +10:00
wchar_t * paran_begin = 0 , * paran_end = 0 ;
2006-01-31 02:51:50 +10:00
2006-06-21 10:48:36 +10:00
CHECK ( in , 0 ) ;
2011-12-26 19:18:46 -08:00
2006-06-15 10:59:31 +10:00
for ( pos = ( wchar_t * ) in ; * pos ; pos + + )
2006-01-31 02:51:50 +10:00
{
if ( prev ! = ' \\ ' )
{
if ( wcschr ( L " \' \" " , * pos ) )
{
2006-06-14 23:22:40 +10:00
wchar_t * q_end = quote_end ( pos ) ;
if ( q_end & & * q_end )
2006-01-31 02:51:50 +10:00
{
2006-06-14 23:22:40 +10:00
pos = q_end ;
2006-01-31 02:51:50 +10:00
}
else
2006-06-15 10:59:31 +10:00
{
2006-01-31 02:51:50 +10:00
break ;
2006-06-15 10:59:31 +10:00
}
2006-01-31 02:51:50 +10:00
}
else
{
if ( * pos = = ' ( ' )
{
if ( ( paran_count = = 0 ) & & ( paran_begin = = 0 ) )
2007-01-16 03:51:44 +10:00
{
2006-01-31 02:51:50 +10:00
paran_begin = pos ;
2007-01-16 03:51:44 +10:00
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
paran_count + + ;
}
else if ( * pos = = ' ) ' )
{
2007-01-16 03:51:44 +10:00
2006-01-31 02:51:50 +10:00
paran_count - - ;
2007-01-16 03:51:44 +10:00
2006-01-31 02:51:50 +10:00
if ( ( paran_count = = 0 ) & & ( paran_end = = 0 ) )
{
paran_end = pos ;
break ;
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
if ( paran_count < 0 )
{
syntax_error = 1 ;
break ;
}
}
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
}
prev = * pos ;
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
syntax_error | = ( paran_count < 0 ) ;
syntax_error | = ( ( paran_count > 0 ) & & ( ! allow_incomplete ) ) ;
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
if ( syntax_error )
{
return - 1 ;
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
if ( paran_begin = = 0 )
{
return 0 ;
}
2006-02-23 01:41:52 +10:00
if ( begin )
2007-01-16 03:51:44 +10:00
{
2006-02-23 01:41:52 +10:00
* begin = paran_begin ;
2007-01-16 03:51:44 +10:00
}
2006-02-23 01:41:52 +10:00
if ( end )
2007-01-16 03:51:44 +10:00
{
2006-06-14 23:22:40 +10:00
* end = paran_count ? ( wchar_t * ) in + wcslen ( in ) : paran_end ;
2007-01-16 03:51:44 +10:00
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
return 1 ;
}
void parse_util_cmdsubst_extent ( const wchar_t * buff ,
2012-08-01 16:32:52 -07:00
size_t cursor_pos ,
2012-02-06 00:57:43 -08:00
const wchar_t * * a ,
const wchar_t * * b )
2006-01-31 02:51:50 +10:00
{
2006-06-14 23:22:40 +10:00
wchar_t * begin , * end ;
wchar_t * pos ;
2006-07-03 20:46:47 +10:00
const wchar_t * cursor = buff + cursor_pos ;
2011-12-26 19:18:46 -08:00
2006-06-21 10:48:36 +10:00
CHECK ( buff , ) ;
2006-01-31 02:51:50 +10:00
if ( a )
2007-01-16 03:51:44 +10:00
{
2006-07-03 20:46:47 +10:00
* a = ( wchar_t * ) buff ;
2007-01-16 03:51:44 +10:00
}
2006-01-31 02:51:50 +10:00
if ( b )
2007-01-16 03:51:44 +10:00
{
2006-07-03 20:46:47 +10:00
* b = ( wchar_t * ) buff + wcslen ( buff ) ;
2007-01-16 03:51:44 +10:00
}
2011-12-26 19:18:46 -08:00
2006-06-14 23:22:40 +10:00
pos = ( wchar_t * ) buff ;
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
while ( 1 )
{
if ( parse_util_locate_cmdsubst ( pos ,
& begin ,
& end ,
1 ) < = 0 )
{
2006-07-03 20:46:47 +10:00
/*
No subshell found
*/
2006-01-31 02:51:50 +10:00
break ;
}
if ( ! end )
{
2006-06-14 23:22:40 +10:00
end = ( wchar_t * ) buff + wcslen ( buff ) ;
2006-01-31 02:51:50 +10:00
}
2006-07-03 20:46:47 +10:00
if ( ( begin < cursor ) & & ( end > = cursor ) )
2006-01-31 02:51:50 +10:00
{
begin + + ;
2007-01-16 03:51:44 +10:00
2006-07-03 20:46:47 +10:00
if ( a )
2007-01-16 03:51:44 +10:00
{
2006-07-03 20:46:47 +10:00
* a = begin ;
2007-01-16 03:51:44 +10:00
}
2006-07-03 20:46:47 +10:00
if ( b )
2007-01-16 03:51:44 +10:00
{
2006-07-03 20:46:47 +10:00
* b = end ;
2007-01-16 03:51:44 +10:00
}
2006-01-31 02:51:50 +10:00
break ;
}
2006-06-15 10:59:31 +10:00
if ( ! * end )
{
break ;
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
pos = end + 1 ;
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
}
/**
Get the beginning and end of the job or process definition under the cursor
*/
static void job_or_process_extent ( const wchar_t * buff ,
int cursor_pos ,
2012-02-06 00:57:43 -08:00
const wchar_t * * a ,
const wchar_t * * b ,
2006-01-31 02:51:50 +10:00
int process )
{
2012-02-06 00:57:43 -08:00
const wchar_t * begin , * end ;
2012-07-28 17:49:46 -07:00
long pos ;
2006-01-31 02:51:50 +10:00
wchar_t * buffcpy ;
int finished = 0 ;
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
tokenizer tok ;
2006-06-21 10:48:36 +10:00
CHECK ( buff , ) ;
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
if ( a )
2007-01-16 03:51:44 +10:00
{
2006-01-31 02:51:50 +10:00
* a = 0 ;
2007-01-16 03:51:44 +10:00
}
2006-01-31 02:51:50 +10:00
if ( b )
2007-01-16 03:51:44 +10:00
{
2006-01-31 02:51:50 +10:00
* b = 0 ;
2007-01-16 03:51:44 +10:00
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
parse_util_cmdsubst_extent ( buff , cursor_pos , & begin , & end ) ;
if ( ! end | | ! begin )
2007-01-16 03:51:44 +10:00
{
2006-01-31 02:51:50 +10:00
return ;
2007-01-16 03:51:44 +10:00
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
pos = cursor_pos - ( begin - buff ) ;
if ( a )
{
* a = begin ;
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
if ( b )
{
* b = end ;
}
buffcpy = wcsndup ( begin , end - begin ) ;
if ( ! buffcpy )
{
2006-07-03 20:39:57 +10:00
DIE_MEM ( ) ;
2006-01-31 02:51:50 +10:00
}
for ( tok_init ( & tok , buffcpy , TOK_ACCEPT_UNFINISHED ) ;
tok_has_next ( & tok ) & & ! finished ;
tok_next ( & tok ) )
{
int tok_begin = tok_get_pos ( & tok ) ;
switch ( tok_last_type ( & tok ) )
{
case TOK_PIPE :
2007-01-16 03:51:44 +10:00
{
2006-01-31 02:51:50 +10:00
if ( ! process )
2007-01-16 03:51:44 +10:00
{
2006-01-31 02:51:50 +10:00
break ;
2007-01-16 03:51:44 +10:00
}
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
case TOK_END :
case TOK_BACKGROUND :
{
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
if ( tok_begin > = pos )
{
2011-12-26 19:18:46 -08:00
finished = 1 ;
2006-01-31 02:51:50 +10:00
if ( b )
2007-01-16 03:51:44 +10:00
{
2006-06-14 23:22:40 +10:00
* b = ( wchar_t * ) buff + tok_begin ;
2007-01-16 03:51:44 +10:00
}
2006-01-31 02:51:50 +10:00
}
else
{
if ( a )
2007-01-16 03:51:44 +10:00
{
2006-06-14 23:22:40 +10:00
* a = ( wchar_t * ) buff + tok_begin + 1 ;
2007-01-16 03:51:44 +10:00
}
2006-01-31 02:51:50 +10:00
}
2007-01-16 03:51:44 +10:00
2011-12-26 19:18:46 -08:00
break ;
2006-01-31 02:51:50 +10:00
}
}
}
free ( buffcpy ) ;
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
tok_destroy ( & tok ) ;
}
void parse_util_process_extent ( const wchar_t * buff ,
int pos ,
2012-02-06 00:57:43 -08:00
const wchar_t * * a ,
const wchar_t * * b )
2006-01-31 02:51:50 +10:00
{
2011-12-26 19:18:46 -08:00
job_or_process_extent ( buff , pos , a , b , 1 ) ;
2006-01-31 02:51:50 +10:00
}
void parse_util_job_extent ( const wchar_t * buff ,
int pos ,
2012-02-06 00:57:43 -08:00
const wchar_t * * a ,
const wchar_t * * b )
2006-01-31 02:51:50 +10:00
{
2011-12-26 19:18:46 -08:00
job_or_process_extent ( buff , pos , a , b , 0 ) ;
2006-01-31 02:51:50 +10:00
}
void parse_util_token_extent ( const wchar_t * buff ,
2012-08-01 16:32:52 -07:00
size_t cursor_pos ,
2012-02-06 00:57:43 -08:00
const wchar_t * * tok_begin ,
const wchar_t * * tok_end ,
const wchar_t * * prev_begin ,
const wchar_t * * prev_end )
2006-01-31 02:51:50 +10:00
{
2012-02-06 00:57:43 -08:00
const wchar_t * begin , * end ;
2012-07-28 17:49:46 -07:00
long pos ;
2006-01-31 02:51:50 +10:00
wchar_t * buffcpy ;
tokenizer tok ;
2012-03-26 01:21:10 -07:00
const wchar_t * a = NULL , * b = NULL , * pa = NULL , * pb = NULL ;
2011-12-26 19:18:46 -08:00
2006-06-21 10:48:36 +10:00
CHECK ( buff , ) ;
2011-12-26 19:18:46 -08:00
2006-06-14 23:22:40 +10:00
assert ( cursor_pos > = 0 ) ;
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
parse_util_cmdsubst_extent ( buff , cursor_pos , & begin , & end ) ;
if ( ! end | | ! begin )
2007-01-16 03:51:44 +10:00
{
2006-01-31 02:51:50 +10:00
return ;
2007-01-16 03:51:44 +10:00
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
pos = cursor_pos - ( begin - buff ) ;
2011-12-26 19:18:46 -08:00
2012-02-06 00:57:43 -08:00
a = buff + pos ;
2006-01-31 02:51:50 +10:00
b = a ;
2012-02-06 00:57:43 -08:00
pa = buff + pos ;
2006-01-31 02:51:50 +10:00
pb = pa ;
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
assert ( begin > = buff ) ;
assert ( begin < = ( buff + wcslen ( buff ) ) ) ;
assert ( end > = begin ) ;
assert ( end < = ( buff + wcslen ( buff ) ) ) ;
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
buffcpy = wcsndup ( begin , end - begin ) ;
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
if ( ! buffcpy )
{
2006-07-03 20:39:57 +10:00
DIE_MEM ( ) ;
2006-01-31 02:51:50 +10:00
}
2012-02-17 15:55:54 -08:00
for ( tok_init ( & tok , buffcpy , TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS ) ;
2006-01-31 02:51:50 +10:00
tok_has_next ( & tok ) ;
tok_next ( & tok ) )
{
int tok_begin = tok_get_pos ( & tok ) ;
int tok_end = tok_begin ;
/*
Calculate end of token
*/
if ( tok_last_type ( & tok ) = = TOK_STRING )
2007-01-16 03:51:44 +10:00
{
2006-01-31 02:51:50 +10:00
tok_end + = wcslen ( tok_last ( & tok ) ) ;
2007-01-16 03:51:44 +10:00
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
/*
Cursor was before beginning of this token , means that the
cursor is between two tokens , so we set it to a zero element
string and break
*/
if ( tok_begin > pos )
{
2006-06-14 23:22:40 +10:00
a = b = ( wchar_t * ) buff + pos ;
2006-01-31 02:51:50 +10:00
break ;
}
/*
If cursor is inside the token , this is the token we are
looking for . If so , set a and b and break
*/
2006-07-24 22:46:29 +10:00
if ( ( tok_last_type ( & tok ) = = TOK_STRING ) & & ( tok_end > = pos ) )
2011-12-26 19:18:46 -08:00
{
2006-01-31 02:51:50 +10:00
a = begin + tok_get_pos ( & tok ) ;
b = a + wcslen ( tok_last ( & tok ) ) ;
break ;
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
/*
Remember previous string token
*/
if ( tok_last_type ( & tok ) = = TOK_STRING )
{
pa = begin + tok_get_pos ( & tok ) ;
pb = pa + wcslen ( tok_last ( & tok ) ) ;
}
}
free ( buffcpy ) ;
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
tok_destroy ( & tok ) ;
if ( tok_begin )
2007-01-16 03:51:44 +10:00
{
2006-01-31 02:51:50 +10:00
* tok_begin = a ;
2007-01-16 03:51:44 +10:00
}
2006-01-31 02:51:50 +10:00
if ( tok_end )
2007-01-16 03:51:44 +10:00
{
2006-01-31 02:51:50 +10:00
* tok_end = b ;
2007-01-16 03:51:44 +10:00
}
2006-01-31 02:51:50 +10:00
if ( prev_begin )
2007-01-16 03:51:44 +10:00
{
2006-01-31 02:51:50 +10:00
* prev_begin = pa ;
2007-01-16 03:51:44 +10:00
}
2006-01-31 02:51:50 +10:00
if ( prev_end )
2007-01-16 03:51:44 +10:00
{
2006-01-31 02:51:50 +10:00
* prev_end = pb ;
2007-01-16 03:51:44 +10:00
}
2011-12-26 19:18:46 -08:00
2006-01-31 02:51:50 +10:00
assert ( pa > = buff ) ;
assert ( pa < = ( buff + wcslen ( buff ) ) ) ;
assert ( pb > = pa ) ;
assert ( pb < = ( buff + wcslen ( buff ) ) ) ;
}
2012-01-29 22:06:58 -08:00
void parse_util_set_argv ( const wchar_t * const * argv , const wcstring_list_t & named_arguments )
2006-02-15 05:56:36 +10:00
{
if ( * argv )
{
2012-01-29 22:06:58 -08:00
const wchar_t * const * arg ;
2012-02-22 12:00:02 -08:00
wcstring sb ;
2011-12-26 19:18:46 -08:00
2006-02-15 05:56:36 +10:00
for ( arg = argv ; * arg ; arg + + )
{
if ( arg ! = argv )
2007-01-16 03:51:44 +10:00
{
2012-02-22 12:00:02 -08:00
sb . append ( ARRAY_SEP_STR ) ;
2007-01-16 03:51:44 +10:00
}
2012-02-22 12:00:02 -08:00
sb . append ( * arg ) ;
2006-02-15 05:56:36 +10:00
}
2011-12-26 19:18:46 -08:00
2012-02-22 12:00:02 -08:00
env_set ( L " argv " , sb . c_str ( ) , ENV_LOCAL ) ;
2006-02-15 05:56:36 +10:00
}
else
{
env_set ( L " argv " , 0 , ENV_LOCAL ) ;
2011-12-26 19:18:46 -08:00
}
2007-04-17 06:06:11 +10:00
2012-01-13 23:44:18 -08:00
if ( named_arguments . size ( ) )
2007-04-17 06:06:11 +10:00
{
2012-01-29 22:06:58 -08:00
const wchar_t * const * arg ;
2012-01-13 23:44:18 -08:00
size_t i ;
2011-12-26 19:18:46 -08:00
2012-01-13 23:44:18 -08:00
for ( i = 0 , arg = argv ; i < named_arguments . size ( ) ; i + + )
2007-04-17 06:06:11 +10:00
{
2012-01-13 23:44:18 -08:00
env_set ( named_arguments . at ( i ) . c_str ( ) , * arg , ENV_LOCAL ) ;
2007-04-17 06:06:11 +10:00
if ( * arg )
arg + + ;
}
2011-12-26 19:18:46 -08:00
2007-04-17 06:06:11 +10:00
}
2011-12-26 19:18:46 -08:00
2006-02-15 05:56:36 +10:00
}
2006-02-19 11:14:32 +10:00
wchar_t * parse_util_unescape_wildcards ( const wchar_t * str )
{
wchar_t * in , * out ;
2006-07-13 00:22:42 +10:00
wchar_t * unescaped ;
CHECK ( str , 0 ) ;
2011-12-26 19:18:46 -08:00
2006-07-13 00:22:42 +10:00
unescaped = wcsdup ( str ) ;
2006-02-19 11:14:32 +10:00
if ( ! unescaped )
2007-01-16 03:51:44 +10:00
{
2006-07-03 20:39:57 +10:00
DIE_MEM ( ) ;
2007-01-16 03:51:44 +10:00
}
2011-12-26 19:18:46 -08:00
2006-02-19 11:14:32 +10:00
for ( in = out = unescaped ; * in ; in + + )
{
switch ( * in )
{
case L ' \\ ' :
2007-01-16 03:51:44 +10:00
{
2012-07-02 11:52:18 +08:00
switch ( * ( in + 1 ) )
{
case L ' * ' :
case L ' ? ' :
{
in + + ;
* ( out + + ) = * in ;
break ;
}
case L ' \\ ' :
{
in + + ;
* ( out + + ) = L ' \\ ' ;
* ( out + + ) = L ' \\ ' ;
break ;
}
default :
{
* ( out + + ) = * in ;
break ;
}
}
2006-02-19 11:14:32 +10:00
break ;
2007-01-16 03:51:44 +10:00
}
2011-12-26 19:18:46 -08:00
2006-02-19 11:14:32 +10:00
case L ' * ' :
2007-01-16 03:51:44 +10:00
{
2011-12-26 19:18:46 -08:00
* ( out + + ) = ANY_STRING ;
2006-02-19 11:14:32 +10:00
break ;
2007-01-16 03:51:44 +10:00
}
2011-12-26 19:18:46 -08:00
2006-02-19 11:14:32 +10:00
case L ' ? ' :
2007-01-16 03:51:44 +10:00
{
2011-12-26 19:18:46 -08:00
* ( out + + ) = ANY_CHAR ;
2006-02-19 11:14:32 +10:00
break ;
2007-01-16 03:51:44 +10:00
}
2011-12-26 19:18:46 -08:00
2006-02-19 11:14:32 +10:00
default :
2007-01-16 03:51:44 +10:00
{
2006-02-19 11:14:32 +10:00
* ( out + + ) = * in ;
break ;
2007-01-16 03:51:44 +10:00
}
2011-12-26 19:18:46 -08:00
}
2006-02-19 11:14:32 +10:00
}
2012-07-02 11:19:30 +08:00
* out = * in ;
2006-02-19 11:14:32 +10:00
return unescaped ;
}
2006-02-15 05:56:36 +10:00
2012-07-06 14:34:53 -07:00
/**
Find the outermost quoting style of current token . Returns 0 if
token is not quoted .
*/
2012-07-28 17:49:46 -07:00
static wchar_t get_quote ( const wchar_t * cmd , size_t len )
2012-07-06 14:34:53 -07:00
{
2012-07-28 17:49:46 -07:00
size_t i = 0 ;
2012-07-06 14:34:53 -07:00
wchar_t res = 0 ;
while ( 1 )
{
if ( ! cmd [ i ] )
break ;
if ( cmd [ i ] = = L ' \\ ' )
{
i + + ;
if ( ! cmd [ i ] )
break ;
i + + ;
}
else
{
if ( cmd [ i ] = = L ' \' ' | | cmd [ i ] = = L ' \" ' )
{
const wchar_t * end = quote_end ( & cmd [ i ] ) ;
//fwprintf( stderr, L"Jump %d\n", end-cmd );
if ( ( end = = 0 ) | | ( ! * end ) | | ( end - cmd > len ) )
{
res = cmd [ i ] ;
break ;
}
i = end - cmd + 1 ;
}
else
i + + ;
}
}
return res ;
}
void parse_util_get_parameter_info ( const wcstring & cmd , const size_t pos , wchar_t * quote , size_t * offset , int * type )
{
size_t prev_pos = 0 ;
wchar_t last_quote = ' \0 ' ;
int unfinished ;
tokenizer tok ;
tok_init ( & tok , cmd . c_str ( ) , TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS ) ;
for ( ; tok_has_next ( & tok ) ; tok_next ( & tok ) )
{
if ( tok_get_pos ( & tok ) > pos )
break ;
if ( tok_last_type ( & tok ) = = TOK_STRING )
last_quote = get_quote ( tok_last ( & tok ) ,
pos - tok_get_pos ( & tok ) ) ;
if ( type ! = NULL )
* type = tok_last_type ( & tok ) ;
prev_pos = tok_get_pos ( & tok ) ;
}
tok_destroy ( & tok ) ;
wchar_t * cmd_tmp = wcsdup ( cmd . c_str ( ) ) ;
cmd_tmp [ pos ] = 0 ;
2012-07-28 17:49:46 -07:00
size_t cmdlen = wcslen ( cmd_tmp ) ;
2012-07-06 14:34:53 -07:00
unfinished = ( cmdlen = = 0 ) ;
if ( ! unfinished )
{
unfinished = ( quote ! = 0 ) ;
if ( ! unfinished )
{
if ( wcschr ( L " \t \n \r " , cmd_tmp [ cmdlen - 1 ] ) ! = 0 )
{
if ( ( cmdlen = = 1 ) | | ( cmd_tmp [ cmdlen - 2 ] ! = L ' \\ ' ) )
{
unfinished = 1 ;
}
}
}
}
if ( quote )
* quote = last_quote ;
if ( offset ! = 0 )
{
if ( ! unfinished )
{
while ( ( cmd_tmp [ prev_pos ] ! = 0 ) & & ( wcschr ( L " ;| " , cmd_tmp [ prev_pos ] ) ! = 0 ) )
prev_pos + + ;
* offset = prev_pos ;
}
else
{
* offset = pos ;
}
}
free ( cmd_tmp ) ;
}
wcstring parse_util_escape_string_with_quote ( const wcstring & cmd , wchar_t quote )
{
wcstring result ;
if ( quote = = L ' \0 ' )
{
result = escape_string ( cmd , ESCAPE_ALL | ESCAPE_NO_QUOTED | ESCAPE_NO_TILDE ) ;
}
else
{
bool unescapable = false ;
for ( size_t i = 0 ; i < cmd . size ( ) ; i + + )
{
wchar_t c = cmd . at ( i ) ;
switch ( c )
{
case L ' \n ' :
case L ' \t ' :
case L ' \b ' :
case L ' \r ' :
unescapable = true ;
break ;
default :
if ( c = = quote )
result . push_back ( L ' \\ ' ) ;
result . push_back ( c ) ;
break ;
}
}
if ( unescapable )
{
result = escape_string ( cmd , ESCAPE_ALL | ESCAPE_NO_QUOTED ) ;
result . insert ( 0 , & quote , 1 ) ;
}
}
return result ;
}