@ -27,261 +27,183 @@
# include "upbc/code_generator_request.h"
# include <assert.h>
# include <inttypes.h>
# include <setjmp.h>
# include <stddef.h>
# include <stdint.h>
# include <stdio.h>
# include <stdlib.h>
# include "google/protobuf/compiler/plugin.upb.h"
# include "upb/def.h"
# include "upb/mini_descriptor.h"
# include "upb/mini_table.h"
// Must be last.
# include "upb/port_def.inc"
enum {
kErrArenaMalloc = 1 ,
kErrEnumName ,
kErrExtensionName ,
kErrFieldName ,
kErrFilePackage ,
kErrMapCollision ,
kErrMiniDescriptorsSet ,
kErrStateGrow ,
} ;
/* upbc_PathState *************************************************************/
// Manages the current fully qualified path name as we dig down into a proto.
// Basically just a string that grows and shrinks like a stack.
typedef struct {
size_t len ;
char path [ 4000 ] ; // TODO(salo): make this dynamic
} upbc_PathState ;
static void upbc_PathState_Init ( upbc_PathState * p ) { p - > len = 0 ; }
static void upbc_PathState_Push ( upbc_PathState * p , upb_StringView name ) {
if ( p - > len ) {
p - > path [ p - > len + + ] = ' . ' ;
}
memcpy ( & p - > path [ p - > len ] , name . data , name . size ) ;
p - > len + = name . size ;
}
static void upbc_PathState_Pop ( upbc_PathState * p , upb_StringView name ) {
p - > len - = name . size ;
if ( p - > len ) {
p - > len - - ;
}
}
static upb_StringView upbc_PathState_String ( const upbc_PathState * p ) {
return upb_StringView_FromDataAndSize ( p - > path , p - > len ) ;
}
/******************************************************************************/
// Kitchen sink storage for the mini descriptor state .
// Kitchen sink storage for all of our state as we build the mini descriptors.
typedef struct {
upb_Arena * a ;
upb_Syntax syntax ;
upb_Arena * arena ;
upb_Status * status ;
upb_DefPool * symtab ;
upbc_CodeGeneratorRequest * out ;
jmp_buf err ;
upbc_PathState path ;
} upbc_ScrapeState ;
jmp_buf jmp ;
} upbc_State ;
static void upbc_ScrapeState_Init ( upbc_ScrapeState * s , upb_Arena * a ) {
s - > a = a ;
upbc_PathState_Init ( & s - > path ) ;
s - > out = upbc_CodeGeneratorRequest_new ( a ) ;
if ( ! s - > out ) UPB_LONGJMP ( s - > err , kErrArenaMalloc ) ;
static void upbc_State_Fini ( upbc_State * s ) {
if ( s - > symtab ) upb_DefPool_Free ( s - > symtab ) ;
}
static void upbc_ScrapeState_Push ( upbc_ScrapeState * s , upb_StringView name ) {
upbc_PathState_Push ( & s - > path , name ) ;
const upb_StringView key = upbc_PathState_String ( & s - > path ) ;
if ( upbc_CodeGeneratorRequest_mini_descriptors_get ( s - > out , key , NULL ) ) {
UPB_LONGJMP ( s - > err , kErrMapCollision ) ;
}
static void upbc_Error ( upbc_State * s , const char * fn , const char * msg ) {
upb_Status_SetErrorFormat ( s - > status , " %s(): %s " , fn , msg ) ;
upbc_State_Fini ( s ) ;
UPB_LONGJMP ( s - > jmp , - 1 ) ;
}
static void upbc_ScrapeState_Pop ( upbc_ScrapeS tate * s , upb_StringView name ) {
upbc_PathState_Pop ( & s - > path , name ) ;
}
static void upbc_State_Init ( upbc_State * s ) {
s - > symtab = upb_DefPool_New ( ) ;
if ( ! s - > symtab ) upbc_Error ( s , __func__ , " could not allocate def pool " ) ;
static void upbc_ScrapeState_String ( upbc_ScrapeState * s ,
upb_StringView encoding ) {
const upb_StringView path = upbc_PathState_String ( & s - > path ) ;
bool ok = upbc_CodeGeneratorRequest_mini_descriptors_set ( s - > out , path ,
encoding , s - > a ) ;
if ( ! ok ) UPB_LONGJMP ( s - > err , kErrMiniDescriptorsSet ) ;
s - > out = upbc_CodeGeneratorRequest_new ( s - > arena ) ;
if ( ! s - > out ) upbc_Error ( s , __func__ , " could not allocate request " ) ;
}
/******************************************************************************/
// File accessors.
static upb_Syntax upbc_File_Syntax ( const google_protobuf_FileDescriptorProto * file ) {
if ( google_protobuf_FileDescriptorProto_has_syntax ( file ) ) {
const upb_StringView syntax = google_protobuf_FileDescriptorProto_syntax ( file ) ;
const upb_StringView proto3 = upb_StringView_FromString ( " proto3 " ) ;
if ( upb_StringView_IsEqual ( syntax , proto3 ) ) return kUpb_Syntax_Proto3 ;
}
return kUpb_Syntax_Proto2 ;
static void upbc_State_Emit ( upbc_State * s , const char * name ,
upb_StringView encoding ) {
const upb_StringView key = upb_StringView_FromString ( name ) ;
bool ok = upbc_CodeGeneratorRequest_mini_descriptors_set ( s - > out , key ,
encoding , s - > arena ) ;
if ( ! ok ) upbc_Error ( s , __func__ , " could not set mini descriptor in map " ) ;
}
/******************************************************************************/
// Forward declaration.
static void upbc_Scrape_Messages ( upbc_ScrapeState * ,
const google_protobuf_DescriptorProto * const * , size_t ) ;
static void upbc_Scrape_Enum ( upbc_ScrapeState * s ,
const google_protobuf_EnumDescriptorProto * enum_type ) {
if ( ! google_protobuf_EnumDescriptorProto_has_name ( enum_type ) ) {
UPB_LONGJMP ( s - > err , kErrEnumName ) ;
}
const upb_StringView name = google_protobuf_EnumDescriptorProto_name ( enum_type ) ;
upbc_ScrapeState_Push ( s , name ) ;
static void upbc_Scrape_Message ( upbc_State * , const upb_MessageDef * ) ;
static void upbc_Scrape_Enum ( upbc_State * s , const upb_EnumDef * enum_def ) {
const char * name = upb_EnumDef_FullName ( enum_def ) ;
const upb_StringView encoding =
upb_MiniDescriptor_EncodeEnum ( enum_type , s - > a ) ;
upb_MiniDescriptor_EncodeEnum ( enum_def , s - > arena ) ;
upbc_State_Emit ( s , name , encoding ) ;
}
upbc_ScrapeState_String ( s , encoding ) ;
upbc_ScrapeState_Pop ( s , name ) ;
static void upbc_Scrape_Extension ( upbc_State * s ,
const upb_FieldDef * field_def ) {
const char * name = upb_FieldDef_FullName ( field_def ) ;
const upb_StringView encoding =
upb_MiniDescriptor_EncodeExtension ( field_def , s - > arena ) ;
upbc_State_Emit ( s , name , encoding ) ;
}
static void upbc_Scrape_Enums (
upbc_ScrapeState * s , const google_protobuf_EnumDescriptorProto * const * enum_types ,
size_t len ) {
static void upbc_Scrape_FileEnums ( upbc_State * s , const upb_FileDef * file_def ) {
const size_t len = upb_FileDef_TopLevelEnumCount ( file_def ) ;
for ( size_t i = 0 ; i < len ; i + + ) {
upbc_Scrape_Enum ( s , enum_types [ i ] ) ;
const upb_EnumDef * enum_def = upb_FileDef_TopLevelEnum ( file_def , i ) ;
upbc_Scrape_Enum ( s , enum_def ) ;
}
}
static void upbc_Scrape_Extension (
upbc_ScrapeState * s , const google_protobuf_FieldDescriptorProto * extension_type ) {
if ( ! google_protobuf_FieldDescriptorProto_has_name ( extension_type ) ) {
UPB_LONGJMP ( s - > err , kErrExtensionName ) ;
static void upbc_Scrape_FileExtensions ( upbc_State * s ,
const upb_FileDef * file_def ) {
const size_t len = upb_FileDef_TopLevelExtensionCount ( file_def ) ;
for ( size_t i = 0 ; i < len ; i + + ) {
const upb_FieldDef * field_def = upb_FileDef_TopLevelExtension ( file_def , i ) ;
upbc_Scrape_Extension ( s , field_def ) ;
}
const upb_StringView name = google_protobuf_FieldDescriptorProto_name ( extension_type ) ;
upbc_ScrapeState_Push ( s , name ) ;
const upb_StringView encoding =
upb_MiniDescriptor_EncodeExtension ( extension_type , s - > syntax , s - > a ) ;
upbc_ScrapeState_String ( s , encoding ) ;
upbc_ScrapeState_Pop ( s , name ) ;
}
static void upbc_Scrape_Extensions (
const google_protobuf_FieldDescriptorProto * const * extension_types , size_t len ,
upbc_ScrapeState * s ) {
static void upbc_Scrape_FileMessages ( upbc_State * s ,
const upb_FileDef * file_def ) {
const size_t len = upb_FileDef_TopLevelMessageCount ( file_def ) ;
for ( size_t i = 0 ; i < len ; i + + ) {
upbc_Scrape_Extension ( s , extension_types [ i ] ) ;
const upb_MessageDef * message_def =
upb_FileDef_TopLevelMessage ( file_def , i ) ;
upbc_Scrape_Message ( s , message_def ) ;
}
}
static void upbc_Scrape_File ( upbc_ScrapeState * s ,
const google_protobuf_FileDescriptorProto * file_type ) {
if ( ! google_protobuf_FileDescriptorProto_has_package ( file_type ) ) {
UPB_LONGJMP ( s - > err , kErrFilePackage ) ;
}
const upb_StringView package = google_protobuf_FileDescriptorProto_package ( file_type ) ;
upbc_ScrapeState_Push ( s , package ) ;
static void upbc_Scrape_File ( upbc_State * s , const upb_FileDef * file_def ) {
upbc_Scrape_FileEnums ( s , file_def ) ;
upbc_Scrape_FileExtensions ( s , file_def ) ;
upbc_Scrape_FileMessages ( s , file_def ) ;
}
s - > syntax = upbc_File_Syntax ( file_type ) ;
static void upbc_Scrape_Files ( upbc_State * s ) {
const google_protobuf_compiler_CodeGeneratorRequest * request =
upbc_CodeGeneratorRequest_request ( s - > out ) ;
size_t len = 0 ;
const google_protobuf_EnumDescriptorProto * const * enum_types =
google_protobuf_FileDescriptorProto_enum_type ( file_type , & len ) ;
upbc_Scrape_Enums ( s , enum_types , len ) ;
const google_protobuf_FieldDescriptorProto * const * extension_types =
google_protobuf_FileDescriptorProto_extension ( file_type , & len ) ;
upbc_Scrape_Extensions ( extension_types , len , s ) ;
const google_protobuf_FileDescriptorProto * const * file_types =
google_protobuf_compiler_CodeGeneratorRequest_proto_file ( request , & len ) ;
const google_protobuf_DescriptorProto * const * message_types =
google_protobuf_FileDescriptorProto_message_type ( file_type , & len ) ;
upbc_Scrape_Messages ( s , message_types , len ) ;
for ( size_t i = 0 ; i < len ; i + + ) {
const upb_FileDef * file_def =
upb_DefPool_AddFile ( s - > symtab , file_types [ i ] , s - > status ) ;
if ( ! file_def ) upbc_Error ( s , __func__ , " could not add file to def pool " ) ;
upbc_ScrapeState_Pop ( s , package ) ;
upbc_Scrape_File ( s , file_def ) ;
}
}
static void upbc_Scrape_Files (
upbc_ScrapeState * s , const google_protobuf_FileDescriptorProto * const * file_types ,
size_t len ) {
static void upbc_Scrape_NestedEnums ( upbc_State * s ,
const upb_MessageDef * message_def ) {
const size_t len = upb_MessageDef_NestedEnumCount ( message_def ) ;
for ( size_t i = 0 ; i < len ; i + + ) {
upbc_Scrape_File ( s , file_types [ i ] ) ;
const upb_EnumDef * enum_def = upb_MessageDef_NestedEnum ( message_def , i ) ;
upbc_Scrape_Enum ( s , enum_def ) ;
}
}
static void upbc_Scrape_Message ( upbc_ScrapeState * s ,
const google_protobuf_DescriptorProto * message_type ) {
if ( ! google_protobuf_DescriptorProto_has_name ( message_type ) ) return ;
const upb_StringView name = google_protobuf_DescriptorProto_name ( message_type ) ;
upbc_ScrapeState_Push ( s , name ) ;
const upb_StringView encoding =
upb_MiniDescriptor_EncodeMessage ( message_type , s - > syntax , s - > a ) ;
upbc_ScrapeState_String ( s , encoding ) ;
size_t len = 0 ;
const google_protobuf_EnumDescriptorProto * const * enum_types =
google_protobuf_DescriptorProto_enum_type ( message_type , & len ) ;
upbc_Scrape_Enums ( s , enum_types , len ) ;
const google_protobuf_FieldDescriptorProto * const * extension_types =
google_protobuf_DescriptorProto_extension ( message_type , & len ) ;
upbc_Scrape_Extensions ( extension_types , len , s ) ;
const google_protobuf_DescriptorProto * const * nested_types =
google_protobuf_DescriptorProto_nested_type ( message_type , & len ) ;
upbc_Scrape_Messages ( s , nested_types , len ) ;
upbc_ScrapeState_Pop ( s , name ) ;
static void upbc_Scrape_NestedExtensions ( upbc_State * s ,
const upb_MessageDef * message_def ) {
const size_t len = upb_MessageDef_NestedExtensionCount ( message_def ) ;
for ( size_t i = 0 ; i < len ; i + + ) {
const upb_FieldDef * field_def =
upb_MessageDef_NestedExtension ( message_def , i ) ;
upbc_Scrape_Extension ( s , field_def ) ;
}
}
static void upbc_Scrape_Messages (
upbc_ScrapeState * s , const google_protobuf_DescriptorProto * const * message_types ,
size_t len ) {
static void upbc_Scrape_NestedMessages ( upbc_State * s ,
const upb_MessageDef * message_def ) {
const size_t len = upb_MessageDef_NestedMessageCount ( message_def ) ;
for ( size_t i = 0 ; i < len ; i + + ) {
upbc_Scrape_Message ( s , message_types [ i ] ) ;
const upb_MessageDef * nested_def =
upb_MessageDef_NestedMessage ( message_def , i ) ;
upbc_Scrape_Message ( s , nested_def ) ;
}
}
static void upbc_Scrape_Message ( upbc_State * s ,
const upb_MessageDef * message_def ) {
const char * name = upb_MessageDef_FullName ( message_def ) ;
const upb_StringView encoding =
upb_MiniDescriptor_EncodeMessage ( message_def , s - > arena ) ;
upbc_State_Emit ( s , name , encoding ) ;
upbc_Scrape_NestedEnums ( s , message_def ) ;
upbc_Scrape_NestedExtensions ( s , message_def ) ;
upbc_Scrape_NestedMessages ( s , message_def ) ;
}
upbc_CodeGeneratorRequest * upbc_MakeCodeGeneratorRequest (
google_protobuf_compiler_CodeGeneratorRequest * request , upb_Arena * a ,
google_protobuf_compiler_CodeGeneratorRequest * request , upb_Arena * arena ,
upb_Status * status ) {
upbc_ScrapeState s ;
int err = UPB_SETJMP ( s . err ) ;
if ( err ) {
upb_Status_SetErrorFormat ( status , " %s(): error %d " , __func__ , err ) ;
return NULL ;
}
upbc_ScrapeState_Init ( & s , a ) ;
upbc_State s = {
. arena = arena ,
. status = status ,
. symtab = NULL ,
. out = NULL ,
} ;
size_t len = 0 ;
const google_protobuf_FileDescriptorProto * const * file_types =
google_protobuf_compiler_CodeGeneratorRequest_proto_file ( request , & len ) ;
upbc_Scrape_Files ( & s , file_types , len ) ;
if ( UPB_SETJMP ( s . jmp ) ) return NULL ;
upbc_State_Init ( & s ) ;
upbc_CodeGeneratorRequest_set_request ( s . out , request ) ;
upbc_Scrape_Files ( & s ) ;
upbc_State_Fini ( & s ) ;
return s . out ;
}