[SOLVED] awk: how to achieve a 64character column file from a list of FORTH commands (and other things) ?
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
The previous solution wrapped at 56 + a new line; that could exceed the 64 length.
The following wraps close to the required 64 (but still does not split lines):
Code:
#!/usr/bin/awk -f
BEGIN { wrap=64 }
# Format the : block ;
$1 == ":" {
line=""
flag=1
}
flag {
nline=(line $0)
if (length(nline) > wrap) {
print line
line=$0
} else {
line=nline }
if ($NF == ";") {
flag=0
print line
}
next
}
{ print }
The following variant looks for the ending semicolon only in the formatted block, and then prints it unconditionally.
Code:
#!/usr/bin/awk -f
BEGIN{wrap=54}
/^:/{
line=""
flag=1
}
flag{
line=line $0
if (/;$/){
flag=0
print line
next
}
if (length(line)>wrap){
print line
line=""
}
next
}
{print}
That code was used for a time ( despite it eats few lines and more than 64 column output). Example below
original
Code:
-1 CONSTANT TRUE
0 CONSTANT FALSE
: >= < 0= ;
: 0<> 0= 0= ;
: .R >R S->D R> D.R ;
: D0= OR 0= ;
: D= D- D0= ;
: 2, , , ;
: 2! SWAP OVER ! 5+ ! ;
: 2@ DUP 5+ @ SWAP @ ;
: 2CONSTANT CREATE , , DOES> 2@ ;
: 2VARIABLE CREATE 0 , 0 , DOES> ;
: AT-XY 27 EMIT 37 EMIT SWAP EMIT EMIT ;
: BLANK 20 FILL ;
: CELLS 5 * ;
: CELL+ 5+ ;
: CELL- 5- ;
: CHAR+ 2+ ;
: CHAR- 2- ;
: CHAR BL WORD CHAR+ C@ ;
: NIP SWAP DROP ;
: AGAIN POSTPONE FALSE POSTPONE UNTIL ; IMMEDIATE
: [CHAR]
?COMP CHAR POSTPONE LITERAL ; IMMEDIATE
: CHARS 2* ;
: CHARI=
OVER XOR DUP 0= IF 2DROP TRUE EXIT THEN
DUP 32 <> IF 2DROP FALSE EXIT THEN
OR [CHAR] a [ CHAR z 1+ ] LITERAL WITHIN
;
: CHARI<>
CHARI= 0=
;
: EQUALSI
ROT OVER <> IF DROP 2DROP FALSE EXIT THEN
OVER + >R
BEGIN DUP R@ U< WHILE
>R COUNT R> COUNT ROT
CHARI<> IF 2DROP RDROP FALSE EXIT THEN
REPEAT 2DROP RDROP TRUE
;
: COMPARE S= 0<> ;
: ?DO
COMPILE 2DUP COMPILE = [COMPILE] IF COMPILE 2DROP
[COMPILE] ELSE [COMPILE] DO ['] THEN ; IMMEDIATE
: LOOP
DUP ['] THEN <> IF [COMPILE] LOOP EXIT THEN
>R [COMPILE] LOOP R> EXECUTE ; IMMEDIATE
: +LOOP
DUP ['] THEN <> IF [COMPILE] +LOOP EXIT THEN
>R [COMPILE] +LOOP R> EXECUTE ; IMMEDIATE
: MS 0 DO LOOP ;
: N>$ S->D STR$ ;
: ON TRUE SWAP ! ;
: OFF FALSE SWAP ! ;
: PAGE 27 EMIT 69 EMIT ;
: PERFORM @ EXECUTE ;
: -ROT ROT ROT ;
: TO
' >BODY STATE @ IF POSTPONE LITERAL POSTPONE ! EXIT
THEN ! ; IMMEDIATE
: +TO ' >BODY STATE @ IF POSTPONE LITERAL POSTPONE +! EXIT THEN
+! ; IMMEDIATE
: UNLOOP R> DROP R> DROP ;
: VALUE CREATE , DOES> @ ;
HEX
: VLIST E0005
D 1 DO
DUP @
BEGIN DUP
COUNT 1F AND 1-
DUP >R 2* SWAP DUP >R
+ C@ 7F AND R> R>
TYPE EMIT CR 5- @ ?DUP 0=
UNTIL
5+ LOOP DROP ;
DECIMAL
: WITHIN
OVER - >R - R> U< ;
filtered
Code:
-1 CONSTANT TRUE
0 CONSTANT FALSE
: >= < 0= ;
: 0<> 0= 0= ;
: .R >R S->D R> D.R ;
: D0= OR 0= ;
: D= D- D0= ;
: 2! SWAP OVER ! 5+ ! ;
: 2CONSTANT CREATE , , DOES> 2@ ;
: 2VARIABLE CREATE 0 , 0 , DOES> ;
: AT-XY 27 EMIT 37 EMIT SWAP EMIT EMIT ;
: BLANK 20 FILL ;
: CELLS 5 * ;
: CELL+ 5+ ;
: CELL- 5- ;
: CHAR+ 2+ ;
: CHAR- 2- ;
: CHAR BL WORD CHAR+ C@ ;
: NIP SWAP DROP ;
: CHARI= OVER XOR DUP 0= IF 2DROP TRUE EXIT THEN DUP 32 <> IF 2DROP FALSE EXIT THEN
OR [CHAR] a [ CHAR z 1+ ] LITERAL WITHIN;
: CHARI<> CHARI= 0=;
: EQUALSI ROT OVER <> IF DROP 2DROP FALSE EXIT THEN OVER + >R
BEGIN DUP R@ U< WHILE >R COUNT R> COUNT ROT CHARI<> IF 2DROP RDROP FALSE EXIT THEN
REPEAT 2DROP RDROP TRUE;
: COMPARE S= 0<> ;
: ?DO COMPILE 2DUP COMPILE = [COMPILE] IF COMPILE 2DROP
: LOOP DUP ['] THEN <> IF [COMPILE] LOOP EXIT THEN >R [COMPILE] LOOP R> EXECUTE ; IMMEDIATE
: +LOOP DUP ['] THEN <> IF [COMPILE] +LOOP EXIT THEN >R [COMPILE] +LOOP R> EXECUTE ; IMMEDIATE
: MS 0 DO LOOP ;
: N>$ S->D STR$ ;
: ON TRUE SWAP ! ;
: OFF FALSE SWAP ! ;
: PAGE 27 EMIT 69 EMIT ;
: PERFORM @ EXECUTE ;
: -ROT ROT ROT ;
: TO ' >BODY STATE @ IF POSTPONE LITERAL POSTPONE ! EXIT
: +TO ' >BODY STATE @ IF POSTPONE LITERAL POSTPONE +! EXIT THEN
: VLIST E0005 D 1 DO DUP @ BEGIN DUP COUNT 1F AND 1- DUP >R 2* SWAP DUP >R
+ C@ 7F AND R> R> TYPE EMIT CR 5- @ ?DUP 0= UNTIL 5+ LOOP DROP ;
DECIMAL
: WITHIN OVER - >R - R> U< ;
For example the HEX (line 66) disappeared. Anybody saying again thats not modern.. then look at the next Forth development ;-) https://8th-dev.com/
Any suggestion for improvement is more than welcome (I am awk limited). However, hand work is my currently plan B.
Target is:
- same structure as the file above top
- maximum 64 columns
Ideally the result
Code:
-1 CONSTANT TRUE
0 CONSTANT FALSE
: >= < 0= ;
: 0<> 0= 0= ;
: .R >R S->D R> D.R ;
: D0= OR 0= ;
: D= D- D0= ;
: 2, , , ;
: 2! SWAP OVER ! 5+ ! ;
: 2@ DUP 5+ @ SWAP @ ;
: 2CONSTANT CREATE , , DOES> 2@ ;
: 2VARIABLE CREATE 0 , 0 , DOES> ;
: AT-XY 27 EMIT 37 EMIT SWAP EMIT EMIT ;
: BLANK 20 FILL ;
: CELLS 5 * ;
: CELL+ 5+ ;
: CELL- 5- ;
: CHAR+ 2+ ;
: CHAR- 2- ;
: CHAR BL WORD CHAR+ C@ ;
: NIP SWAP DROP ;
: AGAIN POSTPONE FALSE POSTPONE UNTIL ; IMMEDIATE
: [CHAR] ?COMP CHAR POSTPONE LITERAL ; IMMEDIATE
: CHARS 2* ;
: CHARI= OVER XOR DUP 0= IF 2DROP TRUE EXIT THEN DUP 32 <> IF
2DROP FALSE EXIT THEN OR [CHAR] a [ CHAR z 1+ ] LITERAL WITHIN ;
: CHARI<> CHARI= 0= ;
: EQUALSI ROT OVER <> IF DROP 2DROP FALSE EXIT THEN OVER + >R
BEGIN DUP R@ U< WHILE >R COUNT R> COUNT ROT CHARI<> IF 2DROP
RDROP FALSE EXIT THEN REPEAT 2DROP RDROP TRUE ;
: COMPARE S= 0<> ;
: ?DO COMPILE 2DUP COMPILE = [COMPILE] IF COMPILE 2DROP
[COMPILE] ELSE [COMPILE] DO ['] THEN ; IMMEDIATE
: LOOP DUP ['] THEN <> IF [COMPILE] LOOP EXIT THEN >R [COMPILE]
LOOP R> EXECUTE ; IMMEDIATE
: +LOOP DUP ['] THEN <> IF [COMPILE] +LOOP EXIT THEN >R
[COMPILE] +LOOP R> EXECUTE ; IMMEDIATE
: MS 0 DO LOOP ;
: N>$ S->D STR$ ;
: ON TRUE SWAP ! ;
: OFF FALSE SWAP ! ;
: PAGE 27 EMIT 69 EMIT ;
: PERFORM @ EXECUTE ;
: -ROT ROT ROT ;
: TO ' >BODY STATE @ IF POSTPONE LITERAL POSTPONE ! EXIT THEN !
; IMMEDIATE
: +TO ' >BODY STATE @ IF POSTPONE LITERAL POSTPONE +! EXIT THEN
+! ; IMMEDIATE
: UNLOOP R> DROP R> DROP ;
: VALUE CREATE , DOES> @ ;
HEX
: VLIST E0005 D 1 DO DUP @ BEGIN DUP COUNT 1F AND 1- DUP >R 2*
SWAP DUP >R + C@ 7F AND R> R> TYPE EMIT CR 5- @ ?DUP 0= UNTIL
5+ LOOP DROP ;
DECIMAL
: WITHIN OVER - >R - R> U< ;
I will have a look. Thanks. My current thoughts are, after a good night sleep (different from my previous spec)
a) a ":" seen in a line should bring it to a carriage return (=new line starting with : )
b) ";" should be ignored (since it can have IMMEDIATE after ; )
c) width 64 is important (my hardware want this maximum length)
d) all identified character must have a blank between them (no concatenation of a character seen at line end with another character seen at next line start)
I will now review the awk codes
Yes. Good remark. Then I was rethinking (I am a bit slow)
In fact, we must think in 2 topics
a) how to form a text for readability
b) how to form a text for compatibilty to Forth INTERPRETER
- never a <CR> after a : because the compiler think it has no words. this mean, better to start a new line with : if it is the last word
- some words needs a word after them example POSTPONE cannot be at the end of the line because it act on the next word, it mean POSTPONE XXXX at the end of the
line is fine (NOT POSTPONE alone). Other words are COMPILE or CONSTANT or VARIABLE which need another word after them before the carriage return is done
From a readability point of view, a : at the beginning of the line is good.
But from Forth point of view, all words ( ; or : or IMMEDIATE or > etc.) are all Forth words which must be separated by a BLANK for the INTERPRETER to work correctly.
so, the code below will work because recognized by the interpreter (tested on gforth with another added file = it will not work alone in gforth).
But its no fun to read. Usually, the : should be at the beginning of the line.
Code:
-1 CONSTANT TRUE 0 CONSTANT FALSE : >= < 0= ; : 0<> 0= 0= ; : .R
>R S->D R> D.R ; : D0= OR 0= ; : D= D- D0= ; : 2, , , ; : 2!
SWAP OVER ! 5+ ! ; : 2@ DUP 5+ @ SWAP @ ; : 2CONSTANT CREATE , ,
DOES> 2@ ; : 2VARIABLE CREATE 0 , 0 , DOES> ; : AT-XY 27 EMIT 37
EMIT SWAP EMIT EMIT ; : BLANK 20 FILL ; : CELLS 5 * ; : CELL+
5+ ; : CELL- 5- ; : CHAR+ 2+ ; : CHAR- 2- ; : CHAR BL WORD CHAR+
C@ ; : NIP SWAP DROP ; : AGAIN POSTPONE FALSE POSTPONE UNTIL ;
IMMEDIATE : [CHAR] ?COMP CHAR POSTPONE LITERAL ; IMMEDIATE
: CHARS 2* ; : CHARI= OVER XOR DUP 0= IF 2DROP TRUE EXIT THEN
DUP 32 <> IF 2DROP FALSE EXIT THEN OR [CHAR] a [ CHAR z 1+ ]
LITERAL WITHIN ; : CHARI<> CHARI= 0= ; : EQUALSI ROT OVER <> IF
DROP 2DROP FALSE EXIT THEN OVER + >R BEGIN DUP R@ U< WHILE >R
COUNT R> COUNT ROT CHARI<> IF 2DROP RDROP FALSE EXIT THEN REPEAT
2DROP RDROP TRUE ; : COMPARE S= 0<> ; : ?DO COMPILE 2DUP
COMPILE = [COMPILE] IF COMPILE 2DROP [COMPILE] ELSE [COMPILE] DO
['] THEN ; IMMEDIATE : LOOP DUP ['] THEN <> IF [COMPILE] LOOP
EXIT THEN >R [COMPILE] LOOP R> EXECUTE ; IMMEDIATE : +LOOP DUP
['] THEN <> IF [COMPILE] +LOOP EXIT THEN >R [COMPILE] +LOOP R>
EXECUTE ; IMMEDIATE : MS 0 DO LOOP ; : N>$ S->D STR$ ; : ON TRUE
SWAP ! ; : OFF FALSE SWAP ! ; : PAGE 27 EMIT 69 EMIT ; : PERFORM
@ EXECUTE ; : -ROT ROT ROT ; : TO ' >BODY STATE @ IF
POSTPONE LITERAL POSTPONE ! EXIT THEN ! ; IMMEDIATE : +TO '
>BODY STATE @ IF POSTPONE LITERAL POSTPONE +! EXIT THEN +! ;
IMMEDIATE : UNLOOP R> DROP R> DROP ; : VALUE CREATE , DOES> @ ;
HEX : VLIST E0005 D 1 DO DUP @ BEGIN DUP COUNT 1F AND 1- DUP >R
2* SWAP DUP >R + C@ 7F AND R> R> TYPE EMIT CR 5- @ ?DUP 0= UNTIL
5+ LOOP DROP ; DECIMAL : WITHIN OVER - >R - R> U< ;
Last edited by floppy_stuttgart; 10-19-2023 at 05:44 AM.
That looks very good. Thanks.
Lets stay with it (with minimum handwork required; room for improvement: no blank at any start or end of the line, full 64 columns for all words ..).
The leading space can be eliminated. I think it is sufficient for the case when in a : block a line is not appended.
Just add one line.
Code:
...
line=$0
# Delete leading space
sub(/^ */, "", line)
...
Still the code can only join lines.
Splitting lines, in order to always fill to the 64 size, would be a new challenge. E.g. I guess that no split may occur in a quoted string like "hello world".
Last edited by MadeInGermany; 10-20-2023 at 01:33 AM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.