[cc65] command line parser hack

Date view Thread view Subject view

From: groepaz (groepaz_at_gmx.net)
Date: 2001-08-13 22:36:55


ok ppl.... the first thing i come up with is a little hack that makes
it possible to pass arguments to a program very simelar to what you do
on a command line of some shell....

like:

RUN:arg1 arg2 arg3

this hack will read what you have written after the RUN command and
setup the respective variables (argc/argv) just as you would expect in
a standard C program.

oh yeah... this was developed on a c64, but should be possible to
convert to any other cbm-machine with minimum effort (will probably
work already on a vic-20)

appended below is a little test-program that just prints the arguments
that you gave them.... it also has an option to generate BASIC
error-messages (i included a modified version of exit() aswell that
does the job)

eg

RUN:!e 1

will print the error with the internal number 1

?too many files  error
ready.

ahyeah... there are still some minor quirks to circumvent in this
implementation, if there is any interest i might fix that ;)

UZ: try this... seems to be the compiler bugs somewhere, some errors
are just tooooo weird to make any sence (and i cant really track them
down to a mistake in my code ;D) ... that is for SOME combinations of
arguments, the test-prog prints out total junk, there doesnt seem to
be some kind of system behind it though ... errrr ;D (too bad, i cant
find one on a quick test, i'll post a combination that fails if i
stumble about one once again)

;=)

....and now i am gone writing test programs for the file i/o stuff ;=)

UZ: is there a possibility of creating some directory for me on your
ftp-server where i could share my file-i/o stuff ? i guess it wouldnt
be too practical to send you emails every day when i make minor
changes...... but i'd really like to get some feedback/bug reports
this early, since it has been a while since i last looked at those
sources and i probably dont remember everything that still has to be
fixed. (and feedback will also help to write some documentation on the
non-standard functions)

-- 
Best regards,
 groepaz                            mailto:groepaz_at_gmx.net

-file"hello.c"--------------------------------------------------------------

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

/* include command line processing */
#include "cmdline.c"

int main(int argc,char **argv) {
int i;

    printf("commandline test (RUN:[ARGS])\n");

    if(argv[1][0]=='!') {
        switch(argv[1][1]){
            /* create an error with specified code */
            case 'e':
                    printf("error no.: %d\n",atoi(argv[2]));
                    return(atoi(argv[2]));
                break;
        }
    } else {

        /* number of arguments (argv[0] is always the full path+name of the executeable) */
        printf(" argc    : %d\n",argc);
        /* arguments */
        for(i=0;i<(argc);i++){
            printf(" argv[%d] : %s\n",i,argv[i]);
        }

    }

    /* return OK */
    return(0);

}

-file"cmdline.h"------------------------------------------------------------

#ifndef _CMDLINE_H_
#define _CMDLINE_H_

#define CMDLINEMAXLEN 50

unsigned char *__cmdlinegetexename(void);
unsigned char *__cmdlinegetcmdline(void);
unsigned char __cmdlinetrimcmdline(unsigned char *ptr);
unsigned char **__cmdlinemakearray(unsigned char numargs,unsigned char *cmdline,unsigned char *nameptr);
int __cmdlinemain(int argc,char **argv);
void __cmdlineexit(unsigned char err);

#include <string.h>

#endif /* _CMDLINE_H_ */

-file"cmdline.c"------------------------------------------------------------

#include "cmdline.h"

/*
        get program filename
*/

unsigned char *__cmdlinegetexename(void) {
unsigned char i,ii;
unsigned char *ptr,*nameptr;

    /* get basic memory top (filename has been buffered here) */
    ptr=(unsigned char*) (*((unsigned char*)0x37))+((*((unsigned char*)0x38))<<8);
    /* length of filename */
    ii=(*((unsigned char*)0xb7));
    /* alloc space for a save copy of the filename string */
    nameptr=(unsigned char*)malloc((ii+1)*sizeof(unsigned char));
    ptr-=ii;
    for(i=0;i<ii;i++){
            nameptr[i]=ptr[i];
    }
    nameptr[i]=0;

    return(nameptr);

}

/*
        get pointer to command line arguments
*/

unsigned char *__cmdlinegetcmdline(void) {
unsigned char *ptr,*cmdline;
unsigned char i,len;

    /* basic input buffer */
    ptr=(unsigned char*)0x0200;
    /* read until ':' */
    i=0;while((ptr[i]!=0)&(i<CMDLINEMAXLEN)&(ptr[i]!=':')) i++;
    /* if ':' found, get arguments-string from command line */
    if(ptr[i]==':') {
        i++;/* one more ;) */
        len=strlen(&ptr[i]);
        cmdline=(unsigned char*)malloc((len+1)*sizeof(unsigned char));
        strcpy(cmdline,&ptr[i]);
        return(cmdline);
    /* return NULL if no arguments found */
    } else {
        return(NULL);
    }

}

/*
    remove spaces from command line & terminate args with zero
 */

unsigned char __cmdlinetrimcmdline(unsigned char *ptr) {
unsigned char src,dest,numargs,len;

    if(ptr==NULL) return(0);

    len=strlen(ptr);
    numargs=0;src=0;dest=0;
    while(src<len){
        /* skip spaces */
        while((ptr[src]!=0)&(src<CMDLINEMAXLEN)&(ptr[src]==' ')){
             src++;
        }
        /* arg */
        while((ptr[src]!=0)&(src<CMDLINEMAXLEN)&(ptr[src]!=' ')){
            ptr[dest]=ptr[src];
            src++;dest++;
        }
        ptr[dest]=0;dest++;src++;
        numargs++;
    }

    return(numargs);
}

/*
    create pointer-structure for array of arguments
 */

unsigned char **__cmdlinemakearray(unsigned char numargs,unsigned char *cmdline,unsigned char *nameptr){
unsigned char **argv;
unsigned char i;

    argv=(unsigned char**)malloc(sizeof(unsigned char*)*(numargs));
    argv[0]=nameptr;
    for(i=1;(i<(numargs));i++,cmdline++){
        argv[i]=cmdline;
        while(*cmdline!=0) cmdline++;
    }
    return(argv);
}

void __cmdlineexit(unsigned char err){
    /* restore the environment */
    asm("\tsei");
    asm("\tlda #$37");
    asm("\tsta $01");
    /* direct mode */
    asm("\tlda #$ff");
    asm("\tsta $3a");
    /* clrch */
    asm("\tjsr $ffcc");
    /* stdin=keyboard */
    asm("\tlda #$00");
    asm("\tsta $13");
    /* init basic */
    asm("\tjsr $a67a");
    asm("\tcli");
    /* get error code */
    asm("\tjsr popa");
    /* reset stack */
    asm("\tldx #$fb");
    asm("\ttxs");
    /* make error code */
    asm("\ttax");
    asm("\tbne @sk");
    asm("\tldx #$80");
    asm("@sk:");
    /* jump to basic warmstart */
    asm("\tcli");
    asm("\tjmp $a437");
}

void main (void) {
unsigned char numargs;
unsigned char *nameptr,*cmdline,**argv;
int err;

    /* get application filename string, alloc+copy to new string if needed */
    nameptr=__cmdlinegetexename();
    /* get command line string, alloc+copy to new string if needed */
    cmdline=__cmdlinegetcmdline();
    /* trim command line string and count args */
    numargs=__cmdlinetrimcmdline(cmdline)+1; /* one arg is filename */
    /* alloc and setup array structure */
    argv=__cmdlinemakearray(numargs,cmdline,nameptr);
    /* call the user's int main(int argc,char **argv) */
    err=__cmdlinemain(numargs,argv);
    /* clean up the environment variables */
    free(argv);free(cmdline);free(nameptr);
    /* exit to environment */
    __cmdlineexit((unsigned char)err);

    /* we will never return from here */

}

#define main(__argc,__argv) __cmdlinemain(__argc,__argv)
#define exit(__err) __cmdlineexit(__err)


----------------------------------------------------------------------
To unsubscribe from the list send mail to majordomo_at_musoftware.de with
the string "unsubscribe cc65" in the body(!) of the mail.


Date view Thread view Subject view

This archive was generated by hypermail 2.1.3 : 2001-12-14 22:05:41 CET