Doxygen
Loading...
Searching...
No Matches
fortranscanner.h File Reference
#include "parserintf.h"
+ Include dependency graph for fortranscanner.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

class  FortranOutlineParser
 Fortran language parser using state-based lexical scanning. More...
 
class  FortranOutlineParserFree
 
class  FortranOutlineParserFixed
 

Functions

const char * prepassFixedForm (const char *contents, int *hasContLine, int fixedCommentAfter)
 

Function Documentation

◆ prepassFixedForm()

const char * prepassFixedForm ( const char * contents,
int * hasContLine,
int fixedCommentAfter )

Definition at line 1866 of file fortranscanner.l.

1867{
1868 int column=0;
1869 int prevLineLength=0;
1870 int prevLineAmpOrExclIndex=-1;
1871 int skipped = 0;
1872 char prevQuote = '\0';
1873 char thisQuote = '\0';
1874 bool emptyLabel=TRUE;
1875 bool commented=FALSE;
1876 bool inSingle=FALSE;
1877 bool inDouble=FALSE;
1878 bool inBackslash=FALSE;
1879 bool fullCommentLine=TRUE;
1880 bool artificialComment=FALSE;
1881 bool spaces=TRUE;
1882 int newContentsSize = (int)strlen(contents)+3; // \000, \n (when necessary) and one spare character (to avoid reallocation)
1883 char* newContents = (char*)malloc(newContentsSize);
1884 int curLine = 1;
1885 size_t sizCont;
1886
1887 int j = -1;
1888 sizCont = strlen(contents);
1889 for(size_t i=0;i<sizCont;i++) {
1890 column++;
1891 char c = contents[i];
1892 if (artificialComment && c != '\n')
1893 {
1894 if (c == '!' && spaces)
1895 {
1896 newContents[j++] = c;
1897 artificialComment = FALSE;
1898 spaces = FALSE;
1899 skipped = 0;
1900 continue;
1901 }
1902 else if (c == ' ' || c == '\t') continue;
1903 else
1904 {
1905 spaces = FALSE;
1906 skipped++;
1907 continue;
1908 }
1909 }
1910
1911 j++;
1912 if (j>=newContentsSize-3) { // check for spare characters, which may be eventually used below (by & and '! ')
1913 newContents = (char*)realloc(newContents, newContentsSize+1000);
1914 newContentsSize = newContentsSize+1000;
1915 }
1916
1917 switch(c) {
1918 case '\n':
1919 if (!fullCommentLine)
1920 {
1921 prevLineLength=column;
1922 prevLineAmpOrExclIndex=getAmpOrExclAtTheEnd(&contents[i-prevLineLength+1], prevLineLength,prevQuote);
1923 if (prevLineAmpOrExclIndex == -1) prevLineAmpOrExclIndex = column - 1;
1924 if (skipped)
1925 {
1926 prevLineAmpOrExclIndex = -1;
1927 skipped = 0;
1928 }
1929 }
1930 else
1931 {
1932 prevLineLength+=column;
1933 /* Even though a full comment line is not really a comment line it can be seen as one. An empty line is also seen as a comment line (small bonus) */
1934 if (hasContLine)
1935 {
1936 hasContLine[curLine - 1] = 1;
1937 }
1938 }
1939 artificialComment=FALSE;
1940 spaces=TRUE;
1941 fullCommentLine=TRUE;
1942 column=0;
1943 emptyLabel=TRUE;
1944 commented=FALSE;
1945 newContents[j]=c;
1946 prevQuote = thisQuote;
1947 curLine++;
1948 break;
1949 case ' ':
1950 case '\t':
1951 newContents[j]=c;
1952 break;
1953 case '\000':
1954 if (hasContLine)
1955 {
1956 free(newContents);
1957 return nullptr;
1958 }
1959 newContents[j]='\000';
1960 newContentsSize = (int)strlen(newContents);
1961 if (newContents[newContentsSize - 1] != '\n')
1962 {
1963 // to be on the safe side
1964 newContents = (char*)realloc(newContents, newContentsSize+2);
1965 newContents[newContentsSize] = '\n';
1966 newContents[newContentsSize + 1] = '\000';
1967 }
1968 return newContents;
1969 case '"':
1970 case '\'':
1971 case '\\':
1972 if ((column <= fixedCommentAfter) && (column!=6) && !commented)
1973 {
1974 // we have some special cases in respect to strings and escaped string characters
1975 fullCommentLine=FALSE;
1976 newContents[j]=c;
1977 if (c == '\\')
1978 {
1979 inBackslash = !inBackslash;
1980 break;
1981 }
1982 else if (c == '\'')
1983 {
1984 if (!inDouble)
1985 {
1986 inSingle = !inSingle;
1987 if (inSingle) thisQuote = c;
1988 else thisQuote = '\0';
1989 }
1990 break;
1991 }
1992 else if (c == '"')
1993 {
1994 if (!inSingle)
1995 {
1996 inDouble = !inDouble;
1997 if (inDouble) thisQuote = c;
1998 else thisQuote = '\0';
1999 }
2000 break;
2001 }
2002 }
2003 inBackslash = FALSE;
2004 // fallthrough
2005 case '#':
2006 case 'C':
2007 case 'c':
2008 case '*':
2009 case '!':
2010 if ((column <= fixedCommentAfter) && (column!=6))
2011 {
2012 emptyLabel=FALSE;
2013 if (column==1)
2014 {
2015 newContents[j]='!';
2016 commented = TRUE;
2017 }
2018 else if ((c == '!') && !inDouble && !inSingle)
2019 {
2020 newContents[j]=c;
2021 commented = TRUE;
2022 }
2023 else
2024 {
2025 if (!commented) fullCommentLine=FALSE;
2026 newContents[j]=c;
2027 }
2028 break;
2029 }
2030 // fallthrough
2031 default:
2032 if (!commented && (column < 6) && ((c - '0') >= 0) && ((c - '0') <= 9))
2033 { // remove numbers, i.e. labels from first 5 positions.
2034 newContents[j]=' ';
2035 }
2036 else if (column==6 && emptyLabel)
2037 { // continuation
2038 if (!commented) fullCommentLine=FALSE;
2039 if (c != '0')
2040 { // 0 not allowed as continuation character, see f95 standard paragraph 3.3.2.3
2041 newContents[j]=' ';
2042
2043 if (prevLineAmpOrExclIndex==-1)
2044 { // add & just before end of previous line
2045 /* first line is not a continuation line in code, just in snippets etc. */
2046 if (curLine != 1) insertCharacter(newContents, j+1, (j+1)-6-1, '&');
2047 j++;
2048 }
2049 else
2050 { // add & just before end of previous line comment
2051 /* first line is not a continuation line in code, just in snippets etc. */
2052 if (curLine != 1) insertCharacter(newContents, j+1, (j+1)-6-prevLineLength+prevLineAmpOrExclIndex+skipped, '&');
2053 skipped = 0;
2054 j++;
2055 }
2056 if (hasContLine)
2057 {
2058 hasContLine[curLine - 1] = 1;
2059 }
2060 }
2061 else
2062 {
2063 newContents[j]=c; // , just handle like space
2064 }
2065 prevLineLength=0;
2066 }
2067 else if ((column > fixedCommentAfter) && !commented)
2068 {
2069 // first non commented non blank character after position fixedCommentAfter
2070 if (c == '&')
2071 {
2072 newContents[j]=' ';
2073 }
2074 else if (c != '!')
2075 {
2076 // I'm not a possible start of doxygen comment
2077 newContents[j]=' ';
2078 artificialComment = TRUE;
2079 spaces=TRUE;
2080 skipped = 0;
2081 }
2082 else
2083 {
2084 newContents[j]=c;
2085 commented = TRUE;
2086 }
2087 }
2088 else
2089 {
2090 if (!commented) fullCommentLine=FALSE;
2091 newContents[j]=c;
2092 emptyLabel=FALSE;
2093 }
2094 break;
2095 }
2096 }
2097
2098 if (hasContLine)
2099 {
2100 free(newContents);
2101 return nullptr;
2102 }
2103
2104 if (j==-1) // contents was empty
2105 {
2106 newContents = (char*)realloc(newContents, 2);
2107 newContents[0] = '\n';
2108 newContents[1] = '\000';
2109 }
2110 else if (newContents[j] == '\n') // content ended with newline
2111 {
2112 newContents = (char*)realloc(newContents, j+2);
2113 newContents[j + 1] = '\000';
2114 }
2115 else // content did not end with a newline
2116 {
2117 newContents = (char*)realloc(newContents, j+3);
2118 newContents[j + 1] = '\n';
2119 newContents[j + 2] = '\000';
2120 }
2121 return newContents;
2122}
static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch)
static void insertCharacter(char *contents, int length, int pos, char c)
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34

References FALSE, getAmpOrExclAtTheEnd(), insertCharacter(), and TRUE.

Referenced by checkContLines(), and parseMain().