Subversion Repositories SvarDOS

Compare Revisions

Ignore whitespace Rev 957 → Rev 956

/svarcom/trunk/cmd/call.c
File deleted
/svarcom/trunk/cmd.c
22,15 → 22,10
* DEALINGS IN THE SOFTWARE.
*/
 
/* entry point for internal commands, it matches internal commands and
* executes them.
*
* returns one of the following values:
* CMD_OK command executed successfully
* CMD_FAIL command ended in error
* CMD_CHANGED command-line has been modified (used by IF)
* CMD_CHANGED_BY_CALL command-line has been modified by CALL
* CMD_NOTFOUND command unrecognized
/* entry point for internal commands
* matches internal commands and executes them
* returns -1 or exit code if processed
* returns -2 if command unrecognized
*/
 
#include <i86.h>
70,7 → 65,6
 
#include "cmd/_notimpl.c"
#include "cmd/break.c"
#include "cmd/call.c"
#include "cmd/cd.c"
#include "cmd/chcp.c"
#include "cmd/cls.c"
105,7 → 99,6
 
const struct CMD_ID INTERNAL_CMDS[] = {
{"BREAK", cmd_break},
{"CALL", cmd_call},
{"CD", cmd_cd},
{"CHCP", cmd_chcp},
{"CHDIR", cmd_cd},
/svarcom/trunk/cmd.h
29,11 → 29,10
 
/* what cmd_process may return */
enum cmd_result {
CMD_OK, /* command executed and succeeded */
CMD_FAIL, /* command executed and failed */
CMD_NOTFOUND, /* no such command (not an internal command) */
CMD_CHANGED, /* command-line transformed, please reparse it */
CMD_CHANGED_BY_CALL /* command-line transformed by CALL */
CMD_OK, /* command executed and succeeded */
CMD_FAIL, /* command executed and failed */
CMD_NOTFOUND, /* no such command (not an internal command) */
CMD_CHANGED /* command-line transformed, please reparse it */
};
 
/* process internal commands */
/svarcom/trunk/command.c
315,11 → 315,7
}
 
 
/* a few internal flags */
#define DELETE_STDIN_FILE 1
#define CALL_FLAG 2
 
static void run_as_external(char *buff, const char *cmdline, unsigned short envseg, struct rmod_props far *rmod, struct redir_data *redir, unsigned char flags) {
static void run_as_external(char *buff, const char *cmdline, unsigned short envseg, struct rmod_props far *rmod, struct redir_data *redir, unsigned char delete_stdin_file) {
char *cmdfile = buff + 512;
const char far *pathptr;
int lookup;
434,39 → 430,31
 
/* special handling of batch files */
if ((ext != NULL) && (imatch(ext, "bat"))) {
struct batctx far *newbat;
 
/* remember the echo flag (in case bat file disables echo, only when starting first bat) */
/* free the bat-context linked list, if present, and replace it with a new entry */
while (rmod->bat != NULL) {
struct batctx far *victim = rmod->bat;
rmod->bat = rmod->bat->parent;
rmod_ffree(victim);
}
rmod->bat = rmod_fmalloc(sizeof(struct batctx), rmod->rmodseg, "SVBATCTX");
if (rmod->bat == NULL) {
rmod->flags &= ~FLAG_ECHO_BEFORE_BAT;
if (rmod->flags & FLAG_ECHOFLAG) rmod->flags |= FLAG_ECHO_BEFORE_BAT;
}
 
/* if bat is not called via a CALL, then free the bat-context linked list */
if ((flags & CALL_FLAG) == 0) {
while (rmod->bat != NULL) {
struct batctx far *victim = rmod->bat;
rmod->bat = rmod->bat->parent;
rmod_ffree(victim);
}
}
/* allocate a new bat context */
newbat = rmod_fcalloc(sizeof(struct batctx), rmod->rmodseg, "SVBATCTX");
if (newbat == NULL) {
nls_outputnl_doserr(8); /* insufficient memory */
outputnl("INTERNAL ERR: OUT OF MEMORY");
return;
}
_fmemset(rmod->bat, 0, sizeof(struct batctx));
 
/* fill the newly allocated batctx structure */
_fstrcpy(newbat->fname, cmdfile); /* truename of the BAT file */
/* copy truename of the bat file to rmod buff */
_fstrcpy(rmod->bat->fname, cmdfile);
 
/* explode args of the bat file and store them in rmod buff */
cmd_explode(buff, cmdline, NULL);
_fmemcpy(newbat->argv, buff, sizeof(newbat->argv));
_fmemcpy(rmod->bat->argv, buff, sizeof(rmod->bat->argv));
 
/* push the new bat to the top of rmod's linked list */
newbat->parent = rmod->bat;
rmod->bat = newbat;
 
/* reset the 'next line to execute' counter */
rmod->bat->nextline = 0;
/* remember the echo flag (in case bat file disables echo) */
rmod->flags &= ~FLAG_ECHO_BEFORE_BAT;
if (rmod->flags & FLAG_ECHOFLAG) rmod->flags |= FLAG_ECHO_BEFORE_BAT;
return;
}
 
478,7 → 466,7
char far *farptr = MK_FP(rmod->rmodseg, RMOD_OFFSET_STDINFILE);
char far *delstdin = MK_FP(rmod->rmodseg, RMOD_OFFSET_STDIN_DEL);
_fstrcpy(farptr, redir->stdinfile);
if (flags & DELETE_STDIN_FILE) {
if (delete_stdin_file) {
*delstdin = redir->stdinfile[0];
} else {
*delstdin = 0;
756,7 → 744,6
}
 
 
 
int main(void) {
static struct config cfg;
static unsigned short far *rmod_envseg;
767,7 → 754,7
static struct redir_data redirprops;
static enum cmd_result cmdres;
static unsigned short i; /* general-purpose variable for short-lived things */
static unsigned char flags;
static unsigned char delete_stdin_file;
 
rmod = rmod_find(BUFFER_len);
if (rmod == NULL) {
841,10 → 828,10
if (rmod->awaitingcmd[0] != 0) {
_fstrcpy(cmdline, rmod->awaitingcmd);
rmod->awaitingcmd[0] = 0;
flags |= DELETE_STDIN_FILE;
delete_stdin_file = 1;
goto EXEC_CMDLINE;
} else {
flags &= ~DELETE_STDIN_FILE;
delete_stdin_file = 0;
}
 
/* skip user input if I have a command to exec (/C or /K) */
860,7 → 847,7
struct batctx far *victim = rmod->bat;
rmod->bat = rmod->bat->parent;
rmod_ffree(victim);
/* end of batch? then restore echo flag as it was before running the (first) bat file */
/* end of batch? then restore echo flag as it was before running the bat file */
if (rmod->bat == NULL) {
rmod->flags &= ~FLAG_ECHOFLAG;
if (rmod->flags & FLAG_ECHO_BEFORE_BAT) rmod->flags |= FLAG_ECHOFLAG;
911,22 → 898,16
}
 
/* try matching (and executing) an internal command */
cmdres = cmd_process(rmod, *rmod_envseg, cmdline, BUFFER, sizeof(BUFFER), &redirprops, flags & DELETE_STDIN_FILE);
cmdres = cmd_process(rmod, *rmod_envseg, cmdline, BUFFER, sizeof(BUFFER), &redirprops, delete_stdin_file);
if ((cmdres == CMD_OK) || (cmdres == CMD_FAIL)) {
/* internal command executed */
continue;
} else if (cmdres == CMD_CHANGED) { /* cmdline changed, needs to be reprocessed */
goto EXEC_CMDLINE;
} else if (cmdres == CMD_CHANGED_BY_CALL) { /* cmdline changed *specifically* by CALL */
/* the distinction is important since it changes the way batch files are processed */
flags |= CALL_FLAG;
goto EXEC_CMDLINE;
} else if (cmdres == CMD_NOTFOUND) {
/* this was not an internal command, try matching an external command */
run_as_external(BUFFER, cmdline, *rmod_envseg, rmod, &redirprops, flags);
flags &= ~CALL_FLAG; /* reset callflag to make sure it is processed only once */
 
/* is it a newly launched BAT file? */
run_as_external(BUFFER, cmdline, *rmod_envseg, rmod, &redirprops, delete_stdin_file);
/* perhaps this is a newly launched BAT file */
if ((rmod->bat != NULL) && (rmod->bat->nextline == 0)) goto SKIP_NEWLINE;
/* run_as_external() does not return on success, if I am still alive then
* external command failed to execute */
/svarcom/trunk/history.txt
3,11 → 3,6
=== SvarCOM's history / changelog ===
 
 
=== ver 2022.1 (xx.xx.xxxx) ==================================================
 
- added CALL support for calling batch files from within batch files
 
 
=== ver 2022.0 (01.02.2022) ==================================================
 
- added "global executable links" support (new command: LN)
/svarcom/trunk/rmodinit.c
228,10 → 228,9
 
 
/* allocates bytes of far memory, flags it as belonging to rmod
* the new block can be optionally flagged as 'ident' (if not null) and zero
* out the newly allocated memory.
* the new block can be optionally flagged as 'ident' (if not null)
* returns a far ptr to the allocated block, or NULL on error */
void far *rmod_fcalloc(unsigned short bytes, unsigned short rmod_seg, char *ident) {
void far *rmod_fmalloc(unsigned short bytes, unsigned short rmod_seg, char *ident) {
unsigned short far *owner;
unsigned short newseg = 0;
 
290,14 → 289,11
}
}
 
/* zero out the memory before handing it out */
_fmemset(MK_FP(newseg, 0), 0, bytes);
 
return(MK_FP(newseg, 0));
}
 
 
/* free memory previously allocated by rmod_fcalloc() */
/* free memory previously allocated by rmod_ffmalloc() */
void rmod_ffree(void far *ptr) {
unsigned short ptrseg;
unsigned short myseg = 0;
/svarcom/trunk/rmodinit.h
68,13 → 68,8
struct rmod_props far *rmod_find(unsigned short rmodcore_len);
void rmod_updatecomspecptr(unsigned short rmod_seg, unsigned short env_seg);
 
/* allocates bytes of far memory, flags it as belonging to rmod
* the new block can be optionally flagged as 'ident' (if not null) and zero
* out the newly allocated memory.
* returns a far ptr to the allocated block, or NULL on error */
void far *rmod_fcalloc(unsigned short bytes, unsigned short rmod_seg, char *ident);
 
/* free memory previously allocated by rmod_fcalloc() */
/* allocate */
void far *rmod_fmalloc(unsigned short bytes, unsigned short rmod_seg, char *ident);
void rmod_ffree(void far *ptr);
 
#endif
/svarcom/trunk/todo.txt
8,7 → 8,7
=== HIGH PRIORITY ============================================================
 
int 24h handler (abort, retry, fail, ignore)
advanced batch constructs: FOR, GOTO
advanced batch constructs: CALL, FOR, GOTO
IF EXIST on an empty drive should not lead to the 'Abort, Retry, Fail' prompt