comparison src/lisp.h @ 5084:6afe991b8135

Add a PARSE_KEYWORDS macro, use it in #'make-hash-table. lisp/ChangeLog addition: 2010-03-01 Aidan Kehoe <kehoea@parhasard.net> * cl-seq.el (cl-parsing-keywords): * cl-macs.el (cl-do-arglist): Use the new invalid-keyword-argument error here. src/ChangeLog addition: 2010-03-01 Aidan Kehoe <kehoea@parhasard.net> * lisp.h (PARSE_KEYWORDS): New macro, for parsing keyword arguments from C subrs. * elhash.c (Fmake_hash_table): Use it. * general-slots.h (Q_allow_other_keys): Add this symbol. * eval.c (non_nil_allow_other_keys_p): (invalid_keyword_argument): New functions, called from the keyword argument parsing code. * data.c (init_errors_once_early): Add the new invalid-keyword-argument error here.
author Aidan Kehoe <kehoea@parhasard.net>
date Mon, 01 Mar 2010 21:05:33 +0000
parents d372b17f63ce
children 99f8ebc082d9 cb4f2e1bacc4
comparison
equal deleted inserted replaced
5083:88f955fa5a7f 5084:6afe991b8135
4039 4039
4040 #define CHECK_FUNCTION(fun) do { \ 4040 #define CHECK_FUNCTION(fun) do { \
4041 while (NILP (Ffunctionp (fun))) \ 4041 while (NILP (Ffunctionp (fun))) \
4042 signal_invalid_function_error (fun); \ 4042 signal_invalid_function_error (fun); \
4043 } while (0) 4043 } while (0)
4044
4045 /************************************************************************/
4046 /* Parsing keyword arguments */
4047 /************************************************************************/
4048
4049 /* The C subr must have been declared with MANY as its max args, and this
4050 PARSE_KEYWORDS call must come before any statements.
4051
4052 FUNCTION is the name of the current function, as a symbol.
4053
4054 NARGS is the count of arguments supplied to FUNCTION.
4055
4056 ARGS is a pointer to the argument vector (not a Lisp vector) supplied to
4057 FUNCTION.
4058
4059 KEYWORDS_OFFSET is the offset into ARGS where the keyword arguments start.
4060
4061 KEYWORD_COUNT is the number of keywords FUNCTION is normally prepared to
4062 handle.
4063
4064 KEYWORDS is a parenthesised list of those keywords, without the initial
4065 Q_.
4066
4067 KEYWORD_DEFAULTS allows you to set non-nil defaults. Put (keywordname =
4068 initial_value) in this parameter, a collection of C statements surrounded
4069 by parentheses and separated by the comma operator. If you don't need
4070 this, supply NULL as KEYWORD_DEFAULTS.
4071
4072 ALLOW_OTHER_KEYS corresponds to the &allow-other-keys argument list
4073 entry in defun*; it is 1 if other keys are normally allowed, 0
4074 otherwise. This may be overridden in the caller by specifying
4075 :allow-other-keys t in the argument list.
4076
4077 For keywords which appear multiple times in the called argument list, the
4078 leftmost one overrides, as specified in section 7.1.1 of the CLHS.
4079
4080 If you want to check whether a given keyword argument was set (as in the
4081 SVAR argument to defun*), supply Qunbound as its default in
4082 KEYWORD_DEFAULTS, and examine it once PARSE_KEYWORDS is done. Lisp code
4083 cannot supply Qunbound as an argument, so if it is still Qunbound, it was
4084 not set.
4085
4086 There is no elegant way with this macro to have one name for the keyword
4087 and an unrelated name for the local variable, as is possible with the
4088 ((:keyword unrelated-var)) syntax in defun* and in Common Lisp. That
4089 shouldn't matter in practice. */
4090
4091 #define PARSE_KEYWORDS(function, nargs, args, keywords_offset, \
4092 keyword_count, keywords, keyword_defaults, \
4093 allow_other_keys) \
4094 DECLARE_N_KEYWORDS_##keyword_count keywords; \
4095 \
4096 do \
4097 { \
4098 Lisp_Object pk_key, pk_value; \
4099 Elemcount pk_i = nargs - 1; \
4100 Boolint pk_allow_other_keys = allow_other_keys; \
4101 \
4102 if ((nargs - keywords_offset) & 1) \
4103 { \
4104 if (!allow_other_keys \
4105 && !(pk_allow_other_keys \
4106 = non_nil_allow_other_keys_p (keywords_offset, \
4107 nargs, args))) \
4108 { \
4109 signal_wrong_number_of_arguments_error (function, nargs); \
4110 } \
4111 else \
4112 { \
4113 /* Ignore the trailing arg; so below always sees an even \
4114 number of arguments. */ \
4115 pk_i -= 1; \
4116 } \
4117 } \
4118 \
4119 (void)(keyword_defaults); \
4120 \
4121 /* Start from the end, because the leftmost element overrides. */ \
4122 while (pk_i > keywords_offset) \
4123 { \
4124 pk_value = args[pk_i--]; \
4125 pk_key = args[pk_i--]; \
4126 \
4127 if (0) {} \
4128 CHECK_N_KEYWORDS_##keyword_count keywords \
4129 else if (allow_other_keys || pk_allow_other_keys) \
4130 { \
4131 continue; \
4132 } \
4133 else if (!(pk_allow_other_keys \
4134 = non_nil_allow_other_keys_p (keywords_offset, \
4135 nargs, args))) \
4136 { \
4137 invalid_keyword_argument (function, pk_key); \
4138 } \
4139 } \
4140 } while (0)
4141
4142 #define DECLARE_N_KEYWORDS_1(a) \
4143 Lisp_Object a = Qnil
4144 #define DECLARE_N_KEYWORDS_2(a,b) \
4145 DECLARE_N_KEYWORDS_1(a), b = Qnil
4146 #define DECLARE_N_KEYWORDS_3(a,b,c) \
4147 DECLARE_N_KEYWORDS_2(a,b), c = Qnil
4148 #define DECLARE_N_KEYWORDS_4(a,b,c,d) \
4149 DECLARE_N_KEYWORDS_3(a,b,c), d = Qnil
4150 #define DECLARE_N_KEYWORDS_5(a,b,c,d,e) \
4151 DECLARE_N_KEYWORDS_4(a,b,c,d), e = Qnil
4152 #define DECLARE_N_KEYWORDS_6(a,b,c,d,e,f) \
4153 DECLARE_N_KEYWORDS_5(a,b,c,d,e), f = Qnil
4154 #define DECLARE_N_KEYWORDS_7(a,b,c,d,e,f,g) \
4155 DECLARE_N_KEYWORDS_6(a,b,c,d,e,f), g = Qnil
4156
4157 #define CHECK_N_KEYWORDS_1(a) \
4158 else if (EQ (pk_key, Q_##a)) { a = pk_value; }
4159 #define CHECK_N_KEYWORDS_2(a,b) CHECK_N_KEYWORDS_1(a) \
4160 else if (EQ (pk_key, Q_##b)) { b = pk_value; }
4161 #define CHECK_N_KEYWORDS_3(a,b,c) CHECK_N_KEYWORDS_2(a,b) \
4162 else if (EQ (pk_key, Q_##c)) { c = pk_value; }
4163 #define CHECK_N_KEYWORDS_4(a,b,c,d) CHECK_N_KEYWORDS_3(a,b,c) \
4164 else if (EQ (pk_key, Q_##d)) { d = pk_value; }
4165 #define CHECK_N_KEYWORDS_5(a,b,c,d,e) CHECK_N_KEYWORDS_4(a,b,c,d) \
4166 else if (EQ (pk_key, Q_##e)) { e = pk_value; }
4167 #define CHECK_N_KEYWORDS_6(a,b,c,d,e,f) CHECK_N_KEYWORDS_5(a,b,c,d,e) \
4168 else if (EQ (pk_key, Q_##f)) { f = pk_value; }
4169 #define CHECK_N_KEYWORDS_7(a,b,c,d,e,f,g) CHECK_N_KEYWORDS_6(a,b,c,d,e,f) \
4170 else if (EQ (pk_key, Q_##g)) { g = pk_value; }
4171
4172 Boolint non_nil_allow_other_keys_p (Elemcount offset, int nargs,
4173 Lisp_Object *args);
4044 4174
4045 4175
4046 /************************************************************************/ 4176 /************************************************************************/
4047 /* Checking for QUIT */ 4177 /* Checking for QUIT */
4048 /************************************************************************/ 4178 /************************************************************************/
4896 5026
4897 extern Lisp_Object Qarith_error, Qbeginning_of_buffer, Qbuffer_read_only, 5027 extern Lisp_Object Qarith_error, Qbeginning_of_buffer, Qbuffer_read_only,
4898 Qcircular_list, Qcircular_property_list, Qconversion_error, 5028 Qcircular_list, Qcircular_property_list, Qconversion_error,
4899 Qcyclic_variable_indirection, Qdomain_error, Qediting_error, 5029 Qcyclic_variable_indirection, Qdomain_error, Qediting_error,
4900 Qend_of_buffer, Qend_of_file, Qerror, Qfile_error, Qinternal_error, 5030 Qend_of_buffer, Qend_of_file, Qerror, Qfile_error, Qinternal_error,
4901 Qinvalid_change, Qinvalid_constant, Qinvalid_function, Qinvalid_operation, 5031 Qinvalid_change, Qinvalid_constant, Qinvalid_function,
5032 Qinvalid_keyword_argument, Qinvalid_operation,
4902 Qinvalid_read_syntax, Qinvalid_state, Qio_error, Qlist_formation_error, 5033 Qinvalid_read_syntax, Qinvalid_state, Qio_error, Qlist_formation_error,
4903 Qmalformed_list, Qmalformed_property_list, Qno_catch, Qout_of_memory, 5034 Qmalformed_list, Qmalformed_property_list, Qno_catch, Qout_of_memory,
4904 Qoverflow_error, Qprinting_unreadable_object, Qquit, Qrange_error, 5035 Qoverflow_error, Qprinting_unreadable_object, Qquit, Qrange_error,
4905 Qsetting_constant, Qsingularity_error, Qstack_overflow, 5036 Qsetting_constant, Qsingularity_error, Qstack_overflow,
4906 Qstructure_formation_error, Qtext_conversion_error, Qunderflow_error, 5037 Qstructure_formation_error, Qtext_conversion_error, Qunderflow_error,
5124 MODULE_API DECLARE_DOESNT_RETURN (invalid_argument_2 (const Ascbyte *reason, 5255 MODULE_API DECLARE_DOESNT_RETURN (invalid_argument_2 (const Ascbyte *reason,
5125 Lisp_Object frob1, 5256 Lisp_Object frob1,
5126 Lisp_Object frob2)); 5257 Lisp_Object frob2));
5127 void maybe_invalid_argument (const Ascbyte *, Lisp_Object, Lisp_Object, 5258 void maybe_invalid_argument (const Ascbyte *, Lisp_Object, Lisp_Object,
5128 Error_Behavior); 5259 Error_Behavior);
5260 MODULE_API DECLARE_DOESNT_RETURN (invalid_keyword_argument (Lisp_Object fun,
5261 Lisp_Object kw));
5129 MODULE_API DECLARE_DOESNT_RETURN (invalid_operation (const Ascbyte *reason, 5262 MODULE_API DECLARE_DOESNT_RETURN (invalid_operation (const Ascbyte *reason,
5130 Lisp_Object frob)); 5263 Lisp_Object frob));
5131 MODULE_API DECLARE_DOESNT_RETURN (invalid_operation_2 (const Ascbyte *reason, 5264 MODULE_API DECLARE_DOESNT_RETURN (invalid_operation_2 (const Ascbyte *reason,
5132 Lisp_Object frob1, 5265 Lisp_Object frob1,
5133 Lisp_Object frob2)); 5266 Lisp_Object frob2));