123 lines
3.2 KiB
C
123 lines
3.2 KiB
C
#include "config.h"
|
|
#include "parsing.h"
|
|
#include "commands.h"
|
|
#include "uart.h"
|
|
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <util/delay.h>
|
|
|
|
// Read and parse command line and dispatch command
|
|
void parseNextCommand() {
|
|
const int bufferLength = 80;
|
|
char buffer[bufferLength];
|
|
|
|
// Read next command
|
|
CommandLine cmdLine = readNextCommand(buffer, bufferLength);
|
|
|
|
// Execute command
|
|
executeCommand(cmdLine);
|
|
}
|
|
|
|
// Read next command line from UART
|
|
CommandLine readNextCommand(char* buffer, uint8_t bufferLength) {
|
|
while (1) {
|
|
// Read next command
|
|
int readChars = uartGetLine(buffer, bufferLength);
|
|
|
|
if (readChars >= bufferLength - 1) {
|
|
// Reading was aborted after bufferLength-1 characters to prevent buffer overflow.
|
|
uartPutLine("ERROR buffer overflow, discarding line");
|
|
|
|
// Discard everything until we read an actual end of line
|
|
for (unsigned char c = 0; c != '\n' && c != '\r'; c = uartGetChar());
|
|
readChars = 0;
|
|
}
|
|
|
|
if (readChars != 0) {
|
|
return tokenizeCommand(buffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Splits a command "CMD ARGS" to two strings "CMD" and "ARGS". Returns pointer
|
|
// to "ARGS" or NULL if no arguments were found. Changes the input string!
|
|
CommandLine tokenizeCommand(char* cmd) {
|
|
CommandLine cmdLine = {
|
|
cmd,
|
|
NULL
|
|
};
|
|
|
|
if (cmd == NULL) {
|
|
return cmdLine;
|
|
}
|
|
|
|
// Search for a space character
|
|
for (char* p = cmd; *p != '\0'; p++) {
|
|
if (*p == ' ') {
|
|
// Split strings by replacing the space by \0, then set argument pointer.
|
|
*p++ = '\0';
|
|
cmdLine.arg = p;
|
|
break;
|
|
}
|
|
}
|
|
return cmdLine;
|
|
}
|
|
|
|
// Address parsing
|
|
bool parseSingleAddressTo(char* addressStr, address_t* address) {
|
|
if (addressStr == NULL || strlen(addressStr) != 4 || address == NULL) {
|
|
return false;
|
|
}
|
|
|
|
for (char* p = addressStr; *p != '\0'; p++) {
|
|
if ((*p < '0' || *p > '9') && (*p < 'A' || *p > 'F')) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
*address = strtol(addressStr, NULL, 16);
|
|
return true;
|
|
}
|
|
|
|
// Parses a single 2-byte hexadecimal address string "XXXX:YYYY" to an actual address.
|
|
AddressRange parseSingleAddress(char* addressStr) {
|
|
AddressRange range = {true, 0, 0};
|
|
if (!parseSingleAddressTo(addressStr, &range.from)) {
|
|
return (AddressRange) {false, 0, 0};
|
|
}
|
|
range.to = range.from;
|
|
return range;
|
|
}
|
|
|
|
// Parses a hexadecimal address range string "XXXX:YYYY" to actual addresses.
|
|
// A single address "XXXX" is equivalent to "XXXX:XXXX", with from == to.
|
|
AddressRange parseAddressRange(char* addressStr) {
|
|
if (addressStr == NULL) {
|
|
return (AddressRange) {false, 0, 0};
|
|
}
|
|
|
|
int len = strlen(addressStr);
|
|
if (len != 4 && len != 9) {
|
|
return (AddressRange) {false, 0, 0};
|
|
}
|
|
|
|
if (len == 9) {
|
|
if (addressStr[4] != ':') {
|
|
return (AddressRange) {false, 0, 0};
|
|
}
|
|
addressStr[4] = '\0';
|
|
}
|
|
|
|
AddressRange range = parseSingleAddress(addressStr);
|
|
|
|
if (range.isValid && len == 9) {
|
|
if (!parseSingleAddressTo(addressStr + 5, &range.to)) {
|
|
return (AddressRange) {false, 0, 0};
|
|
}
|
|
}
|
|
|
|
return range;
|
|
}
|