Add input and error modules for getting input and reporting errors

modified:   Makefile
	new file:   src/error.c
	new file:   src/error.h
	new file:   src/input.c
	new file:   src/input.h
	modified:   src/nms.c
	modified:   src/nmseffect.c
	modified:   src/nmseffect.h
This commit is contained in:
Brian Barto 2018-10-24 21:44:48 -04:00
parent 86181d9b52
commit d921892576
8 changed files with 286 additions and 45 deletions

View File

@ -17,7 +17,7 @@ CFLAGS ?= -Wextra -Wall -O2
.PHONY: all install uninstall clean
nms: $(OBJ)/nmscharset.o $(OBJ)/nmstermio.o $(OBJ)/nmseffect.o $(OBJ)/nms.o | $(BIN)
nms: $(OBJ)/input.o $(OBJ)/error.o $(OBJ)/nmscharset.o $(OBJ)/nmstermio.o $(OBJ)/nmseffect.o $(OBJ)/nms.o | $(BIN)
$(CC) $(CFLAGS) -o $(BIN)/$@ $^
sneakers: $(OBJ)/nmscharset.o $(OBJ)/nmstermio.o $(OBJ)/nmseffect.o $(OBJ)/sneakers.o | $(BIN)

56
src/error.c Normal file
View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2017 Brian Barto
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GPL License. See LICENSE for more details.
*/
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
#define ERROR_LIST_MAX 20
#define ERROR_LENGTH_MAX 100
static char error_stack[ERROR_LIST_MAX][ERROR_LENGTH_MAX];
static int N = 0;
void error_log(char *error, ...)
{
va_list argList;
if (N < ERROR_LIST_MAX)
{
va_start(argList, error);
vsnprintf(error_stack[N++], ERROR_LENGTH_MAX - 1, error, argList);
va_end(argList);
}
}
void error_print(void)
{
int i;
for (i = N-1; i >= 0; --i)
{
fprintf(stderr, "%s ", error_stack[i]);
}
fprintf(stderr, "\n");
}
char *error_get(void)
{
if (N > 0)
{
return error_stack[--N];
}
else
{
return NULL;
}
}
void error_clear(void)
{
N = 0;
}

16
src/error.h Normal file
View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2017 Brian Barto
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GPL License. See LICENSE for more details.
*/
#ifndef ERROR_H
#define ERROR_H 1
void error_log(char *, ...);
void error_print(void);
char *error_get(void);
void error_clear(void);
#endif

166
src/input.c Normal file
View File

@ -0,0 +1,166 @@
/*
* Copyright (c) 2017 Brian Barto
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GPL License. See LICENSE for more details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <time.h>
#include <errno.h>
#include "input.h"
#include "error.h"
int input_get(unsigned char** dest, char *prompt)
{
int r, input_len;
fd_set input_stream;
struct timeval timeout;
void *timeout_p;
FD_ZERO(&input_stream);
input_len = 0;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
if (isatty(STDIN_FILENO))
{
timeout_p = NULL;
if (prompt != NULL)
{
printf("%s", prompt);
fflush(stdout);
}
}
else
{
timeout_p = &timeout;
}
FD_SET(STDIN_FILENO, &input_stream);
r = select(FD_SETSIZE, &input_stream, NULL, NULL, timeout_p);
if (r < 0)
{
error_log("Error while waiting for input data. Errno: %i", errno);
return -1;
}
if (r > 0)
{
r = ioctl(STDIN_FILENO, FIONREAD, &input_len);
if (r < 0)
{
error_log("Could not determine length of input. Errno: %i", errno);
return -1;
}
if (input_len > 0)
{
*dest = malloc(input_len);
if (*dest == NULL)
{
error_log("Memory allocation error.");
return -1;
}
r = read(STDIN_FILENO, *dest, input_len);
if (r < 0)
{
error_log("Input read error. Errno: %i", errno);
return -1;
}
}
}
FD_CLR(STDIN_FILENO, &input_stream);
return input_len;
}
int input_get_str(char** dest, char *prompt)
{
int r, i, input_len;
unsigned char *input;
r = input_get(&input, prompt);
if (r < 0)
{
error_log("Could not get input.");
return -1;
}
if (r > 0)
{
if (input[r - 1] == '\n')
{
--r;
if (r > 0 && input[r - 1] == '\r')
{
--r;
}
}
}
if (r == 0)
{
error_log("No input provided.");
return -1;
}
input_len = r;
*dest = malloc(input_len + 1);
if (*dest == NULL)
{
error_log("Memory allocation error.");
return -1;
}
memset(*dest, 0, input_len + 1);
for (i = 0; i < input_len; ++i)
{
if (isascii(input[i]))
{
(*dest)[i] = input[i];
}
else
{
error_log("Input contains non-ascii characters.");
return -1;
}
}
free(input);
return input_len;
}
int input_get_from_pipe(unsigned char** dest)
{
int r;
if (isatty(STDIN_FILENO))
{
error_log("Input data from a piped or redirected source is required.");
return -1;
}
r = input_get(dest, NULL);
if (r < 0)
{
error_log("Could not get input.");
return -1;
}
if (r == 0)
{
error_log("No input provided.");
return -1;
}
return r;
}

15
src/input.h Normal file
View File

@ -0,0 +1,15 @@
/*
* Copyright (c) 2017 Brian Barto
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GPL License. See LICENSE for more details.
*/
#ifndef INPUT_H
#define INPUT_H 1
int input_get(unsigned char** dest, char *prompt);
int input_get_str(char** dest, char *prompt);
int input_get_from_pipe(unsigned char** dest);
#endif

View File

@ -10,16 +10,17 @@
#include <unistd.h>
#include <ctype.h>
#include "nmseffect.h"
#include "input.h"
#include "error.h"
#define VERSION "0.3.3"
#define INITIAL_CAPACITY 50
#define INPUT_GROWTH_FACTOR 2
int main(int argc, char *argv[]) {
int c, o, i, inCapacity = INITIAL_CAPACITY;
char *input = NULL;
int r, o;
unsigned char *input;
input = NULL;
// Processing command arguments
while ((o = getopt(argc, argv, "f:ascv")) != -1) {
switch (o) {
case 'f':
@ -46,31 +47,23 @@ int main(int argc, char *argv[]) {
}
}
// Allocate memory for our input buffer
if ((input = malloc(inCapacity + 1)) == NULL) {
fprintf (stderr, "Memory Allocation Error! Quitting...\n");
return 1;
r = input_get(&input, "Enter input: ");
if (r < 0)
{
error_log("Could not get input.");
error_print();
return EXIT_FAILURE;
}
else if (r == 0)
{
error_log("Input is empty.");
error_print();
return EXIT_FAILURE;
}
// Geting input
for (i = 0; (c = getchar()) != EOF; ++i) {
if (i >= inCapacity) {
inCapacity *= INPUT_GROWTH_FACTOR;
input = realloc(input, inCapacity + 1);
if (input == NULL) {
fprintf (stderr, "Memory Allocation Error! Quitting...\n");
return 1;
}
}
input[i] = c;
input[i+1] = '\0';
}
r = nmseffect_exec(input, r);
// Execute effect
c = nmseffect_exec(input);
// Free allocated memory (not necessary here, but good practice)
free(input);
return 0;
return EXIT_SUCCESS;
}

View File

@ -58,20 +58,14 @@ static void nmseffect_sleep(int);
* string that is provided as an argument. It returns the last character
* pressed by the user.
*/
char nmseffect_exec(char *string) {
char nmseffect_exec(unsigned char *string, int string_len) {
struct charAttr *list_pointer = NULL;
struct charAttr *list_head = NULL;
struct charAttr *list_temp = NULL;
int i, revealed = 0;
int i, l, revealed = 0;
int maxRows, maxCols, curRow, curCol, origRow = 0, origCol = 0;
char ret = 0;
// Error if we have an empty string.
if (string == NULL || string[0] == '\0') {
fprintf(stderr, "Error. Empty string.\n");
return 0;
}
// Reassociate STDIN to the terminal if needed
if (!isatty(STDIN_FILENO) && !freopen ("/dev/tty", "r", stdin)) {
fprintf(stderr, "Error. Can't associate STDIN with terminal.\n");
@ -108,7 +102,7 @@ char nmseffect_exec(char *string) {
curCol = origCol;
// Processing input
for (i = 0; string[i] != '\0'; ++i) {
for (i = 0; i < string_len; ++i) {
// Don't go beyond maxRows
if (curRow - origRow >= maxRows - 1) {
@ -125,11 +119,12 @@ char nmseffect_exec(char *string) {
}
// Get character's byte-length and store character.
if (mblen(&string[i], 4) > 0) {
list_pointer->source = malloc(mblen(&string[i], 4) + 1);
strncpy(list_pointer->source, &string[i], mblen(&string[i], 4));
list_pointer->source[mblen(&string[i], 4)] = '\0';
i += (mblen(&string[i], 4) - 1);
l = mblen((char *)&string[i], 4);
if (l > 0) {
list_pointer->source = malloc(l + 1);
memcpy(list_pointer->source, &string[i], l);
list_pointer->source[l] = '\0';
i += (l - 1);
} else {
fprintf(stderr, "Unknown character encountered. Quitting.\n");
nmstermio_restore_terminal();

View File

@ -9,7 +9,7 @@
#define NMSEFFECT_H 1
// Function prototypes
char nmseffect_exec(char *);
char nmseffect_exec(unsigned char *, int string_len);
void nmseffect_set_foregroundcolor(char *);
void nmseffect_set_returnopts(char *);
void nmseffect_set_autodecrypt(int);