blob: 3751ec3fd2ba92fb3b033bd18a5cf92c6b1e53ef [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum3f5da241990-12-20 15:06:42 +000025/* Built-in functions */
26
27#include "allobjects.h"
28
29#include "node.h"
30#include "graminit.h"
31#include "errcode.h"
32#include "sysmodule.h"
Guido van Rossum86cd6e61991-01-21 15:12:35 +000033#include "bltinmodule.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000034#include "import.h"
35#include "pythonrun.h"
36#include "compile.h" /* For ceval.h */
37#include "ceval.h"
38#include "modsupport.h"
39
Guido van Rossum006bcd41991-10-24 14:54:44 +000040/* Should be in longobject.h */
41extern stringobject *long_format PROTO((object *, int));
42
Guido van Rossum3f5da241990-12-20 15:06:42 +000043static object *
44builtin_abs(self, v)
45 object *self;
46 object *v;
47{
Guido van Rossumd4905451991-05-05 20:00:36 +000048 number_methods *nm;
49 if (v == NULL || (nm = v->ob_type->tp_as_number) == NULL) {
50 err_setstr(TypeError, "abs() requires numeric argument");
51 return NULL;
Guido van Rossum3f5da241990-12-20 15:06:42 +000052 }
Guido van Rossumd4905451991-05-05 20:00:36 +000053 return (*nm->nb_absolute)(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +000054}
55
56static object *
57builtin_chr(self, v)
58 object *self;
59 object *v;
60{
61 long x;
62 char s[1];
63 if (v == NULL || !is_intobject(v)) {
Guido van Rossum006bcd41991-10-24 14:54:44 +000064 err_setstr(TypeError, "chr() requires int argument");
Guido van Rossum3f5da241990-12-20 15:06:42 +000065 return NULL;
66 }
67 x = getintvalue(v);
68 if (x < 0 || x >= 256) {
69 err_setstr(RuntimeError, "chr() arg not in range(256)");
70 return NULL;
71 }
72 s[0] = x;
73 return newsizedstringobject(s, 1);
74}
75
76static object *
77builtin_dir(self, v)
78 object *self;
79 object *v;
80{
81 object *d;
82 if (v == NULL) {
83 d = getlocals();
Guido van Rossumdc8a1081991-10-20 20:11:03 +000084 INCREF(d);
Guido van Rossum3f5da241990-12-20 15:06:42 +000085 }
86 else {
Guido van Rossumdc8a1081991-10-20 20:11:03 +000087 d = getattr(v, "__dict__");
88 if (d == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +000089 err_setstr(TypeError,
Guido van Rossum006bcd41991-10-24 14:54:44 +000090 "dir() argument must have __dict__ attribute");
Guido van Rossum3f5da241990-12-20 15:06:42 +000091 return NULL;
92 }
Guido van Rossum3f5da241990-12-20 15:06:42 +000093 }
Guido van Rossum006bcd41991-10-24 14:54:44 +000094 if (is_dictobject(d)) {
Guido van Rossumdc8a1081991-10-20 20:11:03 +000095 v = getdictkeys(d);
96 if (sortlist(v) != 0) {
97 DECREF(v);
98 v = NULL;
99 }
100 }
Guido van Rossum006bcd41991-10-24 14:54:44 +0000101 else {
102 v = newlistobject(0);
103 }
Guido van Rossumdc8a1081991-10-20 20:11:03 +0000104 DECREF(d);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000105 return v;
106}
107
108static object *
Guido van Rossumc6bb8f71991-07-01 18:42:41 +0000109builtin_divmod(self, args)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000110 object *self;
Guido van Rossumc6bb8f71991-07-01 18:42:41 +0000111 object *args;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000112{
Guido van Rossumc6bb8f71991-07-01 18:42:41 +0000113 object *v, *w, *x;
114 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
Guido van Rossumd4905451991-05-05 20:00:36 +0000115 err_setstr(TypeError, "divmod() requires 2 arguments");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000116 return NULL;
117 }
Guido van Rossumc6bb8f71991-07-01 18:42:41 +0000118 v = gettupleitem(args, 0);
119 w = gettupleitem(args, 1);
120 if (v->ob_type->tp_as_number == NULL ||
121 w->ob_type->tp_as_number == NULL) {
Guido van Rossumd4905451991-05-05 20:00:36 +0000122 err_setstr(TypeError, "divmod() requires numeric arguments");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000123 return NULL;
124 }
Guido van Rossumc6bb8f71991-07-01 18:42:41 +0000125 if (coerce(&v, &w) != 0)
126 return NULL;
127 x = (*v->ob_type->tp_as_number->nb_divmod)(v, w);
128 DECREF(v);
129 DECREF(w);
130 return x;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000131}
132
133static object *
134exec_eval(v, start)
135 object *v;
136 int start;
137{
138 object *str = NULL, *globals = NULL, *locals = NULL;
139 int n;
140 if (v != NULL) {
141 if (is_stringobject(v))
142 str = v;
143 else if (is_tupleobject(v) &&
144 ((n = gettuplesize(v)) == 2 || n == 3)) {
145 str = gettupleitem(v, 0);
146 globals = gettupleitem(v, 1);
147 if (n == 3)
148 locals = gettupleitem(v, 2);
149 }
150 }
151 if (str == NULL || !is_stringobject(str) ||
152 globals != NULL && !is_dictobject(globals) ||
153 locals != NULL && !is_dictobject(locals)) {
154 err_setstr(TypeError,
155 "exec/eval arguments must be string[,dict[,dict]]");
156 return NULL;
157 }
158 return run_string(getstringvalue(str), start, globals, locals);
159}
160
161static object *
162builtin_eval(self, v)
163 object *self;
164 object *v;
165{
166 return exec_eval(v, eval_input);
167}
168
169static object *
170builtin_exec(self, v)
171 object *self;
172 object *v;
173{
174 return exec_eval(v, file_input);
175}
176
177static object *
178builtin_float(self, v)
179 object *self;
180 object *v;
181{
182 if (v == NULL) {
183 /* */
184 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000185 else if (is_intobject(v)) {
186 long x = getintvalue(v);
187 return newfloatobject((double)x);
188 }
Guido van Rossumd4905451991-05-05 20:00:36 +0000189 else if (is_longobject(v)) {
Guido van Rossumd4905451991-05-05 20:00:36 +0000190 return newfloatobject(dgetlongvalue(v));
191 }
192 else if (is_floatobject(v)) {
193 INCREF(v);
194 return v;
195 }
196 err_setstr(TypeError, "float() argument must be int, long or float");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000197 return NULL;
198}
199
200static object *
Guido van Rossum006bcd41991-10-24 14:54:44 +0000201builtin_hex(self, v)
202 object *self;
203 object *v;
204{
205 if (v != NULL) {
206 if (is_intobject(v)) {
207 char buf[20];
208 long x = getintvalue(v);
209 if (x >= 0)
210 sprintf(buf, "0x%lx", x);
211 else
212 sprintf(buf, "-0x%lx", -x);
213 return newstringobject(buf);
214 }
215 if (is_longobject(v)) {
216 return (object *) long_format(v, 16);
217 }
218 }
219 err_setstr(TypeError, "hex() requires int/long argument");
220 return NULL;
221}
222
223static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000224builtin_input(self, v)
225 object *self;
226 object *v;
227{
228 FILE *in = sysgetfile("stdin", stdin);
229 FILE *out = sysgetfile("stdout", stdout);
230 node *n;
231 int err;
232 object *m, *d;
233 flushline();
Guido van Rossum90933611991-06-07 16:10:43 +0000234 if (v != NULL) {
235 if (printobject(v, out, PRINT_RAW) != 0)
236 return NULL;
237 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000238 m = add_module("__main__");
239 d = getmoduledict(m);
240 return run_file(in, "<stdin>", expr_input, d, d);
241}
242
243static object *
244builtin_int(self, v)
245 object *self;
246 object *v;
247{
248 if (v == NULL) {
249 /* */
250 }
251 else if (is_intobject(v)) {
252 INCREF(v);
253 return v;
254 }
Guido van Rossumd4905451991-05-05 20:00:36 +0000255 else if (is_longobject(v)) {
256 long x;
257 x = getlongvalue(v);
Guido van Rossumad405311991-06-03 10:58:01 +0000258 if (err_occurred())
Guido van Rossumd4905451991-05-05 20:00:36 +0000259 return NULL;
260 return newintobject(x);
261 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000262 else if (is_floatobject(v)) {
263 double x = getfloatvalue(v);
Guido van Rossumad405311991-06-03 10:58:01 +0000264 /* XXX should check for overflow */
Guido van Rossum3f5da241990-12-20 15:06:42 +0000265 return newintobject((long)x);
266 }
Guido van Rossumd4905451991-05-05 20:00:36 +0000267 err_setstr(TypeError, "int() argument must be int, long or float");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000268 return NULL;
269}
270
271static object *
272builtin_len(self, v)
273 object *self;
274 object *v;
275{
276 long len;
277 typeobject *tp;
278 if (v == NULL) {
279 err_setstr(TypeError, "len() without argument");
280 return NULL;
281 }
282 tp = v->ob_type;
283 if (tp->tp_as_sequence != NULL) {
284 len = (*tp->tp_as_sequence->sq_length)(v);
285 }
286 else if (tp->tp_as_mapping != NULL) {
287 len = (*tp->tp_as_mapping->mp_length)(v);
288 }
289 else {
290 err_setstr(TypeError, "len() of unsized object");
291 return NULL;
292 }
293 return newintobject(len);
294}
295
296static object *
Guido van Rossumd4905451991-05-05 20:00:36 +0000297builtin_long(self, v)
298 object *self;
299 object *v;
300{
301 if (v == NULL) {
302 /* */
303 }
304 else if (is_intobject(v)) {
305 return newlongobject(getintvalue(v));
306 }
307 else if (is_longobject(v)) {
308 INCREF(v);
309 return v;
310 }
311 else if (is_floatobject(v)) {
312 double x = getfloatvalue(v);
Guido van Rossumad405311991-06-03 10:58:01 +0000313 return dnewlongobject(x);
Guido van Rossumd4905451991-05-05 20:00:36 +0000314 }
315 err_setstr(TypeError, "long() argument must be int, long or float");
316 return NULL;
317}
318
319static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000320min_max(v, sign)
321 object *v;
322 int sign;
323{
324 int i, n, cmp;
325 object *w, *x;
326 sequence_methods *sq;
327 if (v == NULL) {
328 err_setstr(TypeError, "min() or max() without argument");
329 return NULL;
330 }
331 sq = v->ob_type->tp_as_sequence;
332 if (sq == NULL) {
333 err_setstr(TypeError, "min() or max() of non-sequence");
334 return NULL;
335 }
336 n = (*sq->sq_length)(v);
337 if (n == 0) {
338 err_setstr(RuntimeError, "min() or max() of empty sequence");
339 return NULL;
340 }
341 w = (*sq->sq_item)(v, 0); /* Implies INCREF */
342 for (i = 1; i < n; i++) {
343 x = (*sq->sq_item)(v, i); /* Implies INCREF */
344 cmp = cmpobject(x, w);
345 if (cmp * sign > 0) {
346 DECREF(w);
347 w = x;
348 }
349 else
350 DECREF(x);
351 }
352 return w;
353}
354
355static object *
356builtin_min(self, v)
357 object *self;
358 object *v;
359{
360 return min_max(v, -1);
361}
362
363static object *
364builtin_max(self, v)
365 object *self;
366 object *v;
367{
368 return min_max(v, 1);
369}
370
371static object *
Guido van Rossum006bcd41991-10-24 14:54:44 +0000372builtin_oct(self, v)
373 object *self;
374 object *v;
375{
376 if (v != NULL) {
377 if (is_intobject(v)) {
378 char buf[20];
379 long x = getintvalue(v);
380 if (x >= 0)
381 sprintf(buf, "0%lo", x);
382 else
383 sprintf(buf, "-0%lo", -x);
384 return newstringobject(buf);
385 }
386 if (is_longobject(v)) {
387 return (object *) long_format(v, 8);
388 }
389 }
390 err_setstr(TypeError, "oct() requires int/long argument");
391 return NULL;
392}
393
394static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000395builtin_open(self, v)
396 object *self;
397 object *v;
398{
399 object *name, *mode;
400 if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2 ||
401 !is_stringobject(name = gettupleitem(v, 0)) ||
402 !is_stringobject(mode = gettupleitem(v, 1))) {
403 err_setstr(TypeError, "open() requires 2 string arguments");
404 return NULL;
405 }
406 v = newfileobject(getstringvalue(name), getstringvalue(mode));
407 return v;
408}
409
410static object *
411builtin_ord(self, v)
412 object *self;
413 object *v;
414{
415 if (v == NULL || !is_stringobject(v)) {
416 err_setstr(TypeError, "ord() must have string argument");
417 return NULL;
418 }
419 if (getstringsize(v) != 1) {
420 err_setstr(RuntimeError, "ord() arg must have length 1");
421 return NULL;
422 }
423 return newintobject((long)(getstringvalue(v)[0] & 0xff));
424}
425
426static object *
Guido van Rossumc6bb8f71991-07-01 18:42:41 +0000427builtin_pow(self, args)
Guido van Rossumd4905451991-05-05 20:00:36 +0000428 object *self;
Guido van Rossumc6bb8f71991-07-01 18:42:41 +0000429 object *args;
Guido van Rossumd4905451991-05-05 20:00:36 +0000430{
Guido van Rossumc6bb8f71991-07-01 18:42:41 +0000431 object *v, *w, *x;
432 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
Guido van Rossumd4905451991-05-05 20:00:36 +0000433 err_setstr(TypeError, "pow() requires 2 arguments");
434 return NULL;
435 }
Guido van Rossumc6bb8f71991-07-01 18:42:41 +0000436 v = gettupleitem(args, 0);
437 w = gettupleitem(args, 1);
438 if (v->ob_type->tp_as_number == NULL ||
439 w->ob_type->tp_as_number == NULL) {
Guido van Rossumd4905451991-05-05 20:00:36 +0000440 err_setstr(TypeError, "pow() requires numeric arguments");
441 return NULL;
442 }
Guido van Rossumc6bb8f71991-07-01 18:42:41 +0000443 if (coerce(&v, &w) != 0)
444 return NULL;
445 x = (*v->ob_type->tp_as_number->nb_power)(v, w);
446 DECREF(v);
447 DECREF(w);
448 return x;
Guido van Rossumd4905451991-05-05 20:00:36 +0000449}
450
451static object *
Guido van Rossum3f5da241990-12-20 15:06:42 +0000452builtin_range(self, v)
453 object *self;
454 object *v;
455{
456 static char *errmsg = "range() requires 1-3 int arguments";
457 int i, n;
458 long ilow, ihigh, istep;
459 if (v != NULL && is_intobject(v)) {
460 ilow = 0; ihigh = getintvalue(v); istep = 1;
461 }
462 else if (v == NULL || !is_tupleobject(v)) {
463 err_setstr(TypeError, errmsg);
464 return NULL;
465 }
466 else {
467 n = gettuplesize(v);
468 if (n < 1 || n > 3) {
469 err_setstr(TypeError, errmsg);
470 return NULL;
471 }
472 for (i = 0; i < n; i++) {
473 if (!is_intobject(gettupleitem(v, i))) {
474 err_setstr(TypeError, errmsg);
475 return NULL;
476 }
477 }
478 if (n == 3) {
479 istep = getintvalue(gettupleitem(v, 2));
480 --n;
481 }
482 else
483 istep = 1;
484 ihigh = getintvalue(gettupleitem(v, --n));
485 if (n > 0)
486 ilow = getintvalue(gettupleitem(v, 0));
487 else
488 ilow = 0;
489 }
490 if (istep == 0) {
491 err_setstr(RuntimeError, "zero step for range()");
492 return NULL;
493 }
494 /* XXX ought to check overflow of subtraction */
495 if (istep > 0)
496 n = (ihigh - ilow + istep - 1) / istep;
497 else
498 n = (ihigh - ilow + istep + 1) / istep;
499 if (n < 0)
500 n = 0;
501 v = newlistobject(n);
502 if (v == NULL)
503 return NULL;
504 for (i = 0; i < n; i++) {
505 object *w = newintobject(ilow);
506 if (w == NULL) {
507 DECREF(v);
508 return NULL;
509 }
510 setlistitem(v, i, w);
511 ilow += istep;
512 }
513 return v;
514}
515
516static object *
517builtin_raw_input(self, v)
518 object *self;
519 object *v;
520{
Guido van Rossum3f5da241990-12-20 15:06:42 +0000521 FILE *out = sysgetfile("stdout", stdout);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000522 flushline();
Guido van Rossum90933611991-06-07 16:10:43 +0000523 if (v != NULL) {
524 if (printobject(v, out, PRINT_RAW) != 0)
525 return NULL;
526 }
Guido van Rossum26203aa1991-04-04 15:20:41 +0000527 return filegetline(sysget("stdin"), -1);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000528}
529
530static object *
531builtin_reload(self, v)
532 object *self;
533 object *v;
534{
535 return reload_module(v);
536}
537
538static object *
539builtin_type(self, v)
540 object *self;
541 object *v;
542{
543 if (v == NULL) {
544 err_setstr(TypeError, "type() requres an argument");
545 return NULL;
546 }
547 v = (object *)v->ob_type;
548 INCREF(v);
549 return v;
550}
551
552static struct methodlist builtin_methods[] = {
553 {"abs", builtin_abs},
554 {"chr", builtin_chr},
555 {"dir", builtin_dir},
556 {"divmod", builtin_divmod},
557 {"eval", builtin_eval},
558 {"exec", builtin_exec},
559 {"float", builtin_float},
Guido van Rossum006bcd41991-10-24 14:54:44 +0000560 {"hex", builtin_hex},
Guido van Rossum3f5da241990-12-20 15:06:42 +0000561 {"input", builtin_input},
562 {"int", builtin_int},
563 {"len", builtin_len},
Guido van Rossumd4905451991-05-05 20:00:36 +0000564 {"long", builtin_long},
Guido van Rossum3f5da241990-12-20 15:06:42 +0000565 {"max", builtin_max},
Guido van Rossum865828d1991-02-19 12:21:50 +0000566 {"min", builtin_min},
Guido van Rossum006bcd41991-10-24 14:54:44 +0000567 {"oct", builtin_oct},
Guido van Rossum3f5da241990-12-20 15:06:42 +0000568 {"open", builtin_open}, /* XXX move to OS module */
569 {"ord", builtin_ord},
Guido van Rossumd4905451991-05-05 20:00:36 +0000570 {"pow", builtin_pow},
Guido van Rossum3f5da241990-12-20 15:06:42 +0000571 {"range", builtin_range},
572 {"raw_input", builtin_raw_input},
573 {"reload", builtin_reload},
574 {"type", builtin_type},
575 {NULL, NULL},
576};
577
578static object *builtin_dict;
579
580object *
581getbuiltin(name)
Guido van Rossuma57fb011991-08-16 08:54:58 +0000582 object *name;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000583{
Guido van Rossuma57fb011991-08-16 08:54:58 +0000584 return dict2lookup(builtin_dict, name);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000585}
586
587/* Predefined exceptions */
588
589object *RuntimeError;
590object *EOFError;
591object *TypeError;
592object *MemoryError;
593object *NameError;
594object *SystemError;
595object *KeyboardInterrupt;
596
597static object *
598newstdexception(name, message)
599 char *name, *message;
600{
601 object *v = newstringobject(message);
602 if (v == NULL || dictinsert(builtin_dict, name, v) != 0)
603 fatal("no mem for new standard exception");
604 return v;
605}
606
607static void
608initerrors()
609{
610 RuntimeError = newstdexception("RuntimeError", "run-time error");
611 EOFError = newstdexception("EOFError", "end-of-file read");
612 TypeError = newstdexception("TypeError", "type error");
613 MemoryError = newstdexception("MemoryError", "out of memory");
614 NameError = newstdexception("NameError", "undefined name");
615 SystemError = newstdexception("SystemError", "system error");
616 KeyboardInterrupt =
617 newstdexception("KeyboardInterrupt", "keyboard interrupt");
618}
619
620void
621initbuiltin()
622{
623 object *m;
624 m = initmodule("builtin", builtin_methods);
625 builtin_dict = getmoduledict(m);
626 INCREF(builtin_dict);
627 initerrors();
628 (void) dictinsert(builtin_dict, "None", None);
629}
Guido van Rossumc6bb8f71991-07-01 18:42:41 +0000630
631/* Coerce two numeric types to the "larger" one.
632 Increment the reference count on each argument.
633 Return -1 and raise an exception if no coercion is possible
634 (and then no reference count is incremented).
635 XXX This should be distributed over the various numeric types,
636 XXX but for now I don't see how to implement that.
637 XXX So, for now, if you add a new numeric type,
638 XXX you must add to this function as well. */
639
640int
641coerce(pv, pw)
642 object **pv, **pw;
643{
644 register object *v = *pv;
645 register object *w = *pw;
646 if (v->ob_type == w->ob_type) {
647 INCREF(v);
648 INCREF(w);
649 return 0;
650 }
651 if (v->ob_type->tp_as_number == NULL ||
652 w->ob_type->tp_as_number == NULL) {
653 err_setstr(TypeError, "mixing number and non-number");
654 return -1;
655 }
656 if (is_floatobject(v) || is_floatobject(w)) {
657 v = builtin_float((object *)0, v);
658 w = builtin_float((object *)0, w);
659 }
660 else if (is_longobject(v) || is_longobject(w)) {
661 v = builtin_long((object *)0, v);
662 w = builtin_long((object *)0, w);
663 }
664 else {
665 err_setstr(TypeError, "can't coerce numeric types?!?!?");
666 return -1;
667 }
668 if (v == NULL || w == NULL) {
669 XDECREF(v);
670 XDECREF(w);
671 return -1;
672 }
673 *pv = v;
674 *pw = w;
675 return 0;
676}