PageRenderTime 98ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/macros/cobol2v.vdm

https://bitbucket.org/chriz/z_vedit
Unknown | 2726 lines | 2649 code | 77 blank | 0 comment | 0 complexity | 701ea5b424e9118f22a40753892e63f1 MD5 | raw file
  1. // COBOL2V.VDM - Process COBOL copybook, converting to Greenview's
  2. // "code colbeg,colend" format.
  3. //
  4. // Written by: Thomas C. Burt, Greenview Data, Inc.
  5. // Last change: 07/26/2007
  6. //
  7. // Can now (10/31/2003) handle UniSys streaming nibbles that
  8. // ignore byte boundaries; types 'm', 'mh' and 'mx'.
  9. //
  10. // Will also now optionally treat "COMP" as Packed-No-Zone.
  11. //
  12. // Requires: VEDIT PLUS 6.11.2E dated 11-05-2003 or later for NIBBLES or
  13. // VEDIT PLUS 6.03 dated 06-01-2002 or later, otherwise.
  14. //
  15. // Can be run stand-alone or as a submacro to EBCDIC-n.VDM.
  16. //
  17. // Usage (stand alone):
  18. //
  19. // vpw [-y] -x COBOL2V copybook.cbk [-a layout.lay] [-u options]
  20. //
  21. // -y causes COBOL2V.VDM to exit to DOS when running in
  22. // stand-alone-mode, saving all files. Otherwise, the
  23. // newly generated .lay file is displayed in visual mode.
  24. //
  25. // -a changes the destination filename to something other
  26. // than the source filename.
  27. //
  28. // -u options
  29. //
  30. // DBASE uses ".dbf" as the output extent for filenames
  31. // in the .LAY output file;
  32. // generates "// col (INDEX)" at the end of each
  33. // record and extracted data section ("out" or "rb");
  34. // generates a cross reference .XRF file. E.g.,
  35. //
  36. // "vpw -x cobol2v cobol.cbk -a gv.lay -u DBASE"
  37. //
  38. // produces both "gv.lay" and "gv.xrf".
  39. //
  40. // SQL Generates ..._SQL_CRE.IMP file of SQL types & lengths.
  41. //
  42. // DOS (default): emit <cr><lf> at the end of each
  43. // output line. Uses ".asc" as the output extent.
  44. //
  45. // UNIX: emit <lf> at the end of each output line.
  46. //
  47. // MAC: emit <cr> at the end of each output line.
  48. //
  49. // cc=col_num to set starting column for comment field.
  50. //
  51. // comp=level for default "COMP." level (normally 4 for
  52. // Big Endian (IBM) binary).
  53. //
  54. // NORELAY - don't run RELAY.VDM even in "stand-alone" mode.
  55. //
  56. // ISHORT - Insert short field names into comment section past
  57. // "col" when DBASE is operative.
  58. //
  59. // NAMES - Generate .nam file with COBOL field names.
  60. // Names are quoted and comma delimited.
  61. // A newline is generated at the start of each record;
  62. // i.e., at each "c=0" specification in the source file.
  63. // To be properly included during data conversion by
  64. // the EBCDIC-x conversion package, each line must later
  65. // be extracted into its own separate ".nam" file.
  66. //
  67. // NIBBLES - Packing BCD digits across byte boundaries.
  68. // When used, COMP fields are considered to be
  69. // nibbles (usually BCD, with or without a sign
  70. // nibble), packed streamwise from the left.
  71. //
  72. // PNZ - all "COMP" fields are treated as Packed-No-Zone
  73. // instead of being treated as binary data.
  74. // Archaic; use "comp=6" instead.
  75. //
  76. // In stand alone mode, the entire active file is presumed
  77. // to be COBOL copybook statements. The only extra statements
  78. // are blank lines, VEDIT comments, "c=0[,R]" and, perhaps,
  79. // "p=" and "q=" lines.
  80. //
  81. // The "c=0[,R]" line is used to indicate the start of a new
  82. // record type; 'R' is a unique letter for identifying
  83. // the record type. It generates a 'tx "R.ext"' line and, for
  84. // "-u DBASE", is used in generating the cross reference
  85. // "short" field name.
  86. //
  87. // When being driven by EBCDIC-n.VDM, "p=" and "q=" brackets
  88. // are required around any copybook statements.
  89. //
  90. // Usage as a submacro to EBCDIC-n.VDM:
  91. // Set #64 = 0x200 to strip comments from the copybook.
  92. // = 0x202 to comment out the copybook.
  93. // (The copybook is always commented out when
  94. // run stand-alone).
  95. // Set #65 = base register. Registers (base+10 - base+18)
  96. // are used herein, saving/restoring user's
  97. // contents.
  98. //
  99. // When run as a submacro, the "p=" and "q=" brackets must
  100. // be used around each section of COBOL statements.
  101. //
  102. // Use "c=0[,R]" to indicate the start of a new record type. The 'R' will
  103. // be used to form a proto-filename: 'tx "R.ASC"', e.g.
  104. // The "c=0[,R]" line will be replaced by a proto record specification:
  105. // "t 1,0xff,0xF1 // Record type #1: EBCDIC '1' in col 1"
  106. // "l=reclen"
  107. //
  108. // Note: Comments out all REDEFINES clauses/paragraphs. The user will
  109. // probably need to edit the resulting output file or edit the
  110. // source file and rerun COBOL2V on the edited source file.
  111. //
  112. // Handles multiple, even nested, OCCURS DEPENDING ON clauses.
  113. //
  114. // Handles: [COMP[-n]] [S][9[9...][(n)]] [V 9[9...][(n)]] [COMP[-n]]
  115. // [COMP[-n]] [9[9...][(n)]] [V 9[9...][(n)]]- [COMP[-n]]
  116. // where n={1,2,3,4,6}
  117. // ={Float,Double,BCD,binary,PNZ}.
  118. // where BCD = Binary Coded Decimal = Packed Decimal
  119. // PNZ = Packed-No-Zone = signless BCD
  120. // X[X...][(n)], where 'n' = # bytes.
  121. // B[B...][(n)], "
  122. // C[C...][(n)], "
  123. // D[D...][(n)], "
  124. // F[F...][(n)], "
  125. // H[H...][(n)], "
  126. // Y[Y...][(n)], "
  127. //
  128. // 'B' is binary (including 1-byte binary).
  129. // 'C' is for a custom field.
  130. // 'D' deletes the field.
  131. // 'F' fills the field with spaces.
  132. // 'H' is hexadecimal.
  133. // 'Y' is DATE (for SQL).
  134. //
  135. // Note: 'B', 'C', 'D', 'F', 'H' and 'Y' are special Greenview only codes.
  136. // These codes must be edited into the COBOL copybook, replacing
  137. // ambiguous 'X' picture statements.
  138. //
  139. // Note: 'Y' is converted to 'e' for the .lay file but generates a DATE
  140. // field type and length for the SQL .imp file.
  141. //
  142. // Note: "COMP." is binary (Big Endian) unless the "-u comp=level" parameter is used.
  143. //
  144. // Note: When the "-u NIBBLES" parameter is used for UniSys' streaming nibbles,
  145. // COMP's are assumed to be BCD or PNZ with or without a leading sign nibble.
  146. //
  147. // Note: The archaic "-u PNZ" is still valid but the alternative "-u comp=6" is preferred.
  148. //
  149. // COMP-1 is floating point.
  150. // COMP-2 is double precision.
  151. // COMP-3 is packed decimal.
  152. // COMP-4 is IBM binary (Big Endian).
  153. // COMP-5 is HardWare ordered binary (NYI).
  154. // COMP-6 is Packed-No-Zone (PNZ).
  155. //
  156. // The COBOL specification for binary is PIC [S]9(n) COMP, where normal
  157. // values for 'n' are 4, 8 and 18 for 2-, 4- and 8-byte binaries.
  158. // This macro supports all binary sizes upto 8 bytes.
  159. // It generates ",=len;" where "len" = # digits for picture clauses
  160. // other than the defaults. It generates the "raw" option for
  161. // binaries whose picture clauses specify that values may be larger
  162. // than "all spaces".
  163. //
  164. // It outputs 'u' into the options field for unsigned numbers.
  165. //
  166. // Note: input field width for BCD pictures S9(n)v9... COMP-3 =
  167. // Int(( Total(9's) / 2 )) + 1
  168. //
  169. //////////////////////////////////////////////////////////////////////////
  170. // //
  171. // Cross Reference File //
  172. // //
  173. //////////////////////////////////////////////////////////////////////////
  174. //
  175. // When the "-u DBASE" input option is used in stand-alone mode,
  176. // a cross reference file will be generated consisting of
  177. // "r[s]n" "cobol-statement-name" pairs.
  178. //
  179. // 'r' is a letter denoting the record name as specified by the "c=0,r"
  180. // line or {A,B,C,...} if 'r' is not specified.
  181. //
  182. // 's' = {A,B,C,...} is a letter generated for records containing more than
  183. // 250 fields. Such records are automatically split into 250-field sections.
  184. // 'out "rs.DBF"' ... 'out' brackets are emitted into the .lay file.
  185. // The opening bracket will be moved forward if it would otherwise appear
  186. // in the middle of an "OCCURS" clause.
  187. //
  188. // 'n' is the field index, starting from one. It continues incrementing even
  189. // when records are automatically split into sections. It is reset by each
  190. // "c=0" line.
  191. //
  192. // Each line in the cross reference file consists of 12 spaces, the
  193. // automatically generated "short" name and the full COBOL copybook name
  194. // which starts in column 30.
  195. //
  196. // The filename will have the same name as the current .lay output filename
  197. // with extension ".xrf".
  198. //
  199. //////////////////////////////////////////////////////////////////////////////
  200. //
  201. // Text Marker Usage
  202. //
  203. // Marker(8)-> (moving) start of the COBOL block.
  204. // Marker(9)-> past end of the COBOL block.
  205. // Marker(7)
  206. // Marker(6)-> "." terminating current COBOL line.
  207. // Marker(5)-> BOL of current COBOL statement.
  208. //
  209. //////////////////////////////////////////////////////////////////////////////
  210. //
  211. // Numerical Register Usage
  212. //
  213. // Note: Preserves Numerical Registers 6-8, 64-66, 75,76, 90-92, 99 and 105
  214. // for EBCDIC-x.VDM.
  215. //
  216. // #1 For last usable column + 1 (Set to 73 in Main Processing Loop)
  217. // #2 COMP level (0=no,1-6,0xFF=default)
  218. // (1=Float,2=Double,3=BCD,4=IBM binary,5=HW dependent binary,6=PNZ)
  219. // Note: COMP-5 not yet implemented...
  220. // "COMP." defaults to "COMP-4." (Big Endian (IBM) binary)
  221. // #21 Flag/buffer-ID for cross reference output file
  222. // #22 Running-stand-alone flag
  223. // #23 Field counter
  224. // #24 Record counter
  225. // #25 Record Name (1 letter)
  226. // #26 Record size
  227. // #27 Details record counter (OCCURS DEPENDING ON)
  228. // #28 File type: {DOS,UNIX,MAC,DBASE}
  229. // #29 Starting column for comments
  230. // #30 NORELAY flag
  231. // #32 ISHORT flag to insert short names into comment field
  232. // #33 Level-2 flag (single record, no OCCURS DEPENDING ON)
  233. // #34 NAMES flag to generate COBOL field names in .nam file
  234. // #35 NIBBLES flag for streaming BCD across byte boundaries
  235. // #36 Record size augmentation in half-bytes when NIBBLES
  236. // #37 Default "COMP" level; normally "4" (binary).
  237. // #38 SQL output_flag/buffer_id.
  238. // #90 ID of register this macro is running in.
  239. // #92 current (copybook) edit buffer ID
  240. //
  241. //////////////////////////////////////////////////////////////////////////////
  242. //
  243. // Text register usage (caller's text registers pushed and popped).
  244. //
  245. // 10 Work register converting "+len" to "bc,ec" format at end.
  246. // 10-14 Regular expressions (OCCURS processing submacros).
  247. // 15 "Next_Peer_Field" locating submacro of OCCURS submacro.
  248. // 16 OCCURS processing submacro.
  249. // 17 REDEFINES processing (comment out the paragraph).
  250. //
  251. // Text registers not pushed and popped:
  252. // 0-2 Temporary
  253. // 55 Determine block markers Marker(8) and Marker(9); run RELAY.VDM
  254. // 56 .lay code generator (code +len [vn]) and cross referencer
  255. // 99 Life-indicating message register
  256. //
  257. //////////////////////////////////////////////////////////////////////////////
  258. //
  259. // Abbreviations:
  260. //
  261. // '^' is beginning of a line
  262. // 'v' is the edit position
  263. // '.' is anything
  264. // '01' is an example of a clause level
  265. //
  266. // BOS Beginning Of Statement: "^v...... 01 Clause_Name"
  267. // BOCL Beginning of clause level: "^....... v01"
  268. // EOCL End of clause level: "^....... 01v"
  269. // BOCN Beginning of clause name: "^....... 01 vClause_Name"
  270. // EOCN End of clause name: "^....... 01 Clause_Namev"
  271. //
  272. //////////////////////////////////////////////////////////////////////////////
  273. //
  274. // Initialization.
  275. //
  276. // if (wstat($)<0){wr($,5,bottom)};ws($);bs(1,attach);ws($);update() ?
  277. //
  278. // Just return if "p=,q=" brackets missing while being driven by EBCDIC-n.VDM.
  279. //
  280. if (#64&0x200) { // When running as a submacro...
  281. if (Search("|<p=",BEGIN+NOERR)==0){return}
  282. }
  283. Num_Push(6,8)
  284. Num_Push(64,66)
  285. Num_Push(75,76)
  286. Num_Push(90,92)
  287. Num_Push(99,99)
  288. Num_Push(105,105)
  289. if ((#64&0x200)==0) { // When running stand-alone...
  290. #65 = Reg_Free // Get base register
  291. } // Otherwise, #65 is already defined
  292. Reg_Push(#65+10,#65+18) // Save caller's text registers
  293. Config(U_AUTO_CFG,0)
  294. Config(F_AUTO_SAVE,0)
  295. Config(E_EXP_TAB,1,LOCAL) // Tabs complicate COBOL processing
  296. Config(E_RETAB_BK,0,LOCAL)
  297. Config(E_RETAB_FILL,0,LOCAL)
  298. Config(S_E_MORE,0) // Disable CRT scroll-lock
  299. #90 = Macro_Num
  300. //
  301. //////////////////////////////////////////////////////////////////////////////
  302. //
  303. // Setup submacros in T-Regs[15 - 17].
  304. //
  305. //
  306. // T-Reg[15] - NEXT_PEER_FIELD submacro.
  307. // Goto start of next statement whose level is less than or equal
  308. // to that in #0; goto Marker(9) if no such field.
  309. //
  310. // Enter: #0 = statement level.
  311. // #1 = Maximum usable data column.
  312. // Marker(9).
  313. //
  314. // Uses numreg[10] for search/replace options; usage is consistent
  315. // with that of the calling macro.
  316. //
  317. Reg_Set(#65+15,`
  318. #10 = COLSET+REGEXP+MAX+ADVANCE+NOERR
  319. repeat( all ) {
  320. if (Search_Block("\$+\@(#65+12)[0-9]",Cur_Pos,Marker(9),#10,1,#1-1)==0){
  321. GM(9) // I don't know why 71 instead of 72
  322. }
  323. if (Cur_Pos >= Marker(9)) {
  324. GM(9)
  325. break
  326. }
  327. char(-1)
  328. if (Num_Eval(SUPPRESS)<=#0){
  329. BOL
  330. break
  331. }
  332. Line(1,errbreak)
  333. }
  334. return
  335. `) // T-Reg[15] - NEXT_PEER_FIELD submacro
  336. //////////////////////////////////////////////////////////////////////////////
  337. //
  338. // T-Reg[16] - OCCURS processing submacro.
  339. // Process: OCCURS n TIMES [INDEXED BY...] clauses by duplication.
  340. // OCCURS [ m TO ] n [TIMES] DEPENDING ON x.
  341. //
  342. // Enter: #1 = Maximum usable data column
  343. // Marker(8)-> start of COBOL specs.
  344. // Marker(9)-> past end of COBOL specs.
  345. //
  346. // "OCCURS n [TIMES] [INDEXED BY ... ]."
  347. // Duplicate the paragraph 'n' times, appending '-m' (m=1,n) to names.
  348. // Comment out the "OCCURS" statement.
  349. //
  350. // "OCCURS ... DEPENDING ON x"
  351. // Generate 'rcx', 'rb' and 're' code lines for each occurrence.
  352. //
  353. //////////////////////////////////////////////////////////////////////////////
  354. //
  355. // Numreg usage in T-Reg[16] (caller's values saved by push/pop).
  356. //
  357. // 0 Paragraph level (T-Reg[15] also)
  358. // 2-7,12 Duplicating paragraphs
  359. // 3 OCCURS count
  360. // 9 Edit Buffer Number
  361. // 10 OPTIONS for search/replace (T-Reg[15] also)
  362. // 11 Work Buffer Number
  363. // 12 a.s.
  364. // 27 Index of current "DEPENDING ON" clause, from 0
  365. //
  366. //////////////////////////////////////////////////////////////////////////////
  367. //
  368. // Marker usage:
  369. //
  370. // Marker(1)-> BOS of "occurs ... depending on ...".
  371. // Marker(2)-> BOS defined in the "depending on" clause, if any.
  372. // Marker(3)-> BOS of "occurs" paragraph.
  373. // Marker(4)-> past " occurs ".
  374. // Marker(5)-> past statement terminating "."
  375. // Marker(6)-> one position ahead of the body (sub-clauses) to the <lf>
  376. // following Marker(5). (When such body exists; i.e., no
  377. // PIC clause preceding the OCCURS clause)
  378. // Marker(7)-> past "occurs" paragraph.
  379. // Marker(8)-> start of COBOL specs (entry).
  380. // Marker(9)-> past end of COBOL specs (entry).
  381. //
  382. //////////////////////////////////////////////////////////////////////////////
  383. //
  384. Reg_Set(#65+16,`
  385. Num_Push(0,12)
  386. #11 = Buf_Free(EXTRA) // Get ID of available work buffer
  387. GM(8) // Start at beginning of COBOL specs
  388. repeat( all ){
  389. //
  390. // Set Marker(4) past next " occurs ".
  391. //
  392. #10 = COLSET+REGEXP+MAX+ADVANCE+ERRBREAK
  393. sb("\@(#65+11).* occurs ",cp,Marker(9),#10,1,#1)
  394. Set_Marker(4,Cur_Pos)
  395. //
  396. // Set Marker(5) past statement terminating "."
  397. //
  398. bol
  399. #10 = COLSET+REGEXP+MAX+ADVANCE
  400. sb("\@(#65+11).*\.",curpos,Marker(9),#10,1,#1)
  401. Set_Marker(5,Cur_Pos)
  402. ///////////////////////////////////////////////////////////////////////////
  403. // //
  404. // DEPENDING ON //
  405. // //
  406. ///////////////////////////////////////////////////////////////////////////
  407. //
  408. // Set Marker(1)-> BOS
  409. // Generate 'rb ##27[ "Znr.DBF,Znr"]'<newline>.
  410. // Set Marker(2)-> BOS defined in "depending on" clause.
  411. // Generate "rc ##27"<newline>.
  412. // Go to end of paragraph by finding start of the next
  413. // paragraph at this or lower-numbered level. Don't include
  414. // commented lines at the end of the paragraph.
  415. // Generate "re"<newline>
  416. // Advance to next line.
  417. // Loop
  418. //
  419. GM(4)
  420. if (sb("|bdepending",cp,Marker(5),ADVANCE+NOERR)) {
  421. match("|W",ADVANCE)
  422. if (cn>#1||AtEOL){
  423. sb("^......\s+",cp,Marker(5),#10,1,#1)
  424. }
  425. if (match("on",ADVANCE)==0){
  426. match("|W",ADVANCE)
  427. if (cn>#1||AtEOL){
  428. sb("^......\s+",cp,Marker(5),#10,1,#1)
  429. }
  430. Set_Marker(0,Cur_Pos)
  431. //
  432. // Goto BOS - set Marker(4) and generate 'rb ##27[ "Znr.DBF",Znr]'<newline>.
  433. //
  434. gm(4)
  435. #10 = COLSET+REGEXP+MAX+REVERSE
  436. sb("\$+\@(#65+13)",Marker(8),cp,#10,1,#1)
  437. #27++
  438. Ins_Text('rb #')
  439. Num_Ins(#27,LEFT+NOCR)
  440. if (#21>0){
  441. Ins_Text(' "Z')
  442. Num_Ins(#27,LEFT+NOCR)
  443. Ins_Char(#25)
  444. Ins_Text('.dbf",Z')
  445. Num_Ins(#27,LEFT+NOCR)
  446. Ins_Char(#25)
  447. }
  448. Ins_Newline()
  449. Set_Marker(1,Cur_Pos)
  450. c(7)
  451. #0 = Num_Eval(SUPPRESS)
  452. //
  453. // Goto EOS and copy counter's name into T-Reg[0].
  454. //
  455. GM(0)
  456. s("|{|b,.}")
  457. rcb(0,Marker(0),Cur_Pos)
  458. //
  459. // Goto start of next clause and generate "re"<newline>
  460. //
  461. call(#65+15) // NEXT_PEER_FIELD
  462. Ins_Text("re")
  463. Ins_Newline()
  464. //
  465. // Find the counter's definition.
  466. //
  467. GM(8)
  468. s("|b|@(0)|{|b,.}")
  469. //
  470. // Set Marker(2) and generate "rc ##27"<newline>.
  471. //
  472. BOL
  473. Ins_Text("rc #")
  474. Num_Ins(#27,LEFT)
  475. Set_Marker(2,Cur_Pos)
  476. GM(0)
  477. line(1,errbreak)
  478. continue
  479. }}
  480. ///////////////////////////////////////////////////////////////////////////
  481. // //
  482. // OCCURS n [TIMES]. //
  483. // //
  484. ///////////////////////////////////////////////////////////////////////////
  485. //
  486. // Set #3 = "dup" count.
  487. //
  488. gm(4)
  489. sb("|d",Cur_Pos,Marker(5),colset,7,#1)
  490. #3 = NumEval()
  491. //
  492. // Set #0 = paragraph level.
  493. //
  494. gm(4)
  495. #10 = COLSET+REGEXP+MAX+ADVANCE+REVERSE
  496. sb("\$+\@(#65+13)",Marker(8),cp,#10,1,#1)
  497. s(" ",reverse)
  498. #0 = Num_Eval(SUPPRESS)
  499. //
  500. // Set Marker(3)-> beginning of this line, the BOS.
  501. //
  502. Set_Marker(3,BOL_Pos)
  503. //
  504. // Handle case of single statement (with PIC clause) being duplicated.
  505. // Create subparagraph instance of the statement less the "occurs" clause.
  506. //
  507. GM(3)
  508. if (sb("|bPIC|[TURE]|W|F",Cur_Pos,Marker(5),ADVANCE+COLSET+NOERR,7,#1)) {
  509. //
  510. // Copy the statement into T-Reg[0] and advance to following line.
  511. //
  512. GM(5)
  513. Line(1)
  514. RCB(0,Marker(3),Cur_Pos)
  515. //
  516. // Move the statement into work buffer.
  517. //
  518. #9 = bn
  519. bs(#11)
  520. bof()
  521. dc(all)
  522. ri(0,BEGIN)
  523. //
  524. // Remove any comment lines.
  525. // Convert rest into simple string.
  526. //
  527. while (!At_EOF) {
  528. Del_Char(6)
  529. if (Match(" ")) {
  530. Del_Line(1)
  531. continue
  532. } else {
  533. EOL
  534. if ((#2 = Cur_Pos - BOL_Pos - 66) > 0 ) {
  535. Del_Char(-#2)
  536. }
  537. Line(1,ERRBREAK)
  538. }
  539. }
  540. Replace("|L"," ",ALL+BEGIN+NOERR)
  541. //
  542. // Delete the "OCCURS..." clause.
  543. //
  544. Search(" occurs ",BEGIN+ADVANCE)
  545. #2 = Cur_Pos - 8
  546. Search("|d|s")
  547. Char(1)
  548. If (Search(" TIMES|S",ADVANCE+NOERR)) {
  549. Char(-1)
  550. }
  551. if (Search(" INDEXED|WBY|W",ADVANCE+NOERR)) {
  552. Search("|{ ,.}")
  553. }
  554. Del_Block(#2,Cur_Pos)
  555. //
  556. // Increment the statement level by one.
  557. // (Since this statement has a PIC clause, it has no subparagraphs).
  558. //
  559. BOF
  560. Match("|W",ADVANCE)
  561. #2 = Num_Eval(SUPPRESS) + 1
  562. #4 = Chars_Matched
  563. #5 = Cur_Pos
  564. Del_Char(#4)
  565. Ins_Char(' ',COUNT,#4) // Additional indentation
  566. Num_Ins(#2,LEFT+NOCR)
  567. Set_Marker(0,Cur_Pos) // 1st marker set in this edit buffer
  568. #6 = Cur_Pos - #5 - #4
  569. If (#6<#4) {
  570. GP(#5+#4)
  571. Ins_Char('0',COUNT,#4-#6)
  572. }
  573. //
  574. // Remove excess spaces.
  575. // Better too tight than grossly expansive.
  576. //
  577. GM(0)
  578. Match("|W",ADVANCE)
  579. Replace("|W"," ",ALL+NOERR)
  580. //
  581. // Restore the string to COBOL format.
  582. //
  583. BOF
  584. Ins_Char(' ',COUNT,6)
  585. Replace("|w|>"," ",NOERR)
  586. Ins_Newline(1)
  587. Char(-Newline_Chars)
  588. if (Cur_Pos > #1-5) { // Need room for "-m", (m=1,999)
  589. Search(" PIC|[TURE] ",BEGIN)
  590. Char(1)
  591. Ins_Newline(1)
  592. Ins_Char(' ',COUNT,6+#5+#4+6)
  593. }
  594. BOF
  595. while (!At_EOF) {
  596. EOL
  597. #2 = Cur_Pos - BOL_Pos
  598. if (#2 < #1 ) {
  599. Ins_Char(' ',COUNT,#1 - #2)
  600. }
  601. Line(1,ERRBREAK)
  602. }
  603. //
  604. // Move the reformatted statement into T-Reg[0].
  605. // Switch back to the main edit buffer and insert it.
  606. //
  607. rcb(0,0,EOB_Pos,DELETE)
  608. bs(#9)
  609. Reg_Ins(0)
  610. }
  611. //
  612. // Set Marker(6) two positions ahead of the paragraph's body.
  613. // (Guaranteed now to have one).
  614. //
  615. gm(5)
  616. Line(1,errbreak)
  617. Set_Marker(6,Cur_Pos-2)
  618. //
  619. // Set Marker(7) to end of paragraph by finding start of the next
  620. // paragraph at this or lower-numbered level. Don't include commented
  621. // lines at the end of the paragraph.
  622. //
  623. call(#65+15) // NEXT_PEER_FIELD
  624. Set_Marker(7,Cur_Pos)
  625. #10 = REGEXP+MAX+NOERR
  626. repeat( all ) {
  627. line(-1)
  628. if (Match("^......[^\s]",#10)==0) {
  629. Set_Marker(7,Cur_Pos)
  630. } else {
  631. if (( Match("^......[\s]+",#10)==0) && Chars_Matched >= #1 ) {
  632. Set_Marker(7,Cur_Pos)
  633. } else {
  634. break
  635. }}
  636. }
  637. //
  638. // Move the paragraph body (Marker(6)+2,Marker(7)) to T-Reg[0].
  639. //
  640. RCB(0,Marker(6)+2,Marker(7),DELETE+NORESTORE)
  641. //
  642. // Strip out commented lines.
  643. //
  644. #9 = bn
  645. bs(#11)
  646. bof()
  647. dc(all)
  648. ri(0)
  649. #10 = BEGIN+ALL+REGEXP+MAX+NOERR
  650. rb("^......[^\s].*\N","",0,fsize,#10)
  651. //
  652. // Strip out level 88's (VALUE clauses).
  653. //
  654. bof
  655. #10 = REGEXP+MAX+NOERR
  656. while (sb("^......[\s]+88\s",cp,fsize,#10)) {
  657. #101 = BOL_Pos
  658. s(".") // Comments gone; hope no quoted '.'s
  659. l()
  660. db(#101,cp)
  661. }
  662. RCB(1,0,FSIZE)
  663. bq(OK)
  664. bs(#9)
  665. //
  666. // Insert it #3 times, appending "-m" to each field name, m=1,#3.
  667. // Note: Uses numeric registers 2-7,12.
  668. // Restores T-Reg[0] from T-Reg[1] at bottom of loop.
  669. //
  670. #4 = 1
  671. repeat( #3 ) {
  672. gm(7)
  673. #7 = Cur_Pos
  674. Reg_Ins(0,BEGIN)
  675. #10 = COLSET+REGEXP+MAX+ADVANCE+NOERR
  676. while(sb("\$+\@(#65+12)[0-9]",cp,Marker(7)-2,#10,1,#1-1)) { // BOCL
  677. char(-1)
  678. if (numeval(ADVANCE+SUPPRESS)==88){continue}
  679. match("[\s]+[^\s\t.]+",REGEXP+MAX+ADVANCE)
  680. if (Cur_Pos - BOL_POS >= #1){continue}
  681. #5 = #12 = Cur_Pos
  682. ic('-')
  683. num_ins(#4,left+nocr)
  684. #5 = #6 = #2 = Cur_Pos - #5
  685. if (Cur_Char == '.'){c}
  686. while( #5-- ) {
  687. if ( Cur_Char != ' ' ) {
  688. break
  689. }
  690. Del_Char()
  691. #6--
  692. }
  693. //
  694. // Restore space.
  695. // Check for more space at end of line.
  696. //
  697. if (Cur_Char != ' ') {
  698. Ins_Char(' ')
  699. #6++
  700. Goto_Col(#1+1+#6)
  701. while( #6-- ) {
  702. if ( Cur_Char(-1) != ' ' ) {
  703. Del_Block( Cur_Pos, EOL_Pos )
  704. if (cn<#1){
  705. break
  706. }
  707. Goto_Pos(#12)
  708. Del_Char(#2)
  709. break
  710. }
  711. Del_Char(-1)
  712. }
  713. }
  714. }
  715. if (#4 != 1) {
  716. Block_Fill(' ',#7,Marker(7)-2,COLSET,1,6)
  717. Del_Block(#7,Marker(7)-2,COLSET,#1+1,90)
  718. }
  719. //
  720. // Handle any DEPENDING ON var(n).
  721. // I.e., where "var" is defined within an OCCURS clause.
  722. //
  723. GP(#7)
  724. while(sb("\$+\@(#65+11).*DEPENDING",cp,Marker(7)-2,#10,1,#1-1)) {
  725. sb(" ON ",cp,Marker(7)-2,COLSET+ADVANCE+NOERR,7,#1-1)
  726. char(-1)
  727. sb(" |A",cp,Marker(7)-2,COLSET+ADVANCE,7,#1-1)
  728. #7 = cp - 1
  729. Search("|{ ,.}")
  730. Save_Pos()
  731. rcb(0,#7,cp)
  732. gm(8)
  733. if (sb("\$+\@(#65+11).*\@(0)\h28",cp,Marker(7)-2,#10,1,#1-1)){
  734. Restore_Pos()
  735. Ins_Char(0x28)
  736. ni(#4,LEFT+NOCR)
  737. Ins_Char(0x29)
  738. match(".",advance)
  739. if (cn>70){
  740. dl(1)
  741. in(1)
  742. gp(#7)
  743. in(1)
  744. ic(' ',count,20)
  745. }
  746. } else {
  747. Restore_Pos()
  748. }
  749. }
  750. //
  751. #4++
  752. Reg_Set(0,@1)
  753. }
  754. //
  755. // Comment out the "occurs" statement.
  756. //
  757. gm(3)
  758. Replace_Block("\@(#65+11)","*******",cp,Marker(5),REGEXP+ALL)
  759. //
  760. // Now go to the original paragraph body in case of nested "occurs".
  761. //
  762. GP(Marker(6)+2)
  763. } // (all)
  764. Num_Pop(0,12)
  765. `) // T-Reg[16] - OCCURS submacro
  766. //////////////////////////////////////////////////////////////////////////////
  767. //
  768. // T-Reg[17] - REDEFINES processing submacro.
  769. // Comment out all REDEFINES paragraphs with '.'.
  770. // Enter: Marker(8)-> start of COBOL statements.
  771. // Marker(9)-> past end.
  772. // #1 = Rightmost usable data column.
  773. //
  774. // Note: standard comment is '*' in column 7. Using '.' will identify
  775. // statements commented out by this macro.
  776. //
  777. //////////////////////////////////////////////////////////////////////////////
  778. //
  779. // Numreg usage:
  780. //
  781. // 0,2 Temporary
  782. // 9 - 16 Equivalent-compressed-data processing
  783. // 101 Search options
  784. //
  785. //////////////////////////////////////////////////////////////////////////////
  786. //
  787. // Marker usage:
  788. //
  789. // Marker(5)-> start of REDEFINES statement.
  790. // Marker(6)-> past " REDEFINES".
  791. // Marker(7)-> past REDEFINES block.
  792. //
  793. // Marker(3)-> start of original definition statement.
  794. // Marker(4)-> past end of original definition block.
  795. //
  796. Reg_Set(#65+17,`
  797. GM(8)
  798. repeat ( all ) {
  799. //
  800. // Set marker(6) past next " REDEFINES".
  801. //
  802. #101 = COLSET+REGEXP+MAX+ADVANCE+ERRBREAK
  803. sb("\@(#65+11).* REDEFINES ",Cur_Pos,Marker(9),#101,1,#1)
  804. Set_Marker(6,Cur_Pos)
  805. //
  806. // Set marker(5) to BOS.
  807. // Set #0 = level.
  808. //
  809. #101 = COLSET+REGEXP+MAX+ADVANCE+REVERSE
  810. sb("\$+\@(#65+13)",Marker(8),cp,#101,1,#1)
  811. s(" ",reverse)
  812. #0 = Num_Eval(SUPPRESS)
  813. BOL
  814. Set_Marker(5,Cur_Pos) // Start of "REDEFINES" line
  815. //
  816. // Set marker(7) to end of this paragraph by finding start
  817. // of the next peer or lower indexed statement.
  818. //
  819. line(1,noerr)
  820. call(#65+15) // NEXT_PEER_FIELD
  821. SM(7,Cur_Pos)
  822. //
  823. // Comment out each line in the marked section.
  824. //
  825. GM(5)
  826. Replace_Block(" ",".",Cur_Pos,Marker(7)-1,COLSET+NOERR+ALL,7,7)
  827. //
  828. GM(7)
  829. } // Commenting out REDFINES paragraphs.
  830. `) // T-Reg[17] - REDEFINES submacro
  831. //////////////////////////////////////////////////////////////////////////////
  832. //
  833. // T-Reg[55] - Determine block markers Marker(8) and Marker(9) vis a vis
  834. // p=,q=, and c=0[,R].
  835. // Set "l=reclen" for previous record type.
  836. // Generate record name tx R.asc or R.dbf,R if at c=0,R.
  837. // Generate prototype "t 1,0xFF,0xF1" line.
  838. //
  839. // Set Marker[8]-> start of COBOL block.
  840. // Set Marker[9]-> past COBOL block.
  841. // Delete any bounding "p=" and "q=" records.
  842. //
  843. //////////////////////////////////////////////////////////////////////////////
  844. Reg_Set(55,`
  845. GM(9)
  846. //
  847. // When running stand-alone:
  848. //
  849. if (#22) { // Stand alone...
  850. call("COBBEG") // Find/process start of COBOL block
  851. call("COBEND") // Find/process end of COBOL block
  852. return
  853. //
  854. // When running as a submacro to EBCDIC-n.VDM:
  855. //
  856. } else {
  857. Set_Marker(8,Cur_Pos)
  858. Search("|<|{p=,q=}",NOERR)
  859. if (Error_Match){
  860. EOF()
  861. Set_Marker(8,Cur_Pos) // Marker(8) at EOF
  862. Set_Marker(9,Cur_Pos) // Marker(9) at EOF
  863. return
  864. }
  865. //
  866. // Process p=[.].
  867. //
  868. if (Match_Item==1) {
  869. BOL()
  870. Del_Line(1) // Delete the "p=" line
  871. while(Match("|<c=")==0){
  872. Line(1,NOERR)
  873. }
  874. Set_Marker(8,Cur_Pos) // Marker(8) at beginning of block
  875. Search("|<|{c=,q=}",NOERR)
  876. if (Error_Match){
  877. Set_Marker(9,File_Size)
  878. Return
  879. }
  880. Set_Marker(9,Cur_Pos)
  881. if (Match_Item==2){
  882. Del_Line()
  883. }
  884. Return
  885. }
  886. //
  887. // Process q=
  888. //
  889. Del_Line(1)
  890. Set_Marker(9,Cur_Pos) // Marker(9) at end of block
  891. GM(8)
  892. While(Match("|<c=")==0){
  893. Line(1,NOERR)
  894. }
  895. Set_Marker(8,Cur_Pos)
  896. return
  897. } // end else running as submacro to EBCDIC-x.VDM
  898. // [55] main routine ends
  899. //
  900. // RECLEN - Create "l=reclen" lines for preceding record, if any.
  901. // Enter: #26 = length of preceding record less 'm' digits.
  902. // #36 = # 'm' digits and signs in record when NIBBLES.
  903. // Retrn: #26 = #36 = 0.
  904. //
  905. :RECLEN:
  906. Save_Pos()
  907. if (#26>0) {
  908. BOL()
  909. if ( Search("|<t ",REVERSE+NOERR)) {
  910. Line()
  911. Ins_Text("l=")
  912. Num_Ins(#26+#36/2+remainder,LEFT)
  913. }
  914. }
  915. #26 = #36 = 0
  916. Restore_Pos()
  917. return
  918. // RECLEN ends
  919. //
  920. // RECORD - Generate record extraction name and proto definition if at c=0,R:
  921. // 'tx "file_only.ASC"' normally or "R.DBF",R for DBASE and
  922. // "t 1,0xFF,0xF1 // Proto Record Type - EBCDIC 1 in column 1"
  923. // Append newline char(s) to any .nam file.
  924. // Enter: #23 = field counter.
  925. // #24 = record counter, from 0.
  926. // #27 = detail record counter.
  927. // #29 = Starting column for comments.
  928. // Marker[7]-> column index (from 0)
  929. // Retrn: #23 = 0.
  930. // #24 = (#23>0) ? #24++ : #24.
  931. // #25 = record name = 'A' + #24.
  932. // #27 = 0.
  933. //{
  934. :RECORD:
  935. #27 = 0
  936. if (#23!=0){ // Increment record counter
  937. #24++
  938. }
  939. #25 = #24 + 'A' // Record Name
  940. #23=0 // Field counter
  941. GM(7)
  942. Num_Eval(ADVANCE)
  943. Match("|W",ADVANCE)
  944. //
  945. // Generate 'tx "file_only.asc"', perhaps.
  946. //
  947. if (cc==','){
  948. c
  949. Match("|W",ADVANCE)
  950. if (Match("|A")==0){
  951. #25 = Cur_Char
  952. BOL()
  953. Ins_Text('tx "')
  954. if ( #21 ) {
  955. Ins_Char(#25)
  956. Ins_Text(".dbf")
  957. } else {
  958. rs(0,File_Only)
  959. Reg_Ins(0)
  960. Ins_Text(".asc")
  961. }
  962. Ins_Char('"')
  963. if ( #21 ) {
  964. Ins_Char(',')
  965. Ins_Char(#25)
  966. }
  967. Ins_Newline()
  968. }
  969. } else {
  970. BOL()
  971. }
  972. //
  973. // Generate prototypical record identifier:
  974. // "t 1,0xFF,0xF1 // comment"
  975. //
  976. Ins_Text("t 1,0xFF,0xF1")
  977. Ins_Indent(#29)
  978. Ins_Text("// Proto Record Type - EBCDIC 1 in column 1")
  979. Ins_Newline()
  980. Del_Line()
  981. //
  982. // Finish .nam line
  983. //
  984. Call(#90,"ENDNAME")
  985. return
  986. // RECORD ends}
  987. //
  988. // COBBEG - Return Marker(8) = CurPos at start of next COBOL block.
  989. // if "c=0[,R]", generate:
  990. // l=reclen // for previous record
  991. // t 1,0xff,0xf1 // for current record; preceded by
  992. // tx "R.ext"[,R] // if ",R" option; "ext" = {ASC,DBF}
  993. // Delete any bounding "p=" and "c=0" records.
  994. //{
  995. :COBBEG:
  996. //
  997. // Just return Marker(8) = CurPos when no blocking info.
  998. //
  999. Set_Marker(8,Cur_Pos)
  1000. if (!Search("|<|{p,q,c}=",NOERR)){
  1001. GM(8) // No, ensure CurPos unchanged
  1002. return // Just return Marker(8) = CurPos
  1003. }
  1004. //
  1005. // q=
  1006. //
  1007. if (mi==2){ // Can there be a valid "q=" at this point?
  1008. GM(8)
  1009. return
  1010. }
  1011. //
  1012. //
  1013. //
  1014. while (Match("|<|{p=,c=}",ADVANCE)==0){
  1015. //
  1016. // p=.
  1017. //
  1018. if (Match_Item==1){
  1019. BOL()
  1020. Del_Line(1) // Delete the "p=[.]" line
  1021. //
  1022. // c=0[,R]
  1023. //
  1024. } else {
  1025. Set_Marker(7,Cur_Pos) // Set marker(7) for RECORD()
  1026. call("RECLEN") // Set "l=reclen" for previous record
  1027. call("RECORD") // Generate "tx R.ext"[,R] and "t ..."
  1028. }
  1029. Set_Marker(8,Cur_Pos)
  1030. }
  1031. return
  1032. // COBBEG ends}
  1033. //
  1034. // COBEND - Set Marker(9) to end of current COBOL block.
  1035. //{
  1036. :COBEND:
  1037. GM(8)
  1038. Set_Marker(9,CurPos)
  1039. Search("|<|{p,q,c}=",NOERR) // p= or c=0 or q= ?
  1040. //
  1041. // If no block marking info, just return Marker(9) = File_Size.
  1042. //
  1043. if (Error_Match){
  1044. GM(8)
  1045. Set_Marker(9,File_Size)
  1046. return
  1047. }
  1048. //
  1049. // Otherwise, return Marker(9) at the next blocking indicator.
  1050. // Also, delete any "q=" line.
  1051. //
  1052. Set_Marker(9,Cur_Pos)
  1053. if (mi==2){
  1054. Del_Line()
  1055. }
  1056. return
  1057. // COBEND ends}
  1058. `) // T-Reg[55] - Block Marking Submacro with Marker(8) & Marker(9)
  1059. //////////////////////////////////////////////////////////////////////////////
  1060. //
  1061. // T-Reg[56] - Encoder - generate "code +size[,=len;] [u] [{v,.}n]".
  1062. // Call XREF to perhaps generate an entry in .xrf file.
  1063. // Call DOSQL to perhaps add name to _SQL_CRE.IMP file.
  1064. // Call REDOSQL to perhaps add type info to an entry in _SQL_CRE.IMP file.
  1065. // Enter short field name into comment section if -u ISHORT.
  1066. // Copy quoted-and-comma-delimited COBOL field name to .nam if -u NAMES.
  1067. // Enter: #1 = Maximum usable data column.
  1068. // #26 = record length, less any 'm' digits and signs.
  1069. // #28 = Output record type {0,1,2,3} for {DOS,UNIX,MAC,DBASE}
  1070. // #32 = ISHORT flag.
  1071. // #35 = NIBBLES flag.
  1072. // #36 = # 'm' digits and signs when NIBBLES.
  1073. // #37 = default "COMP" level.
  1074. // #38 = SQL output buffer id/flag
  1075. //
  1076. // Marker(8)-> start of COBOL statements.
  1077. // Marker(9)-> past end.
  1078. // Retrn: #26 and #36 updated.
  1079. // #81 = # digits before decimal point.
  1080. // Marker[5] -> start of statement.
  1081. // Marker[6] -> EOS past '.'
  1082. //
  1083. // Note: uses #2 - #9 internally; pushes and pops them.
  1084. // #2 = current COMP level (0=none,1-6,0xFF=default)
  1085. // #3 = # digits past decimal point
  1086. // #4 = signed # flag
  1087. // #5 = temporary
  1088. // #6 = # bytes in data field
  1089. // #7 = Adjusted COMP level (0,1-6,7) where '7' implies streaming nibbles
  1090. // #8 = # digits = #81 + #3.
  1091. // #9 = flag that '{v,.}[n]' encountered.
  1092. //
  1093. //////////////////////////////////////////////////////////////////////////////
  1094. Reg_Set(56,`
  1095. Num_Push(2,9) // Be safe
  1096. //
  1097. // Convert PACKED-DECIMAL's to COMP-3's.
  1098. //
  1099. Save_Pos()
  1100. while(replace(" PACKED-DECIMAL|[|w]."," COMP-3.",NOERR)){
  1101. Ins_Char(' ',count,chars_matched-8)
  1102. }
  1103. Restore_Pos()
  1104. //
  1105. // Convert BINARY's to COMP's.
  1106. //
  1107. Save_Pos()
  1108. BoF()
  1109. while(replace(" BINARY|[|w]."," COMP.",NOERR)){
  1110. Ins_Char(' ',count,chars_matched-6)
  1111. }
  1112. Restore_Pos()
  1113. //
  1114. // Convert PIC A's to PIC X's.
  1115. //
  1116. Save_Pos()
  1117. BoF()
  1118. while(replace(" PIC|[ture]|wA"," PIC X",NOERR)){
  1119. #2 = Chars_Matched
  1120. if (Match("A",ALL|ADVANCE)==0){
  1121. Del_Char(-Chars_Matched)
  1122. Ins_Char('X',COUNT,Chars_Matched)
  1123. }
  1124. search(".",ADVANCE)
  1125. Ins_Char(' ',count,#2-6)
  1126. }
  1127. Restore_Pos()
  1128. //
  1129. #15 = ((#64 & 2)==2) // Preprocessing-only flag
  1130. repeat( all ) {
  1131. #2 = 0 // No COMP encountered yet
  1132. //
  1133. // Search current block for next " PIC x", where x = {C,B,D,F,H,Y,S,V,X,9,-,+,.}.
  1134. // Set Marker(6) -> EOS (past '.').
  1135. //
  1136. sb("^...... .*[\s\t](picture|pic)[\s\t]+[cbdfhysvxCBDFHYSVX9-+.]",Marker(8),Marker(9),REGEXP+MAX+ADVANCE+ERRBREAK)
  1137. Char(-1)
  1138. //
  1139. // Find terminating period.
  1140. // While allowing PIC 9.9. !!!
  1141. //
  1142. Save_Pos()
  1143. if (sb(".|{|>,|!9}",cp,eolpos,COLSET+NOERR,8,#1)==0) { // Kludge on kludge
  1144. sb("^...... .*\.",eolpos,Marker(9),COLSET+REGEXP+MAX,1,#1)
  1145. }
  1146. Set_Marker(6,Cur_Pos)
  1147. //
  1148. // Set Marker(5) to BOS
  1149. //
  1150. #0 = REGEXP+MAX+ADVANCE+REVERSE
  1151. sb("^...... [\s\t]*[0-9]",Marker(8),Cur_Pos,#0)
  1152. BOL()
  1153. Set_Marker(5,Cur_Pos)
  1154. //
  1155. // Create cross reference entry in .xrf, if specified.
  1156. //
  1157. call("XREF")
  1158. //
  1159. // Create entry in _SQL_CRE.imp, if specified.
  1160. //
  1161. call("DoSQL")
  1162. //
  1163. // Append quoted-and-comma-delimited COBOL fieldname to .nam, maybe
  1164. //
  1165. call("NameIt")
  1166. //
  1167. //
  1168. // Check for SIGN LEADING/TRAILING SEPARATE.
  1169. //
  1170. GM(5)
  1171. #0 = COLSET+REGEXP+MAX+ADVANCE+NOERR
  1172. #4 = 0 // Reset signed number flag
  1173. if (sb("^...... .* SIGN ",cp,Marker(6),#0,1,#1)) {
  1174. BoL
  1175. sb("^...... .* {LEADING|TRAILING} ",cp,Marker(6),#0,1,#1)
  1176. c(-9)
  1177. match("|{ L,T}")
  1178. if (mi==1) {
  1179. #3 = 'l'
  1180. } else {
  1181. #3 = 't'
  1182. }
  1183. #4++ // Flag that LEADING/TRAILING found
  1184. }
  1185. //
  1186. // Process any "COMP[-level]."
  1187. // Normally the default (specified by #37) is "4" = Big Endian Binary
  1188. //
  1189. GM(5)
  1190. #0 = COLSET+REGEXP+MAX+ADVANCE+NOERR
  1191. if (sb("^...... .* (COMPUTATIONAL|COMP)[\s\.-]",cp,Marker(6),#0,1,#1)) {
  1192. if (cc(-1)=='-') { // #2 = {1,2,3,4,[5],6}
  1193. #2 = NumEval(SUPPRESS)
  1194. } else {
  1195. #2 = 0xFF // Default value; use #37
  1196. }
  1197. }
  1198. //
  1199. // Comment-out upto the "PIC" line or delete upto the "PIC" data.
  1200. //
  1201. Restore_Pos() // Just at start of PIC's data
  1202. if ( #15 ) { // if just preprocessing...
  1203. Set_Marker(7,Cur_Pos) // Save pos @ {s or x or v or 9 or - or + or .}, x={B,C,D,F,H,Y,X}
  1204. GM(8)
  1205. while ( Cur_Pos < Marker(7) ) {
  1206. Ins_Indent(#29)
  1207. InsText("// ")
  1208. //
  1209. // Output 11 blanks for short-name alignment if ISHORT.
  1210. //
  1211. if (#32){
  1212. Ins_Char(' ',COUNT+ADVANCE,11)
  1213. }
  1214. line(1)
  1215. }
  1216. GM(7) // Restore pos @ {s or x or v or 9 or - or + or .}
  1217. Set_Marker(7,BOL_Pos) // Marker(7)-> BOL
  1218. } else { // when fully processing...
  1219. Del_Block(Marker(8),Cur_Pos) // Delete back to Marker(8)
  1220. Set_Marker(7,Cur_Pos)
  1221. }
  1222. ///////////////////////////////////////////////////////////////////////
  1223. // //
  1224. // Set #0 = LowerCased(CurChar) = one of {s,x,v,9,-,+,.,b,c,d,f,h,y} //
  1225. // #2 > 0 ==> packing of some sort... //
  1226. // #2 = 1 to 6 for COMP-1,...,COMP-6 or 0xFF for default (use #37). //
  1227. // #37 set for UniSys' streaming nibbles. //
  1228. // //
  1229. ///////////////////////////////////////////////////////////////////////
  1230. #0 = Cur_Char | 0x20 // #0 = 'x' | 'v' | 's' | '9' | '-' | '+' | '.' |
  1231. // 'b' | 'c' | 'd' | 'f' | 'h' | 'y'
  1232. if (#0=='d'){ #0 = '@' } // Break conflict between "Delete" and BCD
  1233. if (#0=='y'){ #0 = '#' } // Break conflict between "Date" and SIGN SEPARATE
  1234. //////////////////////////////////////////////////////////
  1235. // //
  1236. // Most numerics, including GreenView codes. //
  1237. // //
  1238. //////////////////////////////////////////////////////////
  1239. if ( #0=='s' || #0=='+' || #0=='-' || #0=='b' || #0=='c' || #0=='h' || #2>0 ) {
  1240. // signed or binary or custom or hex or COMP-n?
  1241. if (#0=='s' || #0=='+' || #0=='-'){ // signed number
  1242. #4++ // Set flag
  1243. if (#15) { // if just preprocessing...
  1244. Char(1)
  1245. } else {
  1246. Del_Char(1)
  1247. }
  1248. }
  1249. //
  1250. // Set #0 to proper Greenview code.
  1251. // I.e., #0 = a,b,c,d,e,f,h,l,m,u,x,y,z.
  1252. // Needed temporarily for generating proper gvc in column 1.
  1253. // Needed later for handling numeric options.
  1254. //
  1255. Save_Pos()
  1256. //
  1257. // COMP's and SIGN LEADING/TRAILING SEPARATE.
  1258. //
  1259. if ( #0 != 'b' && #0 != 'h' && #0 != 'c' && #0 != '#' ) {
  1260. #7 = #2
  1261. if (#7==0xFF){
  1262. if (#35) { // Streaming nibbles
  1263. #7 = 7
  1264. } else {
  1265. #7 = #37 // Default packing
  1266. }
  1267. }
  1268. if (#7==1||#7==2){
  1269. #0 = 'l'
  1270. } else { if (#7==3) {
  1271. #0 = 'd'
  1272. } else { if (#7==4) {
  1273. #0 = 'b'
  1274. } else { if (#7==6) {
  1275. #0 = 'n'
  1276. } else { if (#7==7) {
  1277. #0 = 'm'
  1278. } else { if (#0=='+'||#0=='-') { // Sign leading separate
  1279. #0 = 'y'
  1280. #3 = 'l'
  1281. } else {
  1282. if (#4==2){ // SIGN SEPARATE
  1283. #0 = 'y'
  1284. } else {
  1285. #0 = 'z'
  1286. }
  1287. }}}}}}
  1288. }
  1289. GM(7)
  1290. Ins_Char(#0)
  1291. if (#0=='y'){ // yol or yot
  1292. Ins_Char('o')
  1293. Ins_Char(#3)
  1294. Del_Char(2*#15) // Delete spaces, perhaps
  1295. }
  1296. Ins_Char(' ')
  1297. Del_Char(2*#15) // Delete spaces, perhaps
  1298. Restore_Pos()
  1299. //////////////////////////////////////////////////
  1300. // //
  1301. // Unsigned number ([v,.]9), perhaps. //
  1302. // //
  1303. //////////////////////////////////////////////////
  1304. } else { if ( #0=='v' || #0=='.' || #0=='9' ) {
  1305. Save_Pos()
  1306. GM(7)
  1307. Ins_Text("u ")
  1308. Del_Char(2*#15) // Delete spaces, perhaps
  1309. Restore_Pos()
  1310. if (#0=='.'){
  1311. Ebc_Settings(InPoint,1) // Explicit decimal point
  1312. }
  1313. #0 = 'u' // Unsigned number
  1314. //////////////////////////////////////////////////////////
  1315. // //
  1316. // Else simple nonnumeric (X), X={@,#,F,X}. //
  1317. // //
  1318. //////////////////////////////////////////////////////////
  1319. } else {
  1320. Save_Pos()
  1321. GM(7)
  1322. if (#0=='@'){
  1323. #0='x' // Delete (eXcise)
  1324. //
  1325. // Remove any COBOL field name from .nam file.
  1326. //
  1327. if (#34){
  1328. File_Open("|(FILE_ONLY).nam",OK+NOMSG)
  1329. Search('|{|<",|,"}',REVERSE)
  1330. Del_Block(Cur_Pos,File_Size)
  1331. Buf_Switch(#92)
  1332. }
  1333. //
  1334. // Remove any COBOL field name from _SQL_CRE.imp file.
  1335. //
  1336. if (#38){
  1337. Buf_Switch(#38)
  1338. Del_Line(-1)
  1339. Buf_Switch(#92)
  1340. }
  1341. } else { if ( #0 != 'f' && #0 != '#' ){
  1342. #0='e'
  1343. }}
  1344. if (#0=='#'){ // Date?
  1345. Ins_Char('e')
  1346. } else {
  1347. Ins_Char(#0) // {e,f,x}
  1348. }
  1349. Ins_Char(' ')
  1350. Del_Char(2*#15) // Delete spaces, perhaps
  1351. Restore_Pos()
  1352. }}
  1353. //
  1354. // Set #81 = # digits/bytes before any decimal point.
  1355. //
  1356. if (Cur_Char(1)==0x28){ // CurChar + 1 == LParen?
  1357. if (#15) { // if just preprocessing...
  1358. Char(2)
  1359. #81 = NumEval(SUPPRESS+ADVANCE) // #81 = 'n'
  1360. Char(1) // Advance past RParen
  1361. } else {
  1362. Del_Char(2) // Delete "x(" or "9("
  1363. #81 = NumEval(SUPPRESS) // #81 = 'n'
  1364. Del_Char(Chars_Matched+1) // Delete "n)" ) for balance
  1365. }
  1366. } else {
  1367. Match("[bcdfhxBCDFHX9]*",REGEXP+MAX+ADVANCE)
  1368. #81 = Chars_Matched // #81 = 'n'
  1369. if (!#15) { // if not just preprocessing
  1370. Del_Char(-Chars_Matched) // Delete all "X..." or "9..."
  1371. }
  1372. }
  1373. //
  1374. // Finish converting to our "code +size [{v,.}n]" format.
  1375. // Compute #3 = # digits past decimal point.
  1376. // #8 = # digits, including before & after decimal point.
  1377. // #9 = {'v' | '.'} ? 1 : 0.
  1378. // EbcSettings(Inpoint) = '.' ? 1 : itself.
  1379. //
  1380. Save_Pos()
  1381. GM(7)
  1382. Ins_Char('+')
  1383. Del_Char(1*#15) // Delete spaces, perhaps
  1384. Restore_Pos()
  1385. #3 = #8 = #9 = 0 // No digits past decimal point, yet
  1386. Ebc_Settings(In_Point,0) // No explicit source decimal point, so far
  1387. if (Match('|{v,.9}')==0) { // Process '{v,.}9...' portion
  1388. #9 = 1 // Flag that 'v' or '.' encountered
  1389. if (CurChar=='.'){
  1390. Ebc_Settings(InPoint,1) // Flag that '.' encountered
  1391. }
  1392. if (#15) { // if just preprocessing...
  1393. Char(1)
  1394. } else {
  1395. Del_Char(1)
  1396. }
  1397. if (Cur_Char(1)==0x28) { // CurChar + 1 == LParen?
  1398. if (#15) { // if just preprocessing...
  1399. Char(2)
  1400. #3 = NumEval(SUPPRESS+ADVANCE) // #3 = 'n'
  1401. Char(1) // Advance past RParen
  1402. } else {
  1403. Del_Char(2) // Delete "9("
  1404. #3 = NumEval(SUPPRESS) // #3 = 'n'
  1405. Del_Char(Chars_Matched+1) // Delete "n)"
  1406. }
  1407. } else {
  1408. Match("9*",regexp+max)
  1409. #3 = Chars_Matched // #3 = # digits past "."
  1410. }
  1411. }
  1412. #8 = #81 + #3 // #8 = # digits
  1413. //
  1414. // Compute #6 = # bytes in data field or compute #36 = # digits and signs for NIBBLES.
  1415. //
  1416. GM(7)
  1417. if ( #0=='b' || #0=='d' || #0=='l' || #0=='m' || #0=='n' ) {
  1418. if (#0=='b') {
  1419. if (#8==1) {
  1420. #6 = 1
  1421. } else {
  1422. if (#8<5) {
  1423. #6 = 2
  1424. } else { if (#8<10) {
  1425. #6 = 4
  1426. } else {
  1427. #6 = 8
  1428. }}}
  1429. } else { if (#0=='d') {
  1430. #6 = ( #8 / 2 ) + 1
  1431. } else { if (#0=='n') {
  1432. #6 = ( #8 / 2 ) + remainder
  1433. } else { if (#0=='l') {
  1434. if (#2==1) {
  1435. #6 = 4 // short Float
  1436. } else {
  1437. #6 = 8 // long Float (double precision)
  1438. }
  1439. } else { // 'm'
  1440. #6 = 0
  1441. }}}}
  1442. } else { if ( #0 == 'y' ) {
  1443. #6 = #8 + 1 // Add sign back in for "+9" and "-9"
  1444. } else {
  1445. #6 = #8 // One-to-one for 'c', 'e', 'f', & 'u'
  1446. }}
  1447. //
  1448. // Adjust for explicit decimal point in PIC clause.
  1449. //
  1450. #6 += EbcSettings(InPoint)
  1451. //
  1452. // Update record length.
  1453. //
  1454. if (#0=='m'){
  1455. #6 = #8+#4 // #6 = # 'm' digits plus any sign
  1456. #36 += #6
  1457. } else {
  1458. #26 += #6 // Update record length
  1459. }
  1460. //
  1461. // Insert field size.
  1462. //
  1463. #5 = Cur_Pos
  1464. Num_Ins(#6,LEFT+NOCR)
  1465. Del_Char((Cur_Pos-#5)*#15) // Delete spaces, perhaps
  1466. //
  1467. // For binaries, include ",=ndigits;", perhaps.
  1468. // Enter: #3 = # digits past decimal point.
  1469. // #8 = total # digits.
  1470. // #4 = signed-number flag.
  1471. // #9 = 'v' encountered flag.
  1472. //
  1473. if (#0=='b'){
  1474. #5 = Cur_Pos
  1475. if ( #8 != 2 && #8 != 4 && #8 != 8 && #8 != 18 ){
  1476. Ins_Text(",=")
  1477. Num_Ins(#8,LEFT+NOCR)
  1478. Ins_Text(";")
  1479. }
  1480. Del_Char((Cur_Pos-#5)*#15) // Delete spaces, perhaps
  1481. }
  1482. //
  1483. // For Floats, Doubles and packed decimals with even # digits, include ",=n;"
  1484. //
  1485. if (#0=='l'||(#0=='d'&&!(#8&1))){
  1486. #5 = Cur_Pos
  1487. Ins_Text(",=")
  1488. Num_Ins(#8,LEFT+NOCR)
  1489. Ins_Text(";")
  1490. Del_Char((Cur_Pos-#5)*#15) // Delete spaces, perhaps
  1491. }
  1492. //
  1493. // For PNZ's with odd # digits, include ",=n;"
  1494. //
  1495. if (#0=='n' && (#8&1)){
  1496. #5 = Cur_Pos
  1497. Ins_Text(",=")
  1498. Num_Ins(#8,LEFT+NOCR)
  1499. Ins_Text(";")
  1500. Del_Char((Cur_Pos-#5)*#15) // Delete spaces, perhaps
  1501. }
  1502. //
  1503. // Include any "unsigned" option.
  1504. //
  1505. if ((#4==0)&&(#0=='b'||#0=='d'||#0=='l'||#0=='m')){
  1506. #5 = Cur_Pos
  1507. Ins_Text(" u")
  1508. Del_Char((Cur_Pos-#5)*#15) // Delete spaces, perhaps
  1509. }
  1510. //
  1511. // Explicit decimal point, perhaps.
  1512. //
  1513. if (#9>0 && (#64&4)) { // Explicit decimal point
  1514. #5=Cur_Pos
  1515. if (EbcSettings(InPoint)){
  1516. Ins_Text(" .")
  1517. } else {
  1518. Ins_Text(" v")
  1519. }
  1520. Num_Ins(#3,LEFT+NOCR)
  1521. Del_Char((Cur_Pos-#5)*#15) // Delete spaces, perhaps
  1522. }
  1523. if (!(#15)) { // If fully processing...
  1524. Del_Block(Cur_Pos,EOL_Pos) // Delete remainder of the line
  1525. }
  1526. Line(1)
  1527. Set_Marker(8,Cur_Pos)
  1528. //
  1529. // Ensure code is generated at the statement beginning when commenting out.
  1530. //
  1531. Num_Push(0,0)
  1532. if (#15) {
  1533. Line(-1)
  1534. Search("//")
  1535. #0 = Cur_Col
  1536. rcb(0,BOL_Pos,Cur_Pos,DELETE)
  1537. Ins_Char(' ',COUNT,#0-1)
  1538. EOL()
  1539. Search("//[\s\t]+[0-9]+[\s\t]+[A-Z0-9']",REVERSE+REGEXP)
  1540. Del_Block(BOL_Pos,Cur_Pos)
  1541. Reg_Ins(0)
  1542. if (#32){
  1543. match("// ",ADVANCE)
  1544. match("|B",count+advance,6)
  1545. if (EOLPos-CurPos>RSIZE(1)){
  1546. Reg_Ins(1,OVERWRITE)
  1547. } else {
  1548. Reg_Ins(1)
  1549. }
  1550. if (Match("|b")!=0){
  1551. InsChar(' ')
  1552. }
  1553. }
  1554. }
  1555. //
  1556. // Append data type, length to _SQL_CRE.IMP, perhaps.
  1557. //
  1558. Num_Pop(0,0)
  1559. if (#0!='x'){
  1560. call("RedoSQL")
  1561. }
  1562. GM(8)
  1563. }
  1564. Num_Pop(2,9)
  1565. //
  1566. // Comment out or delete anything upto Marker(9).
  1567. //
  1568. if (#15) {
  1569. while ( Cur_Pos < Marker(9) ) {
  1570. Ins_Indent(#29)
  1571. InsText("// ")
  1572. line(1)
  1573. }
  1574. } else {
  1575. Del_Block(Marker(8),Marker(9))
  1576. }
  1577. return
  1578. //
  1579. // XREF - Create entry in .xrf file if specified.
  1580. // Enter: Marker(5)-> BOS
  1581. // Marker(6)-> past "." at EOS
  1582. // #21 > 0 ? create entry in Buf_Num(#21).
  1583. // #27 = detail record type counter.
  1584. //
  1585. // Each entry in the file consists of 12 blank spaces, a generated
  1586. // short name, blank spaces upto column 30 and the COBOL copybook
  1587. // name for the current field. If the current record is a detail
  1588. // record, "Zn" is prepended to the record name, where 'n' is {1,2,...}.
  1589. // (There may be upto 40 detail record types per main record type).
  1590. //
  1591. // The short name is of the form rn where 'r'= {A,B,...} is the
  1592. // record name and 'n' = {1,2,...} is the field number.
  1593. //
  1594. // The initial 12 spaces can be used later to create a nickname.
  1595. // Column 29 could be used to indicate that the field is being
  1596. // deleted from the translated data.
  1597. //
  1598. :XREF:
  1599. if (!#21){return}
  1600. call("COBNAM") // Copy COBOL field name into T-Reg[0]
  1601. Buf_Switch(#21)
  1602. Ins_Char(' ',COUNT,12)
  1603. #23++
  1604. #4 = Cur_Pos
  1605. Ins_Char(#25)
  1606. Num_Ins(#23,LEFT+NOCR)
  1607. #5 = Cur_Pos
  1608. ii(30)
  1609. Reg_Ins(0)
  1610. rcb(1,#4,#5)
  1611. Ins_Newline()
  1612. Buf_Switch(#92)
  1613. return
  1614. // XREF ends
  1615. //
  1616. // NameIt - Append quoted-and-comma-delimited COBOL field name to .nam, if specified.
  1617. // Enter: #34 ? doit : return
  1618. // Marker(5) at BOS
  1619. // Marker(6) at EOS
  1620. //
  1621. :NameIt:
  1622. if (#34){
  1623. call("COBNAM") // T-Reg[0] = COBOL field name
  1624. File_Open("|(FILE_ONLY).nam",OK+NOMSG)
  1625. If (!At_BOL){
  1626. Ins_Char(',')
  1627. }
  1628. Ins_Char('"')
  1629. Reg_Ins(0)
  1630. Ins_Char('"')
  1631. Buf_Switch(#92)
  1632. }
  1633. return
  1634. // NameIt ends
  1635. //
  1636. // DoSQL - Append COBOL field name to _SQL_CRE.imp, if specified.
  1637. // Replace all '-' with '_'.
  1638. // Enter: #38 ? doit : return
  1639. // Marker(5) at BOS.
  1640. // Marker(6) at EOS.
  1641. //
  1642. :DoSQL:
  1643. if (#38){
  1644. call("COBNAM") // T-Reg[0] = COBOL field name
  1645. Buf_Switch(#38)
  1646. Reg_Ins(0)
  1647. Ins_Newline(1)
  1648. L(-1)
  1649. Replace("-","_",ALL|NOERR)
  1650. L(1,NOERR)
  1651. Buf_Switch(#92)
  1652. }
  1653. return
  1654. // DoSQL ends
  1655. //
  1656. // RedoSQL - Append data type, length to _SQL_CRE.imp, if specified.
  1657. // Enter: #38 ? doit : return.
  1658. // #38 = Buffer_ID for ..._SQL_CRE.IMP.
  1659. //
  1660. // #0 = Greenview field code or '#'.
  1661. // #0 == '#' ? SQL type -> DATETIME (MS SQL).
  1662. //
  1663. // #2 = current COMP level (0=none,1-6,0xFF=default)
  1664. // #3 = # digits past decimal point
  1665. // #4 = signed # flag
  1666. // #5 = temporary
  1667. // #6 = # bytes in data field
  1668. // #7 = Adjusted COMP level (0,1-6,7) where '7' implies streaming nibbles
  1669. // #8 = # digits = #81 + #3.
  1670. // #9 = flag that '{v,.}[n]' encountered.
  1671. //
  1672. // Marker(5) at BOS.
  1673. // Marker(6) at EOS.
  1674. //
  1675. // Note: Originally programmed for MySQL (AB); changed to work with
  1676. // MS DTS SQL Server. (I know nothing! SGT Shultz).
  1677. //
  1678. :RedoSQL:
  1679. if (#38){
  1680. Buf_Switch(#38)
  1681. Char(-Newline_Chars)
  1682. Ins_Indent(15)
  1683. if (cc(-1)!=' '){
  1684. Ins_Char(' ')
  1685. }
  1686. //
  1687. // Text
  1688. //
  1689. if (#0=='e'||#0=='f'){
  1690. Ins_Text("CHAR")
  1691. Ins_Char(0x28) // Left Paren
  1692. Num_Ins(#8,LEFT|NOCR)
  1693. Ins_Char(0x29) // Right Paren
  1694. //
  1695. // Date
  1696. //
  1697. } else { if (#0=='#'){
  1698. // Ins_Text("DATE")
  1699. Ins_Text("DATETIME")
  1700. //
  1701. // Custom Date
  1702. //
  1703. } else { if (#0=='c'){
  1704. // Ins_Text("DATE")
  1705. Ins_Text("DATETIME")
  1706. //
  1707. // Numeric.
  1708. //
  1709. } else {
  1710. //
  1711. // Fixed Decimal Point (text).
  1712. //
  1713. if (#9) {
  1714. Ins_Text("DECIMAL")
  1715. Ins_Char(0x28) // Left Paren
  1716. Num_Ins(#8,LEFT|NOCR)
  1717. Ins_Char(',')
  1718. Num_Ins(#3,LEFT|NOCR)
  1719. Ins_Char(0x29) // Right Paren
  1720. //
  1721. // TINYINT (8 bits).
  1722. //
  1723. } else { if (#8<3) {
  1724. Ins_Text("TINYINT")
  1725. //
  1726. // SMALLINT (16 bits).
  1727. //
  1728. } else { if (#8<5) {
  1729. Ins_Text("SMALLINT")
  1730. //
  1731. // MEDIUMINT (24 bits).
  1732. // Now, same as INT.
  1733. //
  1734. } else { if (#8<7) {
  1735. // Ins_Text("MEDIUMINT")
  1736. Ins_Text("INT")
  1737. //
  1738. // INT (32 bits).
  1739. //
  1740. } else { if (#8<10) {
  1741. Ins_Text("INT")
  1742. //
  1743. // BIGINT (64 bits).
  1744. //
  1745. } else {
  1746. Ins_Text("BIGINT")
  1747. }}}}
  1748. // Ins_Char(0x28) // Left Paren
  1749. // Num_Ins(#8,LEFT|NOCR)
  1750. }
  1751. // Ins_Char(0x29) // Right Paren
  1752. if (!#4){ // Unsigned?
  1753. // Ins_Text(" UNSIGNED")
  1754. }
  1755. }}}
  1756. Ins_Char(',')
  1757. L(1,NOERR)
  1758. Buf_Switch(#92)
  1759. }
  1760. return
  1761. // RedoSQL ends
  1762. //
  1763. // COBNAM - Copy COBOL field name into T-Reg[0].
  1764. // Enter: Marker(5)-> BOS.
  1765. // Marker(6)-> past "." at EOS.
  1766. //
  1767. :COBNAM:
  1768. GM(5)
  1769. #10 = COLSET+REGEXP+MAX+ADVANCE+ERRBREAK
  1770. // sb("\@(#65+14)",cp,Marker(6),#10,1,#1) // Start of field-name
  1771. // ****** above doesn't work (but should) ************
  1772. sb("^...... [\s\t]*[0-9]+[\s\t]+",cp,Marker(6),#10,1,#1)
  1773. #4 = Cur_Pos
  1774. s("|{|b,|>}")
  1775. rcb(0,#4,Cur_Pos)
  1776. return
  1777. // COBNAM ends
  1778. `) // T-Reg[56] - Generating "type cb,ce"
  1779. //////////////////////////////////////////////////////////////////////////////
  1780. //
  1781. // Main Macro.
  1782. //
  1783. // { Main begins
  1784. //
  1785. // if (wstat($)<0){wr($,5,bottom)};ws($);bs(1,attach);ws($);update() ?
  1786. //
  1787. #21 = #22 = #23 = #24 = #26 = #27 = #36 = 0
  1788. #25 = 'A'
  1789. #33 = 1 // Level-2 flag (single record, no OCCURS DEPENDING ON)
  1790. #92 = Buf_Num
  1791. //
  1792. // Replace tabs with spaces.
  1793. //
  1794. Dtab(0,File_Size)
  1795. //
  1796. // Strip any <Ctrl-Z>'s and other junk at end of file.
  1797. // Ensure file ends in <cr><lf>.
  1798. //
  1799. EoF()
  1800. do { // Keep...
  1801. char(-1) // Backing up...
  1802. } while (Match("|k")==0) // Over low values (except newlines)
  1803. Char(1) // Keep the good stuff
  1804. Del_Char(ALL) // Delete all the junk
  1805. if (cc(-1)!=0x0A){Ins_Newline()} // Insert missing newline char(s)
  1806. BoF()
  1807. //
  1808. if ((#64&0x200)==0) { // When running stand-alone...
  1809. #22 = 1 // Set flag
  1810. #64 = 0x202 // Comment out - don't strip - COBOL copybook
  1811. Call("SIGNON")
  1812. Reg_Set(99,"Preprocessing...")
  1813. call("MESSAGE")
  1814. call("OPTIONZ") // Setup cross reference file if -u DBASE option
  1815. }
  1816. //
  1817. // Regular Expression Search strings for REDEFINES & OCCURS submacros.
  1818. //
  1819. Reg_Set(#65+10,"[\s\t]*[0-9]+") // Regexp from BOL thru clause level
  1820. Reg_Set(#65+11,"^...... ") // Regexp for start of COBOL line
  1821. Reg_Set(#65+12,"^......[\s\t]+") // Regexp from BOL to BOCL
  1822. Reg_Set(#65+13,"\@(#65+11)\@(#65+10)") // Regexp from BOL to EOCL
  1823. Reg_Set(#65+14,"\@(#65+11)\@(#65+10)[\s\t]+") // Regexp from BOL to BOCN
  1824. //////////////////////////////////////////////////////////////////////////////
  1825. // //
  1826. // Remove spaces from any {c=,p=,q=} lines. //
  1827. // //
  1828. //////////////////////////////////////////////////////////////////////////////
  1829. Replace("^\s*{[cpq]}\s*=\s*","\1=",BEGIN+ALL+NOERR+REGEXP+MAX)
  1830. //////////////////////////////////////////////////////////////////////////////
  1831. // //
  1832. // M a i n P r o c e s s i n g L o o p //
  1833. // //
  1834. // For each copybook section (upto next "c=0" when stand-alone) or //
  1835. // between "p=" and "q="... //
  1836. // //
  1837. // Set Maker(8)-> p=; delete p=. //
  1838. // Set Marker(9)->q=; delete q=. //
  1839. // Set #1 = 73 for adjusted rightmost valid column # (see below). //
  1840. // Delete embedded blank lines and GreenView comment lines. //
  1841. // Insert blank columns after col 7 and #1; facilitates inter- //
  1842. // pretation. //
  1843. // Propagate un-PIC'd COMPs over entire paragraph. //
  1844. // Comment out all REDEFINES paragraphs via T-Reg[17]. //
  1845. // Process OCCURS clauses via T-Reg[16]. //
  1846. // Generate .LAY descriptions via T-Reg[56]; also generate //
  1847. // .XRF line if DBASE option specified. //
  1848. // //
  1849. //////////////////////////////////////////////////////////////////////////////
  1850. //
  1851. Begin_Of_File()
  1852. RegSet(99,"
  1853. Main Processing...")
  1854. Call("MESSAGE")
  1855. // if (wstat($)<0){wr($,5,bottom)};ws($);bs(1,attach);ws($);update() ?
  1856. if (Search("DECIMAL-POINT|WIS|WCOMMA",NOERR)){
  1857. Begin_Of_File()
  1858. Ins_Text("COMDOT")
  1859. Ins_Newline(1)
  1860. }
  1861. Set_Marker(8,Cur_Pos)
  1862. Set_Marker(9,Cur_Pos)
  1863. repeat ( all ) {
  1864. Call(55) // Set block markers Marker[8],Marker[9]
  1865. // Generate "l=reclen" for previous record
  1866. // Generate tx "R.ASC" or '"R.dbf",R' lines for c=0,R
  1867. // Generate prototype "t 1,0xFF,0xF1" line
  1868. // Delete "c=0[,R]" line
  1869. if (Marker(9)-Marker(8)==0){
  1870. if (Marker(8)==File_Size){
  1871. break
  1872. } else {
  1873. continue
  1874. }
  1875. }
  1876. RegSet(99,"
  1877. Preprocessing...")
  1878. Call("MESSAGE")
  1879. //
  1880. // Delete any blank lines or Vedit comment lines within the COBOL block.
  1881. //
  1882. GM(8)
  1883. rb("|<|[|w]|L","",Marker(8),Marker(9),ALL+NOERR)
  1884. GM(8)
  1885. rb("|<|[|w]//|Y|L","",Marker(8),Marker(9),ALL+NOERR)
  1886. //
  1887. //
  1888. // Blank columns 1-6.
  1889. //
  1890. GM(8)
  1891. rb("|<|?|?|?|?|?|?"," ",Marker(8),Marker(9),ALL+NOERR)
  1892. //
  1893. // Insert blank column after cols 7 and #1.
  1894. // (Helps recognize keywords).
  1895. //
  1896. #1 = 73 // #1 = Last usable data column + 1
  1897. GM(8)
  1898. Block_Fill(' ',cp,Marker(9)-1,INSERT+COLSET,#1,#1)
  1899. Block_Fill(' ',cp,Marker(9)-1,INSERT+COLSET,8,8) // #1 is now last usable data col
  1900. //
  1901. // Propagate COMP's over entire paragraph when no accompanying PIC.
  1902. //
  1903. call("FIXCOMP")
  1904. //
  1905. // Comment out REDEFINES statements/paragraphs.
  1906. //
  1907. RegSet(99,"
  1908. REDEFINES...")
  1909. Call("MESSAGE")
  1910. Set_Marker(1,CLEAR)
  1911. Set_Marker(2,CLEAR)
  1912. #4 = Marker(8)
  1913. call(#65+17)
  1914. Set_Marker(8,#4)
  1915. //
  1916. // Process OCCURS clauses.
  1917. //
  1918. RegSet(99,"
  1919. OCCURS...")
  1920. Call("MESSAGE")
  1921. Set_Marker(1,CLEAR)
  1922. Set_Marker(2,CLEAR)
  1923. call(#65+16)
  1924. //
  1925. // Code generation and cross referencing loop:
  1926. // Search for next " PIC " or "|<rx" occurrence where 'x'={b,c,e}.
  1927. // Normally delete from Marker(8) through " PIC ".
  1928. // If "#64&2" (stop after preprocessing COBOL statements), comment out
  1929. // each line upto the " PIC " line.
  1930. //
  1931. RegSet(99,"
  1932. Code generation...")
  1933. Call("MESSAGE")
  1934. GM(8)
  1935. #64 |= 4 // Set explicit decimal point flag
  1936. while(sb("|<r|{b,c,e}",cp,Marker(9),NOERR)) {
  1937. #0 = Cur_Pos
  1938. GM(9)
  1939. Save_Pos()
  1940. GP(#0)
  1941. Set_Marker(9,Cur_Pos)
  1942. GM(8)
  1943. call(56) // Code generator: "code +len [{v,.}n]"
  1944. // Also add field name to .xrf if #21
  1945. Line(1,NOERR)
  1946. Set_Marker(8,Cur_Pos)
  1947. Restore_Pos()
  1948. Set_Marker(9,Cur_Pos)
  1949. GM(8)
  1950. }
  1951. call(56) // Code generator for last field
  1952. } // Main conversion (loop for each p= & q= section)
  1953. RegSet(99,"
  1954. Post processing...")
  1955. Call("MESSAGE")
  1956. Call("ENDNAME") // Append newline char(s) to any .nam file
  1957. call(55,"RECLEN") // Generate "l=reclen" for final record type
  1958. call("FIXRC") // Set data type and length into any "rc #n"
  1959. if (#21>0){
  1960. call("DETAIL") // Append "Zn" to "short" names for detail records
  1961. call("FIXBIG") // Break up any record types having more
  1962. // than 250 fields
  1963. call("FIXREF") // Convert short names to 'Fn' format
  1964. }
  1965. Buf_Switch(#92)
  1966. //////////////////////////////////////////////////////////////////////////////
  1967. //
  1968. // Post Processing - Run RELAY.VDM, perhaps.
  1969. //
  1970. // When just COBOL preprocessing and not prohibited by the "-u NORELAY" option,
  1971. // run RELAY.VDM to convert "+len,=outsize;" format to begin-/end-column format
  1972. // and insert the field's output starting column # into the comment field:
  1973. //
  1974. // "bc,ec[,=outsize;] // output_column_# ..."
  1975. //
  1976. // Uses Num_Regs 1 - 8:
  1977. // #0 = temporary
  1978. // #1 = initial code letter
  1979. // #2 = begin_col
  1980. // #3 = end_col
  1981. // #4 = input field size = #3 - #2 + 1
  1982. // #5 = output field size if specified, else 0.
  1983. // #6 = output inflation
  1984. // #7 = 1 when code_letters = "rf".
  1985. // #8-> past code_letter[s]-space
  1986. // #9 = # input_cols to be replaced by new format
  1987. // #10 = "qcd" flag
  1988. // #11 = Length of delimiting string (T-Reg[17]) output after
  1989. // each explicitly specified field.
  1990. // #30 = NORELAY flag
  1991. //
  1992. //////////////////////////////////////////////////////////////////////////////
  1993. //
  1994. if ((#64 & 2) && (#30==0)) {
  1995. RegSet(99,"
  1996. Running RELAY.VDM...")
  1997. Call("MESSAGE")
  1998. Reg_Empty(55)
  1999. callf(55,"relay")
  2000. } // Converting "+len" to "bc,ec" and generating "ascii output col" after "//"
  2001. //
  2002. // Termination.
  2003. //
  2004. Reg_Empty(0)
  2005. Reg_Empty(1)
  2006. Reg_Empty(2)
  2007. Reg_Empty(55)
  2008. Reg_Empty(56)
  2009. if (#22>0 && !IsQuiet){
  2010. Reg_Empty(99)
  2011. }
  2012. BOF
  2013. Reg_Pop(#65+10,#65+18)
  2014. Num_Pop(105,105)
  2015. Num_Pop(99,99)
  2016. Num_Pop(90,92)
  2017. Num_Pop(75,76)
  2018. Num_Pop(64,66)
  2019. Num_Pop(6,8)
  2020. if (#22&&Is_Option(y)){
  2021. XALL
  2022. }
  2023. return
  2024. // } Main ends
  2025. //
  2026. // FIXRC - Insert data type and length from next line into any "rc #n".
  2027. //{
  2028. :FIXRC:
  2029. bof
  2030. while(search("|<rc",ADVANCE+NOERR)) {
  2031. Save_Pos()
  2032. s("|<|Y+|M|b",ADVANCE)
  2033. rcb(0,bolpos,cp-1)
  2034. Restore_Pos()
  2035. ri(0)
  2036. }
  2037. return
  2038. // FIXRC ends}
  2039. //
  2040. // FIXCOMP - Propagate COMP's over entire paragraph when no accompanying PIC.
  2041. // #3 = pos past COMP.
  2042. // #4 = pos of " COMP".
  2043. // Marker(5) = BOSpos
  2044. // Marker(6) = pos past "." in current statement.
  2045. //{
  2046. :FIXCOMP:
  2047. GM(8)
  2048. while (search_block(" COMP|[UTATIONAL]|[-|d]|{|b,.}",cp,Marker(9),advance+noerr)) {
  2049. if ( cc( BOL_Pos - Cur_Pos + 6 ) != ' ' ) {continue}
  2050. #4 = Cur_Pos - 1
  2051. #3 = Cur_Pos - Chars_Matched
  2052. //
  2053. // Set Marker(6) past statement terminating "."
  2054. //
  2055. bol
  2056. #10 = COLSET+REGEXP+MAX+ADVANCE
  2057. sb("\@(#65+11).*\.",bolpos,Marker(9),#10,1,#1)
  2058. Set_Marker(6,Cur_Pos)
  2059. //
  2060. // Goto BOS and set Marker(5).
  2061. //
  2062. GP(#3)
  2063. #10 = COLSET+REGEXP+MAX+REVERSE
  2064. sb("\$+\@(#65+13)",Marker(8),cp,#10,1,#1)
  2065. SM(5,cp)
  2066. //
  2067. // Next case, if any PIC clause.
  2068. //
  2069. #10 = COLSET+REGEXP+MAX+ADVANCE+NOERR
  2070. if (sb("\@(#65+11).* {PICTURE|PIC} ",Cur_Pos,Marker(6),#10,1,#1)) {
  2071. GM(6)
  2072. continue
  2073. }
  2074. //
  2075. // No PIC; get paragraph level.
  2076. //
  2077. GP( Marker( 5 ) + 7 )
  2078. #0 = Num_Eval( SUPPRESS )
  2079. //
  2080. // Set Marker(2) to end of paragraph.
  2081. //
  2082. Line(1,errbreak)
  2083. call(#65+15) // NEXT_PEER_FIELD
  2084. SM(2,cp-1)
  2085. //
  2086. // Move the COMP expression into T-Reg[0].
  2087. //
  2088. GP(#3)
  2089. rcb(0,cp,#4,DELETE)
  2090. //
  2091. // Remove the COMP expression from the header paragraph statement.
  2092. //
  2093. Replace("|*|>")
  2094. BoL()
  2095. rb("|[|w]|>",".",cp,#3,NOERR)
  2096. //
  2097. // Propagate the COMP expression over each statement.
  2098. //
  2099. GM(6)
  2100. #10 = COLSET+REGEXP+MAX+ADVANCE+ERRBREAK
  2101. l(1,errbreak)
  2102. while( cp < Marker( 2 )) {
  2103. sb("\@(#65+11).*\.",curpos,Marker(2),#10,1,#1)
  2104. r("|[|W].","",REVERSE)
  2105. #5 = curpos-bolpos-RSIZE(0)-1
  2106. if ( #1 - cn - 1 < RSIZE(0) + 2) {
  2107. Ins_Char(' ',COUNT,CMAT)
  2108. l(1,NOERR)
  2109. Ins_Text(' ',COUNT,#5)
  2110. ri(0)
  2111. Ins_Char('.')
  2112. Ins_Newline()
  2113. } else {
  2114. ri(0,OVERWRITE)
  2115. Ins_Char('.',OVERWRITE)
  2116. l(1,errbreak) // Note: must occur before "while( expression )"
  2117. }
  2118. }
  2119. } // Propagatating unPIC'd COMPs.
  2120. return
  2121. // FIXCOMP ends}
  2122. //
  2123. // FIXBIG - Break up any record types having more than 250 fields
  2124. // when outputting to DBASE-III file. Also, edit
  2125. // cross reference "short" names to rsn format, where 's'
  2126. // is the section name {A,B,...}.
  2127. // Enter: #21 = BufID of cross reference file.
  2128. // #92 = BufID of copybook/lay file.
  2129. //{
  2130. :FIXBIG:
  2131. Buf_Switch(#92)
  2132. BOF()
  2133. Buf_Switch(#21)
  2134. Replace("|<|[|w]|L","",BEGIN+ALL+NOERR)
  2135. BOF()
  2136. DetabBlock(0,File_Size,RESET)
  2137. rcb(0,12,13)
  2138. rcb(1,12,13)
  2139. #1 = 1
  2140. repeat(all){
  2141. SearchBlock("|<|?|?|?|?|?|?|?|?|?|?|?|?|!|{|@(1)}",0,File_Size,NOERR+NORESTORE)
  2142. call("SECTION")
  2143. if (At_EOF){
  2144. break
  2145. }
  2146. #1 = Cur_Line
  2147. Goto_Col(13)
  2148. if(Match("Z|d|[|d]",ADVANCE)==0){
  2149. rcb(0,CurPos-Chars_Matched,CurPos+1)
  2150. rs(1,@0)
  2151. } else {
  2152. rcb(0,CurPos,CurPos+1)
  2153. rcb(1,CurPos,CurPos+1)
  2154. }
  2155. BOL()
  2156. }
  2157. return
  2158. // FIXBIG ends}
  2159. //
  2160. // FIXREF -
  2161. //{
  2162. :FIXREF:
  2163. if (#32) { // Don't bother unless names are going into the .lay file
  2164. #3=Buf_Num
  2165. Buf_Switch(#92)
  2166. BOF()
  2167. if (Search("|<|{t,r}",NOERR)==0){
  2168. Replace("{//[\s\t]+}A","\1F",REGEXP+ALL+NOERR)
  2169. }
  2170. BOF()
  2171. }
  2172. Buf_Switch(#3)
  2173. return
  2174. // FIXREF ends}
  2175. //
  2176. // DETAIL - Append "Zn" to short names in cross reference file.
  2177. // Resequence the field numbers from 1.
  2178. // Move the section to the end of the primary record.
  2179. // Enter: #92 = ID of .lay file
  2180. // #21 = ID of cross reference file
  2181. //{
  2182. :DETAIL:
  2183. Buf_Switch(#21)
  2184. Detab_Block(0,File_Size)
  2185. Buf_Switch(#92)
  2186. BOF()
  2187. while( Search("|<|rb|w#|m|w|s",ADVANCE+NOERR )){
  2188. //
  2189. // Setup T-Reg[1] = Znr where 'n' is the detail record number
  2190. // and 'r' is the base record name.
  2191. //
  2192. #0 = CurPos
  2193. Search(".")
  2194. rcb(1,#0,CurPos) // R[1] = ZnR
  2195. //
  2196. // Setup T-Reg[0] with base record name.
  2197. //
  2198. #0 = CurPos
  2199. Search("|d",REVERSE+ADVANCE)
  2200. rcb(0,cp,#0) // R[0] = 'r' = base record name
  2201. //
  2202. // Setup T-Reg[2] with first detail COBOL field name.
  2203. //
  2204. Search("|<|a +",ADVANCE+NOERR) // First .lay code
  2205. if (#32) {
  2206. Search("[0-9]*[A-Za-z][0-9A-Za-z]+\s+[0-9]+\s+[A-Z0-9-]+",ADVANCE+REGEXP) // "// sname n COBOL-copy-book-name"
  2207. #0 = CurPos
  2208. Search("|b",REVERSE+ADVANCE)
  2209. } else {
  2210. Search("[0-9]\s+[A-Z0-9-]+",REGEXP) // "n COBOL-copy-book-name"
  2211. #0 = CurPos+CharsMatched
  2212. Search("|A") // "COBOL-copy-book-name"
  2213. }
  2214. rcb(2,CurPos,#0) // R[2] = first detail field name
  2215. //
  2216. // Setup T-Reg[3] = final detail COBOL field name.
  2217. //
  2218. Search("|<re|s")
  2219. SetMarker(0,CurPos)
  2220. Search("|<|a +",REVERSE+ADVANCE)
  2221. if (#32) {
  2222. Search("[0-9]*[A-Za-z][0-9A-Za-z]+\s+[0-9]+\s+[A-Z0-9-]+",ADVANCE+REGEXP) // "// sname n COBOL-copy-book-name"
  2223. #0 = CurPos
  2224. Search("|b",REVERSE+ADVANCE)
  2225. } else {
  2226. Search("[0-9]\s+[A-Z0-9-]+",REGEXP) // "n COBOL-copy-book-name"
  2227. #0 = CurPos+CharsMatched
  2228. Search("|A") // "COBOL-copy-book-name"
  2229. }
  2230. rcb(3,CurPos,#0) // R[3] = final detail field name
  2231. //
  2232. // Advance past "re" line
  2233. //
  2234. GM(0)
  2235. Line(1)
  2236. //
  2237. // Cross Reference Editing - Find start of base record
  2238. //
  2239. Buf_Switch(#21)
  2240. BOF()
  2241. SearchBlock(@0,CurPos,File_Size,COLSET,13,13)
  2242. Set_Marker(8,BOL_Pos)
  2243. //
  2244. // - Find end record
  2245. //
  2246. SearchBlock(@0,CurPos,File_Size,ALL+COLSET,13,13)
  2247. Line(1)
  2248. SetMarker(9,CurPos)
  2249. //
  2250. // - Find start of detail record
  2251. //
  2252. GM(8)
  2253. #0 = 30+RSize(2)-1
  2254. SearchBlock(@2,CurPos,Marker(9),COLSET,30,#0)
  2255. SetMarker(6,BOL_Pos)
  2256. //
  2257. // - Find end of detail record
  2258. //
  2259. #0 = 30+RSize(3)-1
  2260. SearchBlock(@3,CurPos,Marker(9),COLSET,30,#0)
  2261. SetMarker(7,EOL_Pos)
  2262. //
  2263. // - Convert all Rsm to ZnRsm
  2264. //
  2265. GM(6)
  2266. if (RegSize(1)>3){
  2267. rb("[A-Z]{[A-Z]*[0-9]+}\s\s\s","\@(1)\1",Cur_Pos,Marker(7),ALL+REGEXP+COLSET,13,29)
  2268. } else {
  2269. rb("[A-Z]{[A-Z]*[0-9]+}\s\s","\@(1)\1",Cur_Pos,Marker(7),ALL+REGEXP+COLSET,13,29)
  2270. }
  2271. //
  2272. // - Resequence from 1
  2273. //
  2274. GM(6)
  2275. #0 = 1
  2276. while(CurPos<Marker(7)){
  2277. char(12)
  2278. Match("Z|d|[|d]|A|[|a]",ADVANCE)
  2279. SavePos()
  2280. ReplaceBlock("|d"," ",CurPos,CurPos+12,ALL)
  2281. RestorePos()
  2282. ITOA(#0++,0,LEFT+NOCR)
  2283. Reg_Ins(0,OVERWRITE)
  2284. Line(1)
  2285. }
  2286. //
  2287. // - Move detail record to end of base record
  2288. //
  2289. rcb(0,Marker(6),CurPos,DELETE)
  2290. GM(9)
  2291. Reg_Ins(0)
  2292. Buf_Switch(#92)
  2293. }
  2294. return
  2295. // DETAIL ends}
  2296. //
  2297. // SECTION - Generate 'out "name.dbf",name' ... 'out' brackets around
  2298. // each section of 250 fields if current record has
  2299. // more than 250 fields; also, edit cross reference
  2300. // "short" name to 'rsn' format, where 's' is the
  2301. // section name {A,B,...}.
  2302. // Enter: #92 = bufID of .lay file
  2303. // #21 = bufID of cross reference file with
  2304. // #1 = record's starting line number and
  2305. // CurPos = start of next record in buffer(#21)
  2306. // R[0] = current record filename
  2307. // R[1] = current record short name prefix
  2308. //{
  2309. :SECTION:
  2310. Buf_Switch(#92)
  2311. if (Reg_Size(0)>1){
  2312. Search('"|@(0).dbf"',NOERR)
  2313. Line()
  2314. } else {
  2315. if (Search('"|@(0).dbf"|Ml=',NOERR+ADVANCE)) {
  2316. Line()
  2317. } else {
  2318. while (Search("|<|v|b")){
  2319. if (cc!='t'){
  2320. break
  2321. }
  2322. Line()
  2323. }
  2324. }
  2325. }
  2326. Buf_Switch(#21)
  2327. #2 = CurLine
  2328. #3 = 0 // Section counter
  2329. Goto_Line(#1)
  2330. while(Cur_Line+250<#2){
  2331. Line(250)
  2332. //
  2333. // Back up to beginning of any OCCURS section.
  2334. //
  2335. repeat (ALL) {
  2336. line(-1)
  2337. Search("|[|h29|[|w]]|>")
  2338. if ( CharsMatched == 0 ) { break }
  2339. }
  2340. //
  2341. BOL()
  2342. RegCopyBlock(3,cp+30-1,EOL_Pos) // R[3] = copybook field name
  2343. Out_Reg(2)
  2344. Type_Char(#3+'A') // R[2] = section name
  2345. Out_Reg(CLEAR)
  2346. #3++
  2347. ReplaceBlock("{[0-9]+}\s","\@(2)\1",#1,Cur_Line,BEGIN+ALL+LINESET+COLSET+REGEXP,13,18)
  2348. Line()
  2349. #1 = Cur_Line
  2350. //
  2351. // Generate 'out "R.dbf,R"'
  2352. //
  2353. Buf_Switch(#92)
  2354. Ins_Text('out "')
  2355. Reg_Ins(0)
  2356. Reg_Ins(2)
  2357. Ins_Text('.dbf",')
  2358. Reg_Ins(0)
  2359. Reg_Ins(2)
  2360. Ins_Newline()
  2361. //
  2362. // Find end of block and generate "out".
  2363. //
  2364. Search("|b|@(3)|{|b,.,|>}")
  2365. Line()
  2366. Ins_Text("out")
  2367. Ins_Newline()
  2368. //
  2369. Buf_Switch(#21)
  2370. }
  2371. if (#3 > 0 && Cur_Line < #2 ) {
  2372. Out_Reg(2)
  2373. Type_Char(#3+'A') // R[2] = section name
  2374. Out_Reg(CLEAR)
  2375. ReplaceBlock("{[0-9]+}\s","\@(2)\1",Cur_Line,#2-1,ALL+LINESET+COLSET+REGEXP,13,18)
  2376. BOL()
  2377. RegCopyBlock(3,cp+30-1,EOL_Pos) // R[3] = copybook field name
  2378. Line()
  2379. Buf_Switch(#92)
  2380. Ins_Text('out "')
  2381. Reg_Ins(0)
  2382. Ins_Char(#3+'A')
  2383. Ins_Text('.dbf",')
  2384. Reg_Ins(0)
  2385. Ins_Char(#3+'A')
  2386. Ins_Newline()
  2387. //
  2388. // *********** complications if OCCURS DEPENDING ON is followed by anything
  2389. // other than more OCCURS DEPENDING ON clauses...**************
  2390. //
  2391. Search("|b|@(3)|{|b,.,|>}")
  2392. Line()
  2393. Ins_Text("out")
  2394. Ins_Newline()
  2395. if (Search("|<tx",NOERR)==0){
  2396. EOF()
  2397. }
  2398. }
  2399. Buf_Switch(#21)
  2400. GotoLine(#2)
  2401. return
  2402. // SECTION ends}
  2403. //
  2404. // SIGNON - when running stand alone
  2405. //
  2406. :SIGNON:
  2407. //
  2408. // Sign on.
  2409. //
  2410. if (!Is_Quiet) {
  2411. if ( OS_Type == 1 && ( Screen_Lines < 15 || Screen_Cols < 57 )) {
  2412. Screen_Size(15,57)
  2413. Screen_Init()
  2414. } else {
  2415. Win_Clear()
  2416. }
  2417. Type_Newline()
  2418. #0 = ( Screen_Cols - 57 ) >> 1
  2419. Type_Space(#0)
  2420. Message('*********************************************************\n');TS(#0)
  2421. Message('* COBOL2V.VDM 07/26/2007 *\n');TS(#0)
  2422. Message('* Convert COBOL copybook text into .lay data layout *\n');TS(#0)
  2423. Message('*********************************************************\n');TN()
  2424. }
  2425. return
  2426. // SIGNON ends
  2427. //
  2428. // MESSAGE - Display T-Reg[99] on console if running stand alone
  2429. // and not "quiet".
  2430. //
  2431. :MESSAGE:
  2432. if (#22>0 && !IsQuiet){
  2433. WinHor(0)
  2434. RegType(99)
  2435. WinEOL()
  2436. }
  2437. return
  2438. // MESSAGE ends
  2439. //
  2440. // ENDNAME - Append newline char(s) to any .nam file.
  2441. //
  2442. :ENDNAME:
  2443. if (#34){
  2444. File_Open("|(FILE_ONLY).nam",OK+NOMSG)
  2445. if (!At_BoL){
  2446. Ins_Newline()
  2447. }
  2448. Buf_Switch(#92)
  2449. }
  2450. return
  2451. // ENDNAME ends
  2452. //
  2453. // OPTIONZ - "-u option_list" where items in "option_list" are blank separated.
  2454. //
  2455. // Option_List:
  2456. // CC=col_num to set starting column number for comment field (default = 20).
  2457. // COMP=level, level=1,6; default=4 (Big Endian (IBM) binary).
  2458. //
  2459. // DBASE (when stand alone) to generate .XRF file, et al.
  2460. // DOS (default) | UNIX | MAC for r=reclen,ftype {0,1,2}.
  2461. // NORELAY to not run RELAY.VDM even in stand-alone mode.
  2462. // ISHORT to generate short names in the main output comment field;
  2463. // requires DBASE.
  2464. // NAMES to output COBOL field names into .nam file.
  2465. // NIBBLES to propogate BCD or hex digits as a stream across byte
  2466. // boundaries. I.e., to start, the sign or MSN is packed into
  2467. // the upper nibble of a byte, followed by the remaining digits,
  2468. // streamwise; the next packed field will be packed contiguous
  2469. // with the end of the current field, even if that means packing
  2470. // the MSN into the lower nibble of an unfilled byte!
  2471. // PNZ to treat "COMP" as PNZ. (Archaic; use comp=6).
  2472. //
  2473. //
  2474. // If dBASE, create/open .xrf file, deleting any existing contents.
  2475. //
  2476. // Enter: Buf_Num = #92 = .LAY buffer ID.
  2477. // Retrn: #21 = ID of opened .XRF file.
  2478. // #28 = {DOS|UNIX|MAC|DBASE} ? {0,1,2,3} : 0.
  2479. // #29 = Starting comment column (default = 20).
  2480. // #30 = NORELAY ? 1 : 0.
  2481. // #32 = DBASE && ISHORT ? 1 : 0.
  2482. // #34 = NAMES ? 1 : 0.
  2483. // #35 = NIBBLES ? 1 : 0.
  2484. // #37 = default COMP level (1-6).
  2485. // #38 = SQL output flag.
  2486. //
  2487. :OPTIONZ:
  2488. #4 = #28 = #30 = #32 = #34 = #35 = #38 = 0
  2489. #29 = 20
  2490. #37 = 4 // Default COMP is Big Endian binary
  2491. if (vn>=530) {
  2492. Buf_Switch(Buf_Free(EXTRA))
  2493. Ins_Text(CMD_LINE)
  2494. EOF()
  2495. Ins_Char(' ')
  2496. //
  2497. // -u
  2498. //
  2499. if (Replace("|<|M-u|[|b]"," ",BEGIN+NOERR)) {
  2500. #4 = Buf_Num
  2501. //
  2502. // DOS or UNIX or MAC
  2503. //
  2504. if (Replace("|b|{DOS,UNIX,MAC}|b"," ",BEGIN+NOERR)){
  2505. #28 = Match_Item - 1
  2506. }
  2507. //
  2508. // NORELAY
  2509. //
  2510. if (Replace("|bNORELAY|b"," ",BEGIN+NOERR)){
  2511. #30 = 1
  2512. }
  2513. //
  2514. // DBASE
  2515. //
  2516. if (Replace("|bDBASE|b"," ",BEGIN+NOERR)) {
  2517. #28 = 3
  2518. }
  2519. //
  2520. // SQL
  2521. //
  2522. if (Replace("|bSQL|b"," ",BEGIN+NOERR)) {
  2523. #38 = 1
  2524. }
  2525. //
  2526. // ISHORT
  2527. //
  2528. if (Replace("|bISHORT|b"," ",BEGIN+NOERR)){
  2529. #32 = 1
  2530. }
  2531. //
  2532. // NAMES
  2533. //
  2534. if (Replace("|bNAMES|b"," ",BEGIN+NOERR)){
  2535. #34 = 1
  2536. }
  2537. //
  2538. // NIBBLES
  2539. //
  2540. if (Replace("|bNIBBLES|b"," ",BEGIN+NOERR)){
  2541. #35 = 1
  2542. }
  2543. //
  2544. // PNZ (Archaic; use "comp=6")
  2545. //
  2546. if (Replace("|bPNZ|b"," ",BEGIN+NOERR)){
  2547. #37 = 6
  2548. }
  2549. //
  2550. // cc=col_num
  2551. //
  2552. if (Replace("|bcc|[|w]="," ",BEGIN+NOERR)){
  2553. #3 = Cur_Pos
  2554. #29 = Num_Eval(ADVANCE)
  2555. DelBlock(#3,CurPos)
  2556. if (#29 > 35) {#29 = 35}
  2557. if (#29 < 10) {#29 = 10}
  2558. }
  2559. //
  2560. // COMP=level, 1-6
  2561. //
  2562. if (Replace("|bcomp|[|w]="," ",BEGIN+NOERR)){
  2563. #3 = Cur_Pos
  2564. #37 = Num_Eval(ADVANCE)
  2565. DelBlock(#3,CurPos)
  2566. if (#37 < 1) {#37 = 4}
  2567. if (#37 > 6) {#37 = 4}
  2568. }
  2569. }
  2570. Buf_Quit(OK+NOMSG)
  2571. Buf_Switch(#92)
  2572. } else { if (Is_Option(n)) {
  2573. #28 = 3
  2574. }}
  2575. //
  2576. // Create or open and empty fname.XRF if DBASE.
  2577. //
  2578. if (#28 == 3 ){
  2579. //
  2580. // Set T-Reg[0] = "fname.XRF".
  2581. //
  2582. Reg_Set(0,PATH_NAME)
  2583. Buf_Switch(Buf_Free(EXTRA))
  2584. Reg_Ins(0)
  2585. if (Search(".",BEGIN+ALL+ADVANCE+NOERR)){
  2586. char(-1)
  2587. Del_Char(ALL)
  2588. } else {
  2589. EOF()
  2590. }
  2591. Ins_Text(".xrf")
  2592. rc(0,0,REVERSE+DELETE)
  2593. Buf_Quit(OK)
  2594. //
  2595. //
  2596. //
  2597. Buf_Switch(#92)
  2598. File_Open(@0,OK+NOMSG)
  2599. db(0,File_Size)
  2600. #21 = Buf_Num
  2601. Buf_Switch(#92)
  2602. }
  2603. //
  2604. // Create or open and empty fname_SQL_CRE.IMP if DBASE.
  2605. //
  2606. if ( #38 ){
  2607. //
  2608. // Set T-Reg[0] = "fname_SQL_CRE.IMP".
  2609. //
  2610. Reg_Set(0,PATH_NAME)
  2611. Buf_Switch(Buf_Free(EXTRA))
  2612. Reg_Ins(0)
  2613. if (Search(".",BEGIN+ALL+ADVANCE+NOERR)){
  2614. char(-1)
  2615. Del_Char(ALL)
  2616. } else {
  2617. EOF()
  2618. }
  2619. Ins_Text("_SQL_CRE.IMP")
  2620. rc(0,0,REVERSE+DELETE)
  2621. Buf_Quit(OK)
  2622. //
  2623. //
  2624. //
  2625. Buf_Switch(#92)
  2626. File_Open(@0,OK+NOMSG)
  2627. db(0,File_Size)
  2628. #38 = Buf_Num
  2629. Buf_Switch(#92)
  2630. }
  2631. //
  2632. // Reset #32 (ISHORT) if !DBASE.
  2633. //
  2634. if (#28!=3){
  2635. #32=0
  2636. }
  2637. //
  2638. // Create or open and empty fname.nam if NAMES.
  2639. // Set DOS filetype.
  2640. //
  2641. if (#34){
  2642. File_Open("|(FILE_ONLY).nam",OK+NOMSG)
  2643. db(0,File_Size)
  2644. Config(F_F_TYPE,0,LOCAL)
  2645. Buf_Switch(#92)
  2646. }
  2647. //
  2648. return
  2649. // OPTIONZ ends