;/* execute me to compile with SAS/C (note: CPU option has (nearly) no effect here!)
;SC C-struct_union_class.c IGNORE 73 DEBUG=SYMBOLFLUSH STRINGMERGE NOSTKCHK LINK
SC C-struct_union_class.c IGNORE 73 CPU=68020 OPT OPTTIME STRINGMERGE NOSTKCHK
SLink FROM C-struct_union_class.o TO C-struct_union_class SC SD STRIPDEBUG NOICONS
Delete C-struct_union_class.(o|lnk) QUIET
QUIT
*/
/**************************************************************************

C-struct_union_class.c  --  GoldED4-Scanner für C/C++ struct, union und class

AUTOR(EN):        Thies Wellpott
ERSTELLUNG:       23.03.1997
COPYRIGHT:        (c) 1997 Thies Wellpott
BETRIEBSSYSTEM:   AmigaOS
COMPILER:         SAS/C 6.58

BESCHREIBUNG:

Scanner für GoldED Version 4.
Übergabeparameter:
- ULONG len       Länge der aktuellen Textzeile
- STRPTR *text    Zeiger auf aktuelle Textzeile
- ULONG *line     Zeiger auf aktuelle Zeilennummer
Rückgabewerte:
- ULONG return    Länge des gescannten Textes oder 0 für keinen Text
- STRPTR *text    Zeiger auf Text

Sucht struct, union und class. Leerzeichen vor den Wörter werden ignoriert,
ebenfalls ein davorstehendes "typedef". Die Wörter müssen vollständig klein
geschrieben sein (Def. von ANSI-C).

Um erkannt zu werden, muß die Zeile auf "{" oder ein gültiges C-Symbolzeichen
enden; Variablendefinitionen ("struct datum geburt;") werden so nicht
aufgelistet. Möglich sind also "struct datum\n{ ..." oder "struct datum {\n".

In der Anzeige werden die verschiedenen Elemente (struct, union, class) durch
kurze Texte am Ende gekennzeichnet.


FEHLER/EINSCHRÄNKUNGEN:

- Kommentare werden nicht berücksichtigt und führen zu Problemen
- die Maximallänge eines gescannten Textes beträgt 60 Zeichen (wird intern
  überprüft und abgefangen)


ENTWICKLUNGSGESCHICHTE:

V1.000   23.03.1997   Thies Wellpott
- erste Version

V1.001   22.05.1997   Thies Wellpott
- minimale interne Änderungen

V1.002   15.04.1998   Thies Wellpott
- allgemeine Scanner-Headerdatei verwendet
- 68020 compiliert

**************************************************************************/

#include "twscanner.h"



ULONG __asm golded_scanner(register __d0 ULONG len, register __a0 STRPTR *text,
      register __a1 ULONG *line)
{
   const char *version = "\0$VER: C-struct_union_class 1.2 " __AMIGADATE__;
   // Stringkonstante (in Code-Hunk) als Puffer mißbrauchen
   STRPTR puffer = "123456789012345678901234567890123456789012345678901234567890";
#define PUFFERLAENGE  60
   STRPTR zeichen = *text;

   SKIPBLANKS(zeichen, len);

   if (len >= 7)
   {
      enum { TYP_KEIN, TYP_STRUCT, TYP_UNION, TYP_CLASS } typ;
      STRPTR ende;
      unsigned short laenge;        // braucht kein ULONG zu sein

      // evt. "typedef" überspringen
      if (*zeichen == 't')
      {
         // Zeile beginnt mit "t", also auf "typedef" kontrollieren
         zeichen++;
         if ( (len >= 7+8) && STRCMP4(zeichen, 'y', 'p', 'e', 'd') && STRCMP2(zeichen, 'e', 'f') && ISBLANK(*zeichen) )
         {
            zeichen++;
            len -= 8;
            SKIPBLANKS(zeichen, len);
         } else
            return 0;      // kein typedef, also gar nichts
      } // if

      // Typ bestimmen und Schlüsselwort überspringen
      typ = TYP_KEIN;
      if (*zeichen == 's')
      {
         zeichen++;
         if ( STRCMP4(zeichen, 't', 'r', 'u', 'c') && (*zeichen++ == 't') )
         {
            typ = TYP_STRUCT;
            len -= 7;            // Leerzeichen hier schon mitenthalten
         } // if
      }      
      else if (*zeichen == 'u')
      {
         zeichen++;
         if (STRCMP4(zeichen, 'n', 'i', 'o', 'n'))
         {
            typ = TYP_UNION;
            len -= 6;            // Leerzeichen hier schon mitenthalten
         } // if
      }      
      else if (*zeichen == 'c')
      {
         zeichen++;
         if (STRCMP4(zeichen, 'l', 'a', 's', 's'))
         {
            typ = TYP_CLASS;
            len -= 6;            // Leerzeichen hier schon mitenthalten
         } // if
      } // else if

      // kein gültiger Typ oder kein Leerzeichen nach Schlüsselwort?
      if ( (typ == TYP_KEIN) || !ISBLANK(*zeichen) )
         return 0;

      zeichen++;
      SKIPBLANKS(zeichen, len);

      // Leerzeichen am Ende entfernen
      ende = &zeichen[len - 1];
      while ( len && ISBLANK(*ende) )
      {
         ende--;
         len--;
      } // while

      // restliche Zeile leer oder kein C-Symbolzeichen und kein "{" am Zeilenende?
      if ( (len == 0) || (!ISCSYM(*ende) && (*ende != '{')) )
         return 0;

#define EXTRATEXTLAENGE  5       // Zusatzinfo

      // Name kopieren
      *text = puffer;
      laenge = 0;
      while ( len && (laenge < PUFFERLAENGE - EXTRATEXTLAENGE) && ISCSYM(*zeichen) )
      {
         *puffer++ = *zeichen++;
         laenge++;
         len--;
      } // while

      if (laenge == 0)
         return 0;

      // Infotext anhängen   
      *puffer++ = ' ';
      *puffer++ = '[';
      if (typ == TYP_STRUCT)
      {
         *puffer++ = 's';
         *puffer++ = 't';
      }   
      else if (typ == TYP_UNION)
      {
         *puffer++ = 'u';
         *puffer++ = 'n';
      } else // (typ == TYP_CLASS)
      {
         *puffer++ = 'c';
         *puffer++ = 'l';
      }   
      *puffer = ']';
      return (ULONG)(laenge + 5);
   } // if (len >= 7)

   return 0;
} // golded_scanner()



/**
#include <string.h>

int main(int argc, char *argv[])
{
   char text[128], *erg, laenge;
   
   strcpy(text, "typedef struct dateq");
   erg = text;
   laenge = golded_scanner(strlen(text)-1, &erg, 0);
   erg[laenge] = 0;

   strcpy(text, "   union qwe   q");
   erg = text;
   laenge = golded_scanner(strlen(text)-1, &erg, 0);
   erg[laenge] = 0;

   strcpy(text, "   class auto : fahrzeug {  q");
   erg = text;
   laenge = golded_scanner(strlen(text)-1, &erg, 0);
   erg[laenge] = 0;

   strcpy(text, "  struct win fenster;q");
   erg = text;
   laenge = golded_scanner(strlen(text)-1, &erg, 0);
   erg[laenge] = 0;

   strcpy(text, "typedef char *table[20];q");
   erg = text;
   laenge = golded_scanner(strlen(text)-1, &erg, 0);
   erg[laenge] = 0;

   return 0;
} // main()
**/

