1d4c6f1e6SMasatake YAMATO /*
2d4c6f1e6SMasatake YAMATO * Copyright (c) 1996-2002, Darren Hiebert
3d4c6f1e6SMasatake YAMATO *
4d4c6f1e6SMasatake YAMATO * This source code is released for free distribution under the terms of the
50ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
6d4c6f1e6SMasatake YAMATO *
7d316cd59SMasatake YAMATO * This module contains low level input and tag file read functions (newline
8d316cd59SMasatake YAMATO * conversion for input files are performed at this level).
9d4c6f1e6SMasatake YAMATO */
10d4c6f1e6SMasatake YAMATO
11d4c6f1e6SMasatake YAMATO /*
12d4c6f1e6SMasatake YAMATO * INCLUDE FILES
13d4c6f1e6SMasatake YAMATO */
14d4c6f1e6SMasatake YAMATO #include "general.h" /* must always come first */
15d4c6f1e6SMasatake YAMATO
16d4c6f1e6SMasatake YAMATO #include <string.h>
17d4c6f1e6SMasatake YAMATO #include <ctype.h>
18c434aea4SMasatake YAMATO #include <stdlib.h>
19d4c6f1e6SMasatake YAMATO
20d4c6f1e6SMasatake YAMATO #define FILE_WRITE
21d4c6f1e6SMasatake YAMATO #include "read.h"
22b5df137eSMasatake YAMATO #include "read_p.h"
23d4c6f1e6SMasatake YAMATO #include "debug.h"
248cbf052bSMasatake YAMATO #include "entry_p.h"
25d4c6f1e6SMasatake YAMATO #include "routines.h"
2629e40fb6SMasatake YAMATO #include "routines_p.h"
2721996d92SMasatake YAMATO #include "options_p.h"
280d502ef0SMasatake YAMATO #include "parse_p.h"
29e3416868SMasatake YAMATO #include "promise_p.h"
30df2449f1SMasatake YAMATO #include "stats_p.h"
31a219c98cSMasatake YAMATO #include "trace.h"
3256065e52SMasatake YAMATO #include "trashbox.h"
332acdcfa1SYasuhiro Matsumoto #ifdef HAVE_ICONV
342acdcfa1SYasuhiro Matsumoto # include "mbcs.h"
35f38d6693SMasatake YAMATO # include "mbcs_p.h"
362acdcfa1SYasuhiro Matsumoto #endif
37d4c6f1e6SMasatake YAMATO
38d4c6f1e6SMasatake YAMATO /*
39e54558c7SMasatake YAMATO * DATA DECLARATIONS
40e54558c7SMasatake YAMATO */
41e54558c7SMasatake YAMATO
42a8778562SMasatake YAMATO typedef struct sLangStack {
43a8778562SMasatake YAMATO langType *languages;
44a8778562SMasatake YAMATO unsigned int count;
45a8778562SMasatake YAMATO unsigned int size;
46a8778562SMasatake YAMATO } langStack;
47a8778562SMasatake YAMATO
48e54558c7SMasatake YAMATO /* Maintains the state of the current input file.
49e54558c7SMasatake YAMATO */
50a8778562SMasatake YAMATO typedef union sInputLangInfo {
51a8778562SMasatake YAMATO langStack stack;
52a8778562SMasatake YAMATO langType type;
53a8778562SMasatake YAMATO } inputLangInfo;
54a8778562SMasatake YAMATO
55e54558c7SMasatake YAMATO typedef struct sInputFileInfo {
56e54558c7SMasatake YAMATO vString *name; /* name to report for input file */
57e54558c7SMasatake YAMATO vString *tagPath; /* path of input file relative to tag file */
58e54558c7SMasatake YAMATO unsigned long lineNumber;/* line number in the input file */
59aed2b6adSMasatake YAMATO unsigned long lineNumberOrigin; /* The value set to `lineNumber'
60aed2b6adSMasatake YAMATO when `resetInputFile' is called
61aed2b6adSMasatake YAMATO on the input stream.
62aed2b6adSMasatake YAMATO This is needed for nested stream. */
63ce990805SThomas Braun bool isHeader; /* is input file a header file? */
64e54558c7SMasatake YAMATO } inputFileInfo;
65e54558c7SMasatake YAMATO
66c434aea4SMasatake YAMATO typedef struct sComputPos {
67c434aea4SMasatake YAMATO MIOPos pos;
68c434aea4SMasatake YAMATO long offset;
69c434aea4SMasatake YAMATO bool open;
703b035e33SMasatake YAMATO int crAdjustment;
71c434aea4SMasatake YAMATO } compoundPos;
72c434aea4SMasatake YAMATO
73e54558c7SMasatake YAMATO typedef struct sInputLineFposMap {
74c434aea4SMasatake YAMATO compoundPos *pos;
75e54558c7SMasatake YAMATO unsigned int count;
76e54558c7SMasatake YAMATO unsigned int size;
77e54558c7SMasatake YAMATO } inputLineFposMap;
78e54558c7SMasatake YAMATO
79a0c1e6d7SMasatake YAMATO typedef struct sNestedInputStreamInfo {
80a0c1e6d7SMasatake YAMATO unsigned long startLine;
81ef722b09SMasatake YAMATO long startCharOffset;
82a0c1e6d7SMasatake YAMATO unsigned long endLine;
83ef722b09SMasatake YAMATO long endCharOffset;
84a0c1e6d7SMasatake YAMATO } nestedInputStreamInfo;
85a0c1e6d7SMasatake YAMATO
86e54558c7SMasatake YAMATO typedef struct sInputFile {
87e54558c7SMasatake YAMATO vString *path; /* path of input file (if any) */
88e54558c7SMasatake YAMATO vString *line; /* last line read from file */
89e54558c7SMasatake YAMATO const unsigned char* currentLine; /* current line being worked on */
90203c6955SJiří Techet MIO *mio; /* MIO stream used for reading the file */
91c434aea4SMasatake YAMATO compoundPos filePosition; /* file position of current line */
92e54558c7SMasatake YAMATO unsigned int ungetchIdx;
934d985ad2SColomban Wendling int ungetchBuf[8]; /* characters that were ungotten */
94e54558c7SMasatake YAMATO
957d6be565SMasatake YAMATO bool bomFound;
96e54558c7SMasatake YAMATO /* Contains data pertaining to the original `source' file in which the tag
97e54558c7SMasatake YAMATO * was defined. This may be different from the `input' file when #line
98e54558c7SMasatake YAMATO * directives are processed (i.e. the input file is preprocessor output).
99e54558c7SMasatake YAMATO */
100e54558c7SMasatake YAMATO inputFileInfo input; /* name, lineNumber */
101e54558c7SMasatake YAMATO inputFileInfo source;
102e54558c7SMasatake YAMATO
103a0c1e6d7SMasatake YAMATO nestedInputStreamInfo nestedInputStreamInfo;
104a0c1e6d7SMasatake YAMATO
105e54558c7SMasatake YAMATO /* sourceTagPathHolder is a kind of trash box.
106e54558c7SMasatake YAMATO The buffer pointed by tagPath field of source field can
107e54558c7SMasatake YAMATO be referred from tagsEntryInfo instances. sourceTagPathHolder
108e54558c7SMasatake YAMATO is used keeping the buffer till all processing about the current
109e54558c7SMasatake YAMATO input file is done. After all processing is done, the buffers
110759d281dSK.Takata in sourceTagPathHolder are destroyed. */
111e54558c7SMasatake YAMATO stringList * sourceTagPathHolder;
112e54558c7SMasatake YAMATO inputLineFposMap lineFposMap;
1134e0c6ed6SMasatake YAMATO vString *allLines;
1142fa69c1bSMasatake YAMATO int thinDepth;
115c314f261SMasatake YAMATO time_t mtime;
116e54558c7SMasatake YAMATO } inputFile;
117e54558c7SMasatake YAMATO
1187262d5eaSMasatake YAMATO static inputLangInfo inputLang;
1197262d5eaSMasatake YAMATO static langType sourceLang;
120e54558c7SMasatake YAMATO
121e54558c7SMasatake YAMATO /*
122a8778562SMasatake YAMATO * FUNCTION DECLARATIONS
123a8778562SMasatake YAMATO */
124a8778562SMasatake YAMATO static void langStackInit (langStack *langStack);
125a8778562SMasatake YAMATO static langType langStackTop (langStack *langStack);
126657cbb19SMasatake YAMATO static langType langStackBotom(langStack *langStack);
127a8778562SMasatake YAMATO static void langStackPush (langStack *langStack, langType type);
128a8778562SMasatake YAMATO static langType langStackPop (langStack *langStack);
12979758c23SMasatake YAMATO static void langStackClear(langStack *langStack);
130a8778562SMasatake YAMATO
131a8778562SMasatake YAMATO
132a8778562SMasatake YAMATO /*
133d4c6f1e6SMasatake YAMATO * DATA DEFINITIONS
134d4c6f1e6SMasatake YAMATO */
135d41a27faSMasatake YAMATO static inputFile File; /* static read through functions */
1364fa68e36SMasatake YAMATO static inputFile BackupFile; /* File is copied here when a nested parser is pushed */
137c434aea4SMasatake YAMATO static compoundPos StartOfLine; /* holds deferred position of start of line */
138d4c6f1e6SMasatake YAMATO
139d4c6f1e6SMasatake YAMATO /*
140d4c6f1e6SMasatake YAMATO * FUNCTION DEFINITIONS
141d4c6f1e6SMasatake YAMATO */
142d4c6f1e6SMasatake YAMATO
getInputLineNumber(void)143c7adb37bSMasatake YAMATO extern unsigned long getInputLineNumber (void)
144c7adb37bSMasatake YAMATO {
145c7adb37bSMasatake YAMATO return File.input.lineNumber;
146c7adb37bSMasatake YAMATO }
147c7adb37bSMasatake YAMATO
getInputLineOffset(void)148f2d8a3d9SJiří Techet extern int getInputLineOffset (void)
149f2d8a3d9SJiří Techet {
150f2d8a3d9SJiří Techet unsigned char *base = (unsigned char *) vStringValue (File.line);
1512734995fSMasatake YAMATO int ret;
1522734995fSMasatake YAMATO
1532734995fSMasatake YAMATO if (File.currentLine)
1542734995fSMasatake YAMATO ret = File.currentLine - base - File.ungetchIdx;
1552734995fSMasatake YAMATO else if (File.input.lineNumber)
1562734995fSMasatake YAMATO {
1572734995fSMasatake YAMATO /* When EOF is saw, currentLine is set to NULL.
1582734995fSMasatake YAMATO * So the way to calculate the offset at the end of file is tricky.
1592734995fSMasatake YAMATO */
1602734995fSMasatake YAMATO ret = (mio_tell (File.mio) - (File.bomFound? 3: 0))
1612734995fSMasatake YAMATO - getInputFileOffsetForLine(File.input.lineNumber);
1622734995fSMasatake YAMATO }
1632734995fSMasatake YAMATO else
1642734995fSMasatake YAMATO {
1652734995fSMasatake YAMATO /* At the first line of file. */
1662734995fSMasatake YAMATO ret = mio_tell (File.mio) - (File.bomFound? 3: 0);
1672734995fSMasatake YAMATO }
1682734995fSMasatake YAMATO
169f2d8a3d9SJiří Techet return ret >= 0 ? ret : 0;
170f2d8a3d9SJiří Techet }
171f2d8a3d9SJiří Techet
getInputFileName(void)172c7adb37bSMasatake YAMATO extern const char *getInputFileName (void)
173c7adb37bSMasatake YAMATO {
17454c2e083SMasatake YAMATO if (!File.input.name)
17554c2e083SMasatake YAMATO return NULL;
176c7adb37bSMasatake YAMATO return vStringValue (File.input.name);
177c7adb37bSMasatake YAMATO }
178c7adb37bSMasatake YAMATO
getInputFilePosition(void)179c7adb37bSMasatake YAMATO extern MIOPos getInputFilePosition (void)
180c7adb37bSMasatake YAMATO {
181c434aea4SMasatake YAMATO return File.filePosition.pos;
182c7adb37bSMasatake YAMATO }
183c7adb37bSMasatake YAMATO
getInputFileCompoundPosForLine(unsigned int line)1844d3d645dSMasatake YAMATO static compoundPos* getInputFileCompoundPosForLine (unsigned int line)
185c7adb37bSMasatake YAMATO {
186b21b2454SMasatake YAMATO int index;
187b21b2454SMasatake YAMATO if (line > 0)
188b21b2454SMasatake YAMATO {
189b21b2454SMasatake YAMATO if (File.lineFposMap.count > (line - 1))
190b21b2454SMasatake YAMATO index = line - 1;
191b21b2454SMasatake YAMATO else if (File.lineFposMap.count != 0)
192b21b2454SMasatake YAMATO index = File.lineFposMap.count - 1;
193b21b2454SMasatake YAMATO else
194b21b2454SMasatake YAMATO index = 0;
195b21b2454SMasatake YAMATO }
196b21b2454SMasatake YAMATO else
197b21b2454SMasatake YAMATO index = 0;
198b21b2454SMasatake YAMATO
1994d3d645dSMasatake YAMATO return File.lineFposMap.pos + index;
2004d3d645dSMasatake YAMATO }
2014d3d645dSMasatake YAMATO
getInputFilePositionForLine(unsigned int line)2024d3d645dSMasatake YAMATO extern MIOPos getInputFilePositionForLine (unsigned int line)
2034d3d645dSMasatake YAMATO {
2044d3d645dSMasatake YAMATO compoundPos *cpos = getInputFileCompoundPosForLine (line);
2054d3d645dSMasatake YAMATO return cpos->pos;
2064d3d645dSMasatake YAMATO }
2074d3d645dSMasatake YAMATO
getInputFileOffsetForLine(unsigned int line)2084d3d645dSMasatake YAMATO extern long getInputFileOffsetForLine (unsigned int line)
2094d3d645dSMasatake YAMATO {
2104d3d645dSMasatake YAMATO compoundPos *cpos = getInputFileCompoundPosForLine (line);
21129f3d603SMasatake YAMATO return cpos->offset - (File.bomFound? 3: 0);
212c7adb37bSMasatake YAMATO }
213c7adb37bSMasatake YAMATO
getInputLanguage(void)214c7adb37bSMasatake YAMATO extern langType getInputLanguage (void)
215c7adb37bSMasatake YAMATO {
216ebc3af7dSMasatake YAMATO return langStackTop (&inputLang.stack);
217c7adb37bSMasatake YAMATO }
218c7adb37bSMasatake YAMATO
getInputLanguageName(void)219c7adb37bSMasatake YAMATO extern const char *getInputLanguageName (void)
220c7adb37bSMasatake YAMATO {
221a8778562SMasatake YAMATO return getLanguageName (getInputLanguage());
222c7adb37bSMasatake YAMATO }
223c7adb37bSMasatake YAMATO
getInputFileTagPath(void)224c7adb37bSMasatake YAMATO extern const char *getInputFileTagPath (void)
225c7adb37bSMasatake YAMATO {
226c7adb37bSMasatake YAMATO return vStringValue (File.input.tagPath);
227c7adb37bSMasatake YAMATO }
228c7adb37bSMasatake YAMATO
isInputLanguage(langType lang)229ce990805SThomas Braun extern bool isInputLanguage (langType lang)
230c7adb37bSMasatake YAMATO {
231ce990805SThomas Braun return (bool)((lang) == getInputLanguage ());
232c7adb37bSMasatake YAMATO }
233c7adb37bSMasatake YAMATO
isInputHeaderFile(void)234ce990805SThomas Braun extern bool isInputHeaderFile (void)
235c7adb37bSMasatake YAMATO {
236c7adb37bSMasatake YAMATO return File.input.isHeader;
237c7adb37bSMasatake YAMATO }
238c7adb37bSMasatake YAMATO
isInputLanguageKindEnabled(int kindIndex)2395c56d939SMasatake YAMATO extern bool isInputLanguageKindEnabled (int kindIndex)
240c7adb37bSMasatake YAMATO {
2415c56d939SMasatake YAMATO return isLanguageKindEnabled (getInputLanguage (), kindIndex);
242c7adb37bSMasatake YAMATO }
243c7adb37bSMasatake YAMATO
isInputLanguageRoleEnabled(int kindIndex,int roleIndex)244320b1e8bSMasatake YAMATO extern bool isInputLanguageRoleEnabled (int kindIndex, int roleIndex)
245320b1e8bSMasatake YAMATO {
246320b1e8bSMasatake YAMATO return isLanguageRoleEnabled (getInputLanguage (),
247320b1e8bSMasatake YAMATO kindIndex, roleIndex);
248320b1e8bSMasatake YAMATO }
249320b1e8bSMasatake YAMATO
countInputLanguageKinds(void)2500f23950dSMasatake YAMATO extern unsigned int countInputLanguageKinds (void)
2510f23950dSMasatake YAMATO {
2520f23950dSMasatake YAMATO return countLanguageKinds (getInputLanguage ());
2530f23950dSMasatake YAMATO }
2540f23950dSMasatake YAMATO
countInputLanguageRoles(int kindIndex)2550f23950dSMasatake YAMATO extern unsigned int countInputLanguageRoles (int kindIndex)
2560f23950dSMasatake YAMATO {
2570f23950dSMasatake YAMATO return countLanguageRoles (getInputLanguage (), kindIndex);
2580f23950dSMasatake YAMATO }
2590f23950dSMasatake YAMATO
doesInputLanguageAllowNullTag(void)260ce990805SThomas Braun extern bool doesInputLanguageAllowNullTag (void)
261c7adb37bSMasatake YAMATO {
262a8778562SMasatake YAMATO return doesLanguageAllowNullTag (getInputLanguage ());
263c7adb37bSMasatake YAMATO }
264c7adb37bSMasatake YAMATO
doesInputLanguageRequestAutomaticFQTag(const tagEntryInfo * e)2656f0c51d8SMasatake YAMATO extern bool doesInputLanguageRequestAutomaticFQTag (const tagEntryInfo *e)
266c7adb37bSMasatake YAMATO {
2676f0c51d8SMasatake YAMATO return doesLanguageRequestAutomaticFQTag (e->langType);
268c7adb37bSMasatake YAMATO }
269c7adb37bSMasatake YAMATO
getSourceFileTagPath(void)270c7adb37bSMasatake YAMATO extern const char *getSourceFileTagPath (void)
271c7adb37bSMasatake YAMATO {
272c7adb37bSMasatake YAMATO return vStringValue (File.source.tagPath);
273c7adb37bSMasatake YAMATO }
274c7adb37bSMasatake YAMATO
getSourceLanguage(void)2755bd00ccbSMasatake YAMATO extern langType getSourceLanguage (void)
276c7adb37bSMasatake YAMATO {
2777262d5eaSMasatake YAMATO return sourceLang;
278c7adb37bSMasatake YAMATO }
279c7adb37bSMasatake YAMATO
getSourceLineNumber(void)280c7adb37bSMasatake YAMATO extern unsigned long getSourceLineNumber (void)
281c7adb37bSMasatake YAMATO {
282c7adb37bSMasatake YAMATO return File.source.lineNumber;
283c7adb37bSMasatake YAMATO }
284c7adb37bSMasatake YAMATO
freeInputFileInfo(inputFileInfo * finfo)285a5b1fa4aSMasatake YAMATO static void freeInputFileInfo (inputFileInfo *finfo)
286a5b1fa4aSMasatake YAMATO {
287a5b1fa4aSMasatake YAMATO if (finfo->name)
288a5b1fa4aSMasatake YAMATO {
289a5b1fa4aSMasatake YAMATO vStringDelete (finfo->name);
290a5b1fa4aSMasatake YAMATO finfo->name = NULL;
291a5b1fa4aSMasatake YAMATO }
292a5b1fa4aSMasatake YAMATO if (finfo->tagPath)
293a5b1fa4aSMasatake YAMATO {
29454d7e089SMasatake YAMATO vStringDelete (finfo->tagPath);
295a5b1fa4aSMasatake YAMATO finfo->tagPath = NULL;
296a5b1fa4aSMasatake YAMATO }
297a5b1fa4aSMasatake YAMATO }
298a5b1fa4aSMasatake YAMATO
freeInputFileResources(void)2996b659a51SMasatake YAMATO extern void freeInputFileResources (void)
300d4c6f1e6SMasatake YAMATO {
301d4c6f1e6SMasatake YAMATO if (File.path != NULL)
302d4c6f1e6SMasatake YAMATO vStringDelete (File.path);
303d4c6f1e6SMasatake YAMATO if (File.line != NULL)
304d4c6f1e6SMasatake YAMATO vStringDelete (File.line);
305a5b1fa4aSMasatake YAMATO freeInputFileInfo (&File.input);
306a5b1fa4aSMasatake YAMATO freeInputFileInfo (&File.source);
307d4c6f1e6SMasatake YAMATO }
308d4c6f1e6SMasatake YAMATO
getInputFileData(size_t * size)309c0732dcaSMasatake YAMATO extern const unsigned char *getInputFileData (size_t *size)
31031cb4225SMasatake YAMATO {
311203c6955SJiří Techet return mio_memory_get_data (File.mio, size);
31231cb4225SMasatake YAMATO }
31331cb4225SMasatake YAMATO
314d4c6f1e6SMasatake YAMATO /*
31501ceddeaSMasatake YAMATO * inputLineFposMap related functions
31601ceddeaSMasatake YAMATO */
freeLineFposMap(inputLineFposMap * lineFposMap)31701ceddeaSMasatake YAMATO static void freeLineFposMap (inputLineFposMap *lineFposMap)
31801ceddeaSMasatake YAMATO {
31901ceddeaSMasatake YAMATO if (lineFposMap->pos)
32001ceddeaSMasatake YAMATO {
321a32a50f1SMasatake YAMATO eFree (lineFposMap->pos);
32201ceddeaSMasatake YAMATO lineFposMap->pos = NULL;
32301ceddeaSMasatake YAMATO lineFposMap->count = 0;
32401ceddeaSMasatake YAMATO lineFposMap->size = 0;
32501ceddeaSMasatake YAMATO }
32601ceddeaSMasatake YAMATO }
32701ceddeaSMasatake YAMATO
allocLineFposMap(inputLineFposMap * lineFposMap)32801ceddeaSMasatake YAMATO static void allocLineFposMap (inputLineFposMap *lineFposMap)
32901ceddeaSMasatake YAMATO {
33001ceddeaSMasatake YAMATO #define INITIAL_lineFposMap_LEN 256
331c434aea4SMasatake YAMATO lineFposMap->pos = xCalloc (INITIAL_lineFposMap_LEN, compoundPos);
33201ceddeaSMasatake YAMATO lineFposMap->size = INITIAL_lineFposMap_LEN;
33301ceddeaSMasatake YAMATO lineFposMap->count = 0;
33401ceddeaSMasatake YAMATO }
33501ceddeaSMasatake YAMATO
appendLineFposMap(inputLineFposMap * lineFposMap,compoundPos * pos,bool crAdjustment)3363b035e33SMasatake YAMATO static void appendLineFposMap (inputLineFposMap *lineFposMap, compoundPos *pos,
3373b035e33SMasatake YAMATO bool crAdjustment)
33801ceddeaSMasatake YAMATO {
3393b035e33SMasatake YAMATO int lastCrAdjustment = 0;
3403b035e33SMasatake YAMATO
34101ceddeaSMasatake YAMATO if (lineFposMap->size == lineFposMap->count)
34201ceddeaSMasatake YAMATO {
34301ceddeaSMasatake YAMATO lineFposMap->size *= 2;
34401ceddeaSMasatake YAMATO lineFposMap->pos = xRealloc (lineFposMap->pos,
34501ceddeaSMasatake YAMATO lineFposMap->size,
346c434aea4SMasatake YAMATO compoundPos);
34701ceddeaSMasatake YAMATO }
348c434aea4SMasatake YAMATO
349c434aea4SMasatake YAMATO if (lineFposMap->count != 0)
3503b035e33SMasatake YAMATO {
351c434aea4SMasatake YAMATO lineFposMap->pos [lineFposMap->count - 1].open = false;
3523b035e33SMasatake YAMATO lastCrAdjustment = lineFposMap->pos [lineFposMap->count - 1].crAdjustment;
3533b035e33SMasatake YAMATO }
3543b035e33SMasatake YAMATO
355c434aea4SMasatake YAMATO lineFposMap->pos [lineFposMap->count] = *pos;
356c434aea4SMasatake YAMATO lineFposMap->pos [lineFposMap->count].open = true;
3573b035e33SMasatake YAMATO lineFposMap->pos [lineFposMap->count].crAdjustment
3583b035e33SMasatake YAMATO = lastCrAdjustment + ((crAdjustment)? 1: 0);
35901ceddeaSMasatake YAMATO lineFposMap->count++;
36001ceddeaSMasatake YAMATO }
36101ceddeaSMasatake YAMATO
compoundPosForOffset(const void * oft,const void * p)362c434aea4SMasatake YAMATO static int compoundPosForOffset (const void* oft, const void *p)
363c434aea4SMasatake YAMATO {
364c434aea4SMasatake YAMATO long offset = *(long *)oft;
365c434aea4SMasatake YAMATO const compoundPos *pos = p;
366c434aea4SMasatake YAMATO const compoundPos *next = (compoundPos *)(((char *)pos) + sizeof (compoundPos));
367c434aea4SMasatake YAMATO
3683b035e33SMasatake YAMATO if (offset < (pos->offset - pos->crAdjustment))
369c434aea4SMasatake YAMATO return -1;
3703b035e33SMasatake YAMATO else if (((pos->offset - pos->crAdjustment) <= offset)
371c434aea4SMasatake YAMATO && (pos->open
3723b035e33SMasatake YAMATO || (offset < (next->offset - next->crAdjustment))))
373c434aea4SMasatake YAMATO return 0;
374c434aea4SMasatake YAMATO else
375c434aea4SMasatake YAMATO return 1;
376c434aea4SMasatake YAMATO }
377c434aea4SMasatake YAMATO
getInputLineNumberForFileOffset(long offset)378c434aea4SMasatake YAMATO extern unsigned long getInputLineNumberForFileOffset(long offset)
379c434aea4SMasatake YAMATO {
380c434aea4SMasatake YAMATO compoundPos *p;
381c434aea4SMasatake YAMATO
38229f3d603SMasatake YAMATO if (File.bomFound)
38329f3d603SMasatake YAMATO offset += 3;
38429f3d603SMasatake YAMATO
385c434aea4SMasatake YAMATO p = bsearch (&offset, File.lineFposMap.pos, File.lineFposMap.count, sizeof (compoundPos),
386c434aea4SMasatake YAMATO compoundPosForOffset);
387c434aea4SMasatake YAMATO if (p == NULL)
388c434aea4SMasatake YAMATO return 1; /* TODO: 0? */
389c434aea4SMasatake YAMATO else
390c434aea4SMasatake YAMATO return 1 + (p - File.lineFposMap.pos);
391c434aea4SMasatake YAMATO }
392c434aea4SMasatake YAMATO
39301ceddeaSMasatake YAMATO /*
394d316cd59SMasatake YAMATO * Input file access functions
395d4c6f1e6SMasatake YAMATO */
396d4c6f1e6SMasatake YAMATO
setOwnerDirectoryOfInputFile(const char * const fileName)397fd12e3afSMasatake YAMATO static void setOwnerDirectoryOfInputFile (const char *const fileName)
398d4c6f1e6SMasatake YAMATO {
399d4c6f1e6SMasatake YAMATO const char *const head = fileName;
400d4c6f1e6SMasatake YAMATO const char *const tail = baseFilename (head);
401d4c6f1e6SMasatake YAMATO
402d4c6f1e6SMasatake YAMATO if (File.path != NULL)
403d4c6f1e6SMasatake YAMATO vStringDelete (File.path);
404d4c6f1e6SMasatake YAMATO if (tail == head)
405d4c6f1e6SMasatake YAMATO File.path = NULL;
406d4c6f1e6SMasatake YAMATO else
407d4c6f1e6SMasatake YAMATO {
408d4c6f1e6SMasatake YAMATO const size_t length = tail - head - 1;
409d4c6f1e6SMasatake YAMATO File.path = vStringNew ();
410d4c6f1e6SMasatake YAMATO vStringNCopyS (File.path, fileName, length);
411d4c6f1e6SMasatake YAMATO }
412d4c6f1e6SMasatake YAMATO }
413d4c6f1e6SMasatake YAMATO
setInputFileParametersCommon(inputFileInfo * finfo,vString * const fileName,const langType language,stringList * holder)414adff34b1SMasatake YAMATO static void setInputFileParametersCommon (inputFileInfo *finfo, vString *const fileName,
415a8778562SMasatake YAMATO const langType language,
416a8778562SMasatake YAMATO stringList *holder)
417d4c6f1e6SMasatake YAMATO {
418fd12e3afSMasatake YAMATO if (finfo->name != NULL)
419fd12e3afSMasatake YAMATO vStringDelete (finfo->name);
420fd12e3afSMasatake YAMATO finfo->name = fileName;
421d4c6f1e6SMasatake YAMATO
422fd12e3afSMasatake YAMATO if (finfo->tagPath != NULL)
423adff34b1SMasatake YAMATO {
424adff34b1SMasatake YAMATO if (holder)
425adff34b1SMasatake YAMATO stringListAdd (holder, finfo->tagPath);
426adff34b1SMasatake YAMATO else
42754d7e089SMasatake YAMATO vStringDelete (finfo->tagPath);
428adff34b1SMasatake YAMATO }
42978478818SMasatake YAMATO
43078478818SMasatake YAMATO if (0)
43178478818SMasatake YAMATO ;
43278478818SMasatake YAMATO else if ( Option.tagRelative == TREL_ALWAYS )
43378478818SMasatake YAMATO finfo->tagPath =
43478478818SMasatake YAMATO vStringNewOwn (relativeFilename (vStringValue (fileName),
43578478818SMasatake YAMATO getTagFileDirectory ()));
43678478818SMasatake YAMATO else if ( Option.tagRelative == TREL_NEVER )
43778478818SMasatake YAMATO finfo->tagPath =
43878478818SMasatake YAMATO vStringNewOwn (absoluteFilename (vStringValue (fileName)));
43978478818SMasatake YAMATO else if ( Option.tagRelative == TREL_NO || isAbsolutePath (vStringValue (fileName)) )
44054d7e089SMasatake YAMATO finfo->tagPath = vStringNewCopy (fileName);
441d4c6f1e6SMasatake YAMATO else
442fd12e3afSMasatake YAMATO finfo->tagPath =
443c1f939f9SMasatake YAMATO vStringNewOwn (relativeFilename (vStringValue (fileName),
444c1f939f9SMasatake YAMATO getTagFileDirectory ()));
445d4c6f1e6SMasatake YAMATO
446fd12e3afSMasatake YAMATO finfo->isHeader = isIncludeFile (vStringValue (fileName));
447a8778562SMasatake YAMATO }
448a8778562SMasatake YAMATO
resetLangOnStack(inputLangInfo * langInfo,langType lang)449a8778562SMasatake YAMATO static void resetLangOnStack (inputLangInfo *langInfo, langType lang)
450a8778562SMasatake YAMATO {
45179758c23SMasatake YAMATO Assert (langInfo->stack.count > 0);
45279758c23SMasatake YAMATO langStackClear (& (langInfo->stack));
453a8778562SMasatake YAMATO langStackPush (& (langInfo->stack), lang);
454a8778562SMasatake YAMATO }
455a8778562SMasatake YAMATO
baseLangOnStack(inputLangInfo * langInfo)456657cbb19SMasatake YAMATO extern langType baseLangOnStack (inputLangInfo *langInfo)
457657cbb19SMasatake YAMATO {
458657cbb19SMasatake YAMATO Assert (langInfo->stack.count > 0);
459657cbb19SMasatake YAMATO return langStackBotom (& (langInfo->stack));
460657cbb19SMasatake YAMATO }
461657cbb19SMasatake YAMATO
pushLangOnStack(inputLangInfo * langInfo,langType lang)462a8778562SMasatake YAMATO static void pushLangOnStack (inputLangInfo *langInfo, langType lang)
463a8778562SMasatake YAMATO {
464a8778562SMasatake YAMATO langStackPush (& langInfo->stack, lang);
465a8778562SMasatake YAMATO }
466a8778562SMasatake YAMATO
popLangOnStack(inputLangInfo * langInfo)467a8778562SMasatake YAMATO static langType popLangOnStack (inputLangInfo *langInfo)
468a8778562SMasatake YAMATO {
469a8778562SMasatake YAMATO return langStackPop (& langInfo->stack);
470a8778562SMasatake YAMATO }
471a8778562SMasatake YAMATO
clearLangOnStack(inputLangInfo * langInfo)47279758c23SMasatake YAMATO static void clearLangOnStack (inputLangInfo *langInfo)
47379758c23SMasatake YAMATO {
4742b62e072SThomas Braun langStackClear (& langInfo->stack);
47579758c23SMasatake YAMATO }
47679758c23SMasatake YAMATO
setInputFileParameters(vString * const fileName,const langType language)477fd12e3afSMasatake YAMATO static void setInputFileParameters (vString *const fileName, const langType language)
478fd12e3afSMasatake YAMATO {
479a8778562SMasatake YAMATO setInputFileParametersCommon (&File.input, fileName,
480ebc3af7dSMasatake YAMATO language, NULL);
481ebc3af7dSMasatake YAMATO pushLangOnStack(&inputLang, language);
482fd12e3afSMasatake YAMATO }
483fd12e3afSMasatake YAMATO
setSourceFileParameters(vString * const fileName,const langType language)484fd12e3afSMasatake YAMATO static void setSourceFileParameters (vString *const fileName, const langType language)
485fd12e3afSMasatake YAMATO {
486a8778562SMasatake YAMATO setInputFileParametersCommon (&File.source, fileName,
487ebc3af7dSMasatake YAMATO language, File.sourceTagPathHolder);
4887262d5eaSMasatake YAMATO sourceLang = language;
489d4c6f1e6SMasatake YAMATO }
490d4c6f1e6SMasatake YAMATO
setSourceFileName(vString * const fileName)491ce990805SThomas Braun static bool setSourceFileName (vString *const fileName)
492d4c6f1e6SMasatake YAMATO {
4935329ae51SMasatake YAMATO const langType language = getLanguageForFilenameAndContents (vStringValue (fileName));
494ce990805SThomas Braun bool result = false;
495d4c6f1e6SMasatake YAMATO if (language != LANG_IGNORE)
496d4c6f1e6SMasatake YAMATO {
497d4c6f1e6SMasatake YAMATO vString *pathName;
498d4c6f1e6SMasatake YAMATO if (isAbsolutePath (vStringValue (fileName)) || File.path == NULL)
499d4c6f1e6SMasatake YAMATO pathName = vStringNewCopy (fileName);
500d4c6f1e6SMasatake YAMATO else
501d4c6f1e6SMasatake YAMATO {
502d4c6f1e6SMasatake YAMATO char *tmp = combinePathAndFile (
503d4c6f1e6SMasatake YAMATO vStringValue (File.path), vStringValue (fileName));
504d4c6f1e6SMasatake YAMATO pathName = vStringNewOwn (tmp);
505d4c6f1e6SMasatake YAMATO }
506d4c6f1e6SMasatake YAMATO setSourceFileParameters (pathName, language);
507ce990805SThomas Braun result = true;
508d4c6f1e6SMasatake YAMATO }
509d4c6f1e6SMasatake YAMATO return result;
510d4c6f1e6SMasatake YAMATO }
511d4c6f1e6SMasatake YAMATO
512d4c6f1e6SMasatake YAMATO /*
513d4c6f1e6SMasatake YAMATO * Line directive parsing
514d4c6f1e6SMasatake YAMATO */
515d4c6f1e6SMasatake YAMATO
skipWhite(char ** str)5165388d8eaSJiří Techet static void skipWhite (char **str)
517d4c6f1e6SMasatake YAMATO {
5185388d8eaSJiří Techet while (**str == ' ' || **str == '\t')
5195388d8eaSJiří Techet (*str)++;
520d4c6f1e6SMasatake YAMATO }
521d4c6f1e6SMasatake YAMATO
readLineNumber(char ** str)5225388d8eaSJiří Techet static unsigned long readLineNumber (char **str)
523d4c6f1e6SMasatake YAMATO {
5245388d8eaSJiří Techet char *s;
525d4c6f1e6SMasatake YAMATO unsigned long lNum = 0;
5265388d8eaSJiří Techet
5275388d8eaSJiří Techet skipWhite (str);
5285388d8eaSJiří Techet s = *str;
5295388d8eaSJiří Techet while (*s != '\0' && isdigit (*s))
530d4c6f1e6SMasatake YAMATO {
5315388d8eaSJiří Techet lNum = (lNum * 10) + (*s - '0');
5325388d8eaSJiří Techet s++;
533d4c6f1e6SMasatake YAMATO }
5345388d8eaSJiří Techet if (*s != ' ' && *s != '\t')
535d4c6f1e6SMasatake YAMATO lNum = 0;
5365388d8eaSJiří Techet *str = s;
537d4c6f1e6SMasatake YAMATO
538d4c6f1e6SMasatake YAMATO return lNum;
539d4c6f1e6SMasatake YAMATO }
540d4c6f1e6SMasatake YAMATO
541d4c6f1e6SMasatake YAMATO /* While ANSI only permits lines of the form:
542d4c6f1e6SMasatake YAMATO * # line n "filename"
543d4c6f1e6SMasatake YAMATO * Earlier compilers generated lines of the form
544d4c6f1e6SMasatake YAMATO * # n filename
545d4c6f1e6SMasatake YAMATO * GNU C will output lines of the form:
546d4c6f1e6SMasatake YAMATO * # n "filename"
547d4c6f1e6SMasatake YAMATO * So we need to be fairly flexible in what we accept.
548d4c6f1e6SMasatake YAMATO */
readFileName(char * s)5495388d8eaSJiří Techet static vString *readFileName (char *s)
550d4c6f1e6SMasatake YAMATO {
551d4c6f1e6SMasatake YAMATO vString *const fileName = vStringNew ();
552ce990805SThomas Braun bool quoteDelimited = false;
553d4c6f1e6SMasatake YAMATO
5545388d8eaSJiří Techet skipWhite (&s);
5555388d8eaSJiří Techet if (*s == '"')
556d4c6f1e6SMasatake YAMATO {
5575388d8eaSJiří Techet s++; /* skip double-quote */
558ce990805SThomas Braun quoteDelimited = true;
559d4c6f1e6SMasatake YAMATO }
5605388d8eaSJiří Techet while (*s != '\0' && *s != '\n' &&
5615388d8eaSJiří Techet (quoteDelimited ? (*s != '"') : (*s != ' ' && *s != '\t')))
562d4c6f1e6SMasatake YAMATO {
5635388d8eaSJiří Techet vStringPut (fileName, *s);
5645388d8eaSJiří Techet s++;
565d4c6f1e6SMasatake YAMATO }
566d4c6f1e6SMasatake YAMATO vStringPut (fileName, '\0');
567d4c6f1e6SMasatake YAMATO
568d4c6f1e6SMasatake YAMATO return fileName;
569d4c6f1e6SMasatake YAMATO }
570d4c6f1e6SMasatake YAMATO
parseLineDirective(char * s)5715388d8eaSJiří Techet static bool parseLineDirective (char *s)
572d4c6f1e6SMasatake YAMATO {
573ce990805SThomas Braun bool result = false;
5745388d8eaSJiří Techet
5755388d8eaSJiří Techet skipWhite (&s);
576d4c6f1e6SMasatake YAMATO DebugStatement ( const char* lineStr = ""; )
577d4c6f1e6SMasatake YAMATO
5785388d8eaSJiří Techet if (isdigit (*s))
579ce990805SThomas Braun result = true;
5805388d8eaSJiří Techet else if (strncmp (s, "line", 4) == 0)
581d4c6f1e6SMasatake YAMATO {
5825388d8eaSJiří Techet s += 4;
5835388d8eaSJiří Techet if (*s == ' ' || *s == '\t')
584d4c6f1e6SMasatake YAMATO {
585d4c6f1e6SMasatake YAMATO DebugStatement ( lineStr = "line"; )
586ce990805SThomas Braun result = true;
587d4c6f1e6SMasatake YAMATO }
588d4c6f1e6SMasatake YAMATO }
589d4c6f1e6SMasatake YAMATO if (result)
590d4c6f1e6SMasatake YAMATO {
5915388d8eaSJiří Techet const unsigned long lNum = readLineNumber (&s);
592d4c6f1e6SMasatake YAMATO if (lNum == 0)
593ce990805SThomas Braun result = false;
594d4c6f1e6SMasatake YAMATO else
595d4c6f1e6SMasatake YAMATO {
5965388d8eaSJiří Techet vString *const fileName = readFileName (s);
597d4c6f1e6SMasatake YAMATO if (vStringLength (fileName) == 0)
598d4c6f1e6SMasatake YAMATO {
599d4c6f1e6SMasatake YAMATO File.source.lineNumber = lNum - 1; /* applies to NEXT line */
600d4c6f1e6SMasatake YAMATO DebugStatement ( debugPrintf (DEBUG_RAW, "#%s %ld", lineStr, lNum); )
601d4c6f1e6SMasatake YAMATO }
602d4c6f1e6SMasatake YAMATO else if (setSourceFileName (fileName))
603d4c6f1e6SMasatake YAMATO {
604d4c6f1e6SMasatake YAMATO File.source.lineNumber = lNum - 1; /* applies to NEXT line */
605d4c6f1e6SMasatake YAMATO DebugStatement ( debugPrintf (DEBUG_RAW, "#%s %ld \"%s\"",
606d4c6f1e6SMasatake YAMATO lineStr, lNum, vStringValue (fileName)); )
607d4c6f1e6SMasatake YAMATO }
608d4c6f1e6SMasatake YAMATO
60997e10dd0SMasatake YAMATO if (vStringLength (fileName) > 0 &&
610d4c6f1e6SMasatake YAMATO lNum == 1)
61197e10dd0SMasatake YAMATO makeFileTag (vStringValue (fileName));
612d4c6f1e6SMasatake YAMATO vStringDelete (fileName);
613ce990805SThomas Braun result = true;
614d4c6f1e6SMasatake YAMATO }
615d4c6f1e6SMasatake YAMATO }
616d4c6f1e6SMasatake YAMATO return result;
617d4c6f1e6SMasatake YAMATO }
618d4c6f1e6SMasatake YAMATO
619d4c6f1e6SMasatake YAMATO /*
620d316cd59SMasatake YAMATO * Input file I/O operations
621d4c6f1e6SMasatake YAMATO */
6226b917ee2SMasatake YAMATO #ifdef DEBUG
6236b917ee2SMasatake YAMATO #define MAX_IN_MEMORY_FILE_SIZE 0
6246b917ee2SMasatake YAMATO #else
6259d5edacaSJiří Techet #define MAX_IN_MEMORY_FILE_SIZE (1024*1024)
6266b917ee2SMasatake YAMATO #endif
6279d5edacaSJiří Techet
getMioFull(const char * const fileName,const char * const openMode,bool memStreamRequired,time_t * mtime)628c314f261SMasatake YAMATO static MIO *getMioFull (const char *const fileName, const char *const openMode,
629c314f261SMasatake YAMATO bool memStreamRequired, time_t *mtime)
6309d5edacaSJiří Techet {
631c5e3c546SJiří Techet FILE *src;
632c5e3c546SJiří Techet fileStatus *st;
633c5e3c546SJiří Techet unsigned long size;
634c5e3c546SJiří Techet unsigned char *data;
6359d5edacaSJiří Techet
636c5e3c546SJiří Techet st = eStat (fileName);
637c5e3c546SJiří Techet size = st->size;
638c314f261SMasatake YAMATO if (mtime)
639c314f261SMasatake YAMATO *mtime = st->mtime;
640c5e3c546SJiří Techet eStatFree (st);
64131cb4225SMasatake YAMATO if ((!memStreamRequired)
64231cb4225SMasatake YAMATO && (size > MAX_IN_MEMORY_FILE_SIZE || size == 0))
643c5e3c546SJiří Techet return mio_new_file (fileName, openMode);
644c5e3c546SJiří Techet
645c5e3c546SJiří Techet src = fopen (fileName, openMode);
646231e40e7SMasatake YAMATO if (!src)
647231e40e7SMasatake YAMATO return NULL;
648231e40e7SMasatake YAMATO
649231e40e7SMasatake YAMATO data = eMalloc (size);
650c5e3c546SJiří Techet if (fread (data, 1, size, src) != size)
6519d5edacaSJiří Techet {
652c5e3c546SJiří Techet eFree (data);
653c5e3c546SJiří Techet fclose (src);
65431cb4225SMasatake YAMATO if (memStreamRequired)
65531cb4225SMasatake YAMATO return NULL;
65631cb4225SMasatake YAMATO else
657c5e3c546SJiří Techet return mio_new_file (fileName, openMode);
6589d5edacaSJiří Techet }
659c5e3c546SJiří Techet fclose (src);
660a055e2beSMasatake YAMATO return mio_new_memory (data, size, eRealloc, eFreeNoNullCheck);
6619d5edacaSJiří Techet }
6629d5edacaSJiří Techet
getMio(const char * const fileName,const char * const openMode,bool memStreamRequired)663c314f261SMasatake YAMATO extern MIO *getMio (const char *const fileName, const char *const openMode,
664c314f261SMasatake YAMATO bool memStreamRequired)
665c314f261SMasatake YAMATO {
666c314f261SMasatake YAMATO return getMioFull (fileName, openMode, memStreamRequired, NULL);
667c314f261SMasatake YAMATO }
668c314f261SMasatake YAMATO
6697d6be565SMasatake YAMATO /* Return true if utf8 BOM is found */
checkUTF8BOM(MIO * mio,bool skipIfFound)6707d6be565SMasatake YAMATO static bool checkUTF8BOM (MIO *mio, bool skipIfFound)
6717d6be565SMasatake YAMATO {
6727d6be565SMasatake YAMATO bool r = false;
6737d6be565SMasatake YAMATO if ((0xEF == mio_getc (mio))
6747d6be565SMasatake YAMATO && (0xBB == mio_getc (mio))
6757d6be565SMasatake YAMATO && (0xBF == mio_getc (mio)))
6767d6be565SMasatake YAMATO r = true;
6777d6be565SMasatake YAMATO
6787d6be565SMasatake YAMATO if (! (r && skipIfFound))
6797d6be565SMasatake YAMATO mio_rewind (mio);
6807d6be565SMasatake YAMATO return r;
6817d6be565SMasatake YAMATO }
6827d6be565SMasatake YAMATO
rewindInputFile(inputFile * f)6837d6be565SMasatake YAMATO static void rewindInputFile (inputFile *f)
6847d6be565SMasatake YAMATO {
6857d6be565SMasatake YAMATO mio_rewind (f->mio);
6867d6be565SMasatake YAMATO if (f->bomFound)
6877d6be565SMasatake YAMATO {
688ee2b7a33SMasatake YAMATO int c CTAGS_ATTR_UNUSED;
6897d6be565SMasatake YAMATO
6907d6be565SMasatake YAMATO c = mio_getc (f->mio);
6917d6be565SMasatake YAMATO Assert (c == 0xEF);
6927d6be565SMasatake YAMATO c = mio_getc (f->mio);
6937d6be565SMasatake YAMATO Assert (c == 0xBB);
6947d6be565SMasatake YAMATO c = mio_getc (f->mio);
6957d6be565SMasatake YAMATO Assert (c == 0xBF);
6967d6be565SMasatake YAMATO }
6977d6be565SMasatake YAMATO }
6987d6be565SMasatake YAMATO
699d316cd59SMasatake YAMATO /* This function opens an input file, and resets the line counter. If it
700203c6955SJiří Techet * fails, it will display an error message and leave the File.mio set to NULL.
701d4c6f1e6SMasatake YAMATO */
openInputFile(const char * const fileName,const langType language,MIO * mio,time_t mtime)702ce990805SThomas Braun extern bool openInputFile (const char *const fileName, const langType language,
703ce1f2415SMasatake YAMATO MIO *mio, time_t mtime)
704d4c6f1e6SMasatake YAMATO {
705d4c6f1e6SMasatake YAMATO const char *const openMode = "rb";
706ce990805SThomas Braun bool opened = false;
707ce990805SThomas Braun bool memStreamRequired;
708d4c6f1e6SMasatake YAMATO
709d4c6f1e6SMasatake YAMATO /* If another file was already open, then close it.
710d4c6f1e6SMasatake YAMATO */
711203c6955SJiří Techet if (File.mio != NULL)
712d4c6f1e6SMasatake YAMATO {
713b978efd6SMasatake YAMATO mio_unref (File.mio); /* close any open input file */
714203c6955SJiří Techet File.mio = NULL;
715d4c6f1e6SMasatake YAMATO }
716d4c6f1e6SMasatake YAMATO
71746204f78SBen Wiederhake /* File position is used as key for checking the availability of
71855a8e4c6SMasatake YAMATO pattern cache in entry.h. If an input file is changed, the
71955a8e4c6SMasatake YAMATO key is meaningless. So notifying the changing here. */
720800267f1SJonathon Reinhart invalidatePatternCache();
721adff34b1SMasatake YAMATO
722adff34b1SMasatake YAMATO if (File.sourceTagPathHolder == NULL)
72356065e52SMasatake YAMATO {
724adff34b1SMasatake YAMATO File.sourceTagPathHolder = stringListNew ();
72533a6fdb8SMasatake YAMATO DEFAULT_TRASH_BOX(File.sourceTagPathHolder, stringListDelete);
72656065e52SMasatake YAMATO }
727adff34b1SMasatake YAMATO stringListClear (File.sourceTagPathHolder);
728adff34b1SMasatake YAMATO
72931cb4225SMasatake YAMATO memStreamRequired = doesParserRequireMemoryStream (language);
730e9d4c72cSMasatake YAMATO
731e9d4c72cSMasatake YAMATO if (mio)
732e9d4c72cSMasatake YAMATO {
733e9d4c72cSMasatake YAMATO size_t tmp;
734e9d4c72cSMasatake YAMATO if (memStreamRequired && (!mio_memory_get_data (mio, &tmp)))
735e9d4c72cSMasatake YAMATO mio = NULL;
736e9d4c72cSMasatake YAMATO else
737e9d4c72cSMasatake YAMATO mio_rewind (mio);
738e9d4c72cSMasatake YAMATO }
739e9d4c72cSMasatake YAMATO
740c314f261SMasatake YAMATO File.mio = mio? mio_ref (mio): getMioFull (fileName, openMode, memStreamRequired, &File.mtime);
741e9d4c72cSMasatake YAMATO
742203c6955SJiří Techet if (File.mio == NULL)
743d4c6f1e6SMasatake YAMATO error (WARNING | PERROR, "cannot open \"%s\"", fileName);
744d4c6f1e6SMasatake YAMATO else
745d4c6f1e6SMasatake YAMATO {
746ce990805SThomas Braun opened = true;
747d4c6f1e6SMasatake YAMATO
748c314f261SMasatake YAMATO if (File.mio == mio)
749ce1f2415SMasatake YAMATO File.mtime = mtime;
7507d6be565SMasatake YAMATO
7517d6be565SMasatake YAMATO File.bomFound = checkUTF8BOM (File.mio, true);
7527d6be565SMasatake YAMATO
753fd12e3afSMasatake YAMATO setOwnerDirectoryOfInputFile (fileName);
754c434aea4SMasatake YAMATO mio_getpos (File.mio, &StartOfLine.pos);
755c434aea4SMasatake YAMATO mio_getpos (File.mio, &File.filePosition.pos);
756c434aea4SMasatake YAMATO File.filePosition.offset = StartOfLine.offset = mio_tell (File.mio);
757d4c6f1e6SMasatake YAMATO File.currentLine = NULL;
758d4c6f1e6SMasatake YAMATO
759314a657dSMasatake YAMATO File.line = vStringNewOrClear (File.line);
760539a03ffSMasatake YAMATO File.ungetchIdx = 0;
761d4c6f1e6SMasatake YAMATO
762fd12e3afSMasatake YAMATO setInputFileParameters (vStringNewInit (fileName), language);
763aed2b6adSMasatake YAMATO File.input.lineNumberOrigin = 0L;
764aed2b6adSMasatake YAMATO File.input.lineNumber = File.input.lineNumberOrigin;
765d4c6f1e6SMasatake YAMATO setSourceFileParameters (vStringNewInit (fileName), language);
766aed2b6adSMasatake YAMATO File.source.lineNumberOrigin = 0L;
767aed2b6adSMasatake YAMATO File.source.lineNumber = File.source.lineNumberOrigin;
76801ceddeaSMasatake YAMATO allocLineFposMap (&File.lineFposMap);
769d4c6f1e6SMasatake YAMATO
7702fa69c1bSMasatake YAMATO File.thinDepth = 0;
7717d6be565SMasatake YAMATO verbose ("OPENING%s %s as %s language %sfile [%s%s]\n",
7727d6be565SMasatake YAMATO (File.bomFound? "(skipping utf-8 bom)": ""),
7737d6be565SMasatake YAMATO fileName,
774d4c6f1e6SMasatake YAMATO getLanguageName (language),
77587803844SMasatake YAMATO File.input.isHeader ? "include " : "",
77687803844SMasatake YAMATO mio? "reused": "new",
77787803844SMasatake YAMATO memStreamRequired? ",required": "");
778d4c6f1e6SMasatake YAMATO }
779d4c6f1e6SMasatake YAMATO return opened;
780d4c6f1e6SMasatake YAMATO }
781d4c6f1e6SMasatake YAMATO
getInputFileMtime(void)782c314f261SMasatake YAMATO extern time_t getInputFileMtime (void)
783c314f261SMasatake YAMATO {
784c314f261SMasatake YAMATO return File.mtime;
785c314f261SMasatake YAMATO }
786c314f261SMasatake YAMATO
resetInputFile(const langType language)787bc1a5e1bSMasatake YAMATO extern void resetInputFile (const langType language)
788bc1a5e1bSMasatake YAMATO {
789203c6955SJiří Techet Assert (File.mio);
790bc1a5e1bSMasatake YAMATO
7917d6be565SMasatake YAMATO rewindInputFile (&File);
792c434aea4SMasatake YAMATO mio_getpos (File.mio, &StartOfLine.pos);
793c434aea4SMasatake YAMATO mio_getpos (File.mio, &File.filePosition.pos);
794c434aea4SMasatake YAMATO File.filePosition.offset = StartOfLine.offset = mio_tell (File.mio);
795bc1a5e1bSMasatake YAMATO File.currentLine = NULL;
796bc1a5e1bSMasatake YAMATO
797314a657dSMasatake YAMATO Assert (File.line);
798bc1a5e1bSMasatake YAMATO vStringClear (File.line);
799539a03ffSMasatake YAMATO File.ungetchIdx = 0;
800539a03ffSMasatake YAMATO
801587a8e25SMasatake YAMATO if (hasLanguageMultilineRegexPatterns (language))
802587a8e25SMasatake YAMATO File.allLines = vStringNew ();
803bc1a5e1bSMasatake YAMATO
804ebc3af7dSMasatake YAMATO resetLangOnStack (& inputLang, language);
805aed2b6adSMasatake YAMATO File.input.lineNumber = File.input.lineNumberOrigin;
8067262d5eaSMasatake YAMATO sourceLang = language;
807aed2b6adSMasatake YAMATO File.source.lineNumber = File.source.lineNumberOrigin;
808bc1a5e1bSMasatake YAMATO }
809bc1a5e1bSMasatake YAMATO
closeInputFile(void)81049bb7f66SMasatake YAMATO extern void closeInputFile (void)
811d4c6f1e6SMasatake YAMATO {
812203c6955SJiří Techet if (File.mio != NULL)
813d4c6f1e6SMasatake YAMATO {
814ebc3af7dSMasatake YAMATO clearLangOnStack (& inputLang);
815a8778562SMasatake YAMATO
816d4c6f1e6SMasatake YAMATO /* The line count of the file is 1 too big, since it is one-based
817d4c6f1e6SMasatake YAMATO * and is incremented upon each newline.
818d4c6f1e6SMasatake YAMATO */
819d4c6f1e6SMasatake YAMATO if (Option.printTotals)
820d4c6f1e6SMasatake YAMATO {
821a5b1fa4aSMasatake YAMATO fileStatus *status = eStat (vStringValue (File.input.name));
822a5b1fa4aSMasatake YAMATO addTotals (0, File.input.lineNumber - 1L, status->size);
823d4c6f1e6SMasatake YAMATO }
824b978efd6SMasatake YAMATO mio_unref (File.mio);
825203c6955SJiří Techet File.mio = NULL;
82601ceddeaSMasatake YAMATO freeLineFposMap (&File.lineFposMap);
827d4c6f1e6SMasatake YAMATO }
828d4c6f1e6SMasatake YAMATO }
829d4c6f1e6SMasatake YAMATO
getInputFileUserData(void)83061f7a0ebSMasatake YAMATO extern void *getInputFileUserData(void)
83161f7a0ebSMasatake YAMATO {
832203c6955SJiří Techet return mio_get_user_data (File.mio);
83361f7a0ebSMasatake YAMATO }
83461f7a0ebSMasatake YAMATO
835d316cd59SMasatake YAMATO /* Action to take for each encountered input newline.
836d4c6f1e6SMasatake YAMATO */
fileNewline(bool crAdjustment)8373b035e33SMasatake YAMATO static void fileNewline (bool crAdjustment)
838d4c6f1e6SMasatake YAMATO {
839d4c6f1e6SMasatake YAMATO File.filePosition = StartOfLine;
8404fa68e36SMasatake YAMATO
841203c6955SJiří Techet if (BackupFile.mio == NULL)
8423b035e33SMasatake YAMATO appendLineFposMap (&File.lineFposMap, &File.filePosition,
8433b035e33SMasatake YAMATO crAdjustment);
8444fa68e36SMasatake YAMATO
845a5b1fa4aSMasatake YAMATO File.input.lineNumber++;
846d4c6f1e6SMasatake YAMATO File.source.lineNumber++;
847a5b1fa4aSMasatake YAMATO DebugStatement ( if (Option.breakLine == File.input.lineNumber) lineBreak (); )
848a5b1fa4aSMasatake YAMATO DebugStatement ( debugPrintf (DEBUG_RAW, "%6ld: ", File.input.lineNumber); )
849d4c6f1e6SMasatake YAMATO }
850d4c6f1e6SMasatake YAMATO
ungetcToInputFile(int c)85161f14fa5SMasatake YAMATO extern void ungetcToInputFile (int c)
852d4c6f1e6SMasatake YAMATO {
853158a3387SMasatake YAMATO const size_t len = ARRAY_SIZE (File.ungetchBuf);
854956af055SColomban Wendling
855956af055SColomban Wendling Assert (File.ungetchIdx < len);
856956af055SColomban Wendling /* we cannot rely on the assertion that might be disabled in non-debug mode */
857956af055SColomban Wendling if (File.ungetchIdx < len)
858956af055SColomban Wendling File.ungetchBuf[File.ungetchIdx++] = c;
859d4c6f1e6SMasatake YAMATO }
860d4c6f1e6SMasatake YAMATO
861c447d2e2SMasatake YAMATO typedef enum eEolType {
862c447d2e2SMasatake YAMATO eol_eof = 0,
863c447d2e2SMasatake YAMATO eol_nl,
864c447d2e2SMasatake YAMATO eol_cr_nl,
865c447d2e2SMasatake YAMATO } eolType;
866c447d2e2SMasatake YAMATO
readLine(vString * const vLine,MIO * const mio)867c447d2e2SMasatake YAMATO static eolType readLine (vString *const vLine, MIO *const mio)
868d4c6f1e6SMasatake YAMATO {
8695388d8eaSJiří Techet char *str;
8705388d8eaSJiří Techet size_t size;
871c447d2e2SMasatake YAMATO eolType r = eol_nl;
8725388d8eaSJiří Techet
873454b08edSJiří Techet vStringClear (vLine);
874454b08edSJiří Techet
875454b08edSJiří Techet str = vStringValue (vLine);
876454b08edSJiří Techet size = vStringSize (vLine);
8775388d8eaSJiří Techet
8785388d8eaSJiří Techet for (;;)
879d4c6f1e6SMasatake YAMATO {
8805388d8eaSJiří Techet bool newLine;
8815388d8eaSJiří Techet bool eof;
8825388d8eaSJiří Techet
883454b08edSJiří Techet if (mio_gets (mio, str, size) == NULL)
884454b08edSJiří Techet {
885454b08edSJiří Techet if (!mio_eof (mio))
886454b08edSJiří Techet error (FATAL | PERROR, "Failure on attempt to read file");
887454b08edSJiří Techet }
888454b08edSJiří Techet vStringSetLength (vLine);
889454b08edSJiří Techet newLine = vStringLength (vLine) > 0 && vStringLast (vLine) == '\n';
890454b08edSJiří Techet eof = mio_eof (mio);
891c447d2e2SMasatake YAMATO if (eof)
892c447d2e2SMasatake YAMATO r = eol_eof;
8938fac6ad5SJiří Techet
8948fac6ad5SJiří Techet /* Turn line breaks into a canonical form. The three commonly
8958fac6ad5SJiří Techet * used forms of line breaks are: LF (UNIX/Mac OS X), CR-LF (MS-DOS) and
896759d281dSK.Takata * CR (Mac OS 9). As CR-only EOL isn't handled by gets() and Mac OS 9
8978fac6ad5SJiří Techet * is dead, we only handle CR-LF EOLs and convert them into LF. */
898454b08edSJiří Techet if (newLine && vStringLength (vLine) > 1 &&
8997171591bSMasatake YAMATO vStringChar (vLine, vStringLength (vLine) - 2) == '\r')
900d4c6f1e6SMasatake YAMATO {
9017171591bSMasatake YAMATO vStringChar (vLine, vStringLength (vLine) - 2) = '\n';
902454b08edSJiří Techet vStringChop (vLine);
903c447d2e2SMasatake YAMATO r = eol_cr_nl;
9045388d8eaSJiří Techet }
9055388d8eaSJiří Techet
9065388d8eaSJiří Techet if (newLine || eof)
9075388d8eaSJiří Techet break;
9085388d8eaSJiří Techet
909454b08edSJiří Techet vStringResize (vLine, vStringLength (vLine) * 2);
910454b08edSJiří Techet str = vStringValue (vLine) + vStringLength (vLine);
911454b08edSJiří Techet size = vStringSize (vLine) - vStringLength (vLine);
912454b08edSJiří Techet }
913c447d2e2SMasatake YAMATO return r;
9145388d8eaSJiří Techet }
9155388d8eaSJiří Techet
iFileGetLine(bool chop_newline)9165b7dabdaSMasatake YAMATO static vString *iFileGetLine (bool chop_newline)
917454b08edSJiří Techet {
918c447d2e2SMasatake YAMATO eolType eol;
919f98241cdSjannick0 langType lang = getInputLanguage();
920c447d2e2SMasatake YAMATO
921314a657dSMasatake YAMATO Assert (File.line);
922c447d2e2SMasatake YAMATO eol = readLine (File.line, File.mio);
923454b08edSJiří Techet
924454b08edSJiří Techet if (vStringLength (File.line) > 0)
9255388d8eaSJiří Techet {
9265388d8eaSJiří Techet /* Use StartOfLine from previous iFileGetLine() call */
9273b035e33SMasatake YAMATO fileNewline (eol == eol_cr_nl);
9285388d8eaSJiří Techet /* Store StartOfLine for the next iFileGetLine() call */
929c434aea4SMasatake YAMATO mio_getpos (File.mio, &StartOfLine.pos);
930c434aea4SMasatake YAMATO StartOfLine.offset = mio_tell (File.mio);
9315388d8eaSJiří Techet
9325388d8eaSJiří Techet if (Option.lineDirectives && vStringChar (File.line, 0) == '#')
9335388d8eaSJiří Techet parseLineDirective (vStringValue (File.line) + 1);
934a656c9bfSMasatake YAMATO
935587a8e25SMasatake YAMATO if (File.allLines)
9364e0c6ed6SMasatake YAMATO vStringCat (File.allLines, File.line);
9373b035e33SMasatake YAMATO
9385b7dabdaSMasatake YAMATO bool chopped = vStringStripNewline (File.line);
9395b7dabdaSMasatake YAMATO
9405b7dabdaSMasatake YAMATO matchLanguageRegex (lang, File.line);
9415b7dabdaSMasatake YAMATO
9425b7dabdaSMasatake YAMATO if (chopped && !chop_newline)
9435b7dabdaSMasatake YAMATO vStringPutNewlinAgainUnsafe (File.line);
9445b7dabdaSMasatake YAMATO
9455388d8eaSJiří Techet return File.line;
946d4c6f1e6SMasatake YAMATO }
9474e0c6ed6SMasatake YAMATO else
9484e0c6ed6SMasatake YAMATO {
949587a8e25SMasatake YAMATO if (File.allLines)
9504e0c6ed6SMasatake YAMATO {
951f98241cdSjannick0 matchLanguageMultilineRegex (lang, File.allLines);
952f98241cdSjannick0 matchLanguageMultitableRegex (lang, File.allLines);
953587a8e25SMasatake YAMATO
954587a8e25SMasatake YAMATO /* To limit the execution of multiline/multitable parser(s) only
955587a8e25SMasatake YAMATO ONCE, clear File.allLines field. */
9564e0c6ed6SMasatake YAMATO vStringDelete (File.allLines);
9574e0c6ed6SMasatake YAMATO File.allLines = NULL;
9584e0c6ed6SMasatake YAMATO }
9595388d8eaSJiří Techet return NULL;
960d4c6f1e6SMasatake YAMATO }
9614e0c6ed6SMasatake YAMATO }
962d4c6f1e6SMasatake YAMATO
9636c6421daSJiří Techet /* Do not mix use of readLineFromInputFile () and getcFromInputFile () for the same file.
964d4c6f1e6SMasatake YAMATO */
getcFromInputFile(void)965018bce0bSMasatake YAMATO extern int getcFromInputFile (void)
966d4c6f1e6SMasatake YAMATO {
967d4c6f1e6SMasatake YAMATO int c;
968d4c6f1e6SMasatake YAMATO
969d4c6f1e6SMasatake YAMATO /* If there is an ungotten character, then return it. Don't do any
970d4c6f1e6SMasatake YAMATO * other processing on it, though, because we already did that the
971018bce0bSMasatake YAMATO * first time it was read through getcFromInputFile ().
972d4c6f1e6SMasatake YAMATO */
973956af055SColomban Wendling if (File.ungetchIdx > 0)
974d4c6f1e6SMasatake YAMATO {
975956af055SColomban Wendling c = File.ungetchBuf[--File.ungetchIdx];
976d4c6f1e6SMasatake YAMATO return c; /* return here to avoid re-calling debugPutc () */
977d4c6f1e6SMasatake YAMATO }
978d4c6f1e6SMasatake YAMATO do
979d4c6f1e6SMasatake YAMATO {
980d4c6f1e6SMasatake YAMATO if (File.currentLine != NULL)
981d4c6f1e6SMasatake YAMATO {
982d4c6f1e6SMasatake YAMATO c = *File.currentLine++;
983d4c6f1e6SMasatake YAMATO if (c == '\0')
984d4c6f1e6SMasatake YAMATO File.currentLine = NULL;
985d4c6f1e6SMasatake YAMATO }
986d4c6f1e6SMasatake YAMATO else
987d4c6f1e6SMasatake YAMATO {
9885b7dabdaSMasatake YAMATO vString* const line = iFileGetLine (false);
989d4c6f1e6SMasatake YAMATO if (line != NULL)
990d4c6f1e6SMasatake YAMATO File.currentLine = (unsigned char*) vStringValue (line);
991d4c6f1e6SMasatake YAMATO if (File.currentLine == NULL)
992d4c6f1e6SMasatake YAMATO c = EOF;
993d4c6f1e6SMasatake YAMATO else
994d4c6f1e6SMasatake YAMATO c = '\0';
995d4c6f1e6SMasatake YAMATO }
996d4c6f1e6SMasatake YAMATO } while (c == '\0');
997d4c6f1e6SMasatake YAMATO DebugStatement ( debugPutc (DEBUG_READ, c); )
998d4c6f1e6SMasatake YAMATO return c;
999d4c6f1e6SMasatake YAMATO }
1000d4c6f1e6SMasatake YAMATO
10017b90026cSColomban Wendling /* returns the nth previous character (0 meaning current), or def if nth cannot
10027b90026cSColomban Wendling * be accessed. Note that this can't access previous line data. */
getNthPrevCFromInputFile(unsigned int nth,int def)10037b90026cSColomban Wendling extern int getNthPrevCFromInputFile (unsigned int nth, int def)
10047b90026cSColomban Wendling {
10057b90026cSColomban Wendling const unsigned char *base = (unsigned char *) vStringValue (File.line);
1006dfe9904aSColomban Wendling const unsigned int offset = File.ungetchIdx + 1 + nth;
10077b90026cSColomban Wendling
1008dfe9904aSColomban Wendling if (File.currentLine != NULL && File.currentLine >= base + offset)
1009dfe9904aSColomban Wendling return (int) *(File.currentLine - offset);
10107b90026cSColomban Wendling else
10117b90026cSColomban Wendling return def;
10127b90026cSColomban Wendling }
10137b90026cSColomban Wendling
skipToCharacterInInputFile(int c)10144fffc5afSMasatake YAMATO extern int skipToCharacterInInputFile (int c)
1015d4c6f1e6SMasatake YAMATO {
1016d4c6f1e6SMasatake YAMATO int d;
1017d4c6f1e6SMasatake YAMATO do
1018d4c6f1e6SMasatake YAMATO {
1019018bce0bSMasatake YAMATO d = getcFromInputFile ();
1020d4c6f1e6SMasatake YAMATO } while (d != EOF && d != c);
1021d4c6f1e6SMasatake YAMATO return d;
1022d4c6f1e6SMasatake YAMATO }
1023d4c6f1e6SMasatake YAMATO
skipToCharacterInInputFile2(int c0,int c1)102464a05963SMasatake YAMATO extern int skipToCharacterInInputFile2 (int c0, int c1)
102564a05963SMasatake YAMATO {
102664a05963SMasatake YAMATO int d;
102764a05963SMasatake YAMATO do
102864a05963SMasatake YAMATO {
102964a05963SMasatake YAMATO skipToCharacterInInputFile(c0);
103064a05963SMasatake YAMATO do
103164a05963SMasatake YAMATO d = getcFromInputFile ();
103264a05963SMasatake YAMATO while (d == c0 && d != c1);
103364a05963SMasatake YAMATO } while (d != EOF && d != c1);
103464a05963SMasatake YAMATO return d;
103564a05963SMasatake YAMATO }
103664a05963SMasatake YAMATO
10376c6421daSJiří Techet /* An alternative interface to getcFromInputFile (). Do not mix use of readLineFromInputFile()
1038018bce0bSMasatake YAMATO * and getcFromInputFile() for the same file. The returned string does not contain
1039d4c6f1e6SMasatake YAMATO * the terminating newline. A NULL return value means that all lines in the
1040d4c6f1e6SMasatake YAMATO * file have been read and we are at the end of file.
1041d4c6f1e6SMasatake YAMATO */
readLineFromInputFile(void)10421b312fe7SMasatake YAMATO extern const unsigned char *readLineFromInputFile (void)
1043d4c6f1e6SMasatake YAMATO {
10445b7dabdaSMasatake YAMATO vString* const line = iFileGetLine (true);
1045d4c6f1e6SMasatake YAMATO const unsigned char* result = NULL;
1046d4c6f1e6SMasatake YAMATO if (line != NULL)
1047d4c6f1e6SMasatake YAMATO {
1048d4c6f1e6SMasatake YAMATO result = (const unsigned char*) vStringValue (line);
1049d4c6f1e6SMasatake YAMATO DebugStatement ( debugPrintf (DEBUG_READ, "%s\n", result); )
1050d4c6f1e6SMasatake YAMATO }
1051d4c6f1e6SMasatake YAMATO return result;
1052d4c6f1e6SMasatake YAMATO }
1053d4c6f1e6SMasatake YAMATO
1054d4c6f1e6SMasatake YAMATO /*
1055918a642dSMasatake YAMATO * Raw file line reading with automatic buffer sizing
1056d4c6f1e6SMasatake YAMATO */
readLineRaw(vString * const vLine,MIO * const mio)1057203c6955SJiří Techet extern char *readLineRaw (vString *const vLine, MIO *const mio)
1058d4c6f1e6SMasatake YAMATO {
1059203c6955SJiří Techet if (mio == NULL) /* to free memory allocated to buffer */
1060d4c6f1e6SMasatake YAMATO error (FATAL, "NULL file pointer");
1061d4c6f1e6SMasatake YAMATO else
1062d4c6f1e6SMasatake YAMATO {
1063454b08edSJiří Techet readLine (vLine, mio);
10642acdcfa1SYasuhiro Matsumoto
10652acdcfa1SYasuhiro Matsumoto #ifdef HAVE_ICONV
10662acdcfa1SYasuhiro Matsumoto if (isConverting ())
10672acdcfa1SYasuhiro Matsumoto convertString (vLine);
10682acdcfa1SYasuhiro Matsumoto #endif
1069d4c6f1e6SMasatake YAMATO }
1070454b08edSJiří Techet return vStringLength (vLine) > 0 ? vStringValue (vLine) : NULL;
1071d4c6f1e6SMasatake YAMATO }
1072d4c6f1e6SMasatake YAMATO
1073d4c6f1e6SMasatake YAMATO /* Places into the line buffer the contents of the line referenced by
1074d4c6f1e6SMasatake YAMATO * "location".
1075d4c6f1e6SMasatake YAMATO */
readLineFromBypass(vString * const vLine,MIOPos location,long * const pSeekValue)107674e1a7cfSMasatake YAMATO extern char *readLineFromBypass (
1077509a47dbSJiří Techet vString *const vLine, MIOPos location, long *const pSeekValue)
1078d4c6f1e6SMasatake YAMATO {
1079509a47dbSJiří Techet MIOPos orignalPosition;
1080d4c6f1e6SMasatake YAMATO char *result;
1081d4c6f1e6SMasatake YAMATO
1082203c6955SJiří Techet mio_getpos (File.mio, &orignalPosition);
1083203c6955SJiří Techet mio_setpos (File.mio, &location);
108402d2d3b4SJiří Techet mio_clearerr (File.mio);
1085d4c6f1e6SMasatake YAMATO if (pSeekValue != NULL)
1086203c6955SJiří Techet *pSeekValue = mio_tell (File.mio);
1087203c6955SJiří Techet result = readLineRaw (vLine, File.mio);
1088203c6955SJiří Techet mio_setpos (File.mio, &orignalPosition);
10895dbd2e67SK.Takata /* If the file is empty, we can't get the line
109074e1a7cfSMasatake YAMATO for location 0. readLineFromBypass doesn't know
1091521e3c77SMasatake YAMATO what itself should do; just report it to the caller. */
1092d4c6f1e6SMasatake YAMATO return result;
1093d4c6f1e6SMasatake YAMATO }
1094d4c6f1e6SMasatake YAMATO
pushNarrowedInputStream(bool useMemoryStreamInput,unsigned long startLine,long startCharOffset,unsigned long endLine,long endCharOffset,unsigned long sourceLineOffset,int promise)10954d1713c7SMasatake YAMATO extern void pushNarrowedInputStream (
1096*9128cdbaSMasatake YAMATO bool useMemoryStreamInput,
1097ef722b09SMasatake YAMATO unsigned long startLine, long startCharOffset,
1098ef722b09SMasatake YAMATO unsigned long endLine, long endCharOffset,
109911e58e48SMasatake YAMATO unsigned long sourceLineOffset,
110011e58e48SMasatake YAMATO int promise)
11014fa68e36SMasatake YAMATO {
11024fa68e36SMasatake YAMATO long p, q;
11034fa68e36SMasatake YAMATO MIOPos original;
11044fa68e36SMasatake YAMATO MIOPos tmp;
11054fa68e36SMasatake YAMATO MIO *subio;
11064fa68e36SMasatake YAMATO
11072fa69c1bSMasatake YAMATO if (isThinStreamSpec (startLine, startCharOffset,
11082fa69c1bSMasatake YAMATO endLine, endCharOffset,
11092fa69c1bSMasatake YAMATO sourceLineOffset))
11102fa69c1bSMasatake YAMATO {
1111*9128cdbaSMasatake YAMATO if ((!useMemoryStreamInput
1112*9128cdbaSMasatake YAMATO || mio_memory_get_data (File.mio, NULL)))
1113*9128cdbaSMasatake YAMATO {
11142fa69c1bSMasatake YAMATO File.thinDepth++;
11152fa69c1bSMasatake YAMATO verbose ("push thin stream (%d)\n", File.thinDepth);
11162fa69c1bSMasatake YAMATO return;
11172fa69c1bSMasatake YAMATO }
1118*9128cdbaSMasatake YAMATO error(WARNING, "INTERNAL ERROR: though pushing thin MEMORY stream, "
1119*9128cdbaSMasatake YAMATO "underlying input stream is a FILE stream: %s@%s",
1120*9128cdbaSMasatake YAMATO vStringValue (File.input.name), vStringValue (File.input.tagPath));
1121*9128cdbaSMasatake YAMATO AssertNotReached ();
1122*9128cdbaSMasatake YAMATO }
11232fa69c1bSMasatake YAMATO Assert (File.thinDepth == 0);
11242fa69c1bSMasatake YAMATO
11254fa68e36SMasatake YAMATO original = getInputFilePosition ();
11264fa68e36SMasatake YAMATO
11274fa68e36SMasatake YAMATO tmp = getInputFilePositionForLine (startLine);
1128203c6955SJiří Techet mio_setpos (File.mio, &tmp);
1129203c6955SJiří Techet mio_seek (File.mio, startCharOffset, SEEK_CUR);
1130203c6955SJiří Techet p = mio_tell (File.mio);
11314fa68e36SMasatake YAMATO
11324fa68e36SMasatake YAMATO tmp = getInputFilePositionForLine (endLine);
1133203c6955SJiří Techet mio_setpos (File.mio, &tmp);
1134203c6955SJiří Techet mio_seek (File.mio, endCharOffset, SEEK_CUR);
1135203c6955SJiří Techet q = mio_tell (File.mio);
11364fa68e36SMasatake YAMATO
1137203c6955SJiří Techet mio_setpos (File.mio, &original);
11384fa68e36SMasatake YAMATO
1139f546df63SMasatake YAMATO invalidatePatternCache();
1140f546df63SMasatake YAMATO
114111e58e48SMasatake YAMATO size_t size = q - p;
114211e58e48SMasatake YAMATO subio = mio_new_mio (File.mio, p, size);
11431aa31b1aSMasatake YAMATO if (subio == NULL)
11441aa31b1aSMasatake YAMATO error (FATAL, "memory for mio may be exhausted");
11454fa68e36SMasatake YAMATO
114611e58e48SMasatake YAMATO runModifiers (promise,
114711e58e48SMasatake YAMATO startLine, startCharOffset,
114811e58e48SMasatake YAMATO endLine, endCharOffset,
114911e58e48SMasatake YAMATO mio_memory_get_data (subio, NULL),
115011e58e48SMasatake YAMATO size);
115111e58e48SMasatake YAMATO
11524fa68e36SMasatake YAMATO BackupFile = File;
11534fa68e36SMasatake YAMATO
1154203c6955SJiří Techet File.mio = subio;
11557d6be565SMasatake YAMATO File.bomFound = false;
1156a0c1e6d7SMasatake YAMATO File.nestedInputStreamInfo.startLine = startLine;
1157a0c1e6d7SMasatake YAMATO File.nestedInputStreamInfo.startCharOffset = startCharOffset;
1158a0c1e6d7SMasatake YAMATO File.nestedInputStreamInfo.endLine = endLine;
1159a0c1e6d7SMasatake YAMATO File.nestedInputStreamInfo.endCharOffset = endCharOffset;
11604fa68e36SMasatake YAMATO
11614fa68e36SMasatake YAMATO File.input.lineNumberOrigin = ((startLine == 0)? 0: startLine - 1);
11624fa68e36SMasatake YAMATO File.source.lineNumberOrigin = ((sourceLineOffset == 0)? 0: sourceLineOffset - 1);
11634fa68e36SMasatake YAMATO }
11644fa68e36SMasatake YAMATO
doesParserRunAsGuest(void)116513b5aee2SMasatake YAMATO extern bool doesParserRunAsGuest (void)
116613b5aee2SMasatake YAMATO {
116713b5aee2SMasatake YAMATO return !(File.nestedInputStreamInfo.startLine == 0
116813b5aee2SMasatake YAMATO && File.nestedInputStreamInfo.startCharOffset == 0
116913b5aee2SMasatake YAMATO && File.nestedInputStreamInfo.endLine == 0
117013b5aee2SMasatake YAMATO && File.nestedInputStreamInfo.endCharOffset == 0);
117113b5aee2SMasatake YAMATO }
117213b5aee2SMasatake YAMATO
getNestedInputBoundaryInfo(unsigned long lineNumber)1173a0c1e6d7SMasatake YAMATO extern unsigned int getNestedInputBoundaryInfo (unsigned long lineNumber)
1174a0c1e6d7SMasatake YAMATO {
1175a0c1e6d7SMasatake YAMATO unsigned int info;
1176a0c1e6d7SMasatake YAMATO
117713b5aee2SMasatake YAMATO if (!doesParserRunAsGuest())
1178a0c1e6d7SMasatake YAMATO /* Not in a nested input stream */
1179a0c1e6d7SMasatake YAMATO return 0;
1180a0c1e6d7SMasatake YAMATO
1181a0c1e6d7SMasatake YAMATO info = 0;
1182a0c1e6d7SMasatake YAMATO if (File.nestedInputStreamInfo.startLine == lineNumber
1183a0c1e6d7SMasatake YAMATO && File.nestedInputStreamInfo.startCharOffset != 0)
1184a0c1e6d7SMasatake YAMATO info |= BOUNDARY_START;
1185a0c1e6d7SMasatake YAMATO if (File.nestedInputStreamInfo.endLine == lineNumber
1186a0c1e6d7SMasatake YAMATO && File.nestedInputStreamInfo.endCharOffset != 0)
1187a0c1e6d7SMasatake YAMATO info |= BOUNDARY_END;
1188a0c1e6d7SMasatake YAMATO
1189a0c1e6d7SMasatake YAMATO return info;
1190a0c1e6d7SMasatake YAMATO }
popNarrowedInputStream(void)11914fa68e36SMasatake YAMATO extern void popNarrowedInputStream (void)
11924fa68e36SMasatake YAMATO {
11932fa69c1bSMasatake YAMATO if (File.thinDepth)
11942fa69c1bSMasatake YAMATO {
11952fa69c1bSMasatake YAMATO File.thinDepth--;
11962fa69c1bSMasatake YAMATO verbose ("CLEARING thin flag(%d)\n", File.thinDepth);
11972fa69c1bSMasatake YAMATO return;
11982fa69c1bSMasatake YAMATO }
1199b978efd6SMasatake YAMATO mio_unref (File.mio);
12004fa68e36SMasatake YAMATO File = BackupFile;
12014fa68e36SMasatake YAMATO memset (&BackupFile, 0, sizeof (BackupFile));
12024fa68e36SMasatake YAMATO }
12034fa68e36SMasatake YAMATO
pushLanguage(const langType language)1204a8778562SMasatake YAMATO extern void pushLanguage (const langType language)
1205a8778562SMasatake YAMATO {
1206ebc3af7dSMasatake YAMATO pushLangOnStack (& inputLang, language);
1207a8778562SMasatake YAMATO }
1208a8778562SMasatake YAMATO
popLanguage(void)1209a8778562SMasatake YAMATO extern langType popLanguage (void)
1210a8778562SMasatake YAMATO {
1211ebc3af7dSMasatake YAMATO return popLangOnStack (& inputLang);
1212a8778562SMasatake YAMATO }
1213a8778562SMasatake YAMATO
getLanguageForBaseParser(void)1214657cbb19SMasatake YAMATO extern langType getLanguageForBaseParser (void)
1215657cbb19SMasatake YAMATO {
1216657cbb19SMasatake YAMATO return baseLangOnStack (& inputLang);
1217657cbb19SMasatake YAMATO }
1218657cbb19SMasatake YAMATO
langStackInit(langStack * langStack)1219a8778562SMasatake YAMATO static void langStackInit (langStack *langStack)
1220a8778562SMasatake YAMATO {
1221a8778562SMasatake YAMATO langStack->count = 0;
1222a8778562SMasatake YAMATO langStack->size = 1;
1223a8778562SMasatake YAMATO langStack->languages = xCalloc (langStack->size, langType);
122433a6fdb8SMasatake YAMATO DEFAULT_TRASH_BOX(&(langStack->languages), eFreeIndirect);
1225a8778562SMasatake YAMATO }
1226a8778562SMasatake YAMATO
langStackTop(langStack * langStack)1227a8778562SMasatake YAMATO static langType langStackTop (langStack *langStack)
1228a8778562SMasatake YAMATO {
1229a8778562SMasatake YAMATO Assert (langStack->count > 0);
1230a8778562SMasatake YAMATO return langStack->languages [langStack->count - 1];
1231a8778562SMasatake YAMATO }
1232a8778562SMasatake YAMATO
langStackBotom(langStack * langStack)1233657cbb19SMasatake YAMATO static langType langStackBotom(langStack *langStack)
1234657cbb19SMasatake YAMATO {
1235657cbb19SMasatake YAMATO Assert (langStack->count > 0);
1236657cbb19SMasatake YAMATO return langStack->languages [0];
1237657cbb19SMasatake YAMATO }
1238657cbb19SMasatake YAMATO
langStackClear(langStack * langStack)123979758c23SMasatake YAMATO static void langStackClear (langStack *langStack)
124079758c23SMasatake YAMATO {
124179758c23SMasatake YAMATO while (langStack->count > 0)
124279758c23SMasatake YAMATO langStackPop (langStack);
124379758c23SMasatake YAMATO }
124479758c23SMasatake YAMATO
langStackPush(langStack * langStack,langType type)1245a8778562SMasatake YAMATO static void langStackPush (langStack *langStack, langType type)
1246a8778562SMasatake YAMATO {
1247a8778562SMasatake YAMATO if (langStack->size == 0)
1248a8778562SMasatake YAMATO langStackInit (langStack);
1249a8778562SMasatake YAMATO else if (langStack->count == langStack->size)
1250a8778562SMasatake YAMATO langStack->languages = xRealloc (langStack->languages,
1251a8778562SMasatake YAMATO ++ langStack->size, langType);
1252a8778562SMasatake YAMATO langStack->languages [ langStack->count ++ ] = type;
1253a8778562SMasatake YAMATO }
1254a8778562SMasatake YAMATO
langStackPop(langStack * langStack)1255a8778562SMasatake YAMATO static langType langStackPop (langStack *langStack)
1256a8778562SMasatake YAMATO {
1257a8778562SMasatake YAMATO return langStack->languages [ -- langStack->count ];
1258a8778562SMasatake YAMATO }
12592fa69c1bSMasatake YAMATO
isThinStreamSpec(unsigned long startLine,long startCharOffset,unsigned long endLine,long endCharOffset,unsigned long sourceLineOffset)12602fa69c1bSMasatake YAMATO extern bool isThinStreamSpec(unsigned long startLine, long startCharOffset,
12612fa69c1bSMasatake YAMATO unsigned long endLine, long endCharOffset,
12622fa69c1bSMasatake YAMATO unsigned long sourceLineOffset)
12632fa69c1bSMasatake YAMATO {
12642fa69c1bSMasatake YAMATO return (startLine == 0 &&
12652fa69c1bSMasatake YAMATO startCharOffset == 0 &&
12662fa69c1bSMasatake YAMATO endLine == 0 &&
12672fa69c1bSMasatake YAMATO endCharOffset == 0 &&
12682fa69c1bSMasatake YAMATO sourceLineOffset == 0);
12692fa69c1bSMasatake YAMATO }
1270782707aeSMasatake YAMATO
1271782707aeSMasatake YAMATO #ifdef DO_TRACING
isTraced(void)1272782707aeSMasatake YAMATO extern bool isTraced (void)
1273782707aeSMasatake YAMATO {
1274782707aeSMasatake YAMATO if (File.mio == NULL)
1275782707aeSMasatake YAMATO /* A parser is not given. In that case, just check whether --_trace option
1276782707aeSMasatake YAMATO is given or not. */
1277782707aeSMasatake YAMATO return isMainTraced ();
1278782707aeSMasatake YAMATO else
1279782707aeSMasatake YAMATO /* A parser is given. In that case, check whether the current parser is
1280782707aeSMasatake YAMATO specified in --_trace=<LANG>,... option */
1281782707aeSMasatake YAMATO return isLanguageTraced (getInputLanguage ());
1282782707aeSMasatake YAMATO }
1283782707aeSMasatake YAMATO #endif /* DO_TRACING */
1284