xref: /Universal-ctags/parsers/ldscript.c (revision d69940b7160d084b07ccb9a66639454bdd4b5043)
14ffa0fb7SMasatake YAMATO /*
24ffa0fb7SMasatake YAMATO  *   Copyright (c) 2016, Masatake YAMATO
34ffa0fb7SMasatake YAMATO  *   Copyright (c) 2016, Red Hat, Inc.
44ffa0fb7SMasatake YAMATO  *
54ffa0fb7SMasatake YAMATO  *   This source code is released for free distribution under the terms of the
64ffa0fb7SMasatake YAMATO  *   GNU General Public License version 2 or (at your option) any later version.
74ffa0fb7SMasatake YAMATO  *
84ffa0fb7SMasatake YAMATO  *   This module contains functions for generating tags for GNU linker script
94ffa0fb7SMasatake YAMATO  *   files.
104ffa0fb7SMasatake YAMATO  */
114ffa0fb7SMasatake YAMATO 
124ffa0fb7SMasatake YAMATO #include "general.h"
134ffa0fb7SMasatake YAMATO #include "tokeninfo.h"
144ffa0fb7SMasatake YAMATO 
154ffa0fb7SMasatake YAMATO #include "entry.h"
1687214e15SMasatake YAMATO #include "cpreprocessor.h"
174ffa0fb7SMasatake YAMATO #include "keyword.h"
180d502ef0SMasatake YAMATO #include "parse.h"
19*d69940b7SMasatake YAMATO #include "ptrarray.h"
204ffa0fb7SMasatake YAMATO #include "read.h"
21*d69940b7SMasatake YAMATO #include "trace.h"
224ffa0fb7SMasatake YAMATO #include "xtag.h"
234ffa0fb7SMasatake YAMATO 
249a4d7997SMasatake YAMATO #include <string.h>
259a4d7997SMasatake YAMATO 
264ffa0fb7SMasatake YAMATO /*
274ffa0fb7SMasatake YAMATO  *   DATA DEFINITIONS
284ffa0fb7SMasatake YAMATO  */
294ffa0fb7SMasatake YAMATO 
304ffa0fb7SMasatake YAMATO typedef enum {
314ffa0fb7SMasatake YAMATO 	LD_SCRIPT_SYMBOL_ENTRYPOINT,
324ffa0fb7SMasatake YAMATO } ldScriptSymbolRole;
334ffa0fb7SMasatake YAMATO 
3413457258SMasatake YAMATO static roleDefinition LdScriptSymbolRoles [] = {
354ffa0fb7SMasatake YAMATO 	{ true, "entrypoint", "entry points" },
364ffa0fb7SMasatake YAMATO };
374ffa0fb7SMasatake YAMATO 
384ffa0fb7SMasatake YAMATO typedef enum {
39f5b8634aSMasatake YAMATO 	LD_SCRIPT_INPUT_SECTION_MAPPED,
409a4d7997SMasatake YAMATO 	LD_SCRIPT_INPUT_SECTION_DISCARDED,
41f5b8634aSMasatake YAMATO } ldScriptInputSectionRole;
42f5b8634aSMasatake YAMATO 
4313457258SMasatake YAMATO static roleDefinition LdScriptInputSectionRoles [] = {
44f5b8634aSMasatake YAMATO 	{ true, "mapped",  "mapped to output section" },
459a4d7997SMasatake YAMATO 	{ true, "discarded", "discarded when linking" },
46f5b8634aSMasatake YAMATO };
47f5b8634aSMasatake YAMATO 
48f5b8634aSMasatake YAMATO typedef enum {
49705ca28dSMasatake YAMATO 	K_SECTION,
50705ca28dSMasatake YAMATO 	K_SYMBOL,
51705ca28dSMasatake YAMATO 	K_VERSION,
52f5b8634aSMasatake YAMATO 	K_INPUT_SECTION,
534ffa0fb7SMasatake YAMATO } ldScriptKind;
544ffa0fb7SMasatake YAMATO 
55e112e8abSMasatake YAMATO static kindDefinition LdScriptKinds [] = {
564ffa0fb7SMasatake YAMATO 	{ true, 'S', "section", "sections" },
574ffa0fb7SMasatake YAMATO 	{ true, 's', "symbol",  "symbols",
584ffa0fb7SMasatake YAMATO 	  .referenceOnly = false, ATTACH_ROLES(LdScriptSymbolRoles)},
594ffa0fb7SMasatake YAMATO 	{ true, 'v', "version", "versions" },
60f5b8634aSMasatake YAMATO 	{ true, 'i', "inputSection", "input sections",
61f5b8634aSMasatake YAMATO 	  .referenceOnly = true, ATTACH_ROLES(LdScriptInputSectionRoles)},
624ffa0fb7SMasatake YAMATO };
634ffa0fb7SMasatake YAMATO 
644ffa0fb7SMasatake YAMATO enum {
654ffa0fb7SMasatake YAMATO 	KEYWORD_ENTRY,
664ffa0fb7SMasatake YAMATO 	KEYWORD_SECTIONS,
674ffa0fb7SMasatake YAMATO 	KEYWORD_LOC,
684ffa0fb7SMasatake YAMATO 	KEYWORD_AT,
694ffa0fb7SMasatake YAMATO 	KEYWORD_VERSION,
704ffa0fb7SMasatake YAMATO 	KEYWORD_PROVIDE,
714ffa0fb7SMasatake YAMATO 	KEYWORD_PROVIDE_HIDDEN,
724ffa0fb7SMasatake YAMATO 	KEYWORD_HIDDEN,
73f5b8634aSMasatake YAMATO 	KEYWORD_EXCLUDE_FILE,
74f5b8634aSMasatake YAMATO 	KEYWORD_INPUT_SECTION_FLAGS,
75f5b8634aSMasatake YAMATO 	KEYWORD_COMMON,
76f5b8634aSMasatake YAMATO 	KEYWORD_KEEP,
77074f40fdSMasatake YAMATO 	KEYWORD_DATA,
784ffa0fb7SMasatake YAMATO };
794ffa0fb7SMasatake YAMATO typedef int keywordId; /* to allow KEYWORD_NONE */
804ffa0fb7SMasatake YAMATO 
814ffa0fb7SMasatake YAMATO 
824ffa0fb7SMasatake YAMATO static const keywordTable LdScriptKeywordTable[] = {
834ffa0fb7SMasatake YAMATO 	/* keyword			keyword ID */
844ffa0fb7SMasatake YAMATO 	{ "ENTRY",			KEYWORD_ENTRY			},
854ffa0fb7SMasatake YAMATO 	{ "SECTIONS",		KEYWORD_SECTIONS		},
864ffa0fb7SMasatake YAMATO 	{ ".",				KEYWORD_LOC				},
874ffa0fb7SMasatake YAMATO 	{ "AT",				KEYWORD_AT				},
884ffa0fb7SMasatake YAMATO 	{ "VERSION",		KEYWORD_VERSION			},
894ffa0fb7SMasatake YAMATO 	{ "PROVIDE",		KEYWORD_PROVIDE			},
904ffa0fb7SMasatake YAMATO 	{ "PROVIDE_HIDDEN",	KEYWORD_PROVIDE_HIDDEN	},
914ffa0fb7SMasatake YAMATO 	{ "HIDDEN",	        KEYWORD_HIDDEN	        },
92f5b8634aSMasatake YAMATO 	{ "EXCLUDE_FILE",   KEYWORD_EXCLUDE_FILE    },
93f5b8634aSMasatake YAMATO 	{ "INPUT_SECTION_FLAGS", KEYWORD_INPUT_SECTION_FLAGS },
94f5b8634aSMasatake YAMATO 	{ "COMMON",			KEYWORD_COMMON },
95f5b8634aSMasatake YAMATO 	{ "KEEP",			KEYWORD_KEEP },
96074f40fdSMasatake YAMATO 	{ "BYTE",			KEYWORD_DATA },
97074f40fdSMasatake YAMATO 	{ "SHORT",			KEYWORD_DATA },
98074f40fdSMasatake YAMATO 	{ "LONG",			KEYWORD_DATA },
99074f40fdSMasatake YAMATO 	{ "QUAD",			KEYWORD_DATA },
100074f40fdSMasatake YAMATO 	{ "SQUAD",			KEYWORD_DATA },
101074f40fdSMasatake YAMATO 	{ "FILL",			KEYWORD_DATA },
1024ffa0fb7SMasatake YAMATO };
1034ffa0fb7SMasatake YAMATO 
1044ffa0fb7SMasatake YAMATO enum eTokenType {
1054ffa0fb7SMasatake YAMATO 	/* 0..255 are the byte's value */
1064ffa0fb7SMasatake YAMATO 	TOKEN_EOF = 256,
1074ffa0fb7SMasatake YAMATO 	TOKEN_UNDEFINED,
1084ffa0fb7SMasatake YAMATO 	TOKEN_KEYWORD,
1094ffa0fb7SMasatake YAMATO 	TOKEN_IDENTIFIER,
1104ffa0fb7SMasatake YAMATO 	TOKEN_NUMBER,
1114ffa0fb7SMasatake YAMATO 	TOKEN_ASSIGNMENT_OP,
1124ffa0fb7SMasatake YAMATO 	TOKEN_OP,
1134ffa0fb7SMasatake YAMATO 	TOKEN_PHDIR,
1144ffa0fb7SMasatake YAMATO 	TOKEN_REGION,
1154ffa0fb7SMasatake YAMATO 	TOKEN_FILLEXP,
1169a4d7997SMasatake YAMATO 	TOKEN_DISCARD,
1174ffa0fb7SMasatake YAMATO };
1184ffa0fb7SMasatake YAMATO 
1194ffa0fb7SMasatake YAMATO static void readToken (tokenInfo *const token, void *data CTAGS_ATTR_UNUSED);
1204ffa0fb7SMasatake YAMATO static void clearToken (tokenInfo *token);
1214ffa0fb7SMasatake YAMATO static void copyToken (tokenInfo *dest, tokenInfo *src, void *data CTAGS_ATTR_UNUSED);
1224ffa0fb7SMasatake YAMATO 
123002dd246SMasatake YAMATO typedef struct sLdScriptToken {
124002dd246SMasatake YAMATO 	tokenInfo base;
1254ffa0fb7SMasatake YAMATO 	int scopeIndex;
1264ffa0fb7SMasatake YAMATO 	tokenKeyword assignment;
127*d69940b7SMasatake YAMATO 	bool whitespacePrefixed;
128002dd246SMasatake YAMATO } ldScriptToken;
129002dd246SMasatake YAMATO 
130002dd246SMasatake YAMATO #define LDSCRIPT(TOKEN) ((ldScriptToken *)TOKEN)
1314ffa0fb7SMasatake YAMATO 
1321082869bSMasatake YAMATO static struct tokenTypePair ldScriptTypePairs [] = {
1334ffa0fb7SMasatake YAMATO 	{ '{', '}' },
1344ffa0fb7SMasatake YAMATO };
1354ffa0fb7SMasatake YAMATO 
1364ffa0fb7SMasatake YAMATO static struct tokenInfoClass ldScriptTokenInfoClass = {
1374ffa0fb7SMasatake YAMATO 	.nPreAlloc = 4,
1384ffa0fb7SMasatake YAMATO 	.typeForUndefined = TOKEN_UNDEFINED,
1394ffa0fb7SMasatake YAMATO 	.keywordNone      = KEYWORD_NONE,
1404ffa0fb7SMasatake YAMATO 	.typeForKeyword   = TOKEN_KEYWORD,
1414ffa0fb7SMasatake YAMATO 	.typeForEOF       = TOKEN_EOF,
142002dd246SMasatake YAMATO 	.extraSpace       = sizeof (ldScriptToken) - sizeof (tokenInfo),
1434ffa0fb7SMasatake YAMATO 	.pairs            = ldScriptTypePairs,
1444ffa0fb7SMasatake YAMATO 	.pairCount        = ARRAY_SIZE (ldScriptTypePairs),
1454ffa0fb7SMasatake YAMATO 	.read             = readToken,
1464ffa0fb7SMasatake YAMATO 	.clear            = clearToken,
1474ffa0fb7SMasatake YAMATO 	.copy             = copyToken,
1484ffa0fb7SMasatake YAMATO };
1494ffa0fb7SMasatake YAMATO 
1504ffa0fb7SMasatake YAMATO typedef enum {
1514ffa0fb7SMasatake YAMATO 	F_ASSIGNMENT,
1524ffa0fb7SMasatake YAMATO 	COUNT_FIELD
1530f6569aeSMasatake YAMATO } ldScriptField;
1544ffa0fb7SMasatake YAMATO 
155b56bd065SMasatake YAMATO static fieldDefinition LdScriptFields[COUNT_FIELD] = {
1564ffa0fb7SMasatake YAMATO 	{ .name = "assignment",
1574ffa0fb7SMasatake YAMATO 	  .description = "how a value is assigned to the symbol",
1584ffa0fb7SMasatake YAMATO 	  .enabled = true },
1594ffa0fb7SMasatake YAMATO };
1604ffa0fb7SMasatake YAMATO 
1614ffa0fb7SMasatake YAMATO static langType Lang_ldscript;
1624ffa0fb7SMasatake YAMATO 
1634ffa0fb7SMasatake YAMATO /*
1644ffa0fb7SMasatake YAMATO  *   FUNCTION DEFINITIONS
1654ffa0fb7SMasatake YAMATO  */
1664ffa0fb7SMasatake YAMATO 
newLdScriptToken(void)1674ffa0fb7SMasatake YAMATO static tokenInfo *newLdScriptToken (void)
1684ffa0fb7SMasatake YAMATO {
1694ffa0fb7SMasatake YAMATO 	return newToken (&ldScriptTokenInfoClass);
1704ffa0fb7SMasatake YAMATO }
1714ffa0fb7SMasatake YAMATO 
clearToken(tokenInfo * token)1724ffa0fb7SMasatake YAMATO static void clearToken (tokenInfo *token)
1734ffa0fb7SMasatake YAMATO {
174002dd246SMasatake YAMATO 	LDSCRIPT(token)->scopeIndex = CORK_NIL;
175002dd246SMasatake YAMATO 	LDSCRIPT(token)->assignment = KEYWORD_NONE;
1764ffa0fb7SMasatake YAMATO }
1774ffa0fb7SMasatake YAMATO 
copyToken(tokenInfo * dest,tokenInfo * src,void * data CTAGS_ATTR_UNUSED)1784ffa0fb7SMasatake YAMATO static void copyToken (tokenInfo *dest, tokenInfo *src, void *data CTAGS_ATTR_UNUSED)
1794ffa0fb7SMasatake YAMATO {
180002dd246SMasatake YAMATO 	LDSCRIPT (dest)->scopeIndex =
181002dd246SMasatake YAMATO 		LDSCRIPT (src)->scopeIndex;
182002dd246SMasatake YAMATO 	LDSCRIPT (dest)->assignment =
183002dd246SMasatake YAMATO 		LDSCRIPT (src)->assignment;
184*d69940b7SMasatake YAMATO 	LDSCRIPT (dest)->whitespacePrefixed =
185*d69940b7SMasatake YAMATO 		LDSCRIPT (src)->whitespacePrefixed;
1864ffa0fb7SMasatake YAMATO }
1874ffa0fb7SMasatake YAMATO 
makeLdScriptTagMaybe(tagEntryInfo * const e,tokenInfo * const token,int kind,int role)1884ffa0fb7SMasatake YAMATO static int makeLdScriptTagMaybe (tagEntryInfo *const e, tokenInfo *const token,
1894ffa0fb7SMasatake YAMATO 								 int kind, int role)
1904ffa0fb7SMasatake YAMATO {
19124b256e3SMasatake YAMATO 	if (role == ROLE_DEFINITION_INDEX)
1924ffa0fb7SMasatake YAMATO 	{
1934ffa0fb7SMasatake YAMATO 		if (! LdScriptKinds[kind].enabled)
1944ffa0fb7SMasatake YAMATO 			return CORK_NIL;
1954ffa0fb7SMasatake YAMATO 	}
1964ffa0fb7SMasatake YAMATO 	else if (! (isXtagEnabled (XTAG_REFERENCE_TAGS)
1974ffa0fb7SMasatake YAMATO 				&& LdScriptKinds[kind].roles[role].enabled))
1984ffa0fb7SMasatake YAMATO 		return CORK_NIL;
1994ffa0fb7SMasatake YAMATO 
2002fe47fcaSMasatake YAMATO 	initRefTagEntry (e, tokenString (token),
20116a2541cSMasatake YAMATO 					 kind,
2024ffa0fb7SMasatake YAMATO 					 role);
2034ffa0fb7SMasatake YAMATO 	e->lineNumber = token->lineNumber;
2044ffa0fb7SMasatake YAMATO 	e->filePosition = token->filePosition;
205002dd246SMasatake YAMATO 	e->extensionFields.scopeIndex = LDSCRIPT (token)->scopeIndex;
2064ffa0fb7SMasatake YAMATO 
2074ffa0fb7SMasatake YAMATO 	/* TODO: implement file: field. */
2084ffa0fb7SMasatake YAMATO 	if ((kind == K_SYMBOL)
2094ffa0fb7SMasatake YAMATO 		&& LdScriptFields[F_ASSIGNMENT].enabled)
2104ffa0fb7SMasatake YAMATO 	{
211a7b49da1SColomban Wendling 		const char *assignment = NULL;
2124ffa0fb7SMasatake YAMATO 
213002dd246SMasatake YAMATO 		switch (LDSCRIPT (token)->assignment)
2144ffa0fb7SMasatake YAMATO 		{
2154ffa0fb7SMasatake YAMATO 		case KEYWORD_PROVIDE:
2164ffa0fb7SMasatake YAMATO 			assignment = "provide";
2174ffa0fb7SMasatake YAMATO 			break;
2184ffa0fb7SMasatake YAMATO 		case KEYWORD_PROVIDE_HIDDEN:
2194ffa0fb7SMasatake YAMATO 			assignment = "provide_hidden";
2204ffa0fb7SMasatake YAMATO 			break;
2214ffa0fb7SMasatake YAMATO 		case KEYWORD_HIDDEN:
2224ffa0fb7SMasatake YAMATO 			assignment = "hidden";
2234ffa0fb7SMasatake YAMATO 			break;
2244ffa0fb7SMasatake YAMATO 		}
2254ffa0fb7SMasatake YAMATO 
2264ffa0fb7SMasatake YAMATO 		if (assignment)
227aa4def17SMasatake YAMATO 			attachParserField (e, false, LdScriptFields[F_ASSIGNMENT].ftype,
2284ffa0fb7SMasatake YAMATO 							   assignment);
2294ffa0fb7SMasatake YAMATO 	}
2304ffa0fb7SMasatake YAMATO 
2314ffa0fb7SMasatake YAMATO 	return makeTagEntry (e);
2324ffa0fb7SMasatake YAMATO }
2334ffa0fb7SMasatake YAMATO 
2344ffa0fb7SMasatake YAMATO #define isIdentifierChar(c)										\
23597ab90c3SMasatake YAMATO 	(cppIsalnum (c) || (c) == '_' || (c) == '.' || (c) == '-' || (c) >= 0x80)
2364ffa0fb7SMasatake YAMATO 
readPrefixedToken(tokenInfo * const token,int type)2374ffa0fb7SMasatake YAMATO static int readPrefixedToken (tokenInfo *const token, int type)
2384ffa0fb7SMasatake YAMATO {
2394ffa0fb7SMasatake YAMATO 	int n = 0;
2404ffa0fb7SMasatake YAMATO 	int c;
2414ffa0fb7SMasatake YAMATO 
2424ffa0fb7SMasatake YAMATO 	while ((c = cppGetc()) != EOF)
2434ffa0fb7SMasatake YAMATO 	{
2444ffa0fb7SMasatake YAMATO 		if (isIdentifierChar (c))
2454ffa0fb7SMasatake YAMATO 		{
2464ffa0fb7SMasatake YAMATO 			n++;
2472fe47fcaSMasatake YAMATO 			tokenPutc (token, c);
2484ffa0fb7SMasatake YAMATO 		}
2494ffa0fb7SMasatake YAMATO 		else
2504ffa0fb7SMasatake YAMATO 		{
2514ffa0fb7SMasatake YAMATO 			cppUngetc (c);
2524ffa0fb7SMasatake YAMATO 			break;
2534ffa0fb7SMasatake YAMATO 		}
2544ffa0fb7SMasatake YAMATO 	}
2554ffa0fb7SMasatake YAMATO 
2564ffa0fb7SMasatake YAMATO 	if (n)
2574ffa0fb7SMasatake YAMATO 		token->type = type;
2584ffa0fb7SMasatake YAMATO 	return n;
2594ffa0fb7SMasatake YAMATO }
2604ffa0fb7SMasatake YAMATO 
261*d69940b7SMasatake YAMATO // We stop applying macro replacements if a macro is used so many
262*d69940b7SMasatake YAMATO // times in a recursive macro expansion.
263*d69940b7SMasatake YAMATO #define LD_SCRIPT_PARSER_MAXIMUM_MACRO_USE_COUNT 8
264*d69940b7SMasatake YAMATO 
collectMacroArguments(ptrArray * args)265*d69940b7SMasatake YAMATO static bool collectMacroArguments (ptrArray *args)
266*d69940b7SMasatake YAMATO {
267*d69940b7SMasatake YAMATO 	vString *s = vStringNew ();
268*d69940b7SMasatake YAMATO 	tokenInfo *const t = newLdScriptToken ();
269*d69940b7SMasatake YAMATO 	int depth = 1;
270*d69940b7SMasatake YAMATO 
271*d69940b7SMasatake YAMATO 	do
272*d69940b7SMasatake YAMATO 	{
273*d69940b7SMasatake YAMATO 		tokenRead (t);
274*d69940b7SMasatake YAMATO 
275*d69940b7SMasatake YAMATO 		if (tokenIsType (t, EOF))
276*d69940b7SMasatake YAMATO 			break;
277*d69940b7SMasatake YAMATO 		else if (tokenIsTypeVal (t, ')'))
278*d69940b7SMasatake YAMATO 		{
279*d69940b7SMasatake YAMATO 			depth--;
280*d69940b7SMasatake YAMATO 			if (depth == 0)
281*d69940b7SMasatake YAMATO 			{
282*d69940b7SMasatake YAMATO 				char *cstr = vStringDeleteUnwrap (s);
283*d69940b7SMasatake YAMATO 				ptrArrayAdd (args, cstr);
284*d69940b7SMasatake YAMATO 				s = NULL;
285*d69940b7SMasatake YAMATO 			}
286*d69940b7SMasatake YAMATO 			else
287*d69940b7SMasatake YAMATO 				vStringCat (s, t->string);
288*d69940b7SMasatake YAMATO 		}
289*d69940b7SMasatake YAMATO 		else if (tokenIsTypeVal (t, '('))
290*d69940b7SMasatake YAMATO 		{
291*d69940b7SMasatake YAMATO 			depth++;
292*d69940b7SMasatake YAMATO 			vStringCat (s, t->string);
293*d69940b7SMasatake YAMATO 		}
294*d69940b7SMasatake YAMATO 		else if (tokenIsTypeVal (t, ','))
295*d69940b7SMasatake YAMATO 		{
296*d69940b7SMasatake YAMATO 			char *cstr = vStringDeleteUnwrap (s);
297*d69940b7SMasatake YAMATO 			ptrArrayAdd (args, cstr);
298*d69940b7SMasatake YAMATO 			s = vStringNew ();
299*d69940b7SMasatake YAMATO 		}
300*d69940b7SMasatake YAMATO 		else
301*d69940b7SMasatake YAMATO 		{
302*d69940b7SMasatake YAMATO 			if (LDSCRIPT(t)->whitespacePrefixed)
303*d69940b7SMasatake YAMATO 				vStringPut(s, ' ');
304*d69940b7SMasatake YAMATO 			vStringCat (s, t->string);
305*d69940b7SMasatake YAMATO 		}
306*d69940b7SMasatake YAMATO 	}
307*d69940b7SMasatake YAMATO 	while (depth > 0);
308*d69940b7SMasatake YAMATO 
309*d69940b7SMasatake YAMATO 	vStringDelete (s);			/* NULL is acceptable. */
310*d69940b7SMasatake YAMATO 
311*d69940b7SMasatake YAMATO 	tokenDelete (t);
312*d69940b7SMasatake YAMATO 
313*d69940b7SMasatake YAMATO 	if (depth > 0)
314*d69940b7SMasatake YAMATO 		TRACE_PRINT("unbalanced argument list");
315*d69940b7SMasatake YAMATO 
316*d69940b7SMasatake YAMATO 	return (depth > 0)? false: true;
317*d69940b7SMasatake YAMATO }
318*d69940b7SMasatake YAMATO 
expandCppMacro(cppMacroInfo * macroInfo)319*d69940b7SMasatake YAMATO static bool expandCppMacro (cppMacroInfo *macroInfo)
320*d69940b7SMasatake YAMATO {
321*d69940b7SMasatake YAMATO 	ptrArray *args = NULL;
322*d69940b7SMasatake YAMATO 
323*d69940b7SMasatake YAMATO 	if (macroInfo->hasParameterList)
324*d69940b7SMasatake YAMATO 	{
325*d69940b7SMasatake YAMATO 		tokenInfo *const t = newLdScriptToken ();
326*d69940b7SMasatake YAMATO 
327*d69940b7SMasatake YAMATO 		/* Though macro arguments are expected, they are not found. */
328*d69940b7SMasatake YAMATO 		tokenRead (t);
329*d69940b7SMasatake YAMATO 		if (!tokenIsTypeVal (t, '('))
330*d69940b7SMasatake YAMATO 		{
331*d69940b7SMasatake YAMATO 			tokenUnread (t);
332*d69940b7SMasatake YAMATO 			tokenDelete (t);
333*d69940b7SMasatake YAMATO 			TRACE_PRINT("no argument for the %s<%p>", macroInfo->name, macroInfo);
334*d69940b7SMasatake YAMATO 			return false;
335*d69940b7SMasatake YAMATO 		}
336*d69940b7SMasatake YAMATO 
337*d69940b7SMasatake YAMATO 		args = ptrArrayNew (eFree);
338*d69940b7SMasatake YAMATO 		if (!collectMacroArguments (args))
339*d69940b7SMasatake YAMATO 		{
340*d69940b7SMasatake YAMATO 			ptrArrayDelete (args);
341*d69940b7SMasatake YAMATO 			tokenUnread (t);
342*d69940b7SMasatake YAMATO 			tokenDelete (t);
343*d69940b7SMasatake YAMATO 			return false;
344*d69940b7SMasatake YAMATO 		}
345*d69940b7SMasatake YAMATO 		tokenDelete (t);
346*d69940b7SMasatake YAMATO 	}
347*d69940b7SMasatake YAMATO 
348*d69940b7SMasatake YAMATO #ifdef DO_TRACING
349*d69940b7SMasatake YAMATO 	for (int i = 0; i < ptrArrayCount(args); i++)
350*d69940b7SMasatake YAMATO 		TRACE_PRINT("[%d] %s", i, (const char *)ptrArrayItem (args, i));
351*d69940b7SMasatake YAMATO #endif
352*d69940b7SMasatake YAMATO 
353*d69940b7SMasatake YAMATO 	cppBuildMacroReplacementWithPtrArrayAndUngetResult (macroInfo, args);
354*d69940b7SMasatake YAMATO 
355*d69940b7SMasatake YAMATO 	ptrArrayDelete (args);		/* NULL is acceptable. */
356*d69940b7SMasatake YAMATO 	return true;
357*d69940b7SMasatake YAMATO }
358*d69940b7SMasatake YAMATO 
readToken(tokenInfo * const token,void * data CTAGS_ATTR_UNUSED)3594ffa0fb7SMasatake YAMATO static void readToken (tokenInfo *const token, void *data CTAGS_ATTR_UNUSED)
3604ffa0fb7SMasatake YAMATO {
3614ffa0fb7SMasatake YAMATO 	int c, c0, c1;
3624ffa0fb7SMasatake YAMATO 
3634ffa0fb7SMasatake YAMATO 	token->type		= TOKEN_UNDEFINED;
3644ffa0fb7SMasatake YAMATO 	token->keyword	= KEYWORD_NONE;
3654ffa0fb7SMasatake YAMATO 	vStringClear (token->string);
3664ffa0fb7SMasatake YAMATO 
367*d69940b7SMasatake YAMATO 	int prefix_count = -1;
368*d69940b7SMasatake YAMATO 	LDSCRIPT (token)->whitespacePrefixed = false;
3694ffa0fb7SMasatake YAMATO 	do {
3704ffa0fb7SMasatake YAMATO 		c = cppGetc();
371*d69940b7SMasatake YAMATO 		prefix_count++;
372*d69940b7SMasatake YAMATO 		if (prefix_count > 0)
373*d69940b7SMasatake YAMATO 			LDSCRIPT (token)->whitespacePrefixed = true;
3745fb525a6SMasatake YAMATO 	} while (c == ' ' || c== '\t' || c == '\f' || c == '\r' || c == '\n'
3755fb525a6SMasatake YAMATO 			 || c == STRING_SYMBOL || c == CHAR_SYMBOL);
3764ffa0fb7SMasatake YAMATO 
3774ffa0fb7SMasatake YAMATO 	token->lineNumber   = getInputLineNumber ();
3784ffa0fb7SMasatake YAMATO 	token->filePosition = getInputFilePosition ();
3794ffa0fb7SMasatake YAMATO 
3804ffa0fb7SMasatake YAMATO 	switch (c)
3814ffa0fb7SMasatake YAMATO 	{
3824ffa0fb7SMasatake YAMATO 	case EOF:
3834ffa0fb7SMasatake YAMATO 		token->type = TOKEN_EOF;
3844ffa0fb7SMasatake YAMATO 		break;
3854ffa0fb7SMasatake YAMATO 	case ';':
3864ffa0fb7SMasatake YAMATO 	case '(':
3874ffa0fb7SMasatake YAMATO 	case ')':
3884ffa0fb7SMasatake YAMATO 	case '{':
3894ffa0fb7SMasatake YAMATO 	case '}':
390f5b8634aSMasatake YAMATO 	case '[':
391f5b8634aSMasatake YAMATO 	case ']':
392*d69940b7SMasatake YAMATO 		tokenPutc(token, c);
3934ffa0fb7SMasatake YAMATO 		token->type = c;
3944ffa0fb7SMasatake YAMATO 		break;
3954ffa0fb7SMasatake YAMATO 	case '~':
3964ffa0fb7SMasatake YAMATO 	case '%':
3974ffa0fb7SMasatake YAMATO 	case '?':
3982fe47fcaSMasatake YAMATO 		tokenPutc(token, c);
3994ffa0fb7SMasatake YAMATO 		token->type = TOKEN_OP;
4004ffa0fb7SMasatake YAMATO 		break;
4014ffa0fb7SMasatake YAMATO 	case '-':
4024ffa0fb7SMasatake YAMATO 	case '+':
4034ffa0fb7SMasatake YAMATO 	case '*':
4044ffa0fb7SMasatake YAMATO 	case '/':					/* -,+,*,/,-=,+=,*=,/= */
4052fe47fcaSMasatake YAMATO 		tokenPutc(token, c);
4064ffa0fb7SMasatake YAMATO 		c0 = cppGetc ();
4074ffa0fb7SMasatake YAMATO 		token->type = TOKEN_OP;
4084ffa0fb7SMasatake YAMATO 		if (c0 == '=')
4094ffa0fb7SMasatake YAMATO 		{
4102fe47fcaSMasatake YAMATO 			tokenPutc(token, c0);
4114ffa0fb7SMasatake YAMATO 			token->type = TOKEN_ASSIGNMENT_OP;
4124ffa0fb7SMasatake YAMATO 		}
4139a4d7997SMasatake YAMATO 		else if (c == '/' && c0 == 'D')
4149a4d7997SMasatake YAMATO 		{
4159a4d7997SMasatake YAMATO 			tokenInfo *const discard = newLdScriptToken ();
4169a4d7997SMasatake YAMATO 
4179a4d7997SMasatake YAMATO 			cppUngetc (c0);
4189a4d7997SMasatake YAMATO 			tokenRead (discard);
4199a4d7997SMasatake YAMATO 			if (tokenIsType(discard, IDENTIFIER) &&
4209a4d7997SMasatake YAMATO 				(strcmp(tokenString(discard), "DISCARD")) == 0)
4219a4d7997SMasatake YAMATO 			{
4229a4d7997SMasatake YAMATO 				c1 = cppGetc ();
4239a4d7997SMasatake YAMATO 				if (c1 == '/')
4249a4d7997SMasatake YAMATO 					token->type = TOKEN_DISCARD;
4259a4d7997SMasatake YAMATO 				else
4269a4d7997SMasatake YAMATO 				{
4279a4d7997SMasatake YAMATO 					cppUngetc (c1);
4289a4d7997SMasatake YAMATO 					tokenUnread (discard);
4299a4d7997SMasatake YAMATO 				}
4309a4d7997SMasatake YAMATO 			}
4319a4d7997SMasatake YAMATO 			else
4329a4d7997SMasatake YAMATO 				tokenUnread (discard);
433a203ce0eSMasatake YAMATO 			tokenDelete (discard);
4349a4d7997SMasatake YAMATO 		}
4354ffa0fb7SMasatake YAMATO 		else
4364ffa0fb7SMasatake YAMATO 			cppUngetc (c0);
4374ffa0fb7SMasatake YAMATO 		break;
4384ffa0fb7SMasatake YAMATO 	case '!':					/* !, != */
4392fe47fcaSMasatake YAMATO 		tokenPutc(token, c);
4404ffa0fb7SMasatake YAMATO 		token->type = TOKEN_OP;
4414ffa0fb7SMasatake YAMATO 		c0 = cppGetc ();
4424ffa0fb7SMasatake YAMATO 		if (c0 == '=')
4432fe47fcaSMasatake YAMATO 			tokenPutc(token, c0);
4444ffa0fb7SMasatake YAMATO 		else
4454ffa0fb7SMasatake YAMATO 			cppUngetc (c0);
4464ffa0fb7SMasatake YAMATO 	case '<':					/* <,<=,<<,<<= */
4472fe47fcaSMasatake YAMATO 		tokenPutc(token, c);
4484ffa0fb7SMasatake YAMATO 		token->type = TOKEN_OP;
4494ffa0fb7SMasatake YAMATO 		c0 = cppGetc ();
4504ffa0fb7SMasatake YAMATO 		if (c0 == c  || c0 == '=')
4514ffa0fb7SMasatake YAMATO 		{
4522fe47fcaSMasatake YAMATO 			tokenPutc(token, c0);
4534ffa0fb7SMasatake YAMATO 			if (c0 == c)
4544ffa0fb7SMasatake YAMATO 			{
4554ffa0fb7SMasatake YAMATO 				c1 = cppGetc ();
4564ffa0fb7SMasatake YAMATO 				if (c1 == '=')
4574ffa0fb7SMasatake YAMATO 				{
4582fe47fcaSMasatake YAMATO 					tokenPutc(token, c1);
4594ffa0fb7SMasatake YAMATO 					token->type = TOKEN_ASSIGNMENT_OP;
4604ffa0fb7SMasatake YAMATO 				}
4614ffa0fb7SMasatake YAMATO 				else
4624ffa0fb7SMasatake YAMATO 					cppUngetc (c1);
4634ffa0fb7SMasatake YAMATO 			}
4644ffa0fb7SMasatake YAMATO 		}
4654ffa0fb7SMasatake YAMATO 		else
4664ffa0fb7SMasatake YAMATO 			cppUngetc (c0);
4674ffa0fb7SMasatake YAMATO 	case '|':					/* |,||,|= */
4684ffa0fb7SMasatake YAMATO 	case '&':					/* &,&&,&= */
4692fe47fcaSMasatake YAMATO 		tokenPutc(token, c);
4704ffa0fb7SMasatake YAMATO 		token->type = TOKEN_OP;
4714ffa0fb7SMasatake YAMATO 		c0 = cppGetc ();
4724ffa0fb7SMasatake YAMATO 		if (c0 == c)
4732fe47fcaSMasatake YAMATO 			tokenPutc(token, c0);
4744ffa0fb7SMasatake YAMATO 		else if (c0 == '=')
4754ffa0fb7SMasatake YAMATO 		{
4762fe47fcaSMasatake YAMATO 			tokenPutc(token, c0);
4774ffa0fb7SMasatake YAMATO 			token->type = TOKEN_ASSIGNMENT_OP;
4784ffa0fb7SMasatake YAMATO 		}
4794ffa0fb7SMasatake YAMATO 		else
4804ffa0fb7SMasatake YAMATO 			cppUngetc (c0);
4814ffa0fb7SMasatake YAMATO 		break;
4824ffa0fb7SMasatake YAMATO 	case '=':					/* =,== */
4832fe47fcaSMasatake YAMATO 		tokenPutc(token, c);
4844ffa0fb7SMasatake YAMATO 		if (!readPrefixedToken (token, TOKEN_FILLEXP))
4854ffa0fb7SMasatake YAMATO 		{
4864ffa0fb7SMasatake YAMATO 			c0 = cppGetc ();
4874ffa0fb7SMasatake YAMATO 			if (c0 == '=')
4884ffa0fb7SMasatake YAMATO 			{
4892fe47fcaSMasatake YAMATO 				tokenPutc(token, c0);
4904ffa0fb7SMasatake YAMATO 				token->type = TOKEN_OP;
4914ffa0fb7SMasatake YAMATO 			}
4924ffa0fb7SMasatake YAMATO 			else
4934ffa0fb7SMasatake YAMATO 			{
4944ffa0fb7SMasatake YAMATO 				cppUngetc (c0);
4954ffa0fb7SMasatake YAMATO 				token->type = TOKEN_ASSIGNMENT_OP;
4964ffa0fb7SMasatake YAMATO 			}
4974ffa0fb7SMasatake YAMATO 		}
4984ffa0fb7SMasatake YAMATO 		break;
4994ffa0fb7SMasatake YAMATO 	case '>':					/* >,>>,>>= */
5002fe47fcaSMasatake YAMATO 		tokenPutc(token, c);
5014ffa0fb7SMasatake YAMATO 		if (!readPrefixedToken (token, TOKEN_REGION))
5024ffa0fb7SMasatake YAMATO 		{
5034ffa0fb7SMasatake YAMATO 			token->type = TOKEN_OP;
5044ffa0fb7SMasatake YAMATO 			c0 = cppGetc ();
5054ffa0fb7SMasatake YAMATO 			if (c0 == c  || c0 == '=')
5064ffa0fb7SMasatake YAMATO 			{
5072fe47fcaSMasatake YAMATO 				tokenPutc(token, c0);
5084ffa0fb7SMasatake YAMATO 				c1 = cppGetc();
5094ffa0fb7SMasatake YAMATO 				if (c1 == '=')
5104ffa0fb7SMasatake YAMATO 				{
5112fe47fcaSMasatake YAMATO 					tokenPutc(token, c1);
5124ffa0fb7SMasatake YAMATO 					token->type = TOKEN_ASSIGNMENT_OP;
5134ffa0fb7SMasatake YAMATO 				}
5144ffa0fb7SMasatake YAMATO 				else
5154ffa0fb7SMasatake YAMATO 					cppUngetc (c1);
5164ffa0fb7SMasatake YAMATO 			}
5174ffa0fb7SMasatake YAMATO 			else
5184ffa0fb7SMasatake YAMATO 				cppUngetc (c0);
5194ffa0fb7SMasatake YAMATO 		}
5204ffa0fb7SMasatake YAMATO 		break;
5214ffa0fb7SMasatake YAMATO 	case ':':
5222fe47fcaSMasatake YAMATO 		tokenPutc(token, c);
5234ffa0fb7SMasatake YAMATO 		if (!readPrefixedToken (token, TOKEN_PHDIR))
5244ffa0fb7SMasatake YAMATO 			token->type = c;
5254ffa0fb7SMasatake YAMATO 		break;
5264ffa0fb7SMasatake YAMATO 	default:
52710c208a6SMasatake YAMATO 		if (cppIsdigit (c))
5284ffa0fb7SMasatake YAMATO 		{
52910c208a6SMasatake YAMATO 			/* Using cppIsdigit here is redundant.
53010c208a6SMasatake YAMATO 			 *
53110c208a6SMasatake YAMATO 			 * `c' never takes STRING_SYMBOL or CHAR_SYMBOL as
53210c208a6SMasatake YAMATO 			 * its value here.
53310c208a6SMasatake YAMATO 			 * However, the practice using cppIs... macros for the value
53410c208a6SMasatake YAMATO 			 * returned from cppGetc() may avoid unexpected programming
53510c208a6SMasatake YAMATO 			 * mistakes I took repeatedly.
53610c208a6SMasatake YAMATO 			 */
5374ffa0fb7SMasatake YAMATO 			token->type = TOKEN_NUMBER;
5382fe47fcaSMasatake YAMATO 			tokenPutc(token, c);
5394ffa0fb7SMasatake YAMATO 			while ((c = cppGetc()))
5404ffa0fb7SMasatake YAMATO 			{
5414ffa0fb7SMasatake YAMATO 				if (isIdentifierChar (c))
5422fe47fcaSMasatake YAMATO 					tokenPutc(token, c);
5434ffa0fb7SMasatake YAMATO 				else
5444ffa0fb7SMasatake YAMATO 				{
5454ffa0fb7SMasatake YAMATO 					cppUngetc (c);
5464ffa0fb7SMasatake YAMATO 					break;
5474ffa0fb7SMasatake YAMATO 				}
5484ffa0fb7SMasatake YAMATO 			}
5494ffa0fb7SMasatake YAMATO 		}
5504ffa0fb7SMasatake YAMATO 		else if (isIdentifierChar(c))
5514ffa0fb7SMasatake YAMATO 		{
5522fe47fcaSMasatake YAMATO 			tokenPutc(token, c);
5534ffa0fb7SMasatake YAMATO 			while ((c = cppGetc()))
5544ffa0fb7SMasatake YAMATO 			{
5554ffa0fb7SMasatake YAMATO 				if (isIdentifierChar(c))
5562fe47fcaSMasatake YAMATO 					tokenPutc(token, c);
5574ffa0fb7SMasatake YAMATO 				else
5584ffa0fb7SMasatake YAMATO 				{
5594ffa0fb7SMasatake YAMATO 					cppUngetc (c);
5604ffa0fb7SMasatake YAMATO 					break;
5614ffa0fb7SMasatake YAMATO 				}
5624ffa0fb7SMasatake YAMATO 			}
5634ffa0fb7SMasatake YAMATO 			token->keyword = lookupKeyword (vStringValue (token->string), Lang_ldscript);
5644ffa0fb7SMasatake YAMATO 			if (token->keyword == KEYWORD_NONE)
565*d69940b7SMasatake YAMATO 			{
5664ffa0fb7SMasatake YAMATO 				token->type = TOKEN_IDENTIFIER;
567*d69940b7SMasatake YAMATO 
568*d69940b7SMasatake YAMATO 				cppMacroInfo *macroInfo = cppFindMacro (vStringValue (token->string));
569*d69940b7SMasatake YAMATO 				if (macroInfo)
570*d69940b7SMasatake YAMATO 				{
571*d69940b7SMasatake YAMATO 					TRACE_PRINT("Macro expansion: %s<%p>%s", vStringValue (token->string),
572*d69940b7SMasatake YAMATO 								macroInfo, macroInfo->hasParameterList? "(...)": "");
573*d69940b7SMasatake YAMATO 					if (!(macroInfo->useCount < LD_SCRIPT_PARSER_MAXIMUM_MACRO_USE_COUNT))
574*d69940b7SMasatake YAMATO 						TRACE_PRINT ("Overly uesd macro %s<%p> useCount: %d (> %d)",
575*d69940b7SMasatake YAMATO 									 vStringValue (token->string), macroInfo, macroInfo->useCount,
576*d69940b7SMasatake YAMATO 									 LD_SCRIPT_PARSER_MAXIMUM_MACRO_USE_COUNT);
577*d69940b7SMasatake YAMATO 					else if (expandCppMacro (macroInfo))
578*d69940b7SMasatake YAMATO 						readToken (token, NULL);
579*d69940b7SMasatake YAMATO 				}
580*d69940b7SMasatake YAMATO 			}
5814ffa0fb7SMasatake YAMATO 			else
5824ffa0fb7SMasatake YAMATO 				token->type = TOKEN_KEYWORD;
5834ffa0fb7SMasatake YAMATO 		}
5844ffa0fb7SMasatake YAMATO 		else
585*d69940b7SMasatake YAMATO 		{
586*d69940b7SMasatake YAMATO 			tokenPutc(token, c);
5874ffa0fb7SMasatake YAMATO 			token->type = c;
588*d69940b7SMasatake YAMATO 		}
5894ffa0fb7SMasatake YAMATO 		break;
5904ffa0fb7SMasatake YAMATO 	}
5914ffa0fb7SMasatake YAMATO }
5924ffa0fb7SMasatake YAMATO 
parseEntry(tokenInfo * const token)5934ffa0fb7SMasatake YAMATO static void parseEntry (tokenInfo *const token)
5944ffa0fb7SMasatake YAMATO {
5954ffa0fb7SMasatake YAMATO 	tokenRead (token);
5964ffa0fb7SMasatake YAMATO 	if (token->type == '(')
5974ffa0fb7SMasatake YAMATO 	{
5984ffa0fb7SMasatake YAMATO 		tokenInfo *const name = newLdScriptToken ();
5994ffa0fb7SMasatake YAMATO 
6004ffa0fb7SMasatake YAMATO 		tokenRead (name);
601d9d9244eSMasatake YAMATO 		if (tokenIsType(name, IDENTIFIER))
6024ffa0fb7SMasatake YAMATO 		{
6034ffa0fb7SMasatake YAMATO 			tagEntryInfo e;
6044ffa0fb7SMasatake YAMATO 
6054ffa0fb7SMasatake YAMATO 			makeLdScriptTagMaybe (&e, name, K_SYMBOL, LD_SCRIPT_SYMBOL_ENTRYPOINT);
6064ffa0fb7SMasatake YAMATO 			tokenRead (token);
6074ffa0fb7SMasatake YAMATO 			tokenSkipToType (token, ')');
6084ffa0fb7SMasatake YAMATO 		}
609a203ce0eSMasatake YAMATO 		tokenDelete (name);
6104ffa0fb7SMasatake YAMATO 	}
6114ffa0fb7SMasatake YAMATO }
6124ffa0fb7SMasatake YAMATO 
parseProvide(tokenInfo * token)6134ffa0fb7SMasatake YAMATO static void parseProvide (tokenInfo * token)
6144ffa0fb7SMasatake YAMATO {
6154ffa0fb7SMasatake YAMATO 	tokenKeyword p = token->keyword;
6164ffa0fb7SMasatake YAMATO 
6174ffa0fb7SMasatake YAMATO 	if (tokenSkipToType (token, '('))
6184ffa0fb7SMasatake YAMATO 	{
6194ffa0fb7SMasatake YAMATO 		tagEntryInfo e;
6204ffa0fb7SMasatake YAMATO 		tokenRead (token);
621d9d9244eSMasatake YAMATO 		if (tokenIsType(token, IDENTIFIER))
6224ffa0fb7SMasatake YAMATO 		{
623002dd246SMasatake YAMATO 			LDSCRIPT (token)->assignment = p;
6244ffa0fb7SMasatake YAMATO 
6254ffa0fb7SMasatake YAMATO 			makeLdScriptTagMaybe (&e, token,
62624b256e3SMasatake YAMATO 								  K_SYMBOL, ROLE_DEFINITION_INDEX);
627002dd246SMasatake YAMATO 			LDSCRIPT (token)->assignment = KEYWORD_NONE;
6284ffa0fb7SMasatake YAMATO 		}
6294ffa0fb7SMasatake YAMATO 		tokenSkipToType (token, ')');
6304ffa0fb7SMasatake YAMATO 	}
6314ffa0fb7SMasatake YAMATO }
6324ffa0fb7SMasatake YAMATO 
633f5b8634aSMasatake YAMATO /* An example of input sections:
634f5b8634aSMasatake YAMATO 
635f5b8634aSMasatake YAMATO 	(.text .rdata)
636f5b8634aSMasatake YAMATO 
637f5b8634aSMasatake YAMATO   .text and .rtada are input sections. */
parseInputSections(tokenInfo * const token)638f5b8634aSMasatake YAMATO static void parseInputSections (tokenInfo *const token)
639f5b8634aSMasatake YAMATO {
640f5b8634aSMasatake YAMATO 	tagEntryInfo e;
641f5b8634aSMasatake YAMATO 	do {
642f5b8634aSMasatake YAMATO 		tokenRead (token);
643f5b8634aSMasatake YAMATO 		if (token->type == ')')
644f5b8634aSMasatake YAMATO 			break;
645f5b8634aSMasatake YAMATO 		else if (tokenIsType (token, IDENTIFIER))
646f5b8634aSMasatake YAMATO 			makeLdScriptTagMaybe (&e, token,
647f5b8634aSMasatake YAMATO 								  K_INPUT_SECTION,
648002dd246SMasatake YAMATO 								  LDSCRIPT(token)->scopeIndex == CORK_NIL
6499a4d7997SMasatake YAMATO 								  ? LD_SCRIPT_INPUT_SECTION_DISCARDED
6509a4d7997SMasatake YAMATO 								  : LD_SCRIPT_INPUT_SECTION_MAPPED);
651f5b8634aSMasatake YAMATO 		else if (tokenIsKeyword (token, EXCLUDE_FILE))
652f5b8634aSMasatake YAMATO 			tokenSkipToType (token, ')');
653f5b8634aSMasatake YAMATO 	} while (!tokenIsEOF (token));
654f5b8634aSMasatake YAMATO }
655f5b8634aSMasatake YAMATO 
656f5b8634aSMasatake YAMATO /* Symbols and input sections are captured here.
657f5b8634aSMasatake YAMATO    An example of output sections:
658f5b8634aSMasatake YAMATO 
659f5b8634aSMasatake YAMATO 		__brk_base = .;
660f5b8634aSMasatake YAMATO 		. += 64 * 1024;
661f5b8634aSMasatake YAMATO 		*(.brk_reservation)
662f5b8634aSMasatake YAMATO 		__brk_limit = .;
663f5b8634aSMasatake YAMATO 
664f5b8634aSMasatake YAMATO   __brk_base and __brk_limit should be recorded as a symbol.
665f5b8634aSMasatake YAMATO   .brk_reservationshould be recorded as an input section. */
666f5b8634aSMasatake YAMATO 
parseOutputSectionCommands(tokenInfo * const token,int terminator)667f5b8634aSMasatake YAMATO static void parseOutputSectionCommands (tokenInfo *const token, int terminator)
6684ffa0fb7SMasatake YAMATO {
6694ffa0fb7SMasatake YAMATO 	tokenInfo *const tmp = newLdScriptToken ();
670002dd246SMasatake YAMATO 	int scope_index = LDSCRIPT (token)->scopeIndex;
6714ffa0fb7SMasatake YAMATO 
6724ffa0fb7SMasatake YAMATO 	do {
6734ffa0fb7SMasatake YAMATO 		tokenRead (token);
674002dd246SMasatake YAMATO 		LDSCRIPT (token)->scopeIndex = scope_index;
6754ffa0fb7SMasatake YAMATO 
676f5b8634aSMasatake YAMATO 		if (tokenIsKeyword (token, INPUT_SECTION_FLAGS))
677f5b8634aSMasatake YAMATO 		{
678f5b8634aSMasatake YAMATO 			tokenSkipToType (token, '(');
679f5b8634aSMasatake YAMATO 			tokenSkipToType (token, ')');
680f5b8634aSMasatake YAMATO 		}
681f5b8634aSMasatake YAMATO 		else if (tokenIsKeyword (token, KEEP))
682f5b8634aSMasatake YAMATO 		{
683f5b8634aSMasatake YAMATO 			tokenSkipToType (token, '(');
684f5b8634aSMasatake YAMATO 			parseOutputSectionCommands (token, ')');
685f5b8634aSMasatake YAMATO 		}
686f5b8634aSMasatake YAMATO 		else if (tokenIsType (token,IDENTIFIER)
687f5b8634aSMasatake YAMATO 				 || tokenIsKeyword (token, LOC))
6884ffa0fb7SMasatake YAMATO 		{
6894ffa0fb7SMasatake YAMATO 			tagEntryInfo e;
6904ffa0fb7SMasatake YAMATO 
6914ffa0fb7SMasatake YAMATO 			tokenRead (tmp);
692d9d9244eSMasatake YAMATO 			if (tokenIsType (tmp, ASSIGNMENT_OP))
6934ffa0fb7SMasatake YAMATO 			{
694f5b8634aSMasatake YAMATO 				if (! tokenIsKeyword (token, LOC))
6954ffa0fb7SMasatake YAMATO 					makeLdScriptTagMaybe (&e, token,
69624b256e3SMasatake YAMATO 										  K_SYMBOL, ROLE_DEFINITION_INDEX);
6974ffa0fb7SMasatake YAMATO 				tokenSkipToType (token, ';');
6984ffa0fb7SMasatake YAMATO 			}
699f5b8634aSMasatake YAMATO 			else if (tmp->type == '(')
700f5b8634aSMasatake YAMATO 				parseInputSections (token);
7014ffa0fb7SMasatake YAMATO 			else
702f5b8634aSMasatake YAMATO 				tokenUnread (tmp);
703f5b8634aSMasatake YAMATO 		}
704f5b8634aSMasatake YAMATO 		/* `*',`?', `[', `]' can be part of a pattern of input object file names
705f5b8634aSMasatake YAMATO 		   as a meta character.
706f5b8634aSMasatake YAMATO 		   `[' can enumerated here because it cannot be at the end of pattern. */
707f5b8634aSMasatake YAMATO 		else if ((token->type == TOKEN_OP
708f5b8634aSMasatake YAMATO 				  && ((tokenString(token)[0] == '*')
709f5b8634aSMasatake YAMATO 					  || (tokenString(token)[0] == '?'))
710f5b8634aSMasatake YAMATO 				  && (tokenString(token)[1] == '\0'))
711f5b8634aSMasatake YAMATO 				 || token->type == ']')
712f5b8634aSMasatake YAMATO 		{
713f5b8634aSMasatake YAMATO 			tokenRead (tmp);
714f5b8634aSMasatake YAMATO 			if (tmp->type == '(')
715f5b8634aSMasatake YAMATO 				parseInputSections (token);
716f5b8634aSMasatake YAMATO 			else
717f5b8634aSMasatake YAMATO 				tokenUnread (tmp);
7184ffa0fb7SMasatake YAMATO 		}
719d9d9244eSMasatake YAMATO 		else if (tokenIsKeyword (token, PROVIDE)
720d9d9244eSMasatake YAMATO 				 || tokenIsKeyword (token, PROVIDE_HIDDEN)
721d9d9244eSMasatake YAMATO 				 || tokenIsKeyword (token, HIDDEN))
7224ffa0fb7SMasatake YAMATO 			parseProvide (token);
723f5b8634aSMasatake YAMATO 	} while (! (tokenIsEOF (token) || token->type == terminator));
7244ffa0fb7SMasatake YAMATO 
725a203ce0eSMasatake YAMATO 	tokenDelete (tmp);
7264ffa0fb7SMasatake YAMATO }
7274ffa0fb7SMasatake YAMATO 
parseSection(tokenInfo * name)7284ffa0fb7SMasatake YAMATO static void parseSection (tokenInfo * name)
7294ffa0fb7SMasatake YAMATO {
7304ffa0fb7SMasatake YAMATO 	tokenInfo *const token = newLdScriptToken ();
7314ffa0fb7SMasatake YAMATO 	tagEntryInfo e;
7324ffa0fb7SMasatake YAMATO 
7334ffa0fb7SMasatake YAMATO 	tokenRead (token);
7344ffa0fb7SMasatake YAMATO 
735d9d9244eSMasatake YAMATO 	if (tokenIsType (token, ASSIGNMENT_OP))
7364ffa0fb7SMasatake YAMATO 	{
737d9d9244eSMasatake YAMATO 		if (!tokenIsKeyword (name, LOC))
7384ffa0fb7SMasatake YAMATO 			makeLdScriptTagMaybe (&e, name,
73924b256e3SMasatake YAMATO 								  K_SYMBOL, ROLE_DEFINITION_INDEX);
7404ffa0fb7SMasatake YAMATO 		tokenSkipToType (token, ';');
7414ffa0fb7SMasatake YAMATO 	}
7424ffa0fb7SMasatake YAMATO 	else
7434ffa0fb7SMasatake YAMATO 	{
7444ffa0fb7SMasatake YAMATO 	retry:
745d9d9244eSMasatake YAMATO 		if (tokenIsType (token, NUMBER))
7464ffa0fb7SMasatake YAMATO 			tokenSkipToType (token, ':');
747d9d9244eSMasatake YAMATO 		else if (tokenIsType (token, IDENTIFIER))
7484ffa0fb7SMasatake YAMATO 		{
7494ffa0fb7SMasatake YAMATO 			tokenCopy (name, token);
7504ffa0fb7SMasatake YAMATO 			tokenRead (token);
7514ffa0fb7SMasatake YAMATO 			goto retry;
7524ffa0fb7SMasatake YAMATO 		}
7534ffa0fb7SMasatake YAMATO 		else if (token->type == '(')
7544ffa0fb7SMasatake YAMATO 			tokenSkipToType (token, ')');
7554ffa0fb7SMasatake YAMATO 
7564ffa0fb7SMasatake YAMATO 		if (token->type == ':')
7574ffa0fb7SMasatake YAMATO 		{
7584ffa0fb7SMasatake YAMATO 			int scope_index;
7594ffa0fb7SMasatake YAMATO 
7609a4d7997SMasatake YAMATO 			if (tokenIsType (name, DISCARD))
7619a4d7997SMasatake YAMATO 				scope_index = CORK_NIL;
7629a4d7997SMasatake YAMATO 			else
7634ffa0fb7SMasatake YAMATO 				scope_index = makeLdScriptTagMaybe (&e, name,
76424b256e3SMasatake YAMATO 													K_SECTION, ROLE_DEFINITION_INDEX);
765f5b8634aSMasatake YAMATO 
7664ffa0fb7SMasatake YAMATO 			if (tokenSkipToType (token, '{'))
7674ffa0fb7SMasatake YAMATO 			{
768002dd246SMasatake YAMATO 				LDSCRIPT (token)->scopeIndex = scope_index;
769f5b8634aSMasatake YAMATO 				parseOutputSectionCommands (token, '}');
7704ffa0fb7SMasatake YAMATO 			}
7714ffa0fb7SMasatake YAMATO 		}
7724ffa0fb7SMasatake YAMATO 	}
773a203ce0eSMasatake YAMATO 	tokenDelete (token);
7744ffa0fb7SMasatake YAMATO }
7754ffa0fb7SMasatake YAMATO 
parseSections(tokenInfo * const token)7764ffa0fb7SMasatake YAMATO static void parseSections (tokenInfo *const token)
7774ffa0fb7SMasatake YAMATO {
7784ffa0fb7SMasatake YAMATO 	tokenRead (token);
7794ffa0fb7SMasatake YAMATO 	if (token->type == '{')
7804ffa0fb7SMasatake YAMATO 	{
7814ffa0fb7SMasatake YAMATO 		do {
7824ffa0fb7SMasatake YAMATO 			tokenRead (token);
783d9d9244eSMasatake YAMATO 			if (tokenIsKeyword (token, ENTRY))
7844ffa0fb7SMasatake YAMATO 				parseEntry (token);
785d9d9244eSMasatake YAMATO 			else if (tokenIsType(token, IDENTIFIER)
7869a4d7997SMasatake YAMATO 					 || tokenIsKeyword (token, LOC)
7879a4d7997SMasatake YAMATO 					 || tokenIsType (token, DISCARD))
7884ffa0fb7SMasatake YAMATO 				parseSection (token);
789d9d9244eSMasatake YAMATO 			else if (tokenIsKeyword (token, PROVIDE)
790d9d9244eSMasatake YAMATO 					 || tokenIsKeyword (token, PROVIDE_HIDDEN)
791d9d9244eSMasatake YAMATO 					 || tokenIsKeyword (token, HIDDEN))
7924ffa0fb7SMasatake YAMATO 				parseProvide (token);
793d9d9244eSMasatake YAMATO 		} while (! (tokenIsEOF (token) || token->type == '}'));
7944ffa0fb7SMasatake YAMATO 	}
7954ffa0fb7SMasatake YAMATO }
7964ffa0fb7SMasatake YAMATO 
parseVersion(tokenInfo * const token)7974ffa0fb7SMasatake YAMATO static void parseVersion (tokenInfo *const token)
7984ffa0fb7SMasatake YAMATO {
7994ffa0fb7SMasatake YAMATO 	tagEntryInfo e;
8004ffa0fb7SMasatake YAMATO 	makeLdScriptTagMaybe (&e, token,
80124b256e3SMasatake YAMATO 						  K_VERSION, ROLE_DEFINITION_INDEX);
8024ffa0fb7SMasatake YAMATO 
8034ffa0fb7SMasatake YAMATO 	if (tokenSkipToType (token, '{'))
8044ffa0fb7SMasatake YAMATO 		tokenSkipOverPair (token);
8054ffa0fb7SMasatake YAMATO }
8064ffa0fb7SMasatake YAMATO 
parseVersions(tokenInfo * const token)8074ffa0fb7SMasatake YAMATO static void parseVersions (tokenInfo *const token)
8084ffa0fb7SMasatake YAMATO {
8094ffa0fb7SMasatake YAMATO 	tokenRead (token);
8104ffa0fb7SMasatake YAMATO 	if (token->type == '{')
8114ffa0fb7SMasatake YAMATO 	{
8124ffa0fb7SMasatake YAMATO 		do {
8134ffa0fb7SMasatake YAMATO 			tokenRead (token);
814d9d9244eSMasatake YAMATO 			if (tokenIsType(token, IDENTIFIER))
8154ffa0fb7SMasatake YAMATO 				parseVersion (token);
816d9d9244eSMasatake YAMATO 		} while (! (tokenIsEOF (token) || token->type == '}'));
8174ffa0fb7SMasatake YAMATO 		tokenSkipToType (token, ';');
8184ffa0fb7SMasatake YAMATO 	}
8194ffa0fb7SMasatake YAMATO }
8204ffa0fb7SMasatake YAMATO 
findLdScriptTags(void)8214ffa0fb7SMasatake YAMATO static void findLdScriptTags (void)
8224ffa0fb7SMasatake YAMATO {
8234ffa0fb7SMasatake YAMATO 	tokenInfo *const token = newLdScriptToken ();
8244ffa0fb7SMasatake YAMATO 	tokenInfo *const tmp = newLdScriptToken ();
8254ffa0fb7SMasatake YAMATO 
8264ffa0fb7SMasatake YAMATO 	cppInit (false, false, false, false,
827d00bddf9SMasatake YAMATO 			 KIND_GHOST_INDEX, 0, 0,
828d00bddf9SMasatake YAMATO 			 KIND_GHOST_INDEX,
829ee4d2ebdSMasatake YAMATO 			 KIND_GHOST_INDEX, 0, 0,
830ee4d2ebdSMasatake YAMATO 			 FIELD_UNKNOWN);
8314ffa0fb7SMasatake YAMATO 
8324ffa0fb7SMasatake YAMATO 	do {
8334ffa0fb7SMasatake YAMATO 		tokenRead (token);
834d9d9244eSMasatake YAMATO 		if (tokenIsKeyword (token, ENTRY))
8354ffa0fb7SMasatake YAMATO 			parseEntry (token);
836d9d9244eSMasatake YAMATO 		else if (tokenIsKeyword (token, SECTIONS))
8374ffa0fb7SMasatake YAMATO 			parseSections (token);
838d9d9244eSMasatake YAMATO 		else if (tokenIsType(token, IDENTIFIER))
8394ffa0fb7SMasatake YAMATO 		{
8404ffa0fb7SMasatake YAMATO 			tagEntryInfo e;
8414ffa0fb7SMasatake YAMATO 			tokenRead (tmp);
842d9d9244eSMasatake YAMATO 			if (tokenIsType(tmp, ASSIGNMENT_OP))
8434ffa0fb7SMasatake YAMATO 			{
8444ffa0fb7SMasatake YAMATO 				makeLdScriptTagMaybe (&e, token,
84524b256e3SMasatake YAMATO 									  K_SYMBOL, ROLE_DEFINITION_INDEX);
8464ffa0fb7SMasatake YAMATO 				tokenSkipToType (tmp, ';');
8474ffa0fb7SMasatake YAMATO 			}
8484ffa0fb7SMasatake YAMATO 		}
849d9d9244eSMasatake YAMATO 		else if (tokenIsKeyword (token, VERSION))
8504ffa0fb7SMasatake YAMATO 			parseVersions(token);
851d9d9244eSMasatake YAMATO 	} while (!tokenIsEOF (token));
8524ffa0fb7SMasatake YAMATO 
8534ffa0fb7SMasatake YAMATO 	cppTerminate ();
8544ffa0fb7SMasatake YAMATO 
855a203ce0eSMasatake YAMATO 	tokenDelete (tmp);
856a203ce0eSMasatake YAMATO 	tokenDelete (token);
8572438db48SMasatake YAMATO 
8582438db48SMasatake YAMATO 	flashTokenBacklog (&ldScriptTokenInfoClass);
8594ffa0fb7SMasatake YAMATO }
8604ffa0fb7SMasatake YAMATO 
initialize(const langType language)8614ffa0fb7SMasatake YAMATO static void initialize (const langType language)
8624ffa0fb7SMasatake YAMATO {
8634ffa0fb7SMasatake YAMATO 	Lang_ldscript = language;
8644ffa0fb7SMasatake YAMATO }
8654ffa0fb7SMasatake YAMATO 
LdScriptParser(void)8664ffa0fb7SMasatake YAMATO extern parserDefinition* LdScriptParser (void)
8674ffa0fb7SMasatake YAMATO {
8684ffa0fb7SMasatake YAMATO 	parserDefinition* def = parserNew ("LdScript");
8694ffa0fb7SMasatake YAMATO 
87056ff609aSMasatake YAMATO 	/* File name patters are picked from Linux kernel and ecos. */
87156ff609aSMasatake YAMATO 	static const char *const extensions [] = { "lds", "scr", "ld", "ldi", NULL };
8724ffa0fb7SMasatake YAMATO 
87378befd79SMasatake YAMATO 	/* lds.S must be here because Asm parser registers .S as an extension.
87478befd79SMasatake YAMATO 	 * ld.script is used in linux/arch/mips/boot/compressed/ld.script. */
87578befd79SMasatake YAMATO 	static const char *const patterns [] = { "*.lds.S", "ld.script", NULL };
8764ffa0fb7SMasatake YAMATO 
8774ffa0fb7SMasatake YAMATO 	/* Emacs's mode */
8784ffa0fb7SMasatake YAMATO 	static const char *const aliases [] = { "ld-script", NULL };
8794ffa0fb7SMasatake YAMATO 
8804ffa0fb7SMasatake YAMATO 	def->initialize = initialize;
8814ffa0fb7SMasatake YAMATO 	def->parser     = findLdScriptTags;
8824ffa0fb7SMasatake YAMATO 
88309ae690fSMasatake YAMATO 	def->kindTable      = LdScriptKinds;
8844ffa0fb7SMasatake YAMATO 	def->kindCount  = ARRAY_SIZE (LdScriptKinds);
8854ffa0fb7SMasatake YAMATO 	def->extensions = extensions;
8864ffa0fb7SMasatake YAMATO 	def->patterns   = patterns;
8874ffa0fb7SMasatake YAMATO 	def->aliases    = aliases;
8884ffa0fb7SMasatake YAMATO 	def->keywordTable = LdScriptKeywordTable;
8894ffa0fb7SMasatake YAMATO 	def->keywordCount = ARRAY_SIZE (LdScriptKeywordTable);
890a739fa5fSMasatake YAMATO 	def->fieldTable = LdScriptFields;
891a739fa5fSMasatake YAMATO 	def->fieldCount = ARRAY_SIZE (LdScriptFields);
8924ffa0fb7SMasatake YAMATO 
893*d69940b7SMasatake YAMATO 	def->useCork    = CORK_QUEUE|CORK_SYMTAB;
8944ffa0fb7SMasatake YAMATO 
8954ffa0fb7SMasatake YAMATO 	return def;
8964ffa0fb7SMasatake YAMATO }
897