/*
**  $VER: MakePROTO 1.0 (08 Apr 1996)  **
**
**        İ 1996 Timo C. Nentwig
**          All Rights Reserved !
**
**        Tcn@techbase.in-berlin.de
**
** ======================================
**
**  Language:
**  ŻŻŻŻŻŻŻŻ
**
**    Program is compiled by SAS/C
**
**
**  Purpose:
**  ŻŻŻŻŻŻŻ
**
**    Scans given files for PROTO line and
**    generates a file with the Prototypes.
**
**    As like as DICE's MakeProto but more
**    flexible.
**
**    Pattern matching is supported.
**    All arguments are worked up.
**
**
**  Requirements:
**  ŻŻŻŻŻŻŻŻŻŻŻŻ
**
**    · AOS 2+
**
**
**  Solve:
**  ŻŻŻŻŻ
**
**
**
**  Bugs:
**  ŻŻŻŻ
**
**    If pressing CTRL-C it is possible that
**    the current file is not closed (so unaccessable)
**
**
**  ToDo:
**  ŻŻŻŻ
**
**
**  Notes:
**  ŻŻŻŻŻ
**
**
**
** ======================================
**
**  History:
**  ŻŻŻŻŻŻŻ
**
**  08 Apr 1996 - 1.0 : initial release
**
*/

#include <dos/rdargs.h>

#include <exec/types.h>
#include <exec/memory.h>

#include <proto/exec.h>
#include <proto/dos.h>

#include <utility/tagitem.h>

#include <strings.h>
#include <stdlib.h>
#include <stdio.h>


#define    EOS    '\0'

#define    PRG_TITLE      "MakePROTO"
#define    PRG_VERSION    "1.0"
#define    PRG_YEAR       "1996"
#define    PRG_AUTHOR     "Timo C. Nentwig"
#define    PRG_EMAIL      "Tcn@techbase.in-berlin.de"

VOID strwrd (STRPTR src, STRPTR dst, UWORD num);

STATIC BYTE    __ver[] = "$VER: "PRG_TITLE" "PRG_VERSION" "__AMIGADATE__;


/// main

VOID
main (VOID)
{

    #define    ARG_TEMPLATE    "F=FILES/M/A,PK=PROTOKEYWORD/K,DT=DEFINETYPE/S,CPP/S,STATIC/S"

    enum     { ARG_FILES, ARG_KEYWORD, ARG_DEFINE, ARG_CPP, ARG_STATIC, ARG_COUNT };

    STRPTR   *ArgArray;


    if (ArgArray = (STRPTR *) AllocVec (sizeof (STRPTR) * (ARG_COUNT), MEMF_ANY | MEMF_CLEAR))
    {

        struct    RDArgs   *ArgsPtr;

        if (ArgsPtr = (struct RDArgs *) AllocDosObject (DOS_RDARGS, TAG_END))
        {

            ArgsPtr -> RDA_ExtHelp  =  "[2m"PRG_TITLE" "PRG_VERSION"\n"
                                       "Copyright İ "PRG_YEAR" by "PRG_AUTHOR"[0m\n"
                                       "All Rights Reserved !\n"
                                       "\n"
                                       PRG_EMAIL"\n"
                                       "\n"
                                       "EXAMPLE: "PRG_TITLE" src:c/#?.c proj:#?.c <...>\n\n";

            if (ReadArgs (ARG_TEMPLATE, (LONG *) ArgArray, ArgsPtr))
            {

                BOOL      g_define  =  FALSE;
                BOOL      g_cpp     =  FALSE;
                BOOL      g_static  =  FALSE;
                STRPTR    g_key     =  AllocVec (256, MEMF_ANY);
                STRPTR   *g_files   =  (STRPTR *) ArgArray[ARG_FILES];


                if (ArgArray [ARG_KEYWORD])    strcpy (g_key, ArgArray [ARG_KEYWORD]);
                if (ArgArray [ARG_DEFINE] )            g_define  =  TRUE;
                if (ArgArray [ARG_CPP]    )            g_cpp     =  TRUE;
                if (ArgArray [ARG_STATIC] )            g_static  =  TRUE;

                #define    BUFFSIZE    240

                if (NULL != (DOSBase = (struct DosLibrary *) OpenLibrary ("dos.library", 37)))
                {

                    struct    AnchorPath   *ap;
                    LONG      err;


                    if (ap = AllocVec (sizeof (struct AnchorPath) + BUFFSIZE, MEMF_CLEAR))
                    {

                        printf ("/*\n");
                        printf (" *    File generated by "PRG_TITLE"\n");
                        printf (" *\n");
                        printf (" *    Copyright İ "PRG_YEAR" by "PRG_AUTHOR"\n");
                        printf (" *    All Rights Reserved !\n");
                        printf (" *\n");
                        printf (" *    "PRG_EMAIL"\n");
                        printf (" *\n");
                        printf (" */\n");

                        if (strlen (g_key) < 1)
                            strcpy (g_key, "Prototype");

                        if (g_define == TRUE)
                            printf ("\n#define    %s    %s\n\n", g_key, (g_static == TRUE) ? "static" : "extern");

                        for (; *g_files; g_files++)
                        {

                            ap -> ap_Strlen = BUFFSIZE;

                            for (err = MatchFirst (*g_files, ap); err == 0; err = MatchNext (ap))
                            {

                                BPTR    file;

                                if (g_cpp == TRUE)
                                    printf ("\n\n// %s\n\n", ap -> ap_Buf);
                                else
                                    printf ("\n\n/* %s */\n\n", ap -> ap_Buf);

                                if (file = Open (ap -> ap_Buf, MODE_READWRITE))
                                {

                                    UBYTE    line[256];


                                    while (FGets (file, line, 255))
                                    {

                                        UBYTE    tmp[256];


                                        strwrd (line, tmp, 0);

                                        if (stricmp (tmp, g_key) == 0)
                                            printf ("%s", line);


                                    }

                                    Close (file);

                                }
                                else
                                {

                                    if (g_cpp)
                                        printf ("// Couldn't access file \"%s\"\n", ap -> ap_Buf);
                                    else
                                        printf ("/* Couldn't access file \"%s\" */\n", ap -> ap_Buf);

                                }

                                CloseLibrary ((struct Library *) DOSBase);

                            }

                        }

                        MatchEnd (ap);
                        FreeVec  (ap);

                    }

                }

                FreeVec  (g_key);
                FreeArgs (ArgsPtr);

            }

            FreeDosObject (DOS_RDARGS, ArgsPtr);

        }

        FreeVec (ArgArray);

    }

}

///
/// strwrd ()

    /*
     *    Copy the n. word to <dst>
     *
     *    First word is 0 not 1.
     *
     *    Characters in quotes (e.g. "my string")
     *    are handled as one word.
     *
     *    If <num> is out of range <dst> gets
     *    an empty string ("")
     *
     *
     *    Note:  If the a quoting is terminated with two quotes (e.g. "my string"")
     *    ŻŻŻŻ   strwrd will handle the second quote (correctly) as the beginning
     *           of another quoting and not like a typing mistake.
     *           This could be changed by doing
     *
     *                             if (*src == '"')
     *                             {
     *
     *                                 sign = '"';
     *                                 while (*src == '"')      // here !
     *                                     *src++;
     *
     *                             }
     *
     */


VOID
strwrd (STRPTR src, STRPTR dst, UWORD num)
{

             UWORD    cnt;                          // count of words already got
             WORD     sign;                         // copy-until <sign>
    REGISTER UWORD    i;                            // byte position in <dst>


    for (cnt = 0, sign = ' '; cnt <= num; cnt++)    // while not right word <num>
    {

        while (*src == ' ' || *src == '\t')         // skip leading spaces
            *src++;

        if (*src == '"')
        {

            sign = '"';                             // set <sign> to end of quoting
            *src++;                                 // skip the space (' ')

        }

        for (i = 0; *src != sign && *src != EOS; *src++, i++)       // until got <sign> or EOS
            dst[i] = *src;                                          // copy to <dst>

        if (*src == '"')
        {

            sign = ' ';                             // got a quoted string but the wrong <num>
            *src++;                                 // skip the space (' ')

        }

    }

    dst[i++] = EOS;                                 // terminate

}

///



