blob: 48a0b0688591a4c3403d8fff18971cd1164fa1f8 [file]
//===--- cnf_reader.h -------------------------------------------------------===
//
// satoko: Satisfiability solver
//
// This file is distributed under the BSD 2-Clause License.
// See LICENSE for details.
//
//===------------------------------------------------------------------------===
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "satoko.h"
#include "solver.h"
#include "utils/mem.h"
#include "utils/vec/vec_uint.h"
#include "misc/util/abc_global.h"
ABC_NAMESPACE_IMPL_START
/** Read the file into an internal buffer.
*
* This function will receive a file name. The return data is a string ended
* with '\0'.
*
*/
static char * file_open(const char *fname)
{
FILE *file = fopen(fname, "rb");
char *buffer;
int sz_file;
int ret;
if (file == NULL) {
printf("Couldn't open file: %s\n", fname);
return NULL;
}
fseek(file, 0, SEEK_END);
sz_file = ftell(file);
rewind(file);
buffer = satoko_alloc(char, sz_file + 3);
ret = fread(buffer, sz_file, 1, file);
buffer[sz_file + 0] = '\n';
buffer[sz_file + 1] = '\0';
return buffer;
}
static void skip_spaces(char **pos)
{
assert(pos != NULL);
for (; isspace(**pos); (*pos)++);
}
static void skip_line(char **pos)
{
assert(pos != NULL);
for(; **pos != '\n' && **pos != '\r' && **pos != EOF; (*pos)++);
if (**pos != EOF)
(*pos)++;
return;
}
static int read_int(char **token)
{
int value = 0;
int neg = 0;
skip_spaces(token);
if (**token == '-') {
neg = 1;
(*token)++;
} else if (**token == '+')
(*token)++;
if (!isdigit(**token)) {
printf("Parsing error. Unexpected char: %c.\n", **token);
exit(EXIT_FAILURE);
}
while (isdigit(**token)) {
value = (value * 10) + (**token - '0');
(*token)++;
}
return neg ? -value : value;
}
static void read_clause(char **token, vec_uint_t *lits)
{
int var;
unsigned sign;
vec_uint_clear(lits);
while (1) {
var = read_int(token);
if (var == 0)
break;
sign = (var > 0);
var = abs(var) - 1;
vec_uint_push_back(lits, var2lit((unsigned) var, (char)!sign));
}
}
/** Start the solver and reads the DIMAC file.
*
* Returns false upon immediate conflict.
*/
int satoko_parse_dimacs(char *fname, satoko_t **solver)
{
satoko_t *p = NULL;
vec_uint_t *lits = NULL;
int n_var;
int n_clause;
char *buffer = file_open(fname);
char *token;
if (buffer == NULL)
return -1;
token = buffer;
while (1) {
skip_spaces(&token);
if (*token == 0)
break;
else if (*token == 'c')
skip_line(&token);
else if (*token == 'p') {
token++;
skip_spaces(&token);
for(; !isspace(*token); token++); /* skip 'cnf' */
n_var = read_int(&token);
n_clause = read_int(&token);
skip_line(&token);
lits = vec_uint_alloc((unsigned) n_var);
p = satoko_create();
} else {
if (lits == NULL) {
printf("There is no parameter line.\n");
satoko_free(buffer);
return -1;
}
read_clause(&token, lits);
if (!satoko_add_clause(p, (int*)vec_uint_data(lits), vec_uint_size(lits))) {
printf("Unable to add clause: ");
vec_uint_print(lits);
return SATOKO_ERR;
}
}
}
vec_uint_free(lits);
satoko_free(buffer);
*solver = p;
return SATOKO_OK;
}
ABC_NAMESPACE_IMPL_END