master chld/cotton_haiku / src / interpreter.c
  1// i got to eventually clean up this file a bit i feel like its very janky but i suppose i can worry about that later
  2
  3#include <stdio.h>
  4#include <string.h>
  5#include <stdlib.h>
  6#include <unistd.h>
  7#include <OS.h>
  8#include "interpreter.h"
  9#include "cottonwindow.h"
 10#include "eiki.h"
 11
 12// maximum length of a .cot file line
 13#define MAX_LINE 256
 14
 15
 16// da string stuff
 17
 18static void strip_newline(char *s)
 19{
 20    s[strcspn(s, "\r\n")] = 0;
 21}
 22
 23static char *get_arg(char *line)
 24{
 25    char *space = strchr(line, ' ');
 26
 27    if (space != NULL)
 28    {
 29        return space + 1;
 30    }
 31
 32    else
 33    {
 34        return NULL;
 35    }
 36}
 37
 38static char *strip_quotes(char *s)
 39{
 40    if (s[0] == '"')
 41    {
 42        char *end = strrchr(s, '"');
 43
 44        if (end == NULL)
 45        {
 46            fprintf(stderr, "looks like you forgot a quote at the end xP\n");
 47            return s;
 48        }
 49
 50        *end = '\0';
 51        return s + 1;
 52    }
 53
 54    return s;
 55}
 56
 57
 58// da graphics stuff
 59
 60static void draw_pixel(Cotton *cotton, int x, int y)
 61{
 62    cotton->video[y * VIDEO_WIDTH + x] = cotton->c_cottolette;
 63}
 64
 65static void draw_char(Cotton *cotton, char c, int x, int y)
 66{
 67    for (int row = 0; row < FONT_HEIGHT; row++)
 68    {
 69        uint8_t bits = EIKI_FONT[(uint8_t)c][row];
 70
 71    for (int col = 0; col < FONT_WIDTH; col++)
 72    {
 73
 74        if (bits & (1 << col)) 
 75        {
 76            draw_pixel(cotton, x + col, y + row);
 77        }
 78    }
 79
 80    }
 81}
 82
 83
 84// da commands
 85
 86static void cmd_print(Cotton *cotton, CottonWindow *cw, char *arg)
 87{
 88    if (!arg)
 89        return;
 90
 91    char *text = strip_quotes(arg);
 92
 93    printf("%s\n", text);
 94
 95    for (int i = 0; text[i] != '\0'; i++)
 96    {
 97        if (text[i] == '\n')
 98        {
 99            cotton->cursor_x = 0;
100            cotton->cursor_y += FONT_HEIGHT + 4;
101            continue;
102        }
103
104        draw_char(cotton, text[i], cotton->cursor_x, cotton->cursor_y);
105        cotton->cursor_x += FONT_WIDTH + 2;
106
107        if (cotton->cursor_x + FONT_WIDTH + 2 >= VIDEO_WIDTH)
108        {
109            cotton->cursor_x = 0;
110            cotton->cursor_y += FONT_HEIGHT + 4;
111        }
112    }
113
114    cotton->cursor_x = 0;
115    cotton->cursor_y += FONT_HEIGHT + 4;
116
117    cottonwindow_update(cw, cotton->video, sizeof(cotton->video[0]) * VIDEO_WIDTH);
118
119}
120
121static void cmd_wait(Cotton *cotton, char *arg)
122{
123    if (!arg)
124        return;
125
126    int seconds = atoi(arg);
127
128    cotton->ticktock = system_time() / 100 + (seconds * 1000);
129}
130
131static void cmd_kill(void)
132{
133    printf("[cotton stopped]\n");
134    exit(0);
135}
136
137static void cmd_clear(Cotton *cotton, CottonWindow *cw)
138{
139    for (int i = 0; i < VIDEO_WIDTH * VIDEO_HEIGHT; i++)
140    {
141        cotton->video[i] = 0;
142    }
143
144    cotton->cursor_x = 0;
145    cotton->cursor_y = 0;
146
147    cottonwindow_update(cw, cotton->video, sizeof(cotton->video[0]) * VIDEO_WIDTH);
148}
149
150static void cmd_color(Cotton *cotton, char *arg)
151{
152    if (!arg) return;
153
154    if (strcmp(arg, "black") == 0)
155        cotton->c_cottolette = COTTOLETTE[0];
156    
157    else if (strcmp(arg, "white") == 0)
158        cotton->c_cottolette = COTTOLETTE[1];
159    
160    else if (strcmp(arg, "rey") == 0)
161        cotton->c_cottolette = COTTOLETTE[2];
162
163    else if (strcmp(arg, "wist") == 0)
164        cotton->c_cottolette = COTTOLETTE[3];
165
166    else if (strcmp(arg, "wink") == 0)
167        cotton->c_cottolette = COTTOLETTE[4];
168
169    else if (strcmp(arg, "laven") == 0)
170        cotton->c_cottolette = COTTOLETTE[5];
171
172    else if (strcmp(arg, "geen") == 0)
173        cotton->c_cottolette = COTTOLETTE[6];
174
175    else
176        fprintf(stderr, "cotton doesn't know the color \"%s\" sorry,, :(\n", arg);
177}
178
179static void cmd_input(CottonWindow *cw, char *arg)
180{
181    (void)cw;
182    (void)arg;
183
184    // will work on this for v0.2 or whenever it is that i add variables
185}
186
187static void cmd_unknown(const char *cmd)
188{
189    fprintf(stderr, "cotton doesn't know what \"%s\" means, care to type that out again? :<\n", cmd);
190}
191
192
193// da interpreter loop
194
195void cotton_interpret(Cotton *cotton, CottonWindow *cw, FILE *file)
196{
197    char line[MAX_LINE];
198
199    // this reads the file one line at a time until we get to da end of da file
200    if (!fgets(line, sizeof(line), file))
201        return;
202
203    strip_newline(line);
204
205    // cot shall use # comments like C because C is cool and i love C so bwaaa
206    if (line[0] == '\0' || line[0] == '#')
207        return;
208
209
210    char line_copy[MAX_LINE];
211
212    strncpy(line_copy, line, MAX_LINE - 1);
213    line_copy[MAX_LINE - 1] = '\0';
214
215
216    char *cmd = strtok(line_copy, " ");
217
218    if (!cmd)
219        return;
220
221
222    // RELEASE THE KRAKE- I MEAN, RELEASE THE GREAT WALL OF COMMANDS !!! 
223    // could i format this better? maybe,, but but i'd say this is readable and i think readability is gud so i will keep it nice and green,,, green!! :D
224    char *arg = get_arg(line);
225
226
227    if (strcmp(cmd, "print") == 0)
228    {
229        cmd_print(cotton, cw, arg);
230    }
231
232    else if (strcmp(cmd, "clear") == 0)
233    {
234        cmd_clear(cotton, cw);
235    }
236
237    else if (strcmp(cmd, "color") == 0)
238    {
239        cmd_color(cotton, arg);
240    }
241
242    else if (strcmp(cmd, "wait") == 0)
243    {
244        cmd_wait(cotton, arg);
245    }
246
247    else if (strcmp(cmd, "input") == 0)
248    {
249        cmd_input(cw, arg);
250    }
251
252    else if (strcmp(cmd, "kill") == 0)
253    {
254        cmd_kill();
255    }
256
257    else
258    {
259        cmd_unknown(cmd);
260    }
261}