tmsim

A fast turing machine simulator with graphviz export functionality

git clone https://git.8pit.net/tmsim.git

  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 * Shape used for normal states. Normal states are all states that are
 31 * neither an accepting nor an initial state.
 32 */
 33static char *nodeshape = "circle";
 34
 35/**
 36 * Shape used for the initial node.
 37 */
 38static char *initialshape = "diamond";
 39
 40/**
 41 * Shape used for the accepting nodes.
 42 */
 43static char *acceptingshape = "doublecircle";
 44
 45/**
 46 * Writes the dot language reprasentation for a given transition
 47 * from a given state to a given stream.
 48 *
 49 * @param trans Transition to create dot markup for.
 50 * @param state State the transition belongs to.
 51 * @param arg Void pointer to a stream the output should be written to.
 52 */
 53static void
 54exporttrans(tmtrans *trans, tmstate *state, void *arg)
 55{
 56	fprintf(arg, "q%d -> q%d [label=\"%c/%c/%c\"];\n",
 57		state->name, trans->nextstate,
 58		trans->rsym, trans->wsym,
 59		dirstr(trans->headdir));
 60}
 61
 62/**
 63 * Writes the dot language reprasentation for a given state
 64 * to a given stream.
 65 *
 66 * @param state State to create dot markup for.
 67 * @param arg Void pointer to a stream the output should be written to.
 68 */
 69static void
 70exportstate(tmstate *state, void *arg)
 71{
 72	eachtrans(state, exporttrans, arg);
 73}
 74
 75/**
 76 * Writes the dot language reprasentation for a given turing machine
 77 * to a given stream.
 78 *
 79 * @param tm Turing machine to create dot markup for.
 80 * @param stream Stream to write dot markup to.
 81 */
 82static void
 83export(dtm *tm, FILE *stream)
 84{
 85	fprintf(stream, "digraph G {\nrankdir = \"LR\";\n\n");
 86
 87	fprintf(stream, "node [shape = %s];\n", initialshape);
 88	fprintf(stream, "q%d;\n", tm->start);
 89
 90	fprintf(stream, "\nnode [shape = %s];\n", acceptingshape);
 91	for (size_t i = 0; i < tm->acceptsiz; i++)
 92		fprintf(stream, "q%d;\n", tm->accept[i]);
 93
 94	fprintf(stream, "\nnode [shape = %s];\n", nodeshape);
 95	eachstate(tm, exportstate, stream);
 96	fprintf(stream, "}\n");
 97}
 98
 99/**
100 * Writes the usage string for this program to stderr and terminates
101 * the programm with EXIT_FAILURE.
102 */
103static void
104usage(char *prog)
105{
106	fprintf(stderr, "USAGE: %s %s\n", prog,
107		"[-s nodeshape] [-i initialshape]\n"
108		"\t[-a acceptingshape] [-o path] [-h|-v] FILE");
109
110	exit(EXIT_FAILURE);
111}
112
113/**
114 * The main function invoked when the program is started.
115 *
116 * @param argc Amount of command line parameters.
117 * @param argv Command line parameters.
118 */
119int
120main(int argc, char **argv)
121{
122	int opt;
123	parerr ret;
124	dtm *tm;
125	parser *par;
126	char *fc, *fp;
127	FILE *ofd;
128	ssize_t len;
129
130	ofd = stdout;
131	while ((opt = getopt(argc, argv, "s:i:a:o:hv")) != -1) {
132		switch (opt) {
133		case 's':
134			nodeshape = optarg;
135			break;
136		case 'i':
137			initialshape = optarg;
138			break;
139		case 'a':
140			acceptingshape = optarg;
141			break;
142		case 'o':
143			if (!(ofd = fopen(optarg, "w")))
144				die("couldn't open output file");
145			break;
146		case 'v':
147			fprintf(stderr, "tmsim-"VERSION"\n");
148			return EXIT_FAILURE;
149		case 'h':
150		default:
151			usage(argv[0]);
152		}
153	}
154
155	if (argc <= 1 || optind >= argc)
156		usage(argv[0]);
157
158	fp = argv[optind];
159	if ((len = readfile(&fc, fp)) == -1)
160		die("couldn't read from input file");
161	par = newparser(fc, (size_t)len);
162
163	tm = newtm();
164	if ((ret = parsetm(par, tm)) != PAR_OK) {
165		strparerr(par, ret, fp, stdout);
166		return EXIT_FAILURE;
167	}
168	freeparser(par);
169
170	export(tm, ofd);
171	return EXIT_SUCCESS;
172}