Cross-Referenz-Listings in GFA-Basic

Basic, auch wenn es von GFA kommt, hat gegenüber den klassischen Compiler-Sprachen wie PASCAL oder C einen besonderen gravierenden Nachteil: Variable, Unterprogrammnamen und Labels können an jeder beliebigen Stelle im Programm eingeführt werden, ohne vorher deklariert zu werden.

Das mag dem Basic-Freund zunächst als Vorteil erscheinen. Wer jedoch schon einmal eine schlaflose Nacht auf der Suche nach einem Programmierfehler verbracht hat, um hinterher festzustellen, daß bloß ein Tippfehler zu einer neuen Variablen mit dem sinnlosen Anfangswert Null geführt hat, wird vielleicht Zweifel bekommen haben.

Ein Pascal-Compiler z. B. hätte es gar nicht so weit kommen lassen: Bei der Übersetzung und dem Linken wird gnadenlos jeder ’Undefined Identifier’ aufgedeckt.

Um Abhilfe zu schaffen, wurde das vorliegende Cross-Referenz-Programm entwickelt. Es ermöglicht das identifizieren und Lokalisieren aller vom Programmierer erfundenen Bezeichner in einem im ASCII-Format abgespeicherten Programmtext (.LST-File).

Beim Speichern eines Programms mit ’SAVE,A’ ist zu beachten, daß zuvor mit der Anweisung ’DEFLIST 0’ die Standard-Textdarstellung verändert wird.

Hierdurch wird bewirkt, daß alle GFA-Schlüsselworte in Großschreibung und sämtliche Labels, Variablen- und Unterprogrammnamen mit kleinen Buchstaben erscheinen.

Damit ist ein einfaches Unterscheidungsmerkmal für die im Programm verwendete Such-Procedure gegeben.

Die Benutzung von XREF ist denkbar einfach und vollständig mit Alert-Boxen durchzuführen. Wie so oft empfiehlt sich die Verwendung einer RAM-Floppy.

Listing

Abbildung 1

Nach Auswahl des zu bearbeitenden Programms mit der File-Select-Box geht es los. Links oben auf dem Bildschirm sieht man die Nummer der gerade untersuchten Programmzeile: man kann die Bearbeitung an dieser Stelle mit einem Druck auf die Escape-Taste vorzeitig abbrechen.

Sollte das ausgewählte Programm im falschen Textformat vor liegen, so wird dies meist nach wenigen Zeilen entdeckt und mit einer Alert-Meldung kommentiert. Der Anwender hat nun die Möglichkeit, das Cross-Referenz-Programm zu verlassen, um das BAS-File in den Interpreter nachladen zu lassen.

Liegt das Programm nur als ASCII-Text vor, muß man XREF abbrechen und mit ’NEW’ löschen, um ’MERGE’ zu verwenden. Nach Abspeichern mit ’SAVE,A’ kann XREF erneut gestartet werden.

Ist dann alles glatt durchgelaufen, kann man die Cross-Referenz-Liste oder den mit Zeilennummern versehenen Programmtext auf Drucker oder Bildschirm ausgeben.

Bei der Anzeige auf dem Bildschirm kann man mit ’Control-S’ die Ausgabe anhalten und mit ’ Control-Q’ weiterlaufen lassen. Jeweils nach einer Bildschirm-Seite wird automatisch angehalten und auf einen Tastendruck oder Mouse-Klick gewartet.

Bevor man XREF verläßt, hat man die Möglichkeit, die Arbeit auf Diskette zu sichern. Das Cross-Referenz-Listing wird mit der Extension ’.CRF’, das numerierte Programm-Listing mit ’.PRN’, gespeichert.

Mit XREF sollte dem GFA-Basic-Programmierer das Leben hinsichtlich des Aufspürens von Tippfehlern, aber auch bei der Verbesserung der Dokumentation, erleichtert werden.

' ***********************************************************
' *                                                         *
' *	                    — XREF Vers 1.2 —                   *
' *	     Cross-Reference-Listings für GFA-Basic Programme   *
' *                                                         *
' *	                   14.03.1987 H. Bauch                  *
' *                                                         *
' ***********************************************************
'
ALERT 0," XREF Version 1.2! | 14.03.1987 by H. Bauch! ",1," Na los ",dunmy% 
@init
@bearbeiten 
DO 
	CLS 
	PRINT
	PRINT " ";akt_zeile%;" Zeilen in ";prg.name$;".LST"
	ALERT 1,"Programm durchsucht!",1,"Ausgabe|Neul|Quit",antw%
	CLS
	ON antw% GOSUB ausgabe,bearbeiten,ende 
LOOP

' 
' _____________________________________________________________

' ------------- Ende des Hauptprogranms -----------------------
' _____________________________________________________________
'
'
PROCEDURE init 
	DEFLIST 0
	LET typ_max%=5	!	0=Real/1=Integer/2=String/3=Boolean/4=Onterp./5=Label
	LET name_max%=200 ! max. Anz. der Namen pro Typ 
	sp_anz_zeil%=55	! Spaltenanzahl für die Zeilennr.-Ausgabe
	DIM name$(typ_max%,1,name_max%) ! Variablen-, Label oder Uprg.-name 
	DIM zeile$(typ_max%,1,name_max%) ! Zeilennr. in der ein Name steht 
	DIM zeilen_zaehler%(typ_max%,1,name_max%) ! Zähler für akt. Anz. Zeilennr.
	DIM max_nam_anz%(typ_max%,1)
	DIM typ$(typ_max%) 
	typ$(0)="Real-Variablen" 
	typ$(1)="Integer-Variablen" 
	typ$(2)="String-Variablen" 
	typ$(3)="Boolean-Variablen" 
	typ$(4)="Unterprogramm-Namen" 
	typ$(5)="Labels"
	trenn_zei$="+-*/\' ()=<>,; "+CHRS(34)	! Diese Zeichen trennen	Bezeichner.
	inv_ein$=CHR$(27)+CHRS(112)	! Bildschirmausgabe	invers
	inv_aus$=CHR$(27)+CHR$(113)	!	- " -	normal
RETURN! Init
'
'
PROCEDURE bearbeiten 
	ARRAYFILL zeilen_zaehler%(),0 
	ARRAYFILL max_nam_anz%(),0 
	DEFTEXT 1,16
	TEXT 125,30,"Welches Programm soll bearbeitet werden ?"
	FILESELECT "\*.LST","",p.name$
	IF EXIST(p.name$)
		OPEN "I",#1,p.name$
		p.name$=MID$(p.name$,1,LEN(p.name$)-4)
		p%=INSTR(p.name$,"\",p%)
		WHILE p%<>0 
			po%=p%
			p%=INSTR(p.name$,"\",po%+1)
		WEND
		path$=LEFT$(p.name$,po%) 
		prg.name$=MID$(p.name$,po%+1)
	ELSE
		@ende
	ENDIF
	CLS
	PRINT
	PRINT
	PRINT " Erstelle Cross-Reference-Listing von ";prg.name$;".LST"
	PRINT
	PRINT " Zeilen-Nummer in Bearbeitung -> ";
	y%=CRSLIN
	x%=CRSCOL
	akt_zeile%=0
	first!=TRUE
	DEFMOUSE 2
	WHILE (NOT EOF(#1)) AND INKEY$<>CHRS(27)
		INC akt_zeile%
		LINE INPUT #1,basic_zeile$
		PRINT AT(x%,y%);akt_zeile%;
		@entf_leer
		@entf_str_const
		@entf_komm
		@suche_namen
	WEND
	@namen_abspeichern
	DEFMOUSE 0
	CLOSE
RETURN! Bearbeiten
'
'
PROCEDURE entf_leer ! Führende Leerzeichen einer Basic-Zeile entfernen 
	WHILE MID$ (basic_zeile$,1,1)=" " 
		basic_zeile$=MID$(basic_zeile$,2)
	WEND
RETURN! Entf_leer
'
'
PROCEDURE entf_str_const ! Entf. von in Anführungszeichen stehenden Strings 
	CLR l%
	REPEAT
		k%=INSTR(basic_zeile$,CHRS(34),l%+1) ! Position des " am String-Anfang 
		l%=INSTR(basic_zeile$,CHRS(34),k%+1) ! Position des " am String-Ende 
		IF (k%<>0) AND (l%>k%) 
			basic_zeile$=LEFT$(basic_zeile$,k%)+MID$(basic_zeile$,l%) 
			l%=k%+1 
		ENDIF! (k%<>0) And (l%>k%)
	UNITL k%=0 OR k%>l%
RETURN! Entf_str_const
'
'
PROCEDURE entf_komm ! Entf. von Kommentaren die hinter "!"-Zeichen stehen 
	CLR k% ! Position eines '!'
	ok!=FALSE ! Flag für erfolgreiche Suche nach Kommentar-'!'
	REPEAT
		k%=INSTR(basic_zeile$,k%+1)
		IF (k%>2) ! Kommentare nur ab der 3. Spalte möglich
			' Das Zeichen vor dem '!' ist , ')', ‘oder ' '
			komm_found!=INSTR(CHR$(34)+"),; ",MID$(basic_zeile$,k%-1,1))
			IF (INSTR(basic_zeile$,"!!"))
				' ______________________________________________________
				’ Das Kommentar-'!' steht direkt hinter einer bool'schen Variablen
				' ______________________________________________________

				komm_found!=TRUE 
				k%=INSTR(basic_zeile$,"!!")+1 
			ENDIF! (Instr(Basic_zeile$,"!!"))
			IF komm_found!	! Kommentar mit Sicherheit gefunden
				basic_zeile$=LEFT$(basic_zeile$,k%-1) 
				ok!=TRUE
			ELSE	! Weitere Überprüfung notwendig
				i%=k%
				REPEAT	!	Suche Anfang des
					DEC i%	!	Bezeichners	vor
					pch$=MIDS(basic_zeile$,i%,1)	! dem '!'
				UNTIL (INSTR(trenn_zei$,pch$)<>0) OR i%=1 !
				IF (i%>1)
					INC i%
				ENDIF! (i%>1)
				IF ((k%>i%) AND (i%>0))
					' ______________________________________
					' Ermittlung des Bezeichners vor dem ‘!’
					' ______________________________________
					ident$=MID$(basic_zeile$,i%,k%-i%)
					§ident_name	!	Teste, ob GfA-Schlüsselwort
					IF (NOT ident_name!)
						' ___________________________________________
						' Schüsselwort oder Zahlenkonstante liegt vor 
						' ___________________________________________
						ok!=TUE
						basic_zeile$=LEFTS(basic_zeile$,k%-1)
					ENDIF! (Not Search!)
				ENDIF! ((K%>I%) And (I%>0))
			ENDIF! Komm_found!
		ENDIF! (K%>2)
	UNTIL (ok! OR k%=0)
RETURN! Entf_komm
'
'
PROCEDURE suche_namen ! Suche Bezeichner, die nicht GfA-Basic-Schlüsselwort 
	LET o_flag!=FALSE	!	On ... gefunden
	LET lab_flag!=FALSE	!	Label gefunden
	LET up_nam_found!=FALSE	!	Unterprogrammnamen gefunden
	LET name_pos!=FALSE	!	Name überhaupt möglich
	LET b$="§()= :"
	FOR i%=1 TO LEN(b$)
		LET name_pos!=name_pos! OR INSTR(basic_zeile$,MID$(b$,i%,1))
	NEXT i%
	LET name_pos!=name_pos! AND NOT ((MID$(basic_zeile$,1,1)="'") OR (MID$(basic_zeile$,1,3)="REM") OR (MID$(basic_zeile$,1,4)="DATA"))
	IF name_pos!
		' _______________________________________________________________
		' Basic-Zeile enthält mindestens 1 Anweisung mit Klammern oder 
		' Gleichheitszeichen und ist nicht Kommentar- oder Data-Zeile
		' _______________________________________________________________
		WHILE LEN(basic_zeile$)>0 
			§identifier 
			IF first!
				§test_list_def(ident$)
			ENDIF
			IF ident$="ON" 
				o_flag!=TRUE 
			ENDIF
			IF ident$="PROCEDURE" OR ident$="GOSUB" OR ident$="§"
				' Unterscheidung zw. Variablen und Unterprg.-namen bzw. Labeln
				up_nam_found!=TRUE 
			ENDIF! Ident$="PROCEDURE" Or ...
			IF ident$="GOTO" OR ident$="RESUME" OR ident$="RESTORE" 
				lab_flag!=TRUE 
			ENDIF
			§ident_name 
			IF ident_name!
				IF up_nam_found! 
					t%=4
					§name_ablegen 
					IF NOT o_flag!
						up_nam_found!=FALSE 
					ENDIF 
				ELSE
					IF INSTR(ident$,":") OR lab_flag!
						IF RIGHT$(ident$,1)=":"
							ident$=LEFT$(ident$,LEN(ident$)-1)
						ENDIF
						t%=5
						§name_ablegen 
						lab_flag !=FALSE 
					ELSE
						t%=INSTR("%$!",RIGHT$(ident$,1)) ! Typ der Variablen 
						§name_ablegen 
					ENDIF 
				ENDIF 
			ENDIF
		WEND
	ENDIF 
RETURN! Such_namen
'
'
PROCEDURE identifier 
	' Ermittlung des nächsten Bezeichners Beginnend ab der 1. Spalte
	' des restlichen Basic-Zeilen-Strings; der gefundene Bezeichner
	' wird anschließend von diesem entfernt.
	CLR ident$,nch$,i%
	REPEAT 
		INC i%
		ident$=ident$+nch$ 
		nch$=MID$(basic_zeile$,i%,1)
		EXIT IF nch$="§"
	UNITL INSTR(trenn_zei$,nch$)<>0 OR nch$=""
	IF nch$="§" 
		ident$="§"
	ENDIF! Nch$="S"
	k%=ABS(basic_zeile$,1%,1)="(") ! Funktion oder Array-Var 
	basic_zeile$=MID$(basic_zeile$,i%+1) ! Der verbleibende String 
RETURN ! Identifier
'
'
PROCEDURE ident_name ! Identifiziere Namen, falls Erfolg  Ident_name!=TRUE 
	IF LEN(ident$)=0 OR ident$="§" 
		ident_name!=FALSE 
	ELSE
		IF VAL?(ident$)=LEN(ident$)
			' ------------------------
			' Zahlenkonstante gefunden
			' ------------------------
			ident_name!=FALSE 
		ELSE 
			IF LEN(ident$)>1
				' ---------------------------------------------
				' Schlüsselworte sind mindestens 2 Zeichen lang
				' ---------------------------------------------
				f_ch$=LEFT$(ident$)
				IF f_ch$>="a" AND f_ch$<="z" 
					ident_name!=TRUE 
				ELSE
					ident_name!=FALSE 
				ENDIF
			ELSE! (Len(Ident$)=1)
				' -----------------------------------------------------------------
				' Bezeichnerlänge gleich eins bedeutet immer einfache Real-Variable
				' -----------------------------------------------------------------
				ident_name!=TRUE 
			ENDIF! Len(Ident$)>1 
		ENDIF! Val?(Ident$)=Len(Ident$)
	ENDIF! Len(Ident$)=0 
RETURN
'
'
PROCEDURE test_list_def(test$) 
	zw_buchst!=FALSE 
	f_ch$=LEFT$(test$)
	FOR i%=2 TO LEN(test$) 
		n_ch$=UPPER$(MID$(test$,i%,1)) 
		zw_buchst!=(n_ch$>="A" AND n_ch$<="Z")
		EXIT IF zw_buchst!
	NEXT i%
	IF zw_buchst!
		IF f_ch$>="A" AND f_ch$<="Z"
			IF UPPER$(test$)<>test$ 
				meldung$="Das Program ist nicht mit| 'DEFLIST 0' abgespeichert ! |XREF abbrechen nachladen von |"+prg.name$+".BAS ?"
				ALERT 2,meldung$,2," Nö | Klar ",antw%
				IF antw%=2
					meldung$="Nach Abspeichern mit 'SAVE, A' |XREF.BAS mit 'LOAD' aufrufen|und erneut starten !"
					ALERT 1,meldung$,1," Ok ",dummy% 
					l_name$=MID$(prg.name$,LEN(prg.name$)-4)+".BAS"
					IF NOT (EXIST(l_name$))
						ALERT 2, "BAS-File nicht gefunden",1, "Mist",dummy%
						FILESELECT "\*.BAS","",l_name$ 
					ENDIF
					IF l_name$<>""
						LOAD l_name$
					ELSE
						ALERT 2, "Program nicht gefunden.|Neustart",1," Seufz ",dummy%
						RUN
					ENDIF
				ELSE
					RUN
				ENDIF! antw%=2 
			ENDIF! UPPER$(test$)<>test$ 
		ENDIF! f_ch$>="A" AND ... 
		first!=FALSE 
	ENDIF! zw_buchst!
RETURN! test_list_def
'
'
PROCEDURE name_ablegen ! Ablegen der identifizierten Namen in einem Feld
	id_len%=LEN(ident$)
	IF id_len%>0 
		IF k%=1 
			ident$=ident$+"()"
			INC id_len%
			INC id_len%
		ENDIF
		IF id_len%<20 
			ident$=ident$+STRING$(20-id_len%,".")
		ELSE 
			IF id_len%>20 
				ident$=ident$+CHR$(10)+CHR$(13)+SPACE$(20) 
			ENDIF 
		ENDIF 
		zei_nr$="    "
		RSET zei_nr$=STR$(akt_zeile%)
		IF max_nam_anz%(t%,k%)=0 AND zeilen_zaehler%(t%,k%,1)=0
			' ------------------------------
			' Erster Aufruf dieser Procedure
			' ------------------------------
			LET name$(t%,k%,1)=ident$ ! Der gefundene Name 
			LET zeile$(t%,k%,1)=zei_nr$ ! und die zugehörige Zeile 
			zeilen_zaehler%(t%,k%,1)=1 ! Anzahl Zeilen in denen Name$() enth. ist 
			max_nam_anz%(t%,k%)=1
		ELSE
			' --------------------
			' Jeder weitere Aufruf
			' --------------------
			FOR i%=1 TO max_nam_anz%(t%,k%) ! Suchen ob Ident$ schon mal aufgetaucht?
				EXIT IF name$(t%,k%,i%)=ident$ ! falls ja, Aussteigen aus der Schleife 
			NEXT i%	!
			IF i%>max_nam_anz%(t%,!c%)
				' ---------------------------------
				' Ident$ ist noch nicht vorgekomnen
				' ---------------------------------
				INC max_nam_anz%(t%,k%)	! Zähler erhöhen
				INC zeilen_zaehler%(t%,k%,i%)	! Zeilenzähler=1
				LET name$(t%,k%,i%)=ident$	! Neuen Name speichern
				LET zeile$(t%,k%,i%)=zei_nr$	! 1. Zeile ablegen
			ELSE
				IF INSTR(zeile$(t%,k%,i%),zei_nr$)=0
					' ---------------------------------------------
					' Ident$ kennt in Akt_zeile% zum ersten mal vor
					' ---------------------------------------------
					INC zeilen_zaehler%(t%,k%,i%)
					LET zeile$(t%,k%,i%)=zeile$(t%,k%,i%)+zei_nr$ 
				ENDIF
			ENDIF! (I%>max_nam_anz%(t%,k%)
		ENDIF 
	ENDIF 
RETURN! Name_ablegen
'
'
PROCEDURE namen_abspeichern 
	FOR k%=0 TO 1 
		FOR t%=0 TO typ_max%
			IF max_nam_anz%(t%,k%)>0 
				§sort(t%,k%,max_nam_anz%(t%,k%))
			ENDIF 
		NEXT t%
	NEXT k%
RETURN! namen_abspeichern
'
'
PROCEDURE sort(typ%,kl%,m_v_anz%) ! Alphabetisches Sortieren der Namen 
	LOCAL i%,j%
	FOR i%=m_v_anz%-1 DOWNTO 0 
		FOR j%=0 TO i%
			IF name$(typ%,kl%,j%)>name$(typ%,kl%,j%+1)
				SWAP name$(typ%,kl%,j%),name$(typ%,kl%,j%+1)
				SWAP zeile$(typ%,kl%,j%),zeile$(typ%,kl%,j%+1)
				SWAP zeilen_zaehler%(typ%,kl%,j%),zeilen_zaehler%(typ%,kl%,j%+1) 
			ENDIF 
		NEXT j%
	NEXT i%
RETURN! Sort()
'
'
PROCEDURE ausgabe 
	ALERT 2,"Ausgabe auf ",1,"Schirm|Drucker",device%
	IF device%=1 
		device$="CON:"
	ELSE
		device$="PRN:"
	ENDIF
	ALERT 1,"Ausgabe von ",1,"XRF-List|PRG-List",antw%
	CLS
	IF antw%=1 
		@namen_ausgeben(device$)
	ELSE
		@listing_ausgeben(device$)
	ENDIF 
RETURN! Ausgabe
'
'
PROCEDURE namen_ausgeben(dev$)
	OPEN "O",#3,dev$
	PRINT #3
	PRINT #3," Cross-Reference-Listing von ";prg.name$;".LST"
	PRINT #3,STRINGS(80,"=")
	scrn_l%=CRSLIN-1
	FOR t%=0 TO typ_max%
		IF max_nam_anz%(t%,0)+max_nam_anz%(t%,1)>0 
			PRINT #3 
			@halt
			PRINT #3,"*   ";typ$(t%)
			@halt
		ENDIF
		FOR k%=0 TO 1 
			FOR i%=1 TO max_nam_anz%(t%,k%)
				IF LEN(name$(t%,k%,i%))>0 
					PRINT #3,name$(t%,k%,i%);
					IF LEN(name$(t%,k%,i%))>20 
						@halt 
					ENDIF
					IF LEN(zeile$(t%,k%,i%))>sp_anz_zeil% 
						za%=(LEN(zeile$(t%,k%,i%)) DIV sp_anz_zeil%)
						IF LEN(zeile$(t%,k%,i%)) MOD sp_anz_zeil%>0 
							za%=za%+1 
						ENDIF
						PRINT #3,MIDS(zeile$(t%,k%,i%),1,sp_anz_zeil%)
						@halt
						z%=1
						WHILE z%<za%
							PRINT #3,SPACES(20);MID$(zeile$(t%,k%,i%),sp_anz_zeil%*z%+1,sp_anz_zeil%)
							@halt 
							INC z%
						WEND
					ELSE
						PRINT #3,zeile$(t%,k%,i%)
						@halt
					ENDIF
				ENDIF
			NEXT i%
		NEXT k%
	NEXT t%
	CLOSE
	PRINT CHR$(7)
	IF device%<>0
		PRINT "     ";inv_einS;"     Ausgabe beendet - Zurück durch	Tastendruck!      ";inv_aus$
		PAUSE 20 
		REPEAT
		UNITL INKEY$<>"" OR MOUSEK 
	ENDIF
RETURN! Namen_ausgeben()
'
PROCEDURE listing_ausgeben(dev$)
	OPEN "I",#1,p.name$+".LST"
	OPEN "O",#2,dev$
	PRINT #2
	PRINT #2," Nummeriertes Listing von ";p.name$+".LST"
	PRINT #2,STRINGS(80,"=")
	PRINT #2
	scrn_l%=CRSLIN
	akt_zeile%=0
	WHILE (NOT EOF(#1)) AND INKEY$<>CHR$(27)
		INC akt_zeile%
		LINE INPUT #1,basic_zeile$ 
		PRINT #2,USING "###: ",akt_zeile%;
		PRINT #2,basic_zeile$
		§halt
	WEND
	CLOSE
	PRINT CHR$(7)
	IF device%<>0
		PRINT "          ";inv_ein$;“      Ausgabe beendet - Zurück durch Tastendruck!	";inv_aus$
		PAUSE 20 
		REPEAT
		UNTIL INKEY$<>"" OR MOUSEK 
	ENDIF 
RETURN
'
'
PROCEDURE halt 
	IF device%=1
		IF ASC(INKEY$)=19	! Anhalten mit ’S
			PAUSE 10 
			REPEAT
			UNTIL ASC(INKEY$)=17 ! Weiter mit 'Q 
		ENDIF
		INC scrn_l%
		IF scrn_l%>20 
			scrn_l%=0 
			PRINT CHRS (7)
			PRINT SPACES(21);inv_ein$;"	   Weiter durch Drücken einer Taste!   ";inv_aus$
			REPEAT
			UNTIL INKEY$<>"" OR MOUSEK 
			PRINT 
		ENDIF 
	ENDIF 
RETURN
'
'
PROCEDURE ende 
	IF prg.name$<>"" 
		device%=0
		ALERT 3,"Arbeit sichern?",1," Nö | Klar ",antw%
		IF antw%=2
			TEXT 125,30,"     Arbeit sichern.           "
			FILESELECT path$+"*.CRF",prg.name$+".CRF",crf$
			IF crf$<>""
				DEFMOUSE 2
				@namenausgeben(crf$)
				DEFMOUSE 0 
			ENDIF
			FILESELECT path$+"*. PRN",prg.name$+".PRN",prn$ 
			IF prn$<>""
				DEFMOUSE 2
				@listing_ausgeben(prn$)
				DEFMOUSE 0 
			ENDIF 
		ENDIF 
	ENDIF 
	CLS 
	END 
RETURN

Listing 1



Aus: ST-Computer 05 / 1987, Seite 36

Links

Copyright-Bestimmungen: siehe Über diese Seite