PageRenderTime 56ms CodeModel.GetById 23ms RepoModel.GetById 0ms 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

Large files files are truncated, but you can click here to view the full 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. }…

Large files files are truncated, but you can click here to view the full file