From 3e84d4b96c822568b9a6f45f14726e3c5bbf989b Mon Sep 17 00:00:00 2001 From: Terje Io Date: Sun, 23 Feb 2025 22:36:24 +0100 Subject: [PATCH] Imported string utilities from networking plugin, increased max named parameter length to 30. --- CMakeLists.txt | 1 + changelog.md | 15 +++ grbl.h | 2 +- ngc_params.h | 2 +- strutils.c | 337 +++++++++++++++++++++++++++++++++++++++++++++++++ strutils.h | 50 ++++++++ 6 files changed, 405 insertions(+), 2 deletions(-) create mode 100644 strutils.c create mode 100644 strutils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e7bb73d..012da35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ target_sources(grbl INTERFACE ${CMAKE_CURRENT_LIST_DIR}/stream_passthru.c ${CMAKE_CURRENT_LIST_DIR}/stepper.c ${CMAKE_CURRENT_LIST_DIR}/stepper2.c + ${CMAKE_CURRENT_LIST_DIR}/strutils.c ${CMAKE_CURRENT_LIST_DIR}/system.c ${CMAKE_CURRENT_LIST_DIR}/tool_change.c ${CMAKE_CURRENT_LIST_DIR}/alarms.c diff --git a/changelog.md b/changelog.md index a605d56..3b56655 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,20 @@ ## grblHAL changelog +Build 20250223 + +Core: + +* Imported string utilities from networking plugin, increased max named parameter length to 30. + +Plugins: + +* Networking and WebUI: updated for move of string utilities to the core. + +* Plasma: enhanced basic materials support and added import of LinuxCNC and SheetCam style [material files](https://github.com/grblHAL/Plugin_plasma#materials). + Added support for setting feedrate via named parameter set from value in seleced material. + +--- + Build 20250222 Core: diff --git a/grbl.h b/grbl.h index 2f7fcb1..e28d97a 100644 --- a/grbl.h +++ b/grbl.h @@ -42,7 +42,7 @@ #else #define GRBL_VERSION "1.1f" #endif -#define GRBL_BUILD 20250222 +#define GRBL_BUILD 20250223 #define GRBL_URL "https://github.com/grblHAL" diff --git a/ngc_params.h b/ngc_params.h index 70df6a7..3e3a3be 100644 --- a/ngc_params.h +++ b/ngc_params.h @@ -31,7 +31,7 @@ #include "gcode.h" #ifndef NGC_MAX_PARAM_LENGTH -#define NGC_MAX_PARAM_LENGTH 20 +#define NGC_MAX_PARAM_LENGTH 30 #endif #define NGC_MAX_PARAM_ID 65535 diff --git a/strutils.c b/strutils.c new file mode 100644 index 0000000..050e24f --- /dev/null +++ b/strutils.c @@ -0,0 +1,337 @@ +/* + strutils.c - a collection of useful string utilities + + Part of grblHAL + + Copyright (c) 2019-2024 Terje Io + + grblHAL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + grblHAL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with grblHAL. If not, see . +*/ + +#include +#include +#include +#include +#include + +#include "strutils.h" + +#define CAPS(c) ((c >= 'a' && c <= 'z') ? c & 0x5F : c) + +/*! \brief Case insensitive search for first occurrence of a string inside another. +\param s1 pointer to string to search. +\param s2 pointer to string to search for. +\returns pointer to found string or NULL if not found. +*/ +char *stristr (const char *s1, const char *s2) +{ + const char *s = s1, *p = s2, *r = NULL; + + if (!s2 || strlen(s2) == 0) + return (char *)s1; + + while(*s && *p) { + + if(CAPS(*p) == CAPS(*s)) { + if(!r) + r = s; + p++; + } else { + p = s2; + if(r) + s = r + 1; + if(CAPS(*p) == CAPS(*s)) { + r = s; + p++; + } else + r = NULL; + } + s++; + } + + return *p ? NULL : (char *)r; +} + +/*! \brief Case insensitive search for first occurrence of a string inside another. +\param s1 pointer to string to search. +\param s2 pointer to string to search for. +\param len max. number of characters to compare. +\returns pointer to found string or NULL if not found. +*/ +char *strnistr (const char *s1, const char *s2, size_t len) +{ + size_t slen = len; + const char *s = s1, *p = s2, *r = NULL; + + if (!s2 || strlen(s2) == 0 || len == 0) + return (char *)s1; + + while(slen && *s && *p) { + + if(CAPS(*p) == CAPS(*s)) { + if(!r) + r = s; + p++; + } else { + p = s2; + slen = len; + if(r) + s = r + 1; + if(CAPS(*p) == CAPS(*s)) { + r = s; + p++; + } else + r = NULL; + } + s++; + if(r) + slen--; + } + + return slen == 0 || *p == '\0' ? (char *)r : NULL; +} + +// NOTE: ensure buf is large enough to hold concatenated strings! +char *strappend (char *buf, int argc, ...) +{ + char c, *s = buf, *arg; + + va_list list; + va_start(list, argc); + + while(argc--) { + arg = va_arg(list, char *); + do { + c = *s++ = *arg++; + } while(c); + s--; + } + + va_end(list); + + return buf; +} + +uint32_t strnumentries (const char *s, const char delimiter) +{ + char *p = (char *)s; + uint32_t entries = *s ? 1 : 0; + + while(entries && (p = strchr(p, delimiter))) { + p++; + entries++; + } + + return entries; +} + +char *strgetentry (char *res, const char *s, uint32_t entry, const char delimiter) +{ + char *e, *p = (char *)s; + + *res = '\0'; + e = strchr(p, delimiter); + + if(entry == 0 && e == NULL) + strcpy(res, s); + else do { + if(entry) { + p = e; + e = strchr(++p, delimiter); + entry--; + } else { + if(e) { + strncpy(res, p, e - p); + res[e - p] = '\0'; + } else + strcpy(res, p); + break; + } + } while(true); + + return res; +} + +int32_t strlookup (const char *s1, const char *s2, const char delimiter) +{ + bool found = false; + char *e, *p = (char *)s2; + uint32_t idx = strnumentries(s2, delimiter), len = strlen(s1); + int32_t entry = 0; + + while(idx--) { + + if((e = strchr(p, delimiter))) + found = (e - p) == len && !strncmp(p, s1, e - p); + else + found = strlen(p) == len && !strcmp(p, s1); + + if(found || e == NULL) + break; + else { + p = e + 1; + entry++; + } + } + + return found ? entry : -1; +} + +bool strtotime (char *s, struct tm *time) +{ + char c, *s1 = s; + uint_fast16_t idx = 0; + + if(s == NULL || time == NULL) + return false; + + while((c = *s1)) { + if(c == ':') + *s1 = ' '; + s1++; + } + + if(strchr(s, ',')) { // "text format" + + s1 = strtok(s + 5, " "); + while(s1) { + + switch(idx) { + + case 0: + time->tm_mday = atoi(s1); + break; + + case 1: + time->tm_mon = strlookup(s1, "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", ','); + break; + + case 2: + time->tm_year = atoi(s1) - 1900; + break; + + case 3: + time->tm_hour = atoi(s1); + break; + + case 4: + time->tm_min = atoi(s1); + break; + + case 5: + time->tm_sec = atoi(s1); + break; + } + idx++; + s1 = strtok(NULL, " "); + } + } else { // ISO8601 format + + s1 = s; + + while((c = *s1)) { + if(c == '-' || c == 'T') + *s1 = ' '; + else if(c == 'Z') + *s1 = '\0'; + s1++; + } + + s1 = strtok(s, " "); + while(s1) { + + switch(idx) { + + case 0: + time->tm_year = atoi(s1) - 1900; + break; + + case 1: + time->tm_mon = atoi(s1) - 1; + break; + + case 2: + time->tm_mday = atoi(s1); + break; + + case 3: + time->tm_hour = atoi(s1); + break; + + case 4: + time->tm_min = atoi(s1); + break; + + case 5: + time->tm_sec = atoi(s1); + break; + } + idx++; + s1 = strtok(NULL, " "); + } + } + + return idx >= 5; +} + +char *strtoisodt (struct tm *dt) +{ + static char buf[21]; + + if(dt == NULL || snprintf(buf, sizeof(buf), "%04i-%02i-%02iT%02i:%02i:%02i", dt->tm_year < 1000 ? dt->tm_year + 1900 : dt->tm_year, dt->tm_mon + 1, dt->tm_mday, dt->tm_hour, dt->tm_min, dt->tm_sec) > sizeof(buf)) + *buf = '\0'; + + return buf; +} + +char *strtointernetdt (struct tm *dt) +{ + static const char *month_table[12] = { + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + }; + + static const char *day_table[7] = { + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat" + }; + + static char buf[31]; + +#ifdef __MSP432E401Y__ + return "Thu, 01 Jan 1970 00:00:00 GMT"; // snprintf below crashes the MCU! +#else + + if(dt == NULL || snprintf(buf, sizeof(buf), "%s, %02d %s %04d %02d:%02d:%02d GMT", day_table[dt->tm_wday], dt->tm_mday, month_table[dt->tm_mon], dt->tm_year < 1000 ? dt->tm_year + 1900 : dt->tm_year, dt->tm_hour, dt->tm_min, dt->tm_sec) > sizeof(buf)) + return "Thu, 01 Jan 1970 00:00:00 GMT"; + + return buf; + +#endif +} diff --git a/strutils.h b/strutils.h new file mode 100644 index 0000000..4c8dfc2 --- /dev/null +++ b/strutils.h @@ -0,0 +1,50 @@ +/* + strutils.h - a collection of useful string utilities + +Copyright (c) 2019-2022 Terje Io +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its contributors may +be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __STRUTILS_H__ +#define __STRUTILS_H___ + +#include +#include + +char *stristr(const char *s1, const char *s2); +char *strnistr (const char *s1, const char *s2, size_t len); +char *strappend (char *buf, int argc, ...); +uint32_t strnumentries (const char *s, const char delimiter); +char *strgetentry (char *res, const char *s, uint32_t entry, const char delimiter); +int32_t strlookup (const char *s1, const char *s2, const char delimiter); +bool strtotime (char *s, struct tm *time); +char *strtoisodt (struct tm *dt); +char *strtointernetdt (struct tm *dt); + +#endif