/*********************************************************************
* bfs *
* Copyright (C) 2015-2016 Tavian Barnes <tavianator@tavianator.com> *
* *
* This program is free software. It comes without any warranty, to *
* the extent permitted by applicable law. You can redistribute it *
* and/or modify it under the terms of the Do What The Fuck You Want *
* To Public License, Version 2, as published by Sam Hocevar. See *
* the COPYING file or http://www.wtfpl.net/ for more details. *
*********************************************************************/
#include "bfs.h"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <grp.h>
#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
/**
* Create a new expression.
*/
static struct expr *new_expr(eval_fn *eval) {
struct expr *expr = malloc(sizeof(struct expr));
if (!expr) {
perror("malloc()");
return NULL;
}
expr->lhs = NULL;
expr->rhs = NULL;
expr->eval = eval;
return expr;
}
/**
* Singleton true expression instance.
*/
static struct expr expr_true = {
.lhs = NULL,
.rhs = NULL,
.eval = eval_true,
};
/**
* Singleton false expression instance.
*/
static struct expr expr_false = {
.lhs = NULL,
.rhs = NULL,
.eval = eval_false,
};
/**
* Free an expression.
*/
static void free_expr(struct expr *expr) {
if (expr && expr != &expr_true && expr != &expr_false) {
free_expr(expr->lhs);
free_expr(expr->rhs);
free(expr);
}
}
/**
* Create a new unary expression.
*/
static struct expr *new_unary_expr(struct expr *rhs, eval_fn *eval) {
struct expr *expr = new_expr(eval);
if (!expr) {
free_expr(rhs);
return NULL;
}
expr->rhs = rhs;
expr->eval = eval;
return expr;
}
/**
* Create a new binary expression.
*/
static struct expr *new_binary_expr(struct expr *lhs, struct expr *rhs, eval_fn *eval) {
struct expr *expr = new_expr(eval);
if (!expr) {
free_expr(rhs);
free_expr(lhs);
return NULL;
}
expr->lhs = lhs;
expr->rhs = rhs;
expr->eval = eval;
return expr;
}
/**
* Free the parsed command line.
*/
void free_cmdline(struct cmdline *cmdline) {
if (cmdline) {
free_expr(cmdline->expr);
free_colors(cmdline->colors);
free(cmdline->roots);
free(cmdline);
}
}
/**
* Add a root path to the cmdline.
*/
static bool cmdline_add_root(struct cmdline *cmdline, const char *root) {
size_t i = cmdline->