# HG changeset patch # User ZyX <kp-...@ya.ru> # Date 1383490773 -14400 # Sun Nov 03 18:59:33 2013 +0400 # Branch NL-funcs # Node ID d15f8c220a1f84d0b372272adfe430b7a599f486 # Parent 5d29bb3409c9e046fb7a08dcc585dc80362bf758 Add third optional argument to getreg()
Note: it appears that getreg(), getregtype(), setreg() and let-@ are not tested anywhere. diff -r 5d29bb3409c9 -r d15f8c220a1f runtime/doc/eval.txt --- a/runtime/doc/eval.txt Sun Nov 03 17:56:33 2013 +0400 +++ b/runtime/doc/eval.txt Sun Nov 03 18:59:33 2013 +0400 @@ -1799,7 +1799,9 @@ getpid() Number process ID of Vim getpos( {expr}) List position of cursor, mark, etc. getqflist() List list of quickfix items -getreg( [{regname} [, 1]]) String contents of register +getreg( [{regname} [, 1 [, {list}]]]) + String or List + contents of register getregtype( [{regname}]) String type of register gettabvar( {nr}, {varname} [, {def}]) any variable {varname} in tab {nr} or {def} @@ -3436,7 +3438,7 @@ :endfor -getreg([{regname} [, 1]]) *getreg()* +getreg([{regname} [, 1 [, {list}]]]) *getreg()* The result is a String, which is the contents of register {regname}. Example: > :let cliptext = getreg('*') @@ -3445,6 +3447,11 @@ getreg('=', 1) returns the expression itself, so that it can be restored with |setreg()|. For other registers the extra argument is ignored, thus you can always give it. + If {list} is present and non-zero result type is changed to + |List|. Resulting list is similar to |getline()| output with + two arguments. Use it if you care about zero bytes possibly + present inside register: without third argument both NLs and + zero bytes are represented as NLs (see |NL-used-for-Nul|). If {regname} is not specified, |v:register| is used. diff -r 5d29bb3409c9 -r d15f8c220a1f src/eval.c --- a/src/eval.c Sun Nov 03 17:56:33 2013 +0400 +++ b/src/eval.c Sun Nov 03 18:59:33 2013 +0400 @@ -2297,6 +2297,51 @@ } /* + * Convert char_u ** strings array to a list. + * Array must be in allocated memory itself, and so must be all contained + * strings. + * Array is freed afterwards. + */ + static int +char_arr_to_tv(strings, rettv) + char_u **strings; + typval_T *rettv; +{ + char_u **s; + listitem_T *li; + + rettv->vval.v_list = list_alloc(); + if (rettv->vval.v_list == NULL) + return FAIL; + + if (strings == NULL) + { + rettv->v_type = VAR_LIST; + return OK; + } + + for (s = strings ; *s != NULL ; ++s) + { + li = listitem_alloc(); + if (li == NULL) + { + list_free(rettv->vval.v_list, TRUE); + rettv->vval.v_list = NULL; + vim_free(strings); + return FAIL; + } + + li->li_tv.v_type = VAR_STRING; + li->li_tv.vval.v_string = *s; + list_append(rettv->vval.v_list, li); + } + + vim_free(strings); + rettv->v_type = VAR_LIST; + return OK; +} + +/* * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value. * Returns a pointer to the char just after the var name. * Returns NULL if there is an error. @@ -2448,7 +2493,7 @@ p = get_tv_string_chk(tv); if (p != NULL && op != NULL && *op == '.') { - s = get_reg_contents(*arg == '@' ? '"' : *arg, TRUE, TRUE); + s = get_reg_contents(*arg == '@' ? '"' : *arg, GREG_EXPR_SRC); if (s != NULL) { p = ptofree = concat_str(s, p); @@ -5106,7 +5151,8 @@ if (evaluate) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = get_reg_contents(**arg, TRUE, TRUE); + rettv->vval.v_string = get_reg_contents(**arg, + GREG_EXPR_SRC); } if (**arg != NUL) ++*arg; @@ -7945,7 +7991,7 @@ {"getpid", 0, 0, f_getpid}, {"getpos", 1, 1, f_getpos}, {"getqflist", 0, 0, f_getqflist}, - {"getreg", 0, 2, f_getreg}, + {"getreg", 0, 3, f_getreg}, {"getregtype", 0, 1, f_getregtype}, {"gettabvar", 2, 3, f_gettabvar}, {"gettabwinvar", 3, 4, f_gettabwinvar}, @@ -11761,6 +11807,7 @@ char_u *strregname; int regname; int arg2 = FALSE; + int return_list = FALSE; int error = FALSE; if (argvars[0].v_type != VAR_UNKNOWN) @@ -11768,17 +11815,35 @@ strregname = get_tv_string_chk(&argvars[0]); error = strregname == NULL; if (argvars[1].v_type != VAR_UNKNOWN) + { arg2 = get_tv_number_chk(&argvars[1], &error); + if (!error && argvars[2].v_type != VAR_UNKNOWN) + return_list = get_tv_number_chk(&argvars[2], &error); + } } else strregname = vimvars[VV_REG].vv_str; + + if (error) + return; + regname = (strregname == NULL ? '"' : *strregname); if (regname == 0) regname = '"'; - rettv->v_type = VAR_STRING; - rettv->vval.v_string = error ? NULL : - get_reg_contents(regname, TRUE, arg2); + if (return_list) + { + char_u **strings; + strings = (char_u **) get_reg_contents(regname, + (arg2 ? GREG_EXPR_SRC : 0) | GREG_LIST); + char_arr_to_tv(strings, rettv); + } + else + { + rettv->v_type = VAR_STRING; + rettv->vval.v_string = get_reg_contents(regname, + arg2 ? GREG_EXPR_SRC : 0); + } } /* @@ -17787,10 +17852,6 @@ if (error) return; - rettv->vval.v_list = list_alloc(); - if (rettv->vval.v_list == NULL) - return; - match = reg_submatch_list(no); if (match == NULL) { @@ -17798,24 +17859,7 @@ return; } - for (s = match ; *s != NULL ; s++) - { - li = listitem_alloc(); - if (li == NULL) - { - list_free(rettv->vval.v_list, TRUE); - rettv->vval.v_list = NULL; - vim_free(match); - return; - } - - li->li_tv.v_type = VAR_STRING; - li->li_tv.vval.v_string = *s; - list_append(rettv->vval.v_list, li); - } - - vim_free(match); - rettv->v_type = VAR_LIST; + char_arr_to_tv(match, rettv); } } diff -r 5d29bb3409c9 -r d15f8c220a1f src/ops.c --- a/src/ops.c Sun Nov 03 17:56:33 2013 +0400 +++ b/src/ops.c Sun Nov 03 18:59:33 2013 +0400 @@ -6201,15 +6201,40 @@ } /* + * Wrap char_u * line inside an allocated char_u ** in case flags contains + * GREG_EXPR_SRC and leave it as-is otherwise. + */ + static char_u * +getreg_wrap_one_line(s, flags) + char_u *s; + int flags; +{ + char_u **retval; + if (flags & GREG_LIST) + { + retval = (char_u **)alloc(sizeof(char_u *) * 2); + retval[0] = s; + retval[1] = NULL; + } + else + retval = (char_u **) s; + return (char_u *) retval; +} + +/* * Return the contents of a register as a single allocated string. * Used for "@r" in expressions and for getreg(). * Returns NULL for error. + * Flags: + * GREG_NO_EXPR Do not allow expression register + * GREG_EXPR_SRC For the expression register: return expression itself, + * not the result of its evaluation. + * GREG_LIST Return a list of lines in place of a single string. */ char_u * -get_reg_contents(regname, allowexpr, expr_src) +get_reg_contents(regname, flags) int regname; - int allowexpr; /* allow "=" register */ - int expr_src; /* get expression for "=" register */ + int flags; { long i; char_u *retval; @@ -6219,13 +6244,11 @@ /* Don't allow using an expression register inside an expression */ if (regname == '=') { - if (allowexpr) - { - if (expr_src) - return get_expr_line_src(); - return get_expr_line(); - } - return NULL; + if (flags & GREG_NO_EXPR) + return NULL; + if (flags & GREG_EXPR_SRC) + return getreg_wrap_one_line(get_expr_line_src(), flags); + return getreg_wrap_one_line(get_expr_line(), flags); } if (regname == '@') /* "@@" is used for unnamed register */ @@ -6243,8 +6266,10 @@ { if (retval == NULL) return NULL; - if (!allocated) - retval = vim_strsave(retval); + if (allocated) + retval = getreg_wrap_one_line(retval, flags); + else + retval = getreg_wrap_one_line(vim_strsave(retval), flags); return retval; } @@ -6252,6 +6277,21 @@ if (y_current->y_array == NULL) return NULL; + if (flags & GREG_LIST) + { + char_u **retval_arr; + + retval_arr = (char_u **) alloc(sizeof(char_u*) * (y_current->y_size+1)); + if (retval_arr == NULL) + return NULL; + + for (i = 0; i < y_current->y_size; ++i) + retval_arr[i] = vim_strsave(y_current->y_array[i]); + retval_arr[y_current->y_size] = NULL; + + return (char_u *) retval_arr; + } + /* * Compute length of resulting string. */ diff -r 5d29bb3409c9 -r d15f8c220a1f src/proto/ops.pro --- a/src/proto/ops.pro Sun Nov 03 17:56:33 2013 +0400 +++ b/src/proto/ops.pro Sun Nov 03 18:59:33 2013 +0400 @@ -53,7 +53,7 @@ int clip_convert_selection __ARGS((char_u **str, long_u *len, VimClipboard *cbd)); void dnd_yank_drag_data __ARGS((char_u *str, long len)); char_u get_reg_type __ARGS((int regname, long *reglen)); -char_u *get_reg_contents __ARGS((int regname, int allowexpr, int expr_src)); +char_u *get_reg_contents __ARGS((int regname, int flags)); void write_reg_contents __ARGS((int name, char_u *str, int maxlen, int must_append)); void write_reg_contents_ex __ARGS((int name, char_u *str, int maxlen, int must_append, int yank_type, long block_len)); void clear_oparg __ARGS((oparg_T *oap)); diff -r 5d29bb3409c9 -r d15f8c220a1f src/vim.h --- a/src/vim.h Sun Nov 03 17:56:33 2013 +0400 +++ b/src/vim.h Sun Nov 03 18:59:33 2013 +0400 @@ -2243,6 +2243,11 @@ #define SREQ_WIN 1 /* Request window-local option */ #define SREQ_BUF 2 /* Request buffer-local option */ +/* Flags for get_reg_contents */ +#define GREG_NO_EXPR 1 /* Do not allow expression register */ +#define GREG_EXPR_SRC 2 /* Return expression itself for "=" register */ +#define GREG_LIST 4 /* Return list */ + /* Character used as separated in autoload function/variable names. */ #define AUTOLOAD_CHAR '#' -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
diff -crN vim-small-patches.5d29bb3409c9/runtime/doc/eval.txt vim-small-patches.d15f8c220a1f/runtime/doc/eval.txt *** vim-small-patches.5d29bb3409c9/runtime/doc/eval.txt 2013-11-03 19:00:01.549089259 +0400 --- vim-small-patches.d15f8c220a1f/runtime/doc/eval.txt 2013-11-03 19:00:01.589089260 +0400 *************** *** 1799,1805 **** getpid() Number process ID of Vim getpos( {expr}) List position of cursor, mark, etc. getqflist() List list of quickfix items ! getreg( [{regname} [, 1]]) String contents of register getregtype( [{regname}]) String type of register gettabvar( {nr}, {varname} [, {def}]) any variable {varname} in tab {nr} or {def} --- 1799,1807 ---- getpid() Number process ID of Vim getpos( {expr}) List position of cursor, mark, etc. getqflist() List list of quickfix items ! getreg( [{regname} [, 1 [, {list}]]]) ! String or List ! contents of register getregtype( [{regname}]) String type of register gettabvar( {nr}, {varname} [, {def}]) any variable {varname} in tab {nr} or {def} *************** *** 3436,3442 **** :endfor ! getreg([{regname} [, 1]]) *getreg()* The result is a String, which is the contents of register {regname}. Example: > :let cliptext = getreg('*') --- 3438,3444 ---- :endfor ! getreg([{regname} [, 1 [, {list}]]]) *getreg()* The result is a String, which is the contents of register {regname}. Example: > :let cliptext = getreg('*') *************** *** 3445,3450 **** --- 3447,3457 ---- getreg('=', 1) returns the expression itself, so that it can be restored with |setreg()|. For other registers the extra argument is ignored, thus you can always give it. + If {list} is present and non-zero result type is changed to + |List|. Resulting list is similar to |getline()| output with + two arguments. Use it if you care about zero bytes possibly + present inside register: without third argument both NLs and + zero bytes are represented as NLs (see |NL-used-for-Nul|). If {regname} is not specified, |v:register| is used. diff -crN vim-small-patches.5d29bb3409c9/src/eval.c vim-small-patches.d15f8c220a1f/src/eval.c *** vim-small-patches.5d29bb3409c9/src/eval.c 2013-11-03 19:00:01.576089260 +0400 --- vim-small-patches.d15f8c220a1f/src/eval.c 2013-11-03 19:00:01.612089261 +0400 *************** *** 2297,2302 **** --- 2297,2347 ---- } /* + * Convert char_u ** strings array to a list. + * Array must be in allocated memory itself, and so must be all contained + * strings. + * Array is freed afterwards. + */ + static int + char_arr_to_tv(strings, rettv) + char_u **strings; + typval_T *rettv; + { + char_u **s; + listitem_T *li; + + rettv->vval.v_list = list_alloc(); + if (rettv->vval.v_list == NULL) + return FAIL; + + if (strings == NULL) + { + rettv->v_type = VAR_LIST; + return OK; + } + + for (s = strings ; *s != NULL ; ++s) + { + li = listitem_alloc(); + if (li == NULL) + { + list_free(rettv->vval.v_list, TRUE); + rettv->vval.v_list = NULL; + vim_free(strings); + return FAIL; + } + + li->li_tv.v_type = VAR_STRING; + li->li_tv.vval.v_string = *s; + list_append(rettv->vval.v_list, li); + } + + vim_free(strings); + rettv->v_type = VAR_LIST; + return OK; + } + + /* * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value. * Returns a pointer to the char just after the var name. * Returns NULL if there is an error. *************** *** 2448,2454 **** p = get_tv_string_chk(tv); if (p != NULL && op != NULL && *op == '.') { ! s = get_reg_contents(*arg == '@' ? '"' : *arg, TRUE, TRUE); if (s != NULL) { p = ptofree = concat_str(s, p); --- 2493,2499 ---- p = get_tv_string_chk(tv); if (p != NULL && op != NULL && *op == '.') { ! s = get_reg_contents(*arg == '@' ? '"' : *arg, GREG_EXPR_SRC); if (s != NULL) { p = ptofree = concat_str(s, p); *************** *** 5106,5112 **** if (evaluate) { rettv->v_type = VAR_STRING; ! rettv->vval.v_string = get_reg_contents(**arg, TRUE, TRUE); } if (**arg != NUL) ++*arg; --- 5151,5158 ---- if (evaluate) { rettv->v_type = VAR_STRING; ! rettv->vval.v_string = get_reg_contents(**arg, ! GREG_EXPR_SRC); } if (**arg != NUL) ++*arg; *************** *** 7945,7951 **** {"getpid", 0, 0, f_getpid}, {"getpos", 1, 1, f_getpos}, {"getqflist", 0, 0, f_getqflist}, ! {"getreg", 0, 2, f_getreg}, {"getregtype", 0, 1, f_getregtype}, {"gettabvar", 2, 3, f_gettabvar}, {"gettabwinvar", 3, 4, f_gettabwinvar}, --- 7991,7997 ---- {"getpid", 0, 0, f_getpid}, {"getpos", 1, 1, f_getpos}, {"getqflist", 0, 0, f_getqflist}, ! {"getreg", 0, 3, f_getreg}, {"getregtype", 0, 1, f_getregtype}, {"gettabvar", 2, 3, f_gettabvar}, {"gettabwinvar", 3, 4, f_gettabwinvar}, *************** *** 11761,11766 **** --- 11807,11813 ---- char_u *strregname; int regname; int arg2 = FALSE; + int return_list = FALSE; int error = FALSE; if (argvars[0].v_type != VAR_UNKNOWN) *************** *** 11768,11784 **** strregname = get_tv_string_chk(&argvars[0]); error = strregname == NULL; if (argvars[1].v_type != VAR_UNKNOWN) arg2 = get_tv_number_chk(&argvars[1], &error); } else strregname = vimvars[VV_REG].vv_str; regname = (strregname == NULL ? '"' : *strregname); if (regname == 0) regname = '"'; ! rettv->v_type = VAR_STRING; ! rettv->vval.v_string = error ? NULL : ! get_reg_contents(regname, TRUE, arg2); } /* --- 11815,11849 ---- strregname = get_tv_string_chk(&argvars[0]); error = strregname == NULL; if (argvars[1].v_type != VAR_UNKNOWN) + { arg2 = get_tv_number_chk(&argvars[1], &error); + if (!error && argvars[2].v_type != VAR_UNKNOWN) + return_list = get_tv_number_chk(&argvars[2], &error); + } } else strregname = vimvars[VV_REG].vv_str; + + if (error) + return; + regname = (strregname == NULL ? '"' : *strregname); if (regname == 0) regname = '"'; ! if (return_list) ! { ! char_u **strings; ! strings = (char_u **) get_reg_contents(regname, ! (arg2 ? GREG_EXPR_SRC : 0) | GREG_LIST); ! char_arr_to_tv(strings, rettv); ! } ! else ! { ! rettv->v_type = VAR_STRING; ! rettv->vval.v_string = get_reg_contents(regname, ! arg2 ? GREG_EXPR_SRC : 0); ! } } /* *************** *** 17787,17796 **** if (error) return; - rettv->vval.v_list = list_alloc(); - if (rettv->vval.v_list == NULL) - return; - match = reg_submatch_list(no); if (match == NULL) { --- 17852,17857 ---- *************** *** 17798,17821 **** return; } ! for (s = match ; *s != NULL ; s++) ! { ! li = listitem_alloc(); ! if (li == NULL) ! { ! list_free(rettv->vval.v_list, TRUE); ! rettv->vval.v_list = NULL; ! vim_free(match); ! return; ! } ! ! li->li_tv.v_type = VAR_STRING; ! li->li_tv.vval.v_string = *s; ! list_append(rettv->vval.v_list, li); ! } ! ! vim_free(match); ! rettv->v_type = VAR_LIST; } } --- 17859,17865 ---- return; } ! char_arr_to_tv(match, rettv); } } diff -crN vim-small-patches.5d29bb3409c9/src/ops.c vim-small-patches.d15f8c220a1f/src/ops.c *** vim-small-patches.5d29bb3409c9/src/ops.c 2013-11-03 19:00:01.552089259 +0400 --- vim-small-patches.d15f8c220a1f/src/ops.c 2013-11-03 19:00:01.592089260 +0400 *************** *** 6201,6215 **** } /* * Return the contents of a register as a single allocated string. * Used for "@r" in expressions and for getreg(). * Returns NULL for error. */ char_u * ! get_reg_contents(regname, allowexpr, expr_src) int regname; ! int allowexpr; /* allow "=" register */ ! int expr_src; /* get expression for "=" register */ { long i; char_u *retval; --- 6201,6240 ---- } /* + * Wrap char_u * line inside an allocated char_u ** in case flags contains + * GREG_EXPR_SRC and leave it as-is otherwise. + */ + static char_u * + getreg_wrap_one_line(s, flags) + char_u *s; + int flags; + { + char_u **retval; + if (flags & GREG_LIST) + { + retval = (char_u **)alloc(sizeof(char_u *) * 2); + retval[0] = s; + retval[1] = NULL; + } + else + retval = (char_u **) s; + return (char_u *) retval; + } + + /* * Return the contents of a register as a single allocated string. * Used for "@r" in expressions and for getreg(). * Returns NULL for error. + * Flags: + * GREG_NO_EXPR Do not allow expression register + * GREG_EXPR_SRC For the expression register: return expression itself, + * not the result of its evaluation. + * GREG_LIST Return a list of lines in place of a single string. */ char_u * ! get_reg_contents(regname, flags) int regname; ! int flags; { long i; char_u *retval; *************** *** 6219,6231 **** /* Don't allow using an expression register inside an expression */ if (regname == '=') { ! if (allowexpr) ! { ! if (expr_src) ! return get_expr_line_src(); ! return get_expr_line(); ! } ! return NULL; } if (regname == '@') /* "@@" is used for unnamed register */ --- 6244,6254 ---- /* Don't allow using an expression register inside an expression */ if (regname == '=') { ! if (flags & GREG_NO_EXPR) ! return NULL; ! if (flags & GREG_EXPR_SRC) ! return getreg_wrap_one_line(get_expr_line_src(), flags); ! return getreg_wrap_one_line(get_expr_line(), flags); } if (regname == '@') /* "@@" is used for unnamed register */ *************** *** 6243,6250 **** { if (retval == NULL) return NULL; ! if (!allocated) ! retval = vim_strsave(retval); return retval; } --- 6266,6275 ---- { if (retval == NULL) return NULL; ! if (allocated) ! retval = getreg_wrap_one_line(retval, flags); ! else ! retval = getreg_wrap_one_line(vim_strsave(retval), flags); return retval; } *************** *** 6252,6257 **** --- 6277,6297 ---- if (y_current->y_array == NULL) return NULL; + if (flags & GREG_LIST) + { + char_u **retval_arr; + + retval_arr = (char_u **) alloc(sizeof(char_u*) * (y_current->y_size+1)); + if (retval_arr == NULL) + return NULL; + + for (i = 0; i < y_current->y_size; ++i) + retval_arr[i] = vim_strsave(y_current->y_array[i]); + retval_arr[y_current->y_size] = NULL; + + return (char_u *) retval_arr; + } + /* * Compute length of resulting string. */ diff -crN vim-small-patches.5d29bb3409c9/src/proto/ops.pro vim-small-patches.d15f8c220a1f/src/proto/ops.pro *** vim-small-patches.5d29bb3409c9/src/proto/ops.pro 2013-11-03 19:00:01.577089260 +0400 --- vim-small-patches.d15f8c220a1f/src/proto/ops.pro 2013-11-03 19:00:01.613089261 +0400 *************** *** 53,59 **** int clip_convert_selection __ARGS((char_u **str, long_u *len, VimClipboard *cbd)); void dnd_yank_drag_data __ARGS((char_u *str, long len)); char_u get_reg_type __ARGS((int regname, long *reglen)); ! char_u *get_reg_contents __ARGS((int regname, int allowexpr, int expr_src)); void write_reg_contents __ARGS((int name, char_u *str, int maxlen, int must_append)); void write_reg_contents_ex __ARGS((int name, char_u *str, int maxlen, int must_append, int yank_type, long block_len)); void clear_oparg __ARGS((oparg_T *oap)); --- 53,59 ---- int clip_convert_selection __ARGS((char_u **str, long_u *len, VimClipboard *cbd)); void dnd_yank_drag_data __ARGS((char_u *str, long len)); char_u get_reg_type __ARGS((int regname, long *reglen)); ! char_u *get_reg_contents __ARGS((int regname, int flags)); void write_reg_contents __ARGS((int name, char_u *str, int maxlen, int must_append)); void write_reg_contents_ex __ARGS((int name, char_u *str, int maxlen, int must_append, int yank_type, long block_len)); void clear_oparg __ARGS((oparg_T *oap)); diff -crN vim-small-patches.5d29bb3409c9/src/vim.h vim-small-patches.d15f8c220a1f/src/vim.h *** vim-small-patches.5d29bb3409c9/src/vim.h 2013-11-03 19:00:01.540089259 +0400 --- vim-small-patches.d15f8c220a1f/src/vim.h 2013-11-03 19:00:01.580089260 +0400 *************** *** 2243,2248 **** --- 2243,2253 ---- #define SREQ_WIN 1 /* Request window-local option */ #define SREQ_BUF 2 /* Request buffer-local option */ + /* Flags for get_reg_contents */ + #define GREG_NO_EXPR 1 /* Do not allow expression register */ + #define GREG_EXPR_SRC 2 /* Return expression itself for "=" register */ + #define GREG_LIST 4 /* Return list */ + /* Character used as separated in autoload function/variable names. */ #define AUTOLOAD_CHAR '#'