Rev 313 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/** -*- mode: c; tabs: 4 -*- ************************************************* Module name : macro.c* Module type : CMDFILE source file* Environment(s): n/a** Description:*Macro** Version Who Date DescriptionAPY 02/03/00 CreatedAPY 14/03/00 Handle .. correctly16/04/02 realpath() macro26/04/04 argument() macro05/10/04 vpath3, vlib3 and vglob3pathargumentvsep and vhostvlint** $Source: /cvsroot/device/DEVL/UTILS/CMDFILE/macro.c,v $* $Revision: 1.5 $ $Date: 2004/10/11 08:59:27 $ $State: Exp $* $Author: ayoung $ $Locker: $*.........................................................................*/#include "cmdfile.h"static int mlvl; /* macro level */#define FSTRING 0x01#define FEMBEDDEDSPACES 0x02static int nextword( int, const char *, char *, int );/*----------------------------------------------------------------------------** FUNCTION : macro_from_env**** DESCRIPTION : Get data from the users environment and process it** as a macro****** INPUTS : str - output string** s - input arguments**** RETURNS : length of arguments consumed**----------------------------------------------------------------------------*/intmacro_from_env(String_t *str, const char *s){char varname[ 32 ];int len = 0, len2;char *sp;if (expected(s++, ',') > 0 &&(len2 = argument(s, varname, sizeof(varname))) > 0){len = 1+len2, s += len2;sp = getenv(varname);if ( ! sp )fatalerr( "Environment Variable not found: '%s'\n", varname );verbose( " MacroEnvVar %s = %s", varname, sp );process_string (sp);}return (len);}intmacro( String_t *str, const char *s ){char name[ 128 ]; /* macro name */int len, len2;/* macro name */mlvl++;if (*s != LDELIMITOR ||(len = token( s+1, name, sizeof(name) )) < 1) {StringPut( str, MACROCHAR );mlvl--;return (0);}len++; /* include '(' */verbose(" [%d] Macro(%s)", mlvl, name);/* invoke */if (strcasecmp( "vpath", name ) == 0 || strcasecmp( "vpath1", name ) == 0)len2 = vpath(str, s+len, VFLAG_PATH);else if (strcasecmp( "vpath2", name ) == 0)len2 = vpath(str, s+len, VFLAG_PATH|VFLAG_MUSTRESOLVE);else if (strcasecmp( "vpath3", name ) == 0)len2 = vpath(str, s+len, VFLAG_PATH|VFLAG_OPTIONAL);else if (strcasecmp( "vlib", name ) == 0 || strcasecmp( "vlib1", name ) == 0)len2 = vpath(str, s+len, VFLAG_LIBRARY);else if (strcasecmp( "vlib2", name ) == 0)len2 = vpath(str, s+len, VFLAG_LIBRARY|VFLAG_MUSTRESOLVE);else if (strcasecmp( "vlib3", name ) == 0)len2 = vpath(str, s+len, VFLAG_LIBRARY|VFLAG_OPTIONAL);else if (strcasecmp( "vlibgcc", name ) == 0)len2 = do_vlibgcc( str, s+len );else if (strcasecmp( "vhost", name ) == 0)len2 = do_vhost(s+len);else if (strcasecmp( "vsep", name ) == 0)len2 = do_vsep(s+len);else if (strcasecmp( "vglob", name ) == 0 || strcasecmp( "vglob1", name ) == 0)len2 = vpath(str, s+len, VFLAG_GLOB);else if (strcasecmp( "vglob2", name ) == 0)len2 = vpath(str, s+len, VFLAG_GLOB|VFLAG_MUSTRESOLVE);else if (strcasecmp( "vglob3", name ) == 0)len2 = vpath(str, s+len, VFLAG_GLOB|VFLAG_OPTIONAL);else if (strcasecmp( "vlint", name ) == 0 || strcasecmp( "vlint1", name ) == 0)len2 = vpath(str, s+len, VFLAG_LINT);else if (strcasecmp( "vlint2", name ) == 0)len2 = vpath(str, s+len, VFLAG_LINT|VFLAG_MUSTRESOLVE);else if (strcasecmp( "vlint3", name ) == 0)len2 = vpath(str, s+len, VFLAG_LINT|VFLAG_OPTIONAL);else if (strcasecmp( "dosify", name ) == 0)len2 = dosify(str, s+len);else if (strcasecmp( "sep", name ) == 0)len2 = do_clean_sep(str, s+len);else if (strcasecmp( "realpath", name ) == 0)len2 = do_realpath(str, s+len);else if (strcasecmp( "shortpath", name ) == 0)len2 = do_shortpath(str, s+len);else if (strcasecmp( "url2path", name ) == 0)len2 = do_url2path(str, s+len);else if (strcasecmp( "path2url", name ) == 0)len2 = do_path2url(str, s+len);else if (strcasecmp( "env", name ) == 0)len2 = from_env(str, s+len);else if (strcasecmp( "envmacro", name ) == 0)len2 = macro_from_env(str, s+len);else{warning( "unknown macro '%s' -- ignored", name );len2 = 0;}/* termination */if (len2 > 0 && expected(s+len+len2, RDELIMITOR) > 0){verbose(" [%d] Macro(%s) ok = %s", mlvl, name, StringData(str));mlvl--;return (len+len2+1);}verbose(" [%d] Macro(%s) bad = %s", mlvl, name,(StringData(str) ? StringData(str) : "NULL") );StringPut(str, MACROCHAR);mlvl--;return (0); /* echo invalid macro */}intexpected(const char *s, char c){if (*s != c) {if (*s == '\0')warning( "expected '%c', found end-of-file", c );else if (*s == '\n')warning( "expected '%c', found newline\n", c );else warning( "expected '%c', found '%c'\n", c, *s );return (0);}return (1);}/** token ---* Retrieve the next stream word.*/inttoken( const char *s, char *buf, int len ){return nextword( 0, s, buf, len );}/** argument ---* Retrieve the next stream word, allowing strings.*/intargument( const char *s, char *buf, int len ){return nextword( FSTRING, s, buf, len );}/** pathargument ---* Retrieve the next stream word, allowing strings and* embedded white-spaces.*/intpathargument( const char *s, char *buf, int len ){return nextword( FSTRING|FEMBEDDEDSPACES, s, buf, len );}/** nextword ---* Retrieve the next stream word.** Returns:* -1 on failure, otherwise the number of characters consumed.** Notes:* The consumed count and resulting word length may differ if* leading white space, quotes or strings are envcountered.*/static intnextword( int flags, const register char *s, char *buf, int len ){String_t mstr; /* macro buffer */int str, err, blen, sidx; /* token length */const char *os = s;char *p;#define SIGNORE 0 /* string parse status */#define SALLOWED 1#define SDOUBLE 2#define SSINGLE 3if (flags & FSTRING)str = SALLOWED;else str = SIGNORE;for (err = sidx = blen = 0; !err; sidx++, s++){if (*s == '\0'){warning( "unexpected end-of-string in token '%s' -- ignored", os );err = 1;}else if (*s == '\n'){warning( "unexpected new-line in token '%s' -- ignored", os );err = 1;}/* white space */else if (*s == ' ' || *s == '\t'){if (str == SDOUBLE || str == SSINGLE ||(blen && *s == ' ' && (flags & FEMBEDDEDSPACES)) ){/** Inside a string or embedded spaces are allowed.*/if (blen < len-1)buf[ blen++ ] = *s;continue; /* embedded whitespace */} else if (blen) {break; /* end of token */}continue; /* consume leading white space */}/* macros */else if (*s == MACROCHAR && blen == 0){register int mlen; /* macro length */StringInit( &mstr, NULL, MACRO_MAX );mlen = macro( &mstr, s+1 ); /* nested macro def */for (p = StringData(&mstr); *p; p++){if (blen < len-1)buf[ blen++ ] = *p;}free( StringData(&mstr) );sidx += mlen, s += mlen; /* skip definition */}else if ((*s == RDELIMITOR || *s == ',') &&(str == SIGNORE || str == SALLOWED)){break; /* end of token */}/* strings */else if (*s == '"' && (str == SALLOWED || str == SDOUBLE)){if (str == SDOUBLE) {sidx++, s++;break; /* end-of-string */}str = SDOUBLE; /* first character of string */}else if (*s == '\'' && (str == SALLOWED || str == SSINGLE)){if (str == SSINGLE) {sidx++, s++;break; /* end-of-string */}str = SSINGLE; /* first character of string */}else if (*s == '\\' && str > SALLOWED &&(s[1] == '"' || s[1] == '\'' || s[1] == '\\')){if (blen < len-1)buf[ blen++ ] = s[1]; /* quote next */sidx++, s++;}/* general */else if (blen < len-1) /* buffer overflow ? */{buf[ blen++ ] = *s;}}if (blen < len-1) /* terminate buffer */buf[ blen ] = '\0';else buf[ len-1 ] = '\0';if (vflg > 2)verbose( " = [%d] token(%s) : %d", mlvl, buf, err ? -1 : sidx );return (err ? -1 : sidx);}