1%% options 2 3copyright owner = Dirk Krause 4copyright year = 2011-2018 5license = bsd 6 7 8 9%% header 10 11$* 12Function prototypes 13$* 14 15 16#ifdef __cplusplus 17extern "C" { 18#endif 19 20/** Test whether a string is an identifier. 21 @param test String to check. 22 @return 1 on success (string is identifier), 0 on error. 23*/ 24int test_identifier(char const *text); 25 26#ifdef __cplusplus 27} 28#endif 29 30 31 32%% module 33 34/* This program uses functions from the dk4str8.o module. 35 So you should use -ldk4base when linking. 36*/ 37 38#include <dk4conf.h> 39#include <dk4types.h> 40#include <stdio.h> 41#include <stdlib.h> 42#if DK3_HAVE_UNISTD_H 43#include <unistd.h> 44#endif 45#include <dk4str8.h> 46 47$!trace-include 48 49/** Help text, never used, just for demonstration. 50*/ 51static char const * const help_text1[] = { 52$!text preprocessor 53This help text is never shown, it is here just to demonstrate the 54use of the build-in $!text function. 55#ifdef _WIN32 56We are on a Windows system. 57#else 58We are not on a Windows system. 59#endif 60$!end 61}; 62 63/** Help text, never used, just for demonstration. 64*/ 65static char const * const help_text2[] = { 66$!text 67This help text is never shown, it is here just to demonstrate the 68use of the build-in $!text function. 69#Lines with raute are converted to text when the preprocessor 70option was not used. 71$!end 72}; 73 74/** Help text, never used, just for demonstration. 75*/ 76static dkChar const * const help_text3[] = { 77$!text macro=dkT 78This help text is never shown, it is here just to demonstrate the 79use of the macro functionality in the build-in $!text function. 80$!end 81}; 82 83/** Help text, never used, just for demonstration. 84*/ 85static wchar_t const * const help_text4[] = { 86$!text prefix=L 87This help text is never shown, it is here just to demonstrate the 88use of the prefix functionality in the build-in $!text function. 89$!end 90}; 91 92/** Find start of text (first non-whitespace). 93 @param t String to test. 94 @return Pointer to start of text or NULL. 95*/ 96static 97char * 98str_start(char *t) 99{ 100 char *back = NULL; 101 char *ptr; 102 ptr = t; 103 while((*ptr) && (back == NULL)) { 104 if(*ptr != ' ') { 105 if(*ptr != '\t') { 106 back = ptr; 107 } 108 } 109 ptr++; 110 } 111 return back; 112} 113 114/** Remove trailing newline. 115 @param t String to modify. 116*/ 117static 118void 119str_delnl(char *t) 120{ 121 char *ptr; 122 ptr = t; 123 while(*ptr) { 124 if(*ptr == '\r') *ptr = '\0'; 125 if(*ptr == '\n') *ptr = '\0'; 126 ptr++; 127 } 128} 129 130int test_identifier(char const *text) 131{ 132 int back = 0; 133 char const *ptr; 134 int state; 135 int i; 136 $? "+ test_identifier \"%s\"", TR_STR(text) 137 idtest_reset(&state); 138 ptr = text; 139 while(*ptr) { $? ". processing character %c", *ptr 140 if((*ptr >= 'A') && (*ptr <= 'Z')) { 141 i = I_CHAR; 142 } else { 143 if((*ptr >= 'a') && (*ptr <= 'z')) { 144 i = I_CHAR; 145 } else { 146 if((*ptr >= '0') && (*ptr <= '9')) { 147 i = I_DIGIT; 148 } else { 149 if(*ptr == '_') { 150 i = I_UNDER; 151 } else { 152 i = I_ANY; 153 } 154 } 155 } 156 } 157 (void)idtest_step(&state, i); 158 ptr++; 159 } 160 if(idtest_step(&state, I_END) == O_OK) { 161 back = 1; 162 } $? "- test_identifier %d", back 163 return back; 164} 165 166/** Main function. 167 @param argc Number of command line arguments. 168 @param argv Command line arguments array. 169*/ 170int main(int argc, char *argv[]) 171{ 172 char buffer[1024]; 173 char *p1; 174 int cc; 175 176 /* Debug output goes to test-ident.deb in the current directory */ 177 $!trace-init test-ident.deb 178 /* We are entering the main function */ 179 $? "+ main" 180 do { $? ". start of loop" 181 cc = 0; 182 if(fgets(buffer, sizeof(buffer), stdin)) { 183 p1 = dk4str8_start(buffer, NULL); 184 if(p1) { $? ". text found \"%s\"", p1 185 cc = 1; 186 dk4str_delnl(p1); 187 printf("%s %d\n", p1, test_identifier(p1)); 188 } 189 } 190 } while(cc); 191 /* We are about to leave the main function */ 192 $? "- main" 193 /* Close debug output file */ 194 $!trace-end 195 exit(0); return 0; 196} 197 198 199 200%% state machine 201 202[options] 203name = idtest 204write header = no 205 206[states] 207S_START # No character found yet. 208S_OK # Everything ok so far. 209S_ERROR # An error occured. 210 211[inputs] 212I_CHAR # Character. 213I_UNDER # Underscore. 214I_DIGIT # Digit. 215I_ANY # Any other input character. 216I_END # End of input. 217 218[outputs] 219O_ERROR # Error occured. 220O_OK # Everything ok so far. 221 222[rules] 223* * S_ERROR O_ERROR 224* I_END S_START O_ERROR 225S_START I_CHAR S_OK O_OK 226S_START I_UNDER S_OK O_OK 227S_OK I_CHAR S_OK O_OK 228S_OK I_UNDER S_OK O_OK 229S_OK I_DIGIT S_OK O_OK 230S_OK I_END S_START O_OK 231 232 233