PageRenderTime 126ms CodeModel.GetById 77ms RepoModel.GetById 2ms app.codeStats 0ms

/contrib/gdb-7/gdb/jv-exp.y

http://github.com/davshao/dflygsocdrm
Happy | 1448 lines | 1270 code | 178 blank | 0 comment | 0 complexity | a457bda7b114806af3af7ed976e7aa55 MD5 | raw file
Possible License(s): AGPL-1.0, CC-BY-SA-3.0, LGPL-2.0, GPL-3.0, LGPL-2.1, LGPL-3.0, MPL-2.0-no-copyleft-exception, 0BSD, BSD-3-Clause, GPL-2.0
  1. /* YACC parser for Java expressions, for GDB.
  2. Copyright (C) 1997-2000, 2006-2012 Free Software Foundation, Inc.
  3. This file is part of GDB.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. /* Parse a Java expression from text in a string,
  15. and return the result as a struct expression pointer.
  16. That structure contains arithmetic operations in reverse polish,
  17. with constants represented by operations that are followed by special data.
  18. See expression.h for the details of the format.
  19. What is important here is that it can be built up sequentially
  20. during the process of parsing; the lower levels of the tree always
  21. come first in the result. Well, almost always; see ArrayAccess.
  22. Note that malloc's and realloc's in this file are transformed to
  23. xmalloc and xrealloc respectively by the same sed command in the
  24. makefile that remaps any other malloc/realloc inserted by the parser
  25. generator. Doing this with #defines and trying to control the interaction
  26. with include files (<malloc.h> and <stdlib.h> for example) just became
  27. too messy, particularly when such includes can be inserted at random
  28. times by the parser generator. */
  29. %{
  30. #include "defs.h"
  31. #include "gdb_string.h"
  32. #include <ctype.h>
  33. #include "expression.h"
  34. #include "value.h"
  35. #include "parser-defs.h"
  36. #include "language.h"
  37. #include "jv-lang.h"
  38. #include "bfd.h" /* Required by objfiles.h. */
  39. #include "symfile.h" /* Required by objfiles.h. */
  40. #include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
  41. #include "block.h"
  42. #define parse_type builtin_type (parse_gdbarch)
  43. #define parse_java_type builtin_java_type (parse_gdbarch)
  44. /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
  45. as well as gratuitiously global symbol names, so we can have multiple
  46. yacc generated parsers in gdb. Note that these are only the variables
  47. produced by yacc. If other parser generators (bison, byacc, etc) produce
  48. additional global names that conflict at link time, then those parser
  49. generators need to be fixed instead of adding those names to this list. */
  50. #define yymaxdepth java_maxdepth
  51. #define yyparse java_parse
  52. #define yylex java_lex
  53. #define yyerror java_error
  54. #define yylval java_lval
  55. #define yychar java_char
  56. #define yydebug java_debug
  57. #define yypact java_pact
  58. #define yyr1 java_r1
  59. #define yyr2 java_r2
  60. #define yydef java_def
  61. #define yychk java_chk
  62. #define yypgo java_pgo
  63. #define yyact java_act
  64. #define yyexca java_exca
  65. #define yyerrflag java_errflag
  66. #define yynerrs java_nerrs
  67. #define yyps java_ps
  68. #define yypv java_pv
  69. #define yys java_s
  70. #define yy_yys java_yys
  71. #define yystate java_state
  72. #define yytmp java_tmp
  73. #define yyv java_v
  74. #define yy_yyv java_yyv
  75. #define yyval java_val
  76. #define yylloc java_lloc
  77. #define yyreds java_reds /* With YYDEBUG defined */
  78. #define yytoks java_toks /* With YYDEBUG defined */
  79. #define yyname java_name /* With YYDEBUG defined */
  80. #define yyrule java_rule /* With YYDEBUG defined */
  81. #define yylhs java_yylhs
  82. #define yylen java_yylen
  83. #define yydefred java_yydefred
  84. #define yydgoto java_yydgoto
  85. #define yysindex java_yysindex
  86. #define yyrindex java_yyrindex
  87. #define yygindex java_yygindex
  88. #define yytable java_yytable
  89. #define yycheck java_yycheck
  90. #ifndef YYDEBUG
  91. #define YYDEBUG 1 /* Default to yydebug support */
  92. #endif
  93. #define YYFPRINTF parser_fprintf
  94. int yyparse (void);
  95. static int yylex (void);
  96. void yyerror (char *);
  97. static struct type *java_type_from_name (struct stoken);
  98. static void push_expression_name (struct stoken);
  99. static void push_fieldnames (struct stoken);
  100. static struct expression *copy_exp (struct expression *, int);
  101. static void insert_exp (int, struct expression *);
  102. %}
  103. /* Although the yacc "value" of an expression is not used,
  104. since the result is stored in the structure being created,
  105. other node types do have values. */
  106. %union
  107. {
  108. LONGEST lval;
  109. struct {
  110. LONGEST val;
  111. struct type *type;
  112. } typed_val_int;
  113. struct {
  114. DOUBLEST dval;
  115. struct type *type;
  116. } typed_val_float;
  117. struct symbol *sym;
  118. struct type *tval;
  119. struct stoken sval;
  120. struct ttype tsym;
  121. struct symtoken ssym;
  122. struct block *bval;
  123. enum exp_opcode opcode;
  124. struct internalvar *ivar;
  125. int *ivec;
  126. }
  127. %{
  128. /* YYSTYPE gets defined by %union */
  129. static int parse_number (char *, int, int, YYSTYPE *);
  130. %}
  131. %type <lval> rcurly Dims Dims_opt
  132. %type <tval> ClassOrInterfaceType ClassType /* ReferenceType Type ArrayType */
  133. %type <tval> IntegralType FloatingPointType NumericType PrimitiveType ArrayType PrimitiveOrArrayType
  134. %token <typed_val_int> INTEGER_LITERAL
  135. %token <typed_val_float> FLOATING_POINT_LITERAL
  136. %token <sval> IDENTIFIER
  137. %token <sval> STRING_LITERAL
  138. %token <lval> BOOLEAN_LITERAL
  139. %token <tsym> TYPENAME
  140. %type <sval> Name SimpleName QualifiedName ForcedName
  141. /* A NAME_OR_INT is a symbol which is not known in the symbol table,
  142. but which would parse as a valid number in the current input radix.
  143. E.g. "c" when input_radix==16. Depending on the parse, it will be
  144. turned into a name or into a number. */
  145. %token <sval> NAME_OR_INT
  146. %token ERROR
  147. /* Special type cases, put in to allow the parser to distinguish different
  148. legal basetypes. */
  149. %token LONG SHORT BYTE INT CHAR BOOLEAN DOUBLE FLOAT
  150. %token VARIABLE
  151. %token <opcode> ASSIGN_MODIFY
  152. %token SUPER NEW
  153. %left ','
  154. %right '=' ASSIGN_MODIFY
  155. %right '?'
  156. %left OROR
  157. %left ANDAND
  158. %left '|'
  159. %left '^'
  160. %left '&'
  161. %left EQUAL NOTEQUAL
  162. %left '<' '>' LEQ GEQ
  163. %left LSH RSH
  164. %left '+' '-'
  165. %left '*' '/' '%'
  166. %right INCREMENT DECREMENT
  167. %right '.' '[' '('
  168. %%
  169. start : exp1
  170. | type_exp
  171. ;
  172. type_exp: PrimitiveOrArrayType
  173. {
  174. write_exp_elt_opcode(OP_TYPE);
  175. write_exp_elt_type($1);
  176. write_exp_elt_opcode(OP_TYPE);
  177. }
  178. ;
  179. PrimitiveOrArrayType:
  180. PrimitiveType
  181. | ArrayType
  182. ;
  183. StringLiteral:
  184. STRING_LITERAL
  185. {
  186. write_exp_elt_opcode (OP_STRING);
  187. write_exp_string ($1);
  188. write_exp_elt_opcode (OP_STRING);
  189. }
  190. ;
  191. Literal:
  192. INTEGER_LITERAL
  193. { write_exp_elt_opcode (OP_LONG);
  194. write_exp_elt_type ($1.type);
  195. write_exp_elt_longcst ((LONGEST)($1.val));
  196. write_exp_elt_opcode (OP_LONG); }
  197. | NAME_OR_INT
  198. { YYSTYPE val;
  199. parse_number ($1.ptr, $1.length, 0, &val);
  200. write_exp_elt_opcode (OP_LONG);
  201. write_exp_elt_type (val.typed_val_int.type);
  202. write_exp_elt_longcst ((LONGEST)val.typed_val_int.val);
  203. write_exp_elt_opcode (OP_LONG);
  204. }
  205. | FLOATING_POINT_LITERAL
  206. { write_exp_elt_opcode (OP_DOUBLE);
  207. write_exp_elt_type ($1.type);
  208. write_exp_elt_dblcst ($1.dval);
  209. write_exp_elt_opcode (OP_DOUBLE); }
  210. | BOOLEAN_LITERAL
  211. { write_exp_elt_opcode (OP_LONG);
  212. write_exp_elt_type (parse_java_type->builtin_boolean);
  213. write_exp_elt_longcst ((LONGEST)$1);
  214. write_exp_elt_opcode (OP_LONG); }
  215. | StringLiteral
  216. ;
  217. /* UNUSED:
  218. Type:
  219. PrimitiveType
  220. | ReferenceType
  221. ;
  222. */
  223. PrimitiveType:
  224. NumericType
  225. | BOOLEAN
  226. { $$ = parse_java_type->builtin_boolean; }
  227. ;
  228. NumericType:
  229. IntegralType
  230. | FloatingPointType
  231. ;
  232. IntegralType:
  233. BYTE
  234. { $$ = parse_java_type->builtin_byte; }
  235. | SHORT
  236. { $$ = parse_java_type->builtin_short; }
  237. | INT
  238. { $$ = parse_java_type->builtin_int; }
  239. | LONG
  240. { $$ = parse_java_type->builtin_long; }
  241. | CHAR
  242. { $$ = parse_java_type->builtin_char; }
  243. ;
  244. FloatingPointType:
  245. FLOAT
  246. { $$ = parse_java_type->builtin_float; }
  247. | DOUBLE
  248. { $$ = parse_java_type->builtin_double; }
  249. ;
  250. /* UNUSED:
  251. ReferenceType:
  252. ClassOrInterfaceType
  253. | ArrayType
  254. ;
  255. */
  256. ClassOrInterfaceType:
  257. Name
  258. { $$ = java_type_from_name ($1); }
  259. ;
  260. ClassType:
  261. ClassOrInterfaceType
  262. ;
  263. ArrayType:
  264. PrimitiveType Dims
  265. { $$ = java_array_type ($1, $2); }
  266. | Name Dims
  267. { $$ = java_array_type (java_type_from_name ($1), $2); }
  268. ;
  269. Name:
  270. IDENTIFIER
  271. | QualifiedName
  272. ;
  273. ForcedName:
  274. SimpleName
  275. | QualifiedName
  276. ;
  277. SimpleName:
  278. IDENTIFIER
  279. | NAME_OR_INT
  280. ;
  281. QualifiedName:
  282. Name '.' SimpleName
  283. { $$.length = $1.length + $3.length + 1;
  284. if ($1.ptr + $1.length + 1 == $3.ptr
  285. && $1.ptr[$1.length] == '.')
  286. $$.ptr = $1.ptr; /* Optimization. */
  287. else
  288. {
  289. $$.ptr = (char *) malloc ($$.length + 1);
  290. make_cleanup (free, $$.ptr);
  291. sprintf ($$.ptr, "%.*s.%.*s",
  292. $1.length, $1.ptr, $3.length, $3.ptr);
  293. } }
  294. ;
  295. /*
  296. type_exp: type
  297. { write_exp_elt_opcode(OP_TYPE);
  298. write_exp_elt_type($1);
  299. write_exp_elt_opcode(OP_TYPE);}
  300. ;
  301. */
  302. /* Expressions, including the comma operator. */
  303. exp1 : Expression
  304. | exp1 ',' Expression
  305. { write_exp_elt_opcode (BINOP_COMMA); }
  306. ;
  307. Primary:
  308. PrimaryNoNewArray
  309. | ArrayCreationExpression
  310. ;
  311. PrimaryNoNewArray:
  312. Literal
  313. | '(' Expression ')'
  314. | ClassInstanceCreationExpression
  315. | FieldAccess
  316. | MethodInvocation
  317. | ArrayAccess
  318. | lcurly ArgumentList rcurly
  319. { write_exp_elt_opcode (OP_ARRAY);
  320. write_exp_elt_longcst ((LONGEST) 0);
  321. write_exp_elt_longcst ((LONGEST) $3);
  322. write_exp_elt_opcode (OP_ARRAY); }
  323. ;
  324. lcurly:
  325. '{'
  326. { start_arglist (); }
  327. ;
  328. rcurly:
  329. '}'
  330. { $$ = end_arglist () - 1; }
  331. ;
  332. ClassInstanceCreationExpression:
  333. NEW ClassType '(' ArgumentList_opt ')'
  334. { internal_error (__FILE__, __LINE__,
  335. _("FIXME - ClassInstanceCreationExpression")); }
  336. ;
  337. ArgumentList:
  338. Expression
  339. { arglist_len = 1; }
  340. | ArgumentList ',' Expression
  341. { arglist_len++; }
  342. ;
  343. ArgumentList_opt:
  344. /* EMPTY */
  345. { arglist_len = 0; }
  346. | ArgumentList
  347. ;
  348. ArrayCreationExpression:
  349. NEW PrimitiveType DimExprs Dims_opt
  350. { internal_error (__FILE__, __LINE__,
  351. _("FIXME - ArrayCreationExpression")); }
  352. | NEW ClassOrInterfaceType DimExprs Dims_opt
  353. { internal_error (__FILE__, __LINE__,
  354. _("FIXME - ArrayCreationExpression")); }
  355. ;
  356. DimExprs:
  357. DimExpr
  358. | DimExprs DimExpr
  359. ;
  360. DimExpr:
  361. '[' Expression ']'
  362. ;
  363. Dims:
  364. '[' ']'
  365. { $$ = 1; }
  366. | Dims '[' ']'
  367. { $$ = $1 + 1; }
  368. ;
  369. Dims_opt:
  370. Dims
  371. | /* EMPTY */
  372. { $$ = 0; }
  373. ;
  374. FieldAccess:
  375. Primary '.' SimpleName
  376. { push_fieldnames ($3); }
  377. | VARIABLE '.' SimpleName
  378. { push_fieldnames ($3); }
  379. /*| SUPER '.' SimpleName { FIXME } */
  380. ;
  381. FuncStart:
  382. Name '('
  383. { push_expression_name ($1); }
  384. ;
  385. MethodInvocation:
  386. FuncStart
  387. { start_arglist(); }
  388. ArgumentList_opt ')'
  389. { write_exp_elt_opcode (OP_FUNCALL);
  390. write_exp_elt_longcst ((LONGEST) end_arglist ());
  391. write_exp_elt_opcode (OP_FUNCALL); }
  392. | Primary '.' SimpleName '(' ArgumentList_opt ')'
  393. { error (_("Form of method invocation not implemented")); }
  394. | SUPER '.' SimpleName '(' ArgumentList_opt ')'
  395. { error (_("Form of method invocation not implemented")); }
  396. ;
  397. ArrayAccess:
  398. Name '[' Expression ']'
  399. {
  400. /* Emit code for the Name now, then exchange it in the
  401. expout array with the Expression's code. We could
  402. introduce a OP_SWAP code or a reversed version of
  403. BINOP_SUBSCRIPT, but that makes the rest of GDB pay
  404. for our parsing kludges. */
  405. struct expression *name_expr;
  406. push_expression_name ($1);
  407. name_expr = copy_exp (expout, expout_ptr);
  408. expout_ptr -= name_expr->nelts;
  409. insert_exp (expout_ptr-length_of_subexp (expout, expout_ptr),
  410. name_expr);
  411. free (name_expr);
  412. write_exp_elt_opcode (BINOP_SUBSCRIPT);
  413. }
  414. | VARIABLE '[' Expression ']'
  415. { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
  416. | PrimaryNoNewArray '[' Expression ']'
  417. { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
  418. ;
  419. PostfixExpression:
  420. Primary
  421. | Name
  422. { push_expression_name ($1); }
  423. | VARIABLE
  424. /* Already written by write_dollar_variable. */
  425. | PostIncrementExpression
  426. | PostDecrementExpression
  427. ;
  428. PostIncrementExpression:
  429. PostfixExpression INCREMENT
  430. { write_exp_elt_opcode (UNOP_POSTINCREMENT); }
  431. ;
  432. PostDecrementExpression:
  433. PostfixExpression DECREMENT
  434. { write_exp_elt_opcode (UNOP_POSTDECREMENT); }
  435. ;
  436. UnaryExpression:
  437. PreIncrementExpression
  438. | PreDecrementExpression
  439. | '+' UnaryExpression
  440. | '-' UnaryExpression
  441. { write_exp_elt_opcode (UNOP_NEG); }
  442. | '*' UnaryExpression
  443. { write_exp_elt_opcode (UNOP_IND); } /*FIXME not in Java */
  444. | UnaryExpressionNotPlusMinus
  445. ;
  446. PreIncrementExpression:
  447. INCREMENT UnaryExpression
  448. { write_exp_elt_opcode (UNOP_PREINCREMENT); }
  449. ;
  450. PreDecrementExpression:
  451. DECREMENT UnaryExpression
  452. { write_exp_elt_opcode (UNOP_PREDECREMENT); }
  453. ;
  454. UnaryExpressionNotPlusMinus:
  455. PostfixExpression
  456. | '~' UnaryExpression
  457. { write_exp_elt_opcode (UNOP_COMPLEMENT); }
  458. | '!' UnaryExpression
  459. { write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
  460. | CastExpression
  461. ;
  462. CastExpression:
  463. '(' PrimitiveType Dims_opt ')' UnaryExpression
  464. { write_exp_elt_opcode (UNOP_CAST);
  465. write_exp_elt_type (java_array_type ($2, $3));
  466. write_exp_elt_opcode (UNOP_CAST); }
  467. | '(' Expression ')' UnaryExpressionNotPlusMinus
  468. {
  469. int last_exp_size = length_of_subexp(expout, expout_ptr);
  470. struct type *type;
  471. int i;
  472. int base = expout_ptr - last_exp_size - 3;
  473. if (base < 0 || expout->elts[base+2].opcode != OP_TYPE)
  474. error (_("Invalid cast expression"));
  475. type = expout->elts[base+1].type;
  476. /* Remove the 'Expression' and slide the
  477. UnaryExpressionNotPlusMinus down to replace it. */
  478. for (i = 0; i < last_exp_size; i++)
  479. expout->elts[base + i] = expout->elts[base + i + 3];
  480. expout_ptr -= 3;
  481. if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
  482. type = lookup_pointer_type (type);
  483. write_exp_elt_opcode (UNOP_CAST);
  484. write_exp_elt_type (type);
  485. write_exp_elt_opcode (UNOP_CAST);
  486. }
  487. | '(' Name Dims ')' UnaryExpressionNotPlusMinus
  488. { write_exp_elt_opcode (UNOP_CAST);
  489. write_exp_elt_type (java_array_type (java_type_from_name ($2), $3));
  490. write_exp_elt_opcode (UNOP_CAST); }
  491. ;
  492. MultiplicativeExpression:
  493. UnaryExpression
  494. | MultiplicativeExpression '*' UnaryExpression
  495. { write_exp_elt_opcode (BINOP_MUL); }
  496. | MultiplicativeExpression '/' UnaryExpression
  497. { write_exp_elt_opcode (BINOP_DIV); }
  498. | MultiplicativeExpression '%' UnaryExpression
  499. { write_exp_elt_opcode (BINOP_REM); }
  500. ;
  501. AdditiveExpression:
  502. MultiplicativeExpression
  503. | AdditiveExpression '+' MultiplicativeExpression
  504. { write_exp_elt_opcode (BINOP_ADD); }
  505. | AdditiveExpression '-' MultiplicativeExpression
  506. { write_exp_elt_opcode (BINOP_SUB); }
  507. ;
  508. ShiftExpression:
  509. AdditiveExpression
  510. | ShiftExpression LSH AdditiveExpression
  511. { write_exp_elt_opcode (BINOP_LSH); }
  512. | ShiftExpression RSH AdditiveExpression
  513. { write_exp_elt_opcode (BINOP_RSH); }
  514. /* | ShiftExpression >>> AdditiveExpression { FIXME } */
  515. ;
  516. RelationalExpression:
  517. ShiftExpression
  518. | RelationalExpression '<' ShiftExpression
  519. { write_exp_elt_opcode (BINOP_LESS); }
  520. | RelationalExpression '>' ShiftExpression
  521. { write_exp_elt_opcode (BINOP_GTR); }
  522. | RelationalExpression LEQ ShiftExpression
  523. { write_exp_elt_opcode (BINOP_LEQ); }
  524. | RelationalExpression GEQ ShiftExpression
  525. { write_exp_elt_opcode (BINOP_GEQ); }
  526. /* | RelationalExpresion INSTANCEOF ReferenceType { FIXME } */
  527. ;
  528. EqualityExpression:
  529. RelationalExpression
  530. | EqualityExpression EQUAL RelationalExpression
  531. { write_exp_elt_opcode (BINOP_EQUAL); }
  532. | EqualityExpression NOTEQUAL RelationalExpression
  533. { write_exp_elt_opcode (BINOP_NOTEQUAL); }
  534. ;
  535. AndExpression:
  536. EqualityExpression
  537. | AndExpression '&' EqualityExpression
  538. { write_exp_elt_opcode (BINOP_BITWISE_AND); }
  539. ;
  540. ExclusiveOrExpression:
  541. AndExpression
  542. | ExclusiveOrExpression '^' AndExpression
  543. { write_exp_elt_opcode (BINOP_BITWISE_XOR); }
  544. ;
  545. InclusiveOrExpression:
  546. ExclusiveOrExpression
  547. | InclusiveOrExpression '|' ExclusiveOrExpression
  548. { write_exp_elt_opcode (BINOP_BITWISE_IOR); }
  549. ;
  550. ConditionalAndExpression:
  551. InclusiveOrExpression
  552. | ConditionalAndExpression ANDAND InclusiveOrExpression
  553. { write_exp_elt_opcode (BINOP_LOGICAL_AND); }
  554. ;
  555. ConditionalOrExpression:
  556. ConditionalAndExpression
  557. | ConditionalOrExpression OROR ConditionalAndExpression
  558. { write_exp_elt_opcode (BINOP_LOGICAL_OR); }
  559. ;
  560. ConditionalExpression:
  561. ConditionalOrExpression
  562. | ConditionalOrExpression '?' Expression ':' ConditionalExpression
  563. { write_exp_elt_opcode (TERNOP_COND); }
  564. ;
  565. AssignmentExpression:
  566. ConditionalExpression
  567. | Assignment
  568. ;
  569. Assignment:
  570. LeftHandSide '=' ConditionalExpression
  571. { write_exp_elt_opcode (BINOP_ASSIGN); }
  572. | LeftHandSide ASSIGN_MODIFY ConditionalExpression
  573. { write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
  574. write_exp_elt_opcode ($2);
  575. write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); }
  576. ;
  577. LeftHandSide:
  578. ForcedName
  579. { push_expression_name ($1); }
  580. | VARIABLE
  581. /* Already written by write_dollar_variable. */
  582. | FieldAccess
  583. | ArrayAccess
  584. ;
  585. Expression:
  586. AssignmentExpression
  587. ;
  588. %%
  589. /* Take care of parsing a number (anything that starts with a digit).
  590. Set yylval and return the token type; update lexptr.
  591. LEN is the number of characters in it. */
  592. /*** Needs some error checking for the float case ***/
  593. static int
  594. parse_number (char *p, int len, int parsed_float, YYSTYPE *putithere)
  595. {
  596. ULONGEST n = 0;
  597. ULONGEST limit, limit_div_base;
  598. int c;
  599. int base = input_radix;
  600. struct type *type;
  601. if (parsed_float)
  602. {
  603. const char *suffix;
  604. int suffix_len;
  605. if (! parse_float (p, len, &putithere->typed_val_float.dval, &suffix))
  606. return ERROR;
  607. suffix_len = p + len - suffix;
  608. if (suffix_len == 0)
  609. putithere->typed_val_float.type = parse_type->builtin_double;
  610. else if (suffix_len == 1)
  611. {
  612. /* See if it has `f' or `d' suffix (float or double). */
  613. if (tolower (*suffix) == 'f')
  614. putithere->typed_val_float.type =
  615. parse_type->builtin_float;
  616. else if (tolower (*suffix) == 'd')
  617. putithere->typed_val_float.type =
  618. parse_type->builtin_double;
  619. else
  620. return ERROR;
  621. }
  622. else
  623. return ERROR;
  624. return FLOATING_POINT_LITERAL;
  625. }
  626. /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
  627. if (p[0] == '0')
  628. switch (p[1])
  629. {
  630. case 'x':
  631. case 'X':
  632. if (len >= 3)
  633. {
  634. p += 2;
  635. base = 16;
  636. len -= 2;
  637. }
  638. break;
  639. case 't':
  640. case 'T':
  641. case 'd':
  642. case 'D':
  643. if (len >= 3)
  644. {
  645. p += 2;
  646. base = 10;
  647. len -= 2;
  648. }
  649. break;
  650. default:
  651. base = 8;
  652. break;
  653. }
  654. c = p[len-1];
  655. /* A paranoid calculation of (1<<64)-1. */
  656. limit = (ULONGEST)0xffffffff;
  657. limit = ((limit << 16) << 16) | limit;
  658. if (c == 'l' || c == 'L')
  659. {
  660. type = parse_java_type->builtin_long;
  661. len--;
  662. }
  663. else
  664. {
  665. type = parse_java_type->builtin_int;
  666. }
  667. limit_div_base = limit / (ULONGEST) base;
  668. while (--len >= 0)
  669. {
  670. c = *p++;
  671. if (c >= '0' && c <= '9')
  672. c -= '0';
  673. else if (c >= 'A' && c <= 'Z')
  674. c -= 'A' - 10;
  675. else if (c >= 'a' && c <= 'z')
  676. c -= 'a' - 10;
  677. else
  678. return ERROR; /* Char not a digit */
  679. if (c >= base)
  680. return ERROR;
  681. if (n > limit_div_base
  682. || (n *= base) > limit - c)
  683. error (_("Numeric constant too large"));
  684. n += c;
  685. }
  686. /* If the type is bigger than a 32-bit signed integer can be, implicitly
  687. promote to long. Java does not do this, so mark it as
  688. parse_type->builtin_uint64 rather than parse_java_type->builtin_long.
  689. 0x80000000 will become -0x80000000 instead of 0x80000000L, because we
  690. don't know the sign at this point. */
  691. if (type == parse_java_type->builtin_int && n > (ULONGEST)0x80000000)
  692. type = parse_type->builtin_uint64;
  693. putithere->typed_val_int.val = n;
  694. putithere->typed_val_int.type = type;
  695. return INTEGER_LITERAL;
  696. }
  697. struct token
  698. {
  699. char *operator;
  700. int token;
  701. enum exp_opcode opcode;
  702. };
  703. static const struct token tokentab3[] =
  704. {
  705. {">>=", ASSIGN_MODIFY, BINOP_RSH},
  706. {"<<=", ASSIGN_MODIFY, BINOP_LSH}
  707. };
  708. static const struct token tokentab2[] =
  709. {
  710. {"+=", ASSIGN_MODIFY, BINOP_ADD},
  711. {"-=", ASSIGN_MODIFY, BINOP_SUB},
  712. {"*=", ASSIGN_MODIFY, BINOP_MUL},
  713. {"/=", ASSIGN_MODIFY, BINOP_DIV},
  714. {"%=", ASSIGN_MODIFY, BINOP_REM},
  715. {"|=", ASSIGN_MODIFY, BINOP_BITWISE_IOR},
  716. {"&=", ASSIGN_MODIFY, BINOP_BITWISE_AND},
  717. {"^=", ASSIGN_MODIFY, BINOP_BITWISE_XOR},
  718. {"++", INCREMENT, BINOP_END},
  719. {"--", DECREMENT, BINOP_END},
  720. {"&&", ANDAND, BINOP_END},
  721. {"||", OROR, BINOP_END},
  722. {"<<", LSH, BINOP_END},
  723. {">>", RSH, BINOP_END},
  724. {"==", EQUAL, BINOP_END},
  725. {"!=", NOTEQUAL, BINOP_END},
  726. {"<=", LEQ, BINOP_END},
  727. {">=", GEQ, BINOP_END}
  728. };
  729. /* Read one token, getting characters through lexptr. */
  730. static int
  731. yylex (void)
  732. {
  733. int c;
  734. int namelen;
  735. unsigned int i;
  736. char *tokstart;
  737. char *tokptr;
  738. int tempbufindex;
  739. static char *tempbuf;
  740. static int tempbufsize;
  741. retry:
  742. prev_lexptr = lexptr;
  743. tokstart = lexptr;
  744. /* See if it is a special token of length 3. */
  745. for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
  746. if (strncmp (tokstart, tokentab3[i].operator, 3) == 0)
  747. {
  748. lexptr += 3;
  749. yylval.opcode = tokentab3[i].opcode;
  750. return tokentab3[i].token;
  751. }
  752. /* See if it is a special token of length 2. */
  753. for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
  754. if (strncmp (tokstart, tokentab2[i].operator, 2) == 0)
  755. {
  756. lexptr += 2;
  757. yylval.opcode = tokentab2[i].opcode;
  758. return tokentab2[i].token;
  759. }
  760. switch (c = *tokstart)
  761. {
  762. case 0:
  763. return 0;
  764. case ' ':
  765. case '\t':
  766. case '\n':
  767. lexptr++;
  768. goto retry;
  769. case '\'':
  770. /* We either have a character constant ('0' or '\177' for example)
  771. or we have a quoted symbol reference ('foo(int,int)' in C++
  772. for example). */
  773. lexptr++;
  774. c = *lexptr++;
  775. if (c == '\\')
  776. c = parse_escape (parse_gdbarch, &lexptr);
  777. else if (c == '\'')
  778. error (_("Empty character constant"));
  779. yylval.typed_val_int.val = c;
  780. yylval.typed_val_int.type = parse_java_type->builtin_char;
  781. c = *lexptr++;
  782. if (c != '\'')
  783. {
  784. namelen = skip_quoted (tokstart) - tokstart;
  785. if (namelen > 2)
  786. {
  787. lexptr = tokstart + namelen;
  788. if (lexptr[-1] != '\'')
  789. error (_("Unmatched single quote"));
  790. namelen -= 2;
  791. tokstart++;
  792. goto tryname;
  793. }
  794. error (_("Invalid character constant"));
  795. }
  796. return INTEGER_LITERAL;
  797. case '(':
  798. paren_depth++;
  799. lexptr++;
  800. return c;
  801. case ')':
  802. if (paren_depth == 0)
  803. return 0;
  804. paren_depth--;
  805. lexptr++;
  806. return c;
  807. case ',':
  808. if (comma_terminates && paren_depth == 0)
  809. return 0;
  810. lexptr++;
  811. return c;
  812. case '.':
  813. /* Might be a floating point number. */
  814. if (lexptr[1] < '0' || lexptr[1] > '9')
  815. goto symbol; /* Nope, must be a symbol. */
  816. /* FALL THRU into number case. */
  817. case '0':
  818. case '1':
  819. case '2':
  820. case '3':
  821. case '4':
  822. case '5':
  823. case '6':
  824. case '7':
  825. case '8':
  826. case '9':
  827. {
  828. /* It's a number. */
  829. int got_dot = 0, got_e = 0, toktype;
  830. char *p = tokstart;
  831. int hex = input_radix > 10;
  832. if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
  833. {
  834. p += 2;
  835. hex = 1;
  836. }
  837. else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D'))
  838. {
  839. p += 2;
  840. hex = 0;
  841. }
  842. for (;; ++p)
  843. {
  844. /* This test includes !hex because 'e' is a valid hex digit
  845. and thus does not indicate a floating point number when
  846. the radix is hex. */
  847. if (!hex && !got_e && (*p == 'e' || *p == 'E'))
  848. got_dot = got_e = 1;
  849. /* This test does not include !hex, because a '.' always indicates
  850. a decimal floating point number regardless of the radix. */
  851. else if (!got_dot && *p == '.')
  852. got_dot = 1;
  853. else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
  854. && (*p == '-' || *p == '+'))
  855. /* This is the sign of the exponent, not the end of the
  856. number. */
  857. continue;
  858. /* We will take any letters or digits. parse_number will
  859. complain if past the radix, or if L or U are not final. */
  860. else if ((*p < '0' || *p > '9')
  861. && ((*p < 'a' || *p > 'z')
  862. && (*p < 'A' || *p > 'Z')))
  863. break;
  864. }
  865. toktype = parse_number (tokstart, p - tokstart, got_dot|got_e, &yylval);
  866. if (toktype == ERROR)
  867. {
  868. char *err_copy = (char *) alloca (p - tokstart + 1);
  869. memcpy (err_copy, tokstart, p - tokstart);
  870. err_copy[p - tokstart] = 0;
  871. error (_("Invalid number \"%s\""), err_copy);
  872. }
  873. lexptr = p;
  874. return toktype;
  875. }
  876. case '+':
  877. case '-':
  878. case '*':
  879. case '/':
  880. case '%':
  881. case '|':
  882. case '&':
  883. case '^':
  884. case '~':
  885. case '!':
  886. case '<':
  887. case '>':
  888. case '[':
  889. case ']':
  890. case '?':
  891. case ':':
  892. case '=':
  893. case '{':
  894. case '}':
  895. symbol:
  896. lexptr++;
  897. return c;
  898. case '"':
  899. /* Build the gdb internal form of the input string in tempbuf,
  900. translating any standard C escape forms seen. Note that the
  901. buffer is null byte terminated *only* for the convenience of
  902. debugging gdb itself and printing the buffer contents when
  903. the buffer contains no embedded nulls. Gdb does not depend
  904. upon the buffer being null byte terminated, it uses the length
  905. string instead. This allows gdb to handle C strings (as well
  906. as strings in other languages) with embedded null bytes */
  907. tokptr = ++tokstart;
  908. tempbufindex = 0;
  909. do {
  910. /* Grow the static temp buffer if necessary, including allocating
  911. the first one on demand. */
  912. if (tempbufindex + 1 >= tempbufsize)
  913. {
  914. tempbuf = (char *) realloc (tempbuf, tempbufsize += 64);
  915. }
  916. switch (*tokptr)
  917. {
  918. case '\0':
  919. case '"':
  920. /* Do nothing, loop will terminate. */
  921. break;
  922. case '\\':
  923. tokptr++;
  924. c = parse_escape (parse_gdbarch, &tokptr);
  925. if (c == -1)
  926. {
  927. continue;
  928. }
  929. tempbuf[tempbufindex++] = c;
  930. break;
  931. default:
  932. tempbuf[tempbufindex++] = *tokptr++;
  933. break;
  934. }
  935. } while ((*tokptr != '"') && (*tokptr != '\0'));
  936. if (*tokptr++ != '"')
  937. {
  938. error (_("Unterminated string in expression"));
  939. }
  940. tempbuf[tempbufindex] = '\0'; /* See note above */
  941. yylval.sval.ptr = tempbuf;
  942. yylval.sval.length = tempbufindex;
  943. lexptr = tokptr;
  944. return (STRING_LITERAL);
  945. }
  946. if (!(c == '_' || c == '$'
  947. || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
  948. /* We must have come across a bad character (e.g. ';'). */
  949. error (_("Invalid character '%c' in expression"), c);
  950. /* It's a name. See how long it is. */
  951. namelen = 0;
  952. for (c = tokstart[namelen];
  953. (c == '_'
  954. || c == '$'
  955. || (c >= '0' && c <= '9')
  956. || (c >= 'a' && c <= 'z')
  957. || (c >= 'A' && c <= 'Z')
  958. || c == '<');
  959. )
  960. {
  961. if (c == '<')
  962. {
  963. int i = namelen;
  964. while (tokstart[++i] && tokstart[i] != '>');
  965. if (tokstart[i] == '>')
  966. namelen = i;
  967. }
  968. c = tokstart[++namelen];
  969. }
  970. /* The token "if" terminates the expression and is NOT
  971. removed from the input stream. */
  972. if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
  973. {
  974. return 0;
  975. }
  976. lexptr += namelen;
  977. tryname:
  978. /* Catch specific keywords. Should be done with a data structure. */
  979. switch (namelen)
  980. {
  981. case 7:
  982. if (strncmp (tokstart, "boolean", 7) == 0)
  983. return BOOLEAN;
  984. break;
  985. case 6:
  986. if (strncmp (tokstart, "double", 6) == 0)
  987. return DOUBLE;
  988. break;
  989. case 5:
  990. if (strncmp (tokstart, "short", 5) == 0)
  991. return SHORT;
  992. if (strncmp (tokstart, "false", 5) == 0)
  993. {
  994. yylval.lval = 0;
  995. return BOOLEAN_LITERAL;
  996. }
  997. if (strncmp (tokstart, "super", 5) == 0)
  998. return SUPER;
  999. if (strncmp (tokstart, "float", 5) == 0)
  1000. return FLOAT;
  1001. break;
  1002. case 4:
  1003. if (strncmp (tokstart, "long", 4) == 0)
  1004. return LONG;
  1005. if (strncmp (tokstart, "byte", 4) == 0)
  1006. return BYTE;
  1007. if (strncmp (tokstart, "char", 4) == 0)
  1008. return CHAR;
  1009. if (strncmp (tokstart, "true", 4) == 0)
  1010. {
  1011. yylval.lval = 1;
  1012. return BOOLEAN_LITERAL;
  1013. }
  1014. break;
  1015. case 3:
  1016. if (strncmp (tokstart, "int", 3) == 0)
  1017. return INT;
  1018. if (strncmp (tokstart, "new", 3) == 0)
  1019. return NEW;
  1020. break;
  1021. default:
  1022. break;
  1023. }
  1024. yylval.sval.ptr = tokstart;
  1025. yylval.sval.length = namelen;
  1026. if (*tokstart == '$')
  1027. {
  1028. write_dollar_variable (yylval.sval);
  1029. return VARIABLE;
  1030. }
  1031. /* Input names that aren't symbols but ARE valid hex numbers,
  1032. when the input radix permits them, can be names or numbers
  1033. depending on the parse. Note we support radixes > 16 here. */
  1034. if (((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10) ||
  1035. (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
  1036. {
  1037. YYSTYPE newlval; /* Its value is ignored. */
  1038. int hextype = parse_number (tokstart, namelen, 0, &newlval);
  1039. if (hextype == INTEGER_LITERAL)
  1040. return NAME_OR_INT;
  1041. }
  1042. return IDENTIFIER;
  1043. }
  1044. void
  1045. yyerror (char *msg)
  1046. {
  1047. if (prev_lexptr)
  1048. lexptr = prev_lexptr;
  1049. if (msg)
  1050. error (_("%s: near `%s'"), msg, lexptr);
  1051. else
  1052. error (_("error in expression, near `%s'"), lexptr);
  1053. }
  1054. static struct type *
  1055. java_type_from_name (struct stoken name)
  1056. {
  1057. char *tmp = copy_name (name);
  1058. struct type *typ = java_lookup_class (tmp);
  1059. if (typ == NULL || TYPE_CODE (typ) != TYPE_CODE_STRUCT)
  1060. error (_("No class named `%s'"), tmp);
  1061. return typ;
  1062. }
  1063. /* If NAME is a valid variable name in this scope, push it and return 1.
  1064. Otherwise, return 0. */
  1065. static int
  1066. push_variable (struct stoken name)
  1067. {
  1068. char *tmp = copy_name (name);
  1069. int is_a_field_of_this = 0;
  1070. struct symbol *sym;
  1071. sym = lookup_symbol (tmp, expression_context_block, VAR_DOMAIN,
  1072. &is_a_field_of_this);
  1073. if (sym && SYMBOL_CLASS (sym) != LOC_TYPEDEF)
  1074. {
  1075. if (symbol_read_needs_frame (sym))
  1076. {
  1077. if (innermost_block == 0 ||
  1078. contained_in (block_found, innermost_block))
  1079. innermost_block = block_found;
  1080. }
  1081. write_exp_elt_opcode (OP_VAR_VALUE);
  1082. /* We want to use the selected frame, not another more inner frame
  1083. which happens to be in the same block. */
  1084. write_exp_elt_block (NULL);
  1085. write_exp_elt_sym (sym);
  1086. write_exp_elt_opcode (OP_VAR_VALUE);
  1087. return 1;
  1088. }
  1089. if (is_a_field_of_this)
  1090. {
  1091. /* it hangs off of `this'. Must not inadvertently convert from a
  1092. method call to data ref. */
  1093. if (innermost_block == 0 ||
  1094. contained_in (block_found, innermost_block))
  1095. innermost_block = block_found;
  1096. write_exp_elt_opcode (OP_THIS);
  1097. write_exp_elt_opcode (OP_THIS);
  1098. write_exp_elt_opcode (STRUCTOP_PTR);
  1099. write_exp_string (name);
  1100. write_exp_elt_opcode (STRUCTOP_PTR);
  1101. return 1;
  1102. }
  1103. return 0;
  1104. }
  1105. /* Assuming a reference expression has been pushed, emit the
  1106. STRUCTOP_PTR ops to access the field named NAME. If NAME is a
  1107. qualified name (has '.'), generate a field access for each part. */
  1108. static void
  1109. push_fieldnames (struct stoken name)
  1110. {
  1111. int i;
  1112. struct stoken token;
  1113. token.ptr = name.ptr;
  1114. for (i = 0; ; i++)
  1115. {
  1116. if (i == name.length || name.ptr[i] == '.')
  1117. {
  1118. /* token.ptr is start of current field name. */
  1119. token.length = &name.ptr[i] - token.ptr;
  1120. write_exp_elt_opcode (STRUCTOP_PTR);
  1121. write_exp_string (token);
  1122. write_exp_elt_opcode (STRUCTOP_PTR);
  1123. token.ptr += token.length + 1;
  1124. }
  1125. if (i >= name.length)
  1126. break;
  1127. }
  1128. }
  1129. /* Helper routine for push_expression_name.
  1130. Handle a qualified name, where DOT_INDEX is the index of the first '.' */
  1131. static void
  1132. push_qualified_expression_name (struct stoken name, int dot_index)
  1133. {
  1134. struct stoken token;
  1135. char *tmp;
  1136. struct type *typ;
  1137. token.ptr = name.ptr;
  1138. token.length = dot_index;
  1139. if (push_variable (token))
  1140. {
  1141. token.ptr = name.ptr + dot_index + 1;
  1142. token.length = name.length - dot_index - 1;
  1143. push_fieldnames (token);
  1144. return;
  1145. }
  1146. token.ptr = name.ptr;
  1147. for (;;)
  1148. {
  1149. token.length = dot_index;
  1150. tmp = copy_name (token);
  1151. typ = java_lookup_class (tmp);
  1152. if (typ != NULL)
  1153. {
  1154. if (dot_index == name.length)
  1155. {
  1156. write_exp_elt_opcode(OP_TYPE);
  1157. write_exp_elt_type(typ);
  1158. write_exp_elt_opcode(OP_TYPE);
  1159. return;
  1160. }
  1161. dot_index++; /* Skip '.' */
  1162. name.ptr += dot_index;
  1163. name.length -= dot_index;
  1164. dot_index = 0;
  1165. while (dot_index < name.length && name.ptr[dot_index] != '.')
  1166. dot_index++;
  1167. token.ptr = name.ptr;
  1168. token.length = dot_index;
  1169. write_exp_elt_opcode (OP_SCOPE);
  1170. write_exp_elt_type (typ);
  1171. write_exp_string (token);
  1172. write_exp_elt_opcode (OP_SCOPE);
  1173. if (dot_index < name.length)
  1174. {
  1175. dot_index++;
  1176. name.ptr += dot_index;
  1177. name.length -= dot_index;
  1178. push_fieldnames (name);
  1179. }
  1180. return;
  1181. }
  1182. else if (dot_index >= name.length)
  1183. break;
  1184. dot_index++; /* Skip '.' */
  1185. while (dot_index < name.length && name.ptr[dot_index] != '.')
  1186. dot_index++;
  1187. }
  1188. error (_("unknown type `%.*s'"), name.length, name.ptr);
  1189. }
  1190. /* Handle Name in an expression (or LHS).
  1191. Handle VAR, TYPE, TYPE.FIELD1....FIELDN and VAR.FIELD1....FIELDN. */
  1192. static void
  1193. push_expression_name (struct stoken name)
  1194. {
  1195. char *tmp;
  1196. struct type *typ;
  1197. int i;
  1198. for (i = 0; i < name.length; i++)
  1199. {
  1200. if (name.ptr[i] == '.')
  1201. {
  1202. /* It's a Qualified Expression Name. */
  1203. push_qualified_expression_name (name, i);
  1204. return;
  1205. }
  1206. }
  1207. /* It's a Simple Expression Name. */
  1208. if (push_variable (name))
  1209. return;
  1210. tmp = copy_name (name);
  1211. typ = java_lookup_class (tmp);
  1212. if (typ != NULL)
  1213. {
  1214. write_exp_elt_opcode(OP_TYPE);
  1215. write_exp_elt_type(typ);
  1216. write_exp_elt_opcode(OP_TYPE);
  1217. }
  1218. else
  1219. {
  1220. struct minimal_symbol *msymbol;
  1221. msymbol = lookup_minimal_symbol (tmp, NULL, NULL);
  1222. if (msymbol != NULL)
  1223. write_exp_msymbol (msymbol);
  1224. else if (!have_full_symbols () && !have_partial_symbols ())
  1225. error (_("No symbol table is loaded. Use the \"file\" command"));
  1226. else
  1227. error (_("No symbol \"%s\" in current context"), tmp);
  1228. }
  1229. }
  1230. /* The following two routines, copy_exp and insert_exp, aren't specific to
  1231. Java, so they could go in parse.c, but their only purpose is to support
  1232. the parsing kludges we use in this file, so maybe it's best to isolate
  1233. them here. */
  1234. /* Copy the expression whose last element is at index ENDPOS - 1 in EXPR
  1235. into a freshly malloc'ed struct expression. Its language_defn is set
  1236. to null. */
  1237. static struct expression *
  1238. copy_exp (struct expression *expr, int endpos)
  1239. {
  1240. int len = length_of_subexp (expr, endpos);
  1241. struct expression *new
  1242. = (struct expression *) malloc (sizeof (*new) + EXP_ELEM_TO_BYTES (len));
  1243. new->nelts = len;
  1244. memcpy (new->elts, expr->elts + endpos - len, EXP_ELEM_TO_BYTES (len));
  1245. new->language_defn = 0;
  1246. return new;
  1247. }
  1248. /* Insert the expression NEW into the current expression (expout) at POS. */
  1249. static void
  1250. insert_exp (int pos, struct expression *new)
  1251. {
  1252. int newlen = new->nelts;
  1253. /* Grow expout if necessary. In this function's only use at present,
  1254. this should never be necessary. */
  1255. if (expout_ptr + newlen > expout_size)
  1256. {
  1257. expout_size = max (expout_size * 2, expout_ptr + newlen + 10);
  1258. expout = (struct expression *)
  1259. realloc ((char *) expout, (sizeof (struct expression)
  1260. + EXP_ELEM_TO_BYTES (expout_size)));
  1261. }
  1262. {
  1263. int i;
  1264. for (i = expout_ptr - 1; i >= pos; i--)
  1265. expout->elts[i + newlen] = expout->elts[i];
  1266. }
  1267. memcpy (expout->elts + pos, new->elts, EXP_ELEM_TO_BYTES (newlen));
  1268. expout_ptr += newlen;
  1269. }