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 (134 lines) | stat: -rw-r--r-- 3,778 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
;
; 2003-03-07, Ullrich von Bassewitz
; 2011-01-28, Stefan Haubenthal
; 2014-09-10, Greg King
;
; Set up arguments for main
;

        .constructor    initmainargs, 24
        .import         __argc, __argv

        .include        "atmos.inc"
        .macpack        generic

MAXARGS  = 10                   ; Maximum number of arguments allowed
REM      = $9D                  ; BASIC token-code


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

.segment        "ONCE"

.proc   initmainargs

; Assume that the program was loaded, a moment ago, by the traditional LOAD
; statement.  Save the "most-recent filename" as argument #0.

        ldy     #FNAME_LEN      ; Limit the length
        lda     #0              ; The terminating NUL character
        beq     L1              ; Branch always
L0:     lda     CFOUND_NAME,y
L1:     sta     name,y
        dey
        bpl     L0
        inc     __argc          ; argc always is equal to, at least, 1

; Find the "rem" token.

        ldx     #0
L2:     lda     BASIC_BUF,x
        beq     done            ; No "rem", no args.
        inx
        cmp     #REM
        bne     L2

; The arguments must be copied to a safe place because BASIC's input buffer
; might be re-used by the stdin console.

        ldy     #(SCREEN_XSIZE * 2 - 1) - 1
L3:     lda     BASIC_BUF,y
        sta     args,y
        dey
        bpl     L3

        ldy     #1 * 2          ; Point to second argv slot

; Find the next argument

next:   lda     BASIC_BUF,x
        beq     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. This is useful since we
; will check now for a quoted argument, in which case we will have to skip this
; 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     #<args
        sta     argv,y          ; argv[y]=&arg
        lda     #>$0000
        adc     #>args
        sta     argv+1,y
        iny
        iny
        inc     __argc          ; Found another arg

; Search for the end of the argument

argloop:lda     BASIC_BUF,x
        beq     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     #0
        sta     args-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?
        bcc     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

.endproc

.segment        "INIT"

term:   .res    1
name:   .res    FNAME_LEN + 1
args:   .res    SCREEN_XSIZE * 2 - 1

.data

; This array has zeroes when initmainargs starts.
; char* argv[MAXARGS+1]={name};

argv:   .addr   name
        .res    MAXARGS * 2