/* qbm.c * * Copyright (C) 2005-2006 by Andy Goth . * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. */ #define _GNU_SOURCE #include #include #include "qbism.h" /* List of transformation names. Note: this list must be manually sync'ed with * the xform_op_t typedef in qbism.h. */ static char* xform_names[] = { "PROJECTION", "SHIFT", "SHIFTBACK", "ROTATE", "ROTATEBACK", "MULTIPLY", "SINE", "CONDITIONAL", "COMPLEMENT" }; /* Read a QBM file into an algorithm structure. */ void qbm_read(algo_t* algo, FILE* in) { char* line = NULL; size_t line_len = 0; char xform_name[16]; int i, j; /* Read and check the first line. */ if (getline(&line, &line_len, in) < 0) { if (ferror(in)) { perror("getline"); } else { fprintf(stderr, "Malformed QBM input file: zero length.\n"); } free(line); exit(EXIT_FAILURE); } if (strcmp(line, "QBM VERSION 1\n") != 0) { fprintf(stderr, "Malformed QBM or unsupported version.\n"); free(line); exit(EXIT_FAILURE); } algo->seq = NULL; algo->seq_len = 0; algo->num_regs = 0; while (1) { /* Read the line. */ if (getline(&line, &line_len, in) < 0) { if (ferror(in)) { perror("getline"); free(algo->seq); exit(EXIT_FAILURE); } else { break; } } /* Got a line, so allocate space for new data. */ i = algo->seq_len; algo->seq_len++; algo->seq = xrealloc(algo->seq, sizeof(*algo->seq) * algo->seq_len); /* Extract the fields from the line. */ if (sscanf(line, " %16s %d %d %d", &xform_name, &algo->seq[i].source, &algo->seq[i].control, &algo->seq[i].dest) != 4) { fprintf(stderr, "Malformed QBM input file.\n"); free(line); free(algo->seq); exit(EXIT_FAILURE); } /* Find opcode in name table. */ for (j = 0; j < XOP_COUNT; j++) { if (strcmp(xform_name, xform_names[j]) == 0) { algo->seq[i].opcode = j; break; } } if (j == XOP_COUNT) { fprintf(stderr, "Malformed QBM input file: " "unknown opcode \"%s\".\n", xform_name); free(line); free(algo->seq); exit(EXIT_FAILURE); } /* Identify the highest-numbered register. */ if (algo->seq[i].source > algo->num_regs) { algo->num_regs = algo->seq[i].source; } if (algo->seq[i].control > algo->num_regs) { algo->num_regs = algo->seq[i].control; } if (algo->seq[i].dest > algo->num_regs) { algo->num_regs = algo->seq[i].dest; } } /* The number of registers is one plus the highest-numbered register. */ ++algo->num_regs; free(line); } /* Write an algorithm structure to a QBM file. */ void qbm_write(algo_t* algo, FILE* out) { int i; fprintf(out, "QBM VERSION 1\n"); for (i = 0; i < algo->seq_len; ++i) { fprintf(out, "%-11s %2d %2d %2d\n", xform_names[algo->seq[i].opcode], algo->seq[i].source, algo->seq[i].control, algo->seq[i].dest); } } /* vim: set ts=4 sts=4 sw=4 tw=80 et: */