view level1/cmds/ngu.asm @ 2758:e4a0f58a5f9b

Found that people who do not have the envirornment variable NITROS9DIR set before building the project get a error missing file "/rules.mak". Found this is caused do to the fact that the code to set this envirornment variable is in the rules.mak which can't get loaded. To fix this the code needed to set the envirornment variable that is in the rules.mak is now in the makefile(s) right before the include for the rules.mak file. This should fix the problem for those who do not have the NITROS9DIR envirornment variable preset.
author drencor-xeen
date Mon, 14 Jan 2013 14:37:46 -0600
parents 20841f236e32
children
line wrap: on
line source

********************************************************************
* NGU - The "Next Great Utility"
*
* $Id$
*
* NGU is a template for writing utilities under OS-9/6809. It has
* robust option handling and is littered with comments to help you
* write your own utilities.
*
* NGU uses a two-pass method for parsing the command line.  On the
* first pass, dash options are processed and internal flags are set
* accordingly.  As the options are processed, they are cleared to
* spaces so that they won't be present on the second pass.
*
*  e.g.
*       1st pass:   ngu -x foo1 -y foo2 -t=bar1 -ab
*       2nd pass:   ngu    foo1    foo2
*
* For the second pass, NGU parses the remaining arguments, which don't
* begin with -. Presumably these are filenames or other names that are to be
* processed.
*
* Features:
*    - Written for 6809 and 6309 processors in fast, compact
*      assembly language.
*
*    - Both options and files can be specified anywhere
*      on the command line
*          (i.e ngu -a test1 -b test2 -c=foo)
*
*    - Multiple options can be combined behind one dash:
*          (i.e ngu -ab test1 -c=foo test2 test3)
*
*    - Several useful assembly routines are provided for
*      copying strings and determining string length.
*
* Limitations:
*    - Only single character option names can be processed.
*      Multi-character option names (i.e. -delete) aren't supported.
*
*    - The current file counter is one byte, counting a maximum
*      of 255 files.
*
* Edt/Rev  YYYY/MM/DD  Modified by
* Comment
* ------------------------------------------------------------------
*   1      2003/01/11  Boisy G. Pitre
* Put your development info here.

         nam   NGU
         ttl   The "Next Great Utility"

         ifp1
         use   defsfile
         endc

* Here are some tweakable options
DOHELP   set   1	1 = include help info
STACKSZ  set   128	estimated stack size in bytes
PARMSZ   set   256	estimated parameter size in bytes
COPTSIZ  set   64	max size of C option's parameter

* Module header definitions
tylg     set   Prgrm+Objct   
atrv     set   ReEnt+rev
rev      set   $00
edition  set   1

         mod   eom,name,tylg,atrv,start,size

* Your utility's static storage vars go here
         org   0
* These vars are used by the base template and shouldn't be removed
parmptr  rmb   2	pointer to our command line params
bufptr   rmb   2	pointer to user expandable buffer
bufsiz   rmb   2	size of user expandable buffer
filecnt  rmb   1
* These vars are used for this example, it will probably change for you
gota     rmb   1
gotb     rmb   1
coptflg  rmb   1	1 = this option has been processed once already
cleartop equ   .	everything up to here gets cleared at start
copt     rmb   COPTSIZ	buffer for what follows after -c=
* Next is a user adjustable buffer with # modifier on command line.
* Some utilities won't need this flexibility, some will.
* Currently set up to be larger for Level 2 than Level 1
* Note: this buffer must come just before the stack
         IFGT  Level-1
bigbuff  rmb   8*1024		8K default buffer for Level 2
         ELSE
bigbuff  rmb   512		512 byte default buffer for Level 1
         ENDC
* Finally the stack for any PSHS/PULS/BSR/LBSRs that we might do
         rmb   STACKSZ+PARMSZ
size     equ   .

* The utility name and edition goes here
name     fcs   /NGU/
         fcb   edition

* Place constant strings here
         IFNE  DOHELP
HlpMsg   fcb   C$LF
         fcc   /Use: NGU [<opts>] <path> [<path>] [<opts>]/
         fcb   C$LF
         fcc   /   -a    option 1/
         fcb   C$LF
         fcc   /   -b    option 2/
         fcb   C$LF
         fcc   /   -c=f  option 3/
         fcb   C$LF
CR       fcb   C$CR
HlpMsgL  equ   *-HlpMsg
         ENDC
UnkOpt   fcc   /unknown option: /
UnkOptL  equ   *-UnkOpt

* Here's how registers are set when this process is forked:
*
*   +-----------------+  <--  Y          (highest address)
*   !   Parameter     !
*   !     Area        !
*   +-----------------+  <-- X, SP
*   !   Data Area     !
*   +-----------------+
*   !   Direct Page   !
*   +-----------------+  <-- U, DP       (lowest address)
*
*   D = parameter area size
*  PC = module entry point abs. address
*  CC = F=0, I=0, others undefined

* The start of the program is here.
* Before any command line processing is done, we clear out
* our static memory from U to cleartop, then determine the
* size of our data area (minus the stack).
start    pshs  u,x		save registers for later
         leax  <cleartop,u	point to end of area to zero out
         IFNE  H6309
         subr  u,x		subtract U from X
         tfr   x,w		and put X in W
         clr   ,-s		put a zero on the stack
         tfm   s,u+		and use TFM to clear starting at U
         leas  1,s		clean up the stack
         ELSE
         pshs   x		save end pointer on stack
clrnxt   clr   ,u+		clear out
         cmpu  ,s		done?
         bne   clrnxt		branch if not
         leas  2,s		else clear stack
         ENDC
         puls  x,u		and restore our earlier saved registers
         leay  bigbuff,u	point Y to copy buffer offset in U
         stx   <parmptr		save parameter pointer
         sty   <bufptr		save pointer to buffer
         tfr   s,d		place top of stack in D
         IFNE  H6309
         subr  y,d
         ELSE
         pshs  y		save Y on stack
         subd  ,s++		get size of space between copybuf and X
         ENDC
         subd  #STACKSZ+PARMSZ	subtract out our stack/param size
         std   <bufsiz		size of our buffer

* At this point we have determined our buffer space and saved pointers
* for later use.  Now we will parse the command line for options that
* begin with a dash.
* Note that X will NOT point to a space, but to either a CR (if no
* parameters were passed) or the first non-space character of the
* parameter.
* Here we merely grab the byte at X into A and test for end of line,
* exiting if so.  Utilities that don't require arguments should
* comment out the following three lines.
         lda   ,x         	get first char
         cmpa  #C$CR		CR?
         lbeq  ShowHelp		if so, no parameters... show help and exit
GetChar  lda   ,x+		get next character on cmd line
         cmpa  #C$CR		CR?
         lbeq  DoNGU		if so, do whatever this utility does
         cmpa  #'-		is it an option?
         beq   GetDash		if so, process it
         inc   <filecnt         else must be a non-option argument (file)
         lbsr  SkipNSpc         move past the argument
ChkDash  lbsr  SkipSpcs         and any following spaces
         bra   GetChar          start processing again
GetDash  clr   -1,x		and wipe out the dash from the cmd line
GetDash2 ldd   ,x+		load option char and char following
         ora   #$20		make lowercase
IsItA    cmpa  #'a		is it this option?
         bne   IsItB		branch if not
         inc   <gota
         bra  FixCmdLn
IsItB    cmpa  #'b		is it this option?
         bne   IsItC		branch if not
         inc   <gotb
         bra   FixCmdLn
IsItC    cmpa  #'c		is it this option?
         bne   BadOpt		branch if not
         tst   <coptflg		was this option already specified?
         bne   BadOpt		show help if so
         cmpb  #'=		2nd char =?
         lbne  ShowHelp		show help if not
         inc   <coptflg		else tag this option as parsed
*         ldb   #C$SPAC		get space
         clr   -$01,x		write over c
         clr   ,x+		and = sign, inc X to dest dir
* check for valid char after -c=
         lda   ,x
         lbeq  ShowHelp         
         cmpa  #C$SPAC
         lbeq  ShowHelp         
         cmpa  #C$CR
         lbeq  ShowHelp         
         leay  <copt,u		point Y to parameber buffer
         tfr   y,d		transfer Y to D
         addd  #COPTSIZ
         pshs  b,a		save updated ptr value
L0339    lda   ,x		get byte at X
         clr   ,x+		store nul byte at X and inc
         sta   ,y+		save loaded byte at Y and inc
         cmpy  ,s		are we at end?
         beq   L035D		branch if so (buffer too small)
         tsta			else is char in A a nul byte?
         beq   L0350		branch if so
         cmpa  #C$SPAC		a space?
         beq   L0350		branch if so
         cmpa  #C$CR		cr?
         bne   L0339		get next byte if not
L0350    leax  -1,x
         sta   ,x		restore previous A
         leas  $02,s		kill stack
         lbra  ChkDash
L035D    leas  $02,s
         ldb   #$BF		else buffer size too small
         orcc  #Carry
         lbra  Exit
FixCmdLn clr   -$01,x		and wipe out option character
         cmpb  #'0
         lblt  ChkDash		start dash option processing again
         lbra  GetDash		possibly another option following?

* We branch here if we encounter an unknown option character
* A = bad option character
BadOpt   leax  UnkOpt,pcr
         ldy   #UnkOptL
         ldb   #C$CR
         pshs  d		save bad option and CR on stack
         lda   #$02		stderr
         os9   I$Write
         leax  ,s		point X at option char on stack
         os9   I$WritLn		print option and CR
         puls  d		clean up stack
         lbra  ShowHelp


* At this point options are processed.
* We load X with our parameter pointer and go down the command line
* looking at each file to process (options have been wiped out with
* spaces)
*
* Note, the following two instructions may not be needed, depending on
* if your utility requires a non-option on the command line.
DoNGU    tst   <filecnt		we should have at least one file on cmdline
         lbeq  ShowHelp		if not, exit with error
         ldx   <parmptr		get our parameter pointer
DoLoop   lbsr  SkipSpcs		skip any leading spaces
         cmpa  #C$CR		end of parameters?
         beq   ExitOk		if so, end the utility
         pshs  x		save pointer to arg
         bsr   ProcFile		process file at X
         puls  x		get arg pointer
         lbsr  SkipNSpc         skip the argument we just processed
         bra   DoLoop

* This routine processes one file at a time.
* Entry: X = ptr to argument on the command line.
* On exit, X can point to the argument or past it.
* Note that there are NO leading spaces.
* They have been skipped by the caller.
* The following code just echos the command line argument, followed
* by a carriage return.
ProcFile 
         pshs  x		save ptr
         lda   #$01		standard output
         bsr   StrLen		get length of argument in Y
         puls  x		recover ptr
         os9   I$Write		write name out
         leax  CR,pcr		point to carriage return
         os9   I$WritLn		write it out
         rts

ShowHelp equ   *
         IFNE  DOHELP
         leax  >HlpMsg,pcr	point to help message
         ldy   #HlpMsgL		get length
         lda   #$02		std error
         os9   I$WritLn 	write it
         ENDC
ExitOk   clrb  			clear carry
Exit     os9   F$Exit   	and exit

* This routine counts the number of non-whitespace characters
* starting at X
*
* Entry:
*   X = ptr to string (space, nul byte or CR terminated)
* Exit:
*   Y = length of string
*   X = ptr to byte after string
StrLen   pshs  a
         ldy   #$0000
StrLenLp lda   ,x+
         beq   StrLenEx
         cmpa  #C$SPAC
         beq   StrLenEx
         cmpa  #C$CR
         beq   StrLenEx
         leay  1,y
         bra   StrLenLp
StrLenEx puls  a,pc

* This routine copies a string of text from X to Y until
* a whitespace character or CR is encountered
*
* Entry:
*   X = ptr to src string
*   Y = ptr to dest string
* Exit:
*   D = number of bytes copied
*   X = ptr to byte after original string
*   Y = ptr to byte after copied string
StrCpy   pshs  u
         ldu   #$0000
CopyFnLp lda   ,x+
         beq   CopyFnEx
         cmpa  #C$SPAC
         beq   CopyFnEx
         cmpa  #C$CR
         beq   CopyFnEx
         sta   ,y+
         leau  1,u
         bra   CopyFnLp
CopyFnEx tfr   u,d
         puls  u,pc

* This routine skip over spaces and nul bytes
*
* Entry:
*   X = ptr to data to parse
* Exit:
*   X = ptr to first non-whitespace char
*   A = non-whitespace char
SkipSpcs lda   ,x+
         beq   SkipSpcs
         cmpa  #C$SPAC
         beq   SkipSpcs
         leax  -1,x
         rts

* This routine skips over everything but spaces, nul bytes and CRs
*
* Entry:
*   X = ptr to data to parse
* Exit:
*   X = ptr to first whitespace char
*   A = whitespace char
SkipNSpc lda   ,x+
         beq   EatOut
         cmpa  #C$SPAC
         beq   EatOut
         cmpa  #C$CR
         bne   SkipNSpc
EatOut   leax  -1,x
         rts

         emod
eom      equ   *
         end