📄 jannotate.c
字号:
#include <stdio.h>#include <stdlib.h>#include <jpr/type.h>#include <jpr/log.h>#include <jpr/system.h>#include <jpr/io.h>#include <jpr/arena.h>#include <prelude/parse.h>#include <prelude/verify.h>#include <prelude/pretty_print.h>#include "parser.tab.h"#include "globals.h"//#define JAN_DEBUGconst char *attribute_name = 0;const char *class_annotation = 0;ju2 constants_count = 0;const char **constant_annotations = 0;ju2 fields_count = 0;const char **field_annotations = 0;ju2 methods_count = 0;const char **method_annotations = 0;voiddefine_attribute_name(const char *name) { if (attribute_name != 0) { free((void*) attribute_name); } attribute_name = name;}voiddefine_class_annotation(const char *annotation) { class_annotation = annotation;}voiddefine_constant_annotation(ju2 index, const char *annotation) { if (index < constants_count) { if (constant_annotations[index] != 0) free((void *) constant_annotations[index]); constant_annotations[index] = annotation; }}voiddefine_field_annotation(ju2 index, const char *annotation) { if (index < fields_count) { if (field_annotations[index] != 0) free((void *) field_annotations[index]); field_annotations[index] = annotation; }}voiddefine_method_annotation(ju2 index, const char *annotation) { if (index < methods_count) { if (method_annotations[index] != 0) free((void *) method_annotations[index]); method_annotations[index] = annotation; }}void init_constant_annotations(ju2 count) { constants_count = count; constant_annotations = calloc(count, sizeof(const char *));}void init_field_annotations(ju2 count) { fields_count = count; field_annotations = calloc(count, sizeof(const char *));}void init_method_annotations(ju2 count) { methods_count = count; method_annotations = calloc(count, sizeof(const char *));}boolcheck_constant_annotations(const PREClassFile *classfile) { const PREConstantPool *constant_pool = pre_classfile_constant_pool(classfile); ju2 i; if (constant_annotations[0] != 0) return false; for (i = 1; i < constants_count; i++) { const void *cp = pre_classfile_constant_pool_entry(classfile, i); if (cp == 0) { if (constant_annotations[i] != 0) return false; } else { ju1 tag = pre_cp_tag(cp); if (tag == J_CONSTANT_NameAndType || tag == J_CONSTANT_Utf8) { if (constant_annotations[i] != 0) return false; } } } return true;}voidyyerror(char *s) { fprintf(stderr, "%s\n", s);}void *yy_create_buffer(void *file, size_t size);struct id_index_map_t { ju2 id; ju2 index;};intmain(int argc, const char * const * argv) { int result; FILE *spec_file, *outfile; JFile infile; void *yy_buffer_state; int errno; if (argc != 3) { fprintf(stderr, "usage: %s specfile infile\n", argv[0]); exit(1); } spec_file = fopen(argv[1], "r"); if (spec_file == NULL) { fprintf(stderr, "%s: unable to open %s\n", argv[0], argv[1]); exit(1); } if (j_load_file(argv[2], &infile) < 0) { fprintf(stderr, "%s: unable to open %s\n", argv[0], argv[2]); exit(1); } JArena *arena = j_arena_new(); if (arena == 0) { fprintf(stderr, "%s: memory allocation failure\n", argv[0]); exit(1); } PREClassFile *classfile = pre_parse_classfile(arena, j_file_data(&infile), j_file_size(&infile), &errno); if (classfile == 0) { fprintf(stderr, "%s: unable to parse %s: %d\n", argv[0], argv[2], errno); exit(1); } if (pre_verify_classfile(classfile) < 0) { fprintf(stderr, "%s: unable to verify %s\n", argv[0], argv[2]); exit(1); } yy_buffer_state = yy_create_buffer(spec_file, 16384); yy_switch_to_buffer(yy_buffer_state); init_constant_annotations(pre_classfile_constant_pool_count(classfile)); init_field_annotations(pre_classfile_fields_count(classfile)); init_method_annotations(pre_classfile_methods_count(classfile)); if ((result = yyparse()) != 0) return result; yy_delete_buffer(yy_buffer_state);#ifdef JAN_DEBUG fprintf(stderr, "attribute \"%s\"\n", attribute_name); if (class_annotation != 0) fprintf(stderr, "class \"%s\"\n", class_annotation); { ju2 i; for (i = 0; i < pre_classfile_constant_pool_count(classfile); i++) { if (constant_annotations[i] != 0) fprintf(stderr, "constant [%i] \"%s\"\n", i, constant_annotations[i]); } } { ju2 i; for (i = 0; i < pre_classfile_fields_count(classfile); i++) { if (field_annotations[i] != 0) fprintf(stderr, "field [%i] \"%s\"\n", i, field_annotations[i]); } } { ju2 i; for (i = 0; i < pre_classfile_methods_count(classfile); i++) { if (method_annotations[i] != 0) fprintf(stderr, "method [%i] \"%s\"\n", i, method_annotations[i]); } }#endif /* Check constant annotations */ if (! check_constant_annotations(classfile)) { fprintf(stderr, "%s: invalid constant annotation(s)\n", argv[0]); exit(1); } /* Create cp entry for attribute name */ PREConstantPool *constant_pool = pre_classfile_constant_pool(classfile); ju2 attribute_name_index = pre_constant_pool_define_utf8(arena, constant_pool, attribute_name); if (attribute_name_index == 0) { fprintf(stderr, "%s: unable to create cp entry for attribute name: %s\n", argv[0], attribute_name); exit(1); } /* Create cp entry for class annotation */ ju2 class_annotation_index; if (class_annotation == 0) { class_annotation_index = 0; } else { class_annotation_index = pre_constant_pool_define_utf8(arena, constant_pool, class_annotation); if (class_annotation_index == 0) { fprintf(stderr, "%s: unable to create cp entry class annotation\n", argv[0]); exit(1); } } /* Create mapping from constant id to index of cp entry holding corresponding annotation */ ju2 constant_annotations_count = 0; ju2 i; struct id_index_map_t con_map[constants_count]; for (i = 0; i < constants_count; i++) { if (constant_annotations[i] != 0) { ju2 index = pre_constant_pool_define_utf8(arena, constant_pool, constant_annotations[i]); if (index == 0) { fprintf(stderr, "%s: unable to create cp entry for annotation " "of field %d: %s\n", argv[0], i, constant_annotations[i]); exit(1); } con_map[constant_annotations_count].id = i; con_map[constant_annotations_count].index = index; ++constant_annotations_count; } } /* Create mapping from field id to index of cp entry holding corresponding annotation */ ju2 field_annotations_count = 0; struct id_index_map_t fld_map[fields_count]; for (i = 0; i < fields_count; i++) { if (field_annotations[i] != 0) { ju2 index = pre_constant_pool_define_utf8(arena, constant_pool, field_annotations[i]); if (index == 0) { fprintf(stderr, "%s: unable to create cp entry for annotation " "of field %d: %s\n", argv[0], i, field_annotations[i]); exit(1); } fld_map[field_annotations_count].id = i; fld_map[field_annotations_count].index = index; ++field_annotations_count; } } /* Create mapping from method id to index of cp entry holding corresponding annotation */ ju2 method_annotations_count = 0; struct id_index_map_t mth_map[methods_count]; for (i = 0; i < methods_count; i++) { if (method_annotations[i] != 0) { ju2 index = pre_constant_pool_define_utf8(arena, constant_pool, method_annotations[i]); if (index == 0) { fprintf(stderr, "%s: unable to create cp entry for annotation " "of method %d: %s\n", argv[0], i, method_annotations[i]); exit(1); } mth_map[method_annotations_count].id = i; mth_map[method_annotations_count].index = index; ++method_annotations_count; } } /* Estimate attribute length */ ju4 attribute_length = sizeof(ju2) + /* class_annotation_index */ sizeof(ju2) + /* constant_annotations_count */ sizeof(ju2) + /* field_annotations_count */ sizeof(ju2) + /* method_annotations_count */ constant_annotations_count * (sizeof(ju2) + sizeof(ju2)) + field_annotations_count * (sizeof(ju2) + sizeof(ju2)) + method_annotations_count * (sizeof(ju2) + sizeof(ju2));#ifdef JAN_DEBUG fprintf(stderr, "attribute_name_index = %d \"%s\"\n", attribute_name_index, pre_constant_pool_utf8_bytes(constant_pool, attribute_name_index)); fprintf(stderr, "attribute_length = %d\n", attribute_length); if (class_annotation_index != 0) { fprintf(stderr, "class_annotation_index = %d \"%s\"\n", class_annotation_index, pre_constant_pool_utf8_bytes(constant_pool, class_annotation_index)); } else { fprintf(stderr, "class_annotation_index = 0\n"); } fprintf(stderr, "Constant Mapping (x%d):\n", constant_annotations_count); for (i = 0; i < constant_annotations_count; i++) fprintf(stderr, "<%d, %d \"%s\">\n", con_map[i].id, con_map[i].index, pre_constant_pool_utf8_bytes(constant_pool, con_map[i].index)); fprintf(stderr, "Field Mapping (x%d):\n", field_annotations_count); for (i = 0; i < field_annotations_count; i++) fprintf(stderr, "<%d, %d \"%s\">\n", fld_map[i].id, fld_map[i].index, pre_constant_pool_utf8_bytes(constant_pool, fld_map[i].index)); fprintf(stderr, "Method Mapping (x%d)\n", method_annotations_count); for (i = 0; i < method_annotations_count; i++) fprintf(stderr, "<%d, %d \"%s\">\n", mth_map[i].id, mth_map[i].index, pre_constant_pool_utf8_bytes(constant_pool, mth_map[i].index));#endif /* Create info for generic attribute */ ju1 *info = j_arena_alloc(arena, attribute_length); if (info == 0) { fprintf(stderr, "%s: unable to create info for attribute\n", argv[0]); exit(1); } ju1 *p = info; j_encode_u2(class_annotation_index, &p); j_encode_u2(constant_annotations_count, &p); j_encode_u2(field_annotations_count, &p); j_encode_u2(method_annotations_count, &p); for (i = 0; i < constant_annotations_count; i++) { j_encode_u2(con_map[i].id, &p); j_encode_u2(con_map[i].index, &p); } for (i = 0; i < field_annotations_count; i++) { j_encode_u2(fld_map[i].id, &p); j_encode_u2(fld_map[i].index, &p); } for (i = 0; i < method_annotations_count; i++) { j_encode_u2(mth_map[i].id, &p); j_encode_u2(mth_map[i].index, &p); }#ifdef JAN_DEBUG fprintf(stderr, "info = "); ju4 j; for (j = 0; j < attribute_length; j++) fprintf(stderr, "%02x ", info[j]); fprintf(stderr, "\n");#endif /* Append attribute */ void *attr = pre_make_attribute_generic(arena, attribute_name_index, attribute_length, info); if (attr == 0) { fprintf(stderr, "%s: unable to create attribute\n", argv[0]); exit(1); } pre_classfile_append_attribute(classfile, attr); /* Output modified classfile */ size_t length = pre_classfile_length(classfile); ju1 buf[length]; ju1 *q = buf; pre_gencode_classfile(&q, classfile); const char *r = buf; const char *s = buf + length; for (; r != s; ++r) putchar(*r); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -