xref: /Universal-ctags/parsers/protobuf.c (revision 2de665ec38716d7e07ec13332b377344974241de)
16ea83ed2SMasatake YAMATO /*
26ea83ed2SMasatake YAMATO  *
36ea83ed2SMasatake YAMATO  *   Copyright (c) 2011, Ivan Krasilnikov
46ea83ed2SMasatake YAMATO  *
56ea83ed2SMasatake YAMATO  *   This source code is released for free distribution under the terms of the
66ea83ed2SMasatake YAMATO  *   GNU General Public License version 2 or (at your option) any later version.
76ea83ed2SMasatake YAMATO  *
86ea83ed2SMasatake YAMATO  *   This module implements parsing of protocol buffers definition files
96ea83ed2SMasatake YAMATO  *   (http://code.google.com/apis/protocolbuffers/docs/proto.html)
106ea83ed2SMasatake YAMATO  */
116ea83ed2SMasatake YAMATO 
126ea83ed2SMasatake YAMATO /*
136ea83ed2SMasatake YAMATO   Masatake YAMATO takes this from https://sourceforge.net/p/ctags/patches/74/
146ea83ed2SMasatake YAMATO   after getting following approval:
156ea83ed2SMasatake YAMATO   ===============================================================================
166ea83ed2SMasatake YAMATO   Message-ID: <CALPttHe+hSa_kjwx6GoWS6CsDf_OG0bcmhmPahb4shnKb8tkWg@mail.gmail.com>
176ea83ed2SMasatake YAMATO   Subject: Re: your protobuf.patch
186ea83ed2SMasatake YAMATO   From: Ivan Krasilnikov <infnty@gmail.com>
196ea83ed2SMasatake YAMATO   To: m_yamato@users.sf.net
206ea83ed2SMasatake YAMATO   Date: Fri, 8 Jul 2016 15:37:07 +0200
216ea83ed2SMasatake YAMATO 
226ea83ed2SMasatake YAMATO   Hi, yes, it's fine, no problem.
236ea83ed2SMasatake YAMATO 
246ea83ed2SMasatake YAMATO   --
256ea83ed2SMasatake YAMATO   Ivan
266ea83ed2SMasatake YAMATO 
276ea83ed2SMasatake YAMATO   On 8 July 2016 at 06:31, <m_yamato@users.sf.net> wrote:
286ea83ed2SMasatake YAMATO 
296ea83ed2SMasatake YAMATO   > Hi,
306ea83ed2SMasatake YAMATO   >
316ea83ed2SMasatake YAMATO   > I am a developer of universal ctags(http://ctags.io).
326ea83ed2SMasatake YAMATO   >
336ea83ed2SMasatake YAMATO   > I would like to merge your patch for protobuf in *GPL v2 or later*.
346ea83ed2SMasatake YAMATO   >
356ea83ed2SMasatake YAMATO   > Is it o.k.?
366ea83ed2SMasatake YAMATO   > ------------------------------
376ea83ed2SMasatake YAMATO   >
386ea83ed2SMasatake YAMATO   > This message was sent to you via the SourceForge web mail form.
396ea83ed2SMasatake YAMATO   > You may reply to this message directly, or at
406ea83ed2SMasatake YAMATO   > https://sourceforge.net/u/userid-2121776/profile/send_message
416ea83ed2SMasatake YAMATO   >
426ea83ed2SMasatake YAMATO   ===============================================================================
436ea83ed2SMasatake YAMATO */
446ea83ed2SMasatake YAMATO 
456ea83ed2SMasatake YAMATO /*
466ea83ed2SMasatake YAMATO  *   INCLUDE FILES
476ea83ed2SMasatake YAMATO  */
486ea83ed2SMasatake YAMATO #include "general.h"  /* must always come first */
496ea83ed2SMasatake YAMATO 
506ea83ed2SMasatake YAMATO #include <string.h>
516ea83ed2SMasatake YAMATO #include <ctype.h>
526ea83ed2SMasatake YAMATO 
5387214e15SMasatake YAMATO #include "cpreprocessor.h"
546ea83ed2SMasatake YAMATO 
556ea83ed2SMasatake YAMATO #include "entry.h"
566ea83ed2SMasatake YAMATO #include "keyword.h"
576ea83ed2SMasatake YAMATO #include "parse.h"
5859b6f293SMasatake YAMATO #include "read.h"
596ea83ed2SMasatake YAMATO #include "vstring.h"
606ea83ed2SMasatake YAMATO 
616ea83ed2SMasatake YAMATO /*
626ea83ed2SMasatake YAMATO  *   DATA DEFINITIONS
636ea83ed2SMasatake YAMATO  */
646ea83ed2SMasatake YAMATO static langType Lang_protobuf;
656ea83ed2SMasatake YAMATO 
666ea83ed2SMasatake YAMATO typedef enum {
67e09c310eSMasatake YAMATO 	SYNTAX_UNKNOWN,
68e09c310eSMasatake YAMATO 	SYNTAX_PROTO2,
69e09c310eSMasatake YAMATO 	SYNTAX_PROTO3,
70e09c310eSMasatake YAMATO } protobufSyntax;
71*2de665ecSMasatake YAMATO static protobufSyntax syntax = SYNTAX_UNKNOWN;
72e09c310eSMasatake YAMATO 
73e09c310eSMasatake YAMATO typedef enum {
746ea83ed2SMasatake YAMATO 	PK_PACKAGE,
756ea83ed2SMasatake YAMATO 	PK_MESSAGE,
766ea83ed2SMasatake YAMATO 	PK_FIELD,
776ea83ed2SMasatake YAMATO 	PK_ENUMERATOR,
786ea83ed2SMasatake YAMATO 	PK_ENUM,
796ea83ed2SMasatake YAMATO 	PK_SERVICE,
80ac4a85f0SMasatake YAMATO 	PK_RPC,
81ac4a85f0SMasatake YAMATO 	PK_ONEOF,
82602d6ba1SMasatake YAMATO 	PK_GROUP,
831fa2993eSMasatake YAMATO 	PK_PROTODEF,
846ea83ed2SMasatake YAMATO } protobufKind;
856ea83ed2SMasatake YAMATO 
86b2e1d739SMasatake YAMATO typedef enum {
87b2e1d739SMasatake YAMATO 	R_MESSAGE_EXTENSION,
88b2e1d739SMasatake YAMATO } protobufMessageRole;
89b2e1d739SMasatake YAMATO 
901fa2993eSMasatake YAMATO typedef enum {
911fa2993eSMasatake YAMATO 	R_PROTODEF_IMPORTED,
921fa2993eSMasatake YAMATO } protobufProtodefRole;
931fa2993eSMasatake YAMATO 
94b2e1d739SMasatake YAMATO static roleDefinition ProtobufMessageRoles [] = {
95b2e1d739SMasatake YAMATO 	{ true, "extension", "extending the message" },
96b2e1d739SMasatake YAMATO };
97b2e1d739SMasatake YAMATO 
981fa2993eSMasatake YAMATO static roleDefinition ProtobufProtodefRoles [] = {
991fa2993eSMasatake YAMATO 	{ true, "imported", "imported" },
1001fa2993eSMasatake YAMATO };
1011fa2993eSMasatake YAMATO 
102e112e8abSMasatake YAMATO static kindDefinition ProtobufKinds [] = {
103ce990805SThomas Braun 	{ true,  'p', "package",    "packages" },
104b2e1d739SMasatake YAMATO 	{ true,  'm', "message",    "messages",
105b2e1d739SMasatake YAMATO 	  .referenceOnly = false, ATTACH_ROLES (ProtobufMessageRoles)},
106ce990805SThomas Braun 	{ true,  'f', "field",      "fields" },
107ce990805SThomas Braun 	{ true,  'e', "enumerator", "enum constants" },
108ce990805SThomas Braun 	{ true,  'g', "enum",       "enum types" },
109ce990805SThomas Braun 	{ true,  's', "service",    "services" },
110f64240f4SMasatake YAMATO 	{ true,  'r', "rpc",        "RPC methods" },
111ac4a85f0SMasatake YAMATO 	{ true,  'o', "oneof",      "oneof names" },
112602d6ba1SMasatake YAMATO 	{ true,  'G', "group",      "groups" },
1131fa2993eSMasatake YAMATO 	{ true,  'D', "protodef",   ".proto definition",
1141fa2993eSMasatake YAMATO 	  .referenceOnly = true, ATTACH_ROLES (ProtobufProtodefRoles)},
1156ea83ed2SMasatake YAMATO };
1166ea83ed2SMasatake YAMATO 
1176ea83ed2SMasatake YAMATO typedef enum eKeywordId {
1186ea83ed2SMasatake YAMATO 	KEYWORD_OPTION,
1196ea83ed2SMasatake YAMATO 	KEYWORD_PACKAGE,
1206ea83ed2SMasatake YAMATO 	KEYWORD_MESSAGE,
1216ea83ed2SMasatake YAMATO 	KEYWORD_ENUM,
1226ea83ed2SMasatake YAMATO 	KEYWORD_REPEATED,
1236ea83ed2SMasatake YAMATO 	KEYWORD_OPTIONAL,
1246ea83ed2SMasatake YAMATO 	KEYWORD_REQUIRED,
1256ea83ed2SMasatake YAMATO 	KEYWORD_SERVICE,
1266ea83ed2SMasatake YAMATO 	KEYWORD_RPC,
127ccb2363fSMasatake YAMATO 	KEYWORD_STREAM,
128ccb2363fSMasatake YAMATO 	KEYWORD_RETURNS,
129b2e1d739SMasatake YAMATO 	KEYWORD_EXTEND,
130ac4a85f0SMasatake YAMATO 	KEYWORD_ONEOF,
1312fab7ad8SMasatake YAMATO 	KEYWORD_MAP,
132602d6ba1SMasatake YAMATO 	KEYWORD_GROUP,
1331fa2993eSMasatake YAMATO 	KEYWORD_IMPORT,
1341fa2993eSMasatake YAMATO 	KEYWORD_PUBLIC,
1351fa2993eSMasatake YAMATO 	KEYWORD_WEAK,
136e09c310eSMasatake YAMATO 	KEYWORD_SYNTAX,
1376ea83ed2SMasatake YAMATO } keywordId;
1386ea83ed2SMasatake YAMATO 
1396ea83ed2SMasatake YAMATO static const keywordTable ProtobufKeywordTable [] = {
1406ea83ed2SMasatake YAMATO 	{ "option",   KEYWORD_OPTION   },
1416ea83ed2SMasatake YAMATO 	{ "package",  KEYWORD_PACKAGE  },
1426ea83ed2SMasatake YAMATO 	{ "message",  KEYWORD_MESSAGE  },
1436ea83ed2SMasatake YAMATO 	{ "enum",     KEYWORD_ENUM     },
1446ea83ed2SMasatake YAMATO 	{ "repeated", KEYWORD_REPEATED },
1456ea83ed2SMasatake YAMATO 	{ "optional", KEYWORD_OPTIONAL },
1466ea83ed2SMasatake YAMATO 	{ "required", KEYWORD_REQUIRED },
1476ea83ed2SMasatake YAMATO 	{ "service",  KEYWORD_SERVICE  },
1486ea83ed2SMasatake YAMATO 	{ "rpc",      KEYWORD_RPC      },
149ccb2363fSMasatake YAMATO 	{ "stream",   KEYWORD_STREAM   },
150ccb2363fSMasatake YAMATO 	{ "returns",  KEYWORD_RETURNS  },
151b2e1d739SMasatake YAMATO 	{ "extend",   KEYWORD_EXTEND   },
152ac4a85f0SMasatake YAMATO 	{ "oneof",    KEYWORD_ONEOF    },
1532fab7ad8SMasatake YAMATO 	{ "map",      KEYWORD_MAP      },
154602d6ba1SMasatake YAMATO 	{ "group",    KEYWORD_GROUP    },
1551fa2993eSMasatake YAMATO 	{ "import",   KEYWORD_IMPORT   },
1561fa2993eSMasatake YAMATO 	{ "public",   KEYWORD_PUBLIC   },
1571fa2993eSMasatake YAMATO 	{ "weak",     KEYWORD_WEAK     },
158e09c310eSMasatake YAMATO 	{ "syntax",   KEYWORD_SYNTAX   },
1596ea83ed2SMasatake YAMATO };
1606ea83ed2SMasatake YAMATO 
1616ea83ed2SMasatake YAMATO #define TOKEN_EOF   0
1626ea83ed2SMasatake YAMATO #define TOKEN_ID    'i'
1631fa2993eSMasatake YAMATO #define TOKEN_STR   's'
1646ea83ed2SMasatake YAMATO 
1656ea83ed2SMasatake YAMATO static struct sTokenInfo {
1666ea83ed2SMasatake YAMATO 	int type;         /* one of TOKEN_* constants or punctuation characters */
1676ea83ed2SMasatake YAMATO 	keywordId keyword;
1686ea83ed2SMasatake YAMATO 	vString *value;
1696ea83ed2SMasatake YAMATO } token;
1706ea83ed2SMasatake YAMATO 
171602d6ba1SMasatake YAMATO 
172602d6ba1SMasatake YAMATO /*
173602d6ba1SMasatake YAMATO  *   FUNCTION DECLARATIONS
174602d6ba1SMasatake YAMATO  */
175602d6ba1SMasatake YAMATO static void findProtobufTags0 (bool oneshot, int originalScopeCorkIndex);
176602d6ba1SMasatake YAMATO 
177602d6ba1SMasatake YAMATO 
1786ea83ed2SMasatake YAMATO /*
1796ea83ed2SMasatake YAMATO  *   FUNCTION DEFINITIONS
1806ea83ed2SMasatake YAMATO  */
1816ea83ed2SMasatake YAMATO 
nextTokenFull(bool expectingStringLiteral)1821fa2993eSMasatake YAMATO static void nextTokenFull (bool expectingStringLiteral)
1836ea83ed2SMasatake YAMATO {
1846ea83ed2SMasatake YAMATO 	int c;
1856ea83ed2SMasatake YAMATO 
1866ea83ed2SMasatake YAMATO repeat:
1876ea83ed2SMasatake YAMATO 	/*
1886ea83ed2SMasatake YAMATO 	 * .proto files may contain C and C++ style comments and
1896ea83ed2SMasatake YAMATO 	 * quoted strings. cppGetc() takes care of them.
1906ea83ed2SMasatake YAMATO 	 */
1916ea83ed2SMasatake YAMATO 	c = cppGetc ();
1926ea83ed2SMasatake YAMATO 
1936ea83ed2SMasatake YAMATO 	token.keyword = KEYWORD_NONE;
1946ea83ed2SMasatake YAMATO 	if (c <= 0)
1956ea83ed2SMasatake YAMATO 		token.type = TOKEN_EOF;
1962fab7ad8SMasatake YAMATO 	else if (c == '{' || c == '}' || c == ';' || c == '.' || c == '=' || c == ',' || c == '<' || c == '>')
1976ea83ed2SMasatake YAMATO 		token.type = c;
1984851a58bSMasatake YAMATO 	else if (cppIsalnum (c) || c == '_')
1996ea83ed2SMasatake YAMATO 	{
2006ea83ed2SMasatake YAMATO 		token.type = TOKEN_ID;
2016ea83ed2SMasatake YAMATO 		vStringClear (token.value);
2024851a58bSMasatake YAMATO 		while (c > 0 && (cppIsalnum (c) || c == '_')) {
2036ea83ed2SMasatake YAMATO 			vStringPut (token.value, c);
2046ea83ed2SMasatake YAMATO 			c = cppGetc ();
2056ea83ed2SMasatake YAMATO 		}
20631a85388SJiří Techet 		token.keyword = lookupCaseKeyword (vStringValue (token.value), Lang_protobuf);
2076ea83ed2SMasatake YAMATO 		cppUngetc (c);
2086ea83ed2SMasatake YAMATO 	}
2091fa2993eSMasatake YAMATO 	else if (expectingStringLiteral && c == STRING_SYMBOL)
2101fa2993eSMasatake YAMATO 	{
2111fa2993eSMasatake YAMATO 		token.type = TOKEN_STR;
2121fa2993eSMasatake YAMATO 		vStringCopy (token.value,
2131fa2993eSMasatake YAMATO 					 cppGetLastCharOrStringContents ());
2141fa2993eSMasatake YAMATO 	}
2156ea83ed2SMasatake YAMATO 	else
2166ea83ed2SMasatake YAMATO 		goto repeat;  /* anything else is not important for this parser */
2176ea83ed2SMasatake YAMATO }
2186ea83ed2SMasatake YAMATO 
nextToken(void)2191fa2993eSMasatake YAMATO static void nextToken (void)
2201fa2993eSMasatake YAMATO {
2211fa2993eSMasatake YAMATO 	nextTokenFull (false);
2221fa2993eSMasatake YAMATO }
2231fa2993eSMasatake YAMATO 
skipUntil(const char * punctuation)2246ea83ed2SMasatake YAMATO static void skipUntil (const char *punctuation)
2256ea83ed2SMasatake YAMATO {
2266ea83ed2SMasatake YAMATO 	while (token.type != TOKEN_EOF && strchr (punctuation, token.type) == NULL)
2276ea83ed2SMasatake YAMATO 		nextToken ();
2286ea83ed2SMasatake YAMATO }
2296ea83ed2SMasatake YAMATO 
parseFullQualifiedId(vString * buf)23092491b0bSMasatake YAMATO static void parseFullQualifiedId (vString *buf)
23192491b0bSMasatake YAMATO {
23292491b0bSMasatake YAMATO 	while (true)
23392491b0bSMasatake YAMATO 	{
23492491b0bSMasatake YAMATO 		nextToken ();
23592491b0bSMasatake YAMATO 
23692491b0bSMasatake YAMATO 		if (token.type == TOKEN_ID)
23792491b0bSMasatake YAMATO 		{
23892491b0bSMasatake YAMATO 			if (vStringIsEmpty (buf) || vStringLast (buf) == '.')
23992491b0bSMasatake YAMATO 				vStringCat (buf, token.value);
24092491b0bSMasatake YAMATO 			else
24192491b0bSMasatake YAMATO 				break;
24292491b0bSMasatake YAMATO 		}
24392491b0bSMasatake YAMATO 		else if (token.type == '.')
24492491b0bSMasatake YAMATO 		{
24592491b0bSMasatake YAMATO 			if (vStringIsEmpty (buf) || vStringLast (buf) != '.')
24692491b0bSMasatake YAMATO 				vStringPut (buf, '.');
24792491b0bSMasatake YAMATO 			else
24892491b0bSMasatake YAMATO 				break;
24992491b0bSMasatake YAMATO 		}
25092491b0bSMasatake YAMATO 		else
25192491b0bSMasatake YAMATO 			break;
25292491b0bSMasatake YAMATO 	}
25392491b0bSMasatake YAMATO }
25492491b0bSMasatake YAMATO 
tokenIsKeyword(keywordId keyword)2556ea83ed2SMasatake YAMATO static int tokenIsKeyword(keywordId keyword)
2566ea83ed2SMasatake YAMATO {
2576ea83ed2SMasatake YAMATO 	return token.type == TOKEN_ID && token.keyword == keyword;
2586ea83ed2SMasatake YAMATO }
2596ea83ed2SMasatake YAMATO 
createProtobufTagFull(const vString * name,int kind,int role,int scopeCorkIndex)26070e24df0SMasatake YAMATO static int createProtobufTagFull (const vString *name, int kind, int role, int scopeCorkIndex)
2616ea83ed2SMasatake YAMATO {
2626ea83ed2SMasatake YAMATO 	static tagEntryInfo tag;
263ccb2363fSMasatake YAMATO 	int corkIndex = CORK_NIL;
2646ea83ed2SMasatake YAMATO 
2656ea83ed2SMasatake YAMATO 	if (ProtobufKinds [kind].enabled)
2666ea83ed2SMasatake YAMATO 	{
26770e24df0SMasatake YAMATO 		initRefTagEntry (&tag, vStringValue (name), kind, role);
26870e24df0SMasatake YAMATO 		tag.extensionFields.scopeIndex = scopeCorkIndex;
269ccb2363fSMasatake YAMATO 		corkIndex = makeTagEntry (&tag);
2706ea83ed2SMasatake YAMATO 	}
271ccb2363fSMasatake YAMATO 
272ccb2363fSMasatake YAMATO 	return corkIndex;
2736ea83ed2SMasatake YAMATO }
2746ea83ed2SMasatake YAMATO 
createProtobufTag(const vString * name,int kind,int scopeCorkIndex)27570e24df0SMasatake YAMATO static int createProtobufTag (const vString *name, int kind, int scopeCorkIndex)
27670e24df0SMasatake YAMATO {
27770e24df0SMasatake YAMATO 	return createProtobufTagFull (name, kind, ROLE_DEFINITION_INDEX, scopeCorkIndex);
27870e24df0SMasatake YAMATO }
27970e24df0SMasatake YAMATO 
parseEnumConstants(int scopeCorkIndex)28070e24df0SMasatake YAMATO static void parseEnumConstants (int scopeCorkIndex)
2816ea83ed2SMasatake YAMATO {
2826ea83ed2SMasatake YAMATO 	if (token.type != '{')
2836ea83ed2SMasatake YAMATO 		return;
2846ea83ed2SMasatake YAMATO 	nextToken ();
2856ea83ed2SMasatake YAMATO 
2866ea83ed2SMasatake YAMATO 	while (token.type != TOKEN_EOF && token.type != '}')
2876ea83ed2SMasatake YAMATO 	{
2886ea83ed2SMasatake YAMATO 		if (token.type == TOKEN_ID && !tokenIsKeyword (KEYWORD_OPTION))
2896ea83ed2SMasatake YAMATO 		{
2906ea83ed2SMasatake YAMATO 			nextToken ();  /* doesn't clear token.value if it's punctuation */
2916ea83ed2SMasatake YAMATO 			if (token.type == '=')
29270e24df0SMasatake YAMATO 				createProtobufTag (token.value, PK_ENUMERATOR, scopeCorkIndex);
2936ea83ed2SMasatake YAMATO 		}
2946ea83ed2SMasatake YAMATO 
2956ea83ed2SMasatake YAMATO 		skipUntil (";}");
2966ea83ed2SMasatake YAMATO 
2976ea83ed2SMasatake YAMATO 		if (token.type == ';')
2986ea83ed2SMasatake YAMATO 			nextToken ();
2996ea83ed2SMasatake YAMATO 	}
30059b6f293SMasatake YAMATO 	tagEntryInfo *e = getEntryInCorkQueue (scopeCorkIndex);
3013671ad72SMasatake YAMATO 	if (e)
30259b6f293SMasatake YAMATO 		e->extensionFields.endLine = getInputLineNumber ();
3036ea83ed2SMasatake YAMATO }
3046ea83ed2SMasatake YAMATO 
parseOneofField(int scopeCorkIndex)305ac4a85f0SMasatake YAMATO static void parseOneofField (int scopeCorkIndex)
306ac4a85f0SMasatake YAMATO {
307602d6ba1SMasatake YAMATO 	if (tokenIsKeyword (KEYWORD_GROUP))
308602d6ba1SMasatake YAMATO 	{
309602d6ba1SMasatake YAMATO 		findProtobufTags0 (true, scopeCorkIndex);
310602d6ba1SMasatake YAMATO 		return;
311602d6ba1SMasatake YAMATO 	}
312602d6ba1SMasatake YAMATO 
313ac4a85f0SMasatake YAMATO 	vString *type = vStringNewCopy (token.value);
314ac4a85f0SMasatake YAMATO 	parseFullQualifiedId (type);
315ac4a85f0SMasatake YAMATO 
316ac4a85f0SMasatake YAMATO 	if (token.type == TOKEN_ID)
317ac4a85f0SMasatake YAMATO 	{
318ac4a85f0SMasatake YAMATO 		int corkIndex = createProtobufTag (token.value, PK_FIELD, scopeCorkIndex);
319ac4a85f0SMasatake YAMATO 		tagEntryInfo *e = getEntryInCorkQueue (corkIndex);
320ac4a85f0SMasatake YAMATO 		if (e)
321ac4a85f0SMasatake YAMATO 		{
322ac4a85f0SMasatake YAMATO 			e->extensionFields.typeRef [0] = eStrdup ("typename"); /* As C++ parser does */
323ac4a85f0SMasatake YAMATO 			e->extensionFields.typeRef [1] = vStringDeleteUnwrap (type);
324ac4a85f0SMasatake YAMATO 			type = NULL;
325ac4a85f0SMasatake YAMATO 		}
326ac4a85f0SMasatake YAMATO 	}
327ac4a85f0SMasatake YAMATO 
328ac4a85f0SMasatake YAMATO 	skipUntil (";}");
329ac4a85f0SMasatake YAMATO 	vStringDelete (type);		/* NULL is acceptable */
330ac4a85f0SMasatake YAMATO }
331ac4a85f0SMasatake YAMATO 
parseOneofFields(int scopeCorkIndex)332ac4a85f0SMasatake YAMATO static void parseOneofFields (int scopeCorkIndex)
333ac4a85f0SMasatake YAMATO {
334ac4a85f0SMasatake YAMATO 	if (token.type != '{')
335ac4a85f0SMasatake YAMATO 		return;
336ac4a85f0SMasatake YAMATO 	nextToken ();
337ac4a85f0SMasatake YAMATO 
338ac4a85f0SMasatake YAMATO 	while (token.type != TOKEN_EOF && token.type != '}')
339ac4a85f0SMasatake YAMATO 	{
340ac4a85f0SMasatake YAMATO 		if (token.type == TOKEN_ID || token.type == '.')
341ac4a85f0SMasatake YAMATO 		{
342ac4a85f0SMasatake YAMATO 			parseOneofField (scopeCorkIndex);
343ac4a85f0SMasatake YAMATO 			if (token.type == ';')
344ac4a85f0SMasatake YAMATO 				nextToken ();
345ac4a85f0SMasatake YAMATO 		}
346ac4a85f0SMasatake YAMATO 		else
347ac4a85f0SMasatake YAMATO 			break;
348ac4a85f0SMasatake YAMATO 	}
34959b6f293SMasatake YAMATO 
35059b6f293SMasatake YAMATO 	tagEntryInfo *e = getEntryInCorkQueue (scopeCorkIndex);
3513671ad72SMasatake YAMATO 	if (e)
35259b6f293SMasatake YAMATO 		e->extensionFields.endLine = getInputLineNumber ();
353ac4a85f0SMasatake YAMATO }
354ac4a85f0SMasatake YAMATO 
355ccb2363fSMasatake YAMATO #define gatherTypeinfo(VSTRING,CONDITION)			\
356ccb2363fSMasatake YAMATO 	while (CONDITION)								\
357ccb2363fSMasatake YAMATO 	{												\
358ccb2363fSMasatake YAMATO 		if (token.type == TOKEN_ID)					\
359ccb2363fSMasatake YAMATO 			vStringCat (VSTRING, token.value);		\
360ccb2363fSMasatake YAMATO 		else if (tokenIsKeyword (KEYWORD_STREAM))	\
361ccb2363fSMasatake YAMATO 		{											\
362ccb2363fSMasatake YAMATO 			vStringCat (VSTRING, token.value);		\
363ccb2363fSMasatake YAMATO 			vStringPut (VSTRING, ' ');				\
364ccb2363fSMasatake YAMATO 		}											\
365ccb2363fSMasatake YAMATO 		else										\
366ccb2363fSMasatake YAMATO 			vStringPut (VSTRING, token.type);		\
367ccb2363fSMasatake YAMATO 		nextToken ();								\
368ccb2363fSMasatake YAMATO 	}
369ccb2363fSMasatake YAMATO 
parseRPCTypeinfos(int corkIndex)370ccb2363fSMasatake YAMATO static void parseRPCTypeinfos (int corkIndex)
371ccb2363fSMasatake YAMATO {
372ccb2363fSMasatake YAMATO 	tagEntryInfo *e = getEntryInCorkQueue (corkIndex);
3733671ad72SMasatake YAMATO 	if (!e)
3743671ad72SMasatake YAMATO 		return;
375ccb2363fSMasatake YAMATO 
376ccb2363fSMasatake YAMATO 	vString *signature = vStringNew ();
377ccb2363fSMasatake YAMATO 	gatherTypeinfo(signature,
378ccb2363fSMasatake YAMATO 				   (token.type != TOKEN_EOF
379ccb2363fSMasatake YAMATO 					&& token.type != '{' && token.type != ';'
380ccb2363fSMasatake YAMATO 					&& !tokenIsKeyword (KEYWORD_RETURNS)));
381ccb2363fSMasatake YAMATO 	if (!vStringIsEmpty(signature))
382ccb2363fSMasatake YAMATO 		e->extensionFields.signature = vStringDeleteUnwrap (signature);
383ccb2363fSMasatake YAMATO 	else
384ccb2363fSMasatake YAMATO 		vStringDelete (signature);
385ccb2363fSMasatake YAMATO 
386ccb2363fSMasatake YAMATO 	if (!tokenIsKeyword (KEYWORD_RETURNS))
387ccb2363fSMasatake YAMATO 		return;
388ccb2363fSMasatake YAMATO 	nextToken ();
389ccb2363fSMasatake YAMATO 
390ccb2363fSMasatake YAMATO 	vString *typeref = vStringNew ();
391ccb2363fSMasatake YAMATO 	gatherTypeinfo(typeref, (token.type != EOF
392ccb2363fSMasatake YAMATO 							 && token.type != '{' && token.type != ';'));
393ccb2363fSMasatake YAMATO 	if (!vStringIsEmpty(typeref))
394ccb2363fSMasatake YAMATO 	{
395ccb2363fSMasatake YAMATO 		e->extensionFields.typeRef [0] = eStrdup ("typename"); /* As C++ parser does */
396ccb2363fSMasatake YAMATO 		e->extensionFields.typeRef [1] = vStringDeleteUnwrap (typeref);
397ccb2363fSMasatake YAMATO 	}
398ccb2363fSMasatake YAMATO 	else
399ccb2363fSMasatake YAMATO 		vStringDelete (typeref);
400ccb2363fSMasatake YAMATO }
401ccb2363fSMasatake YAMATO 
parseStatementFull(int kind,int role,int scopeCorkIndex)40270e24df0SMasatake YAMATO static int parseStatementFull (int kind, int role, int scopeCorkIndex)
4036ea83ed2SMasatake YAMATO {
4044549fa56SMasatake YAMATO 	int corkIndex = CORK_NIL;
405b2e1d739SMasatake YAMATO 	vString *fullName = NULL;
4064549fa56SMasatake YAMATO 	vString *fieldType = NULL;
4076ea83ed2SMasatake YAMATO 
4086ea83ed2SMasatake YAMATO 	if (kind == PK_FIELD)
4096ea83ed2SMasatake YAMATO 	{
4104549fa56SMasatake YAMATO 		fieldType = vStringNew ();
41113522841SMasatake YAMATO 
41213522841SMasatake YAMATO 		if (syntax == SYNTAX_PROTO3
41313522841SMasatake YAMATO 			&& !tokenIsKeyword (KEYWORD_REPEATED))
41413522841SMasatake YAMATO 		{
41513522841SMasatake YAMATO 			if (token.type == TOKEN_ID)
41613522841SMasatake YAMATO 				vStringCat (fieldType, token.value);
41713522841SMasatake YAMATO 			else if (token.type == '.')
41813522841SMasatake YAMATO 				vStringPut (fieldType, '.');
41913522841SMasatake YAMATO 		}
42013522841SMasatake YAMATO 
4214549fa56SMasatake YAMATO 		parseFullQualifiedId (fieldType);
4224549fa56SMasatake YAMATO 		if (vStringIsEmpty (fieldType) || vStringLast (fieldType) == '.')
4234549fa56SMasatake YAMATO 			goto out;
4246ea83ed2SMasatake YAMATO 	}
4254549fa56SMasatake YAMATO 	else
4264549fa56SMasatake YAMATO 		nextToken ();
4276ea83ed2SMasatake YAMATO 
428b2e1d739SMasatake YAMATO 	/* When extending message defined in the external package, the name
429b2e1d739SMasatake YAMATO 	 * becomes longer. */
430b2e1d739SMasatake YAMATO 	if (kind == PK_MESSAGE && role == R_MESSAGE_EXTENSION)
431b2e1d739SMasatake YAMATO 	{
4326ea83ed2SMasatake YAMATO 		if (token.type != TOKEN_ID)
4334549fa56SMasatake YAMATO 			goto out;
4346ea83ed2SMasatake YAMATO 
435b2e1d739SMasatake YAMATO 		fullName = vStringNewCopy (token.value);
43692491b0bSMasatake YAMATO 		parseFullQualifiedId (fullName);
437b2e1d739SMasatake YAMATO 	}
438b2e1d739SMasatake YAMATO 	else if (token.type != TOKEN_ID)
4394549fa56SMasatake YAMATO 		goto out;
440b2e1d739SMasatake YAMATO 
4414549fa56SMasatake YAMATO 	corkIndex = createProtobufTagFull (fullName? fullName: token.value,
442b2e1d739SMasatake YAMATO 									   kind, role, scopeCorkIndex);
443b2e1d739SMasatake YAMATO 
444b2e1d739SMasatake YAMATO 	if (!fullName)
445b2e1d739SMasatake YAMATO 		nextToken ();
4464549fa56SMasatake YAMATO 
4474549fa56SMasatake YAMATO 	tagEntryInfo *e = getEntryInCorkQueue (corkIndex);
4483671ad72SMasatake YAMATO 	if (fieldType && e)
4493671ad72SMasatake YAMATO 	{
4504549fa56SMasatake YAMATO 		e->extensionFields.typeRef [0] = eStrdup ("typename"); /* As C++ parser does */
4514549fa56SMasatake YAMATO 		e->extensionFields.typeRef [1] = vStringDeleteUnwrap (fieldType);
4524549fa56SMasatake YAMATO 		fieldType = NULL;
4534549fa56SMasatake YAMATO 	}
454b2e1d739SMasatake YAMATO 
455ccb2363fSMasatake YAMATO 	if (kind == PK_RPC && corkIndex != CORK_NIL)
456ccb2363fSMasatake YAMATO 		parseRPCTypeinfos (corkIndex);
457ccb2363fSMasatake YAMATO 
4586ea83ed2SMasatake YAMATO 	if (kind == PK_ENUM)
45970e24df0SMasatake YAMATO 		parseEnumConstants (corkIndex);
460ac4a85f0SMasatake YAMATO 	else if (kind == PK_ONEOF)
461ac4a85f0SMasatake YAMATO 		parseOneofFields (corkIndex);
46270e24df0SMasatake YAMATO 
4634549fa56SMasatake YAMATO  out:
4644549fa56SMasatake YAMATO 	vStringDelete (fieldType);	/* NULL is acceptable. */
4654549fa56SMasatake YAMATO 	vStringDelete (fullName);	/* NULL is acceptable. */
46670e24df0SMasatake YAMATO 	return corkIndex;
4676ea83ed2SMasatake YAMATO }
4686ea83ed2SMasatake YAMATO 
parseStatement(int kind,int scopeCorkIndex)46970e24df0SMasatake YAMATO static int parseStatement (int kind, int scopeCorkIndex)
470f203b714SMasatake YAMATO {
47170e24df0SMasatake YAMATO 	return parseStatementFull (kind, ROLE_DEFINITION_INDEX, scopeCorkIndex);
47270e24df0SMasatake YAMATO }
47370e24df0SMasatake YAMATO 
parsePackage(void)47470e24df0SMasatake YAMATO static int parsePackage (void)
47570e24df0SMasatake YAMATO {
47670e24df0SMasatake YAMATO 	int corkIndex = CORK_NIL;
47770e24df0SMasatake YAMATO 
478f203b714SMasatake YAMATO 	vString *pkg = vStringNew ();
47992491b0bSMasatake YAMATO 	parseFullQualifiedId (pkg);
480f203b714SMasatake YAMATO 	if (vStringLength (pkg) > 0)
48170e24df0SMasatake YAMATO 		corkIndex = createProtobufTag (pkg, PK_PACKAGE, CORK_NIL);
482f203b714SMasatake YAMATO 	vStringDelete (pkg);
48392491b0bSMasatake YAMATO 
48470e24df0SMasatake YAMATO 	return corkIndex;
485f203b714SMasatake YAMATO }
486f203b714SMasatake YAMATO 
parseMap(int scopeCorkIndex)4872fab7ad8SMasatake YAMATO static void parseMap (int scopeCorkIndex)
4882fab7ad8SMasatake YAMATO {
4892fab7ad8SMasatake YAMATO 	nextToken ();
4902fab7ad8SMasatake YAMATO 	if (token.type != '<')
4912fab7ad8SMasatake YAMATO 		return;
4922fab7ad8SMasatake YAMATO 
4932fab7ad8SMasatake YAMATO 	vString *typeref = vStringNewInit ("map<");
4942fab7ad8SMasatake YAMATO 
4952fab7ad8SMasatake YAMATO 	nextToken ();
4962fab7ad8SMasatake YAMATO 	if (token.type != TOKEN_ID)
4972fab7ad8SMasatake YAMATO 		goto out;
4982fab7ad8SMasatake YAMATO 
4992fab7ad8SMasatake YAMATO 	vStringCat (typeref, token.value);
5002fab7ad8SMasatake YAMATO 
5012fab7ad8SMasatake YAMATO 	nextToken ();
5022fab7ad8SMasatake YAMATO 	if (token.type != ',')
5032fab7ad8SMasatake YAMATO 		goto out;
5042fab7ad8SMasatake YAMATO 	vStringPut (typeref, ',');
5052fab7ad8SMasatake YAMATO 
5062fab7ad8SMasatake YAMATO 	vString *vtyperef = vStringNew ();
5072fab7ad8SMasatake YAMATO 	parseFullQualifiedId (vtyperef);
5082fab7ad8SMasatake YAMATO 	vStringCat (typeref, vtyperef);
5092fab7ad8SMasatake YAMATO 	vStringDelete (vtyperef);
5102fab7ad8SMasatake YAMATO 	if (vStringLast (typeref) == ',')
5112fab7ad8SMasatake YAMATO 		goto out;
5122fab7ad8SMasatake YAMATO 
5132fab7ad8SMasatake YAMATO 	if (token.type != '>')
5142fab7ad8SMasatake YAMATO 		goto out;
5152fab7ad8SMasatake YAMATO 	vStringPut (typeref, '>');
5162fab7ad8SMasatake YAMATO 
5172fab7ad8SMasatake YAMATO 	nextToken ();
5182fab7ad8SMasatake YAMATO 	if (token.type != TOKEN_ID)
5192fab7ad8SMasatake YAMATO 		goto out;
5202fab7ad8SMasatake YAMATO 
5212fab7ad8SMasatake YAMATO 	int corkIndex = createProtobufTag (token.value, PK_FIELD, scopeCorkIndex);
5222fab7ad8SMasatake YAMATO 	tagEntryInfo *e = getEntryInCorkQueue (corkIndex);
5232fab7ad8SMasatake YAMATO 	if (e)
5242fab7ad8SMasatake YAMATO 	{
5252fab7ad8SMasatake YAMATO 		e->extensionFields.typeRef [0] = eStrdup ("typename"); /* As C++ parser does */
5262fab7ad8SMasatake YAMATO 		e->extensionFields.typeRef [1] = vStringDeleteUnwrap (typeref);
5272fab7ad8SMasatake YAMATO 		typeref = NULL;
5282fab7ad8SMasatake YAMATO 	}
5292fab7ad8SMasatake YAMATO 
5302fab7ad8SMasatake YAMATO  out:
5312fab7ad8SMasatake YAMATO 	vStringDelete (typeref);
5322fab7ad8SMasatake YAMATO }
5332fab7ad8SMasatake YAMATO 
parseImport(int scopeCorkIndex)5341fa2993eSMasatake YAMATO static int parseImport (int scopeCorkIndex)
5351fa2993eSMasatake YAMATO {
5361fa2993eSMasatake YAMATO 	nextTokenFull (true);
5371fa2993eSMasatake YAMATO 	if (token.type == TOKEN_ID)
5381fa2993eSMasatake YAMATO 	{
5391fa2993eSMasatake YAMATO 		if (tokenIsKeyword (KEYWORD_PUBLIC)
5401fa2993eSMasatake YAMATO 			|| tokenIsKeyword (KEYWORD_WEAK))
5411fa2993eSMasatake YAMATO 			nextTokenFull (true);
5421fa2993eSMasatake YAMATO 		else
5431fa2993eSMasatake YAMATO 			return CORK_NIL;	/* Unexpected */
5441fa2993eSMasatake YAMATO 	}
5451fa2993eSMasatake YAMATO 
5461fa2993eSMasatake YAMATO 	if (token.type == TOKEN_STR)
5471fa2993eSMasatake YAMATO 		return createProtobufTagFull (token.value,
5481fa2993eSMasatake YAMATO 									  PK_PROTODEF, R_PROTODEF_IMPORTED,
5491fa2993eSMasatake YAMATO 									  /* TODO: whether the package scope should be specified or not. */
5501fa2993eSMasatake YAMATO 									  scopeCorkIndex
5511fa2993eSMasatake YAMATO 			);
5521fa2993eSMasatake YAMATO 
5531fa2993eSMasatake YAMATO 	return CORK_NIL;
5541fa2993eSMasatake YAMATO }
555602d6ba1SMasatake YAMATO 
parseSyntax(void)556e09c310eSMasatake YAMATO static void parseSyntax (void)
557e09c310eSMasatake YAMATO {
558e09c310eSMasatake YAMATO 	nextToken ();
559e09c310eSMasatake YAMATO 	if (token.type != '=')
560e09c310eSMasatake YAMATO 		return;
561e09c310eSMasatake YAMATO 
562e09c310eSMasatake YAMATO 	nextTokenFull (true);
563e09c310eSMasatake YAMATO 	if (token.type == TOKEN_STR)
564e09c310eSMasatake YAMATO 	{
565e09c310eSMasatake YAMATO 		const vString *proto = cppGetLastCharOrStringContents ();
566e09c310eSMasatake YAMATO 		if (strcmp (vStringValue (proto), "proto2") == 0)
567e09c310eSMasatake YAMATO 			syntax = SYNTAX_PROTO2;
568e09c310eSMasatake YAMATO 		else if (strcmp (vStringValue (proto), "proto3") == 0)
569e09c310eSMasatake YAMATO 			syntax = SYNTAX_PROTO3;
570e09c310eSMasatake YAMATO 		else
571e09c310eSMasatake YAMATO 			syntax = SYNTAX_UNKNOWN;
572e09c310eSMasatake YAMATO 	}
573e09c310eSMasatake YAMATO }
574e09c310eSMasatake YAMATO 
findProtobufTags0(bool oneshot,int originalScopeCorkIndex)575602d6ba1SMasatake YAMATO static void findProtobufTags0 (bool oneshot, int originalScopeCorkIndex)
5766ea83ed2SMasatake YAMATO {
577602d6ba1SMasatake YAMATO 	int scopeCorkIndex = originalScopeCorkIndex;
5786ea83ed2SMasatake YAMATO 	while (token.type != TOKEN_EOF)
5796ea83ed2SMasatake YAMATO 	{
58070e24df0SMasatake YAMATO 		int corkIndex = CORK_NIL;
58170e24df0SMasatake YAMATO 		bool dontChangeScope = false;
582e09c310eSMasatake YAMATO 
583e09c310eSMasatake YAMATO 		if (tokenIsKeyword (KEYWORD_SYNTAX) && originalScopeCorkIndex == CORK_NIL)
584e09c310eSMasatake YAMATO 		{
585e09c310eSMasatake YAMATO 			parseSyntax ();
586e09c310eSMasatake YAMATO 			dontChangeScope = true;
587e09c310eSMasatake YAMATO 		}
588e09c310eSMasatake YAMATO 		else if (tokenIsKeyword (KEYWORD_PACKAGE))
58970e24df0SMasatake YAMATO 		{
59070e24df0SMasatake YAMATO 			corkIndex = parsePackage ();
59170e24df0SMasatake YAMATO 			scopeCorkIndex = corkIndex;
59270e24df0SMasatake YAMATO 		}
5936ea83ed2SMasatake YAMATO 		else if (tokenIsKeyword (KEYWORD_MESSAGE))
59470e24df0SMasatake YAMATO 			corkIndex = parseStatement (PK_MESSAGE, scopeCorkIndex);
5956ea83ed2SMasatake YAMATO 		else if (tokenIsKeyword (KEYWORD_ENUM))
59670e24df0SMasatake YAMATO 		{
59770e24df0SMasatake YAMATO 			corkIndex = parseStatement (PK_ENUM, scopeCorkIndex);
59870e24df0SMasatake YAMATO 			dontChangeScope = true;
59970e24df0SMasatake YAMATO 		}
6006ea83ed2SMasatake YAMATO 		else if (tokenIsKeyword (KEYWORD_REPEATED) || tokenIsKeyword (KEYWORD_OPTIONAL) || tokenIsKeyword (KEYWORD_REQUIRED))
60170e24df0SMasatake YAMATO 			corkIndex = parseStatement (PK_FIELD, scopeCorkIndex);
6026ea83ed2SMasatake YAMATO 		else if (tokenIsKeyword (KEYWORD_SERVICE))
60370e24df0SMasatake YAMATO 			corkIndex = parseStatement (PK_SERVICE, scopeCorkIndex);
6046ea83ed2SMasatake YAMATO 		else if (tokenIsKeyword (KEYWORD_RPC))
60570e24df0SMasatake YAMATO 			corkIndex = parseStatement (PK_RPC, scopeCorkIndex);
606b2e1d739SMasatake YAMATO 		else if (tokenIsKeyword (KEYWORD_EXTEND))
607b2e1d739SMasatake YAMATO 			corkIndex = parseStatementFull (PK_MESSAGE, R_MESSAGE_EXTENSION, scopeCorkIndex);
608ac4a85f0SMasatake YAMATO 		else if (tokenIsKeyword (KEYWORD_ONEOF))
609ac4a85f0SMasatake YAMATO 		{
610ac4a85f0SMasatake YAMATO 			corkIndex = parseStatement (PK_ONEOF, scopeCorkIndex);
611ac4a85f0SMasatake YAMATO 			dontChangeScope = true;
612ac4a85f0SMasatake YAMATO 		}
6132fab7ad8SMasatake YAMATO 		else if (tokenIsKeyword (KEYWORD_MAP))
6142fab7ad8SMasatake YAMATO 			parseMap (scopeCorkIndex);
615602d6ba1SMasatake YAMATO 		else if (tokenIsKeyword (KEYWORD_GROUP))
616602d6ba1SMasatake YAMATO 			corkIndex = parseStatement (PK_GROUP, scopeCorkIndex);
6171fa2993eSMasatake YAMATO 		else if (tokenIsKeyword (KEYWORD_IMPORT))
6181fa2993eSMasatake YAMATO 		{
6191fa2993eSMasatake YAMATO 			corkIndex = parseImport (scopeCorkIndex);
6201fa2993eSMasatake YAMATO 			dontChangeScope = true;
6211fa2993eSMasatake YAMATO 		}
62213522841SMasatake YAMATO 		else if (tokenIsKeyword (KEYWORD_OPTION))
62313522841SMasatake YAMATO 			dontChangeScope = true;
62413522841SMasatake YAMATO 		else if (syntax == SYNTAX_PROTO3
6253671ad72SMasatake YAMATO 				 && (token.type == '.' || token.type == TOKEN_ID))
62613522841SMasatake YAMATO 		{
62713522841SMasatake YAMATO 			tagEntryInfo *e = getEntryInCorkQueue (scopeCorkIndex);
6283671ad72SMasatake YAMATO 			if (e && e->kindIndex == PK_MESSAGE)
62913522841SMasatake YAMATO 				corkIndex = parseStatement (PK_FIELD, scopeCorkIndex);
63013522841SMasatake YAMATO 		}
6316ea83ed2SMasatake YAMATO 
6326ea83ed2SMasatake YAMATO 		skipUntil (";{}");
63370e24df0SMasatake YAMATO 		if (!dontChangeScope && token.type == '{' && corkIndex != CORK_NIL)
63470e24df0SMasatake YAMATO 		{
63570e24df0SMasatake YAMATO 			/* Enter the new scope. */
63670e24df0SMasatake YAMATO 			scopeCorkIndex = corkIndex;
63770e24df0SMasatake YAMATO 		}
6383671ad72SMasatake YAMATO 		else if (!dontChangeScope && token.type == '}')
63970e24df0SMasatake YAMATO 		{
64070e24df0SMasatake YAMATO 			/* Return to the parent scope. */
64170e24df0SMasatake YAMATO 			tagEntryInfo *e = getEntryInCorkQueue (scopeCorkIndex);
6423671ad72SMasatake YAMATO 			if (e)
6433671ad72SMasatake YAMATO 			{
64470e24df0SMasatake YAMATO 				scopeCorkIndex = e->extensionFields.scopeIndex;
64559b6f293SMasatake YAMATO 				e->extensionFields.endLine = getInputLineNumber ();
64670e24df0SMasatake YAMATO 			}
6473671ad72SMasatake YAMATO 		}
6486ea83ed2SMasatake YAMATO 		nextToken ();
649602d6ba1SMasatake YAMATO 
650602d6ba1SMasatake YAMATO 		if (oneshot && scopeCorkIndex == originalScopeCorkIndex)
651602d6ba1SMasatake YAMATO 			break;
6526ea83ed2SMasatake YAMATO 	}
653602d6ba1SMasatake YAMATO }
654602d6ba1SMasatake YAMATO 
findProtobufTags(void)655602d6ba1SMasatake YAMATO static void findProtobufTags (void)
656602d6ba1SMasatake YAMATO {
657602d6ba1SMasatake YAMATO 	cppInit (false, false, false, false,
658d00bddf9SMasatake YAMATO 			 KIND_GHOST_INDEX, 0, 0,
659d00bddf9SMasatake YAMATO 			 KIND_GHOST_INDEX,
660602d6ba1SMasatake YAMATO 			 KIND_GHOST_INDEX, 0, 0,
661602d6ba1SMasatake YAMATO 			 FIELD_UNKNOWN);
662602d6ba1SMasatake YAMATO 	token.value = vStringNew ();
663602d6ba1SMasatake YAMATO 
6642cc84b9fSChris Wendt 	syntax = SYNTAX_UNKNOWN;
6652cc84b9fSChris Wendt 
666602d6ba1SMasatake YAMATO 	nextToken ();
667602d6ba1SMasatake YAMATO 	findProtobufTags0 (false, CORK_NIL);
6686ea83ed2SMasatake YAMATO 
6696ea83ed2SMasatake YAMATO 	vStringDelete (token.value);
6706ea83ed2SMasatake YAMATO 	cppTerminate ();
6716ea83ed2SMasatake YAMATO }
6726ea83ed2SMasatake YAMATO 
initialize(const langType language)6736ea83ed2SMasatake YAMATO static void initialize (const langType language)
6746ea83ed2SMasatake YAMATO {
6756ea83ed2SMasatake YAMATO 	Lang_protobuf = language;
6766ea83ed2SMasatake YAMATO }
6776ea83ed2SMasatake YAMATO 
ProtobufParser(void)6786ea83ed2SMasatake YAMATO extern parserDefinition* ProtobufParser (void)
6796ea83ed2SMasatake YAMATO {
6806ea83ed2SMasatake YAMATO 	static const char *const extensions [] = { "proto", NULL };
6816ea83ed2SMasatake YAMATO 	parserDefinition* def = parserNew ("Protobuf");
6826ea83ed2SMasatake YAMATO 
6836ea83ed2SMasatake YAMATO 	def->extensions = extensions;
68409ae690fSMasatake YAMATO 	def->kindTable      = ProtobufKinds;
6856ea83ed2SMasatake YAMATO 	def->initialize = initialize;
6866ea83ed2SMasatake YAMATO 	def->kindCount  = ARRAY_SIZE (ProtobufKinds);
6876ea83ed2SMasatake YAMATO 	def->parser     = findProtobufTags;
6886ea83ed2SMasatake YAMATO 	def->keywordTable = ProtobufKeywordTable;
6896ea83ed2SMasatake YAMATO 	def->keywordCount = ARRAY_SIZE (ProtobufKeywordTable);
6906ea83ed2SMasatake YAMATO 
691e484fe2eSMasatake YAMATO 	/* cpreprocessor wants corkQueue. */
6926b1a862eSMasatake YAMATO 	def->useCork    = CORK_QUEUE;
693e484fe2eSMasatake YAMATO 
6946ea83ed2SMasatake YAMATO 	return def;
6956ea83ed2SMasatake YAMATO }
696