/** Convert valid Roman numerals given on the command line to decimals. */
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <regex.h> // POSIX

static int
roman_numeral_value(unsigned char c)
{
  switch(toupper(c)) {
  case 'I': return 1;
  case 'V': return 5;
  case 'X': return 10;
  case 'L': return 50;
  case 'C': return 100;
  case 'D': return 500;
  case 'M': return 1000;
  default: return 0; // error
  }
}


static int
roman_numeral_to_int(const char *restrict s, int size)
{
  int total = 0, prev = 0;
  for (int i = size-1; i >= 0; --i) { // in reverse order
    int value = roman_numeral_value(s[i]);
    total += value < prev ? -value : value;
    prev = value;
  }
  return total;
}


int main(void) {
  const char *argv[] = {"roman-numerals", "IX", "XII", NULL};

  regex_t reg;
  if (regcomp(&reg,"^(M{0,3})"
                  "(D?C{0,3}|CM|CD)"
                  "(L?X{0,3}|XC|XL)"
                  "(V?I{0,3}|IX|IV)$", REG_EXTENDED | REG_ICASE))
    exit(2);

  for (const char **pp = argv + 1; *pp; ++pp) {
    if (**pp == '\0' || regexec(&reg, *pp, 0, NULL, 0)) {
      exit(EXIT_FAILURE); // invalid literal(empty or doesn't match the regex)
    }
    printf("%d\n", roman_numeral_to_int(*pp, strlen(*pp)));
  }
  regfree(&reg);
}