first commit
This commit is contained in:
parent
50d0a2c3c9
commit
c8d704a06c
18 changed files with 871 additions and 0 deletions
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# kdevelop
|
||||||
|
.kde*
|
||||||
|
*.kdev4
|
||||||
|
# other
|
||||||
|
*.zip
|
||||||
|
*.wasm
|
||||||
|
*.lst
|
||||||
|
*.map
|
||||||
|
*.o
|
33
Makefile
Normal file
33
Makefile
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
CC = clang
|
||||||
|
CX = clang++
|
||||||
|
CODE ?= wasm
|
||||||
|
|
||||||
|
MOBJS = calc.yy.o calc.tab.o calculator.o
|
||||||
|
|
||||||
|
ifeq ($(CODE),wasm)
|
||||||
|
include wasm.mk
|
||||||
|
else
|
||||||
|
include unix.mk
|
||||||
|
endif
|
||||||
|
|
||||||
|
OBJS = $(MOBJS) $(MAIN)
|
||||||
|
CFLAGS += -Wno-unused-function
|
||||||
|
|
||||||
|
all: $(PR)
|
||||||
|
%.o: %.cpp
|
||||||
|
$(CX) -std=c++14 -c $(CFLAGS) -fno-exceptions -fno-rtti $< -o $@
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) -c $(CFLAGS) $< -o $@
|
||||||
|
calc.tab.o: calc.tab.c
|
||||||
|
$(CX) -std=c++14 -c $(CFLAGS) -Wno-deprecated -Wno-writable-strings -fno-exceptions -fno-rtti $< -o $@
|
||||||
|
$(PR): $(OBJS) $(WALIB)
|
||||||
|
$(LD) $(LFLAGS) $(OBJS) -o $(PR) $(LDLIBS)
|
||||||
|
calc.yy.cpp: calc.l calc.tab.h
|
||||||
|
flex calc.l
|
||||||
|
calc.tab.c calc.tab.h: calc.y
|
||||||
|
bison -d calc.y
|
||||||
|
clean:
|
||||||
|
rm -f *.o *.yy.* *.tab.*
|
||||||
|
distclean: clean
|
||||||
|
rm -f $(PR)
|
||||||
|
.PHONY: all clean distclean
|
46
bin/index.html
Normal file
46
bin/index.html
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>CALC</title>
|
||||||
|
<style>
|
||||||
|
tr, td { border-collapse: collapse; }
|
||||||
|
table { width:100%; border-collapse: collapse; text-align: center; }
|
||||||
|
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
|
||||||
|
textarea.emscripten { font-family: monospace; font-size: 16px; width: 100%; overflow-x: scroll; white-space: pre; background: black; color: rgb(0,255,0);}
|
||||||
|
.frame1 { width: 96%; margin: 0; padding: 10px; background-color: #FFFFC0; border: 10px solid #F0C0F0; }
|
||||||
|
.canvas { width: 100%; height: 65vh; background-color: black; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="module" src="index.js"></script>
|
||||||
|
<div class="frame1"><canvas id="canvas" class="canvas"></canvas></div>
|
||||||
|
<div class="frame1"><input id="buttonTest" type="button" value="Submit"></div>
|
||||||
|
<div class="frame1">
|
||||||
|
<table><tr>
|
||||||
|
<td width="40%"><textarea class="emscripten" id="input" rows="10" spellcheck="false"></textarea></td>
|
||||||
|
<td><textarea readonly class="emscripten" id="stdout" rows="10" spellcheck="false"></textarea></td>
|
||||||
|
</tr></table>
|
||||||
|
</div>
|
||||||
|
<div class="frame1">
|
||||||
|
<h2>Kalkulátor s grafickým výstupem.</h2>
|
||||||
|
<p>Když jsem přepisoval z nudy syntax highlighter pro C++ z pythonu do C++, zjistil jsem, že regulární výrazy
|
||||||
|
jsou kupodivu v tom pythonu efektivnější. V tomto ohledu je STL knihovna asi dost naprd. Ale vzpomněl jsem si
|
||||||
|
na prastarý pár flex a bison, který umí nejen regulární výrazy, ale jde s tím parsovat dost jednoduše gramatika.
|
||||||
|
Mělo by to jít i v C++, ale příklady na webu byly dost zamotané a bylo nutné použít STL, kterou jsem pro tento
|
||||||
|
účel neměl k dispozici. Vyřešilo se to jednoduše - vygenerovaný C-čkový kód se přeloží jako C++, přičemž je
|
||||||
|
nutné povypínat něktetré warningy.
|
||||||
|
</p>
|
||||||
|
<p>Je to tedy jednoduchý kalkulátor, jde napsat výraz s normální notací (+-*/^), obsahující čísla (i desetinná),
|
||||||
|
který to normálně vyhodnotí. Postupně přibyly proměnné (jen písmenkové řetězce), které mohou mít i rozsah ve
|
||||||
|
kterém se pak výraz zobrazí jako funkce. Komentáře jsou ve složených závorkách. Vložené matematické funkce
|
||||||
|
jsou sin(), cos(), exp(), log() (přirozené).<b>Na konci výrazu musí být ENTER.</b>
|
||||||
|
</p>
|
||||||
|
<p>Jsou v tom chyby, celé je to vlasně hloupost, celé by to šlo napsat v javascriptu mnohem jednodušeji,
|
||||||
|
ale v podstatě to funguje a jde si podle toho udělat představu, jak daná funkce vypadá. Zdrojáky v licenci
|
||||||
|
MIT <a href="flex.zip">přikládám</a>. Pro kompilaci je použit jen clang a jím kompilovaná C-čková knihovna
|
||||||
|
<a href="https://sourceware.org/newlib/" target="_blank">newlib</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
126
bin/index.js
Normal file
126
bin/index.js
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
var gWASM; // globální proměnná + elementy stránky
|
||||||
|
const Outs = document.getElementById('stdout');
|
||||||
|
const Btnt = document.getElementById('buttonTest');
|
||||||
|
const Canvas = document.getElementById('canvas');
|
||||||
|
// async/await z příkladu na webu
|
||||||
|
window.onload = async function() {
|
||||||
|
Btnt.disabled = true;
|
||||||
|
Outs.value = 'Compiling ...¨\n'; // presets
|
||||||
|
// Build WebAssembly instance - WebAssembly.instantiateStreaming problem
|
||||||
|
const memory = new WebAssembly.Memory({ initial: 4 });
|
||||||
|
const importObject = {
|
||||||
|
env: { memory }, // nutné pro práci a pamětí
|
||||||
|
imports: { // importované funkce do wasm
|
||||||
|
printout : (ptr, len) => {
|
||||||
|
// pohled do paměti - ptr je vlastně číslo
|
||||||
|
const view = new Uint8Array (memory.buffer, ptr, len);
|
||||||
|
const utf8decoder = new TextDecoder();
|
||||||
|
Outs.value += utf8decoder.decode(view); // to String
|
||||||
|
},
|
||||||
|
memoryGrow : (len) => {
|
||||||
|
console.log ('Growing the memory by ' + len.toString() + '. 64K blocks');
|
||||||
|
memory.grow (len); // patrně to jde volat přímo z C/C++ kódu, ale tohle funguje
|
||||||
|
},
|
||||||
|
drawPoints : (px, py, len, pj, jl) => {
|
||||||
|
const xview = new Float32Array (memory.buffer, px, len);
|
||||||
|
const yview = new Float32Array (memory.buffer, py, len);
|
||||||
|
const view = new Uint8Array (memory.buffer, pj, jl);
|
||||||
|
const utf8decoder = new TextDecoder();
|
||||||
|
const obj = JSON.parse (utf8decoder.decode(view));
|
||||||
|
// console.log (obj);
|
||||||
|
if (!obj) obj = '{"name":"nothing"}';
|
||||||
|
polyLine (xview, yview, len, obj);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const response = await fetch('./module.wasm');
|
||||||
|
const bytes = await response.arrayBuffer();
|
||||||
|
const module = await WebAssembly.instantiate(bytes, importObject);
|
||||||
|
gWASM = {
|
||||||
|
asm : module.instance.exports,
|
||||||
|
mem : memory,
|
||||||
|
};
|
||||||
|
gWASM.asm.init(memory.buffer.byteLength);
|
||||||
|
Btnt.onclick = () => {
|
||||||
|
Outs.value = '';
|
||||||
|
const expression = document.getElementById('input').value;
|
||||||
|
// console.log(expression);
|
||||||
|
stringToModule (expression, gWASM.asm.compute);
|
||||||
|
};
|
||||||
|
Outs.value = 'Module compiled - [insert formula and] press button Submit\n';
|
||||||
|
Btnt.disabled = false;
|
||||||
|
// console.log (gWASM);
|
||||||
|
window.addEventListener('resize', resizeCanvas, false);
|
||||||
|
resizeCanvas();
|
||||||
|
getFile ('test.txt');
|
||||||
|
Splash ();
|
||||||
|
};
|
||||||
|
function stringToModule (str, mfunc) {
|
||||||
|
const utf8EncodeText = new TextEncoder();
|
||||||
|
const bytes = utf8EncodeText.encode(str);
|
||||||
|
// alokovat pamet v modulu je nutne, aby bylo kam kopirovat
|
||||||
|
const cArrayPointer = gWASM.asm.cAlloc(bytes.length);
|
||||||
|
if (!cArrayPointer) return;
|
||||||
|
const cArray = new Uint8Array(gWASM.mem.buffer, cArrayPointer, bytes.length);
|
||||||
|
cArray.set(bytes); // naplnit dekodovanym stringem
|
||||||
|
mfunc (cArrayPointer, cArray.length);
|
||||||
|
}
|
||||||
|
function resizeCanvas () {
|
||||||
|
const width = canvas.clientWidth;
|
||||||
|
const height = canvas.clientHeight;
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
// console.log (width, height);
|
||||||
|
gWASM.asm.resizeCanvas (width, height);
|
||||||
|
}
|
||||||
|
function drawLine (ctx, line, x, y) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(line.b[0], line.b[1]);
|
||||||
|
ctx.lineTo(line.e[0], line.e[1]);
|
||||||
|
ctx.lineWidth = line.w;
|
||||||
|
ctx.strokeStyle = line.color;
|
||||||
|
if (line.lbl) {
|
||||||
|
//console.log (line.lbl);
|
||||||
|
ctx.fillStyle = line.color;
|
||||||
|
ctx.fillText (line.lbl, line.b[0] + x, line.b[1] - y);
|
||||||
|
}
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
function polyLine (ax, ay, len, obj) {
|
||||||
|
// console.log (ax, ay);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
ctx.font = '16px serif';
|
||||||
|
ctx.textAlign = 'left';
|
||||||
|
if (obj.name === "axes") {
|
||||||
|
drawLine (ctx, obj.x, 0, 0);
|
||||||
|
drawLine (ctx, obj.y, 0, 0);
|
||||||
|
const ndotsx = obj.xdots.length;
|
||||||
|
for (let n=0; n<ndotsx; n++) { drawLine (ctx, obj.xdots[n], 0, 5); }
|
||||||
|
const ndotsy = obj.ydots.length;
|
||||||
|
for (let n=0; n<ndotsy; n++) { drawLine (ctx, obj.ydots[n], 10, 0); }
|
||||||
|
}
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(ax[0], ay[0]);
|
||||||
|
for (let n=1; n<len; n++) {
|
||||||
|
ctx.lineTo(ax[n], ay[n]);
|
||||||
|
}
|
||||||
|
ctx.lineWidth = 3;
|
||||||
|
ctx.strokeStyle = "#00ff00";
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
async function getFile (name) {
|
||||||
|
const response = await fetch (name);
|
||||||
|
if (!response.ok) return;
|
||||||
|
const bytes = await response.arrayBuffer();
|
||||||
|
const array = new Uint8Array(bytes);
|
||||||
|
const decoder = new TextDecoder();
|
||||||
|
document.getElementById('input').value = decoder.decode(bytes);
|
||||||
|
}
|
||||||
|
function Splash () {
|
||||||
|
const content = Canvas.getContext('2d');
|
||||||
|
content.font = '96px serif';
|
||||||
|
content.fillStyle = '#00FF00';
|
||||||
|
content.textAlign = 'center';
|
||||||
|
content.fillText ('Graphic calculator', Canvas.width / 2, Canvas.height / 2);
|
||||||
|
}
|
7
bin/test.txt
Normal file
7
bin/test.txt
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{vlnový balík}
|
||||||
|
max=10
|
||||||
|
x=-max,max,1000
|
||||||
|
a=1/4
|
||||||
|
omega=2*pi
|
||||||
|
phi=omega/4
|
||||||
|
1.e-8 * sin (omega*x - phi) * exp (-(x*a)^2)
|
31
calc.l
Normal file
31
calc.l
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
%{
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "calc.tab.h"
|
||||||
|
#include "calculator.h"
|
||||||
|
%}
|
||||||
|
%option outfile="calc.yy.cpp" header-file="calc.yy.h"
|
||||||
|
%option case-sensitive
|
||||||
|
%option array
|
||||||
|
|
||||||
|
D [0-9]
|
||||||
|
E [Ee][+-]?{D}+
|
||||||
|
|
||||||
|
%%
|
||||||
|
pi { return MATHPI; }
|
||||||
|
sin { return FCESIN; }
|
||||||
|
cos { return FCECOS; }
|
||||||
|
exp { return FCEEXP; }
|
||||||
|
log { return FCELOG; }
|
||||||
|
[a-zA-Z]+ { yylval.svalue = strdup (yytext); return IDENT; }
|
||||||
|
{D}+ { yylval.svalue = strdup (yytext); return INTEGER; }
|
||||||
|
{D}*\.{D}+({E})? { yylval.svalue = strdup (yytext); return DOUBLE; }
|
||||||
|
{D}*\.{D}*({E})? { yylval.svalue = strdup (yytext); return DOUBLE; }
|
||||||
|
\{.*\}
|
||||||
|
[ \t]+ /* ignored */
|
||||||
|
\n { return ENDLINE; }
|
||||||
|
. { return yytext[0]; }
|
||||||
|
%%
|
||||||
|
void prevent_unused (void) {
|
||||||
|
(void) yyunput;
|
||||||
|
/* (void) input; */
|
||||||
|
}
|
68
calc.y
Normal file
68
calc.y
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
%{
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "calculator.h"
|
||||||
|
int yylex (void);
|
||||||
|
int yyerror (char *);
|
||||||
|
%}
|
||||||
|
%language "C"
|
||||||
|
%union {
|
||||||
|
char * svalue;
|
||||||
|
double dvalue;
|
||||||
|
class Expression * evalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
%token ENDLINE
|
||||||
|
%token DOUBLE
|
||||||
|
%token INTEGER
|
||||||
|
%token MATHPI
|
||||||
|
%token FCESIN
|
||||||
|
%token FCECOS
|
||||||
|
%token FCEEXP
|
||||||
|
%token FCELOG
|
||||||
|
%token IDENT
|
||||||
|
%token TEXT
|
||||||
|
%left '+' '-'
|
||||||
|
%left '*' '/'
|
||||||
|
%left '^'
|
||||||
|
|
||||||
|
%type <svalue> ENDLINE DOUBLE INTEGER IDENT line lines
|
||||||
|
%type <evalue> expr
|
||||||
|
%type <dvalue> constnt
|
||||||
|
%start input
|
||||||
|
%%
|
||||||
|
|
||||||
|
input: /* empty */
|
||||||
|
| lines
|
||||||
|
;
|
||||||
|
lines: line
|
||||||
|
| lines line
|
||||||
|
;
|
||||||
|
line: ENDLINE
|
||||||
|
| IDENT '=' expr ENDLINE { addVariable ($1, $3->eval()); free ($1); }
|
||||||
|
| IDENT '=' expr ',' expr ',' expr ENDLINE { addRange ($1, $3->eval(), $5->eval(), $7->eval()); free ($1); }
|
||||||
|
| expr ENDLINE { addExpression ($1); }
|
||||||
|
| error ENDLINE { printf ("what:%s\n", $$); }
|
||||||
|
;
|
||||||
|
constnt: DOUBLE { $$ = str_to_double ($1); free ($1); }
|
||||||
|
| INTEGER { $$ = str_to_long ($1); free ($1); }
|
||||||
|
| MATHPI { $$ = 3.14159265359; }
|
||||||
|
;
|
||||||
|
expr: constnt { $$ = new Constant ($1); }
|
||||||
|
| IDENT { $$ = new Variable ($1); free ($1); }
|
||||||
|
| '-' expr { $$ = new Unary ($2, UNARY_MINUS); }
|
||||||
|
| expr '+' expr { $$ = new Binary ($1, $3, BINARY_PLUS); }
|
||||||
|
| expr '-' expr { $$ = new Binary ($1, $3, BINARY_MINUS);}
|
||||||
|
| expr '*' expr { $$ = new Binary ($1, $3, BINARY_MULT); }
|
||||||
|
| expr '/' expr { $$ = new Binary ($1, $3, BINARY_DIV); }
|
||||||
|
| expr '^' expr { $$ = new Binary ($1, $3, BINARY_POW); }
|
||||||
|
| '(' expr ')' { $$ = $2; }
|
||||||
|
| FCESIN '(' expr ')' { $$ = new Unary ($3, UNARY_SIN); }
|
||||||
|
| FCECOS '(' expr ')' { $$ = new Unary ($3, UNARY_COS); }
|
||||||
|
| FCEEXP '(' expr ')' { $$ = new Unary ($3, UNARY_EXP); }
|
||||||
|
| FCELOG '(' expr ')' { $$ = new Unary ($3, UNARY_LOG); }
|
||||||
|
;
|
||||||
|
%%
|
||||||
|
int yyerror(char * err) {
|
||||||
|
printf("Error:\"%s\"\n", err);
|
||||||
|
return 0;
|
||||||
|
}
|
82
calculator.cpp
Normal file
82
calculator.cpp
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "calculator.h"
|
||||||
|
|
||||||
|
double str_to_double (const char * str) {
|
||||||
|
return strtod (str, NULL);
|
||||||
|
}
|
||||||
|
long str_to_long (const char * str) {
|
||||||
|
return strtol (str, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double u_minus (const double x) { return -x; }
|
||||||
|
const unary_function unary_function_table [UNARY_max] = {
|
||||||
|
u_minus,
|
||||||
|
sin, cos, exp, log,
|
||||||
|
};
|
||||||
|
static double b_plus (const double a, const double b) { return a + b; }
|
||||||
|
static double b_minus (const double a, const double b) { return a - b; }
|
||||||
|
static double b_multiply (const double a, const double b) { return a * b; }
|
||||||
|
static double b_divide (const double a, const double b) { return b !=0.0 ? a / b : 1.0; }
|
||||||
|
const binary_function binary_function_table [BINARY_max] = {
|
||||||
|
b_plus, b_minus, b_multiply, b_divide, pow,
|
||||||
|
};
|
||||||
|
static CommonData * main_data = nullptr;
|
||||||
|
void addVariable (const char * str, const double x) {
|
||||||
|
printf ("\"%s\"\t= %g\n", str, x);
|
||||||
|
if (main_data->list == nullptr) {
|
||||||
|
main_data->list = new VariableList (str, x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
main_data->list->add(str, x);
|
||||||
|
}
|
||||||
|
void addRange (const char * str, const double x, const double e, const double s) {
|
||||||
|
printf ("\"%s\"\t= [%g:%g],%g\n", str, x, e, s);
|
||||||
|
if (main_data->list == nullptr) {
|
||||||
|
main_data->list = new VariableList (str, x, e, s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
main_data->list->add(str, x, e, s);
|
||||||
|
}
|
||||||
|
static Range zero = {0.0, 0.0, 0.0};
|
||||||
|
Variable::Variable(const char * name) {
|
||||||
|
data = main_data->list->find (name);
|
||||||
|
if (!data) {
|
||||||
|
printf("variable \"%s\" not assigned, zero used\n", name);
|
||||||
|
data = & zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extern void emitData (double * x, double * y, const int len);
|
||||||
|
void addExpression (Expression * e) {
|
||||||
|
if (main_data->root) delete main_data->root;
|
||||||
|
main_data->root = e;
|
||||||
|
|
||||||
|
VariableList * vl = main_data->list->find_ranged();
|
||||||
|
if (!vl) {
|
||||||
|
printf("f() = %g\n", e->eval());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Range * r = vl->get();
|
||||||
|
const double x0 = r->value, x1 = r->end, s = fabs (r->step);
|
||||||
|
int n = (x1 - x0) / s;
|
||||||
|
if (n <= 0) return;
|
||||||
|
double * vx = new double [n + 1];
|
||||||
|
double * vy = new double [n + 1];
|
||||||
|
// printf("n=%d\n", n);
|
||||||
|
for (int i=0; i<n+1; i++) {
|
||||||
|
const double x = x0 + (double) i * s;
|
||||||
|
r->value = x;
|
||||||
|
const double y = e->eval();
|
||||||
|
vx[i] = x; vy[i] = y;
|
||||||
|
}
|
||||||
|
emitData (vx, vy, n+1);
|
||||||
|
delete [] vx; delete [] vy;
|
||||||
|
}
|
||||||
|
void initData () {
|
||||||
|
main_data = new CommonData();
|
||||||
|
}
|
||||||
|
void finiData () {
|
||||||
|
delete main_data;
|
||||||
|
}
|
||||||
|
|
121
calculator.h
Normal file
121
calculator.h
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
/* inclusion guard */
|
||||||
|
#ifndef __CALCULATOR_H__
|
||||||
|
#define __CALCULATOR_H__
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
extern double str_to_double (const char * str);
|
||||||
|
extern long str_to_long (const char * str);
|
||||||
|
extern void addVariable (const char * str, const double x);
|
||||||
|
extern void addRange (const char * str, const double x, const double e, const double s);
|
||||||
|
|
||||||
|
extern void initData ();
|
||||||
|
extern void finiData ();
|
||||||
|
|
||||||
|
class Expression {
|
||||||
|
public:
|
||||||
|
virtual double eval () = 0;
|
||||||
|
virtual ~Expression () {}
|
||||||
|
};
|
||||||
|
class Constant : public Expression {
|
||||||
|
double data;
|
||||||
|
public:
|
||||||
|
explicit Constant (const double x) : data (x) {}
|
||||||
|
explicit Constant (const long x) : data (x) {}
|
||||||
|
double eval () override { /*printf("c=%g", data);*/ return data; }
|
||||||
|
virtual ~Constant() {}
|
||||||
|
};
|
||||||
|
extern void addExpression (Expression * e);
|
||||||
|
enum UNARY_FNCS {
|
||||||
|
UNARY_MINUS = 0, UNARY_SIN, UNARY_COS, UNARY_EXP, UNARY_LOG, UNARY_max
|
||||||
|
};
|
||||||
|
enum BINARY_FNCS {
|
||||||
|
BINARY_PLUS = 0, BINARY_MINUS, BINARY_MULT, BINARY_DIV, BINARY_POW, BINARY_max
|
||||||
|
};
|
||||||
|
typedef double (*unary_function) (const double);
|
||||||
|
typedef double (*binary_function) (const double, const double);
|
||||||
|
extern const unary_function unary_function_table [UNARY_max];
|
||||||
|
extern const binary_function binary_function_table [BINARY_max];
|
||||||
|
class Unary : public Expression {
|
||||||
|
Expression * m_expr;
|
||||||
|
unary_function m_f;
|
||||||
|
public:
|
||||||
|
explicit Unary (Expression * e, const UNARY_FNCS nf) : m_expr(e), m_f (unary_function_table[nf]) {}
|
||||||
|
double eval () override { /*printf("(*%p)(%p)", m_f, m_expr);*/ return (m_f (m_expr->eval())); }
|
||||||
|
virtual ~Unary () { delete m_expr; }
|
||||||
|
};
|
||||||
|
class Binary : public Expression {
|
||||||
|
Expression * m_l, * m_r;
|
||||||
|
binary_function m_f;
|
||||||
|
public:
|
||||||
|
explicit Binary (Expression * l, Expression * r, const BINARY_FNCS nf) : m_l(l), m_r(r), m_f(binary_function_table[nf]) {}
|
||||||
|
double eval () override { /*printf("{%p}[%p]{%p}", m_l, m_f, m_r);*/ return (m_f (m_l->eval(), m_r->eval())); }
|
||||||
|
virtual ~Binary() { delete m_l; delete m_r; }
|
||||||
|
};
|
||||||
|
struct Range {
|
||||||
|
double value, end, step;
|
||||||
|
};
|
||||||
|
class VariableList {
|
||||||
|
VariableList * next;
|
||||||
|
char * name;
|
||||||
|
Range data;
|
||||||
|
public:
|
||||||
|
explicit VariableList (const char * _name, const double _value) : next(nullptr) {
|
||||||
|
name = strdup (_name);
|
||||||
|
data.value = _value;
|
||||||
|
data.end = _value;
|
||||||
|
data.step = 0.0;
|
||||||
|
}
|
||||||
|
explicit VariableList (const char * _name, const double _value, const double _end, const double steps) : next(nullptr) {
|
||||||
|
name = strdup (_name);
|
||||||
|
if (_value > _end) {
|
||||||
|
data.value = _end;
|
||||||
|
data.end = _value;
|
||||||
|
} else {
|
||||||
|
data.value = _value;
|
||||||
|
data.end = _end;
|
||||||
|
}
|
||||||
|
if (steps != 0.0) data.step = (data.end - data.value) / steps;
|
||||||
|
else data.step = 1.0;
|
||||||
|
}
|
||||||
|
~VariableList () {
|
||||||
|
if (next) delete next;
|
||||||
|
free (name);
|
||||||
|
}
|
||||||
|
void add (const char * _name, const double _value) {
|
||||||
|
if (!next) next = new VariableList (_name, _value);
|
||||||
|
else next->add (_name, _value);
|
||||||
|
}
|
||||||
|
void add (const char * _name, const double _value, const double _end, const double steps) {
|
||||||
|
if (!next) next = new VariableList (_name, _value, _end, steps);
|
||||||
|
else next->add (_name, _value, _end, steps);
|
||||||
|
}
|
||||||
|
Range * find (const char * _name) {
|
||||||
|
if (!strcmp (name, _name)) return & data;
|
||||||
|
if (next) return next->find (_name);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
VariableList * find_ranged () {
|
||||||
|
if (data.step) return this;
|
||||||
|
if (next) return next->find_ranged();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
Range * get () { return & data; }
|
||||||
|
};
|
||||||
|
class Variable : public Expression {
|
||||||
|
Range * data;
|
||||||
|
public:
|
||||||
|
explicit Variable (const char * name);
|
||||||
|
double eval() override { return data->value; }
|
||||||
|
virtual ~Variable () {}
|
||||||
|
};
|
||||||
|
struct CommonData {
|
||||||
|
VariableList * list;
|
||||||
|
Expression * root;
|
||||||
|
explicit CommonData() : list(nullptr), root(nullptr) {}
|
||||||
|
~CommonData () {
|
||||||
|
if (list) delete list;
|
||||||
|
if (root) delete root;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __CALCULATOR_H__ */
|
46
heap.c
Normal file
46
heap.c
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#include "heap.h"
|
||||||
|
extern void IMPORT(memoryGrow) (const int block);
|
||||||
|
extern char __heap_base;
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
|
||||||
|
static const char * _HEAP_START = &__heap_base;
|
||||||
|
char * _HEAP_MAX = &__heap_base;
|
||||||
|
|
||||||
|
void * sbrk (unsigned long size) {
|
||||||
|
static const char * heap_ptr;
|
||||||
|
const char * old_heap_ptr;
|
||||||
|
static unsigned int init_sbrk = 0;
|
||||||
|
/* heap_ptr is initialized to HEAP_START */
|
||||||
|
if (init_sbrk == 0) {
|
||||||
|
heap_ptr = _HEAP_START;
|
||||||
|
init_sbrk = 1;
|
||||||
|
}
|
||||||
|
old_heap_ptr = heap_ptr;
|
||||||
|
/* Tohle je jen zkusmo, uvidíme, zatím se zdá, že to chodí.
|
||||||
|
* Těžko říct, co to udělá, když dojde paměť, ale pár MiB to zvládne.
|
||||||
|
*/
|
||||||
|
if ((heap_ptr + size) > _HEAP_MAX) {
|
||||||
|
const int blocks = (((heap_ptr + size) - _HEAP_MAX) >> 16) + 1;
|
||||||
|
memoryGrow (blocks);
|
||||||
|
_HEAP_MAX += blocks << 16;
|
||||||
|
}
|
||||||
|
heap_ptr += size;
|
||||||
|
return (void *)old_heap_ptr;
|
||||||
|
}
|
||||||
|
/* Následující je někde použito v parseru, ale nemusí to moc fungovat.
|
||||||
|
*/
|
||||||
|
int write(int fd, const void * b, size_t l) {
|
||||||
|
if ((fd == 1) || (fd == 2)) printout(b, l);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
// formátování pro long double asi nebudu používat
|
||||||
|
extern void exit (int x)__attribute__((noreturn));
|
||||||
|
void _exit (int x) __attribute__ ((noreturn));
|
||||||
|
void _exit (int x) { exit(x); }
|
||||||
|
double __trunctfdf2(long double a) { return (double)(a); }
|
||||||
|
int isatty () { return 1; }
|
||||||
|
|
||||||
|
void close (int fd) {}
|
||||||
|
int read (int fd, void * b, size_t l) { return l; }
|
||||||
|
size_t lseek(int fd, size_t offset, int whence) { return 0; }
|
||||||
|
int fstat(int fd, void * statbuf) { return 0; }
|
15
heap.h
Normal file
15
heap.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef _HEAP_H
|
||||||
|
#define _HEAP_H
|
||||||
|
#define EXPORT(name) __attribute__((used, export_name(#name))) name
|
||||||
|
// "imports" odpovídá importObject.imports v JS, default je to importObject.env
|
||||||
|
#define IMPORT(name) __attribute__((import_module("imports"),import_name(#name))) name
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif //__cplusplus
|
||||||
|
extern void IMPORT(printout) (const char * ptr, const int len); // external javascript function
|
||||||
|
extern void * sbrk (unsigned long size);
|
||||||
|
extern char * _HEAP_MAX;
|
||||||
|
#ifdef __cplusplus
|
||||||
|
};
|
||||||
|
#endif //__cplusplus
|
||||||
|
#endif // _HEAP_H
|
23
newdel.cpp
Normal file
23
newdel.cpp
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
void* operator new (unsigned long size) {
|
||||||
|
return calloc(1,size);
|
||||||
|
}
|
||||||
|
void operator delete (void* p) {
|
||||||
|
free (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* operator new[] (unsigned long size) {
|
||||||
|
return calloc(1,size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[] (void* p) {
|
||||||
|
free (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete (void* p, unsigned size) {
|
||||||
|
(void) size;
|
||||||
|
free (p);
|
||||||
|
}
|
||||||
|
|
3
symbols.txt
Normal file
3
symbols.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
printout
|
||||||
|
memoryGrow
|
||||||
|
drawPoints
|
3
test.txt
Normal file
3
test.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
x=2,8,20
|
||||||
|
y=1
|
||||||
|
y*x^2 + 5*y*x + 1
|
59
unix.cpp
Normal file
59
unix.cpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "calc.yy.h"
|
||||||
|
#include "calculator.h"
|
||||||
|
|
||||||
|
extern void yyparse ();
|
||||||
|
extern "C" int yywrap () {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char * from_file (const char * filename) {
|
||||||
|
struct stat statbuf;
|
||||||
|
int r = stat (filename, & statbuf);
|
||||||
|
if (r) return nullptr;
|
||||||
|
char * buffer = (char*) malloc (statbuf.st_size + 1);
|
||||||
|
FILE * in = fopen (filename,"r");
|
||||||
|
r = fread (buffer, 1, statbuf.st_size, in);
|
||||||
|
if (r != statbuf.st_size) {
|
||||||
|
free (buffer);
|
||||||
|
fclose (in);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
buffer [r] = '\0';
|
||||||
|
fclose (in);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
void emitData (double * x, double * y, const int len) {
|
||||||
|
for (int n=0; n<len; n++) {
|
||||||
|
printf("f(%g) = %g\n", x[n], y[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
static const char * multipliers [] = {"f","p","n","μ","m","","k","M","G","T","P"};
|
||||||
|
static void test () {
|
||||||
|
const int ofs = 5 * 3;
|
||||||
|
for (int n=-15; n<18; n++) {
|
||||||
|
div_t dt = div (n + ofs, 3);
|
||||||
|
printf("n=%d, q=%d, r=%d (%d)\t%g %s\n", n, dt.quot, dt.rem, dt.quot * 3 + dt.rem - ofs,
|
||||||
|
pow(10.0, dt.rem), multipliers[dt.quot]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
int main () {
|
||||||
|
char * buffer = from_file("test.txt");
|
||||||
|
if (!buffer) return 1;
|
||||||
|
|
||||||
|
initData();
|
||||||
|
YY_BUFFER_STATE result = yy_scan_string(buffer);
|
||||||
|
yyparse();
|
||||||
|
yy_delete_buffer(result);
|
||||||
|
free (buffer);
|
||||||
|
finiData();
|
||||||
|
|
||||||
|
//test();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
7
unix.mk
Normal file
7
unix.mk
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
MAIN = unix.o
|
||||||
|
LD = clang++
|
||||||
|
PR = test
|
||||||
|
CFLAGS = -Wall -Oz -g -I. -I./lib
|
||||||
|
LFLAGS =
|
||||||
|
LDLIBS =
|
||||||
|
|
172
wasm.cpp
Normal file
172
wasm.cpp
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "calculator.h"
|
||||||
|
#include "heap.h"
|
||||||
|
extern "C" void EXPORT(init) (const int memlen);
|
||||||
|
extern "C" int EXPORT(cAlloc) (int len);
|
||||||
|
extern "C" void EXPORT(compute) (char * ptr, int len);
|
||||||
|
extern "C" void EXPORT(resizeCanvas)(int x, int y);
|
||||||
|
extern "C" void IMPORT(drawPoints) (float * x, float * y, int len, char * json, int jl);
|
||||||
|
extern "C" void __wasm_call_ctors ();
|
||||||
|
extern "C++" {
|
||||||
|
typedef struct yy_buffer_state * YY_BUFFER_STATE;
|
||||||
|
extern int yyparse();
|
||||||
|
extern YY_BUFFER_STATE yy_scan_string(const char * str);
|
||||||
|
extern void yy_delete_buffer(YY_BUFFER_STATE buffer);
|
||||||
|
};
|
||||||
|
extern "C" int yywrap () {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
void init (const int memlen) {
|
||||||
|
_HEAP_MAX = reinterpret_cast<char*>(memlen);
|
||||||
|
__wasm_call_ctors();
|
||||||
|
printf("Module initialized\n\n");
|
||||||
|
}
|
||||||
|
int cAlloc (int len) {
|
||||||
|
return int (malloc(len + 1));
|
||||||
|
}
|
||||||
|
void compute (char * ptr, int len) {
|
||||||
|
ptr [len] = '\0';
|
||||||
|
|
||||||
|
initData();
|
||||||
|
YY_BUFFER_STATE result = yy_scan_string(ptr);
|
||||||
|
yyparse();
|
||||||
|
yy_delete_buffer(result);
|
||||||
|
free (ptr);
|
||||||
|
finiData();
|
||||||
|
}
|
||||||
|
struct Canvas {
|
||||||
|
double width, height;
|
||||||
|
double xscale, yscale;
|
||||||
|
double xofset, yofset;
|
||||||
|
float xt (const double x) {
|
||||||
|
return float (xscale * (x - xofset));
|
||||||
|
}
|
||||||
|
float yt (const double y) {
|
||||||
|
return float (height - yscale * (y - yofset));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static const char * multipliers [] = {"f","p","n","μ","m","","k","M","G","T","P"};
|
||||||
|
struct Stepping {
|
||||||
|
double b,e,s;
|
||||||
|
char fmtbuf [16];
|
||||||
|
explicit Stepping (const double from, const double to) {
|
||||||
|
double lp;
|
||||||
|
const double z = log10 (fabs (to - from));
|
||||||
|
const double fp = modf (z, & lp);
|
||||||
|
if (fp < 0.30103) s = 1.0;
|
||||||
|
else if (fp > 0.69897) s = 5.0;
|
||||||
|
else s = 2.0;
|
||||||
|
int ip = int (lp) - 1;
|
||||||
|
if (z < 0.0) ip -= 1;
|
||||||
|
s *= ::pow (10.0, double (ip));
|
||||||
|
do {
|
||||||
|
const int k = int (fabs(to - from) / s);
|
||||||
|
b = round (from / s) * s;
|
||||||
|
e = round (to / s) * s;
|
||||||
|
if (k > 50) s *= 10.0; // prevence přeplnění osy, nevím proč, ale tohle to odstraní
|
||||||
|
else break; // patrně log10() nedává přesně to, co bych čekal
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
void f () {printf("stepping = %g, b = %g, e = %g\n", s, b, e);}
|
||||||
|
char * ing (const double x, int n=0) {
|
||||||
|
if (fabs(x) < 0.5 * s) {
|
||||||
|
fmtbuf[n++] = ' ';
|
||||||
|
fmtbuf[n++] = '\0';
|
||||||
|
return fmtbuf;
|
||||||
|
}
|
||||||
|
if (x < 0.0) {
|
||||||
|
fmtbuf[n++] = '-';
|
||||||
|
return ing (-x, n);
|
||||||
|
}
|
||||||
|
if (x > 0.0) {
|
||||||
|
double ip;
|
||||||
|
const double fp = modf(log10(x), & ip);
|
||||||
|
int pi = ip, ofs = 5 * 3;
|
||||||
|
if (pi < -ofs) pi = -ofs;
|
||||||
|
if (pi > 18 ) pi = 18;
|
||||||
|
const div_t dt = div(pi + ofs, 3);
|
||||||
|
n += snprintf (fmtbuf + n, 16 - n, "%g%s", ::pow (10.0, fp + double (dt.rem)), multipliers [dt.quot]);
|
||||||
|
}
|
||||||
|
return fmtbuf;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
};
|
||||||
|
static Canvas canvas;
|
||||||
|
void resizeCanvas (int x, int y) {
|
||||||
|
printf("resizeCanvas: x=%d, y=%d\n", x, y);
|
||||||
|
canvas.width = x;
|
||||||
|
canvas.height = y;
|
||||||
|
}
|
||||||
|
void emitData (double * x, double * y, const int len) {
|
||||||
|
double ymin = 1.0e100, ymax = -1.0e100;
|
||||||
|
for (int n=0; n<len; n++) {
|
||||||
|
if (y[n] < ymin) ymin = y[n];
|
||||||
|
if (y[n] > ymax) ymax = y[n];
|
||||||
|
// printf("f(%g) = %g\n", x[n], y[n]);
|
||||||
|
}
|
||||||
|
const double xmin = x[0];
|
||||||
|
const double xmax = x[len - 1];
|
||||||
|
printf("xmin = %g, xmax = %g, ymin = %g, ymax = %g\n", xmin, xmax, ymin, ymax);
|
||||||
|
const double f = 1.0;
|
||||||
|
ymin *= f;
|
||||||
|
ymax *= f;
|
||||||
|
canvas.xofset = xmin;
|
||||||
|
canvas.yofset = ymin;
|
||||||
|
canvas.xscale = canvas.width / (xmax - xmin);
|
||||||
|
canvas.yscale = canvas.height / (ymax - ymin);
|
||||||
|
Stepping sx (xmin, xmax), sy (ymin, ymax);
|
||||||
|
// sx.f(); sy.f();
|
||||||
|
|
||||||
|
float * ix = new float [len]; // float32 stačí
|
||||||
|
float * iy = new float [len];
|
||||||
|
for (int n=0; n<len; n++) {
|
||||||
|
ix[n] = canvas.xt (x[n]); // přepočteno na velikost canvasu
|
||||||
|
iy[n] = canvas.yt (y[n]);
|
||||||
|
// printf("f(%d) = %d\n", ix[n], iy[n]);
|
||||||
|
}
|
||||||
|
const int json_max = 0x8000; // string bude poměrně dlouhý
|
||||||
|
char * json = new char [json_max];
|
||||||
|
int n = 0;
|
||||||
|
const uint32_t xColor = 0xffff00;
|
||||||
|
const uint32_t yColor = 0x00ffff;
|
||||||
|
const double wd = 4.0; // šířka čárky na osách v px
|
||||||
|
const double pos0x = canvas.xt(0.0) > 0 and canvas.xt(0.0) < canvas.width ? canvas.xt(0.0) : 0.0;
|
||||||
|
const double pos0y = canvas.yt(0.0) > 0 and canvas.yt(0.0) < canvas.height ? canvas.yt(0.0) : canvas.height;
|
||||||
|
n += snprintf(json + n, json_max - n, "{ \"name\":\"axes\", ");
|
||||||
|
n += snprintf(json + n, json_max - n, "\"x\":{ \"color\":\"#%06X\", \"w\":%d, ", xColor, 2);
|
||||||
|
n += snprintf(json + n, json_max - n, "\"b\": [%g,%g], ", 0.0, pos0y);
|
||||||
|
n += snprintf(json + n, json_max - n, "\"e\": [%g,%g] }, ", canvas.width, pos0y);
|
||||||
|
n += snprintf(json + n, json_max - n, "\"y\": { \"color\":\"#%06X\", \"w\":%d, ", yColor, 2);
|
||||||
|
n += snprintf(json + n, json_max - n, "\"b\": [%g,%g], ", pos0x, 0.0);
|
||||||
|
n += snprintf(json + n, json_max - n, "\"e\": [%g,%g] }, \"xdots\": [", pos0x, canvas.height);
|
||||||
|
for (double dx=sx.b; dx<sx.e; dx+=sx.s) {
|
||||||
|
n += snprintf(json + n, json_max - n, "{ \"color\":\"#%06X\", \"w\":%d, \"lbl\":\"%s\", ", xColor, 2, sx.ing(dx));
|
||||||
|
n += snprintf(json + n, json_max - n, "\"b\": [%g,%g], " , canvas.xt(dx), pos0y - wd);
|
||||||
|
n += snprintf(json + n, json_max - n, "\"e\": [%g,%g] }, ", canvas.xt(dx), pos0y + wd);
|
||||||
|
}
|
||||||
|
json [n-2] = ' '; // přepiš poslední čárku, jinak json nefunguje
|
||||||
|
n += snprintf(json + n, json_max - n, "], \"ydots\": [\n");
|
||||||
|
for (double dy=sy.b; dy<sy.e; dy+=sy.s) {
|
||||||
|
n += snprintf(json + n, json_max - n, "{ \"color\":\"#%06X\", \"w\":%d, \"lbl\":\"%s\", ", yColor, 2, sy.ing(dy));
|
||||||
|
n += snprintf(json + n, json_max - n, "\"b\": [%g,%g], " , pos0x - wd, canvas.yt(dy));
|
||||||
|
n += snprintf(json + n, json_max - n, "\"e\": [%g,%g] }, ", pos0x + wd, canvas.yt(dy));
|
||||||
|
}
|
||||||
|
json [n-2] = ' ';
|
||||||
|
n += snprintf(json + n, json_max - n, "] }\n");
|
||||||
|
// printf("%d\n", n);
|
||||||
|
/* Pro kreslení na canvas se používají 2 metody:
|
||||||
|
* 1. Přímé předání dat pomocí ukazatelů.
|
||||||
|
* Ukázalo se, že typ int nestačí, zaokrouhlení je kostrbaté, double je zbytečně velký,
|
||||||
|
* takže stačí float (32.bit), je to normováno na velikost canvas, takže tam nejsou skoky v řádech
|
||||||
|
* 2. Z dat uděláme JSON a ten zpracuje javascript. Není to moc efektivní, ale funguje.
|
||||||
|
* (3. zde nepoužito) Vytvoříme přímo javascript zdroják, který to celé vykreslí
|
||||||
|
* a ten pak spustíme v javascriptu pomocí eval(). Funguje také, ale je to divné.
|
||||||
|
* */
|
||||||
|
drawPoints (ix, iy, len, json, n);
|
||||||
|
delete [] ix; delete [] iy;
|
||||||
|
delete [] json;
|
||||||
|
}
|
20
wasm.mk
Normal file
20
wasm.mk
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
MAIN = wasm.o
|
||||||
|
MOBJS+=heap.o newdel.o
|
||||||
|
LD = wasm-ld-10
|
||||||
|
TARGET = --target=wasm32-unknown-unknown
|
||||||
|
PR = bin/module.wasm
|
||||||
|
# Cesta k newlib
|
||||||
|
LPATH = ${HOME}/local/wasm32-none-eabi
|
||||||
|
CFLAGS = -Wall -Oz -flto -I. -I$(LPATH)/include $(TARGET)
|
||||||
|
#CFLAGS+= --sysroot=${HOME}/local/wasm32-none-eabi
|
||||||
|
CFLAGS+= -ffunction-sections -fdata-sections
|
||||||
|
#CFLAGS+= -Wno-incompatible-library-redeclaration
|
||||||
|
# Pro clang by muselo ještě přibýt -nostartfiles $(TARGET) a LFLAGS by bylo -Wl,
|
||||||
|
LFLAGS = --no-entry --import-memory --lto-O3 --gc-sections
|
||||||
|
# vetsi stack znamena zvetsit i WebAssembly.Memory({ initial: n 64K block })
|
||||||
|
#LFLAGS+= -z stack-size=1048576
|
||||||
|
#LFLAGS+= --print-gc-sections
|
||||||
|
#LFLAGS+= --allow-undefined
|
||||||
|
LFLAGS+= --allow-undefined-file=symbols.txt
|
||||||
|
LDLIBS = -L$(LPATH)/lib -lc -lm
|
||||||
|
|
Loading…
Reference in a new issue