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