line source
/*
+-----------------------------------------------------------------------------
| Project : GSM-F&D (8411)
| Modul : ATI
+-----------------------------------------------------------------------------
| Copyright 2002 Texas Instruments Berlin, AG
| All rights reserved.
|
| This file is confidential and a trade secret of Texas
| Instruments Berlin, AG
| The receipt of or possession of this file does not convey
| any rights to reproduce or disclose its contents or to
| manufacture, use, or sell anything it may describe, in
| whole, or in part, without the specific written consent of
| Texas Instruments Berlin, AG.
+-----------------------------------------------------------------------------
| Purpose : AT Command parameter parser
+-----------------------------------------------------------------------------
*/
#ifndef ATI_PRS_C
#define ATI_PRS_C
#include "aci_all.h"
#include <stdarg.h>
#include <ctype.h>
#include "aci_cmh.h"
#include "ati_cmd.h"
#include "aci_cmd.h"
#ifdef OPTION_RELATIVE
LOCAL ULONG offset;
#endif
static UBYTE parse_index = 0;
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411) MODULE : ACI_PRS |
| STATE : code ROUTINE : parseBin |
+--------------------------------------------------------------------+
PURPOSE : parse binary value
*/
GLOBAL char *parseBin (int digits, char *b, SHORT *i)
{
int found = 0;
*i = 0;
while (digits-- AND *b >= '0' AND *b <= '1')
{
found++;
*i *= 2;
*i += *b - '0';
b++;
}
return ((found) ? b : 0);
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411) MODULE : ACI_PRS |
| STATE : code ROUTINE : parseHex |
+--------------------------------------------------------------------+
PURPOSE : parse hexadecimal value
*/
GLOBAL char *parseHex (int digits, char *b, UBYTE *i)
{
int found = 0;
*i = 0;
while (digits-- AND ((*b >= '0' AND *b <= '9') OR
(*b >= 'a' AND *b <= 'f') OR
(*b >= 'A' AND *b <= 'F')))
{
found++;
*i *= 16;
if (*b >= '0' AND *b <= '9')
*i += *b - '0';
if (*b >= 'a' AND *b <= 'f')
*i += *b - 'a' + 10;
if (*b >= 'A' AND *b <= 'F')
*i += *b - 'A' + 10;
b++;
}
return ((found AND found <= 2) ? b : 0);
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411) MODULE : ACI_PRS |
| STATE : code ROUTINE : parseHexToLong |
+--------------------------------------------------------------------+
PURPOSE : parse hexadecimal value
*/
GLOBAL char *parseHexToLong (int digits, char *b, LONG *i)
{
*i = 0;
while (digits-- AND ((*b >= '0' AND *b <= '9') OR
(*b >= 'a' AND *b <= 'f') OR
(*b >= 'A' AND *b <= 'F')))
{
*i *= 16;
if (*b >= '0' AND *b <= '9')
*i += *b - '0';
if (*b >= 'a' AND *b <= 'f')
*i += *b - 'a' + 10;
if (*b >= 'A' AND *b <= 'F')
*i += *b - 'A' + 10;
b++;
}
return ( digits EQ 0 ? 0 : b );
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411) MODULE : ACI_PRS |
| STATE : code ROUTINE : parseEnum |
+--------------------------------------------------------------------+
PURPOSE : parse enum value
*/
GLOBAL char *parseEnum (int digits, char *b, int *i)
{
int found = 0;
*i = 0;
while (digits-- AND *b >= '0' AND *b <= '9')
{
found++;
*i *= 10;
*i += *b - '0';
b++;
}
return ((found) ? b : 0);
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411) MODULE : ACI_PRS |
| STATE : code ROUTINE : parseShort |
+--------------------------------------------------------------------+
PURPOSE : parse Short value
*/
GLOBAL char *parseShort (int digits, char *b, SHORT *i)
{
int found = 0;
*i = 0;
while (digits-- AND *b >= '0' AND *b <= '9')
{
found++;
*i *= 10;
*i += *b - '0';
b++;
}
return ((found) ? b : 0);
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411) MODULE : ACI_PRS |
| STATE : code ROUTINE : parseStr |
+--------------------------------------------------------------------+
PURPOSE : parse string value
*/
GLOBAL char *parseStr (int digits, char *b, char *s)
{
int found = 0;
*s = 0;
if (*b != '"')
return 0;
b++;
while (digits-- AND *b AND *b >= 0x20)
{
found++;
if (*b == '"')
{
*s = 0;
b++;
break;
}
if (*b == '\\')
{
b = parseHex(2,b+1,(UBYTE *) s); /* ES!! ZERO ? */
if (!b)
return 0;
s++;
}
else
*s++ = *b++;
}
if(*(b-1) NEQ '"')
return 0;
*s = 0; /* zero terminated */
return ((found) ? b : 0);
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411) MODULE : ACI_PRS |
| STATE : code ROUTINE : parseZStr |
+--------------------------------------------------------------------+
PURPOSE : parse string value
*/
GLOBAL char *parseZStr (int digits, char *b, char *s)
{
int found = 0;
*s = 0;
if (*b != '"')
return 0;
b++;
while (digits--)
{
found++;
if (*b == '"')
{
*s = 0;
b++;
break;
}
if (*b == '\\')
{
b = parseHex(2,b+1,(UBYTE *) s); /* ES!! ZERO ? */
if (!b)
return 0;
s++;
}
else
*s++ = *b++;
}
if(*(b-1) NEQ '"')
return 0;
*s = 0; /* zero terminated */
return ((found) ? b : 0);
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411) MODULE : ACI_PRS |
| STATE : code ROUTINE : parseNStr |
+--------------------------------------------------------------------+
PURPOSE : parse string value and if not numeric returns error
*/
GLOBAL char *parseNStr (int digits, char *b, char *s)
{
int found = 0;
*s = 0;
if (*b != '"')
return 0;
b++;
while (digits-- AND *b AND *b >= 0x20)
{
found++;
if (*b == '"')
{
*s = 0;
b++;
break;
}
if (*b == '\\')
{
b = parseHex(2,b+1,(UBYTE *) s); /* ES!! ZERO ? */
if (!b)
return 0;
s++;
}
if ( *b > '9' OR *b < '0') return 0; /*check if numeric value*/
else
*s++ = *b++;
}
if(*(b-1) NEQ '"')
return 0;
*s = 0; /* zero terminated */
return ((found) ? b : 0);
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411) MODULE : ACI_PRS |
| STATE : code ROUTINE : parseASCII |
+--------------------------------------------------------------------+
PURPOSE : parse ASCII value
*/
GLOBAL char *parseASCII (int digits, char *b, char *i)
{
int found = 0;
*i = 0;
while (digits-- AND *b NEQ ' ' AND *b NEQ ',' AND *b NEQ ';' )
{
found++;
*i = *b;
i++;
b++;
}
return ((found) ? b : 0);
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411) MODULE : ACI_PRS |
| STATE : code ROUTINE : parseQASCII |
+--------------------------------------------------------------------+
PURPOSE : parse ASCII value and terminate with 0
*/
GLOBAL char *parseQASCII (int digits, char *b, char *i)
{
int found = 0;
*i = 0;
while (digits-- AND *b NEQ ',' AND *b NEQ ';' AND *b NEQ '\0')
{
found++;
*i = *b;
i++;
b++;
}
if (found)
{
*i = 0;
return (b);
}
return (NULL);
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411) MODULE : ACI_PRS |
| STATE : code ROUTINE : parseStrLen |
+--------------------------------------------------------------------+
PURPOSE : parse sting, return length and startpoint
*/
GLOBAL char *parseStrLen (USHORT *len, char *b, char **p)
{
*len = 0;
if( *b EQ '"' )
b++;
*p = b;
while ( *b NEQ '\0' AND *b NEQ ',' AND *b NEQ ';' AND *b NEQ '"' )
{
(*len)++;
b++;
}
/* needs to process the ending '"' also, otherwise parse returns an error */
if( *b EQ '"' )
b++;
return ((*len) ? b : 0);
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411) MODULE : ACI_PRS |
| STATE : code ROUTINE : parse |
+--------------------------------------------------------------------+
PURPOSE : parse AT command parameter
*/
GLOBAL char *parse (char *b, char *f, ...)
{
char fc;
USHORT *i;
LONG digits=-1;
BOOL value_is_valid;
va_list varpars;
va_start (varpars, f); /* Initialize variable arguments. */
parse_index=0;
while ((fc = *f++) != 0)
{
parse_index++; /* Save the position of current parsing item */
value_is_valid = TRUE;
if (islower(fc))
{
if (*b == 0 OR *b == ';')
{
va_end (varpars); /* Reset variable arguments. */
return b;
}
if (*b == ',')
{
b++;
value_is_valid = FALSE;
}
}
switch (toupper(fc))
{
case 'B':
if (value_is_valid)
b = parseBin(-1,b,va_arg (varpars, SHORT*));
else
va_arg (varpars, SHORT*);
break;
case 'X':
if (value_is_valid)
b = parseHex(-1,b,va_arg (varpars, UBYTE*));
else
va_arg (varpars, SHORT*);
break;
case 'Y':
if (value_is_valid)
b = parseHexToLong(-1,b,va_arg (varpars, LONG*));
else
va_arg (varpars, LONG*);
break;
case 'D':
if (value_is_valid)
b = parseEnum(-1,b,va_arg (varpars, int*));
else
va_arg (varpars, int*);
break;
case 'R':
if (value_is_valid)
b = parseShort(-1,b,va_arg (varpars, SHORT*));
else
va_arg (varpars, SHORT*);
break;
case 'S':
if (value_is_valid)
{
digits=va_arg (varpars, LONG);
b = parseStr(digits,b,va_arg (varpars, char*));
}
else
{
va_arg (varpars, LONG);
va_arg (varpars, char*);
}
break;
case 'N':
if (value_is_valid)
{
digits=va_arg (varpars, LONG);
b = parseNStr(digits,b,va_arg (varpars, char*));
}
else
{
va_arg (varpars, LONG);
va_arg (varpars, char*);
}
break;
case 'Z':
if (value_is_valid)
{
char* c = b;
USHORT* plen = NULL;
char* cmdPtr;
USHORT cmdLen;
digits = va_arg ( varpars, LONG );
cmdLen = va_arg ( varpars, size_t );
cmdPtr = va_arg ( varpars, char* );
plen = va_arg ( varpars, USHORT*);
b = parseZStr
( MINIMUM (digits, cmdLen - ( b - cmdPtr )),
b, va_arg ( varpars, char* ) );
if ( plen NEQ NULL )
{
if ( b NEQ NULL )
*plen = b - c - 2; /* a string always includes two characters '"' */
else
*plen = 0;
}
}
else
{
va_arg (varpars, LONG);
va_arg (varpars, USHORT*);
va_arg (varpars, char*);
}
break;
case 'A':
if (value_is_valid)
{
digits=va_arg (varpars, LONG);
b = parseASCII(digits,b,va_arg (varpars, char*));
}
else
{
va_arg (varpars, LONG);
va_arg (varpars, char*);
}
break;
case 'Q':
if (value_is_valid)
{
digits=va_arg (varpars, LONG);
b = parseQASCII(digits,b,va_arg (varpars, char*));
}
else
{
va_arg (varpars, LONG);
va_arg (varpars, char*);
}
break;
case 'L':
if (value_is_valid)
{
i = va_arg(varpars, USHORT*);
b = parseStrLen (i,b,va_arg(varpars, char**));
}
else
{
va_arg (varpars, int*);
va_arg (varpars, char**);
}
break;
}
if (!b)
{
va_end (varpars); /* Reset variable arguments. */
return 0;
}
if (*f AND *b == ',' AND value_is_valid)
{
b++;
}
else if (*b AND *b != ';' AND *b != ',' AND value_is_valid) /* if comma or semicolon is missing */
{
TRACE_EVENT ("missing separator detected, aborting parse!");
va_end (varpars);
return 0;
}
}
if (*b AND *b != ';')
{
va_end (varpars); /* Reset variable arguments. */
return 0;
}
va_end (varpars); /* Reset variable arguments. */
return b;
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411) MODULE : ACI_PRS |
| STATE : code ROUTINE : parse |
+--------------------------------------------------------------------+
PURPOSE : get last parsed index (to determinate which component was malicious)
*/
GLOBAL UBYTE get_parse_index ()
{
return parse_index;
}
#endif /* ATI_PRS_C */