expprint.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /* Print in infix form a struct expression.
  2. Copyright (C) 1986 Free Software Foundation, Inc.
  3. GDB is distributed in the hope that it will be useful, but WITHOUT ANY
  4. WARRANTY. No author or distributor accepts responsibility to anyone
  5. for the consequences of using it or for whether it serves any
  6. particular purpose or works at all, unless he says so in writing.
  7. Refer to the GDB General Public License for full details.
  8. Everyone is granted permission to copy, modify and redistribute GDB,
  9. but only under the conditions described in the GDB General Public
  10. License. A copy of this license is supposed to have been given to you
  11. along with GDB so you can know your rights and responsibilities. It
  12. should be in a file named COPYING. Among other things, the copyright
  13. notice and this notice must be preserved on all copies.
  14. In other words, go ahead and share GDB, but don't try to stop
  15. anyone else from sharing it farther. Help stamp out software hoarding!
  16. */
  17. #include "defs.h"
  18. #include "symtab.h"
  19. #include "expression.h"
  20. #include <stdio.h>
  21. /* These codes indicate operator precedences, least tightly binding first. */
  22. /* Adding 1 to a precedence value is done for binary operators,
  23. on the operand which is more tightly bound, so that operators
  24. of equal precedence within that operand will get parentheses. */
  25. /* PREC_HYPER and PREC_ABOVE_COMMA are not the precedence of any operator;
  26. they are used as the "surrounding precedence" to force
  27. various kinds of things to be parenthesized. */
  28. enum precedence
  29. { PREC_NULL, PREC_COMMA, PREC_ABOVE_COMMA, PREC_ASSIGN, PREC_OR, PREC_AND,
  30. PREC_LOGIOR, PREC_LOGAND, PREC_LOGXOR, PREC_EQUAL, PREC_ORDER,
  31. PREC_SHIFT, PREC_ADD, PREC_MUL, PREC_REPEAT,
  32. PREC_HYPER, PREC_PREFIX, PREC_SUFFIX };
  33. /* Table mapping opcodes into strings for printing operators
  34. and precedences of the operators. */
  35. struct op_print
  36. {
  37. char *string;
  38. enum exp_opcode opcode;
  39. /* Precedence of operator. These values are used only by comparisons. */
  40. enum precedence precedence;
  41. int right_assoc;
  42. };
  43. static struct op_print op_print_tab[] =
  44. {
  45. {",", BINOP_COMMA, PREC_COMMA, 0},
  46. {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
  47. {"||", BINOP_OR, PREC_OR, 0},
  48. {"&&", BINOP_AND, PREC_AND, 0},
  49. {"|", BINOP_LOGIOR, PREC_LOGIOR, 0},
  50. {"&", BINOP_LOGAND, PREC_LOGAND, 0},
  51. {"^", BINOP_LOGXOR, PREC_LOGXOR, 0},
  52. {"==", BINOP_EQUAL, PREC_EQUAL, 0},
  53. {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
  54. {"<=", BINOP_LEQ, PREC_ORDER, 0},
  55. {">=", BINOP_GEQ, PREC_ORDER, 0},
  56. {">", BINOP_GTR, PREC_ORDER, 0},
  57. {"<", BINOP_LESS, PREC_ORDER, 0},
  58. {">>", BINOP_RSH, PREC_SHIFT, 0},
  59. {"<<", BINOP_LSH, PREC_SHIFT, 0},
  60. {"+", BINOP_ADD, PREC_ADD, 0},
  61. {"-", BINOP_SUB, PREC_ADD, 0},
  62. {"*", BINOP_MUL, PREC_MUL, 0},
  63. {"/", BINOP_DIV, PREC_MUL, 0},
  64. {"%", BINOP_REM, PREC_MUL, 0},
  65. {"@", BINOP_REPEAT, PREC_REPEAT, 0},
  66. {"-", UNOP_NEG, PREC_PREFIX, 0},
  67. {"!", UNOP_ZEROP, PREC_PREFIX, 0},
  68. {"~", UNOP_LOGNOT, PREC_PREFIX, 0},
  69. {"*", UNOP_IND, PREC_PREFIX, 0},
  70. {"&", UNOP_ADDR, PREC_PREFIX, 0},
  71. {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
  72. {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
  73. {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0}
  74. };
  75. static void print_subexp ();
  76. void
  77. print_expression (exp, stream)
  78. struct expression *exp;
  79. FILE *stream;
  80. {
  81. int pc = 0;
  82. print_subexp (exp, &pc, stream, PREC_NULL);
  83. }
  84. /* Print the subexpression of EXP that starts in position POS, on STREAM.
  85. PREC is the precedence of the surrounding operator;
  86. if the precedence of the main operator of this subexpression is less,
  87. parentheses are needed here. */
  88. static void
  89. print_subexp (exp, pos, stream, prec)
  90. register struct expression *exp;
  91. register int *pos;
  92. FILE *stream;
  93. enum precedence prec;
  94. {
  95. register int tem;
  96. register int pc;
  97. int nargs;
  98. register char *op_str;
  99. int assign_modify = 0;
  100. enum exp_opcode opcode;
  101. enum precedence myprec;
  102. /* Set to 1 for a right-associative operator. */
  103. int assoc;
  104. pc = (*pos)++;
  105. opcode = exp->elts[pc].opcode;
  106. switch (opcode)
  107. {
  108. case OP_LONG:
  109. (*pos) += 3;
  110. value_print (value_from_long (exp->elts[pc + 1].type,
  111. exp->elts[pc + 2].longconst),
  112. stream);
  113. return;
  114. case OP_DOUBLE:
  115. (*pos) += 3;
  116. value_print (value_from_double (exp->elts[pc + 1].type,
  117. exp->elts[pc + 2].doubleconst),
  118. stream);
  119. return;
  120. case OP_VAR_VALUE:
  121. (*pos) += 2;
  122. fprintf (stream, "%s", SYMBOL_NAME (exp->elts[pc + 1].symbol));
  123. return;
  124. case OP_LAST:
  125. (*pos) += 2;
  126. fprintf (stream, "$%d", exp->elts[pc + 1].longconst);
  127. return;
  128. case OP_REGISTER:
  129. (*pos) += 2;
  130. fprintf (stream, "$%s", reg_names[exp->elts[pc + 1].longconst]);
  131. return;
  132. case OP_INTERNALVAR:
  133. (*pos) += 2;
  134. fprintf (stream, "$%s",
  135. internalvar_name (exp->elts[pc + 1].internalvar));
  136. return;
  137. case OP_FUNCALL:
  138. (*pos) += 2;
  139. nargs = exp->elts[pc + 1].longconst;
  140. print_subexp (exp, pos, stream, PREC_SUFFIX);
  141. fprintf (stream, " (");
  142. for (tem = 0; tem < nargs; tem++)
  143. {
  144. if (tem > 0)
  145. fprintf (stream, ", ");
  146. print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
  147. }
  148. fprintf (stream, ")");
  149. return;
  150. case OP_STRING:
  151. nargs = strlen (&exp->elts[pc + 1].string);
  152. (*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
  153. fprintf (stream, "\"");
  154. for (tem = 0; tem < nargs; tem++)
  155. printchar ((&exp->elts[pc + 1].string)[tem], stream);
  156. fprintf (stream, "\"");
  157. return;
  158. case TERNOP_COND:
  159. if ((int) prec > (int) PREC_COMMA)
  160. fprintf (stream, "(");
  161. /* Print the subexpressions, forcing parentheses
  162. around any binary operations within them.
  163. This is more parentheses than are strictly necessary,
  164. but it looks clearer. */
  165. print_subexp (exp, pos, stream, PREC_HYPER);
  166. fprintf (stream, " ? ");
  167. print_subexp (exp, pos, stream, PREC_HYPER);
  168. fprintf (stream, " : ");
  169. print_subexp (exp, pos, stream, PREC_HYPER);
  170. if ((int) prec > (int) PREC_COMMA)
  171. fprintf (stream, ")");
  172. return;
  173. case STRUCTOP_STRUCT:
  174. tem = strlen (&exp->elts[pc + 1].string);
  175. (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
  176. print_subexp (exp, pos, stream, PREC_SUFFIX);
  177. fprintf (stream, ".%s", &exp->elts[pc + 1].string);
  178. return;
  179. case STRUCTOP_PTR:
  180. tem = strlen (&exp->elts[pc + 1].string);
  181. (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
  182. print_subexp (exp, pos, stream, PREC_SUFFIX);
  183. fprintf (stream, "->%s", &exp->elts[pc + 1].string);
  184. return;
  185. case BINOP_SUBSCRIPT:
  186. print_subexp (exp, pos, stream, PREC_SUFFIX);
  187. fprintf (stream, "[");
  188. print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
  189. fprintf (stream, "]");
  190. return;
  191. case UNOP_POSTINCREMENT:
  192. print_subexp (exp, pos, stream, PREC_SUFFIX);
  193. fprintf (stream, "++");
  194. return;
  195. case UNOP_POSTDECREMENT:
  196. print_subexp (exp, pos, stream, PREC_SUFFIX);
  197. fprintf (stream, "--");
  198. return;
  199. case UNOP_CAST:
  200. (*pos) += 2;
  201. if ((int) prec > (int) PREC_PREFIX)
  202. fprintf (stream, "(");
  203. fprintf (stream, "(");
  204. type_print (exp->elts[pc + 1].type, "", stream, 0);
  205. fprintf (stream, ") ");
  206. print_subexp (exp, pos, stream, PREC_PREFIX);
  207. if ((int) prec > (int) PREC_PREFIX)
  208. fprintf (stream, ")");
  209. return;
  210. case UNOP_MEMVAL:
  211. (*pos) += 2;
  212. if ((int) prec > (int) PREC_PREFIX)
  213. fprintf (stream, "(");
  214. fprintf (stream, "{");
  215. type_print (exp->elts[pc + 1].type, "", stream, 0);
  216. fprintf (stream, "} ");
  217. print_subexp (exp, pos, stream, PREC_PREFIX);
  218. if ((int) prec > (int) PREC_PREFIX)
  219. fprintf (stream, ")");
  220. return;
  221. case BINOP_ASSIGN_MODIFY:
  222. opcode = exp->elts[pc + 1].opcode;
  223. (*pos) += 2;
  224. myprec = PREC_ASSIGN;
  225. assoc = 1;
  226. assign_modify = 1;
  227. for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
  228. if (op_print_tab[tem].opcode == opcode)
  229. {
  230. op_str = op_print_tab[tem].string;
  231. break;
  232. }
  233. default:
  234. for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
  235. if (op_print_tab[tem].opcode == opcode)
  236. {
  237. op_str = op_print_tab[tem].string;
  238. myprec = op_print_tab[tem].precedence;
  239. assoc = op_print_tab[tem].right_assoc;
  240. break;
  241. }
  242. }
  243. if ((int) myprec < (int) prec)
  244. fprintf (stream, "(");
  245. if ((int) opcode > (int) BINOP_END)
  246. {
  247. /* Unary prefix operator. */
  248. fprintf (stream, "%s", op_str);
  249. print_subexp (exp, pos, stream, PREC_PREFIX);
  250. }
  251. else
  252. {
  253. /* Binary operator. */
  254. /* Print left operand.
  255. If operator is right-associative,
  256. increment precedence for this operand. */
  257. print_subexp (exp, pos, stream, (int) myprec + assoc);
  258. /* Print the operator itself. */
  259. if (assign_modify)
  260. fprintf (stream, " %s= ", op_str);
  261. else if (op_str[0] == ',')
  262. fprintf (stream, "%s ", op_str);
  263. else
  264. fprintf (stream, " %s ", op_str);
  265. /* Print right operand.
  266. If operator is left-associative,
  267. increment precedence for this operand. */
  268. print_subexp (exp, pos, stream, (int) myprec + !assoc);
  269. }
  270. if ((int) myprec < (int) prec)
  271. fprintf (stream, ")");
  272. }