Warning dependency cycle detected when installing lolcat

I fixed a bug where atrazine would leave the terminal dirty in case it is interrupted by a signal.

LATEST VERSION

Source
// compile with: gcc atrazine.c -o atrazine -lm -O2 -Wpedantic -Wall -Wextra

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define CSI "\033["
#define RESET CSI"m"

void cleanup(void) {
  printf(RESET);
}

void rainbow(float phase) {
  printf("%s38;2;%d;%d;%dm", CSI,
    /* red   */ (int) (sinf(phase + 0       ) * 127 + 128),
    /* green */ (int) (sinf(phase + 2*M_PI/3) * 127 + 128),
    /* blue  */ (int) (sinf(phase + 4*M_PI/3) * 127 + 128)
  );
}

inline int is_UTF8_continuation(char c) {
  return (c & 0xc0) == 0x80;
}

/* state machine that detects ANSI escape sequences, somewhat poorly */
int in_ANSI(char c) {
  static int state = 0;
  if (state && (isalpha(c) || c == '~' || c == '\033'))  state = 0;
  if (c == '\033' && !state)                             state = 1;
  return state;
}

int main() {
  float omega = 0.05f;
  int nl_offset = 3, t = 0, line = 0;
  char c, peek;

  atexit(cleanup);

  rainbow(omega * t);

  while ((c = getchar()) != EOF) {
    peek = getchar();
    ungetc(peek, stdin);

    if (c == '\n') {
      t = 0;
      line++;
      printf(RESET);
    }

    printf("%c", c);

    if (!is_UTF8_continuation(peek) && !in_ANSI(c)) {
      rainbow(omega * ((++t) + nl_offset * line));
    }
  }
}

Also, angular frequency is adjusted to make a bigger, smoother rainbow. I should probably randomise it in a later version…

3 Likes