summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-01-23 19:46:28 +0100
committerBram Moolenaar <Bram@vim.org>2016-01-23 19:46:28 +0100
commit520e1e41f35b063ede63b41738c82d6636e78c34 (patch)
tree4c6a94e4e8f3f2047b91886077d4ecb916b30401
parent6920c72d4d62c8dc5596e9f392e38204f561d7af (diff)
patch 7.4.1154v7.4.1154
Problem: No support for JSON. Solution: Add jsonencode() and jsondecode(). Also add v:false, v:true, v:null and v:none.
-rw-r--r--Filelist2
-rw-r--r--runtime/doc/eval.txt41
-rw-r--r--src/Make_bc3.mak1
-rw-r--r--src/Make_bc5.mak1
-rw-r--r--src/Make_cyg_ming.mak1
-rw-r--r--src/Make_dice.mak4
-rw-r--r--src/Make_ivc.mak5
-rw-r--r--src/Make_manx.mak6
-rw-r--r--src/Make_morph.mak1
-rw-r--r--src/Make_mvc.mak4
-rw-r--r--src/Make_sas.mak5
-rw-r--r--src/Make_vms.mms10
-rw-r--r--src/Makefile23
-rw-r--r--src/eval.c107
-rw-r--r--src/globals.h1
-rw-r--r--src/if_lua.c8
-rw-r--r--src/if_mzsch.c14
-rw-r--r--src/if_py_both.h19
-rw-r--r--src/if_ruby.c5
-rw-r--r--src/json.c509
-rw-r--r--src/proto.h1
-rw-r--r--src/proto/eval.pro5
-rw-r--r--src/proto/json.pro5
-rw-r--r--src/structs.h13
-rw-r--r--src/testdir/test_alot.vim1
-rw-r--r--src/testdir/test_json.vim91
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h12
28 files changed, 863 insertions, 34 deletions
diff --git a/Filelist b/Filelist
index 34ff0bd26c..0032b76241 100644
--- a/Filelist
+++ b/Filelist
@@ -40,6 +40,7 @@ SRC_ALL = \
src/hardcopy.c \
src/hashtab.c \
src/keymap.h \
+ src/json.c \
src/macros.h \
src/main.c \
src/mark.c \
@@ -132,6 +133,7 @@ SRC_ALL = \
src/proto/gui_beval.pro \
src/proto/hardcopy.pro \
src/proto/hashtab.pro \
+ src/proto/json.pro \
src/proto/main.pro \
src/proto/mark.pro \
src/proto/mbyte.pro \
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 2073f289e4..c227d0c4be 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt* For Vim version 7.4. Last change: 2016 Jan 21
+*eval.txt* For Vim version 7.4. Last change: 2016 Jan 23
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1409,6 +1409,10 @@ v:exception The value of the exception most recently caught and not
:endtry
< Output: "caught oops".
+ *v:false* *false-variable*
+v:false A Number with value zero. Used to put "false" in JSON. See
+ |jsonencode()|.
+
*v:fcs_reason* *fcs_reason-variable*
v:fcs_reason The reason why the |FileChangedShell| event was triggered.
Can be used in an autocommand to decide what to do and/or what
@@ -1542,6 +1546,14 @@ v:mouse_col Column number for a mouse click obtained with |getchar()|.
This is the screen column number, like with |virtcol()|. The
value is zero when there was no mouse button click.
+ *v:none* *none-variable*
+v:none An empty String. Used to put an empty item in JSON. See
+ |jsonencode()|.
+
+ *v:null* *null-variable*
+v:null An empty String. Used to put "null" in JSON. See
+ |jsonencode()|.
+
*v:oldfiles* *oldfiles-variable*
v:oldfiles List of file names that is loaded from the |viminfo| file on
startup. These are the files that Vim remembers marks for.
@@ -1707,6 +1719,10 @@ v:throwpoint The point where the exception most recently caught and not
:endtry
< Output: "Exception from test.vim, line 2"
+ *v:true* *true-variable*
+v:true A Number with value one. Used to put "true" in JSON. See
+ |jsonencode()|.
+
*v:val* *val-variable*
v:val Value of the current item of a |List| or |Dictionary|. Only
valid while evaluating the expression used with |map()| and
@@ -1913,6 +1929,8 @@ isdirectory( {directory}) Number TRUE if {directory} is a directory
islocked( {expr}) Number TRUE if {expr} is locked
items( {dict}) List key-value pairs in {dict}
join( {list} [, {sep}]) String join {list} items into one String
+jsondecode( {string}) any decode JSON
+jsonencode( {expr}) String encode JSON
keys( {dict}) List keys in {dict}
len( {expr}) Number the length of {expr}
libcall( {lib}, {func}, {arg}) String call {func} in library {lib} with {arg}
@@ -4215,6 +4233,27 @@ join({list} [, {sep}]) *join()*
converted into a string like with |string()|.
The opposite function is |split()|.
+jsondecode({string}) *jsondecode()*
+ TODO
+
+jsonencode({expr}) *jsonencode()*
+ Encodode {expr} as JSON and return this as a string.
+ The encoding is specified in:
+ http://www.ietf.org/rfc/rfc4627.txt
+ Vim values are converted as follows:
+ Number decimal number
+ Float floating point number
+ String in double quotes (possibly null)
+ Funcref nothing
+ List as an array (possibly null); when
+ used recursively: []
+ Dict as an object (possibly null); when
+ used recursively: {}
+ v:false "false"
+ v:true "true"
+ v:none nothing
+ v:null "null"
+
keys({dict}) *keys()*
Return a |List| with all the keys of {dict}. The |List| is in
arbitrary order.
diff --git a/src/Make_bc3.mak b/src/Make_bc3.mak
index a23174fefb..0de7847663 100644
--- a/src/Make_bc3.mak
+++ b/src/Make_bc3.mak
@@ -72,6 +72,7 @@ EXE_dependencies = \
getchar.obj \
hardcopy.obj \
hashtab.obj \
+ json.obj \
main.obj \
mark.obj \
memfile.obj \
diff --git a/src/Make_bc5.mak b/src/Make_bc5.mak
index ddbdbe304a..8dcb6e8b4c 100644
--- a/src/Make_bc5.mak
+++ b/src/Make_bc5.mak
@@ -598,6 +598,7 @@ vimobj = \
$(OBJDIR)\getchar.obj \
$(OBJDIR)\hardcopy.obj \
$(OBJDIR)\hashtab.obj \
+ $(OBJDIR)\json.obj \
$(OBJDIR)\main.obj \
$(OBJDIR)\mark.obj \
$(OBJDIR)\memfile.obj \
diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak
index 203438a597..7c7acbd4b1 100644
--- a/src/Make_cyg_ming.mak
+++ b/src/Make_cyg_ming.mak
@@ -601,6 +601,7 @@ OBJ = \
$(OUTDIR)/getchar.o \
$(OUTDIR)/hardcopy.o \
$(OUTDIR)/hashtab.o \
+ $(OUTDIR)/json.o \
$(OUTDIR)/main.o \
$(OUTDIR)/mark.o \
$(OUTDIR)/memfile.o \
diff --git a/src/Make_dice.mak b/src/Make_dice.mak
index 890f15d09c..c20ba89ee4 100644
--- a/src/Make_dice.mak
+++ b/src/Make_dice.mak
@@ -45,6 +45,7 @@ SRC = \
getchar.c \
hardcopy.c \
hashtab.c \
+ json.c \
main.c \
mark.c \
memfile.c \
@@ -93,6 +94,7 @@ OBJ = o/blowfish.o \
o/getchar.o \
o/hardcopy.o \
o/hashtab.o \
+ o/json.o \
o/main.o \
o/mark.o \
o/memfile.o \
@@ -179,6 +181,8 @@ o/hardcopy.o: hardcopy.c $(SYMS)
o/hashtab.o: hashtab.c $(SYMS)
+o/json.o: json.c $(SYMS)
+
o/main.o: main.c $(SYMS)
o/mark.o: mark.c $(SYMS)
diff --git a/src/Make_ivc.mak b/src/Make_ivc.mak
index a891a9743b..2dbe95768c 100644
--- a/src/Make_ivc.mak
+++ b/src/Make_ivc.mak
@@ -229,6 +229,7 @@ LINK32_OBJS= \
"$(INTDIR)/getchar.obj" \
"$(INTDIR)/hardcopy.obj" \
"$(INTDIR)/hashtab.obj" \
+ "$(INTDIR)/json.obj" \
"$(INTDIR)/main.obj" \
"$(INTDIR)/mark.obj" \
"$(INTDIR)/mbyte.obj" \
@@ -555,6 +556,10 @@ SOURCE=.\if_ole.idl
# End Source File
# Begin Source File
+SOURCE=.\json.c
+# End Source File
+# Begin Source File
+
SOURCE=.\main.c
# End Source File
# Begin Source File
diff --git a/src/Make_manx.mak b/src/Make_manx.mak
index dd1311ac87..1574f056ef 100644
--- a/src/Make_manx.mak
+++ b/src/Make_manx.mak
@@ -55,6 +55,7 @@ SRC = blowfish.c \
getchar.c \
hardcopy.c \
hashtab.c \
+ json.c \
main.c \
mark.c \
memfile.c \
@@ -105,6 +106,7 @@ OBJ = obj/blowfish.o \
obj/getchar.o \
obj/hardcopy.o \
obj/hashtab.o \
+ obj/json.o \
obj/main.o \
obj/mark.o \
obj/memfile.o \
@@ -153,6 +155,7 @@ PRO = proto/blowfish.pro \
proto/getchar.pro \
proto/hardcopy.pro \
proto/hashtab.pro \
+ proto/json.pro \
proto/main.pro \
proto/mark.pro \
proto/memfile.pro \
@@ -284,6 +287,9 @@ obj/hardcopy.o: hardcopy.c
obj/hashtab.o: hashtab.c
$(CCSYM) $@ hashtab.c
+obj/json.o: json.c
+ $(CCSYM) $@ json.c
+
# Don't use $(SYMS) here, because main.c defines EXTERN
obj/main.o: main.c option.h globals.h
$(CCNOSYM) $@ main.c
diff --git a/src/Make_morph.mak b/src/Make_morph.mak
index 15a74773c2..2f2f08b8e2 100644
--- a/src/Make_morph.mak
+++ b/src/Make_morph.mak
@@ -43,6 +43,7 @@ SRC = blowfish.c \
getchar.c \
hardcopy.c \
hashtab.c \
+ json.c \
main.c \
mark.c \
mbyte.c \
diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak
index 217df5710a..c009aa9777 100644
--- a/src/Make_mvc.mak
+++ b/src/Make_mvc.mak
@@ -536,6 +536,7 @@ OBJ = \
$(OUTDIR)\getchar.obj \
$(OUTDIR)\hardcopy.obj \
$(OUTDIR)\hashtab.obj \
+ $(OUTDIR)\json.obj \
$(OUTDIR)\main.obj \
$(OUTDIR)\mark.obj \
$(OUTDIR)\mbyte.obj \
@@ -1202,6 +1203,8 @@ $(OUTDIR)/if_sniff.obj: $(OUTDIR) if_sniff.c $(INCL)
$(OUTDIR)/if_tcl.obj: $(OUTDIR) if_tcl.c $(INCL)
$(CC) $(CFLAGS) $(TCL_INC) if_tcl.c
+$(OUTDIR)/json.obj: $(OUTDIR) json.c $(INCL)
+
$(OUTDIR)/main.obj: $(OUTDIR) main.c $(INCL)
$(OUTDIR)/mark.obj: $(OUTDIR) mark.c $(INCL)
@@ -1329,6 +1332,7 @@ proto.h: \
proto/getchar.pro \
proto/hardcopy.pro \
proto/hashtab.pro \
+ proto/json.pro \
proto/main.pro \
proto/mark.pro \
proto/memfile.pro \
diff --git a/src/Make_sas.mak b/src/Make_sas.mak
index 49dcb6bdcd..6d2ca844f4 100644
--- a/src/Make_sas.mak
+++ b/src/Make_sas.mak
@@ -108,6 +108,7 @@ SRC = \
getchar.c \
hardcopy.c \
hashtab.c \
+ json.c \
main.c \
mark.c \
memfile.c \
@@ -157,6 +158,7 @@ OBJ = \
getchar.o \
hardcopy.o \
hashtab.o \
+ json.o \
main.o \
mark.o \
memfile.o \
@@ -206,6 +208,7 @@ PRO = \
proto/getchar.pro \
proto/hardcopy.pro \
proto/hashtab.pro \
+ proto/json.pro \
proto/main.pro \
proto/mark.pro \
proto/memfile.pro \
@@ -328,6 +331,8 @@ hardcopy.o: hardcopy.c
proto/hardcopy.pro: hardcopy.c
hashtab.o: hashtab.c
proto/hashtab.pro: hashtab.c
+json.o: json.c
+proto/json.pro: json.c
main.o: main.c
proto/main.pro: main.c
mark.o: mark.c
diff --git a/src/Make_vms.mms b/src/Make_vms.mms
index f19b688585..da535b90f5 100644
--- a/src/Make_vms.mms
+++ b/src/Make_vms.mms
@@ -2,7 +2,7 @@
# Makefile for Vim on OpenVMS
#
# Maintainer: Zoltan Arpadffy <arpadffy@polarhome.com>
-# Last change: 2014 Aug 10
+# Last change: 2016 Jan 22
#
# This has script been tested on VMS 6.2 to 8.2 on DEC Alpha, VAX and IA64
# with MMS and MMK
@@ -311,7 +311,7 @@ ALL_LIBS = $(LIBS) $(GUI_LIB_DIR) $(GUI_LIB) \
SRC = blowfish.c buffer.c charset.c crypt.c, crypt_zip.c diff.c digraph.c edit.c eval.c ex_cmds.c ex_cmds2.c \
ex_docmd.c ex_eval.c ex_getln.c if_xcmdsrv.c fileio.c fold.c getchar.c \
- hardcopy.c hashtab.c main.c mark.c menu.c mbyte.c memfile.c memline.c message.c misc1.c \
+ hardcopy.c hashtab.c json.c main.c mark.c menu.c mbyte.c memfile.c memline.c message.c misc1.c \
misc2.c move.c normal.c ops.c option.c popupmnu.c quickfix.c regexp.c search.c sha256.c\
spell.c syntax.c tag.c term.c termlib.c ui.c undo.c version.c screen.c \
window.c os_unix.c os_vms.c pathdef.c \
@@ -320,7 +320,7 @@ SRC = blowfish.c buffer.c charset.c crypt.c, crypt_zip.c diff.c digraph.c edit.c
OBJ = blowfish.obj buffer.obj charset.obj crypt.obj, crypt_zip.obj diff.obj digraph.obj edit.obj eval.obj \
ex_cmds.obj ex_cmds2.obj ex_docmd.obj ex_eval.obj ex_getln.obj \
- if_xcmdsrv.obj fileio.obj fold.obj getchar.obj hardcopy.obj hashtab.obj main.obj mark.obj \
+ if_xcmdsrv.obj fileio.obj fold.obj getchar.obj hardcopy.obj hashtab.obj json.obj main.obj mark.obj \
menu.obj memfile.obj memline.obj message.obj misc1.obj misc2.obj \
move.obj mbyte.obj normal.obj ops.obj option.obj popupmnu.obj quickfix.obj \
regexp.obj search.obj sha256.obj spell.obj syntax.obj tag.obj term.obj termlib.obj \
@@ -572,6 +572,10 @@ if_mzsch.obj : if_mzsch.c vim.h [.auto]config.h feature.h os_unix.h \
ascii.h keymap.h term.h macros.h option.h structs.h \
regexp.h gui.h gui_beval.h [.proto]gui_beval.pro ex_cmds.h proto.h \
globals.h farsi.h arabic.h if_mzsch.h
+json.obj : json.c vim.h [.auto]config.h feature.h os_unix.h \
+ ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h gui_beval.h \
+ [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h farsi.h \
+ arabic.h version.h
main.obj : main.c vim.h [.auto]config.h feature.h os_unix.h \
ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h gui_beval.h \
[.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h farsi.h \
diff --git a/src/Makefile b/src/Makefile
index 4aa5a48b2b..91f3b77197 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1487,6 +1487,7 @@ BASIC_SRC = \
hashtab.c \
if_cscope.c \
if_xcmdsrv.c \
+ json.c \
main.c \
mark.c \
memfile.c \
@@ -1580,6 +1581,7 @@ OBJ_COMMON = \
$(HANGULIN_OBJ) \
objects/if_cscope.o \
objects/if_xcmdsrv.o \
+ objects/json.o \
objects/mark.o \
objects/memline.o \
objects/menu.o \
@@ -1654,6 +1656,7 @@ PRO_AUTO = \
if_python.pro \
if_python3.pro \
if_ruby.pro \
+ json.pro \
main.pro \
mark.pro \
memfile.pro \
@@ -1986,6 +1989,8 @@ test_arglist \
test_expand \
test_hardcopy \
test_increment \
+ test_json \
+ test_langmap \
test_lispwords \
test_menu \
test_perl \
@@ -1993,6 +1998,7 @@ test_arglist \
test_searchpos \
test_set \
test_sort \
+ test_syntax \
test_undolevels \
test_unlet \
test_viminfo \
@@ -2770,6 +2776,9 @@ objects/if_tcl.o: if_tcl.c
objects/integration.o: integration.c
$(CCC) -o $@ integration.c
+objects/json.o: json.c
+ $(CCC) -o $@ json.c
+
objects/main.o: main.c
$(CCC) -o $@ main.c
@@ -3060,6 +3069,10 @@ objects/if_xcmdsrv.o: if_xcmdsrv.c vim.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
globals.h farsi.h arabic.h version.h
+objects/json.o: json.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
+ ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
+ gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
+ arabic.h
objects/main.o: main.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
@@ -3114,7 +3127,7 @@ objects/option.o: option.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h
objects/os_unix.o: os_unix.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
- arabic.h if_mzsch.h os_unixx.h
+ arabic.h os_unixx.h
objects/pathdef.o: auto/pathdef.c vim.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
@@ -3179,7 +3192,7 @@ objects/gui.o: gui.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h ascii.
objects/gui_gtk.o: gui_gtk.c gui_gtk_f.h vim.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
- globals.h farsi.h arabic.h ../pixmaps/stock_icons.h
+ globals.h farsi.h arabic.h
objects/gui_gtk_f.o: gui_gtk_f.c vim.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
@@ -3245,8 +3258,8 @@ objects/gui_athena.o: gui_athena.c vim.h auto/config.h feature.h os_unix.h \
objects/gui_gtk_x11.o: gui_gtk_x11.c vim.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
- globals.h farsi.h arabic.h gui_gtk_f.h ../runtime/vim32x32.xpm \
- ../runtime/vim16x16.xpm ../runtime/vim48x48.xpm $(GRESOURCE_HDR)
+ globals.h farsi.h arabic.h auto/gui_gtk_gresources.h gui_gtk_f.h \
+ ../runtime/vim32x32.xpm ../runtime/vim16x16.xpm ../runtime/vim48x48.xpm
objects/gui_x11.o: gui_x11.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
@@ -3278,7 +3291,7 @@ objects/if_lua.o: if_lua.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h
objects/if_mzsch.o: if_mzsch.c vim.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
- globals.h farsi.h arabic.h if_mzsch.h mzscheme_base.c
+ globals.h farsi.h arabic.h if_mzsch.h
objects/if_perl.o: auto/if_perl.c vim.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
diff --git a/src/eval.c b/src/eval.c
index 565d71d786..a0cc6d0170 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -99,7 +99,6 @@ static char *e_undefvar = N_("E121: Undefined variable: %s");
static char *e_missbrac = N_("E111: Missing ']'");
static char *e_listarg = N_("E686: Argument of %s must be a List");
static char *e_listdictarg = N_("E712: Argument of %s must be a List or Dictionary");
-static char *e_emptykey = N_("E713: Cannot use empty key for Dictionary");
static char *e_listreq = N_("E714: List required");
static char *e_dictreq = N_("E715: Dictionary required");
static char *e_toomanyarg = N_("E118: Too many arguments for function: %s");
@@ -371,6 +370,10 @@ static struct vimvar
{VV_NAME("option_old", VAR_STRING), VV_RO},
{VV_NAME("option_type", VAR_STRING), VV_RO},
{VV_NAME("errors", VAR_LIST), 0},
+ {VV_NAME("false", VAR_SPECIAL), VV_RO},
+ {VV_NAME("true", VAR_SPECIAL), VV_RO},
+ {VV_NAME("null", VAR_SPECIAL), VV_RO},
+ {VV_NAME("none", VAR_SPECIAL), VV_RO},
};
/* shorthand */
@@ -428,7 +431,6 @@ static int get_option_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
static int get_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
-static int rettv_list_alloc __ARGS((typval_T *rettv));
static long list_len __ARGS((list_T *l));
static int list_equal __ARGS((list_T *l1, list_T *l2, int ic, int recursive));
static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic, int recursive));
@@ -443,7 +445,6 @@ static char_u *list2string __ARGS((typval_T *tv, int copyID));
static int list_join_inner __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo_style, int copyID, garray_T *join_gap));
static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo, int copyID));
static int free_unref_items __ARGS((int copyID));
-static int rettv_dict_alloc __ARGS((typval_T *rettv));
static dictitem_T *dictitem_copy __ARGS((dictitem_T *org));
static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item));
static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID));
@@ -453,9 +454,6 @@ static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));
static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));
static char_u *string_quote __ARGS((char_u *str, int function));
-#ifdef FEAT_FLOAT
-static int string2float __ARGS((char_u *text, float_T *value));
-#endif
static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
static int find_internal_func __ARGS((char_u *name));
static char_u *deref_func_name __ARGS((char_u *name, int *lenp, int no_autoload));
@@ -617,6 +615,8 @@ static void f_isdirectory __ARGS((typval_T *argvars, typval_T *rettv));
static void f_islocked __ARGS((typval_T *argvars, typval_T *rettv));
static void f_items __ARGS((typval_T *argvars, typval_T *rettv));
static void f_join __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_jsondecode __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_jsonencode __ARGS((typval_T *argvars, typval_T *rettv));
static void f_keys __ARGS((typval_T *argvars, typval_T *rettv));
static void f_last_buffer_nr __ARGS((typval_T *argvars, typval_T *rettv));
static void f_len __ARGS((typval_T *argvars, typval_T *rettv));
@@ -816,7 +816,6 @@ static linenr_T get_tv_lnum __ARGS((typval_T *argvars));
static linenr_T get_tv_lnum_buf __ARGS((typval_T *argvars, buf_T *buf));
static char_u *get_tv_string __ARGS((typval_T *varp));
static char_u *get_tv_string_buf __ARGS((typval_T *varp, char_u *buf));
-static char_u *get_tv_string_buf_chk __ARGS((typval_T *varp, char_u *buf));
static dictitem_T *find_var __ARGS((char_u *name, hashtab_T **htp, int no_autoload));
static dictitem_T *find_var_in_ht __ARGS((hashtab_T *ht, int htname, char_u *varname, int no_autoload));
static hashtab_T *find_var_ht __ARGS((char_u *name, char_u **varname));
@@ -915,6 +914,12 @@ eval_init()
set_vim_var_nr(VV_HLSEARCH, 1L);
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
set_vim_var_list(VV_ERRORS, list_alloc());
+
+ set_vim_var_nr(VV_FALSE, VVAL_FALSE);
+ set_vim_var_nr(VV_TRUE, VVAL_TRUE);
+ set_vim_var_nr(VV_NONE, VVAL_NONE);
+ set_vim_var_nr(VV_NULL, VVAL_NULL);
+
set_reg_var(0); /* default for v:register is not 0 but '"' */
#ifdef EBCDIC
@@ -3080,13 +3085,15 @@ tv_op(tv1, tv2, op)
char_u numbuf[NUMBUFLEN];
char_u *s;
- /* Can't do anything with a Funcref or a Dict on the right. */
- if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT)
+ /* Can't do anything with a Funcref, Dict, v:true on the right. */
+ if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT
+ && tv2->v_type != VAR_SPECIAL)
{
switch (tv1->v_type)
{
case VAR_DICT:
case VAR_FUNC:
+ case VAR_SPECIAL:
break;
case VAR_LIST:
@@ -5390,6 +5397,10 @@ eval_index(arg, rettv, evaluate, verbose)
return FAIL;
}
#endif
+ else if (rettv->v_type == VAR_SPECIAL)
+ {
+ return FAIL;
+ }
init_tv(&var1);
init_tv(&var2);
@@ -5999,7 +6010,7 @@ list_alloc()
* Allocate an empty list for a return value.
* Returns OK or FAIL.
*/
- static int
+ int
rettv_list_alloc(rettv)
typval_T *rettv;
{
@@ -6246,6 +6257,9 @@ tv_equal(tv1, tv2, ic, recursive)
s1 = get_tv_string_buf(tv1, buf1);
s2 = get_tv_string_buf(tv2, buf2);
return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0);
+
+ case VAR_SPECIAL:
+ return tv1->vval.v_number == tv2->vval.v_number;
}
EMSG2(_(e_intern2), "tv_equal()");
@@ -6838,6 +6852,17 @@ list_join(gap, l, sep, echo_style, copyID)
}
/*
+ * Return the next (unique) copy ID.
+ * Used for serializing nested structures.
+ */
+ int
+get_copyID()
+{
+ current_copyID += COPYID_INC;
+ return current_copyID;
+}
+
+/*
* Garbage collection for lists and dictionaries.
*
* We use reference counts to be able to free most items right away when they
@@ -6883,8 +6908,7 @@ garbage_collect()
/* We advance by two because we add one for items referenced through
* previous_funccal. */
- current_copyID += COPYID_INC;
- copyID = current_copyID;
+ copyID = get_copyID();
/*
* 1. Go through all accessible variables and mark all lists and dicts
@@ -7236,7 +7260,7 @@ dict_alloc()
* Allocate an empty dict for a return value.
* Returns OK or FAIL.
*/
- static int
+ int
rettv_dict_alloc(rettv)
typval_T *rettv;
{
@@ -7891,6 +7915,18 @@ echo_string(tv, tofree, numbuf, copyID)
break;
#endif
+ case VAR_SPECIAL:
+ *tofree = NULL;
+ switch (tv->vval.v_number)
+ {
+ case VVAL_FALSE: r = (char_u *)"false"; break;
+ case VVAL_TRUE: r = (char_u *)"true"; break;
+ case VVAL_NONE: r = (char_u *)"none"; break;
+ case VVAL_NULL: r = (char_u *)"null"; break;
+ default: EMSG2(_(e_intern2), "echo_string(special)");
+ }
+ break;
+
default:
EMSG2(_(e_intern2), "echo_string()");
*tofree = NULL;
@@ -7932,6 +7968,7 @@ tv2string(tv, tofree, numbuf, copyID)
case VAR_NUMBER:
case VAR_LIST:
case VAR_DICT:
+ case VAR_SPECIAL:
break;
default:
EMSG2(_(e_intern2), "tv2string()");
@@ -7985,14 +8022,14 @@ string_quote(str, function)
return s;
}
-#ifdef FEAT_FLOAT
+#if defined(FEAT_FLOAT) || defined(PROTO)
/*
* Convert the string "text" to a floating point number.
* This uses strtod(). setlocale(LC_NUMERIC, "C") has been used to make sure
* this always uses a decimal point.
* Returns the length of the text that was consumed.
*/
- static int
+ int
string2float(text, value)
char_u *text;
float_T *value; /* result stored here */
@@ -8237,6 +8274,8 @@ static struct fst
{"islocked", 1, 1, f_islocked},
{"items", 1, 1, f_items},
{"join", 1, 2, f_join},
+ {"jsondecode", 1, 1, f_jsondecode},
+ {"jsonencode", 1, 1, f_jsonencode},
{"keys", 1, 1, f_keys},
{"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
{"len", 1, 1, f_len},
@@ -14394,6 +14433,34 @@ f_join(argvars, rettv)
}
/*
+ * "jsondecode()" function
+ */
+ static void
+f_jsondecode(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ js_read_T reader;
+
+ reader.js_buf = get_tv_string(&argvars[0]);
+ reader.js_eof = TRUE;
+ reader.js_used = 0;
+ json_decode(&reader, rettv);
+}
+
+/*
+ * "jsonencode()" function
+ */
+ static void
+f_jsonencode(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = json_encode(&argvars[0]);
+}
+
+/*
* "keys()" function
*/
static void
@@ -21558,6 +21625,7 @@ clear_tv(varp)
varp->vval.v_dict = NULL;
break;
case VAR_NUMBER:
+ case VAR_SPECIAL:
varp->vval.v_number = 0;
break;
#ifdef FEAT_FLOAT
@@ -21759,7 +21827,7 @@ get_tv_string_chk(varp)
return get_tv_string_buf_chk(varp, mybuf);
}
- static char_u *
+ char_u *
get_tv_string_buf_chk(varp, buf)
typval_T *varp;
char_u *buf;
@@ -22120,8 +22188,7 @@ list_one_var(v, prefix, first)
char_u *s;
char_u numbuf[NUMBUFLEN];
- current_copyID += COPYID_INC;
- s = echo_string(&v->di_tv, &tofree, numbuf, current_copyID);
+ s = echo_string(&v->di_tv, &tofree, numbuf, get_copyID());
list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
s == NULL ? (char_u *)"" : s, first);
vim_free(tofree);
@@ -22435,6 +22502,7 @@ copy_tv(from, to)
switch (from->v_type)
{
case VAR_NUMBER:
+ case VAR_SPECIAL:
to->vval.v_number = from->vval.v_number;
break;
#ifdef FEAT_FLOAT
@@ -22609,8 +22677,7 @@ ex_echo(eap)
}
else if (eap->cmdidx == CMD_echo)
msg_puts_attr((char_u *)" ", echo_attr);
- current_copyID += COPYID_INC;
- p = echo_string(&rettv, &tofree, numbuf, current_copyID);
+ p = echo_string(&rettv, &tofree, numbuf, get_copyID());
if (p != NULL)
for ( ; *p != NUL && !got_int; ++p)
{
diff --git a/src/globals.h b/src/globals.h
index 4dc0b81a1c..f252aeeea0 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1523,6 +1523,7 @@ EXTERN char_u e_readonly[] INIT(= N_("E45: 'readonly' option is set (add ! to ov
#ifdef FEAT_EVAL
EXTERN char_u e_readonlyvar[] INIT(= N_("E46: Cannot change read-only variable \"%s\""));
EXTERN char_u e_readonlysbx[] INIT(= N_("E794: Cannot set variable in the sandbox: \"%s\""));
+EXTERN char_u e_emptykey[] INIT(= N_("E713: Cannot use empty key for Dictionary"));
#endif
#ifdef FEAT_QUICKFIX
EXTERN char_u e_readerrf[] INIT(= N_("E47: Error while reading errorfile"));
diff --git a/src/if_lua.c b/src/if_lua.c
index 46f881a9bd..1c8512fec5 100644
--- a/src/if_lua.c
+++ b/src/if_lua.c
@@ -499,6 +499,12 @@ luaV_pushtypval(lua_State *L, typval_T *tv)
case VAR_DICT:
luaV_pushdict(L, tv->vval.v_dict);
break;
+ case VAR_SPECIAL:
+ if (tv->vval.v_number <= VVAL_TRUE)
+ lua_pushinteger(L, (int) tv->vval.v_number);
+ else
+ lua_pushnil(L);
+ break;
default:
lua_pushnil(L);
}
@@ -510,7 +516,7 @@ luaV_totypval (lua_State *L, int pos, typval_T *tv)
{
switch(lua_type(L, pos)) {
case LUA_TBOOLEAN:
- tv->v_type = VAR_NUMBER;
+ tv->v_type = VAR_SPECIAL;
tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos);
break;
case LUA_TSTRING:
diff --git a/src/if_mzsch.c b/src/if_mzsch.c
index ea04705459..0884c9f5ee 100644
--- a/src/if_mzsch.c
+++ b/src/if_mzsch.c
@@ -3084,6 +3084,14 @@ vim_to_mzscheme_impl(typval_T *vim_value, int depth, Scheme_Hash_Table *visited)
MZ_GC_UNREG();
}
+ else if (vim_value->v_type == VAR_SPECIAL)
+ {
+ if (vim_value->vval.v_number <= VVAL_TRUE)
+ result = scheme_make_integer((long)vim_value->vval.v_number);
+ else
+ result = scheme_null;
+ MZ_GC_CHECK();
+ }
else
{
result = scheme_void;
@@ -3148,8 +3156,8 @@ mzscheme_to_vim_impl(Scheme_Object *obj, typval_T *tv, int depth,
copy_tv(found, tv);
else if (SCHEME_VOIDP(obj))
{
- tv->v_type = VAR_NUMBER;
- tv->vval.v_number = 0;
+ tv->v_type = VAR_SPECIAL;
+ tv->vval.v_number = VVAL_NULL;
}
else if (SCHEME_INTP(obj))
{
@@ -3158,7 +3166,7 @@ mzscheme_to_vim_impl(Scheme_Object *obj, typval_T *tv, int depth,
}
else if (SCHEME_BOOLP(obj))
{
- tv->v_type = VAR_NUMBER;
+ tv->v_type = VAR_SPECIAL;
tv->vval.v_number = SCHEME_TRUEP(obj);
}
# ifdef FEAT_FLOAT
diff --git a/src/if_py_both.h b/src/if_py_both.h
index e220e3fec7..e8a5f5de9c 100644
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -810,6 +810,25 @@ VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict)
}
}
}