📄 util.cc
字号:
/* file "util.cc" *//* Copyright (c) 1994 Stanford University All rights reserved. This software is provided under the terms described in the "suif_copyright.h" include file. */#include <suif_copyright.h>#include <stdlib.h>#include <string.h>#include "s2c.h"#include <stdarg.h>class auto_string;static void make_c_type_helper(type_node *tn, auto_string *basetype, auto_string *pretype, auto_string *posttype);static void append_type_comments(type_node *the_type, auto_string *the_string, int prefix_space, int suffix_space);static void check_function_type(func_type *the_type);class auto_string { private: char *the_string; int space; void make_space(int new_size); public: auto_string(void) { space = 10; the_string = new char[10]; the_string[0] = 0; } auto_string(const char *initial_string) { space = strlen(initial_string) + 1; the_string = new char[space]; strcpy(the_string, initial_string); } ~auto_string() { delete[] the_string; } char *value(void) { return the_string; } void set(const char *new_string); void append(char *new_string); void prepend(char *new_string); void append_int(int new_int); };struct format_unit { int num_args; char *format_string; format_unit &operator=(const format_unit &other) { num_args = other.num_args; format_string = other.format_string; return *this; } boolean operator==(const format_unit &other) const { return ((num_args == other.num_args) && (format_string == other.format_string)); } };DECLARE_DLIST_CLASS(format_unit_list, format_unit);struct format_record { char *op_name; char *default_format; format_unit_list *unit_list; format_record &operator=(const format_record &other) { op_name = other.op_name; default_format = other.default_format; unit_list = other.unit_list; return *this; } boolean operator==(const format_record &other) const { return ((op_name == other.op_name) && (default_format == other.default_format) && (unit_list == other.unit_list)); } };DECLARE_DLIST_CLASS(format_record_list, format_record);/* * The following is a pointer to a format_record_list instead of just * being the list as a work-around for a common bug in C++ * implementations: global constructors don't always get called * correctly. This is a problem in the current g++ (2.5.8) for SGI's * IRIX 5.2 as well as the current g++ for Solaris running on SPARCs. */format_record_list *record_list = NULL;void auto_string::make_space(int new_size) { if (new_size <= space) return; char *new_string = new char[new_size]; strcpy(new_string, the_string); delete the_string; the_string = new_string; space = new_size; }void auto_string::set(const char *new_string) { int new_size = strlen(new_string) + 1; if (space < new_size) make_space(new_size); strcpy(the_string, new_string); }void auto_string::append(char *new_string) { int new_size = strlen(new_string) + strlen(the_string) + 1; if (space < new_size) make_space(new_size); strcat(the_string, new_string); }void auto_string::prepend(char *new_string) { int old_size = strlen(the_string); int new_size = strlen(new_string) + old_size + 1; if (space < new_size) make_space(new_size); char *temp_string = new char[old_size + 1]; strcpy(temp_string, the_string); strcpy(the_string, new_string); strcat(the_string, temp_string); delete temp_string; }void auto_string::append_int(int new_int) { static char num_buffer[20]; sprintf(num_buffer, "%d", new_int); append(num_buffer); }extern boolean expressable_as_char_const(i_integer c) { return ((c >= 0) && (c < 0777)); }extern void get_c_char(int c, char **p, boolean is_string){ assert(expressable_as_char_const(c)); if (limit_escape_sequences) { switch (c) { case '\a': case '\b': case '\f': case '\r': case '\t': case '\v': sprintf(*p, "\\%03o", (unsigned)c); (*p) += 4; **p = '\0'; return; default: break; } } switch (c) { case '\a': strcpy(*p, "\\a"); (*p) += 2; break; case '\b': strcpy(*p, "\\b"); (*p) += 2; break; case '\f': strcpy(*p, "\\f"); (*p) += 2; break; case '\n': strcpy(*p, "\\n"); (*p) += 2; break; case '\r': strcpy(*p, "\\r"); (*p) += 2; break; case '\t': strcpy(*p, "\\t"); (*p) += 2; break; case '\v': strcpy(*p, "\\v"); (*p) += 2; break; case '\'': if (is_string) { **p = c; (*p)++; } else { strcpy(*p, "\\\'"); (*p) += 2; } break; case '"': if (is_string) { strcpy(*p, "\\\""); (*p) += 2; } else { **p = c; (*p)++; } break; case '\\': strcpy(*p, "\\\\"); (*p) += 2; break; default: if (c >= 32 && c < 127) { **p = c; (*p)++; } else { sprintf(*p, "\\%03o", (unsigned)c); (*p) += 4; } break; } **p = '\0';}void print_c_char(io_class *out, i_integer c){ char bfr[16]; char *ptr = bfr; assert(c.is_c_int()); get_c_char(c.c_int(), &ptr, FALSE); out->printf("%s", bfr);}extern void remove_trailing_zero(char *string) { char *new_end = string; char *follow = new_end; while (*follow != 0) { if (*follow == '\\') { if ((follow[1] == '0') && (follow[2] == '0') && (follow[3] == '0')) { follow += 4; } else { follow += 2; new_end = follow; } } else { ++follow; new_end = follow; } } if (new_end != follow) *(follow - 4) = 0; }extern void comment_operand(operand the_op) { if (the_op.is_instr()) comment_instr(the_op.instr()); }extern void comment_instr(instruction *the_instr) { comment_object(the_instr); unsigned num_srcs = the_instr->num_srcs(); for (unsigned src_num = 0; src_num < num_srcs; ++src_num) comment_operand(the_instr->src_op(src_num)); }/* * Convert a type to a nice C type-decl string with the variable * name in the right place. */static void make_c_type_helper(type_node *tn, auto_string *basetype, auto_string *pretype, auto_string *posttype){ switch (tn->op()) { case TYPE_CONST: case TYPE_VOLATILE: case TYPE_CALL_BY_REF: case TYPE_NULL: { auto_string qualification_string; if (tn->is_const()) qualification_string.append("const "); if (tn->is_volatile()) qualification_string.append("volatile "); type_node *tn_unqual = tn; while (tn_unqual->is_modifier()) { modifier_type *this_modifier = (modifier_type *)tn_unqual; append_type_comments(this_modifier, &qualification_string, 0, 1); tn_unqual = this_modifier->base(); } type_ops tn_op = tn_unqual->op(); switch (tn_op) { case TYPE_INT: case TYPE_FLOAT: case TYPE_VOID: case TYPE_ENUM: case TYPE_GROUP: case TYPE_STRUCT: case TYPE_UNION: case TYPE_ARRAY: /* Note for array types: though C doesn't allow * qualified array types, any qualifications on the * array type specification instead apply to the * element type. This is a reasonable thing to do for * types that are qualified array types in SUIF. */ basetype->append(qualification_string.value()); break; case TYPE_PTR: pretype->prepend(qualification_string.value()); break; case TYPE_FUNC: { /* Only const or volatile qualifications are not * allowed -- other qualifications aren't part of C, * so they don't matter */ if (tn->is_const() || tn->is_volatile()) { static boolean array_warn = FALSE; static boolean func_warn = FALSE; boolean *warning = (tn_op == TYPE_ARRAY) ? &array_warn : &func_warn; mistake(warning, tn, "qualified %s type cannot be represented in C", (tn_op == TYPE_ARRAY) ? "array" : "function"); basetype->append(qualification_string.value()); } break; } default: assert(FALSE); } make_c_type_helper(tn_unqual, basetype, pretype, posttype); return; } case TYPE_INT: { base_type *btn = (base_type *) tn; enum C_types the_c_type = c_int_type(tn); if (the_c_type == C_char) { if (target.char_is_signed && !btn->is_signed()) basetype->append("unsigned "); if ((!target.char_is_signed) && btn->is_signed()) basetype->append("signed "); basetype->append("char"); append_type_comments(tn, basetype, 1, 0); return; } if (!btn->is_signed()) basetype->append("unsigned "); boolean use_intnum = FALSE; if (the_c_type == C_int) { basetype->append("int"); } else if (the_c_type == C_short) { basetype->append("short"); } else if (the_c_type == C_long) { basetype->append("long"); } else if (the_c_type == C_longlong) { if (!no_warn) warning_line(NULL, "non-ANSI ``long long int'' type used"); basetype->append("long long"); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -