remove const
This commit is contained in:
parent
2d7c2371e4
commit
98d5a1a3bc
@ -96,11 +96,7 @@ $ sh boot.sh
|
|||||||
|
|
||||||
### 关键字
|
### 关键字
|
||||||
|
|
||||||
本语言包含的关键字即为支持的标量类型的关键字和流程控制的关键字,还有 `const` 和 `extern` 和 `enum`。
|
本语言包含的关键字即为支持的标量类型的关键字和流程控制的关键字,还有 `extern` 和 `enum`。
|
||||||
|
|
||||||
#### `const` 关键字
|
|
||||||
|
|
||||||
`const` 关键字可以在类型中使用,会被直接忽略。支持它是为了更好兼容 C 程序。
|
|
||||||
|
|
||||||
#### `extern` 关键字
|
#### `extern` 关键字
|
||||||
|
|
||||||
@ -162,7 +158,7 @@ $ sh boot.sh
|
|||||||
编译过程中涉及的以下参数:
|
编译过程中涉及的以下参数:
|
||||||
|
|
||||||
- 符号表总长度、字符串表总长度
|
- 符号表总长度、字符串表总长度
|
||||||
- 符号数、字符串数、局部变量数、虚拟寄存器数
|
- 符号数、字符串数、局部变量数、(虚拟)寄存器数
|
||||||
|
|
||||||
不能超过源代码中指定的常数。
|
不能超过源代码中指定的常数。
|
||||||
|
|
||||||
|
96
boot.c
96
boot.c
@ -8,16 +8,16 @@
|
|||||||
* Purely for educational purposes. Do not use in production.
|
* Purely for educational purposes. Do not use in production.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// libc dependency
|
// glibc dependency
|
||||||
|
|
||||||
extern void* stdin;
|
extern void* stdin;
|
||||||
extern void* stdout;
|
extern void* stdout;
|
||||||
extern void* stderr;
|
extern void* stderr;
|
||||||
|
|
||||||
int printf(const char* format, ...);
|
int printf(char* format, ...);
|
||||||
int getchar();
|
int getchar();
|
||||||
void exit(int status);
|
void exit(int status);
|
||||||
int fprintf(void* file, const char* format, ...);
|
int fprintf(void* file, char* format, ...);
|
||||||
int ungetc(int ch, void* file);
|
int ungetc(int ch, void* file);
|
||||||
|
|
||||||
void ungetchar(int ch) {
|
void ungetchar(int ch) {
|
||||||
@ -98,7 +98,6 @@ enum {
|
|||||||
TOKEN_RETURN,
|
TOKEN_RETURN,
|
||||||
TOKEN_ENUM,
|
TOKEN_ENUM,
|
||||||
TOKEN_EXTERN,
|
TOKEN_EXTERN,
|
||||||
TOKEN_CONST,
|
|
||||||
|
|
||||||
TOKEN_VOID = 128,
|
TOKEN_VOID = 128,
|
||||||
TOKEN_INT,
|
TOKEN_INT,
|
||||||
@ -159,7 +158,7 @@ enum {
|
|||||||
REG_T6,
|
REG_T6,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* reg_name(int reg) {
|
char* reg_name(int reg) {
|
||||||
// special begin
|
// special begin
|
||||||
if (reg == REG_ZERO) return "zero";
|
if (reg == REG_ZERO) return "zero";
|
||||||
if (reg == REG_RA) return "ra";
|
if (reg == REG_RA) return "ra";
|
||||||
@ -200,7 +199,7 @@ const char* reg_name(int reg) {
|
|||||||
|
|
||||||
// lexer
|
// lexer
|
||||||
|
|
||||||
int streq(const char* s1, const char* s2) {
|
int streq(char* s1, char* s2) {
|
||||||
while (*s1 && *s2 && *s1 == *s2) {
|
while (*s1 && *s2 && *s1 == *s2) {
|
||||||
s1++;
|
s1++;
|
||||||
s2++;
|
s2++;
|
||||||
@ -351,8 +350,6 @@ void parse_id_like(int ch) {
|
|||||||
token_type = TOKEN_RETURN;
|
token_type = TOKEN_RETURN;
|
||||||
} else if (streq(id, "void")) {
|
} else if (streq(id, "void")) {
|
||||||
token_type = TOKEN_VOID;
|
token_type = TOKEN_VOID;
|
||||||
} else if (streq(id, "const")) {
|
|
||||||
token_type = TOKEN_CONST;
|
|
||||||
} else if (streq(id, "char")) {
|
} else if (streq(id, "char")) {
|
||||||
token_type = TOKEN_CHAR;
|
token_type = TOKEN_CHAR;
|
||||||
} else if (streq(id, "for")) {
|
} else if (streq(id, "for")) {
|
||||||
@ -586,7 +583,7 @@ void next_token() {
|
|||||||
if (0) {
|
if (0) {
|
||||||
fprintf(stderr, "token: %d\n", token_type);
|
fprintf(stderr, "token: %d\n", token_type);
|
||||||
if (token_type == TOKEN_ID) {
|
if (token_type == TOKEN_ID) {
|
||||||
const char* name = id_table + id_lut[token_data];
|
char* name = id_table + id_lut[token_data];
|
||||||
fprintf(stderr, " id: %s\n", name);
|
fprintf(stderr, " id: %s\n", name);
|
||||||
} else if (token_type == TOKEN_NUMBER) {
|
} else if (token_type == TOKEN_NUMBER) {
|
||||||
fprintf(stderr, " number: %d\n", token_data);
|
fprintf(stderr, " number: %d\n", token_data);
|
||||||
@ -602,21 +599,12 @@ void expect_token(int expected_type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ignore_const() {
|
|
||||||
if (token_type == TOKEN_CONST) {
|
|
||||||
next_token();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int parse_type() {
|
int parse_type() {
|
||||||
ignore_const();
|
|
||||||
if (token_type == TOKEN_INT || token_type == TOKEN_CHAR || token_type == TOKEN_VOID) {
|
if (token_type == TOKEN_INT || token_type == TOKEN_CHAR || token_type == TOKEN_VOID) {
|
||||||
int type = token_type & ~TYPE_TOKEN_MASK;
|
int type = token_type & ~TYPE_TOKEN_MASK;
|
||||||
next_token();
|
next_token();
|
||||||
ignore_const();
|
|
||||||
if (token_type == TOKEN_MUL) {
|
if (token_type == TOKEN_MUL) {
|
||||||
next_token();
|
next_token();
|
||||||
ignore_const();
|
|
||||||
type |= TYPE_PTR_MASK;
|
type |= TYPE_PTR_MASK;
|
||||||
}
|
}
|
||||||
unget_token();
|
unget_token();
|
||||||
@ -757,7 +745,7 @@ int check_itype_immediate(int value) {
|
|||||||
return value >= -2048 && value <= 2047;
|
return value >= -2048 && value <= 2047;
|
||||||
}
|
}
|
||||||
|
|
||||||
void asm_ld(const char* rd, int imm, const char* rs) {
|
void asm_ld(char* rd, int imm, char* rs) {
|
||||||
if (check_itype_immediate(imm)) {
|
if (check_itype_immediate(imm)) {
|
||||||
printf(" ld %s, %d(%s)\n", rd, imm, rs);
|
printf(" ld %s, %d(%s)\n", rd, imm, rs);
|
||||||
} else {
|
} else {
|
||||||
@ -767,7 +755,7 @@ void asm_ld(const char* rd, int imm, const char* rs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void asm_sd(const char* rs1, int imm, const char* rs2) {
|
void asm_sd(char* rs1, int imm, char* rs2) {
|
||||||
if (check_itype_immediate(imm)) {
|
if (check_itype_immediate(imm)) {
|
||||||
printf(" sd %s, %d(%s)\n", rs1, imm, rs2);
|
printf(" sd %s, %d(%s)\n", rs1, imm, rs2);
|
||||||
} else {
|
} else {
|
||||||
@ -777,7 +765,7 @@ void asm_sd(const char* rs1, int imm, const char* rs2) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void asm_addi(const char* rd, const char* rs, int imm) {
|
void asm_addi(char* rd, char* rs, int imm) {
|
||||||
if (check_itype_immediate(imm)) {
|
if (check_itype_immediate(imm)) {
|
||||||
printf(" addi %s, %s, %d\n", rd, rs, imm);
|
printf(" addi %s, %s, %d\n", rd, rs, imm);
|
||||||
} else {
|
} else {
|
||||||
@ -788,7 +776,7 @@ void asm_addi(const char* rd, const char* rs, int imm) {
|
|||||||
|
|
||||||
// assembly helpers
|
// assembly helpers
|
||||||
|
|
||||||
const char* load_op_of_type(int type) {
|
char* load_op_of_type(int type) {
|
||||||
if (type & TYPE_PTR_MASK) {
|
if (type & TYPE_PTR_MASK) {
|
||||||
return "ld";
|
return "ld";
|
||||||
} else if (type == TYPE_CHAR) {
|
} else if (type == TYPE_CHAR) {
|
||||||
@ -798,7 +786,7 @@ const char* load_op_of_type(int type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* store_op_of_type(int type) {
|
char* store_op_of_type(int type) {
|
||||||
if (type & TYPE_PTR_MASK) {
|
if (type & TYPE_PTR_MASK) {
|
||||||
return "sd";
|
return "sd";
|
||||||
} else if (type == TYPE_CHAR) {
|
} else if (type == TYPE_CHAR) {
|
||||||
@ -816,8 +804,8 @@ void load_local_address(int rd, int slot_id) {
|
|||||||
|
|
||||||
// load a non-trivial register into trivial one
|
// load a non-trivial register into trivial one
|
||||||
void load(int rd, int rs) {
|
void load(int rd, int rs) {
|
||||||
const char* op = load_op_of_type(reg_type[rs]);
|
char* op = load_op_of_type(reg_type[rs]);
|
||||||
const char* rd_name = reg_name(rd);
|
char* rd_name = reg_name(rd);
|
||||||
if (is_overflow(rs)) {
|
if (is_overflow(rs)) {
|
||||||
load_local_address(rd, overflow[rs]);
|
load_local_address(rd, overflow[rs]);
|
||||||
if (indirection[rs]) {
|
if (indirection[rs]) {
|
||||||
@ -829,8 +817,8 @@ void load(int rd, int rs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// store a trivial register into a non-trivial one
|
// store a trivial register into a non-trivial one
|
||||||
void store(const char* rs, int reg) {
|
void store(char* rs, int reg) {
|
||||||
const char* op = store_op_of_type(reg_type[reg]);
|
char* op = store_op_of_type(reg_type[reg]);
|
||||||
if (is_overflow(reg)) {
|
if (is_overflow(reg)) {
|
||||||
load_local_address(REG_T2, overflow[reg]);
|
load_local_address(REG_T2, overflow[reg]);
|
||||||
if (indirection[reg]) {
|
if (indirection[reg]) {
|
||||||
@ -845,7 +833,7 @@ int is_nontrivial(int reg) {
|
|||||||
return is_overflow(reg) || indirection[reg];
|
return is_overflow(reg) || indirection[reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* trivialize(int rs, int t) {
|
char* trivialize(int rs, int t) {
|
||||||
if (is_nontrivial(rs)) {
|
if (is_nontrivial(rs)) {
|
||||||
load(t, rs);
|
load(t, rs);
|
||||||
return reg_name(t);
|
return reg_name(t);
|
||||||
@ -853,10 +841,10 @@ const char* trivialize(int rs, int t) {
|
|||||||
return reg_name(rs);
|
return reg_name(rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _asm_r(const char* op, int rd, int rs1) {
|
void _asm_r(char* op, int rd, int rs1) {
|
||||||
const char* rd_name = reg_name(rd);
|
char* rd_name = reg_name(rd);
|
||||||
if (is_nontrivial(rd)) rd_name = "t0";
|
if (is_nontrivial(rd)) rd_name = "t0";
|
||||||
const char* rs1_name = trivialize(rs1, REG_T0);
|
char* rs1_name = trivialize(rs1, REG_T0);
|
||||||
printf(" %s %s, %s\n", op, rd_name, rs1_name);
|
printf(" %s %s, %s\n", op, rd_name, rs1_name);
|
||||||
if (is_nontrivial(rd)) {
|
if (is_nontrivial(rd)) {
|
||||||
store("t0", rd);
|
store("t0", rd);
|
||||||
@ -864,20 +852,20 @@ void _asm_r(const char* op, int rd, int rs1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void asm_mv(int rd, int rs1) {
|
void asm_mv(int rd, int rs1) {
|
||||||
const char* rs1_name = trivialize(rs1, REG_T0);
|
char* rs1_name = trivialize(rs1, REG_T0);
|
||||||
if (is_nontrivial(rd)) {
|
if (is_nontrivial(rd)) {
|
||||||
store(rs1_name, rd);
|
store(rs1_name, rd);
|
||||||
} else {
|
} else {
|
||||||
const char* rd_name = reg_name(rd);
|
char* rd_name = reg_name(rd);
|
||||||
if (!streq(rd_name, rs1_name))
|
if (!streq(rd_name, rs1_name))
|
||||||
printf(" mv %s, %s\n", rd_name, rs1_name);
|
printf(" mv %s, %s\n", rd_name, rs1_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _asm_rr(const char* op, int rd, int rs1, int rs2) {
|
void _asm_rr(char* op, int rd, int rs1, int rs2) {
|
||||||
const char* rd_name = reg_name(rd);
|
char* rd_name = reg_name(rd);
|
||||||
const char* rs1_name = trivialize(rs1, REG_T0);
|
char* rs1_name = trivialize(rs1, REG_T0);
|
||||||
const char* rs2_name = trivialize(rs2, REG_T1);
|
char* rs2_name = trivialize(rs2, REG_T1);
|
||||||
if (is_nontrivial(rd)) rd_name = "t0";
|
if (is_nontrivial(rd)) rd_name = "t0";
|
||||||
printf(" %s %s, %s, %s\n", op, rd_name, rs1_name, rs2_name);
|
printf(" %s %s, %s, %s\n", op, rd_name, rs1_name, rs2_name);
|
||||||
if (is_nontrivial(rd)) {
|
if (is_nontrivial(rd)) {
|
||||||
@ -885,23 +873,23 @@ void _asm_rr(const char* op, int rd, int rs1, int rs2) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _asm_ri(const char* op, int rd, int rs1, int imm) {
|
void _asm_ri(char* op, int rd, int rs1, int imm) {
|
||||||
const char* rd_name = reg_name(rd);
|
char* rd_name = reg_name(rd);
|
||||||
if (is_nontrivial(rd)) rd_name = "t0";
|
if (is_nontrivial(rd)) rd_name = "t0";
|
||||||
const char* rs1_name = trivialize(rs1, REG_T0);
|
char* rs1_name = trivialize(rs1, REG_T0);
|
||||||
printf(" %s %s, %s, %d\n", op, rd_name, rs1_name, imm);
|
printf(" %s %s, %s, %d\n", op, rd_name, rs1_name, imm);
|
||||||
if (is_nontrivial(rd)) {
|
if (is_nontrivial(rd)) {
|
||||||
store("t0", rd);
|
store("t0", rd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void asm_branch(const char* op, int rs1, int label) {
|
void asm_branch(char* op, int rs1, int label) {
|
||||||
const char* rs1_name = trivialize(rs1, REG_T0);
|
char* rs1_name = trivialize(rs1, REG_T0);
|
||||||
printf(" %s %s, L%d\n", op, rs1_name, label);
|
printf(" %s %s, L%d\n", op, rs1_name, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _asm_i(const char* op, int rd, const char* prefix1, const char* prefix2, int imm) {
|
void _asm_i(char* op, int rd, char* prefix1, char* prefix2, int imm) {
|
||||||
const char* rd_name = reg_name(rd);
|
char* rd_name = reg_name(rd);
|
||||||
if (is_nontrivial(rd)) rd_name = "t0";
|
if (is_nontrivial(rd)) rd_name = "t0";
|
||||||
printf(" %s %s, %s%s%d\n", op, rd_name, prefix1, prefix2, imm);
|
printf(" %s %s, %s%s%d\n", op, rd_name, prefix1, prefix2, imm);
|
||||||
if (is_nontrivial(rd)) {
|
if (is_nontrivial(rd)) {
|
||||||
@ -913,14 +901,14 @@ int is_not_reusable(int rs1, int expected_type) {
|
|||||||
return indirection[rs1] || reg_type[rs1] != expected_type || rs1 == REG_ZERO;
|
return indirection[rs1] || reg_type[rs1] != expected_type || rs1 == REG_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
int asm_r(int type, const char* op, int rs1) {
|
int asm_r(int type, char* op, int rs1) {
|
||||||
int rd = rs1;
|
int rd = rs1;
|
||||||
if (is_not_reusable(rs1, type)) rd = next_reg(type);
|
if (is_not_reusable(rs1, type)) rd = next_reg(type);
|
||||||
_asm_r(op, rd, rs1);
|
_asm_r(op, rd, rs1);
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
int asm_rr(int type, const char* op, int rs1, int rs2) {
|
int asm_rr(int type, char* op, int rs1, int rs2) {
|
||||||
int rd = rs1;
|
int rd = rs1;
|
||||||
if (is_not_reusable(rs1, type)) rd = rs2;
|
if (is_not_reusable(rs1, type)) rd = rs2;
|
||||||
if (is_not_reusable(rs2, type)) rd = next_reg(type);
|
if (is_not_reusable(rs2, type)) rd = next_reg(type);
|
||||||
@ -929,7 +917,7 @@ int asm_rr(int type, const char* op, int rs1, int rs2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void store_into_local(int rs1, int slot) {
|
void store_into_local(int rs1, int slot) {
|
||||||
const char* rs1_name = trivialize(rs1, REG_T0);
|
char* rs1_name = trivialize(rs1, REG_T0);
|
||||||
load_local_address(REG_T2, slot);
|
load_local_address(REG_T2, slot);
|
||||||
printf(" %s %s, 0(t2)\n", store_op_of_type(local_type[slot]), rs1_name);
|
printf(" %s %s, 0(t2)\n", store_op_of_type(local_type[slot]), rs1_name);
|
||||||
}
|
}
|
||||||
@ -968,7 +956,7 @@ int lookup(int id) {
|
|||||||
if (is_const[id]) {
|
if (is_const[id]) {
|
||||||
return load_imm(const_table[id]);
|
return load_imm(const_table[id]);
|
||||||
}
|
}
|
||||||
const char* name = id_table + id_lut[id];
|
char* name = id_table + id_lut[id];
|
||||||
if (global_kind[id]) {
|
if (global_kind[id]) {
|
||||||
if (global_kind[id] == KIND_FUNCTION) {
|
if (global_kind[id] == KIND_FUNCTION) {
|
||||||
fprintf(stderr, "function name must not appear outside function call: %s\n", name);
|
fprintf(stderr, "function name must not appear outside function call: %s\n", name);
|
||||||
@ -982,7 +970,7 @@ int lookup(int id) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int asm_r_arith(const char* op, int rs1) {
|
int asm_r_arith(char* op, int rs1) {
|
||||||
if (reg_type[rs1] & TYPE_PTR_MASK) {
|
if (reg_type[rs1] & TYPE_PTR_MASK) {
|
||||||
fprintf(stderr, "pointer cannot be arithmetically operated by %s\n", op);
|
fprintf(stderr, "pointer cannot be arithmetically operated by %s\n", op);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -990,7 +978,7 @@ int asm_r_arith(const char* op, int rs1) {
|
|||||||
return asm_r(TYPE_INT, op, rs1);
|
return asm_r(TYPE_INT, op, rs1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int asm_rr_arith(const char* op, int rs1, int rs2) {
|
int asm_rr_arith(char* op, int rs1, int rs2) {
|
||||||
if (reg_type[rs1] & TYPE_PTR_MASK || reg_type[rs2] & TYPE_PTR_MASK) {
|
if (reg_type[rs1] & TYPE_PTR_MASK || reg_type[rs2] & TYPE_PTR_MASK) {
|
||||||
fprintf(stderr, "pointer cannot be arithmetically operated by %s\n", op);
|
fprintf(stderr, "pointer cannot be arithmetically operated by %s\n", op);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -998,7 +986,7 @@ int asm_rr_arith(const char* op, int rs1, int rs2) {
|
|||||||
return asm_rr(TYPE_INT, op, rs1, rs2);
|
return asm_rr(TYPE_INT, op, rs1, rs2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int asm_rr_cmp(const char* op, int rs1, int rs2) {
|
int asm_rr_cmp(char* op, int rs1, int rs2) {
|
||||||
// since NULL is virtually 0, it is considered a valid example of a pointer comparing with an integer
|
// since NULL is virtually 0, it is considered a valid example of a pointer comparing with an integer
|
||||||
return asm_rr(TYPE_INT, op, rs1, rs2);
|
return asm_rr(TYPE_INT, op, rs1, rs2);
|
||||||
}
|
}
|
||||||
@ -1151,7 +1139,7 @@ int parse_expr();
|
|||||||
int parse_assign_expr();
|
int parse_assign_expr();
|
||||||
|
|
||||||
int parse_function_call(int id) {
|
int parse_function_call(int id) {
|
||||||
const char* name = id_table + id_lut[id];
|
char* name = id_table + id_lut[id];
|
||||||
if (global_kind[id] != KIND_FUNCTION) {
|
if (global_kind[id] != KIND_FUNCTION) {
|
||||||
fprintf(stderr, "not a function name: %s\n", name);
|
fprintf(stderr, "not a function name: %s\n", name);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -1774,7 +1762,7 @@ void parse_stmt() {
|
|||||||
reset_temp();
|
reset_temp();
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_function(const char* name) {
|
void parse_function(char* name) {
|
||||||
reset_local();
|
reset_local();
|
||||||
int arg = 0;
|
int arg = 0;
|
||||||
int args[8];
|
int args[8];
|
||||||
@ -1879,7 +1867,7 @@ void parse_function(const char* name) {
|
|||||||
reset_local_table();
|
reset_local_table();
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_global_variable(int id, const char* name, int type) {
|
void parse_global_variable(int id, char* name, int type) {
|
||||||
printf(".data\n");
|
printf(".data\n");
|
||||||
printf(".globl %s\n", name);
|
printf(".globl %s\n", name);
|
||||||
printf(".align 5\n");
|
printf(".align 5\n");
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
int printf(const char format[], ...);
|
int printf(char* format, ...);
|
||||||
int scanf(const char format[], ...);
|
|
||||||
|
|
||||||
void should_be(int expected, int actual) {
|
void should_be(int expected, int actual) {
|
||||||
if (expected != actual) {
|
if (expected != actual) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
int printf(const char* format, ...);
|
int printf(char* format, ...);
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
printf("hello world %d\n", 42);
|
printf("hello world %d\n", 42);
|
||||||
|
46
demo/lut.c
46
demo/lut.c
@ -1,46 +0,0 @@
|
|||||||
int printf(const char format[], ...);
|
|
||||||
int getchar();
|
|
||||||
|
|
||||||
char string_table[65536];
|
|
||||||
int string_offset;
|
|
||||||
int string_lut[4096];
|
|
||||||
int string_lut_size;
|
|
||||||
|
|
||||||
int parse_string() {
|
|
||||||
int offset = string_offset;
|
|
||||||
int ch;
|
|
||||||
while ((ch = getchar()) != '"') {
|
|
||||||
if (ch == -1 || ch == '\n') {
|
|
||||||
printf("expecting '\"'\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
string_table[string_offset++] = ch;
|
|
||||||
}
|
|
||||||
string_table[string_offset++] = 0;
|
|
||||||
string_lut[string_lut_size] = offset;
|
|
||||||
return string_lut_size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int streq(const char* s1, const char* s2) {
|
|
||||||
while (*s1 && *s2 && *s1 == *s2) {
|
|
||||||
s1++;
|
|
||||||
s2++;
|
|
||||||
}
|
|
||||||
return *s1 == *s2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_string_table() {
|
|
||||||
printf(".data\n");
|
|
||||||
for (int i = 0; i < string_lut_size; ++i) {
|
|
||||||
char* id = string_table + string_lut[i];
|
|
||||||
printf(".LC%d: .string \"%s\", const: %d\n",
|
|
||||||
i, id, streq(id, "const"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
char ch;
|
|
||||||
while ((ch = getchar()) == '"') parse_string();
|
|
||||||
dump_string_table();
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
int printf(const char format[], ...);
|
int printf(char* format, ...);
|
||||||
int putchar(int ch);
|
int putchar(int ch);
|
||||||
|
|
||||||
int a[9];
|
int a[9];
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
int printf(const char format[], ...);
|
int printf(char* format, ...);
|
||||||
int scanf(const char format[], ...);
|
int scanf(char* format, ...);
|
||||||
|
|
||||||
void sort(int a[], int n) {
|
void sort(int a[], int n) {
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
int printf(const char* format, ...);
|
int printf(char* format, ...);
|
||||||
|
|
||||||
int strcmp(const char* s1, const char* s2) {
|
int strcmp(char* s1, char* s2) {
|
||||||
while (*s1 && *s2 && *s1 == *s2) {
|
while (*s1 && *s2 && *s1 == *s2) {
|
||||||
s1++;
|
s1++;
|
||||||
s2++;
|
s2++;
|
||||||
@ -9,8 +9,8 @@ int strcmp(const char* s1, const char* s2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
const char* s1 = "helloworld";
|
char* s1 = "helloworld";
|
||||||
const char* s2 = "world";
|
char* s2 = "world";
|
||||||
printf("%d\n", strcmp(s1, s2));
|
printf("%d\n", strcmp(s1, s2));
|
||||||
printf("%d\n", strcmp(s1 + 5, s2));
|
printf("%d\n", strcmp(s1 + 5, s2));
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user