Bläddra i källkod

Implement source file splitting and debugging #line directives (code not used yet, will be used for temp files during compilation).

git-svn-id: file:///var/svn/tigccpp/trunk@618 9552661e-59e3-4036-b4f2-dbe53926924f
kevinkofler 18 år sedan
förälder
incheckning
d495161439
7 ändrade filer med 236 tillägg och 27 borttagningar
  1. 4 0
      ktigcc/ktigcc.h
  2. 3 3
      ktigcc/mainform.ui.h
  3. 0 2
      ktigcc/programoptions.ui.h
  4. 0 2
      ktigcc/projectoptions.ui.h
  5. 3 3
      ktigcc/srcfile.h
  6. 218 17
      ktigcc/tpr.cpp
  7. 8 0
      ktigcc/tpr.h

+ 4 - 0
ktigcc/ktigcc.h

@@ -26,6 +26,8 @@
 class QAssistantClient;
 class QClipboard;
 class SourceFile;
+typedef struct tprsettings tprSettings;
+typedef struct tprlibopts tprLibOpts;
 
 extern const char *tigcc_base;
 extern const char *quill_drv;
@@ -43,3 +45,5 @@ extern const char *parg;
 extern QAssistantClient *assistant;
 extern QClipboard *clipboard;
 extern QPtrList<SourceFile> sourceFiles;
+extern tprSettings settings;
+extern tprLibOpts libopts;

+ 3 - 3
ktigcc/mainform.ui.h

@@ -350,8 +350,8 @@ static QDockWindow *errorListDock;
 static ErrorList *errorList;
 QAssistantClient *assistant;
 static int fileCount=0, hFileCount=0, cFileCount=0, sFileCount=0, asmFileCount=0, qllFileCount=0, oFileCount=0, aFileCount=0, txtFileCount=0, othFileCount=0;
-tprSettings settings; //static is turned off here so ProjectOptions can access it.
-tprLibOpts libopts; //static is turned off here so ProgramOptions can access it.
+tprSettings settings;
+tprLibOpts libopts;
 static QString projectFileName;
 static QString lastDirectory;
 QClipboard *clipboard;
@@ -1478,7 +1478,7 @@ bool MainForm::openProject(const QString &fileName)
                    (type==2)?"GNU Assembler 68k":
                    (type==3)?"Motorola Assembler 68k":
                    (type==1)?"C":
-                    "None",(type==1),(category==cFilesListItem),(type>1));
+                    "None",category,(type==1),(type>1));
     return FALSE;
   }
 }

+ 0 - 2
ktigcc/programoptions.ui.h

@@ -39,8 +39,6 @@
 #include "ktigcc.h"
 #include "tpr.h"
 
-extern tprLibOpts libopts;
-
 void ProgramOptions::ImportSettings()
 {
   //Tab: Calculator

+ 0 - 2
ktigcc/projectoptions.ui.h

@@ -37,8 +37,6 @@
 #include "tpr.h"
 #include "programoptions.h"
 
-extern tprSettings settings;
-
 ProgramOptions *programoptions;
 //the program options subdialog is created at initialization of a ProjectOptions and remains existant until the ProjectOptions is destroyed.
 

+ 3 - 3
ktigcc/srcfile.h

@@ -37,9 +37,9 @@ class KDirWatch;
 
 struct SourceFile : public SourceFileWindow {
   SourceFile(MainForm *mainfrm, const QString &fn, const QString &ft,
-             const QString &hlm, bool isc, bool iscsrc, bool isasm) :
+             const QString &hlm, void *cat, bool isc, bool isasm) :
     SourceFileWindow(), mainForm(mainfrm), fileName(fn), fileText(ft),
-    hlMode(hlm), isCFile(isc), isCSourceFile(iscsrc), isASMFile(isasm)
+    hlMode(hlm), category(cat), isCFile(isc), isASMFile(isasm)
   {
     initBase(); // We can do this only after initializing the variables here.
     show();
@@ -49,8 +49,8 @@ struct SourceFile : public SourceFileWindow {
   QString fileName;
   QString fileText;
   QString hlMode;
+  void *category;
   bool isCFile;
-  bool isCSourceFile; // as opposed to C header file
   bool isASMFile;
 
   KReplaceWithSelectionS *kreplace;

+ 218 - 17
ktigcc/tpr.cpp

@@ -36,6 +36,7 @@
 #include <qtextcodec.h>
 #include <glib.h>
 #include <ticonv.h>
+#include "ktigcc.h"
 #include "tpr.h"
 #include "preferences.h"
 
@@ -749,10 +750,38 @@ static void mkdir_multi(const char *fileName)
   }
 }
 
-int saveFileText(const char *fileName,const QString &fileText)
+static int writeToFile(FILE *f, const QString &text)
+{
+  if (preferences.useCalcCharset) {
+    const unsigned short *utf16=text.ucs2();
+    if (utf16) {
+      char *s=ticonv_charset_utf16_to_ti(CALC_TI89,utf16);
+      size_t l=std::strlen(s);
+      if (fwrite(s,1,l,f)<l) {
+        g_free(s);
+        return -2;
+      }
+      g_free(s);
+    }
+  } else {
+    const char *s=smartAscii(text);
+    size_t l=text.length();
+    if (fwrite(s,1,l,f)<l) return -2;
+  }
+  return 0;
+}
+
+enum CharModes {cmNone, cmNormalText, cmNumber, cmMultiSymbol, cmString, cmChar,
+                cmComment, cmUnchangeableLine, cmExtUnchangeableLine,
+                cmExtUnchangeableLineString, cmTrigraph};
+
+int saveAndSplitFileText(const char *fileName, const QString &fileText,
+                         bool split, bool addCLineDirective,
+                         bool addASMLineDirective, const QString &origFileName,
+                         LineStartList *pLineStartList)
 {
   FILE *f;
-  size_t l;
+  LineStartList lineStartList;
   // remove trailing spaces if requested
   QString text=fileText;
   if (preferences.removeTrailingSpaces && !text.isNull()) {
@@ -768,30 +797,202 @@ int saveFileText(const char *fileName,const QString &fileText)
     if (!f)
         return -1;
   }
-  if (preferences.useCalcCharset) {
-    const unsigned short *utf16=text.ucs2();
-    if (utf16) {
-      char *s=ticonv_charset_utf16_to_ti(CALC_TI89,utf16);
-      l=std::strlen(s);
-      if (fwrite(s,1,l,f)<l) {
-        g_free(s);
-        fclose(f);
-        return -2;
+  if (split && preferences.splitSourceFiles && !settings.debug_info) {
+    unsigned curPos=0, curLine=0, curCol=0, l=text.length();
+    bool atLineStart;
+    CharModes curMode=cmNone;
+
+    #define INSERT_CHAR(ch) do {if (writeToFile(f,QString((ch)))) {fclose(f); return -2;}} while(0)
+    #define INSERT_STRING(str) do {if (writeToFile(f,(str))) {fclose(f); return -2;}} while(0)
+    #define ADD_LINE() do {lineStartList.append(qMakePair(curLine,curCol)); atLineStart=TRUE;} while(0)
+    #define IS_NEWLINE() (text[curPos]=='\n')
+    #define ADD_LINE_NEXT() do {lineStartList.append(qMakePair(curLine+(unsigned)(IS_NEWLINE()),(IS_NEWLINE())?0u:(curCol+1u))); atLineStart=TRUE;} while(0)
+    #define NEW_LINE() do {if((!(atLineStart||IS_NEWLINE())) || (text[curPos]=='#')) {INSERT_CHAR(QChar('\n')); ADD_LINE();} curMode=cmNone;} while(0)
+    #define SET_MULTI_CHAR_MODE(mode) do {if (curMode!=(mode)) {NEW_LINE(); curMode=(mode);}} while(0)
+
+    ADD_LINE(); // Line 0
+    ADD_LINE(); // Line 1
+    for (; curPos<l; curPos++) {
+      bool noInsert=FALSE;
+      QChar c=text[curPos];
+      if (c=='\n')
+        ADD_LINE_NEXT();
+      switch (curMode) {
+        case cmString:
+          if (c=='\"') {
+            bool b=TRUE;
+            unsigned i=curPos-1;
+            while (i && ((text[i]=='\\')||(i>=2&&!text.mid(i-2,3).compare("?""?""/")))) {
+              b=!b;
+              if (text[i]=='\\') --i; else i-=3;
+            }
+            if (b) {
+              curMode=cmNone;
+              noInsert=TRUE;
+              INSERT_STRING(QString(c)+"\n");
+              atLineStart=TRUE;
+              ADD_LINE_NEXT();
+            }
+          }
+          break;
+        case cmChar:
+          if (c=='\'') {
+            bool b=TRUE;
+            unsigned i=curPos-1;
+            while (i && ((text[i]=='\\')||(i>=2&&!text.mid(i-2,3).compare("?""?""/")))) {
+              b=!b;
+              if (text[i]=='\\') --i; else i-=3;
+            }
+            if (b) curMode=cmNone;
+          }
+          break;
+        case cmComment:
+          if ((c=='/')&&(text[curPos-1]=='*')) curMode=cmNone;
+          break;
+        case cmUnchangeableLine:
+          if (c=='\n') curMode=cmNone;
+          break;
+        case cmExtUnchangeableLine:
+          if ((c=='\n')&&(text[curPos-1]!='\\')) curMode=cmNone;
+          else if (c=='\"') curMode=cmExtUnchangeableLineString;
+          break;
+        case cmExtUnchangeableLineString:
+          if (c=='\"') {
+            bool b=TRUE;
+            unsigned i=curPos-1;
+            while (i && ((text[i]=='\\')||(i>=2&&!text.mid(i-2,3).compare("?""?""/")))) {
+              b=!b;
+              if (text[i]=='\\') --i; else i-=3;
+            }
+            if (b) curMode=cmExtUnchangeableLine;
+          }
+          break;
+        case cmTrigraph:
+          if ((c!='?')&&((curPos+1>=l)||(text[curPos+1]!='?'))) curMode=cmNone;
+          break;
+        default:
+          if (!text.mid(curPos,2).compare("//"))
+            SET_MULTI_CHAR_MODE(cmUnchangeableLine);
+          else if (!text.mid(curPos,2).compare("/*"))
+            SET_MULTI_CHAR_MODE(cmComment);
+          else if (!text.mid(curPos,2).compare("?""?""="))
+            SET_MULTI_CHAR_MODE(cmExtUnchangeableLine);
+          else if (!text.mid(curPos,2).compare("?""?")&&(curPos+2<l)
+                   &&QString("()/\'<>!-").contains(text[curPos+2]))
+            SET_MULTI_CHAR_MODE(cmTrigraph);
+          else {
+            switch(c.unicode()) {
+              case ' ':
+              case '\t':
+                if (curPos && text[curPos-1]!=' ' && text[curPos-1]!='\t')
+                  NEW_LINE();
+                break;
+              case 'A' ... 'Z':
+              case 'a' ... 'z':
+              case '0' ... '9':
+              case '_':
+              case '$':
+                if (curMode!=cmNormalText && curMode!=cmNumber) {
+                  NEW_LINE();
+                  if (c>=QChar('0') && c<=QChar('9'))
+                    curMode=cmNumber;
+                  else
+                    curMode=cmNormalText;
+                }
+                break;
+              case '\"':
+                SET_MULTI_CHAR_MODE(cmString);
+                break;
+              case '\'':
+                SET_MULTI_CHAR_MODE(cmChar);
+                break;
+              case '#':
+                SET_MULTI_CHAR_MODE(cmExtUnchangeableLine);
+                break;
+              case '.':
+                if (curMode!=cmNumber) {
+                  if ((curPos+1<l)
+                      &&(text[curPos+1]>=QChar('0')
+                         &&text[curPos+1]<=QChar('9'))) {
+                    NEW_LINE();
+                    curMode=cmNumber;
+                  } else SET_MULTI_CHAR_MODE(cmMultiSymbol);
+                }
+                break;
+              case '+':
+              case '-':
+                if ((curMode!=cmNumber)||(curPos<=1)
+                    ||!QString("eEpP").contains(text[curPos-1]))
+                  SET_MULTI_CHAR_MODE(cmMultiSymbol);
+                break;
+              default:
+                if (QString(",;()[]{}").contains(c)) {
+                  if (curMode!=cmNone) {
+                    NEW_LINE();
+                    curMode=cmNone;
+                  }
+                  if ((curPos+1<l)&&text[curPos+1]!='\n') {
+                    noInsert=TRUE;
+                    INSERT_STRING(QString(c)+"\n");
+                    ADD_LINE_NEXT();
+                  } else SET_MULTI_CHAR_MODE(cmMultiSymbol);
+                }
+                break;
+            }
+          }
+          break;
       }
-      g_free(s);
+      if (!noInsert) {
+        INSERT_CHAR(c);
+        if (c!='\n') atLineStart=FALSE;
+      }
+      if (c=='\n') {
+        curLine++;
+        curCol=0;
+      } else curCol++;
     }
+    NEW_LINE();
+    
+    #undef INSERT_CHAR
+    #undef INSERT_STRING
+    #undef ADD_LINE
+    #undef IS_NEWLINE
+    #undef ADD_LINE_NEXT
+    #undef NEW_LINE
+    #undef SET_MULTI_CHAR_MODE
   } else {
-    const char *s=smartAscii(text);
-    l=fileText.length();
-    if (fwrite(s,1,l,f)<l) {
-      fclose(f);
-      return -2;
+    if ((addCLineDirective || addASMLineDirective) && settings.debug_info) {
+      QString escapedFileName=origFileName, lineDirective;
+      escapedFileName.replace("\\","\\\\");
+      escapedFileName.replace("\"","\\\"");
+      // These have no business to be in a file name, but someone somewhere may
+      // have that very bad idea...
+      escapedFileName.replace("\r","\\r");
+      escapedFileName.replace("\n","\\n");
+      lineDirective=QString(addCLineDirective
+                            ?"#line 1 \"%1\"\n"
+                            :".appfile \"%1\"; .appline 1\n").arg(escapedFileName);
+      // Don't use calc charset for this, it's a host file name.
+      const char *s=smartAscii(escapedFileName);
+      size_t l=escapedFileName.length();
+      if (fwrite(s,1,l,f)<l) return -2;
+    }
+    if (writeToFile(f,text)) {fclose(f); return -2;}
+    if (addCLineDirective) {
+      if (fwrite("\n",1,1,f)<1) {fclose(f); return -2;}
     }
   }
   if (fclose(f)) return -2;
+  if (pLineStartList) *pLineStartList=lineStartList;
   return 0;
 }
 
+int saveFileText(const char *fileName,const QString &fileText)
+{
+  return saveAndSplitFileText(fileName,fileText,FALSE,FALSE,FALSE,QString::null,
+                              static_cast<LineStartList *>(NULL));
+}
+
 void kurlNewFileName(KURL &dir,const QString &newFileName)
 {
   if (newFileName[0]=='/')

+ 8 - 0
ktigcc/tpr.h

@@ -24,6 +24,8 @@
 class KURL;
 #include <qstring.h>
 #include <qstringlist.h>
+#include <qvaluevector.h>
+#include <qpair.h>
 
 /*Structure definitions from tprbuilder source; slightly modified
     to work under C++
@@ -154,6 +156,8 @@ typedef struct
 
 enum {PATH_ERROR,PATH_NOTFOUND,PATH_FILE,PATH_FOLDER}; //return types for getPathType
 
+typedef QValueVector<QPair<unsigned,unsigned> > LineStartList;
+
 const char *smartAscii(const QString &s);
 
 void newSettings(tprSettings *settings,tprLibOpts *libopts);
@@ -162,6 +166,10 @@ int loadTPR(const QString &fileName,TPRDataStruct *dest);
 QString loadFileText(const char *fileName);
 
 int saveTPR(const QString &fileName,TPRDataStruct *src);
+int saveAndSplitFileText(const char *fileName, const QString &fileText,
+                         bool split, bool addCLineDirective,
+                         bool addASMLineDirective, const QString &origFileName,
+                         LineStartList *pLineStartList);
 int saveFileText(const char *fileName,const QString &fileText);
 
 void kurlNewFileName(KURL &dir,const QString &newFileName);