1/*
2 * Copyright © 2016-2018 Sören Tempel
3 *
4 * This program is free software: you can redistribute it and/or
5 * modify it under the terms of the GNU Affero General Public
6 * License as published by the Free Software Foundation, either
7 * version 3 of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public
15 * License along with this program. If not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <unistd.h>
22
23#include <sys/types.h>
24
25#include "turing.h"
26#include "parser.h"
27#include "util.h"
28
29/**
30 * Writes the usage string for this program to stderr and terminates
31 * the program with EXIT_FAILURE.
32 */
33static void
34usage(char *prog)
35{
36 fprintf(stderr, "USAGE: %s %s\n", prog,
37 "[-r] [-h|-v] FILE [INPUT]");
38 exit(EXIT_FAILURE);
39}
40
41/**
42 * Writes an input error message to stderr and terminates the program
43 * with EXIT_FAILURE.
44 *
45 * @param str The input string which contained an invalid symbol.
46 * @param pos Position of the first invalid character. The first
47 * character is located at position 0 not 1.
48 */
49static void
50inputerr(char *str, size_t pos)
51{
52 char *marker, *msg;
53
54 msg = "Input can only consist of alphanumeric "
55 "characters.\n\t Besides it can't contain the "
56 "special blank character.";
57
58 marker = mark(pos, str);
59 fprintf(stderr, "Input error at position %zu: %s\n %s\n %s\n",
60 ++pos, msg, str, marker);
61
62 exit(EXIT_FAILURE);
63}
64
65/**
66 * The main function invoked when the program is started.
67 *
68 * @param argc Amount of command line parameters.
69 * @param argv Command line parameters.
70 */
71int
72main(int argc, char **argv)
73{
74 size_t pos;
75 int opt, ext, rtape;
76 parerr ret;
77 dtm *tm;
78 parser *par;
79 char *in, *fc, *fp;
80 ssize_t len;
81
82 rtape = 0;
83 while ((opt = getopt(argc, argv, "rhv")) != -1) {
84 switch (opt) {
85 case 'r':
86 rtape = 1;
87 break;
88 case 'v':
89 fprintf(stderr, "tmsim-"VERSION"\n");
90 return EXIT_FAILURE;
91 case 'h':
92 default:
93 usage(argv[0]);
94 }
95 }
96
97 if (argc <= 1 || optind >= argc)
98 usage(argv[0]);
99
100 fp = argv[optind];
101 if ((len = readfile(&fc, fp)) == -1)
102 die("couldn't read from input file");
103 par = newparser(fc, (size_t)len);
104
105 tm = newtm();
106 if ((ret = parsetm(par, tm)) != PAR_OK) {
107 strparerr(par, ret, fp, stderr);
108 return EXIT_FAILURE;
109 }
110 freeparser(par);
111
112 if (argc <= 2 || ++optind >= argc)
113 return EXIT_SUCCESS;
114
115 in = argv[optind];
116 if (!verifyinput(in, &pos))
117 inputerr(in, pos);
118 writetape(tm, in);
119
120 ext = (runtm(tm)) ? EXIT_FAILURE : EXIT_SUCCESS;
121 if (rtape)
122 printtape(tm);
123
124 return ext;
125}