Added tests for `or` subroutine from stdlib.
[vvhitespace] / vv_compiler.c
CommitLineData
249fb9ba
AT
1/*
2 * (c) 2019 Aaron Taylor <ataylor at subgeniuskitty dot com>
3 * All rights reserved.
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <unistd.h>
9#include <string.h>
10#include <errno.h>
11#include <getopt.h>
12#include <stdint.h>
13
14#define VERSION 1
15
16void
17print_usage(char ** argv)
18{
19 printf( "VVhitespace Interpreter v%d (www.subgeniuskitty.com)\n"
20 "Usage: %s -i <file> -o <file>\n"
21 " -h Help (prints this message)\n"
22 " -i <file> Specify a pseudo-VVhitespace source file as input.\n"
23 " -o <file> Specify location for VVhitespace output.\n"
24 , VERSION, argv[0]
25 );
26}
27
f10da6e3
AT
28/* Builds an ASCII string on the stack using VVS PUSH_IMMEDIATE commands. */
29/* The syntax: A"test" results in six PUSH_IMMEDIATE commands for the four */
30/* letters, newline, and null-terminator. */
b8b65c17
AT
31/* Expects 'input' to present a double-quoted ('"') ASCII string. */
32/* The 'A' has already been chomped. */
33void
34parse_ascii_string(FILE * input, FILE * output)
35{
36 uint8_t temp_byte;
37 fread(&temp_byte, 1, 1, input);
0e014963
AT
38 if (temp_byte != '"') {
39 /* Die here since we walk the string backward and look for '"' as a terminator. */
40 fprintf(stderr, "ERROR: Expected double-quote to begin string.\n");
41 exit(EXIT_FAILURE);
42 }
b8b65c17
AT
43
44 /* Put the letters on the stack in reverse. Don't forget to put a null-terminator first. */
45 for (fread(&temp_byte,1,1,input); temp_byte != '"'; fread(&temp_byte,1,1,input)) continue;
46 temp_byte = '\0';
47
48 while (temp_byte != '"') {
49 /* First, push three spaces to start a PUSH_IMMEDIATE command for a positive number. */
50 uint8_t temp_output = ' ';
51 for(int i=0;i<3;i++) fwrite(&temp_output, 1, 1, output);
0e014963 52 /* Second, push the ASCII character, 7 bits total, most significant bit first. */
b8b65c17
AT
53 /* Remember, [Tab]=1 and [Space]=0. */
54 uint8_t index = 7; /* 7 bits needed per ASCII character. */
55 while (index) {
56 ((temp_byte >> (index-1)) & 1) ? (temp_output = '\t') : (temp_output = ' ');
57 fwrite(&temp_output, 1, 1, output);
58 index--;
59 }
60 /* Third, close the number with a newline. */
61 temp_output = '\n';
62 fwrite(&temp_output, 1, 1, output);
63
64 /* Read the next byte to prepare for the loop test. */
65 fseek(input, -2, SEEK_CUR);
66 fread(&temp_byte, 1, 1, input);
67 }
68}
69
249fb9ba
AT
70int
71main(int argc, char ** argv)
72{
73 /*
74 * Process command line arguments
75 */
76 int c;
77 FILE * input = NULL, * output = NULL;
78 while ((c = getopt(argc,argv,"i:o:h")) != -1) {
79 switch (c) {
80 case 'i':
81 if ((input = fopen(optarg, "r")) == NULL) {
82 fprintf(stderr, "ERROR: %s: %s\n", optarg, strerror(errno));
83 }
84 break;
85 case 'o':
86 if ((output = fopen(optarg, "w+")) == NULL) {
87 fprintf(stderr, "ERROR: %s: %s\n", optarg, strerror(errno));
88 }
89 break;
90 case 'h':
91 print_usage(argv);
92 exit(EXIT_SUCCESS);
93 break;
94 default:
95 break;
96 }
97 }
98 if (input == NULL) {
99 fprintf(stderr, "ERROR: Must specify a pseudo-VVhitespace source file with -i flag.\n");
100 print_usage(argv);
101 exit(EXIT_FAILURE);
102 }
103 if (output == NULL) {
104 fprintf(stderr, "ERROR: Must specify destination for VVhitespace source file with -o flag.\n");
105 print_usage(argv);
106 exit(EXIT_FAILURE);
107 }
108
109 /*
110 * Main Loop
111 */
112 uint8_t temp_byte;
113 while (fread(&temp_byte, 1, 1, input)) {
114 switch (temp_byte) {
115 case 't':
116 case 'T':
117 temp_byte = '\t';
118 fwrite(&temp_byte, 1, 1, output);
119 break;
120 case 's':
121 case 'S':
122 temp_byte = ' ';
123 fwrite(&temp_byte, 1, 1, output);
124 break;
125 case 'n':
126 case 'N':
127 temp_byte = '\n';
128 fwrite(&temp_byte, 1, 1, output);
129 break;
130 case 'v':
131 case 'V':
132 temp_byte = '\v';
133 fwrite(&temp_byte, 1, 1, output);
134 break;
b8b65c17
AT
135 case 'a':
136 case 'A':
137 parse_ascii_string(input, output);
138 break;
249fb9ba
AT
139 case '\n':
140 /* Intentionally empty */
141 break;
142 default:
b8b65c17 143 /* The first non-[tTsSnNvVaA] character begins a comment lasting until end of line. */
249fb9ba
AT
144 while (fread(&temp_byte, 1, 1, input)) {
145 if (temp_byte == '\n') break;
146 }
147 break;
148 }
149 }
150
151 /*
152 * Cleanup and exit
153 */
154 fclose(input);
155 fclose(output);
156
249fb9ba
AT
157 exit(EXIT_SUCCESS);
158}