File: mainargs.s

package info (click to toggle)
cc65 2.19-2
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 20,268 kB
  • sloc: ansic: 117,151; asm: 66,339; pascal: 4,248; makefile: 1,009; perl: 607
file content (156 lines) | stat: -rw-r--r-- 4,676 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
; mainargs.s
;
; 2003-03-07, Ullrich von Bassewitz,
;   based on code from Stefan A. Haubenthal, <polluks@web.de>
; 2005-02-26, Ullrich von Bassewitz
; 2014-09-10, Greg King
;
; Scan a group of arguments that are in BASIC's input-buffer.
; Build an array that points to the beginning of each argument.
; Send, to main(), that array and the count of the arguments.
;
; Command-lines look like these lines:
;
; run
; run : rem
; run:rem arg1 " arg 2 is quoted "  arg3 "" arg5
;
; "run" and "rem" are entokenned; the args. are not.  Leading and trailing
; spaces outside of quotes are ignored.
;
; TO-DO:
; - The "file-name" might be a path-name; don't copy the directory-components.
; - Add a control-character quoting mechanism.

        .constructor    initmainargs, 24
        .import         __argc, __argv
        .import         sys_bank, restore_bank
        .import         sysp0:zp, ptr1:zp

        .include        "cbm510.inc"
        .macpack        generic


MAXARGS  = 10                   ; Maximum number of arguments allowed
REM      = $8f                  ; BASIC token-code
NAME_LEN = 16                   ; Maximum length of command-name

; Get possible command-line arguments. Goes into the special ONCE segment,
; which may be reused after the startup code is run.
;
.segment        "ONCE"

initmainargs:

; Assume that the program was loaded, a moment ago, by the traditional LOAD
; statement.  Save the "most-recent filename" as argument #0.
; Because the buffer, that we're copying into, was zeroed out,
; we don't need to add a NUL character.
;
        jsr     sys_bank
        ldy     #FNAM
        lda     (sysp0),y       ; Get file-name pointer from system bank
        sta     ptr1
        iny
        lda     (sysp0),y
        sta     ptr1+1
        iny                     ; FNAM_BANK
        lda     (sysp0),y
        tax
        ldy     #FNAM_LEN
        lda     (sysp0),y
        tay
        lda     #0              ; The terminating NUL character
        stx     IndReg          ; Look for name in correct bank
        cpy     #NAME_LEN + 1
        blt     L1
        ldy     #NAME_LEN       ; Limit the length
        bne     L1              ; Branch always
L0:     lda     (ptr1),y
L1:     sta     name,y
        dey
        bpl     L0
        jsr     restore_bank
        inc     __argc          ; argc always is equal to at least 1

; Find a "rem" token.

        ldx     #0
L2:     lda     BASIC_BUF,x
        bze     done            ; No "rem," no args.
        inx
        cmp     #REM
        bne     L2
        ldy     #1 * 2

; Find the next argument.

next:   lda     BASIC_BUF,x
        bze     done            ; End of line reached
        inx
        cmp     #' '            ; Skip leading spaces
        beq     next

; Found start of next argument. We've incremented the pointer in X already, so
; it points to the second character of the argument. That is useful because we
; will check now for a quoted argument; in which case, we will have to skip that
; first character.

found:  cmp     #'"'            ; Is the argument quoted?
        beq     setterm         ; Jump if so
        dex                     ; Reset pointer to first argument character
        lda     #' '            ; A space ends the argument
setterm:sta     term            ; Set end-of-argument marker

; Now, store a pointer to the argument into the next slot.

        txa                     ; Get low byte
        add     #<BASIC_BUF
        sta     argv,y          ; argv[y]= &arg
        lda     #>$0000
        adc     #>BASIC_BUF
        sta     argv+1,y
        iny
        iny
        inc     __argc          ; Found another arg

; Search for the end of the argument.

argloop:lda     BASIC_BUF,x
        bze     done
        inx
        cmp     term
        bne     argloop

; We've found the end of the argument. X points one character behind it, and
; A contains the terminating character. To make the argument a valid C string,
; replace the terminating character by a zero.

        lda     #$00
        sta     BASIC_BUF-1,x

; Check if the maximum number of command-line arguments is reached. If not,
; parse the next one.
;
        lda     __argc          ; Get low byte of argument count
        cmp     #MAXARGS        ; Maximum number of arguments reached?
        blt     next            ; Parse next one if not

; (The last vector in argv[] already is NULL.)

done:   lda     #<argv
        ldx     #>argv
        sta     __argv
        stx     __argv + 1
        rts

.segment        "INIT"

term:   .res    1
name:   .res    NAME_LEN + 1

.data

; char* argv[MAXARGS+1]={name};
argv:   .addr   name
        .res    MAXARGS * 2