/*
	WARNING: This file was generated by dkct.
	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: test-ident.ctr
*/

/*
Copyright (C) 2011-2013, Dirk Krause

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 opyright 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 author nor the names of 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.
*/

/**	@file test-ident.c The test-ident module.
*/

/** @defgroup dkct_state_machine_idtest The idtest state machine. */
/**@{*/

#ifndef S_ERROR
/** State: An error occured. */
#line 163 "test-ident.ctr"
#define S_ERROR 0
#else
#line 163 "test-ident.ctr"
#error "Redefinition of S_ERROR"
#endif

#ifndef S_OK
/** State: Everything ok so far. */
#line 162 "test-ident.ctr"
#define S_OK 1
#else
#line 162 "test-ident.ctr"
#error "Redefinition of S_OK"
#endif

#ifndef S_START
/** State: No character found yet. */
#line 161 "test-ident.ctr"
#define S_START 2
#else
#line 161 "test-ident.ctr"
#error "Redefinition of S_START"
#endif

#ifndef I_ANY
/** State machine input: Any other input character. */
#line 169 "test-ident.ctr"
#define I_ANY 0
#else
#line 169 "test-ident.ctr"
#error "Redefinition of I_ANY"
#endif

#ifndef I_CHAR
/** State machine input: Character. */
#line 166 "test-ident.ctr"
#define I_CHAR 1
#else
#line 166 "test-ident.ctr"
#error "Redefinition of I_CHAR"
#endif

#ifndef I_DIGIT
/** State machine input: Digit. */
#line 168 "test-ident.ctr"
#define I_DIGIT 2
#else
#line 168 "test-ident.ctr"
#error "Redefinition of I_DIGIT"
#endif

#ifndef I_END
/** State machine input: End of input. */
#line 170 "test-ident.ctr"
#define I_END 3
#else
#line 170 "test-ident.ctr"
#error "Redefinition of I_END"
#endif

#ifndef I_UNDER
/** State machine input: Underscore. */
#line 167 "test-ident.ctr"
#define I_UNDER 4
#else
#line 167 "test-ident.ctr"
#error "Redefinition of I_UNDER"
#endif

#ifndef O_ERROR
/** State machine output: Error occured. */
#line 173 "test-ident.ctr"
#define O_ERROR 0
#else
#line 173 "test-ident.ctr"
#error "Redefinition of O_ERROR"
#endif

#ifndef O_OK
/** State machine output: Everything ok so far. */
#line 174 "test-ident.ctr"
#define O_OK 1
#else
#line 174 "test-ident.ctr"
#error "Redefinition of O_OK"
#endif

/**@}*/

/**	Reset idtest state machine.
	@param	st	Pointer to state variable.
*/
static
void
idtest_reset(int *st)
{
  if(st) { *st = S_START; }
}

/**	State machine idtest step.
	@param	st	Pointer to state variable.
	@param	in	Input.
	@return	Transition output.
*/
static
int
idtest_step(int *st, int in)
{
  int back = O_ERROR;
  if(st) {
    int os;
    int nf = 1;
    int ns = S_ERROR;
    os = *st;
    switch(os) {
      case S_OK: {
        switch(in) {
          case I_CHAR: {
            ns = S_OK; back = O_OK; nf = 0;
          } break;
          case I_DIGIT: {
            ns = S_OK; back = O_OK; nf = 0;
          } break;
          case I_END: {
            ns = S_START; back = O_OK; nf = 0;
          } break;
          case I_UNDER: {
            ns = S_OK; back = O_OK; nf = 0;
          } break;
        }
      } break;
      case S_START: {
        switch(in) {
          case I_CHAR: {
            ns = S_OK; back = O_OK; nf = 0;
          } break;
          case I_UNDER: {
            ns = S_OK; back = O_OK; nf = 0;
          } break;
        }
      } break;
    }
    if(nf) {
      if(in == I_END) {
      ns = S_START; back = O_ERROR;
      } else {
      }
    }
    *st = ns;
  } else {
  }
  return back;
}


#line 29 "test-ident.ctr"

#include "dk3all.h"
#include <stdio.h>
#include <stdlib.h>
#if DK3_HAVE_UNISTD_H
#include <unistd.h>
#endif


/**	Help text, never used, just for demonstration.
*/
static char const * const help_text[] = {
"This help text is never shown, it is here just to demonstrate the",
"use of the build-in $!text function.",
NULL


#line 45 "test-ident.ctr"
};

/**	Find start of text (first non-whitespace).
	@param	t	String to test.
	@return	Pointer to start of text or NULL.
*/
static
char *
str_start(char *t)
{
  char *back = NULL;
  char *ptr;
  ptr = t;
  while((*ptr) && (back == NULL)) {
    if(*ptr != ' ') {
      if(*ptr != '\t') {
        back = ptr;
      }
    }
    ptr++;
  }
  return back;
}

/**	Remove trailing newline.
	@param	t	String to modify.
*/
static
void
str_delnl(char *t)
{
  char *ptr;
  ptr = t;
  while(*ptr) {
    if(*ptr == '\r') *ptr = '\0';
    if(*ptr == '\n') *ptr = '\0';
    ptr++;
  }
}

/**	Test whether a string is an identifier.
	@param	test	String to check.
	@return	1 on success (string is identifier), 0 on error.
*/
int test_identifier(char const *text)
{
  int back = 0;
  char const	*ptr;
  int		state;
  int		i;
  

#line 96 "test-ident.ctr"
  idtest_reset(&state);
  ptr = text;
  while(*ptr) {		

#line 99 "test-ident.ctr"
    if((*ptr >= 'A') && (*ptr <= 'Z')) {
      i = I_CHAR;
    } else {
      if((*ptr >= 'a') && (*ptr <= 'z')) {
        i = I_CHAR;
      } else {
        if((*ptr >= '0') && (*ptr <= '9')) {
	  i = I_DIGIT;
	} else {
	  if(*ptr == '_') {
	    i = I_UNDER;
	  } else {
	    i = I_ANY;
	  }
	}
      }
    }
    (void)idtest_step(&state, i);
    ptr++;
  }
  if(idtest_step(&state, I_END) == O_OK) {
    back = 1;
  } 

#line 122 "test-ident.ctr"
  return back;
}

/**	Main function.
	@param	argc	Number of command line arguments.
	@param	argv	Command line arguments array.
*/
int main(int argc, char *argv[])
{
  char	buffer[1024];
  char	*p1;
  int	cc;
  

#line 135 "test-ident.ctr"
  

#line 136 "test-ident.ctr"
  do {		

#line 137 "test-ident.ctr"
    cc = 0;
    if(fgets(buffer, sizeof(buffer), stdin)) {
      p1 = str_start(buffer);
      if(p1) {	

#line 141 "test-ident.ctr"
        cc = 1;
	str_delnl(p1);
	printf("%s %d\n", p1, test_identifier(p1));
      }
    }
  } while(cc);
  

#line 148 "test-ident.ctr"
  

#line 149 "test-ident.ctr"
  exit(0); return 0;
}



