	SUBROUTINE BIDENT(M,LAST)
C
C	THIS SUBROUTINE PRODUCES AN IDENTIFIER (SYMBOL) STRING.
C	VALID IDENTIFIER CHARACTERS ARE A-Z, $, UNDERSCORE.
C	ALL LOWER CASE ALPHA ARE CONVERTED TO UPPER CASE.
C
	INTEGER*4	FORMAT_LINE
	LOGICAL*1	L(256),LS(16),EOL
	CHARACTER*1	EOLCHAR,COMMANDC
	CHARACTER*256	LINE
	CHARACTER*16	STRING,RESERVED(200)
C
	COMMON/FXREFA/ LINE,RESERVED
	COMMON/FXREFB/ FORMAT_LINE,NCHAR,MAX,LINE_NO,MAX_RES,IFIRST,IDO
	COMMON/FXREFD/ ISB,MAXI
	COMMON/FXREFE/ STRING
	COMMON/FXREFF/ EOLCHAR,COMMANDC
	COMMON/FXREFG/ NOCMODE,ICRK
	COMMON/FXREFS/ K1A(128),K2A(128)
	EQUIVALENCE (L(1),LINE(1:1))
	EQUIVALENCE (LS(1),STRING(1:1))
	EQUIVALENCE (EOL,EOLCHAR(1:1))
C
	N=M	!INPUT LINE POINTER
	I=1	!OUTPUT STRING LENGTH AND POINTER
	ISBSAV=ISB
	IF(L(N).EQ."46) ISB=1 !& TEST - & OCCURS ONLY WHEN ICRK=1
	STRING(16:16)=' '
	IF(L(N).GE."141.AND.L(N).LE."172) L(N)=L(N)-"40 !LOWER TO UPPER CASE
C	SAVE THIS CHARACTER
100	STRING(I:I)=LINE(N:N)
	J=I+1
110	N=N+1
	LAST=N
	IF(N.GT.NCHAR) GO TO 300
	IF(L(N).NE."40.AND.L(N).NE."11) GO TO 115
C ***	MUST TEST FOR RESERVED WORD BEFORE SWALLOWING BLANK OR TAB
	IF(ISB.EQ.1) GO TO 300 !BLANKS MAY BE SIGNIFICANT
	IF(I.EQ.1) GO TO 110 !NO RESERVED WORDS WITH ONE LETTER
	IF(MAX_RES.EQ.0) GO TO 115
	IF(J.GT.16) GO TO 113
	DO 112 K=J,16
112	STRING(K:K)=' '
113	K1=K1A(LS(1))
	IF(K1.EQ.0) GO TO 110
	K2=K2A(LS(1))
	JJ=J
	IF(JJ.GT.15) JJ=15
	DO 114 K=K1,K2
	IF(STRING(2:JJ).EQ.RESERVED(K)(2:JJ)) GO TO 420
114	CONTINUE
	GO TO 110
C ***	END OF TEST FOR RESERVED WORD
115	IF(L(N).GE."101.AND.L(N).LE."132) GO TO 120
	IF(L(N).GE."60.AND.L(N).LE."71) GO TO 120
	IF(L(N).EQ."44) GO TO 120
	IF(L(N).EQ."137.AND.ICRK.EQ.0) GO TO 120
	IF(ICRK.EQ.0) GO TO 119
C	CROCK TESTS
	IF(LS(1).EQ."46.AND.L(N).EQ."56.AND.   !TEST FOR &P100.10 LABEL FORMAT
	1 L(N+1).GE."60.AND.L(N+1).LE."71.AND.(N+1).LE.NCHAR) GO TO 120
	IF(L(N).EQ."137.AND.L(N+1).NE."46.AND.
	1 (N+1).LE.NCHAR) GO TO 120  !UNDERSCORE NOT PART OF SYMBOL HERE
119	IF(L(N).LT."141.OR.L(N).GT."172) GO TO 300
C	CONVERT LOWER CASE TO UPPER CASE
	L(N)=L(N)-"40
C	SAVE THIS CHARACTER
120	IF(J.GT.15) GO TO 200
	I=J
	GO TO 100
C	STRING GT 15 CHARACTERS
200	STRING(16:16)='*'
C	BLANK REST OF LINE AND THEN PRODUCE IT
300	IF(J.GE.16) GO TO 400
	DO 320 K=J,15
320	STRING(K:K)=' '
400	MAXI=I
	CALL PRODUCE('@',LINE_NO,MAX_RES)
420	IF(IFIRST.EQ.0) GO TO 430
	IF(ISB) 427,425,427 !DON'T TEST WHEN BLANKS SIGNIFICANT
425	IF(STRING(1:7).EQ.'FORMAT ') FORMAT_LINE=1
	IF(STRING(1:3).EQ.'DO ') IDO=1
427	IFIRST=0
C	CHECK FOR THE CASE THAT A NUMBER OR QUOTED STRING STARTS NEXT
430	IF((L(LAST).GE."60.AND.L(LAST).LE."71).OR.
	1   L(LAST).EQ."47) LAST=LAST-1
	IF(ICRK.EQ.0) GO TO 500
	IF(LS(3).EQ."46) IFIRST=1 !CROCK LABELS MAY BE SYMBOLS
	IF(L(LAST).EQ."46) LAST=LAST-1 !& NOT LAST
C	EOLCHAR TESTS FOR CROCK
	IF(STRING(3:10).NE.'EOLCHAR ') GO TO 460 !PRODUCE MOVES STRING
	NN=N
440	IF(NN.GT.NCHAR) GO TO 500
	IF(L(NN).EQ."47) GO TO 450 !LOOK FOR SINGLE QUOTE
	IF(LINE(NN:NN).EQ.';') GO TO 445 !LOOK FOR SEMICOLON (NO EOLCHAR)
	NN=NN+1
	GO TO 440
445	EOL=0
	GO TO 500
450	NN=NN+1
	IF(NN.GT.NCHAR) GO TO 500
	EOLCHAR=LINE(NN:NN) !THIS IS EOLCHAR
	GO TO 500
C	TEST FOR CROCK COMMANDC RESERVED WORD
460	IF(STRING(3:11).NE.'COMMANDC ') GO TO 470
	NN=N
461	IF(NN.GT.NCHAR) GO TO 500
	IF(L(NN).EQ."47) GO TO 462
	IF(LINE(NN:NN).EQ.';') GO TO 500
	NN=NN+1
	GO TO 461
462	NN=NN+1
	IF(NN.GT.NCHAR) GO TO 500
	COMMANDC=LINE(NN:NN) !THIS IS NEW CROCK CHARACTER FOR COL 1
	GO TO 500
C	TEST FOR CROCK NOCMODE RESERVED WORD
470	IF(STRING(3:10).NE.'NOCMODE ') GO TO 480
	NOCMODE=1 !THIS MEANS CROCK LINES MUST HAVE COMMANDC CHARACTER IN COL 1
	GO TO 500
C	TEST FOR CROCK CMODE RESERVED WORD
480	IF(STRING(3:8).NE.'CMODE ') GO TO 500
	NOCMODE=0 !CMODE IN EFFECT MEANS ALL LINES TREATED AS CROCK LINES
500	ISB=ISBSAV
	RETURN
	END
