Ignore:
Timestamp:
Mar 26, 2018, 10:25:56 PM (7 years ago)
Author:
bird
Message:

kmkbuiltin: funnel output thru output.c (usually via err.c).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/kmkbuiltin/test.c

    r3065 r3192  
    1616#endif*/
    1717
     18
     19/*********************************************************************************************************************************
     20*   Header Files                                                                                                                 *
     21*********************************************************************************************************************************/
    1822#include "config.h"
    1923#include <sys/stat.h>
     
    3236# include <process.h>
    3337# include "mscfakes.h"
     38# include "quote_argv.h"
    3439#else
    3540# include <unistd.h>
     
    4045#include "kmkbuiltin.h"
    4146
     47
     48/*********************************************************************************************************************************
     49*   Defined Constants And Macros                                                                                                 *
     50*********************************************************************************************************************************/
    4251#ifndef __arraycount
    4352# define __arraycount(a)        ( sizeof(a) / sizeof(a[0]) )
     
    4554
    4655
     56/*********************************************************************************************************************************
     57*   Structures and Typedefs                                                                                                      *
     58*********************************************************************************************************************************/
    4759/* test(1) accepts the following grammar:
    4860        oexpr   ::= aexpr | aexpr "-o" oexpr ;
     
    118130};
    119131
     132/** kmk_test instance data.   */
     133typedef struct TESTINSTANCE
     134{
     135    PKMKBUILTINCTX pCtx;
     136    char **t_wp;
     137    struct t_op const *t_wp_op;
     138} TESTINSTANCE;
     139typedef TESTINSTANCE *PTESTINSTANCE;
     140
     141
     142/*********************************************************************************************************************************
     143*   Global Variables                                                                                                             *
     144*********************************************************************************************************************************/
    120145static const struct t_op cop[] = {
    121146        {"!",   UNOT,   BUNOP},
     
    169194};
    170195
    171 static char **t_wp;
    172 static struct t_op const *t_wp_op;
    173 
    174 static int syntax(const char *, const char *);
    175 static int oexpr(enum token);
    176 static int aexpr(enum token);
    177 static int nexpr(enum token);
    178 static int primary(enum token);
    179 static int binop(void);
     196
     197/*********************************************************************************************************************************
     198*   Internal Functions                                                                                                           *
     199*********************************************************************************************************************************/
     200static int syntax(PTESTINSTANCE, const char *, const char *);
     201static int oexpr(PTESTINSTANCE, enum token);
     202static int aexpr(PTESTINSTANCE, enum token);
     203static int nexpr(PTESTINSTANCE, enum token);
     204static int primary(PTESTINSTANCE, enum token);
     205static int binop(PTESTINSTANCE);
    180206static int test_access(struct stat *, mode_t);
    181207static int filstat(char *, enum token);
    182 static enum token t_lex(char *);
    183 static int isoperand(void);
    184 static int getn(const char *);
     208static enum token t_lex(PTESTINSTANCE, char *);
     209static int isoperand(PTESTINSTANCE);
     210static int getn(PTESTINSTANCE, const char *);
    185211static int newerf(const char *, const char *);
    186212static int olderf(const char *, const char *);
    187213static int equalf(const char *, const char *);
    188 static int usage(const char *);
    189 
    190 #if !defined(kmk_builtin_test) || defined(ELECTRIC_HEAP)
     214static int usage(PKMKBUILTINCTX, int);
     215
     216#if !defined(KMK_BUILTIN_STANDALONE) || defined(ELECTRIC_HEAP)
    191217extern void *xmalloc(unsigned int);
    192218#else
     
    195221    void *p = malloc(sz);
    196222    if (!p) {
    197             fprintf(stderr, "%s: malloc(%u) failed\n", g_progname, sz);
     223            fprintf(stderr, "kmk_test: malloc(%u) failed\n", sz);
    198224            exit(1);
    199225    }
     
    202228#endif
    203229
    204 int kmk_builtin_test(int argc, char **argv, char **envp
    205 #ifndef kmk_builtin_test
    206                      , char ***ppapszArgvSpawn
    207 #endif
    208                      )
    209 {
     230
     231
     232int kmk_builtin_test(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, char ***ppapszArgvSpawn)
     233{
     234        TESTINSTANCE This;
    210235        int res;
    211236        char **argv_spawn;
    212237        int i;
    213238
    214         g_progname = argv[0];
     239        This.pCtx = pCtx;
     240        This.t_wp = NULL;
     241        This.t_wp_op = NULL;
    215242
    216243        /* look for the '--', '--help' and '--version'. */
     
    235262                        }
    236263                        if (!strcmp(argv[i], "--help"))
    237                                 return usage(argv[0]);
     264                                return usage(pCtx, 0);
    238265                        if (!strcmp(argv[i], "--version"))
    239266                                return kbuild_version(argv[0]);
     
    242269
    243270        /* are we '['? then check for ']'. */
    244         if (strcmp(g_progname, "[") == 0) { /** @todo should skip the path in g_progname */
     271        if (strcmp(argv[0], "[") == 0) { /** @todo should skip the path in g_progname */
    245272                if (strcmp(argv[--argc], "]"))
    246                         return errx(1, "missing ]");
     273                        return errx(pCtx, 1, "missing ]");
    247274                argv[argc] = NULL;
    248275        }
     
    252279                res = 1;
    253280        else {
    254                 t_wp = &argv[1];
    255                 res = oexpr(t_lex(*t_wp));
    256                 if (res != -42 && *t_wp != NULL && *++t_wp != NULL)
    257                         res = syntax(*t_wp, "unexpected operator");
     281                This.t_wp = &argv[1];
     282                res = oexpr(&This, t_lex(&This, *This.t_wp));
     283                if (res != -42 && *This.t_wp != NULL && *++This.t_wp != NULL)
     284                        res = syntax(&This, *This.t_wp, "unexpected operator");
    258285                if (res == -42)
    259286                        return 1; /* don't mix syntax errors with the argv_spawn ignore */
     
    266293                        res = 0; /* ignored */
    267294                else {
    268 #ifdef kmk_builtin_test
     295#ifdef KMK_BUILTIN_STANDALONE
    269296                        /* try exec the specified process */
    270297# if defined(_MSC_VER)
    271                         res = _spawnvp(_P_WAIT, argv_spawn[0], argv_spawn);
    272                         if (res == -1)
    273                             res = err(1, "_spawnvp(_P_WAIT,%s,..)", argv_spawn[0]);
     298                        int argc_spawn = 0;
     299                        while (argv_spawn[argc_spawn])
     300                                argc_spawn++;
     301                        if (quote_argv(argc, argv_spawn, 0 /*fWatcomBrainDamage*/, 0/*fFreeOrLeak*/) != -1)
     302                        {
     303                            res = _spawnvp(_P_WAIT, argv_spawn[0], argv_spawn);
     304                            if (res == -1)
     305                                res = err(pCtx, 1, "_spawnvp(_P_WAIT,%s,..)", argv_spawn[0]);
     306                        }
     307                        else
     308                            res = err(pCtx, 1, "quote_argv: out of memory");
    274309# else
    275310                        execvp(argv_spawn[0], argv_spawn);
     
    305340}
    306341
    307 static int
    308 syntax(const char *op, const char *msg)
     342#ifdef KMK_BUILTIN_STANDALONE
     343int main(int argc, char **argv, char **envp)
     344{
     345    KMKBUILTINCTX Ctx = { "kmk_test", NULL };
     346    return kmk_builtin_test(argc, argv, envp, &Ctx, NULL);
     347}
     348#endif
     349
     350static int
     351syntax(PTESTINSTANCE pThis, const char *op, const char *msg)
    309352{
    310353
    311354        if (op && *op)
    312                 errx(1, "%s: %s", op, msg);
     355                errx(pThis->pCtx, 1, "%s: %s", op, msg);
    313356        else
    314                 errx(1, "%s", msg);
     357                errx(pThis->pCtx, 1, "%s", msg);
    315358        return -42;
    316359}
    317360
    318361static int
    319 oexpr(enum token n)
     362oexpr(PTESTINSTANCE pThis, enum token n)
    320363{
    321364        int res;
    322365
    323         res = aexpr(n);
    324         if (res == -42 || *t_wp == NULL)
     366        res = aexpr(pThis, n);
     367        if (res == -42 || *pThis->t_wp == NULL)
    325368                return res;
    326         if (t_lex(*++t_wp) == BOR) {
    327                 int res2 = oexpr(t_lex(*++t_wp));
     369        if (t_lex(pThis, *++(pThis->t_wp)) == BOR) {
     370                int res2 = oexpr(pThis, t_lex(pThis, *++(pThis->t_wp)));
    328371                return res2 != -42 ? res2 || res : res2;
    329372        }
    330         t_wp--;
     373        pThis->t_wp--;
    331374        return res;
    332375}
    333376
    334377static int
    335 aexpr(enum token n)
     378aexpr(PTESTINSTANCE pThis, enum token n)
    336379{
    337380        int res;
    338381
    339         res = nexpr(n);
    340         if (res == -42 || *t_wp == NULL)
     382        res = nexpr(pThis, n);
     383        if (res == -42 || *pThis->t_wp == NULL)
    341384                return res;
    342         if (t_lex(*++t_wp) == BAND) {
    343                 int res2 = aexpr(t_lex(*++t_wp));
     385        if (t_lex(pThis, *++(pThis->t_wp)) == BAND) {
     386                int res2 = aexpr(pThis, t_lex(pThis, *++(pThis->t_wp)));
    344387                return res2 != -42 ? res2 && res : res2;
    345388        }
    346         t_wp--;
     389        pThis->t_wp--;
    347390        return res;
    348391}
    349392
    350393static int
    351 nexpr(enum token n)
     394nexpr(PTESTINSTANCE pThis, enum token n)
    352395{
    353396        if (n == UNOT) {
    354                 int res = nexpr(t_lex(*++t_wp));
     397                int res = nexpr(pThis, t_lex(pThis, *++(pThis->t_wp)));
    355398                return res != -42 ? !res : res;
    356399        }
    357         return primary(n);
    358 }
    359 
    360 static int
    361 primary(enum token n)
     400        return primary(pThis, n);
     401}
     402
     403static int
     404primary(PTESTINSTANCE pThis, enum token n)
    362405{
    363406        enum token nn;
     
    367410                return 0;               /* missing expression */
    368411        if (n == LPAREN) {
    369                 if ((nn = t_lex(*++t_wp)) == RPAREN)
     412                if ((nn = t_lex(pThis, *++(pThis->t_wp))) == RPAREN)
    370413                        return 0;       /* missing expression */
    371                 res = oexpr(nn);
    372                 if (res != -42 && t_lex(*++t_wp) != RPAREN)
    373                         return syntax(NULL, "closing paren expected");
     414                res = oexpr(pThis, nn);
     415                if (res != -42 && t_lex(pThis, *++(pThis->t_wp)) != RPAREN)
     416                        return syntax(pThis, NULL, "closing paren expected");
    374417                return res;
    375418        }
    376         if (t_wp_op && t_wp_op->op_type == UNOP) {
     419        if (pThis->t_wp_op && pThis->t_wp_op->op_type == UNOP) {
    377420                /* unary expression */
    378                 if (*++t_wp == NULL)
    379                         return syntax(t_wp_op->op_text, "argument expected");
     421                if (*++(pThis->t_wp) == NULL)
     422                        return syntax(pThis, pThis->t_wp_op->op_text, "argument expected");
    380423                switch (n) {
    381424                case STREZ:
    382                         return strlen(*t_wp) == 0;
     425                        return strlen(*pThis->t_wp) == 0;
    383426                case STRNZ:
    384                         return strlen(*t_wp) != 0;
     427                        return strlen(*pThis->t_wp) != 0;
    385428                case FILTT:
    386                         return isatty(getn(*t_wp));
     429                        return isatty(getn(pThis, *pThis->t_wp));
    387430                default:
    388                         return filstat(*t_wp, n);
     431                        return filstat(*pThis->t_wp, n);
    389432                }
    390433        }
    391434
    392         if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) {
    393                 return binop();
    394         }
    395 
    396         return strlen(*t_wp) > 0;
    397 }
    398 
    399 static int
    400 binop(void)
     435        if (t_lex(pThis, pThis->t_wp[1]), pThis->t_wp_op && pThis->t_wp_op->op_type == BINOP) {
     436                return binop(pThis);
     437        }
     438
     439        return strlen(*pThis->t_wp) > 0;
     440}
     441
     442static int
     443binop(PTESTINSTANCE pThis)
    401444{
    402445        const char *opnd1, *opnd2;
    403446        struct t_op const *op;
    404447
    405         opnd1 = *t_wp;
    406         (void) t_lex(*++t_wp);
    407         op = t_wp_op;
    408 
    409         if ((opnd2 = *++t_wp) == NULL)
    410                 return syntax(op->op_text, "argument expected");
     448        opnd1 = *pThis->t_wp;
     449        (void) t_lex(pThis, *++(pThis->t_wp));
     450        op = pThis->t_wp_op;
     451
     452        if ((opnd2 = *++(pThis->t_wp)) == NULL)
     453                return syntax(pThis, op->op_text, "argument expected");
    411454
    412455        switch (op->op_num) {
     
    420463                return strcmp(opnd1, opnd2) > 0;
    421464        case INTEQ:
    422                 return getn(opnd1) == getn(opnd2);
     465                return getn(pThis, opnd1) == getn(pThis, opnd2);
    423466        case INTNE:
    424                 return getn(opnd1) != getn(opnd2);
     467                return getn(pThis, opnd1) != getn(pThis, opnd2);
    425468        case INTGE:
    426                 return getn(opnd1) >= getn(opnd2);
     469                return getn(pThis, opnd1) >= getn(pThis, opnd2);
    427470        case INTGT:
    428                 return getn(opnd1) > getn(opnd2);
     471                return getn(pThis, opnd1) > getn(pThis, opnd2);
    429472        case INTLE:
    430                 return getn(opnd1) <= getn(opnd2);
     473                return getn(pThis, opnd1) <= getn(pThis, opnd2);
    431474        case INTLT:
    432                 return getn(opnd1) < getn(opnd2);
     475                return getn(pThis, opnd1) < getn(pThis, opnd2);
    433476        case FILNT:
    434477                return newerf(opnd1, opnd2);
     
    714757                        return NULL;
    715758                if (s[2] == '\0')
    716                         return bsearch(s + 1, mop2, __arraycount(mop2),
    717                             sizeof(*mop2), compare1);
     759                        return bsearch(s + 1, mop2, __arraycount(mop2), sizeof(*mop2), compare1);
    718760                else if (s[3] != '\0')
    719761                        return NULL;
    720762                else
    721                         return bsearch(s + 1, mop3, __arraycount(mop3),
    722                             sizeof(*mop3), compare2);
     763                        return bsearch(s + 1, mop3, __arraycount(mop3), sizeof(*mop3), compare2);
    723764        } else {
    724765                if (s[1] == '\0')
    725                         return bsearch(s, cop, __arraycount(cop), sizeof(*cop),
    726                             compare1);
     766                        return bsearch(s, cop, __arraycount(cop), sizeof(*cop), compare1);
    727767                else if (strcmp(s, cop2[0].op_text) == 0)
    728768                        return cop2;
     
    733773
    734774static enum token
    735 t_lex(char *s)
     775t_lex(PTESTINSTANCE pThis, char *s)
    736776{
    737777        struct t_op const *op;
    738778
    739779        if (s == NULL) {
    740                 t_wp_op = NULL;
     780                pThis->t_wp_op = NULL;
    741781                return EOI;
    742782        }
    743783
    744784        if ((op = findop(s)) != NULL) {
    745                 if (!((op->op_type == UNOP && isoperand()) ||
    746                     (op->op_num == LPAREN && *(t_wp+1) == 0))) {
    747                         t_wp_op = op;
     785                if (!((op->op_type == UNOP && isoperand(pThis)) ||
     786                    (op->op_num == LPAREN && *(pThis->t_wp+1) == 0))) {
     787                        pThis->t_wp_op = op;
    748788                        return op->op_num;
    749789                }
    750790        }
    751         t_wp_op = NULL;
     791        pThis->t_wp_op = NULL;
    752792        return OPERAND;
    753793}
    754794
    755795static int
    756 isoperand(void)
     796isoperand(PTESTINSTANCE pThis)
    757797{
    758798        struct t_op const *op;
    759799        char *s, *t;
    760800
    761         if ((s  = *(t_wp+1)) == 0)
     801        if ((s  = *(pThis->t_wp+1)) == 0)
    762802                return 1;
    763         if ((t = *(t_wp+2)) == 0)
     803        if ((t = *(pThis->t_wp+2)) == 0)
    764804                return 0;
    765805        if ((op = findop(s)) != NULL)
     
    770810/* atoi with error detection */
    771811static int
    772 getn(const char *s)
     812getn(PTESTINSTANCE pThis, const char *s)
    773813{
    774814        char *p;
     
    779819
    780820        if (errno != 0)
    781               return errx(-42, "%s: out of range", s);
     821              return errx(pThis->pCtx, -42, "%s: out of range", s);
    782822
    783823        while (isspace((unsigned char)*p))
     
    785825
    786826        if (*p)
    787               return errx(-42, "%s: bad number", s);
     827              return errx(pThis->pCtx, -42, "%s: bad number", s);
    788828
    789829        return (int) r;
     
    822862
    823863static int
    824 usage(const char *argv0)
    825 {
    826         fprintf(stdout,
    827                 "usage: %s expression [-- <prog> [args]]\n", argv0);
     864usage(PKMKBUILTINCTX pCtx, int fIsErr)
     865{
     866        kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s expression [-- <prog> [args]]\n", pCtx->pszProgName);
    828867        return 0; /* only used in --help. */
    829868}
     869
Note: See TracChangeset for help on using the changeset viewer.