Subversion Repositories DevTools

Rev

Go to most recent revision | Details | 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
 
34
 
35
int
36
macro( String_t *str, const char *s )
37
{
38
    char name[ 128 ];                           /* macro name */
39
    int len, len2;
40
 
41
/* macro name */
42
    mlvl++;
43
    if (*s != LDELIMITOR ||
44
            (len = token( s+1, name, sizeof(name) )) < 1) {
45
        StringPut( str, MACROCHAR );
46
        mlvl--;
47
        return (0);
48
    }
49
    len++;                                      /* include '(' */
50
 
51
    verbose(" [%d] Macro(%s)", mlvl, name);
52
 
53
/* invoke */
54
    if (strcasecmp( "vpath", name ) == 0 || strcasecmp( "vpath1", name ) == 0)
55
        len2 = vpath(str, s+len, VFLAG_PATH);
56
 
57
    else if (strcasecmp( "vpath2", name ) == 0)
58
        len2 = vpath(str, s+len, VFLAG_PATH|VFLAG_MUSTRESOLVE);
59
 
60
    else if (strcasecmp( "vpath3", name ) == 0)
61
        len2 = vpath(str, s+len, VFLAG_PATH|VFLAG_OPTIONAL);
62
 
63
    else if (strcasecmp( "vlib",  name ) == 0 || strcasecmp( "vlib1",  name ) == 0)
64
        len2 = vpath(str, s+len, VFLAG_LIBRARY);
65
 
66
    else if (strcasecmp( "vlib2", name ) == 0)
67
        len2 = vpath(str, s+len, VFLAG_LIBRARY|VFLAG_MUSTRESOLVE);
68
 
69
    else if (strcasecmp( "vlib3", name ) == 0)
70
        len2 = vpath(str, s+len, VFLAG_LIBRARY|VFLAG_OPTIONAL);
71
 
72
    else if (strcasecmp( "vlibgcc", name ) == 0)
73
        len2 = do_vlibgcc( str, s+len );
74
 
75
    else if (strcasecmp( "vhost", name ) == 0)
76
        len2 = do_vhost(s+len);
77
 
78
    else if (strcasecmp( "vsep", name ) == 0)
79
        len2 = do_vsep(s+len);
80
 
81
    else if (strcasecmp( "vglob",  name ) == 0 || strcasecmp( "vglob1",  name ) == 0)
82
        len2 = vpath(str, s+len, VFLAG_GLOB);
83
 
84
    else if (strcasecmp( "vglob2", name ) == 0)
85
        len2 = vpath(str, s+len, VFLAG_GLOB|VFLAG_MUSTRESOLVE);
86
 
87
    else if (strcasecmp( "vglob3", name ) == 0)
88
        len2 = vpath(str, s+len, VFLAG_GLOB|VFLAG_OPTIONAL);
89
 
90
    else if (strcasecmp( "vlint",  name ) == 0 || strcasecmp( "vlint1",  name ) == 0)
91
        len2 = vpath(str, s+len, VFLAG_LINT);
92
 
93
    else if (strcasecmp( "vlint2", name ) == 0)
94
        len2 = vpath(str, s+len, VFLAG_LINT|VFLAG_MUSTRESOLVE);
95
 
96
    else if (strcasecmp( "vlint3", name ) == 0)
97
        len2 = vpath(str, s+len, VFLAG_LINT|VFLAG_OPTIONAL);
98
 
99
    else if (strcasecmp( "dosify", name ) == 0)
100
        len2 = dosify(str, s+len);
101
 
102
    else if (strcasecmp( "sep", name ) == 0)
103
        len2 = do_clean_sep(str, s+len);
104
 
105
    else if (strcasecmp( "realpath", name ) == 0)
106
        len2 = do_realpath(str, s+len);
107
 
108
    else if (strcasecmp( "shortpath", name ) == 0)
109
        len2 = do_shortpath(str, s+len);
110
 
111
    else if (strcasecmp( "url2path", name ) == 0)
112
        len2 = do_url2path(str, s+len);
113
 
114
    else if (strcasecmp( "path2url", name ) == 0)
115
        len2 = do_path2url(str, s+len);
116
 
117
    else if (strcasecmp( "env", name ) == 0)
118
        len2 = from_env(str, s+len);
119
 
120
    else
121
    {
122
        warning( "unknown macro '%s' -- ignored", name );
123
        len2 = 0;
124
    }
125
 
126
/* termination */
127
    if (len2 > 0 && expected(s+len+len2, RDELIMITOR) > 0)
128
    {
129
        verbose(" [%d] Macro(%s) ok = %s", mlvl, name, StringData(str));
130
        mlvl--;
131
        return (len+len2+1);
132
    }
133
    verbose(" [%d] Macro(%s) bad = %s", mlvl, name,
134
        (StringData(str) ? StringData(str) : "NULL") );
135
 
136
    StringPut(str, MACROCHAR);
137
    mlvl--;
138
    return (0);                                 /* echo invalid macro */
139
}
140
 
141
 
142
int
143
expected(
144
    const char *s, char c)
145
{
146
    if (*s != c) {
147
        if (*s == '\0')
148
            warning( "expected '%c', found end-of-file", c );
149
        else if (*s == '\n')
150
            warning( "expected '%c', found newline\n", c );
151
        else warning( "expected '%c', found '%c'\n", c, *s );
152
        return (0);
153
    }
154
    return (1);
155
}
156
 
157
 
158
/*
159
 *  token ---
160
 *      Retrieve the next stream word.
161
 */
162
int
163
token( const char *s, char *buf, int len )
164
{
165
    return nextword( 0, s, buf, len );
166
}
167
 
168
 
169
/*
170
 *  argument ---
171
 *      Retrieve the next stream word, allowing strings.
172
 */
173
int
174
argument( const char *s, char *buf, int len )
175
{
176
    return nextword( FSTRING, s, buf, len );
177
}
178
 
179
 
180
/*
181
 *  pathargument ---
182
 *      Retrieve the next stream word, allowing strings and
183
 *      embedded white-spaces.
184
 */
185
int
186
pathargument( const char *s, char *buf, int len )
187
{
188
    return nextword( FSTRING|FEMBEDDEDSPACES, s, buf, len );
189
}
190
 
191
 
192
/*
193
 *  nextword ---
194
 *      Retrieve the next stream word.
195
 *
196
 *  Returns:
197
 *      -1 on failure, otherwise the number of characters consumed.
198
 *
199
 *  Notes:
200
 *      The consumed count and resulting word length may differ if
201
 *      leading white space, quotes or strings are envcountered.
202
 */
203
static int
204
nextword( int flags, const register char *s, char *buf, int len )
205
{
206
    String_t mstr;                              /* macro buffer */
207
    int str, err, blen, sidx;                   /* token length */
208
    const char *os = s;
209
    char *p;
210
 
211
#define SIGNORE         0                       /* string parse status */
212
#define SALLOWED        1
213
#define SDOUBLE         2
214
#define SSINGLE         3
215
 
216
    if (flags & FSTRING)
217
        str = SALLOWED;
218
    else str = SIGNORE;
219
 
220
    for (err = sidx = blen = 0; !err; sidx++, s++)
221
    {
222
        if (*s == '\0')
223
        {
224
            warning( "unexpected end-of-string in token '%s' -- ignored", os );
225
            err = 1;
226
        }
227
        else if (*s == '\n')
228
        {
229
            warning( "unexpected new-line in token '%s' -- ignored", os );
230
            err = 1;
231
        }
232
 
233
    /* white space */
234
        else if (*s == ' ' || *s == '\t')
235
        {
236
            if (str == SDOUBLE || str == SSINGLE ||
237
                    (blen && *s == ' ' && (flags & FEMBEDDEDSPACES)) )
238
            {
239
                /*
240
                 *  Inside a string or embedded spaces are allowed.
241
                 */
242
                if (blen < len-1)
243
                    buf[ blen++ ] = *s;
244
                continue;                       /* embedded whitespace */
245
 
246
            } else if (blen) {
247
                break;                          /* end of token */
248
            }
249
 
250
            continue;                           /* consume leading white space */
251
        }
252
 
253
    /* macros */
254
        else if (*s == MACROCHAR && blen == 0)
255
        {
256
            register int mlen;                  /* macro length */
257
 
258
            StringInit( &mstr, NULL, MACRO_MAX );
259
            mlen = macro( &mstr, s+1 );         /* nested macro def */
260
            for (p = StringData(&mstr); *p; p++)
261
            {
262
                if (blen < len-1)
263
                    buf[ blen++ ] = *p;
264
            }
265
            free( StringData(&mstr) );
266
            sidx += mlen, s += mlen;            /* skip definition */
267
        }
268
 
269
        else if ((*s == RDELIMITOR || *s == ',') &&
270
                    (str == SIGNORE || str == SALLOWED))
271
        {
272
            break;                              /* end of token */
273
        }
274
 
275
    /* strings */
276
        else if (*s == '"' && (str == SALLOWED || str == SDOUBLE))
277
        {
278
            if (str == SDOUBLE) {
279
                sidx++, s++;
280
                break;                          /* end-of-string */
281
            }
282
            str = SDOUBLE;                      /* first character of string */
283
        }
284
 
285
        else if (*s == '\'' && (str == SALLOWED || str == SSINGLE))
286
        {
287
            if (str == SSINGLE) {
288
                sidx++, s++;
289
                break;                          /* end-of-string */
290
            }
291
            str = SSINGLE;                      /* first character of string */
292
        }
293
 
294
        else if (*s == '\\' && str > SALLOWED &&
295
                    (s[1] == '"' || s[1] == '\'' || s[1] == '\\'))
296
        {
297
            if (blen < len-1)
298
                buf[ blen++ ] = s[1];           /* quote next */
299
            sidx++, s++;
300
        }
301
 
302
    /* general */
303
        else if (blen < len-1)                  /* buffer overflow ? */
304
        {
305
            buf[ blen++ ] = *s;
306
        }
307
    }
308
 
309
    if (blen < len-1)                           /* terminate buffer */
310
        buf[ blen ] = '\0';
311
    else buf[ len-1 ] = '\0';
312
 
313
    if (vflg > 2)
314
        verbose( "  = [%d] token(%s) : %d", mlvl, buf, err ? -1 : sidx );
315
 
316
    return (err ? -1 : sidx);
317
}
318