Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 6be4142 in mainline


Ignore:
Timestamp:
2012-08-12T04:53:47Z (9 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master
Children:
1b6b76d
Parents:
0153c87
Message:

Bithenge: print transform errors; fixes and fat.bh improvements

Location:
uspace
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bithenge/expression.c

    r0153c87 r6be4142  
    464464        rc = bithenge_node_get(node, self->key, out);
    465465        bithenge_node_dec_ref(node);
     466        if (rc == ENOENT)
     467                return bithenge_scope_error(scope, "No member %t", self->key);
    466468        return rc;
    467469}
     
    549551                        return rc;
    550552        }
    551         return ENOENT;
     553        return bithenge_scope_error(scope, "No scope member %t", self->key);
    552554}
    553555
  • uspace/app/bithenge/print.c

    r0153c87 r6be4142  
    3838
    3939#include <errno.h>
     40#include <stdarg.h>
    4041#include <stdio.h>
    4142#include "blob.h"
     
    4748        bool first;
    4849        int depth;
     50        char *buffer;
     51        size_t buffer_size;
    4952} state_t;
    5053
     54static void state_printf(state_t *state, const char *format, ...)
     55{
     56        va_list ap;
     57        va_start(ap, format);
     58        if (state->buffer) {
     59                int rc = vsnprintf(state->buffer, state->buffer_size, format,
     60                    ap);
     61                if (rc > 0 && (size_t)rc >= state->buffer_size)
     62                        rc = state->buffer_size - 1;
     63                if (rc > 0) {
     64                        state->buffer += rc;
     65                        state->buffer_size -= rc;
     66                }
     67        } else {
     68                vprintf(format, ap);
     69        }
     70        va_end(ap);
     71}
     72
    5173static int print_node(state_t *, bithenge_node_t *);
    5274
    5375static void newline(state_t *state)
    5476{
    55         printf("\n");
     77        state_printf(state, "\n");
    5678        for (int i = 0; i < state->depth; i++) {
    57                 printf("    ");
     79                state_printf(state, "    ");
    5880        }
    5981}
     
    7496        int rc = EOK;
    7597        if (!state->first)
    76                 printf(",");
     98                state_printf(state, ",");
    7799        newline(state);
    78100        state->first = false;
     
    80102            && bithenge_node_type(key) != BITHENGE_NODE_STRING;
    81103        if (add_quotes)
    82                 printf("\"");
     104                state_printf(state, "\"");
    83105        rc = print_node(state, key);
    84106        if (rc != EOK)
    85107                goto end;
    86108        if (add_quotes)
    87                 printf("\"");
    88         printf(": ");
     109                state_printf(state, "\"");
     110        state_printf(state, ": ");
    89111        rc = print_node(state, value);
    90112        if (rc != EOK)
     
    99121{
    100122        int rc;
    101         printf("{");
     123        state_printf(state, "{");
    102124        increase_depth(state);
    103125        state->first = true;
     
    109131                newline(state);
    110132        state->first = false;
    111         printf("}");
     133        state_printf(state, "}");
    112134        return EOK;
    113135}
     
    118140        switch (state->type) {
    119141        case BITHENGE_PRINT_PYTHON:
    120                 printf(value ? "True" : "False");
     142                state_printf(state, value ? "True" : "False");
    121143                break;
    122144        case BITHENGE_PRINT_JSON:
    123                 printf(value ? "true" : "false");
     145                state_printf(state, value ? "true" : "false");
    124146                break;
    125147        }
     
    130152{
    131153        bithenge_int_t value = bithenge_integer_node_value(node);
    132         printf("%" BITHENGE_PRId, value);
     154        state_printf(state, "%" BITHENGE_PRId, value);
    133155        return EOK;
    134156}
     
    137159{
    138160        const char *value = bithenge_string_node_value(node);
    139         printf("\"");
     161        state_printf(state, "\"");
    140162        for (string_iterator_t i = string_iterator(value); !string_iterator_done(&i); ) {
    141163                wchar_t ch;
     
    144166                        return rc;
    145167                if (ch == '"' || ch == '\\') {
    146                         printf("\\%lc", (wint_t) ch);
     168                        state_printf(state, "\\%lc", (wint_t) ch);
    147169                } else if (ch <= 0x1f) {
    148                         printf("\\u%04x", (unsigned int) ch);
     170                        state_printf(state, "\\u%04x", (unsigned int) ch);
    149171                } else {
    150                         printf("%lc", (wint_t) ch);
     172                        state_printf(state, "%lc", (wint_t) ch);
    151173                }
    152174        }
    153         printf("\"");
     175        state_printf(state, "\"");
    154176        return EOK;
    155177}
     
    162184        aoff64_t size = sizeof(buffer);
    163185        int rc;
    164         printf(state->type == BITHENGE_PRINT_PYTHON ? "b\"" : "\"");
     186        state_printf(state,
     187            state->type == BITHENGE_PRINT_PYTHON ? "b\"" : "\"");
    165188        do {
    166189                rc = bithenge_blob_read(blob, pos, buffer, &size);
     
    168191                        return rc;
    169192                for (aoff64_t i = 0; i < size; i++)
    170                         printf("\\x%02x", (unsigned int)(uint8_t)buffer[i]);
     193                        state_printf(state, "\\x%02x",
     194                            (unsigned int)(uint8_t)buffer[i]);
    171195                pos += size;
    172196        } while (size == sizeof(buffer));
    173         printf("\"");
     197        state_printf(state, "\"");
    174198        return EOK;
    175199}
     
    192216}
    193217
    194 /** Print a tree as text.
     218/** Print a tree as text to stdout.
    195219 * @param type The format to use.
    196220 * @param tree The root node of the tree to print.
     
    198222int bithenge_print_node(bithenge_print_type_t type, bithenge_node_t *tree)
    199223{
    200         state_t state = {type, true, 0};
     224        state_t state = {type, true, 0, NULL, 0};
    201225        return print_node(&state, tree);
    202226}
    203227
     228/** Print a tree as text into a buffer.
     229 * @param[in,out] str Holds a pointer to the buffer; changed to point to the
     230 * null character.
     231 * @param[in,out] size Holds the size of the buffer; changed to hold the
     232 * remaining size.
     233 * @param type The format to use.
     234 * @param tree The root node of the tree to print.
     235 * @return EOK on success or an error code from errno.h. */
     236int bithenge_print_node_to_string(char **str, size_t *size,
     237    bithenge_print_type_t type, bithenge_node_t *tree)
     238{
     239        state_t state = {type, true, 0, *str, *size};
     240        int rc = print_node(&state, tree);
     241        *str = state.buffer;
     242        *size = state.buffer_size;
     243        return rc;
     244}
     245
    204246/** @}
    205247 */
  • uspace/app/bithenge/print.h

    r0153c87 r6be4142  
    5151
    5252int bithenge_print_node(bithenge_print_type_t, bithenge_node_t *);
     53int bithenge_print_node_to_string(char **, size_t *, bithenge_print_type_t,
     54    bithenge_node_t *);
    5355
    5456#endif
  • uspace/app/bithenge/sequence.c

    r0153c87 r6be4142  
    418418        struct_node_t *node = node_as_struct(base);
    419419
    420         /* We didn't inc_ref for the scope in struct_transform_make_node, so
    421          * make sure it doesn't try to dec_ref. */
    422         seq_node_scope(struct_as_seq(node))->current_node = NULL;
    423         seq_node_destroy(struct_as_seq(node));
     420        /* Treat the scope carefully because of the circular reference. In
     421         * struct_transform_make_node, things are set up so node owns a
     422         * reference to the scope, but scope doesn't own a reference to node,
     423         * so node's reference count is too low. */
     424        bithenge_scope_t *scope = seq_node_scope(struct_as_seq(node));
     425        if (scope->refs == 1) {
     426                /* Mostly normal destroy, but we didn't inc_ref(node) for the
     427                 * scope in struct_transform_make_node, so make sure it doesn't
     428                 * try to dec_ref. */
     429                scope->current_node = NULL;
     430                seq_node_destroy(struct_as_seq(node));
     431        } else if (scope->refs > 1) {
     432                /* The scope is still needed, but node isn't otherwise needed.
     433                 * Switch things around so scope owns a reference to node, but
     434                 * not vice versa, and scope's reference count is too low. */
     435                bithenge_node_inc_ref(base);
     436                bithenge_scope_dec_ref(scope);
     437                return;
     438        } else {
     439                /* This happens after the previous case, when scope is no
     440                 * longer used and is being destroyed. Since scope is already
     441                 * being destroyed, set it to NULL here so we don't try to
     442                 * destroy it twice. */
     443                struct_as_seq(node)->scope = NULL;
     444                seq_node_destroy(struct_as_seq(node));
     445        }
    424446
    425447        bithenge_transform_dec_ref(struct_as_transform(node->transform));
  • uspace/app/bithenge/test.c

    r0153c87 r6be4142  
    5050        int rc;
    5151        if (argc < 3) {
    52                 // {True: {}, -1351: "\"false\"", "true": False, 0: b"..."}
    53                 const char data[] = "'Twas brillig, and the slithy toves";
    54                 bithenge_node_t *node;
    55                 bithenge_node_t *subnodes[8];
    56                 bithenge_new_boolean_node(&subnodes[0], true);
    57                 bithenge_new_simple_internal_node(&subnodes[1], NULL, 0, false);
    58                 bithenge_new_integer_node(&subnodes[2], -1351);
    59                 bithenge_new_string_node(&subnodes[3], "\"false\"", false);
    60                 bithenge_new_string_node(&subnodes[4], "true", false);
    61                 bithenge_new_boolean_node(&subnodes[5], false);
    62                 bithenge_new_integer_node(&subnodes[6], 0);
    63                 bithenge_new_blob_from_data(&subnodes[7], data, sizeof(data));
    64                 bithenge_new_simple_internal_node(&node, subnodes, 4, false);
    65                 bithenge_print_node(BITHENGE_PRINT_PYTHON, node);
    66                 printf("\n");
    67                 bithenge_print_node(BITHENGE_PRINT_JSON, node);
    68                 printf("\n");
    69                 bithenge_node_dec_ref(node);
     52                fprintf(stderr, "Usage: %s <script> <source>\n", argv[0]);
     53                return 1;
    7054        } else {
    7155                bithenge_scope_t *scope = NULL;
     
    9680                rc = bithenge_transform_apply(transform, scope, node, &node2);
    9781                if (rc != EOK) {
    98                         printf("Error applying transform: %s\n", str_error(rc));
     82                        const char *message = bithenge_scope_get_error(scope);
     83                        printf("Error applying transform: %s\n",
     84                            message ? message : str_error(rc));
    9985                        node2 = NULL;
    10086                        goto error;
     
    10894                rc = bithenge_print_node(BITHENGE_PRINT_PYTHON, node2);
    10995                if (rc != EOK) {
    110                         printf("Error printing node: %s\n", str_error(rc));
     96                        const char *message = bithenge_scope_get_error(scope);
     97                        printf("Error printing node: %s\n",
     98                            message ? message : str_error(rc));
    11199                        goto error;
    112100                }
  • uspace/app/bithenge/transform.c

    r0153c87 r6be4142  
    3737#include <assert.h>
    3838#include <errno.h>
     39#include <stdarg.h>
    3940#include <stdlib.h>
    4041#include "blob.h"
     42#include "print.h"
    4143#include "transform.h"
    4244
     
    187189                bithenge_scope_inc_ref(outer);
    188190        self->outer = outer;
     191        self->error = NULL;
    189192        self->barrier = false;
    190193        self->num_params = 0;
     
    209212        bithenge_scope_dec_ref(self->outer);
    210213        free(self->params);
     214        free(self->error);
    211215        free(self);
    212216}
     
    218222{
    219223        return self->outer;
     224}
     225
     226/** Get the error message stored in the scope, which may be NULL. The error
     227 * message only exists as long as the scope does.
     228 * @param scope The scope to get the error message from.
     229 * @return The error message, or NULL. */
     230const char *bithenge_scope_get_error(bithenge_scope_t *scope)
     231{
     232        return scope->error;
     233}
     234
     235/** Set the error message for the scope. The error message is stored in the
     236 * outermost scope, but if any scope already has an error message this error
     237 * message is ignored.
     238 * @param scope The scope.
     239 * @param format The format string.
     240 * @return EINVAL normally, or another error code from errno.h. */
     241int bithenge_scope_error(bithenge_scope_t *scope, const char *format, ...)
     242{
     243        if (scope->error)
     244                return EINVAL;
     245        while (scope->outer) {
     246                scope = scope->outer;
     247                if (scope->error)
     248                        return EINVAL;
     249        }
     250        size_t space_left = 256;
     251        scope->error = malloc(space_left);
     252        if (!scope->error)
     253                return ENOMEM;
     254        char *out = scope->error;
     255        va_list ap;
     256        va_start(ap, format);
     257
     258        while (*format) {
     259                if (format[0] == '%' && format[1] == 't') {
     260                        format += 2;
     261                        int rc = bithenge_print_node_to_string(&out,
     262                            &space_left, BITHENGE_PRINT_PYTHON,
     263                            va_arg(ap, bithenge_node_t *));
     264                        if (rc != EOK) {
     265                                va_end(ap);
     266                                return rc;
     267                        }
     268                } else {
     269                        const char *end = str_chr(format, '%');
     270                        if (!end)
     271                                end = format + str_length(format);
     272                        size_t size = min((size_t)(end - format),
     273                            space_left - 1);
     274                        memcpy(out, format, size);
     275                        format = end;
     276                        out += size;
     277                        space_left -= size;
     278                }
     279        }
     280        *out = '\0';
     281
     282        va_end(ap);
     283        return EINVAL;
    220284}
    221285
  • uspace/app/bithenge/transform.h

    r0153c87 r6be4142  
    5454        unsigned int refs;
    5555        struct bithenge_scope *outer;
     56        char *error;
    5657        bool barrier;
    5758        int num_params;
     
    152153void bithenge_scope_dec_ref(bithenge_scope_t *);
    153154bithenge_scope_t *bithenge_scope_outer(bithenge_scope_t *);
     155const char *bithenge_scope_get_error(bithenge_scope_t *);
     156int bithenge_scope_error(bithenge_scope_t *, const char *, ...);
    154157bithenge_node_t *bithenge_scope_get_current_node(bithenge_scope_t *);
    155158void bithenge_scope_set_current_node(bithenge_scope_t *, bithenge_node_t *);
  • uspace/dist/src/bithenge/fat.bh

    r0153c87 r6be4142  
    2727# FAT filesystem script.
    2828# Largely based on https://en.wikipedia.org/wiki/File_Allocation_Table
     29# Currently only FAT12 and FAT16 are supported.
    2930
    3031transform u8 = uint8;
     
    3233transform u32 = uint32le;
    3334
     35transform fat_attributes = struct {
     36        .read_only <- bit;
     37        .hidden <- bit;
     38        .system <- bit;
     39        .volume_label <- bit;
     40        .subdirectory <- bit;
     41        .archive <- bit;
     42        .device <- bit;
     43        .reserved <- bit;
     44} <- bits_le <- known_length(1);
     45
    3446transform fat_dir_entry(disk) = struct {
    3547        .filename <- known_length(8);
    3648        .extension <- known_length(3);
    37         .attrs <- u8;
     49        .attrs <- fat_attributes;
    3850        .flags <- u8;
    3951        .ctime_fine <- u8;
     
    7991        };
    8092
    81         .num_sectors <- if (.bpb331.ignore) {
    82                 (.num_sectors_16)
    83         } else {
    84                 (.bpb331.num_sectors_32)
    85         };
    86 
    87         .first_root_sector <- (.num_reserved_sectors + .num_fats * .sectors_per_fat);
    88         .first_data_sector <- (.first_root_sector +
    89             (.num_root_entries * 32 + .bytes_per_sector - 1) //
    90             .bytes_per_sector);
    91         .num_clusters <- (2 + (.num_sectors - .first_data_sector) // .sectors_per_cluster);
    92         .bits <- if (.num_clusters < 4085) { (12) }
    93             else { if (.num_clusters < 65525) { (16) } else { (32) } };
    94 
    95         .fats <- partial(.num_reserved_sectors * .bytes_per_sector) {
    96                 repeat(.num_fats) {
    97                         fat_table(.bits, .num_clusters) <-
    98                                 known_length(.sectors_per_fat * .bytes_per_sector)
    99                 }
    100         } <- (disk);
    101 
    102         .root <- partial(.first_root_sector * .bytes_per_sector) {
    103                 repeat(.num_root_entries) { fat_dir_entry(disk) } } <- (disk);
     93        .drive_number <- u8;
     94        .chkdsk_flags <- u8;
     95        .extended_boot_signature <- u8;
     96        if (.extended_boot_signature == 41) {
     97                .volume_id <- u32;
     98                .volume_label <- ascii <- known_length(11);
     99                .type <- ascii <- known_length(8);
     100        }
    104101
    105102        .boot_signature <- (disk[510,2]); # b"\x55\xaa"; TODO: what if .bytes_per_sector < 512?
    106103};
    107104
    108 transform fat_filesystem = partial { fat_super(in) };
     105transform fat_filesystem_tree(disk) = struct {
     106        .super <- partial{fat_super(disk)} <- (disk);
     107
     108        .num_sectors <- if (.super.bpb331.ignore) {
     109                (.super.num_sectors_16)
     110        } else {
     111                (.super.bpb331.num_sectors_32)
     112        };
     113
     114        .first_root_sector <- (.super.num_reserved_sectors + .super.num_fats * .super.sectors_per_fat);
     115        .first_data_sector <- (.first_root_sector +
     116            (.super.num_root_entries * 32 + .super.bytes_per_sector - 1) //
     117            .super.bytes_per_sector);
     118        .num_clusters <- (2 + (.num_sectors - .first_data_sector) // .super.sectors_per_cluster);
     119        .bits <- if (.num_clusters < 4085) { (12) }
     120            else { if (.num_clusters < 65525) { (16) } else { (32) } };
     121
     122        .fats <- partial(.super.num_reserved_sectors * .super.bytes_per_sector) {
     123                repeat(.super.num_fats) {
     124                        fat_table(.bits, .num_clusters) <-
     125                                known_length(.super.sectors_per_fat * .super.bytes_per_sector)
     126                }
     127        } <- (disk);
     128
     129        .root <- partial(.first_root_sector * .super.bytes_per_sector) {
     130                repeat(.super.num_root_entries) { fat_dir_entry(disk) } } <- (disk);
     131};
     132
     133transform fat_filesystem = partial {fat_filesystem_tree(in)};
    109134
    110135transform main = fat_filesystem;
Note: See TracChangeset for help on using the changeset viewer.