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 1875 of file fortranscanner.l.

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