Mercurial > hg > xemacs-beta
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)); |