OSSP CVS Repository

ossp - ossp-pkg/var/command.c
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

ossp-pkg/var/command.c
#include "internal.h"

int command(const char* begin, const char* end, const var_config_t* config,
            const char nameclass[256], var_cb_t lookup, void* lookup_context,
            int force_expand, tokenbuf* data)
    {
    const char* p = begin;
    tokenbuf tmptokbuf;
    tokenbuf search, replace, flags;
    tokenbuf number1, number2;
    int isrange;
    int rc;

    init_tokenbuf(&tmptokbuf);
    init_tokenbuf(&search);
    init_tokenbuf(&replace);
    init_tokenbuf(&flags);
    init_tokenbuf(&number1);
    init_tokenbuf(&number2);

    if (begin == end)
        return 0;

    switch (tolower(*p))
        {
        case 'l':               /* Turn data to lowercase. */
            if (data->begin)
                {
                char* ptr;
                /* If the buffer does not life in an allocated buffer,
                   we have to copy it before modifying the contents. */

                if (data->buffer_size == 0)
                    {
                    if (!assign_to_tokenbuf(data, data->begin, data->end - data->begin))
                        {
                        rc = VAR_OUT_OF_MEMORY;
                        goto error_return;
                        }
                    }
                for (ptr = (char*)data->begin; ptr != data->end; ++ptr)
                    *ptr = tolower(*ptr);
                }
            ++p;
            break;

        case 'u':               /* Turn data to uppercase. */
            if (data->begin)
                {
                char* ptr;
                if (data->buffer_size == 0)
                    {
                    if (!assign_to_tokenbuf(data, data->begin, data->end - data->begin))
                        {
                        rc = VAR_OUT_OF_MEMORY;
                        goto error_return;
                        }
                    }
                for (ptr = (char*)data->begin; ptr != data->end; ++ptr)
                    *ptr = toupper(*ptr);
                }
            ++p;
            break;

        case 'o':               /* Cut out substrings. */
            ++p;
            rc = number(p, end);
            if (rc == 0)
                {
                rc = VAR_MISSING_START_OFFSET;
                goto error_return;
                }
            else
                {
                number1.begin = p;
                number1.end   = p + rc;
                number1.buffer_size = 0;
                p += rc;
                }

            if (*p == ',')
                {
                isrange = 0;
                ++p;
                }
            else if (*p == '-')
                {
                isrange = 1;
                ++p;
                }
            else
                {
                rc = VAR_INVALID_OFFSET_DELIMITER;
                goto error_return;
                }

            rc = number(p, end);
            number2.begin = p;
            number2.end   = p + rc;
            number2.buffer_size = 0;
            p += rc;
            if (data->begin)
                {
                rc = cut_out_offset(data, &number1, &number2, isrange);
                if (rc < 0)
                    goto error_return;
                }
            break;

        case '#':               /* Substitute length of the string. */
            if (data->begin)
                {
                char buf[1024];
                sprintf(buf, "%d", data->end - data->begin);
                free_tokenbuf(data);
                if (!assign_to_tokenbuf(data, buf, strlen(buf)))
                    {
                    rc = VAR_OUT_OF_MEMORY;
                    goto error_return;
                    }
                }
            ++p;
            break;

        case '-':               /* Substitute parameter if data is empty. */
            ++p;
            rc = exptext_or_variable(p, end, config, nameclass, lookup, lookup_context,
                                     force_expand, &tmptokbuf);
            if (rc < 0)
                goto error_return;
            else if (rc == 0)
                {
                rc = VAR_MISSING_PARAMETER_IN_COMMAND;
                goto error_return;
                }
            else
                p += rc;
            if (data->begin != NULL && data->begin == data->end)
                {
                free_tokenbuf(data);
                move_tokenbuf(&tmptokbuf, data);
                }
            break;

        case '*':               /* Return "" if data is not empty, parameter otherwise. */
            ++p;
            rc = exptext_or_variable(p, end, config, nameclass, lookup, lookup_context,
                                     force_expand, &tmptokbuf);
            if (rc < 0)
                goto error_return;
            else if (rc == 0)
                {
                rc = VAR_MISSING_PARAMETER_IN_COMMAND;
                goto error_return;
                }
            else
                p += rc;
            if (data->begin != NULL)
                {
                if (data->begin == data->end)
                    {
                    free_tokenbuf(data);
                    move_tokenbuf(&tmptokbuf, data);
                    }
                else
                    {
                    free_tokenbuf(data);
                    data->begin = data->end = "";
                    data->buffer_size = 0;
                    }
                }
            break;

        case '+':               /* Substitute parameter if data is not empty. */
            ++p;
            rc = exptext_or_variable(p, end, config, nameclass, lookup, lookup_context,
                                     force_expand, &tmptokbuf);
            if (rc < 0)
                goto error_return;
            else if (rc == 0)
                {
                rc = VAR_MISSING_PARAMETER_IN_COMMAND;
                goto error_return;
                }
            else
                p += rc;
            if (data->begin != NULL)
                {
                if (data->begin != data->end)
                    {
                    free_tokenbuf(data);
                    move_tokenbuf(&tmptokbuf, data);
                    }
                }
            break;

        case 's':               /* Search and replace. */
            ++p;

            if (*p != '/')
                return VAR_MALFORMATTED_REPLACE;
            else
                ++p;

            rc = substext_or_variable(p, end, config, nameclass, lookup, lookup_context,
                                      force_expand, &search);
            if (rc < 0)
                goto error_return;
            else
                p += rc;

            if (*p != '/')
                {
                rc = VAR_MALFORMATTED_REPLACE;
                goto error_return;
                }
            else
                ++p;

            rc = substext_or_variable(p, end, config, nameclass, lookup, lookup_context,
                                      force_expand, &replace);
            if (rc < 0)
                goto error_return;
            else
                p += rc;

            if (*p != '/')
                {
                rc = VAR_MALFORMATTED_REPLACE;
                goto error_return;
                }
            else
                ++p;

            rc = exptext(p, end, config);
            if (rc < 0)
                goto error_return;
            else
                {
                flags.begin = p;
                flags.end = p + rc;
                flags.buffer_size = 0;
                p += rc;
                }

            if (data->begin)
                {
                rc = search_and_replace(data, &search, &replace, &flags);
                if (rc < 0)
                    goto error_return;
                }
            break;

        case 'y':               /* Transpose characters from class A to class B. */
            ++p;

            if (*p != '/')
                return VAR_MALFORMATTED_TRANSPOSE;
            else
                ++p;

            rc = substext_or_variable(p, end, config, nameclass, lookup, lookup_context,
                                      force_expand, &search);
            if (rc < 0)
                goto error_return;
            else
                p += rc;

            if (*p != '/')
                {
                rc = VAR_MALFORMATTED_TRANSPOSE;
                goto error_return;
                }
            else
                ++p;

            rc = substext_or_variable(p, end, config, nameclass, lookup, lookup_context,
                                      force_expand, &replace);
            if (rc < 0)
                goto error_return;
            else
                p += rc;

            if (*p != '/')
                {
                rc = VAR_MALFORMATTED_TRANSPOSE;
                goto error_return;
                }
            else
                ++p;

            if (data->begin)
                {
                rc = transpose(data, &search, &replace);
                if (rc < 0)
                    goto error_return;
                }
            break;


        case 'p':               /* Padding. */
            ++p;

            if (*p != '/')
                return VAR_MALFORMATTED_PADDING;
            else
                ++p;

            rc = number(p, end);
            if (rc == 0)
                {
                rc = VAR_MISSING_PADDING_WIDTH;
                goto error_return;
                }
            else
                {
                number1.begin = p;
                number1.end   = p + rc;
                number1.buffer_size = 0;
                p += rc;
                }

            if (*p != '/')
                {
                rc = VAR_MALFORMATTED_PADDING;
                goto error_return;
                }
            else
                ++p;

            rc = substext_or_variable(p, end, config, nameclass, lookup, lookup_context,
                                      force_expand, &replace);
            if (rc < 0)
                goto error_return;
            else
                p += rc;

            if (*p != '/')
                {
                rc = VAR_MALFORMATTED_PADDING;
                goto error_return;
                }
            else
                ++p;

            if (*p != 'l' && *p != 'c' && *p != 'r')
                {
                rc = VAR_MALFORMATTED_PADDING;
                goto error_return;
                }
            else
                ++p;

            if (data->begin)
                {
                rc = padding(data, &number1, &replace, p[-1]);
                if (rc < 0)
                    goto error_return;
                }
            break;

        default:
            return VAR_UNKNOWN_COMMAND_CHAR;
        }

    /* Exit gracefully. */

    free_tokenbuf(&tmptokbuf);
    free_tokenbuf(&search);
    free_tokenbuf(&replace);
    free_tokenbuf(&flags);
    free_tokenbuf(&number1);
    free_tokenbuf(&number2);
    return p - begin;

  error_return:
    free_tokenbuf(data);
    free_tokenbuf(&tmptokbuf);
    free_tokenbuf(&search);
    free_tokenbuf(&replace);
    free_tokenbuf(&flags);
    free_tokenbuf(&number1);
    free_tokenbuf(&number2);
    return rc;
    }

CVSTrac 2.0.1