/*************************************************************************** * Copyright (c) 2011, Broadcom Corporation * All Rights Reserved * Confidential Property of Broadcom Corporation * * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. * * $brcm_Workfile: $ * $brcm_Revision: $ * $brcm_Date: $ * * Module Description: parser for CCAD input file format * * Revision History: * * $brcm_Log: $ * * ***************************************************************************/ #include "input_parser.h" #define EOF_SYMBOL '$' /* Parser recognizes following tockens: DIGIT - a hexdecimal digit 0-F or 0-f COMMA - , COMMENT - # NEWLINE - \r or \n or any combination of these EOF - $ or any other symbol defined below Anything else is ignored. Anything betwee COMMENT and NEWLINE is ignored even if it is DIGIT or COMMA */ enum token_t { TO_XDIGIT, TO_COMMA, TO_COMMENT, TO_NEWLINE, TO_EOF, TO_OTHER }; /* state_transitions[input][current_state] = new_state */ int state_transitions [6][3] = { {1, 0, 2}, /* xdig */ {1, 1, 2}, /* comma */ {2, 2, 2}, /* comment */ {0, 1, 1}, /* nl */ {99, 99, 99}, /* eof */ {0, 1, 2}, /* other */ }; struct parser_data_t { int ps; int pps; unsigned int number; unsigned char * buffer; unsigned int size; unsigned int idx; }; struct parser_data_t pd; int iparser_hex2nibble(int ch); enum token_t tokenize(int ch) { if(('0' <= ch) && ('9' >= ch)){ return TO_XDIGIT; } if(('A' <= ch) && ('F' >= ch)){ return TO_XDIGIT; } if(('a' <= ch) && ('f' >= ch)){ return TO_XDIGIT; } switch(ch){ case ',': return TO_COMMA; case '#': return TO_COMMENT; case '\r': return TO_NEWLINE; case '\n': return TO_NEWLINE; case EOF_SYMBOL: return TO_EOF; default: return TO_OTHER; } return TO_OTHER; } void iparser_init(unsigned char * buffer, unsigned int size) { pd.number = 0; pd.buffer = buffer; pd.size = size; pd.idx = 0; pd.ps = 1; } int iparser_process(int ch) { enum token_t tok; int nps; /* new parser state */ tok = tokenize(ch); if(2 != pd.ps){ switch(tok){ case TO_XDIGIT: pd.number = (pd.number << 4) | iparser_hex2nibble(ch); break; default: break; } } nps = state_transitions[tok][pd.ps]; if(nps != pd.ps){ /* changing state */ switch(pd.ps){ case 2: /* coming out of consume */ pd.ps = pd.pps; /* restore state */ return 0; default: /* all other states save state */ pd.pps = pd.ps; break; } } switch(nps){ case 1: if(1 != pd.ps){ pd.buffer[pd.idx] = (unsigned char)pd.number; pd.number = 0; pd.idx++; if(pd.idx >= pd.size){ pd.idx = pd.size - 1; return -1; } } break; case MATCHED_EOF: if(0 == pd.ps){ pd.buffer[pd.idx] = (unsigned char)pd.number; pd.number = 0; pd.idx++; } pd.ps = nps; return MATCHED_EOF; default: break; } pd.ps = nps; return 0; } unsigned int iparser_size(void) { return pd.idx; } int iparser_hex2nibble(int ch) { if(('0' <= ch) && ('9' >= ch)){ return (ch - '0'); }else if(('A' <= ch) && ('F' >= ch)){ return (ch - 'A' + 0xa); }else{ return (ch - 'a' + 0xa); } } /* enumeration to reduce size of the table */ enum keyw_token_t { KW_OTHER, KW_A, KW_D, KW_R, KW_P, KW_I, KW_M, KW_S, KW_G, KW_EQ, KW_SP, KW_EOF, }; enum keyw_token_t tokenize_keyw(int ch) { switch(ch){ case 'A': return KW_A; case 'D': return KW_D; case 'R': return KW_R; case 'P': return KW_P; case 'I': return KW_I; case 'M': return KW_M; case 'S': return KW_S; case 'G': return KW_G; case '=': return KW_EQ; case ' ': return KW_SP; case EOF_SYMBOL: return KW_EOF; default: break; } return KW_OTHER; } /* state 0 is starting state state_transitions_keyw[input][current_state] = new_state o - means other 5 - match ADDR= 8 - match PID= 14 - match MSG= e - eof */ int state_transitons_keyw[12][14] = { /*o*/ {00,00,00,00,00,00,00,00,00,00,00,00,00,00,}, /*A*/ { 1,00,00,00,00,00,00,00,00,00,00,00,00,00,}, /*D*/ {00,02,03,00,00,00,00, 8,00,00,00,00,00,00,}, /*R*/ { 0, 0, 0, 4, 0, 0, 0, 0, 0,00,00,00,00,00,}, /*P*/ { 6, 0, 0, 0, 0, 0, 0, 0, 0,00,00,00,00,00,}, /*I*/ { 0, 0, 0, 0, 0, 0, 7, 0, 0,00,00,00,00,00,}, /*M*/ {10, 0, 0, 0, 0, 0, 0, 0, 0,00,00,00,00,00,}, /*S*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0,00,11,00,00,00,}, /*G*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0,00,00,12,00,00,}, /*=*/ { 0, 0, 0, 0, 5, 0, 0, 0, 9,00,00,00,13,00,}, /* */ { 0, 0, 0, 0, 4, 0, 0, 0, 8,00,00,00,12,00,}, /*e*/ {99,99,99,99,99,99,99,99,99,99,99,99,99,99,}, }; struct fparser_data_t { int ps; }; struct fparser_data_t fpd; void iparser_init_keyw(void) { fpd.ps = 0; /* set initial state */ } int iparser_process_keyw(int ch) { enum keyw_token_t tok; int nps; /* new state */ tok = tokenize_keyw(ch); nps = state_transitons_keyw[tok][fpd.ps]; switch(nps){ case MATCHED_ADDR: case MATCHED_PID: case MATCHED_MSG: fpd.ps = 0; return nps; case MATCHED_EOF: fpd.ps = 0; return nps; default: break; } fpd.ps = nps; return 0; } /* tokens for hex digits */ enum hex_token_t { HX_DIGIT, HX_DELIM, HX_OTHER, HX_EOF, }; enum hex_token_t tokenize_hex(int ch) { switch(ch){ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': return HX_DIGIT; case ' ': case ',': case '\r': case '\n': return HX_DELIM; case EOF_SYMBOL: return HX_EOF; default: break; } return HX_OTHER; } int state_transitons_hex[4][2] = { /*di*/ {01,01,}, /*de*/ {00,02,}, /*ot*/ {00,00,}, /*eo*/ {99,99,}, }; struct xparser_data_t { int ps; int value; }; struct xparser_data_t xpd; void iparser_init_hex(void) { xpd.ps = 0; xpd.value = 0; } int iparser_process_hex(int ch, int * value) { enum hex_token_t tok; int nps; tok = tokenize_hex(ch); nps = state_transitons_hex[tok][xpd.ps]; if(HX_DIGIT == tok){ xpd.value = (xpd.value << 4) | iparser_hex2nibble(ch); } if(MATCHED_XNUMBER == nps){ *value = xpd.value; /* return matched number */ xpd.value = 0; xpd.ps = 0; return MATCHED_XNUMBER; } if(MATCHED_EOF == nps){ *value = xpd.value; /* return matched number */ xpd.value = 0; xpd.ps = 0; return MATCHED_EOF; } xpd.ps = nps; return 0; }