Added ASCII string capability to `vvc`.
[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
b8b65c17
AT
28/* Allows building an ASCII string on the stack. */
29/* This syntax: A"test" */
30/* Results in five PUSH_IMMEDIATE commands for the four letters and newline. */
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);
38 if (temp_byte != '"') fprintf(stderr, "WARNING: Expected double-quote to begin string.\n");
39
40 /* Put the letters on the stack in reverse. Don't forget to put a null-terminator first. */
41 for (fread(&temp_byte,1,1,input); temp_byte != '"'; fread(&temp_byte,1,1,input)) continue;
42 temp_byte = '\0';
43
44 while (temp_byte != '"') {
45 /* First, push three spaces to start a PUSH_IMMEDIATE command for a positive number. */
46 uint8_t temp_output = ' ';
47 for(int i=0;i<3;i++) fwrite(&temp_output, 1, 1, output);
48 /* Second, push the ASCII character, 7 bits total, most signficant bit first. */
49 /* Remember, [Tab]=1 and [Space]=0. */
50 uint8_t index = 7; /* 7 bits needed per ASCII character. */
51 while (index) {
52 ((temp_byte >> (index-1)) & 1) ? (temp_output = '\t') : (temp_output = ' ');
53 fwrite(&temp_output, 1, 1, output);
54 index--;
55 }
56 /* Third, close the number with a newline. */
57 temp_output = '\n';
58 fwrite(&temp_output, 1, 1, output);
59
60 /* Read the next byte to prepare for the loop test. */
61 fseek(input, -2, SEEK_CUR);
62 fread(&temp_byte, 1, 1, input);
63 }
64}
65
249fb9ba
AT
66int
67main(int argc, char ** argv)
68{
69 /*
70 * Process command line arguments
71 */
72 int c;
73 FILE * input = NULL, * output = NULL;
74 while ((c = getopt(argc,argv,"i:o:h")) != -1) {
75 switch (c) {
76 case 'i':
77 if ((input = fopen(optarg, "r")) == NULL) {
78 fprintf(stderr, "ERROR: %s: %s\n", optarg, strerror(errno));
79 }
80 break;
81 case 'o':
82 if ((output = fopen(optarg, "w+")) == NULL) {
83 fprintf(stderr, "ERROR: %s: %s\n", optarg, strerror(errno));
84 }
85 break;
86 case 'h':
87 print_usage(argv);
88 exit(EXIT_SUCCESS);
89 break;
90 default:
91 break;
92 }
93 }
94 if (input == NULL) {
95 fprintf(stderr, "ERROR: Must specify a pseudo-VVhitespace source file with -i flag.\n");
96 print_usage(argv);
97 exit(EXIT_FAILURE);
98 }
99 if (output == NULL) {
100 fprintf(stderr, "ERROR: Must specify destination for VVhitespace source file with -o flag.\n");
101 print_usage(argv);
102 exit(EXIT_FAILURE);
103 }
104
105 /*
106 * Main Loop
107 */
108 uint8_t temp_byte;
109 while (fread(&temp_byte, 1, 1, input)) {
110 switch (temp_byte) {
111 case 't':
112 case 'T':
113 temp_byte = '\t';
114 fwrite(&temp_byte, 1, 1, output);
115 break;
116 case 's':
117 case 'S':
118 temp_byte = ' ';
119 fwrite(&temp_byte, 1, 1, output);
120 break;
121 case 'n':
122 case 'N':
123 temp_byte = '\n';
124 fwrite(&temp_byte, 1, 1, output);
125 break;
126 case 'v':
127 case 'V':
128 temp_byte = '\v';
129 fwrite(&temp_byte, 1, 1, output);
130 break;
b8b65c17
AT
131 case 'a':
132 case 'A':
133 parse_ascii_string(input, output);
134 break;
249fb9ba
AT
135 case '\n':
136 /* Intentionally empty */
137 break;
138 default:
b8b65c17 139 /* The first non-[tTsSnNvVaA] character begins a comment lasting until end of line. */
249fb9ba
AT
140 while (fread(&temp_byte, 1, 1, input)) {
141 if (temp_byte == '\n') break;
142 }
143 break;
144 }
145 }
146
147 /*
148 * Cleanup and exit
149 */
150 fclose(input);
151 fclose(output);
152
249fb9ba
AT
153 exit(EXIT_SUCCESS);
154}