if.c 3.44 KB
/* GNU Mailutils -- a suite of utilities for electronic mail
   Copyright (C) 1999, 2001-2002, 2007, 2010-2012, 2014-2016 Free
   Software Foundation, Inc.

   GNU Mailutils 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 3, or (at your option)
   any later version.

   GNU Mailutils 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 GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */

#include "mail.h"

#define COND_STK_SIZE 64
#define COND_STK_INCR 16
static int *_cond_stack;     /* Stack of conditions */
static int _cond_stack_size; /* Number of elements allocated this far */
static int _cond_level;      /* Number of nested `if' blocks */

static void _cond_push(int val);
static int _cond_pop(void);

int
if_cond()
{
  if (_cond_level == 0)
    return 1;
  return _cond_stack[_cond_level-1];
}

void
_cond_push(int val)
{
  if (!_cond_stack)
    {
      _cond_stack = calloc(COND_STK_SIZE, sizeof(_cond_stack[0]));
      _cond_stack_size = COND_STK_SIZE;
      _cond_level = 0;
    }
  else if (_cond_level >= _cond_stack_size)
    {
      _cond_stack_size += COND_STK_INCR;
      _cond_stack = realloc(_cond_stack,
			    sizeof(_cond_stack[0])*_cond_stack_size);
    }

  if (!_cond_stack)
    {
      mu_error(_("Not enough memory"));
      exit (EXIT_FAILURE);
    }
  _cond_stack[_cond_level++] = val;
}

int
_cond_pop()
{
  if (_cond_level == 0)
    {
      mu_error(_("Internal error: condition stack underflow"));
      abort();
    }
  return _cond_stack[--_cond_level];
}

/*
 * i[f] s|r|t
 * mail-commands
 * el[se]
 * mail-commands
 * en[dif]
 */

int
mail_if (int argc, char **argv)
{
  char *mode;
  int cond;

  if (argc != 2)
    {
      /* TRANSLATORS: 'if' is the function name. Do not translate it */
      mu_error(_("if requires an argument: s | r | t"));
      return 1;
    }

  if (argv[1][1] != 0)
    {
      mu_error(_("Valid if arguments are: s | r | t"));
      return 1;
    }

  if (mailvar_get (&mode, "mode", mailvar_type_string, 1))
    exit (EXIT_FAILURE);

  if (if_cond() == 0)
    /* Propagate negative condition */
    cond = 0;
  else
    {
      switch (argv[1][0])
	{
	case 's': /* Send mode */
	  cond = strcmp(mode, "send") == 0;
	  break;
	case 'r': /* Read mode */
	  cond = strcmp(mode, "read") == 0;
	  break;
	case 't': /* Stdout is a terminal device? */
	  cond = isatty (fileno (stdout));
	  break;
	default:
	  mu_error(_("Valid if arguments are: s | r | t"));
	  return 1;
	}
    }
  _cond_push(cond);
  return 0;
}


int
mail_else (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
  int cond;

  if (_cond_level == 0)
    {
      /* TRANSLATORS: 'else' and 'if' are function names. Do not translate them */
      mu_error(_("else without matching if"));
      return 1;
    }
  cond = _cond_pop();
  if (if_cond ())
    cond = !cond;
  _cond_push(cond);
  return 0;
}

int
mail_endif (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
  if (_cond_level == 0)
    {
      /* TRANSLATORS: 'endif' and 'if' are function names. Do not translate them */
      mu_error (_("endif without matching if"));
      return 1;
    }
  _cond_pop();
  return 1;
}