#include <stdlib.h>
#include <ctype.h>
-#ifdef __INTEL_COMPILER
+#if defined(__INTEL_COMPILER)
#include <mathimf.h>
+#elif defined(__CYGWIN__)
+#include "win32/cygwin_math_ext.h"
#else
#include <math.h>
#endif
fputc(border, out);
const char *end = string->begin + string->size - skip;
for (const char *c = string->begin; c != end; ++c) {
- if (*c == border) {
+ unsigned char const tc = *c;
+ if (tc == border) {
fputc('\\', out);
}
- switch (*c) {
+ switch (tc) {
case '\\': fputs("\\\\", out); break;
case '\a': fputs("\\a", out); break;
case '\b': fputs("\\b", out); break;
}
/* FALLTHROUGH */
default:
- if (!isprint(*c)) {
- fprintf(out, "\\%03o", (unsigned)*c);
- break;
+ if (tc < 0x80 && !isprint(tc)) {
+ fprintf(out, "\\%03o", (unsigned)tc);
+ } else {
+ fputc(tc, out);
}
- fputc(*c, out);
break;
}
}
default: {
const unsigned tc = *c;
if (tc < 0x80U) {
- if (!isprint(*c)) {
- fprintf(out, "\\%03o", (char)*c);
- } else {
+ if (isprint(*c)) {
fputc(*c, out);
+ } else {
+ fprintf(out, "\\%03o", tc);
}
} else if (tc < 0x800) {
fputc(0xC0 | (tc >> 6), out);
print_initializer(expression->initializer);
}
+static void print_assignment_expression(const expression_t *const expr)
+{
+ print_expression_prec(expr, PREC_ASSIGNMENT);
+}
+
/**
* Prints a call expression.
*
} else {
first = 0;
}
- print_expression_prec(argument->expression, PREC_ASSIGNMENT);
+ print_assignment_expression(argument->expression);
argument = argument->next;
}
break;
case EXPR_UNARY_ASSUME:
fputs("__assume(", out);
- print_expression_prec(unexpr->value, PREC_ASSIGNMENT);
+ print_assignment_expression(unexpr->value);
fputc(')', out);
return;
static void print_builtin_constant(const builtin_constant_expression_t *expression)
{
fputs("__builtin_constant_p(", out);
- print_expression_prec(expression->value, PREC_ASSIGNMENT);
+ print_assignment_expression(expression->value);
fputc(')', out);
}
static void print_builtin_prefetch(const builtin_prefetch_expression_t *expression)
{
fputs("__builtin_prefetch(", out);
- print_expression_prec(expression->adr, PREC_ASSIGNMENT);
+ print_assignment_expression(expression->adr);
if (expression->rw) {
fputc(',', out);
- print_expression_prec(expression->rw, PREC_ASSIGNMENT);
+ print_assignment_expression(expression->rw);
}
if (expression->locality) {
fputc(',', out);
- print_expression_prec(expression->locality, PREC_ASSIGNMENT);
+ print_assignment_expression(expression->locality);
}
fputc(')', out);
}
static void print_va_start(const va_start_expression_t *const expression)
{
fputs("__builtin_va_start(", out);
- print_expression_prec(expression->ap, PREC_ASSIGNMENT);
+ print_assignment_expression(expression->ap);
fputs(", ", out);
fputs(expression->parameter->base.base.symbol->string, out);
fputc(')', out);
static void print_va_arg(const va_arg_expression_t *expression)
{
fputs("__builtin_va_arg(", out);
- print_expression_prec(expression->ap, PREC_ASSIGNMENT);
+ print_assignment_expression(expression->ap);
fputs(", ", out);
print_type(expression->base.type);
fputc(')', out);
const classify_type_expression_t *const expr)
{
fputs("__builtin_classify_type(", out);
- print_expression_prec(expr->type_expression, PREC_ASSIGNMENT);
+ print_assignment_expression(expr->type_expression);
fputc(')', out);
}
if (expression->kind == EXPR_UNARY_CAST_IMPLICIT && !print_implicit_casts) {
expression = expression->unary.value;
}
- unsigned prec = get_expression_precedence(expression->base.kind);
- if (print_parenthesis && top_prec != PREC_BOTTOM)
- top_prec = PREC_TOP;
- if (top_prec > prec)
+
+ bool parenthesized =
+ expression->base.parenthesized ||
+ (print_parenthesis && top_prec != PREC_BOTTOM) ||
+ top_prec > get_expression_precedence(expression->base.kind);
+
+ if (parenthesized)
fputc('(', out);
switch (expression->kind) {
case EXPR_UNKNOWN:
fprintf(out, "some expression of type %d", (int)expression->kind);
break;
}
- if (top_prec > prec)
+ if (parenthesized)
fputc(')', out);
}
}
--indent;
print_indent();
- fputs("}\n", out);
+ fputs(block->stmt_expr ? "}" : "}\n", out);
}
/**
}
}
-static void print_local_label(const local_label_statement_t *statement)
-{
- fputs("__label__ ", out);
-
- bool first = true;
- entity_t *entity = statement->labels_begin;
- for (;
- entity != statement->labels_end->base.next;
- entity = entity->base.next) {
- if (!first) {
- fputs(", ", out);
- } else {
- first = false;
- }
- fputs(entity->base.symbol->string, out);
- }
- fputs(";\n", out);
-}
-
static void print_typedef(const entity_t *entity)
{
fputs("typedef ", out);
entity_t *const end = statement->declarations_end->base.next;
for (; entity != end; entity = entity->base.next) {
- if (!is_declaration(entity) && entity->kind != ENTITY_TYPEDEF)
+ if (entity->kind == ENTITY_ENUM_VALUE)
continue;
if (is_generated_entity(entity))
continue;
first = false;
}
- if (entity->kind == ENTITY_TYPEDEF) {
- print_typedef(entity);
- } else {
- assert(is_declaration(entity));
- print_declaration(entity);
- }
-
+ print_entity(entity);
fputc('\n', out);
}
}
if (entity->base.next != NULL) {
panic("multiple declarations in for statement not supported yet");
}
- fputc(' ', out);
} else {
if (statement->initialisation) {
print_expression(statement->initialisation);
}
- fputs("; ", out);
+ fputc(';', out);
}
if (statement->condition != NULL) {
+ fputc(' ', out);
print_expression(statement->condition);
}
- fputs("; ", out);
+ fputc(';', out);
if (statement->step != NULL) {
+ fputc(' ', out);
print_expression(statement->step);
}
fputs(") ", out);
case STATEMENT_LABEL:
print_label_statement(&statement->label);
break;
- case STATEMENT_LOCAL_LABEL:
- print_local_label(&statement->local_label);
- break;
case STATEMENT_GOTO:
print_goto_statement(&statement->gotos);
break;
*/
static void print_storage_class(storage_class_tag_t storage_class)
{
- const char *text;
switch (storage_class) {
case STORAGE_CLASS_NONE: return;
- case STORAGE_CLASS_TYPEDEF: text = "typedef "; break;
- case STORAGE_CLASS_EXTERN: text = "extern "; break;
- case STORAGE_CLASS_STATIC: text = "static "; break;
- case STORAGE_CLASS_AUTO: text = "auto "; break;
- case STORAGE_CLASS_REGISTER: text = "register "; break;
+ case STORAGE_CLASS_TYPEDEF: fputs("typedef ", out); return;
+ case STORAGE_CLASS_EXTERN: fputs("extern ", out); return;
+ case STORAGE_CLASS_STATIC: fputs("static ", out); return;
+ case STORAGE_CLASS_AUTO: fputs("auto ", out); return;
+ case STORAGE_CLASS_REGISTER: fputs("register ", out); return;
}
- fputs(text, out);
+ panic("invalid storage class");
}
/**
switch (initializer->kind) {
case INITIALIZER_VALUE: {
const initializer_value_t *value = &initializer->value;
- print_expression(value->value);
+ print_assignment_expression(value->value);
return;
}
case INITIALIZER_LIST: {
case ENTITY_NAMESPACE:
print_namespace(&entity->namespacee);
return;
+ case ENTITY_LOCAL_LABEL:
+ fprintf(out, "__label__ %s;", entity->base.symbol->string);
+ return;
case ENTITY_LABEL:
case ENTITY_ENUM_VALUE:
- case ENTITY_LOCAL_LABEL:
panic("print_entity used on unexpected entity type");
case ENTITY_INVALID:
break;
case EXPR_BINARY_BITWISE_AND:
case EXPR_BINARY_BITWISE_OR:
case EXPR_BINARY_BITWISE_XOR:
- case EXPR_BINARY_LOGICAL_AND:
- case EXPR_BINARY_LOGICAL_OR:
case EXPR_BINARY_SHIFTLEFT:
case EXPR_BINARY_SHIFTRIGHT:
case EXPR_BINARY_ISGREATER:
return is_constant_expression(expression->binary.left)
&& is_constant_expression(expression->binary.right);
+ case EXPR_BINARY_LOGICAL_AND: {
+ expression_t const *const left = expression->binary.left;
+ if (!is_constant_expression(left))
+ return false;
+ if (fold_constant(left) == 0)
+ return true;
+ return is_constant_expression(expression->binary.right);
+ }
+
+ case EXPR_BINARY_LOGICAL_OR: {
+ expression_t const *const left = expression->binary.left;
+ if (!is_constant_expression(left))
+ return false;
+ if (fold_constant(left) != 0)
+ return true;
+ return is_constant_expression(expression->binary.right);
+ }
+
case EXPR_COMPOUND_LITERAL:
return is_constant_initializer(expression->compound_literal.initializer);