1/*2 * Copyright © 2016-2018 Sören Tempel3 *4 * This program is free software: you can redistribute it and/or5 * modify it under the terms of the GNU Affero General Public6 * License as published by the Free Software Foundation, either7 * 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 of11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12 * Affero General Public License for more details.13 *14 * You should have received a copy of the GNU Affero General Public15 * License along with this program. If not, see16 * <http://www.gnu.org/licenses/>.17 */1819#include <stdio.h>20#include <stdlib.h>21#include <unistd.h>2223#include <sys/types.h>2425#include "turing.h"26#include "parser.h"27#include "util.h"2829/**30 * Shape used for normal states. Normal states are all states that are31 * neither an accepting nor an initial state.32 */33static char *nodeshape = "circle";3435/**36 * Shape used for the initial node.37 */38static char *initialshape = "diamond";3940/**41 * Shape used for the accepting nodes.42 */43static char *acceptingshape = "doublecircle";4445/**46 * Writes the dot language reprasentation for a given transition47 * 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 void54exporttrans(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}6162/**63 * Writes the dot language reprasentation for a given state64 * 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 void70exportstate(tmstate *state, void *arg)71{72 eachtrans(state, exporttrans, arg);73}7475/**76 * Writes the dot language reprasentation for a given turing machine77 * 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 void83export(dtm *tm, FILE *stream)84{85 fprintf(stream, "digraph G {\nrankdir = \"LR\";\n\n");8687 fprintf(stream, "node [shape = %s];\n", initialshape);88 fprintf(stream, "q%d;\n", tm->start);8990 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]);9394 fprintf(stream, "\nnode [shape = %s];\n", nodeshape);95 eachstate(tm, exportstate, stream);96 fprintf(stream, "}\n");97}9899/**100 * Writes the usage string for this program to stderr and terminates101 * the programm with EXIT_FAILURE.102 */103static void104usage(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");109110 exit(EXIT_FAILURE);111}112113/**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 */119int120main(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;129130 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 }154155 if (argc <= 1 || optind >= argc)156 usage(argv[0]);157158 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);162163 tm = newtm();164 if ((ret = parsetm(par, tm)) != PAR_OK) {165 strparerr(par, ret, fp, stdout);166 return EXIT_FAILURE;167 }168 freeparser(par);169170 export(tm, ofd);171 return EXIT_SUCCESS;172}