File:  [Coherent Logic Development] / freem / src / strings.c
Revision 1.4: download - view: text, annotated - select for diffs
Wed Apr 9 19:52:02 2025 UTC (5 months, 1 week ago) by snw
Branches: MAIN
CVS tags: HEAD
Eliminate as many warnings as possible while building with -Wall

    1: /*
    2:  *   $Id: strings.c,v 1.4 2025/04/09 19:52:02 snw Exp $
    3:  *    freem string library
    4:  *
    5:  *  
    6:  *   Author: Serena Willis <snw@coherent-logic.com>
    7:  *    Copyright (C) 1998 MUG Deutschland
    8:  *    Copyright (C) 2020, 2025 Coherent Logic Development LLC
    9:  *
   10:  *
   11:  *   This file is part of FreeM.
   12:  *
   13:  *   FreeM is free software: you can redistribute it and/or modify
   14:  *   it under the terms of the GNU Affero Public License as published by
   15:  *   the Free Software Foundation, either version 3 of the License, or
   16:  *   (at your option) any later version.
   17:  *
   18:  *   FreeM is distributed in the hope that it will be useful,
   19:  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   20:  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   21:  *   GNU Affero Public License for more details.
   22:  *
   23:  *   You should have received a copy of the GNU Affero Public License
   24:  *   along with FreeM.  If not, see <https://www.gnu.org/licenses/>.
   25:  *
   26:  *   $Log: strings.c,v $
   27:  *   Revision 1.4  2025/04/09 19:52:02  snw
   28:  *   Eliminate as many warnings as possible while building with -Wall
   29:  *
   30:  *   Revision 1.3  2025/03/09 19:50:47  snw
   31:  *   Second phase of REUSE compliance and header reformat
   32:  *
   33:  *
   34:  * SPDX-FileCopyrightText:  (C) 2025 Coherent Logic Development LLC
   35:  * SPDX-License-Identifier: AGPL-3.0-or-later
   36:  **/
   37: 
   38: #include "mpsdef.h"
   39: #include <ctype.h>
   40: #include <stdarg.h>
   41: #include <string.h>
   42: #include <stdlib.h>
   43: 
   44: /* length of 'source' string in bytes */
   45: long int stlen (const char *source)				
   46: {
   47:     register int length = 0;
   48: 
   49:     while (*source++ != EOL) length++;
   50: 
   51:     return length;
   52: }
   53: 
   54: long int stnlen (const char *source, size_t siz)
   55: {
   56:     register int length = 0;
   57: 
   58:     while ((*source++ != EOL) && (length < siz)) length++;
   59: 
   60:     return length;
   61: }
   62: 
   63: /* copy string from 'source' to 'dest' */
   64: long int stcpy (char *dest, const char *source)			
   65: {
   66:     register int count = 0;
   67: 
   68:     while ((*dest++ = *source++) != EOL) count++;
   69: 
   70:     return count;
   71: }
   72: 
   73: long int stncpy (char *dest, const char *source, size_t siz)
   74: {
   75:     register int count = 0;
   76: 
   77:     while (((*dest++ = *source++) != EOL) && (count < siz)) count++;
   78: 
   79:     return count;
   80: }
   81:     
   82: 
   83: /* copy exactly 'length' characters from source to dest */
   84: void stcpy0 (char *dest, const char *source, long length)		
   85: {
   86:     while (length-- > 0) *dest++ = *source++;
   87: 
   88:     return;
   89: }
   90: 
   91: 
   92: /* copy exactly 'length' characters from source to dest*/
   93: void stcpy1 (char *dest, const char *source, long length)		
   94: {
   95:     while (length-- > 0) *dest-- = *source--;
   96: 
   97:     return;
   98: }
   99: 
  100: 
  101: /* concatenate string from 'source' to the end of 'dest' */
  102: short int stcat (char *dest, const char *source)
  103: {
  104:     register int i = 0;
  105: 
  106:     while (dest[i++] != EOL);
  107: 
  108:     i--;
  109:     
  110:     while ((dest[i] = *source++) != EOL) {
  111: 	   
  112:        if (i++ >= STRLEN) {
  113:            //printf("i = %d\r\n", i);
  114:            dest[--i] = EOL;	   
  115:            return FALSE;
  116:        }
  117: 
  118:     }
  119: 
  120:     return TRUE;
  121: }
  122: 
  123: /* compare str1 and str2 */
  124: short int stcmp (char *str1, char *str2)			
  125: {
  126:     while (*str1 == *str2) {
  127: 	
  128:         if (*str1 == EOL) return 0;
  129: 	
  130:         str1++;
  131:         str2++;
  132: 
  133:     }
  134:     
  135:     return *str1 - *str2;
  136: }
  137: 
  138: /* trim whitespace from string 's' */
  139: char *trim (char *s)
  140: {
  141:     
  142:     char *t = strdup (s);
  143:     char *end;
  144:     char *result;
  145:     int final_len;
  146:     
  147:     if (t == NULL) return NULL;
  148: 
  149:     while (isspace ((unsigned char) *t)) t++;
  150: 
  151:     if (*t == 0) return t;
  152: 
  153:     end = t + strlen (t) - 1;
  154: 
  155:     while (end > t && isspace ((unsigned char) *end)) end--;
  156: 
  157:     end[1] = '\0';
  158: 
  159:     /* recover waste ('t' still occupies the same heap
  160:      * as it did before the whitespace was stripped)
  161:      */
  162:     
  163:     final_len = strlen (t);
  164:     result = (char *) malloc ((final_len + 1) * sizeof (char));
  165: 
  166:     if (result == NULL) return NULL;
  167:     
  168:     strcpy (result, t);
  169:     free (t);
  170: 
  171:     return result;
  172: 
  173: }
  174: 
  175: 
  176: /* convert EOL-terminated string 'mstr' to NUL-terminated string in-place */
  177: void stcnv_m2c(char *mstr)
  178: {
  179:     mstr[stlen(mstr)] = NUL; 
  180: }
  181: 
  182: void stncnv_m2c(char *mstr, size_t siz)
  183: {
  184:     mstr[stnlen (mstr, siz)] = NUL;
  185: }      
  186: 
  187: /* convert NUL-terminated string 'cstr' to EOL-terminated string in-place */
  188: void stcnv_c2m(char *cstr)
  189: {
  190:     register int i;
  191:     
  192:     for(i = 0; i < 256; i++) {
  193: 
  194:         if(cstr[i] == '\0') {
  195:             cstr[i] = '\201';
  196:         
  197:             return;
  198:         }
  199:         
  200:     }
  201: }
  202: 
  203: void stncnv_c2m(char *cstr, size_t siz)
  204: {
  205:     register int i;
  206: 
  207:     for (i = 0; i < siz; i++) {
  208: 
  209:         if (cstr[i] == NUL) {
  210:             cstr[i] = EOL;
  211:             return;
  212:         }
  213:         
  214:     }
  215: 
  216:     return;
  217: }
  218: 
  219: /* convert at most 'count' characters of *key into human-readable format in *buf */
  220: size_t key_to_name(char *buf, const char *key, size_t count)
  221: {
  222:     size_t i;
  223:     int j = 0;
  224:     int first = 1;
  225:     int has_subs = 0;
  226:     int in_strlit = 0;
  227:     char c;
  228:     char next;
  229: 
  230:     if (key[0] == NUL) {
  231:         buf[0] = NUL;
  232: 
  233:         return 0;
  234:     }
  235: 
  236:     buf[0] = '^';
  237: 
  238:     for (i = 0; i < count; i++) {
  239: 
  240:         c = key[i];
  241:         next = key[i + 1];
  242:         
  243:         switch (c) {
  244: 
  245:             case EOL:
  246:                 
  247:                 if (first == 0) {
  248: 
  249:                     if (has_subs == 1) {
  250: 
  251:                         if (!in_strlit) {
  252:                             buf[j++] = ')';
  253:                             buf[j] = NUL;
  254:                         }
  255:                         else {
  256:                             buf[j++] = '\"';
  257:                             buf[j++] = ')';
  258:                             buf[j] = NUL;
  259:                         }
  260: 
  261:                     }
  262:                     else {                        
  263:                         buf[j] = NUL;
  264:                     }
  265: 
  266:                 }
  267:                 else {
  268:                     buf[j] = NUL;
  269:                 }
  270:                 
  271:                 return i;
  272: 
  273: 
  274:             case DELIM:
  275:                 
  276:                 if (first == 1) {
  277:                 
  278:                     buf[j] = '(';
  279:                     first = 0;
  280:                     has_subs = 1;                    
  281: 
  282:                 }
  283:                 else {
  284: 
  285:                     if (!in_strlit) {
  286:                         buf[j] = ',';
  287:                     }
  288:                     else {
  289: 
  290:                         buf[j++] = '\"';
  291:                         buf[j] = ',';
  292: 
  293:                         in_strlit = 0;
  294: 
  295:                     }
  296: 
  297:                 }
  298: 
  299:                 if (isalpha(next) && !in_strlit) {                    
  300:                     in_strlit = 1;
  301:                     buf[++j] = '\"';
  302:                 }
  303:                 else if (in_strlit) {
  304:                     in_strlit = 0;
  305:                     buf[++j] = '\"';
  306:                 }
  307:                 
  308:                 break;
  309: 
  310: 
  311:             default:
  312:                 buf[j] = key[i];
  313:                 break;
  314:         }
  315: 
  316:         j++;
  317:     }
  318: 
  319:     return count;
  320: 
  321: }
  322: 
  323: size_t name_to_key(char *buf, const char *name, size_t count)
  324: {
  325:     size_t i;
  326:     size_t j = 0;
  327: 
  328:     short insubs = FALSE;
  329:     short instr = FALSE;
  330: 
  331:     char ch;
  332: 
  333:     for (i = 0; i < count; i++) buf[i] = NUL;
  334: 
  335:     for (i = 0; i < count; i++) {
  336: 
  337:         ch = name[i];
  338: 
  339:         switch (ch) {
  340: 
  341:             case EOL:
  342:                 buf[j] = ch;
  343:                 goto n_to_k_done;
  344: 
  345:             case '(':
  346:                 if (insubs == FALSE && instr == FALSE) {
  347:                     insubs = TRUE;
  348:                     buf[j++] = DELIM;
  349:                 }
  350:                 else {
  351:                     if (instr == TRUE) {
  352:                         buf[j++] = ch;
  353:                     }
  354:                 }
  355:                 break;
  356: 
  357: 
  358:             case ')':
  359:                 if (insubs == TRUE && instr == FALSE) {
  360:                     buf[j] = EOL;
  361: 
  362:                     goto n_to_k_done;
  363:                 }
  364:                 else {
  365:                     if (insubs == TRUE && instr == TRUE) {
  366:                         buf[j++] = ch;                        
  367:                     }
  368:                 }
  369:                 break;
  370: 
  371: 
  372:             case ',':
  373:                 if (insubs == TRUE && instr == FALSE) {
  374:                     if (buf[j - 1] != DELIM) {
  375:                         buf[j++] = DELIM;
  376:                     }
  377:                 }
  378:                 else if (insubs == TRUE && instr == TRUE) {
  379:                     buf[j++] = ch;                    
  380:                 }
  381: 
  382:                 break;
  383: 
  384: 
  385:             case '"':
  386: 
  387:                 if (insubs == TRUE && instr == FALSE) {
  388:                     instr = TRUE;
  389:                     
  390:                     if (buf[j - 1] != DELIM) {
  391:                         buf[j++] = DELIM;
  392:                     }
  393:                     
  394:                     break;
  395:                 }
  396: 
  397:                 if (instr == TRUE) {
  398:                     instr = FALSE;
  399:                     buf[j++] = DELIM;
  400:                 }
  401: 
  402:                 break;
  403: 
  404: 
  405:             default:
  406:                 buf[j++] = ch;
  407:                 break;
  408:         }
  409: 
  410:     }
  411: 
  412: n_to_k_done:
  413: 
  414:     return j;
  415: 
  416: }
  417: 
  418: void create_var_key (char *buf, int subct, char *nam, ...)
  419: {
  420:     int i;
  421:     va_list args;
  422:     
  423:     strcat (buf, nam);
  424:     strcat (buf, "\202");
  425:     
  426:     va_start (args, nam);
  427: 
  428:     for (i = 0; i < subct; i++) {
  429:         
  430:         strcat (buf, va_arg (args, char *));
  431: 
  432:         if (i < (subct - 1)) strcat (buf, "\202");
  433: 
  434:     }
  435: 
  436:     va_end (args);
  437: 
  438:     strcat (buf, "\201");
  439: }
  440: 
  441: void trim_decimal (char *s)
  442: {
  443:     register int i;
  444: 
  445:     for (i = stlen (s) - 1; s[i] == '0'; i--) s[i] = EOL;
  446: 
  447:     if (s[i] == '.') s[i] = EOL;
  448: }
  449: 
  450: void uuid_v4 (char *buf)
  451: {
  452:     
  453:     char *chars = "0123456789abcdef";
  454:     int seg3num;
  455:     int seg4num;
  456:     int i;
  457: 
  458:     char seg1[9];
  459:     char seg2[5];
  460:     char seg3[5];
  461:     char seg4[5];
  462:     char seg5[13];
  463:     
  464:     seg3num = (rand () % 4095) + 16384;
  465:     seg4num = (rand () % 16383) + 32768;
  466: 
  467:     for (i = 0; i < 9; i++) {
  468:         seg1[i] = chars[rand () % 16];
  469:     }
  470: 
  471:     seg1[8] = '\0';
  472: 
  473:     for (i = 0; i < 4; i++) {
  474:         seg2[i] = chars[rand () % 16];
  475:     }
  476: 
  477:     seg2[4] = '\0';
  478: 
  479:     snprintf (seg3, 5, "%04x", seg3num);
  480:     snprintf (seg4, 5, "%04x", seg4num);
  481: 
  482:     for (i = 0; i < 12; i++) {
  483:         seg5[i] = chars[rand () % 16];
  484:     }
  485: 
  486:     seg5[12] = '\0';
  487: 
  488:     sprintf (buf, "%s-%s-%s-%s-%s", seg1, seg2, seg3, seg4, seg5);
  489: 
  490:     return;
  491:     
  492: }
  493: 
  494:         

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>