diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-01-23 19:46:28 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-01-23 19:46:28 +0100 |
commit | 520e1e41f35b063ede63b41738c82d6636e78c34 (patch) | |
tree | 4c6a94e4e8f3f2047b91886077d4ecb916b30401 | |
parent | 6920c72d4d62c8dc5596e9f392e38204f561d7af (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-- | Filelist | 2 | ||||
-rw-r--r-- | runtime/doc/eval.txt | 41 | ||||
-rw-r--r-- | src/Make_bc3.mak | 1 | ||||
-rw-r--r-- | src/Make_bc5.mak | 1 | ||||
-rw-r--r-- | src/Make_cyg_ming.mak | 1 | ||||
-rw-r--r-- | src/Make_dice.mak | 4 | ||||
-rw-r--r-- | src/Make_ivc.mak | 5 | ||||
-rw-r--r-- | src/Make_manx.mak | 6 | ||||
-rw-r--r-- | src/Make_morph.mak | 1 | ||||
-rw-r--r-- | src/Make_mvc.mak | 4 | ||||
-rw-r--r-- | src/Make_sas.mak | 5 | ||||
-rw-r--r-- | src/Make_vms.mms | 10 | ||||
-rw-r--r-- | src/Makefile | 23 | ||||
-rw-r--r-- | src/eval.c | 107 | ||||
-rw-r--r-- | src/globals.h | 1 | ||||
-rw-r--r-- | src/if_lua.c | 8 | ||||
-rw-r--r-- | src/if_mzsch.c | 14 | ||||
-rw-r--r-- | src/if_py_both.h | 19 | ||||
-rw-r--r-- | src/if_ruby.c | 5 | ||||
-rw-r--r-- | src/json.c | 509 | ||||
-rw-r--r-- | src/proto.h | 1 | ||||
-rw-r--r-- | src/proto/eval.pro | 5 | ||||
-rw-r--r-- | src/proto/json.pro | 5 | ||||
-rw-r--r-- | src/structs.h | 13 | ||||
-rw-r--r-- | src/testdir/test_alot.vim | 1 | ||||
-rw-r--r-- | src/testdir/test_json.vim | 91 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim.h | 12 |
28 files changed, 863 insertions, 34 deletions
@@ -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) } } } |