Skip to content

Manipulation with dc Macros: An Expert Guide

How to Work with Macros

In this example, we'll explore how to use macros with the dc command to manipulate and print characters.

Macros are a powerful feature in dc that allow you to define sequences of commands for reuse.

To print the character 'e', we can create a macro and execute it as follows:

dc -e '[101P]sa lax'

So it wont be possible to simply execute

dc -e "lax"

Explanation:

  • [101P]sa: This portion of the command defines a macro that does the following:
  • [101P]: Pushes the ASCII value 101 (which corresponds to 'e') onto the stack.
  • sa: Stores the defined macro in register 'a'.

  • lax: This part of the command loads and executes the macro stored in register 'a', which will result in the character 'e' being printed.

Now, let's take a look at how various commands in the dc language can be used to print different characters:

dc Command Sentence
lHA 'H'
lax 'e'
lbx 'l'
lcx 'l'
ldx 'o'
lex ' '
lfx 'w'
lgx 'o'
lhx 'r'
lix 'l'
ljx 'd'
dc Command Digits
lHA '10'

These commands demonstrate how to use dc to manipulate and print characters by defining and executing macros. You can create custom macros to handle various tasks and calculations in the dc language.

dc Command Uppercase
lAA 'A'
lBA 'B'
lCA 'C'
lDA 'D'
lEA 'E'
lFA 'F'
lGA 'G'
lHA 'H'
lIA 'I'
lJA 'J'
lKA 'K'
lLA 'L'
lMA 'M'
lNA 'N'
lOA 'O'
lPA 'P'
lQA 'Q'
lRA 'R'
lSA 'S'
lTA 'T'
lUA 'U'
lVA 'V'
lWA 'W'
lXA 'X'
lYA 'Y'
lZA 'Z'
dc Command Lowercase
laa 'a'
lba 'b'
lca 'c'
lda 'd'
lea 'e'
lfa 'f'
lga 'g'
lha 'h'
lia 'i'
lja 'j'
lka 'k'
lla 'l'
lma 'm'
lna 'n'
loa 'o'
lpa 'p'
lqa 'q'
lra 'r'
lsa 's'
lta 't'
lua 'u'
lva 'v'
lwa 'w'
lxa 'x'
lya 'y'
lza 'z'
dc Command Digits
l0a '0'
l1a '1'
l2a '2'
l3a '3'
l4a '4'
l5a '5'
l6a '6'
l7a '7'
l8a '8'
l9a '9'
dc Command Special
lsca ' ' (space)
ldota '.'
lcommaa ','
lexcla '!'
lquosa '"'
laposa '''
llbra '['
lrbra ']'
llpara '('
lrpara ')'
lhasha '#'
lampera '&'
lplusa '+'
lminusa '-'
lslasha '/'
lbacksla '\'
lquesta '?'
latra '@'
lastera '*'
lperca '%'
lcola ':'
lsemia ';'
lltbra '<'
lgtbra '>'
lequala '='
lcara '^'
ltildea '~'
lundera '_'
lpipa '
dc Command Character
lnewlinea 'n' (newline)
ltaba 't' (tab)
lcura '^' (caret)
ldolara '$' (dollar)
lgrava '`' (backtick)
lpipea '
ltildea '~' (tilde)
lbracka '{' (brace)
lrbracka '}' (right brace)
llesstha '<' (less than)
lgreatha '>' (greater than)
lequala '=' (equal)
lperca '%' (percent)
lplusa '+' (plus)
lminusa '-' (minus/hyphen)
lslasha '/' (forward slash)
lbacksla '\' (backslash)
lquesa '?' (question mark)
lexcla '!' (exclamation mark)
latra '@' (at symbol)
lhasha '#' (hash)
lampera '&' (ampersand)
lastera '*' (asterisk)
lsemia ';' (semicolon)
lcola ':' (colon)
lcommaa ',' (comma)
lperiosa '.' (period)
laposa ''' (apostrophe)
lquosa '"' (quotation mark)
llpara '(' (left parenthesis)
lrpara ')' (right parenthesis)
llbra '[' (left bracket)
lrbra ']' (right bracket)
lltbra '<' (less than)
lgtbra '>' (greater than)
lequala '=' (equal)
lcara '^' (caret)
lundera '_' (underscore)
ldota '.' (dot)
lbackticka '`' (backtick)

Execute Commands

Print H+$\(!p!\),

dc -e '72dP [101-72+dP]sa [108-101+dP]sb [108-108+dP]sc [111-108+dP]sd [32-111+dP]se [119-32+dP]sf [111-119+dP]sg [114-111+dP]sh [108-114+dP]si [100-108+dP]sj lax lbx lcx ldx lex lfx lgx lhx lix ljx'dc -e '0sI [72]sA0 [101]sA1 [108]sA2 [108]sA3 [111]sA4 [32]sA5 [87]sA6 [111]sA7 [114]sA8 [108]sA9 [100]sA10 [lAIsI lAI 1+ dsi 11<M]dsMx lI0<M'

Print same as above with x' above

dc -e '72dP [101-72+dP]sa [108-101+dP]sb [108-108+dP]sc [111-108+dP]sd [32-111+dP]se [119-32+dP]sf [111-119+dP]sg [114-111+dP]sh [108-114+dP]si [100-108+dP]sj lax lbx lcx ldx lex lfx lgx lhx lix ljx'
dc -e '[72P]sa [101P]sb [108P]sc [111P]sd [32P]se [87P]sf [114P]sg [100P]sh lax lbx lcxlcx ldx lex lfx ldx lgx lcx lhx'
dc -e '[72P]sa [101P]sb [108P]sc [111P]sd [32P]se [87P]sf [114P]sg [100P]sh lax lbx lcx lcx ldx lex lfx ldx lgx lcx lhx 32P'
dc -e '
[#]P[#]P
[#]P32P 
[H]P[E]P 
[L]P[L]P 
[O]P32P
[W]P [O]P[R]P 
[L]P[D]P32P'

And in a oneliner

dc -e '[#]P[#]P [#]P32P [H]P[E]P [L]P[L]P [O]P32P [W]P [O]P[R]P[L]P[D]P32P'

Use manual instead of apt, rtfm! // Patrik

dc -e "16i[q]sa[ln0=aln100%Pln100/snlbx]sb557365206D616E75616C20696E7374656164206F66206170742C207274666D21202F2F2050617472696Bsnlbxq" |rev

Direct Stack Manipulation (reversed)

You can push the ASCII values onto the stack in reverse order and print each one. This approach directly manipulates the stack

echo '100P 108P 114P 111P 87P 32P 111P 108P 108P 101P 72P' | dc

95P = _ 94P = ^ 50 = 2

Using Macros for Each Character

dc -e '[72P]sa [101P]sb [108P]sc [111P]sd [32P]se [87P]sf [114P]sg [100P]sh lax lbx lcx lcx ldx lex lfx ldx lgx lcx lhx 32P'

Incremental ASCII Print

You can start from a base character and incrementally add to it, printing along the way

dc -e '72dP 29d+P 7d+P 0d+P 3d+P 21d+P 55d+P 24d+P 3d+P 6d+P'

Script Example

Solving Complex Equations with dc

Let us illustrate how the desktop calculator can be adeptly employed for complex calculations. Consider the following equation:

\(p(x|y) = \frac{p(y|x)p(x)}{p(y)}\)

\((10 J) / (196 * x^2) = 4 kW/s\)

\(√, √2, √[n](), √[3]{x^3+y^3/2}\)

Firstly, we need to convert 4 kW/s to joules per second:

4 kW = 4000 J/s

Thus, the equation becomes:

(10 J) / (196 * x^2) = 4000 J/s

Now, let's solve for x^2:

x^2 = (10 J) / (196 * 4000 J/s)

And then take the square root to find x.

We will use dc to accomplish this:

dc -e '10 196 4000 * / v p'

This script performs the following steps:

  • 10 196 4000 * / computes (10 / (196 * 4000)), which gives us x^2.
  • v computes the square root of the result.
  • p prints the output.

If this yields 0, it could be due to the very small value of x^2. To address this, try increasing the precision in dc. Add the k command at the beginning of the script to set the precision. For example:

dc -e '10k 10 196 4000 * / v p'

Here, 10k sets the precision to 10 decimal places. Test this to see if it yields a more reasonable result for x.

Other examples

$ = dc -e '[1060P]sa lax'
! = dc -e '[1057P]sa lax'
[:space:] = dc -e '[1056P]sa lax'
\n = dc -e "[#]12P lax"
dc -e "[15]p[#]98P lax"|xargs|sed 's/ //g'