diff --git a/programs/other/graph/branches/tcc_current/Tupfile.lua b/programs/other/graph/branches/tcc_current/Tupfile.lua new file mode 100755 index 0000000000..3d4d158c0f --- /dev/null +++ b/programs/other/graph/branches/tcc_current/Tupfile.lua @@ -0,0 +1,10 @@ +if tup.getconfig("NO_TCC") ~= "" then return end +if tup.getconfig("HELPERDIR") == "" +then + HELPERDIR = "../../../../../programs" +end +tup.include(HELPERDIR .. "/use_tcc.lua") + +LIBS = "-lbox_lib" + +link_tcc({"main.c", "func.c", "parser.c"}, "graph"); diff --git a/programs/other/graph/branches/tcc_current/build_kolibrios.sh b/programs/other/graph/branches/tcc_current/build_kolibrios.sh new file mode 100755 index 0000000000..d626d98294 --- /dev/null +++ b/programs/other/graph/branches/tcc_current/build_kolibrios.sh @@ -0,0 +1,3 @@ +#SHS +/kolibrios/develop/tcc/tcc main.c func.c parser.c -o Graph.kex -lbox_lib +exit diff --git a/programs/other/graph/branches/tcc_current/func.c b/programs/other/graph/branches/tcc_current/func.c new file mode 100755 index 0000000000..ac34fbce0d --- /dev/null +++ b/programs/other/graph/branches/tcc_current/func.c @@ -0,0 +1,63 @@ +#include "func.h" + +char debuf[50] = ""; + +double textwidth(const char* s, int len) { + int i; + for (i = 0; i < len; i++) + if (s[i] == 0) + break; + return i * 6; +} + +double textheight(const char* s, int len) { + return 8.0; +} + +int isalpha(char c) { + return (c==' ' || c=='\n' || c=='\t' || c=='\r'); +} + +// эта функция - велосипед. но проще было написать чем найти. +double convert(const char* s, int* len) { + int i; + double sign, res, tail, div; + res = 0.0; + i = 0; + while (s[i] && isalpha(s[i])) i++; + if (len) *len=i; + if (s[i] == '\0') + return ERROR_END; + + sign=1.0; + if (s[i] == '-') { + sign=-1.0; + i++; + } + while (s[i] && s[i] >= '0' && s[i] <= '9') { + res *= 10.0; + res += s[i] - '0'; + i++; + } + if (len) *len=i; + if (!s[i] || isalpha(s[i])) + return sign*res; + if (s[i] != '.' && s[i] != ',') + return ERROR; + i++; + if (len) *len=i; + if (!s[i]) + return sign*res; + + div = 1.0; + tail = 0.0; + while (s[i] && s[i] >= '0' && s[i] <= '9') { + tail *= 10.0; + tail += s[i] - '0'; + div *= 10.0; + i++; + } + res += tail/div; + if (len) *len=i; + return sign*res; +} \ No newline at end of file diff --git a/programs/other/graph/branches/tcc_current/func.h b/programs/other/graph/branches/tcc_current/func.h new file mode 100755 index 0000000000..8a3538e607 --- /dev/null +++ b/programs/other/graph/branches/tcc_current/func.h @@ -0,0 +1,20 @@ +#ifndef FUNC_H +#define FUNC_H + +#define ERROR 8888888888.9 +#define ERROR_END 8888888888.7 + +extern char debuf[50]; + +typedef struct { + double x, y; +} TCoord; + +double textwidth(const char* s, int len); +double textheight(const char* s, int len); + +typedef double (*function_t)(double); +int isalpha(char c); +double convert(const char* s, int* len); + +#endif /* FUNC_H */ diff --git a/programs/other/graph/branches/tcc_current/main.c b/programs/other/graph/branches/tcc_current/main.c new file mode 100755 index 0000000000..c6781e5bdd --- /dev/null +++ b/programs/other/graph/branches/tcc_current/main.c @@ -0,0 +1,544 @@ +#include +#include +#include +#include +#include + +#include "func.h" +#include "parser.h" + +#define nullptr 0 +#define dword unsigned int + +enum BUTTONS { + BTN_QUIT = 1, + BTN_EDIT = 5 +}; + +const char header[] = "Graph"; +const char empty_text[] = "No function loaded. Type file name and press Enter. "; +const char er_file_not_found[] = "Cannot open file. "; +const char str_filename[] = "Filename:"; +const char str_editfile[] = "Edit"; + +// начальные размеры +#define WND_W 600 +#define WND_H 470 + +#define LIGHTGREEN 0xff0000 +#define WHITE 0xffffff +#define BLACK 0x0 +#define LIGHTBLUE 0x0000ff +#define LIGHTRED 0xff0000 + +// font colors +#define BIGFONTCOLOR BLACK +#define SMALLFONTCOLOR BLACK + +#define THREE 3.0 +// minimum space: 3 pixels + +#define BIG_HEIGHT 4.0 +#define SMALL_HEIGHT 2.0 +#define TEXT_X 15.0 +// numeric format for output +#define FORMAT "%.2f%c" +// format for two coords +#define FORMAT_COORD "(%.2f, %.2f)%c" +// special value to text if enough space +#define FORMAT_TEST "0.00" + +#define DELTA_BIG 1.0 +#define DELTA_SMALL 0.1 + +int SysColor = 0; + +double* points; +dword point_count = 0; +double x1, y1, x2, y2; +char* funct = nullptr; + +char edit_path[256]; +edit_box mybox = { 200, 92, WND_H-16-32, 0xffffff, 0x94AECE, 0, 0x808080, 0x10000000, + sizeof(edit_path)-1, (void*)&edit_path, 0, 0, 0 }; + +char* full_head; + +char* HugeBuf = nullptr; + +// constructor of TCoord +TCoord coord(double x, double y) { + TCoord r; + r.x = x; + r.y = y; + return r; +} + +// move and scale mathematical coords to fit screen coords +TCoord mat2Graf(TCoord c, TCoord scrMin, TCoord scrMax, TCoord mMin, TCoord mMax) { + TCoord r; + if (c.x > mMax.x) + c.x = mMax.x; + if (c.x < mMin.x) + c.x = mMin.x; + if (c.y > mMax.y) + c.y = mMax.y; + if (c.y < mMin.y) + c.y = mMin.y; + r.x = (scrMax.x - scrMin.x) / (mMax.x - mMin.x) * (c.x - mMin.x) + scrMin.x; + r.y = (scrMax.y - scrMin.y) / (mMax.y - mMin.y) * (mMax.y - c.y) + scrMin.y; + + return r; +} + +// huge function to draw all the stuff except the function itself +void drawAxis(TCoord scrMin, TCoord scrMax, TCoord mMin, TCoord mMax) { + TCoord cZero={0.0,0.0}, + gMin, gMax, gZero, step; + TCoord from, to; + double i=0.0; + int j; + double xmin, xmin2, ymin, ymin2; + char buf[30]=""; + int strlentemp; + + +// scr means Screen(bounding rect) +// m means Mathematical +// g means Graphic(real screen position) + + //_ksys_debug_puts("draw axis called\n"); + + //sprintf(debuf, "test: %f,%f,%f,%f\n", 123.45, 1.0, -0.9, 12.57); + //_ksys_debug_puts(debuf); + + gMin = mat2Graf(mMin, scrMin, scrMax, mMin, mMax); + gMax = mat2Graf(mMax, scrMin, scrMax, mMin, mMax); + gZero = mat2Graf(cZero, scrMin, scrMax, mMin, mMax); + + // clear + // SysColor = WHITE; + //rectangle(di(gMin.x), di(gMin.y), di(gMax.x), di(gMax.y)); + // ftopku + + SysColor = BLACK; + // osy X + _ksys_draw_line(gMin.x, gZero.y ,gMax.x, gZero.y, SysColor); + // osy Y + _ksys_draw_line(gZero.x, gMin.y, gZero.x, gMax.y, SysColor); + // bounding rect + _ksys_draw_line(gMin.x, gMin.y, gMax.x, gMin.y, SysColor); + _ksys_draw_line(gMin.x, gMax.y, gMax.x, gMax.y, SysColor); + + _ksys_draw_line(gMin.x, gMin.y, gMin.x, gMax.y, SysColor); + _ksys_draw_line(gMax.x, gMin.y, gMax.x, gMax.y, SysColor); + + // coords of the rect : lower left + sprintf(buf, FORMAT_COORD, x1, y1, '\0'); + //_ksys_debug_puts(buf); + strlentemp = strlen(buf); + _ksys_draw_text(buf, gMin.x, gMin.y + textheight(buf, strlentemp), strlentemp, SysColor); + // upper left + sprintf(buf, FORMAT_COORD, x1, y2, '\0'); + strlentemp = strlen(buf); + _ksys_draw_text(buf, gMin.x, gMax.y - textheight(buf, strlentemp), strlentemp, SysColor); + // lower right + sprintf(buf, FORMAT_COORD, x2, y1, '\0'); + strlentemp = strlen(buf); + _ksys_draw_text(buf, gMax.x - textwidth(buf, strlentemp), gMin.y + textheight(buf, strlentemp), strlentemp, SysColor); + // upper right + sprintf(buf, FORMAT_COORD, x2, y2, '\0'); + strlentemp = strlen(buf); + _ksys_draw_text(buf, gMax.x - textwidth(buf, strlentemp), gMax.y - textheight(buf, strlentemp), strlentemp, SysColor); + + //_ksys_debug_puts("some lines painted\n"); + + + step.x = (mMax.x - mMin.x) / (scrMax.x - scrMin.x); + step.y = (mMax.y - mMin.y) / (scrMax.y - scrMin.y); + +// round values + xmin = (int)((mMin.x / DELTA_BIG) * DELTA_BIG); + ymin = (int)((mMin.y / DELTA_BIG) * DELTA_BIG); + + // (0,0) + + if ((x1 * x2 <= 0.0) && (y1 * y2 <= 0.0)) + { + from.x=0.0; + from.y=0.0; + from = mat2Graf(from, scrMin, scrMax, mMin, mMax); + SysColor = BLACK; + sprintf(buf, FORMAT, 0.0, '\0'); + strlentemp = strlen(buf); + _ksys_draw_text(buf, from.x - textwidth(buf, strlentemp), from.y + textheight(buf, strlentemp), strlentemp, SysColor); + } + + + // big marks on X + //settextstyle(0, 0, 1); + if (DELTA_BIG / step.x > THREE) { + for (i = xmin; i <= mMax.x; i += DELTA_BIG) { + if (i != 0.0) { + from.x = i; + to.x = from.x; + from.y = -BIG_HEIGHT * step.y; + to.y = BIG_HEIGHT * step.y; + from = mat2Graf(from, scrMin, scrMax, mMin, mMax); + to = mat2Graf(to, scrMin, scrMax, mMin, mMax); + SysColor = BLACK; + _ksys_draw_line(from.x, from.y, to.x, to.y, SysColor); + // write number + sprintf(buf, FORMAT, i, '\0'); + strlentemp = strlen(buf); + // if it fits in the GAP, then write it + if (from.y > scrMin.y && (DELTA_BIG > (textwidth(buf, strlentemp) + 1.0) * step.x)) { + SysColor = BIGFONTCOLOR; + _ksys_draw_text(buf, from.x - textwidth(buf, strlentemp) / 2.0, to.y - textheight(buf, strlentemp), strlentemp, SysColor); + } + } + } + } + //_ksys_debug_puts("big marks x painted\n"); + + // big marks on Y + if (DELTA_BIG / step.y > THREE) { + for (i = ymin; i <= mMax.y; i += DELTA_BIG) { + if (i != 0.0) { + from.y = i; + to.y = from.y; + from.x = -BIG_HEIGHT * step.x; + to.x = BIG_HEIGHT * step.x; + from = mat2Graf(from, scrMin, scrMax, mMin, mMax); + to = mat2Graf(to, scrMin, scrMax, mMin, mMax); + SysColor = BLACK; + _ksys_draw_line(from.x, from.y, to.x, to.y, SysColor); + sprintf(buf, FORMAT, i, '\0'); + strlentemp = strlen(buf); + if (from.x > scrMin.x && (DELTA_BIG > textheight(buf, strlentemp) * step.y)) { + SysColor = BIGFONTCOLOR; + _ksys_draw_text(buf, from.x + TEXT_X, to.y - textheight(buf, strlentemp) / 2.0, strlentemp, SysColor); + } + } + } + } + + xmin2 = (int)(mMin.x / DELTA_SMALL) * DELTA_SMALL; + ymin2 = (int)(mMin.y / DELTA_SMALL) * DELTA_SMALL; + + if (DELTA_SMALL / step.x > THREE) { + j = (int)(( - xmin + xmin2 ) / DELTA_SMALL); + for (i = xmin2; i <= mMax.x; i += DELTA_SMALL, j++) { + if (j % 10 == 0) { + // we need to skip every tenth mark, to avoid overwriting big marks + j = 0; + continue; + } + from.x = i; + to.x = from.x; + from.y = -SMALL_HEIGHT * step.y; + to.y = SMALL_HEIGHT * step.y; + from = mat2Graf(from, scrMin, scrMax, mMin, mMax); + to = mat2Graf(to, scrMin, scrMax, mMin, mMax); + SysColor = BLACK; + _ksys_draw_line(from.x, from.y, to.x, to.y, SysColor); + sprintf(buf, FORMAT, i, '\0'); + strlentemp = strlen(buf); + if (from.y > scrMin.y && (DELTA_SMALL > textwidth(buf, strlentemp) * step.x)) { + SysColor = SMALLFONTCOLOR; + _ksys_draw_text(buf, from.x - textwidth(buf, strlentemp) / 2.0, to.y - textheight(buf, strlentemp), strlentemp, SysColor); + } + + + } + + } + + // finally small marks on Y + if (DELTA_SMALL / step.y > THREE) { + //_ksys_debug_puts("really small marks y painted\n"); + j = (int)(( - ymin + ymin2) / DELTA_SMALL); + for (i = ymin2; i <= mMax.y; i += DELTA_SMALL, j++) { + if (j % 10 == 0) { + // we need to skip every tenth, to avoid overwriting + j = 0; + continue; + } + from.y = i; + to.y = from.y; + from.x = -SMALL_HEIGHT * step.x; + to.x = SMALL_HEIGHT * step.x; + from = mat2Graf(from, scrMin, scrMax, mMin, mMax); + to = mat2Graf(to, scrMin, scrMax, mMin, mMax); + SysColor = BLACK; + _ksys_draw_line(from.x, from.y, to.x, to.y, SysColor); + sprintf(buf, FORMAT, i, '\0'); + strlentemp = strlen(buf); + if (from.x > scrMin.x && (DELTA_SMALL > textheight(buf, strlentemp) * step.y)) { + SysColor = SMALLFONTCOLOR; + _ksys_draw_text(buf, from.x + TEXT_X, from.y - textheight(buf, strlentemp) / 2.0, strlentemp, SysColor); + } + } + } + +} + +/* + ends fucking piece of shit +*/ + +void drawFunction( function_t fi, TCoord scrMin, TCoord scrMax, + TCoord mMin, TCoord mMax, int color) { + double x; + double y; + int firstPoint = 1; + TCoord p, p0 = {0.0, 0.0}, step; + + drawAxis(scrMin, scrMax, mMin, mMax); + + SysColor = color; + step.x = (mMax.x - mMin.x) / (scrMax.x - scrMin.x); + + for (x = mMin.x; x < mMax.x; x += step.x) { + y = fi(x); +// function is defined here and gets in the range + if (1) { // тут было условие, что функция правильно вычислена + if ((y > mMin.y) && (y < mMax.y)) { + p = mat2Graf(coord(x, y), scrMin, scrMax, mMin, mMax); + // if it's our first point, only remember its coords + // otherwise, draw a line from prev to current + if (firstPoint == 0) { + _ksys_draw_line(p0.x, p0.y, p.x, p.y, SysColor); + } else firstPoint = 0; + p0 = p; + } + else {// too big/small + firstPoint = 1; + } + } + else { // no value + firstPoint = 1; + } + } + +} + +// итоговая версия читалки текстовых файлов +int load_points3() { + ksys_bdfe_t bdfe; + int filePointer = 0; + + int i,j,k; + double d; + dword filesize, num_number; + + double* p2=0; + + // get file size + int rr = _ksys_file_get_info(edit_path, &bdfe); + sprintf(debuf, "getsize: %d\n", rr); + _ksys_debug_puts(debuf); + if (rr != 0) { + _ksys_draw_text((char*)er_file_not_found, 10, 10, strlen(er_file_not_found), 0x90FF0000); + return 0; + } + + filesize = bdfe.size; + num_number = filesize / 2; + + HugeBuf = (char*)malloc(filesize + 1); // разбираем как строку, отсюда терминатор \0 + + for (i=0;i= points[(point_count-1) * 2]) + return points[(point_count-1) * 2 + 1]; + + for (i = 0; i < point_count; i++) { + if ((x >= points[2 * i]) && (x < points[2 * (i + 1)])) + break; + } + + return (x - points[2 * i]) / (points[2 * (i + 1)] - points[2 * i]) + * (points[2 * (i + 1) + 1] - points[2 * i + 1]) + points[2 * i + 1]; + +} + +void draw_window(void) { + double xx0=0.0, yy0=0.0; + + _ksys_start_draw(); + _ksys_create_window(100, 80, WND_W, WND_H, full_head, 0xFFFFFF, 0x33); + _ksys_end_draw(); + + ksys_thread_t info; + _ksys_thread_info(&info, 0xFFFFFFFF); + int cWidth = info.winx_size - 9; + int cHeight = info.winy_size - _ksys_get_skin_height() - 4; + + mybox.top = cHeight - 50; + mybox.width = cWidth - mybox.left - 80; + + if (info.window_state&0x04) return; //draw nothing if window is rolled-up + + if (point_count == 0 && funct == NULL) { + _ksys_draw_text((char *)empty_text, (cWidth - 8 * strlen(empty_text))/2,cHeight/2-25, strlen(empty_text), 0x90000000); + } else { + drawFunction(&fu, coord(10, 20), coord(cWidth - 20, cHeight - 70), coord(x1,y1), coord(x2,y2), 0x00ff0000); + } + + _ksys_draw_text((char*)str_filename, 15, mybox.top + 4, strlen(str_filename), 0x90000000); + + edit_box_draw(&mybox); + + _ksys_define_button(cWidth - 70, mybox.top, 50, 21, BTN_EDIT, 0xc0c0c0); + _ksys_draw_text((char*)str_editfile, cWidth - 60, mybox.top + 4, 0, 0x90000000); +} + +int main() { + full_head = (char*)malloc(300); + strcpy(full_head, "Graph"); + _ksys_set_event_mask(0xC0000027); + int event; + while (1) { + edit_box_mouse(&mybox); + event = _ksys_get_event(); + switch (event) { + case KSYS_EVENT_REDRAW: + draw_window(); + break; + case KSYS_EVENT_KEY: { + ksys_oskey_t kc = _ksys_get_key(); + switch (kc.code) { + case 0x0D: + if (HugeBuf) { + //sprintf(debuf, "freemem: HugeBuf = %X", HugeBuf); + //_ksys_debug_puts(debuf); + free(HugeBuf); // что за баг - понять не могу. + HugeBuf = nullptr; + funct = nullptr; + } + if (points) { + //sprintf(debuf, "freemem: points = %X", points); + //_ksys_debug_puts(debuf); + free(points); // и тут. ну не обращаюсь я к этому указателю, только память в него, потом снова выделяю + points = nullptr; + } + point_count = 0; + _ksys_draw_bar(10, 10, 200, 20, 0xFFFFFF); // фон для сообщений об ошибках + if (load_points3()) + draw_window(); + break; + default: + edit_box_key_safe(&mybox, kc); + } + break; + } + case KSYS_EVENT_BUTTON: { + // button pressed; we have only one button, close + uint32_t button = _ksys_get_button(); + if (button == BTN_QUIT) + _ksys_exit(); + else if (button == BTN_EDIT) + _ksys_exec("/sys/develop/cedit", edit_path); + } + } + } + return 0; +} \ No newline at end of file diff --git a/programs/other/graph/branches/tcc_current/parser.c b/programs/other/graph/branches/tcc_current/parser.c new file mode 100755 index 0000000000..279a6ac63c --- /dev/null +++ b/programs/other/graph/branches/tcc_current/parser.c @@ -0,0 +1,418 @@ +#include +#include + +#include "func.h" +#include "parser.h" + +#define nullptr 0 + +// token types +#define DELIMITER 1 +#define VARIABLE 2 +#define NUMBER 3 +#define FUNCTION 4 +#define FINISHED 10 + +// error codes +#define ERR_BADFUNCTION -1 +#define ERR_BADNUMER -2 +#define ERR_GENERAL -3 +#define ERR_NOBRACKET -4 +#define ERR_BADVARIABLE -5 +#define ERR_OVERFLOW -6 + +//I guess it's not the best idea but we need pointers to functions anyway +double sin_p(double d) { + return sin(d); +} + +double cos_p(double d) { + return cos(d); +} + +double exp_p(double d) { + return exp(d); +} + +double sqrt_p(double d) { + return sqrt(d); +} + +double log_p(double d) { + return log(d); +} + +double tan_p(double d) { + return tan(d); +} + +double ctg(double d) { + return 1 / tan(d); +} + +double asin_p(double d) { + return asin(d); +} + +double acos_p(double d) { + return acos(d); +} + +double atan_p(double d) { + return atan(d); +} + +double fabs_p(double d) { + return fabs(d); +} + +double sgn(double d) { + if (d < 0) return -1; + return 1; +} + +double arcctg(double d) { + return atan(1 / d); +} + +double sec(double d) { + return 1 / sin(d); +} + +double cosec(double d) { + return 1 / cos(d); +} + +double log2_p(double d) { + return log(d) / log(2); +} + +double log10_p(double d) { + return log(d) / log(10); +} + +double log3(double d) { + return log(d) / log(3); +} + +// represents general mathematical function +typedef double(*matfunc)(double); + +// used to link function name to the function +typedef struct { + char name[10]; + matfunc f; +} func; + +// the list of functions +#define MAX_FUNCS 26 +func functions[MAX_FUNCS] = { + "", (matfunc)nullptr, + "sin", (matfunc)&sin_p, + "cos", (matfunc)&cos_p, + "exp", (matfunc)&exp_p, + "sqrt", (matfunc)&sqrt_p, + "log", (matfunc)&log_p, + "tg", (matfunc)&tan_p, + "tan", (matfunc)&tan_p, + "ctg", (matfunc)&ctg, + "cot", (matfunc)&ctg, + "arcsin", (matfunc)&asin_p, + "arccos", (matfunc)&acos_p, + "arctg", (matfunc)&atan_p, + "arctan", (matfunc)&atan_p, + "abs", (matfunc)&fabs_p, + "sgn", (matfunc)&sgn, + "arcctg", (matfunc)&arcctg, + "arccot", (matfunc)&arcctg, + "sec", (matfunc)&sec, + "cosec", (matfunc)&cosec, + "lb", (matfunc)&log2_p, + "log2", (matfunc)&log2_p, + "lg", (matfunc)&log10_p, + "log10", (matfunc)&log10_p, + "log3", (matfunc)&log3, + "ln", (matfunc)&log_p +}; + +// all delimiters +const char* delim="+-*^/%=;(),><"; // not bad words + +// structure for most parser functions +char token[80]; +int token_type; +char* prog; +double x_value; +int code; // error code + +int isdelim(char c) { + //return strchr(delim, c) != 0; + for (int i = 0; i < 14; i++) + if (c == delim[i]) + return 1; + return 0; +} + +int isdigit(char c) { + return (c >= '0' && c <= '9'); +} + +int isalpha2(char c) { + return ((c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z')); +} + +int iswhite(char c) { + return (c==' ' || c=='\t'); +} + +void serror(int code) { + //TODO (vitalkrilov): for what?: "::code = code;" + // longjmp(j, code); +} + +void set_exp(char* exp, double x) { + prog = exp; + x_value = x; +} + +int get_token() { + int tok; + char* temp; + (token_type) = 0; + tok = 0; + temp = (token); + + if (*(prog) == '\0') { + *(token) = 0; + tok = FINISHED; + return ((token_type) = DELIMITER); + } + while (iswhite(*(prog))) ++(prog); + if (isdelim(*(prog))) { + *temp = *(prog); + (prog)++; + temp++; + *temp = 0; + return ((token_type) = DELIMITER); + } + if (isdigit(*(prog))) { + while (!isdelim(*(prog))) + *temp++=*(prog)++; + *temp = '\0'; + return ((token_type) = NUMBER); + } + if (isalpha2(*(prog))) { + while (!isdelim(*(prog))) + *temp++=*(prog)++; + (token_type) = VARIABLE; + } + *temp = '\0'; + if ((token_type) == VARIABLE) { + tok = look_up((token)); + if (tok) + (token_type) = FUNCTION; + } + return (token_type); +} + +int sign(double d) { + if (d > 0.0) + return 1.0; + if (d < 0.0) + return -1.0; + return 0.0; +} + +void putback() { + char* t; + t = (token); + for (;*t;t++) + (prog)--; +} + +int get_exp(double* hold) { + int res; + code = 0; +// if (res = setjmp(j) != 0) +// return code; + get_token(); + if (!*(token)) { + return 0; + } + level2( hold); + putback(); + return 0; +} + +void level2(double* hold) { + char op; + double h; + + level3( hold); + while ((op=*(token)) == '+' || op == '-') { + get_token(); + level3( &h); + arith(op, hold, &h); + } +} + +void level3(double* hold) { + char op; + double h; + + level4( hold); + while ((op=*(token)) == '*' || op == '/' || op == '%') { + get_token(); + level4( &h); + arith( op, hold, &h); + } +} + +void level4(double* hold) { + double h; + level5( hold); + + if (*(token) == '^') { + get_token(); + level5( &h); + arith( '^', hold, &h); + } +} + +void level5(double* hold) { + char op; + + op = 0; + if (((token_type) == DELIMITER) && *(token) == '+' || *(token) == '-') { + op = *(token); + get_token(); + } + level6( hold); + + if (op) unary(op, hold); +} + +void level6(double* hold) { + if ((*(token) == '(') && ((token_type) == DELIMITER)) { + get_token(); + level2( hold); + if (*(token) != ')') + serror( ERR_NOBRACKET); + get_token(); + } + else + primitive( hold); +} + +void calc_function(double* hold) { + double d; + int i; + + i = look_up(token); + + if (i == 0) + serror(ERR_BADFUNCTION); // error + + get_token(); + if (*(token) != '(') + serror(ERR_NOBRACKET); // error + get_token(); + level2(hold); + get_token(); + + d = functions[i].f(*hold); + *hold = (functions[i].f)(*hold); +// else +// serror( ERR_OVERFLOW); + +} + +void primitive(double* hold) { + switch (token_type) { + case VARIABLE: + *hold = find_var(token); + get_token(); + return; + case NUMBER: + //*hold = atof((token)); + //if (sscanf(token, "%lf", hold) != 1) + *hold = convert(token, nullptr); + if (*hold == ERROR) + serror( ERR_BADNUMER); + get_token(); + return; + case FUNCTION: + calc_function( hold); + return; + default: // error + return; + } +} + +void arith(char op, double* r, double* h) { + double t; + switch(op) { + case '-': + *r = *r - *h; + break; + case '+': + *r = *r + *h; + break; + case '*': + *r = *r * *h; + break; + case '/': + if (*h == 0) + serror( ERR_OVERFLOW); + else + *r = (*r) / (*h); + break; + case '%': + if (*h == 0) + serror( ERR_OVERFLOW); + else + *r = fmod(*r, *h); + if (*r < 0) *r += *h; + break; + case '^': + *r = pow(*r, *h); + break; + } +} + +void unary(char op, double* r) { + if (op == '-') + *r = -(*r); +} + +double find_var(const char* s) { + //return 0; // not imp + //int i; + + //for (i = 0; i < kvar; i++) + // if (strcmp(vars[i].name, s) == 0) + // return vars[i].value; + + if (s[1] == '\0' && (s[0] == 'x' || s[0] == 'X')) + //if (strcmp(s,"x") == 0 || strcmp(s,"X") == 0) + return x_value; + + serror( ERR_BADVARIABLE); + return 0; // to make compiler very happy + + //printf("\nPlease enter value for variable \"%s\": ", s); + //scanf("%lf", &vars[kvar].value); + //strcpy(vars[kvar].name, s); + //kvar++; + //return vars[kvar - 1].value; +} + +int look_up(const char* s) { + int i; + + for (i = 0; i < MAX_FUNCS; i++) + if (strcmp(s, functions[i].name) == 0) + return i; + return 0; // search command/function name +} diff --git a/programs/other/graph/branches/tcc_current/parser.h b/programs/other/graph/branches/tcc_current/parser.h new file mode 100755 index 0000000000..a4d882b0a3 --- /dev/null +++ b/programs/other/graph/branches/tcc_current/parser.h @@ -0,0 +1,32 @@ +#ifndef PARSER_H +#define PARSER_H + +void set_exp(char* exp, double x); + +void putback(double* hold); // puts the token back to line + +int get_exp(double* hold); // gets the expression. This function is used externally + +void level2(double* hold); // works with +- + +void level3(double* hold); // works with */% + +void level4(double* hold); // works with ^ + +void level5(double* hold); // works with () + +void level6(double* hold); // works with elementary tokens + +void primitive(double* hold); // gets value of number, function or variable + +void arith(char op, double* r, double* h); // performs arithmetical operation + +void unary(char op, double* r); // performs unary (one-operand) operation + +double find_var(const char* s); // gets variable value by name + +void serror(int code); // stops execution of parser and return error code + +int look_up(const char* s); // checks the function table to see if such a function exists + +#endif /* PARSER_H */ \ No newline at end of file