Compare commits
No commits in common. "2dae3f98e9b0b01a645364ee037b732fdf501920" and "63f9eb48a4d8dfe2627788ab7c510afb9096a7c7" have entirely different histories.
2dae3f98e9
...
63f9eb48a4
@ -1,13 +0,0 @@
|
|||||||
name: Build and Test
|
|
||||||
on: [push]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
- name: Build
|
|
||||||
run: make
|
|
||||||
- name: Test
|
|
||||||
run: make test
|
|
||||||
119
Makefile
119
Makefile
@ -1,6 +1,6 @@
|
|||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -Wall -Wextra -O2 -Isrc
|
CFLAGS = -Wall -Wextra -O2 -Isrc
|
||||||
LDFLAGS = -lm -lpthread
|
LDFLAGS = -lm
|
||||||
|
|
||||||
SRC_DIR = src
|
SRC_DIR = src
|
||||||
TEST_DIR = tests
|
TEST_DIR = tests
|
||||||
@ -16,8 +16,7 @@ SOURCES = $(SRC_DIR)/main.c \
|
|||||||
$(SRC_DIR)/parser.c \
|
$(SRC_DIR)/parser.c \
|
||||||
$(SRC_DIR)/interpreter.c \
|
$(SRC_DIR)/interpreter.c \
|
||||||
$(SRC_DIR)/native_functions.c \
|
$(SRC_DIR)/native_functions.c \
|
||||||
$(SRC_DIR)/string_utils.c \
|
$(SRC_DIR)/string_utils.c
|
||||||
$(SRC_DIR)/preprocessor.c
|
|
||||||
|
|
||||||
OBJECTS = $(SOURCES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
|
OBJECTS = $(SOURCES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
|
||||||
|
|
||||||
@ -26,25 +25,11 @@ TESTS = $(TEST_DIR)/feature_test.rc \
|
|||||||
$(TEST_DIR)/math_test.rc \
|
$(TEST_DIR)/math_test.rc \
|
||||||
$(TEST_DIR)/string_test.rc \
|
$(TEST_DIR)/string_test.rc \
|
||||||
$(TEST_DIR)/string_manip_test.rc \
|
$(TEST_DIR)/string_manip_test.rc \
|
||||||
$(TEST_DIR)/increment_decrement_test.rc \
|
$(TEST_DIR)/increment_decrement_test.rc
|
||||||
$(TEST_DIR)/file_io_test.rc \
|
|
||||||
$(TEST_DIR)/double_test.rc \
|
|
||||||
$(TEST_DIR)/break_continue_test.rc \
|
|
||||||
$(TEST_DIR)/async_io_test.rc \
|
|
||||||
$(TEST_DIR)/array_test.rc \
|
|
||||||
$(TEST_DIR)/pointer_test.rc \
|
|
||||||
$(TEST_DIR)/logical_test.rc \
|
|
||||||
$(TEST_DIR)/comparison_test.rc \
|
|
||||||
$(TEST_DIR)/functions_test.rc \
|
|
||||||
$(TEST_DIR)/trig_test.rc \
|
|
||||||
$(TEST_DIR)/file_seek_test.rc \
|
|
||||||
$(TEST_DIR)/include_test.rc \
|
|
||||||
$(TEST_DIR)/nested_include_test.rc
|
|
||||||
|
|
||||||
EXAMPLES = $(EXAMPLE_DIR)/http_simple.rc \
|
EXAMPLES = $(EXAMPLE_DIR)/http_simple.rc \
|
||||||
$(EXAMPLE_DIR)/http_persistent.rc \
|
$(EXAMPLE_DIR)/http_persistent.rc \
|
||||||
$(EXAMPLE_DIR)/http_multi.rc \
|
$(EXAMPLE_DIR)/http_multi.rc
|
||||||
$(EXAMPLE_DIR)/async_demo.rc
|
|
||||||
|
|
||||||
.PHONY: all clean test run-tests run-examples help
|
.PHONY: all clean test run-tests run-examples help
|
||||||
|
|
||||||
@ -83,45 +68,6 @@ test: $(TARGET)
|
|||||||
@echo "Running increment decrement tests..."
|
@echo "Running increment decrement tests..."
|
||||||
@$(TARGET) $(TEST_DIR)/increment_decrement_test.rc 2>&1 | grep -v "Error at token" || true
|
@$(TARGET) $(TEST_DIR)/increment_decrement_test.rc 2>&1 | grep -v "Error at token" || true
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "Running file I/O tests..."
|
|
||||||
@$(TARGET) $(TEST_DIR)/file_io_test.rc 2>&1 | grep -v "Error at token" || true
|
|
||||||
@echo ""
|
|
||||||
@echo "Running double tests..."
|
|
||||||
@$(TARGET) $(TEST_DIR)/double_test.rc 2>&1 | grep -v "Error at token" || true
|
|
||||||
@echo ""
|
|
||||||
@echo "Running break/continue tests..."
|
|
||||||
@$(TARGET) $(TEST_DIR)/break_continue_test.rc 2>&1 | grep -v "Error at token" || true
|
|
||||||
@echo ""
|
|
||||||
@echo "Running async I/O tests..."
|
|
||||||
@$(TARGET) $(TEST_DIR)/async_io_test.rc 2>&1 | grep -v "Error at token" || true
|
|
||||||
@echo ""
|
|
||||||
@echo "Running array tests..."
|
|
||||||
@$(TARGET) $(TEST_DIR)/array_test.rc 2>&1 | grep -v "Error at token" || true
|
|
||||||
@echo ""
|
|
||||||
@echo "Running pointer tests..."
|
|
||||||
@$(TARGET) $(TEST_DIR)/pointer_test.rc 2>&1 | grep -v "Error at token" || true
|
|
||||||
@echo ""
|
|
||||||
@echo "Running logical operators tests..."
|
|
||||||
@$(TARGET) $(TEST_DIR)/logical_test.rc 2>&1 | grep -v "Error at token" || true
|
|
||||||
@echo ""
|
|
||||||
@echo "Running comparison operators tests..."
|
|
||||||
@$(TARGET) $(TEST_DIR)/comparison_test.rc 2>&1 | grep -v "Error at token" || true
|
|
||||||
@echo ""
|
|
||||||
@echo "Running functions tests..."
|
|
||||||
@$(TARGET) $(TEST_DIR)/functions_test.rc 2>&1 | grep -v "Error at token" || true
|
|
||||||
@echo ""
|
|
||||||
@echo "Running trigonometry tests..."
|
|
||||||
@$(TARGET) $(TEST_DIR)/trig_test.rc 2>&1 | grep -v "Error at token" || true
|
|
||||||
@echo ""
|
|
||||||
@echo "Running file seek tests..."
|
|
||||||
@$(TARGET) $(TEST_DIR)/file_seek_test.rc 2>&1 | grep -v "Error at token" || true
|
|
||||||
@echo ""
|
|
||||||
@echo "Running include tests..."
|
|
||||||
@$(TARGET) $(TEST_DIR)/include_test.rc 2>&1 | grep -v "Error at token" || true
|
|
||||||
@echo ""
|
|
||||||
@echo "Running nested include tests..."
|
|
||||||
@$(TARGET) $(TEST_DIR)/nested_include_test.rc 2>&1 | grep -v "Error at token" || true
|
|
||||||
@echo ""
|
|
||||||
@echo "=== All Tests Completed ==="
|
@echo "=== All Tests Completed ==="
|
||||||
|
|
||||||
run-feature-test: $(TARGET)
|
run-feature-test: $(TARGET)
|
||||||
@ -142,45 +88,6 @@ run-string-manip: $(TARGET)
|
|||||||
run-increment-decrement-test: $(TARGET)
|
run-increment-decrement-test: $(TARGET)
|
||||||
$(TARGET) $(TEST_DIR)/increment_decrement_test.rc
|
$(TARGET) $(TEST_DIR)/increment_decrement_test.rc
|
||||||
|
|
||||||
run-file-io-test: $(TARGET)
|
|
||||||
$(TARGET) $(TEST_DIR)/file_io_test.rc
|
|
||||||
|
|
||||||
run-double-test: $(TARGET)
|
|
||||||
$(TARGET) $(TEST_DIR)/double_test.rc
|
|
||||||
|
|
||||||
run-break-continue-test: $(TARGET)
|
|
||||||
$(TARGET) $(TEST_DIR)/break_continue_test.rc
|
|
||||||
|
|
||||||
run-async-io-test: $(TARGET)
|
|
||||||
$(TARGET) $(TEST_DIR)/async_io_test.rc
|
|
||||||
|
|
||||||
run-array-test: $(TARGET)
|
|
||||||
$(TARGET) $(TEST_DIR)/array_test.rc
|
|
||||||
|
|
||||||
run-pointer-test: $(TARGET)
|
|
||||||
$(TARGET) $(TEST_DIR)/pointer_test.rc
|
|
||||||
|
|
||||||
run-logical-test: $(TARGET)
|
|
||||||
$(TARGET) $(TEST_DIR)/logical_test.rc
|
|
||||||
|
|
||||||
run-comparison-test: $(TARGET)
|
|
||||||
$(TARGET) $(TEST_DIR)/comparison_test.rc
|
|
||||||
|
|
||||||
run-functions-test: $(TARGET)
|
|
||||||
$(TARGET) $(TEST_DIR)/functions_test.rc
|
|
||||||
|
|
||||||
run-trig-test: $(TARGET)
|
|
||||||
$(TARGET) $(TEST_DIR)/trig_test.rc
|
|
||||||
|
|
||||||
run-file-seek-test: $(TARGET)
|
|
||||||
$(TARGET) $(TEST_DIR)/file_seek_test.rc
|
|
||||||
|
|
||||||
run-include-test: $(TARGET)
|
|
||||||
$(TARGET) $(TEST_DIR)/include_test.rc
|
|
||||||
|
|
||||||
run-nested-include-test: $(TARGET)
|
|
||||||
$(TARGET) $(TEST_DIR)/nested_include_test.rc
|
|
||||||
|
|
||||||
run-http-simple: $(TARGET)
|
run-http-simple: $(TARGET)
|
||||||
$(TARGET) $(EXAMPLE_DIR)/http_simple.rc
|
$(TARGET) $(EXAMPLE_DIR)/http_simple.rc
|
||||||
|
|
||||||
@ -190,9 +97,6 @@ run-http-persistent: $(TARGET)
|
|||||||
run-http-multi: $(TARGET)
|
run-http-multi: $(TARGET)
|
||||||
$(TARGET) $(EXAMPLE_DIR)/http_multi.rc
|
$(TARGET) $(EXAMPLE_DIR)/http_multi.rc
|
||||||
|
|
||||||
run-async-demo: $(TARGET)
|
|
||||||
$(TARGET) $(EXAMPLE_DIR)/async_demo.rc
|
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@echo "RC - Retoor's C Interpreter"
|
@echo "RC - Retoor's C Interpreter"
|
||||||
@echo ""
|
@echo ""
|
||||||
@ -207,26 +111,11 @@ help:
|
|||||||
@echo " make run-math-test - Run math_test.rc (math functions)"
|
@echo " make run-math-test - Run math_test.rc (math functions)"
|
||||||
@echo " make run-string-test - Run string_test.rc (string concatenation)"
|
@echo " make run-string-test - Run string_test.rc (string concatenation)"
|
||||||
@echo " make run-string-manip - Run string_manip_test.rc (string manipulation & slicing)"
|
@echo " make run-string-manip - Run string_manip_test.rc (string manipulation & slicing)"
|
||||||
@echo " make run-increment-decrement-test - Run increment_decrement_test.rc (++/--)"
|
|
||||||
@echo " make run-file-io-test - Run file_io_test.rc (file I/O operations)"
|
|
||||||
@echo " make run-double-test - Run double_test.rc (double data type)"
|
|
||||||
@echo " make run-break-continue-test - Run break_continue_test.rc (break/continue)"
|
|
||||||
@echo " make run-async-io-test - Run async_io_test.rc (async I/O)"
|
|
||||||
@echo " make run-array-test - Run array_test.rc (arrays)"
|
|
||||||
@echo " make run-pointer-test - Run pointer_test.rc (pointers & dereference)"
|
|
||||||
@echo " make run-logical-test - Run logical_test.rc (&&, ||)"
|
|
||||||
@echo " make run-comparison-test - Run comparison_test.rc (<, >, <=, >=)"
|
|
||||||
@echo " make run-functions-test - Run functions_test.rc (function calls & recursion)"
|
|
||||||
@echo " make run-trig-test - Run trig_test.rc (sin, cos, tan)"
|
|
||||||
@echo " make run-file-seek-test - Run file_seek_test.rc (fseek, ftell)"
|
|
||||||
@echo " make run-include-test - Run include_test.rc (#include directive)"
|
|
||||||
@echo " make run-nested-include-test - Run nested_include_test.rc (nested includes)"
|
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "Examples:"
|
@echo "Examples:"
|
||||||
@echo " make run-http-simple - Run http_simple.rc (single connection HTTP server)"
|
@echo " make run-http-simple - Run http_simple.rc (single connection HTTP server)"
|
||||||
@echo " make run-http-persistent - Run http_persistent.rc (persistent HTTP server)"
|
@echo " make run-http-persistent - Run http_persistent.rc (persistent HTTP server)"
|
||||||
@echo " make run-http-multi - Run http_multi.rc (HTTP server, 100 connections)"
|
@echo " make run-http-multi - Run http_multi.rc (HTTP server, 100 connections)"
|
||||||
@echo " make run-async-demo - Run async_demo.rc (comprehensive async I/O demo)"
|
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "Directory Structure:"
|
@echo "Directory Structure:"
|
||||||
@echo " src/ - Source code files"
|
@echo " src/ - Source code files"
|
||||||
|
|||||||
34
README.md
34
README.md
@ -8,7 +8,6 @@ RC is a lightweight, recursive-descent C interpreter written in C. It executes a
|
|||||||
|
|
||||||
**Data Types**
|
**Data Types**
|
||||||
- Integers (long)
|
- Integers (long)
|
||||||
- Doubles (floating-point numbers)
|
|
||||||
- Character pointers (char*)
|
- Character pointers (char*)
|
||||||
- Pointer operations (address-of &, dereference *)
|
- Pointer operations (address-of &, dereference *)
|
||||||
- Array declarations and indexing
|
- Array declarations and indexing
|
||||||
@ -16,7 +15,6 @@ RC is a lightweight, recursive-descent C interpreter written in C. It executes a
|
|||||||
**Control Flow**
|
**Control Flow**
|
||||||
- if/else statements
|
- if/else statements
|
||||||
- while loops (including infinite loops)
|
- while loops (including infinite loops)
|
||||||
- break and continue statements
|
|
||||||
- Comparison operators: ==, !=, <, >, <=, >=
|
- Comparison operators: ==, !=, <, >, <=, >=
|
||||||
- Logical operators: &&, ||
|
- Logical operators: &&, ||
|
||||||
|
|
||||||
@ -41,13 +39,6 @@ RC is a lightweight, recursive-descent C interpreter written in C. It executes a
|
|||||||
- sin(x), cos(x), tan(x) - Trigonometric functions
|
- sin(x), cos(x), tan(x) - Trigonometric functions
|
||||||
- floor(x), ceil(x) - Rounding functions
|
- floor(x), ceil(x) - Rounding functions
|
||||||
|
|
||||||
**Double Type Functions**
|
|
||||||
- int_to_double(i) - Convert int to double
|
|
||||||
- double_to_int(d) - Convert double to int
|
|
||||||
- double_add(a, b), double_sub(a, b) - Double arithmetic
|
|
||||||
- double_mul(a, b), double_div(a, b) - Double arithmetic
|
|
||||||
- printf with %f format for doubles
|
|
||||||
|
|
||||||
**String Functions**
|
**String Functions**
|
||||||
- strpos(haystack, needle) - Find substring position
|
- strpos(haystack, needle) - Find substring position
|
||||||
- substr(str, start, length) - Extract substring
|
- substr(str, start, length) - Extract substring
|
||||||
@ -58,27 +49,6 @@ RC is a lightweight, recursive-descent C interpreter written in C. It executes a
|
|||||||
- endswith(str, suffix) - Suffix check
|
- endswith(str, suffix) - Suffix check
|
||||||
- strlen(str) - String length
|
- strlen(str) - String length
|
||||||
|
|
||||||
**File I/O**
|
|
||||||
- fopen(filename, mode) - Open a file
|
|
||||||
- fclose(file) - Close a file
|
|
||||||
- fread(file, buffer, size) - Read from file
|
|
||||||
- fwrite(file, buffer, size) - Write to file
|
|
||||||
- fgets(file, max_size) - Read a line
|
|
||||||
- fputs(file, string) - Write a string
|
|
||||||
- feof(file) - Check end of file
|
|
||||||
- ftell(file), fseek(file, offset, whence) - File positioning
|
|
||||||
- fremove(filename), frename(old, new) - File operations
|
|
||||||
- SEEK_SET, SEEK_CUR, SEEK_END constants
|
|
||||||
|
|
||||||
**Async I/O (Multi-threaded)**
|
|
||||||
- async_fread(file, buffer, size) - Async file read
|
|
||||||
- async_fwrite(file, buffer, size) - Async file write
|
|
||||||
- async_recv(socket, buffer, len, flags) - Async socket receive
|
|
||||||
- async_send(socket, buffer, len, flags) - Async socket send
|
|
||||||
- async_wait(handle) - Wait for async operation to complete
|
|
||||||
- async_poll(handle) - Check if async operation is complete
|
|
||||||
- async_result(handle) - Get result of completed async operation
|
|
||||||
|
|
||||||
**Socket Programming**
|
**Socket Programming**
|
||||||
- socket(), bind(), listen(), accept()
|
- socket(), bind(), listen(), accept()
|
||||||
- send(), recv(), close()
|
- send(), recv(), close()
|
||||||
@ -199,12 +169,10 @@ Extensible system for binding C functions. Current bindings include math operati
|
|||||||
|
|
||||||
- Memory model uses long cells (not byte-accurate)
|
- Memory model uses long cells (not byte-accurate)
|
||||||
- No support for structs, unions, or enums as user types
|
- No support for structs, unions, or enums as user types
|
||||||
- Limited type system (int, double, and char*)
|
- Limited type system (int and char* only)
|
||||||
- Double arithmetic requires explicit helper functions
|
|
||||||
- No preprocessor directives
|
- No preprocessor directives
|
||||||
- Error messages show token index rather than line/column
|
- Error messages show token index rather than line/column
|
||||||
- Pointer arithmetic works on virtual memory addresses
|
- Pointer arithmetic works on virtual memory addresses
|
||||||
- Maximum 100 concurrent async operations
|
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
|
|||||||
20
TODO2.md
20
TODO2.md
@ -1,20 +0,0 @@
|
|||||||
# TO BUILD
|
|
||||||
|
|
||||||
1. Read the whole source code in src.
|
|
||||||
2. Add File I/O Functions to the scripting language
|
|
||||||
2.1 Add working tests within the tests directory.
|
|
||||||
3. Implement async I/O functions for File I/O / Socket I/O / Async I/O. The basic asyncio for methods should be we working using threads so it's a multicore application. It must be a safe way of threading but still performance.
|
|
||||||
3.1 Add working tests within the tests directory.
|
|
||||||
3.2 Add a nice example script source file (.rc) to the examples directory that shows file I/O, async I/O, and socket I/O.
|
|
||||||
4. Add double data type to the language
|
|
||||||
4.1 Add working tests within the tests directory.
|
|
||||||
5. Implement break and continue statements in the language
|
|
||||||
5.1 Add working tests within the tests directory.
|
|
||||||
6. Update Makefile, README.md, and TUTORIAL.md.
|
|
||||||
|
|
||||||
# IMPORTANT
|
|
||||||
1. Consistency (By researching how other things are implemented)
|
|
||||||
2. Performance (But readability is also important)
|
|
||||||
3. Ease of use for the user of the new language (No weird caveats)
|
|
||||||
4. Safety (for using the langauge by defensive coding)
|
|
||||||
|
|
||||||
171
TUTORIAL.md
171
TUTORIAL.md
@ -986,174 +986,3 @@ int main() {
|
|||||||
---
|
---
|
||||||
|
|
||||||
For more examples, see the `tests/` and `examples/` directories in the RC repository.
|
For more examples, see the `tests/` and `examples/` directories in the RC repository.
|
||||||
|
|
||||||
## File I/O
|
|
||||||
|
|
||||||
### Writing to a File
|
|
||||||
|
|
||||||
```c
|
|
||||||
int main() {
|
|
||||||
int f = fopen("output.txt", "w");
|
|
||||||
fputs(f, "Hello, File!\n");
|
|
||||||
fputs(f, "Second line\n");
|
|
||||||
fclose(f);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Reading from a File
|
|
||||||
|
|
||||||
```c
|
|
||||||
int main() {
|
|
||||||
int f = fopen("output.txt", "r");
|
|
||||||
char *line = fgets(f, 256);
|
|
||||||
while (strlen(line) > 0 && feof(f) == 0) {
|
|
||||||
printf("%s", line);
|
|
||||||
line = fgets(f, 256);
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Double Data Type
|
|
||||||
|
|
||||||
### Using Doubles
|
|
||||||
|
|
||||||
```c
|
|
||||||
int main() {
|
|
||||||
double pi = 3.14159;
|
|
||||||
double radius = 5.0;
|
|
||||||
|
|
||||||
printf("Pi: %f\n", pi);
|
|
||||||
printf("Radius: %f\n", radius);
|
|
||||||
|
|
||||||
double area = double_mul(pi, double_mul(radius, radius));
|
|
||||||
printf("Circle area: %f\n", area);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Type Conversions
|
|
||||||
|
|
||||||
```c
|
|
||||||
int main() {
|
|
||||||
int x = 42;
|
|
||||||
double dx = int_to_double(x);
|
|
||||||
printf("Int %d as double: %f\n", x, dx);
|
|
||||||
|
|
||||||
double y = 99.9;
|
|
||||||
int iy = double_to_int(y);
|
|
||||||
printf("Double %f as int: %d\n", y, iy);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Break and Continue
|
|
||||||
|
|
||||||
### Break Statement
|
|
||||||
|
|
||||||
```c
|
|
||||||
int main() {
|
|
||||||
int i = 0;
|
|
||||||
while (i < 10) {
|
|
||||||
i = i + 1;
|
|
||||||
if (i == 5) {
|
|
||||||
printf("Breaking at %d\n", i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("%d ", i);
|
|
||||||
}
|
|
||||||
printf("\nDone\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Continue Statement
|
|
||||||
|
|
||||||
```c
|
|
||||||
int main() {
|
|
||||||
int i = 0;
|
|
||||||
while (i < 10) {
|
|
||||||
i = i + 1;
|
|
||||||
if (i == 3 || i == 7) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
printf("%d ", i);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Async I/O
|
|
||||||
|
|
||||||
### Async File Operations
|
|
||||||
|
|
||||||
```c
|
|
||||||
int main() {
|
|
||||||
int f = fopen("async_file.txt", "w");
|
|
||||||
|
|
||||||
int write_handle = async_fwrite(f, "Async write!", 12);
|
|
||||||
printf("Write started, handle: %d\n", write_handle);
|
|
||||||
|
|
||||||
int result = async_wait(write_handle);
|
|
||||||
printf("Write completed, bytes: %d\n", result);
|
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Polling for Completion
|
|
||||||
|
|
||||||
```c
|
|
||||||
int main() {
|
|
||||||
int f = fopen("data.txt", "r");
|
|
||||||
int buffer[1024];
|
|
||||||
|
|
||||||
int read_handle = async_fread(f, &buffer, 1024);
|
|
||||||
|
|
||||||
printf("Reading asynchronously...\n");
|
|
||||||
while (async_poll(read_handle) == 0) {
|
|
||||||
printf(".");
|
|
||||||
}
|
|
||||||
printf("\nRead complete!\n");
|
|
||||||
|
|
||||||
int bytes = async_result(read_handle);
|
|
||||||
printf("Bytes read: %d\n", bytes);
|
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Async Socket I/O
|
|
||||||
|
|
||||||
```c
|
|
||||||
int main() {
|
|
||||||
int server = socket(AF_INET(), SOCK_STREAM(), 0);
|
|
||||||
bind(server, 8080);
|
|
||||||
listen(server, 5);
|
|
||||||
|
|
||||||
int client = accept(server);
|
|
||||||
|
|
||||||
int buffer[1024];
|
|
||||||
int recv_handle = async_recv(client, &buffer, 1024, 0);
|
|
||||||
|
|
||||||
printf("Async receive started...\n");
|
|
||||||
int bytes = async_wait(recv_handle);
|
|
||||||
printf("Received %d bytes\n", bytes);
|
|
||||||
|
|
||||||
char *response = "HTTP/1.1 200 OK\r\n\r\nOK";
|
|
||||||
int send_handle = async_send(client, response, strlen(response), 0);
|
|
||||||
async_wait(send_handle);
|
|
||||||
|
|
||||||
close(client);
|
|
||||||
close(server);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|||||||
@ -1,86 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("=== Async I/O Demo: File I/O + Async I/O + Socket I/O ===\n\n");
|
|
||||||
|
|
||||||
printf("Step 1: Synchronous File I/O\n");
|
|
||||||
int log_file = fopen("demo_log.txt", "w");
|
|
||||||
fputs(log_file, "Server Log Started\n");
|
|
||||||
fclose(log_file);
|
|
||||||
printf("Created log file\n\n");
|
|
||||||
|
|
||||||
printf("Step 2: Async File Operations\n");
|
|
||||||
log_file = fopen("demo_log.txt", "a");
|
|
||||||
int write_op1 = async_fwrite(log_file, "Initializing server...\n", 24);
|
|
||||||
int write_op2 = async_fwrite(log_file, "Binding to port 8080...\n", 25);
|
|
||||||
|
|
||||||
printf("Multiple async writes queued\n");
|
|
||||||
async_wait(write_op1);
|
|
||||||
async_wait(write_op2);
|
|
||||||
printf("All async writes completed\n\n");
|
|
||||||
|
|
||||||
printf("Step 3: Socket Server Setup\n");
|
|
||||||
int server_socket = socket(AF_INET(), SOCK_STREAM(), 0);
|
|
||||||
if (server_socket < 0) {
|
|
||||||
printf("ERROR: Could not create socket\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
printf("Socket created: %d\n", server_socket);
|
|
||||||
|
|
||||||
int bind_result = bind(server_socket, 8080);
|
|
||||||
if (bind_result < 0) {
|
|
||||||
printf("ERROR: Could not bind to port\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
printf("Bound to port 8080\n");
|
|
||||||
|
|
||||||
listen(server_socket, 5);
|
|
||||||
printf("Listening for connections...\n\n");
|
|
||||||
|
|
||||||
printf("Step 4: Log async write while waiting for connection\n");
|
|
||||||
int log_op = async_fwrite(log_file, "Waiting for client...\n", 23);
|
|
||||||
|
|
||||||
printf("Accepting client (this will wait for a connection)\n");
|
|
||||||
printf("In another terminal, run: curl http://localhost:8080/\n\n");
|
|
||||||
|
|
||||||
int client = accept(server_socket);
|
|
||||||
async_wait(log_op);
|
|
||||||
printf("Client connected: %d\n\n", client);
|
|
||||||
|
|
||||||
printf("Step 5: Handle client with async socket I/O\n");
|
|
||||||
int buffer[1024];
|
|
||||||
int recv_op = async_recv(client, &buffer, 1024, 0);
|
|
||||||
|
|
||||||
printf("Async receive started...\n");
|
|
||||||
while (async_poll(recv_op) == 0) {
|
|
||||||
printf(".");
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
int bytes = async_result(recv_op);
|
|
||||||
printf("Received %d bytes\n", bytes);
|
|
||||||
|
|
||||||
char *response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nAsync I/O Demo Success!\n";
|
|
||||||
int send_op = async_send(client, response, strlen(response), 0);
|
|
||||||
async_wait(send_op);
|
|
||||||
printf("Response sent asynchronously\n\n");
|
|
||||||
|
|
||||||
printf("Step 6: Final log entry\n");
|
|
||||||
int final_log = async_fwrite(log_file, "Client served successfully\n", 28);
|
|
||||||
async_wait(final_log);
|
|
||||||
|
|
||||||
close(client);
|
|
||||||
close(server_socket);
|
|
||||||
fclose(log_file);
|
|
||||||
|
|
||||||
printf("\nStep 7: Read log file\n");
|
|
||||||
log_file = fopen("demo_log.txt", "r");
|
|
||||||
char *line = fgets(log_file, 256);
|
|
||||||
while (strlen(line) > 0 && feof(log_file) == 0) {
|
|
||||||
printf("LOG: %s", line);
|
|
||||||
line = fgets(log_file, 256);
|
|
||||||
}
|
|
||||||
fclose(log_file);
|
|
||||||
|
|
||||||
printf("\n=== Demo Complete ===\n");
|
|
||||||
printf("Demonstrated: Sync File I/O, Async File I/O, Socket I/O, and Async Socket I/O\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -16,4 +16,3 @@ char *src_code;
|
|||||||
char str_pool[STR_POOL_SIZE];
|
char str_pool[STR_POOL_SIZE];
|
||||||
int str_pool_idx = 0;
|
int str_pool_idx = 0;
|
||||||
long ax = 0;
|
long ax = 0;
|
||||||
int return_flag = 0;
|
|
||||||
|
|||||||
@ -73,20 +73,11 @@ void statement() {
|
|||||||
pc++;
|
pc++;
|
||||||
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != '}' && tokens[pc].type != 0) {
|
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != '}' && tokens[pc].type != 0) {
|
||||||
statement();
|
statement();
|
||||||
if (return_flag || ax == -998 || ax == -997) {
|
if (ax == -999) break;
|
||||||
int brace = 1;
|
|
||||||
while (brace > 0 && pc < MAX_TOK && pc < tk_idx && tokens[pc].type != 0) {
|
|
||||||
if (tokens[pc].type == '{') brace++;
|
|
||||||
if (tokens[pc].type == '}') brace--;
|
|
||||||
pc++;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
match('}');
|
match('}');
|
||||||
}
|
}
|
||||||
else if (tokens[pc].type == Int || tokens[pc].type == Char || tokens[pc].type == Double) {
|
else if (tokens[pc].type == Int || tokens[pc].type == Char) {
|
||||||
int var_type = tokens[pc].type;
|
|
||||||
pc++;
|
pc++;
|
||||||
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') {
|
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') {
|
||||||
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '*') pc++;
|
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '*') pc++;
|
||||||
@ -103,7 +94,6 @@ void statement() {
|
|||||||
int addr = sp;
|
int addr = sp;
|
||||||
Symbol *s = &locals[loc_cnt++];
|
Symbol *s = &locals[loc_cnt++];
|
||||||
strncpy(s->name, t->text, t->val); s->name[t->val] = 0;
|
strncpy(s->name, t->text, t->val); s->name[t->val] = 0;
|
||||||
s->type = var_type;
|
|
||||||
s->addr = addr;
|
s->addr = addr;
|
||||||
s->is_array = 0;
|
s->is_array = 0;
|
||||||
|
|
||||||
@ -139,45 +129,42 @@ void statement() {
|
|||||||
match(')');
|
match(')');
|
||||||
if (cond) {
|
if (cond) {
|
||||||
statement();
|
statement();
|
||||||
if (return_flag || ax == -998 || ax == -997) return;
|
if (ax == -999) return;
|
||||||
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) { pc++; skip_block(); }
|
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) { pc++; skip_block(); }
|
||||||
} else {
|
} else {
|
||||||
skip_block();
|
skip_block();
|
||||||
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) {
|
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) {
|
||||||
pc++;
|
pc++;
|
||||||
statement();
|
statement();
|
||||||
if (return_flag || ax == -998 || ax == -997) return;
|
if (ax == -999) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tokens[pc].type == While) {
|
else if (tokens[pc].type == While) {
|
||||||
pc++;
|
pc++;
|
||||||
int loop_start = pc;
|
int loop_start = pc;
|
||||||
int body_start;
|
|
||||||
int iteration_count = 0;
|
|
||||||
while (1) {
|
|
||||||
if (++iteration_count > 1000000) {
|
|
||||||
error("Potential infinite loop detected");
|
|
||||||
}
|
|
||||||
pc = loop_start;
|
|
||||||
match('(');
|
match('(');
|
||||||
long cond = expression();
|
long cond = expression();
|
||||||
match(')');
|
match(')');
|
||||||
if (!cond) {
|
if (!cond) {
|
||||||
skip_block();
|
skip_block();
|
||||||
break;
|
} else {
|
||||||
|
int iteration_count = 0;
|
||||||
|
while (1) {
|
||||||
|
if (++iteration_count > 1000000) {
|
||||||
|
error("Potential infinite loop detected");
|
||||||
}
|
}
|
||||||
body_start = pc;
|
|
||||||
statement();
|
statement();
|
||||||
if (return_flag) return;
|
if (ax == -999) return;
|
||||||
if (ax == -998) {
|
int save_pc = pc;
|
||||||
ax = 0;
|
if (loop_start >= MAX_TOK || loop_start >= tk_idx) {
|
||||||
pc = body_start;
|
error("Loop start out of bounds");
|
||||||
skip_block();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (ax == -997) {
|
pc = loop_start;
|
||||||
ax = 0;
|
match('(');
|
||||||
|
cond = expression();
|
||||||
|
match(')');
|
||||||
|
if (!cond) { pc = save_pc; break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,17 +173,7 @@ void statement() {
|
|||||||
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') ax = expression();
|
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') ax = expression();
|
||||||
else ax = 0;
|
else ax = 0;
|
||||||
match(';');
|
match(';');
|
||||||
return_flag = 1;
|
ax = -999;
|
||||||
}
|
|
||||||
else if (tokens[pc].type == Break) {
|
|
||||||
pc++;
|
|
||||||
match(';');
|
|
||||||
ax = -998;
|
|
||||||
}
|
|
||||||
else if (tokens[pc].type == Continue) {
|
|
||||||
pc++;
|
|
||||||
match(';');
|
|
||||||
ax = -997;
|
|
||||||
}
|
}
|
||||||
else if (tokens[pc].type == Printf) {
|
else if (tokens[pc].type == Printf) {
|
||||||
pc++;
|
pc++;
|
||||||
@ -210,16 +187,11 @@ void statement() {
|
|||||||
|
|
||||||
char *p = fmt;
|
char *p = fmt;
|
||||||
while (*p) {
|
while (*p) {
|
||||||
if (*p == '%' && (p[1] == 'd' || p[1] == 's' || p[1] == 'f')) {
|
if (*p == '%' && (p[1] == 'd' || p[1] == 's')) {
|
||||||
p++;
|
p++;
|
||||||
match(',');
|
match(',');
|
||||||
long val = expression();
|
long val = expression();
|
||||||
if (*p == 'd') printf("%ld", val);
|
if (*p == 'd') printf("%ld", val);
|
||||||
else if (*p == 'f') {
|
|
||||||
union { double d; long l; } u;
|
|
||||||
u.l = val;
|
|
||||||
printf("%f", u.d);
|
|
||||||
}
|
|
||||||
else if (*p == 's') {
|
else if (*p == 's') {
|
||||||
char *str = (char*)val;
|
char *str = (char*)val;
|
||||||
if (str) printf("%s", str);
|
if (str) printf("%s", str);
|
||||||
@ -242,7 +214,7 @@ void scan_functions() {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < MAX_TOK && i < tk_idx && tokens[i].type != 0) {
|
while (i < MAX_TOK && i < tk_idx && tokens[i].type != 0) {
|
||||||
if (i + 2 < MAX_TOK && i + 2 < tk_idx &&
|
if (i + 2 < MAX_TOK && i + 2 < tk_idx &&
|
||||||
(tokens[i].type == Int || tokens[i].type == Char || tokens[i].type == Double) &&
|
(tokens[i].type == Int || tokens[i].type == Char) &&
|
||||||
tokens[i+1].type == Id && tokens[i+2].type == '(') {
|
tokens[i+1].type == Id && tokens[i+2].type == '(') {
|
||||||
|
|
||||||
if (func_cnt >= 100) {
|
if (func_cnt >= 100) {
|
||||||
@ -253,10 +225,9 @@ void scan_functions() {
|
|||||||
strncpy(f->name, name->text, name->val); f->name[name->val] = 0;
|
strncpy(f->name, name->text, name->val); f->name[name->val] = 0;
|
||||||
|
|
||||||
i += 3;
|
i += 3;
|
||||||
f->params_start = i;
|
|
||||||
int params = 0;
|
int params = 0;
|
||||||
while(i < MAX_TOK && i < tk_idx && tokens[i].type != ')') {
|
while(i < MAX_TOK && i < tk_idx && tokens[i].type != ')') {
|
||||||
if (tokens[i].type == Int || tokens[i].type == Char || tokens[i].type == Double) {
|
if (tokens[i].type == Int || tokens[i].type == Char) {
|
||||||
params++;
|
params++;
|
||||||
i++;
|
i++;
|
||||||
while (i < MAX_TOK && i < tk_idx && tokens[i].type == '*') i++;
|
while (i < MAX_TOK && i < tk_idx && tokens[i].type == '*') i++;
|
||||||
|
|||||||
30
src/main.c
30
src/main.c
@ -1,12 +1,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <libgen.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "tokenizer.h"
|
#include "tokenizer.h"
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
#include "native_functions.h"
|
#include "native_functions.h"
|
||||||
#include "preprocessor.h"
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
@ -14,21 +11,24 @@ int main(int argc, char **argv) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char file_path[512];
|
FILE *f = fopen(argv[1], "rb");
|
||||||
strncpy(file_path, argv[1], 511);
|
if (!f) {
|
||||||
file_path[511] = 0;
|
printf("Could not open file.\n");
|
||||||
|
|
||||||
char dir_path[512];
|
|
||||||
strncpy(dir_path, argv[1], 511);
|
|
||||||
dir_path[511] = 0;
|
|
||||||
char *dir = dirname(dir_path);
|
|
||||||
|
|
||||||
src_code = preprocess(file_path, dir);
|
|
||||||
if (!src_code) {
|
|
||||||
printf("Preprocessing failed.\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
src_code = malloc(MAX_SRC + 1);
|
||||||
|
if (!src_code) {
|
||||||
|
printf("Memory allocation failed.\n");
|
||||||
|
fclose(f);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t n = fread(src_code, 1, MAX_SRC, f);
|
||||||
|
if (n >= MAX_SRC) n = MAX_SRC - 1;
|
||||||
|
src_code[n] = 0;
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
register_native_functions();
|
register_native_functions();
|
||||||
|
|
||||||
tokenize(src_code);
|
tokenize(src_code);
|
||||||
|
|||||||
@ -7,193 +7,10 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <pthread.h>
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "native_functions.h"
|
#include "native_functions.h"
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
#define MAX_ASYNC_OPS 100
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int active;
|
|
||||||
int complete;
|
|
||||||
long result;
|
|
||||||
pthread_t thread;
|
|
||||||
void *data;
|
|
||||||
} AsyncOp;
|
|
||||||
|
|
||||||
static AsyncOp async_ops[MAX_ASYNC_OPS];
|
|
||||||
static pthread_mutex_t async_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
static int async_initialized = 0;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
FILE *f;
|
|
||||||
int addr;
|
|
||||||
int size;
|
|
||||||
} AsyncFileReadData;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
FILE *f;
|
|
||||||
long buf_arg;
|
|
||||||
int size;
|
|
||||||
} AsyncFileWriteData;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int sockfd;
|
|
||||||
int addr;
|
|
||||||
int len;
|
|
||||||
int flags;
|
|
||||||
} AsyncRecvData;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int sockfd;
|
|
||||||
long buf_arg;
|
|
||||||
int len;
|
|
||||||
int flags;
|
|
||||||
} AsyncSendData;
|
|
||||||
|
|
||||||
void init_async() {
|
|
||||||
if (!async_initialized) {
|
|
||||||
for (int i = 0; i < MAX_ASYNC_OPS; i++) {
|
|
||||||
async_ops[i].active = 0;
|
|
||||||
async_ops[i].complete = 0;
|
|
||||||
async_ops[i].result = 0;
|
|
||||||
async_ops[i].data = NULL;
|
|
||||||
}
|
|
||||||
async_initialized = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int alloc_async_op() {
|
|
||||||
init_async();
|
|
||||||
pthread_mutex_lock(&async_mutex);
|
|
||||||
for (int i = 0; i < MAX_ASYNC_OPS; i++) {
|
|
||||||
if (!async_ops[i].active) {
|
|
||||||
async_ops[i].active = 1;
|
|
||||||
async_ops[i].complete = 0;
|
|
||||||
async_ops[i].result = 0;
|
|
||||||
pthread_mutex_unlock(&async_mutex);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&async_mutex);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* async_fread_thread(void *arg) {
|
|
||||||
int id = *(int*)arg;
|
|
||||||
free(arg);
|
|
||||||
AsyncFileReadData *data = (AsyncFileReadData*)async_ops[id].data;
|
|
||||||
|
|
||||||
char temp_buf[8192];
|
|
||||||
int size = data->size;
|
|
||||||
if (size > 8192) size = 8192;
|
|
||||||
|
|
||||||
int result = fread(temp_buf, 1, size, data->f);
|
|
||||||
if (result > 0) {
|
|
||||||
for (int i = 0; i < result && data->addr + i < MEM_SIZE; i++) {
|
|
||||||
memory[data->addr + i] = temp_buf[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&async_mutex);
|
|
||||||
async_ops[id].result = result;
|
|
||||||
async_ops[id].complete = 1;
|
|
||||||
pthread_mutex_unlock(&async_mutex);
|
|
||||||
|
|
||||||
free(data);
|
|
||||||
async_ops[id].data = NULL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* async_fwrite_thread(void *arg) {
|
|
||||||
int id = *(int*)arg;
|
|
||||||
free(arg);
|
|
||||||
AsyncFileWriteData *data = (AsyncFileWriteData*)async_ops[id].data;
|
|
||||||
|
|
||||||
long result = -1;
|
|
||||||
if (data->buf_arg > MEM_SIZE * 8 || data->buf_arg < 0) {
|
|
||||||
result = fwrite((char*)data->buf_arg, 1, data->size, data->f);
|
|
||||||
} else if (data->buf_arg < MEM_SIZE) {
|
|
||||||
char temp_buf[8192];
|
|
||||||
int size = data->size;
|
|
||||||
if (size > 8192) size = 8192;
|
|
||||||
if (data->buf_arg + size > MEM_SIZE) {
|
|
||||||
size = MEM_SIZE - data->buf_arg;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
temp_buf[i] = (char)memory[data->buf_arg + i];
|
|
||||||
}
|
|
||||||
result = fwrite(temp_buf, 1, size, data->f);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&async_mutex);
|
|
||||||
async_ops[id].result = result;
|
|
||||||
async_ops[id].complete = 1;
|
|
||||||
pthread_mutex_unlock(&async_mutex);
|
|
||||||
|
|
||||||
free(data);
|
|
||||||
async_ops[id].data = NULL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* async_recv_thread(void *arg) {
|
|
||||||
int id = *(int*)arg;
|
|
||||||
free(arg);
|
|
||||||
AsyncRecvData *data = (AsyncRecvData*)async_ops[id].data;
|
|
||||||
|
|
||||||
char temp_buf[8192];
|
|
||||||
int len = data->len;
|
|
||||||
if (len > 8192) len = 8192;
|
|
||||||
|
|
||||||
int result = recv(data->sockfd, temp_buf, len, data->flags);
|
|
||||||
if (result > 0) {
|
|
||||||
for (int i = 0; i < result && data->addr + i < MEM_SIZE; i++) {
|
|
||||||
memory[data->addr + i] = temp_buf[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&async_mutex);
|
|
||||||
async_ops[id].result = result;
|
|
||||||
async_ops[id].complete = 1;
|
|
||||||
pthread_mutex_unlock(&async_mutex);
|
|
||||||
|
|
||||||
free(data);
|
|
||||||
async_ops[id].data = NULL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* async_send_thread(void *arg) {
|
|
||||||
int id = *(int*)arg;
|
|
||||||
free(arg);
|
|
||||||
AsyncSendData *data = (AsyncSendData*)async_ops[id].data;
|
|
||||||
|
|
||||||
long result = -1;
|
|
||||||
if (data->buf_arg > MEM_SIZE * 8 || data->buf_arg < 0) {
|
|
||||||
result = send(data->sockfd, (char*)data->buf_arg, data->len, data->flags);
|
|
||||||
} else if (data->buf_arg < MEM_SIZE) {
|
|
||||||
char temp_buf[8192];
|
|
||||||
int len = data->len;
|
|
||||||
if (len > 8192) len = 8192;
|
|
||||||
if (data->buf_arg + len > MEM_SIZE) {
|
|
||||||
len = MEM_SIZE - data->buf_arg;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
temp_buf[i] = (char)memory[data->buf_arg + i];
|
|
||||||
}
|
|
||||||
result = send(data->sockfd, temp_buf, len, data->flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&async_mutex);
|
|
||||||
async_ops[id].result = result;
|
|
||||||
async_ops[id].complete = 1;
|
|
||||||
pthread_mutex_unlock(&async_mutex);
|
|
||||||
|
|
||||||
free(data);
|
|
||||||
async_ops[id].data = NULL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void register_native_func(char *name, NativeFunc func) {
|
void register_native_func(char *name, NativeFunc func) {
|
||||||
if (!name || !func || native_func_cnt >= 100) {
|
if (!name || !func || native_func_cnt >= 100) {
|
||||||
return;
|
return;
|
||||||
@ -211,12 +28,7 @@ long native_socket(long *args, int argc) {
|
|||||||
int domain = (int)args[0];
|
int domain = (int)args[0];
|
||||||
int type = (int)args[1];
|
int type = (int)args[1];
|
||||||
int protocol = (int)args[2];
|
int protocol = (int)args[2];
|
||||||
int sockfd = socket(domain, type, protocol);
|
return socket(domain, type, protocol);
|
||||||
if (sockfd >= 0) {
|
|
||||||
int opt = 1;
|
|
||||||
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
|
||||||
}
|
|
||||||
return sockfd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long native_bind(long *args, int argc) {
|
long native_bind(long *args, int argc) {
|
||||||
@ -636,405 +448,6 @@ long native_endswith(long *args, int argc) {
|
|||||||
return strcmp(str + str_len - suffix_len, suffix) == 0;
|
return strcmp(str + str_len - suffix_len, suffix) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
long native_fopen(long *args, int argc) {
|
|
||||||
if (!args || argc < 2) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
char *filename = (char*)args[0];
|
|
||||||
char *mode = (char*)args[1];
|
|
||||||
if (!filename || !mode) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
FILE *f = fopen(filename, mode);
|
|
||||||
return (long)f;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_fclose(long *args, int argc) {
|
|
||||||
if (!args || argc < 1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
FILE *f = (FILE*)args[0];
|
|
||||||
if (!f) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return fclose(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_fread(long *args, int argc) {
|
|
||||||
if (!args || argc < 3) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
FILE *f = (FILE*)args[0];
|
|
||||||
int addr = (int)args[1];
|
|
||||||
int size = (int)args[2];
|
|
||||||
|
|
||||||
if (!f || addr < 0 || addr >= MEM_SIZE || size <= 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addr + size > MEM_SIZE) {
|
|
||||||
size = MEM_SIZE - addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
char temp_buf[8192];
|
|
||||||
if (size > 8192) size = 8192;
|
|
||||||
|
|
||||||
int result = fread(temp_buf, 1, size, f);
|
|
||||||
if (result > 0) {
|
|
||||||
for (int i = 0; i < result && addr + i < MEM_SIZE; i++) {
|
|
||||||
memory[addr + i] = temp_buf[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_fwrite(long *args, int argc) {
|
|
||||||
if (!args || argc < 3) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
FILE *f = (FILE*)args[0];
|
|
||||||
long buf_arg = args[1];
|
|
||||||
int size = (int)args[2];
|
|
||||||
|
|
||||||
if (!f || size <= 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf_arg > MEM_SIZE * 8 || buf_arg < 0) {
|
|
||||||
return fwrite((char*)buf_arg, 1, size, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf_arg >= MEM_SIZE) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char temp_buf[8192];
|
|
||||||
if (size > 8192) size = 8192;
|
|
||||||
|
|
||||||
if (buf_arg + size > MEM_SIZE) {
|
|
||||||
size = MEM_SIZE - buf_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < size && buf_arg + i < MEM_SIZE; i++) {
|
|
||||||
temp_buf[i] = (char)memory[buf_arg + i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return fwrite(temp_buf, 1, size, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_fgets(long *args, int argc) {
|
|
||||||
static char empty_str[] = "";
|
|
||||||
if (!args || argc < 2) {
|
|
||||||
return (long)empty_str;
|
|
||||||
}
|
|
||||||
FILE *f = (FILE*)args[0];
|
|
||||||
int max_size = (int)args[1];
|
|
||||||
|
|
||||||
if (!f || max_size <= 0) {
|
|
||||||
return (long)empty_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str_pool_idx >= STR_POOL_SIZE) {
|
|
||||||
error("String pool overflow");
|
|
||||||
return (long)empty_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *result = &str_pool[str_pool_idx];
|
|
||||||
if (max_size > STR_POOL_SIZE - str_pool_idx) {
|
|
||||||
max_size = STR_POOL_SIZE - str_pool_idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fgets(result, max_size, f) == NULL) {
|
|
||||||
return (long)empty_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
int len = strlen(result);
|
|
||||||
str_pool_idx += len + 1;
|
|
||||||
return (long)result;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_fputs(long *args, int argc) {
|
|
||||||
if (!args || argc < 2) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
FILE *f = (FILE*)args[0];
|
|
||||||
char *str = (char*)args[1];
|
|
||||||
|
|
||||||
if (!f || !str) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fputs(str, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_feof(long *args, int argc) {
|
|
||||||
if (!args || argc < 1) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
FILE *f = (FILE*)args[0];
|
|
||||||
if (!f) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return feof(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_ftell(long *args, int argc) {
|
|
||||||
if (!args || argc < 1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
FILE *f = (FILE*)args[0];
|
|
||||||
if (!f) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return ftell(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_fseek(long *args, int argc) {
|
|
||||||
if (!args || argc < 3) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
FILE *f = (FILE*)args[0];
|
|
||||||
long offset = args[1];
|
|
||||||
int whence = (int)args[2];
|
|
||||||
|
|
||||||
if (!f) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return fseek(f, offset, whence);
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_fremove(long *args, int argc) {
|
|
||||||
if (!args || argc < 1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
char *filename = (char*)args[0];
|
|
||||||
if (!filename) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return remove(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_frename(long *args, int argc) {
|
|
||||||
if (!args || argc < 2) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
char *oldname = (char*)args[0];
|
|
||||||
char *newname = (char*)args[1];
|
|
||||||
if (!oldname || !newname) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return rename(oldname, newname);
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_SEEK_SET(long *args, int argc) {
|
|
||||||
return SEEK_SET;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_SEEK_CUR(long *args, int argc) {
|
|
||||||
return SEEK_CUR;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_SEEK_END(long *args, int argc) {
|
|
||||||
return SEEK_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_int_to_double(long *args, int argc) {
|
|
||||||
if (!args || argc < 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
union { double d; long l; } u;
|
|
||||||
u.d = (double)args[0];
|
|
||||||
return u.l;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_double_to_int(long *args, int argc) {
|
|
||||||
if (!args || argc < 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
union { double d; long l; } u;
|
|
||||||
u.l = args[0];
|
|
||||||
return (long)u.d;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_double_add(long *args, int argc) {
|
|
||||||
if (!args || argc < 2) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
union { double d; long l; } u1, u2, result;
|
|
||||||
u1.l = args[0];
|
|
||||||
u2.l = args[1];
|
|
||||||
result.d = u1.d + u2.d;
|
|
||||||
return result.l;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_double_sub(long *args, int argc) {
|
|
||||||
if (!args || argc < 2) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
union { double d; long l; } u1, u2, result;
|
|
||||||
u1.l = args[0];
|
|
||||||
u2.l = args[1];
|
|
||||||
result.d = u1.d - u2.d;
|
|
||||||
return result.l;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_double_mul(long *args, int argc) {
|
|
||||||
if (!args || argc < 2) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
union { double d; long l; } u1, u2, result;
|
|
||||||
u1.l = args[0];
|
|
||||||
u2.l = args[1];
|
|
||||||
result.d = u1.d * u2.d;
|
|
||||||
return result.l;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_double_div(long *args, int argc) {
|
|
||||||
if (!args || argc < 2) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
union { double d; long l; } u1, u2, result;
|
|
||||||
u1.l = args[0];
|
|
||||||
u2.l = args[1];
|
|
||||||
if (u2.d != 0.0) {
|
|
||||||
result.d = u1.d / u2.d;
|
|
||||||
} else {
|
|
||||||
result.d = 0.0;
|
|
||||||
}
|
|
||||||
return result.l;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_async_fread(long *args, int argc) {
|
|
||||||
if (!args || argc < 3) return -1;
|
|
||||||
FILE *f = (FILE*)args[0];
|
|
||||||
int addr = (int)args[1];
|
|
||||||
int size = (int)args[2];
|
|
||||||
if (!f || addr < 0 || addr >= MEM_SIZE || size <= 0) return -1;
|
|
||||||
|
|
||||||
int id = alloc_async_op();
|
|
||||||
if (id < 0) return -1;
|
|
||||||
|
|
||||||
AsyncFileReadData *data = malloc(sizeof(AsyncFileReadData));
|
|
||||||
data->f = f;
|
|
||||||
data->addr = addr;
|
|
||||||
data->size = size;
|
|
||||||
async_ops[id].data = data;
|
|
||||||
|
|
||||||
int *id_ptr = malloc(sizeof(int));
|
|
||||||
*id_ptr = id;
|
|
||||||
pthread_create(&async_ops[id].thread, NULL, async_fread_thread, id_ptr);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_async_fwrite(long *args, int argc) {
|
|
||||||
if (!args || argc < 3) return -1;
|
|
||||||
FILE *f = (FILE*)args[0];
|
|
||||||
long buf_arg = args[1];
|
|
||||||
int size = (int)args[2];
|
|
||||||
if (!f || size <= 0) return -1;
|
|
||||||
|
|
||||||
int id = alloc_async_op();
|
|
||||||
if (id < 0) return -1;
|
|
||||||
|
|
||||||
AsyncFileWriteData *data = malloc(sizeof(AsyncFileWriteData));
|
|
||||||
data->f = f;
|
|
||||||
data->buf_arg = buf_arg;
|
|
||||||
data->size = size;
|
|
||||||
async_ops[id].data = data;
|
|
||||||
|
|
||||||
int *id_ptr = malloc(sizeof(int));
|
|
||||||
*id_ptr = id;
|
|
||||||
pthread_create(&async_ops[id].thread, NULL, async_fwrite_thread, id_ptr);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_async_recv(long *args, int argc) {
|
|
||||||
if (!args || argc < 4) return -1;
|
|
||||||
int sockfd = (int)args[0];
|
|
||||||
int addr = (int)args[1];
|
|
||||||
int len = (int)args[2];
|
|
||||||
int flags = (int)args[3];
|
|
||||||
if (addr < 0 || addr >= MEM_SIZE) return -1;
|
|
||||||
|
|
||||||
int id = alloc_async_op();
|
|
||||||
if (id < 0) return -1;
|
|
||||||
|
|
||||||
AsyncRecvData *data = malloc(sizeof(AsyncRecvData));
|
|
||||||
data->sockfd = sockfd;
|
|
||||||
data->addr = addr;
|
|
||||||
data->len = len;
|
|
||||||
data->flags = flags;
|
|
||||||
async_ops[id].data = data;
|
|
||||||
|
|
||||||
int *id_ptr = malloc(sizeof(int));
|
|
||||||
*id_ptr = id;
|
|
||||||
pthread_create(&async_ops[id].thread, NULL, async_recv_thread, id_ptr);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_async_send(long *args, int argc) {
|
|
||||||
if (!args || argc < 4) return -1;
|
|
||||||
int sockfd = (int)args[0];
|
|
||||||
long buf_arg = args[1];
|
|
||||||
int len = (int)args[2];
|
|
||||||
int flags = (int)args[3];
|
|
||||||
|
|
||||||
int id = alloc_async_op();
|
|
||||||
if (id < 0) return -1;
|
|
||||||
|
|
||||||
AsyncSendData *data = malloc(sizeof(AsyncSendData));
|
|
||||||
data->sockfd = sockfd;
|
|
||||||
data->buf_arg = buf_arg;
|
|
||||||
data->len = len;
|
|
||||||
data->flags = flags;
|
|
||||||
async_ops[id].data = data;
|
|
||||||
|
|
||||||
int *id_ptr = malloc(sizeof(int));
|
|
||||||
*id_ptr = id;
|
|
||||||
pthread_create(&async_ops[id].thread, NULL, async_send_thread, id_ptr);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_async_wait(long *args, int argc) {
|
|
||||||
if (!args || argc < 1) return -1;
|
|
||||||
int id = (int)args[0];
|
|
||||||
if (id < 0 || id >= MAX_ASYNC_OPS || !async_ops[id].active) return -1;
|
|
||||||
|
|
||||||
pthread_join(async_ops[id].thread, NULL);
|
|
||||||
|
|
||||||
pthread_mutex_lock(&async_mutex);
|
|
||||||
long result = async_ops[id].result;
|
|
||||||
async_ops[id].active = 0;
|
|
||||||
pthread_mutex_unlock(&async_mutex);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_async_poll(long *args, int argc) {
|
|
||||||
if (!args || argc < 1) return 0;
|
|
||||||
int id = (int)args[0];
|
|
||||||
if (id < 0 || id >= MAX_ASYNC_OPS || !async_ops[id].active) return 0;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&async_mutex);
|
|
||||||
int complete = async_ops[id].complete;
|
|
||||||
pthread_mutex_unlock(&async_mutex);
|
|
||||||
|
|
||||||
return complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
long native_async_result(long *args, int argc) {
|
|
||||||
if (!args || argc < 1) return -1;
|
|
||||||
int id = (int)args[0];
|
|
||||||
if (id < 0 || id >= MAX_ASYNC_OPS || !async_ops[id].active) return -1;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&async_mutex);
|
|
||||||
long result = async_ops[id].result;
|
|
||||||
async_ops[id].active = 0;
|
|
||||||
pthread_mutex_unlock(&async_mutex);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void register_native_functions() {
|
void register_native_functions() {
|
||||||
register_native_func("socket", native_socket);
|
register_native_func("socket", native_socket);
|
||||||
register_native_func("bind", native_bind);
|
register_native_func("bind", native_bind);
|
||||||
@ -1062,31 +475,4 @@ void register_native_functions() {
|
|||||||
register_native_func("replace", native_replace);
|
register_native_func("replace", native_replace);
|
||||||
register_native_func("startswith", native_startswith);
|
register_native_func("startswith", native_startswith);
|
||||||
register_native_func("endswith", native_endswith);
|
register_native_func("endswith", native_endswith);
|
||||||
register_native_func("fopen", native_fopen);
|
|
||||||
register_native_func("fclose", native_fclose);
|
|
||||||
register_native_func("fread", native_fread);
|
|
||||||
register_native_func("fwrite", native_fwrite);
|
|
||||||
register_native_func("fgets", native_fgets);
|
|
||||||
register_native_func("fputs", native_fputs);
|
|
||||||
register_native_func("feof", native_feof);
|
|
||||||
register_native_func("ftell", native_ftell);
|
|
||||||
register_native_func("fseek", native_fseek);
|
|
||||||
register_native_func("fremove", native_fremove);
|
|
||||||
register_native_func("frename", native_frename);
|
|
||||||
register_native_func("SEEK_SET", native_SEEK_SET);
|
|
||||||
register_native_func("SEEK_CUR", native_SEEK_CUR);
|
|
||||||
register_native_func("SEEK_END", native_SEEK_END);
|
|
||||||
register_native_func("int_to_double", native_int_to_double);
|
|
||||||
register_native_func("double_to_int", native_double_to_int);
|
|
||||||
register_native_func("double_add", native_double_add);
|
|
||||||
register_native_func("double_sub", native_double_sub);
|
|
||||||
register_native_func("double_mul", native_double_mul);
|
|
||||||
register_native_func("double_div", native_double_div);
|
|
||||||
register_native_func("async_fread", native_async_fread);
|
|
||||||
register_native_func("async_fwrite", native_async_fwrite);
|
|
||||||
register_native_func("async_recv", native_async_recv);
|
|
||||||
register_native_func("async_send", native_async_send);
|
|
||||||
register_native_func("async_wait", native_async_wait);
|
|
||||||
register_native_func("async_poll", native_async_poll);
|
|
||||||
register_native_func("async_result", native_async_result);
|
|
||||||
}
|
}
|
||||||
|
|||||||
63
src/parser.c
63
src/parser.c
@ -35,12 +35,6 @@ long factor() {
|
|||||||
pc++;
|
pc++;
|
||||||
return t->val;
|
return t->val;
|
||||||
}
|
}
|
||||||
else if (t->type == Dbl) {
|
|
||||||
pc++;
|
|
||||||
union { double d; long l; } u;
|
|
||||||
u.d = t->dval;
|
|
||||||
return u.l;
|
|
||||||
}
|
|
||||||
else if (t->type == Str) {
|
else if (t->type == Str) {
|
||||||
pc++;
|
pc++;
|
||||||
return (long)t->text;
|
return (long)t->text;
|
||||||
@ -78,9 +72,9 @@ long factor() {
|
|||||||
int f_idx = find_func(t->text, t->val);
|
int f_idx = find_func(t->text, t->val);
|
||||||
if (f_idx == -1) error("Unknown function");
|
if (f_idx == -1) error("Unknown function");
|
||||||
if (f_idx < 0 || f_idx >= func_cnt) return 0;
|
if (f_idx < 0 || f_idx >= func_cnt) return 0;
|
||||||
int call_pc = pc;
|
|
||||||
pc += 2;
|
pc += 2;
|
||||||
|
|
||||||
|
int old_bp = bp;
|
||||||
long args[10];
|
long args[10];
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
|
|
||||||
@ -95,58 +89,25 @@ long factor() {
|
|||||||
match(')');
|
match(')');
|
||||||
|
|
||||||
int ret_pc = pc;
|
int ret_pc = pc;
|
||||||
int old_loc_cnt = loc_cnt;
|
|
||||||
int old_bp = bp;
|
|
||||||
|
|
||||||
if (sp >= MEM_SIZE) return 0;
|
if (sp >= MEM_SIZE) return 0;
|
||||||
if (bp < 0 || bp >= MEM_SIZE) return 0;
|
if (bp < 0 || bp >= MEM_SIZE) return 0;
|
||||||
memory[sp] = bp; bp = sp++;
|
memory[sp] = bp; bp = sp++;
|
||||||
if (sp >= MEM_SIZE) return 0;
|
if (sp >= MEM_SIZE) return 0;
|
||||||
memory[sp++] = ret_pc;
|
memory[sp++] = ret_pc;
|
||||||
memory[sp++] = old_loc_cnt;
|
|
||||||
|
|
||||||
int param_base = sp;
|
|
||||||
for(int i=0; i<argc; i++) {
|
for(int i=0; i<argc; i++) {
|
||||||
if (sp >= MEM_SIZE) break;
|
if (sp >= MEM_SIZE) break;
|
||||||
memory[sp++] = args[i];
|
memory[sp++] = args[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
int scan_pc = funcs[f_idx].params_start;
|
|
||||||
int param_idx = 0;
|
|
||||||
while (scan_pc < MAX_TOK && scan_pc < tk_idx && tokens[scan_pc].type != ')') {
|
|
||||||
if (tokens[scan_pc].type == Int || tokens[scan_pc].type == Char || tokens[scan_pc].type == Double) {
|
|
||||||
scan_pc++;
|
|
||||||
while (scan_pc < MAX_TOK && tokens[scan_pc].type == '*') scan_pc++;
|
|
||||||
if (scan_pc < MAX_TOK && tokens[scan_pc].type == Id && param_idx < argc && loc_cnt < VAR_MAX) {
|
|
||||||
Token *param_name = &tokens[scan_pc];
|
|
||||||
Symbol *sym = &locals[loc_cnt++];
|
|
||||||
int name_len = param_name->val;
|
|
||||||
if (name_len > 31) name_len = 31;
|
|
||||||
strncpy(sym->name, param_name->text, name_len);
|
|
||||||
sym->name[name_len] = 0;
|
|
||||||
sym->type = Int;
|
|
||||||
sym->addr = param_base + param_idx;
|
|
||||||
sym->is_array = 0;
|
|
||||||
param_idx++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scan_pc++;
|
|
||||||
}
|
|
||||||
|
|
||||||
pc = funcs[f_idx].entry_point;
|
pc = funcs[f_idx].entry_point;
|
||||||
return_flag = 0;
|
|
||||||
statement();
|
statement();
|
||||||
|
|
||||||
val = ax;
|
val = ax;
|
||||||
ax = 0;
|
|
||||||
return_flag = 0;
|
|
||||||
|
|
||||||
loc_cnt = old_loc_cnt;
|
|
||||||
if (bp < 0 || bp >= MEM_SIZE) return 0;
|
if (bp < 0 || bp >= MEM_SIZE) return 0;
|
||||||
sp = bp;
|
sp = bp;
|
||||||
if (sp < 0 || sp >= MEM_SIZE) return 0;
|
if (sp < 0 || sp >= MEM_SIZE) return 0;
|
||||||
bp = memory[sp];
|
bp = memory[sp];
|
||||||
if (sp + 1 < MEM_SIZE) ret_pc = memory[sp + 1];
|
|
||||||
pc = ret_pc;
|
pc = ret_pc;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@ -295,26 +256,6 @@ long relational() {
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
long logical_and() {
|
|
||||||
long val = relational();
|
|
||||||
while (pc < MAX_TOK && tokens[pc].type == And) {
|
|
||||||
pc++;
|
|
||||||
long val2 = relational();
|
|
||||||
val = val && val2;
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
long logical_or() {
|
|
||||||
long val = logical_and();
|
|
||||||
while (pc < MAX_TOK && tokens[pc].type == Or) {
|
|
||||||
pc++;
|
|
||||||
long val2 = logical_and();
|
|
||||||
val = val || val2;
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
long expression() {
|
long expression() {
|
||||||
if (pc >= MAX_TOK) return 0;
|
if (pc >= MAX_TOK) return 0;
|
||||||
if (tokens[pc].type == '*') {
|
if (tokens[pc].type == '*') {
|
||||||
@ -386,5 +327,5 @@ long expression() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return logical_or();
|
return relational();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,6 @@
|
|||||||
#define PARSER_H
|
#define PARSER_H
|
||||||
|
|
||||||
long expression();
|
long expression();
|
||||||
long logical_or();
|
|
||||||
long logical_and();
|
|
||||||
long relational();
|
long relational();
|
||||||
long add();
|
long add();
|
||||||
long term();
|
long term();
|
||||||
|
|||||||
@ -1,247 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include "preprocessor.h"
|
|
||||||
|
|
||||||
static IncludedFile included_files[MAX_INCLUDED_FILES];
|
|
||||||
static int included_count = 0;
|
|
||||||
static int include_depth = 0;
|
|
||||||
|
|
||||||
static void normalize_path(const char *path, char *normalized) {
|
|
||||||
strncpy(normalized, path, 255);
|
|
||||||
normalized[255] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int is_already_included(const char *path) {
|
|
||||||
char normalized[256];
|
|
||||||
normalize_path(path, normalized);
|
|
||||||
|
|
||||||
for (int i = 0; i < included_count; i++) {
|
|
||||||
if (strcmp(included_files[i].path, normalized) == 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mark_as_included(const char *path) {
|
|
||||||
if (included_count >= MAX_INCLUDED_FILES) {
|
|
||||||
fprintf(stderr, "Error: Too many included files (max %d)\n", MAX_INCLUDED_FILES);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char normalized[256];
|
|
||||||
normalize_path(path, normalized);
|
|
||||||
|
|
||||||
strncpy(included_files[included_count].path, normalized, 255);
|
|
||||||
included_files[included_count].path[255] = 0;
|
|
||||||
included_files[included_count].included = 1;
|
|
||||||
included_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char* read_file(const char *filename) {
|
|
||||||
FILE *f = fopen(filename, "rb");
|
|
||||||
if (!f) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fseek(f, 0, SEEK_END);
|
|
||||||
long size = ftell(f);
|
|
||||||
fseek(f, 0, SEEK_SET);
|
|
||||||
|
|
||||||
if (size <= 0 || size > MAX_PREPROCESSED_SIZE) {
|
|
||||||
fclose(f);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *content = malloc(size + 1);
|
|
||||||
if (!content) {
|
|
||||||
fclose(f);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t read_size = fread(content, 1, size, f);
|
|
||||||
content[read_size] = 0;
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void resolve_include_path(const char *current_dir, const char *include_file, char *resolved_path) {
|
|
||||||
if (include_file[0] == '/') {
|
|
||||||
strncpy(resolved_path, include_file, 511);
|
|
||||||
resolved_path[511] = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(resolved_path, 512, "%s/%s", current_dir, include_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char* process_includes(const char *filename, const char *content, const char *current_dir);
|
|
||||||
|
|
||||||
static char* extract_include_filename(const char *line) {
|
|
||||||
const char *p = line;
|
|
||||||
while (*p && isspace(*p)) p++;
|
|
||||||
|
|
||||||
if (*p != '#') return NULL;
|
|
||||||
p++;
|
|
||||||
|
|
||||||
while (*p && isspace(*p)) p++;
|
|
||||||
|
|
||||||
if (strncmp(p, "include", 7) != 0) return NULL;
|
|
||||||
p += 7;
|
|
||||||
|
|
||||||
while (*p && isspace(*p)) p++;
|
|
||||||
|
|
||||||
if (*p != '"' && *p != '<') return NULL;
|
|
||||||
|
|
||||||
char quote = (*p == '"') ? '"' : '>';
|
|
||||||
p++;
|
|
||||||
|
|
||||||
static char filename[256];
|
|
||||||
int i = 0;
|
|
||||||
while (*p && *p != quote && i < 255) {
|
|
||||||
filename[i++] = *p++;
|
|
||||||
}
|
|
||||||
filename[i] = 0;
|
|
||||||
|
|
||||||
if (*p != quote) return NULL;
|
|
||||||
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char* process_includes(const char *filename, const char *content, const char *current_dir) {
|
|
||||||
if (include_depth >= MAX_INCLUDE_DEPTH) {
|
|
||||||
fprintf(stderr, "Error: Include depth exceeded (max %d) in file: %s\n",
|
|
||||||
MAX_INCLUDE_DEPTH, filename);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
include_depth++;
|
|
||||||
|
|
||||||
size_t result_size = MAX_PREPROCESSED_SIZE;
|
|
||||||
char *result = malloc(result_size);
|
|
||||||
if (!result) {
|
|
||||||
fprintf(stderr, "Error: Memory allocation failed\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
result[0] = 0;
|
|
||||||
size_t result_len = 0;
|
|
||||||
|
|
||||||
const char *p = content;
|
|
||||||
char line[1024];
|
|
||||||
|
|
||||||
while (*p) {
|
|
||||||
int line_len = 0;
|
|
||||||
while (*p && *p != '\n' && line_len < 1023) {
|
|
||||||
line[line_len++] = *p++;
|
|
||||||
}
|
|
||||||
line[line_len] = 0;
|
|
||||||
if (*p == '\n') {
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *include_file = extract_include_filename(line);
|
|
||||||
|
|
||||||
if (include_file) {
|
|
||||||
char resolved_path[512];
|
|
||||||
resolve_include_path(current_dir, include_file, resolved_path);
|
|
||||||
|
|
||||||
if (is_already_included(resolved_path)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
mark_as_included(resolved_path);
|
|
||||||
|
|
||||||
char *included_content = read_file(resolved_path);
|
|
||||||
if (!included_content) {
|
|
||||||
fprintf(stderr, "Error: Cannot open included file: %s\n", resolved_path);
|
|
||||||
fprintf(stderr, " Included from: %s\n", filename);
|
|
||||||
free(result);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char include_dir[512];
|
|
||||||
char temp_path[512];
|
|
||||||
strncpy(temp_path, resolved_path, 511);
|
|
||||||
temp_path[511] = 0;
|
|
||||||
char *dir = dirname(temp_path);
|
|
||||||
strncpy(include_dir, dir, 511);
|
|
||||||
include_dir[511] = 0;
|
|
||||||
|
|
||||||
char *processed = process_includes(resolved_path, included_content, include_dir);
|
|
||||||
free(included_content);
|
|
||||||
|
|
||||||
size_t processed_len = strlen(processed);
|
|
||||||
if (result_len + processed_len + 2 >= result_size) {
|
|
||||||
fprintf(stderr, "Error: Preprocessed output too large (max %d bytes)\n",
|
|
||||||
MAX_PREPROCESSED_SIZE);
|
|
||||||
free(processed);
|
|
||||||
free(result);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(result + result_len, processed, processed_len);
|
|
||||||
result_len += processed_len;
|
|
||||||
result[result_len++] = '\n';
|
|
||||||
result[result_len] = 0;
|
|
||||||
|
|
||||||
free(processed);
|
|
||||||
} else {
|
|
||||||
size_t line_total = line_len + 1;
|
|
||||||
if (result_len + line_total >= result_size) {
|
|
||||||
fprintf(stderr, "Error: Preprocessed output too large (max %d bytes)\n",
|
|
||||||
MAX_PREPROCESSED_SIZE);
|
|
||||||
free(result);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line_len > 0) {
|
|
||||||
memcpy(result + result_len, line, line_len);
|
|
||||||
result_len += line_len;
|
|
||||||
}
|
|
||||||
result[result_len++] = '\n';
|
|
||||||
result[result_len] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
include_depth--;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* preprocess(const char *filename, const char *source_dir) {
|
|
||||||
included_count = 0;
|
|
||||||
include_depth = 0;
|
|
||||||
memset(included_files, 0, sizeof(included_files));
|
|
||||||
|
|
||||||
mark_as_included(filename);
|
|
||||||
|
|
||||||
char *content = read_file(filename);
|
|
||||||
if (!content) {
|
|
||||||
fprintf(stderr, "Error: Cannot read file: %s\n", filename);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char dir_path[512];
|
|
||||||
if (source_dir) {
|
|
||||||
strncpy(dir_path, source_dir, 511);
|
|
||||||
dir_path[511] = 0;
|
|
||||||
} else {
|
|
||||||
char temp_path[512];
|
|
||||||
strncpy(temp_path, filename, 511);
|
|
||||||
temp_path[511] = 0;
|
|
||||||
char *dir = dirname(temp_path);
|
|
||||||
strncpy(dir_path, dir, 511);
|
|
||||||
dir_path[511] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *result = process_includes(filename, content, dir_path);
|
|
||||||
free(content);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
#ifndef PREPROCESSOR_H
|
|
||||||
#define PREPROCESSOR_H
|
|
||||||
|
|
||||||
#define MAX_INCLUDE_DEPTH 32
|
|
||||||
#define MAX_INCLUDED_FILES 256
|
|
||||||
#define MAX_PREPROCESSED_SIZE 500000
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char path[256];
|
|
||||||
int included;
|
|
||||||
} IncludedFile;
|
|
||||||
|
|
||||||
char* preprocess(const char *filename, const char *source_dir);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -34,14 +34,11 @@ void tokenize(char *src) {
|
|||||||
|
|
||||||
if (!strcmp(buf, "int")) t->type = Int;
|
if (!strcmp(buf, "int")) t->type = Int;
|
||||||
else if (!strcmp(buf, "char")) t->type = Char;
|
else if (!strcmp(buf, "char")) t->type = Char;
|
||||||
else if (!strcmp(buf, "double")) t->type = Double;
|
|
||||||
else if (!strcmp(buf, "if")) t->type = If;
|
else if (!strcmp(buf, "if")) t->type = If;
|
||||||
else if (!strcmp(buf, "else")) t->type = Else;
|
else if (!strcmp(buf, "else")) t->type = Else;
|
||||||
else if (!strcmp(buf, "while")) t->type = While;
|
else if (!strcmp(buf, "while")) t->type = While;
|
||||||
else if (!strcmp(buf, "return")) t->type = Return;
|
else if (!strcmp(buf, "return")) t->type = Return;
|
||||||
else if (!strcmp(buf, "printf")) t->type = Printf;
|
else if (!strcmp(buf, "printf")) t->type = Printf;
|
||||||
else if (!strcmp(buf, "break")) t->type = Break;
|
|
||||||
else if (!strcmp(buf, "continue")) t->type = Continue;
|
|
||||||
else t->type = Id;
|
else t->type = Id;
|
||||||
|
|
||||||
t->val = len;
|
t->val = len;
|
||||||
@ -49,20 +46,9 @@ void tokenize(char *src) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isdigit(*s) || (*s == '.' && s[1] && isdigit(s[1]))) {
|
if (isdigit(*s)) {
|
||||||
char *start = s;
|
|
||||||
int has_dot = 0;
|
|
||||||
while (*s && (isdigit(*s) || (*s == '.' && !has_dot))) {
|
|
||||||
if (*s == '.') has_dot = 1;
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
if (has_dot) {
|
|
||||||
t->type = Dbl;
|
|
||||||
t->dval = strtod(start, NULL);
|
|
||||||
} else {
|
|
||||||
t->type = Num;
|
t->type = Num;
|
||||||
t->val = strtol(start, NULL, 10);
|
t->val = strtol(s, &s, 10);
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,14 +8,13 @@
|
|||||||
#define STR_POOL_SIZE 100000
|
#define STR_POOL_SIZE 100000
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
Num = 128, Dbl, Str, Id, Int, Char, Double, Else, If, While, Return, Printf,
|
Num = 128, Str, Id, Int, Char, Else, If, While, Return, Printf,
|
||||||
Assign, Eq, Ne, Lt, Gt, Le, Ge, Or, And, Inc, Dec, Break, Continue
|
Assign, Eq, Ne, Lt, Gt, Le, Ge, Or, And, Inc, Dec
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int type;
|
int type;
|
||||||
long val;
|
long val;
|
||||||
double dval;
|
|
||||||
char *text;
|
char *text;
|
||||||
} Token;
|
} Token;
|
||||||
|
|
||||||
@ -30,7 +29,6 @@ typedef struct {
|
|||||||
char name[32];
|
char name[32];
|
||||||
int entry_point;
|
int entry_point;
|
||||||
int param_count;
|
int param_count;
|
||||||
int params_start;
|
|
||||||
} Func;
|
} Func;
|
||||||
|
|
||||||
typedef long (*NativeFunc)(long*, int);
|
typedef long (*NativeFunc)(long*, int);
|
||||||
@ -56,6 +54,5 @@ extern char *src_code;
|
|||||||
extern char str_pool[STR_POOL_SIZE];
|
extern char str_pool[STR_POOL_SIZE];
|
||||||
extern int str_pool_idx;
|
extern int str_pool_idx;
|
||||||
extern long ax;
|
extern long ax;
|
||||||
extern int return_flag;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,63 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("=== Array Tests ===\n");
|
|
||||||
|
|
||||||
printf("Test 1: Array declaration and initialization\n");
|
|
||||||
int arr[5];
|
|
||||||
arr[0] = 10;
|
|
||||||
arr[1] = 20;
|
|
||||||
arr[2] = 30;
|
|
||||||
arr[3] = 40;
|
|
||||||
arr[4] = 50;
|
|
||||||
printf("arr[0] = %d\n", arr[0]);
|
|
||||||
printf("arr[1] = %d\n", arr[1]);
|
|
||||||
printf("arr[2] = %d\n", arr[2]);
|
|
||||||
printf("arr[3] = %d\n", arr[3]);
|
|
||||||
printf("arr[4] = %d\n", arr[4]);
|
|
||||||
printf("PASS: Array indexing works\n");
|
|
||||||
|
|
||||||
printf("Test 2: Array modification\n");
|
|
||||||
arr[2] = 100;
|
|
||||||
printf("After arr[2] = 100: arr[2] = %d\n", arr[2]);
|
|
||||||
printf("PASS: Array element modification works\n");
|
|
||||||
|
|
||||||
printf("Test 3: Loop through array\n");
|
|
||||||
int i = 0;
|
|
||||||
int sum = 0;
|
|
||||||
while (i < 5) {
|
|
||||||
sum = sum + arr[i];
|
|
||||||
i = i + 1;
|
|
||||||
}
|
|
||||||
printf("Sum of array elements: %d\n", sum);
|
|
||||||
printf("PASS: Array iteration works\n");
|
|
||||||
|
|
||||||
printf("Test 4: Array with calculations\n");
|
|
||||||
int nums[3];
|
|
||||||
nums[0] = 5;
|
|
||||||
nums[1] = 10;
|
|
||||||
nums[2] = 15;
|
|
||||||
int total = 0;
|
|
||||||
total = total + nums[0];
|
|
||||||
total = total + nums[1];
|
|
||||||
total = total + nums[2];
|
|
||||||
printf("nums[0] + nums[1] + nums[2] = %d\n", total);
|
|
||||||
printf("PASS: Array arithmetic works\n");
|
|
||||||
|
|
||||||
printf("Test 5: Larger array\n");
|
|
||||||
int big[10];
|
|
||||||
int j = 0;
|
|
||||||
while (j < 10) {
|
|
||||||
big[j] = j * j;
|
|
||||||
j = j + 1;
|
|
||||||
}
|
|
||||||
printf("Squares (0-9): ");
|
|
||||||
int k = 0;
|
|
||||||
while (k < 10) {
|
|
||||||
printf("%d ", big[k]);
|
|
||||||
k = k + 1;
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
printf("PASS: Larger arrays work\n");
|
|
||||||
|
|
||||||
printf("\n=== All Array Tests Completed ===\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("=== Async I/O Tests ===\n");
|
|
||||||
|
|
||||||
printf("Test 1: Async file write\n");
|
|
||||||
int f = fopen("async_test.txt", "w");
|
|
||||||
if (f == 0) {
|
|
||||||
printf("ERROR: Could not open file\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int write_handle = async_fwrite(f, "Hello from async I/O!", 21);
|
|
||||||
printf("Write started, handle: %d\n", write_handle);
|
|
||||||
int result = async_wait(write_handle);
|
|
||||||
printf("Write completed, bytes written: %d\n", result);
|
|
||||||
fclose(f);
|
|
||||||
printf("PASS: Async write works\n");
|
|
||||||
|
|
||||||
printf("Test 2: Async file read\n");
|
|
||||||
f = fopen("async_test.txt", "r");
|
|
||||||
if (f == 0) {
|
|
||||||
printf("ERROR: Could not open file\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int buffer[256];
|
|
||||||
int read_handle = async_fread(f, &buffer, 256);
|
|
||||||
printf("Read started, handle: %d\n", read_handle);
|
|
||||||
|
|
||||||
printf("Polling for completion...\n");
|
|
||||||
while (async_poll(read_handle) == 0) {
|
|
||||||
printf(".");
|
|
||||||
}
|
|
||||||
printf("\nRead complete!\n");
|
|
||||||
|
|
||||||
result = async_result(read_handle);
|
|
||||||
printf("Bytes read: %d\n", result);
|
|
||||||
fclose(f);
|
|
||||||
printf("PASS: Async read works\n");
|
|
||||||
|
|
||||||
printf("Test 3: Cleanup\n");
|
|
||||||
fremove("async_test.txt");
|
|
||||||
printf("PASS: File removed\n");
|
|
||||||
|
|
||||||
printf("\n=== All Async I/O Tests Completed ===\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("=== Break and Continue Tests ===\n");
|
|
||||||
|
|
||||||
printf("Test 1: Break statement\n");
|
|
||||||
int count = 0;
|
|
||||||
while (count < 10) {
|
|
||||||
count = count + 1;
|
|
||||||
if (count == 5) {
|
|
||||||
printf("Breaking at count = %d\n", count);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("count = %d\n", count);
|
|
||||||
}
|
|
||||||
printf("Final count after break: %d\n", count);
|
|
||||||
printf("PASS: Break works\n");
|
|
||||||
|
|
||||||
printf("Test 2: Continue statement\n");
|
|
||||||
int i = 0;
|
|
||||||
int sum = 0;
|
|
||||||
while (i < 10) {
|
|
||||||
i = i + 1;
|
|
||||||
if (i == 3 || i == 7) {
|
|
||||||
printf("Skipping i = %d\n", i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sum = sum + i;
|
|
||||||
printf("Adding i = %d, sum = %d\n", i, sum);
|
|
||||||
}
|
|
||||||
printf("Final sum (skipped 3 and 7): %d\n", sum);
|
|
||||||
printf("PASS: Continue works\n");
|
|
||||||
|
|
||||||
printf("Test 3: Break in nested if\n");
|
|
||||||
int j = 0;
|
|
||||||
while (j < 10) {
|
|
||||||
j = j + 1;
|
|
||||||
if (j > 3) {
|
|
||||||
if (j == 6) {
|
|
||||||
printf("Breaking at j = %d (nested if)\n", j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("j = %d\n", j);
|
|
||||||
}
|
|
||||||
printf("Final j: %d\n", j);
|
|
||||||
printf("PASS: Nested break works\n");
|
|
||||||
|
|
||||||
printf("Test 4: Continue in nested if\n");
|
|
||||||
int k = 0;
|
|
||||||
int even_sum = 0;
|
|
||||||
while (k < 10) {
|
|
||||||
k = k + 1;
|
|
||||||
if (k > 0) {
|
|
||||||
int rem = k - (k / 2) * 2;
|
|
||||||
if (rem == 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
even_sum = even_sum + k;
|
|
||||||
}
|
|
||||||
printf("Sum of even numbers 1-10: %d\n", even_sum);
|
|
||||||
printf("PASS: Nested continue works\n");
|
|
||||||
|
|
||||||
printf("Test 5: Multiple breaks and continues\n");
|
|
||||||
int n = 0;
|
|
||||||
int result = 0;
|
|
||||||
while (n < 20) {
|
|
||||||
n = n + 1;
|
|
||||||
if (n < 5) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (n > 15) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
result = result + 1;
|
|
||||||
}
|
|
||||||
printf("Numbers counted between 5 and 15: %d\n", result);
|
|
||||||
printf("PASS: Multiple break/continue works\n");
|
|
||||||
|
|
||||||
printf("\n=== All Break/Continue Tests Completed ===\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("=== Break Test ===\n");
|
|
||||||
int count = 0;
|
|
||||||
while (count < 10) {
|
|
||||||
count = count + 1;
|
|
||||||
if (count == 5) {
|
|
||||||
printf("Breaking at count = %d\n", count);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("count = %d\n", count);
|
|
||||||
}
|
|
||||||
printf("Final count: %d\n", count);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("=== Break Test ===\n");
|
|
||||||
int count = 0;
|
|
||||||
while (count < 10) {
|
|
||||||
count = count + 1;
|
|
||||||
if (count == 5) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("count = %d\n", count);
|
|
||||||
}
|
|
||||||
printf("Final count: %d\n", count);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("=== Comparison Operators Tests ===\n");
|
|
||||||
|
|
||||||
int a = 10;
|
|
||||||
int b = 20;
|
|
||||||
int c = 10;
|
|
||||||
|
|
||||||
printf("Test 1: Less than (<)\n");
|
|
||||||
if (a < b) {
|
|
||||||
printf("10 < 20 = true\n");
|
|
||||||
}
|
|
||||||
if (b < a) {
|
|
||||||
printf("20 < 10 = true (SHOULD NOT PRINT)\n");
|
|
||||||
} else {
|
|
||||||
printf("20 < 10 = false\n");
|
|
||||||
}
|
|
||||||
if (a < c) {
|
|
||||||
printf("10 < 10 = true (SHOULD NOT PRINT)\n");
|
|
||||||
} else {
|
|
||||||
printf("10 < 10 = false\n");
|
|
||||||
}
|
|
||||||
printf("PASS: Less than operator works\n");
|
|
||||||
|
|
||||||
printf("Test 2: Greater than (>)\n");
|
|
||||||
if (b > a) {
|
|
||||||
printf("20 > 10 = true\n");
|
|
||||||
}
|
|
||||||
if (a > b) {
|
|
||||||
printf("10 > 20 = true (SHOULD NOT PRINT)\n");
|
|
||||||
} else {
|
|
||||||
printf("10 > 20 = false\n");
|
|
||||||
}
|
|
||||||
if (a > c) {
|
|
||||||
printf("10 > 10 = true (SHOULD NOT PRINT)\n");
|
|
||||||
} else {
|
|
||||||
printf("10 > 10 = false\n");
|
|
||||||
}
|
|
||||||
printf("PASS: Greater than operator works\n");
|
|
||||||
|
|
||||||
printf("Test 3: Less than or equal (<=)\n");
|
|
||||||
if (a <= b) {
|
|
||||||
printf("10 <= 20 = true\n");
|
|
||||||
}
|
|
||||||
if (a <= c) {
|
|
||||||
printf("10 <= 10 = true\n");
|
|
||||||
}
|
|
||||||
if (b <= a) {
|
|
||||||
printf("20 <= 10 = true (SHOULD NOT PRINT)\n");
|
|
||||||
} else {
|
|
||||||
printf("20 <= 10 = false\n");
|
|
||||||
}
|
|
||||||
printf("PASS: Less than or equal operator works\n");
|
|
||||||
|
|
||||||
printf("Test 4: Greater than or equal (>=)\n");
|
|
||||||
if (b >= a) {
|
|
||||||
printf("20 >= 10 = true\n");
|
|
||||||
}
|
|
||||||
if (a >= c) {
|
|
||||||
printf("10 >= 10 = true\n");
|
|
||||||
}
|
|
||||||
if (a >= b) {
|
|
||||||
printf("10 >= 20 = true (SHOULD NOT PRINT)\n");
|
|
||||||
} else {
|
|
||||||
printf("10 >= 20 = false\n");
|
|
||||||
}
|
|
||||||
printf("PASS: Greater than or equal operator works\n");
|
|
||||||
|
|
||||||
printf("Test 5: Negative number comparisons\n");
|
|
||||||
int neg1 = -5;
|
|
||||||
int neg2 = -10;
|
|
||||||
if (neg1 > neg2) {
|
|
||||||
printf("-5 > -10 = true\n");
|
|
||||||
}
|
|
||||||
if (neg2 < neg1) {
|
|
||||||
printf("-10 < -5 = true\n");
|
|
||||||
}
|
|
||||||
if (neg1 < 0) {
|
|
||||||
printf("-5 < 0 = true\n");
|
|
||||||
}
|
|
||||||
printf("PASS: Negative number comparisons work\n");
|
|
||||||
|
|
||||||
printf("Test 6: Comparisons in expressions\n");
|
|
||||||
int result = a < b;
|
|
||||||
printf("result of (10 < 20) = %d\n", result);
|
|
||||||
int result2 = a > b;
|
|
||||||
printf("result of (10 > 20) = %d\n", result2);
|
|
||||||
printf("PASS: Comparisons as expressions work\n");
|
|
||||||
|
|
||||||
printf("\n=== All Comparison Operators Tests Completed ===\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("Test OR with continue\n");
|
|
||||||
int i = 0;
|
|
||||||
while (i < 10) {
|
|
||||||
i = i + 1;
|
|
||||||
if (i == 3 || i == 7) {
|
|
||||||
printf("Skip %d\n", i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
printf("i = %d\n", i);
|
|
||||||
}
|
|
||||||
printf("Done\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("Start\n");
|
|
||||||
int i = 0;
|
|
||||||
while (i < 5) {
|
|
||||||
i = i + 1;
|
|
||||||
if (i == 3) {
|
|
||||||
printf("Skipping i = %d\n", i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
printf("i = %d\n", i);
|
|
||||||
}
|
|
||||||
printf("Done\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("=== Double Data Type Tests ===\n");
|
|
||||||
|
|
||||||
printf("Test 1: Double variable declaration and assignment\n");
|
|
||||||
double pi = 3.14159;
|
|
||||||
printf("pi = %f\n", pi);
|
|
||||||
printf("PASS: Double variable works\n");
|
|
||||||
|
|
||||||
printf("Test 2: Double arithmetic using helper functions\n");
|
|
||||||
double a = 10.5;
|
|
||||||
double b = 2.5;
|
|
||||||
printf("a = %f, b = %f\n", a, b);
|
|
||||||
|
|
||||||
double sum = double_add(a, b);
|
|
||||||
printf("a + b = %f\n", sum);
|
|
||||||
|
|
||||||
double diff = double_sub(a, b);
|
|
||||||
printf("a - b = %f\n", diff);
|
|
||||||
|
|
||||||
double prod = double_mul(a, b);
|
|
||||||
printf("a * b = %f\n", prod);
|
|
||||||
|
|
||||||
double quot = double_div(a, b);
|
|
||||||
printf("a / b = %f\n", quot);
|
|
||||||
printf("PASS: Double arithmetic works\n");
|
|
||||||
|
|
||||||
printf("Test 3: Type conversions\n");
|
|
||||||
int x = 42;
|
|
||||||
double dx = int_to_double(x);
|
|
||||||
printf("int %d converted to double: %f\n", x, dx);
|
|
||||||
|
|
||||||
double y = 99.9;
|
|
||||||
int iy = double_to_int(y);
|
|
||||||
printf("double %f converted to int: %d\n", y, iy);
|
|
||||||
printf("PASS: Type conversions work\n");
|
|
||||||
|
|
||||||
printf("Test 4: Double with mathematical functions\n");
|
|
||||||
double num = 16.0;
|
|
||||||
double sq = sqrt(double_to_int(num));
|
|
||||||
double sq_double = int_to_double(sq);
|
|
||||||
printf("sqrt(%f) = %f\n", num, sq_double);
|
|
||||||
printf("PASS: Math functions work with doubles\n");
|
|
||||||
|
|
||||||
printf("Test 5: Complex calculation\n");
|
|
||||||
double radius = 5.0;
|
|
||||||
double pi2 = 3.14159;
|
|
||||||
double area = double_mul(pi2, double_mul(radius, radius));
|
|
||||||
printf("Circle area (r=%f): %f\n", radius, area);
|
|
||||||
printf("PASS: Complex calculations work\n");
|
|
||||||
|
|
||||||
printf("\n=== All Double Tests Completed ===\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,82 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("=== File I/O Tests ===\n");
|
|
||||||
|
|
||||||
printf("Test 1: Writing to a file\n");
|
|
||||||
int f = fopen("test_output.txt", "w");
|
|
||||||
if (f == 0) {
|
|
||||||
printf("ERROR: Could not open file for writing\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
fputs(f, "Hello, File I/O!\n");
|
|
||||||
fputs(f, "This is line 2.\n");
|
|
||||||
fputs(f, "Testing file operations.\n");
|
|
||||||
fclose(f);
|
|
||||||
printf("PASS: File written successfully\n");
|
|
||||||
|
|
||||||
printf("Test 2: Reading from file using fgets\n");
|
|
||||||
f = fopen("test_output.txt", "r");
|
|
||||||
if (f == 0) {
|
|
||||||
printf("ERROR: Could not open file for reading\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
char *line1 = fgets(f, 256);
|
|
||||||
printf("Line 1: %s", line1);
|
|
||||||
char *line2 = fgets(f, 256);
|
|
||||||
printf("Line 2: %s", line2);
|
|
||||||
char *line3 = fgets(f, 256);
|
|
||||||
printf("Line 3: %s", line3);
|
|
||||||
fclose(f);
|
|
||||||
printf("PASS: File read successfully\n");
|
|
||||||
|
|
||||||
printf("Test 3: File position operations\n");
|
|
||||||
f = fopen("test_output.txt", "r");
|
|
||||||
if (f == 0) {
|
|
||||||
printf("ERROR: Could not open file\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int pos = ftell(f);
|
|
||||||
printf("Initial position: %d\n", pos);
|
|
||||||
fseek(f, 7, SEEK_SET());
|
|
||||||
pos = ftell(f);
|
|
||||||
printf("Position after seek: %d\n", pos);
|
|
||||||
char *partial = fgets(f, 256);
|
|
||||||
printf("Read after seek: %s", partial);
|
|
||||||
fclose(f);
|
|
||||||
printf("PASS: File positioning works\n");
|
|
||||||
|
|
||||||
printf("Test 4: End of file detection\n");
|
|
||||||
f = fopen("test_output.txt", "r");
|
|
||||||
if (f == 0) {
|
|
||||||
printf("ERROR: Could not open file\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int line_count = 0;
|
|
||||||
while (feof(f) == 0) {
|
|
||||||
char *line = fgets(f, 256);
|
|
||||||
if (strlen(line) > 0) {
|
|
||||||
line_count = line_count + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("Total lines read: %d\n", line_count);
|
|
||||||
fclose(f);
|
|
||||||
printf("PASS: EOF detection works\n");
|
|
||||||
|
|
||||||
printf("Test 5: File rename operation\n");
|
|
||||||
int result = frename("test_output.txt", "test_renamed.txt");
|
|
||||||
if (result == 0) {
|
|
||||||
printf("PASS: File renamed successfully\n");
|
|
||||||
} else {
|
|
||||||
printf("ERROR: File rename failed\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Test 6: File removal\n");
|
|
||||||
result = fremove("test_renamed.txt");
|
|
||||||
if (result == 0) {
|
|
||||||
printf("PASS: File removed successfully\n");
|
|
||||||
} else {
|
|
||||||
printf("ERROR: File removal failed\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n=== All File I/O Tests Completed ===\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("=== File Seek Operations Tests ===\n");
|
|
||||||
|
|
||||||
printf("Test 1: Create test file\n");
|
|
||||||
int f = fopen("seek_test.txt", "w");
|
|
||||||
if (f == 0) {
|
|
||||||
printf("ERROR: Could not create file\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
fputs(f, "0123456789ABCDEFGHIJ");
|
|
||||||
fclose(f);
|
|
||||||
printf("PASS: File created with content\n");
|
|
||||||
|
|
||||||
printf("Test 2: ftell() - get current position\n");
|
|
||||||
f = fopen("seek_test.txt", "r");
|
|
||||||
int pos = ftell(f);
|
|
||||||
printf("Initial position: %d\n", pos);
|
|
||||||
char *line = fgets(f, 5);
|
|
||||||
printf("Read: '%s'\n", line);
|
|
||||||
pos = ftell(f);
|
|
||||||
printf("Position after reading 5 bytes: %d\n", pos);
|
|
||||||
fclose(f);
|
|
||||||
printf("PASS: ftell() works\n");
|
|
||||||
|
|
||||||
printf("Test 3: fseek() with SEEK_SET\n");
|
|
||||||
f = fopen("seek_test.txt", "r");
|
|
||||||
fseek(f, 10, SEEK_SET());
|
|
||||||
pos = ftell(f);
|
|
||||||
printf("Position after fseek(10, SEEK_SET): %d\n", pos);
|
|
||||||
line = fgets(f, 5);
|
|
||||||
printf("Read from position 10: '%s'\n", line);
|
|
||||||
fclose(f);
|
|
||||||
printf("PASS: fseek with SEEK_SET works\n");
|
|
||||||
|
|
||||||
printf("Test 4: fseek() with SEEK_CUR\n");
|
|
||||||
f = fopen("seek_test.txt", "r");
|
|
||||||
line = fgets(f, 5);
|
|
||||||
printf("First read: '%s'\n", line);
|
|
||||||
fseek(f, 3, SEEK_CUR());
|
|
||||||
pos = ftell(f);
|
|
||||||
printf("Position after fseek(3, SEEK_CUR): %d\n", pos);
|
|
||||||
line = fgets(f, 5);
|
|
||||||
printf("Read after seek: '%s'\n", line);
|
|
||||||
fclose(f);
|
|
||||||
printf("PASS: fseek with SEEK_CUR works\n");
|
|
||||||
|
|
||||||
printf("Test 5: fseek() with SEEK_END\n");
|
|
||||||
f = fopen("seek_test.txt", "r");
|
|
||||||
fseek(f, -5, SEEK_END());
|
|
||||||
pos = ftell(f);
|
|
||||||
printf("Position after fseek(-5, SEEK_END): %d\n", pos);
|
|
||||||
line = fgets(f, 10);
|
|
||||||
printf("Read from near end: '%s'\n", line);
|
|
||||||
fclose(f);
|
|
||||||
printf("PASS: fseek with SEEK_END works\n");
|
|
||||||
|
|
||||||
printf("Test 6: Random access pattern\n");
|
|
||||||
f = fopen("seek_test.txt", "r");
|
|
||||||
fseek(f, 5, SEEK_SET());
|
|
||||||
line = fgets(f, 3);
|
|
||||||
printf("Position 5: '%s'\n", line);
|
|
||||||
fseek(f, 0, SEEK_SET());
|
|
||||||
line = fgets(f, 3);
|
|
||||||
printf("Position 0: '%s'\n", line);
|
|
||||||
fseek(f, 15, SEEK_SET());
|
|
||||||
line = fgets(f, 3);
|
|
||||||
printf("Position 15: '%s'\n", line);
|
|
||||||
fclose(f);
|
|
||||||
printf("PASS: Random access works\n");
|
|
||||||
|
|
||||||
printf("Test 7: Cleanup\n");
|
|
||||||
fremove("seek_test.txt");
|
|
||||||
printf("PASS: File removed\n");
|
|
||||||
|
|
||||||
printf("\n=== All File Seek Tests Completed ===\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
int getValue() {
|
|
||||||
return 42;
|
|
||||||
}
|
|
||||||
|
|
||||||
int add(int a, int b) {
|
|
||||||
return a + b;
|
|
||||||
}
|
|
||||||
|
|
||||||
int square(int x) {
|
|
||||||
int result = x * x;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int max(int a, int b) {
|
|
||||||
if (a > b) {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
printf("=== Functions Tests ===\n");
|
|
||||||
printf("Testing no-parameter functions...\n");
|
|
||||||
int val = getValue();
|
|
||||||
printf("getValue() = %d\n", val);
|
|
||||||
|
|
||||||
printf("Testing two-parameter functions...\n");
|
|
||||||
int sum = add(5, 3);
|
|
||||||
printf("add(5, 3) = %d\n", sum);
|
|
||||||
|
|
||||||
printf("Testing functions with local variables...\n");
|
|
||||||
int sq = square(7);
|
|
||||||
printf("square(7) = %d\n", sq);
|
|
||||||
|
|
||||||
printf("Testing conditional functions...\n");
|
|
||||||
int m1 = max(15, 20);
|
|
||||||
printf("max(15, 20) = %d\n", m1);
|
|
||||||
|
|
||||||
printf("Testing nested function calls...\n");
|
|
||||||
int nested = add(square(3), getValue());
|
|
||||||
printf("add(square(3), getValue()) = %d\n", nested);
|
|
||||||
|
|
||||||
printf("\n=== All Tests Completed ===\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
#include "includes/math_lib.rc"
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
printf("=== Include Directive Tests ===\n");
|
|
||||||
|
|
||||||
printf("Test 1: Basic include\n");
|
|
||||||
int sum = add(10, 5);
|
|
||||||
printf("add(10, 5) = %d\n", sum);
|
|
||||||
printf("PASS: Included function works\n");
|
|
||||||
|
|
||||||
printf("Test 2: Multiple functions from include\n");
|
|
||||||
int diff = subtract(20, 7);
|
|
||||||
printf("subtract(20, 7) = %d\n", diff);
|
|
||||||
int prod = multiply(6, 4);
|
|
||||||
printf("multiply(6, 4) = %d\n", prod);
|
|
||||||
int quot = divide(15, 3);
|
|
||||||
printf("divide(15, 3) = %d\n", quot);
|
|
||||||
printf("PASS: All included functions work\n");
|
|
||||||
|
|
||||||
printf("Test 3: Using included functions in expressions\n");
|
|
||||||
int result = add(multiply(3, 4), subtract(10, 5));
|
|
||||||
printf("add(multiply(3, 4), subtract(10, 5)) = %d\n", result);
|
|
||||||
printf("PASS: Included functions in expressions work\n");
|
|
||||||
|
|
||||||
printf("\n=== All Include Tests Completed ===\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
int add(int a, int b) {
|
|
||||||
return a + b;
|
|
||||||
}
|
|
||||||
|
|
||||||
int subtract(int a, int b) {
|
|
||||||
return a - b;
|
|
||||||
}
|
|
||||||
|
|
||||||
int multiply(int a, int b) {
|
|
||||||
return a * b;
|
|
||||||
}
|
|
||||||
|
|
||||||
int divide(int a, int b) {
|
|
||||||
if (b == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return a / b;
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
int string_length(char *s) {
|
|
||||||
return strlen(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
char* string_upper(char *s) {
|
|
||||||
return upper(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
char* string_lower(char *s) {
|
|
||||||
return lower(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
int string_contains(char *haystack, char *needle) {
|
|
||||||
int pos = strpos(haystack, needle);
|
|
||||||
if (pos >= 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
#include "math_lib.rc"
|
|
||||||
#include "string_lib.rc"
|
|
||||||
|
|
||||||
int is_even(int n) {
|
|
||||||
int half = divide(n, 2);
|
|
||||||
return multiply(half, 2) == n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int is_odd(int n) {
|
|
||||||
if (is_even(n)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("=== Logical Operators Tests ===\n");
|
|
||||||
|
|
||||||
printf("Test 1: AND operator (&&)\n");
|
|
||||||
int a = 1;
|
|
||||||
int b = 1;
|
|
||||||
if (a && b) {
|
|
||||||
printf("1 && 1 = true\n");
|
|
||||||
}
|
|
||||||
int c = 1;
|
|
||||||
int d = 0;
|
|
||||||
if (c && d) {
|
|
||||||
printf("1 && 0 = true (SHOULD NOT PRINT)\n");
|
|
||||||
} else {
|
|
||||||
printf("1 && 0 = false\n");
|
|
||||||
}
|
|
||||||
int e = 0;
|
|
||||||
int f = 0;
|
|
||||||
if (e && f) {
|
|
||||||
printf("0 && 0 = true (SHOULD NOT PRINT)\n");
|
|
||||||
} else {
|
|
||||||
printf("0 && 0 = false\n");
|
|
||||||
}
|
|
||||||
printf("PASS: AND operator works\n");
|
|
||||||
|
|
||||||
printf("Test 2: OR operator (||)\n");
|
|
||||||
if (a || b) {
|
|
||||||
printf("1 || 1 = true\n");
|
|
||||||
}
|
|
||||||
if (c || d) {
|
|
||||||
printf("1 || 0 = true\n");
|
|
||||||
}
|
|
||||||
if (e || f) {
|
|
||||||
printf("0 || 0 = true (SHOULD NOT PRINT)\n");
|
|
||||||
} else {
|
|
||||||
printf("0 || 0 = false\n");
|
|
||||||
}
|
|
||||||
printf("PASS: OR operator works\n");
|
|
||||||
|
|
||||||
printf("Test 3: Combined logical operations\n");
|
|
||||||
int x = 5;
|
|
||||||
int y = 10;
|
|
||||||
int z = 15;
|
|
||||||
if (x < y && y < z) {
|
|
||||||
printf("5 < 10 && 10 < 15 = true\n");
|
|
||||||
}
|
|
||||||
if (x > y || y < z) {
|
|
||||||
printf("5 > 10 || 10 < 15 = true\n");
|
|
||||||
}
|
|
||||||
if (x > y && y > z) {
|
|
||||||
printf("5 > 10 && 10 > 15 = true (SHOULD NOT PRINT)\n");
|
|
||||||
} else {
|
|
||||||
printf("5 > 10 && 10 > 15 = false\n");
|
|
||||||
}
|
|
||||||
printf("PASS: Combined logical operations work\n");
|
|
||||||
|
|
||||||
printf("Test 4: Logical operators in while loops\n");
|
|
||||||
int i = 0;
|
|
||||||
int j = 10;
|
|
||||||
while (i < 5 && j > 5) {
|
|
||||||
i = i + 1;
|
|
||||||
j = j - 1;
|
|
||||||
}
|
|
||||||
printf("After loop with &&: i = %d, j = %d\n", i, j);
|
|
||||||
printf("PASS: Logical operators in loops work\n");
|
|
||||||
|
|
||||||
printf("Test 5: Complex conditions\n");
|
|
||||||
int age = 25;
|
|
||||||
int hasLicense = 1;
|
|
||||||
int hasInsurance = 1;
|
|
||||||
if ((age >= 18 && hasLicense) && hasInsurance) {
|
|
||||||
printf("Can drive: age >= 18, has license and insurance\n");
|
|
||||||
}
|
|
||||||
int temp = 30;
|
|
||||||
if (temp < 0 || temp > 35) {
|
|
||||||
printf("Extreme temperature (SHOULD NOT PRINT)\n");
|
|
||||||
} else {
|
|
||||||
printf("Normal temperature range\n");
|
|
||||||
}
|
|
||||||
printf("PASS: Complex conditions work\n");
|
|
||||||
|
|
||||||
printf("\n=== All Logical Operators Tests Completed ===\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
#include "includes/utils.rc"
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
printf("=== Nested Include Tests ===\n");
|
|
||||||
|
|
||||||
printf("Test 1: Functions from nested includes\n");
|
|
||||||
int sum = add(5, 3);
|
|
||||||
printf("add(5, 3) = %d\n", sum);
|
|
||||||
printf("PASS: Functions from first-level include work\n");
|
|
||||||
|
|
||||||
printf("Test 2: Utility functions using nested includes\n");
|
|
||||||
if (is_even(10)) {
|
|
||||||
printf("is_even(10) = true\n");
|
|
||||||
}
|
|
||||||
if (is_odd(7)) {
|
|
||||||
printf("is_odd(7) = true\n");
|
|
||||||
}
|
|
||||||
printf("PASS: Utility functions using nested includes work\n");
|
|
||||||
|
|
||||||
printf("\n=== All Nested Include Tests Completed ===\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("Test OR\n");
|
|
||||||
int i = 3;
|
|
||||||
if (i == 3 || i == 7) {
|
|
||||||
printf("Match\n");
|
|
||||||
}
|
|
||||||
printf("Done\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("=== Pointer Tests ===\n");
|
|
||||||
|
|
||||||
printf("Test 1: Address-of operator (&)\n");
|
|
||||||
int x = 42;
|
|
||||||
int addr = &x;
|
|
||||||
printf("x = %d\n", x);
|
|
||||||
printf("&x = %d\n", addr);
|
|
||||||
printf("PASS: Address-of operator works\n");
|
|
||||||
|
|
||||||
printf("Test 2: Dereference operator (*)\n");
|
|
||||||
int y = 100;
|
|
||||||
int *ptr = &y;
|
|
||||||
int val = *ptr;
|
|
||||||
printf("y = %d\n", y);
|
|
||||||
printf("*ptr = %d\n", val);
|
|
||||||
printf("PASS: Dereference operator works\n");
|
|
||||||
|
|
||||||
printf("Test 3: Modify through pointer\n");
|
|
||||||
int z = 50;
|
|
||||||
int *p = &z;
|
|
||||||
*p = 75;
|
|
||||||
printf("After *p = 75, z = %d\n", z);
|
|
||||||
printf("PASS: Pointer modification works\n");
|
|
||||||
|
|
||||||
printf("Test 4: Multiple pointers\n");
|
|
||||||
int a = 10;
|
|
||||||
int b = 20;
|
|
||||||
int *pa = &a;
|
|
||||||
int *pb = &b;
|
|
||||||
printf("a = %d, b = %d\n", a, b);
|
|
||||||
printf("*pa = %d, *pb = %d\n", *pa, *pb);
|
|
||||||
int sum = *pa + *pb;
|
|
||||||
printf("*pa + *pb = %d\n", sum);
|
|
||||||
printf("PASS: Multiple pointers work\n");
|
|
||||||
|
|
||||||
printf("Test 5: Pointer with arrays\n");
|
|
||||||
int arr[3];
|
|
||||||
arr[0] = 1;
|
|
||||||
arr[1] = 2;
|
|
||||||
arr[2] = 3;
|
|
||||||
printf("arr[0] = %d, arr[1] = %d, arr[2] = %d\n", arr[0], arr[1], arr[2]);
|
|
||||||
int *arrptr = &arr;
|
|
||||||
printf("Array base address: %d\n", arrptr);
|
|
||||||
printf("PASS: Pointers with arrays work\n");
|
|
||||||
|
|
||||||
printf("\n=== All Pointer Tests Completed ===\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("Start\n");
|
|
||||||
int i = 0;
|
|
||||||
while (i < 5) {
|
|
||||||
i = i + 1;
|
|
||||||
printf("i = %d\n", i);
|
|
||||||
if (i == 3) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("After loop, i = %d\n", i);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
int main() {
|
|
||||||
printf("=== Trigonometric Functions Tests ===\n");
|
|
||||||
printf("Note: Results are scaled by 1,000,000\n");
|
|
||||||
|
|
||||||
printf("Test 1: sin() function\n");
|
|
||||||
int sin0 = sin(0);
|
|
||||||
printf("sin(0) * 1000000 = %d\n", sin0);
|
|
||||||
int sin1 = sin(1);
|
|
||||||
printf("sin(1) * 1000000 = %d\n", sin1);
|
|
||||||
int sin2 = sin(2);
|
|
||||||
printf("sin(2) * 1000000 = %d\n", sin2);
|
|
||||||
printf("PASS: sin() function works\n");
|
|
||||||
|
|
||||||
printf("Test 2: cos() function\n");
|
|
||||||
int cos0 = cos(0);
|
|
||||||
printf("cos(0) * 1000000 = %d\n", cos0);
|
|
||||||
int cos1 = cos(1);
|
|
||||||
printf("cos(1) * 1000000 = %d\n", cos1);
|
|
||||||
int cos2 = cos(2);
|
|
||||||
printf("cos(2) * 1000000 = %d\n", cos2);
|
|
||||||
printf("PASS: cos() function works\n");
|
|
||||||
|
|
||||||
printf("Test 3: tan() function\n");
|
|
||||||
int tan0 = tan(0);
|
|
||||||
printf("tan(0) * 1000000 = %d\n", tan0);
|
|
||||||
int tan1 = tan(1);
|
|
||||||
printf("tan(1) * 1000000 = %d\n", tan1);
|
|
||||||
printf("PASS: tan() function works\n");
|
|
||||||
|
|
||||||
printf("Test 4: Multiple angles\n");
|
|
||||||
int i = 0;
|
|
||||||
while (i < 4) {
|
|
||||||
int s = sin(i);
|
|
||||||
int c = cos(i);
|
|
||||||
printf("Angle %d: sin = %d, cos = %d\n", i, s, c);
|
|
||||||
i = i + 1;
|
|
||||||
}
|
|
||||||
printf("PASS: Multiple angle calculations work\n");
|
|
||||||
|
|
||||||
printf("Test 5: Trig with negative values\n");
|
|
||||||
int sinNeg = sin(-1);
|
|
||||||
printf("sin(-1) * 1000000 = %d\n", sinNeg);
|
|
||||||
int cosNeg = cos(-1);
|
|
||||||
printf("cos(-1) * 1000000 = %d\n", cosNeg);
|
|
||||||
printf("PASS: Negative angle calculations work\n");
|
|
||||||
|
|
||||||
printf("\n=== All Trigonometric Tests Completed ===\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user