Provided by GNU Savannah

Savannah CVS Surfing - project autogen - View of /autogen/agen5/cgi-fsm.c

[autogen] / autogen / agen5 / cgi-fsm.c
cvs -d:pserver:anonymous@cvs.sv.gnu.org:/sources/autogen co autogen/agen5/cgi-fsm.c
(to check out web pages for a project, replace /sources with /web in the path above)

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4.14 - (download) (as text) (annotate)
Thu Jan 1 16:51:42 2009 UTC (10 months, 2 weeks ago) by bkorb
Branch: MAIN
CVS Tags: HEAD
Changes since 4.13: +1 -1 lines
update copyright dates
/*  
 *  EDIT THIS FILE WITH CAUTION  (cgi-fsm.c)
 *  
 *  It has been AutoGen-ed  Thursday June 19, 2008 at 09:45:14 AM PDT
 *  From the definitions    cgi.def
 *  and the template file   fsm
 *
 *  Automated Finite State Machine
 *
 *  copyright (c) 2001-2009 by Bruce Korb - all rights reserved
 *
 *  AutoFSM is free software copyrighted by Bruce Korb.
 *  
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name ``Bruce Korb'' nor the name of any other
 *     contributor may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *  
 *  AutoFSM IS PROVIDED BY Bruce Korb ``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 Bruce Korb OR ANY OTHER 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.
 */
#define DEFINE_FSM
#include "cgi-fsm.h"
#include <stdio.h>
#include <ctype.h>

/*
 *  Do not make changes to this file, except between the START/END
 *  comments, or it will be removed the next time it is generated.
 */
/* START === USER HEADERS === DO NOT CHANGE THIS COMMENT */

#include "autogen.h"

/* END   === USER HEADERS === DO NOT CHANGE THIS COMMENT */

#ifndef NULL
#  define NULL 0
#endif

/*
 *  Enumeration of the valid transition types
 *  Some transition types may be common to several transitions.
 */
typedef enum {
    CGI_TR_INVALID,
    CGI_TR_NAME_EQUAL,
    CGI_TR_SEPARATE,
    CGI_TR_STASH,
    CGI_TR_VALUE_ESCAPE
} te_cgi_trans;
#define CGI_TRANSITION_CT  5

/*
 *  the state transition handling map
 *  This table maps the state enumeration + the event enumeration to
 *  the new state and the transition enumeration code (in that order).
 *  It is indexed by first the current state and then the event code.
 */
typedef struct cgi_transition t_cgi_transition;
struct cgi_transition {
    te_cgi_state  next_state;
    te_cgi_trans  transition;
};
static const t_cgi_transition
cgi_trans_table[ CGI_STATE_CT ][ CGI_EVENT_CT ] = {

  /* STATE 0:  CGI_ST_INIT */
  { { CGI_ST_NAME, CGI_TR_STASH },                  /* EVT:  alpha */
    { CGI_ST_INVALID, CGI_TR_INVALID },             /* EVT:  name_char */
    { CGI_ST_INVALID, CGI_TR_INVALID },             /* EVT:  = */
    { CGI_ST_INVALID, CGI_TR_INVALID },             /* EVT:  + */
    { CGI_ST_INVALID, CGI_TR_INVALID },             /* EVT:  % */
    { CGI_ST_INVALID, CGI_TR_INVALID },             /* EVT:  other */
    { CGI_ST_INVALID, CGI_TR_INVALID },             /* EVT:  & */
    { CGI_ST_INVALID, CGI_TR_INVALID }              /* EVT:  end */
  },


  /* STATE 1:  CGI_ST_NAME */
  { { CGI_ST_NAME, CGI_TR_STASH },                  /* EVT:  alpha */
    { CGI_ST_NAME, CGI_TR_STASH },                  /* EVT:  name_char */
    { CGI_ST_VALUE, CGI_TR_NAME_EQUAL },            /* EVT:  = */
    { CGI_ST_INVALID, CGI_TR_INVALID },             /* EVT:  + */
    { CGI_ST_INVALID, CGI_TR_INVALID },             /* EVT:  % */
    { CGI_ST_INVALID, CGI_TR_INVALID },             /* EVT:  other */
    { CGI_ST_INVALID, CGI_TR_INVALID },             /* EVT:  & */
    { CGI_ST_INVALID, CGI_TR_INVALID }              /* EVT:  end */
  },


  /* STATE 2:  CGI_ST_VALUE */
  { { CGI_ST_VALUE, CGI_TR_STASH },                 /* EVT:  alpha */
    { CGI_ST_VALUE, CGI_TR_STASH },                 /* EVT:  name_char */
    { CGI_ST_VALUE, CGI_TR_STASH },                 /* EVT:  = */
    { CGI_ST_VALUE, CGI_TR_STASH },                 /* EVT:  + */
    { CGI_ST_VALUE, CGI_TR_VALUE_ESCAPE },          /* EVT:  % */
    { CGI_ST_VALUE, CGI_TR_STASH },                 /* EVT:  other */
    { CGI_ST_INIT, CGI_TR_SEPARATE },               /* EVT:  & */
    { CGI_ST_DONE, CGI_TR_SEPARATE }                /* EVT:  end */
  }
};


#define CgiFsmErr_off     19
#define CgiEvInvalid_off  75
#define CgiStInit_off     83


static char const zCgiStrings[133] =
    "** OUT-OF-RANGE **\0"
    "FSM Error:  in state %d (%s), event %d (%s) is invalid\n\0"
    "invalid\0"
    "init\0"
    "name\0"
    "value\0"
    "alpha\0"
    "name_char\0"
    "=\0"
    "+\0"
    "%\0"
    "other\0"
    "&\0"
    "end\0";

static const size_t aszCgiStates[3] = {
    83, 88, 93 };

static const size_t aszCgiEvents[9] = {
    99,  105, 115, 117, 119, 121, 127, 129, 75 };


#define CGI_EVT_NAME(t)   ( (((unsigned)(t)) >= 9) \
    ? zCgiStrings : zCgiStrings + aszCgiEvents[t])

#define CGI_STATE_NAME(s) ( (((unsigned)(s)) >= 3) \
    ? zCgiStrings : zCgiStrings + aszCgiStates[s])

#ifndef EXIT_FAILURE
# define EXIT_FAILURE 1
#endif

static int cgi_invalid_transition( te_cgi_state st, te_cgi_event evt );

/* * * * * * * * * THE CODE STARTS HERE * * * * * * * *
 *
 *  Print out an invalid transition message and return EXIT_FAILURE
 */
static int
cgi_invalid_transition( te_cgi_state st, te_cgi_event evt )
{
    /* START == INVALID TRANS MSG == DO NOT CHANGE THIS COMMENT */
    char* pz = aprf( zCgiStrings + CgiFsmErr_off, st, CGI_STATE_NAME( st ),
                     evt, CGI_EVT_NAME( evt ));

    AG_ABEND( aprf( "CGI parsing error:  %s", pz ));
    /* END   == INVALID TRANS MSG == DO NOT CHANGE THIS COMMENT */

    return EXIT_FAILURE;
}

/*
 *  Run the FSM.  Will return CGI_ST_DONE or CGI_ST_INVALID
 */
te_cgi_state
cgi_run_fsm(
    char const* pzSrc,
    int inlen,
    char* pzOut,
    int outlen )
{
    te_cgi_state cgi_state = CGI_ST_INIT;
    te_cgi_event trans_evt;
    te_cgi_state nxtSt;
    te_cgi_trans trans;

    while (cgi_state < CGI_ST_INVALID) {

        /* START == FIND TRANSITION == DO NOT CHANGE THIS COMMENT */

        char  curCh;
        if (--inlen < 0) {
            trans_evt = CGI_EV_END;
            curCh = NUL;

        } else {
            if (outlen < 4) {
                strcpy( pzOut, "output space exhausted\n" );
                return CGI_ST_INVALID;
            }
            curCh = *(pzSrc++);
            if (isalpha( curCh ))
                trans_evt = CGI_EV_ALPHA;
            else if (isdigit( curCh ))
                trans_evt = CGI_EV_NAME_CHAR;
            else switch (curCh) {
            case '_': trans_evt = CGI_EV_NAME_CHAR; break;
            case '=': trans_evt = CGI_EV_EQUAL;     break;
            case '+': trans_evt = CGI_EV_SPACE;     curCh = ' '; break;
            case '%': trans_evt = CGI_EV_ESCAPE;    break;
            case '&': trans_evt = CGI_EV_SEPARATOR; break;
            default:  trans_evt = CGI_EV_OTHER;     break;
            }
        }

        /* END   == FIND TRANSITION == DO NOT CHANGE THIS COMMENT */

        if (trans_evt >= CGI_EV_INVALID) {
            nxtSt = CGI_ST_INVALID;
            trans = CGI_TR_INVALID;
        } else {
            const t_cgi_transition* pTT =
            cgi_trans_table[ cgi_state ] + trans_evt;
            nxtSt = pTT->next_state;
            trans = pTT->transition;
        }


        switch (trans) {
        case CGI_TR_INVALID:
            /* START == INVALID == DO NOT CHANGE THIS COMMENT */
            exit( cgi_invalid_transition( cgi_state, trans_evt ));
            /* END   == INVALID == DO NOT CHANGE THIS COMMENT */
            break;


        case CGI_TR_NAME_EQUAL:
            /* START == NAME_EQUAL == DO NOT CHANGE THIS COMMENT */
            strcpy( pzOut, "='" );
            outlen -= 2;
            pzOut += 2;
            /* END   == NAME_EQUAL == DO NOT CHANGE THIS COMMENT */
            break;


        case CGI_TR_SEPARATE:
            /* START == SEPARATE == DO NOT CHANGE THIS COMMENT */
            strcpy( pzOut, "';\n" );
            outlen -= 2;
            pzOut += 3;
            /* END   == SEPARATE == DO NOT CHANGE THIS COMMENT */
            break;


        case CGI_TR_STASH:
            /* START == STASH == DO NOT CHANGE THIS COMMENT */
            *(pzOut++) = curCh;
            outlen--;
            /* END   == STASH == DO NOT CHANGE THIS COMMENT */
            break;


        case CGI_TR_VALUE_ESCAPE:
            /* START == VALUE_ESCAPE == DO NOT CHANGE THIS COMMENT */
            {
            char z[4];
            if (inlen < 2)
                exit( cgi_invalid_transition( cgi_state, trans_evt ));

            z[0] = *(pzSrc++);
            z[1] = *(pzSrc++);
            z[2] = NUL;
            inlen -= 2;

            /*
             *  We must backslash quote certain characters that are %-quoted
             *  in the input string:
             */
            switch (*(pzOut++) = (int)strtol( z, NULL, 16 )) {
            case '\'':
            case '\\':
            case '#':
                pzOut[0]  = pzOut[-1];
                pzOut[-1] = '\\';
                pzOut++;
            }
            }
            /* END   == VALUE_ESCAPE == DO NOT CHANGE THIS COMMENT */
            break;


        default:
            /* START == BROKEN MACHINE == DO NOT CHANGE THIS COMMENT */
            exit( cgi_invalid_transition( cgi_state, trans_evt ));
            /* END   == BROKEN MACHINE == DO NOT CHANGE THIS COMMENT */
        }

        cgi_state = nxtSt;
    }
    return cgi_state;
}
/*
 * Local Variables:
 * mode: C
 * c-file-style: "stroustrup"
 * indent-tabs-mode: nil
 * End:
 * end of cgi-fsm.c */

Send suggestions and report system problems to the Savannah Hackers.
ViewVC Help
Powered by ViewVC 1.0.7