calc/calc.h
#include "stack.h"
enum pre_flag {
OPR,
NUM,
};
typedef ssize_t num_t;
struct calc_info {
const char *expr;
char *cur;
struct stack_info opr;
struct stack_info num;
enum pre_flag flag;
num_t (*output)(struct calc_info *, const char *);
};
void calc_init(struct calc_info *);
void calc_destroy(struct calc_info *);
calc/calc.c
#include <stdio.h>
#include <assert.h>
#include "calc.h"
#define DEBUG
#ifdef DEBUG
#define DEBUG_PRT(fmt, arg...) printf(fmt, arg)
#else
#define DEBUG_PRT(fmt, arg...)
#endif
#define PUSH_NUM(n) do {info->num.push(&info->num, &n, sizeof(num_t));} while (0)
#define POP_NUM(n) ({info->num.pop(&info->num, &n, sizeof(num_t));})
#define TOP_NUM(n) ({info->num.top(&info->num, &n, sizeof(num_t));})
#define ISEMPTY_NUM ({info->num.isempty(&info->num);})
#define PUSH_OPR(n) do {info->opr.push(&info->opr, &n, sizeof(char));} while (0)
#define POP_OPR(n) ({info->opr.pop(&info->opr, &n, sizeof(char));})
#define TOP_OPR(n) ({info->opr.top(&info->opr, &n, sizeof(char));})
#define ISEMPTY_OPR ({info->opr.isempty(&info->opr);})
static void num_handler(struct calc_info *info)
{
num_t num = *info->cur - '0';
num_t pre_num = 0;
if (info->flag == NUM) {
assert(!ISEMPTY_NUM);
POP_NUM(pre_num);
num += pre_num * 10;
}
PUSH_NUM(num);
info->flag = NUM;
}
static int do_stack(struct calc_info *info)
{
num_t a = 0;
num_t b = 0;
char opr = 0;
num_t ret = 0;
assert(!(ISEMPTY_NUM));
POP_NUM(b);
assert(!(ISEMPTY_NUM));
POP_NUM(a);
assert(!(ISEMPTY_OPR));
POP_OPR(opr);
switch (opr) {
case '+':
ret = a + b;
break;
case '-':
ret = a - b;
break;
case '*':
ret = a * b;
break;
case '/':
ret = a / b;
break;
case '(':
fprintf(stderr, "?..?..宸?.??n");
return -1;
default:
DEBUG_PRT("%d: %s - wrong elem in stack\n", __LINE__, __FUNCTION__);
assert(0);
};
DEBUG_PRT("%ld %c %ld = %ld\n", a, opr, b, ret);
PUSH_NUM(ret);
return 0;
}
static int opr_level(char opr)
{
int level = 0;
switch (opr) {
case '(':
break;
case '+':
case '-':
level += 1;
break;
case '*':
case '/':
level += 2;
break;
default:
DEBUG_PRT("%d: %s - wrong opr in level check\n", __LINE__, __FUNCTION__);
assert(0);
};
return level;
}
static inline int cmp_opr(char opr_a, char opr_b)
{
return opr_level(opr_a) - opr_level(opr_b);
}
static int opr_handler(struct calc_info *info)
{
char opr = 0;
if (info->flag == OPR ) {//褰..cur?..璐..
if (*info->cur != '-') {
fprintf(stderr, "?..?.?缁.?绠..\n");
return -1;
} else {
//寰num?.腑?.?涓.锛.舰?..-?..琛ㄨ揪寮.??ユ.浠h??
num_t zero = 0;
PUSH_NUM(zero);
}
} else {//褰..cur?..杩..琛ㄨ揪寮
while (!(ISEMPTY_OPR || (TOP_OPR(opr), cmp_opr(*info->cur, opr) > 0))) {
if (do_stack(info) < 0) {
return -1;
}
}
}
PUSH_OPR(*info->cur);
info->flag = OPR;
return 0;
}
static int bracket_handler(struct calc_info *info)
{
char opr = 0;
switch (*info->cur) {
case '(':
PUSH_OPR(*info->cur);
info->flag = OPR;
break;
case ')':
assert(!ISEMPTY_OPR);
while (!(TOP_OPR(opr) < 0) && (opr != '(')) {
if (do_stack(info) < 0) {
return -1;
}
}
if (opr == '(') {
POP_OPR(opr);
} else { //宸?.?风己?.??..?..?..
fprintf(stderr, "?..?..?虫.??n");
return -1;
}
break;
default:
DEBUG_PRT("%d: %s - wrong opr in bracket_handler\n", __LINE__, __FUNCTION__);
assert(0);
};
return 0;
}
static num_t calc(struct calc_info *info, const char *expr)
{
//init
info->expr = expr;
info->cur = (char*)info->expr;
stack_init(&info->opr);
stack_init(&info->num);
info->flag = OPR;
for (; *info->cur; ++(info->cur)) {
switch (*info->cur) {
case '0'...'9':
num_handler(info);
break;
case '+':
case '-':
case '*':
case '/':
if (opr_handler(info) < 0) {
goto error;
}
break;
case '(':
case ')':
if (bracket_handler(info) < 0) {
goto error;
}
break;
default:
break;
};
}
while (!(ISEMPTY_OPR)) {
if (do_stack(info) < 0) {
goto error;
}
}
num_t ret = 0;
POP_NUM(ret);
DEBUG_PRT("%s = %ld\n", info->expr, ret);
stack_destroy(&info->num);
stack_destroy(&info->opr);
return ret;
error:
stack_destroy(&info->num);
stack_destroy(&info->opr);
return -1;
}
void calc_init(struct calc_info *info)
{
info->output = calc;
}
void calc_destroy(struct calc_info *info)
{
}
calc/list.h
struct node_info {
struct node_info *prev;
struct node_info *next;
char priv[];
};
struct list_info {
struct node_info *head;
void (*add)(struct list_info *,
const void *data_entry,
size_t data_size);
void (*add_tail)(struct list_info *,
const void *data_entry,
size_t data_size);
void (*del)(struct list_info *,
struct node_info *,
size_t data_size);
};
#define list_for_each(cur, head) \
for (cur = (head)->next; \
(cur) != (head); \
cur = (cur)->next)
#define list_for_each_safe(cur, tmp, head) \
for (cur = (head)->next, tmp = (cur)->next; \
(cur) != (head); \
cur = tmp, tmp = (tmp)->next)
#define ENTRY(node, type) ((type*)(node->priv))
void list_init(struct list_info*);
void list_destroy(struct list_info*);
calc/list.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
static void __list_add(struct node_info *prev,
struct node_info *next,
const void *data_entry,
size_t data_size)
{
struct node_info *node = (struct node_info *)malloc(sizeof(struct node_info) + data_size);
memcpy(node->priv, data_entry, data_size);
node->prev = prev;
node->next = next;
prev->next = node;
next->prev = node;
}
static void list_add(struct list_info *info,
const void *data_entry, size_t data_size)
{
__list_add(info->head, info->head->next,
data_entry, data_size);
}
static void list_add_tail(struct list_info *info,
const void *data_entry, size_t data_size)
{
__list_add(info->head->prev, info->head,
data_entry, data_size);
}
static void list_del(struct list_info *info,
struct node_info *node,
size_t data_size)
{
node->prev->next = node->next;
node->next->prev = node->prev;
node->prev = node;
node->next = node;
if (data_size) {
memset(node->priv, 0, data_size);
}
free(node);
}
void list_init(struct list_info *info)
{
info->head = (struct node_info *)malloc(sizeof(struct node_info));
info->head->prev = info->head;
info->head->next = info->head;
info->add = list_add;
info->add_tail = list_add_tail;
info->del = list_del;
}
void list_destroy(struct list_info *info)
{
struct node_info *cur = info->head->next;
for (; cur != info->head; cur = info->head->next) {
list_del(info, cur, 0);
}
free(info->head);
}
calc/Makefile
TGT := calc
SRCS := list.c stack.c calc.c test.c
CFLAGS :=
$(TGT): $(SRCS)
$(CC) $(CFLAGS) -o $@ $^
clean:
$(RM) $(TGT)
~
calc/stack.h
#include "list.h"
struct stack_info {
struct list_info list;
void (*push)(struct stack_info *,
const void *data_entry,
size_t data_size);
int (*pop)(struct stack_info *,
void *data_entry,
size_t data_size);
int (*top)(struct stack_info *,
void *data_entry,
size_t data_size);
int (*isempty)(struct stack_info *);
};
void stack_init(struct stack_info *);
void stack_destroy(struct stack_info *);
~
calc/stack.c
#include "stack.h"
static void stack_push(struct stack_info *info,
const void *data_entry,
size_t data_size)
{
info->list.add(&info->list, data_entry, data_size);
}
static int stack_isempty(struct stack_info *info)
{
return info->list.head->next == info->list.head;
}
static int stack_top(struct stack_info *info,
void *data_entry,
size_t data_size)
{
if (stack_isempty(info)) {
return -1;
}
if (data_entry) {
memcpy(data_entry, info->list.head->next->priv, data_size);
}
return 0;
}
static int stack_pop(struct stack_info *info,
void *data_entry,
size_t data_size)
{
if (stack_top(info, data_entry, data_size) < 0) {
return -1;
}
//?..绗.?涓..?..?
info->list.del(&info->list, info->list.head->next, data_size);
return 0;
}
void stack_init(struct stack_info *info)
{
list_init(&info->list);
info->push = stack_push;
info->pop = stack_pop;
info->top = stack_top;
info->isempty = stack_isempty;
}
void stack_destroy(struct stack_info *info)
{
list_destroy(&info->list);
}
calc/test.c
#include <stdio.h>
#include "calc.h"
int main(int argc, char **argv)
{
const char *expr = "(115+(-( -126 - (-2) )))* (84 / (41 + (-1)))";
const char *banner = "璁$.???ㄦ?锛..浠?琛ㄨ揪寮.n?
struct calc_info calc;
calc_init(&calc);
if (argc == 1) {
printf("%ld\n", calc.output(&calc, expr));
}
else if (argc == 2) {
printf("%ld\n", calc.output(&calc, argv[1]));
} else {
fprintf(stderr, "%s\n", banner);
}
calc_destroy(&calc);
return 0;
}
calc/macro_test.c
#include <stdio.h>
#define DEBUG_PRT(fmt, arg...) printf(fmt, arg)
#define ABC(a, b...) ""#b""
/*#define ABC(a, b...) "b"*/
#define DEF(a, b) a##hello##b
void func(int a, ...)
{
}
int main()
{
DEBUG_PRT("%s %c %d\n", "abc", 'X', 100);
func(100, 200, 300, 400);
printf("%s\n", ABC(aa, bb, cc, dd));
int DEF(aa, bb) = 1234;
printf("%d\n", aahellobb);
return 0;
}