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:
parent
86181d9b52
commit
d921892576
2
Makefile
2
Makefile
@ -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
56
src/error.c
Normal 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
16
src/error.h
Normal 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
166
src/input.c
Normal 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
15
src/input.h
Normal 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
|
47
src/nms.c
47
src/nms.c
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user