/* Copyright (C) 2017-2020, Dirk Krause SPDX-License-Identifier: BSD-3-Clause */ /* WARNING: This file was generated by the dkct program (see http://dktools.sourceforge.net/ for details). Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk3strkv.ctr */ /** @file dk3strkv.c The dk3strkv module. */ /** States for state machine dk3strkv_stm. */ enum { /** State: Expect double quoted value */ #line 44 "dk3strkv.ctr" ST_DQ_EXPECT = 0, /** State: Having double quoted value */ #line 46 "dk3strkv.ctr" ST_DQ_VALUE = 1, /** State: Error occured */ #line 47 "dk3strkv.ctr" ST_ERROR = 2, /** State: Expect value */ #line 41 "dk3strkv.ctr" ST_EXPECT = 3, /** State: In a key */ #line 40 "dk3strkv.ctr" ST_KEY = 4, /** State: Expect single quoted value */ #line 43 "dk3strkv.ctr" ST_SQ_EXPECT = 5, /** State: Having single quoted value */ #line 45 "dk3strkv.ctr" ST_SQ_VALUE = 6, /** State: Waiting for anything to happen */ #line 39 "dk3strkv.ctr" ST_START = 7, /** State: Having value */ #line 42 "dk3strkv.ctr" ST_VALUE = 8 }; /** Inputs for state machine dk3strkv_stm. */ enum { /** State machine input: Backslash */ #line 53 "dk3strkv.ctr" I_BS = 0, /** State machine input: Double quote */ #line 52 "dk3strkv.ctr" I_DQ = 1, /** State machine input: Equal sign */ #line 54 "dk3strkv.ctr" I_EQ = 2, /** State machine input: Any other character */ #line 49 "dk3strkv.ctr" I_OT = 3, /** State machine input: Single quote */ #line 51 "dk3strkv.ctr" I_SQ = 4, /** State machine input: White space */ #line 50 "dk3strkv.ctr" I_WH = 5 }; /** Outputs for state machine dk3strkv_stm. */ enum { /** State machine output: End key string and count upwards */ #line 61 "dk3strkv.ctr" O_ENDCOUNT = 0, /** State machine output: End key string (change to finalizer) */ #line 60 "dk3strkv.ctr" O_ENDKEY = 1, /** State machine output: End value string (change to finalizer) */ #line 62 "dk3strkv.ctr" O_ENDVAL = 2, /** State machine output: Error occured */ #line 56 "dk3strkv.ctr" O_ERROR = 3, /** State machine output: Do nothing */ #line 57 "dk3strkv.ctr" O_NO = 4, /** State machine output: Start and end value */ #line 65 "dk3strkv.ctr" O_SEVAL = 5, /** State machine output: Start key */ #line 59 "dk3strkv.ctr" O_SKEY = 6, /** State machine output: Squeeze */ #line 58 "dk3strkv.ctr" O_SQ = 7, /** State machine output: Squeeze and start value */ #line 64 "dk3strkv.ctr" O_SQ_SVAL = 8, /** State machine output: Start value */ #line 63 "dk3strkv.ctr" O_SVAL = 9 }; /** Reset dk3strkv_stm state machine. @param st Pointer to state variable. */ static void dk3strkv_stm_reset(int *st) { if(st) { *st = ST_START; } } /** State machine dk3strkv_stm step. @param st Pointer to state variable. @param in Input. @return Transition output. */ static int dk3strkv_stm_step(int *st, int in) { int back = O_ERROR; if(st) { int os; int nf = 1; int ns = ST_ERROR; os = *st; switch(os) { case ST_DQ_EXPECT: { switch(in) { case I_BS: { ns = ST_DQ_VALUE; back = O_SQ_SVAL; nf = 0; } break; case I_DQ: { ns = ST_START; back = O_SEVAL; nf = 0; } break; } } break; case ST_DQ_VALUE: { switch(in) { case I_BS: { ns = ST_DQ_VALUE; back = O_SQ; nf = 0; } break; case I_DQ: { ns = ST_START; back = O_ENDVAL; nf = 0; } break; } } break; case ST_EXPECT: { switch(in) { case I_BS: { ns = ST_VALUE; back = O_SQ_SVAL; nf = 0; } break; case I_DQ: { ns = ST_DQ_EXPECT; back = O_NO; nf = 0; } break; case I_SQ: { ns = ST_SQ_EXPECT; back = O_NO; nf = 0; } break; case I_WH: { ns = ST_EXPECT; back = O_NO; nf = 0; } break; } } break; case ST_KEY: { switch(in) { case I_EQ: { ns = ST_EXPECT; back = O_ENDKEY; nf = 0; } break; case I_WH: { ns = ST_START; back = O_ENDCOUNT; nf = 0; } break; } } break; case ST_SQ_EXPECT: { switch(in) { case I_BS: { ns = ST_SQ_VALUE; back = O_SQ_SVAL; nf = 0; } break; case I_SQ: { ns = ST_START; back = O_SEVAL; nf = 0; } break; } } break; case ST_SQ_VALUE: { switch(in) { case I_BS: { ns = ST_SQ_VALUE; back = O_SQ; nf = 0; } break; case I_SQ: { ns = ST_START; back = O_ENDVAL; nf = 0; } break; } } break; case ST_START: { switch(in) { case I_OT: { ns = ST_KEY; back = O_SKEY; nf = 0; } break; case I_WH: { ns = ST_START; back = O_NO; nf = 0; } break; } } break; case ST_VALUE: { switch(in) { case I_BS: { ns = ST_VALUE; back = O_SQ; nf = 0; } break; case I_WH: { ns = ST_START; back = O_ENDVAL; nf = 0; } break; } } break; } if(nf) { if(os == ST_KEY) { ns = ST_KEY; back = O_NO; } else { if(os == ST_EXPECT) { ns = ST_VALUE; back = O_SVAL; } else { if(os == ST_VALUE) { ns = ST_VALUE; back = O_NO; } else { if(os == ST_SQ_EXPECT) { ns = ST_SQ_VALUE; back = O_SVAL; } else { if(os == ST_SQ_VALUE) { ns = ST_SQ_VALUE; back = O_NO; } else { if(os == ST_DQ_EXPECT) { ns = ST_DQ_VALUE; back = O_SVAL; } else { if(os == ST_DQ_VALUE) { ns = ST_DQ_VALUE; back = O_NO; } else { } } } } } } } } *st = ns; } else { } return back; } #line 103 "dk3strkv.ctr" #include "dk3all.h" #include "dk3strkv.h" /** Classify input character @param c Character to classify. @return Character class. */ static int dk3strkv_classify(dkChar c) { int back = I_OT; #line 120 "dk3strkv.ctr" switch(c) { case dkT(' '): case dkT('\t'): { back = I_WH; } break; case dkT('"'): { back = I_DQ; } break; case dkT('\''): { back = I_SQ; } break; case dkT('\\'): { back = I_BS; } break; case dkT('='): { back = I_EQ; } break; } #line 137 "dk3strkv.ctr" return back; } /** Empty line. */ static dkChar const dk3strkv_empty_line[] = { dkT("") }; /** Report error for unexpected end of text. @param app Application structure for diagnostics, may be NULL. @param il Input line to complain about. */ static void dk3strkv_error_unexpected_eot(dk3_app_t *app, dkChar *il) { dkChar const *ptr; if(app) { ptr = il; if(!(ptr)) { ptr = dk3strkv_empty_line; } dk3app_log_i3(app, DK3_LL_ERROR, 389, 390, ptr); } } /** Report error, too many key value items. @param app Application structure for diagnostics, may be NULL. @param il Input line to complain about. @param pos Position in line. */ static void dk3strkv_error_too_many(dk3_app_t *app, dkChar *il, unsigned long pos) { dkChar buffer[64]; dkChar const *ptr; if(app) { ptr = il; if(!(ptr)) { ptr = dk3strkv_empty_line; } #if VERSION_BEFORE_20140716 dk3sf_sprintf3(buffer, dkT("%lu"), pos); dk3app_log_i5(app, DK3_LL_ERROR, 386, 387, 388, buffer, ptr); #else if (dk3ma_um_to_string(buffer, DK3_SIZEOF(buffer, dkChar), (dk3_um_t)pos)) { dk3app_log_i5(app, DK3_LL_ERROR, 386, 387, 388, buffer, ptr); } #endif } } int dk3str_to_key_value( dk3_key_value_t *kvp, size_t *szp, dkChar *il, dk3_app_t *app ) { dkChar *ptr; /* Traverse string. */ dkChar *mycopy; /* Private copy for diagnostics. */ unsigned long charno; /* Character number. */ size_t i; /* Current key value pair index. */ int icl; /* Input class. */ int act; /* Action to take. */ int stm; /* State machine. */ int cc; /* Flag: Can continue. */ int rtm = 0; /* Reported too many. */ int error = 0; /* Flag: Have error. */ int back = 0; #line 214 "dk3strkv.ctr" if((kvp) && (szp)) { for(i = 0; i < *szp; i++) { kvp[i].key = NULL; kvp[i].val = NULL; } } if((kvp) && (szp) && (il)) { if(*szp) { mycopy = dk3str_dup_app(il, app); i = 0; ptr = il; cc = 1; charno = 1UL; dk3strkv_stm_reset(&stm); while(cc) { if(*ptr) { #line 225 "dk3strkv.ctr" icl = dk3strkv_classify(*ptr); #line 226 "dk3strkv.ctr" act = dk3strkv_stm_step(&stm, icl); #line 227 "dk3strkv.ctr" switch(act) { case O_ERROR: { #line 229 "dk3strkv.ctr" error = 1; } break; case O_SQ: { #line 232 "dk3strkv.ctr" dk3str_cpy(ptr, &(ptr[1])); if(*ptr) { charno++; } else { cc = 0; error = 1; dk3strkv_error_unexpected_eot(app, mycopy); } } break; case O_SKEY: { #line 242 "dk3strkv.ctr" if(i < (*szp)) { kvp[i].key = ptr; } else { error = 1; if(0 == rtm) { rtm = 1; dk3strkv_error_too_many(app, mycopy, charno); } } } break; case O_ENDKEY: { #line 253 "dk3strkv.ctr" *ptr = dkT('\0'); } break; case O_ENDCOUNT: { #line 256 "dk3strkv.ctr" *ptr = dkT('\0'); i++; } break; case O_ENDVAL: { #line 260 "dk3strkv.ctr" *ptr = dkT('\0'); i++; } break; case O_SVAL: { #line 264 "dk3strkv.ctr" if(i < (*szp)) { kvp[i].val = ptr; } else { error = 1; if(0 == rtm) { rtm = 1; dk3strkv_error_too_many(app, mycopy, charno); } } } break; case O_SQ_SVAL: { #line 275 "dk3strkv.ctr" dk3str_cpy(ptr, &(ptr[1])); if(*ptr) { charno++; if(i < (*szp)) { kvp[i].val = ptr; } else { error = 1; if(0 == rtm) { rtm = 1; dk3strkv_error_too_many(app, mycopy, charno); } } } else { cc = 0; error = 1; dk3strkv_error_unexpected_eot(app, mycopy); } } break; case O_SEVAL: { #line 294 "dk3strkv.ctr" *ptr = dkT('\0'); if(i < (*szp)) { kvp[i].val = ptr; i++; } else { error = 1; if(0 == rtm) { rtm = 1; dk3strkv_error_too_many(app, mycopy, charno); } } } break; } ptr++; charno++; } else { cc = 0; } } switch(stm) { case ST_START: { #line 315 "dk3strkv.ctr" if(0 == error) { back = 1; *szp = i; } } break; case ST_KEY: { #line 321 "dk3strkv.ctr" if(0 == error) { i++; back = 1; *szp = i; } } break; case ST_VALUE: { #line 328 "dk3strkv.ctr" if(0 == error) { i++; back = 1; *szp = i; } } break; } dk3_release(mycopy); } } else { if((kvp) && (szp) && (!(il))) { *szp = 0; back = 1; } } #line 343 "dk3strkv.ctr" return back; }