Compare commits

..

7 Commits

Author SHA1 Message Date
kilroy
5976d6b5a6 Added basic arena implementation w/ linear allocator 2025-11-30 22:37:18 -05:00
kilroy
767085b160 Started work on implementing Markdown parser 2025-11-29 21:19:07 -05:00
kilroy
2a7bd4bef7 Added feature to run after compiling in Makefile 2025-11-28 19:43:53 -05:00
kilroy
b222c27f46 Fixed tests 2025-11-28 19:41:37 -05:00
kilroy
b16e085240 Basic Markdown document to do testing with 2025-11-28 19:38:38 -05:00
kilroy
a7a2759053 Added simple testing capabilities 2025-11-28 19:38:18 -05:00
kilroy
b7ce065002 Established length-based strings 2025-11-28 19:31:49 -05:00
10 changed files with 578 additions and 3 deletions

View File

@@ -29,9 +29,18 @@ $(OBJS): dir
@mkdir -p $(BUILD_DIR)/$(@D) @mkdir -p $(BUILD_DIR)/$(@D)
@$(CC) $(CFLAGS) -o $(BUILD_DIR)/$@ -c $*.c @$(CC) $(CFLAGS) -o $(BUILD_DIR)/$@ -c $*.c
# Compiles and runs
run: dir $(OBJS) $(NAME)
@$(BIN_DIR)/$(NAME)
# Runs CUnit tests # Runs CUnit tests
# test: dir
# @$(CC) $(CFLAGS) -lcunit -o $(BIN_DIR)/$(NAME)_test $(TESTS_DIR)/*.c
# @$(BIN_DIR)/$(NAME)_test
# Runs tests
test: dir test: dir
@$(CC) $(CFLAGS) -lcunit -o $(BIN_DIR)/$(NAME)_test $(TESTS_DIR)/*.c @$(CC) $(CFLAGS) -o $(BIN_DIR)/$(NAME)_test $(TESTS_DIR)/*.c
@$(BIN_DIR)/$(NAME)_test @$(BIN_DIR)/$(NAME)_test
# Run valgrind memory checker on executable # Run valgrind memory checker on executable

27
include/arena.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef ARENA_H
#define ARENA_H
#include <stdint.h>
typedef struct {
uint8_t *buffer;
size_t capacity;
size_t offset;
} Arena;
Arena *ArenaInit(size_t capacity);
void ArenaDestroy(Arena *arena);
void *ArenaAlloc(Arena *arena, size_t size);
void *ArenaAllocZero(Arena *arena, size_t size);
void ArenaFree(Arena *arena, size_t size);
void ArenaFreeAndNullify(Arena *arena, size_t size, void **ptrAddress);
// Fundamentally returns how many bytes have been allocated
size_t ArenaGetOffset(Arena *arena);
void ArenaSetOffsetBack(Arena *arena, size_t offset);
void ArenaClear(Arena *arena);
#endif // ARENA_H

22
include/lenstr.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef LENSTR_H
#define LENSTR_H
/* Length-based strings
* and methods to go with them. */
#define PrintStr(str) printf("%.*s\n", str.length, str.chars)
#define StrLit(s) (string) {s, sizeof(s)-1}
typedef struct {
char *chars;
size_t length;
} string;
string CStyleToLengthString_Assign(char *cstr); // StrLit(s) macro but in function form.
string CStyleToLengthString_Copy(char *cstr);
string StringCopy(string str);
string StringSlice_Index(string str, size_t starti, size_t endi);
string StringSlice_Length(string str, size_t starti, size_t length);
#endif // LENSTR_H

69
src/arena.c Normal file
View File

@@ -0,0 +1,69 @@
#include "../include/arena.h"
//#include <string.h>
#include <stdint.h>
#include <stdio.h>
Arena *ArenaInit(size_t capacity)
{
Arena arena;
arena.buffer = malloc(capacity);
arena.capacity = capacity;
arena.offset = 0;
return &arena;
}
void ArenaDestroy(Arena *arena)
{
free(arena->buffer);
arena->buffer = NULL;
arena->capacity = 0;
arena->offset = 0;
}
void *ArenaAlloc(Arena *arena, size_t size)
{
void *ptr = arena->buffer + arena->offset;
arena->offset += size;
return ptr;
}
void *ArenaAllocZero(Arena *arena, size_t size)
{
void *ptr = arena->buffer + arena->offset;
arena->offset += size;
// should I just use memset?
for (void *i = ptr; i != ptr + size; ++i) {
*(uint8_t*)i = 0;
}
return ptr;
}
void ArenaFree(Arena *arena, size_t size)
{
arena->offset -= size;
}
// Frees the memory in the arena *and* sets the pointer to null
void ArenaFreeAndNullify(Arena *arena, size_t size, void **ptrAddress)
{
arena->offset -= size;
*ptrAddress = NULL;
}
// Fundamentally returns how many bytes have been allocated
size_t ArenaGetOffset(Arena *arena)
{
return arena->offset;
}
void ArenaSetOffsetBack(Arena *arena, size_t offset)
{
if (offset > arena->offset) {
*(int*)0 = 0; // Should crash here
}
arena->offset = offset;
}
void ArenaClear(Arena *arena)
{
arena->offset = 0;
}

57
src/lenstr.c Normal file
View File

@@ -0,0 +1,57 @@
#include "../include/lenstr.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
string CStyleToLengthString_Assign(char *cstr)
{
string x;
x.chars = cstr;
x.length = strlen(x.chars);
return x;
}
string CStyleToLengthString_Copy(char *cstr)
{
string x;
x.length = strlen(cstr);
x.chars = malloc(sizeof(char) * x.length); // Should I add +1 here for null terminator?
char *d = x.chars;
char *s = cstr;
while (*d++ = *s++);
return x;
}
// Research and implement memory arenas before implementing this
// char *LengthStringToCStyle(string str)
// {
// char *cstr;
// cstr = malloc
// }
string StringCopy(string str)
{
string x;
x.length = str.length;
x.chars = malloc(sizeof(char) * x.length);
for (int i = 0; i < x.length; i++) {
x.chars[i] = str.chars[i];
}
return x;
}
string StringSlice_Index(string str, size_t starti, size_t endi)
{
string x;
x.chars = &str.chars[starti];
x.length = (endi - starti);
return x;
}
string StringSlice_Length(string str, size_t starti, size_t length)
{
string x;
x.chars = &str.chars[starti];
x.length = length;
return x;
}

View File

@@ -1,7 +1,17 @@
#include "../include/lenstr.h"
#include <ctype.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main()
int main(void)
{ {
printf("hello world\n"); FILE *mdFile = fopen("../tests/markdown_specification.md", "r");
return 0; return 0;
} }

BIN
tests/gfx/tux.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

45
tests/main.c Normal file
View File

@@ -0,0 +1,45 @@
#include "../include/lenstr.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
// C-style to string
string a;
a.chars = "Manual transformation of C-style to String";
a.length = strlen(a.chars);
PrintStr(a);
// Automatic c-style to string
string b = CStyleToLengthString_Assign("Function transformation of C-style to String");
PrintStr(b);
// String assigning (shallow copy) and copying (deep copy)
char xx[] = "String Assign Copy";
char yy[] = "String Deep Copy";
string x = CStyleToLengthString_Assign(xx);
string y = CStyleToLengthString_Assign(yy);
string c = x;
PrintStr(c);
string d = StringCopy(y);
PrintStr(d);
x.chars[3] = '!';
y.chars[3] = '!';
PrintStr(c);
PrintStr(d);
// Manual string slicing
string e;
e.chars = &a.chars[7];
e.length = 14;
PrintStr(e);
// Automatic string slicing (by length or by index range)
string f = StringSlice_Length(a, 7, 14);
string g = StringSlice_Index(a, 7, 21);
PrintStr(f);
PrintStr(g);
return 0;
}

View File

@@ -0,0 +1,331 @@
# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6
Horizontal rule below me
---
Horizontal rule above me
# Heading 1 No Space
## Heading 2 No Space
### Heading 3 No Space
#### Heading 4 No Space
##### Heading 5 No Space
###### Heading 6 No Space
---
Heading 1 with two or more equal signs
===
Heading 2 with two or more dashes
---
---
Paragraph 1.
Paragraph 2
with many line
breaks that will
automatically be
turned into
one
long
line.
Paragraph 3; one literal long line.
---
Paragraph 4 with rendered
line breaks (two spaces
after the end of a
line)
Paragraph 5 with HTML<br>
line breaks in \<br\> tags<br>
...yeah...
---
**Bold** is made with two asterisks (\*\*I'm emboldened\*\*).
*Italics* is made with one asterisk (\*I'm in italics\*).
__Bold__ and _italics_ can also be done with underscores.
Underscores will *not* work in these instances:<br>
Love__is__bold (It should look like "Loveisbold", not "Love<strong>is</strong>bold")<br>
A_cat_meow (It should look like "Acatmeow", not "A<em>cat</em>meow")
Bold *and* italic text can be made with one emboldening pair of characters
and one italicizing pair of characters.
I say ***Hello world!*** (three asterisks \*\*\*)<br>
I say ___Hello world!___ (three underscores \_\_\_)<br>
I say _**Hello world!**_ (one underscore; two asterisks \_\*\*)<br>
I say **_Hello world!_** (two asterisks; one underscore \*\*\_)<br>
I say __*Hello world!*__ (two underscores; one asterisk \_\_\*)<br>
I say *__Hello world!__* (one asterisk; two underscores \*\_\_)
Again, there cannot be underscores in the middle of a word.
---
> I'm a blockquote
> I'm a blockquote...
>
> ...with many paragraphs.
> I'm a blockquote...
>
>> So am I! But within another one.
> I'm a blockquote
>
> #### With a heading
>
> - And a
> - list...
>
> Along with some *more* formatting!
> **Very cool**.
---
1. I'm
2. An
3. Ordered
4. List
1. I am also an ordered list.
1. But I should still be the same output as the above list.
1. Yeah.
1. Same
8. Thing
4. Here
6. BTW
1. I'm an ordered list.
2. Here are some indents.
1. Wow
2. Very nice
3. Third Item
4. Fourth...
1. Indented item
1) Some may use parentheses
2) Like me.
---
- I'm an unordered list
- 2
- 3
- 4
* I'm also an unordered list
* But with asterisks
* Very...
* nice...
+ Again, I'm an unordered list
+ With plus signs!
- And here are some indents.
- Second Item
- Third Item
- Indented 1
- Indented 2
- Fourth Item
To start unordered lists with numbers followed by a period, do this:
- 1969\. What a great year for science!
- Beat that, USSR!
Mixing unordered list signs is bad.
But, I think it should still be allowed, but with a warning in the parser.
+ First (+)
- Second (-)
* Third (*)
+ Fourth (+)
Now onto adding elements in lists.
To "interrupt" a list with some element, then "continue" the list again, do this:
* First
* Second. Let's interrupt:
There is an empty (or at least, a newline with some whitespace) line above and below me. I am also indented by four spaces or one tab.
* Third. I continue!
Same with blockquotes:
* First
* Second
> Blockquote
* Third
Adding codeblocks in lists.
Indent by 8 spaces or two tabs, because the first indent is for adding the
element, and the second is for making the code block.
1. Step 1
2. Step 2
<html>
<head>
<title>hello world</title>
</head>
3. Step 3
Images
1. Blah
2. Blah blah
![TUX!!!](gfx/tux.webp)
3. Wow that was Tux!
You can nest lists within lists.
1. First
2. Second
3. Third
- Unordered
- Wow.
4. Fourth
- Unordered
- Un
- Or
1. First
2. Second
- Dered
---
Code!
Enclose in \`backticks\`:
Type `vim` to open one of the best editors ever.
To escape backticks, do this:<br>
\`\`Okay we're escaping this: \`vim\`. Wow that was easy.\`\`<br>
Which looks like:<br>
<code>Okay we're escaping this: `vim`. Wow that was easy.</code>
Code blocks:
Two ways...
Indent by 4 spaces or one tab:<br>
int main()
{
printf("wow\n");
return 0;
}
Or, my personal favorite, use three backticks:<br>
```
int main()
{
printf("wow\n");
return 0;
}
```
Then to enable highlighting for a language:
> \`\`\`python
> `...Python code here...`
> \`\`\`
```python
print("hello world!")
```
```c
#include <stdio.h>
int main()
{
printf("hello world!\n");
return 0;
}
```
---
Links:
\[Alias; like the alt attribute in \<a\> tags\]\(www.actual-link.com\)
I like [Duck Duck Go](https://duckduckgo.com)
To add a title that shows when you hover your cursor over the link, add a string after the link
\[Alias; like the alt attribute in \<a\> tags\]\(www.actual-link.com "I'm a title"\)
I like [Duck Duck Go](https://duckduckgo.com "The best search engine for privacy")
URLs & Emails:
\<link here\>
<https://www.markdownguide.org>
<fake@example.com>
And you can use formatting within the links:
```
I love supporting the **[EFF](https://eff.org)**.
This is the *[Markdown Guide](https://www.markdownguide.org)*.
See the section on [`code`](#code).
```
I love supporting the **[EFF](https://eff.org)**.
This is the *[Markdown Guide](https://www.markdownguide.org)*.
See the section on [`code`](#code).
---
Reference style links:
First part:
[hobbit-hole][1]
Second part (in multiple formats):
```
[1]: https://en.wikipedia.org/wiki/Hobbit#Lifestyle
[1]: https://en.wikipedia.org/wiki/Hobbit#Lifestyle "Hobbit lifestyles"
[1]: https://en.wikipedia.org/wiki/Hobbit#Lifestyle 'Hobbit lifestyles'
[1]: https://en.wikipedia.org/wiki/Hobbit#Lifestyle (Hobbit lifestyles)
[1]: <https://en.wikipedia.org/wiki/Hobbit#Lifestyle> "Hobbit lifestyles"
[1]: <https://en.wikipedia.org/wiki/Hobbit#Lifestyle> 'Hobbit lifestyles'
[1]: <https://en.wikipedia.org/wiki/Hobbit#Lifestyle> (Hobbit lifestyles)
```
And so:
I live in a [hobbit-hole][1]. It's very nice.
You should read [Tolkien][2]!
[1]: https://en.wikipedia.org/wiki/Hobbit#Lifestyle "Hobbit lifestyles"
[2]: https://en.wikipedia.org/wiki/J._R._R._Tolkien

5
tests/other_src.c Normal file
View File

@@ -0,0 +1,5 @@
/* For adding all necessary source files.
* I could just do symlinks rather than this.
*/
#include "../src/lenstr.c"