brainfuck  0.1
A full fledged brainfuck compiler
common.c
Go to the documentation of this file.
1 
9 #include <ctype.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include "common.h"
15 
23 int is_uint(const char *str)
24 {
25  if (!*str)
26  return 0;
27  for (;*str; str++)
28  if (!isdigit(*str))
29  return 0;
30  return 1;
31 }
32 
38 void print_help(void)
39 {
40  fputs("Usage: bfc [input file] [options]\n", stderr);
41  fputs("\n", stderr);
42  fputs("\t-s [NUMBER] sets the stack size to this number\n", stderr);
43  fputs("\t-a [ARRSIZE] sets the array size in the program to this number\n", stderr);
44  fputs("\t-c only compile and assemble\n", stderr);
45  fputs("\t-S only compile\n", stderr);
46  fputs("\t-o [FILE] specify an output file\n", stderr);
47  fputs("\t-v enable verbose output\n", stderr);
48  fputs("\t-h, --help print this help message\n", stderr);
49  fputs("\t-i get input from stdin\n", stderr);
50  fputs("\t-pipe pipe to assembler if -S is not set, otherwise print to stdout\n", stderr);
51  fputs("\n", stderr);
52 }
53 
71 int my_getopt(int argc, char **argv, int *stack_size, int *array_size, char **output_file, char **input_file, int *mode)
72 {
73  int i;
74  for (i = 1; i < argc; i++) {
75  if (!strcmp(argv[i], "-s")) {
76  if (i + 1 < argc && is_uint(argv[i + 1])) {
77  *stack_size = atoi(argv[++i]);
78  } else {
79  fprintf(stderr, "%s: option requires a numerical argument -- 's'\n", *argv);
80  return -1;
81  }
82  } else if (!strcmp(argv[i], "-a")) {
83  if (i + 1 < argc && is_uint(argv[i + 1])) {
84  *array_size = atoi(argv[++i]);
85  } else {
86  fprintf(stderr, "%s: option requires a numerical argument -- 'a'\n", *argv);
87  return -1;
88  }
89  } else if (!strcmp(argv[i], "-c")) {
90  *mode &= ~(LINK);
91  } else if (!strcmp(argv[i], "-S")) {
92  *mode &= ~(LINK | ASSEMBLE);
93  } else if (!strcmp(argv[i], "-o")) {
94  if (i + 1 < argc) {
95  *output_file = argv[++i];
96  *mode &= ~(PIPE_OUT);
97  } else {
98  fprintf(stderr, "%s: option requires an argument -- 'o'\n", *argv);
99  return -1;
100  }
101  } else if (!strcmp(argv[i], "-v")) {
102  *mode |= VERBOSE;
103  } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
104  print_help();
105  return -1;
106  } else if (!strcmp(argv[i], "-pipe")) {
107  *mode |= PIPE_OUT;
108  } else if (!strcmp(argv[i], "-i")) {
109  *mode |= PIPE_IN;
110  } else {
111  *input_file = argv[i];
112  *mode &= ~(PIPE_IN);
113  }
114  }
115  return *mode;
116 }
117 
125 char *remove_extenstion(const char *str)
126 {
127  int strl = strlen(str);
128  const char *s = str + strl - 1;
129  for (; *s; s--) {
130  if (*s == '/')
131  break;
132  if (*s == '.') {
133  char *newstr = malloc(1 + s - str);
134  memcpy(newstr, str, s - str);
135  newstr[s - str] = '\0';
136  return newstr;
137  }
138  }
139  return strdup(str);
140 }
141 
153 char *get_as(int mode, const char *name, const char *original, char **ret)
154 {
155  if (name != NULL && ~(mode & ASSEMBLE))
156  *ret = strdup(name);
157  else if (mode & PIPE_OUT)
158  *ret = NULL;
159  else if (original != NULL) {
160  char *base = remove_extenstion(original);
161  int strl = strlen(base);
162  char *new_base = realloc(base, strl + 3);
163  if (new_base == NULL) {
164  fprintf(stderr, "error: couldn't realloc string: ");
165  perror(NULL);
166  return (*ret = NULL);
167  }
168  base = new_base;
169  *ret = strncat(base, ".s", strl + 3);
170  } else
171  *ret = strdup("a.out.s");
172  return *ret;
173 }
174 
184 char *get_obj(int mode, const char *name, const char *original, char **ret)
185 {
186  if (name != NULL && ~(mode & LINK)) {
187  *ret = strdup(name);
188  } else if (original != NULL) {
189  char *base = remove_extenstion(original);
190  int strl = strlen(base);
191  char *new_base = realloc(base, strl + 3);
192  if (new_base == NULL) {
193  puts("error: couldn't realloc string");
194  return NULL;
195  }
196  base = new_base;
197  *ret = strncat(base, ".o", strl + 3);
198  } else {
199  *ret = strdup("a.out.o");
200  }
201  return *ret;
202 }
203 
217 int get_as_file(int mode, FILE **out, const char *name, const char *input_name)
218 {
219  if (name != NULL && ~(mode & ASSEMBLE)) {
220  *out = fopen(name, "w");
221  if (*out == NULL) {
222  fprintf(stderr, "error: couldn't open file %s: ", name);
223  perror(NULL);
224  return -1;
225  }
226  } else if ((mode & PIPE_OUT) && (mode & ASSEMBLE)) {
227  char buf[100];
228  char *foo = NULL;
229  if (get_obj(mode, name, input_name, &foo) == NULL)
230  return -1;
231  snprintf(buf, 100, "as -g -o %s", foo);
232  free(foo);
233  *out = popen(buf, "w");
234  if (*out == NULL) {
235  fprintf(stderr, "error: couldn't open process %s: ", buf);
236  perror(NULL);
237  return -1;
238  }
239  } else if (mode & PIPE_OUT) {
240  *out = stdout;
241  } else {
242  char *foo = NULL;
243  if (get_as(mode, name, input_name, &foo) == NULL)
244  return -1;
245  *out = fopen(foo, "w");
246  if (*out == NULL) {
247  fprintf(stderr, "error: couldn't open file %s: ", foo);
248  perror(NULL);
249  return -1;
250  }
251  free(foo);
252  }
253  return 0;
254 }
255 
267 int close_as_file(int mode, FILE *f)
268 {
269  int ret = 0;
270  if ((mode & PIPE_OUT) && (mode & ASSEMBLE))
271  ret = pclose(f);
272  else if (f != stdout)
273  ret = fclose(f);
274  f = NULL;
275  return ret;
276 }
277 
289 int assemble(int mode, const char *as_file, const char *obj_file)
290 {
291  if (!(mode & ASSEMBLE) || mode & PIPE_OUT)
292  return 0;
293  char buf[256];
294  snprintf(buf, 256, "as %s -g -o %s", as_file, obj_file);
295  int ret = system(buf);
296  if (ret == 0 && !(mode & LINK)) {
297  ret = remove(as_file);
298  }
299  return ret;
300 }
301 
310 int get_in(int mode, const char *input_file, FILE **in)
311 {
312  if (input_file == NULL && !(mode & PIPE_IN)) {
313  fprintf(stderr, "bfc: error: no input files\ncompilation terminated.\n");
314  return -1;
315  }
316  if (mode & PIPE_IN)
317  *in = stdin;
318  else {
319  *in = fopen(input_file, "r");
320  if (mode & VERBOSE)
321  printf("opening file %s\n", input_file);
322  }
323  if (*in == NULL) {
324  fprintf(stderr, "error: couldn't open file %s: ", input_file);
325  perror(NULL);
326  return -1;
327  }
328  return 0;
329 }
int assemble(int mode, const char *as_file, const char *obj_file)
Wrapper around assembling the assembly code.
Definition: common.c:289
char * get_as(int mode, const char *name, const char *original, char **ret)
Gets the name of the assembly code file.
Definition: common.c:153
char * remove_extenstion(const char *str)
Removes the file extension from a string, if there is one at all.
Definition: common.c:125
int my_getopt(int argc, char **argv, int *stack_size, int *array_size, char **output_file, char **input_file, int *mode)
Custom getopt function.
Definition: common.c:71
int is_uint(const char *str)
Checks if the given string can represent a positive integer.
Definition: common.c:23
char * get_obj(int mode, const char *name, const char *original, char **ret)
Gets the name of the assembled file.
Definition: common.c:184
int get_in(int mode, const char *input_file, FILE **in)
Gets the source code file pointer and deals with IO errors.
Definition: common.c:310
int get_as_file(int mode, FILE **out, const char *name, const char *input_name)
Gets the file pointer to the assembly code file.
Definition: common.c:217
void print_help(void)
Prints the help message when "-h" or "--help" are command line arguments.
Definition: common.c:38
Header for extern functions.
int close_as_file(int mode, FILE *f)
Closes the file pointer to the assembly source file.
Definition: common.c:267