36 #include <qplatformdefs.h>
37 #if defined(Q_OS_UNIX)
47 #include <sys/types.h>
50 #if defined(_MSC_VER) && _MSC_VER >= 1400
58 #define qmake_endOfLine(c) (c == '\r' || c == '\n')
103 int hash(
const char *);
146 int SourceFiles::hash(
const char *
file)
151 if ((
g = (
h & 0xf0000000)) != 0)
185 if(
node->traversed || !
node->exists)
188 node->traversed =
true;
190 for(
int i = 0;
i <
node->deps->used_nodes;
i++)
191 dependTreeWalker(
node->deps->children[
i], place);
199 for (
int i = 0;
i <
l.count(); ++
i) {
218 for(
int i = 0;
i <
node->deps->used_nodes;
i++)
219 dependTreeWalker(
node->deps->children[
i], &place);
238 return node->included_count;
245 return node->mocable;
255 includes = files =
nullptr;
256 files_changed =
false;
259 spare_buffer =
nullptr;
260 spare_buffer_size = 0;
268 spare_buffer =
nullptr;
269 spare_buffer_size = 0;
280 for(
int i=0;
i<
l.size(); ++
i)
325 for (
int i = 0;
i < systemIncludes.size(); ++
i) {
327 QDir systemDir(systemIncludes.at(
i));
333 debug_msg(5,
"File/dir %s is in system dir %s, skipping",
334 qPrintable(
name), qPrintable(systemIncludes.at(
i)));
340 char *QMakeSourceFileInfo::getBuffer(
int s) {
341 if(!spare_buffer || spare_buffer_size <
s)
342 spare_buffer = (
char *)realloc(spare_buffer, spare_buffer_size=
s);
347 #define S_ISDIR(x) (x & _S_IFDIR)
366 static int skipEscapedLineEnds(
const char *
buffer,
int buffer_len,
int offset,
int *lines)
369 while (
offset + 1 < buffer_len
382 static bool matchWhileUnsplitting(
const char *
buffer,
int buffer_len,
int start,
383 const char *needle,
int needle_len,
384 int *matchlen,
int *lines)
387 for (
int n = 0;
n < needle_len;
388 n++,
x = skipEscapedLineEnds(
buffer, buffer_len,
x + 1, lines)) {
389 if (
x >= buffer_len ||
buffer[
x] != needle[
n])
401 static int scanPastString(
char *
buffer,
int buffer_len,
int offset,
int *lines)
410 while (explore >= 0) {
414 &&
buffer[explore - 1] ==
'\\') {
416 }
else if (explore > 1
417 &&
buffer[explore] ==
'\n'
418 &&
buffer[explore - 1] ==
'\r'
419 &&
buffer[explore - 2] ==
'\\') {
422 }
else if (saw8 &&
buffer[explore] ==
'u') {
426 }
else if (saw8 || prefix) {
428 }
else if (explore > 1 &&
buffer[explore] ==
'8') {
431 }
else if (
buffer[explore] ==
'L'
433 ||
buffer[explore] ==
'u') {
436 }
else if (
buffer[explore] ==
'R') {
446 if (israw && explore >= 0
447 && (isalnum(
buffer[explore]) ||
buffer[explore] ==
'_')) {
453 #define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), lines)
477 int matchlen = delimlen, extralines = 0;
481 !matchWhileUnsplitting(
buffer, buffer_len,
482 offset + 1, delim, delimlen,
483 &matchlen, &extralines))
490 *lines += extralines;
513 files_changed =
true;
514 file->dep_checked =
true;
523 #if defined(_MSC_VER) && _MSC_VER >= 1400
525 _O_RDONLY, _SH_DENYNO, _S_IREAD) != 0)
530 if (
fd == -1 || fstat(
fd, &fst) ||
S_ISDIR(fst.st_mode)) {
535 buffer = getBuffer(fst.st_size);
536 for(
int have_read = 0;
537 (have_read =
QT_READ(
fd,
buffer + buffer_len, fst.st_size - buffer_len));
538 buffer_len += have_read) ;
558 } cpp_state = AtStart;
561 if (buffer_len >= 3) {
562 const unsigned char *
p = (
unsigned char *)
buffer;
564 if (
p[0] == 0xEF &&
p[1] == 0xBB &&
p[2] == 0xBF)
567 for (;
x < buffer_len; ++
x) {
568 bool try_local =
true;
580 for (++x; x + inc_len < buffer_len && buffer[x + inc_len] != '<
'; ++inc_len) {} // skip
581 if (x + inc_len < buffer_len) {
582 buffer[x + inc_len] = '\0
';
585 } else if (buffer_len >= x + 13 && !strncmp(buffer + x, "customwidget", 12) &&
586 (buffer[x + 12] == ' ' || buffer[x + 12] == '>
')) {
587 for (x += 13; x < buffer_len && buffer[x] != '>
'; ++x) {} // skip up to >
588 while(x < buffer_len) {
589 while (++x < buffer_len && buffer[x] != '<
') {} // skip up to <
591 if(buffer_len >= x + 7 && !strncmp(buffer+x, "header", 6) &&
592 (buffer[x + 6] == ' ' || buffer[x + 6] == '>
')) {
593 for (x += 7; x < buffer_len && buffer[x] != '>
'; ++x) {} // skip up to >
595 for (++x; x + inc_len < buffer_len && buffer[x + inc_len] != '<
';
596 ++inc_len) {} // skip
597 if (x + inc_len < buffer_len) {
598 buffer[x + inc_len] = '\0
';
602 } else if(buffer_len >= x + 14 && !strncmp(buffer+x, "/customwidget", 13) &&
603 (buffer[x + 13] == ' ' || buffer[x + 13] == '>
')) {
608 } else if(buffer_len >= x + 8 && !strncmp(buffer + x, "include", 7) &&
609 (buffer[x + 7] == ' ' || buffer[x + 7] == '>
')) {
610 for (x += 8; x < buffer_len && buffer[x] != '>
'; ++x) {
611 if (buffer_len >= x + 9 && buffer[x] == 'i' &&
612 !strncmp(buffer + x, "impldecl", 8)) {
613 for (x += 8; x < buffer_len && buffer[x] != '=
'; ++x) {} // skip
614 while (++x < buffer_len && (buffer[x] == '\t' || buffer[x] == ' ')) {} // skip
616 if (x < buffer_len && (buffer[x] == '\
'' ||
buffer[
x] ==
'"')) {
621 for (val_len = 0;
x + val_len < buffer_len; ++val_len) {
623 if (
buffer[
x + val_len] == quote)
625 }
else if (
buffer[
x + val_len] ==
'>' ||
631 if (
x + val_len < buffer_len) {
640 for (++
x;
x + inc_len < buffer_len &&
buffer[
x + inc_len] !=
'<';
643 if (
x + inc_len < buffer_len) {
655 for (;
x < buffer_len; ++
x) {
657 #define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count)
665 int y = skipEscapedLineEnds(
buffer, buffer_len,
x + 1, &extralines);
666 if (
y >= buffer_len) {
670 line_count += extralines;
678 line_count += extralines;
683 y = skipEscapedLineEnds(
buffer, buffer_len,
685 if (
y < buffer_len &&
buffer[
y] ==
'/') {
686 line_count += extralines;
715 const char *
const keyword =
buffer +
x;
731 ((keyword_len == 7 && !
strncmp(keyword,
"include", 7))
732 || (keyword_len == 6 && !
strncmp(keyword,
"import", 6)))
743 }
else if (term !=
'"') {
780 if (cpp_state == WantName)
800 x = scanPastString(
buffer, buffer_len,
x, &line_count);
826 QDir sourceDir = findFileInfo(sourceFile).dir();
828 if(findFileInfo(
f).exists()) {
829 lfn = fixPathForFile(
f);
838 lfn = fixPathForFile(
f);
846 if((exists = !lfn.isNull()))
847 lfn = fixPathForFile(lfn);
852 if (!lfn.isNull() && !isSystemInclude(lfn.real())) {
853 dep =
files->lookupFile(lfn);
863 includes->addFile(dep,
key,
false);
868 if(dep && dep->
file !=
file->file) {
871 debug_msg(5,
"%s:%d Found dependency to %s",
file->file.real().toLatin1().constData(),
873 file->deps->addChild(dep);
879 for(
int i = 0;
i <
file->deps->used_nodes;
i++) {
887 static bool isCWordChar(
char c) {
889 || (
c >=
'a' &&
c <=
'z')
890 || (
c >=
'A' &&
c <=
'Z')
891 || (
c >=
'0' &&
c <=
'9');
896 if(
file->moc_checked)
898 files_changed =
true;
899 file->moc_checked =
true;
906 #if defined(_MSC_VER) && _MSC_VER >= 1400
908 _O_RDONLY, _SH_DENYNO, _S_IREAD) != 0)
913 if (
fd == -1 || fstat(
fd, &fst) ||
S_ISDIR(fst.st_mode)) {
918 buffer = getBuffer(fst.st_size);
919 while (
int have_read =
QT_READ(
fd,
buffer + buffer_len, fst.st_size - buffer_len))
920 buffer_len += have_read;
925 debug_msg(2,
"findMocs: %s",
file->file.local().toLatin1().constData());
930 Q_GADGET_EXPORT_Keyword,
932 Q_NAMESPACE_EXPORT_Keyword,
936 static const char keywords[][19] = {
941 "Q_NAMESPACE_EXPORT",
943 static_assert(
std::size(keywords) == NumKeywords);
944 bool ignore[NumKeywords] = {};
950 for(
int x = 0;
x < buffer_len;
x++) {
951 #define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count)
955 int y = skipEscapedLineEnds(
buffer, buffer_len,
x + 1, &extralines);
956 if (buffer_len >
y) {
959 line_count += extralines;
966 line_count += extralines;
970 const char tag[] =
"make ignore ";
971 const auto starts_with = [](
const char *haystack,
const char *needle) {
974 const auto is_ignore = [&](
const char *keyword) {
980 for (
const char *keyword : keywords) {
981 if (is_ignore(keyword)){
982 debug_msg(2,
"Mocgen: %s:%d Found \"q%s%s\"",
983 file->file.real().toLatin1().constData(), line_count,
986 x +=
static_cast<int>(
strlen(keyword));
987 ignore[interest] =
true;
993 y = skipEscapedLineEnds(
buffer, buffer_len,
x + 1, &extralines);
994 if (buffer_len >
y &&
buffer[
y] ==
'/') {
995 line_count += extralines;
1007 x = scanPastString(
buffer, buffer_len,
x, &line_count);
1013 if (buffer_len >
x + 8 && !isCWordChar(
buffer[
x])) {
1015 int y = skipEscapedLineEnds(
buffer, buffer_len,
x + 1, &morelines);
1017 for (
int interest = 0; interest < NumKeywords; ++interest) {
1018 if (ignore[interest])
1021 int matchlen = 0, extralines = 0;
1022 size_t needle_len =
strlen(keywords[interest]);
1024 if (matchWhileUnsplitting(
buffer, buffer_len,
y,
1026 static_cast<int>(needle_len),
1027 &matchlen, &extralines)
1028 &&
y + matchlen < buffer_len
1029 && !isCWordChar(
buffer[
y + matchlen])) {
1032 debug_msg(2,
"Mocgen: %s:%d Found MOC symbol %s",
1033 file->file.real().toLatin1().constData(),
1034 line_count + morelines,
buffer +
y);
1036 file->mocable =
true;
small capitals from c petite p scientific i
[1]
The QByteArray class provides an array of bytes.
const char * constData() const noexcept
The QDir class provides access to directory structures and their contents.
static bool isAbsolutePath(const QString &path)
static bool isRelativePath(const QString &path)
QString relativeFilePath(const QString &fileName) const
QString absoluteFilePath(const QString &fileName) const
The QFileInfo class provides system-independent file information.
void append(parameter_type t)
const QString & local() const
const QString & real() const
QMakeLocalFileName()=default
virtual ~QMakeSourceFileInfo()
QStringList dependencies(const QString &file)
bool isSystemInclude(const QString &)
void addSourceFiles(const ProStringList &, uchar seek, SourceFileType type=TYPE_C)
virtual QMakeLocalFileName fixPathForFile(const QMakeLocalFileName &, bool forOpen=false)
virtual QMakeLocalFileName findFileForDep(const QMakeLocalFileName &, const QMakeLocalFileName &)
int included(const QString &file)
void addSourceFile(const QString &, uchar seek, SourceFileType type=TYPE_C)
bool containsSourceFile(const QString &, SourceFileType type=TYPE_C)
void setDependencyPaths(const QList< QMakeLocalFileName > &)
bool mocable(const QString &file)
virtual QFileInfo findFileInfo(const QMakeLocalFileName &)
const QObjectList & children() const
The QString class provides a Unicode character string.
QByteArray toLatin1() const &
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
QByteArray toLocal8Bit() const &
The QStringList class provides a list of strings.
SourceFile * lookupFile(const QString &f)
struct SourceFiles::SourceFileNode ** nodes
SourceFile * lookupFile(const char *)
SourceFile * lookupFile(const QMakeLocalFileName &f)
void addFile(SourceFile *, const char *k=nullptr, bool own=true)
#define qmake_endOfLine(c)
void warn_msg(QMakeWarn type, const char *fmt,...)
int PRIV() strcmp(PCRE2_SPTR str1, PCRE2_SPTR str2)
int PRIV() strncmp(PCRE2_SPTR str1, PCRE2_SPTR str2, size_t len)
PCRE2_SIZE PRIV() strlen(PCRE2_SPTR str)
Q_CORE_EXPORT char * qstrdup(const char *)
QT_BEGIN_INCLUDE_NAMESPACE typedef unsigned char uchar
GLint GLint GLint GLint GLint x
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLintptr offset
GLfloat GLfloat GLfloat GLfloat h
file open(QIODevice::ReadOnly)
QFileInfo fi("c:/temp/foo")
[newstuff]
static QString normalizePath(const QString &in, bool fix_env=true, bool canonical=true)
bool contains(const AT &t) const noexcept
void addChild(SourceFile *s)
SourceDependChildren * deps
QMakeSourceFileInfo::SourceFileType type
XmlOutput::xml_output tag(const QString &name)