home *** CD-ROM | disk | FTP | other *** search
- /*
- ** $Id: sasc.module.c,v 1.3 2001/03/04 18:56:04 damato Exp $
- **
- ** AmIDE - Amiga Integrated Development Environment
- ** API Functions
- **
- ** Copyright (C) 1998-2001 by
- **
- ** LightSpeed Communications GbR
- **
- ** Jens Langner Jens Troeger
- ** Bergstrasse 68 i4/182 Dornoch Tce
- ** 01069 Dresden Highgate Hill, QLD, 4101
- ** Germany Australia
- ** <damato@light-speed.de> <savage@light-speed.de>
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation; either version 2 of the License, or
- ** any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- **
- */
-
- #define __USE_SYSBASE // perhaps only recognized by SAS/C
-
- #include <clib/alib_protos.h>
- #include <dos/dostags.h>
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <utility/hooks.h>
- #include <proto/utility.h>
- #include <proto/dos.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <clib/debug_protos.h>
- #include <string.h>
-
- #ifdef __MAXON__
- #include <clib/exec_protos.h>
- #include <clib/intuition_protos.h>
- #else
- #include <proto/exec.h>
- #include <proto/intuition.h>
- #include <intuition/intuition.h>
- #endif
-
- #include <proto/exec.h>
-
- #include "compiler.h"
- #include "sasc.module.h"
-
- #include <amide/amide_api.h>
- #include <clib/savage_protos.h>
-
- /*
- ** Global variables
- */
-
- struct IClass *cl = 0;
-
- #ifdef DEBUG
- static const char *id="@(#) $Id: sasc.module.c,v 1.3 2001/03/04 18:56:04 damato Exp $";
- #endif
-
- /*
- ** AmIDE_API_GetClass
- **
- ** This is the only public function of the shared library
- ** It should only return the created class from the LibInit.c
- **
- ** parameters:
- ** ~~~~~~~~~~~
- ** void
- **
- ** Rückgabewerte:
- ** ~~~~~~~~~~~~~
- ** struct IClass *: Pointer to the created Class
- */
-
- SAVEDS ASM struct IClass *AmIDE_API_GetClass(void)
- {
- return(cl);
- }
-
- /***************************************************************************************
- **
- ** Here follows the internal Methods and dispatcher function
- **
- */
-
- /*
- ** AmIDE_API_New
- **
- ** Method to create the object
- **
- ** Übergabeparameter:
- ** ~~~~~~~~~~~~~~~~~
- ** Class *: Die aufrufende Klasse
- ** Object *: Das Objekt
- ** struct opSet *: Die Message
- **
- ** Rückgabewerte:
- ** ~~~~~~~~~~~~~
- ** METHOD: Das neue Objekt
- */
-
- METHOD MODULE_New(Class *cl, Object *obj, struct opSet *msg)
- {
- struct MODS_InstData *Data;
-
- Object *newobj;
-
- #ifdef DEBUG
- DEBUG_MAKRO
- #endif
-
- if(newobj = (Object *)DoSuperMethodA(cl, obj, (Msg) msg))
- {
- // get the InstData
- Data = INST_DATA(cl, newobj);
-
- // get the attributes from the NewObject() call
- Data->parent_obj = (Object *)GetTagData(AmIDEA_API_parentObj, NULL, msg->ops_AttrList);
- }
-
- return((ULONG)newobj);
- }
-
- /*
- ** AmIDE_API_Get
- **
- ** Method to get attributes of an object
- **
- ** parameters:
- ** ~~~~~~~~~~
- ** Class * : The created class
- ** Object * : The object
- ** struct opGet * : The opGet Message
- **
- ** return-values:
- ** ~~~~~~~~~~~~~~
- ** METHOD: 0 at sucess
- */
-
- METHOD MODULE_Get(Class *cl, Object *obj, struct opGet *msg)
- {
- #ifdef DEBUG
- DEBUG_MAKRO
- #endif
-
- switch (msg->opg_AttrID)
- {
- case AmIDEA_API_author: { *(msg -> opg_Storage) = (ULONG)AUTHOR; } break;
- case AmIDEA_API_api_vers: { *(msg -> opg_Storage) = (ULONG)API_VERS; } break;
- case AmIDEA_API_lib_vers: { *(msg -> opg_Storage) = (ULONG)LIBNAME LIBVER; } break;
- case AmIDEA_API_compiler: { *(msg -> opg_Storage) = (ULONG)COMPILER; } break;
-
- default: { DoSuperMethodA(cl, obj, (Msg) msg); break; };
- }
-
- return(0);
- }
-
- /*
- ** AmIDE_API__Set
- ** The OM_SET Method of the object
- ** With this method all attributes will be set
- **
- ** parameters:
- ** ~~~~~~~~~~
- ** Class * : The created class
- ** Object * : The object
- ** struct opSet * : The opSet Message structure
- **
- ** return values:
- ** ~~~~~~~~~~~~~
- ** 0
- */
-
- METHOD MODULE_Set(Class *cl, Object *obj, struct opSet *msg)
- {
- struct MODS_InstData *Data = INST_DATA(cl, obj);
- struct TagItem *newdata;
-
- #ifdef DEBUG
- DEBUG_MAKRO
- #endif
-
- // find the TagItem and set the variable
- if (newdata = FindTagItem(AmIDEA_API_parentObj, msg -> ops_AttrList))
- {
- Data->parent_obj = (Object *)(newdata->ti_Data);
- }
-
- // All other item are not belonging to us
- DoSuperMethodA(cl, obj, (Msg) msg);
-
- return(0);
- }
-
- /*
- ** AmIDE_API_compile
- **
- ** This method is the MAIN Method of this shared-library.
- ** It handles all the compilation stuff. Will start the compiler with the correct options
- ** and also returns the compiler messages by calling a AmIDE Method.
- ** It should also preparse the messages and insert standard MUI-NList styles to the
- ** message
- **
- ** parameters:
- ** ~~~~~~~~~~
- ** Class * : The created class
- ** Object * : The object
- ** Msg : The Message
- **
- ** return-values:
- ** ~~~~~~~~~~~~~~
- ** METHOD: 0 at sucess
- */
-
- METHOD MODULE_Compile(Class *cl, Object *obj, struct AmIDEP_API_compile_Message *msg)
- {
- struct MODS_InstData *Data = INST_DATA(cl, obj);
-
- char command[256];
- BPTR fh, nil;
-
- #ifdef DEBUG
- DEBUG_MAKRO
- #endif
-
- // Set log position to zero
- Data->log_position = 0;
-
- // create logfile-name
- sprintf(Data->logfile, "T:AmIDE-%s-compile.log", FilePart(msg->filename));
-
- // delete existing log-file
- DeleteFile(Data->logfile);
-
- fh = Open(Data->logfile, MODE_READWRITE);
- nil = Open("NIL:", MODE_OLDFILE);
-
- if(fh)
- {
- BOOL rc;
-
- // create the execute command
- sprintf(command, "sc:c/sc %s VERBOSE", msg->filename);
-
- rc = SystemTags( command,
- SYS_Input, nil,
- SYS_Output, fh,
- SYS_Asynch, TRUE,
- SYS_UserShell, TRUE,
- NP_Priority, 0,
- NP_Error, fh,
- NP_WindowPtr, NULL,
- NP_Cli, TRUE,
- TAG_DONE);
-
- if(!rc)
- {
- BPTR lock;
-
- while(!(lock = Lock(Data->logfile, ACCESS_WRITE)))
- {
- // Das Logfile einlesen
- DoMethod(obj, MODM_Logfile_Read, TAG_DONE);
- }
- if(lock) UnLock(lock);
-
- // if there are something left in the logfile
- while(Data->log_position != sav_FileSize(Data->logfile)) DoMethod(obj, MODM_Logfile_Read, TAG_DONE);
-
- }
-
- }
-
- return(0);
- }
-
- /*
- ** MODULE_Link
- ** Method to link all files passed in the message
- **
- ** parameters:
- ** ~~~~~~~~~~~
- ** Class * : the class itself
- ** Object *: the object
- ** Msg : the AmIDEP_API_link_Message
- **
- ** return-values:
- ** ~~~~~~~~~~~~~~
- ** METHOD: The new object or NULL
- */
-
- METHOD MODULE_Link(Class *cl, Object *obj, struct AmIDEP_API_link_Message *msg)
- {
- struct MODS_InstData *Data = INST_DATA(cl, obj);
-
- STRPTR *file_array = msg->file_array;
- STRPTR exe_name = msg->exe_name;
-
- char obj_list[1024] = "";
- char lib_list[1024] = "";
- char command[256];
- BOOL rc;
- BPTR lock;
- BPTR fh, nil;
- LONG i;
-
- #ifdef DEBUG
- DEBUG_MAKRO
- #endif
-
- // Now we have to create the temporary WITH file
- for(i=0; file_array[i]; i++)
- {
- // Now we search for .lib files so that this one will be linked together with the other object files
- if(sav_MatchPatternNoCase("#?.lib", file_array[i]))
- {
- strcat(lib_list, file_array[i]);
- strcat(lib_list, " ");
-
- }else
- {
- strcat(obj_list, file_array[i]);
- strcat(obj_list, " ");
- }
- }
-
- if(fh = Open("T:AmIDE.tmp", MODE_NEWFILE))
- {
- FPrintf(fh, "VERBOSE\n");
- FPrintf(fh, "TO %s\n", exe_name);
- FPrintf(fh, "FROM %s\n", obj_list);
- FPrintf(fh, "LIBRARY %s\n", lib_list);
-
- Close(fh);
- }
-
- strcpy(command, "sc:c/slink WITH T:AmIDE.tmp");
-
- // first we set the log position to zero
- Data->log_position = 0;
-
- // create logfile-name
- strcpy(Data->logfile, "T:AmIDE-link.log");
-
- // delete a existing log file first
- DeleteFile(Data->logfile);
-
- fh = Open(Data->logfile, MODE_READWRITE);
- nil = Open("NIL:", MODE_OLDFILE);
-
- if(fh)
- {
- rc = SystemTags( command,
- SYS_Input, nil,
- SYS_Output, fh,
- SYS_Asynch, TRUE,
- SYS_UserShell, TRUE,
- NP_Priority, 0,
- NP_Error, fh,
- NP_WindowPtr, NULL,
- NP_Cli, TRUE,
- TAG_DONE);
-
- if(!rc)
- {
-
- while(!(lock = Lock(Data->logfile, ACCESS_WRITE)))
- {
- // read the logfile now
- DoMethod(obj, MODM_Logfile_Read, TAG_DONE);
- }
- if(lock) UnLock(lock);
-
- // check if there is something left in the logfile and read the rest again
- while(Data->log_position != sav_FileSize(Data->logfile)) DoMethod(obj, MODM_Logfile_Read, TAG_DONE);
- }
-
- }
-
- return(0);
- }
-
- /*
- ** MODULE_Log_Read
- ** Method for reading the logfile and parsing it step by step
- **
- ** parameters:
- ** ~~~~~~~~~~~
- ** Class * : the class itself
- ** Object *: the object
- ** Msg : the Message
- **
- ** return-values:
- ** ~~~~~~~~~~~~~~
- ** METHOD: NULL
- */
-
- METHOD MODULE_Log_Read(Class *cl, Object *obj, Msg msg)
- {
- struct MODS_InstData *Data = INST_DATA(cl, obj);
-
- STRPTR buffer, endstring;
- BPTR mfile;
- ULONG size = Data->log_position;
- ULONG newsize;
- APTR tmpbuf;
-
- #ifdef DEBUG
- DEBUG_MAKRO
- #endif
-
- newsize = sav_FileSize(Data->logfile);
-
- if(size != newsize && newsize > 0)
- {
- if(mfile = Open(Data->logfile, MODE_OLDFILE))
- {
- buffer = tmpbuf = sav_AllocVec(((newsize-size)+1) * sizeof(char), MEMF_ANY);
-
- if(!buffer || !tmpbuf)
- {
- Close(mfile);
- return(0);
- }
-
- Seek(mfile, size, OFFSET_BEGINNING);
- FRead(mfile, buffer, 1, (newsize-size));
- Close(mfile);
-
- while(endstring = strchr(buffer, '\n'))
- {
- *endstring = 0;
- Data->msg_text = buffer;
- DoMethod(obj, MODM_Msg_Parse, 0);
- buffer = endstring + 1;
- }
-
- // If there is already a string
- if(strlen(buffer) > 0)
- {
- Data->msg_text = buffer;
- DoMethod(obj, MODM_Msg_Parse, 0);
- newsize = newsize + 1;
- }
-
- // set the position to which we parsed the logfile yet
- Data->log_position = newsize;
-
- sav_FreeVec(tmpbuf);
- }
- }
-
- return(0);
- }
-
- /*
- ** MODULE_Msg_Parse
- ** Method to parse the strings from the logfile and modify them to get it back to AmIDE
- **
- ** parameters:
- ** ~~~~~~~~~~~
- ** Class * : the class itself
- ** Object *: the object
- ** Msg : the Message
- **
- ** return-values:
- ** ~~~~~~~~~~~~~~
- ** METHOD: the new object or NULL
- */
-
- METHOD MODULE_Msg_Parse(Class *cl, Object *obj, Msg msg)
- {
- struct MODS_InstData *Data = INST_DATA(cl, obj);
-
- #ifdef DEBUG
- DEBUG_MAKRO
- #endif
-
- /*
- ** messages that we ignore and don`t want to be displayed in AmIDE
- */
-
- if(strlen(Data->msg_text) < 4) return(0);
- if(strstr(Data->msg_text, "Using options file")) return(0);
- if(strstr(Data->msg_text, "Pass1 for")) return(0);
- if(strstr(Data->msg_text, "Pass2 for")) return(0);
- if(strstr(Data->msg_text, "\033[F")) return(0);
- if(strstr(Data->msg_text, "\033[K")) return(0);
- if(strstr(Data->msg_text, "Slink -")) return(0);
-
- /*
- ** The following messages are relevant ones so we insert them with MODM_Msg_Insert into the AmIDE MsgBrowser
- */
-
- if(strcmp(Data->msg_text, "====================") == 0) { return(DoMethod(obj, MODM_Msg_Insert, MODA_MSG_BAR, TAG_DONE)); };
- if(strstr(Data->msg_text, " Warning ")) { return(DoMethod(obj, MODM_Msg_Insert, MODA_MSG_WARNING, TAG_DONE)); };
- if(strstr(Data->msg_text, " Note ")) { return(DoMethod(obj, MODM_Msg_Insert, MODA_MSG_NOTE, TAG_DONE)); };
- if(strstr(Data->msg_text, "\033[33;7m")) { return(DoMethod(obj, MODM_Msg_Insert, MODA_MSG_WARNING_TXT, TAG_DONE)); };
- if(strstr(Data->msg_text, " Error ")) { return(DoMethod(obj, MODM_Msg_Insert, MODA_MSG_ERROR, TAG_DONE)); };
- if(strstr(Data->msg_text, "Compiler Phase 1")) { return(DoMethod(obj, MODM_Msg_Insert, MODA_MSG_COMPILER_P1, TAG_DONE)); };
- if(strstr(Data->msg_text, "Compiler Phase 2")) { return(DoMethod(obj, MODM_Msg_Insert, MODA_MSG_COMPILER_P2, TAG_DONE)); };
- if(strstr(Data->msg_text, "Global Optimizer")) { return(DoMethod(obj, MODM_Msg_Insert, MODA_MSG_OPTIMIZER, TAG_DONE)); };
-
-
- return(DoMethod(obj, MODM_Msg_Insert, MODA_MSG_DEFAULT, TAG_DONE));
- }
-
- /*
- ** MODULE_Msg_Insert
- ** Method to send the parsed strings to AmIDE in the correct format
- **
- ** parameters:
- ** ~~~~~~~~~~~
- ** Class * : the class itself
- ** Object *: the object
- ** Msg : the MODS_Msg_Insert Message
- **
- ** return-values:
- ** ~~~~~~~~~~~~~~
- ** METHOD: The new object or NULL
- */
-
- METHOD MODULE_Msg_Insert(Class *cl, Object *obj, struct MODS_Msg_Insert *msg)
- {
- struct MODS_InstData *Data = INST_DATA(cl, obj);
-
- // First we allocate memory for a message
- struct AmIDES_message *message = sav_AllocVec(sizeof(struct AmIDES_message), MEMF_ANY);
-
- #ifdef DEBUG
- DEBUG_MAKRO
- #endif
-
- if(!message) return(0);
-
- // fill it with some standard values
- message->errnr = -1;
- message->line = -1;
- message->text = NULL;
-
- // Depending on the message type we are going to modify it different and send it to AmIDE
- switch(msg->msg_type)
- {
- //
- // If this is a BAR we send a MUI BAR string
- //
- case MODA_MSG_BAR:
- {
- message->text = sav_AllocVec((strlen(AmIDE_MSG_STYLE_BAR)+10)*sizeof(char), MEMF_ANY);
- if(!message->text) return(0);
-
- strcpy(message->text, AmIDE_MSG_STYLE_BAR);
-
- message->type = AmIDE_MSG_DEFAULT;
- }
- break;
-
- //
- // If this is a NOTE/EROOR or WARNING we do the following
- //
- case MODA_MSG_NOTE:
- case MODA_MSG_ERROR:
- case MODA_MSG_WARNING:
- {
- int pos;
- char tmp_str2[256];
- char tmp_type[256];
- STRPTR tmp_errnr;
- STRPTR tmp_line;
- STRPTR tmp_str;
-
- //
- // Now we parse the string and get out error-number and line-number
-
- // read the message text
- tmp_str = strstr(Data->msg_text, ": ")+2;
-
- message->text = sav_AllocVec((strlen(tmp_str)+1)*sizeof(char), MEMF_ANY);
- if(!message->text) return(0);
- strcpy(message->text, tmp_str);
-
- // now we get the error/warning number out of the string
- pos = strlen(Data->msg_text)-strlen(tmp_str)-2;
- strncpy(tmp_str2, Data->msg_text, pos);
- tmp_str2[pos] = '\0';
- tmp_errnr = strrchr(tmp_str2, ' ')+1;
-
- message->errnr = atol(tmp_errnr);
-
- // now lets get the line number
- tmp_str2[strlen(tmp_str2)-strlen(tmp_errnr)-1] = '\0';
- strcpy(tmp_type, strrchr(tmp_str2, ' ')+1);
- tmp_str2[strlen(tmp_str2)-strlen(tmp_type)-1] = '\0';
- tmp_line = strrchr(tmp_str2, ' ')+1;
-
- message->line = atol(tmp_line);
-
- switch(msg->msg_type)
- {
- case MODA_MSG_NOTE: { message->type = AmIDE_MSG_NOTE; } break;
- case MODA_MSG_ERROR: { message->type = AmIDE_MSG_ERROR; } break;
- case MODA_MSG_WARNING: { message->type = AmIDE_MSG_WARNING; } break;
- }
- }
- break;
-
- //
- // If this is the text of a warning message
- //
- case MODA_MSG_WARNING_TXT:
- {
- LONG tmp;
- STRPTR tmp_str = Data->msg_text;
-
- message->text = sav_AllocVec(256*sizeof(char), MEMF_ANY);
- if(!message->text) return(0);
-
- // Now we copy everything in front of the ANSI characters
- tmp = (strlen(tmp_str)-strlen(strstr(tmp_str, "\033[33;7m")));
- strncpy(message->text, tmp_str, tmp);
-
- // Now insert some ESC sequences for MUI
- strcat(message->text, AmIDE_MSG_STYLE_TXT_START);
-
- // Now we copy the text in between of the ANSI chars.
- tmp_str += (tmp+7);
-
- tmp = (strlen(tmp_str)-strlen(strstr(tmp_str, "\033[0m")));
- strncat(message->text, tmp_str, tmp);
-
- // and again we append some ESC sequeneces
- strcat(message->text, AmIDE_MSG_STYLE_TXT_STOP);
-
- // and don`t forget the rest of the text
- tmp_str += (tmp+4);
- strcat(message->text, tmp_str);
-
- message->type = AmIDE_MSG_WARNING;
- }
- break;
-
- //
- // For Compiler-Phase1 messages of SAS/C
- //
- case MODA_MSG_COMPILER_P1:
- {
- message->status = "compiling phase1...";
-
- message->text = sav_AllocVec((strlen(AmIDE_MSG_STYLE_PHASES "Compiler Phase 1:")+1)*sizeof(char), MEMF_ANY);
- strcpy(message->text, AmIDE_MSG_STYLE_PHASES "Compiler Phase 1:");
-
- message->type = AmIDE_MSG_DEFAULT;
- }
- break;
-
- //
- // For Compiler-Phase2 messages of SAS/C
- //
- case MODA_MSG_COMPILER_P2:
- {
- message->status = "compiling phase2...";
-
- message->text = sav_AllocVec((strlen(AmIDE_MSG_STYLE_PHASES "Compiler Phase 2:")+1)*sizeof(char), MEMF_ANY);
- strcpy(message->text, AmIDE_MSG_STYLE_PHASES "Compiler Phase 2:");
-
- message->type = AmIDE_MSG_DEFAULT;
- }
- break;
-
- //
- // For Global-Optimizer messages
- //
- case MODA_MSG_OPTIMIZER:
- {
- message->status = "global optimizing...";
-
- message->text = sav_AllocVec((strlen(AmIDE_MSG_STYLE_PHASES "Global Optimizer:")+1)*sizeof(char), MEMF_ANY);
- strcpy(message->text, AmIDE_MSG_STYLE_PHASES "Global Optimizer:");
-
- message->type = AmIDE_MSG_DEFAULT;
- }
- break;
-
- //
- // For default messages we just send the whole string
- //
- case MODA_MSG_DEFAULT:
- {
- message->text = sav_AllocVec((strlen(Data->msg_text)+1)*sizeof(char), MEMF_ANY);
- strcpy(message->text, Data->msg_text);
-
- message->type = AmIDE_MSG_DEFAULT;
- }
- break;
- }
-
- // main method call to insert the message into AmIDE
- DoMethod(Data->parent_obj, AmIDEM_msginsert, message, TAG_DONE);
-
- // Now lets free the allocated stuff
- if(message->text) sav_FreeVec(message->text);
- if(message) sav_FreeVec(message);
-
- return(0);
- }
-
-
- /*
- ** MODULE_Dispatcher
- **
- ** This is the dispatcher for the module library
- **
- ** parameters
- ** ~~~~~~~~~~
- ** Class * (a0): the class of the object
- ** Object * (a2): the object
- ** Msg (a1): the message (METHOD_IDs)
- **
- ** return-values:
- ** ~~~~~~~~~~~~~~
- ** ULONG: the new object
- */
-
- SAVEDS ASM ULONG MODULE_Dispatcher(REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) Msg msg)
- {
- #ifdef DEBUG
- DEBUG_MAKRO
- #endif
-
- switch (msg->MethodID)
- {
- // public Methods (defined in the API)
- case OM_NEW : return(MODULE_New (cl, obj, (APTR)msg));
- case OM_GET : return(MODULE_Get (cl, obj, (APTR)msg));
- case OM_SET : return(MODULE_Set (cl, obj, (APTR)msg));
- case AmIDEM_API_compile : return(MODULE_Compile (cl, obj, (APTR)msg));
- case AmIDEM_API_link : return(MODULE_Link (cl, obj, (APTR)msg));
-
- // Not implemented yet:
- // case AmIDEM_API_break : return(MODULE_break (cl, obj, (APTR)msg));
- // case AmIDEM_API_prefs : return(MODULE_prefs (cl, obj, (APTR)msg));
-
- // private Methods (only for internal module use)
- case MODM_Logfile_Read : return(MODULE_Log_Read (cl, obj, (APTR)msg));
- case MODM_Msg_Parse : return(MODULE_Msg_Parse (cl, obj, (APTR)msg));
- case MODM_Msg_Insert : return(MODULE_Msg_Insert (cl, obj, (APTR)msg));
- }
-
- return (DoSuperMethodA(cl, obj, msg));
- }
-