1760c2415Smrg /* Character scanner.
2*0bfacb9bSmrg    Copyright (C) 2000-2020 Free Software Foundation, Inc.
3760c2415Smrg    Contributed by Andy Vaught
4760c2415Smrg 
5760c2415Smrg This file is part of GCC.
6760c2415Smrg 
7760c2415Smrg GCC is free software; you can redistribute it and/or modify it under
8760c2415Smrg the terms of the GNU General Public License as published by the Free
9760c2415Smrg Software Foundation; either version 3, or (at your option) any later
10760c2415Smrg version.
11760c2415Smrg 
12760c2415Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13760c2415Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14760c2415Smrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15760c2415Smrg for more details.
16760c2415Smrg 
17760c2415Smrg You should have received a copy of the GNU General Public License
18760c2415Smrg along with GCC; see the file COPYING3.  If not see
19760c2415Smrg <http://www.gnu.org/licenses/>.  */
20760c2415Smrg 
21760c2415Smrg /* Set of subroutines to (ultimately) return the next character to the
22760c2415Smrg    various matching subroutines.  This file's job is to read files and
23760c2415Smrg    build up lines that are parsed by the parser.  This means that we
24760c2415Smrg    handle continuation lines and "include" lines.
25760c2415Smrg 
26760c2415Smrg    The first thing the scanner does is to load an entire file into
27760c2415Smrg    memory.  We load the entire file into memory for a couple reasons.
28760c2415Smrg    The first is that we want to be able to deal with nonseekable input
29760c2415Smrg    (pipes, stdin) and there is a lot of backing up involved during
30760c2415Smrg    parsing.
31760c2415Smrg 
32760c2415Smrg    The second is that we want to be able to print the locus of errors,
33760c2415Smrg    and an error on line 999999 could conflict with something on line
34760c2415Smrg    one.  Given nonseekable input, we've got to store the whole thing.
35760c2415Smrg 
36760c2415Smrg    One thing that helps are the column truncation limits that give us
37760c2415Smrg    an upper bound on the size of individual lines.  We don't store the
38760c2415Smrg    truncated stuff.
39760c2415Smrg 
40760c2415Smrg    From the scanner's viewpoint, the higher level subroutines ask for
41760c2415Smrg    new characters and do a lot of jumping backwards.  */
42760c2415Smrg 
43760c2415Smrg #include "config.h"
44760c2415Smrg #include "system.h"
45760c2415Smrg #include "coretypes.h"
46760c2415Smrg #include "gfortran.h"
47760c2415Smrg #include "toplev.h"	/* For set_src_pwd.  */
48760c2415Smrg #include "debug.h"
49760c2415Smrg #include "options.h"
50760c2415Smrg #include "cpp.h"
51760c2415Smrg #include "scanner.h"
52760c2415Smrg 
53760c2415Smrg /* List of include file search directories.  */
54760c2415Smrg gfc_directorylist *include_dirs, *intrinsic_modules_dirs;
55760c2415Smrg 
56760c2415Smrg static gfc_file *file_head, *current_file;
57760c2415Smrg 
58760c2415Smrg static int continue_flag, end_flag, gcc_attribute_flag;
59760c2415Smrg /* If !$omp/!$acc occurred in current comment line.  */
60760c2415Smrg static int openmp_flag, openacc_flag;
61760c2415Smrg static int continue_count, continue_line;
62760c2415Smrg static locus openmp_locus;
63760c2415Smrg static locus openacc_locus;
64760c2415Smrg static locus gcc_attribute_locus;
65760c2415Smrg 
66760c2415Smrg gfc_source_form gfc_current_form;
67760c2415Smrg static gfc_linebuf *line_head, *line_tail;
68760c2415Smrg 
69760c2415Smrg locus gfc_current_locus;
70760c2415Smrg const char *gfc_source_file;
71760c2415Smrg static FILE *gfc_src_file;
72760c2415Smrg static gfc_char_t *gfc_src_preprocessor_lines[2];
73760c2415Smrg 
74760c2415Smrg static struct gfc_file_change
75760c2415Smrg {
76760c2415Smrg   const char *filename;
77760c2415Smrg   gfc_linebuf *lb;
78760c2415Smrg   int line;
79760c2415Smrg } *file_changes;
80760c2415Smrg size_t file_changes_cur, file_changes_count;
81760c2415Smrg size_t file_changes_allocated;
82760c2415Smrg 
83760c2415Smrg static gfc_char_t *last_error_char;
84760c2415Smrg 
85760c2415Smrg /* Functions dealing with our wide characters (gfc_char_t) and
86760c2415Smrg    sequences of such characters.  */
87760c2415Smrg 
88760c2415Smrg int
gfc_wide_fits_in_byte(gfc_char_t c)89760c2415Smrg gfc_wide_fits_in_byte (gfc_char_t c)
90760c2415Smrg {
91760c2415Smrg   return (c <= UCHAR_MAX);
92760c2415Smrg }
93760c2415Smrg 
94760c2415Smrg static inline int
wide_is_ascii(gfc_char_t c)95760c2415Smrg wide_is_ascii (gfc_char_t c)
96760c2415Smrg {
97760c2415Smrg   return (gfc_wide_fits_in_byte (c) && ((unsigned char) c & ~0x7f) == 0);
98760c2415Smrg }
99760c2415Smrg 
100760c2415Smrg int
gfc_wide_is_printable(gfc_char_t c)101760c2415Smrg gfc_wide_is_printable (gfc_char_t c)
102760c2415Smrg {
103760c2415Smrg   return (gfc_wide_fits_in_byte (c) && ISPRINT ((unsigned char) c));
104760c2415Smrg }
105760c2415Smrg 
106760c2415Smrg gfc_char_t
gfc_wide_tolower(gfc_char_t c)107760c2415Smrg gfc_wide_tolower (gfc_char_t c)
108760c2415Smrg {
109760c2415Smrg   return (wide_is_ascii (c) ? (gfc_char_t) TOLOWER((unsigned char) c) : c);
110760c2415Smrg }
111760c2415Smrg 
112760c2415Smrg gfc_char_t
gfc_wide_toupper(gfc_char_t c)113760c2415Smrg gfc_wide_toupper (gfc_char_t c)
114760c2415Smrg {
115760c2415Smrg   return (wide_is_ascii (c) ? (gfc_char_t) TOUPPER((unsigned char) c) : c);
116760c2415Smrg }
117760c2415Smrg 
118760c2415Smrg int
gfc_wide_is_digit(gfc_char_t c)119760c2415Smrg gfc_wide_is_digit (gfc_char_t c)
120760c2415Smrg {
121760c2415Smrg   return (c >= '0' && c <= '9');
122760c2415Smrg }
123760c2415Smrg 
124760c2415Smrg static inline int
wide_atoi(gfc_char_t * c)125760c2415Smrg wide_atoi (gfc_char_t *c)
126760c2415Smrg {
127760c2415Smrg #define MAX_DIGITS 20
128760c2415Smrg   char buf[MAX_DIGITS+1];
129760c2415Smrg   int i = 0;
130760c2415Smrg 
131760c2415Smrg   while (gfc_wide_is_digit(*c) && i < MAX_DIGITS)
132760c2415Smrg     buf[i++] = *c++;
133760c2415Smrg   buf[i] = '\0';
134760c2415Smrg   return atoi (buf);
135760c2415Smrg }
136760c2415Smrg 
137760c2415Smrg size_t
gfc_wide_strlen(const gfc_char_t * str)138760c2415Smrg gfc_wide_strlen (const gfc_char_t *str)
139760c2415Smrg {
140760c2415Smrg   size_t i;
141760c2415Smrg 
142760c2415Smrg   for (i = 0; str[i]; i++)
143760c2415Smrg     ;
144760c2415Smrg 
145760c2415Smrg   return i;
146760c2415Smrg }
147760c2415Smrg 
148760c2415Smrg gfc_char_t *
gfc_wide_memset(gfc_char_t * b,gfc_char_t c,size_t len)149760c2415Smrg gfc_wide_memset (gfc_char_t *b, gfc_char_t c, size_t len)
150760c2415Smrg {
151760c2415Smrg   size_t i;
152760c2415Smrg 
153760c2415Smrg   for (i = 0; i < len; i++)
154760c2415Smrg     b[i] = c;
155760c2415Smrg 
156760c2415Smrg   return b;
157760c2415Smrg }
158760c2415Smrg 
159760c2415Smrg static gfc_char_t *
wide_strcpy(gfc_char_t * dest,const gfc_char_t * src)160760c2415Smrg wide_strcpy (gfc_char_t *dest, const gfc_char_t *src)
161760c2415Smrg {
162760c2415Smrg   gfc_char_t *d;
163760c2415Smrg 
164760c2415Smrg   for (d = dest; (*d = *src) != '\0'; ++src, ++d)
165760c2415Smrg     ;
166760c2415Smrg 
167760c2415Smrg   return dest;
168760c2415Smrg }
169760c2415Smrg 
170760c2415Smrg static gfc_char_t *
wide_strchr(const gfc_char_t * s,gfc_char_t c)171760c2415Smrg wide_strchr (const gfc_char_t *s, gfc_char_t c)
172760c2415Smrg {
173760c2415Smrg   do {
174760c2415Smrg     if (*s == c)
175760c2415Smrg       {
176760c2415Smrg         return CONST_CAST(gfc_char_t *, s);
177760c2415Smrg       }
178760c2415Smrg   } while (*s++);
179760c2415Smrg   return 0;
180760c2415Smrg }
181760c2415Smrg 
182760c2415Smrg char *
gfc_widechar_to_char(const gfc_char_t * s,int length)183760c2415Smrg gfc_widechar_to_char (const gfc_char_t *s, int length)
184760c2415Smrg {
185760c2415Smrg   size_t len, i;
186760c2415Smrg   char *res;
187760c2415Smrg 
188760c2415Smrg   if (s == NULL)
189760c2415Smrg     return NULL;
190760c2415Smrg 
191760c2415Smrg   /* Passing a negative length is used to indicate that length should be
192760c2415Smrg      calculated using gfc_wide_strlen().  */
193760c2415Smrg   len = (length >= 0 ? (size_t) length : gfc_wide_strlen (s));
194760c2415Smrg   res = XNEWVEC (char, len + 1);
195760c2415Smrg 
196760c2415Smrg   for (i = 0; i < len; i++)
197760c2415Smrg     {
198760c2415Smrg       gcc_assert (gfc_wide_fits_in_byte (s[i]));
199760c2415Smrg       res[i] = (unsigned char) s[i];
200760c2415Smrg     }
201760c2415Smrg 
202760c2415Smrg   res[len] = '\0';
203760c2415Smrg   return res;
204760c2415Smrg }
205760c2415Smrg 
206760c2415Smrg gfc_char_t *
gfc_char_to_widechar(const char * s)207760c2415Smrg gfc_char_to_widechar (const char *s)
208760c2415Smrg {
209760c2415Smrg   size_t len, i;
210760c2415Smrg   gfc_char_t *res;
211760c2415Smrg 
212760c2415Smrg   if (s == NULL)
213760c2415Smrg     return NULL;
214760c2415Smrg 
215760c2415Smrg   len = strlen (s);
216760c2415Smrg   res = gfc_get_wide_string (len + 1);
217760c2415Smrg 
218760c2415Smrg   for (i = 0; i < len; i++)
219760c2415Smrg     res[i] = (unsigned char) s[i];
220760c2415Smrg 
221760c2415Smrg   res[len] = '\0';
222760c2415Smrg   return res;
223760c2415Smrg }
224760c2415Smrg 
225760c2415Smrg static int
wide_strncmp(const gfc_char_t * s1,const char * s2,size_t n)226760c2415Smrg wide_strncmp (const gfc_char_t *s1, const char *s2, size_t n)
227760c2415Smrg {
228760c2415Smrg   gfc_char_t c1, c2;
229760c2415Smrg 
230760c2415Smrg   while (n-- > 0)
231760c2415Smrg     {
232760c2415Smrg       c1 = *s1++;
233760c2415Smrg       c2 = *s2++;
234760c2415Smrg       if (c1 != c2)
235760c2415Smrg 	return (c1 > c2 ? 1 : -1);
236760c2415Smrg       if (c1 == '\0')
237760c2415Smrg 	return 0;
238760c2415Smrg     }
239760c2415Smrg   return 0;
240760c2415Smrg }
241760c2415Smrg 
242760c2415Smrg int
gfc_wide_strncasecmp(const gfc_char_t * s1,const char * s2,size_t n)243760c2415Smrg gfc_wide_strncasecmp (const gfc_char_t *s1, const char *s2, size_t n)
244760c2415Smrg {
245760c2415Smrg   gfc_char_t c1, c2;
246760c2415Smrg 
247760c2415Smrg   while (n-- > 0)
248760c2415Smrg     {
249760c2415Smrg       c1 = gfc_wide_tolower (*s1++);
250760c2415Smrg       c2 = TOLOWER (*s2++);
251760c2415Smrg       if (c1 != c2)
252760c2415Smrg 	return (c1 > c2 ? 1 : -1);
253760c2415Smrg       if (c1 == '\0')
254760c2415Smrg 	return 0;
255760c2415Smrg     }
256760c2415Smrg   return 0;
257760c2415Smrg }
258760c2415Smrg 
259760c2415Smrg 
260760c2415Smrg /* Main scanner initialization.  */
261760c2415Smrg 
262760c2415Smrg void
gfc_scanner_init_1(void)263760c2415Smrg gfc_scanner_init_1 (void)
264760c2415Smrg {
265760c2415Smrg   file_head = NULL;
266760c2415Smrg   line_head = NULL;
267760c2415Smrg   line_tail = NULL;
268760c2415Smrg 
269760c2415Smrg   continue_count = 0;
270760c2415Smrg   continue_line = 0;
271760c2415Smrg 
272760c2415Smrg   end_flag = 0;
273760c2415Smrg   last_error_char = NULL;
274760c2415Smrg }
275760c2415Smrg 
276760c2415Smrg 
277760c2415Smrg /* Main scanner destructor.  */
278760c2415Smrg 
279760c2415Smrg void
gfc_scanner_done_1(void)280760c2415Smrg gfc_scanner_done_1 (void)
281760c2415Smrg {
282760c2415Smrg   gfc_linebuf *lb;
283760c2415Smrg   gfc_file *f;
284760c2415Smrg 
285760c2415Smrg   while(line_head != NULL)
286760c2415Smrg     {
287760c2415Smrg       lb = line_head->next;
288760c2415Smrg       free (line_head);
289760c2415Smrg       line_head = lb;
290760c2415Smrg     }
291760c2415Smrg 
292760c2415Smrg   while(file_head != NULL)
293760c2415Smrg     {
294760c2415Smrg       f = file_head->next;
295760c2415Smrg       free (file_head->filename);
296760c2415Smrg       free (file_head);
297760c2415Smrg       file_head = f;
298760c2415Smrg     }
299760c2415Smrg }
300760c2415Smrg 
301760c2415Smrg 
302760c2415Smrg /* Adds path to the list pointed to by list.  */
303760c2415Smrg 
304760c2415Smrg static void
add_path_to_list(gfc_directorylist ** list,const char * path,bool use_for_modules,bool head,bool warn)305760c2415Smrg add_path_to_list (gfc_directorylist **list, const char *path,
306760c2415Smrg 		  bool use_for_modules, bool head, bool warn)
307760c2415Smrg {
308760c2415Smrg   gfc_directorylist *dir;
309760c2415Smrg   const char *p;
310760c2415Smrg   char *q;
311760c2415Smrg   struct stat st;
312760c2415Smrg   size_t len;
313760c2415Smrg   int i;
314760c2415Smrg 
315760c2415Smrg   p = path;
316760c2415Smrg   while (*p == ' ' || *p == '\t')  /* someone might do "-I include" */
317760c2415Smrg     if (*p++ == '\0')
318760c2415Smrg       return;
319760c2415Smrg 
320760c2415Smrg   /* Strip trailing directory separators from the path, as this
321760c2415Smrg      will confuse Windows systems.  */
322760c2415Smrg   len = strlen (p);
323760c2415Smrg   q = (char *) alloca (len + 1);
324760c2415Smrg   memcpy (q, p, len + 1);
325760c2415Smrg   i = len - 1;
326760c2415Smrg   while (i >=0 && IS_DIR_SEPARATOR (q[i]))
327760c2415Smrg     q[i--] = '\0';
328760c2415Smrg 
329760c2415Smrg   if (stat (q, &st))
330760c2415Smrg     {
331760c2415Smrg       if (errno != ENOENT)
332760c2415Smrg 	gfc_warning_now (0, "Include directory %qs: %s", path,
333760c2415Smrg 			 xstrerror(errno));
334760c2415Smrg       else if (warn)
335760c2415Smrg 	gfc_warning_now (OPT_Wmissing_include_dirs,
336760c2415Smrg 			 "Nonexistent include directory %qs", path);
337760c2415Smrg       return;
338760c2415Smrg     }
339760c2415Smrg   else if (!S_ISDIR (st.st_mode))
340760c2415Smrg     {
341760c2415Smrg       gfc_fatal_error ("%qs is not a directory", path);
342760c2415Smrg       return;
343760c2415Smrg     }
344760c2415Smrg 
345760c2415Smrg   if (head || *list == NULL)
346760c2415Smrg     {
347760c2415Smrg       dir = XCNEW (gfc_directorylist);
348760c2415Smrg       if (!head)
349760c2415Smrg         *list = dir;
350760c2415Smrg     }
351760c2415Smrg   else
352760c2415Smrg     {
353760c2415Smrg       dir = *list;
354760c2415Smrg       while (dir->next)
355760c2415Smrg 	dir = dir->next;
356760c2415Smrg 
357760c2415Smrg       dir->next = XCNEW (gfc_directorylist);
358760c2415Smrg       dir = dir->next;
359760c2415Smrg     }
360760c2415Smrg 
361760c2415Smrg   dir->next = head ? *list : NULL;
362760c2415Smrg   if (head)
363760c2415Smrg     *list = dir;
364760c2415Smrg   dir->use_for_modules = use_for_modules;
365760c2415Smrg   dir->path = XCNEWVEC (char, strlen (p) + 2);
366760c2415Smrg   strcpy (dir->path, p);
367760c2415Smrg   strcat (dir->path, "/");	/* make '/' last character */
368760c2415Smrg }
369760c2415Smrg 
370760c2415Smrg 
371760c2415Smrg void
gfc_add_include_path(const char * path,bool use_for_modules,bool file_dir,bool warn)372760c2415Smrg gfc_add_include_path (const char *path, bool use_for_modules, bool file_dir,
373760c2415Smrg 		      bool warn)
374760c2415Smrg {
375760c2415Smrg   add_path_to_list (&include_dirs, path, use_for_modules, file_dir, warn);
376760c2415Smrg 
377760c2415Smrg   /* For '#include "..."' these directories are automatically searched.  */
378760c2415Smrg   if (!file_dir)
379760c2415Smrg     gfc_cpp_add_include_path (xstrdup(path), true);
380760c2415Smrg }
381760c2415Smrg 
382760c2415Smrg 
383760c2415Smrg void
gfc_add_intrinsic_modules_path(const char * path)384760c2415Smrg gfc_add_intrinsic_modules_path (const char *path)
385760c2415Smrg {
386760c2415Smrg   add_path_to_list (&intrinsic_modules_dirs, path, true, false, false);
387760c2415Smrg }
388760c2415Smrg 
389760c2415Smrg 
390760c2415Smrg /* Release resources allocated for options.  */
391760c2415Smrg 
392760c2415Smrg void
gfc_release_include_path(void)393760c2415Smrg gfc_release_include_path (void)
394760c2415Smrg {
395760c2415Smrg   gfc_directorylist *p;
396760c2415Smrg 
397760c2415Smrg   while (include_dirs != NULL)
398760c2415Smrg     {
399760c2415Smrg       p = include_dirs;
400760c2415Smrg       include_dirs = include_dirs->next;
401760c2415Smrg       free (p->path);
402760c2415Smrg       free (p);
403760c2415Smrg     }
404760c2415Smrg 
405760c2415Smrg   while (intrinsic_modules_dirs != NULL)
406760c2415Smrg     {
407760c2415Smrg       p = intrinsic_modules_dirs;
408760c2415Smrg       intrinsic_modules_dirs = intrinsic_modules_dirs->next;
409760c2415Smrg       free (p->path);
410760c2415Smrg       free (p);
411760c2415Smrg     }
412760c2415Smrg 
413760c2415Smrg   free (gfc_option.module_dir);
414760c2415Smrg }
415760c2415Smrg 
416760c2415Smrg 
417760c2415Smrg static FILE *
open_included_file(const char * name,gfc_directorylist * list,bool module,bool system)418760c2415Smrg open_included_file (const char *name, gfc_directorylist *list,
419760c2415Smrg 		    bool module, bool system)
420760c2415Smrg {
421760c2415Smrg   char *fullname;
422760c2415Smrg   gfc_directorylist *p;
423760c2415Smrg   FILE *f;
424760c2415Smrg 
425760c2415Smrg   for (p = list; p; p = p->next)
426760c2415Smrg     {
427760c2415Smrg       if (module && !p->use_for_modules)
428760c2415Smrg 	continue;
429760c2415Smrg 
430760c2415Smrg       fullname = (char *) alloca(strlen (p->path) + strlen (name) + 1);
431760c2415Smrg       strcpy (fullname, p->path);
432760c2415Smrg       strcat (fullname, name);
433760c2415Smrg 
434760c2415Smrg       f = gfc_open_file (fullname);
435760c2415Smrg       if (f != NULL)
436760c2415Smrg 	{
437760c2415Smrg 	  if (gfc_cpp_makedep ())
438760c2415Smrg 	    gfc_cpp_add_dep (fullname, system);
439760c2415Smrg 
440760c2415Smrg 	  return f;
441760c2415Smrg 	}
442760c2415Smrg     }
443760c2415Smrg 
444760c2415Smrg   return NULL;
445760c2415Smrg }
446760c2415Smrg 
447760c2415Smrg 
448760c2415Smrg /* Opens file for reading, searching through the include directories
449760c2415Smrg    given if necessary.  If the include_cwd argument is true, we try
450760c2415Smrg    to open the file in the current directory first.  */
451760c2415Smrg 
452760c2415Smrg FILE *
gfc_open_included_file(const char * name,bool include_cwd,bool module)453760c2415Smrg gfc_open_included_file (const char *name, bool include_cwd, bool module)
454760c2415Smrg {
455760c2415Smrg   FILE *f = NULL;
456760c2415Smrg 
457760c2415Smrg   if (IS_ABSOLUTE_PATH (name) || include_cwd)
458760c2415Smrg     {
459760c2415Smrg       f = gfc_open_file (name);
460760c2415Smrg       if (f && gfc_cpp_makedep ())
461760c2415Smrg 	gfc_cpp_add_dep (name, false);
462760c2415Smrg     }
463760c2415Smrg 
464760c2415Smrg   if (!f)
465760c2415Smrg     f = open_included_file (name, include_dirs, module, false);
466760c2415Smrg 
467760c2415Smrg   return f;
468760c2415Smrg }
469760c2415Smrg 
470760c2415Smrg 
471760c2415Smrg /* Test to see if we're at the end of the main source file.  */
472760c2415Smrg 
473760c2415Smrg int
gfc_at_end(void)474760c2415Smrg gfc_at_end (void)
475760c2415Smrg {
476760c2415Smrg   return end_flag;
477760c2415Smrg }
478760c2415Smrg 
479760c2415Smrg 
480760c2415Smrg /* Test to see if we're at the end of the current file.  */
481760c2415Smrg 
482760c2415Smrg int
gfc_at_eof(void)483760c2415Smrg gfc_at_eof (void)
484760c2415Smrg {
485760c2415Smrg   if (gfc_at_end ())
486760c2415Smrg     return 1;
487760c2415Smrg 
488760c2415Smrg   if (line_head == NULL)
489760c2415Smrg     return 1;			/* Null file */
490760c2415Smrg 
491760c2415Smrg   if (gfc_current_locus.lb == NULL)
492760c2415Smrg     return 1;
493760c2415Smrg 
494760c2415Smrg   return 0;
495760c2415Smrg }
496760c2415Smrg 
497760c2415Smrg 
498760c2415Smrg /* Test to see if we're at the beginning of a new line.  */
499760c2415Smrg 
500760c2415Smrg int
gfc_at_bol(void)501760c2415Smrg gfc_at_bol (void)
502760c2415Smrg {
503760c2415Smrg   if (gfc_at_eof ())
504760c2415Smrg     return 1;
505760c2415Smrg 
506760c2415Smrg   return (gfc_current_locus.nextc == gfc_current_locus.lb->line);
507760c2415Smrg }
508760c2415Smrg 
509760c2415Smrg 
510760c2415Smrg /* Test to see if we're at the end of a line.  */
511760c2415Smrg 
512760c2415Smrg int
gfc_at_eol(void)513760c2415Smrg gfc_at_eol (void)
514760c2415Smrg {
515760c2415Smrg   if (gfc_at_eof ())
516760c2415Smrg     return 1;
517760c2415Smrg 
518760c2415Smrg   return (*gfc_current_locus.nextc == '\0');
519760c2415Smrg }
520760c2415Smrg 
521760c2415Smrg static void
add_file_change(const char * filename,int line)522760c2415Smrg add_file_change (const char *filename, int line)
523760c2415Smrg {
524760c2415Smrg   if (file_changes_count == file_changes_allocated)
525760c2415Smrg     {
526760c2415Smrg       if (file_changes_allocated)
527760c2415Smrg 	file_changes_allocated *= 2;
528760c2415Smrg       else
529760c2415Smrg 	file_changes_allocated = 16;
530760c2415Smrg       file_changes = XRESIZEVEC (struct gfc_file_change, file_changes,
531760c2415Smrg 				 file_changes_allocated);
532760c2415Smrg     }
533760c2415Smrg   file_changes[file_changes_count].filename = filename;
534760c2415Smrg   file_changes[file_changes_count].lb = NULL;
535760c2415Smrg   file_changes[file_changes_count++].line = line;
536760c2415Smrg }
537760c2415Smrg 
538760c2415Smrg static void
report_file_change(gfc_linebuf * lb)539760c2415Smrg report_file_change (gfc_linebuf *lb)
540760c2415Smrg {
541760c2415Smrg   size_t c = file_changes_cur;
542760c2415Smrg   while (c < file_changes_count
543760c2415Smrg 	 && file_changes[c].lb == lb)
544760c2415Smrg     {
545760c2415Smrg       if (file_changes[c].filename)
546760c2415Smrg 	(*debug_hooks->start_source_file) (file_changes[c].line,
547760c2415Smrg 					   file_changes[c].filename);
548760c2415Smrg       else
549760c2415Smrg 	(*debug_hooks->end_source_file) (file_changes[c].line);
550760c2415Smrg       ++c;
551760c2415Smrg     }
552760c2415Smrg   file_changes_cur = c;
553760c2415Smrg }
554760c2415Smrg 
555760c2415Smrg void
gfc_start_source_files(void)556760c2415Smrg gfc_start_source_files (void)
557760c2415Smrg {
558760c2415Smrg   /* If the debugger wants the name of the main source file,
559760c2415Smrg      we give it.  */
560760c2415Smrg   if (debug_hooks->start_end_main_source_file)
561760c2415Smrg     (*debug_hooks->start_source_file) (0, gfc_source_file);
562760c2415Smrg 
563760c2415Smrg   file_changes_cur = 0;
564760c2415Smrg   report_file_change (gfc_current_locus.lb);
565760c2415Smrg }
566760c2415Smrg 
567760c2415Smrg void
gfc_end_source_files(void)568760c2415Smrg gfc_end_source_files (void)
569760c2415Smrg {
570760c2415Smrg   report_file_change (NULL);
571760c2415Smrg 
572760c2415Smrg   if (debug_hooks->start_end_main_source_file)
573760c2415Smrg     (*debug_hooks->end_source_file) (0);
574760c2415Smrg }
575760c2415Smrg 
576760c2415Smrg /* Advance the current line pointer to the next line.  */
577760c2415Smrg 
578760c2415Smrg void
gfc_advance_line(void)579760c2415Smrg gfc_advance_line (void)
580760c2415Smrg {
581760c2415Smrg   if (gfc_at_end ())
582760c2415Smrg     return;
583760c2415Smrg 
584760c2415Smrg   if (gfc_current_locus.lb == NULL)
585760c2415Smrg     {
586760c2415Smrg       end_flag = 1;
587760c2415Smrg       return;
588760c2415Smrg     }
589760c2415Smrg 
590760c2415Smrg   if (gfc_current_locus.lb->next
591760c2415Smrg       && !gfc_current_locus.lb->next->dbg_emitted)
592760c2415Smrg     {
593760c2415Smrg       report_file_change (gfc_current_locus.lb->next);
594760c2415Smrg       gfc_current_locus.lb->next->dbg_emitted = true;
595760c2415Smrg     }
596760c2415Smrg 
597760c2415Smrg   gfc_current_locus.lb = gfc_current_locus.lb->next;
598760c2415Smrg 
599760c2415Smrg   if (gfc_current_locus.lb != NULL)
600760c2415Smrg     gfc_current_locus.nextc = gfc_current_locus.lb->line;
601760c2415Smrg   else
602760c2415Smrg     {
603760c2415Smrg       gfc_current_locus.nextc = NULL;
604760c2415Smrg       end_flag = 1;
605760c2415Smrg     }
606760c2415Smrg }
607760c2415Smrg 
608760c2415Smrg 
609760c2415Smrg /* Get the next character from the input, advancing gfc_current_file's
610760c2415Smrg    locus.  When we hit the end of the line or the end of the file, we
611760c2415Smrg    start returning a '\n' in order to complete the current statement.
612760c2415Smrg    No Fortran line conventions are implemented here.
613760c2415Smrg 
614760c2415Smrg    Requiring explicit advances to the next line prevents the parse
615760c2415Smrg    pointer from being on the wrong line if the current statement ends
616760c2415Smrg    prematurely.  */
617760c2415Smrg 
618760c2415Smrg static gfc_char_t
next_char(void)619760c2415Smrg next_char (void)
620760c2415Smrg {
621760c2415Smrg   gfc_char_t c;
622760c2415Smrg 
623760c2415Smrg   if (gfc_current_locus.nextc == NULL)
624760c2415Smrg     return '\n';
625760c2415Smrg 
626760c2415Smrg   c = *gfc_current_locus.nextc++;
627760c2415Smrg   if (c == '\0')
628760c2415Smrg     {
629760c2415Smrg       gfc_current_locus.nextc--; /* Remain on this line.  */
630760c2415Smrg       c = '\n';
631760c2415Smrg     }
632760c2415Smrg 
633760c2415Smrg   return c;
634760c2415Smrg }
635760c2415Smrg 
636760c2415Smrg 
637760c2415Smrg /* Skip a comment.  When we come here the parse pointer is positioned
638760c2415Smrg    immediately after the comment character.  If we ever implement
639760c2415Smrg    compiler directives within comments, here is where we parse the
640760c2415Smrg    directive.  */
641760c2415Smrg 
642760c2415Smrg static void
skip_comment_line(void)643760c2415Smrg skip_comment_line (void)
644760c2415Smrg {
645760c2415Smrg   gfc_char_t c;
646760c2415Smrg 
647760c2415Smrg   do
648760c2415Smrg     {
649760c2415Smrg       c = next_char ();
650760c2415Smrg     }
651760c2415Smrg   while (c != '\n');
652760c2415Smrg 
653760c2415Smrg   gfc_advance_line ();
654760c2415Smrg }
655760c2415Smrg 
656760c2415Smrg 
657760c2415Smrg int
gfc_define_undef_line(void)658760c2415Smrg gfc_define_undef_line (void)
659760c2415Smrg {
660760c2415Smrg   char *tmp;
661760c2415Smrg 
662760c2415Smrg   /* All lines beginning with '#' are either #define or #undef.  */
663760c2415Smrg   if (debug_info_level != DINFO_LEVEL_VERBOSE || gfc_peek_ascii_char () != '#')
664760c2415Smrg     return 0;
665760c2415Smrg 
666760c2415Smrg   if (wide_strncmp (gfc_current_locus.nextc, "#define ", 8) == 0)
667760c2415Smrg     {
668760c2415Smrg       tmp = gfc_widechar_to_char (&gfc_current_locus.nextc[8], -1);
669760c2415Smrg       (*debug_hooks->define) (gfc_linebuf_linenum (gfc_current_locus.lb),
670760c2415Smrg 			      tmp);
671760c2415Smrg       free (tmp);
672760c2415Smrg     }
673760c2415Smrg 
674760c2415Smrg   if (wide_strncmp (gfc_current_locus.nextc, "#undef ", 7) == 0)
675760c2415Smrg     {
676760c2415Smrg       tmp = gfc_widechar_to_char (&gfc_current_locus.nextc[7], -1);
677760c2415Smrg       (*debug_hooks->undef) (gfc_linebuf_linenum (gfc_current_locus.lb),
678760c2415Smrg 			     tmp);
679760c2415Smrg       free (tmp);
680760c2415Smrg     }
681760c2415Smrg 
682760c2415Smrg   /* Skip the rest of the line.  */
683760c2415Smrg   skip_comment_line ();
684760c2415Smrg 
685760c2415Smrg   return 1;
686760c2415Smrg }
687760c2415Smrg 
688760c2415Smrg 
689760c2415Smrg /* Return true if GCC$ was matched.  */
690760c2415Smrg static bool
skip_gcc_attribute(locus start)691760c2415Smrg skip_gcc_attribute (locus start)
692760c2415Smrg {
693760c2415Smrg   bool r = false;
694760c2415Smrg   char c;
695760c2415Smrg   locus old_loc = gfc_current_locus;
696760c2415Smrg 
697760c2415Smrg   if ((c = next_char ()) == 'g' || c == 'G')
698760c2415Smrg     if ((c = next_char ()) == 'c' || c == 'C')
699760c2415Smrg       if ((c = next_char ()) == 'c' || c == 'C')
700760c2415Smrg 	if ((c = next_char ()) == '$')
701760c2415Smrg 	  r = true;
702760c2415Smrg 
703760c2415Smrg   if (r == false)
704760c2415Smrg     gfc_current_locus = old_loc;
705760c2415Smrg   else
706760c2415Smrg    {
707760c2415Smrg       gcc_attribute_flag = 1;
708760c2415Smrg       gcc_attribute_locus = old_loc;
709760c2415Smrg       gfc_current_locus = start;
710760c2415Smrg    }
711760c2415Smrg 
712760c2415Smrg   return r;
713760c2415Smrg }
714760c2415Smrg 
715760c2415Smrg /* Return true if CC was matched.  */
716760c2415Smrg static bool
skip_free_oacc_sentinel(locus start,locus old_loc)717760c2415Smrg skip_free_oacc_sentinel (locus start, locus old_loc)
718760c2415Smrg {
719760c2415Smrg   bool r = false;
720760c2415Smrg   char c;
721760c2415Smrg 
722760c2415Smrg   if ((c = next_char ()) == 'c' || c == 'C')
723760c2415Smrg     if ((c = next_char ()) == 'c' || c == 'C')
724760c2415Smrg       r = true;
725760c2415Smrg 
726760c2415Smrg   if (r)
727760c2415Smrg    {
728760c2415Smrg       if ((c = next_char ()) == ' ' || c == '\t'
729760c2415Smrg 	  || continue_flag)
730760c2415Smrg 	{
731760c2415Smrg 	  while (gfc_is_whitespace (c))
732760c2415Smrg 	    c = next_char ();
733760c2415Smrg 	  if (c != '\n' && c != '!')
734760c2415Smrg 	    {
735760c2415Smrg 	      openacc_flag = 1;
736760c2415Smrg 	      openacc_locus = old_loc;
737760c2415Smrg 	      gfc_current_locus = start;
738760c2415Smrg 	    }
739760c2415Smrg 	  else
740760c2415Smrg 	    r = false;
741760c2415Smrg 	}
742760c2415Smrg       else
743760c2415Smrg 	{
744760c2415Smrg 	  gfc_warning_now (0, "!$ACC at %C starts a commented "
745760c2415Smrg 			   "line as it neither is followed "
746760c2415Smrg 			   "by a space nor is a "
747760c2415Smrg 			   "continuation line");
748760c2415Smrg 	  r = false;
749760c2415Smrg 	}
750760c2415Smrg    }
751760c2415Smrg 
752760c2415Smrg   return r;
753760c2415Smrg }
754760c2415Smrg 
755760c2415Smrg /* Return true if MP was matched.  */
756760c2415Smrg static bool
skip_free_omp_sentinel(locus start,locus old_loc)757760c2415Smrg skip_free_omp_sentinel (locus start, locus old_loc)
758760c2415Smrg {
759760c2415Smrg   bool r = false;
760760c2415Smrg   char c;
761760c2415Smrg 
762760c2415Smrg   if ((c = next_char ()) == 'm' || c == 'M')
763760c2415Smrg     if ((c = next_char ()) == 'p' || c == 'P')
764760c2415Smrg       r = true;
765760c2415Smrg 
766760c2415Smrg   if (r)
767760c2415Smrg    {
768760c2415Smrg       if ((c = next_char ()) == ' ' || c == '\t'
769760c2415Smrg 	  || continue_flag)
770760c2415Smrg 	{
771760c2415Smrg 	  while (gfc_is_whitespace (c))
772760c2415Smrg 	    c = next_char ();
773760c2415Smrg 	  if (c != '\n' && c != '!')
774760c2415Smrg 	    {
775760c2415Smrg 	      openmp_flag = 1;
776760c2415Smrg 	      openmp_locus = old_loc;
777760c2415Smrg 	      gfc_current_locus = start;
778760c2415Smrg 	    }
779760c2415Smrg 	  else
780760c2415Smrg 	    r = false;
781760c2415Smrg 	}
782760c2415Smrg       else
783760c2415Smrg 	{
784760c2415Smrg 	  gfc_warning_now (0, "!$OMP at %C starts a commented "
785760c2415Smrg 			   "line as it neither is followed "
786760c2415Smrg 			   "by a space nor is a "
787760c2415Smrg 			   "continuation line");
788760c2415Smrg 	  r = false;
789760c2415Smrg 	}
790760c2415Smrg    }
791760c2415Smrg 
792760c2415Smrg   return r;
793760c2415Smrg }
794760c2415Smrg 
795760c2415Smrg /* Comment lines are null lines, lines containing only blanks or lines
796760c2415Smrg    on which the first nonblank line is a '!'.
797760c2415Smrg    Return true if !$ openmp or openacc conditional compilation sentinel was
798760c2415Smrg    seen.  */
799760c2415Smrg 
800760c2415Smrg static bool
skip_free_comments(void)801760c2415Smrg skip_free_comments (void)
802760c2415Smrg {
803760c2415Smrg   locus start;
804760c2415Smrg   gfc_char_t c;
805760c2415Smrg   int at_bol;
806760c2415Smrg 
807760c2415Smrg   for (;;)
808760c2415Smrg     {
809760c2415Smrg       at_bol = gfc_at_bol ();
810760c2415Smrg       start = gfc_current_locus;
811760c2415Smrg       if (gfc_at_eof ())
812760c2415Smrg 	break;
813760c2415Smrg 
814760c2415Smrg       do
815760c2415Smrg 	c = next_char ();
816760c2415Smrg       while (gfc_is_whitespace (c));
817760c2415Smrg 
818760c2415Smrg       if (c == '\n')
819760c2415Smrg 	{
820760c2415Smrg 	  gfc_advance_line ();
821760c2415Smrg 	  continue;
822760c2415Smrg 	}
823760c2415Smrg 
824760c2415Smrg       if (c == '!')
825760c2415Smrg 	{
826760c2415Smrg 	  /* Keep the !GCC$ line.  */
827760c2415Smrg 	  if (at_bol && skip_gcc_attribute (start))
828760c2415Smrg 	    return false;
829760c2415Smrg 
830760c2415Smrg 	  /* If -fopenmp/-fopenacc, we need to handle here 2 things:
831760c2415Smrg 	     1) don't treat !$omp/!$acc as comments, but directives
832760c2415Smrg 	     2) handle OpenMP/OpenACC conditional compilation, where
833760c2415Smrg 		!$ should be treated as 2 spaces (for initial lines
834760c2415Smrg 		only if followed by space).  */
835760c2415Smrg 	  if (at_bol)
836760c2415Smrg 	  {
837760c2415Smrg 	    if ((flag_openmp || flag_openmp_simd)
838760c2415Smrg 		&& flag_openacc)
839760c2415Smrg 	      {
840760c2415Smrg 		locus old_loc = gfc_current_locus;
841760c2415Smrg 		if (next_char () == '$')
842760c2415Smrg 		  {
843760c2415Smrg 		    c = next_char ();
844760c2415Smrg 		    if (c == 'o' || c == 'O')
845760c2415Smrg 		      {
846760c2415Smrg 			if (skip_free_omp_sentinel (start, old_loc))
847760c2415Smrg 			  return false;
848760c2415Smrg 			gfc_current_locus = old_loc;
849760c2415Smrg 			next_char ();
850760c2415Smrg 			c = next_char ();
851760c2415Smrg 		      }
852760c2415Smrg 		    else if (c == 'a' || c == 'A')
853760c2415Smrg 		      {
854760c2415Smrg 			if (skip_free_oacc_sentinel (start, old_loc))
855760c2415Smrg 			  return false;
856760c2415Smrg 			gfc_current_locus = old_loc;
857760c2415Smrg 			next_char ();
858760c2415Smrg 			c = next_char ();
859760c2415Smrg 		      }
860760c2415Smrg 		    if (continue_flag || c == ' ' || c == '\t')
861760c2415Smrg 		      {
862760c2415Smrg 			gfc_current_locus = old_loc;
863760c2415Smrg 			next_char ();
864760c2415Smrg 			openmp_flag = openacc_flag = 0;
865760c2415Smrg 			return true;
866760c2415Smrg 		      }
867760c2415Smrg 		  }
868760c2415Smrg 		gfc_current_locus = old_loc;
869760c2415Smrg 	      }
870760c2415Smrg 	    else if ((flag_openmp || flag_openmp_simd)
871760c2415Smrg 		     && !flag_openacc)
872760c2415Smrg 	      {
873760c2415Smrg 		locus old_loc = gfc_current_locus;
874760c2415Smrg 		if (next_char () == '$')
875760c2415Smrg 		  {
876760c2415Smrg 		    c = next_char ();
877760c2415Smrg 		    if (c == 'o' || c == 'O')
878760c2415Smrg 		      {
879760c2415Smrg 			if (skip_free_omp_sentinel (start, old_loc))
880760c2415Smrg 			  return false;
881760c2415Smrg 			gfc_current_locus = old_loc;
882760c2415Smrg 			next_char ();
883760c2415Smrg 			c = next_char ();
884760c2415Smrg 		      }
885760c2415Smrg 		    if (continue_flag || c == ' ' || c == '\t')
886760c2415Smrg 		      {
887760c2415Smrg 			gfc_current_locus = old_loc;
888760c2415Smrg 			next_char ();
889760c2415Smrg 			openmp_flag = 0;
890760c2415Smrg 			return true;
891760c2415Smrg 		      }
892760c2415Smrg 		  }
893760c2415Smrg 		gfc_current_locus = old_loc;
894760c2415Smrg 	      }
895760c2415Smrg 	    else if (flag_openacc
896760c2415Smrg 		     && !(flag_openmp || flag_openmp_simd))
897760c2415Smrg 	      {
898760c2415Smrg 		locus old_loc = gfc_current_locus;
899760c2415Smrg 		if (next_char () == '$')
900760c2415Smrg 		  {
901760c2415Smrg 		    c = next_char ();
902760c2415Smrg 		      if (c == 'a' || c == 'A')
903760c2415Smrg 			{
904760c2415Smrg 			  if (skip_free_oacc_sentinel (start, old_loc))
905760c2415Smrg 			    return false;
906760c2415Smrg 			  gfc_current_locus = old_loc;
907760c2415Smrg 			  next_char();
908760c2415Smrg 			  c = next_char();
909760c2415Smrg 			}
910760c2415Smrg 		      if (continue_flag || c == ' ' || c == '\t')
911760c2415Smrg 			{
912760c2415Smrg 			  gfc_current_locus = old_loc;
913760c2415Smrg 			  next_char();
914760c2415Smrg 			  openacc_flag = 0;
915760c2415Smrg 			  return true;
916760c2415Smrg 			}
917760c2415Smrg 		  }
918760c2415Smrg 		gfc_current_locus = old_loc;
919760c2415Smrg 	      }
920760c2415Smrg 	  }
921760c2415Smrg 	  skip_comment_line ();
922760c2415Smrg 	  continue;
923760c2415Smrg 	}
924760c2415Smrg 
925760c2415Smrg       break;
926760c2415Smrg     }
927760c2415Smrg 
928760c2415Smrg   if (openmp_flag && at_bol)
929760c2415Smrg     openmp_flag = 0;
930760c2415Smrg 
931760c2415Smrg   if (openacc_flag && at_bol)
932760c2415Smrg     openacc_flag = 0;
933760c2415Smrg 
934760c2415Smrg   gcc_attribute_flag = 0;
935760c2415Smrg   gfc_current_locus = start;
936760c2415Smrg   return false;
937760c2415Smrg }
938760c2415Smrg 
939760c2415Smrg /* Return true if MP was matched in fixed form.  */
940760c2415Smrg static bool
skip_fixed_omp_sentinel(locus * start)941760c2415Smrg skip_fixed_omp_sentinel (locus *start)
942760c2415Smrg {
943760c2415Smrg   gfc_char_t c;
944760c2415Smrg   if (((c = next_char ()) == 'm' || c == 'M')
945760c2415Smrg       && ((c = next_char ()) == 'p' || c == 'P'))
946760c2415Smrg     {
947760c2415Smrg       c = next_char ();
948760c2415Smrg       if (c != '\n'
949760c2415Smrg 	  && (continue_flag
950760c2415Smrg 	      || c == ' ' || c == '\t' || c == '0'))
951760c2415Smrg 	{
952760c2415Smrg 	  do
953760c2415Smrg 	    c = next_char ();
954760c2415Smrg 	  while (gfc_is_whitespace (c));
955760c2415Smrg 	  if (c != '\n' && c != '!')
956760c2415Smrg 	    {
957760c2415Smrg 	      /* Canonicalize to *$omp.  */
958760c2415Smrg 	      *start->nextc = '*';
959760c2415Smrg 	      openmp_flag = 1;
960760c2415Smrg 	      gfc_current_locus = *start;
961760c2415Smrg 	      return true;
962760c2415Smrg 	    }
963760c2415Smrg 	}
964760c2415Smrg     }
965760c2415Smrg   return false;
966760c2415Smrg }
967760c2415Smrg 
968760c2415Smrg /* Return true if CC was matched in fixed form.  */
969760c2415Smrg static bool
skip_fixed_oacc_sentinel(locus * start)970760c2415Smrg skip_fixed_oacc_sentinel (locus *start)
971760c2415Smrg {
972760c2415Smrg   gfc_char_t c;
973760c2415Smrg   if (((c = next_char ()) == 'c' || c == 'C')
974760c2415Smrg       && ((c = next_char ()) == 'c' || c == 'C'))
975760c2415Smrg     {
976760c2415Smrg       c = next_char ();
977760c2415Smrg       if (c != '\n'
978760c2415Smrg 	  && (continue_flag
979760c2415Smrg 	      || c == ' ' || c == '\t' || c == '0'))
980760c2415Smrg 	{
981760c2415Smrg 	  do
982760c2415Smrg 	    c = next_char ();
983760c2415Smrg 	  while (gfc_is_whitespace (c));
984760c2415Smrg 	  if (c != '\n' && c != '!')
985760c2415Smrg 	    {
986760c2415Smrg 	      /* Canonicalize to *$acc.  */
987760c2415Smrg 	      *start->nextc = '*';
988760c2415Smrg 	      openacc_flag = 1;
989760c2415Smrg 	      gfc_current_locus = *start;
990760c2415Smrg 	      return true;
991760c2415Smrg 	    }
992760c2415Smrg 	}
993760c2415Smrg     }
994760c2415Smrg   return false;
995760c2415Smrg }
996760c2415Smrg 
997760c2415Smrg /* Skip comment lines in fixed source mode.  We have the same rules as
998760c2415Smrg    in skip_free_comment(), except that we can have a 'c', 'C' or '*'
999760c2415Smrg    in column 1, and a '!' cannot be in column 6.  Also, we deal with
1000760c2415Smrg    lines with 'd' or 'D' in column 1, if the user requested this.  */
1001760c2415Smrg 
1002760c2415Smrg static void
skip_fixed_comments(void)1003760c2415Smrg skip_fixed_comments (void)
1004760c2415Smrg {
1005760c2415Smrg   locus start;
1006760c2415Smrg   int col;
1007760c2415Smrg   gfc_char_t c;
1008760c2415Smrg 
1009760c2415Smrg   if (! gfc_at_bol ())
1010760c2415Smrg     {
1011760c2415Smrg       start = gfc_current_locus;
1012760c2415Smrg       if (! gfc_at_eof ())
1013760c2415Smrg 	{
1014760c2415Smrg 	  do
1015760c2415Smrg 	    c = next_char ();
1016760c2415Smrg 	  while (gfc_is_whitespace (c));
1017760c2415Smrg 
1018760c2415Smrg 	  if (c == '\n')
1019760c2415Smrg 	    gfc_advance_line ();
1020760c2415Smrg 	  else if (c == '!')
1021760c2415Smrg 	    skip_comment_line ();
1022760c2415Smrg 	}
1023760c2415Smrg 
1024760c2415Smrg       if (! gfc_at_bol ())
1025760c2415Smrg 	{
1026760c2415Smrg 	  gfc_current_locus = start;
1027760c2415Smrg 	  return;
1028760c2415Smrg 	}
1029760c2415Smrg     }
1030760c2415Smrg 
1031760c2415Smrg   for (;;)
1032760c2415Smrg     {
1033760c2415Smrg       start = gfc_current_locus;
1034760c2415Smrg       if (gfc_at_eof ())
1035760c2415Smrg 	break;
1036760c2415Smrg 
1037760c2415Smrg       c = next_char ();
1038760c2415Smrg       if (c == '\n')
1039760c2415Smrg 	{
1040760c2415Smrg 	  gfc_advance_line ();
1041760c2415Smrg 	  continue;
1042760c2415Smrg 	}
1043760c2415Smrg 
1044760c2415Smrg       if (c == '!' || c == 'c' || c == 'C' || c == '*')
1045760c2415Smrg 	{
1046760c2415Smrg 	  if (skip_gcc_attribute (start))
1047760c2415Smrg 	    {
1048760c2415Smrg 	      /* Canonicalize to *$omp.  */
1049760c2415Smrg 	      *start.nextc = '*';
1050760c2415Smrg 	      return;
1051760c2415Smrg 	    }
1052760c2415Smrg 
1053760c2415Smrg 	  if (gfc_current_locus.lb != NULL
1054760c2415Smrg 	      && continue_line < gfc_linebuf_linenum (gfc_current_locus.lb))
1055760c2415Smrg 	    continue_line = gfc_linebuf_linenum (gfc_current_locus.lb);
1056760c2415Smrg 
1057760c2415Smrg 	  /* If -fopenmp/-fopenacc, we need to handle here 2 things:
1058760c2415Smrg 	     1) don't treat !$omp/!$acc|c$omp/c$acc|*$omp / *$acc as comments,
1059760c2415Smrg 		but directives
1060760c2415Smrg 	     2) handle OpenMP/OpenACC conditional compilation, where
1061760c2415Smrg 		!$|c$|*$ should be treated as 2 spaces if the characters
1062760c2415Smrg 		in columns 3 to 6 are valid fixed form label columns
1063760c2415Smrg 		characters.  */
1064760c2415Smrg 	  if ((flag_openmp || flag_openmp_simd) && !flag_openacc)
1065760c2415Smrg 	    {
1066760c2415Smrg 	      if (next_char () == '$')
1067760c2415Smrg 		{
1068760c2415Smrg 		  c = next_char ();
1069760c2415Smrg 		  if (c == 'o' || c == 'O')
1070760c2415Smrg 		    {
1071760c2415Smrg 		      if (skip_fixed_omp_sentinel (&start))
1072760c2415Smrg 			return;
1073760c2415Smrg 		    }
1074760c2415Smrg 		  else
1075760c2415Smrg 		    goto check_for_digits;
1076760c2415Smrg 		}
1077760c2415Smrg 	      gfc_current_locus = start;
1078760c2415Smrg 	    }
1079760c2415Smrg 
1080760c2415Smrg 	  if (flag_openacc && !(flag_openmp || flag_openmp_simd))
1081760c2415Smrg 	    {
1082760c2415Smrg 	      if (next_char () == '$')
1083760c2415Smrg 		{
1084760c2415Smrg 		  c = next_char ();
1085760c2415Smrg 		  if (c == 'a' || c == 'A')
1086760c2415Smrg 		    {
1087760c2415Smrg 		      if (skip_fixed_oacc_sentinel (&start))
1088760c2415Smrg 			return;
1089760c2415Smrg 		    }
1090760c2415Smrg 		  else
1091760c2415Smrg 		    goto check_for_digits;
1092760c2415Smrg 		}
1093760c2415Smrg 	      gfc_current_locus = start;
1094760c2415Smrg 	    }
1095760c2415Smrg 
1096760c2415Smrg 	  if (flag_openacc || flag_openmp || flag_openmp_simd)
1097760c2415Smrg 	    {
1098760c2415Smrg 	      if (next_char () == '$')
1099760c2415Smrg 		{
1100760c2415Smrg 		  c = next_char ();
1101760c2415Smrg 		  if (c == 'a' || c == 'A')
1102760c2415Smrg 		    {
1103760c2415Smrg 		      if (skip_fixed_oacc_sentinel (&start))
1104760c2415Smrg 			return;
1105760c2415Smrg 		    }
1106760c2415Smrg 		  else if (c == 'o' || c == 'O')
1107760c2415Smrg 		    {
1108760c2415Smrg 		      if (skip_fixed_omp_sentinel (&start))
1109760c2415Smrg 			return;
1110760c2415Smrg 		    }
1111760c2415Smrg 		  else
1112760c2415Smrg 		    goto check_for_digits;
1113760c2415Smrg 		}
1114760c2415Smrg 	      gfc_current_locus = start;
1115760c2415Smrg 	    }
1116760c2415Smrg 
1117760c2415Smrg 	  skip_comment_line ();
1118760c2415Smrg 	  continue;
1119760c2415Smrg 
1120760c2415Smrg 	  gcc_unreachable ();
1121760c2415Smrg check_for_digits:
1122760c2415Smrg 	  {
1123760c2415Smrg 	    int digit_seen = 0;
1124760c2415Smrg 
1125760c2415Smrg 	    for (col = 3; col < 6; col++, c = next_char ())
1126760c2415Smrg 	      if (c == ' ')
1127760c2415Smrg 		continue;
1128760c2415Smrg 	      else if (c == '\t')
1129760c2415Smrg 		{
1130760c2415Smrg 		  col = 6;
1131760c2415Smrg 		  break;
1132760c2415Smrg 		}
1133760c2415Smrg 	      else if (c < '0' || c > '9')
1134760c2415Smrg 		break;
1135760c2415Smrg 	      else
1136760c2415Smrg 		digit_seen = 1;
1137760c2415Smrg 
1138760c2415Smrg 	    if (col == 6 && c != '\n'
1139760c2415Smrg 		&& ((continue_flag && !digit_seen)
1140760c2415Smrg 		    || c == ' ' || c == '\t' || c == '0'))
1141760c2415Smrg 	      {
1142760c2415Smrg 		gfc_current_locus = start;
1143760c2415Smrg 		start.nextc[0] = ' ';
1144760c2415Smrg 		start.nextc[1] = ' ';
1145760c2415Smrg 		continue;
1146760c2415Smrg 	      }
1147760c2415Smrg 	    }
1148760c2415Smrg 	  skip_comment_line ();
1149760c2415Smrg 	  continue;
1150760c2415Smrg 	}
1151760c2415Smrg 
1152760c2415Smrg       if (gfc_option.flag_d_lines != -1 && (c == 'd' || c == 'D'))
1153760c2415Smrg 	{
1154760c2415Smrg 	  if (gfc_option.flag_d_lines == 0)
1155760c2415Smrg 	    {
1156760c2415Smrg 	      skip_comment_line ();
1157760c2415Smrg 	      continue;
1158760c2415Smrg 	    }
1159760c2415Smrg 	  else
1160760c2415Smrg 	    *start.nextc = c = ' ';
1161760c2415Smrg 	}
1162760c2415Smrg 
1163760c2415Smrg       col = 1;
1164760c2415Smrg 
1165760c2415Smrg       while (gfc_is_whitespace (c))
1166760c2415Smrg 	{
1167760c2415Smrg 	  c = next_char ();
1168760c2415Smrg 	  col++;
1169760c2415Smrg 	}
1170760c2415Smrg 
1171760c2415Smrg       if (c == '\n')
1172760c2415Smrg 	{
1173760c2415Smrg 	  gfc_advance_line ();
1174760c2415Smrg 	  continue;
1175760c2415Smrg 	}
1176760c2415Smrg 
1177760c2415Smrg       if (col != 6 && c == '!')
1178760c2415Smrg 	{
1179760c2415Smrg 	  if (gfc_current_locus.lb != NULL
1180760c2415Smrg 	      && continue_line < gfc_linebuf_linenum (gfc_current_locus.lb))
1181760c2415Smrg 	    continue_line = gfc_linebuf_linenum (gfc_current_locus.lb);
1182760c2415Smrg 	  skip_comment_line ();
1183760c2415Smrg 	  continue;
1184760c2415Smrg 	}
1185760c2415Smrg 
1186760c2415Smrg       break;
1187760c2415Smrg     }
1188760c2415Smrg 
1189760c2415Smrg   openmp_flag = 0;
1190760c2415Smrg   openacc_flag = 0;
1191760c2415Smrg   gcc_attribute_flag = 0;
1192760c2415Smrg   gfc_current_locus = start;
1193760c2415Smrg }
1194760c2415Smrg 
1195760c2415Smrg 
1196760c2415Smrg /* Skips the current line if it is a comment.  */
1197760c2415Smrg 
1198760c2415Smrg void
gfc_skip_comments(void)1199760c2415Smrg gfc_skip_comments (void)
1200760c2415Smrg {
1201760c2415Smrg   if (gfc_current_form == FORM_FREE)
1202760c2415Smrg     skip_free_comments ();
1203760c2415Smrg   else
1204760c2415Smrg     skip_fixed_comments ();
1205760c2415Smrg }
1206760c2415Smrg 
1207760c2415Smrg 
1208760c2415Smrg /* Get the next character from the input, taking continuation lines
1209760c2415Smrg    and end-of-line comments into account.  This implies that comment
1210760c2415Smrg    lines between continued lines must be eaten here.  For higher-level
1211760c2415Smrg    subroutines, this flattens continued lines into a single logical
1212760c2415Smrg    line.  The in_string flag denotes whether we're inside a character
1213760c2415Smrg    context or not.  */
1214760c2415Smrg 
1215760c2415Smrg gfc_char_t
gfc_next_char_literal(gfc_instring in_string)1216760c2415Smrg gfc_next_char_literal (gfc_instring in_string)
1217760c2415Smrg {
1218760c2415Smrg   locus old_loc;
1219760c2415Smrg   int i, prev_openmp_flag, prev_openacc_flag;
1220760c2415Smrg   gfc_char_t c;
1221760c2415Smrg 
1222760c2415Smrg   continue_flag = 0;
1223760c2415Smrg   prev_openacc_flag = prev_openmp_flag = 0;
1224760c2415Smrg 
1225760c2415Smrg restart:
1226760c2415Smrg   c = next_char ();
1227760c2415Smrg   if (gfc_at_end ())
1228760c2415Smrg     {
1229760c2415Smrg       continue_count = 0;
1230760c2415Smrg       return c;
1231760c2415Smrg     }
1232760c2415Smrg 
1233760c2415Smrg   if (gfc_current_form == FORM_FREE)
1234760c2415Smrg     {
1235760c2415Smrg       bool openmp_cond_flag;
1236760c2415Smrg 
1237760c2415Smrg       if (!in_string && c == '!')
1238760c2415Smrg 	{
1239760c2415Smrg 	  if (gcc_attribute_flag
1240760c2415Smrg 	      && memcmp (&gfc_current_locus, &gcc_attribute_locus,
1241760c2415Smrg 		 sizeof (gfc_current_locus)) == 0)
1242760c2415Smrg 	    goto done;
1243760c2415Smrg 
1244760c2415Smrg 	  if (openmp_flag
1245760c2415Smrg 	      && memcmp (&gfc_current_locus, &openmp_locus,
1246760c2415Smrg 		 sizeof (gfc_current_locus)) == 0)
1247760c2415Smrg 	    goto done;
1248760c2415Smrg 
1249760c2415Smrg 	  if (openacc_flag
1250760c2415Smrg 	      && memcmp (&gfc_current_locus, &openacc_locus,
1251760c2415Smrg 	         sizeof (gfc_current_locus)) == 0)
1252760c2415Smrg 	    goto done;
1253760c2415Smrg 
1254760c2415Smrg 	  /* This line can't be continued */
1255760c2415Smrg 	  do
1256760c2415Smrg 	    {
1257760c2415Smrg 	      c = next_char ();
1258760c2415Smrg 	    }
1259760c2415Smrg 	  while (c != '\n');
1260760c2415Smrg 
1261760c2415Smrg 	  /* Avoid truncation warnings for comment ending lines.  */
1262760c2415Smrg 	  gfc_current_locus.lb->truncated = 0;
1263760c2415Smrg 
1264760c2415Smrg 	  goto done;
1265760c2415Smrg 	}
1266760c2415Smrg 
1267760c2415Smrg       /* Check to see if the continuation line was truncated.  */
1268760c2415Smrg       if (warn_line_truncation && gfc_current_locus.lb != NULL
1269760c2415Smrg 	  && gfc_current_locus.lb->truncated)
1270760c2415Smrg 	{
1271760c2415Smrg 	  int maxlen = flag_free_line_length;
1272760c2415Smrg 	  gfc_char_t *current_nextc = gfc_current_locus.nextc;
1273760c2415Smrg 
1274760c2415Smrg 	  gfc_current_locus.lb->truncated = 0;
1275760c2415Smrg 	  gfc_current_locus.nextc =  gfc_current_locus.lb->line + maxlen;
1276760c2415Smrg 	  gfc_warning_now (OPT_Wline_truncation,
1277760c2415Smrg 			   "Line truncated at %L", &gfc_current_locus);
1278760c2415Smrg 	  gfc_current_locus.nextc = current_nextc;
1279760c2415Smrg 	}
1280760c2415Smrg 
1281760c2415Smrg       if (c != '&')
1282760c2415Smrg 	goto done;
1283760c2415Smrg 
1284760c2415Smrg       /* If the next nonblank character is a ! or \n, we've got a
1285760c2415Smrg 	 continuation line.  */
1286760c2415Smrg       old_loc = gfc_current_locus;
1287760c2415Smrg 
1288760c2415Smrg       c = next_char ();
1289760c2415Smrg       while (gfc_is_whitespace (c))
1290760c2415Smrg 	c = next_char ();
1291760c2415Smrg 
1292760c2415Smrg       /* Character constants to be continued cannot have commentary
1293760c2415Smrg 	 after the '&'. However, there are cases where we may think we
1294760c2415Smrg 	 are still in a string and we are looking for a possible
1295760c2415Smrg 	 doubled quote and we end up here. See PR64506.  */
1296760c2415Smrg 
1297760c2415Smrg       if (in_string && c != '\n')
1298760c2415Smrg 	{
1299760c2415Smrg 	  gfc_current_locus = old_loc;
1300760c2415Smrg 	  c = '&';
1301760c2415Smrg 	  goto done;
1302760c2415Smrg 	}
1303760c2415Smrg 
1304760c2415Smrg       if (c != '!' && c != '\n')
1305760c2415Smrg 	{
1306760c2415Smrg 	  gfc_current_locus = old_loc;
1307760c2415Smrg 	  c = '&';
1308760c2415Smrg 	  goto done;
1309760c2415Smrg 	}
1310760c2415Smrg 
1311760c2415Smrg       if (flag_openmp)
1312760c2415Smrg 	prev_openmp_flag = openmp_flag;
1313760c2415Smrg       if (flag_openacc)
1314760c2415Smrg 	prev_openacc_flag = openacc_flag;
1315760c2415Smrg 
1316760c2415Smrg       /* This can happen if the input file changed or via cpp's #line
1317760c2415Smrg 	 without getting reset (e.g. via input_stmt). It also happens
1318760c2415Smrg 	 when pre-including files via -fpre-include=.  */
1319760c2415Smrg       if (continue_count == 0
1320760c2415Smrg 	  && gfc_current_locus.lb
1321760c2415Smrg 	  && continue_line > gfc_linebuf_linenum (gfc_current_locus.lb) + 1)
1322760c2415Smrg 	continue_line = gfc_linebuf_linenum (gfc_current_locus.lb) + 1;
1323760c2415Smrg 
1324760c2415Smrg       continue_flag = 1;
1325760c2415Smrg       if (c == '!')
1326760c2415Smrg 	skip_comment_line ();
1327760c2415Smrg       else
1328760c2415Smrg 	gfc_advance_line ();
1329760c2415Smrg 
1330760c2415Smrg       if (gfc_at_eof ())
1331760c2415Smrg 	goto not_continuation;
1332760c2415Smrg 
1333760c2415Smrg       /* We've got a continuation line.  If we are on the very next line after
1334760c2415Smrg 	 the last continuation, increment the continuation line count and
1335760c2415Smrg 	 check whether the limit has been exceeded.  */
1336760c2415Smrg       if (gfc_linebuf_linenum (gfc_current_locus.lb) == continue_line + 1)
1337760c2415Smrg 	{
1338760c2415Smrg 	  if (++continue_count == gfc_option.max_continue_free)
1339760c2415Smrg 	    {
1340760c2415Smrg 	      if (gfc_notification_std (GFC_STD_GNU) || pedantic)
1341760c2415Smrg 		gfc_warning (0, "Limit of %d continuations exceeded in "
1342760c2415Smrg 			     "statement at %C", gfc_option.max_continue_free);
1343760c2415Smrg 	    }
1344760c2415Smrg 	}
1345760c2415Smrg 
1346760c2415Smrg       /* Now find where it continues. First eat any comment lines.  */
1347760c2415Smrg       openmp_cond_flag = skip_free_comments ();
1348760c2415Smrg 
1349760c2415Smrg       if (gfc_current_locus.lb != NULL
1350760c2415Smrg 	  && continue_line < gfc_linebuf_linenum (gfc_current_locus.lb))
1351760c2415Smrg 	continue_line = gfc_linebuf_linenum (gfc_current_locus.lb);
1352760c2415Smrg 
1353760c2415Smrg       if (flag_openmp)
1354760c2415Smrg 	if (prev_openmp_flag != openmp_flag && !openacc_flag)
1355760c2415Smrg 	  {
1356760c2415Smrg 	    gfc_current_locus = old_loc;
1357760c2415Smrg 	    openmp_flag = prev_openmp_flag;
1358760c2415Smrg 	    c = '&';
1359760c2415Smrg 	    goto done;
1360760c2415Smrg 	  }
1361760c2415Smrg 
1362760c2415Smrg       if (flag_openacc)
1363760c2415Smrg 	if (prev_openacc_flag != openacc_flag && !openmp_flag)
1364760c2415Smrg 	  {
1365760c2415Smrg 	    gfc_current_locus = old_loc;
1366760c2415Smrg 	    openacc_flag = prev_openacc_flag;
1367760c2415Smrg 	    c = '&';
1368760c2415Smrg 	    goto done;
1369760c2415Smrg 	  }
1370760c2415Smrg 
1371760c2415Smrg       /* Now that we have a non-comment line, probe ahead for the
1372760c2415Smrg 	 first non-whitespace character.  If it is another '&', then
1373760c2415Smrg 	 reading starts at the next character, otherwise we must back
1374760c2415Smrg 	 up to where the whitespace started and resume from there.  */
1375760c2415Smrg 
1376760c2415Smrg       old_loc = gfc_current_locus;
1377760c2415Smrg 
1378760c2415Smrg       c = next_char ();
1379760c2415Smrg       while (gfc_is_whitespace (c))
1380760c2415Smrg 	c = next_char ();
1381760c2415Smrg 
1382760c2415Smrg       if (openmp_flag && !openacc_flag)
1383760c2415Smrg 	{
1384760c2415Smrg 	  for (i = 0; i < 5; i++, c = next_char ())
1385760c2415Smrg 	    {
1386760c2415Smrg 	      gcc_assert (gfc_wide_tolower (c) == (unsigned char) "!$omp"[i]);
1387760c2415Smrg 	      if (i == 4)
1388760c2415Smrg 		old_loc = gfc_current_locus;
1389760c2415Smrg 	    }
1390760c2415Smrg 	  while (gfc_is_whitespace (c))
1391760c2415Smrg 	    c = next_char ();
1392760c2415Smrg 	}
1393760c2415Smrg       if (openacc_flag && !openmp_flag)
1394760c2415Smrg 	{
1395760c2415Smrg 	  for (i = 0; i < 5; i++, c = next_char ())
1396760c2415Smrg 	    {
1397760c2415Smrg 	      gcc_assert (gfc_wide_tolower (c) == (unsigned char) "!$acc"[i]);
1398760c2415Smrg 	      if (i == 4)
1399760c2415Smrg 		old_loc = gfc_current_locus;
1400760c2415Smrg 	    }
1401760c2415Smrg 	  while (gfc_is_whitespace (c))
1402760c2415Smrg 	    c = next_char ();
1403760c2415Smrg 	}
1404760c2415Smrg 
1405760c2415Smrg       /* In case we have an OpenMP directive continued by OpenACC
1406760c2415Smrg 	 sentinel, or vice versa, we get both openmp_flag and
1407760c2415Smrg 	 openacc_flag on.  */
1408760c2415Smrg 
1409760c2415Smrg       if (openacc_flag && openmp_flag)
1410760c2415Smrg 	{
1411760c2415Smrg 	  int is_openmp = 0;
1412760c2415Smrg 	  for (i = 0; i < 5; i++, c = next_char ())
1413760c2415Smrg 	    {
1414760c2415Smrg 	      if (gfc_wide_tolower (c) != (unsigned char) "!$acc"[i])
1415760c2415Smrg 		is_openmp = 1;
1416760c2415Smrg 	      if (i == 4)
1417760c2415Smrg 		old_loc = gfc_current_locus;
1418760c2415Smrg 	    }
1419760c2415Smrg 	  gfc_error (is_openmp
1420760c2415Smrg 		     ? G_("Wrong OpenACC continuation at %C: "
1421760c2415Smrg 			  "expected !$ACC, got !$OMP")
1422760c2415Smrg 		     : G_("Wrong OpenMP continuation at %C: "
1423760c2415Smrg 			  "expected !$OMP, got !$ACC"));
1424760c2415Smrg 	}
1425760c2415Smrg 
1426760c2415Smrg       if (c != '&')
1427760c2415Smrg 	{
1428760c2415Smrg 	  if (in_string && gfc_current_locus.nextc)
1429760c2415Smrg 	    {
1430760c2415Smrg 	      gfc_current_locus.nextc--;
1431760c2415Smrg 	      if (warn_ampersand && in_string == INSTRING_WARN)
1432760c2415Smrg 		gfc_warning (OPT_Wampersand,
1433760c2415Smrg 			     "Missing %<&%> in continued character "
1434760c2415Smrg 			     "constant at %C");
1435760c2415Smrg 	    }
1436760c2415Smrg 	  else if (!in_string && (c == '\'' || c == '"'))
1437760c2415Smrg 	      goto done;
1438760c2415Smrg 	  /* Both !$omp and !$ -fopenmp continuation lines have & on the
1439760c2415Smrg 	     continuation line only optionally.  */
1440760c2415Smrg 	  else if (openmp_flag || openacc_flag || openmp_cond_flag)
1441760c2415Smrg 	    {
1442760c2415Smrg 	      if (gfc_current_locus.nextc)
1443760c2415Smrg 		  gfc_current_locus.nextc--;
1444760c2415Smrg 	    }
1445760c2415Smrg 	  else
1446760c2415Smrg 	    {
1447760c2415Smrg 	      c = ' ';
1448760c2415Smrg 	      gfc_current_locus = old_loc;
1449760c2415Smrg 	      goto done;
1450760c2415Smrg 	    }
1451760c2415Smrg 	}
1452760c2415Smrg     }
1453760c2415Smrg   else /* Fixed form.  */
1454760c2415Smrg     {
1455760c2415Smrg       /* Fixed form continuation.  */
1456760c2415Smrg       if (in_string != INSTRING_WARN && c == '!')
1457760c2415Smrg 	{
1458760c2415Smrg 	  /* Skip comment at end of line.  */
1459760c2415Smrg 	  do
1460760c2415Smrg 	    {
1461760c2415Smrg 	      c = next_char ();
1462760c2415Smrg 	    }
1463760c2415Smrg 	  while (c != '\n');
1464760c2415Smrg 
1465760c2415Smrg 	  /* Avoid truncation warnings for comment ending lines.  */
1466760c2415Smrg 	  gfc_current_locus.lb->truncated = 0;
1467760c2415Smrg 	}
1468760c2415Smrg 
1469760c2415Smrg       if (c != '\n')
1470760c2415Smrg 	goto done;
1471760c2415Smrg 
1472760c2415Smrg       /* Check to see if the continuation line was truncated.  */
1473760c2415Smrg       if (warn_line_truncation && gfc_current_locus.lb != NULL
1474760c2415Smrg 	  && gfc_current_locus.lb->truncated)
1475760c2415Smrg 	{
1476760c2415Smrg 	  gfc_current_locus.lb->truncated = 0;
1477760c2415Smrg 	  gfc_warning_now (OPT_Wline_truncation,
1478760c2415Smrg 			   "Line truncated at %L", &gfc_current_locus);
1479760c2415Smrg 	}
1480760c2415Smrg 
1481760c2415Smrg       if (flag_openmp)
1482760c2415Smrg 	prev_openmp_flag = openmp_flag;
1483760c2415Smrg       if (flag_openacc)
1484760c2415Smrg 	prev_openacc_flag = openacc_flag;
1485760c2415Smrg 
1486760c2415Smrg       /* This can happen if the input file changed or via cpp's #line
1487760c2415Smrg 	 without getting reset (e.g. via input_stmt). It also happens
1488760c2415Smrg 	 when pre-including files via -fpre-include=.  */
1489760c2415Smrg       if (continue_count == 0
1490760c2415Smrg 	  && gfc_current_locus.lb
1491760c2415Smrg 	  && continue_line > gfc_linebuf_linenum (gfc_current_locus.lb) + 1)
1492760c2415Smrg 	continue_line = gfc_linebuf_linenum (gfc_current_locus.lb) + 1;
1493760c2415Smrg 
1494760c2415Smrg       continue_flag = 1;
1495760c2415Smrg       old_loc = gfc_current_locus;
1496760c2415Smrg 
1497760c2415Smrg       gfc_advance_line ();
1498760c2415Smrg       skip_fixed_comments ();
1499760c2415Smrg 
1500760c2415Smrg       /* See if this line is a continuation line.  */
1501760c2415Smrg       if (flag_openmp && openmp_flag != prev_openmp_flag && !openacc_flag)
1502760c2415Smrg 	{
1503760c2415Smrg 	  openmp_flag = prev_openmp_flag;
1504760c2415Smrg 	  goto not_continuation;
1505760c2415Smrg 	}
1506760c2415Smrg       if (flag_openacc && openacc_flag != prev_openacc_flag && !openmp_flag)
1507760c2415Smrg 	{
1508760c2415Smrg 	  openacc_flag = prev_openacc_flag;
1509760c2415Smrg 	  goto not_continuation;
1510760c2415Smrg 	}
1511760c2415Smrg 
1512760c2415Smrg       /* In case we have an OpenMP directive continued by OpenACC
1513760c2415Smrg 	 sentinel, or vice versa, we get both openmp_flag and
1514760c2415Smrg 	 openacc_flag on.  */
1515760c2415Smrg       if (openacc_flag && openmp_flag)
1516760c2415Smrg 	{
1517760c2415Smrg 	  int is_openmp = 0;
1518760c2415Smrg 	  for (i = 0; i < 5; i++)
1519760c2415Smrg 	    {
1520760c2415Smrg 	      c = next_char ();
1521760c2415Smrg 	      if (gfc_wide_tolower (c) != (unsigned char) "*$acc"[i])
1522760c2415Smrg 		is_openmp = 1;
1523760c2415Smrg 	    }
1524760c2415Smrg 	  gfc_error (is_openmp
1525760c2415Smrg 		     ? G_("Wrong OpenACC continuation at %C: "
1526760c2415Smrg 			  "expected !$ACC, got !$OMP")
1527760c2415Smrg 		     : G_("Wrong OpenMP continuation at %C: "
1528760c2415Smrg 			  "expected !$OMP, got !$ACC"));
1529760c2415Smrg 	}
1530760c2415Smrg       else if (!openmp_flag && !openacc_flag)
1531760c2415Smrg 	for (i = 0; i < 5; i++)
1532760c2415Smrg 	  {
1533760c2415Smrg 	    c = next_char ();
1534760c2415Smrg 	    if (c != ' ')
1535760c2415Smrg 	      goto not_continuation;
1536760c2415Smrg 	  }
1537760c2415Smrg       else if (openmp_flag)
1538760c2415Smrg 	for (i = 0; i < 5; i++)
1539760c2415Smrg 	  {
1540760c2415Smrg 	    c = next_char ();
1541760c2415Smrg 	    if (gfc_wide_tolower (c) != (unsigned char) "*$omp"[i])
1542760c2415Smrg 	      goto not_continuation;
1543760c2415Smrg 	  }
1544760c2415Smrg       else if (openacc_flag)
1545760c2415Smrg 	for (i = 0; i < 5; i++)
1546760c2415Smrg 	  {
1547760c2415Smrg 	    c = next_char ();
1548760c2415Smrg 	    if (gfc_wide_tolower (c) != (unsigned char) "*$acc"[i])
1549760c2415Smrg 	      goto not_continuation;
1550760c2415Smrg 	  }
1551760c2415Smrg 
1552760c2415Smrg       c = next_char ();
1553760c2415Smrg       if (c == '0' || c == ' ' || c == '\n')
1554760c2415Smrg 	goto not_continuation;
1555760c2415Smrg 
1556760c2415Smrg       /* We've got a continuation line.  If we are on the very next line after
1557760c2415Smrg 	 the last continuation, increment the continuation line count and
1558760c2415Smrg 	 check whether the limit has been exceeded.  */
1559760c2415Smrg       if (gfc_linebuf_linenum (gfc_current_locus.lb) == continue_line + 1)
1560760c2415Smrg 	{
1561760c2415Smrg 	  if (++continue_count == gfc_option.max_continue_fixed)
1562760c2415Smrg 	    {
1563760c2415Smrg 	      if (gfc_notification_std (GFC_STD_GNU) || pedantic)
1564760c2415Smrg 		gfc_warning (0, "Limit of %d continuations exceeded in "
1565760c2415Smrg 			     "statement at %C",
1566760c2415Smrg 			     gfc_option.max_continue_fixed);
1567760c2415Smrg 	    }
1568760c2415Smrg 	}
1569760c2415Smrg 
1570760c2415Smrg       if (gfc_current_locus.lb != NULL
1571760c2415Smrg 	  && continue_line < gfc_linebuf_linenum (gfc_current_locus.lb))
1572760c2415Smrg 	continue_line = gfc_linebuf_linenum (gfc_current_locus.lb);
1573760c2415Smrg     }
1574760c2415Smrg 
1575760c2415Smrg   /* Ready to read first character of continuation line, which might
1576760c2415Smrg      be another continuation line!  */
1577760c2415Smrg   goto restart;
1578760c2415Smrg 
1579760c2415Smrg not_continuation:
1580760c2415Smrg   c = '\n';
1581760c2415Smrg   gfc_current_locus = old_loc;
1582760c2415Smrg   end_flag = 0;
1583760c2415Smrg 
1584760c2415Smrg done:
1585760c2415Smrg   if (c == '\n')
1586760c2415Smrg     continue_count = 0;
1587760c2415Smrg   continue_flag = 0;
1588760c2415Smrg   return c;
1589760c2415Smrg }
1590760c2415Smrg 
1591760c2415Smrg 
1592760c2415Smrg /* Get the next character of input, folded to lowercase.  In fixed
1593760c2415Smrg    form mode, we also ignore spaces.  When matcher subroutines are
1594760c2415Smrg    parsing character literals, they have to call
1595760c2415Smrg    gfc_next_char_literal().  */
1596760c2415Smrg 
1597760c2415Smrg gfc_char_t
gfc_next_char(void)1598760c2415Smrg gfc_next_char (void)
1599760c2415Smrg {
1600760c2415Smrg   gfc_char_t c;
1601760c2415Smrg 
1602760c2415Smrg   do
1603760c2415Smrg     {
1604760c2415Smrg       c = gfc_next_char_literal (NONSTRING);
1605760c2415Smrg     }
1606760c2415Smrg   while (gfc_current_form == FORM_FIXED && gfc_is_whitespace (c));
1607760c2415Smrg 
1608760c2415Smrg   return gfc_wide_tolower (c);
1609760c2415Smrg }
1610760c2415Smrg 
1611760c2415Smrg char
gfc_next_ascii_char(void)1612760c2415Smrg gfc_next_ascii_char (void)
1613760c2415Smrg {
1614760c2415Smrg   gfc_char_t c = gfc_next_char ();
1615760c2415Smrg 
1616760c2415Smrg   return (gfc_wide_fits_in_byte (c) ? (unsigned char) c
1617760c2415Smrg 				    : (unsigned char) UCHAR_MAX);
1618760c2415Smrg }
1619760c2415Smrg 
1620760c2415Smrg 
1621760c2415Smrg gfc_char_t
gfc_peek_char(void)1622760c2415Smrg gfc_peek_char (void)
1623760c2415Smrg {
1624760c2415Smrg   locus old_loc;
1625760c2415Smrg   gfc_char_t c;
1626760c2415Smrg 
1627760c2415Smrg   old_loc = gfc_current_locus;
1628760c2415Smrg   c = gfc_next_char ();
1629760c2415Smrg   gfc_current_locus = old_loc;
1630760c2415Smrg 
1631760c2415Smrg   return c;
1632760c2415Smrg }
1633760c2415Smrg 
1634760c2415Smrg 
1635760c2415Smrg char
gfc_peek_ascii_char(void)1636760c2415Smrg gfc_peek_ascii_char (void)
1637760c2415Smrg {
1638760c2415Smrg   gfc_char_t c = gfc_peek_char ();
1639760c2415Smrg 
1640760c2415Smrg   return (gfc_wide_fits_in_byte (c) ? (unsigned char) c
1641760c2415Smrg 				    : (unsigned char) UCHAR_MAX);
1642760c2415Smrg }
1643760c2415Smrg 
1644760c2415Smrg 
1645760c2415Smrg /* Recover from an error.  We try to get past the current statement
1646760c2415Smrg    and get lined up for the next.  The next statement follows a '\n'
1647760c2415Smrg    or a ';'.  We also assume that we are not within a character
1648760c2415Smrg    constant, and deal with finding a '\'' or '"'.  */
1649760c2415Smrg 
1650760c2415Smrg void
gfc_error_recovery(void)1651760c2415Smrg gfc_error_recovery (void)
1652760c2415Smrg {
1653760c2415Smrg   gfc_char_t c, delim;
1654760c2415Smrg 
1655760c2415Smrg   if (gfc_at_eof ())
1656760c2415Smrg     return;
1657760c2415Smrg 
1658760c2415Smrg   for (;;)
1659760c2415Smrg     {
1660760c2415Smrg       c = gfc_next_char ();
1661760c2415Smrg       if (c == '\n' || c == ';')
1662760c2415Smrg 	break;
1663760c2415Smrg 
1664760c2415Smrg       if (c != '\'' && c != '"')
1665760c2415Smrg 	{
1666760c2415Smrg 	  if (gfc_at_eof ())
1667760c2415Smrg 	    break;
1668760c2415Smrg 	  continue;
1669760c2415Smrg 	}
1670760c2415Smrg       delim = c;
1671760c2415Smrg 
1672760c2415Smrg       for (;;)
1673760c2415Smrg 	{
1674760c2415Smrg 	  c = next_char ();
1675760c2415Smrg 
1676760c2415Smrg 	  if (c == delim)
1677760c2415Smrg 	    break;
1678760c2415Smrg 	  if (c == '\n')
1679760c2415Smrg 	    return;
1680760c2415Smrg 	  if (c == '\\')
1681760c2415Smrg 	    {
1682760c2415Smrg 	      c = next_char ();
1683760c2415Smrg 	      if (c == '\n')
1684760c2415Smrg 		return;
1685760c2415Smrg 	    }
1686760c2415Smrg 	}
1687760c2415Smrg       if (gfc_at_eof ())
1688760c2415Smrg 	break;
1689760c2415Smrg     }
1690760c2415Smrg }
1691760c2415Smrg 
1692760c2415Smrg 
1693760c2415Smrg /* Read ahead until the next character to be read is not whitespace.  */
1694760c2415Smrg 
1695760c2415Smrg void
gfc_gobble_whitespace(void)1696760c2415Smrg gfc_gobble_whitespace (void)
1697760c2415Smrg {
1698760c2415Smrg   static int linenum = 0;
1699760c2415Smrg   locus old_loc;
1700760c2415Smrg   gfc_char_t c;
1701760c2415Smrg 
1702760c2415Smrg   do
1703760c2415Smrg     {
1704760c2415Smrg       old_loc = gfc_current_locus;
1705760c2415Smrg       c = gfc_next_char_literal (NONSTRING);
1706760c2415Smrg       /* Issue a warning for nonconforming tabs.  We keep track of the line
1707760c2415Smrg 	 number because the Fortran matchers will often back up and the same
1708760c2415Smrg 	 line will be scanned multiple times.  */
1709760c2415Smrg       if (warn_tabs && c == '\t')
1710760c2415Smrg 	{
1711760c2415Smrg 	  int cur_linenum = LOCATION_LINE (gfc_current_locus.lb->location);
1712760c2415Smrg 	  if (cur_linenum != linenum)
1713760c2415Smrg 	    {
1714760c2415Smrg 	      linenum = cur_linenum;
1715760c2415Smrg 	      gfc_warning_now (OPT_Wtabs, "Nonconforming tab character at %C");
1716760c2415Smrg 	    }
1717760c2415Smrg 	}
1718760c2415Smrg     }
1719760c2415Smrg   while (gfc_is_whitespace (c));
1720760c2415Smrg 
1721760c2415Smrg   if (!ISPRINT(c) && c != '\n' && last_error_char != gfc_current_locus.nextc)
1722760c2415Smrg     {
1723760c2415Smrg       char buf[20];
1724760c2415Smrg       last_error_char = gfc_current_locus.nextc;
1725760c2415Smrg       snprintf (buf, 20, "%2.2X", c);
1726760c2415Smrg       gfc_error_now ("Invalid character 0x%s at %C", buf);
1727760c2415Smrg     }
1728760c2415Smrg 
1729760c2415Smrg   gfc_current_locus = old_loc;
1730760c2415Smrg }
1731760c2415Smrg 
1732760c2415Smrg 
1733760c2415Smrg /* Load a single line into pbuf.
1734760c2415Smrg 
1735760c2415Smrg    If pbuf points to a NULL pointer, it is allocated.
1736760c2415Smrg    We truncate lines that are too long, unless we're dealing with
1737760c2415Smrg    preprocessor lines or if the option -ffixed-line-length-none is set,
1738760c2415Smrg    in which case we reallocate the buffer to fit the entire line, if
1739760c2415Smrg    need be.
1740760c2415Smrg    In fixed mode, we expand a tab that occurs within the statement
1741760c2415Smrg    label region to expand to spaces that leave the next character in
1742760c2415Smrg    the source region.
1743760c2415Smrg 
1744760c2415Smrg    If first_char is not NULL, it's a pointer to a single char value holding
1745760c2415Smrg    the first character of the line, which has already been read by the
1746760c2415Smrg    caller.  This avoids the use of ungetc().
1747760c2415Smrg 
1748760c2415Smrg    load_line returns whether the line was truncated.
1749760c2415Smrg 
1750760c2415Smrg    NOTE: The error machinery isn't available at this point, so we can't
1751760c2415Smrg 	 easily report line and column numbers consistent with other
1752760c2415Smrg 	 parts of gfortran.  */
1753760c2415Smrg 
1754760c2415Smrg static int
load_line(FILE * input,gfc_char_t ** pbuf,int * pbuflen,const int * first_char)1755760c2415Smrg load_line (FILE *input, gfc_char_t **pbuf, int *pbuflen, const int *first_char)
1756760c2415Smrg {
1757760c2415Smrg   int c, maxlen, i, preprocessor_flag, buflen = *pbuflen;
1758*0bfacb9bSmrg   int quoted = ' ', comment_ix = -1;
1759*0bfacb9bSmrg   bool seen_comment = false;
1760*0bfacb9bSmrg   bool first_comment = true;
1761*0bfacb9bSmrg   bool trunc_flag = false;
1762*0bfacb9bSmrg   bool seen_printable = false;
1763*0bfacb9bSmrg   bool seen_ampersand = false;
1764760c2415Smrg   bool found_tab = false;
1765760c2415Smrg   bool warned_tabs = false;
1766*0bfacb9bSmrg   gfc_char_t *buffer;
1767760c2415Smrg 
1768760c2415Smrg   /* Determine the maximum allowed line length.  */
1769760c2415Smrg   if (gfc_current_form == FORM_FREE)
1770760c2415Smrg     maxlen = flag_free_line_length;
1771760c2415Smrg   else if (gfc_current_form == FORM_FIXED)
1772760c2415Smrg     maxlen = flag_fixed_line_length;
1773760c2415Smrg   else
1774760c2415Smrg     maxlen = 72;
1775760c2415Smrg 
1776760c2415Smrg   if (*pbuf == NULL)
1777760c2415Smrg     {
1778760c2415Smrg       /* Allocate the line buffer, storing its length into buflen.
1779760c2415Smrg 	 Note that if maxlen==0, indicating that arbitrary-length lines
1780760c2415Smrg 	 are allowed, the buffer will be reallocated if this length is
1781760c2415Smrg 	 insufficient; since 132 characters is the length of a standard
1782760c2415Smrg 	 free-form line, we use that as a starting guess.  */
1783760c2415Smrg       if (maxlen > 0)
1784760c2415Smrg 	buflen = maxlen;
1785760c2415Smrg       else
1786760c2415Smrg 	buflen = 132;
1787760c2415Smrg 
1788760c2415Smrg       *pbuf = gfc_get_wide_string (buflen + 1);
1789760c2415Smrg     }
1790760c2415Smrg 
1791760c2415Smrg   i = 0;
1792760c2415Smrg   buffer = *pbuf;
1793760c2415Smrg 
1794760c2415Smrg   if (first_char)
1795760c2415Smrg     c = *first_char;
1796760c2415Smrg   else
1797760c2415Smrg     c = getc (input);
1798760c2415Smrg 
1799760c2415Smrg   /* In order to not truncate preprocessor lines, we have to
1800760c2415Smrg      remember that this is one.  */
1801*0bfacb9bSmrg   preprocessor_flag = (c == '#');
1802760c2415Smrg 
1803760c2415Smrg   for (;;)
1804760c2415Smrg     {
1805760c2415Smrg       if (c == EOF)
1806760c2415Smrg 	break;
1807760c2415Smrg 
1808760c2415Smrg       if (c == '\n')
1809760c2415Smrg 	{
1810760c2415Smrg 	  /* Check for illegal use of ampersand. See F95 Standard 3.3.1.3.  */
1811760c2415Smrg 	  if (gfc_current_form == FORM_FREE
1812760c2415Smrg 	      && !seen_printable && seen_ampersand)
1813760c2415Smrg 	    {
1814760c2415Smrg 	      if (pedantic)
1815760c2415Smrg 		gfc_error_now ("%<&%> not allowed by itself in line %d",
1816760c2415Smrg 			       current_file->line);
1817760c2415Smrg 	      else
1818760c2415Smrg 		gfc_warning_now (0, "%<&%> not allowed by itself in line %d",
1819760c2415Smrg 				 current_file->line);
1820760c2415Smrg 	    }
1821760c2415Smrg 	  break;
1822760c2415Smrg 	}
1823760c2415Smrg 
1824760c2415Smrg       if (c == '\r' || c == '\0')
1825760c2415Smrg 	goto next_char;			/* Gobble characters.  */
1826760c2415Smrg 
1827760c2415Smrg       if (c == '&')
1828760c2415Smrg 	{
1829760c2415Smrg 	  if (seen_ampersand)
1830760c2415Smrg 	    {
1831*0bfacb9bSmrg 	      seen_ampersand = false;
1832*0bfacb9bSmrg 	      seen_printable = true;
1833760c2415Smrg 	    }
1834760c2415Smrg 	  else
1835*0bfacb9bSmrg 	    seen_ampersand = true;
1836760c2415Smrg 	}
1837760c2415Smrg 
1838760c2415Smrg       if ((c != '&' && c != '!' && c != ' ') || (c == '!' && !seen_ampersand))
1839*0bfacb9bSmrg 	seen_printable = true;
1840760c2415Smrg 
1841760c2415Smrg       /* Is this a fixed-form comment?  */
1842760c2415Smrg       if (gfc_current_form == FORM_FIXED && i == 0
1843*0bfacb9bSmrg 	  && (c == '*' || c == 'c' || c == 'C'
1844*0bfacb9bSmrg 	      || (gfc_option.flag_d_lines != -1 && (c == 'd' || c == 'D'))))
1845*0bfacb9bSmrg 	{
1846*0bfacb9bSmrg 	  seen_comment = true;
1847*0bfacb9bSmrg 	  comment_ix = i;
1848*0bfacb9bSmrg 	}
1849760c2415Smrg 
1850760c2415Smrg       if (quoted == ' ')
1851760c2415Smrg 	{
1852760c2415Smrg 	  if (c == '\'' || c == '"')
1853760c2415Smrg 	    quoted = c;
1854760c2415Smrg 	}
1855760c2415Smrg       else if (c == quoted)
1856760c2415Smrg 	quoted = ' ';
1857760c2415Smrg 
1858760c2415Smrg       /* Is this a free-form comment?  */
1859760c2415Smrg       if (c == '!' && quoted == ' ')
1860*0bfacb9bSmrg 	{
1861*0bfacb9bSmrg 	  if (seen_comment)
1862*0bfacb9bSmrg 	    first_comment = false;
1863*0bfacb9bSmrg 	  seen_comment = true;
1864*0bfacb9bSmrg 	  comment_ix = i;
1865*0bfacb9bSmrg 	}
1866*0bfacb9bSmrg 
1867*0bfacb9bSmrg       /* For truncation and tab warnings, set seen_comment to false if one has
1868*0bfacb9bSmrg 	 either an OpenMP or OpenACC directive - or a !GCC$ attribute.  If
1869*0bfacb9bSmrg 	 OpenMP is enabled, use '!$' as as conditional compilation sentinel
1870*0bfacb9bSmrg 	 and OpenMP directive ('!$omp').  */
1871*0bfacb9bSmrg       if (seen_comment && first_comment && flag_openmp && comment_ix + 1 == i
1872*0bfacb9bSmrg 	  && c == '$')
1873*0bfacb9bSmrg 	first_comment = seen_comment = false;
1874*0bfacb9bSmrg       if (seen_comment && first_comment && comment_ix + 4 == i)
1875*0bfacb9bSmrg 	{
1876*0bfacb9bSmrg 	  if (((*pbuf)[comment_ix+1] == 'g' || (*pbuf)[comment_ix+1] == 'G')
1877*0bfacb9bSmrg 	      && ((*pbuf)[comment_ix+2] == 'c' || (*pbuf)[comment_ix+2] == 'C')
1878*0bfacb9bSmrg 	      && ((*pbuf)[comment_ix+3] == 'c' || (*pbuf)[comment_ix+3] == 'C')
1879*0bfacb9bSmrg 	      && (*pbuf)[comment_ix+4] == '$')
1880*0bfacb9bSmrg 	    first_comment = seen_comment = false;
1881*0bfacb9bSmrg 	  if (flag_openacc
1882*0bfacb9bSmrg 	      && (*pbuf)[comment_ix+1] == '$'
1883*0bfacb9bSmrg 	      && ((*pbuf)[comment_ix+2] == 'a' || (*pbuf)[comment_ix+2] == 'A')
1884*0bfacb9bSmrg 	      && ((*pbuf)[comment_ix+3] == 'c' || (*pbuf)[comment_ix+3] == 'C')
1885*0bfacb9bSmrg 	      && ((*pbuf)[comment_ix+4] == 'c' || (*pbuf)[comment_ix+4] == 'C'))
1886*0bfacb9bSmrg 	    first_comment = seen_comment = false;
1887*0bfacb9bSmrg 	}
1888760c2415Smrg 
1889760c2415Smrg       /* Vendor extension: "<tab>1" marks a continuation line.  */
1890760c2415Smrg       if (found_tab)
1891760c2415Smrg 	{
1892760c2415Smrg 	  found_tab = false;
1893760c2415Smrg 	  if (c >= '1' && c <= '9')
1894760c2415Smrg 	    {
1895760c2415Smrg 	      *(buffer-1) = c;
1896760c2415Smrg 	      goto next_char;
1897760c2415Smrg 	    }
1898760c2415Smrg 	}
1899760c2415Smrg 
1900760c2415Smrg       if (gfc_current_form == FORM_FIXED && c == '\t' && i < 6)
1901760c2415Smrg 	{
1902760c2415Smrg 	  found_tab = true;
1903760c2415Smrg 
1904760c2415Smrg 	  if (warn_tabs && seen_comment == 0 && !warned_tabs)
1905760c2415Smrg 	    {
1906760c2415Smrg 	      warned_tabs = true;
1907760c2415Smrg 	      gfc_warning_now (OPT_Wtabs,
1908760c2415Smrg 			       "Nonconforming tab character in column %d "
1909760c2415Smrg 			       "of line %d", i + 1, current_file->line);
1910760c2415Smrg 	    }
1911760c2415Smrg 
1912760c2415Smrg 	  while (i < 6)
1913760c2415Smrg 	    {
1914760c2415Smrg 	      *buffer++ = ' ';
1915760c2415Smrg 	      i++;
1916760c2415Smrg 	    }
1917760c2415Smrg 
1918760c2415Smrg 	  goto next_char;
1919760c2415Smrg 	}
1920760c2415Smrg 
1921760c2415Smrg       *buffer++ = c;
1922760c2415Smrg       i++;
1923760c2415Smrg 
1924760c2415Smrg       if (maxlen == 0 || preprocessor_flag)
1925760c2415Smrg 	{
1926760c2415Smrg 	  if (i >= buflen)
1927760c2415Smrg 	    {
1928760c2415Smrg 	      /* Reallocate line buffer to double size to hold the
1929760c2415Smrg 		overlong line.  */
1930760c2415Smrg 	      buflen = buflen * 2;
1931760c2415Smrg 	      *pbuf = XRESIZEVEC (gfc_char_t, *pbuf, (buflen + 1));
1932760c2415Smrg 	      buffer = (*pbuf) + i;
1933760c2415Smrg 	    }
1934760c2415Smrg 	}
1935760c2415Smrg       else if (i >= maxlen)
1936760c2415Smrg 	{
1937760c2415Smrg 	  bool trunc_warn = true;
1938760c2415Smrg 
1939760c2415Smrg 	  /* Enhancement, if the very next non-space character is an ampersand
1940760c2415Smrg 	     or comment that we would otherwise warn about, don't mark as
1941760c2415Smrg 	     truncated.  */
1942760c2415Smrg 
1943760c2415Smrg 	  /* Truncate the rest of the line.  */
1944760c2415Smrg 	  for (;;)
1945760c2415Smrg 	    {
1946760c2415Smrg 	      c = getc (input);
1947760c2415Smrg 	      if (c == '\r' || c == ' ')
1948760c2415Smrg 	        continue;
1949760c2415Smrg 
1950760c2415Smrg 	      if (c == '\n' || c == EOF)
1951760c2415Smrg 		break;
1952760c2415Smrg 
1953760c2415Smrg 	      if (!trunc_warn && c != '!')
1954760c2415Smrg 		trunc_warn = true;
1955760c2415Smrg 
1956760c2415Smrg 	      if (trunc_warn && ((gfc_current_form == FORM_FIXED && c == '&')
1957760c2415Smrg 		  || c == '!'))
1958760c2415Smrg 		trunc_warn = false;
1959760c2415Smrg 
1960760c2415Smrg 	      if (c == '!')
1961760c2415Smrg 		seen_comment = 1;
1962760c2415Smrg 
1963760c2415Smrg 	      if (trunc_warn && !seen_comment)
1964760c2415Smrg 		trunc_flag = 1;
1965760c2415Smrg 	    }
1966760c2415Smrg 
1967760c2415Smrg 	  c = '\n';
1968760c2415Smrg 	  continue;
1969760c2415Smrg 	}
1970760c2415Smrg 
1971760c2415Smrg next_char:
1972760c2415Smrg       c = getc (input);
1973760c2415Smrg     }
1974760c2415Smrg 
1975760c2415Smrg   /* Pad lines to the selected line length in fixed form.  */
1976760c2415Smrg   if (gfc_current_form == FORM_FIXED
1977760c2415Smrg       && flag_fixed_line_length != 0
1978760c2415Smrg       && flag_pad_source
1979760c2415Smrg       && !preprocessor_flag
1980760c2415Smrg       && c != EOF)
1981760c2415Smrg     {
1982760c2415Smrg       while (i++ < maxlen)
1983760c2415Smrg 	*buffer++ = ' ';
1984760c2415Smrg     }
1985760c2415Smrg 
1986760c2415Smrg   *buffer = '\0';
1987760c2415Smrg   *pbuflen = buflen;
1988760c2415Smrg 
1989760c2415Smrg   return trunc_flag;
1990760c2415Smrg }
1991760c2415Smrg 
1992760c2415Smrg 
1993760c2415Smrg /* Get a gfc_file structure, initialize it and add it to
1994760c2415Smrg    the file stack.  */
1995760c2415Smrg 
1996760c2415Smrg static gfc_file *
get_file(const char * name,enum lc_reason reason)1997760c2415Smrg get_file (const char *name, enum lc_reason reason)
1998760c2415Smrg {
1999760c2415Smrg   gfc_file *f;
2000760c2415Smrg 
2001760c2415Smrg   f = XCNEW (gfc_file);
2002760c2415Smrg 
2003760c2415Smrg   f->filename = xstrdup (name);
2004760c2415Smrg 
2005760c2415Smrg   f->next = file_head;
2006760c2415Smrg   file_head = f;
2007760c2415Smrg 
2008760c2415Smrg   f->up = current_file;
2009760c2415Smrg   if (current_file != NULL)
2010760c2415Smrg     f->inclusion_line = current_file->line;
2011760c2415Smrg 
2012760c2415Smrg   linemap_add (line_table, reason, false, f->filename, 1);
2013760c2415Smrg 
2014760c2415Smrg   return f;
2015760c2415Smrg }
2016760c2415Smrg 
2017760c2415Smrg 
2018760c2415Smrg /* Deal with a line from the C preprocessor. The
2019760c2415Smrg    initial octothorp has already been seen.  */
2020760c2415Smrg 
2021760c2415Smrg static void
preprocessor_line(gfc_char_t * c)2022760c2415Smrg preprocessor_line (gfc_char_t *c)
2023760c2415Smrg {
2024760c2415Smrg   bool flag[5];
2025760c2415Smrg   int i, line;
2026760c2415Smrg   gfc_char_t *wide_filename;
2027760c2415Smrg   gfc_file *f;
2028760c2415Smrg   int escaped, unescape;
2029760c2415Smrg   char *filename;
2030760c2415Smrg 
2031760c2415Smrg   c++;
2032760c2415Smrg   while (*c == ' ' || *c == '\t')
2033760c2415Smrg     c++;
2034760c2415Smrg 
2035760c2415Smrg   if (*c < '0' || *c > '9')
2036760c2415Smrg     goto bad_cpp_line;
2037760c2415Smrg 
2038760c2415Smrg   line = wide_atoi (c);
2039760c2415Smrg 
2040760c2415Smrg   c = wide_strchr (c, ' ');
2041760c2415Smrg   if (c == NULL)
2042760c2415Smrg     {
2043760c2415Smrg       /* No file name given.  Set new line number.  */
2044760c2415Smrg       current_file->line = line;
2045760c2415Smrg       return;
2046760c2415Smrg     }
2047760c2415Smrg 
2048760c2415Smrg   /* Skip spaces.  */
2049760c2415Smrg   while (*c == ' ' || *c == '\t')
2050760c2415Smrg     c++;
2051760c2415Smrg 
2052760c2415Smrg   /* Skip quote.  */
2053760c2415Smrg   if (*c != '"')
2054760c2415Smrg     goto bad_cpp_line;
2055760c2415Smrg   ++c;
2056760c2415Smrg 
2057760c2415Smrg   wide_filename = c;
2058760c2415Smrg 
2059760c2415Smrg   /* Make filename end at quote.  */
2060760c2415Smrg   unescape = 0;
2061760c2415Smrg   escaped = false;
2062760c2415Smrg   while (*c && ! (!escaped && *c == '"'))
2063760c2415Smrg     {
2064760c2415Smrg       if (escaped)
2065760c2415Smrg 	escaped = false;
2066760c2415Smrg       else if (*c == '\\')
2067760c2415Smrg 	{
2068760c2415Smrg 	  escaped = true;
2069760c2415Smrg 	  unescape++;
2070760c2415Smrg 	}
2071760c2415Smrg       ++c;
2072760c2415Smrg     }
2073760c2415Smrg 
2074760c2415Smrg   if (! *c)
2075760c2415Smrg     /* Preprocessor line has no closing quote.  */
2076760c2415Smrg     goto bad_cpp_line;
2077760c2415Smrg 
2078760c2415Smrg   *c++ = '\0';
2079760c2415Smrg 
2080760c2415Smrg   /* Undo effects of cpp_quote_string.  */
2081760c2415Smrg   if (unescape)
2082760c2415Smrg     {
2083760c2415Smrg       gfc_char_t *s = wide_filename;
2084760c2415Smrg       gfc_char_t *d = gfc_get_wide_string (c - wide_filename - unescape);
2085760c2415Smrg 
2086760c2415Smrg       wide_filename = d;
2087760c2415Smrg       while (*s)
2088760c2415Smrg 	{
2089760c2415Smrg 	  if (*s == '\\')
2090760c2415Smrg 	    *d++ = *++s;
2091760c2415Smrg 	  else
2092760c2415Smrg 	    *d++ = *s;
2093760c2415Smrg 	  s++;
2094760c2415Smrg 	}
2095760c2415Smrg       *d = '\0';
2096760c2415Smrg     }
2097760c2415Smrg 
2098760c2415Smrg   /* Get flags.  */
2099760c2415Smrg 
2100760c2415Smrg   flag[1] = flag[2] = flag[3] = flag[4] = false;
2101760c2415Smrg 
2102760c2415Smrg   for (;;)
2103760c2415Smrg     {
2104760c2415Smrg       c = wide_strchr (c, ' ');
2105760c2415Smrg       if (c == NULL)
2106760c2415Smrg 	break;
2107760c2415Smrg 
2108760c2415Smrg       c++;
2109760c2415Smrg       i = wide_atoi (c);
2110760c2415Smrg 
2111760c2415Smrg       if (i >= 1 && i <= 4)
2112760c2415Smrg 	flag[i] = true;
2113760c2415Smrg     }
2114760c2415Smrg 
2115760c2415Smrg   /* Convert the filename in wide characters into a filename in narrow
2116760c2415Smrg      characters.  */
2117760c2415Smrg   filename = gfc_widechar_to_char (wide_filename, -1);
2118760c2415Smrg 
2119760c2415Smrg   /* Interpret flags.  */
2120760c2415Smrg 
2121760c2415Smrg   if (flag[1]) /* Starting new file.  */
2122760c2415Smrg     {
2123760c2415Smrg       f = get_file (filename, LC_RENAME);
2124760c2415Smrg       add_file_change (f->filename, f->inclusion_line);
2125760c2415Smrg       current_file = f;
2126760c2415Smrg     }
2127760c2415Smrg 
2128760c2415Smrg   if (flag[2]) /* Ending current file.  */
2129760c2415Smrg     {
2130760c2415Smrg       if (!current_file->up
2131760c2415Smrg 	  || filename_cmp (current_file->up->filename, filename) != 0)
2132760c2415Smrg 	{
2133760c2415Smrg 	  linemap_line_start (line_table, current_file->line, 80);
2134760c2415Smrg 	  /* ??? One could compute the exact column where the filename
2135760c2415Smrg 	     starts and compute the exact location here.  */
2136760c2415Smrg 	  gfc_warning_now_at (linemap_position_for_column (line_table, 1),
2137760c2415Smrg 			      0, "file %qs left but not entered",
2138760c2415Smrg 			      filename);
2139760c2415Smrg 	  current_file->line++;
2140760c2415Smrg 	  if (unescape)
2141760c2415Smrg 	    free (wide_filename);
2142760c2415Smrg 	  free (filename);
2143760c2415Smrg 	  return;
2144760c2415Smrg 	}
2145760c2415Smrg 
2146760c2415Smrg       add_file_change (NULL, line);
2147760c2415Smrg       current_file = current_file->up;
2148760c2415Smrg       linemap_add (line_table, LC_RENAME, false, current_file->filename,
2149760c2415Smrg 		   current_file->line);
2150760c2415Smrg     }
2151760c2415Smrg 
2152760c2415Smrg   /* The name of the file can be a temporary file produced by
2153760c2415Smrg      cpp. Replace the name if it is different.  */
2154760c2415Smrg 
2155760c2415Smrg   if (filename_cmp (current_file->filename, filename) != 0)
2156760c2415Smrg     {
2157760c2415Smrg        /* FIXME: we leak the old filename because a pointer to it may be stored
2158760c2415Smrg           in the linemap.  Alternative could be using GC or updating linemap to
2159760c2415Smrg           point to the new name, but there is no API for that currently.  */
2160760c2415Smrg       current_file->filename = xstrdup (filename);
2161760c2415Smrg 
2162760c2415Smrg       /* We need to tell the linemap API that the filename changed.  Just
2163760c2415Smrg 	 changing current_file is insufficient.  */
2164760c2415Smrg       linemap_add (line_table, LC_RENAME, false, current_file->filename, line);
2165760c2415Smrg     }
2166760c2415Smrg 
2167760c2415Smrg   /* Set new line number.  */
2168760c2415Smrg   current_file->line = line;
2169760c2415Smrg   if (unescape)
2170760c2415Smrg     free (wide_filename);
2171760c2415Smrg   free (filename);
2172760c2415Smrg   return;
2173760c2415Smrg 
2174760c2415Smrg  bad_cpp_line:
2175760c2415Smrg   linemap_line_start (line_table, current_file->line, 80);
2176760c2415Smrg   /* ??? One could compute the exact column where the directive
2177760c2415Smrg      starts and compute the exact location here.  */
2178760c2415Smrg   gfc_warning_now_at (linemap_position_for_column (line_table, 2), 0,
2179760c2415Smrg 		      "Illegal preprocessor directive");
2180760c2415Smrg   current_file->line++;
2181760c2415Smrg }
2182760c2415Smrg 
2183760c2415Smrg 
2184760c2415Smrg static bool load_file (const char *, const char *, bool);
2185760c2415Smrg 
2186760c2415Smrg /* include_line()-- Checks a line buffer to see if it is an include
2187760c2415Smrg    line.  If so, we call load_file() recursively to load the included
2188760c2415Smrg    file.  We never return a syntax error because a statement like
2189760c2415Smrg    "include = 5" is perfectly legal.  We return 0 if no include was
2190760c2415Smrg    processed, 1 if we matched an include or -1 if include was
2191760c2415Smrg    partially processed, but will need continuation lines.  */
2192760c2415Smrg 
2193760c2415Smrg static int
include_line(gfc_char_t * line)2194760c2415Smrg include_line (gfc_char_t *line)
2195760c2415Smrg {
2196760c2415Smrg   gfc_char_t quote, *c, *begin, *stop;
2197760c2415Smrg   char *filename;
2198760c2415Smrg   const char *include = "include";
2199760c2415Smrg   bool allow_continuation = flag_dec_include;
2200760c2415Smrg   int i;
2201760c2415Smrg 
2202760c2415Smrg   c = line;
2203760c2415Smrg 
2204760c2415Smrg   if (flag_openmp || flag_openmp_simd)
2205760c2415Smrg     {
2206760c2415Smrg       if (gfc_current_form == FORM_FREE)
2207760c2415Smrg 	{
2208760c2415Smrg 	  while (*c == ' ' || *c == '\t')
2209760c2415Smrg 	    c++;
2210760c2415Smrg 	  if (*c == '!' && c[1] == '$' && (c[2] == ' ' || c[2] == '\t'))
2211760c2415Smrg 	    c += 3;
2212760c2415Smrg 	}
2213760c2415Smrg       else
2214760c2415Smrg 	{
2215760c2415Smrg 	  if ((*c == '!' || *c == 'c' || *c == 'C' || *c == '*')
2216760c2415Smrg 	      && c[1] == '$' && c[2] == ' ')
2217760c2415Smrg 	    c += 3;
2218760c2415Smrg 	}
2219760c2415Smrg     }
2220760c2415Smrg 
2221760c2415Smrg   if (gfc_current_form == FORM_FREE)
2222760c2415Smrg     {
2223760c2415Smrg       while (*c == ' ' || *c == '\t')
2224760c2415Smrg 	c++;
2225760c2415Smrg       if (gfc_wide_strncasecmp (c, "include", 7))
2226760c2415Smrg 	{
2227760c2415Smrg 	  if (!allow_continuation)
2228760c2415Smrg 	    return 0;
2229760c2415Smrg 	  for (i = 0; i < 7; ++i)
2230760c2415Smrg 	    {
2231760c2415Smrg 	      gfc_char_t c1 = gfc_wide_tolower (*c);
2232760c2415Smrg 	      if (c1 != (unsigned char) include[i])
2233760c2415Smrg 		break;
2234760c2415Smrg 	      c++;
2235760c2415Smrg 	    }
2236760c2415Smrg 	  if (i == 0 || *c != '&')
2237760c2415Smrg 	    return 0;
2238760c2415Smrg 	  c++;
2239760c2415Smrg 	  while (*c == ' ' || *c == '\t')
2240760c2415Smrg 	    c++;
2241760c2415Smrg 	  if (*c == '\0' || *c == '!')
2242760c2415Smrg 	    return -1;
2243760c2415Smrg 	  return 0;
2244760c2415Smrg 	}
2245760c2415Smrg 
2246760c2415Smrg       c += 7;
2247760c2415Smrg     }
2248760c2415Smrg   else
2249760c2415Smrg     {
2250760c2415Smrg       while (*c == ' ' || *c == '\t')
2251760c2415Smrg 	c++;
2252760c2415Smrg       if (flag_dec_include && *c == '0' && c - line == 5)
2253760c2415Smrg 	{
2254760c2415Smrg 	  c++;
2255760c2415Smrg 	  while (*c == ' ' || *c == '\t')
2256760c2415Smrg 	    c++;
2257760c2415Smrg 	}
2258760c2415Smrg       if (c - line < 6)
2259760c2415Smrg 	allow_continuation = false;
2260760c2415Smrg       for (i = 0; i < 7; ++i)
2261760c2415Smrg 	{
2262760c2415Smrg 	  gfc_char_t c1 = gfc_wide_tolower (*c);
2263760c2415Smrg 	  if (c1 != (unsigned char) include[i])
2264760c2415Smrg 	    break;
2265760c2415Smrg 	  c++;
2266760c2415Smrg 	  while (*c == ' ' || *c == '\t')
2267760c2415Smrg 	    c++;
2268760c2415Smrg 	}
2269760c2415Smrg       if (!allow_continuation)
2270760c2415Smrg 	{
2271760c2415Smrg 	  if (i != 7)
2272760c2415Smrg 	    return 0;
2273760c2415Smrg 	}
2274760c2415Smrg       else if (i != 7)
2275760c2415Smrg 	{
2276760c2415Smrg 	  if (i == 0)
2277760c2415Smrg 	    return 0;
2278760c2415Smrg 
2279760c2415Smrg 	  /* At the end of line or comment this might be continued.  */
2280760c2415Smrg 	  if (*c == '\0' || *c == '!')
2281760c2415Smrg 	    return -1;
2282760c2415Smrg 
2283760c2415Smrg 	  return 0;
2284760c2415Smrg 	}
2285760c2415Smrg     }
2286760c2415Smrg 
2287760c2415Smrg   while (*c == ' ' || *c == '\t')
2288760c2415Smrg     c++;
2289760c2415Smrg 
2290760c2415Smrg   /* Find filename between quotes.  */
2291760c2415Smrg 
2292760c2415Smrg   quote = *c++;
2293760c2415Smrg   if (quote != '"' && quote != '\'')
2294760c2415Smrg     {
2295760c2415Smrg       if (allow_continuation)
2296760c2415Smrg 	{
2297760c2415Smrg 	  if (gfc_current_form == FORM_FREE)
2298760c2415Smrg 	    {
2299760c2415Smrg 	      if (quote == '&')
2300760c2415Smrg 		{
2301760c2415Smrg 		  while (*c == ' ' || *c == '\t')
2302760c2415Smrg 		    c++;
2303760c2415Smrg 		  if (*c == '\0' || *c == '!')
2304760c2415Smrg 		    return -1;
2305760c2415Smrg 		}
2306760c2415Smrg 	    }
2307760c2415Smrg 	  else if (quote == '\0' || quote == '!')
2308760c2415Smrg 	    return -1;
2309760c2415Smrg 	}
2310760c2415Smrg       return 0;
2311760c2415Smrg     }
2312760c2415Smrg 
2313760c2415Smrg   begin = c;
2314760c2415Smrg 
2315760c2415Smrg   bool cont = false;
2316760c2415Smrg   while (*c != quote && *c != '\0')
2317760c2415Smrg     {
2318760c2415Smrg       if (allow_continuation && gfc_current_form == FORM_FREE)
2319760c2415Smrg 	{
2320760c2415Smrg 	  if (*c == '&')
2321760c2415Smrg 	    cont = true;
2322760c2415Smrg 	  else if (*c != ' ' && *c != '\t')
2323760c2415Smrg 	    cont = false;
2324760c2415Smrg 	}
2325760c2415Smrg       c++;
2326760c2415Smrg     }
2327760c2415Smrg 
2328760c2415Smrg   if (*c == '\0')
2329760c2415Smrg     {
2330760c2415Smrg       if (allow_continuation
2331760c2415Smrg 	  && (cont || gfc_current_form != FORM_FREE))
2332760c2415Smrg 	return -1;
2333760c2415Smrg       return 0;
2334760c2415Smrg     }
2335760c2415Smrg 
2336760c2415Smrg   stop = c++;
2337760c2415Smrg 
2338760c2415Smrg   while (*c == ' ' || *c == '\t')
2339760c2415Smrg     c++;
2340760c2415Smrg 
2341760c2415Smrg   if (*c != '\0' && *c != '!')
2342760c2415Smrg     return 0;
2343760c2415Smrg 
2344760c2415Smrg   /* We have an include line at this point.  */
2345760c2415Smrg 
2346760c2415Smrg   *stop = '\0'; /* It's ok to trash the buffer, as this line won't be
2347760c2415Smrg 		   read by anything else.  */
2348760c2415Smrg 
2349760c2415Smrg   filename = gfc_widechar_to_char (begin, -1);
2350760c2415Smrg   if (!load_file (filename, NULL, false))
2351760c2415Smrg     exit (FATAL_EXIT_CODE);
2352760c2415Smrg 
2353760c2415Smrg   free (filename);
2354760c2415Smrg   return 1;
2355760c2415Smrg }
2356760c2415Smrg 
2357760c2415Smrg /* Similarly, but try to parse an INCLUDE statement, using gfc_next_char etc.
2358760c2415Smrg    APIs.  Return 1 if recognized as valid INCLUDE statement and load_file has
2359760c2415Smrg    been called, 0 if it is not a valid INCLUDE statement and -1 if eof has
2360760c2415Smrg    been encountered while parsing it.  */
2361760c2415Smrg static int
include_stmt(gfc_linebuf * b)2362760c2415Smrg include_stmt (gfc_linebuf *b)
2363760c2415Smrg {
2364760c2415Smrg   int ret = 0, i, length;
2365760c2415Smrg   const char *include = "include";
2366760c2415Smrg   gfc_char_t c, quote = 0;
2367760c2415Smrg   locus str_locus;
2368760c2415Smrg   char *filename;
2369760c2415Smrg 
2370760c2415Smrg   continue_flag = 0;
2371760c2415Smrg   end_flag = 0;
2372760c2415Smrg   gcc_attribute_flag = 0;
2373760c2415Smrg   openmp_flag = 0;
2374760c2415Smrg   openacc_flag = 0;
2375760c2415Smrg   continue_count = 0;
2376760c2415Smrg   continue_line = 0;
2377760c2415Smrg   gfc_current_locus.lb = b;
2378760c2415Smrg   gfc_current_locus.nextc = b->line;
2379760c2415Smrg 
2380760c2415Smrg   gfc_skip_comments ();
2381760c2415Smrg   gfc_gobble_whitespace ();
2382760c2415Smrg 
2383760c2415Smrg   for (i = 0; i < 7; i++)
2384760c2415Smrg     {
2385760c2415Smrg       c = gfc_next_char ();
2386760c2415Smrg       if (c != (unsigned char) include[i])
2387760c2415Smrg 	{
2388760c2415Smrg 	  if (gfc_current_form == FORM_FIXED
2389760c2415Smrg 	      && i == 0
2390760c2415Smrg 	      && c == '0'
2391760c2415Smrg 	      && gfc_current_locus.nextc == b->line + 6)
2392760c2415Smrg 	    {
2393760c2415Smrg 	      gfc_gobble_whitespace ();
2394760c2415Smrg 	      i--;
2395760c2415Smrg 	      continue;
2396760c2415Smrg 	    }
2397760c2415Smrg 	  gcc_assert (i != 0);
2398760c2415Smrg 	  if (c == '\n')
2399760c2415Smrg 	    {
2400760c2415Smrg 	      gfc_advance_line ();
2401760c2415Smrg 	      gfc_skip_comments ();
2402760c2415Smrg 	      if (gfc_at_eof ())
2403760c2415Smrg 		ret = -1;
2404760c2415Smrg 	    }
2405760c2415Smrg 	  goto do_ret;
2406760c2415Smrg 	}
2407760c2415Smrg     }
2408760c2415Smrg   gfc_gobble_whitespace ();
2409760c2415Smrg 
2410760c2415Smrg   c = gfc_next_char ();
2411760c2415Smrg   if (c == '\'' || c == '"')
2412760c2415Smrg     quote = c;
2413760c2415Smrg   else
2414760c2415Smrg     {
2415760c2415Smrg       if (c == '\n')
2416760c2415Smrg 	{
2417760c2415Smrg 	  gfc_advance_line ();
2418760c2415Smrg 	  gfc_skip_comments ();
2419760c2415Smrg 	  if (gfc_at_eof ())
2420760c2415Smrg 	    ret = -1;
2421760c2415Smrg 	}
2422760c2415Smrg       goto do_ret;
2423760c2415Smrg     }
2424760c2415Smrg 
2425760c2415Smrg   str_locus = gfc_current_locus;
2426760c2415Smrg   length = 0;
2427760c2415Smrg   do
2428760c2415Smrg     {
2429760c2415Smrg       c = gfc_next_char_literal (INSTRING_NOWARN);
2430760c2415Smrg       if (c == quote)
2431760c2415Smrg 	break;
2432760c2415Smrg       if (c == '\n')
2433760c2415Smrg 	{
2434760c2415Smrg 	  gfc_advance_line ();
2435760c2415Smrg 	  gfc_skip_comments ();
2436760c2415Smrg 	  if (gfc_at_eof ())
2437760c2415Smrg 	    ret = -1;
2438760c2415Smrg 	  goto do_ret;
2439760c2415Smrg 	}
2440760c2415Smrg       length++;
2441760c2415Smrg     }
2442760c2415Smrg   while (1);
2443760c2415Smrg 
2444760c2415Smrg   gfc_gobble_whitespace ();
2445760c2415Smrg   c = gfc_next_char ();
2446760c2415Smrg   if (c != '\n')
2447760c2415Smrg     goto do_ret;
2448760c2415Smrg 
2449760c2415Smrg   gfc_current_locus = str_locus;
2450760c2415Smrg   ret = 1;
2451760c2415Smrg   filename = XNEWVEC (char, length + 1);
2452760c2415Smrg   for (i = 0; i < length; i++)
2453760c2415Smrg     {
2454760c2415Smrg       c = gfc_next_char_literal (INSTRING_WARN);
2455760c2415Smrg       gcc_assert (gfc_wide_fits_in_byte (c));
2456760c2415Smrg       filename[i] = (unsigned char) c;
2457760c2415Smrg     }
2458760c2415Smrg   filename[length] = '\0';
2459760c2415Smrg   if (!load_file (filename, NULL, false))
2460760c2415Smrg     exit (FATAL_EXIT_CODE);
2461760c2415Smrg 
2462760c2415Smrg   free (filename);
2463760c2415Smrg 
2464760c2415Smrg do_ret:
2465760c2415Smrg   continue_flag = 0;
2466760c2415Smrg   end_flag = 0;
2467760c2415Smrg   gcc_attribute_flag = 0;
2468760c2415Smrg   openmp_flag = 0;
2469760c2415Smrg   openacc_flag = 0;
2470760c2415Smrg   continue_count = 0;
2471760c2415Smrg   continue_line = 0;
2472760c2415Smrg   memset (&gfc_current_locus, '\0', sizeof (locus));
2473760c2415Smrg   memset (&openmp_locus, '\0', sizeof (locus));
2474760c2415Smrg   memset (&openacc_locus, '\0', sizeof (locus));
2475760c2415Smrg   memset (&gcc_attribute_locus, '\0', sizeof (locus));
2476760c2415Smrg   return ret;
2477760c2415Smrg }
2478760c2415Smrg 
2479760c2415Smrg /* Load a file into memory by calling load_line until the file ends.  */
2480760c2415Smrg 
2481760c2415Smrg static bool
load_file(const char * realfilename,const char * displayedname,bool initial)2482760c2415Smrg load_file (const char *realfilename, const char *displayedname, bool initial)
2483760c2415Smrg {
2484760c2415Smrg   gfc_char_t *line;
2485760c2415Smrg   gfc_linebuf *b, *include_b = NULL;
2486760c2415Smrg   gfc_file *f;
2487760c2415Smrg   FILE *input;
2488760c2415Smrg   int len, line_len;
2489760c2415Smrg   bool first_line;
2490760c2415Smrg   struct stat st;
2491760c2415Smrg   int stat_result;
2492760c2415Smrg   const char *filename;
2493760c2415Smrg   /* If realfilename and displayedname are different and non-null then
2494760c2415Smrg      surely realfilename is the preprocessed form of
2495760c2415Smrg      displayedname.  */
2496760c2415Smrg   bool preprocessed_p = (realfilename && displayedname
2497760c2415Smrg 			 && strcmp (realfilename, displayedname));
2498760c2415Smrg 
2499760c2415Smrg   filename = displayedname ? displayedname : realfilename;
2500760c2415Smrg 
2501760c2415Smrg   for (f = current_file; f; f = f->up)
2502760c2415Smrg     if (filename_cmp (filename, f->filename) == 0)
2503760c2415Smrg       {
2504760c2415Smrg 	fprintf (stderr, "%s:%d: Error: File '%s' is being included "
2505760c2415Smrg 		 "recursively\n", current_file->filename, current_file->line,
2506760c2415Smrg 		 filename);
2507760c2415Smrg 	return false;
2508760c2415Smrg       }
2509760c2415Smrg 
2510760c2415Smrg   if (initial)
2511760c2415Smrg     {
2512760c2415Smrg       if (gfc_src_file)
2513760c2415Smrg 	{
2514760c2415Smrg 	  input = gfc_src_file;
2515760c2415Smrg 	  gfc_src_file = NULL;
2516760c2415Smrg 	}
2517760c2415Smrg       else
2518760c2415Smrg 	input = gfc_open_file (realfilename);
2519760c2415Smrg 
2520760c2415Smrg       if (input == NULL)
2521760c2415Smrg 	{
2522760c2415Smrg 	  gfc_error_now ("Cannot open file %qs", filename);
2523760c2415Smrg 	  return false;
2524760c2415Smrg 	}
2525760c2415Smrg     }
2526760c2415Smrg   else
2527760c2415Smrg     {
2528760c2415Smrg       input = gfc_open_included_file (realfilename, false, false);
2529760c2415Smrg       if (input == NULL)
2530760c2415Smrg 	{
2531760c2415Smrg 	  /* For -fpre-include file, current_file is NULL.  */
2532760c2415Smrg 	  if (current_file)
2533760c2415Smrg 	    fprintf (stderr, "%s:%d: Error: Can't open included file '%s'\n",
2534760c2415Smrg 		     current_file->filename, current_file->line, filename);
2535760c2415Smrg 	  else
2536760c2415Smrg 	    fprintf (stderr, "Error: Can't open pre-included file '%s'\n",
2537760c2415Smrg 		     filename);
2538760c2415Smrg 
2539760c2415Smrg 	  return false;
2540760c2415Smrg 	}
2541760c2415Smrg       stat_result = stat (realfilename, &st);
2542760c2415Smrg       if (stat_result == 0 && !S_ISREG(st.st_mode))
2543760c2415Smrg 	{
2544760c2415Smrg 	  fprintf (stderr, "%s:%d: Error: Included path '%s'"
2545760c2415Smrg 		   " is not a regular file\n",
2546760c2415Smrg 		   current_file->filename, current_file->line, filename);
2547760c2415Smrg 	  fclose (input);
2548760c2415Smrg 	  return false;
2549760c2415Smrg 	}
2550760c2415Smrg     }
2551760c2415Smrg 
2552760c2415Smrg   /* Load the file.
2553760c2415Smrg 
2554760c2415Smrg      A "non-initial" file means a file that is being included.  In
2555760c2415Smrg      that case we are creating an LC_ENTER map.
2556760c2415Smrg 
2557760c2415Smrg      An "initial" file means a main file; one that is not included.
2558760c2415Smrg      That file has already got at least one (surely more) line map(s)
2559760c2415Smrg      created by gfc_init.  So the subsequent map created in that case
2560760c2415Smrg      must have LC_RENAME reason.
2561760c2415Smrg 
2562760c2415Smrg      This latter case is not true for a preprocessed file.  In that
2563760c2415Smrg      case, although the file is "initial", the line maps created by
2564760c2415Smrg      gfc_init was used during the preprocessing of the file.  Now that
2565760c2415Smrg      the preprocessing is over and we are being fed the result of that
2566760c2415Smrg      preprocessing, we need to create a brand new line map for the
2567760c2415Smrg      preprocessed file, so the reason is going to be LC_ENTER.  */
2568760c2415Smrg 
2569760c2415Smrg   f = get_file (filename, (initial && !preprocessed_p) ? LC_RENAME : LC_ENTER);
2570760c2415Smrg   if (!initial)
2571760c2415Smrg     add_file_change (f->filename, f->inclusion_line);
2572760c2415Smrg   current_file = f;
2573760c2415Smrg   current_file->line = 1;
2574760c2415Smrg   line = NULL;
2575760c2415Smrg   line_len = 0;
2576760c2415Smrg   first_line = true;
2577760c2415Smrg 
2578760c2415Smrg   if (initial && gfc_src_preprocessor_lines[0])
2579760c2415Smrg     {
2580760c2415Smrg       preprocessor_line (gfc_src_preprocessor_lines[0]);
2581760c2415Smrg       free (gfc_src_preprocessor_lines[0]);
2582760c2415Smrg       gfc_src_preprocessor_lines[0] = NULL;
2583760c2415Smrg       if (gfc_src_preprocessor_lines[1])
2584760c2415Smrg 	{
2585760c2415Smrg 	  preprocessor_line (gfc_src_preprocessor_lines[1]);
2586760c2415Smrg 	  free (gfc_src_preprocessor_lines[1]);
2587760c2415Smrg 	  gfc_src_preprocessor_lines[1] = NULL;
2588760c2415Smrg 	}
2589760c2415Smrg     }
2590760c2415Smrg 
2591760c2415Smrg   for (;;)
2592760c2415Smrg     {
2593760c2415Smrg       int trunc = load_line (input, &line, &line_len, NULL);
2594760c2415Smrg       int inc_line;
2595760c2415Smrg 
2596760c2415Smrg       len = gfc_wide_strlen (line);
2597760c2415Smrg       if (feof (input) && len == 0)
2598760c2415Smrg 	break;
2599760c2415Smrg 
2600760c2415Smrg       /* If this is the first line of the file, it can contain a byte
2601760c2415Smrg 	 order mark (BOM), which we will ignore:
2602760c2415Smrg 	   FF FE is UTF-16 little endian,
2603760c2415Smrg 	   FE FF is UTF-16 big endian,
2604760c2415Smrg 	   EF BB BF is UTF-8.  */
2605760c2415Smrg       if (first_line
2606760c2415Smrg 	  && ((line_len >= 2 && line[0] == (unsigned char) '\xFF'
2607760c2415Smrg 			     && line[1] == (unsigned char) '\xFE')
2608760c2415Smrg 	      || (line_len >= 2 && line[0] == (unsigned char) '\xFE'
2609760c2415Smrg 			        && line[1] == (unsigned char) '\xFF')
2610760c2415Smrg 	      || (line_len >= 3 && line[0] == (unsigned char) '\xEF'
2611760c2415Smrg 				&& line[1] == (unsigned char) '\xBB'
2612760c2415Smrg 				&& line[2] == (unsigned char) '\xBF')))
2613760c2415Smrg 	{
2614760c2415Smrg 	  int n = line[1] == (unsigned char) '\xBB' ? 3 : 2;
2615760c2415Smrg 	  gfc_char_t *new_char = gfc_get_wide_string (line_len);
2616760c2415Smrg 
2617760c2415Smrg 	  wide_strcpy (new_char, &line[n]);
2618760c2415Smrg 	  free (line);
2619760c2415Smrg 	  line = new_char;
2620760c2415Smrg 	  len -= n;
2621760c2415Smrg 	}
2622760c2415Smrg 
2623760c2415Smrg       /* There are three things this line can be: a line of Fortran
2624760c2415Smrg 	 source, an include line or a C preprocessor directive.  */
2625760c2415Smrg 
2626760c2415Smrg       if (line[0] == '#')
2627760c2415Smrg 	{
2628760c2415Smrg 	  /* When -g3 is specified, it's possible that we emit #define
2629760c2415Smrg 	     and #undef lines, which we need to pass to the middle-end
2630760c2415Smrg 	     so that it can emit correct debug info.  */
2631760c2415Smrg 	  if (debug_info_level == DINFO_LEVEL_VERBOSE
2632760c2415Smrg 	      && (wide_strncmp (line, "#define ", 8) == 0
2633760c2415Smrg 		  || wide_strncmp (line, "#undef ", 7) == 0))
2634760c2415Smrg 	    ;
2635760c2415Smrg 	  else
2636760c2415Smrg 	    {
2637760c2415Smrg 	      preprocessor_line (line);
2638760c2415Smrg 	      continue;
2639760c2415Smrg 	    }
2640760c2415Smrg 	}
2641760c2415Smrg 
2642760c2415Smrg       /* Preprocessed files have preprocessor lines added before the byte
2643760c2415Smrg 	 order mark, so first_line is not about the first line of the file
2644760c2415Smrg 	 but the first line that's not a preprocessor line.  */
2645760c2415Smrg       first_line = false;
2646760c2415Smrg 
2647760c2415Smrg       inc_line = include_line (line);
2648760c2415Smrg       if (inc_line > 0)
2649760c2415Smrg 	{
2650760c2415Smrg 	  current_file->line++;
2651760c2415Smrg 	  continue;
2652760c2415Smrg 	}
2653760c2415Smrg 
2654760c2415Smrg       /* Add line.  */
2655760c2415Smrg 
2656760c2415Smrg       b = XCNEWVAR (gfc_linebuf, gfc_linebuf_header_size
2657760c2415Smrg 		    + (len + 1) * sizeof (gfc_char_t));
2658760c2415Smrg 
2659760c2415Smrg 
2660760c2415Smrg       b->location
2661760c2415Smrg 	= linemap_line_start (line_table, current_file->line++, len);
2662760c2415Smrg       /* ??? We add the location for the maximum column possible here,
2663760c2415Smrg 	 because otherwise if the next call creates a new line-map, it
2664760c2415Smrg 	 will not reserve space for any offset.  */
2665760c2415Smrg       if (len > 0)
2666760c2415Smrg 	linemap_position_for_column (line_table, len);
2667760c2415Smrg 
2668760c2415Smrg       b->file = current_file;
2669760c2415Smrg       b->truncated = trunc;
2670760c2415Smrg       wide_strcpy (b->line, line);
2671760c2415Smrg 
2672760c2415Smrg       if (line_head == NULL)
2673760c2415Smrg 	line_head = b;
2674760c2415Smrg       else
2675760c2415Smrg 	line_tail->next = b;
2676760c2415Smrg 
2677760c2415Smrg       line_tail = b;
2678760c2415Smrg 
2679760c2415Smrg       while (file_changes_cur < file_changes_count)
2680760c2415Smrg 	file_changes[file_changes_cur++].lb = b;
2681760c2415Smrg 
2682760c2415Smrg       if (flag_dec_include)
2683760c2415Smrg 	{
2684760c2415Smrg 	  if (include_b && b != include_b)
2685760c2415Smrg 	    {
2686760c2415Smrg 	      int inc_line2 = include_stmt (include_b);
2687760c2415Smrg 	      if (inc_line2 == 0)
2688760c2415Smrg 		include_b = NULL;
2689760c2415Smrg 	      else if (inc_line2 > 0)
2690760c2415Smrg 		{
2691760c2415Smrg 		  do
2692760c2415Smrg 		    {
2693760c2415Smrg 		      if (gfc_current_form == FORM_FIXED)
2694760c2415Smrg 			{
2695760c2415Smrg 			  for (gfc_char_t *p = include_b->line; *p; p++)
2696760c2415Smrg 			    *p = ' ';
2697760c2415Smrg 			}
2698760c2415Smrg 		      else
2699760c2415Smrg 			include_b->line[0] = '\0';
2700760c2415Smrg                       if (include_b == b)
2701760c2415Smrg 			break;
2702760c2415Smrg 		      include_b = include_b->next;
2703760c2415Smrg 		    }
2704760c2415Smrg 		  while (1);
2705760c2415Smrg 		  include_b = NULL;
2706760c2415Smrg 		}
2707760c2415Smrg 	    }
2708760c2415Smrg 	  if (inc_line == -1 && !include_b)
2709760c2415Smrg 	    include_b = b;
2710760c2415Smrg 	}
2711760c2415Smrg     }
2712760c2415Smrg 
2713760c2415Smrg   /* Release the line buffer allocated in load_line.  */
2714760c2415Smrg   free (line);
2715760c2415Smrg 
2716760c2415Smrg   fclose (input);
2717760c2415Smrg 
2718760c2415Smrg   if (!initial)
2719760c2415Smrg     add_file_change (NULL, current_file->inclusion_line + 1);
2720760c2415Smrg   current_file = current_file->up;
2721760c2415Smrg   linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
2722760c2415Smrg   return true;
2723760c2415Smrg }
2724760c2415Smrg 
2725760c2415Smrg 
2726760c2415Smrg /* Open a new file and start scanning from that file. Returns true
2727760c2415Smrg    if everything went OK, false otherwise.  If form == FORM_UNKNOWN
2728760c2415Smrg    it tries to determine the source form from the filename, defaulting
2729760c2415Smrg    to free form.  */
2730760c2415Smrg 
2731760c2415Smrg bool
gfc_new_file(void)2732760c2415Smrg gfc_new_file (void)
2733760c2415Smrg {
2734760c2415Smrg   bool result;
2735760c2415Smrg 
2736760c2415Smrg   if (flag_pre_include != NULL
2737760c2415Smrg       && !load_file (flag_pre_include, NULL, false))
2738760c2415Smrg     exit (FATAL_EXIT_CODE);
2739760c2415Smrg 
2740760c2415Smrg   if (gfc_cpp_enabled ())
2741760c2415Smrg     {
2742760c2415Smrg       result = gfc_cpp_preprocess (gfc_source_file);
2743760c2415Smrg       if (!gfc_cpp_preprocess_only ())
2744760c2415Smrg         result = load_file (gfc_cpp_temporary_file (), gfc_source_file, true);
2745760c2415Smrg     }
2746760c2415Smrg   else
2747760c2415Smrg     result = load_file (gfc_source_file, NULL, true);
2748760c2415Smrg 
2749760c2415Smrg   gfc_current_locus.lb = line_head;
2750760c2415Smrg   gfc_current_locus.nextc = (line_head == NULL) ? NULL : line_head->line;
2751760c2415Smrg 
2752760c2415Smrg #if 0 /* Debugging aid.  */
2753760c2415Smrg   for (; line_head; line_head = line_head->next)
2754760c2415Smrg     printf ("%s:%3d %s\n", LOCATION_FILE (line_head->location),
2755760c2415Smrg 	    LOCATION_LINE (line_head->location), line_head->line);
2756760c2415Smrg 
2757760c2415Smrg   exit (SUCCESS_EXIT_CODE);
2758760c2415Smrg #endif
2759760c2415Smrg 
2760760c2415Smrg   return result;
2761760c2415Smrg }
2762760c2415Smrg 
2763760c2415Smrg static char *
unescape_filename(const char * ptr)2764760c2415Smrg unescape_filename (const char *ptr)
2765760c2415Smrg {
2766760c2415Smrg   const char *p = ptr, *s;
2767760c2415Smrg   char *d, *ret;
2768760c2415Smrg   int escaped, unescape = 0;
2769760c2415Smrg 
2770760c2415Smrg   /* Make filename end at quote.  */
2771760c2415Smrg   escaped = false;
2772760c2415Smrg   while (*p && ! (! escaped && *p == '"'))
2773760c2415Smrg     {
2774760c2415Smrg       if (escaped)
2775760c2415Smrg 	escaped = false;
2776760c2415Smrg       else if (*p == '\\')
2777760c2415Smrg 	{
2778760c2415Smrg 	  escaped = true;
2779760c2415Smrg 	  unescape++;
2780760c2415Smrg 	}
2781760c2415Smrg       ++p;
2782760c2415Smrg     }
2783760c2415Smrg 
2784760c2415Smrg   if (!*p || p[1])
2785760c2415Smrg     return NULL;
2786760c2415Smrg 
2787760c2415Smrg   /* Undo effects of cpp_quote_string.  */
2788760c2415Smrg   s = ptr;
2789760c2415Smrg   d = XCNEWVEC (char, p + 1 - ptr - unescape);
2790760c2415Smrg   ret = d;
2791760c2415Smrg 
2792760c2415Smrg   while (s != p)
2793760c2415Smrg     {
2794760c2415Smrg       if (*s == '\\')
2795760c2415Smrg 	*d++ = *++s;
2796760c2415Smrg       else
2797760c2415Smrg 	*d++ = *s;
2798760c2415Smrg       s++;
2799760c2415Smrg     }
2800760c2415Smrg   *d = '\0';
2801760c2415Smrg   return ret;
2802760c2415Smrg }
2803760c2415Smrg 
2804760c2415Smrg /* For preprocessed files, if the first tokens are of the form # NUM.
2805760c2415Smrg    handle the directives so we know the original file name.  */
2806760c2415Smrg 
2807760c2415Smrg const char *
gfc_read_orig_filename(const char * filename,const char ** canon_source_file)2808760c2415Smrg gfc_read_orig_filename (const char *filename, const char **canon_source_file)
2809760c2415Smrg {
2810760c2415Smrg   int c, len;
2811760c2415Smrg   char *dirname, *tmp;
2812760c2415Smrg 
2813760c2415Smrg   gfc_src_file = gfc_open_file (filename);
2814760c2415Smrg   if (gfc_src_file == NULL)
2815760c2415Smrg     return NULL;
2816760c2415Smrg 
2817760c2415Smrg   c = getc (gfc_src_file);
2818760c2415Smrg 
2819760c2415Smrg   if (c != '#')
2820760c2415Smrg     return NULL;
2821760c2415Smrg 
2822760c2415Smrg   len = 0;
2823760c2415Smrg   load_line (gfc_src_file, &gfc_src_preprocessor_lines[0], &len, &c);
2824760c2415Smrg 
2825760c2415Smrg   if (wide_strncmp (gfc_src_preprocessor_lines[0], "# 1 \"", 5) != 0)
2826760c2415Smrg     return NULL;
2827760c2415Smrg 
2828760c2415Smrg   tmp = gfc_widechar_to_char (&gfc_src_preprocessor_lines[0][5], -1);
2829760c2415Smrg   filename = unescape_filename (tmp);
2830760c2415Smrg   free (tmp);
2831760c2415Smrg   if (filename == NULL)
2832760c2415Smrg     return NULL;
2833760c2415Smrg 
2834760c2415Smrg   c = getc (gfc_src_file);
2835760c2415Smrg 
2836760c2415Smrg   if (c != '#')
2837760c2415Smrg     return filename;
2838760c2415Smrg 
2839760c2415Smrg   len = 0;
2840760c2415Smrg   load_line (gfc_src_file, &gfc_src_preprocessor_lines[1], &len, &c);
2841760c2415Smrg 
2842760c2415Smrg   if (wide_strncmp (gfc_src_preprocessor_lines[1], "# 1 \"", 5) != 0)
2843760c2415Smrg     return filename;
2844760c2415Smrg 
2845760c2415Smrg   tmp = gfc_widechar_to_char (&gfc_src_preprocessor_lines[1][5], -1);
2846760c2415Smrg   dirname = unescape_filename (tmp);
2847760c2415Smrg   free (tmp);
2848760c2415Smrg   if (dirname == NULL)
2849760c2415Smrg     return filename;
2850760c2415Smrg 
2851760c2415Smrg   len = strlen (dirname);
2852760c2415Smrg   if (len < 3 || dirname[len - 1] != '/' || dirname[len - 2] != '/')
2853760c2415Smrg     {
2854760c2415Smrg       free (dirname);
2855760c2415Smrg       return filename;
2856760c2415Smrg     }
2857760c2415Smrg   dirname[len - 2] = '\0';
2858760c2415Smrg   set_src_pwd (dirname);
2859760c2415Smrg 
2860760c2415Smrg   if (! IS_ABSOLUTE_PATH (filename))
2861760c2415Smrg     {
2862760c2415Smrg       char *p = XCNEWVEC (char, len + strlen (filename));
2863760c2415Smrg 
2864760c2415Smrg       memcpy (p, dirname, len - 2);
2865760c2415Smrg       p[len - 2] = '/';
2866760c2415Smrg       strcpy (p + len - 1, filename);
2867760c2415Smrg       *canon_source_file = p;
2868760c2415Smrg     }
2869760c2415Smrg 
2870760c2415Smrg   free (dirname);
2871760c2415Smrg   return filename;
2872760c2415Smrg }
2873