SCAN0.PAS 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163
  1. (* changes:
  2. 11-nov-92
  3. Now in m+ mode "AB""CD" is accespted as AB"CD value
  4. Earlier it were two values "AB" and "CD"
  5. *)
  6. {$DEFINE RAMSCAN}
  7. {$DEFINE SCANU}
  8. { Rigal integrated environment (c) 1991 Software house Riga }
  9. { }
  10. { }
  11. {$IFDEF SCANU}
  12. Unit Scan;
  13. interface
  14. uses
  15. {$IFDEF WIN} tmemstrm,winprocs, {$ENDIF}
  16. define;
  17. { Separate scanner for input strings and output Rigal objects }
  18. Procedure INITIALIZE_SCAN_VARIABLES;
  19. Procedure Scaner
  20. {*****************************************}
  21. (mode_parm:integer;
  22. {1=from file,2=list of strings,3=absulute address,
  23. 4=stream memory handle }
  24. filename:string80;
  25. options_str:string80;
  26. var rez:a; { result; set to NULL if input is absent }
  27. var erlist_parm:a; { error number list; set to NULL if no errors }
  28. strlist:a; { list of atoms }
  29. segm,ofs:longint); { parts of absolute address }
  30. implementation
  31. uses defpage,nef,poutlexu,doutu;
  32. {$ELSE}
  33. #include "define.p"
  34. #include "defpage.inc"
  35. #include "nef2.inc"
  36. #include "outs.inc"
  37. #include "scan.inc"
  38. {$ENDIF}
  39. {VARIABLES}
  40. type bigstring=
  41. {$IFDEF xSUN}
  42. varying array[127] of char;
  43. {$ELSE}
  44. string [127];
  45. {$ENDIF}
  46. var a1: a; { global variable for ONLY LOCAL use }
  47. {aa1 : aa ;} { --"-- }
  48. X : MPD; { --"-- }
  49. bl801 : bl80; { -- " -- }{ array[1..80] of char}
  50. k,kk:integer; { -"- }
  51. c1:char;
  52. saved_coord, { where current token began }
  53. coord_mark , { what was set by coordinate marker }
  54. line_byte_number , { number of totally read bytes till beginning
  55. of current line }
  56. last_mark_byte_number , { number of totally read bytes till
  57. last coordinate marker }
  58. old_line_length { length of the current line,
  59. used only for incrementation of "lyne_byte_number"}
  60. :word;
  61. DT:descriptortype; { type of last read token or control character }
  62. AADR:a; { A-space address of last read token }
  63. Linenumber:longint; { Current line number }
  64. Tokennumber:longint;{ Current token number }
  65. Errlist :a; { List of numbers of errors }
  66. Read_mode:integer; { 1,2,3 }
  67. PTR1 : PTR; { List pointer when read from list of atoms }
  68. {$IFDEF RAMSCAN}
  69. ABSPNT : Pointer;{ RAM pointer when read from RAM }
  70. {$ENDIF}
  71. inpfile : text;
  72. var
  73. c_lexics,
  74. pascal_lexics,
  75. row80_coord,
  76. byte_coord,
  77. mark_byte_coord,
  78. mark_only_coord,
  79. string_coord,
  80. char_coord,
  81. token_coord,
  82. collect_errors,
  83. screen_errors,
  84. to_uppercase,
  85. pascal_comment,
  86. c_comment,
  87. ada_comment,
  88. pascal_string,
  89. modula_string:boolean;
  90. const new_line_code=Chr(13); { Chr(0 is allowed too }
  91. endfile_code =Chr(26);
  92. var s:bigstring;
  93. s_for_val:bigstring; { added 17-FEB-92 }
  94. i:integer;
  95. type is_something=
  96. (is_control, is_letter, is_digit, is_underscore, is_printable,
  97. is_special, is_space , is_first_of_two);
  98. type pair=packed array[1..2]of char;
  99. var as:array[char]of is_something;
  100. isa : is_something;
  101. upcase_tab:array[char]of char;
  102. set_of_second_of_two:set of char;
  103. two_char_symbols_num:integer;
  104. two_char_symbols:array[1..30]of pair;
  105. b123 : record
  106. case integer of
  107. 1:(b1:char);
  108. 2:(b2:packed array[1..2]of char);
  109. 3:(b3:packed array[1..3]of char);
  110. end;
  111. var in_comment,in_string : boolean;
  112. var is_2quote : boolean; { if in_string then it is possible }
  113. var Str_constlen:longint;
  114. Str_const : string80; { array of char is allowed too }
  115. {===== SUN VERSION ===}
  116. {$IFDEF SUN}
  117. procedure inc{1}(var xxx:longint);
  118. begin xxx:=xxx+1; end;
  119. procedure inc{2}(var xxx:longint;yyy:longint);
  120. begin xxx:=xxx+yyy; end;
  121. procedure inc{3}(var xxx:integer);
  122. begin xxx:=xxx+1; end;
  123. procedure inc{4}(var xxx:integer;yyy:integer);
  124. begin xxx:=xxx+yyy; end;
  125. {$ENDIF}
  126. {=====}
  127. function CONT_CHAR_TO_DT(c:char):descriptortype;forward;
  128. function Getcoord:word;forward;
  129. procedure ER_LEX(er_number:integer);forward;
  130. {Procedure INITIALIZE_SCAN_VARIABLES;forward;}
  131. Procedure READ_FILE(var read_file_rez:a);forward;
  132. Function READ_ITEM:a;forward;
  133. Procedure READLINE;forward;
  134. Procedure PutAtom(j:integer);forward;
  135. Procedure PutIt(dd:descriptortype;j:integer);forward;
  136. Procedure PutIdent(j:integer);forward;
  137. Procedure PutFloat(j:integer;digits_before_dot,digits_after_dot:integer);forward;
  138. Procedure PutNumber;forward;
  139. Procedure PutStr;forward;
  140. Procedure PutStr2;forward;
  141. {Procedure Scaner;forward;}
  142. Procedure SETLEXICS;forward;
  143. Procedure StrAdd(c:char);forward;
  144. Procedure StrBegin;forward;
  145. Procedure Token;forward;
  146. Function TAKE_DIGITS(var jj:integer):longint;forward;
  147. Function TAKE_LETTERS:integer;forward;
  148. { uses global string, received from Readline procedure,
  149. produces global attributes of new one token read.
  150. Some variables also should be initialized if by Initial_token
  151. procedure at the start of the WHOLE programm }
  152. { This procedure is oriented to Turbo Pascal language }
  153. { Procedure call graph follows :
  154. /self\
  155. USEPAS -> SCAN -> READFILE -> READITEM -> ADDEL.nef
  156. -> LCONC.nef ER_LEX
  157. -> SETOPTIONS GETS1.defpage
  158. -> FIRST.nef TOKEN
  159. -> ASSIGN.system POINTR.defpage
  160. -> RESET.system LCONC.nef
  161. -> READLINE
  162. TOKEN -> ER
  163. -> READ_LETTERS_OR_DIGITS
  164. -> READ_DIGITS
  165. -> STRBEGIN
  166. -> PUTNUMBER
  167. -> StrAdd -> ER
  168. -> PUTSTR -> PUTATM.defpage
  169. -> PutAtom ->\
  170. -> PUTFLOAT -> PUTIT -> PUTATM.defpage
  171. -> PUTIDENT ->/
  172. }
  173. function CONT_CHAR_TO_DT(c:char):descriptortype;
  174. {**********************************************}
  175. begin
  176. Cont_char_to_dt:=descriptortype(c);
  177. end;
  178. function Getcoord:word;
  179. {***********************}
  180. begin
  181. if row80_coord then Getcoord:=i+Linenumber*80
  182. else
  183. if mark_only_coord then Getcoord:=coord_mark
  184. else
  185. if mark_byte_coord then
  186. Getcoord:=coord_mark+
  187. (line_byte_number+i-last_mark_byte_number)
  188. else
  189. if byte_coord then Getcoord:=line_byte_number+i
  190. else
  191. if string_coord then Getcoord:=Linenumber
  192. else
  193. if token_coord then Getcoord:=Tokennumber
  194. else
  195. Getcoord:=0;
  196. end;
  197. procedure ER_LEX(er_number:integer);
  198. {***********************************}
  199. var er_atom:a;co:word;erm:string80;
  200. begin
  201. co:=Getcoord;
  202. if collect_errors then begin
  203. Gets1(er_atom,x.sa);
  204. with x.snd^ do begin
  205. dtype:=number;
  206. cord:=co;
  207. val:=er_number;
  208. end;
  209. lconc(errlist {global} ,er_atom);
  210. end;
  211. if screen_errors then
  212. begin
  213. case er_number of
  214. 1 : erm:=' unexpected end of file before end of tree';
  215. 2 : erm:=' unexpected end of file within tree branch ';
  216. 3 : erm:=' unexpected end of file within tree ';
  217. 4 : erm:=' unexpected end of file before end of list ';
  218. 5 : erm:=' unexpected end of tree ';
  219. 6 : erm:=' unexpected end of list or another control character';
  220. 7 : erm:=' unexpected end of file in name ';
  221. 8 : erm:=' unexpected end of file in named object ';
  222. 9 : erm:=' unexpected control character ';
  223. 10 : erm:=' too long atom ( more than 80 bytes ) ';
  224. 11 : erm:=' end of string constant not found in the current line';
  225. 12 : erm:=' end of file before end of comment';
  226. 13 : erm:=' control character within comment ';
  227. 14 : erm:=' control character within string constant';
  228. end;
  229. writeln('Lexical error :',erm);
  230. writeln('Line=',linenumber,' column=',i);
  231. end;
  232. end;
  233. Procedure INITIALIZE_SCAN_VARIABLES;
  234. {***********************************}
  235. var c:char;
  236. begin
  237. for c:=Chr(0) to Chr(255) do upcase_tab[c]:=c;
  238. for c:=Chr(97) to Chr(122) do upcase_tab[c]:=Chr(ord(c)-32);{ASCII}
  239. (* for c:=Chr(160) to Chr(175) do upcase_tab[c]:=Chr(ord(c)-32); *){Russian}
  240. (* for c:=Chr(224) to Chr(239) do upcase_tab[c]:=Chr(ord(c)-60);*){Russian}
  241. { German for Windows }
  242. upcase_tab[chr(228)]:=chr(196);
  243. upcase_tab[chr(246)]:=chr(214);
  244. upcase_tab[chr(252)]:=chr(220);
  245. for c:=Chr(0) to Chr(31) do as[c]:=is_control;
  246. for c:=Chr(128) to Chr(255) do as[c]:=is_letter; { Russian and pseudographics }
  247. for c:=Chr(32) to Chr(127) do as[c]:=is_printable; { not used actually }
  248. as[new_line_code]:=is_control;
  249. as[' ']:=is_space;
  250. as[Chr(9)] :=is_space;
  251. { these are allowed to be First letter of identifiers }
  252. for c:='A'to'Z' do as[c]:=is_letter;
  253. for c:='a'to'z' do as[c]:=is_letter;
  254. for c:='0'to'9' do as[c]:=is_digit;
  255. { allowed to be non-first letter of odentifier }
  256. as['_']:=is_underscore;
  257. { All the rest settings - see procedure SETLEXICS }
  258. end;
  259. Procedure READ_FILE(var read_file_rez:a);
  260. {******************************}
  261. { reads whole input, produces list of items }
  262. label 99;
  263. begin read_file_rez:=NULL;
  264. repeat a1:=read_item;
  265. if (dt=start_tree)or(dt=end_tree)or(dt=start_list)or
  266. (dt=end_list)or(dt=name_obj) then begin ER_LEX(6);goto 99;end;
  267. if DT<>eof_desk then lconc(read_file_rez,a1);
  268. until DT=eof_desk;
  269. 99: end;
  270. Function READ_ITEM:a;
  271. {********************}
  272. label 99;
  273. var aadr1:a; result,temp_res:a;
  274. begin
  275. READ_ITEM:=NULL; { default value for exits with errors }
  276. result:=NULL;
  277. TOKEN;
  278. case DT of
  279. atom,idatom,tatom,fatom,keyword:
  280. begin gets1(result,x.sa);
  281. with x.sad^ do begin
  282. dtype:=DT; cord:=saved_coord;
  283. name := AADR;
  284. end
  285. end;
  286. number:
  287. begin gets1(result,x.sa);
  288. with x.snd^ do begin
  289. dtype:=DT; cord:=saved_coord;
  290. val:= AADR; { is set in TOKEN .. is_digit }
  291. end;
  292. end;
  293. start_tree:
  294. begin result:=NULL;
  295. repeat
  296. TOKEN;
  297. aadr1:=AADR; { to save }
  298. if (DT=idatom)or(DT=atom)or(DT=tatom)or(DT=keyword)
  299. { What is allowed selector in scaner input ?
  300. Normally - idatom only, but here
  301. atom is allowed too - for experiment purposes }
  302. then
  303. begin
  304. a1:=Read_item;
  305. if DT=end_list then begin ER_LEX(6); goto 99; end;
  306. if DT=eof_desk then begin ER_LEX(1);goto 99;end;
  307. Addel3(result,aadr1,a1);
  308. end
  309. else if DT<>end_tree then begin ER_LEX(2);goto 99;end;
  310. ;
  311. until (DT=end_tree)or(DT=eof_desk);
  312. if DT=eof_desk then begin ER_LEX(3);goto 99;end;
  313. DT:=complex_desk; { to ignore analysis in upper level of
  314. recursion }
  315. end;
  316. start_list :
  317. begin
  318. result:=NULL;
  319. repeat
  320. a1:=read_item;
  321. if DT=eof_desk then begin ER_LEX(4);goto 99;end;
  322. if (DT<>end_list) then lconc(result,a1);
  323. until DT=end_list;
  324. DT:=complex_desk;
  325. end;
  326. end_tree : begin ER_LEX(5); goto 99; end;
  327. end_list : begin end; {immodiately returns to the upper level}
  328. name_obj: begin
  329. temp_res:=read_item;
  330. if DT=end_list then begin ER_LEX(6); goto 99; end;
  331. if DT=eof_desk then begin ER_LEX(7); goto 99; end;
  332. result :=read_item;
  333. if DT=end_list then begin ER_LEX(6); goto 99; end;
  334. if DT=eof_desk then begin ER_LEX(8); goto 99; end;
  335. if result<>NULL then begin
  336. points(result,x.sa);
  337. if (x.smld^.dtype=listmain)or(x.smtd^.dtype=treemain)
  338. then x.smtd^.name:=temp_res;
  339. end;
  340. DT:=complex_desk;
  341. end;
  342. eof_desk:begin end; { returns to the upper level }
  343. {$IFDEF xSUN}
  344. OTHERWISE
  345. {$ELSE}
  346. ELSE
  347. {$ENDIF}
  348. begin ER_LEX(9);goto 99; end { impossible value }
  349. end; { case }
  350. read_item:=result;
  351. 99: end; { Procedure Read_item }
  352. Procedure READLINE;
  353. {***************************}
  354. { sets new values for "s" and "i" global variables }
  355. label 99;
  356. begin
  357. i:=1; { In any case, so; only here it is initialized.
  358. it is column number.
  359. Variable "s" is string only for speed purposes;
  360. It plays exactly as Packed array of char,
  361. never used as whole and the Length byte is never used }
  362. Linenumber:=linenumber+1;
  363. line_byte_number:=line_byte_number+old_line_length;
  364. case read_mode of
  365. 1:
  366. begin
  367. if eof(inpfile) then begin s[1]:=endfile_code;close(inpfile);end
  368. else
  369. begin readln(inpfile,s);s[length(s)+1]:=new_line_code;
  370. old_line_length:=length(s);
  371. end;
  372. end;
  373. 2:
  374. begin
  375. if PTR1.nel=0 then begin s[1]:=endfile_code;goto 99;end;
  376. if PTR1.cel=0
  377. then begin
  378. s[1]:=new_line_code;
  379. old_line_length:=0;
  380. end
  381. else begin
  382. Pointr(PTR1.cel,X.sa);
  383. with x.sad^ do begin
  384. if (dtype=atom)or (dtype=idatom)or
  385. (dtype=fatom)or (dtype=tatom)or (dtype=keyword)
  386. then begin
  387. pointa(name,bl801,k);
  388. for kk:=1 to k do s[kk]:=bl801[kk];
  389. old_line_length:=k;
  390. s[k+1]:=new_line_code;
  391. end
  392. else
  393. begin
  394. s[1]:=new_line_code; { other objects are ignored }
  395. old_line_length:=0;
  396. end
  397. end; { with }
  398. end; { <>0 }
  399. NEXT(PTR1);
  400. end; {=2}
  401. 3:
  402. begin
  403. {$IFDEF RAMSCAN}
  404. k:=0;
  405. repeat c1:=char(Pointer(ABSPNT)^);
  406. write(':',ord(c1));
  407. inc{1}(longint(ABSPNT));
  408. inc{1}(k);
  409. s[k]:=c1;
  410. until (c1=new_line_code)or(k=126);
  411. if (k=126) then
  412. begin
  413. writeln('SCANNER DIRECT ACCESS WARNING !');
  414. s[127]:=new_line_code;
  415. end;
  416. old_line_length:=k;
  417. {$ENDIF}
  418. end;
  419. 4: begin
  420. {$IFDEF WIN}
  421. (* reads by-byte from global memory stream *)
  422. s:='';
  423. k:=0;
  424. while true do begin
  425. byte(c1):=SM^.readbyte;
  426. if c1=#13 then begin (* eoln symbol reached *)
  427. old_line_length:=k;
  428. (* this variable must refer to last symbol before eoln *)
  429. s[k+1]:=new_line_code;Exit;end;
  430. if c1=#26 then begin (* end of file reached *)
  431. old_line_length:=k;
  432. inc(k);
  433. s[k]:=endfile_code;
  434. SM^.Close;Dispose(SM,Done);Exit;end;
  435. if c1<>#10 then
  436. begin
  437. Inc(k);s[k]:=c1;inc(byte(s[0])); (* adds one character to string *)
  438. end;
  439. end;
  440. {$ENDIF}
  441. end;
  442. end; (* case *)
  443. 99:;
  444. end;
  445. Procedure PutAtom(j:integer);
  446. {***********************}
  447. begin
  448. PutIt(atom,j);
  449. end;
  450. Procedure PutIt(dd:descriptortype;j:integer);
  451. {***********************}
  452. begin
  453. if j>80 then begin DT:=Keyword;ER_LEX(10);j:=80; end else DT:=dd;
  454. putatm(s[i],j,AADR);
  455. saved_coord:=Getcoord;
  456. Tokennumber:=Tokennumber+1;
  457. end;
  458. Procedure PutIdent(j:integer);
  459. {***********************}
  460. begin
  461. PutIt(idatom,j);
  462. end;
  463. Procedure PutFloat(j:integer;digits_before_dot,digits_after_dot:integer);
  464. {***********************}
  465. var REA_VAL:real; ii:integer;
  466. AR:array[1..sizeof(real)+2]of char;
  467. begin
  468. (* Val2(Copy(s,i,j),REA_VAL,ii ignored ); *)
  469. system.Val(Copy(s,i,j),REA_VAL,ii);
  470. if ii<>0 then
  471. begin
  472. if j>80 then j:=80;
  473. DT:=keyword; (* WRONG REAL CONSTANT *)
  474. putatm(s[i],j,aadr);
  475. end
  476. else
  477. begin
  478. ii:=sizeof(real)+2;
  479. for j:=1 to ii-2 do
  480. AR[j]:=REAL_CHAR(REA_VAL)[j];
  481. AR[ii-1]:=chr(digits_before_dot);
  482. AR[ii] :=chr(digits_after_dot);
  483. putatm(AR[1],ii,AADR);
  484. DT:=fatom;
  485. end;
  486. (* writeln(' BEF, AFT =',digits_before_dot,' ',digits_after_dot); *)
  487. saved_coord:=Getcoord;
  488. inc{1}(Tokennumber);
  489. end;
  490. Procedure PutNumber;
  491. {***********************}
  492. begin
  493. DT:=number;
  494. saved_coord:=Getcoord;
  495. inc{1}(Tokennumber);
  496. end;
  497. Procedure PutStr;
  498. {***********************}
  499. begin
  500. if str_constlen>80 then
  501. begin
  502. str_constlen:=80;
  503. DT:=keyword; (* TOO LONG STRING CONSTANT *)
  504. end
  505. else
  506. DT:=TATOM;
  507. putatm(Str_const[1],Str_constlen, AADR);
  508. in_string:=false;
  509. Tokennumber:=Tokennumber+1;
  510. end;
  511. Procedure PutStr2;
  512. {***********************}
  513. begin
  514. if str_constlen>80 then str_constlen:=80;
  515. putatm(Str_const[1],Str_constlen, AADR);
  516. DT:=keyword;
  517. in_string:=false;
  518. Tokennumber:=Tokennumber+1;
  519. end;
  520. { this procedure used only for Modula2 or C-style string constants like 'x', -
  521. to show difference between 'x' and "x".
  522. Access via #_KEYWORD built_in rule is possible.
  523. When input use 'm+p-' !
  524. When output such tokens you should write
  525. IF #_KEYWORD($X) -> OUT <] @ '"' $X '"' ELSIF T-> OUT <] $X FI;
  526. }
  527. Procedure Scaner
  528. {*****************************************}
  529. (mode_parm:integer;
  530. {1=from file,2=list of strings,3=absulute address}
  531. filename:string80;
  532. options_str:string80;
  533. var rez:a; { result; set to NULL if input is absent }
  534. var erlist_parm:a; { error number list; set to NULL if no errors }
  535. strlist:a; { list of atoms }
  536. segm,ofs:longint); { parts of absolute address }
  537. LABEL 1,99;
  538. {INNER FUNCTION}
  539. Function Setop(c:char):boolean;
  540. begin
  541. Setop:=false;
  542. {$IFDEF xSUN}
  543. k:=Index(options_str,c);
  544. {$ELSE}
  545. k:=Pos(c,options_str);
  546. {$ENDIF}
  547. if k<>0 then
  548. if options_str[k+1]<>'-' then Setop:=true;
  549. end;
  550. begin
  551. read_mode:=mode_parm ; { save for global use }
  552. rez:=NULL;
  553. erlist_parm:=NULL;
  554. ERRLIST { global }:=NULL;
  555. { INITIALIZES ALL OPTIONS }
  556. { DEFAULTS }
  557. options_str:=options_str+'D-C-P+p+m-U+S+O+s-t-L-A+R+Y-B-N-';
  558. { to every option su,me default value should be given,
  559. otherwise the flag remains uninitialized }
  560. {ERRORS}
  561. screen_errors :=Setop('S');
  562. collect_errors:=Setop('O');
  563. {COMMENTS}
  564. ada_comment :=Setop('D');
  565. c_comment :=Setop('C');
  566. pascal_comment:=Setop('P');
  567. {STRING CONSTANTS}
  568. pascal_string :=Setop('p');
  569. modula_string :=Setop('m');
  570. to_uppercase :=Setop('U');
  571. {COORDINATE}
  572. string_coord :=Setop('s');
  573. token_coord :=Setop('t');
  574. row80_coord :=Setop('R');
  575. byte_coord :=Setop('Y');
  576. mark_byte_coord:=Setop('B');
  577. mark_only_coord:=Setop('N');
  578. {LANGUAGE_SPECIFIC LEXICS}
  579. c_lexics :=Setop('L');
  580. pascal_lexics :=Setop('A');
  581. { INITIALIZES LANGUAGE-SPECIFIC SETTINGS }
  582. SETLEXICS;
  583. { INITIALIZES "SESSION" FLAGS (alf order)}
  584. coord_mark:=0;
  585. in_comment:=false;
  586. in_string :=false;
  587. is_2quote :=false;
  588. last_mark_byte_number:=0;
  589. line_byte_number:=0;
  590. linenumber:=0;
  591. old_line_length :=0;
  592. str_constlen:=0;
  593. tokennumber:=0;
  594. { INITIALIZES PHYSICAL LEVEL READING }
  595. case read_mode of
  596. 1: begin { READ FROM FILE }
  597. if not existfile(filename)then begin Rez:=0;goto 1;end;
  598. {$IFDEF xSUN}
  599. Reset(inpfile,filename);
  600. {$ELSE}
  601. Assign(inpfile,filename);
  602. Reset(inpfile);
  603. {$ENDIF}
  604. readline; { reads first line of file }
  605. end;
  606. 2:
  607. begin { READ FROM LIST }
  608. if strlist=NULL then begin Rez:=0; goto 99; end;
  609. First(strlist,PTR1); { sets global list-pointer PTR1 }
  610. if (PTR1.ptrtype<>ptrlist) or
  611. (PTR1.nel=0) then begin Rez:=0; goto 99; end;
  612. readline; { reads line from current list-pointer position }
  613. end;
  614. 3:
  615. begin { READ FROM MS-DOS RAM MEMORY }
  616. {$IFDEF RAMSCAN}
  617. { Normalizing memory address }
  618. { Is it necessary for Windows model ? }
  619. { segm:=segm+ofs div 16;
  620. ofs:=ofs mod 16; }
  621. ABSPNT:=system.Ptr(segm,ofs); { This place is DOS-dependent !!! }
  622. if char (ABSPNT^) <> new_line_code
  623. then begin Rez:=0; goto 99; end;
  624. ABSPNT:=Pointer(longint(ABSPNT)+1);
  625. readline;
  626. {$ENDIF}
  627. end;
  628. 4: begin
  629. {$IFDEF WIN}
  630. New(SM,Init);
  631. SM^.open(segm);
  632. if (SM^.GETSIZE>128000)or(SM^.GETSIZE<0) THEN
  633. begin
  634. MESSAGEBOX(0,'Wrong handle to LDT stream',nil,16);
  635. rez:=0; goto 99; end
  636. else if (SM^.GETSIZE=0) then
  637. begin
  638. MESSAGEBOX(0,'Empty LDT stream',nil,16);
  639. rez:=0; goto 99; end
  640. else
  641. begin
  642. readline;
  643. end;
  644. {$ENDIF}
  645. end;
  646. end; (* case *)
  647. READ_FILE(REZ); { Main call ... }
  648. erlist_parm:=ERRLIST {global} ;
  649. 1:;99:;
  650. end;{ procedure Scaner }
  651. Procedure SETLEXICS;
  652. {***********************}
  653. var j:integer;
  654. begin
  655. if pascal_lexics then begin { changes in standard, necessary for Pascal}
  656. as['{']:=is_special;
  657. as['#']:=is_special;
  658. as['$']:=is_special;
  659. as['%']:=is_special;
  660. as['''']:=is_special;
  661. as['(']:=is_special;
  662. two_char_symbols[1]:=':=';
  663. two_char_symbols[2]:='<=';
  664. two_char_symbols[3]:='>=';
  665. two_char_symbols[4]:='**';
  666. two_char_symbols[5]:='..';
  667. two_char_symbols[6]:='<>';
  668. two_char_symbols_num:=6;
  669. set_of_second_of_two:=['=','*','.','>'];
  670. for j:=1 to two_char_symbols_num do
  671. as[two_char_symbols[j][1]]:=is_first_of_two;
  672. if modula_string then
  673. begin
  674. as['"']:=is_special;
  675. as['{']:=is_printable;
  676. end
  677. end
  678. else
  679. if c_lexics then begin
  680. as['_']:=is_letter;
  681. as['$']:=is_letter;
  682. two_char_symbols[1]:='->';
  683. two_char_symbols[2]:='++';
  684. two_char_symbols[3]:='--';
  685. two_char_symbols[4]:='>>';
  686. two_char_symbols[5]:='<<';
  687. two_char_symbols[6]:='==';
  688. two_char_symbols[7]:='+=';
  689. two_char_symbols[8]:='*=';
  690. two_char_symbols[9]:='-=';
  691. two_char_symbols[10]:='/=';
  692. two_char_symbols[11]:='%=';
  693. two_char_symbols[12]:='&=';
  694. two_char_symbols[13]:='^=';
  695. two_char_symbols[14]:='|=';
  696. two_char_symbols[15]:='!=';
  697. two_char_symbols_num:=15;
  698. set_of_second_of_two:=['>','+','-','<','='];
  699. for j:=1 to two_char_symbols_num do
  700. as[two_char_symbols[j][1]]:=is_first_of_two;
  701. as['<']:=is_special; { used to process <<= }
  702. as['>']:=is_special; { used to process >>= }
  703. as['/']:=is_special; { used to process /* }
  704. { otherwise isa:=is_first_of_two
  705. is assigned ! }
  706. as['''']:=is_special;
  707. as['"']:=is_special;
  708. end;
  709. end;
  710. Procedure StrAdd(c:char);
  711. {***********************}
  712. begin
  713. inc{1}(Str_constlen);
  714. if Str_constlen<=80 then Str_const[Str_constlen]:=c;
  715. end;
  716. Procedure StrBegin;
  717. {******************}
  718. begin
  719. saved_coord:=GetCoord;
  720. { It will be used when PutStr works and TOKEN EXITs - in READ_ITEM}
  721. in_string:=true;
  722. Str_constlen:=0;
  723. end;
  724. Procedure Token;
  725. {********************}
  726. label 1,99;
  727. var J,i_saved:integer; { positions }
  728. var digits_before_dot,digits_after_dot:integer;
  729. begin
  730. { at beginning time
  731. "i" - is already set to character in string "s";
  732. array "as" is already initialized;
  733. coordinate mode "coord_mode" is already known;
  734. }
  735. with b123 do begin { variant record ,b1=b2[1]=b3[1]; b2[2]=b3[2] }
  736. 1: { we return to this label if token is not ready still }
  737. b1:=s[i];
  738. isa:=as[b1]; { type of this character }
  739. if isa=is_control then begin {1}
  740. if b1=new_line_code
  741. then
  742. begin
  743. Readline; { skips to next line, sets new "s" and "i" }
  744. if in_string then begin ER_LEX(11); PutStr2; goto 99; end;
  745. { ERROR= end of line appears in string constant }
  746. goto 1;
  747. end
  748. else
  749. if b1=endfile_code
  750. then
  751. begin
  752. if in_comment then ER_LEX(12);
  753. { ERROR = end of file appears in comment }
  754. DT:=eof_desk;
  755. goto 99;
  756. end
  757. else
  758. { others are control characters; }
  759. { they set "DT" field and then form Rigal list/tree structure }
  760. begin{2}
  761. if in_comment then begin ER_LEX(13); in_comment:=false; end;
  762. { ERROR = control char in comment }
  763. if in_string then begin ER_LEX(14); PutStr2; goto 99;
  764. { will take control character next time }
  765. end;
  766. { ERROR = control char in string }
  767. DT:=Cont_char_to_dt(b1);
  768. I:=I+1;
  769. If (DT=set_coord)and(as[s[i]]=is_digit)
  770. { this control character sets coordinate to value given in input }
  771. then begin
  772. Coord_mark:=TAKE_DIGITS(J);
  773. Last_mark_byte_number:=line_byte_number+i;
  774. I:=I+J;
  775. goto 1; { DOES NOT RETURNS ! }
  776. end;
  777. goto 99;
  778. end; {2}
  779. {NEVER HERE}
  780. end; {1}
  781. { all the following executes AFTER check of is_control }
  782. {b3[1]:=s[i];} { this character }
  783. b3[2]:=s[i+1]; { next }
  784. b3[3]:=s[i+2]; { next }
  785. if in_comment { CHECK FOR END OF COMMENT }
  786. then begin {1}
  787. { we are in comment;
  788. here only comments that have some special end mark are processed }
  789. if pascal_comment then begin {2}
  790. if b1='}' then begin inc{3}(i); in_comment:=false; goto 1;end;
  791. if b2='*)' then begin inc{4}(i,2); in_comment:=false; goto 1; end;
  792. end {2}
  793. else
  794. if c_comment then begin {2}
  795. if b2='*/' then begin inc{4}(i,2); in_comment:=false; goto 1;end;
  796. end {2}
  797. ;
  798. inc{3}(i);
  799. goto 1;
  800. end;{1}
  801. if in_string
  802. { CHECK FOR END OF STRING or SOMETHING SPECIAL IN STRING }
  803. then begin {1}
  804. if pascal_string then begin {2}
  805. if b1='''' then begin {3}
  806. if b2[2]='''' then begin StrAdd('''');
  807. inc{4}(i,2);
  808. goto 1;end
  809. { this allow to save '''' as '' }
  810. else begin Putstr;inc{3}(i);goto 99;end;
  811. end {3}
  812. else begin {3}
  813. StrAdd(b1);
  814. inc{3}(i);
  815. goto 1;
  816. end {3}
  817. end; {2}
  818. if modula_string then begin {2}
  819. if is_2quote and (b1='"') then
  820. begin
  821. if b2[2]='"' then begin StrAdd('"');Inc{4}(i,2);goto 1;end
  822. else begin Putstr;inc{3}(i);goto 99;end;
  823. end;
  824. if not(is_2quote) and (b1='''') then
  825. begin Putstr2;inc{3}(i);goto 99;end
  826. else begin {3}
  827. if b1='\' then
  828. begin
  829. StrAdd(b1);
  830. StrAdd(b2[2]);
  831. { this allows to save \? as ? even if \" appears}
  832. inc{4}(i,2);
  833. goto 1;
  834. end;
  835. StrAdd(b1);
  836. inc{3}(i);
  837. goto 1;
  838. end; {3}
  839. end {2}
  840. end ; {1}
  841. { all the following executes AFTER check for in_string & in_comment }
  842. if isa=is_special then begin{1}
  843. if pascal_comment then begin{2}
  844. if (b2='(*')
  845. then begin in_comment:=true;inc{4}(i,2);goto 1;end;
  846. if (b1='{')and(b2[2]<>'$')
  847. then begin in_comment:=true;inc{3}(i) ;goto 1;end;
  848. end{2}
  849. else
  850. if c_comment then begin{2}
  851. if b2='/*' then begin in_comment:=true;inc{4}(i,2);goto 1;end;
  852. end {2}
  853. else
  854. if ada_comment then begin {2}
  855. if b2='--' then begin Readline;goto 1; end;
  856. end {2}
  857. ;
  858. if pascal_string then begin {2}
  859. if b1='''' then begin StrBegin;is_2quote:=false;inc{3}(i);goto 1;end;
  860. end {2}
  861. else
  862. if modula_string then begin {2}
  863. if b1='''' then begin StrBegin;is_2quote:=false;inc{3}(i);goto 1;end;
  864. if b1='"' then begin StrBegin;is_2quote:=true;inc{3}(i);goto 1;end;
  865. end {2}
  866. ;
  867. if pascal_lexics then begin {2}
  868. { SPECIALLY TAKES TURBO PASCAL DIRECTIVE-COMMENTS }
  869. if (b2='{$') then begin {3}
  870. j:=0;
  871. repeat inc{3}(j);
  872. until (s[i+j]='}')or(as[s[i+j]]=is_control);
  873. if s[i+j]='}' then inc{3}(j);
  874. PutAtom(j);
  875. inc{4}(i,j);
  876. goto 99;
  877. end; {3}
  878. { ADDITIONAL SYMBOLS }
  879. if (b1='#')or(b1='$')or(b1='%')
  880. then begin {3}
  881. inc{3}(i);
  882. J:=TAKE_LETTERS; { starts from i-th position }
  883. i:=i-1;
  884. PutAtom(J+1); { takes token from i-th position }
  885. inc{4}(i,j+1);
  886. goto 99;
  887. end; {3}
  888. end{2}
  889. else
  890. if c_lexics then begin {2} { SYMBOLS= > < }
  891. { SPECIAL CASES FOR C LANGUAGE }
  892. if (b3='<<=')or(b3='>>=') then begin
  893. PutAtom(3); inc{4}(i,3); goto 99;
  894. end;
  895. isa:=is_first_of_two;
  896. { !! in C case <<, >>, >=, <= will be tested further
  897. in TWO_char_symbols section, hence we go to there
  898. using assignment to "ISA" }
  899. end {2}
  900. end; {1}
  901. if isa=is_space then begin inc{3}(i); goto 1;end;
  902. if isa=is_letter then begin
  903. J:=TAKE_LETTERS;
  904. PutIdent(J);
  905. I:=I+J;
  906. goto 99;
  907. end;
  908. if isa=is_digit then begin {1}
  909. if c_lexics then begin {2}
  910. { ADDITIONAL SYMBOLS; HERE hex and octal numbers are saved as
  911. normal ATOMs }
  912. if (b1='0')
  913. then begin {3}
  914. inc{3}(i);
  915. J:=TAKE_LETTERS; { starts from i-th position }
  916. i:=i-1;
  917. PutAtom(J+1); { takes token from i-th position }
  918. inc{4}(i,j+1);
  919. goto 99;
  920. end; {3}
  921. end; {2}
  922. i_saved:=i; { remember starting position }
  923. AADR:=TAKE_DIGITS(J);
  924. digits_before_dot:=j;
  925. if (j<10)and
  926. ( ((s[i+j]='.')and(s[i+j+1]='.'))
  927. or
  928. (not(s[i+j]in['e','E','.'])) )
  929. then begin PutNumber;inc{4}(i,j);goto 99;end;
  930. inc{4}(i,j);
  931. if s[i]='.' then begin
  932. inc{3}(i);
  933. AADR:=TAKE_DIGITS(J);
  934. digits_after_dot:=j;
  935. inc{4}(i,j);
  936. end;
  937. if s[i] in ['e','E'] then
  938. begin
  939. digits_before_dot:=0;
  940. digits_after_dot:=0;
  941. inc{3}(i);
  942. if s[i] in ['+','-'] then inc{3}(i);
  943. AADR:=TAKE_DIGITS(J);
  944. inc{4}(i,j);
  945. end;
  946. J:=i-i_saved;
  947. i:=i_saved; { to set "i" to starting position }
  948. PutFloat(J,digits_before_dot,digits_after_dot);
  949. inc{4}(i,j);
  950. goto 99;
  951. end;{1}
  952. if isa=is_first_of_two then begin {1}
  953. if b2[2] in set_of_second_of_two then
  954. for j:=1 to two_char_symbols_num do
  955. if b2=two_char_symbols[j] then begin
  956. PutAtom(2);I:=I+2;goto 99;
  957. end
  958. end;{1}
  959. PutAtom(1);inc{3}(i);
  960. end; { with}
  961. 99:;
  962. end; { Procedure }
  963. Function TAKE_LETTERS:integer;
  964. {**************************************}
  965. label 99;
  966. { Reads only letters, digits and underscores.
  967. returns number of characters read }
  968. var JJ:integer; c:char;
  969. begin
  970. JJ:=0;
  971. while true do begin
  972. c:=s[i+jj];
  973. isa:=as[c];
  974. if (isa=is_letter)or(isa=is_digit)or(isa=is_underscore)
  975. then begin
  976. if to_uppercase then s[i+jj]:=upcase_tab[c];
  977. inc{3}(jj)
  978. end
  979. else begin
  980. TAKE_LETTERS:=jj;goto 99;
  981. end;
  982. end;
  983. 99:;
  984. end;
  985. Function TAKE_DIGITS(var jj:integer):longint;
  986. {************************************************}
  987. label 99;
  988. var summator:longint; c:char;
  989. begin
  990. JJ:=0; summator:=0;
  991. while true do begin
  992. c:=s[i+jj];
  993. if as[c]=is_digit then
  994. begin summator:=summator*10+ord(c)-ord('0');inc{3}(jj);end
  995. else begin TAKE_DIGITS:=summator;goto 99;end;
  996. end;
  997. 99:;
  998. end;
  999. (*begin*)
  1000. { PRESS F8 when debugging ! }
  1001. (*INITIALIZE_SCAN_VARIABLES;*)
  1002. end.