Subversion Repositories DevTools

Rev

Rev 313 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
313 dpurdie 1
/** -*- mode: c; tabs: 4 -*- ************************************************
2
* Module name   : macro.c
3
* Module type   : CMDFILE source file
4
* Environment(s): n/a
5
*
6
* Description:
7
*
8
   Macro
9
*
10
* Version   Who     Date        Description
11
            APY     02/03/00    Created
12
            APY     14/03/00    Handle .. correctly
13
                    16/04/02    realpath() macro
14
                    26/04/04    argument() macro
15
                    05/10/04    vpath3, vlib3 and vglob3
16
                                pathargument
17
                                vsep and vhost
18
                                vlint
19
*
20
* $Source: /cvsroot/device/DEVL/UTILS/CMDFILE/macro.c,v $
21
* $Revision: 1.5 $ $Date: 2004/10/11 08:59:27 $ $State: Exp $
22
* $Author: ayoung $ $Locker:  $
23
*.........................................................................*/
24
 
25
#include "cmdfile.h"
26
 
27
static int              mlvl;                   /* macro level */
28
 
29
#define FSTRING         0x01
30
#define FEMBEDDEDSPACES 0x02
31
 
32
static int              nextword( int, const char *, char *, int );
33
 
317 dpurdie 34
/*----------------------------------------------------------------------------
35
** FUNCTION           : macro_from_env
36
**
37
** DESCRIPTION        : Get data from the users environment and process it
38
**                      as a macro
39
**
40
**
41
** INPUTS             : str     - output string
42
**                      s       - input arguments
43
**
44
** RETURNS            : length of arguments consumed
45
**
46
----------------------------------------------------------------------------*/
313 dpurdie 47
 
48
int
317 dpurdie 49
macro_from_env(String_t *str, const char *s)
50
{
51
    char varname[ 32 ];
52
    int len = 0, len2;
53
    char *sp;
54
 
55
    if (expected(s++, ',') > 0 &&
56
            (len2 = argument(s, varname, sizeof(varname))) > 0)
57
    {
58
        len = 1+len2, s += len2;
59
        sp = getenv(varname);
60
        if ( ! sp )
61
            fatalerr( "Environment Variable not found: '%s'\n", varname );
62
 
63
        verbose( " MacroEnvVar %s  = %s", varname, sp );
64
        process_string (sp);
65
    }
66
    return (len);
67
}
68
 
69
int
313 dpurdie 70
macro( String_t *str, const char *s )
71
{
72
    char name[ 128 ];                           /* macro name */
73
    int len, len2;
74
 
75
/* macro name */
76
    mlvl++;
77
    if (*s != LDELIMITOR ||
78
            (len = token( s+1, name, sizeof(name) )) < 1) {
79
        StringPut( str, MACROCHAR );
80
        mlvl--;
81
        return (0);
82
    }
83
    len++;                                      /* include '(' */
84
 
85
    verbose(" [%d] Macro(%s)", mlvl, name);
86
 
87
/* invoke */
88
    if (strcasecmp( "vpath", name ) == 0 || strcasecmp( "vpath1", name ) == 0)
89
        len2 = vpath(str, s+len, VFLAG_PATH);
90
 
91
    else if (strcasecmp( "vpath2", name ) == 0)
92
        len2 = vpath(str, s+len, VFLAG_PATH|VFLAG_MUSTRESOLVE);
93
 
94
    else if (strcasecmp( "vpath3", name ) == 0)
95
        len2 = vpath(str, s+len, VFLAG_PATH|VFLAG_OPTIONAL);
96
 
97
    else if (strcasecmp( "vlib",  name ) == 0 || strcasecmp( "vlib1",  name ) == 0)
98
        len2 = vpath(str, s+len, VFLAG_LIBRARY);
99
 
100
    else if (strcasecmp( "vlib2", name ) == 0)
101
        len2 = vpath(str, s+len, VFLAG_LIBRARY|VFLAG_MUSTRESOLVE);
102
 
103
    else if (strcasecmp( "vlib3", name ) == 0)
104
        len2 = vpath(str, s+len, VFLAG_LIBRARY|VFLAG_OPTIONAL);
105
 
106
    else if (strcasecmp( "vlibgcc", name ) == 0)
107
        len2 = do_vlibgcc( str, s+len );
108
 
109
    else if (strcasecmp( "vhost", name ) == 0)
110
        len2 = do_vhost(s+len);
111
 
112
    else if (strcasecmp( "vsep", name ) == 0)
113
        len2 = do_vsep(s+len);
114
 
115
    else if (strcasecmp( "vglob",  name ) == 0 || strcasecmp( "vglob1",  name ) == 0)
116
        len2 = vpath(str, s+len, VFLAG_GLOB);
117
 
118
    else if (strcasecmp( "vglob2", name ) == 0)
119
        len2 = vpath(str, s+len, VFLAG_GLOB|VFLAG_MUSTRESOLVE);
120
 
121
    else if (strcasecmp( "vglob3", name ) == 0)
122
        len2 = vpath(str, s+len, VFLAG_GLOB|VFLAG_OPTIONAL);
123
 
124
    else if (strcasecmp( "vlint",  name ) == 0 || strcasecmp( "vlint1",  name ) == 0)
125
        len2 = vpath(str, s+len, VFLAG_LINT);
126
 
127
    else if (strcasecmp( "vlint2", name ) == 0)
128
        len2 = vpath(str, s+len, VFLAG_LINT|VFLAG_MUSTRESOLVE);
129
 
130
    else if (strcasecmp( "vlint3", name ) == 0)
131
        len2 = vpath(str, s+len, VFLAG_LINT|VFLAG_OPTIONAL);
132
 
133
    else if (strcasecmp( "dosify", name ) == 0)
134
        len2 = dosify(str, s+len);
135
 
136
    else if (strcasecmp( "sep", name ) == 0)
137
        len2 = do_clean_sep(str, s+len);
138
 
139
    else if (strcasecmp( "realpath", name ) == 0)
140
        len2 = do_realpath(str, s+len);
141
 
142
    else if (strcasecmp( "shortpath", name ) == 0)
143
        len2 = do_shortpath(str, s+len);
144
 
145
    else if (strcasecmp( "url2path", name ) == 0)
146
        len2 = do_url2path(str, s+len);
147
 
148
    else if (strcasecmp( "path2url", name ) == 0)
149
        len2 = do_path2url(str, s+len);
150
 
151
    else if (strcasecmp( "env", name ) == 0)
152
        len2 = from_env(str, s+len);
153
 
317 dpurdie 154
    else if (strcasecmp( "envmacro", name ) == 0)
155
        len2 = macro_from_env(str, s+len);
156
 
313 dpurdie 157
    else
158
    {
159
        warning( "unknown macro '%s' -- ignored", name );
160
        len2 = 0;
161
    }
162
 
163
/* termination */
164
    if (len2 > 0 && expected(s+len+len2, RDELIMITOR) > 0)
165
    {
166
        verbose(" [%d] Macro(%s) ok = %s", mlvl, name, StringData(str));
167
        mlvl--;
168
        return (len+len2+1);
169
    }
170
    verbose(" [%d] Macro(%s) bad = %s", mlvl, name,
171
        (StringData(str) ? StringData(str) : "NULL") );
172
 
173
    StringPut(str, MACROCHAR);
174
    mlvl--;
175
    return (0);                                 /* echo invalid macro */
176
}
177
 
178
 
179
int
180
expected(
181
    const char *s, char c)
182
{
183
    if (*s != c) {
184
        if (*s == '\0')
185
            warning( "expected '%c', found end-of-file", c );
186
        else if (*s == '\n')
187
            warning( "expected '%c', found newline\n", c );
188
        else warning( "expected '%c', found '%c'\n", c, *s );
189
        return (0);
190
    }
191
    return (1);
192
}
193
 
194
 
195
/*
196
 *  token ---
197
 *      Retrieve the next stream word.
198
 */
199
int
200
token( const char *s, char *buf, int len )
201
{
202
    return nextword( 0, s, buf, len );
203
}
204
 
205
 
206
/*
207
 *  argument ---
208
 *      Retrieve the next stream word, allowing strings.
209
 */
210
int
211
argument( const char *s, char *buf, int len )
212
{
213
    return nextword( FSTRING, s, buf, len );
214
}
215
 
216
 
217
/*
218
 *  pathargument ---
219
 *      Retrieve the next stream word, allowing strings and
220
 *      embedded white-spaces.
221
 */
222
int
223
pathargument( const char *s, char *buf, int len )
224
{
225
    return nextword( FSTRING|FEMBEDDEDSPACES, s, buf, len );
226
}
227
 
228
 
229
/*
230
 *  nextword ---
231
 *      Retrieve the next stream word.
232
 *
233
 *  Returns:
234
 *      -1 on failure, otherwise the number of characters consumed.
235
 *
236
 *  Notes:
237
 *      The consumed count and resulting word length may differ if
238
 *      leading white space, quotes or strings are envcountered.
239
 */
240
static int
241
nextword( int flags, const register char *s, char *buf, int len )
242
{
243
    String_t mstr;                              /* macro buffer */
244
    int str, err, blen, sidx;                   /* token length */
245
    const char *os = s;
246
    char *p;
247
 
248
#define SIGNORE         0                       /* string parse status */
249
#define SALLOWED        1
250
#define SDOUBLE         2
251
#define SSINGLE         3
252
 
253
    if (flags & FSTRING)
254
        str = SALLOWED;
255
    else str = SIGNORE;
256
 
257
    for (err = sidx = blen = 0; !err; sidx++, s++)
258
    {
259
        if (*s == '\0')
260
        {
261
            warning( "unexpected end-of-string in token '%s' -- ignored", os );
262
            err = 1;
263
        }
264
        else if (*s == '\n')
265
        {
266
            warning( "unexpected new-line in token '%s' -- ignored", os );
267
            err = 1;
268
        }
269
 
270
    /* white space */
271
        else if (*s == ' ' || *s == '\t')
272
        {
273
            if (str == SDOUBLE || str == SSINGLE ||
274
                    (blen && *s == ' ' && (flags & FEMBEDDEDSPACES)) )
275
            {
276
                /*
277
                 *  Inside a string or embedded spaces are allowed.
278
                 */
279
                if (blen < len-1)
280
                    buf[ blen++ ] = *s;
281
                continue;                       /* embedded whitespace */
282
 
283
            } else if (blen) {
284
                break;                          /* end of token */
285
            }
286
 
287
            continue;                           /* consume leading white space */
288
        }
289
 
290
    /* macros */
291
        else if (*s == MACROCHAR && blen == 0)
292
        {
293
            register int mlen;                  /* macro length */
294
 
295
            StringInit( &mstr, NULL, MACRO_MAX );
296
            mlen = macro( &mstr, s+1 );         /* nested macro def */
297
            for (p = StringData(&mstr); *p; p++)
298
            {
299
                if (blen < len-1)
300
                    buf[ blen++ ] = *p;
301
            }
302
            free( StringData(&mstr) );
303
            sidx += mlen, s += mlen;            /* skip definition */
304
        }
305
 
306
        else if ((*s == RDELIMITOR || *s == ',') &&
307
                    (str == SIGNORE || str == SALLOWED))
308
        {
309
            break;                              /* end of token */
310
        }
311
 
312
    /* strings */
313
        else if (*s == '"' && (str == SALLOWED || str == SDOUBLE))
314
        {
315
            if (str == SDOUBLE) {
316
                sidx++, s++;
317
                break;                          /* end-of-string */
318
            }
319
            str = SDOUBLE;                      /* first character of string */
320
        }
321
 
322
        else if (*s == '\'' && (str == SALLOWED || str == SSINGLE))
323
        {
324
            if (str == SSINGLE) {
325
                sidx++, s++;
326
                break;                          /* end-of-string */
327
            }
328
            str = SSINGLE;                      /* first character of string */
329
        }
330
 
331
        else if (*s == '\\' && str > SALLOWED &&
332
                    (s[1] == '"' || s[1] == '\'' || s[1] == '\\'))
333
        {
334
            if (blen < len-1)
335
                buf[ blen++ ] = s[1];           /* quote next */
336
            sidx++, s++;
337
        }
338
 
339
    /* general */
340
        else if (blen < len-1)                  /* buffer overflow ? */
341
        {
342
            buf[ blen++ ] = *s;
343
        }
344
    }
345
 
346
    if (blen < len-1)                           /* terminate buffer */
347
        buf[ blen ] = '\0';
348
    else buf[ len-1 ] = '\0';
349
 
350
    if (vflg > 2)
351
        verbose( "  = [%d] token(%s) : %d", mlvl, buf, err ? -1 : sidx );
352
 
353
    return (err ? -1 : sidx);
354
}
355