#include #include #include #include struct fenum { char name[128]; struct fenum *next; unsigned value; }; struct field { char name[128]; struct field *next; unsigned mask; unsigned shift; struct fenum *fenums; }; struct reg { char name[128]; unsigned offset; struct reg *next; struct field *fields; }; struct ctx { struct reg *regs; struct reg *last_reg; struct field *last_field; struct fenum *last_fenum; char tokens[4][64]; unsigned ntokens; unsigned nheading_space; unsigned line; }; static void ptoken(struct ctx *ctx) { unsigned i; for (i = 0; i < ctx->ntokens; i++) { fprintf(stderr, "token[%d] %s\n", i, ctx->tokens[i]); } } static int parse_fenum(struct ctx *ctx, const char *line) { struct fenum *fenum; if (ctx->ntokens != 2) { fprintf(stderr, "%s %d [%d] wrong nomber of token for fenum %d\n", __func__, __LINE__, ctx->line, ctx->ntokens); ptoken(ctx); return -EINVAL; } fenum = calloc(1, sizeof(*fenum)); if (fenum == NULL) { return -ENOMEM; } strcpy(fenum->name, ctx->tokens[0]); fenum->value = strtoul(ctx->tokens[1], NULL, 0); if (ctx->last_fenum) { ctx->last_fenum->next = fenum; } if (ctx->last_field->fenums == NULL) { ctx->last_field->fenums = fenum; } ctx->last_fenum = fenum; return 0; } static int parse_field(struct ctx *ctx, const char *line) { struct field *field; char *tmp; /* only do _mask or _bit */ if (strstr(line, "_mask") == NULL && strstr(line, "_bit") == NULL) { return 0; } if (ctx->ntokens != 3) { fprintf(stderr, "%s %d [%d] wrong nomber of token for field %d\n", __func__, __LINE__, ctx->line, ctx->ntokens); ptoken(ctx); return -EINVAL; } field = calloc(1, sizeof(*field)); if (field == NULL) { return -ENOMEM; } strcpy(field->name, ctx->tokens[0]); tmp = strstr(field->name, "_mask"); if (tmp == NULL) { tmp = strstr(field->name, "_bit"); } *tmp = 0; field->mask = strtoul(ctx->tokens[1], NULL, 0); field->shift = strtoul(ctx->tokens[2], NULL, 0); if (ctx->last_field) { ctx->last_field->next = field; } if (ctx->last_reg->fields == NULL) { ctx->last_reg->fields = field; } ctx->last_field = field; return 0; } static int parse_reg(struct ctx *ctx, const char *line) { struct reg *reg; if (ctx->ntokens != 2) { fprintf(stderr, "%s %d [%d] wrong nomber of token for reg %d\n", __func__, __LINE__, ctx->line, ctx->ntokens); return -EINVAL; } reg = calloc(1, sizeof(*reg)); if (reg == NULL) { return -ENOMEM; } strcpy(reg->name, ctx->tokens[0]); reg->offset = strtoul(ctx->tokens[1], NULL, 0); if (ctx->last_reg) { ctx->last_reg->next = reg; } if (ctx->regs == NULL) { ctx->regs = reg; } ctx->last_reg = reg; return 0; } static int valid_char(unsigned ts, char c) { if (c >= 'A' && c <= 'Z') return 1; if (c >= 'a' && c <= 'z') return 1; if (ts) { if (c >= '0' && c <= '9') return 1; if (c == '_') return 1; } return 0; } static int valid_value(unsigned ts, char c) { if (c >= '0' && c <= '9') return 1; if (ts == 1) { if (c == 'x') return 1; } if (ts > 1) { if (c >= 'a' && c <= 'f') return 1; if (c >= 'A' && c <= 'F') return 1; } return 0; } static int parse_tokenize(struct ctx *ctx, const char *line) { unsigned i = 0; unsigned ts = 0; ctx->ntokens = 0; ctx->nheading_space = 0; do { if (valid_char(ts, line[i])) { ctx->tokens[ctx->ntokens][ts++] = line[i]; continue; } if (valid_value(ts, line[i])) { ctx->tokens[ctx->ntokens][ts++] = line[i]; continue; } switch (line[i]) { case 0: return 0; case '<': if (line[i + 1] != '<') break; case '=': case ',': ctx->tokens[ctx->ntokens][ts] = 0; ts = 0; ctx->ntokens++; break; case ' ': if (!ctx->ntokens && !ts) ctx->nheading_space++; default: break; } } while (line[++i]); return 0; } static int parse(struct ctx *ctx, const char *filename) { FILE *file; char line[128]; int r; file = fopen(filename, "r"); if (file == NULL) { fprintf(stderr, "%s %d failed opening %s\n", __func__, __LINE__, filename); return -EINVAL; } while (!feof(file)) { if (fgets(line, sizeof(line), file) == NULL) { continue; } ctx->line++; ctx->nheading_space = 0; r = parse_tokenize(ctx, line); if (r) { return r; } switch (ctx->nheading_space) { case 4: r = parse_reg(ctx, line); ctx->last_field = NULL; break; case 8: r = parse_field(ctx, line); ctx->last_fenum = NULL; break; case 12: r = parse_fenum(ctx, line); break; default: continue; } if (r) { return r; } } return 0; } void pspace(unsigned n, unsigned s) { unsigned i; if (s >= n) { printf(" "); return; } for (i = 0; i < (n - s - 1); i++) { printf(" "); } } int main(int argc, char *argv[]) { struct ctx *ctx; struct reg *reg; struct field *field; struct fenum *fenum; int r; ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) { return -ENOMEM; } r = parse(ctx, argv[1]); if (r) { return r; } reg = ctx->regs; while (reg) { printf("#define %s", reg->name); pspace(61, strlen(reg->name) + 8); printf("0x%08x\n", reg->offset); field = reg->fields; while (field) { printf("#define %s__%s(x)", reg->name, field->name); pspace(61, strlen(reg->name) + strlen(field->name) + 13); printf("(((x) & 0x%08x) << %d)\n", field->mask, field->shift); fenum = field->fenums; while (fenum) { printf("#define %s", fenum->name); pspace(65, strlen(fenum->name) + 12); printf("%d\n", fenum->value); fenum = fenum->next; } field = field->next; } reg = reg->next; } }