/*------------------------------------------------------*
 | Strings.c - Unix-like utility.                       |
 | Syntax: strings [-N] [-A] [-L] [file [file [ ... ] ] |
 | Prints on stdout the "strings" found in the input    |
 | file(s), or in stdin; a "string" is a sequence of at |
 | least N (default: N_DEFVAL) printing characters,     |
 | ending with a newline or a NULL; or a sequence of at |
 | least N printable characters if the switch -A (for   |
 | ALL) has been given. If -L is present, printable     |
 | characters are limited to the range 0x0-0x7F, NULL   |
 | to DEL, and do not include 8-bit characters.         |
 | v1.00 MLO 920325                                     |
 *------------------------------------------------------*/

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include "mlo.h"

#define N_DEFVAL      4
#define LINE_LENGTH   256
#define DEL           0177

void DoTheStuff(FILE *fp, int n, Boolean all, Boolean low);
void Syntax(void);

void main(
  int argc,
  char **argv
){
  int nChars = N_DEFVAL;
  Boolean all = False;
  Boolean low = False;

  while (--argc) {
    if ( ((*++argv)[0] == '-') ) {
      if (isdigit((*argv)[1])) {
        if ( (nChars = atoi(*argv+1)) < 1) Syntax();
      } else {
        switch ((*argv)[1]) {
          case 'a':
          case 'A':
            all = True;
            break;
          case 'l':
          case 'L':
            low = True;
            break;
          default:
            Syntax();
        }
      }
    } else if ((*argv)[0] == '?') {
      Syntax();
    } else {
      break;
    }
  }

  if (argc) {
    while (argc--) {
      FILE *fp;

      if ( (fp = fopen(*argv, "r")) == NULL) {
        printf("strings: couldn't open file \"%s\".\n", *argv);
      } else {
        DoTheStuff(fp, nChars, all, low);
        fclose(fp);
      }
      ++argv;
    }
  } else {
    DoTheStuff(stdin, nChars, all, low);
  }

  exit(SYS_NORMAL_CODE);
}

void DoTheStuff(
  FILE *fp,
  int n,
  Boolean all,
  Boolean low
){
  char line[LINE_LENGTH];
  char *pc = line;
  int c;

  while ( (c =fgetc(fp)) != EOF) {
    if (isprint(c)   &&   (!low  ||  c < DEL)) {
      *pc++ = c;
    } else {
      if ((pc - line) >= n) {
        if (all   ||   (c == NEWLINE  ||  c == NIHIL)) {
          *pc = NIHIL;
          puts(line);
        }
      }
      pc = line;
    }
  }
}

void Syntax(void)
{
  puts("\nUsage:   strings [-N] [-A] [-L] [file [file [ ... ]]]");
  puts("Purpose: prints on stdout the \"strings\" found in the given");
  puts("         file(s), or in stdin. A \"string\" is defined as a");
  printf("         sequence of at least N (default: %d) printable\n",
         N_DEFVAL);
  puts("         characters ended from newline or a NULL; or as a");
  puts("         sequence of N printable characters, if the switch");
  puts("         -A (for ALL) has been given. The switch -L limits");
  puts("         printable characters to the range 0x0-0x7F, NULL");
  puts("         to DEL, and do not consider printables 8 bit");
  puts("         characters.\n");

  exit(SYS_NORMAL_CODE);
}
