PageRenderTime 73ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/macros/ebcdic-t.vdm

https://bitbucket.org/chriz/z_vedit
Unknown | 3417 lines | 3324 code | 93 blank | 0 comment | 0 complexity | 279dd5af47de3d772dc7346120caacec MD5 | raw file
  1. // EBCDIC-T.VDM -- EBCDIC Level-2 Trial version - Limited to 5000 fields.
  2. // Convert EBCDIC with packed fields into ASCII.
  3. // Supports EBCDIC text, packed-decimal, packed-binary, zoned,
  4. // packed-no-zone, floating point, hexadecimal, ignored and
  5. // custom fields. (Floating point data whose magnitudes are
  6. // greater than 10E18 are blanked.)
  7. //
  8. // Converts COBOL picture specifications into commands
  9. // recognized by the rest of this macro. The picture
  10. // specifications may be edited to include new Greenview codes
  11. // for more flexibility in the translation. See COBOL2V.VDM.
  12. //
  13. // Note: comments out "REDEFINES" statements which are
  14. // otherwise unsupported.
  15. //
  16. //
  17. // Output Options:
  18. // Append newline char(s) at the end of each record.
  19. // Emit an explicit decimal point for packed and zoned fields.
  20. // Quote and comma delimit each field.
  21. // Optionally emit specified delimiter(s) after each field.
  22. // Write error messages to ebcdic.err (default).
  23. //
  24. // Now, optionally outputs records into DBASE .dbf files,
  25. // including creating and updating the DBASE header record.
  26. // Also, optionally includes a field-names record at the start
  27. // of each output file. The initial field names can be generated
  28. // from a COBOL copy-book. See COBOL2V.VDM.
  29. //
  30. // Originally by: Theodore Green, Greenview Data, Inc.
  31. // Generalized by: Thomas C. Burt, Greenview Data, Inc.
  32. // Last change: 09/26/2003
  33. //
  34. // Requires: VEDIT PLUS 6.10 dated 03-05-2003 or later.
  35. // EBCDIC.LAY or alias (see below).
  36. // REGPREP.VDM
  37. //
  38. // Optional: COBOL2V.VDM (for preprocessing COBOL copybooks).
  39. // RELAY.VDM for generating output column #'s.
  40. // EBCDIC-2.VCM (customization submacro library).
  41. // EBCDIC.CUS (q.v.)
  42. //
  43. // From OS: VPW [-N[mask]] [-Y] -X EBCDIC-2 fname [-A oname] [lname] [-u options]
  44. //
  45. // When done, saves the output file as fname.X, where 'X' is
  46. // "ASC", normally, or "DBF" for DBASE output, or as specified
  47. // by "-A oname" and displays it on the screen.
  48. //
  49. // Use {FILE, Exit} to exit.
  50. //
  51. // Unless an explicit data layout filename is specified via
  52. // optional parameter 'lname', the data layout file EBCDIC.LAY
  53. // (or "fname.LAY when option "-N" is specified) must exist
  54. // in the current directory or in Vedit's "Home" directory.
  55. // EBCDIC.LAY is described below.
  56. //
  57. // -Y exits Vedit automatically after saving the translated file.
  58. //
  59. // -A specifies the name of the output file, including optional
  60. // drive and path.
  61. //
  62. // -N[mask] with no parameter or when (mask&1) is true, uses
  63. // "fname.LAY" as its record description file.
  64. // Alternatively, to always use "fname.LAY", edit this macro
  65. // setting numeric variable #64 = 1 as described, below.
  66. //
  67. // When (mask&2) is true, this macro terminates after
  68. // COBOL preprocessing.
  69. //
  70. // When (mask&256) is true, this macro terminates after
  71. // all preprocessing has finished. (However, any "v="
  72. // commands are not executed).
  73. //
  74. // -U leadin to options for this macro. If used, must occur after
  75. // all filenames have been specified.
  76. //
  77. // Unique ID options (auto-generated record# [run_no] run_date)
  78. // run_no 0 <= n < 9; default == 1.
  79. // UID=val val={off,auto,on or all}={0,1,2};
  80. // default == 1.
  81. // d=run_date mm/dd/yyyy
  82. //
  83. // To include .nam at start of each output file:
  84. // i[nclude][=val] val={off,on}={0,1}; default == 0.
  85. //
  86. // NOD to prevent decimal points from being output
  87. //
  88. // E.g., -u 2 specifies that "2" is to be inserted into the
  89. // run_no bytes of any unique ID.
  90. //
  91. // ##### NOTE: WIN95 batch processing strips "="; so, in .BAT files
  92. // using the "-u" options, substitute "-" for the equals
  93. // signs in the above-mentioned options.
  94. //
  95. // Note: blank-fills, by default, invalid zoned/packed decimal fields (see
  96. // bc=, below). Also, writes error message to EBCDIC.ERR (see "e=" below).
  97. //
  98. //////////////////////////////////////////////////////////////////////////////
  99. //
  100. // EBCDIC-2.LAY - Describes the file being translated.
  101. // Lines specify optional header size, record size,
  102. // comment lines, Vedit command lines and data descriptions.
  103. // Columns must be specified in ascending order. Undescribed
  104. // columns may be optionally ignored (copied from input to
  105. // output as is); else are converted from EBCDIC to ASCII.
  106. // Cobol copybook statements may also be used.
  107. //
  108. // Data description (layout) lines:
  109. //
  110. // [code col_siz [sop] [#r] [: cusops]] [// comment]
  111. //
  112. // code is a string of letters followed by a space describing the
  113. // field to be translated. E.g., "e " describes EBCDIC text.
  114. // The codes are listed, below.
  115. //
  116. // col_siz specifies the columns to be decoded; this may be done in
  117. // two ways:
  118. //
  119. // a) begin_col<sep>end_col
  120. //
  121. // The separator is typically a comma or a hyphen.
  122. // Columns begin counting from one.
  123. // The end column is inclusive.
  124. //
  125. // The begin_col need not immediately follow any
  126. // preceding end_col since any unspecified columns are
  127. // processed according to the default type which is 'e'
  128. // unless changed with the "u=type" command (see below).
  129. //
  130. // E.g., e 1-4 // specifies that columns one through
  131. // // four are simple EBCDIC text.
  132. //
  133. // b) +size
  134. //
  135. // Specifies the length of the field; assumes this item
  136. // is adjacent to the preceding item, although a column
  137. // number can be specified by preceding this item with
  138. // a "c=col" line.
  139. //
  140. // Note the '+' prefix.
  141. //
  142. // E.g., e +4 // the next four colums are EBCDIC text
  143. //
  144. // sop (standard options):
  145. //
  146. // [,[-|=]padlen;] [numops] [[pc=]'padch'] [[bc=]'badch']
  147. //
  148. //
  149. // padlen = # padchars to insert behind the output field;
  150. // default "padch" is a blank space; changeable
  151. // by the "pc=" specification.
  152. //
  153. // -padlen = # padchars to insert before the output field.
  154. //
  155. // =padlen = # digits to be output for 'b', 'd', 'l',
  156. // 'n' & 'u' commands.
  157. //
  158. // = # bytes for 'pb', 'pd', 'pn' and 'pz' commands.
  159. //
  160. // Note: the leading comma is required; the semicolon
  161. // should be used to prevent misinterpretations.
  162. // (Memento Murphi)!
  163. //
  164. // numops: [+][b][z][u] [r[aw]] [v[n]]
  165. // [-][e][p][s]
  166. //
  167. // + to force plus sign for positive numbers, including
  168. // unsigned packed decimal data that are not specified
  169. // as unsigned; else, a blank is output. (Does not
  170. // affect negative numbers for which a minus sign is
  171. // always output).
  172. // - to override '+' specified on 'o=' (options) command.
  173. //
  174. // b to display sign at the beginning of the number.
  175. // e to override 'b' specified on 'o=' (options) command.
  176. //
  177. // s for signed numeric output. This is the default.
  178. // u for unsigned numeric output. No sign is expressed.
  179. //
  180. // z to display leading zeros.
  181. // p to override 'z' specified on 'o=' (options) command.
  182. //
  183. // r or raw to force non-compliant binaries to be evaluated.
  184. // I.e., those whose magnitude is > normal maximum value.
  185. // e.g., 0xc757 = 51031 which is larger than 4 digits which
  186. // is the normal maximum for a 2-byte binary described
  187. // as PIC 9(4) COMP. The previous example requires the ",=5;"
  188. // parameter as well.
  189. //
  190. // v[n] to output a decimal point 'n' digits from the
  191. // right for numeric fields. If 'n' is zero or omitted,
  192. // no fractional digits are output.
  193. //
  194. // [pc=]'padch': specify the padding character for the current
  195. // field; default is space; used with "[-]padlen";
  196. // when "pc=" is not specified, sets "badchar" as
  197. // well as "padchar". Also, used for the 'f' (fill
  198. // or replace) specification.
  199. //
  200. // [bc=]'badch': specify the "erase" character for the current
  201. // field when invalid zoned/packed fields are
  202. // encountered. Default is space. When "bc=" is not
  203. // specified, sets padchar" as well as "badchar".
  204. //
  205. // The specified padchar or badchar may be an ASCII char in the
  206. // range 0x20 to 0x7e ('a', e.g.) or null ('') or it may be
  207. // specified as a hex number 0xhh. (This is probably necessary
  208. // when translating from ASCII to EBCDIC).
  209. //
  210. // Note: the apostrophes are still required: '0x99', e.g.
  211. //
  212. // #r Specify the register that contains the custom macro
  213. // to execute for the current custom field (code='c').
  214. //
  215. // : cusops - The ":" indicates the presence of custom parameters
  216. // for the custom macro (code='c').
  217. //
  218. // // starts a comment field.
  219. //
  220. // Note: as indicated by the syntax above, blank lines and comment lines
  221. // are valid. All comments and blank lines are stripped during
  222. // preprocessing.
  223. //
  224. // Note: Not described above is the "code=arg" form. Such lines are
  225. // acted upon during preprocessing and then stripped from the
  226. // working layout file. These codes are listed below.
  227. //
  228. // Current codes are:
  229. // h= (header size)
  230. // r= (input record size/type[,output record type])
  231. // e= (max error report count, error filename)
  232. // i= (1 to include field-names header files *.nam)
  233. // o= (Set default output options: '+buz[,b2z]'; '-esp' is standard)
  234. //
  235. // c= (Set field beginning column; COBOL cut & paste)
  236. // p= (Start of COBOL record description)
  237. // q= (End of COBOL record description)
  238. //
  239. // u= (e[bcdic] (default) or i[gnore]) for unspecified cols
  240. // v= (Vedit commands - executed immediately)
  241. // x= (Vedit post-processing commands)
  242. //
  243. // a= (Additional offset for unique ID calculation)
  244. // b= (Base_date for unique ID calculation)
  245. // d= (Run_date for unique ID calculation)
  246. // n= (# digits displayed for unique ID's)
  247. //
  248. // bc=(badchar)
  249. // pc=(padchar)
  250. // xrf= (use DBASE cross reference file)
  251. //
  252. // b (binary)
  253. // c (customized processing)
  254. // d (packed decimal)
  255. // e (EBCDIC)
  256. // f (fill) i.e., replace with pad char, default = Space
  257. // h (hex)
  258. // i (ignore) i.e., copy to output
  259. // l (float/double) Upto 10E18.
  260. // n (packed_no_zone)
  261. // out [fname]
  262. // q or qcd: quote and comma delimit each output field (no parms)
  263. // s (signed ASCII decimal)
  264. // u (unsigned EBCDIC numeric)
  265. // x (delete)
  266. // z (zoned decimal)
  267. //
  268. // Details for some of the above commands:
  269. //
  270. // c Customized processing:
  271. // Initialization:
  272. // v=Reg_Set(r,'macro commands') or
  273. // v=Reg_Load(r,'macfile.vdm')
  274. //
  275. // Field specification:
  276. // c col_siz [sop] [#r] [: custom parameters] [// comment]
  277. //
  278. // col_siz, and [sop] are described above.
  279. // 'r' is the number of the T-Reg containing the
  280. // customized translation commands (default=12) aka
  281. // EBC_Settings(CustomMacro).
  282. // 'custom parameters' must be parsed by the
  283. // customizing macro. E.g.,
  284. // Buf_Switch(XLayBufNum)
  285. // processing code
  286. // Buf_Switch(XDataBufNum)
  287. // '//' starts a comment field. This field is stripped
  288. // during preprocessing, so any custom parameter
  289. // cracking need not be concerned about it.
  290. //
  291. // The custom macro must entirely process its source data
  292. // from CurPos upto but not including CurPos+XInpFieldSize;
  293. // i.e., replace, delete or skip over (ignore). On exit,
  294. // CurPos must be at the byte that was located, on entry,
  295. // at CurPos + XInpFieldSize.
  296. //
  297. // Note: on entry, the current buffer is the source input
  298. // data buffer XDataBufNum; i.e., (bn==xdata).
  299. //
  300. // f Fill (overwrite) with "padchar" (default=space) or specified char. E.g.,
  301. // f cb-ce '*' // Fill columns cb through ce with asterisks.
  302. //
  303. // Useful for cleaning "filler" areas containing garbage.
  304. // Especially needed if this garbage gets translated into
  305. // weird control characters.
  306. //
  307. // h Hex - Output each byte as two hex digits '0' - '9', 'A' - 'F'.
  308. //
  309. // l Floating point (IBM 360 style).
  310. // l bc,ec[,=ndigs;] [sop] [v[n]] [// comment]
  311. //
  312. // Fixed format only, right justified; short floats (single precision)
  313. // can express seven significant digits; long floats (double precision)
  314. // can express sixteen. Values upto 10E18 can be processed; least
  315. // significant digits beyond the seventh or sixteenth are always 0.
  316. // Floating point values > 10E18 are BAD-CHAR erased. Fractions smaller
  317. // than 10E-18 are output as zeros.
  318. //
  319. // Optional 'ndigs' specifies total # digit-output columns. The
  320. // decimal point, if any, is not counted nor is the sign.
  321. //
  322. // "sop" are standard options "+bz-esp".
  323. //
  324. // 'n' specifies the number of fractional digits to display.
  325. //
  326. // "v0" or "v" outputs a decimal point with no fractional digits
  327. // displayed.
  328. //
  329. // If "v[n]" is omitted, no decimal point is output.
  330. //
  331. // q[cd] Quote and comma delimit each output field (no parms).
  332. // Each field must be specified. Since only the first letter
  333. // is examined, this may be specified as "qcd" or "quote and
  334. // comma delimit".
  335. //
  336. // s Signed ASCII field being converted to ASCII. Analagous to
  337. // signed (zoned) EBCDIC field. Presumes the final signed
  338. // byte of the field is one of (ASCII) '{', 'A' - 'R', '}'.
  339. //
  340. // u Unsigned numeric field. Needed only if an explicit decimal
  341. // point is to be output or if leading zeros are desired or
  342. // if an entirely blank/null field is to be expressed as text
  343. // zero(s).
  344. //
  345. // x Delete the field. When quoting and comma delimiting or
  346. // outputting a user defined delimiter after each field,
  347. // nothing is output, including the delimiters.
  348. //
  349. // a=n Additional offset for calculating unique ID's.
  350. // Use when processing more than one file with extracted
  351. // fields on a given day. Set greater than or equal to last
  352. // record # processed by the previous run. Not very useful.
  353. // Use the "-u n" invocation option with the "n=,,1"
  354. // layout specification as described below.
  355. //
  356. // b=date Base date for calculating unique ID's. Default is 1-1-2000.
  357. // Date must be expressed in mm/dd/yyyy format. The separator
  358. // can be one of "/\._:-". The year must be completely expressed.
  359. //
  360. // d=date Run date for calculating unique ID's. Default is current date.
  361. //
  362. // n=l,m,n Control # digits displayed for each part of the unique ID.
  363. // 'l' is the number of digits for the days-elapsed count;
  364. // 'm' is the number of digits for the record count;
  365. // 'n' is the number of digits for "run_number".
  366. // Default is "n=5,6,1". Use "n=,,0" to remove the position
  367. // reserved for the run #, if so desired. Setting the run #
  368. // requires the use of the "-u run_number" invocation option.
  369. //
  370. // c=col Set field beginning column (actually, preceding field's
  371. // ending column) for use with 'code +len' style specs
  372. // that are not contiguous with the last specified field.
  373. // Particularly useful for cut-&-pasting COBOL specs.
  374. //
  375. // e=n[,f] Control writing of error messages to error file.
  376. // Default is to write all errors to EBCDIC.ERR, including
  377. // upto 1000 occurrences of invalid compressed data items.
  378. // This command allows changing the limit for reporting invalid
  379. // compressed data items; changing the default error filename;
  380. // and disabling error writing completely.
  381. //
  382. // 'n' is the maximum # of invalid data messages.
  383. // 'f' is the name of the error file, including optional
  384. // drive and path.
  385. // Disable error messages by including "e=" by itself.
  386. // e.g., "e= // Disable writing errors to file"
  387. //
  388. // The form "e=n" reports upto 'n' errors in "ebcdic.err".
  389. // The form "e=,errfname" reports upto 1000 errors in errfname.
  390. // Alternatively, use "e=errfname".
  391. //
  392. // Note: The file ebcdic.err is always deleted at startup.
  393. // Any explicitly named error file is emptied when the
  394. // "e=" line is processed.
  395. //
  396. // Note: Errors that occur during preprocessing generally
  397. // cause processing to stop immediately.
  398. //
  399. // N.B., Errors that occur before this command is processed
  400. // are written to EBCDIC.ERR.
  401. //
  402. // i=val Flag to include header files "*.nam" at the start of each
  403. // output file that contains data. These files are expected to
  404. // consist of quoted and comma delimited field-names. "val"
  405. // is one of {0,1,off,on}, default == "off". The filename
  406. // proper of each ".nam" file must be the same as that of the
  407. // output file into which it is to be included. This option
  408. // may also be turned on with the "-u include=1" invocation
  409. // option.
  410. //
  411. // h= Size of header. Used to pass over (copy to output)
  412. // header information. Ordinarily not used.
  413. //
  414. // o=nops[,b2z]
  415. //
  416. // Examples: o=+bz // explicit '+'; leading sign; leading zeros
  417. // o=uz // Unsigned numeric values; leading zeros
  418. // Default: o=-eps// blanked positive sign; trailing sign;
  419. // // blank padding; numbers are signed values
  420. //
  421. // Options are:
  422. // + for explicit plus sign for positive/unsigned numbers.
  423. // - to output a space instead of '+' (default).
  424. //
  425. // b to output the sign at the beginning of the number.
  426. // e to output the sign at the end of the number (default).
  427. //
  428. // s (signed) to express the sign at all. (Default).
  429. // u (unsigned) to suppress the sign.
  430. //
  431. // z to output leading zeros.
  432. // p for blank padding (default).
  433. //
  434. // ,b2z specifies that packed decimals, binaries and unsigned
  435. // numeric fields that are entirely blank or null will be
  436. // output as zero(s) formatted according to the other
  437. // options.
  438. //
  439. // This sets default output actions for 'b', 'd', 'l', 'n',
  440. // 'u' & 'z' fields. The defaults may be overriden by the
  441. // individual field specifications. E.g., d 5,12 +bz
  442. //
  443. // At most only one 'o=' line is needed. If more are used, the
  444. // effect is cumulative. Since these lines are preprocessed and
  445. // then stripped, there is little reason to use more than one
  446. // line.
  447. //
  448. // p=[x] Specifies start of COBOL picture specifications block;
  449. // 'x' to output explicit decimal point for 9...v99... formats.
  450. // Otherwise, no decimal point is output. (If initial field is
  451. // not contiguous with last specified field, follow with
  452. // "c=colm1" where colm1 is the starting column less one).
  453. //
  454. // q= Specifies end of COBOL specifications block. Multiple
  455. // blocks may be specified within the data description file.
  456. //
  457. // r= Record size 'r= input_size_or_type[,output_type]', where
  458. // type may be 0, 1, 2 or "f" (output only). If no output
  459. // record type is specified, the input type is used.
  460. //
  461. // When input/output records are/will be terminated by Carriage-
  462. // Return and/or Line-Feed, use record type:
  463. // 0 for <cr><lf> (DOS)
  464. // 1 for <lf> (UNIX)
  465. // 2 for <cr> (MAC)
  466. //
  467. // Record terminators are stripped from the input record.
  468. // They will then be appended to the output if output_type
  469. // (explicit or default) is one of the above three types.
  470. //
  471. // Record terminators are not normally used with EBCDIC data
  472. // files. They cannot be used when the data file contains
  473. // binary fields.
  474. //
  475. // When records are unterminated, specify the input record
  476. // length upto but not including the variable portion of
  477. // variable length records; i.e., fields occurring after a 'rf'
  478. // specification (OCCURS .... DEPENDING ON ... clause in COBOL).
  479. //
  480. // When unterminated multiple record types differing in length
  481. // are being processed, setting input_record_size_or_type to the
  482. // size of the largest record is probably appropriate.
  483. //
  484. // The input record size must be specified for unterminated
  485. // records; it may also be specified for fixed length records
  486. // even when they have terminating character(s). Be sure to
  487. // include the terminators in the record length and process
  488. // them in the .LAY file.
  489. //
  490. // Normally, no length is specified for the output record since
  491. // it is determined dynamically. Thus, for fixed length input
  492. // and output records, just specify the input record size:
  493. // "r=100", e.g.
  494. //
  495. // If the output is to be unterminated but the input is
  496. // terminated, use 'f' for the output_type. Thus, "r=0,f"
  497. // inputs records terminated by Carriage-Return and Line-Feed
  498. // but strips them from the output ("f" stands for "fixed").
  499. //
  500. // Examples: r=100,0 //Input record size = 100
  501. // //append <cr><lf> on output
  502. //
  503. // r=100 //Input record size = 100
  504. // //Output records are unterminated
  505. //
  506. // r=0 //Both input and output records
  507. // //terminated by <cr><lf>
  508. //
  509. // r=0,1 //Input records terminated by <cr><lf>
  510. // //Output records terminated by <lf>
  511. //
  512. // u=arg Specify action for non-specified fields.
  513. // arg=ebcdic to translate from EBCDIC to ASCII;
  514. // arg=ignore to simply copy the input columns to output.
  515. // Only the initial letter need be specified.
  516. // E.g, u=i // Copy unspecified columns to output.
  517. //
  518. // v= Vedit commands are executed as soon as they are encountered
  519. // and are then stripped from the layout file. The commands must
  520. // fit on one line but as many "v=" lines may be used as needed.
  521. // One line is sufficient for executing a macro file via a text
  522. // register.
  523. //
  524. // May be used to put a user-defined output field delimiter
  525. // (string) into T-Reg[XDREG]: e.g., v=Reg_Set(XDREG,"|"); or
  526. // v=rs(XDREG,' ^ '). Unlike quoted and comma delimited fields,
  527. // not all fields need be specified; a group of unspecified
  528. // fields will have just one instance of the delimiter string
  529. // appended to the end of the group.
  530. //
  531. // x= Vedit commands are stored into T-Reg[14]. They are then
  532. // executed in a post processing pass after all other commands
  533. // have been applied to the entire file. These commands must
  534. // fit on one line. Use Call_File() if more lines are needed.
  535. //
  536. // xrf=arg Use DBASE cross reference file fname.XRF for generating the DBASE
  537. // header record. "arg" = "1" or "on" to use; "0" or "off" may be
  538. // used to generate the names automatically or the "xrf" line may
  539. // be omitted to achieve the same result. If the file fname.XRF is
  540. // empty, the field names will be automatically generated.
  541. //
  542. // example EBCDIC-2.LAY file:
  543. //
  544. // // Each input record is 256 bytes long.
  545. // // Output records have <cr><lf> appended.
  546. // // The first 3 fields are packed decimal.
  547. // // Columns 42-45 and 50-53 are binary.
  548. // // Columns 54-57 are zoned decimal.
  549. // //
  550. // r=256,0 //Size of input records
  551. // //<cr><lf> appended to output
  552. // d 7-10 //Packed decimal
  553. // d 20-24 //Also packed decimal, (default = previous)
  554. // d 32-38
  555. // b 42-45 //Binary
  556. // b 50-53
  557. // z 54-57 //Zoned decimal
  558. // //
  559. // // The final fields contain leading zeros that are
  560. // // to be converted to blanks with 1 leading blank inserted.
  561. // //
  562. // v=RegLoad(EBC_Settings(CustomMacro),"nolzero.cus")
  563. // c 60-69 #12 // Field size remains contstant
  564. // c 70-75 // Uses T-Reg 12 for custom processing
  565. //
  566. //////////////////////////////////////////////////////////////////////////////
  567. //
  568. // Numeric register usage:
  569. //
  570. // #0 - #5 Temp
  571. // #3 Preprocessing: field counter
  572. // #4 Preprocessing: max # fields in any record
  573. // #8 Reserved for levels 3 & 4
  574. // #10-#13 Temp; used as such by customizing macros
  575. // Note: #10 - #74 are used implicitly by UNPAKDEC.VDM.
  576. // #14-#19 Reserved for customizing macros
  577. // #15 Preprocessing: temp
  578. // #16 Preprocessing: buffer ID of extraction file
  579. // #17 Preprocessing: 'out' counter
  580. // #18 Preprocessing: flag that .VCM customization submacros have been loaded
  581. // #26 DBASE field counter
  582. // #27 Preprocessing: DBASE output record counter
  583. // #28 DBASE flag
  584. // #31-#39 Statistics
  585. // #40 Run # size in unique ID
  586. // #41 Data "segment" count. Normally set by "-u count".
  587. // #42 Unique ID control: {0,1,2} for {off,auto,all}; set by UID=on,off,auto
  588. // or "-u uid=n"
  589. // #43 Flag to include ".nam" header file at start of each output file
  590. // #44 Explicit decimal point flag (default = 1)
  591. // #50 Run date for unique ID's (preprocessing); # digits to display (processing)
  592. // #51 Preprocessing: statistics
  593. // #52 Reserved for level 4
  594. // #54 Flag that extraction file(s) present.
  595. // #55 Julian base date for unique ID generation (default = 1-1-2000)
  596. // #56 Reserved for level 4
  597. // #57 Default input record type or length ("r={type|length}");
  598. // Config(F_F_TYPE) when no "r="
  599. // #58 Preprocessing: statistics
  600. // #59 Preprocessing: record-types counter (= 1, always)
  601. // #61 Additional offset for unique ID calculation
  602. // #62 # digits displayed for unique ID (3 parts)
  603. // #63 Buffer ID of .xrf file for obtaining DBASE field names or zero
  604. // #64 Flag variable (hex values)
  605. // 01 to use "fname.LAY" instead of EBCDIC.LAY
  606. // 02 to stop after COBOL preprocessing
  607. // 04 to force explicit decimal point when translating
  608. // COBOL picture lines of type 9...v9...
  609. // 08 to call T-Reg[14] for post processing ('x=').
  610. // 40 when explicit data layout file "lname"
  611. // 100 stops after preprocessing (doesn't execute v=)
  612. // 200 Flag to COBOL2V.VDM to run as submacro.
  613. // 800 to prevent generating unique ID's; archaic; use uid=off
  614. // #65 T-Reg offset for running under WILDFILE.VDM
  615. // #66 Save WILDFILE's Locked-in-Macro ID.
  616. // #67 Input record type (r=type): 0,1,2,3,6=fixed (see #87)
  617. // Determined from Config(F_F_TYPE) if no "r="
  618. // #68 Output record type: 0,1,2,6=fixed,7=DBASE (see #88)
  619. // #69 Zero 1st time; else 1
  620. // #73 Reserved for levels 3 & 4
  621. // #74 Reserved for level 4
  622. // #75 Main output buffer #
  623. // #76 Approx record size
  624. // #77 Current output buffer # for 'out' extractions
  625. // Temporary for initial statistics
  626. // #78 Temporary for stacking/popping XLASTCOLPROC with #77
  627. // #79 Reserved for level 4
  628. // #81 Preprocessing: temporary
  629. // #82 Reserved for levels 3 & 4
  630. // #85 Current data type (b,c,d,e,f,i,l,n,s,u,x,z)
  631. // #86 File header size (h=size) or -1
  632. // #87 Current input record size (r=size) or zero (see #67)
  633. // #88 Output record size or zero (see #68)
  634. // #90 Preprocessing: source data buffer
  635. // #91 Wildfile running flag
  636. // #92 Preprocessing: data layout buffer
  637. // #93 1st line number to convert
  638. // #99 ID flag, possibly set by WILDFILE macro
  639. //
  640. //////////////////////////////////////////////////////////////////////////////
  641. //
  642. // Text register usage:
  643. // Registers 10 - 19 are offset by Num_Reg(65) for running under WILDFILE.
  644. //
  645. // Note: cannot push COBOL preprocessing text register.
  646. // This register is loaded at startup before text registers are pushed.
  647. // This is partly due to the comment stripping processor and partly
  648. // due to WILDFILE interaction.
  649. //
  650. // 2 table of "raw" binary sizes
  651. // 3 DBASE preprocessing: record name
  652. // 4 table of "cooked" binary sizes
  653. // 5 Temporary layout output pathname for editing purposes
  654. // 6 Temporary data output pathame for editing purposes
  655. // 7 Full path to output subdirectory
  656. // 8 Full pathname of .xrf file (DBASE only)
  657. // 9 .lay input pathname.
  658. // 10 Data output pathname.
  659. // 11 Used to execute Vedit commands ('v=') from EBCDIC.LAY
  660. // Used initially in constructing output filenames
  661. // 12 Default T-Reg for custom decoding ('c').
  662. // 13 Default T-Reg for custom record determination ('tc').
  663. // 14 Optional post-processing macro ('x=')
  664. // 15 Source data file's full pathname.
  665. // "NEXT_PEER_CLAUSE" sub-macro (COBOL preprocessing).
  666. // 16 Explicit decimal point handling.
  667. // OCCURS clause sub-macro (COBOL preprocessing).
  668. // 17 Optional delimiter string output after each field.
  669. // REDEFINES clause commenting-out (COBOL preprocessing).
  670. // 18 Holds (path)name of error file. None when empty.
  671. // 19 Main COBOL preprocessing macro. Must not be pushed!
  672. // 46 - 54 Submacros
  673. // 55 - 56 Reserved for COBOL preprocessing.
  674. // 57 - 63 Submacros
  675. // 'A' - 'Z' Code to process each data type (T-Regs 65 - 90).
  676. // 101 Data error processing. Comment stripping, initially.
  677. // 102 Unexpected error breakout trapping macro.
  678. //
  679. //////////////////////////////////////////////////////////////////////////////
  680. // //
  681. // Execution starts here. //
  682. // //
  683. //////////////////////////////////////////////////////////////////////////////
  684. //
  685. // Speed optimize the EBCDIC-2 macro itself.
  686. //
  687. if (File_Exist(VEDIT_TEMP)==0) { //Create vedit/temp dir if needed
  688. File_Mkdir(VEDIT_TEMP)
  689. }
  690. if (#99==0x57495C44&&#91){goto noprep} // No prep for 2nd and later WILDFILE pass
  691. Reg_Prep() // Can't be nested when self-prepping
  692. :NOPREP:
  693. //
  694. // Initialize optional delimiter(s) to be output after each field.
  695. // Overriden by any "v=rs(XDREG,'delimiter string')" in the layout file.
  696. //
  697. #103 = Macro_Num // #103 = T-Reg # this macro is in
  698. if (#99==0x57495C44) { // When WILDFILE is running...
  699. if (!#91){ // Set == 0 by Wildfile
  700. #65 = Reg_Free // #65 = 1st available T-Reg
  701. #69 = 0 // 1st time in
  702. }
  703. } else {
  704. #65 = #69 = 0 // For backwards compatibility
  705. }
  706. #91++ // Update Wildfile pass counter
  707. if (!#69){ // 1st time in
  708. //
  709. // Check version #.
  710. //
  711. #0 = 520
  712. if (Version_Num<#0) {
  713. Reg_Set(1,"EBCDIC translation package requires VEDIT PLUS version ")
  714. #1 = #0/100
  715. #2 = Remainder
  716. ITOA(#1,1,LEFT+NOCR+APPEND)
  717. Reg_Set(1,".",APPEND)
  718. ITOA(#2,1,LEFT+NOCR+APPEND)
  719. Reg_Set(1," or later.",APPEND)
  720. Alert()
  721. Dialog_Input_1(0,`"Error","|@(1)"`)
  722. if (Is_Quiet) {
  723. XALL(1)
  724. } else {
  725. Reg_Empty(0)
  726. Reg_Empty(1)
  727. Break_Out(EXTRA)
  728. }
  729. }
  730. //
  731. // Load T-Reg[19] with COBOL preprocessor and speed optimize the code.
  732. //
  733. Reg_Empty(#65+19) // In case COBOL2V can't be found
  734. Reg_Load(#65+19,"COBOL2V.VDM",EXTRA+NOERR)
  735. Reg_Prep(#65+19)
  736. //
  737. // Use T-Reg[1] to load and speed optimize submacros.
  738. // Then distribute the code to their proper T-Regs.
  739. //
  740. Reg_Set(1,$
  741. //////////////////////////////////////////////////////////////////////////
  742. // //
  743. // Submacros for EBCDIC-2.VDM //
  744. // Last change: 07/24/2003 //
  745. // //
  746. // Note: most named submacros are now contained in EBCDIC-2.VCM //
  747. // for use by custom macros. They are reserved for this //
  748. // purpose. These are: a-f, h, i, s, u, x & z. //
  749. // //
  750. // Note: Named submacros 'a' - 'z' are actually stored into //
  751. // T-Reg['A'] - T-Reg['Z']. To invoke a given named macro, //
  752. // convert its name to upper case; e.g., call('r'-32). //
  753. // //
  754. //////////////////////////////////////////////////////////////////////////
  755. //
  756. // T-Reg[l] - Floating Point.
  757. //
  758. Reg_Set(l,`
  759. //
  760. // "NULL" for undefined?
  761. // Go figure!
  762. //
  763. if ((match("|{|HD5|HE4|HD3|HD3,|H80|H00|H00|H00}")==0)||CC==0){
  764. #7 = 0
  765. #9 = EBC_Settings(Field_Size)
  766. if (XFSIZ>4){ // DOUBLE
  767. if (#9==0){
  768. #7 = 16
  769. }
  770. } else { // FLOAT
  771. if (#9==0){
  772. #7 = 7
  773. }
  774. }
  775. if (#9==0){
  776. #9=#7
  777. }
  778. if (EBC_Settings(Out_Point) & 0xff){
  779. #9++
  780. }
  781. if (!EBC_Settings(Unsigned)){
  782. #9++
  783. }
  784. DC(XFSIZ)
  785. IC(' ',COUNT,#9)
  786. }else{
  787. #1=upf('l',XFSIZ)
  788. if (#1) {if (#38){call(101,"DATERR")}}
  789. }
  790. `) // [l]
  791. //
  792. // T-Reg[48] - Unique ID Processing.
  793. //
  794. Reg_Set(48,`
  795. //
  796. // UID - Generate unique ID at end of fixed portion of variable length record.
  797. // Similar to 'rb' & 're' processing, above.
  798. // Enter: #40 = # digits to display segment count of unique ID.
  799. // #50 = # digits to display elapsed days count of unique ID.
  800. // #62 = # digits to display record count of unique ID.
  801. // #41 = data segment/section/run #.
  802. // #55 = days elapsed since base date.
  803. // XRecNum = record #.
  804. // #61 = additional offset when more than 1 run per day.
  805. //
  806. :UID:
  807. if (XQCD){ // If Quoting & comma delimiting...
  808. IT(',"') // Output comma and quote mark
  809. NI(#55,SIMPLE+FILL+COUNT,#50) // Output JDate
  810. if (#40>0){
  811. NI(#41,SIMPLE+FILL+COUNT,#40) // Output the segment #
  812. }
  813. NI(XRecNum+#61,SIMPLE+FILL+COUNT,#62) // Output the record #
  814. IC('"') // Output quote mark
  815. } else { // Else...
  816. IC(' ') // Space for separation
  817. NI(#55,SIMPLE+FILL+COUNT,#50) // Output JDate
  818. if (#40>0){
  819. NI(#41,SIMPLE+FILL+COUNT,#40) // Output the segment #
  820. }
  821. NI(XRecNum+#61,SIMPLE+FILL+COUNT,#62) // Output the record #
  822. }
  823. `) // [48]
  824. //
  825. // T-Reg[49] - DBASE preprocessing.
  826. //
  827. Reg_Set(49,`
  828. //
  829. // DBINIT0 - Zero-out DBASE header's 1st 32-byte structure; insert '3' for
  830. // signature and current date in YMD (binary) format where
  831. // 'y' = year -1900.
  832. // Initialize record length (pos 10,11) = 1 for the initial blank
  833. // column, the deleted-record field.
  834. // Set 0x0d byte at end of header.
  835. //
  836. // Enter: #16 = ID of extraction buffer
  837. // #28 > 0 (DBASE flag)
  838. //
  839. :DBINIT0:
  840. Num_Push(0,5)
  841. Buf_Switch(#16) // DBASE output file
  842. Del_Block(0,FileSize)
  843. //
  844. // Zero-out initial header structure.
  845. // Set 0x0d byte at end.
  846. //
  847. Ins_Char(0,COUNT,32)
  848. Ins_Char(0x0d) // End of header byte
  849. Config(F_REC_HEAD,FSize,LOCAL)
  850. //
  851. // Set record-length to 1 to account for initial "deleted-record" field.
  852. //
  853. GP(10)
  854. Ins_Char(1,OVERWRITE)
  855. //
  856. // Set #1,#2,#3 = current date = MDY.
  857. //
  858. Buf_Switch(Buf_Free(EXTRA))
  859. OI() DATE(NOMSG) OI(CLEAR)
  860. BOF()
  861. #1=NumEval(ADVANCE+SUPPRESS)
  862. c(1)
  863. #2=NumEval(ADVANCE+SUPPRESS)
  864. c(1)
  865. #3=NumEval()
  866. Buf_Quit(OK)
  867. //
  868. // Enter DBASE signature and current date as YMD (binary).
  869. //
  870. Buf_Switch(#16)
  871. BOF()
  872. Ins_Char(3,OVERWRITE)
  873. Ins_Char(#3-1900,OVERWRITE)
  874. Ins_Char(#1,OVERWRITE)
  875. Ins_Char(#2,OVERWRITE)
  876. //
  877. Buf_Switch(XLay)
  878. Num_Pop(0,5)
  879. return
  880. `) // [49]
  881. //
  882. // T-Reg[50] - Output diversion.
  883. //
  884. Reg_Set(50,`
  885. //
  886. // POST - Diversion termination.
  887. // Enter: Buf_Num = XLayBufNum.
  888. // Retrn: Buf_Num = XLayBufNum.
  889. //
  890. :POST:
  891. BS(XData)
  892. if (#42){ // If Unique ID wanted...
  893. if (XQCD){ // If Quoting & comma delimiting...
  894. IT(',"') // Output comma and opening quote
  895. NI(#55,SIMPLE+FILL+COUNT,#50) // Output JDate
  896. if (#40>0){
  897. NI(#41,SIMPLE+FILL+COUNT,#40) // Output the segment #
  898. }
  899. NI(XRecNum+#61,SIMPLE+FILL+COUNT,#62) // Output the record #
  900. IT('"') // Output closing quote
  901. } else { // Else...
  902. IC(' ') // Space for separation
  903. NI(#55,SIMPLE+FILL+COUNT,#50) // Output JDate
  904. if (#40>0){
  905. NI(#41,SIMPLE+FILL+COUNT,#40) // Output the segment #
  906. }
  907. NI(XRecNum+#61,SIMPLE+FILL+COUNT,#62) // Output the record #
  908. }
  909. }
  910. //
  911. // Move translated input fields into output file.
  912. //
  913. RCB(0,0,CP,DELETE)
  914. BS(#77)
  915. EOF()
  916. if (RSIZE(0)>0){
  917. if (#28&&AtBOL){
  918. ic(' ')
  919. // XLCP(XLCP+1) May need to update when appending allowed...
  920. }
  921. RI(0)
  922. }
  923. //
  924. // Append newline char(s), if specified.
  925. //
  926. if ((0<=#68)&&(#68<6)){
  927. if ((#68&1)==0){IC(0x0d)} // DOS and MAC
  928. if (#68<2){IC(0x0a)} // DOS and UNIX
  929. }
  930. //
  931. BS(XLay)
  932. return
  933. //
  934. // PRE - Diversion initialization.
  935. // Any passed over bytes translated.
  936. // All processed bytes moved into the output buffer.
  937. // Enter: Buf_Num = layout buffer XLayBufNum.
  938. // Retrn: Buf_Num = layout buffer XLayBufNum.
  939. //
  940. :PRE:
  941. //
  942. // Set XNextCol = XAdjBeg = column # of 1st field adjusted for inflation
  943. // (The 1st column must be specified by next layout line).
  944. // Do default processing on any passed-over fields.
  945. //
  946. SPOS()
  947. s("|<|Y|w",advance) //Pick up start of first field from next layout line
  948. XAB(NE()+XSO+XI) //XAdjBeg = beginning column # (inflation adjusted)
  949. RPOS() //Back to "rb" line
  950. call(57) //Translate any passed-over fields
  951. //XNextCol = 1st column #, inflation adjusted
  952. //
  953. // Move translated bytes into output buffer via T-Reg[0].
  954. //
  955. RCB(0,0,CP,DELETE) //Move bytes into T-Reg[0]
  956. BS(#77) //Switch to output buffer
  957. EOF()
  958. //
  959. // Include any .nam header file, if so specified.
  960. //
  961. if (#43&&AtBOF){
  962. Ins_File("|(FILE_ONLY).nam")
  963. }
  964. if (RSIZE(0)>0){
  965. if (#28&&AtBOL){
  966. ic(' ')
  967. XLCP(XLCP+1) // Note: XLCP already reflects the processed output length
  968. }
  969. RI(0) //Insert the bytes
  970. }
  971. //
  972. BS(XLay) //Reenter layout buffer
  973. return
  974. `) // [50]
  975. //
  976. // T-Reg[53] - Name Pre-Processor (error checking).
  977. // Name may be quoted or not; quotes stripped.
  978. // Return: T-Reg[0] = name
  979. // Cur_Pos past name["].
  980. //
  981. Reg_Set(53,`
  982. if (cc!='''&&cc!='"'){
  983. Set_Marker(8,Cur_Pos)
  984. sb("|{|b,//,|>}",cp,eolpos+1)
  985. Set_Marker(9,Cur_Pos)
  986. } else {
  987. rcb(0,cp,cp+1,norestore)
  988. Set_Marker(8,Cur_Pos)
  989. if(!sb(@0,cp,eolpos,advance+noerr)){
  990. goto BADLAY
  991. }
  992. Set_Marker(9,Cur_Pos-1)
  993. }
  994. rcb(0,Marker(8),Marker(9))
  995. return
  996. //
  997. :BADLAY:
  998. chain(#103,"BAD_LAY")
  999. `) // [53]
  1000. //
  1001. // T-Reg[54] - Name Processor.
  1002. // Name may be quoted or not; quotes stripped.
  1003. // Return: T-Reg[0] = name
  1004. // Cur_Pos past name["].
  1005. //
  1006. //
  1007. Reg_Set(54,`
  1008. if (cc!='''&&cc!='"'){
  1009. SM(8,CP)
  1010. sb("|{|b,//,|>}",cp,eolpos+1)
  1011. SM(9,CP)
  1012. }else{
  1013. rcb(0,cp,cp+1,norestore)
  1014. SM(8,Cur_Pos)
  1015. sb(@0,cp,eolpos,advance)
  1016. SM(9,CP-1)
  1017. }
  1018. RCB(0,Marker(8),Marker(9))
  1019. `) // [54]
  1020. //////////////////////////////////////////////////////////
  1021. // //
  1022. // T-Reg[55] & T-Reg[56] //
  1023. // Reserved for COBOL2V.VDM //
  1024. // //
  1025. //////////////////////////////////////////////////////////
  1026. //
  1027. // T-Reg[57] - Perform default translation on passed-over fields.
  1028. //
  1029. Reg_Set(57,`
  1030. BS(XData)
  1031. if ((#0=XAB-XNC)>0){
  1032. XDC(XDC+#0) // Update total-bytes-processed counter
  1033. XLCP(XLCP+#0)
  1034. if (XDefType=='e'){
  1035. TRB(CP,CP+#0,REVERSE+NORESTORE)
  1036. }else{if (XDefType=='a'){
  1037. TRB(CP,CP+#0,NORESTORE)
  1038. }else{
  1039. C(#0)
  1040. }}
  1041. XNC(XAB)
  1042. }
  1043. `) // [57]
  1044. //
  1045. // T-Reg[58] - Extraction Filename Processor.
  1046. //
  1047. // Enter: Buf_Num = XLayBufNum.
  1048. // Retrn: #77 = output buffer ID.
  1049. // #54 |= 1 (flag to output unique # at end of main output record).
  1050. // Buf_Num = XLayBufNum.
  1051. //
  1052. // Note: to force UID's on main records that have no extracted subsections,
  1053. // use uid=on option in the .lay file or as a "-u" invocation parameter.
  1054. //
  1055. Reg_Set(58,`
  1056. call(54) // T-Reg[0] = name
  1057. bs(#75) // Switch to main buffer so that we can
  1058. // use e.g. tx "|(FILEONLY).as1"
  1059. FO("|@(0)",NOMSG+NOEVENT)
  1060. #77=BN // #77 = output buffer
  1061. #54 = #54 | 1
  1062. XLCP(0)
  1063. BS(XLay)
  1064. `) // [58]
  1065. //
  1066. // T-Reg[59] - Extraction Filename Preprocessor.
  1067. //
  1068. // Processes 'code "filename"[,R]' where 'R' is a one or two letter
  1069. // record name for DBASE output.
  1070. // Deletes any existing file.
  1071. // Opens an empty file.
  1072. //
  1073. // For DBASE, generates 1st header row and sets T-Reg[3] <== 'R', if
  1074. // specified.
  1075. //
  1076. // Enter: #28 = DBASE flag.
  1077. // Retrn: #16 = buffer ID of extraction file.
  1078. // #27++ DBASE output record counter.
  1079. // [3] = #28 && 'R' present ? upto 1st 2 letters of "R" : [3]
  1080. //
  1081. // Called when preprocessing 'out'.
  1082. //
  1083. Reg_Set(59,`
  1084. call(53) // T-Reg[0] = filename
  1085. //
  1086. //
  1087. //
  1088. if (#28) { // If DBASE...
  1089. if ( match("|[|w],|[|w]",ADVANCE)==0) {
  1090. if (match("|a|[|a]")==0){
  1091. RegCopyBlock(3,cp,cp+cmat,norestore)
  1092. }
  1093. }
  1094. }
  1095. //
  1096. #27++
  1097. if (Buf_Free()>0){
  1098. bs(#75) // Switch to main buffer so that we can
  1099. // use e.g. tx "|(FILEONLY).as1"
  1100. File_Delete(@0,OK+NOERR)
  1101. FO("|@(0)",OVERWRITE+NOMSG+NOERR+NOEVENT)
  1102. #16 = Buf_Num
  1103. if (#68<6) {
  1104. Config(F_F_TYPE,#68,LOCAL)
  1105. } else {
  1106. if (#28) { // If DBASE...
  1107. Config(F_F_TYPE,32,LOCAL) // Header consists of 32-byte structures
  1108. } else { // else...
  1109. Config(F_F_TYPE,64,LOCAL) // For now...
  1110. }
  1111. }
  1112. } else {
  1113. goto TOOMANY
  1114. }
  1115. //
  1116. // For DBASE, initialize 1st 32-byte header structure; append terminating <cr>.
  1117. //
  1118. if (#28) { call(49) } // DBINIT0()
  1119. //
  1120. Buf_Switch(XLay)
  1121. return
  1122. :TOOMANY:
  1123. chain(#103,"TOO_MANY")
  1124. :BADLAY:
  1125. chain(#103,"BAD_LAY")
  1126. `) // [59]
  1127. //
  1128. // T-Reg[62] - Progress Display.
  1129. //
  1130. // First time, display estimated processing time.
  1131. // Also display persistent "Converted records: "
  1132. // Every time, display count and percentage of records processed.
  1133. //
  1134. Reg_Set(62,`
  1135. if (XRecNum==#31){call(63)}
  1136. WH(#33)
  1137. NT(XRecNum,NOCR) // count
  1138. #37=FSize-CP
  1139. if (#37>1000000){#34=100-(#37/(#36/100))}
  1140. else{if (#36==0){#34=100}
  1141. else{#34=100-((100*#37)/#36)}
  1142. }
  1143. Message(" (")
  1144. NT(#34,LEFT+NOCR) // percentage
  1145. Message("%)")
  1146. `) // [62] Progress Display
  1147. //
  1148. // T-Reg[63] - Progress Display (Initial Message).
  1149. //
  1150. // Display estimated processing time.
  1151. // Also display persistent "Converted records: "
  1152. // Empties itself on exit.
  1153. //
  1154. Reg_Set(63,`
  1155. #35=TT
  1156. WH(1)
  1157. Message("Estimated processing time is ")
  1158. #34=((#35-#32)*((#36/(#36-FSize+CP)))+500)/1000
  1159. NT(#34,LEFT+NOCR)
  1160. Message(" seconds\n")
  1161. Message("Converted records: ")
  1162. #33=WH
  1163. RE(MN,EXTRA)
  1164. `) // [63] Progress Display (Initial Message)
  1165. ///////////// [65] - [90] correspond to [A] - [Z], so DO NOT USE ////////////
  1166. //
  1167. // T-Reg[101] - Process invalid data error messages.
  1168. //
  1169. //
  1170. // DATERR - Report errors decompressing packed data, if enabled.
  1171. // On first error, report name of file being translated,
  1172. // the name of the edited layout file and a short description
  1173. // of a report line:
  1174. // XRecNum (data record #)
  1175. // .TMP layout line #
  1176. // the layout line itself
  1177. // position in the input file at which the data field began
  1178. // the source bytes themselves (in hex format).
  1179. // Upto #38 errors (default 1000) will be reported.
  1180. //
  1181. // Enter: T-Reg[103] = source bytes.
  1182. //
  1183. Reg_Set(101,`
  1184. :DATERR:
  1185. if (RSize(#65+18) && #38){ // If error reporting enabled...
  1186. num_push(1,10)
  1187. #1 = bn // Store current edit buffer id
  1188. //
  1189. // Set T-Reg[0] = offended layout line.
  1190. //
  1191. bs(XLay) // Switch to the edited layout file
  1192. char(-newline_chars)
  1193. rc(0,0) // Copy the line into T-Reg[0]
  1194. #2 = Cur_Line // Get its line #
  1195. line(1)
  1196. //
  1197. // Set T-Reg[1] = pathname of edited layout file layout.tmp
  1198. //
  1199. or(1) // Begin diversion into T-Reg[1]
  1200. nw(EXTRA+NOMSG) // Get full pathname of the edited layout file
  1201. or(CLEAR) // Turn diversion off
  1202. //
  1203. // On first error, report general information.
  1204. //
  1205. File_Open("|@(#65+18)",OVERWRITE+NOERR+NOMSG) // Switch to the error file
  1206. if ( File_Size == 0 ) {
  1207. //
  1208. // Output name of source data file.
  1209. //
  1210. Ins_Text("***** Invalid compressed data item(s) in ")
  1211. Reg_Ins(#65+15)
  1212. Ins_Newline(2)
  1213. //
  1214. // Describe error report line.
  1215. //
  1216. Ins_Text("line = layout line number from edited file ")
  1217. ri(1); re(1)
  1218. Ins_Text("record = source record number");in
  1219. Ins_Text("location = source file position of start of invalid data item (from 0)");in
  1220. in(2)
  1221. Ins_Text(" line data descriptor record location data item (hex)");in
  1222. Ins_Text(" ==== =============== ====== ======== ===============");in
  1223. }
  1224. //
  1225. // Report the edited layout line #.
  1226. //
  1227. Ins_Text(" ")
  1228. ni(#2,NOCR) // edited layout line #
  1229. //
  1230. // Include the edited layout line.
  1231. //
  1232. Ins_Text(" ")
  1233. ri(0) // The edited layout line
  1234. //
  1235. // Report the data record #.
  1236. //
  1237. Ins_Char(' ', COUNT, BOL_Pos + 27 - Cur_Pos )
  1238. Del_Block(BOL_Pos+27,cp)
  1239. ni(XRecNum,FORCE+NOCR) // data record #
  1240. //
  1241. // Report the field's starting location in the source file (from 0).
  1242. //
  1243. bs(XData) // Switch to the data source file
  1244. #3 = #36 - (File_Size - Cur_Pos) - XFSIZ
  1245. File_Open("|@(#65+18)",NOMSG) // Switch back to the error file
  1246. Ins_Text(" ")
  1247. ni(#3,FORCE+NOCR) // The field's starting position
  1248. //
  1249. // Display the source field in hex.
  1250. //
  1251. Ins_Text(" ")
  1252. Out_Ins()
  1253. Reg_Type(103,0x800) // Display in hex format
  1254. Out_Ins(CLEAR)
  1255. Ins_Newline(1)
  1256. //
  1257. // Finish up and return.
  1258. //
  1259. #38--
  1260. bs(#1)
  1261. num_pop(1,10)
  1262. }
  1263. return
  1264. `) // [101,DATERR]
  1265. //
  1266. // T-Reg[102] - Unexpected error breakout trap.
  1267. // Writes message into error file.
  1268. // Restores some original config values.
  1269. // Terminates.
  1270. //
  1271. Reg_Set(102,`
  1272. Reg_Lock_Macro(CLEAR) // Disable further error trapping
  1273. Reg_Empty(0)
  1274. File_Open("|@(#65+18)",OVERWRITE+NOERR+NOMSG) // Access error file
  1275. EOF
  1276. #0 = Cur_Pos
  1277. Ins_Newline()
  1278. Ins_Text("***** Unexpected breakout occurred.")
  1279. Ins_Newline()
  1280. #1 = Cur_Pos
  1281. Reg_Ins(120)
  1282. Reg_Copy_Block(0,#0,#1)
  1283. Reg_Push(0,0)
  1284. Call(#103,"CleanUp")
  1285. Call(#103,"CloseErr")
  1286. Reg_Pop(0,0)
  1287. Num_Pop(70,99) //Restore numeric regs
  1288. Num_Pop(0,59)
  1289. Config(U_AUTO_CFG,#0) //Restore user's config values
  1290. Config(F_AUTO_SAVE,#1)
  1291. Config(F_OVER_MODE,#2)
  1292. // no Config(F_F_TYPE,#3)
  1293. // no Config(F_REC_HEAD,#4)
  1294. Config(E_EXP_TAB,#5)
  1295. Config(E_RETAB_BK,#6)
  1296. Config(E_RETAB_FILL,#7&0xff)
  1297. Config(S_E_MORE,#8)
  1298. Config(D_DSP_WRAP,#9)
  1299. Num_Pop(0,10) //Restore remaining user numregs
  1300. Reg_Lock_Macro(#66)
  1301. #69 = 1 //WILDFILE flag for next time in
  1302. if (Is_Quiet || Is_Option(y)){
  1303. XALL(1)
  1304. } else {
  1305. if (Reg_Size(0)){
  1306. Reg_Type(0)
  1307. }
  1308. if (#105){
  1309. vm(SET)
  1310. }
  1311. }
  1312. `) // [102] Unexpected Error Breakout
  1313. $) // [1] - Submacros
  1314. Reg_Prep(1)
  1315. Call(1)
  1316. Reg_Empty(1)
  1317. } // 1st time in
  1318. :START:
  1319. Num_Push(0,10)
  1320. #0 = Config(U_AUTO_CFG,0) // Turn off auto-save-config
  1321. #1 = Config(F_AUTO_SAVE,0) // Turn off auto-save-changes every x minutes
  1322. #2 = Config(F_OVER_MODE,0) // Allow insert/delete even for fixed-records
  1323. #3 = Config(F_F_TYPE)
  1324. #4 = Config(F_REC_HEAD)
  1325. #5 = Config(E_EXP_TAB) // Tabs complicate COBOL processing
  1326. #6 = Config(E_RETAB_BK)
  1327. #7 = Config(E_RETAB_FILL)
  1328. #8 = Config(S_E_MORE,0)
  1329. #9 = Config(D_DSP_WRAP,0)
  1330. #66 = Reg_Lock_Macro // Save WILDFILE's locked-in-macro ID
  1331. Num_Push(0,59) // Save numeric regs used herein
  1332. Num_Push(70,99) // Except for #60-#69
  1333. //
  1334. // Default delimiter between output fields (none, normally)
  1335. //
  1336. XDREG(#65+17) // Register to hold user defined output field delimiter
  1337. Reg_Set(XDREG,'') // To define, use "v=Reg_Set(XDREG,'delimiter_string')"
  1338. //Reg_Set(XDREG," | ") // Or uncomment one of these lines
  1339. //Reg_Set(XDREG,'^') // Any string is permissible
  1340. //
  1341. #8 = 0 //No customizing record determining submacro
  1342. #26 = #27 = #28 = 0 //Reset DBASE field & record counters & flag
  1343. #76 = 0 //For calculating approx. line size
  1344. #105 = vm; vm(CLEAR)
  1345. Reg_Lock_Macro(102)
  1346. /////////////////////////////////////////////////////////////////////////////
  1347. //
  1348. // Sign-on and File Handling.
  1349. //
  1350. // Set #90 = source data file's buffer ID unless "-N2" was present on the
  1351. // command line; in which case, the current buffer is assumed to
  1352. // be the layout file (no other file is processed). Normally, the
  1353. // current edit buffer is considered to be the source data file.
  1354. // It will be closed and reopened for reading in another buffer
  1355. // and the initial buffer will be used as the standard output
  1356. // buffer.
  1357. //
  1358. // Set #92 = buffer ID of/for the data layout file.
  1359. // Presume any file in buffer[2] is the data layout file if
  1360. // this macro is being run from the command line: e.g.,
  1361. // vpw -x ebcdic-2 dname.ebc lname.lay
  1362. //
  1363. // Set #75 = buffer number for translated output; referred to herein as
  1364. // the standard output buffer.
  1365. //
  1366. // #1 used herein as a flag to prevent final renaming of the data
  1367. // output file to ".dbf" as determined by the layout file
  1368. // "r=n,DBASE-III". This flag is set below when processing "-a".
  1369. //
  1370. // To initiate data conversion manually, the layout file must be named
  1371. // EBCDIC.LAY and exist in the current or VEDIT HOME directory.
  1372. // In which case, after loading the data file, the user can initiate
  1373. // processing via {Misc,Load/Execute macro,EBCDIC-2.VDM}.
  1374. //
  1375. // Likewise, the layout file must be named EBCDIC.LAY to run under
  1376. // WILDFILE.VDM.
  1377. //
  1378. // To initiate just COBOL preprocessing manually, VEDIT must be started
  1379. // with the "-N2" option. Then, after loading the layout file, processing
  1380. // can be initiated as in the above paragraph. Or, run COBOL2V.VDM.
  1381. //
  1382. // E.g., vpw -n2 lname.lay
  1383. // {Misc,Load/Execute macro,EBCDIC-2.VDM}
  1384. //
  1385. //
  1386. #90 = #75 = Buf_Num //#90 = current buffer #
  1387. #92 = 0 //#92 = layout buffer ID; not yet set
  1388. #64 = 0 //Set = 1 to always use fname.LAY
  1389. //instead of EBCDIC.LAY when no explicit
  1390. //filename parameter "lname"
  1391. //
  1392. // For autoexecution (-x), presume anything in buffer #2 is the layout file.
  1393. //
  1394. // if ( -x && !Wildfile && 2nd buffer )
  1395. if ( Is_Auto_Execution && #99!=0x57495C44 && Buf_Status(2) >= 0 ) {
  1396. #92 = 2 // #92 = data layout buffer
  1397. #64 = #64 | 0x40 // Flag data description file already loaded
  1398. //
  1399. // Else, if "-N2", presume the current buffer has/will have the layout file.
  1400. //
  1401. } else { if (Is_Option(n) && (N_Option&2)) {
  1402. #92 = Buf_Num // #92 = data layout buffer
  1403. if ( Is_Open_Write ) {
  1404. #64 = #64 | 0x40 // Flag data description file already loaded
  1405. }
  1406. }}
  1407. if (Is_Option(n)) {
  1408. #0 = #64 & 0x40 //Save "explicit data layout file" bit
  1409. if (N_Option == 0) { #64 = 1 } // Handle "-N" with no parameter
  1410. #64 = #64 | (N_Option & 0xfffff) | #0
  1411. }
  1412. //
  1413. // Sign on.
  1414. //
  1415. if (#69==0) { if (!Is_Quiet) {
  1416. if ( OS_Type == 1 && ( Screen_Lines < 15 || Screen_Cols < 57 )) {
  1417. Screen_Size(15,57)
  1418. Screen_Init()
  1419. } else {
  1420. Win_Clear()
  1421. }
  1422. Type_Newline()
  1423. #0 = ( Screen_Cols - 57 ) >> 1
  1424. Type_Space(#0)
  1425. Message('*********************************************************\n');TS(#0)
  1426. Message('* EBCDIC-2.VDM 09/26/2003 *\n');TS(#0)
  1427. Message('* Convert EBCDIC file with encoded fields to ASCII *\n');TS(#0)
  1428. Message('*********************************************************\n');TN()
  1429. //
  1430. // If no file open, prompt for filename and open it.
  1431. //
  1432. if (#64&2) { // If just COBOL preprocessing...
  1433. Reg_Set(0,"data layout file")
  1434. } else { // Normally...
  1435. Reg_Set(0,"file to convert")
  1436. }
  1437. if (!Is_Open_Write) {
  1438. repeat(ALL) {
  1439. Reg_Set(0,"Enter name of ",INSERT)
  1440. Reg_Set(0,": ",APPEND)
  1441. Type_Newline()
  1442. Reg_Type(0)
  1443. Get_Input(#65+10,"",NOCR)
  1444. if (File_Exist(@(#65+10))) { Break }
  1445. Alert()
  1446. Message("\nFile not found; please try again or <Ctrl-C> to cancel.\n")
  1447. }
  1448. File_Open("|@(#65+10)",NOEVENT)
  1449. #90 = Buf_Num
  1450. if (#64&2) {
  1451. #92 = Buf_Num
  1452. #64 = #64 | 0x40
  1453. }
  1454. }
  1455. }}
  1456. // if (wstat($)<0){wr($,5,bottom)};Reg_Lock_Macro(CLEAR);ws($);update() ?
  1457. if ( File_Size == 0 ){
  1458. goto DONE
  1459. }
  1460. //
  1461. // Set Current Directory to source data file.
  1462. //
  1463. Reg_Push(0,0)
  1464. Reg_Set(0,INPUT_FILE)
  1465. Buf_Switch(Buf_Free(EXTRA))
  1466. Reg_Ins(0)
  1467. EOF()
  1468. Replace("|{\,:}","",REVERSE)
  1469. if(Match_Item==2){
  1470. Ins_Text(":\")
  1471. }
  1472. Del_Line()
  1473. Reg_Copy(1,0)
  1474. ChDir(@(1))
  1475. Buf_Quit(OK)
  1476. Buf_Switch(#90)
  1477. //
  1478. // Set T-Reg[10] = data output pathname.
  1479. // = path\fname.asc (normally)
  1480. // = user specified (-a)
  1481. //
  1482. // Set #1 if "-a" input parameter.
  1483. //
  1484. #1 = 0 // Allow renaming output file to *.dbf
  1485. if ( Is_SaveAs ) {
  1486. #1 = 1 // Disallow changing output file's extension
  1487. Reg_Set(#65+10,PATH_NAME) //T-Reg[10] = user-specified output pathname
  1488. } else {
  1489. Reg_Set(#65+10,PATH_ONLY) // = path
  1490. Reg_Set(#65+10,"\",APPEND)
  1491. Reg_Set(#65+10,FILE_ONLY,APPEND) // = path\fname
  1492. Reg_Set(#65+10,".ASC",APPEND) // = path\fname.ASC
  1493. }
  1494. //
  1495. // Set T-Reg[7] = output_path\.
  1496. //
  1497. #0 = Buf_Num
  1498. Buf_Switch(Buf_Free(EXTRA))
  1499. Reg_Ins(#65+10) //buf[] = full_path_name (output)
  1500. Search("\",BEGIN+ALL+ADVANCE+NOERR) //Skip over pathname
  1501. Reg_Copy(7,0) //T-Reg[7] = output_path\
  1502. Buf_Quit(OK)
  1503. Buf_Switch(#0)
  1504. //
  1505. // Delete default error file from the output directory.
  1506. // Set T-Reg[18] with its full pathname.
  1507. //
  1508. Reg_Set(#65+18,@(7))
  1509. Reg_Set(#65+18,`ebcdic.err`,APPEND)
  1510. File_Delete( @(#65+18), OK + NOERR )
  1511. //
  1512. // Check for missing/empty data file.
  1513. //
  1514. if (! Is_Open_Write || FSize == 0 ) {
  1515. Reg_Empty(1)
  1516. Out_Reg(1,APPEND)
  1517. Message("\n***** Misssing or empty data file ")
  1518. Reg_Type(0)
  1519. Message("\n")
  1520. Out_Reg(CLEAR)
  1521. Call("ERRMSG")
  1522. if (Is_Quiet) {
  1523. XALL(1)
  1524. } else { if (#99==0x57495C44) {
  1525. break_out
  1526. } else {
  1527. break_out(EXTRA)
  1528. }}
  1529. }
  1530. //
  1531. // Set T-Reg[15] = source_data_pathname.
  1532. //
  1533. Out_Reg(#65+15)
  1534. Name_Read(EXTRA+NOMSG+NOCR)
  1535. Out_Reg(CLEAR)
  1536. //
  1537. // Close the source data file.
  1538. // Open an empty output buffer with the specified data output filename.
  1539. // Set #75 = main output buffer ID.
  1540. //
  1541. Buf_Empty(OK)
  1542. File_Open_Write(@(#65+10),OVERWRITE+OK+NOMSG)
  1543. #75 = Buf_Num
  1544. //
  1545. // Set T-Reg[6] = temporary output pathname to allow editing the
  1546. // source data file = outputpath\EBCDAT.TMP.
  1547. //
  1548. Reg_Set(0,@7) //T-Reg[0] = outputpath\
  1549. Reg_Set(0,"EBCDAT",APPEND) //T-Reg[0] = outputpath\EBCDAT
  1550. Reg_Set(6,@0) //T-Reg[6] =
  1551. for ( #0=0; FileExist("|@(6).TMP",NOERR); #0++ ) {
  1552. Reg_Set(6,@0) // T-Reg[6] = outputpath\EBCDAT
  1553. Out_Reg(6,APPEND) // Divert output to end of T-Reg[6]
  1554. Type_Char((#0/10)+'0')
  1555. Type_Char(remainder+'0')
  1556. Out_Reg(CLEAR) // Stop diverting output
  1557. }
  1558. Reg_Set(6,".TMP",APPEND) // T-Reg[6] = outputpath\EBCDAT[nn].TMP
  1559. //
  1560. // Reopen the source data file with temporary output pathname T-Reg[6].
  1561. // Set #90 = buffer ID.
  1562. //
  1563. File_Open('"|@(#65+15)" -a "|@(6)"',OVERWRITE+OK+NOMSG)
  1564. #90 = Buf_Num
  1565. Config(F_OVER_MODE,0,ALL)
  1566. //
  1567. // Set T-Reg[9] = "source_data_path\fname.LAY".
  1568. // Set T-Reg[11] = "fname.LAY".
  1569. //
  1570. Buf_Switch(Buf_Free(EXTRA)) //Switch to temp buffer
  1571. Reg_Ins(#65+15) //buf[] = source_data_full_pathname
  1572. Replace(".|M|>","",REVERSE+NOERR) //Delete any existing extent
  1573. Ins_Text(".LAY",BEGIN) //Append ".LAY"
  1574. Reg_Copy_Block(9,0,File_Size) //T-Reg[9] = "path\fname.LAY"
  1575. //
  1576. Search("\",BEGIN+ALL+ADVANCE+NOERR) //Skip over pathname
  1577. Reg_Copy_Block(#65+11,CP,EOL_Pos) //T-Reg[11] = "fname.LAY"
  1578. //
  1579. Buf_Quit(OK) //Discard temporary buffer
  1580. //
  1581. // Open data layout file with temporary name for editing.
  1582. // Unless already loaded, determine name: EBCDIC.LAY or fname.LAY;
  1583. // then load it from the current directory if possible;
  1584. // else from the VEDIT Home Directory;
  1585. // quit if no such file.
  1586. // Enter: T-Reg[9] = "source_data_path\fname.LAY".
  1587. // T-Reg[11] = "fname.LAY".
  1588. //
  1589. if (#92>0) {
  1590. Buf_Switch(#92) //Switch to data layout buffer
  1591. }
  1592. if (#64&0x40) { // If explicit data layout file
  1593. Reg_Set(9,INPUT_FILE) // Full pathname for error handling
  1594. Out_Reg(#65+11)
  1595. Name_Read(NOMSG) // Filename only (for consistency)
  1596. Out_Reg(CLEAR)
  1597. } else { // No explicit layout file
  1598. if (!(#64&1)) { // If !( -N 1 ) i.e., not fname.lay
  1599. Reg_Set(9,"ebcdic.lay") // full pathname (current directory)
  1600. Reg_Set(#65+11,"ebcdic.lay") // for VEDIT home directory
  1601. }
  1602. Reg_Set(0,"UNPAKEBC.DAT") // Archaic name
  1603. if (File_Exist(@(9))) { //If local layout file, load it
  1604. File_Open("|@(9)",OVERWRITE+OK+NOMSG) // but do not create backup file
  1605. } else { if (File_Exist(@(0))) { //If local UNPAKEBC.DAT, load it
  1606. File_Open("|@(0)",OVERWRITE+OK+NOMSG)
  1607. } else { if (File_Exist("|(HOME)\|@(#65+11)")) {
  1608. File_Open("|(HOME)\|@(#65+11)",OVERWRITE+OK+NOMSG)
  1609. } else { if (File_Exist("|(HOME)\|@(0)")) {
  1610. File_Open("|(HOME)\|@(0)",OVERWRITE+OK+NOMSG)
  1611. } else {
  1612. Reg_Empty(1)
  1613. Out_Reg(1,APPEND)
  1614. if (Is_Quiet) {
  1615. Message("\n***** No data layout file.")
  1616. }
  1617. Message(`\nCannot find `); Reg_Type(9)
  1618. Message(` in current nor VEDIT's "home" directory.`)
  1619. Message(`\nRefer to EBCDIC-2.TXT for details.\n`)
  1620. Out_Reg(CLEAR)
  1621. Call("ERRMSG")
  1622. if (Is_Quiet) {
  1623. XALL(1)
  1624. } else {
  1625. Type_Newline(1)
  1626. Buf_Quit(OK)
  1627. Buf_Switch(#90)
  1628. GetKey("Press any key to view data file...")
  1629. Call("CloseErr")
  1630. Break_Out(EXTRA)
  1631. }
  1632. }}}}
  1633. }
  1634. //
  1635. // Close and reopen the layout file for editing as LAYOUTnn.TMP
  1636. // Where nn is a number that, if present, creates a unique name.
  1637. // Set T-Reg[5] = temporary layout pathname.
  1638. //
  1639. Reg_Set(9,INPUT_FILE) // For BADLAY
  1640. Reg_Set(0,@7) //T-Reg[0] = outputpath\
  1641. Reg_Set(0,"LAYOUT",APPEND) //T-Reg[0] = outputpath\EBCDAT
  1642. Reg_Set(5,@0) //T-Reg[5] =
  1643. for ( #0=0; FileExist("|@(5).TMP",NOERR); #0++ ) {
  1644. Reg_Set(5,@0) // T-Reg[5] = outputpath\LAYOUT
  1645. Out_Reg(5,APPEND) // Divert output to end of T-Reg[5]
  1646. Type_Char((#0/10)+'0')
  1647. Type_Char(remainder+'0')
  1648. Out_Reg(CLEAR) // Stop diverting output
  1649. }
  1650. Reg_Set(5,".TMP",APPEND) // T-Reg[5] = outputpath\LAYOUT[nn].TMP
  1651. Buf_Empty(OK)
  1652. File_Open('"|@(9)" -a "|@(5)"',OVERWRITE+OK+NOMSG)
  1653. #92 = Buf_Num
  1654. //
  1655. // Set T-Reg[8] = Cross Reference filename, in case DBASE.
  1656. // Open the cross reference file in read only mode.
  1657. //
  1658. Reg_Set(0,INPUT_FILE)
  1659. Buf_Switch(Buf_Free(EXTRA))
  1660. Reg_Ins(0)
  1661. if (Search(".",BEGIN+ALL+NOERR+ADVANCE)){
  1662. Del_Block(CurPos-1,EOB_Pos)
  1663. }
  1664. EOF()
  1665. Ins_Text(".xrf")
  1666. BOL()
  1667. rc(8,1)
  1668. Buf_Quit(OK)
  1669. Buf_Switch(#92)
  1670. if (File_Exist(@(8))) {
  1671. File_Open("|@(8)",BROWSE|OK|NOMSG)
  1672. Buf_Switch(#92)
  1673. }
  1674. //
  1675. // Remove junk (0x1a, e.g.) at end of layout file.
  1676. //
  1677. End_Of_File(); bol; if ( match("|[|w]|k") == 0 ) { db(cp,eolpos) }
  1678. //
  1679. // Ensure layout file is newline-terminated.
  1680. //
  1681. End_Of_File()
  1682. Ins_Newline(1) //Ensure final newline
  1683. line(-10,NOERR) //Back up a bit
  1684. r("|<|L","",ALL+NOERR) //Strip empty lines
  1685. //
  1686. Config(E_EXP_TAB,1,LOCAL) // Tabs complicate COBOL processing
  1687. Config(E_RETAB_BK,0,LOCAL)
  1688. Config(E_RETAB_FILL,0,LOCAL)
  1689. Detab_Block(0,File_Size)
  1690. BOF()
  1691. //
  1692. // Rename data output file when not invoked with "-a"
  1693. // to .dbf if DBASE.
  1694. //
  1695. if (#1==0) { // When not "-a"
  1696. //
  1697. // r=len,DBASE-III
  1698. //
  1699. if (s("^[\s\t]*r[\s\t]*=.*,[\s\t]*DB",REGEXP+NOERR)){
  1700. Reg_Set(1,"dbf")
  1701. Buf_Switch(#75)
  1702. Reg_Set(0,FILE_ONLY)
  1703. Buf_Quit(OK)
  1704. Buf_Switch(#75)
  1705. File_Open_Write('"|@(7)|@(0).|@(1)"',OVERWRITE+OK+NOMSG)
  1706. #75 = Buf_Num // Belts and suspenders
  1707. Reg_Set(#65+10,PATH_NAME)
  1708. Buf_Switch(#92)
  1709. }
  1710. BOF()
  1711. }
  1712. //////////////////////////////////////////////////////////////////////////
  1713. // //
  1714. // Preprocessing COBOL copybook statements //
  1715. // //
  1716. //////////////////////////////////////////////////////////////////////////
  1717. if (!Is_Quiet) {
  1718. Message("Processing data description file... ")
  1719. }
  1720. #64 = #64 | 0x200 // Tell COBOL2V.VDM that it is a submacro
  1721. call(#65+19) // COBOL preprocessing
  1722. if (#99!=0x57495C44) { // When not running under WILDFILE...
  1723. Reg_Empty(#65+19) // COBOL processor no longer needed
  1724. }
  1725. if ( #64 & 2 ) { // Quit when just preprocessing COBOL
  1726. goto DONE
  1727. }
  1728. //
  1729. // Check for and process invocation "-u option_list" parameter.
  1730. // Need to do it now, for COBOL2V and RELAY and initial pre-processing
  1731. // settings. Need to do it again after preprocessing in case the .lay
  1732. // file set some values, since the "-u" parameters should prevail.
  1733. //
  1734. #41 = 0 //Unique ID run_no
  1735. #42 = -1 //Unique ID flag
  1736. #43 = 0 //Flags that .nam files to be included at start of each output file
  1737. #44 = 1 //Output decimal points as specified by "vn" field options
  1738. #50 = JDate() //#50 Run date; combined into #55 at end of preprocessing
  1739. #55 = JDate("1-1-2000") //#55 is base date for unique extraction ID's
  1740. call("OPTIONZ")
  1741. //////////////////////////////////////////////////////////////////////////
  1742. // //
  1743. // Preprocessing our own data descriptions //
  1744. // //
  1745. //////////////////////////////////////////////////////////////////////////
  1746. //
  1747. // Strip comments, leading whitespace and blank lines.
  1748. //
  1749. // if (wstat($)<0){wr($,5,bottom)};Reg_Lock_Macro(CLEAR);ws($);update() ?
  1750. Replace("|<|w","",BEGIN+ALL+NOERR) //Remove leading whitespace
  1751. Replace("|<|[|W]//|Y|L","",BEGIN+ALL+NOERR) //Strip comment lines
  1752. Replace("|[|W]//|Y|>","",BEGIN+ALL+NOERR) //Strip inline comments
  1753. Replace("|<|L","",BEGIN+ALL+NOERR) //Remove blank lines
  1754. Replace("^{[a-z]+[\s\t]+.*,[\s\t]*[0-9]+}[\s\t]+{[^\s\t].*}$","\1 \2",REGEXP+BEGIN+ALL+NOERR)
  1755. //
  1756. // Prevent explicit decimal points from being generated, as directed.
  1757. //
  1758. call("DOPOINT")
  1759. //
  1760. // Setup T-Regs[2,4] with binary output field sizes.
  1761. //
  1762. call("SETBREGS")
  1763. //
  1764. // Strip any "i=inflation" parameter; this is for relay.vdm only.
  1765. //
  1766. bof
  1767. while (search("|<|[|w]|?|*|{:,|s|[|w]i|[nflation]|[|w]=}",noerr)){
  1768. if (Match_Item!=1){
  1769. Search("|[|w]i|[nflation]|[|w]=|[|w]")
  1770. Del_Char(Chars_Matched)
  1771. Num_Eval()
  1772. Del_Char(Chars_Matched)
  1773. if (Match("|[|w];|[|w]")==0){
  1774. Del_Char(Chars_Matched)
  1775. }
  1776. if (!AtEOL){
  1777. Ins_Char(' ')
  1778. }
  1779. } else {
  1780. l(1,noerr)
  1781. }
  1782. }
  1783. //
  1784. // Set DBASE flag #23 if "r=len,DBASE".
  1785. //
  1786. if (s("^[\s\t]*r[\s\t]*=.*,[\s\t]*dbase",BEGIN+REGEXP+NOERR)){
  1787. #28 = 1 // DBASE flag
  1788. }
  1789. //
  1790. // Ascertain header & record size and optional output filetype code.
  1791. // Set type explicitly for blank type fields.
  1792. // Ensure codes are lower case.
  1793. // Execute any Vedit ('v=') command lines.
  1794. // Delete lines of type 'code letter=' after processing.
  1795. //
  1796. // Delete lines specifying the default type (XDefType) (e,i) when possible.
  1797. //
  1798. // Perform error checking; break out if bad input.
  1799. // Convert to "cb,ce" format.
  1800. // If the 'q' record has been specified (quote & comma delimit), it
  1801. // must have been specified before any field specification;
  1802. // and each field must be specified; (the start of each field_j
  1803. // must = end of field_i + 1).
  1804. //
  1805. XNextCol(0) //XNextCol = last column #
  1806. #3 = 0 //#3 = # fields current record
  1807. #4 = 0 //#4 = max fields/record
  1808. #17 = 0 //#17 counts 'out's
  1809. #18 = 0 //#18 flags that .VCM customization submacros have been loaded
  1810. #63 = 0 //#63 is DBASE .xrf Buffer ID or zero
  1811. #67 = #68 = #86 = -1 //Record types & header size not yet specified
  1812. #85 = 'd' //#85 = last code encountered, initially BCD
  1813. #87 = #51 = #57 = #58 = #59 = #88 = 0 //Record sizes not yet specified
  1814. XDefType('e') //Consider unspecified cols to be EBCDIC
  1815. #38 = 1000 //Max # data errors to report
  1816. //
  1817. // Repeated Fields variables
  1818. //
  1819. #56 = #61 = #79 = 0 //#79 keeps from stripping default types ('rb')
  1820. //#56 is record offset for multiple runs in one day
  1821. //#61 is additional offset for unique ID calculation
  1822. #62 = (5<<16) | (1<<8) | 6 //#62 is # digits displayed for unique ID (3 parts)
  1823. XQCD(0) //Not Quoting and comma delimiting, yet
  1824. XData(#90) //Define data input buffer
  1825. XLay(#92) //Define .LAY buffer
  1826. // if (wstat($)<0){wr($,5,bottom)};Reg_Lock_Macro(CLEAR);ws($);update() ?
  1827. Begin_Of_File()
  1828. while(!At_EOF) {
  1829. //
  1830. // #
  1831. //
  1832. if (match("#")==0){ // Level-4, repeat count adjuster
  1833. goto ENDR
  1834. }
  1835. //////////////////////////////////////////////////////
  1836. // //
  1837. // code= processing //
  1838. // //
  1839. //////////////////////////////////////////////////////
  1840. if (cc(1)=='='||cc(2)=='=') {
  1841. //
  1842. // p=
  1843. //
  1844. if (match("p=")==0) {goto MISSING} // COBOL2V.VDM wasn't found
  1845. //
  1846. // q=
  1847. //
  1848. if (match("q=")==0) {goto BAD_LAY} // Unmatched bracket
  1849. //
  1850. // h=
  1851. //
  1852. if (match("h=",advance)==0){ //If "h=" header specified
  1853. #86=Num_Eval() //#86 = header length
  1854. goto DELLN //Now delete this line
  1855. }
  1856. //
  1857. // r=n
  1858. //
  1859. if (match("r=",advance)==0) { // If "r=" record types specified
  1860. #57=#67=#68=Num_Eval(ADVANCE) // #57 = default input record type or length
  1861. // #67 = input record type {0,1,2,3,6}
  1862. // #68 = default output record type
  1863. if (#67>4) {
  1864. #87 = #67 // #87 = input record size
  1865. #68 = #67 = 6 // #67 = fixed length input records
  1866. // assume fixed output records
  1867. }
  1868. //
  1869. // r=n,x where x={v,f=len,dbase}
  1870. //
  1871. if (match("|[|W],",advance)==0){
  1872. if (Match("|{f,v}",advance)==0) {
  1873. #68 = 6 // #68 = 6 = fixed output records
  1874. Match("|[|w]=",advance)
  1875. #88 = Num_Eval() // #88 = output record size
  1876. } else { if (Match("DBASE")==0) {
  1877. #68 = 7 // #68 = 7 = DBASE file
  1878. #88 = 512 // Actual size determined dynamically
  1879. #16 = #75
  1880. Buf_Switch(#16)
  1881. Del_Block(0,File_Size)
  1882. Config(F_F_TYPE,32,LOCAL) // Header consists of 32-byte structures
  1883. #27 = #59 = 1 // # records and record types
  1884. Reg_Set(3,'F') // Short field name = "Fn", where n = field ordinal
  1885. call(49) // DBINIT0()
  1886. } else {
  1887. #68 = Num_Eval() // #68 = {0,1,2,3} = output record type
  1888. if (#68 > 4) {
  1889. #88 = #68
  1890. #68 = 6
  1891. }
  1892. }}
  1893. }
  1894. goto DELLN
  1895. }
  1896. //
  1897. // c= // Column #
  1898. //
  1899. if ( match("c=",advance) == 0 ) { //If "c=" column #
  1900. XNextCol(Num_Eval() - 1) //XNextCol = preceding field's ending col #
  1901. goto DELLN //Now delete this line
  1902. }
  1903. //
  1904. // a= // Additional offset for unique ID calculation
  1905. //
  1906. if ( match("a=",advance) == 0 ) { // if "a=" additional offset
  1907. #61 = Num_Eval()
  1908. goto DELLN
  1909. }
  1910. //
  1911. // b= // base_date for unique Repeated Group extraction ID's
  1912. //
  1913. if ( match("b=",advance) == 0 ) { // if "b=" base_date
  1914. #55 = Num_Eval_Date()
  1915. goto DELLN
  1916. }
  1917. //
  1918. // d= // current_date for unique Repeated Group extraction ID's
  1919. //
  1920. if ( match("d=",advance) == 0 ) { // if "d=" (run) date
  1921. #50 = Num_Eval_Date()
  1922. goto DELLN
  1923. }
  1924. //
  1925. // n= // # digits displayed for each part of unique ID
  1926. //
  1927. if ( match("n=|[|w]",advance) == 0 ) { // if "n=" l,m,n
  1928. #0 = 5 // Days elapsed
  1929. #1 = 6 // Record count
  1930. #2 = 1 // Run # count
  1931. //
  1932. // Days elapsed (default 5)
  1933. //
  1934. #5 = Num_Eval(ADVANCE)
  1935. if (cmat>0){#0=#5}
  1936. //
  1937. // Record count (default 6)
  1938. //
  1939. Match("|w",ADVANCE)
  1940. if (!At_EOL){
  1941. Match("|s|[|w]",ADVANCE)
  1942. #5 = Num_Eval(ADVANCE)
  1943. if (cmat>0){#1=#5}
  1944. //
  1945. // Run # (default 1)
  1946. //
  1947. Match("|w",ADVANCE)
  1948. if (!At_EOL){
  1949. Match("|s|[|w]",ADVANCE)
  1950. #5 = Num_Eval(ADVANCE)
  1951. if (cmat>0&&#5>=0){#2=#5}
  1952. }
  1953. }
  1954. //
  1955. #62 = (#0 << 16) | (#2 << 8) | #1
  1956. goto DELLN
  1957. }
  1958. //
  1959. // e= // Error file
  1960. //
  1961. if ( match("e=|[|w]",advance) == 0 ) { // "e="
  1962. //
  1963. // Just "e=".
  1964. //
  1965. if ( At_EOL || (Match("//") == 0 )) { // Just "e=" turns feature off
  1966. FO("|@(#65+18)",OVERWRITE+NOEVENT) // In case ever any early messages
  1967. if ( fsize ) {
  1968. db(0,fsize) // User doesn't want to know
  1969. File_Close(NOMSG+NOEVENT)
  1970. }
  1971. Buf_Quit(OK)
  1972. Reg_Empty(#65+18)
  1973. #38 = 0 // Speed optimization
  1974. Buf_Switch(XLAY)
  1975. //
  1976. // e=n,filename
  1977. //
  1978. } else {
  1979. //
  1980. // Process limit on # invalid compressed data item messages.
  1981. //
  1982. #5 = Num_Eval(advance+suppress)
  1983. if (Chars_Matched>0) {
  1984. if (#5>=0) { // e=n
  1985. #38 = #5 // #38 = limit
  1986. }
  1987. }
  1988. //
  1989. // Advance past ",[whitespace]"
  1990. //
  1991. match("|[|w],|[|w]",advance) // Advance past ","
  1992. //
  1993. // Process explicit error filename.
  1994. // Set path to the main output directory unless an
  1995. // explicit path is specified (at least one "\").
  1996. //
  1997. if (match("|{//,|>}")) { // When not at comment or eol
  1998. call(53) // T-Reg[0] = filename
  1999. Buf_Switch(Buf_Free(EXTRA))
  2000. Reg_Ins(0)
  2001. if (search("\",BEGIN+NOERR)==0) {
  2002. Reg_Set(0,@(7),INSERT)
  2003. }
  2004. Buf_Quit(OK)
  2005. Buf_Switch(XLAY)
  2006. if (File_Check(@(#65+18))>0) { // If early processing errors...
  2007. FO("|@(#65+18)",NOEVENT) // Switch to the error buffer
  2008. File_Save_As(@0,OK+NOMSG) // Change filename
  2009. File_Delete(@(#65+18),OK+NOERR)
  2010. Reg_Set(#65+18,PATHNAME) // Copy error pathname into T-Reg[18]
  2011. } else { // else if file not yet open ...
  2012. if (Reg_Size(0)>0){ Reg_Set(#65+18,@0) }
  2013. File_Open("|@(#65+18)",OVERWRITE+NOMSG+NOEVENT) // Open any pre-existing file
  2014. Del_Char(ALL) // Empty it
  2015. }
  2016. Buf_Switch(XLAY) // Switch back to layout file
  2017. }
  2018. Reg_Lock_Macro(102,EXTRA) // Trap unexpected breakouts
  2019. }
  2020. goto DELLN
  2021. }
  2022. //
  2023. // i=
  2024. //
  2025. if ( match("i=",advance) == 0 ) { //If "i=" include .nam header files
  2026. if (match("|A")==0){
  2027. if (match("on")==0){
  2028. #43 = 1
  2029. }
  2030. } else {
  2031. #43 = Num_Eval()
  2032. }
  2033. if (#43!=1) {
  2034. #43 = 0
  2035. }
  2036. goto DELLN
  2037. }
  2038. //
  2039. // o=
  2040. //
  2041. if ( match("o=",advance) == 0 ) { //If "o=" default options
  2042. while( match("|[|w]|{b2z,+,b,u,z,-,e,s,p}",ADVANCE) == 0 ) {
  2043. #1 = mi - 1
  2044. if ( #1 == 0 ) {
  2045. EBC_Settings( SP_2_ZERO, 1 )
  2046. } else {
  2047. #0 = 1
  2048. if ( #1 > 4 ) {
  2049. #0 = 0
  2050. #1 -= 4
  2051. }
  2052. if ( #1 == 1 ) {
  2053. EBC_Settings( Force_Plus,#0)
  2054. } else { if ( #1 == 2 ) {
  2055. EBC_Settings( Begin_Sign,#0)
  2056. } else { if ( #1 == 3 ) {
  2057. EBC_Settings( Unsigned,#0)
  2058. } else { if ( #1 == 4 ) {
  2059. EBC_Settings( Leading_Zeros,#0)
  2060. }}}}
  2061. }
  2062. match(",",advance)
  2063. }
  2064. goto DELLN // Now delete this line
  2065. }
  2066. //
  2067. // bc=badchar
  2068. //
  2069. if (match("bc=",advance)==0){
  2070. if (match("|{'',',0x}")!=0){goto BAD_LAY}
  2071. #0=0
  2072. if (mi>1){
  2073. #0=Num_Eval()
  2074. }
  2075. EBC_Settings(badchar,#0&0xFF)
  2076. goto DELLN //Now delete this line
  2077. }
  2078. //
  2079. // pc=padchar
  2080. //
  2081. if (match("pc=",advance)==0){
  2082. if (match("|{'',',0x}")!=0){goto BAD_LAY}
  2083. #0=0
  2084. if (mi>1){
  2085. #0=Num_Eval()
  2086. }
  2087. EBC_Settings(padchar,#0&0xFF)
  2088. goto DELLN //Now delete this line
  2089. }
  2090. //
  2091. // u= // Ignore,Ascii,Ebcdic
  2092. //
  2093. if (match("u=|[|W]",advance)==0){ // If "u=" unspecified columns
  2094. XDefType(CurChar | 0x20) // ebcdic or ignore
  2095. goto DELLN
  2096. }
  2097. //
  2098. // v=
  2099. //
  2100. if (match("v=",advance)==0){ // if "v=" Vedit command
  2101. if (#64&256) { goto ENDR }
  2102. rcb(#65+11,cp,eolpos) // Copy command(s) into T-Reg[11]
  2103. Buf_Switch(XData) // Switch to the source data buffer
  2104. call(#65+11) // Perform them
  2105. Buf_Switch(XLAY) // Reenter the data layout buffer
  2106. goto DELLN // Delete this line!
  2107. }
  2108. //
  2109. // x=
  2110. //
  2111. if (match("x=",advance)==0){ // if "x=" post processing commands
  2112. rcb(#65+14,cp,eolpos) // Copy command(s) into T-Reg[14]
  2113. #64 = #64 | 8 // Set flag
  2114. goto DELLN // Delete this line!
  2115. }
  2116. } // (cc(1)=='='||cc(2)=='=')
  2117. //
  2118. // uid={off,auto,all}
  2119. //
  2120. if (match("uid|[|w]=|[|w]",advance)==0) { // If Unique ID is (not) wanted...
  2121. if (match("|d")==0){
  2122. #42 = Num_Eval()
  2123. } else { if (match("|{off,auto,all}")==0) {
  2124. #42 = Match_Item - 1
  2125. } else { if (match("|{on,force}")==0) {
  2126. #42 = 2
  2127. } else {
  2128. #42 = 0
  2129. }}}
  2130. if ( #42 < 0 || #42 > 2 ) {
  2131. #42 = 1
  2132. }
  2133. goto DELLN
  2134. }
  2135. //
  2136. // xrf=arg where arg = 1 or "on" to enable.
  2137. //
  2138. if (match("xrf|[|w]=|[|w]",advance)==0){
  2139. #63 = 0
  2140. if (match("|{1,on}")==0){
  2141. File_Open("|@(8)",NOMSG) // Switch to the cross reference file
  2142. if (File_Size > 0) {
  2143. #63 = Buf_Num
  2144. }
  2145. Buf_Switch(XLAY) // Switch back to the .LAY file
  2146. } else {
  2147. #63 = 0 // Auto-generate the field names
  2148. }
  2149. goto DELLN
  2150. }
  2151. //////////////////////////////////////////////////////
  2152. // //
  2153. // Output diversion filename. //
  2154. // //
  2155. //////////////////////////////////////////////////////
  2156. if (match("out|{|w,//,|>}",ADVANCE)==0) {
  2157. #17 += 0x10000 // Count this "out"
  2158. if(Match("|{//,|>}")) {
  2159. NumPush(16,16)
  2160. RegSet(0,@3)
  2161. RegPush(0,0)
  2162. or(3,APPEND); TypeChar('A' + ((#17>>8) & 0xff)); or(CLEAR)
  2163. #17 += 0x100 // Update # "out" autogenerated short names
  2164. call(59)
  2165. } else {
  2166. call("DBEOR")
  2167. RegPop(3,3)
  2168. NumPop(16,16)
  2169. }
  2170. goto ENDR
  2171. }
  2172. //////////////////////////////////////////////////////
  2173. // //
  2174. // Other Code Processing //
  2175. // //
  2176. //////////////////////////////////////////////////////
  2177. #5 = 0
  2178. //
  2179. // Set #2 = lower case code letter.
  2180. //
  2181. if (match("|A")==0) {
  2182. #2 = Cur_Char | 0x20 // make lower case
  2183. //
  2184. // q - quote and comma delimit
  2185. //
  2186. if (#2=='q') {
  2187. XQCD(1) // Set Quote-and-Comma-Delimit flag
  2188. if (#3!=0) { // Cannot have processed any fields yet
  2189. goto BAD_LAY
  2190. }
  2191. if (#28) { // Cannot mix QCD and DBASE
  2192. goto BAD_LAY
  2193. }
  2194. goto DELLN // Delete this line from the layout file
  2195. }
  2196. //
  2197. // Set #85 = initial valid code letter and advance past it.
  2198. //
  2199. if (match("|{b,c,d,e,f,h,i,l,n,s,u,x,y,z}",advance)==0) {
  2200. #85 = #2
  2201. } else {
  2202. goto BAD_LAY
  2203. }
  2204. } else {
  2205. goto BAD_LAY
  2206. }
  2207. //
  2208. // c - custom field.
  2209. //
  2210. if (#85 == 'c' && #18 == 0 ){
  2211. //
  2212. // Use T-Reg[1] to load and speed optimize submacros.
  2213. // Then distribute the code to their proper T-Regs.
  2214. //
  2215. Reg_Load(1,"EBCDIC-2.VCM",EXTRA)
  2216. Reg_Prep(1)
  2217. Call(1)
  2218. Reg_Empty(1)
  2219. #18 = 1
  2220. }
  2221. //
  2222. // Convert "+size" to "bc,ec".
  2223. //
  2224. Match("|W",ADVANCE)
  2225. if (Cur_Char=='+'){ //Process code +size
  2226. Del_Char(1)
  2227. #10 = Num_Eval(SUPPRESS)
  2228. XAdjBeg(XNextCol + 1) // cb
  2229. XAdjEnd(XNextCol + #10) // ce
  2230. Del_Char(Chars_Matched)
  2231. Num_Ins(XAdjBeg,LEFT+NOCR)
  2232. Ins_Char(',')
  2233. Num_Ins(XAdjEnd,LEFT+NOCR)
  2234. } else { //Process code bc,ec
  2235. //
  2236. // Check for invalid beginning column number.
  2237. //
  2238. XAdjBeg(Num_Eval(SUPPRESS+ADVANCE)) //Set field starting column
  2239. if (XAdjBeg < 1 ) { goto BAD_LAY } //Check for valid number
  2240. if (XQCD>0 && XAdjBeg!=XNextCol+1){goto BAD_LAY} //Contiguous quoted fields
  2241. if (XAdjBeg < XNextCol) { goto BAD_LAY } //Fields must be in ascending order
  2242. //
  2243. // Convert "m<sep>n" to "m,n".
  2244. //
  2245. if (!Replace_Block("|[|W]|S|[|W]",",",Cur_Pos,EOL_Pos,NOERR)) {
  2246. goto BAD_LAY }
  2247. //
  2248. // Check for invalid ending column number.
  2249. //
  2250. XAdjEnd(Num_Eval(SUPPRESS+ADVANCE)) //Set field ending column
  2251. if (XAdjEnd < 1 ) { goto BAD_LAY } //Check for valid number
  2252. if (XAdjEnd < XAdjBeg) { goto BAD_LAY } //Fields must be in ascending order
  2253. }
  2254. //
  2255. // Valid field; count it.
  2256. //
  2257. #3++
  2258. //
  2259. // Set XNextCol to last specified column.
  2260. //
  2261. XNextCol(XAdjEnd)
  2262. //
  2263. // Process options.
  2264. //
  2265. EBC_Get_Opt()
  2266. //
  2267. // Add field to DBASE header, perhaps.
  2268. //
  2269. if (#28) {call("DBFIELD")}
  2270. //
  2271. // Optimize by stripping default field (ebcdic) specifications if able.
  2272. //
  2273. call("OPTIMIZE")
  2274. if (Return_Value) {Goto DELLN}
  2275. //
  2276. // ENDR - Advance to next description line and loop, if possible;
  2277. // terminate loop, otherwise.
  2278. //
  2279. :ENDR:
  2280. line(1,errbreak)
  2281. continue
  2282. //
  2283. // DELLN - Delete "code=" line from buffer.
  2284. // Continue at top of loop.
  2285. //
  2286. :DELLN:
  2287. if ( #64 & 256 ) { goto ENDR } // When just preprocessing
  2288. BOL()
  2289. Del_Line(1)
  2290. continue
  2291. ///////////////////////////////////////////////////////////////////////////////
  2292. //
  2293. // OPTIMIZE - Delete unnecessary specifications ('e', 'i' or 'u').
  2294. // Cannot strip when QCD nor user delimited fields.
  2295. // Cannot strip if FieldSize or PadCount.
  2296. // Cannot strip 'u' if LeadingZeros, OutPoint or SP2Zero.
  2297. // Cannot strip 1st nor last specification in an "out...out"
  2298. // extraction block.
  2299. //
  2300. // Enter: #2 = current specification code's 1st letter.
  2301. // #17 = 00 oo nn rr, where
  2302. // rr = # out's
  2303. // oo = # out-auto-generated short names
  2304. // XDefType = default code {a,e,i}.
  2305. // CurPos should be at EOL unless custom field.
  2306. // Retrn: (RET_VAL == 1) if line is to be deleted.
  2307. // CurPos on same line; may be at BOL.
  2308. //
  2309. :OPTIMIZE:
  2310. //
  2311. // Return NOSTRIP when not default item nor 'u';
  2312. // also when quoting and comma delimiting or
  2313. // using explicitly specified item separators.
  2314. //
  2315. if (( #2 != XDefType && #2 != 'u') || XQCD + RSize(XDREG) > 0 ) {
  2316. return(0)
  2317. }
  2318. //
  2319. // Give BADPARM error if !AtEOL/EOF.
  2320. //
  2321. if (!AtEOL){goto BAD_PARM}
  2322. //
  2323. // Return NOSTRIP if either FieldSize or PadCount.
  2324. //
  2325. if ( EBC_Settings( FieldSize ) || EBC_Settings( PadCount )) {
  2326. return(0)
  2327. }
  2328. //
  2329. // For 'u', return NOSTRIP if LeadingZeros, OutPoint or SP2Zero.
  2330. //
  2331. if ( #2 == 'u' ) {
  2332. if ( EBC_Settings( LeadingZeros ) || EBC_Settings( OutPoint ) || EBC_Settings( SP2Zero )) {
  2333. return(0)
  2334. }
  2335. }
  2336. //
  2337. // Backup to previous description.
  2338. // If none, it's OK to STRIP.
  2339. //
  2340. BOL()
  2341. SavePos()
  2342. if (Search("|<|a",REVERSE+NOERR)==0){
  2343. RestorePos()
  2344. return(1)
  2345. }
  2346. //
  2347. // If previous description is beginning 'out',
  2348. // return NOSTRIP.
  2349. //
  2350. #0 = 0
  2351. if (match("out|s")==0 && ((#17>>16)&1)) {
  2352. #0 = 1
  2353. }
  2354. RestorePos()
  2355. if (#0) {return(0)}
  2356. //
  2357. // Return NOSTRIP if the next description, if any, is
  2358. // the ending 'out', else STRIP.
  2359. //
  2360. SavePos()
  2361. Char(1)
  2362. #0 = 1 // STRIP
  2363. if (Search("|<|a",NOERR)){
  2364. if (match("out|s")==0 && ((#17>>16)&1)) {
  2365. #0 = 0
  2366. }
  2367. }
  2368. RestorePos()
  2369. return(#0)
  2370. // OPTIMIZE ends
  2371. ///////////////////////////////////////////////////////////////////////////////
  2372. //
  2373. // DOPOINT - Strip "vn" from field options as specified.
  2374. // Enter: #44 = Allow-decimal-point flag.
  2375. // Retrn: Lines beginning with "NOD" or "DOD" have been deleted.
  2376. // Fields within purview of "NOD" have "vn" stripped out.
  2377. // #44 undefined (not needed anymore).
  2378. //
  2379. :DOPOINT:
  2380. bof
  2381. Set_Marker(0,Cur_Pos)
  2382. while (search("|<|[|w]|{n,d}od",NOERR)) {
  2383. if (match("|[|w]n")==0){
  2384. if (#44){
  2385. Set_Marker(0,Cur_Pos)
  2386. }
  2387. #44 = 0;
  2388. Del_Line(1)
  2389. } else {
  2390. if (#44==0){
  2391. call("XPOINT")
  2392. }
  2393. #44 = 1
  2394. Del_Line(1)
  2395. }
  2396. }
  2397. if (#44==0){
  2398. eof
  2399. }
  2400. :XPOINT:
  2401. #0 = Cur_Pos
  2402. Goto_Marker(0)
  2403. Set_Marker(0,#0)
  2404. while (search_block("|bv|[|d|[|d]]|s",Cur_Pos,Marker(0),NOERR)){
  2405. replace("|bv|[|d|[|d]]","")
  2406. }
  2407. Goto_Marker(0)
  2408. return
  2409. ///////////////////////////////////////////////////////////////////////////////
  2410. //
  2411. // DBFIELD - Add current field to DBASE header; update header size; update record size.
  2412. // Enter: #3 = Field Counter.
  2413. // #28 > 0 (DBASE flag).
  2414. // #63 = .xrf BufID
  2415. // [3] = RecName
  2416. // DBF - #16 = BufID of .dbf file.
  2417. // #85 = field specifier {a,b,c,d,e,f,h,i,l,n,s,u,x,z}
  2418. // XAdjBeg = begin column (input).
  2419. // XAdjEnd = end column (input).
  2420. //
  2421. :DBFIELD:
  2422. if (#85=='x'){return} // Do nothing when field is being deleted
  2423. //
  2424. // Set T-Reg[1] = field name.
  2425. //
  2426. if (#63>0){ // When .xrf file has been specified
  2427. //
  2428. // Use first name on .xrf file's current line and advance to next line.
  2429. //
  2430. Buf_Switch(#63)
  2431. Match("|W",ADVANCE)
  2432. #0 = Cur_Pos
  2433. s("|b")
  2434. rcb(1,#0,Cur_Pos) // T-Reg[1] = first name on current line
  2435. Line(1,NOERR) // Advance to next line
  2436. } else {
  2437. //
  2438. // Else auto-generate the field name.
  2439. //
  2440. RegSet(1,@3) // Record name
  2441. ITOA(#3,1,LEFT+NOCR+APPEND) // Field number
  2442. }
  2443. //
  2444. // DBF -
  2445. // Enter: #16 = .dbf BufID
  2446. // #85 = Field Type (.lay code)
  2447. // XAdjBeg = Field Beginning Col
  2448. // XAdjEnd = Field Ending Col (only need XAdjEnd - XAdjBeg to be valid)
  2449. // [1] = Field Name
  2450. //
  2451. :DBF:
  2452. BufSwitch(#16) // Switch to .dbf file
  2453. NumPush(0,5)
  2454. #0 = File_Size - 1 // Position just ahead of <cr> terminator
  2455. GP(#0)
  2456. Ins_Char(0,COUNT,32) // Zero-out current 32-byte structure
  2457. //
  2458. // Insert field name (Pos 0-10)
  2459. //
  2460. GP(#0)
  2461. RegIns(1,OVERWRITE)
  2462. //
  2463. // Insert field type (Pos 11) {C,D,L,N}
  2464. //
  2465. GP(#0+11)
  2466. Ins_Char('C',OVERWRITE) // Character type
  2467. //
  2468. // Compute and insert field length (Pos 16)
  2469. //
  2470. call("FIELD_SIZE") // #2 = size
  2471. GP(#0+16)
  2472. Ins_Char(Return_Value,OVERWRITE)
  2473. //
  2474. // Update # bytes in the header (pos 8-9).
  2475. //
  2476. GP(8)
  2477. Ins_Char(FSIZE&0xFF,OVERWRITE)
  2478. Ins_Char((FSIZE>>8)&0xFF,OVERWRITE)
  2479. Config(F_REC_HEAD,FSIZE,LOCAL)
  2480. //
  2481. // Update # bytes in the record (pos 10-11).
  2482. //
  2483. #1 = cc + (cc(1)<<8) + #2
  2484. Ins_Char(#1&0xFF,OVERWRITE)
  2485. Ins_Char((#1>>8)&0xFF,OVERWRITE)
  2486. Config(F_F_TYPE,#1,LOCAL)
  2487. //
  2488. Num_Pop(0,5)
  2489. Buf_Switch(XLAY)
  2490. return
  2491. // DBFIELD ends
  2492. //
  2493. // SETBREGS - Set T-Reg[4] with table of default (cooked) binary sizes;
  2494. // Set T-Reg[2] with table of max binary sizes when "raw";
  2495. // (must agree with BMAX[] and RMAX[] in Veditc2.asm)
  2496. //
  2497. // BMAX DB 1,4,6, 8,11,13,16,18 ;Standard (cooked) binary sizes
  2498. // RMAX DB 3,5,8,10,13,15,17,20 ;Raw binary sizes
  2499. //
  2500. :SETBREGS:
  2501. #0 = Buf_Num
  2502. Buf_Switch(Buf_Free(EXTRA))
  2503. Ins_Char('.')
  2504. Replace(".","|H01|H04|H06|H08|H0B|H0D|H10|H12",BEGIN)
  2505. Reg_Copy_Block(4,0,Cur_Pos,DELETE)
  2506. Ins_Char('.')
  2507. Replace(".","|H03|H05|H08|H0A|H0D|H0F|H11|H14",BEGIN)
  2508. Reg_Copy_Block(2,0,Cur_Pos,DELETE)
  2509. Buf_Quit(OK)
  2510. Buf_Switch(#0)
  2511. Return
  2512. // SETBREGS() ends
  2513. ///////////////////////////////////////////////////////////////////////////////
  2514. //
  2515. // FIELD_SIZE - return # bytes in output field.
  2516. // Enter: #85 = field specifier {a,b,c,d,e,f,h,i,l,n,s,u,x,z}.
  2517. // XAdjBeg = begin column (input).
  2518. // XAdjEnd = end column (input).
  2519. // Retrn: Return_Value = field size.
  2520. //
  2521. // BMAX DB 1,4,6, 8,11,13,16,18 ;Standard binary sizes
  2522. // RMAX DB 3,5,8,10,13,15,17,20 ;Raw binary sizes
  2523. //
  2524. :FIELD_SIZE:
  2525. Num_Push(0,1)
  2526. #0 = EBC_Settings( UNSIGNED )
  2527. #2 = XAdjEnd - XAdjBeg + 1
  2528. //
  2529. if (#85=='b') {
  2530. if (EBC_Settings(raw)){
  2531. #5 = BtoI( 2, #2 - 1, 1 ) // #5 = max # decimal digits
  2532. // packed into #2 binary bytes
  2533. } else {
  2534. #5 = BtoI( 4, #2 - 1, 1 ) // #5 = standard max # decimal digits
  2535. // packed into #2 binary bytes
  2536. }
  2537. #2 = #5
  2538. //
  2539. // Other codes
  2540. //
  2541. } else { if (#85=='d'||#85=='n'||#85=='h'){
  2542. #2 += #2
  2543. if (#85=='d'){
  2544. #2-- // Further adjustments yet to come
  2545. }
  2546. }}
  2547. //
  2548. // Adjust/recompute for ",[{-,=}]padlen;" option.
  2549. //
  2550. if (#1 = EBC_Settings( FIELD_SIZE )) {
  2551. #2 = #1
  2552. } else {
  2553. #2 += abs( EBC_Settings( PAD_COUNT ) )
  2554. }
  2555. //
  2556. // Adjust for any sign.
  2557. //
  2558. if ((#85=='b'||#85=='d'||#85=='z'||#85=='l'||#85=='s')&&!#0){
  2559. #2++
  2560. }
  2561. //
  2562. // Adjust for any explicit decimal point.
  2563. //
  2564. if ( EBC_Settings( Out_Point ) !=0 ) { #2++ }
  2565. //
  2566. Num_Pop(0,1)
  2567. return(#2)
  2568. // FIELD_SIZE ends
  2569. ///////////////////////////////////////////////////////////////////////////////
  2570. //
  2571. // DQEOR - Proceed to DBEOR if current record type has extracted portions.
  2572. // Note: CurPos is at start of next record type.
  2573. // Enter: #28 = DBASE flag.
  2574. // #59 = record types counter
  2575. // #73 = segment level
  2576. //
  2577. :DQEOR:
  2578. //
  2579. // Just return if not DBASE or no items.
  2580. //
  2581. if (#28==0||#59==0){return}
  2582. //
  2583. if (#73){goto DBEOR}
  2584. Set_Marker(9,CurPos)
  2585. BOL()
  2586. Search("|<|{l=,st,so,t}",REVERSE+NORESTORE+NOERR)
  2587. l
  2588. #0 = 0
  2589. while(SearchBlock("|<|{out,rb|[|w#|d|[|d]]}|[|w]",CurPos,Marker(9),ADVANCE+NOERR)){
  2590. if (!AtEOL){
  2591. #0 = 1
  2592. break
  2593. }
  2594. }
  2595. GM(9)
  2596. if (#0==0){return}
  2597. //
  2598. // DBEOR - For DBASE, enter unique field into header & set F_F_TYPE.
  2599. // Enter: #59 = # record types (do nothing when 0).
  2600. // #28 = DBASE flag.
  2601. // #62 = sizes of reccnt, segcnt, jdate : { 0000 jjjj ssss rrrr }
  2602. // [3] = DBASE record name.
  2603. :DBEOR:
  2604. if (#59==0){return}
  2605. if (#28) {
  2606. RegSet(1,@3)
  2607. RegSet(1,"UID",APPEND)
  2608. #85 = XDefType // #85 = default code ('e' for EBCDIC, e.g.)
  2609. XAdjEnd((#62&0xFF) + ((#62>>8)&0xFF) + ((#62>>16)&0xFF) + 1) // XAdjEnd = length of unique ID
  2610. XAdjBeg(1) // Only interested in XAdjEnd - XAdjBeg
  2611. #85 = XDefType // Set field type to default
  2612. EBC_Reset(LOCAL) // Reset all current options
  2613. call("DBF")
  2614. }
  2615. return
  2616. // DBEOR ends
  2617. } // Preprocessing loop ends
  2618. call("DQEOR")
  2619. //////////////////////////////////////////////////////////////////////////
  2620. // //
  2621. // End of .LAY Preprocessing Loop //
  2622. // //
  2623. //////////////////////////////////////////////////////////////////////////
  2624. //
  2625. //
  2626. // Check for and reprocess invocation "-u option_list" parameter.
  2627. // Any settings in the invocation list should prevail.
  2628. //
  2629. Num_Push(14,14)
  2630. call("OPTIONZ")
  2631. if (#42<0){#42=1} // Auto option for UID's if not otherwise specified
  2632. Num_Pop(14,14)
  2633. //
  2634. // Compute #55 = date portion of unique ID for Repeated Group extractions
  2635. //
  2636. #55 = #50 - #55
  2637. //
  2638. // Set #50 = # digits to display elapsed days count of unique ID
  2639. // Set #62 = # digits to display record count of unique ID
  2640. //
  2641. #50 = (#62 >> 16) & 0xff
  2642. #40 = (#62 >> 8) & 0xff
  2643. #62 = #62 & 0xff
  2644. if (#64 & 256) { goto DONE } // Quit when just preprocessing
  2645. //////////////////////////////////////////////////////////////////////////////
  2646. //
  2647. // Final initialization.
  2648. //
  2649. BOF()
  2650. Buf_Switch(XData) //Switch to source data file
  2651. //
  2652. // Deal with record size/type, allowing user to set record type
  2653. // from {Config} menu.
  2654. //
  2655. if (#67>=0) { //For defined record types
  2656. Config(F_F_TYPE,#57,LOCAL) //Set input record type/default-size
  2657. //
  2658. // Allow user to configure the record size/type by hand.
  2659. //
  2660. } else {
  2661. #57 = #67 = #87 = Config(F_F_TYPE) //#87 = input record size/type
  2662. if (#67<6) {
  2663. #87 = 0
  2664. } else {
  2665. #67 = 6
  2666. }
  2667. }
  2668. //
  2669. // Move any header into output buffer via T-Reg[0].
  2670. //
  2671. if (#86>0) {
  2672. RCB(0,0,#86,DELETE)
  2673. EOF()
  2674. BS(#75) //Standard output buffer
  2675. RI(0)
  2676. BS(XData)
  2677. Config(F_REC_HEAD,#86,LOCAL)
  2678. }
  2679. //
  2680. // For DBASE, output initial blank column.
  2681. //
  2682. if (#28){
  2683. bs(#75)
  2684. EOF()
  2685. if (XDefType=='a'){
  2686. Ins_Char(0x40)
  2687. }else{
  2688. Ins_Char(0x20)
  2689. }
  2690. }
  2691. //
  2692. #93 = 1
  2693. Goto_Line(#93) //Start at 1st record
  2694. #0 = CurPos+1 //Flag/value for record size adjustments
  2695. //
  2696. // Compute intermediate statistic values.
  2697. // Enter: #67 = input record type {0,1,2,3,6} or = -1.
  2698. // #58 = sum of record sizes.
  2699. // #59 = # record-types.
  2700. // Exit: #76 = (approx) record size.
  2701. // #77 = (approx) # records in the file.
  2702. //
  2703. if (#67>3){ //If fixed-length records...
  2704. if (#59>0) {
  2705. #76 = (#58 + (#59>>1) + 1) / #59
  2706. } else {
  2707. #76 = #57 //Default record size
  2708. }
  2709. } else { //Else file should have newlines...
  2710. Line(100,NOERR) //Advance a few lines
  2711. #76 = (Cur_Pos - #0 + 1)/100 //Approx line size
  2712. Goto_Line(#93) //Restore pos
  2713. }
  2714. #77 = (File_Size-#0+1) / #76 //#77 = # of records in file
  2715. //
  2716. // Set #31 = # records per reporting period {100 or 10 or 2}.
  2717. //
  2718. #31 = 100
  2719. if (#77 < 500){ #31 = 10 }
  2720. if (#77 < 50){ #31 = 2 }
  2721. //
  2722. // Show life by displaying "Processing first xxx data records..." message.
  2723. //
  2724. //
  2725. if (!Is_Quiet) {
  2726. Win_Hor(1)
  2727. Message("Input file: ") // Display input drive:\path\name
  2728. Reg_Type(#65+15,0)
  2729. Win_EOL()
  2730. Type_Newline()
  2731. Buf_Switch(#75)
  2732. Name_Write(EXTRA) // Ditto for output file
  2733. Buf_Switch(XData)
  2734. if (Reg_Size(#65+18)){
  2735. Message("Error file: ") // Ditto for error error file
  2736. Reg_Type(#65+18,0)
  2737. Win_EOL()
  2738. Type_Newline()
  2739. }
  2740. Message("Processing first ")
  2741. Num_Type(#31,LEFT+NOCR)
  2742. Message(" data records... ")
  2743. }
  2744. //
  2745. // More statistics.
  2746. //
  2747. #36 = File_Size
  2748. #39 = Reg_Free // Do nothing for record #0
  2749. // if (wstat($)<0){wr($,5,bottom)};Reg_Lock_Macro(CLEAR);ws($);update() ?
  2750. //////////////////////////////////////////////////////////////////////////////
  2751. //
  2752. // Main Processing loop.
  2753. //
  2754. #77 = #75 //Initially, output buffer = standard output buffer
  2755. #32 = Time_Tick
  2756. XAdjEnd(-1) //1st time flag for empty record type (all default data)
  2757. XRecNum(0) //Init record counter
  2758. XDataByteCount(0) //No bytes processed yet
  2759. XSegOfs(0) //Segment column offset
  2760. while(!AtEOF){ //For each record
  2761. //
  2762. // Switch to source data buffer.
  2763. //
  2764. BS(XData)
  2765. //
  2766. // Show progress message every 100 or 10 or 2 iterations.
  2767. //
  2768. if (!IsQuiet&&!(XRecNum%#31)){
  2769. call(#39) // T-Reg(#39) is empty, initially
  2770. #39=62 // Next time it'll have the right stuff
  2771. }
  2772. //
  2773. // Initialization for each record:
  2774. // Increment record #
  2775. // Reset XRecByteCount - # bytes processed in current record
  2776. // XInflation
  2777. // XLastColProc
  2778. // #54 - Extraction-file-present flag
  2779. // Set XNextCol = 1
  2780. // Set XAdjEnd = -1 - for u=ignore for extraction process
  2781. //
  2782. #54=0 // Extraction-file-present flag
  2783. X_Init_Record()
  2784. //////////////////////////////////////////////////////////////////////////
  2785. //
  2786. // Field processing loop
  2787. //
  2788. BS(XLAY) //Switch to ebcdic.lay file
  2789. BOF
  2790. while(!AtEOF){ //For each field
  2791. //
  2792. // Process Vedit Macro expression.
  2793. // Allows adjusting pseudo repeat count (actually, variable record
  2794. // length counter) that counts the counter itself.
  2795. //
  2796. if (CC=='#'){
  2797. NE(ADVANCE) // Actually evaluates #x++ or #x+=2, e.g.
  2798. // ADVANCE helps tracing
  2799. l(1,errbreak)
  2800. continue
  2801. }
  2802. //
  2803. // out [filename]
  2804. //
  2805. if (match("out|[|W]",ADVANCE)==0){
  2806. if(Match("|{//,|>}")) {
  2807. #78=XLCP
  2808. Num_Push(77,78) // Save current output stream
  2809. call(50,"PRE")
  2810. call(58) // #77 = extraction buffer ID
  2811. } else {
  2812. call(50) // "POST"
  2813. Num_Pop(77,78) // Restore original output stream
  2814. XLCP(#78)
  2815. }
  2816. l(1,noerr) // Advance to next field description
  2817. continue
  2818. }
  2819. //////////////////////////////////////////////////////////////////////
  2820. // //
  2821. // Translate current field. //
  2822. // //
  2823. // Each independent subsection must entirely process its field, //
  2824. // leaving the edit position just past it and past any extra //
  2825. // characters that may have been added. //
  2826. // //
  2827. //////////////////////////////////////////////////////////////////////
  2828. X_Doit()
  2829. //
  2830. // Switch back to data description file.
  2831. //
  2832. BS(XLAY) //Switch to ebcdic.lay file
  2833. } // (!At_EOF)
  2834. //////////////////////////////////////////////////////////////////////
  2835. // //
  2836. // End of record processing. //
  2837. // //
  2838. //////////////////////////////////////////////////////////////////////
  2839. //
  2840. // Convert any final unspecified columns.
  2841. //
  2842. BS(XData)
  2843. //
  2844. //
  2845. //
  2846. if (#67<6){ // If terminated input records...
  2847. #0=eolpos-CP
  2848. }else{ // But for fixed length records...
  2849. #0=#87+XI-XNC+1
  2850. } // Anyway, #0 = # chars to eol
  2851. if (#0>0){
  2852. if (XDefType=='e'){
  2853. TRB(CP,CP+#0,REVERSE+NORESTORE)
  2854. }else{
  2855. C(#0)
  2856. }
  2857. }
  2858. //
  2859. // Delete any newline char(s).
  2860. //
  2861. if (#67<6) {
  2862. R("|L","")
  2863. }
  2864. //
  2865. // Move translated bytes into output buffer via T-Reg[0].
  2866. //
  2867. RCB(0,0,CP,DELETE)
  2868. BS(#77)
  2869. EOF()
  2870. //
  2871. // Include any .nam header file, if so specified.
  2872. //
  2873. if (#43&&AtBOF){
  2874. Ins_File("|(FILE_ONLY).nam")
  2875. }
  2876. if (RSIZE(0)>0){
  2877. if (#28&&AtBOL){
  2878. ic(' ')
  2879. XLCP(XLCP+1)
  2880. }
  2881. RI(0)
  2882. }
  2883. if (!AtBOL()){
  2884. //
  2885. // If any detail extraction file(s) specified, output unique ID
  2886. // plus comma and quote marks, if so specified.
  2887. //
  2888. if((#42&2)||(#54&&#42)){call(48)} // UID()
  2889. //
  2890. // Insert newline char(s), if so specified.
  2891. //
  2892. if ((0<=#68)&&(#68<6)){
  2893. if (#68!=1){IC(0x0d)} // DOS and MAC
  2894. if (#68!=2){IC(0x0a)} // DOS and UNIX
  2895. }
  2896. }
  2897. //
  2898. // Switch back to the source data buffer.
  2899. //
  2900. BS(XData)
  2901. } // Main processing loop
  2902. /////////////////////////////////////////////////////////////////////////////
  2903. //
  2904. // Set true to view final statistics.
  2905. //
  2906. if ( 0 ) { if (!Is_Quiet) {
  2907. Win_Hor(1)
  2908. Message("Converted records: ")
  2909. Num_Type(XRecNum-1,NOCR)
  2910. Message(" (")
  2911. Num_Type(100,LEFT+NOCR)
  2912. Message("%)")
  2913. Win_EOL()
  2914. Message("\nActual elapsed time: ")
  2915. if ( 0 ) {
  2916. Num_Type((Time_Tick - #32 + 500)/1000,LEFT+NOCR)
  2917. GetKey(" seconds.") // Pause at end of message
  2918. } else {
  2919. Num_Type(Time_Tick - #32,LEFT+NOCR)
  2920. GetKey(" milliseconds.") // Pause at end of message
  2921. }
  2922. }}
  2923. //////////////////////////////////////////////////////////////////////////////
  2924. //
  2925. call("CleanUp")
  2926. File_Save(BEGIN+NOMSG) // Save output file; goto BOF (quickly)
  2927. //
  2928. // Do any specified post-processing.
  2929. //
  2930. if (#64&8){call(#65+14)}
  2931. //
  2932. // Discard data description buffer.
  2933. // Delete the temporary file.
  2934. //
  2935. Buf_Switch(XLAY)
  2936. Buf_Quit(OK)
  2937. File_Delete(@(5),OK+NOERR)
  2938. //
  2939. // Release temporary source data file & delete it.
  2940. //
  2941. Buf_Switch(XData)
  2942. Buf_Quit(OK)
  2943. File_Delete(@(6),OK+NOERR) // Delete temporary data file
  2944. //
  2945. // Restore text and numerical registers and then terminate.
  2946. //
  2947. //{
  2948. :DONE:
  2949. Buf_Switch(#75) //Switch to main output buffer
  2950. Reg_Empty(101) //Empty error reporting submacro
  2951. Reg_Empty(102) //Empty unexpected breakout trapper
  2952. Call("CloseErr")
  2953. Num_Pop(70,99) //Restore numeric regs
  2954. Num_Pop(0,59)
  2955. Config(U_AUTO_CFG,#0) //Restore user's config values
  2956. Config(F_AUTO_SAVE,#1)
  2957. Config(F_OVER_MODE,#2)
  2958. Config(E_EXP_TAB,#5)
  2959. Config(E_RETAB_BK,#6)
  2960. Config(E_RETAB_FILL,#7 & 0xff )
  2961. Config(S_E_MORE,#8)
  2962. Config(D_DSP_WRAP,#9)
  2963. if (#99==0x57495C44) { //If WILDFILE macro running
  2964. Config(F_F_TYPE,#4)
  2965. Config(F_REC_HEAD,#5)
  2966. }
  2967. Num_Pop(0,10) //Restore remaining user numregs
  2968. Reg_Lock_Macro(#66)
  2969. #69 = 1 //WILDFILE flag for next time in
  2970. if (Is_Option(y)) { Xall(NOMSG) } //If "-Y" invocation, exit now
  2971. if (#99==0x57495C44) { //If WILDFILE macro running
  2972. if (!Is_Quiet) {
  2973. Type_Newline()
  2974. }
  2975. }
  2976. if (#105) {
  2977. vm(NOMSG)
  2978. }
  2979. return
  2980. //} DONE()
  2981. //////////////////////////////////////////////////////////////////////////////
  2982. //
  2983. // Clean up:
  2984. // Release source data file.
  2985. // Set appropriate viewing display modes for the output files.
  2986. // For DBASE, append <ctrl-z>'s and fixup header info.
  2987. //
  2988. //
  2989. // {
  2990. :CleanUp:
  2991. //
  2992. // Release source file.
  2993. //
  2994. BS(XData)
  2995. Buf_Quit(OK)
  2996. //
  2997. // Release .xrf file, unless DBASE
  2998. //
  2999. if (#28==0||#63==0){
  3000. File_Open("|@(8)",OK+NOMSG)
  3001. Buf_Quit(OK)
  3002. }
  3003. //
  3004. // Configure, save, goto 1st line of each output file.
  3005. //
  3006. Buf_Switch(#75)
  3007. call("SETDISP")
  3008. if ( #68 >= 0 ) { // (Any "r=" sets #68 > -1)
  3009. //
  3010. // Primary output file.
  3011. //
  3012. if (#68 <= 4 ) { // #68 = output record type?
  3013. Config(F_F_TYPE,#68,LOCAL) // Set record type for clean viewing
  3014. } else { if (#28==0){ // But when fixed output but not DBASE
  3015. if (#88<=0){
  3016. Config(F_F_TYPE,64,LOCAL) // Set arbitrary record size
  3017. } else {
  3018. Config(F_F_TYPE,#88,LOCAL)
  3019. }
  3020. } else { // For DBASE...
  3021. call("FIXDB")
  3022. }}
  3023. //
  3024. // Also for extracted files
  3025. //
  3026. BS(XLAY)
  3027. bof
  3028. repeat(all){
  3029. s("|<|{tx,rb|[|w]|[#|d|[|d]],out|!|L}|[|w]",advance+errbreak)
  3030. if (At_EOL){continue}
  3031. sm(8,cp)
  3032. rcb(0,cp,cp+1,norestore) // Copy delimiter into T-Reg[0]
  3033. s(@0) // Find terminating delimiter
  3034. rcb(0,marker(8),cp) // Copy filename into T-Reg[0]
  3035. bs(#75) // Switch to main buffer so that we can
  3036. // use e.g. tx "|(FILEONLY).as1"
  3037. fo("|@(0)",NOEVENT+NOMSG) // Switch to the buffer
  3038. call("SETDISP")
  3039. if (Is_Altered) {
  3040. if (#28==0){ // When not debased...
  3041. if (#68 <= 4 ) {
  3042. Config(F_F_TYPE,#68,LOCAL) // Set record type for clean viewing
  3043. } else {
  3044. Config(F_F_TYPE,64,LOCAL) // Set arbitrary record size
  3045. }
  3046. } else { // DBASE ...
  3047. call("FIXDB")
  3048. }
  3049. }
  3050. bs(XLAY) // Switch back to the data description file
  3051. }
  3052. bs(#75) // Switch back to the standard output file
  3053. }
  3054. return
  3055. // } // CleanUp()
  3056. //
  3057. // SETDISP -
  3058. //
  3059. // {
  3060. :SETDISP:
  3061. if (XDefType=='e') {
  3062. Config(D_DSP_MODE,4,LOCAL)
  3063. }
  3064. return
  3065. // } // SETDISP()
  3066. //
  3067. // FIXDB -
  3068. //
  3069. // {
  3070. :FIXDB:
  3071. EOF()
  3072. if ( Cur_Pos - BOL_Pos == 1 ){
  3073. Del_Char(-1) // Remove any orphaned "deleted-item" column
  3074. }
  3075. #0 = File_Size - Config( F_REC_HEAD )
  3076. if ( #0 > 0 ) {
  3077. Ins_Char( 0x1a ) // Append <EOF>
  3078. File_Save(BEGIN+NOMSG) // Set edit position to file beginning
  3079. Char(4) // Advance Cur_Pos to record counter field
  3080. #0 = #0 / Config( F_F_TYPE ) // #0 = # records
  3081. repeat(4){
  3082. Ins_Char(#0&0xFF,OVERWRITE)
  3083. #0 = #0 >> 8
  3084. }
  3085. Goto_Line(1) // Skip over any DBASE header
  3086. }
  3087. return
  3088. // } // FIXDB()
  3089. //////////////////////////////////////////////////////////////////////////////
  3090. // //
  3091. // Error Processing //
  3092. // //
  3093. //////////////////////////////////////////////////////////////////////////////
  3094. :MISSING:
  3095. Reg_Empty(1)
  3096. Out_Reg(1,APPEND)
  3097. Message("\n***** COBOL2V.VDM could not be found.")
  3098. Message("\n Invalid data description line:\n")
  3099. goto ALLBAD
  3100. :BAD_PARM:
  3101. Reg_Empty(1)
  3102. Out_Reg(1,APPEND)
  3103. Message("\n***** Unrecognized option: ")
  3104. type(1)
  3105. Message(" Occurred in line:\n")
  3106. goto ALLBAD
  3107. :BAD_LAY:
  3108. Reg_Empty(1)
  3109. Out_Reg(1,APPEND)
  3110. Message("\n***** Invalid data description line:\n")
  3111. //
  3112. // ALLBAD - Main Fatal Error handling routine.
  3113. // T-Reg[1] contains the error message; output has not yet been
  3114. // displayed but appended to the end of this register. This is done
  3115. // for quietness' sake.
  3116. // Enter: T-Reg[1] contains main error message.
  3117. // E-Buf[XLay] is the current edit buffer.
  3118. // Exit: Additional info put into T-Reg[1], which is then copied
  3119. // to the end of the .err file. Unless "-q" option, T-Reg[1]
  3120. // is also copied to the screen.
  3121. // Processing is terminated either with "xall" for ("-q") or
  3122. // Break-Out(Extra), otherwise.
  3123. //
  3124. // Note: See "DATERR" in T-Reg[101] for non-fatal data error reporting.
  3125. //
  3126. :ALLBAD:
  3127. BOL()
  3128. type(1) // Copy current .lay line to the end of T-Reg[1]
  3129. Out_Reg(CLEAR) // Turn output diversion off
  3130. //
  3131. // Find location of invalid specification in source .LAY file.
  3132. //
  3133. Search("|s")
  3134. if (At_EOL) {
  3135. #0 = Cur_Pos
  3136. } else {
  3137. #0 = Cur_Pos + 1
  3138. }
  3139. Reg_Copy_Block(0,BOL_Pos,Cur_Pos)
  3140. BOF
  3141. #1 = Search_Block("|<|@(0)",0,#0,ALL)
  3142. #0 = 0
  3143. if (!Is_Quiet) { // Want to keep edited layout file for "-q"
  3144. Buf_Quit(OK)
  3145. Buf_Switch(XLAY)
  3146. }
  3147. File_Open("|@(9)",OVERWRITE+NOMSG+NOERR) // Open source .lay file
  3148. Search("|<|@(0)",COUNT+NOERR,#1) // Won't be there for manufactured codes
  3149. //
  3150. // Write source line # and filename into .err file for "-q".
  3151. //
  3152. if (Is_Quiet) {
  3153. Out_Reg(1,APPEND)
  3154. Message("Line # ")
  3155. Num_Type(Cur_Line,LEFT)
  3156. Message("File: ")
  3157. Name_Write(EXTRA+NOMSG)
  3158. Out_Reg(CLEAR)
  3159. }
  3160. Call("ERRMSG")
  3161. if (Is_Quiet) {
  3162. XALL(1)
  3163. } else {
  3164. GetKey("\nPress any key to edit data layout file...")
  3165. Call("CloseErr")
  3166. Break_Out(EXTRA)
  3167. }
  3168. //
  3169. // ERRMSG - Output message in T-Reg[1] to screen and/or error file.
  3170. //
  3171. :ERRMSG:
  3172. if ( Reg_Size(#65+18) ) {
  3173. #0 = Buf_Num
  3174. File_Open("|@(#65+18)",NOMSG) // Really just a buffer switch
  3175. EOF
  3176. Reg_Ins(1)
  3177. Buf_Switch(#0)
  3178. }
  3179. if (!Is_Quiet) {
  3180. Reg_Type(1)
  3181. Reg_Empty(1)
  3182. Alert()
  3183. }
  3184. return
  3185. //
  3186. // CloseErr -
  3187. //
  3188. :CloseErr:
  3189. if (Reg_Size(#65+18)) { // If .err file exists
  3190. #0 = Buf_Num
  3191. File_Open("|@(#65+18)",NOMSG) // Buffer switch
  3192. if (#0==Buf_Num) {
  3193. #0 = XData // Don't want empty buffer/window
  3194. }
  3195. if (File_Size) { // If any errors
  3196. Buf_Close(NOMSG+DELETE) // Save the message(s)
  3197. } else {
  3198. Buf_Quit(OK) // Else discard the empty file
  3199. }
  3200. Buf_Switch(#0)
  3201. }
  3202. return
  3203. //////////////////////////////////////////////////////////////////////////////
  3204. // //
  3205. // Processing Macro specific parameters from DOS command via "-u" //
  3206. // //
  3207. //////////////////////////////////////////////////////////////////////////////
  3208. //
  3209. // OPTIONZ - Process user definable options from invocation line's "-u option_list".
  3210. //
  3211. // Note: WIN95 batch-file processing strips '=' from the parameter line.
  3212. // So, use '-' instead.
  3213. //
  3214. // Option_List:
  3215. // run_no // where 0 <= run_no < 10
  3216. // UID=val // (Default = auto = 1)
  3217. // d=run_date // For setting run date in Unique ID
  3218. // i[nclude][=val] // To include .nam at start of each output file
  3219. // // val={off,on} or {0,1}
  3220. // NOD // No explicit decimal points
  3221. //
  3222. // Enter:
  3223. // Retrn: #41 = run_no, 0 <= n < 9; run # for unique ID; default == 1.
  3224. // #42 = {0,1,2} for UID={off,auto,on or all}; default == 1.
  3225. // #43 = {0,1} for Include={off,on}; default == 0.
  3226. // #44 = {0,1} for preventing/allowing decimal points; default=1
  3227. // #50 = Run Date (# days since 1-1-1, more or less).
  3228. //
  3229. // Note: this routine is called both before and after preprocessing.
  3230. //
  3231. :OPTIONZ:
  3232. #3 = Buf_Num
  3233. #4 = 0
  3234. if (#64&0x800){ // Old style, from "-n 0x800"
  3235. #42 = 0
  3236. }
  3237. //
  3238. // Process "-u options" for version 5.30 and later
  3239. //
  3240. if (vn>=530){
  3241. Buf_Switch(Buf_Free(EXTRA))
  3242. Ins_Text(CMD_LINE)
  3243. EOF()
  3244. Ins_Char(' ')
  3245. if (Replace("|<|M-u"," ",BEGIN+NOERR)) {
  3246. #4 = Buf_Num
  3247. //
  3248. // Set Unique ID option to {off,auto,all}
  3249. //
  3250. if (Replace("|buid|[|w]|{=,-}"," ",BEGIN+NOERR)) {
  3251. #14 = Cur_Pos
  3252. if (match("|d")==0){
  3253. #42 = Num_Eval(ADVANCE)
  3254. } else { if (match("|{off,auto,all}",advance)==0) {
  3255. #42 = Match_Item - 1
  3256. } else { if (match("|{on,force}",advance)==0) {
  3257. #42 = 2
  3258. } else {
  3259. #42 = 0
  3260. }}}
  3261. if ( #42 < 0 || #42 > 2 ) {
  3262. #42 = 0
  3263. }
  3264. Del_Block(#14,CurPos)
  3265. }
  3266. //
  3267. // Include .nam header file at start of each output file, perhaps.
  3268. //
  3269. if (Search("|bi|[nclude]|s",BEGIN+NOERR)){
  3270. Del_Char(CMAT-1)
  3271. match("|W",ADVANCE)
  3272. #43 = 1
  3273. if (Match("|{=,-}|[|w]")==0){
  3274. Del_Char(Chars_Matched)
  3275. if (Match("|d")==0){
  3276. #43=Num_Eval()
  3277. } else { if (Match("|{off,on}")==0){
  3278. #43 = Match_Item - 1
  3279. }}
  3280. #43 = max(#43,0)
  3281. Del_Char(Chars_Matched)
  3282. }
  3283. }
  3284. //
  3285. // Set run_date for Unique ID: d=mm/dd/yyyy.
  3286. //
  3287. if (Replace("|bd|[|w]|{=,-}|[|w]","",BEGIN+NOERR)){
  3288. #50 = Num_Eval_Date()
  3289. Del_Char(Chars_Matched)
  3290. }
  3291. //
  3292. // Prohibit generation of explicit decimal points, perhaps.
  3293. //
  3294. if (Search("|bnod|s",BEGIN+NOERR)){
  3295. Del_Char(CMAT-1)
  3296. #44 = 0
  3297. }
  3298. //
  3299. // Process run-# for unique ID.
  3300. // Note: Keep this code at the end of the <IF "-u"> clause.
  3301. //
  3302. BOF()
  3303. if (match("|w|d|[|d]|b")==0){
  3304. #14 = Cur_Pos + 1
  3305. if ((#0 = Num_Eval(ADVANCE)) > 0 ) {
  3306. #41 = #0
  3307. Del_Block(#14,Cur_Pos)
  3308. }
  3309. }
  3310. } // <IF "-u">
  3311. }
  3312. //
  3313. // Clean up.
  3314. //
  3315. if (#4>0){
  3316. Buf_Switch(#4)
  3317. Buf_Quit(OK)
  3318. }
  3319. //
  3320. //
  3321. //
  3322. Buf_Switch(#3)
  3323. return
  3324. // OPTIONZ ends