revert between 56095 -> 55830 in arch
[AROS.git] / arch / m68k-all / dos / bcpl_support.c
blobb69c0c2044015c96d5bbe930701265c8cf5bf21b
1 /*
2 Copyright © 2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: BCPL support
6 Lang: english
7 */
8 #define DEBUG 0
9 #include <aros/debug.h>
10 #include <aros/asmcall.h>
12 #include <dos/dosextens.h>
13 #include <dos/filehandler.h>
14 #include <dos/dostags.h>
16 #include <proto/dos.h>
17 #include <proto/exec.h>
19 #include "dos_intern.h"
20 #include "bcpl.h"
22 /* Externs */
23 extern void BCPL_dummy(void);
24 #define BCPL(id, name) extern void BCPL_##name(void);
25 #include "bcpl.inc"
26 #undef BCPL
28 #define BCPL_SlotCount (BCPL_GlobVec_PosSize>>2)
30 /* Default Global Vector */
31 #define BCPL(id, name) \
32 [(BCPL_GlobVec_NegSize + id)>>2] = (ULONG)BCPL_##name,
34 const ULONG BCPL_GlobVec[(BCPL_GlobVec_NegSize + BCPL_GlobVec_PosSize) >> 2] = {
35 #include "bcpl.inc"
37 #undef BCPL
39 #define BCPL_ENTRY(proc) (((APTR *)(proc)->pr_GlobVec)[1])
41 * Set up the process's initial global vector
43 ULONG BCPL_InstallSeg(BPTR seg, ULONG *globvec)
45 ULONG *segment;
46 ULONG *table;
48 if (seg == BNULL) {
49 D(bug("BCPL_InstallSeg: Empty segment\n"));
50 return DOSTRUE;
53 if (seg == (ULONG)-1) {
54 ULONG slots = globvec[0];
55 int i;
56 if (slots > (BCPL_GlobVec_PosSize>>2))
57 slots = (BCPL_GlobVec_PosSize>>2);
58 D(bug("BCPL_InstallSeg: Inserting %d Faux system entries.\n", slots));
60 /* Copy over the negative entries from the default global vector */
61 CopyMem(&BCPL_GlobVec[0], &globvec[-(BCPL_GlobVec_NegSize>>2)], BCPL_GlobVec_NegSize);
63 for (i = 2; i < slots; i++) {
64 ULONG gv = BCPL_GlobVec[(BCPL_GlobVec_NegSize>>2) + i];
65 if (gv == 0)
66 continue;
68 globvec[i] = gv;
71 D(bug("BCPL_InstallSeg: Inserting DOSBase global\n"));
72 globvec[GV_DOSBase >> 2] = (IPTR)OpenLibrary("dos.library",0);
74 return DOSTRUE;
77 if (seg == (ULONG)-2) {
78 return DOSTRUE;
81 while (seg) {
82 segment = BADDR(seg);
83 seg = (BPTR)segment[0]; /* next segment */
85 if ((segment[-1] < segment[1])) {
86 D(bug("BCPL_InstallSeg: segList @%p does not look like BCPL.\n", segment));
87 continue;
90 D(bug("BCPL_InstallSeg: SegList @%p\n", segment));
91 table = &segment[segment[1]];
93 D(bug("\tFill in for %p:\n", segment));
95 for (; table[-1] != 0; table = &table[-2]) {
96 D(bug("\t globvec[%d] = %p\n", table[-2], (APTR)&segment[1] + table[-1]));
97 globvec[table[-2]] = (ULONG)((APTR)&segment[1] + table[-1]);
101 return DOSTRUE;
105 /* Create the global vector for a process
107 BOOL BCPL_AllocGlobVec(struct Process *me)
109 APTR globvec;
110 int i;
111 ULONG *seglist = BADDR(me->pr_SegList);
113 globvec = AllocMem(sizeof(BCPL_GlobVec), MEMF_ANY | MEMF_CLEAR);
114 if (globvec == NULL)
115 return FALSE;
117 globvec += BCPL_GlobVec_NegSize;
118 ((ULONG *)globvec)[0] = BCPL_GlobVec_PosSize >> 2;
120 /* Install the segments into the Global Vector */
121 for (i = 0; i < seglist[0]; i++) {
122 BCPL_InstallSeg(seglist[i+1], globvec);
125 me->pr_GlobVec = globvec;
127 return TRUE;
130 void BCPL_FreeGlobVec(struct Process *me)
132 APTR globvec = me->pr_GlobVec;
133 struct DosLibrary *DOSBase;
135 DOSBase = *(APTR *)(globvec + GV_DOSBase);
136 D(bug("[BCPL_FreeGlobVec] Freed globvec %p\n", globvec));
138 globvec -= BCPL_GlobVec_NegSize;
139 FreeMem(globvec, sizeof(BCPL_GlobVec));
141 me->pr_GlobVec = DOSBase->dl_GV;
144 void BCPL_Fixup(struct Process *me)
146 BPTR *segment = BADDR(me->pr_SegList);
148 if (segment[2] == (BPTR)0x0000abcd) {
149 D(bug("[BCPL_Fixup] Fixing up overlay\n"));
151 /* overlayed executable, fun..
152 * 2 = id
153 * 3 = filehandle (BPTR)
154 * 4 = overlay table (APTR)
155 * 5 = hunk table (BPTR)
156 * 6 = global vector (APTR)
158 segment[6] = (ULONG)me->pr_GlobVec;
162 extern void BCPL_thunk(void);
164 /* Under AOS, BCPL handlers expect the OS to build
165 * their GlobalVector, and to receive a pointer to their
166 * startup packet in D1.
168 * Both filesystem handlers and CLI shells use this routine.
170 * The 'Shell' shell is C based, and does not go here.
172 * This wrapper is here to support that.
174 ULONG BCPL_RunHandler(void)
176 struct DosPacket *dp;
177 struct Process *me = (struct Process *)FindTask(NULL);
178 APTR oldReturnAddr;
179 ULONG ret;
181 WaitPort(&me->pr_MsgPort);
182 dp = (struct DosPacket *)(GetMsg(&me->pr_MsgPort)->mn_Node.ln_Name);
183 D(bug("[RunHandlerBCPL] Startup packet = %p\n", dp));
185 if (!BCPL_AllocGlobVec(me)) {
186 if (dp != NULL)
187 internal_ReplyPkt(dp, &me->pr_MsgPort, DOSFALSE, ERROR_NO_FREE_STORE);
188 return ERROR_NO_FREE_STORE;
191 D(bug("[RunHandlerBCPL] BCPL_ENTRY = %p\n", BCPL_ENTRY(me)));
193 oldReturnAddr = me->pr_ReturnAddr;
194 ret = AROS_UFC8(ULONG, BCPL_thunk,
195 AROS_UFCA(ULONG, MKBADDR(dp), D1),
196 AROS_UFCA(ULONG, 0, D2),
197 AROS_UFCA(ULONG, 0, D3),
198 AROS_UFCA(ULONG, 0, D4),
199 AROS_UFCA(APTR, me->pr_Task.tc_SPLower, A1),
200 AROS_UFCA(APTR, me->pr_GlobVec, A2),
201 AROS_UFCA(APTR, &me->pr_ReturnAddr, A3),
202 AROS_UFCA(LONG_FUNC, BCPL_ENTRY(me), A4));
203 me->pr_ReturnAddr = oldReturnAddr;
205 BCPL_FreeGlobVec(me);
207 return ret;
210 /* Create the necessary process wrappings for a BCPL
211 * segment. Only needed by Workbench's C:Run, C:NewCLI,
212 * C:NewShell, and a few other applications.
214 struct MsgPort *BCPL_CreateProcBCPL(struct DosLibrary *DOSBase, CONST_STRPTR name, BPTR *segarray, ULONG stacksize, LONG pri)
216 struct Process *proc, *me = (struct Process *)FindTask(NULL);
218 D(bug("[BCPL_CreateProcBCPL] Window=%p name=\"%s\", segArray=%p, stacksize=%u, pri=%d\n", me->pr_WindowPtr, name, segarray, stacksize, pri));
220 proc = CreateNewProcTags(
221 NP_Name, name,
222 NP_Entry, BCPL_RunHandler,
223 NP_Input, BNULL,
224 NP_Output, BNULL,
225 NP_Error, BNULL,
226 NP_CloseInput, FALSE,
227 NP_CloseOutput, FALSE,
228 NP_CloseError, FALSE,
229 NP_StackSize, stacksize,
230 NP_WindowPtr, me->pr_WindowPtr,
231 NP_CurrentDir, 0,
232 NP_Cli, TRUE,
233 NP_HomeDir, 0,
234 TAG_END);
236 /* Fix up the segarray before the first packet gets
237 * to it.
239 if (proc) {
240 BPTR *oldsegarray;
242 oldsegarray = BADDR(proc->pr_SegList);
243 if (oldsegarray[0] < segarray[0]) {
244 FreeVec(oldsegarray);
245 oldsegarray = AllocVec(sizeof(BPTR)*(segarray[0]+1), MEMF_PUBLIC | MEMF_CLEAR);
246 oldsegarray[0] = segarray[0];
247 oldsegarray[1] = (BPTR)-1;
248 oldsegarray[2] = (BPTR)-2;
250 CopyMem(&segarray[3], &oldsegarray[3], (oldsegarray[0]-2)*sizeof(BPTR));
254 return proc ? &proc->pr_MsgPort : NULL;
257 void bcpl_command_name(void)
259 struct Process *me = (struct Process *)FindTask(NULL);
260 struct CommandLineInterface *cli = BADDR(me->pr_CLI);
262 if (cli == NULL || cli->cli_Module == BNULL)
263 bug("%s: ", me->pr_Task.tc_Node.ln_Name);
264 else
265 bug("%b: ", cli->cli_CommandName);