Changeset f988834


Ignore:
Timestamp:
Jan 19, 2024, 2:44:41 AM (20 months ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
ac939461
Parents:
59c8dff (diff), e8b3717 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
6 added
42 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/common.sty

    r59c8dff rf988834  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Fri Sep 29 16:48:59 2023
    14 %% Update Count     : 587
     13%% Last Modified On : Sun Jan 14 12:28:26 2024
     14%% Update Count     : 631
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    273273\setlength{\columnposn}{\gcolumnposn}
    274274\newcommand{\setgcolumn}[1]{\global\gcolumnposn=#1\global\columnposn=\gcolumnposn}
    275 \newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}}
     275\newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\LstCommentStyle{#2}}}
     276\newcommand{\CD}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\LstBasicStyle{#2}}}
    276277\newcommand{\CRT}{\global\columnposn=\gcolumnposn}
    277278
     
    292293xleftmargin=\parindentlnth,                             % indent code to paragraph indentation
    293294extendedchars=true,                                             % allow ASCII characters in the range 128-255
    294 escapechar=\$,                                                  % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-'
     295escapechar=§,                                                   % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-'
    295296mathescape=false,                                               % disable LaTeX math escape in CFA code $...$
    296297keepspaces=true,                                                %
     
    302303% replace/adjust listing characters that look bad in sanserif
    303304literate=
    304   {-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1
     305%  {-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1
     306  {-}{\raisebox{-1pt}{\texttt{-}}}1
    305307  {^}{\raisebox{0.6ex}{$\scriptstyle\land\,$}}1
    306308  {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1
     
    308310  {<-}{$\leftarrow$}2
    309311  {=>}{$\Rightarrow$}2
    310   {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex\textgreater}2,
     312%  {->}{\raisebox{-1pt}{\texttt{-}}\kern-0.1ex\textgreater}2,
    311313}% lstset
    312314}% CFAStyle
  • doc/LaTeXmacros/common.tex

    r59c8dff rf988834  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Fri Sep 29 16:49:02 2023
    14 %% Update Count     : 590
     13%% Last Modified On : Sun Jan 14 17:59:02 2024
     14%% Update Count     : 592
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    276276\setlength{\columnposn}{\gcolumnposn}
    277277\newcommand{\setgcolumn}[1]{\global\gcolumnposn=#1\global\columnposn=\gcolumnposn}
    278 \newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}}
     278\newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\LstCommentStyle{#2}}}
     279\newcommand{\CD}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\LstBasicStyle{#2}}}
    279280\newcommand{\CRT}{\global\columnposn=\gcolumnposn}
    280281
     
    296297xleftmargin=\parindentlnth,                             % indent code to paragraph indentation
    297298extendedchars=true,                                             % allow ASCII characters in the range 128-255
    298 escapechar=\$,                                                  % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-'
     299escapechar=§,                                                   % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-'
    299300mathescape=false,                                               % disable LaTeX math escape in CFA code $...$
    300301keepspaces=true,                                                %
     
    306307% replace/adjust listing characters that look bad in sanserif
    307308literate=
    308   {-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1
     309%  {-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1
     310  {-}{\raisebox{-1pt}{\texttt{-}}}1
    309311  {^}{\raisebox{0.6ex}{$\scriptstyle\land\,$}}1
    310312  {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1
     
    312314  {<-}{$\leftarrow$}2
    313315  {=>}{$\Rightarrow$}2
    314   {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex\textgreater}2,
     316%  {->}{\raisebox{-1pt}{\texttt{-}}\kern-0.1ex\textgreater}2,
    315317}% lstset
    316318}% CFAStyle
  • doc/user/user.tex

    r59c8dff rf988834  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sat Sep 30 22:46:19 2023
    14 %% Update Count     : 5658
     13%% Last Modified On : Sun Jan 14 17:27:41 2024
     14%% Update Count     : 5764
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    5555\SetWatermarkLightness{0.9}
    5656
    57 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
    58 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
    59 % AFTER HYPERREF.
    60 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
     57% Default underscore is too low. Cannot use lstlisting "literate" as replacing underscore removes it
     58% as a variable-name character so keywords in variables are highlighted. MUST APPEAR AFTER HYPERREF.
     59\renewcommand{\textunderscore}{\makebox[1.4ex][c]{{\raisebox{1.25pt}{\char`\_}}}}
    6160
    6261\setlength{\topmargin}{-0.45in}                                                 % move running title into header
     
    6766\CFAStyle                                                                                               % use default CFA format-style
    6867\setgcolumn{2.25in}
    69 %\lstset{language=CFA}                                                                  % CFA default lnaguage
     68\lstset{language=CFA}                                                                   % CFA default lnaguage
    7069\lstnewenvironment{C++}[1][]                            % use C++ style
    7170{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}
     
    172171\begin{tabular}{@{}lll@{}}
    173172\multicolumn{1}{@{}c}{\textbf{C}}       & \multicolumn{1}{c}{\textbf{\CFA}}     & \multicolumn{1}{c@{}}{\textbf{\CC}}   \\
    174 \begin{cfa}[tabsize=3]
    175 #include <stdio.h>$\indexc{stdio.h}$
     173\begin{cfa}
     174#include <stdio.h>§\indexc{stdio.h}§
    176175
    177176int main( void ) {
     
    182181&
    183182\begin{cfa}[tabsize=3]
    184 #include <fstream>$\indexc{fstream}$
     183#include <fstream>§\indexc{fstream}§
    185184
    186185int main( void ) {
    187186        int x = 0, y = 1, z = 2;
    188         ®sout | x | y | z;®$\indexc{sout}$
     187        ®sout | x | y | z;®§\indexc{sout}§
    189188}
    190189\end{cfa}
    191190&
    192191\begin{cfa}[tabsize=3]
    193 #include <iostream>$\indexc{iostream}$
     192#include <iostream>§\indexc{iostream}§
    194193using namespace std;
    195194int main() {
     
    260259\begin{cfa}
    261260®forall( T )® T identity( T val ) { return val; }
    262 int forty_two = identity( 42 ); $\C{// T is bound to int, forty\_two == 42}$
     261int forty_two = identity( 42 ); §\C{// T is bound to int, forty\_two == 42}§
    263262\end{cfa}
    264263% extending the C type system with parametric polymorphism and overloading, as opposed to the \Index*[C++]{\CC{}} approach of object-oriented extensions.
     
    288287
    289288double key = 5.0, vals[10] = { /* 10 sorted floating values */ };
    290 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); $\C{// search sorted array}$
     289double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); §\C{// search sorted array}§
    291290\end{cfa}
    292291which can be augmented simply with a polymorphic, type-safe, \CFA-overloaded wrappers:
     
    297296
    298297forall( T | { int ?<?( T, T ); } ) unsigned int bsearch( T key, const T * arr, size_t size ) {
    299         T * result = bsearch( key, arr, size ); $\C{// call first version}$
    300         return result ? result - arr : size; } $\C{// pointer subtraction includes sizeof(T)}$
    301 
    302 double * val = bsearch( 5.0, vals, 10 ); $\C{// selection based on return type}$
     298        T * result = bsearch( key, arr, size ); §\C{// call first version}§
     299        return result ? result - arr : size; } §\C{// pointer subtraction includes sizeof(T)}§
     300
     301double * val = bsearch( 5.0, vals, 10 ); §\C{// selection based on return type}§
    303302int posn = bsearch( 5.0, vals, 10 );
    304303\end{cfa}
     
    312311\begin{cfa}
    313312forall( dtype T | sized(T) ) T * malloc( void ) { return (T *)malloc( sizeof(T) ); }
    314 int * ip = malloc(); $\C{// select type and size from left-hand side}$
     313int * ip = malloc(); §\C{// select type and size from left-hand side}§
    315314double * dp = malloc();
    316315struct S {...} * sp = malloc();
     
    324323\begin{cfa}
    325324char ®abs®( char );
    326 extern "C" { int ®abs®( int ); } $\C{// use default C routine for int}$
     325extern "C" { int ®abs®( int ); } §\C{// use default C routine for int}§
    327326long int ®abs®( long int );
    328327long long int ®abs®( long long int );
     
    349348The command ©cfa© is used to compile a \CFA program and is based on the \Index{GNU} \Indexc{gcc} command, \eg:
    350349\begin{cfa}
    351 cfa$\indexc{cfa}\index{compilation!cfa@©cfa©}$ [ gcc/$\CFA{}$-options ] [ C/$\CFA{}$ source-files ] [ assembler/loader files ]
     350cfa§\indexc{cfa}\index{compilation!cfa@©cfa©}§ [ gcc/§\CFA{}§-options ] [ C/§\CFA{}§ source-files ] [ assembler/loader files ]
    352351\end{cfa}
    353352There is no ordering among options (flags) and files, unless an option has an argument, which must appear immediately after the option possibly with or without a space separating option and argument.
     
    438437\begin{cfa}
    439438#ifndef __CFORALL__
    440 #include <stdio.h>$\indexc{stdio.h}$ $\C{// C header file}$
     439#include <stdio.h>§\indexc{stdio.h}§ §\C{// C header file}§
    441440#else
    442 #include <fstream>$\indexc{fstream}$ $\C{// \CFA header file}$
     441#include <fstream>§\indexc{fstream}§ §\C{// \CFA header file}§
    443442#endif
    444443\end{cfa}
     
    450449Each option must be escaped with \Indexc{-XCFA}\index{translator option!-XCFA@{©-XCFA©}} to direct it to the compiler step, similar to the ©-Xlinker© flag for the linker, \eg:
    451450\begin{lstlisting}[language=sh]
    452 cfa $test$.cfa -CFA -XCFA -p # print translated code without printing the standard prelude
    453 cfa $test$.cfa -XCFA -P -XCFA parse -XCFA -n # show program parse without prelude
     451cfa §test§.cfa -CFA -XCFA -p # print translated code without printing the standard prelude
     452cfa §test§.cfa -XCFA -P -XCFA parse -XCFA -n # show program parse without prelude
    454453\end{lstlisting}
    455 Alternatively, multiple flages can be specified separated with commas and \emph{without} spaces.
     454Alternatively, multiple flags can be specified separated with commas and \emph{without} spaces.
    456455\begin{lstlisting}[language=sh,{moredelim=**[is][\protect\color{red}]{®}{®}}]
    457 cfa $test$.cfa -XCFA®,®-Pparse®,®-n # show program parse without prelude
     456cfa §test§.cfa -XCFA®,®-Pparse®,®-n # show program parse without prelude
    458457\end{lstlisting}
    459458\begin{description}[topsep=5pt,itemsep=0pt,parsep=0pt]
     
    537536Keyword clashes are accommodated by syntactic transformations using the \CFA backquote escape-mechanism:
    538537\begin{cfa}
    539 int ®``®coroutine = 3;                                  $\C{// make keyword an identifier}$
     538int ®``®coroutine = 3;                                  §\C{// make keyword an identifier}§
    540539double ®``®forall = 3.5;
    541540\end{cfa}
     
    547546\begin{cfa}
    548547// include file uses the CFA keyword "with".
    549 #if ! defined( with )                                   $\C{// nesting ?}$
    550 #define with ®``®with                                   $\C{// make keyword an identifier}$
     548#if ! defined( with )                                   §\C{// nesting ?}§
     549#define with ®``®with                                   §\C{// make keyword an identifier}§
    551550#define __CFA_BFD_H__
    552551#endif
    553 $\R{\#include\_next} <bfdlink.h>$               $\C{// must have internal check for multiple expansion}$
    554 #if defined( with ) && defined( __CFA_BFD_H__ ) $\C{// reset only if set}$
     552§\R{\#include\_next} <bfdlink.h>§               §\C{// must have internal check for multiple expansion}§
     553#if defined( with ) && defined( __CFA_BFD_H__ ) §\C{// reset only if set}§
    555554#undef with
    556555#undef __CFA_BFD_H__
     
    566565Numeric constants are extended to allow \Index{underscore}s\index{constant!underscore} as a separator, \eg:
    567566\begin{cfa}
    568 2®_®147®_®483®_®648;                                    $\C{// decimal constant}$
    569 56®_®ul;                                                                $\C{// decimal unsigned long constant}$
    570 0®_®377;                                                                $\C{// octal constant}$
    571 0x®_®ff®_®ff;                                                   $\C{// hexadecimal constant}$
    572 0x®_®ef3d®_®aa5c;                                               $\C{// hexadecimal constant}$
    573 3.141®_®592®_®654;                                              $\C{// floating constant}$
    574 10®_®e®_®+1®_®00;                                               $\C{// floating constant}$
    575 0x®_®ff®_®ff®_®p®_®3;                                   $\C{// hexadecimal floating}$
    576 0x®_®1.ffff®_®ffff®_®p®_®128®_®l;               $\C{// hexadecimal floating long constant}$
    577 L®_®$"\texttt{\textbackslash{x}}$®_®$\texttt{ff}$®_®$\texttt{ee}"$; $\C{// wide character constant}$
     5672®_®147®_®483®_®648;                                    §\C{// decimal constant}§
     56856®_®ul;                                                                §\C{// decimal unsigned long constant}§
     5690®_®377;                                                                §\C{// octal constant}§
     5700x®_®ff®_®ff;                                                   §\C{// hexadecimal constant}§
     5710x®_®ef3d®_®aa5c;                                               §\C{// hexadecimal constant}§
     5723.141®_®592®_®654;                                              §\C{// floating constant}§
     57310®_®e®_®+1®_®00;                                               §\C{// floating constant}§
     5740x®_®ff®_®ff®_®p®_®3;                                   §\C{// hexadecimal floating}§
     5750x®_®1.ffff®_®ffff®_®p®_®128®_®l;               §\C{// hexadecimal floating long constant}§
     576L®_®§"\texttt{\textbackslash{x}}§®_®§\texttt{ff}§®_®§\texttt{ee}"§; §\C{// wide character constant}§
    578577\end{cfa}
    579578The rules for placement of underscores are:
     
    635634Declarations in the \Indexc{do}-©while© condition are not useful because they appear after the loop body.}
    636635\begin{cfa}
    637 if ( ®int x = f()® ) ...                        $\C{// x != 0}$
    638 if ( ®int x = f(), y = g()® ) ...       $\C{// x != 0 \&\& y != 0}$
    639 if ( ®int x = f(), y = g(); x < y® ) ... $\C{// relational expression}$
    640 if ( ®struct S { int i; } x = { f() }; x.i < 4® ) $\C{// relational expression}$
    641 
    642 while ( ®int x = f()® ) ...                     $\C{// x != 0}$
    643 while ( ®int x = f(), y = g()® ) ... $\C{// x != 0 \&\& y != 0}$
    644 while ( ®int x = f(), y = g(); x < y® ) ... $\C{// relational expression}$
    645 while ( ®struct S { int i; } x = { f() }; x.i < 4® ) ... $\C{// relational expression}$
     636if ( ®int x = f()® ) ...                        §\C{// x != 0}§
     637if ( ®int x = f(), y = g()® ) ...       §\C{// x != 0 \&\& y != 0}§
     638if ( ®int x = f(), y = g(); x < y® ) ... §\C{// relational expression}§
     639if ( ®struct S { int i; } x = { f() }; x.i < 4® ) §\C{// relational expression}§
     640
     641while ( ®int x = f()® ) ...                     §\C{// x != 0}§
     642while ( ®int x = f(), y = g()® ) ... §\C{// x != 0 \&\& y != 0}§
     643while ( ®int x = f(), y = g(); x < y® ) ... §\C{// relational expression}§
     644while ( ®struct S { int i; } x = { f() }; x.i < 4® ) ... §\C{// relational expression}§
    646645\end{cfa}
    647646Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard semantics for the ©if©/©while© expression, and the results are combined using the logical \Indexc{&&} operator.
     
    713712\begin{cfa}
    714713switch ( i ) {
    715   case 1$\R{\textvisiblespace}$®...®4:
     714  case 1§\R{\textvisiblespace}§®...®4:
    716715        ...
    717   case 10$\R{\textvisiblespace}$®...®13:
     716  case 10§\R{\textvisiblespace}§®...®13:
    718717        ...
    719718}
     
    752751  case 1:
    753752        ...
    754         $\R{\LstCommentStyle{// fall-through}}$
     753        §\R{\LstCommentStyle{// fall-through}}§
    755754  case 2:
    756755        ...
     
    853852\begin{cfa}
    854853switch ( x ) {
    855         ®int y = 1;® $\C{// unreachable initialization}$
    856         ®x = 7;® $\C{// unreachable code without label/branch}$
     854        ®int y = 1;® §\C{// unreachable initialization}§
     855        ®x = 7;® §\C{// unreachable code without label/branch}§
    857856  case 0: ...
    858857        ...
    859         ®int z = 0;® $\C{// unreachable initialization, cannot appear after case}$
     858        ®int z = 0;® §\C{// unreachable initialization, cannot appear after case}§
    860859        z = 2;
    861860  case 1:
    862         ®x = z;® $\C{// without fall through, z is uninitialized}$
     861        ®x = z;® §\C{// without fall through, z is uninitialized}§
    863862}
    864863\end{cfa}
     
    895894  case 1:  case 2:  case 3:
    896895        ...
    897         $\R{\LstCommentStyle{// implicit end of switch (break)}}$
     896        §\R{\LstCommentStyle{// implicit end of switch (break)}}§
    898897  case 5:
    899898        ...
    900         ®fallthru®; $\C{// explicit fall through}$
     899        ®fallthru®; §\C{// explicit fall through}§
    901900  case 7:
    902901        ...
    903         ®break® $\C{// explicit end of switch (redundant)}$
     902        ®break® §\C{// explicit end of switch (redundant)}§
    904903  default:
    905904        j = 3;
     
    922921\begin{cfa}
    923922switch ( x ) {
    924         ®int i = 0;®                                            $\C{// allowed only at start}$
     923        ®int i = 0;®                                            §\C{// allowed only at start}§
    925924  case 0:
    926925        ...
    927         ®int j = 0;®                                            $\C{// disallowed}$
     926        ®int j = 0;®                                            §\C{// disallowed}§
    928927  case 1:
    929928        {
    930                 ®int k = 0;®                                    $\C{// allowed at different nesting levels}$
     929                ®int k = 0;®                                    §\C{// allowed at different nesting levels}§
    931930                ...
    932           ®case 2:®                                                     $\C{// disallow case in nested statements}$
     931          ®case 2:®                                                     §\C{// disallow case in nested statements}§
    933932        }
    934933  ...
     
    10041003while () { sout | "empty"; break; }
    10051004do { sout | "empty"; break; } while ();
    1006 for () { sout | "empty"; break; }                                                       $\C[3in]{sout | nl | nlOff;}$
    1007 
    1008 for ( 0 ) { sout | "A"; } sout | "zero";                                        $\C{sout | nl;}$
    1009 for ( 1 ) { sout | "A"; }                                                                       $\C{sout | nl;}$
    1010 for ( 10 ) { sout | "A"; }                                                                      $\C{sout | nl;}$
    1011 for ( ~= 10 ) { sout | "A"; }                                                           $\C{sout | nl;}$
    1012 for ( 1 ~= 10 ~ 2 ) { sout | "B"; }                                                     $\C{sout | nl;}$
    1013 for ( 1 -~= 10 ~ 2 ) { sout | "C"; }                                            $\C{sout | nl;}$
    1014 for ( 0.5 ~ 5.5 ) { sout | "D"; }                                                       $\C{sout | nl;}$
    1015 for ( 0.5 -~ 5.5 ) { sout | "E"; }                                                      $\C{sout | nl;}$
    1016 for ( i; 10 ) { sout | i; }                                                                     $\C{sout | nl;}$
    1017 for ( i; ~= 10 ) { sout | i; }                                                          $\C{sout | nl;}$
    1018 for ( i; 1 ~= 10 ~ 2 ) { sout | i; }                                            $\C{sout | nl;}$
    1019 for ( i; 1 -~= 10 ~ 2 ) { sout | i; }                                           $\C{sout | nl;}$
    1020 for ( i; 0.5 ~ 5.5 ) { sout | i; }                                                      $\C{sout | nl;}$
    1021 for ( i; 0.5 -~ 5.5 ) { sout | i; }                                                     $\C{sout | nl;}$
    1022 for ( ui; 2u ~= 10u ~ 2u ) { sout | ui; }                                       $\C{sout | nl;}$
    1023 for ( ui; 2u -~= 10u ~ 2u ) { sout | ui; }                                      $\C{sout | nl | nl | nl;}$
     1005for () { sout | "empty"; break; }                                                       §\C[3in]{sout | nl | nlOff;}§
     1006
     1007for ( 0 ) { sout | "A"; } sout | "zero";                                        §\C{sout | nl;}§
     1008for ( 1 ) { sout | "A"; }                                                                       §\C{sout | nl;}§
     1009for ( 10 ) { sout | "A"; }                                                                      §\C{sout | nl;}§
     1010for ( ~= 10 ) { sout | "A"; }                                                           §\C{sout | nl;}§
     1011for ( 1 ~= 10 ~ 2 ) { sout | "B"; }                                                     §\C{sout | nl;}§
     1012for ( 1 -~= 10 ~ 2 ) { sout | "C"; }                                            §\C{sout | nl;}§
     1013for ( 0.5 ~ 5.5 ) { sout | "D"; }                                                       §\C{sout | nl;}§
     1014for ( 0.5 -~ 5.5 ) { sout | "E"; }                                                      §\C{sout | nl;}§
     1015for ( i; 10 ) { sout | i; }                                                                     §\C{sout | nl;}§
     1016for ( i; ~= 10 ) { sout | i; }                                                          §\C{sout | nl;}§
     1017for ( i; 1 ~= 10 ~ 2 ) { sout | i; }                                            §\C{sout | nl;}§
     1018for ( i; 1 -~= 10 ~ 2 ) { sout | i; }                                           §\C{sout | nl;}§
     1019for ( i; 0.5 ~ 5.5 ) { sout | i; }                                                      §\C{sout | nl;}§
     1020for ( i; 0.5 -~ 5.5 ) { sout | i; }                                                     §\C{sout | nl;}§
     1021for ( ui; 2u ~= 10u ~ 2u ) { sout | ui; }                                       §\C{sout | nl;}§
     1022for ( ui; 2u -~= 10u ~ 2u ) { sout | ui; }                                      §\C{sout | nl | nl | nl;}§
    10241023
    10251024enum { N = 10 };
    1026 for ( N ) { sout | "N"; }                                                                       $\C{sout | nl;}$
    1027 for ( i; N ) { sout | i; }                                                                      $\C{sout | nl;}$
    1028 for ( i; -~ N ) { sout | i; }                                                           $\C{sout | nl | nl | nl;}$
     1025for ( N ) { sout | "N"; }                                                                       §\C{sout | nl;}§
     1026for ( i; N ) { sout | i; }                                                                      §\C{sout | nl;}§
     1027for ( i; -~ N ) { sout | i; }                                                           §\C{sout | nl | nl | nl;}§
    10291028
    10301029const int low = 3, high = 10, inc = 2;
    1031 for ( i; low ~ high ~ inc + 1 ) { sout | i; }                           $\C{sout | nl;}$
    1032 for ( i; 1 ~ @ ) { if ( i > 10 ) break; sout | i; }                     $\C{sout | nl;}$
    1033 for ( i; @ -~ 10 ) { if ( i < 0 ) break; sout | i; }            $\C{sout | nl;}$
    1034 for ( i; 2 ~ @ ~ 2 ) { if ( i > 10 ) break; sout | i; }         $\C{sout | nl;}$
    1035 for ( i; 2.1 ~ @ ~ @ ) { if ( i > 10.5 ) break; sout | i; i += 1.7; } $\C{sout | nl;}$
    1036 for ( i; @ -~ 10 ~ 2 ) { if ( i < 0 ) break; sout | i; }        $\C{sout | nl;}$
    1037 for ( i; 12.1 ~ @ ~ @ ) { if ( i < 2.5 ) break; sout | i; i -= 1.7; } $\C{sout | nl;}$
    1038 for ( i; 5 : j; -5 ~ @ ) { sout | i | j; }                                      $\C{sout | nl;}$
    1039 for ( i; 5 : j; @ -~ -5 ) { sout | i | j; }                                     $\C{sout | nl;}$
    1040 for ( i; 5 : j; -5 ~ @ ~ 2 ) { sout | i | j; }                          $\C{sout | nl;}$
    1041 for ( i; 5 : j; @ -~ -5 ~ 2 ) { sout | i | j; }                         $\C{sout | nl;}$
    1042 for ( i; 5 : j; -5 ~ @ ) { sout | i | j; }                                      $\C{sout | nl;}$
    1043 for ( i; 5 : j; @ -~ -5 ) { sout | i | j; }                                     $\C{sout | nl;}$
    1044 for ( i; 5 : j; -5 ~ @ ~ 2 ) { sout | i | j; }                          $\C{sout | nl;}$
    1045 for ( i; 5 : j; @ -~ -5 ~ 2 ) { sout | i | j; }                         $\C{sout | nl;}$
    1046 for ( i; 5 : j; @ -~ -5 ~ 2 : k; 1.5 ~ @ ) { sout | i | j | k; } $\C{sout | nl;}$
    1047 for ( i; 5 : j; @ -~ -5 ~ 2 : k; 1.5 ~ @ ) { sout | i | j | k; } $\C{sout | nl;}$
    1048 for ( i; 5 : k; 1.5 ~ @ : j; @ -~ -5 ~ 2 ) { sout | i | j | k; } $\C{sout | nl;}\CRT$
     1030for ( i; low ~ high ~ inc + 1 ) { sout | i; }                           §\C{sout | nl;}§
     1031for ( i; 1 ~ @ ) { if ( i > 10 ) break; sout | i; }                     §\C{sout | nl;}§
     1032for ( i; @ -~ 10 ) { if ( i < 0 ) break; sout | i; }            §\C{sout | nl;}§
     1033for ( i; 2 ~ @ ~ 2 ) { if ( i > 10 ) break; sout | i; }         §\C{sout | nl;}§
     1034for ( i; 2.1 ~ @ ~ @ ) { if ( i > 10.5 ) break; sout | i; i += 1.7; } §\C{sout | nl;}§
     1035for ( i; @ -~ 10 ~ 2 ) { if ( i < 0 ) break; sout | i; }        §\C{sout | nl;}§
     1036for ( i; 12.1 ~ @ ~ @ ) { if ( i < 2.5 ) break; sout | i; i -= 1.7; } §\C{sout | nl;}§
     1037for ( i; 5 : j; -5 ~ @ ) { sout | i | j; }                                      §\C{sout | nl;}§
     1038for ( i; 5 : j; @ -~ -5 ) { sout | i | j; }                                     §\C{sout | nl;}§
     1039for ( i; 5 : j; -5 ~ @ ~ 2 ) { sout | i | j; }                          §\C{sout | nl;}§
     1040for ( i; 5 : j; @ -~ -5 ~ 2 ) { sout | i | j; }                         §\C{sout | nl;}§
     1041for ( i; 5 : j; -5 ~ @ ) { sout | i | j; }                                      §\C{sout | nl;}§
     1042for ( i; 5 : j; @ -~ -5 ) { sout | i | j; }                                     §\C{sout | nl;}§
     1043for ( i; 5 : j; -5 ~ @ ~ 2 ) { sout | i | j; }                          §\C{sout | nl;}§
     1044for ( i; 5 : j; @ -~ -5 ~ 2 ) { sout | i | j; }                         §\C{sout | nl;}§
     1045for ( i; 5 : j; @ -~ -5 ~ 2 : k; 1.5 ~ @ ) { sout | i | j | k; } §\C{sout | nl;}§
     1046for ( i; 5 : j; @ -~ -5 ~ 2 : k; 1.5 ~ @ ) { sout | i | j | k; } §\C{sout | nl;}§
     1047for ( i; 5 : k; 1.5 ~ @ : j; @ -~ -5 ~ 2 ) { sout | i | j | k; } §\C{sout | nl;}\CRT§
    10491048\end{cfa}
    10501049&
     
    11171116The \Indexc{for}, \Indexc{while}, and \Indexc{do} loop-control allow an empty conditional, which implies a comparison value of ©1© (true).
    11181117\begin{cfa}
    1119 while ( ®/* empty */®  )                                $\C{// while ( true )}$
    1120 for ( ®/* empty */®  )                                  $\C{// for ( ; true; )}$
    1121 do ... while ( ®/* empty */®  )                 $\C{// do ... while ( true )}$
     1118while ( ®/* empty */®  )                                §\C{// while ( true )}§
     1119for ( ®/* empty */®  )                                  §\C{// for ( ; true; )}§
     1120do ... while ( ®/* empty */®  )                 §\C{// do ... while ( true )}§
    11221121\end{cfa}
    11231122
     
    11491148If no type is specified for the loop index, it is the type of the high value H (when the low value is implicit) or the low value L.
    11501149\begin{cfa}
    1151 for ( ®5® )                                                             $\C{// typeof(5) anonymous-index; 5 is high value}$
    1152 for ( i; ®1.5® ~ 5.5 )                                  $\C{// typeof(1.5) i; 1.5 is low value}$
    1153 for ( ®int i®; 0 ~ 10 ~ 2 )                             $\C{// int i; type is explicit}$
     1150for ( ®5® )                                                             §\C{// typeof(5) anonymous-index; 5 is high value}§
     1151for ( i; ®1.5® ~ 5.5 )                                  §\C{// typeof(1.5) i; 1.5 is low value}§
     1152for ( ®int i®; 0 ~ 10 ~ 2 )                             §\C{// int i; type is explicit}§
    11541153\end{cfa}
    11551154
     
    11591158H is implicit up-to exclusive range [0,H\R{)}.
    11601159\begin{cfa}
    1161 for ( ®5® )                                                             $\C{// for ( typeof(5) i; i < 5; i += 1 )}$
     1160for ( ®5® )                                                             §\C{// for ( typeof(5) i; i < 5; i += 1 )}§
    11621161\end{cfa}
    11631162\item
    11641163©~=© H is implicit up-to inclusive range [0,H\R{]}.
    11651164\begin{cfa}
    1166 for ( ®~=® 5 )                                                  $\C{// for ( typeof(5) i; i <= 5; i += 1 )}$
     1165for ( ®~=® 5 )                                                  §\C{// for ( typeof(5) i; i <= 5; i += 1 )}§
    11671166\end{cfa}
    11681167\item
    11691168L ©~©\index{~@©~©} H is explicit up-to exclusive range [L,H\R{)}.
    11701169\begin{cfa}
    1171 for ( 1 ®~® 5 )                                                 $\C{// for ( typeof(1) i = 1; i < 5; i += 1 )}$
     1170for ( 1 ®~® 5 )                                                 §\C{// for ( typeof(1) i = 1; i < 5; i += 1 )}§
    11721171\end{cfa}
    11731172\item
    11741173L ©~=©\index{~=@©~=©} H is explicit up-to inclusive range [L,H\R{]}.
    11751174\begin{cfa}
    1176 for ( 1 ®~=® 5 )                                                $\C{// for ( typeof(1) i = 1; i <= 5; i += 1 )}$
     1175for ( 1 ®~=® 5 )                                                §\C{// for ( typeof(1) i = 1; i <= 5; i += 1 )}§
    11771176\end{cfa}
    11781177\item
    11791178L ©-~©\index{-~@©-~©} H is explicit down-to exclusive range [H,L\R{)}, where L and H are implicitly interchanged to make the range down-to.
    11801179\begin{cfa}
    1181 for ( 1 ®-~® 5 )                                                $\C{// for ( typeof(1) i = 5; i > 0; i -= 1 )}$
     1180for ( 1 ®-~® 5 )                                                §\C{// for ( typeof(1) i = 5; i > 0; i -= 1 )}§
    11821181\end{cfa}
    11831182\item
    11841183L ©-~=©\index{-~=@©-~=©} H is explicit down-to inclusive range [H,L\R{]}, where L and H are implicitly interchanged to make the range down-to.
    11851184\begin{cfa}
    1186 for ( 1 ®-~=® 5 )                                               $\C{// for ( typeof(1) i = 5; i >= 0; i -= 1 )}$
     1185for ( 1 ®-~=® 5 )                                               §\C{// for ( typeof(1) i = 5; i >= 0; i -= 1 )}§
    11871186\end{cfa}
    11881187\item
    11891188©@© means put nothing in this field.
    11901189\begin{cfa}
    1191 for ( i; 1 ~ ®@® ~ 2 )                                  $\C{// for ( typeof(1) i = 1; \R{/* empty */}; i += 2 )}$
    1192 for ( i; 1 ~ 10 ~ ®@® )                                 $\C{// for ( typeof(1) i = 1; i < 10; \R{/* empty */} )}$
    1193 for ( i; 1 ~ ®@® ~ ®@® )                                $\C{// for ( typeof(1) i = 1; /*empty*/; \R{/* empty */} )}$
     1190for ( i; 1 ~ ®@® ~ 2 )                                  §\C{// for ( typeof(1) i = 1; \R{/* empty */}; i += 2 )}§
     1191for ( i; 1 ~ 10 ~ ®@® )                                 §\C{// for ( typeof(1) i = 1; i < 10; \R{/* empty */} )}§
     1192for ( i; 1 ~ ®@® ~ ®@® )                                §\C{// for ( typeof(1) i = 1; /*empty*/; \R{/* empty */} )}§
    11941193\end{cfa}
    11951194L cannot be elided for the up-to range, \lstinline{@ ~ 5}, and H for the down-to range, \lstinline{1 -~ @}, because then the loop index is uninitialized.
     
    11981197©:© means low another index.
    11991198\begin{cfa}
    1200 for ( i; 5 ®:® j; 2 ~ 12 ~ 3 )                  $\C{// for ( typeof(i) i = 1, j = 2; i < 5 \&\& j < 12; i += 1, j += 3 )}$
     1199for ( i; 5 ®:® j; 2 ~ 12 ~ 3 )                  §\C{// for ( typeof(i) i = 1, j = 2; i < 5 \&\& j < 12; i += 1, j += 3 )}§
    12011200\end{cfa}
    12021201\end{itemize}
    12031202\R{Warning}: specifying the down-to range maybe unexpected because the loop control \emph{implicitly} switches the L and H values (and toggles the increment/decrement for I):
    12041203\begin{cfa}
    1205 for ( i; 1 ~ 10 )                                               ${\C{// up range}$
    1206 for ( i; 1 -~ 10 )                                              ${\C{// down range}$
    1207 for ( i; ®10 -~ 1® )                                    ${\C{// \R{WRONG down range!}}}$
     1204for ( i; 1 ~ 10 )                                               §{\C{// up range}§
     1205for ( i; 1 -~ 10 )                                              §{\C{// down range}§
     1206for ( i; ®10 -~ 1® )                                    §{\C{// \R{WRONG down range!}}}§
    12081207\end{cfa}
    12091208The reason for this semantics is that the range direction can be toggled by adding/removing the minus, ©'-'©, versus interchanging the L and H expressions, which has a greater chance of introducing errors.
     
    13611360Grouping heterogeneous data into an \newterm{aggregate} (structure/union) is a common programming practice, and aggregates may be nested:
    13621361\begin{cfa}
    1363 struct Person {                                                 $\C{// aggregate}$
    1364         struct Name {                                           $\C{// nesting}$
     1362struct Person {                                                 §\C{// aggregate}§
     1363        struct Name {                                           §\C{// nesting}§
    13651364                char first[20], last[20];
    13661365        } name;
    1367         struct Address {                                        $\C{// nesting}$
     1366        struct Address {                                        §\C{// nesting}§
    13681367                ...
    13691368        } address;
     
    13741373\begin{cfa}
    13751374Person p
    1376 ®p.®name; ®p.®address; ®p.®sex;                 $\C{// access containing fields}$
     1375®p.®name; ®p.®address; ®p.®sex;                 §\C{// access containing fields}§
    13771376\end{cfa}
    13781377which extends to multiple levels of qualification for nested aggregates and multiple aggregates.
    13791378\begin{cfa}
    13801379struct Ticket { ... } t;
    1381 ®p.name®.first; ®p.address®.street;             $\C{// access nested fields}$
    1382 ®t.®departure; ®t.®cost;                                $\C{// access multiple aggregate}$
     1380®p.name®.first; ®p.address®.street;             §\C{// access nested fields}§
     1381®t.®departure; ®t.®cost;                                §\C{// access multiple aggregate}§
    13831382\end{cfa}
    13841383Repeated aggregate qualification is tedious and makes code difficult to read.
     
    13891388\begin{cfa}
    13901389struct S {
    1391         struct $\R{\LstCommentStyle{/* unnamed */}}$  { int g,  h; } __attribute__(( aligned(64) ));
     1390        struct §\R{\LstCommentStyle{/* unnamed */}}§  { int g,  h; } __attribute__(( aligned(64) ));
    13921391        int tag;
    1393         union $\R{\LstCommentStyle{/* unnamed */}}$  {
     1392        union §\R{\LstCommentStyle{/* unnamed */}}§  {
    13941393                struct { char c1,  c2; } __attribute__(( aligned(128) ));
    13951394                struct { int i1,  i2; };
     
    14051404struct S {
    14061405        char ®c®;   int ®i®;   double ®d®;
    1407         void f( /* S * this */ ) {                      $\C{// implicit ``this'' parameter}$
    1408                 ®c®;   ®i®;   ®d®;                              $\C{// this->c; this->i; this->d;}$
     1406        void f( /* S * this */ ) {                      §\C{// implicit ``this'' parameter}§
     1407                ®c®;   ®i®;   ®d®;                              §\C{// this->c; this->i; this->d;}§
    14091408        }
    14101409}
     
    14141413\begin{cfa}
    14151414struct T {
    1416         char ®m®;   int ®i®;   double ®n®;      $\C{// derived class variables}$
     1415        char ®m®;   int ®i®;   double ®n®;      §\C{// derived class variables}§
    14171416};
    14181417struct S : public T {
    1419         char ®c®;   int ®i®;   double ®d®;      $\C{// class variables}$
     1418        char ®c®;   int ®i®;   double ®d®;      §\C{// class variables}§
    14201419        void g( double ®d®, T & t ) {
    1421                 d;   ®t®.m;   ®t®.i;   ®t®.n;   $\C{// function parameter}$
    1422                 c;   i;   ®this->®d;   ®S::®d;  $\C{// class S variables}$
    1423                 m;   ®T::®i;   n;                               $\C{// class T variables}$
     1420                d;   ®t®.m;   ®t®.i;   ®t®.n;   §\C{// function parameter}§
     1421                c;   i;   ®this->®d;   ®S::®d;  §\C{// class S variables}§
     1422                m;   ®T::®i;   n;                               §\C{// class T variables}§
    14241423        }
    14251424};
     
    14311430Hence, the qualified fields become variables with the side-effect that it is simpler to write, easier to read, and optimize field references in a block.
    14321431\begin{cfa}
    1433 void f( S & this ) ®with ( this )® {    $\C{// with statement}$
    1434         ®c®;   ®i®;   ®d®;                                      $\C{// this.c, this.i, this.d}$
     1432void f( S & this ) ®with ( this )® {    §\C{// with statement}§
     1433        ®c®;   ®i®;   ®d®;                                      §\C{// this.c, this.i, this.d}§
    14351434}
    14361435\end{cfa}
    14371436with the generality of opening multiple aggregate-parameters:
    14381437\begin{cfa}
    1439 void g( S & s, T & t ) ®with ( s, t )® {$\C{// multiple aggregate parameters}$
    1440         c;   ®s.®i;   d;                                        $\C{// s.c, s.i, s.d}$
    1441         m;   ®t.®i;   n;                                        $\C{// t.m, t.i, t.n}$
     1438void g( S & s, T & t ) ®with ( s, t )® {§\C{// multiple aggregate parameters}§
     1439        c;   ®s.®i;   d;                                        §\C{// s.c, s.i, s.d}§
     1440        m;   ®t.®i;   n;                                        §\C{// t.m, t.i, t.n}§
    14421441}
    14431442\end{cfa}
     
    14621461struct R { int ®i®; int j; double ®m®; } r, w;
    14631462with ( r, q ) {
    1464         j + k;                                                          $\C{// unambiguous, r.j + q.k}$
    1465         m = 5.0;                                                        $\C{// unambiguous, q.m = 5.0}$
    1466         m = 1;                                                          $\C{// unambiguous, r.m = 1}$
    1467         int a = m;                                                      $\C{// unambiguous, a = r.i }$
    1468         double b = m;                                           $\C{// unambiguous, b = q.m}$
    1469         int c = r.i + q.i;                                      $\C{// disambiguate with qualification}$
    1470         (double)m;                                                      $\C{// disambiguate with cast}$
     1463        j + k;                                                          §\C{// unambiguous, r.j + q.k}§
     1464        m = 5.0;                                                        §\C{// unambiguous, q.m = 5.0}§
     1465        m = 1;                                                          §\C{// unambiguous, r.m = 1}§
     1466        int a = m;                                                      §\C{// unambiguous, a = r.i }§
     1467        double b = m;                                           §\C{// unambiguous, b = q.m}§
     1468        int c = r.i + q.i;                                      §\C{// disambiguate with qualification}§
     1469        (double)m;                                                      §\C{// disambiguate with cast}§
    14711470}
    14721471\end{cfa}
     
    14761475\begin{cfa}
    14771476with ( r ) {
    1478         i;                                                                      $\C{// unambiguous, r.i}$
     1477        i;                                                                      §\C{// unambiguous, r.i}§
    14791478        with ( q ) {
    1480                 i;                                                              $\C{// unambiguous, q.i}$
     1479                i;                                                              §\C{// unambiguous, q.i}§
    14811480        }
    14821481}
     
    14851484A cast can also be used to disambiguate among overload variables in a ©with© \emph{expression}:
    14861485\begin{cfa}
    1487 with ( w ) { ... }                                              $\C{// ambiguous, same name and no context}$
    1488 with ( (Q)w ) { ... }                                   $\C{// unambiguous, cast}$
     1486with ( w ) { ... }                                              §\C{// ambiguous, same name and no context}§
     1487with ( (Q)w ) { ... }                                   §\C{// unambiguous, cast}§
    14891488\end{cfa}
    14901489Because there is no left-side in the ©with© expression to implicitly disambiguate between the ©w© variables, it is necessary to explicitly disambiguate by casting ©w© to type ©Q© or ©R©.
     
    14931492\begin{cfa}
    14941493void f( S & s, char c ) with ( s ) {
    1495         ®s.c = c;®  i = 3;  d = 5.5;            $\C{// initialize fields}$
     1494        ®s.c = c;®  i = 3;  d = 5.5;            §\C{// initialize fields}§
    14961495}
    14971496\end{cfa}
     
    14991498To solve this problem, parameters \emph{not} explicitly opened are treated like an initialized aggregate:
    15001499\begin{cfa}
    1501 struct Params {                                                 $\C{// s explicitly opened so S \& s elided}$
     1500struct Params {                                                 §\C{// s explicitly opened so S \& s elided}§
    15021501        char c;
    15031502} params;
     
    15051504and implicitly opened \emph{after} a function-body open, to give them higher priority:
    15061505\begin{cfa}
    1507 void f( S & s, char ®c® ) with ( s ) ®with( $\emph{\R{params}}$ )® { // syntax not allowed, illustration only
     1506void f( S & s, char ®c® ) with ( s ) ®with( §\emph{\R{params}}§ )® { // syntax not allowed, illustration only
    15081507        s.c = ®c;®  i = 3;  d = 5.5;
    15091508}
     
    15381537
    15391538\begin{cfa}
    1540 exception_t E {}; $\C{// exception type}$
     1539exception_t E {}; §\C{// exception type}§
    15411540void f(...) {
    1542         ... throw E{}; ... $\C{// termination}$
    1543         ... throwResume E{}; ... $\C{// resumption}$
     1541        ... throw E{}; ... §\C{// termination}§
     1542        ... throwResume E{}; ... §\C{// resumption}§
    15441543}
    15451544try {
    15461545        f(...);
    1547 } catch( E e ; $boolean-predicate$ ) {  $\C{// termination handler}$
     1546} catch( E e ; §boolean-predicate§ ) {  §\C{// termination handler}§
    15481547        // recover and continue
    1549 } catchResume( E e ; $boolean-predicate$ ) { $\C{// resumption handler}$
     1548} catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}§
    15501549        // repair and return
    15511550} finally {
     
    16241623For example, a routine returning a \Index{pointer} to an array of integers is defined and used in the following way:
    16251624\begin{cfa}
    1626 int ®(*®f®())[®5®]® {...}; $\C{// definition}$
    1627  ... ®(*®f®())[®3®]® += 1; $\C{// usage}$
     1625int ®(*®f®())[®5®]® {...}; §\C{// definition}§
     1626 ... ®(*®f®())[®3®]® += 1; §\C{// usage}§
    16281627\end{cfa}
    16291628Essentially, the return type is wrapped around the routine name in successive layers (like an \Index{onion}).
     
    18701869For example, \Index*{Algol68}~\cite{Algol68} infers pointer dereferencing to select the best meaning for each pointer usage
    18711870\begin{cfa}
    1872 p2 = p1 + x; $\C{// compiler infers *p2 = *p1 + x;}$
     1871p2 = p1 + x; §\C{// compiler infers *p2 = *p1 + x;}§
    18731872\end{cfa}
    18741873Algol68 infers the following dereferencing ©*p2 = *p1 + x©, because adding the arbitrary integer value in ©x© to the address of ©p1© and storing the resulting address into ©p2© is an unlikely operation.
     
    18781877In C, objects of pointer type always manipulate the pointer object's address:
    18791878\begin{cfa}
    1880 p1 = p2; $\C{// p1 = p2\ \ rather than\ \ *p1 = *p2}$
    1881 p2 = p1 + x; $\C{// p2 = p1 + x\ \ rather than\ \ *p2 = *p1 + x}$
     1879p1 = p2; §\C{// p1 = p2\ \ rather than\ \ *p1 = *p2}§
     1880p2 = p1 + x; §\C{// p2 = p1 + x\ \ rather than\ \ *p2 = *p1 + x}§
    18821881\end{cfa}
    18831882even though the assignment to ©p2© is likely incorrect, and the programmer probably meant:
    18841883\begin{cfa}
    1885 p1 = p2; $\C{// pointer address assignment}$
    1886 ®*®p2 = ®*®p1 + x; $\C{// pointed-to value assignment / operation}$
     1884p1 = p2; §\C{// pointer address assignment}§
     1885®*®p2 = ®*®p1 + x; §\C{// pointed-to value assignment / operation}§
    18871886\end{cfa}
    18881887The C semantics work well for situations where manipulation of addresses is the primary meaning and data is rarely accessed, such as storage management (©malloc©/©free©).
     
    19011900\begin{cfa}
    19021901int x, y, ®&® r1, ®&® r2, ®&&® r3;
    1903 ®&®r1 = &x; $\C{// r1 points to x}$
    1904 ®&®r2 = &r1; $\C{// r2 points to x}$
    1905 ®&®r1 = &y; $\C{// r1 points to y}$
    1906 ®&&®r3 = ®&®&r2; $\C{// r3 points to r2}$
    1907 r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15); $\C{// implicit dereferencing}$
     1902®&®r1 = &x; §\C{// r1 points to x}§
     1903®&®r2 = &r1; §\C{// r2 points to x}§
     1904®&®r1 = &y; §\C{// r1 points to y}§
     1905®&&®r3 = ®&®&r2; §\C{// r3 points to r2}§
     1906r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15); §\C{// implicit dereferencing}§
    19081907\end{cfa}
    19091908Except for auto-dereferencing by the compiler, this reference example is the same as the previous pointer example.
     
    19201919For a \CFA reference type, the cancellation on the left-hand side of assignment leaves the reference as an address (\Index{lvalue}):
    19211920\begin{cfa}
    1922 (&®*®)r1 = &x; $\C{// (\&*) cancel giving address in r1 not variable pointed-to by r1}$
     1921(&®*®)r1 = &x; §\C{// (\&*) cancel giving address in r1 not variable pointed-to by r1}§
    19231922\end{cfa}
    19241923Similarly, the address of a reference can be obtained for assignment or computation (\Index{rvalue}):
    19251924\begin{cfa}
    1926 (&(&®*®)®*®)r3 = &(&®*®)r2; $\C{// (\&*) cancel giving address in r2, (\&(\&*)*) cancel giving address in r3}$
     1925(&(&®*®)®*®)r3 = &(&®*®)r2; §\C{// (\&*) cancel giving address in r2, (\&(\&*)*) cancel giving address in r3}§
    19271926\end{cfa}
    19281927Cancellation\index{cancellation!pointer/reference}\index{pointer!cancellation} works to arbitrary depth.
     
    19321931int x, *p1 = &x, **p2 = &p1, ***p3 = &p2,
    19331932                 &r1 = x,    &&r2 = r1,   &&&r3 = r2;
    1934 ***p3 = 3; $\C{// change x}$
    1935 r3 = 3; $\C{// change x, ***r3}$
    1936 **p3 = ...; $\C{// change p1}$
    1937 &r3 = ...; $\C{// change r1, (\&*)**r3, 1 cancellation}$
    1938 *p3 = ...; $\C{// change p2}$
    1939 &&r3 = ...; $\C{// change r2, (\&(\&*)*)*r3, 2 cancellations}$
    1940 &&&r3 = p3; $\C{// change r3 to p3, (\&(\&(\&*)*)*)r3, 3 cancellations}$
     1933***p3 = 3; §\C{// change x}§
     1934r3 = 3; §\C{// change x, ***r3}§
     1935**p3 = ...; §\C{// change p1}§
     1936&r3 = ...; §\C{// change r1, (\&*)**r3, 1 cancellation}§
     1937*p3 = ...; §\C{// change p2}§
     1938&&r3 = ...; §\C{// change r2, (\&(\&*)*)*r3, 2 cancellations}§
     1939&&&r3 = p3; §\C{// change r3 to p3, (\&(\&(\&*)*)*)r3, 3 cancellations}§
    19411940\end{cfa}
    19421941Furthermore, both types are equally performant, as the same amount of dereferencing occurs for both types.
     
    19451944As for a pointer type, a reference type may have qualifiers:
    19461945\begin{cfa}
    1947 const int cx = 5; $\C{// cannot change cx;}$
    1948 const int & cr = cx; $\C{// cannot change what cr points to}$
    1949 ®&®cr = &cx; $\C{// can change cr}$
    1950 cr = 7; $\C{// error, cannot change cx}$
    1951 int & const rc = x; $\C{// must be initialized}$
    1952 ®&®rc = &x; $\C{// error, cannot change rc}$
    1953 const int & const crc = cx; $\C{// must be initialized}$
    1954 crc = 7; $\C{// error, cannot change cx}$
    1955 ®&®crc = &cx; $\C{// error, cannot change crc}$
     1946const int cx = 5; §\C{// cannot change cx;}§
     1947const int & cr = cx; §\C{// cannot change what cr points to}§
     1948®&®cr = &cx; §\C{// can change cr}§
     1949cr = 7; §\C{// error, cannot change cx}§
     1950int & const rc = x; §\C{// must be initialized}§
     1951®&®rc = &x; §\C{// error, cannot change rc}§
     1952const int & const crc = cx; §\C{// must be initialized}§
     1953crc = 7; §\C{// error, cannot change cx}§
     1954®&®crc = &cx; §\C{// error, cannot change crc}§
    19561955\end{cfa}
    19571956Hence, for type ©& const©, there is no pointer assignment, so ©&rc = &x© is disallowed, and \emph{the address value cannot be the null pointer unless an arbitrary pointer is coerced\index{coercion} into the reference}:
    19581957\begin{cfa}
    1959 int & const cr = *0; $\C{// where 0 is the int * zero}$
     1958int & const cr = *0; §\C{// where 0 is the int * zero}§
    19601959\end{cfa}
    19611960Note, constant reference-types do not prevent \Index{addressing errors} because of explicit storage-management:
     
    19641963cr = 5;
    19651964free( &cr );
    1966 cr = 7; $\C{// unsound pointer dereference}$
     1965cr = 7; §\C{// unsound pointer dereference}§
    19671966\end{cfa}
    19681967
     
    19721971\begin{cquote}
    19731972\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1974 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{Cy}}  & \multicolumn{1}{c}{\textbf{\CFA}}     \\
     1973\multicolumn{1}{c@{\hspace{3em}}}{\textbf{C}}   & \multicolumn{1}{c}{\textbf{\CFA}}     \\
    19751974\begin{cfa}
    19761975const int * ®const® * ®const® ccp;
     
    19881987Finally, like pointers, references are usable and composable with other type operators and generators.
    19891988\begin{cfa}
    1990 int w, x, y, z, & ar[3] = { x, y, z }; $\C{// initialize array of references}$
    1991 &ar[1] = &w; $\C{// change reference array element}$
    1992 typeof( ar[1] ) p; $\C{// (gcc) is int, \ie the type of referenced object}$
    1993 typeof( &ar[1] ) q; $\C{// (gcc) is int \&, \ie the type of reference}$
    1994 sizeof( ar[1] ) == sizeof( int ); $\C{// is true, \ie the size of referenced object}$
    1995 sizeof( &ar[1] ) == sizeof( int *) $\C{// is true, \ie the size of a reference}$
     1989int w, x, y, z, & ar[3] = { x, y, z }; §\C{// initialize array of references}§
     1990&ar[1] = &w; §\C{// change reference array element}§
     1991typeof( ar[1] ) p; §\C{// (gcc) is int, \ie the type of referenced object}§
     1992typeof( &ar[1] ) q; §\C{// (gcc) is int \&, \ie the type of reference}§
     1993sizeof( ar[1] ) == sizeof( int ); §\C{// is true, \ie the size of referenced object}§
     1994sizeof( &ar[1] ) == sizeof( int *) §\C{// is true, \ie the size of a reference}§
    19961995\end{cfa}
    19971996
     
    20102009Therefore, for pointer/reference initialization, the initializing value must be an address not a value.
    20112010\begin{cfa}
    2012 int * p = &x; $\C{// assign address of x}$
    2013 ®int * p = x;® $\C{// assign value of x}$
    2014 int & r = x; $\C{// must have address of x}$
     2011int * p = &x;                           §\C{// assign address of x}§
     2012®int * p = x;®                          §\C{// assign value of x}§
     2013int & r = x;                            §\C{// must have address of x}§
    20152014\end{cfa}
    20162015Like the previous example with C pointer-arithmetic, it is unlikely assigning the value of ©x© into a pointer is meaningful (again, a warning is usually given).
     
    20212020Similarly, when a reference type is used for a parameter/return type, the call-site argument does not require a reference operator for the same reason.
    20222021\begin{cfa}
    2023 int & f( int & r ); $\C{// reference parameter and return}$
    2024 z = f( x ) + f( y ); $\C{// reference operator added, temporaries needed for call results}$
     2022int & f( int & r );                     §\C{// reference parameter and return}§
     2023z = f( x ) + f( y );            §\C{// reference operator added, temporaries needed for call results}§
    20252024\end{cfa}
    20262025Within routine ©f©, it is possible to change the argument by changing the corresponding parameter, and parameter ©r© can be locally reassigned within ©f©.
     
    20492048void f( int & r );
    20502049void g( int * p );
    2051 f( 3 );                   g( ®&®3 ); $\C{// compiler implicit generates temporaries}$
    2052 f( x + y );             g( ®&®(x + y) ); $\C{// compiler implicit generates temporaries}$
     2050f( 3 );                   g( ®&®3 ); §\C{// compiler implicit generates temporaries}§
     2051f( x + y );             g( ®&®(x + y) ); §\C{// compiler implicit generates temporaries}§
    20532052\end{cfa}
    20542053Essentially, there is an implicit \Index{rvalue} to \Index{lvalue} conversion in this case.\footnote{
     
    20612060\begin{cfa}
    20622061void f( int i );
    2063 void (* fp)( int ); $\C{// routine pointer}$
    2064 fp = f; $\C{// reference initialization}$
    2065 fp = &f; $\C{// pointer initialization}$
    2066 fp = *f; $\C{// reference initialization}$
    2067 fp(3); $\C{// reference invocation}$
    2068 (*fp)(3); $\C{// pointer invocation}$
     2062void (* fp)( int );                     §\C{// routine pointer}§
     2063fp = f;                                         §\C{// reference initialization}§
     2064fp = &f;                                        §\C{// pointer initialization}§
     2065fp = *f;                                        §\C{// reference initialization}§
     2066fp(3);                                          §\C{// reference invocation}§
     2067(*fp)(3);                                       §\C{// pointer invocation}§
    20692068\end{cfa}
    20702069While C's treatment of routine objects has similarity to inferring a reference type in initialization contexts, the examples are assignment not initialization, and all possible forms of assignment are possible (©f©, ©&f©, ©*f©) without regard for type.
    20712070Instead, a routine object should be referenced by a ©const© reference:
    20722071\begin{cfa}
    2073 ®const® void (®&® fr)( int ) = f; $\C{// routine reference}$
    2074 fr = ... $\C{// error, cannot change code}$
    2075 &fr = ...; $\C{// changing routine reference}$
    2076 fr( 3 ); $\C{// reference call to f}$
    2077 (*fr)(3); $\C{// error, incorrect type}$
     2072®const® void (®&® fr)( int ) = f; §\C{// routine reference}§
     2073fr = ...;                                       §\C{// error, cannot change code}§
     2074&fr = ...;                                      §\C{// changing routine reference}§
     2075fr( 3 );                                        §\C{// reference call to f}§
     2076(*fr)(3);                                       §\C{// error, incorrect type}§
    20782077\end{cfa}
    20792078because the value of the routine object is a routine literal, \ie the routine code is normally immutable during execution.\footnote{
     
    20972096int x, * px, ** ppx, *** pppx, **** ppppx;
    20982097int & rx = x, && rrx = rx, &&& rrrx = rrx ;
    2099 x = rrrx; $\C[2.0in]{// rrrx is an lvalue with type int \&\&\& (equivalent to x)}$
    2100 px = &rrrx; $\C{// starting from rrrx, \&rrrx is an rvalue with type int *\&\&\& (\&x)}$
    2101 ppx = &&rrrx; $\C{// starting from \&rrrx, \&\&rrrx is an rvalue with type int **\&\& (\&rx)}$
    2102 pppx = &&&rrrx; $\C{// starting from \&\&rrrx, \&\&\&rrrx is an rvalue with type int ***\& (\&rrx)}$
    2103 ppppx = &&&&rrrx; $\C{// starting from \&\&\&rrrx, \&\&\&\&rrrx is an rvalue with type int **** (\&rrrx)}$
     2098x = rrrx;                                       §\C{// rrrx is an lvalue with type int \&\&\& (equivalent to x)}§
     2099px = &rrrx;                                     §\C{// starting from rrrx, \&rrrx is an rvalue with type int *\&\&\& (\&x)}§
     2100ppx = &&rrrx;                           §\C{// starting from \&rrrx, \&\&rrrx is an rvalue with type int **\&\& (\&rx)}§
     2101pppx = &&&rrrx;                         §\C{// starting from \&\&rrrx, \&\&\&rrrx is an rvalue with type int ***\& (\&rrx)}§
     2102ppppx = &&&&rrrx;                       §\C{// starting from \&\&\&rrrx, \&\&\&\&rrrx is an rvalue with type int **** (\&rrrx)}§
    21042103\end{cfa}
    21052104The following example shows the second rule applied to different \Index{lvalue} contexts:
     
    21072106int x, * px, ** ppx, *** pppx;
    21082107int & rx = x, && rrx = rx, &&& rrrx = rrx ;
    2109 rrrx = 2; $\C{// rrrx is an lvalue with type int \&\&\& (equivalent to x)}$
    2110 &rrrx = px; $\C{// starting from rrrx, \&rrrx is an rvalue with type int *\&\&\& (rx)}$
    2111 &&rrrx = ppx; $\C{// starting from \&rrrx, \&\&rrrx is an rvalue with type int **\&\& (rrx)}$
    2112 &&&rrrx = pppx; $\C{// starting from \&\&rrrx, \&\&\&rrrx is an rvalue with type int ***\& (rrrx)}\CRT$
     2108rrrx = 2;                                       §\C{// rrrx is an lvalue with type int \&\&\& (equivalent to x)}§
     2109&rrrx = px;                                     §\C{// starting from rrrx, \&rrrx is an rvalue with type int *\&\&\& (rx)}§
     2110&&rrrx = ppx;                           §\C{// starting from \&rrrx, \&\&rrrx is an rvalue with type int **\&\& (rrx)}§
     2111&&&rrrx = pppx;                         §\C{// starting from \&\&rrrx, \&\&\&rrrx is an rvalue with type int ***\& (rrrx)}§
    21132112\end{cfa}
    21142113
     
    21232122\begin{cfa}
    21242123int x;
    2125 x + 1; $\C[2.0in]{// lvalue variable (int) converts to rvalue for expression}$
     2124x + 1;                                          §\C{// lvalue variable (int) converts to rvalue for expression}§
    21262125\end{cfa}
    21272126An rvalue has no type qualifiers (©cv©), so the lvalue qualifiers are dropped.
     
    21332132\begin{cfa}
    21342133int x, &r = x, f( int p );
    2135 x = ®r® + f( ®r® ); $\C{// lvalue reference converts to rvalue}$
     2134x = ®r® + f( ®r® );                     §\C{// lvalue reference converts to rvalue}§
    21362135\end{cfa}
    21372136An rvalue has no type qualifiers (©cv©), so the reference qualifiers are dropped.
     
    21402139lvalue to reference conversion: \lstinline[deletekeywords=lvalue]{lvalue-type cv1 T} converts to ©cv2 T &©, which allows implicitly converting variables to references.
    21412140\begin{cfa}
    2142 int x, &r = ®x®, f( int & p ); $\C{// lvalue variable (int) convert to reference (int \&)}$
    2143 f( ®x® ); $\C{// lvalue variable (int) convert to reference (int \&)}\CRT$
     2141int x, &r = ®x®, f( int & p ); §\C{// lvalue variable (int) convert to reference (int \&)}§
     2142f( ®x® );                                       §\C{// lvalue variable (int) convert to reference (int \&)}§
    21442143\end{cfa}
    21452144Conversion can restrict a type, where ©cv1© $\le$ ©cv2©, \eg passing an ©int© to a ©const volatile int &©, which has low cost.
     
    21512150\begin{cfa}
    21522151int x, & f( int & p );
    2153 f( ®x + 3® );   $\C[1.5in]{// rvalue parameter (int) implicitly converts to lvalue temporary reference (int \&)}$
    2154 ®&f®(...) = &x; $\C{// rvalue result (int \&) implicitly converts to lvalue temporary reference (int \&)}\CRT$
     2152f( ®x + 3® );                           §\C{// rvalue parameter (int) implicitly converts to lvalue temporary reference (int \&)}§
     2153®&f®(...) = &x;                         §\C{// rvalue result (int \&) implicitly converts to lvalue temporary reference (int \&)}§
    21552154\end{cfa}
    21562155In both case, modifications to the temporary are inaccessible (\Index{warning}).
     
    23192318
    23202319
     2320\section{\lstinline{string} Type}
     2321\label{s:stringType}
     2322
     2323The \CFA \Indexc{string} type is for manipulation of dynamically-size character-strings versus C \Indexc{char *} type for manipulation of statically-size null-terminated character-strings.
     2324That is, the amount of storage for a \CFA string changes dynamically at runtime to fit the string size, whereas the amount of storage for a C string is fixed at compile time.
     2325Hence, a ©string© declaration does not specify a maximum length;
     2326as a string dynamically grows and shrinks in size, so does its underlying storage.
     2327In contrast, a C string also dynamically grows and shrinks is size, but its underlying storage is fixed.
     2328The maximum storage for a \CFA ©string© value is ©size_t© characters, which is $2^{32}$ or $2^{64}$ respectively.
     2329A \CFA string manages its length separately from the string, so there is no null (©'\0'©) terminating value at the end of a string value.
     2330Hence, a \CFA string cannot be passed to a C string manipulation routine, such as ©strcat©.
     2331Like C strings, the characters in a ©string© are numbered starting from 0.
     2332
     2333The following operations have been defined to manipulate an instance of type ©string©.
     2334The discussion assumes the following declarations and assignment statements are executed.
     2335\begin{cfa}
     2336#include ®<string.hfa>®
     2337®string® s, peter, digit, alpha, punctuation, ifstmt;
     2338int i;
     2339peter  = "PETER";
     2340digit  = "0123456789";
     2341punctuation = "().,";
     2342ifstmt = "IF (A > B) {";
     2343\end{cfa}
     2344Note, the include file \Indexc{string.hfa} to access type ©string©.
     2345
     2346
     2347\subsection{Implicit String Conversions}
     2348
     2349The types ©char©, ©char *©, ©int©, ©double©, ©_Complex©, including signness and different sizes, implicitly convert to type ©string©.
     2350\VRef[Figure]{f:ImplicitStringConversions} shows examples of implicit conversion between C strings, integral, floating-point and complex types to ©string©
     2351The implicit conversions can be specified explicitly, as in:
     2352\begin{cfa}
     2353s = string( "abc" );            // converts char * to string
     2354s = string( 5 );                        // converts int to string
     2355s = string( 5.5 );                      // converts double to string
     2356\end{cfa}
     2357Conversions from ©string© to ©char *© are supported but with restrictions.
     2358Explicit As well, when a string is converted to a ©char *©, the storage for the ©char *© is created by the conversion operation, which must be subsequently deleted:
     2359\begin{cfa}
     2360string x = "abc";
     2361char *p = x;                            // convert from string to char *
     2362...
     2363delete p;                                       // free storage created for p
     2364\end{cfa}
     2365
     2366\begin{figure}
     2367\begin{tabular}{@{}l@{\hspace{15pt}}|@{\hspace{15pt}}l@{}}
     2368\begin{cfa}
     2369//      string s = 5;                                   sout | s;
     2370        string s;
     2371        // conversion of char and char * to string
     2372        s = 'x';                                                §\CD{sout | s;}§
     2373        s = "abc";                                              §\CD{sout | s;}§
     2374        char cs[5] = "abc";
     2375        s = cs;                                                 §\CD{sout | s;}§
     2376        // conversion of integral, floating-point, and complex to string
     2377        s = 45hh;                                               §\CD{sout | s;}§
     2378        s = 45h;                                                §\CD{sout | s;}§
     2379        s = -(ssize_t)MAX - 1;                  §\CD{sout | s;}§
     2380        s = (size_t)MAX;                                §\CD{sout | s;}§
     2381        s = 5.5;                                                §\CD{sout | s;}§
     2382        s = 5.5L;                                               §\CD{sout | s;}§
     2383        s = 5.5+3.4i;                                   §\CD{sout | s;}§
     2384        s = 5.5L+3.4Li;                                 §\CD{sout | s;}§
     2385        // safe conversion from string to char *
     2386        strncpy( cs, s, sizeof(cs) );   §\CD{sout | cs;}§
     2387        char * cp = s;                                  §\CD{sout | cp; // ownership}§
     2388        delete( cp );
     2389        cp = s + ' ' + s;                               §\CD{sout | cp; // ownership}§
     2390        delete( cp );
     2391\end{cfa}
     2392&
     2393\begin{cfa}
     2394
     2395
     2396
     2397x
     2398abc
     2399
     2400abc
     2401
     240245
     240345
     2404-9223372036854775808
     240518446744073709551615
     24065.5
     24075.5
     24085.5+3.4i
     24095.5+3.4i
     2410
     24115.5+
     24125.5+3.4i
     2413
     24145.5+3.4i 5.5+3.4i
     2415
     2416\end{cfa}
     2417\end{tabular}
     2418\caption{Implicit String Conversions}
     2419\label{f:ImplicitStringConversions}
     2420\end{figure}
     2421
     2422
     2423\subsection{Comparison Operators}
     2424
     2425The binary relational and equality operators ©<©, ©<=©, ©>©, ©>=©, ©==©, ©!=© compare ©string© using lexicographical ordering, where longer strings are greater than shorter strings.
     2426
     2427
     2428\subsection{Concatenation}
     2429
     2430The binary operator ©+© concatenates two strings.
     2431\begin{cfa}
     2432s = peter + digit;                                      §\C{// s is assigned "PETER0123456789"}§
     2433s += peter;                                                     §\C{// s is assigned "PETER0123456789PETER"}§
     2434\end{cfa}
     2435There is also an assignment form ©+=©.
     2436
     2437
     2438\subsection{Repetition}
     2439
     2440The binary operator \Indexc{*} returns a string that is the string repeated ©n© times.
     2441If ©n = 0©, a zero length string, ©""© is returned.
     2442\begin{cfa}
     2443s = (peter + ' ') * 3;                          §\C{// s is assigned "PETER PETER PETER"}§
     2444\end{cfa}
     2445There is also an assignment form ©*=©.
     2446
     2447
     2448\subsection{Length}
     2449
     2450The ©length© operation
     2451\begin{cfa}
     2452int length()
     2453\end{cfa}
     2454returns the length of a string variable.
     2455\begin{cfa}
     2456i = peter.length();                     §\C{// i is assigned the value 5}§
     2457\end{cfa}
     2458
     2459
     2460\subsection{Substring}
     2461The substring operation:
     2462\begin{cfa}
     2463string operator () (int start, int lnth);
     2464\end{cfa}
     2465performs a substring operation that returns the string starting at a specified position (©start©) in the current string, and having the specified length (©lnth©).
     2466A negative starting position is a specification from the right end of the string.
     2467A negative length means that characters are selected in the opposite (right to left) direction from the starting position.
     2468If the substring request extends beyond the beginning or end of the string, it is clipped (shortened) to the bounds of the string.
     2469If the substring request is completely outside of the original string, a null string located at the end of the original string is returned.
     2470\begin{cfa}
     2471s = peter( 2, 3 );                      §\C{// s is assigned "ETE"}§
     2472s = peter( 4, -3 );                     §\C{// s is assigned "ETE", length is opposite direction}§
     2473s = peter( 2, 8 );                      §\C{// s is assigned "ETER", length is clipped to 4}§
     2474s = peter( 0, -1 );                     §\C{// s is assigned "", beyond string so clipped to null}§
     2475s = peter(-1, -1 );                     §\C{// s is assigned "R", start and length are negative}§
     2476\end{cfa}
     2477The substring operation can also appear on the left hand side of the assignment operator.
     2478The substring is replaced by the value on the right hand side of the assignment.
     2479The length of the right-hand-side value may be shorter, the same length, or longer than the length of the substring that is selected on the left hand side of the assignment.
     2480\begin{cfa}[mathescape=false]
     2481digit( 3, 3 ) = "";             §\C{// digit is assigned "0156789"}§
     2482digit( 4, 3 ) = "xyz";          §\C{// digit is assigned "015xyz9"}§
     2483digit( 7, 0 ) = "***";          §\C{// digit is assigned "015xyz***9"}§
     2484digit(-4, 3 ) = "$$$";          §\C{// digit is assigned "015xyz\$\$\$9"}§
     2485\end{cfa}
     2486A substring is treated as a pointer into the base (substringed) string rather than creating a copy of the subtext.
     2487As with all pointers, if the item they are pointing at is changed, then the pointer is referring to the changed item.
     2488Pointers to the result value of a substring operation are defined to always start at the same location in their base string as long as that starting location exists, independent of changes to themselves or the base string.
     2489However, if the base string value changes, this may affect the values of one or more of the substrings to that base string.
     2490If the base string value shortens so that its end is before the starting location of a substring, resulting in the substring starting location disappearing, the substring becomes a null string located at the end of the base string.
     2491
     2492The following example illustrates passing the results of substring operations by reference and by value to a subprogram.
     2493Notice the side-effects to other reference parameters as one is modified.
     2494\begin{cfa}
     2495main() {
     2496        string x = "xxxxxxxxxxxxx";
     2497        test( x, x(1,3), x(3,3), x(5,5), x(9,5), x(9,5) );
     2498}
     2499
     2500// x, a, b, c, & d are substring results passed by reference
     2501// e is a substring result passed by value
     2502void test(string &x, string &a, string &b, string &c, string &d, string e) {
     2503                                                        §\C{//   x                                a               b               c               d               e}§
     2504        a( 1, 2 ) = "aaa";              §\C{// aaaxxxxxxxxxxx   aaax    axx             xxxxx   xxxxx   xxxxx}§
     2505        b( 2, 12 ) = "bbb";             §\C{// aaabbbxxxxxxxxx  aaab    abbb    bbxxx   xxxxx   xxxxx}§
     2506        c( 4, 5 ) = "ccc";              §\C{// aaabbbxcccxxxxxx aaab    abbb    bbxccc  ccxxx   xxxxx}§
     2507        c = "yyy";                              §\C{// aaabyyyxxxxxx    aaab    abyy    yyy             xxxxx   xxxxx}§
     2508        d( 1, 3 ) = "ddd";              §\C{// aaabyyyxdddxx    aaab    abyy    yyy             dddxx   xxxxx}§
     2509        e( 1, 3 ) = "eee";              §\C{// aaabyyyxdddxx    aaab    abyy    yyy             dddxx   eeexx}§
     2510        x = e;                                  §\C{// eeexx                    eeex    exx             x                               eeexx}§
     2511}
     2512\end{cfa}
     2513
     2514There is an assignment form of substring in which only the starting position is specified and the length is assumed to be the remainder of the string.
     2515\begin{cfa}
     2516string operator () (int start);
     2517\end{cfa}
     2518For example:
     2519\begin{cfa}
     2520s = peter( 2 );                         §\C{// s is assigned "ETER"}§
     2521peter( 2 ) = "IPER";            §\C{// peter is assigned "PIPER"}§
     2522\end{cfa}
     2523It is also possible to substring using a string as the index for selecting the substring portion of the string.
     2524\begin{cfa}
     2525string operator () (const string &index);
     2526\end{cfa}
     2527For example:
     2528\begin{cfa}[mathescape=false]
     2529digit( "xyz$$$" ) = "678";      §\C{// digit is assigned "0156789"}§
     2530digit( "234") = "***";          §\C{// digit is assigned "0156789***"}§
     2531\end{cfa}
     2532%$
     2533
     2534
     2535\subsection{Searching}
     2536
     2537The ©index© operation
     2538\begin{cfa}
     2539int index( const string &key, int start = 1, occurrence occ = first );
     2540\end{cfa}
     2541returns the position of the first or last occurrence of the ©key© (depending on the occurrence indicator ©occ© that is either ©first© or ©last©) in the current string starting the search at position ©start©.
     2542If the ©key© does not appear in the current string, the length of the current string plus one is returned.
     2543%If the ©key© has zero length, the value 1 is returned regardless of what the current string contains.
     2544A negative starting position is a specification from the right end of the string.
     2545\begin{cfa}
     2546i = digit.index( "567" );                       §\C{// i is assigned 3}§
     2547i = digit.index( "567", 7 );            §\C{// i is assigned 11}§
     2548i = digit.index( "567", -1, last );     §\C{// i is assigned 3}§
     2549i = peter.index( "E", 5, last );        §\C{// i is assigned 4}§
     2550\end{cfa}
     2551
     2552The next two string operations test a string to see if it is or is not composed completely of a particular class of characters.
     2553For example, are the characters of a string all alphabetic or all numeric?
     2554Use of these operations involves a two step operation.
     2555First, it is necessary to create an instance of type ©strmask© and initialize it to a string containing the characters of the particular character class, as in:
     2556\begin{cfa}
     2557strmask digitmask = digit;
     2558strmask alphamask = string( "abcdefghijklmnopqrstuvwxyz" );
     2559\end{cfa}
     2560Second, the character mask is used in the functions ©include© and ©exclude© to check a string for compliance of its characters with the characters indicated by the mask.
     2561
     2562The ©include© operation
     2563\begin{cfa}
     2564int include( const strmask &, int = 1, occurrence occ = first );
     2565\end{cfa}
     2566returns the position of the first or last character (depending on the occurrence indicator, which is either ©first© or ©last©) in the current string that does not appear in the ©mask© starting the search at position ©start©;
     2567hence it skips over characters in the current string that are included (in) the ©mask©.
     2568The characters in the current string do not have to be in the same order as the ©mask©.
     2569If all the characters in the current string appear in the ©mask©, the length of the current string plus one is returned, regardless of which occurrence is being searched for.
     2570A negative starting position is a specification from the right end of the string.
     2571\begin{cfa}
     2572i = peter.include( digitmask ); §\C{// i is assigned 1}§
     2573i = peter.include( alphamask ); §\C{// i is assigned 6}§
     2574\end{cfa}
     2575
     2576The ©exclude© operation
     2577\begin{cfa}
     2578int exclude( string &mask, int start = 1, occurrence occ = first )
     2579\end{cfa}
     2580returns the position of the first or last character (depending on the occurrence indicator, which is either ©first© or ©last©) in the current string that does appear in the ©mask© string starting the search at position ©start©;
     2581hence it skips over characters in the current string that are excluded from (not in) in the ©mask© string.
     2582The characters in the current string do not have to be in the same order as the ©mask© string.
     2583If all the characters in the current string do NOT appear in the ©mask© string, the length of the current string plus one is returned, regardless of which occurrence is being searched for.
     2584A negative starting position is a specification from the right end of the string.
     2585\begin{cfa}
     2586i = peter.exclude( digitmask );         §\C{// i is assigned 6}§
     2587i = ifstmt.exclude( strmask( punctuation ) ); §\C{// i is assigned 4}§
     2588\end{cfa}
     2589
     2590The ©includeStr© operation:
     2591\begin{cfa}
     2592string includeStr( strmask &mask, int start = 1, occurrence occ = first )
     2593\end{cfa}
     2594returns the longest substring of leading or trailing characters (depending on the occurrence indicator, which is either ©first© or ©last©) of the current string that ARE included in the ©mask© string starting the search at position ©start©.
     2595A negative starting position is a specification from the right end of the string.
     2596\begin{cfa}
     2597s = peter.includeStr( alphamask );      §\C{// s is assigned "PETER"}§
     2598s = ifstmt.includeStr( alphamask );     §\C{// s is assigned "IF"}§
     2599s = peter.includeStr( digitmask );      §\C{// s is assigned ""}§
     2600\end{cfa}
     2601
     2602The ©excludeStr© operation:
     2603\begin{cfa}
     2604string excludeStr( strmask &mask, int start = 1, occurrence = first )
     2605\end{cfa}
     2606returns the longest substring of leading or trailing characters (depending on the occurrence indicator, which is either ©first© or ©last©) of the current string that are excluded (NOT) in the ©mask© string starting the search at position ©start©.
     2607A negative starting position is a specification from the right end of the string.
     2608\begin{cfa}
     2609s = peter.excludeStr( digitmask);       §\C{// s is assigned "PETER"}§
     2610s = ifstmt.excludeStr( strmask( punctuation ) ); §\C{// s is assigned "IF "}§
     2611s = peter.excludeStr( alphamask);       §\C{// s is assigned ""}§
     2612\end{cfa}
     2613
     2614
     2615\subsection{Miscellaneous}
     2616
     2617The ©trim© operation
     2618\begin{cfa}
     2619string trim( string &mask, occurrence occ = first )
     2620\end{cfa}
     2621returns a string in that is the longest substring of leading or trailing characters (depending on the occurrence indicator, which is either ©first© or ©last©) which ARE included in the ©mask© are removed.
     2622\begin{cfa}
     2623// remove leading blanks
     2624s = string( "   ABC" ).trim( " " );                     §\C{// s is assigned "ABC",}§
     2625// remove trailing blanks
     2626s = string( "ABC   " ).trim( " ", last );       §\C{// s is assigned "ABC",}§
     2627\end{cfa}
     2628
     2629The ©translate© operation
     2630\begin{cfa}
     2631string translate( string &from, string &to )
     2632\end{cfa}
     2633returns a string that is the same length as the original string in which all occurrences of the characters that appear in the ©from© string have been translated into their corresponding character in the ©to© string.
     2634Translation is done on a character by character basis between the ©from© and ©to© strings; hence these two strings must be the same length.
     2635If a character in the original string does not appear in the ©from© string, then it simply appears as is in the resulting string.
     2636\begin{cfa}
     2637// upper to lower case
     2638peter = peter.translate( "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz" );
     2639                        // peter is assigned "peter"
     2640s = ifstmt.translate( "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz" );
     2641                        // ifstmt is assigned "if (a > b) {"
     2642// lower to upper case
     2643peter = peter.translate( "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
     2644                        // peter is assigned "PETER"
     2645\end{cfa}
     2646
     2647The ©replace© operation
     2648\begin{cfa}
     2649string replace( string &from, string &to )
     2650\end{cfa}
     2651returns a string in which all occurrences of the ©from© string in the current string have been replaced by the ©to© string.
     2652\begin{cfa}
     2653s = peter.replace( "E", "XX" ); §\C{// s is assigned "PXXTXXR"}§
     2654\end{cfa}
     2655The replacement is done left-to-right.
     2656When an instance of the ©from© string is found and changed to the ©to© string, it is NOT examined again for further replacement.
     2657
     2658
     2659\section{Returning N+1 on Failure}
     2660
     2661Any of the string search routines can fail at some point during the search.
     2662When this happens it is necessary to return indicating the failure.
     2663Many string types in other languages use some special value to indicate the failure.
     2664This value is often 0 or -1 (PL/I returns 0).
     2665This section argues that a value of N+1, where N is the length of the base string in the search, is a more useful value to return.
     2666The index-of function in APL returns N+1.
     2667These are the boundary situations and are often overlooked when designing a string type.
     2668
     2669The situation that can be optimized by returning N+1 is when a search is performed to find the starting location for a substring operation.
     2670For example, in a program that is extracting words from a text file, it is necessary to scan from left to right over whitespace until the first alphabetic character is found.
     2671\begin{cfa}
     2672line = line( line.exclude( alpha ) );
     2673\end{cfa}
     2674If a text line contains all whitespaces, the exclude operation fails to find an alphabetic character.
     2675If ©exclude© returns 0 or -1, the result of the substring operation is unclear.
     2676Most string types generate an error, or clip the starting value to 1, resulting in the entire whitespace string being selected.
     2677If ©exclude© returns N+1, the starting position for the substring operation is beyond the end of the string leaving a null string.
     2678
     2679The same situation occurs when scanning off a word.
     2680\begin{cfa}
     2681start = line.include(alpha);
     2682word = line(1, start - 1);
     2683\end{cfa}
     2684If the entire line is composed of a word, the include operation will  fail to find a non-alphabetic character.
     2685In general, returning 0 or -1 is not an appropriate starting position for the substring, which must substring off the word leaving a null string.
     2686However, returning N+1 will substring off the word leaving a null string.
     2687
     2688
     2689\subsection{Input/Output Operators}
     2690
     2691Both the \CC operators ©<<© and ©>>© are defined on type ©string©.
     2692However, input of a string value is different from input of a ©char *© value.
     2693When a string value is read, \emph{all} input characters from the current point in the input stream to either the end of line (©'\n'©) or the end of file are read.
     2694
     2695
    23212696\section{Enumeration}
    23222697
     
    23322707Hence, enums may be overloaded with variable, enum, and function names.
    23332708\begin{cfa}
    2334 int Foo;                        $\C{// type/variable separate namespaces}$
     2709int Foo;                        §\C{// type/variable separate namespaces}§
    23352710enum Foo { Bar };
    2336 enum Goo { Bar };       $\C[1.75in]{// overload Foo.Bar}$
    2337 double Bar;                     $\C{// overload Foo.Bar, Goo.Bar}\CRT$
     2711enum Goo { Bar };       §\C[1.75in]{// overload Foo.Bar}§
     2712double Bar;                     §\C{// overload Foo.Bar, Goo.Bar}\CRT§
    23382713\end{cfa}
    23392714An anonymous enumeration injects enums with specific values into a scope.
     
    24082783The following examples illustrate the difference between the enumeration type and the type of its enums.
    24092784\begin{cfa}
    2410 Math m = PI;    $\C[1.5in]{// allowed}$
    2411 double d = PI;  $\C{// allowed, conversion to base type}$
    2412 m = E;                  $\C{// allowed}$
    2413 m = Alph;               $\C{// {\color{red}disallowed}}$
    2414 m = 3.141597;   $\C{// {\color{red}disallowed}}$
    2415 d = m;                  $\C{// allowed}$
    2416 d = Alph;               $\C{// {\color{red}disallowed}}$
    2417 Letter l = A;   $\C{// allowed}$
    2418 Greek g = Alph; $\C{// allowed}$
    2419 l = Alph;               $\C{// allowed, conversion to base type}$
    2420 g = A;                  $\C{// {\color{red}disallowed}}\CRT$
     2785Math m = PI;    §\C[1.5in]{// allowed}§
     2786double d = PI;  §\C{// allowed, conversion to base type}§
     2787m = E;                  §\C{// allowed}§
     2788m = Alph;               §\C{// {\color{red}disallowed}}§
     2789m = 3.141597;   §\C{// {\color{red}disallowed}}§
     2790d = m;                  §\C{// allowed}§
     2791d = Alph;               §\C{// {\color{red}disallowed}}§
     2792Letter l = A;   §\C{// allowed}§
     2793Greek g = Alph; §\C{// allowed}§
     2794l = Alph;               §\C{// allowed, conversion to base type}§
     2795g = A;                  §\C{// {\color{red}disallowed}}\CRT§
    24212796\end{cfa}
    24222797
     
    25082883\begin{cfa}
    25092884®[ int o1, int o2, char o3 ]® f( int i1, char i2, char i3 ) {
    2510         $\emph{routine body}$
     2885        §\emph{routine body}§
    25112886}
    25122887\end{cfa}
     
    25192894Declaration qualifiers can only appear at the start of a routine definition, \eg:
    25202895\begin{cfa}
    2521 ®extern® [ int x ] g( int y ) {$\,$}
     2896®extern® [ int x ] g( int y ) {§\,§}
    25222897\end{cfa}
    25232898Lastly, if there are no output parameters or input parameters, the brackets and/or parentheses must still be specified;
    25242899in both cases the type is assumed to be void as opposed to old style C defaults of int return type and unknown parameter types, respectively, as in:
    25252900\begin{cfa}
    2526 [$\,$] g(); $\C{// no input or output parameters}$
    2527 [ void ] g( void ); $\C{// no input or output parameters}$
     2901[§\,§] g(); §\C{// no input or output parameters}§
     2902[ void ] g( void ); §\C{// no input or output parameters}§
    25282903\end{cfa}
    25292904
     
    25432918\begin{cfa}
    25442919typedef int foo;
    2545 int f( int (* foo) ); $\C{// foo is redefined as a parameter name}$
     2920int f( int (* foo) ); §\C{// foo is redefined as a parameter name}§
    25462921\end{cfa}
    25472922The string ``©int (* foo)©'' declares a C-style named-parameter of type pointer to an integer (the parenthesis are superfluous), while the same string declares a \CFA style unnamed parameter of type routine returning integer with unnamed parameter of type pointer to foo.
     
    25512926C-style declarations can be used to declare parameters for \CFA style routine definitions, \eg:
    25522927\begin{cfa}
    2553 [ int ] f( * int, int * ); $\C{// returns an integer, accepts 2 pointers to integers}$
    2554 [ * int, int * ] f( int ); $\C{// returns 2 pointers to integers, accepts an integer}$
     2928[ int ] f( * int, int * ); §\C{// returns an integer, accepts 2 pointers to integers}§
     2929[ * int, int * ] f( int ); §\C{// returns 2 pointers to integers, accepts an integer}§
    25552930\end{cfa}
    25562931The reason for allowing both declaration styles in the new context is for backwards compatibility with existing preprocessor macros that generate C-style declaration-syntax, as in:
    25572932\begin{cfa}
    25582933#define ptoa( n, d ) int (*n)[ d ]
    2559 int f( ptoa( p, 5 ) ) ... $\C{// expands to int f( int (*p)[ 5 ] )}$
    2560 [ int ] f( ptoa( p, 5 ) ) ... $\C{// expands to [ int ] f( int (*p)[ 5 ] )}$
     2934int f( ptoa( p, 5 ) ) ... §\C{// expands to int f( int (*p)[ 5 ] )}§
     2935[ int ] f( ptoa( p, 5 ) ) ... §\C{// expands to [ int ] f( int (*p)[ 5 ] )}§
    25612936\end{cfa}
    25622937Again, programmers are highly encouraged to use one declaration form or the other, rather than mixing the forms.
     
    25802955        int z;
    25812956        ... x = 0; ... y = z; ...
    2582         ®return;® $\C{// implicitly return x, y}$
     2957        ®return;® §\C{// implicitly return x, y}§
    25832958}
    25842959\end{cfa}
     
    25902965[ int x, int y ] f() {
    25912966        ...
    2592 } $\C{// implicitly return x, y}$
     2967} §\C{// implicitly return x, y}§
    25932968\end{cfa}
    25942969In this case, the current values of ©x© and ©y© are returned to the calling routine just as if a ©return© had been encountered.
     
    25992974[ int x, int y ] f( int, x, int y ) {
    26002975        ...
    2601 } $\C{// implicitly return x, y}$
     2976} §\C{// implicitly return x, y}§
    26022977\end{cfa}
    26032978This notation allows the compiler to eliminate temporary variables in nested routine calls.
    26042979\begin{cfa}
    2605 [ int x, int y ] f( int, x, int y ); $\C{// prototype declaration}$
     2980[ int x, int y ] f( int, x, int y ); §\C{// prototype declaration}§
    26062981int a, b;
    26072982[a, b] = f( f( f( a, b ) ) );
     
    26172992as well, parameter names are optional, \eg:
    26182993\begin{cfa}
    2619 [ int x ] f (); $\C{// returning int with no parameters}$
    2620 [ * int ] g (int y); $\C{// returning pointer to int with int parameter}$
    2621 [ ] h ( int, char ); $\C{// returning no result with int and char parameters}$
    2622 [ * int, int ] j ( int ); $\C{// returning pointer to int and int, with int parameter}$
     2994[ int x ] f (); §\C{// returning int with no parameters}§
     2995[ * int ] g (int y); §\C{// returning pointer to int with int parameter}§
     2996[ ] h ( int, char ); §\C{// returning no result with int and char parameters}§
     2997[ * int, int ] j ( int ); §\C{// returning pointer to int and int, with int parameter}§
    26232998\end{cfa}
    26242999This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa).
     
    26263001\begin{cfa}
    26273002C :             const double bar1(), bar2( int ), bar3( double );
    2628 $\CFA$: [const double] foo(), foo( int ), foo( double ) { return 3.0; }
     3003§\CFA§: [const double] foo(), foo( int ), foo( double ) { return 3.0; }
    26293004\end{cfa}
    26303005\CFA allows the last routine in the list to define its body.
     
    26413016The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg:
    26423017\begin{cfa}
    2643 * [ int x ] () fp; $\C[2.25in]{// pointer to routine returning int with no parameters}$
    2644 * [ * int ] (int y) gp; $\C{// pointer to routine returning pointer to int with int parameter}$
    2645 * [ ] (int,char) hp; $\C{// pointer to routine returning no result with int and char parameters}$
    2646 * [ * int,int ] ( int ) jp; $\C{// pointer to routine returning pointer to int and int, with int parameter}\CRT$
     3018* [ int x ] () fp; §\C[2.25in]{// pointer to routine returning int with no parameters}§
     3019* [ * int ] (int y) gp; §\C{// pointer to routine returning pointer to int with int parameter}§
     3020* [ ] (int,char) hp; §\C{// pointer to routine returning no result with int and char parameters}§
     3021* [ * int,int ] ( int ) jp; §\C{// pointer to routine returning pointer to int and int, with int parameter}\CRT§
    26473022\end{cfa}
    26483023While parameter names are optional, \emph{a routine name cannot be specified};
    26493024for example, the following is incorrect:
    26503025\begin{cfa}
    2651 * [ int x ] f () fp; $\C{// routine name "f" is not allowed}$
     3026* [ int x ] f () fp; §\C{// routine name "f" is not allowed}§
    26523027\end{cfa}
    26533028
     
    26723047whereas a named (keyword) call may be:
    26733048\begin{cfa}
    2674 p( z : 3, x : 4, y : 7 );  $\C{// rewrite \(\Rightarrow\) p( 4, 7, 3 )}$
     3049p( z : 3, x : 4, y : 7 );  §\C{// rewrite \(\Rightarrow\) p( 4, 7, 3 )}§
    26753050\end{cfa}
    26763051Here the order of the arguments is unimportant, and the names of the parameters are used to associate argument values with the corresponding parameters.
     
    26893064For example, the following routine prototypes and definition are all valid.
    26903065\begin{cfa}
    2691 void p( int, int, int ); $\C{// equivalent prototypes}$
     3066void p( int, int, int ); §\C{// equivalent prototypes}§
    26923067void p( int x, int y, int z );
    26933068void p( int y, int x, int z );
    26943069void p( int z, int y, int x );
    2695 void p( int q, int r, int s ) {} $\C{// match with this definition}$
     3070void p( int q, int r, int s ) {} §\C{// match with this definition}§
    26963071\end{cfa}
    26973072Forcing matching parameter names in routine prototypes with corresponding routine definitions is possible, but goes against a strong tradition in C programming.
     
    27053080int f( int x, double y );
    27063081
    2707 f( j : 3, i : 4 ); $\C{// 1st f}$
    2708 f( x : 7, y : 8.1 ); $\C{// 2nd f}$
    2709 f( 4, 5 );  $\C{// ambiguous call}$
     3082f( j : 3, i : 4 ); §\C{// 1st f}§
     3083f( x : 7, y : 8.1 ); §\C{// 2nd f}§
     3084f( 4, 5 );  §\C{// ambiguous call}§
    27103085\end{cfa}
    27113086However, named arguments compound routine resolution in conjunction with conversions:
    27123087\begin{cfa}
    2713 f( i : 3, 5.7 ); $\C{// ambiguous call ?}$
     3088f( i : 3, 5.7 ); §\C{// ambiguous call ?}§
    27143089\end{cfa}
    27153090Depending on the cost associated with named arguments, this call could be resolvable or ambiguous.
     
    27253100the allowable positional calls are:
    27263101\begin{cfa}
    2727 p(); $\C{// rewrite \(\Rightarrow\) p( 1, 2, 3 )}$
    2728 p( 4 ); $\C{// rewrite \(\Rightarrow\) p( 4, 2, 3 )}$
    2729 p( 4, 4 ); $\C{// rewrite \(\Rightarrow\) p( 4, 4, 3 )}$
    2730 p( 4, 4, 4 ); $\C{// rewrite \(\Rightarrow\) p( 4, 4, 4 )}$
     3102p(); §\C{// rewrite \(\Rightarrow\) p( 1, 2, 3 )}§
     3103p( 4 ); §\C{// rewrite \(\Rightarrow\) p( 4, 2, 3 )}§
     3104p( 4, 4 ); §\C{// rewrite \(\Rightarrow\) p( 4, 4, 3 )}§
     3105p( 4, 4, 4 ); §\C{// rewrite \(\Rightarrow\) p( 4, 4, 4 )}§
    27313106// empty arguments
    2732 p(  , 4, 4 ); $\C{// rewrite \(\Rightarrow\) p( 1, 4, 4 )}$
    2733 p( 4,  , 4 ); $\C{// rewrite \(\Rightarrow\) p( 4, 2, 4 )}$
    2734 p( 4, 4,   ); $\C{// rewrite \(\Rightarrow\) p( 4, 4, 3 )}$
    2735 p( 4,  ,   ); $\C{// rewrite \(\Rightarrow\) p( 4, 2, 3 )}$
    2736 p(  , 4,   ); $\C{// rewrite \(\Rightarrow\) p( 1, 4, 3 )}$
    2737 p(  ,  , 4 ); $\C{// rewrite \(\Rightarrow\) p( 1, 2, 4 )}$
    2738 p(  ,  ,   ); $\C{// rewrite \(\Rightarrow\) p( 1, 2, 3 )}$
     3107p(  , 4, 4 ); §\C{// rewrite \(\Rightarrow\) p( 1, 4, 4 )}§
     3108p( 4,  , 4 ); §\C{// rewrite \(\Rightarrow\) p( 4, 2, 4 )}§
     3109p( 4, 4,   ); §\C{// rewrite \(\Rightarrow\) p( 4, 4, 3 )}§
     3110p( 4,  ,   ); §\C{// rewrite \(\Rightarrow\) p( 4, 2, 3 )}§
     3111p(  , 4,   ); §\C{// rewrite \(\Rightarrow\) p( 1, 4, 3 )}§
     3112p(  ,  , 4 ); §\C{// rewrite \(\Rightarrow\) p( 1, 2, 4 )}§
     3113p(  ,  ,   ); §\C{// rewrite \(\Rightarrow\) p( 1, 2, 3 )}§
    27393114\end{cfa}
    27403115Here the missing arguments are inserted from the default values in the parameter list.
     
    27603135Default values may only appear in a prototype versus definition context:
    27613136\begin{cfa}
    2762 void p( int x, int y = 2, int z = 3 ); $\C{// prototype: allowed}$
    2763 void p( int, int = 2, int = 3 ); $\C{// prototype: allowed}$
    2764 void p( int x, int y = 2, int z = 3 ) {} $\C{// definition: not allowed}$
     3137void p( int x, int y = 2, int z = 3 ); §\C{// prototype: allowed}§
     3138void p( int, int = 2, int = 3 ); §\C{// prototype: allowed}§
     3139void p( int x, int y = 2, int z = 3 ) {} §\C{// definition: not allowed}§
    27653140\end{cfa}
    27663141The reason for this restriction is to allow separate compilation.
     
    27773152\begin{cfa}
    27783153p( int x, int y, int z, ... );
    2779 p( 1, 4, 5, 6, z : 3, y : 2 ); $\C{// assume p( /* positional */, ... , /* named */ );}$
    2780 p( 1, z : 3, y : 2, 4, 5, 6 ); $\C{// assume p( /* positional */, /* named */, ... );}$
     3154p( 1, 4, 5, 6, z : 3, y : 2 ); §\C{// assume p( /* positional */, ... , /* named */ );}§
     3155p( 1, z : 3, y : 2, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§
    27813156\end{cfa}
    27823157In the first call, it is necessary for the programmer to conceptually rewrite the call, changing named arguments into positional, before knowing where the ellipse arguments begin.
     
    27873162\begin{cfa}
    27883163void p( int x, int y = 2, int z = 3... );
    2789 p( 1, 4, 5, 6, z : 3 ); $\C{// assume p( /* positional */, ... , /* named */ );}$
    2790 p( 1, z : 3, 4, 5, 6 ); $\C{// assume p( /* positional */, /* named */, ... );}$
     3164p( 1, 4, 5, 6, z : 3 ); §\C{// assume p( /* positional */, ... , /* named */ );}§
     3165p( 1, z : 3, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§
    27913166\end{cfa}
    27923167The first call is an error because arguments 4 and 5 are actually positional not ellipse arguments;
     
    28183193Furthermore, overloading cannot handle accessing default arguments in the middle of a positional list, via a missing argument, such as:
    28193194\begin{cfa}
    2820 p( 1, /* default */, 5 ); $\C{// rewrite \(\Rightarrow\) p( 1, 2, 5 )}$
     3195p( 1, /* default */, 5 ); §\C{// rewrite \(\Rightarrow\) p( 1, 2, 5 )}§
    28213196\end{cfa}
    28223197
     
    28313206\begin{cfa}
    28323207struct {
    2833         int f1; $\C{// named field}$
    2834         int f2 : 4; $\C{// named field with bit field size}$
    2835         int : 3; $\C{// unnamed field for basic type with bit field size}$
    2836         int ; $\C{// disallowed, unnamed field}$
    2837         int *; $\C{// disallowed, unnamed field}$
    2838         int (*)( int ); $\C{// disallowed, unnamed field}$
     3208        int f1; §\C{// named field}§
     3209        int f2 : 4; §\C{// named field with bit field size}§
     3210        int : 3; §\C{// unnamed field for basic type with bit field size}§
     3211        int ; §\C{// disallowed, unnamed field}§
     3212        int *; §\C{// disallowed, unnamed field}§
     3213        int (*)( int ); §\C{// disallowed, unnamed field}§
    28393214};
    28403215\end{cfa}
     
    28443219\begin{cfa}
    28453220struct {
    2846         int , , ; $\C{// 3 unnamed fields}$
     3221        int , , ; §\C{// 3 unnamed fields}§
    28473222}
    28483223\end{cfa}
     
    29383313const unsigned int size = 5;
    29393314int ia[size];
    2940 ... $\C{// assign values to array ia}$
    2941 qsort( ia, size ); $\C{// sort ascending order using builtin ?<?}$
     3315... §\C{// assign values to array ia}§
     3316qsort( ia, size ); §\C{// sort ascending order using builtin ?<?}§
    29423317{
    2943         ®int ?<?( int x, int y ) { return x > y; }® $\C{// nested routine}$
    2944         qsort( ia, size ); $\C{// sort descending order by local redefinition}$
     3318        ®int ?<?( int x, int y ) { return x > y; }® §\C{// nested routine}§
     3319        qsort( ia, size ); §\C{// sort descending order by local redefinition}§
    29453320}
    29463321\end{cfa}
     
    29503325The following program in undefined in \CFA (and Indexc{gcc})
    29513326\begin{cfa}
    2952 [* [int]( int )] foo() { $\C{// int (* foo())( int )}$
     3327[* [int]( int )] foo() { §\C{// int (* foo())( int )}§
    29533328        int ®i® = 7;
    29543329        int bar( int p ) {
    2955                 ®i® += 1; $\C{// dependent on local variable}$
     3330                ®i® += 1; §\C{// dependent on local variable}§
    29563331                sout | ®i®;
    29573332        }
    2958         return bar; $\C{// undefined because of local dependence}$
     3333        return bar; §\C{// undefined because of local dependence}§
    29593334}
    29603335int main() {
    2961         * [int]( int ) fp = foo(); $\C{// int (* fp)( int )}$
     3336        * [int]( int ) fp = foo(); §\C{// int (* fp)( int )}§
    29623337        sout | fp( 3 );
    29633338}
     
    29723347In C and \CFA, lists of elements appear in several contexts, such as the parameter list of a routine call.
    29733348\begin{cfa}
    2974 f( ®2, x, 3 + i® ); $\C{// element list}$
     3349f( ®2, x, 3 + i® ); §\C{// element list}§
    29753350\end{cfa}
    29763351A list of elements is called a \newterm{tuple}, and is different from a \Index{comma expression}.
     
    29873362For example, consider C's \Indexc{div} function, which returns the quotient and remainder for a division of an integer value.
    29883363\begin{cfa}
    2989 typedef struct { int quot, rem; } div_t;        $\C[7cm]{// from include stdlib.h}$
     3364typedef struct { int quot, rem; } div_t;        §\C[7cm]{// from include stdlib.h}§
    29903365div_t div( int num, int den );
    2991 div_t qr = div( 13, 5 ); $\C{// return quotient/remainder aggregate}$
    2992 printf( "%d %d\n", qr.quot, qr.rem ); $\C{// print quotient/remainder}$
     3366div_t qr = div( 13, 5 ); §\C{// return quotient/remainder aggregate}§
     3367printf( "%d %d\n", qr.quot, qr.rem ); §\C{// print quotient/remainder}§
    29933368\end{cfa}
    29943369This approach requires a name for the return type and fields, where \Index{naming} is a common programming-language issue.
     
    30003375For example, consider C's \Indexc{modf} function, which returns the integral and fractional part of a floating value.
    30013376\begin{cfa}
    3002 double modf( double x, double * i ); $\C{// from include math.h}$
    3003 double intp, frac = modf( 13.5, &intp ); $\C{// return integral and fractional components}$
    3004 printf( "%g %g\n", intp, frac ); $\C{// print integral/fractional components}$
     3377double modf( double x, double * i ); §\C{// from include math.h}§
     3378double intp, frac = modf( 13.5, &intp ); §\C{// return integral and fractional components}§
     3379printf( "%g %g\n", intp, frac ); §\C{// print integral/fractional components}§
    30053380\end{cfa}
    30063381This approach requires allocating storage for the return values, which complicates the call site with a sequence of variable declarations leading to the call.
     
    30293404When a function call is passed as an argument to another call, the best match of actual arguments to formal parameters is evaluated given all possible expression interpretations in the current scope.
    30303405\begin{cfa}
    3031 void g( int, int ); $\C{// 1}$
    3032 void g( double, double ); $\C{// 2}$
    3033 g( div( 13, 5 ) ); $\C{// select 1}$
    3034 g( modf( 13.5 ) ); $\C{// select 2}$
     3406void g( int, int ); §\C{// 1}§
     3407void g( double, double ); §\C{// 2}§
     3408g( div( 13, 5 ) ); §\C{// select 1}§
     3409g( modf( 13.5 ) ); §\C{// select 2}§
    30353410\end{cfa}
    30363411In this case, there are two overloaded ©g© routines.
     
    30413416The previous examples can be rewritten passing the multiple returned-values directly to the ©printf© function call.
    30423417\begin{cfa}
    3043 [ int, int ] div( int x, int y ); $\C{// from include stdlib}$
    3044 printf( "%d %d\n", div( 13, 5 ) ); $\C{// print quotient/remainder}$
    3045 
    3046 [ double, double ] modf( double x ); $\C{// from include math}$
    3047 printf( "%g %g\n", modf( 13.5 ) ); $\C{// print integral/fractional components}$
     3418[ int, int ] div( int x, int y ); §\C{// from include stdlib}§
     3419printf( "%d %d\n", div( 13, 5 ) ); §\C{// print quotient/remainder}§
     3420
     3421[ double, double ] modf( double x ); §\C{// from include math}§
     3422printf( "%g %g\n", modf( 13.5 ) ); §\C{// print integral/fractional components}§
    30483423\end{cfa}
    30493424This approach provides the benefits of compile-time checking for appropriate return statements as in aggregation, but without the required verbosity of declaring a new named type.
     
    30553430\begin{cfa}
    30563431int quot, rem;
    3057 [ quot, rem ] = div( 13, 5 ); $\C{// assign multiple variables}$
    3058 printf( "%d %d\n", quot, rem ); $\C{// print quotient/remainder}\CRT$
     3432[ quot, rem ] = div( 13, 5 ); §\C{// assign multiple variables}§
     3433printf( "%d %d\n", quot, rem ); §\C{// print quotient/remainder}\CRT§
    30593434\end{cfa}
    30603435Here, the multiple return-values are matched in much the same way as passing multiple return-values to multiple parameters in a call.
     
    30853460In \CFA, it is possible to overcome this restriction by declaring a \newterm{tuple variable}.
    30863461\begin{cfa}
    3087 [int, int] ®qr® = div( 13, 5 ); $\C{// initialize tuple variable}$
    3088 printf( "%d %d\n", ®qr® ); $\C{// print quotient/remainder}$
     3462[int, int] ®qr® = div( 13, 5 ); §\C{// initialize tuple variable}§
     3463printf( "%d %d\n", ®qr® ); §\C{// print quotient/remainder}§
    30893464\end{cfa}
    30903465It is now possible to match the multiple return-values to a single variable, in much the same way as \Index{aggregation}.
     
    30923467One way to access the individual components of a tuple variable is with assignment.
    30933468\begin{cfa}
    3094 [ quot, rem ] = qr; $\C{// assign multiple variables}$
     3469[ quot, rem ] = qr; §\C{// assign multiple variables}§
    30953470\end{cfa}
    30963471
     
    31153490[int, double] * p;
    31163491
    3117 int y = x.0; $\C{// access int component of x}$
    3118 y = f().1; $\C{// access int component of f}$
    3119 p->0 = 5; $\C{// access int component of tuple pointed-to by p}$
    3120 g( x.1, x.0 ); $\C{// rearrange x to pass to g}$
    3121 double z = [ x, f() ].0.1; $\C{// access second component of first component of tuple expression}$
     3492int y = x.0; §\C{// access int component of x}§
     3493y = f().1; §\C{// access int component of f}§
     3494p->0 = 5; §\C{// access int component of tuple pointed-to by p}§
     3495g( x.1, x.0 ); §\C{// rearrange x to pass to g}§
     3496double z = [ x, f() ].0.1; §\C{// access second component of first component of tuple expression}§
    31223497\end{cfa}
    31233498Tuple-index expressions can occur on any tuple-typed expression, including tuple-returning functions, square-bracketed tuple expressions, and other tuple-index expressions, provided the retrieved component is also a tuple.
     
    31873562double y;
    31883563[int, double] z;
    3189 [y, x] = 3.14; $\C{// mass assignment}$
    3190 [x, y] = z;                                                         $\C{// multiple assignment}$
    3191 z = 10;                                                         $\C{// mass assignment}$
    3192 z = [x, y]; $\C{// multiple assignment}$
     3564[y, x] = 3.14; §\C{// mass assignment}§
     3565[x, y] = z;                                                         §\C{// multiple assignment}§
     3566z = 10;                                                         §\C{// mass assignment}§
     3567z = [x, y]; §\C{// multiple assignment}§
    31933568\end{cfa}
    31943569Let $L_i$ for $i$ in $[0, n)$ represent each component of the flattened left side, $R_i$ represent each component of the flattened right side of a multiple assignment, and $R$ represent the right side of a mass assignment.
     
    31983573\begin{cfa}
    31993574[ int, int ] x, y, z;
    3200 [ x, y ] = z;                                              $\C{// multiple assignment, invalid 4 != 2}$
     3575[ x, y ] = z;                                              §\C{// multiple assignment, invalid 4 != 2}§
    32013576\end{cfa}
    32023577Multiple assignment assigns $R_i$ to $L_i$ for each $i$.
     
    32343609        double c, d;
    32353610        [ void ] f( [ int, int ] );
    3236         f( [ c, a ] = [ b, d ] = 1.5 ); $\C{// assignments in parameter list}$
     3611        f( [ c, a ] = [ b, d ] = 1.5 ); §\C{// assignments in parameter list}§
    32373612\end{cfa}
    32383613The tuple expression begins with a mass assignment of ©1.5© into ©[b, d]©, which assigns ©1.5© into ©b©, which is truncated to ©1©, and ©1.5© into ©d©, producing the tuple ©[1, 1.5]© as a result.
     
    32473622\begin{cfa}
    32483623struct S;
    3249 void ?{}(S *); $\C{// (1)}$
    3250 void ?{}(S *, int); $\C{// (2)}$
    3251 void ?{}(S * double); $\C{// (3)}$
    3252 void ?{}(S *, S); $\C{// (4)}$
    3253 
    3254 [S, S] x = [3, 6.28]; $\C{// uses (2), (3), specialized constructors}$
    3255 [S, S] y; $\C{// uses (1), (1), default constructor}$
    3256 [S, S] z = x.0; $\C{// uses (4), (4), copy constructor}$
     3624void ?{}(S *); §\C{// (1)}§
     3625void ?{}(S *, int); §\C{// (2)}§
     3626void ?{}(S * double); §\C{// (3)}§
     3627void ?{}(S *, S); §\C{// (4)}§
     3628
     3629[S, S] x = [3, 6.28]; §\C{// uses (2), (3), specialized constructors}§
     3630[S, S] y; §\C{// uses (1), (1), default constructor}§
     3631[S, S] z = x.0; §\C{// uses (4), (4), copy constructor}§
    32573632\end{cfa}
    32583633In this example, ©x© is initialized by the multiple constructor calls ©?{}(&x.0, 3)© and ©?{}(&x.1, 6.28)©, while ©y© is initialized by two default constructor calls ©?{}(&y.0)© and ©?{}(&y.1)©.
     
    32953670A member-access tuple may be used anywhere a tuple can be used, \eg:
    32963671\begin{cfa}
    3297 s.[ y, z, x ] = [ 3, 3.2, 'x' ]; $\C{// equivalent to s.x = 'x', s.y = 3, s.z = 3.2}$
    3298 f( s.[ y, z ] ); $\C{// equivalent to f( s.y, s.z )}$
     3672s.[ y, z, x ] = [ 3, 3.2, 'x' ]; §\C{// equivalent to s.x = 'x', s.y = 3, s.z = 3.2}§
     3673f( s.[ y, z ] ); §\C{// equivalent to f( s.y, s.z )}§
    32993674\end{cfa}
    33003675Note, the fields appearing in a record-field tuple may be specified in any order;
     
    33063681void f( double, long );
    33073682
    3308 f( x.[ 0, 3 ] ); $\C{// f( x.0, x.3 )}$
    3309 x.[ 0, 1 ] = x.[ 1, 0 ]; $\C{// [ x.0, x.1 ] = [ x.1, x.0 ]}$
     3683f( x.[ 0, 3 ] ); §\C{// f( x.0, x.3 )}§
     3684x.[ 0, 1 ] = x.[ 1, 0 ]; §\C{// [ x.0, x.1 ] = [ x.1, x.0 ]}§
    33103685[ long, int, long ] y = x.[ 2, 0, 2 ];
    33113686\end{cfa}
     
    33243699\begin{cfa}
    33253700[ int, float, double ] f();
    3326 [ double, float ] x = f().[ 2, 1 ]; $\C{// f() called once}$
     3701[ double, float ] x = f().[ 2, 1 ]; §\C{// f() called once}§
    33273702\end{cfa}
    33283703
     
    33373712That is, a cast can be used to select the type of an expression when it is ambiguous, as in the call to an overloaded function.
    33383713\begin{cfa}
    3339 int f(); $\C{// (1)}$
    3340 double f(); $\C{// (2)}$
    3341 
    3342 f(); $\C{// ambiguous - (1),(2) both equally viable}$
    3343 (int)f(); $\C{// choose (2)}$
     3714int f(); §\C{// (1)}§
     3715double f(); §\C{// (2)}§
     3716
     3717f(); §\C{// ambiguous - (1),(2) both equally viable}§
     3718(int)f(); §\C{// choose (2)}§
    33443719\end{cfa}
    33453720Since casting is a fundamental operation in \CFA, casts need to be given a meaningful interpretation in the context of tuples.
     
    33493724void g();
    33503725
    3351 (void)f(); $\C{// valid, ignore results}$
    3352 (int)g(); $\C{// invalid, void cannot be converted to int}$
     3726(void)f(); §\C{// valid, ignore results}§
     3727(int)g(); §\C{// invalid, void cannot be converted to int}§
    33533728
    33543729struct A { int x; };
    3355 (struct A)f(); $\C{// invalid, int cannot be converted to A}$
     3730(struct A)f(); §\C{// invalid, int cannot be converted to A}§
    33563731\end{cfa}
    33573732In C, line 4 is a valid cast, which calls ©f© and discards its result.
     
    33693744        [int, [int, int], int] g();
    33703745
    3371         ([int, double])f(); $\C{// (1) valid}$
    3372         ([int, int, int])g(); $\C{// (2) valid}$
    3373         ([void, [int, int]])g(); $\C{// (3) valid}$
    3374         ([int, int, int, int])g(); $\C{// (4) invalid}$
    3375         ([int, [int, int, int]])g(); $\C{// (5) invalid}$
     3746        ([int, double])f(); §\C{// (1) valid}§
     3747        ([int, int, int])g(); §\C{// (2) valid}§
     3748        ([void, [int, int]])g(); §\C{// (3) valid}§
     3749        ([int, int, int, int])g(); §\C{// (4) invalid}§
     3750        ([int, [int, int, int]])g(); §\C{// (5) invalid}§
    33763751\end{cfa}
    33773752
     
    34333808void f([int, int], int, int);
    34343809
    3435 f([0, 0], 0, 0); $\C{// no cost}$
    3436 f(0, 0, 0, 0); $\C{// cost for structuring}$
    3437 f([0, 0,], [0, 0]); $\C{// cost for flattening}$
    3438 f([0, 0, 0], 0); $\C{// cost for flattening and structuring}$
     3810f([0, 0], 0, 0); §\C{// no cost}§
     3811f(0, 0, 0, 0); §\C{// cost for structuring}§
     3812f([0, 0,], [0, 0]); §\C{// cost for flattening}§
     3813f([0, 0, 0], 0); §\C{// cost for flattening and structuring}§
    34393814\end{cfa}
    34403815
     
    35003875[ unsigned int, char ]
    35013876[ double, double, double ]
    3502 [ * int, int * ] $\C{// mix of CFA and ANSI}$
     3877[ * int, int * ] §\C{// mix of CFA and ANSI}§
    35033878[ * [ 5 ] int, * * char, * [ [ int, int ] ] (int, int) ]
    35043879\end{cfa}
     
    35073882Examples of declarations using tuple types are:
    35083883\begin{cfa}
    3509 [ int, int ] x; $\C{// 2 element tuple, each element of type int}$
    3510 * [ char, char ] y; $\C{// pointer to a 2 element tuple}$
     3884[ int, int ] x; §\C{// 2 element tuple, each element of type int}§
     3885* [ char, char ] y; §\C{// pointer to a 2 element tuple}§
    35113886[ [ int, int ] ] z ([ int, int ]);
    35123887\end{cfa}
     
    35253900[ int, int ] w1;
    35263901[ int, int, int ] w2;
    3527 [ void ] f (int, int, int); $\C{// three input parameters of type int}$
    3528 [ void ] g ([ int, int, int ]); $\C{3 element tuple as input}$
     3902[ void ] f (int, int, int); §\C{// three input parameters of type int}§
     3903[ void ] g ([ int, int, int ]); §\C{3 element tuple as input}§
    35293904f( [ 1, 2, 3 ] );
    35303905f( w1, 3 );
     
    36073982[ int, int, int, int ] w = [ 1, 2, 3, 4 ];
    36083983int x = 5;
    3609 [ x, w ] = [ w, x ]; $\C{// all four tuple coercions}$
     3984[ x, w ] = [ w, x ]; §\C{// all four tuple coercions}§
    36103985\end{cfa}
    36113986Starting on the right-hand tuple in the last assignment statement, w is opened, producing a tuple of four values;
     
    36974072both these examples produce indeterminate results:
    36984073\begin{cfa}
    3699 f( x++, x++ ); $\C{// C routine call with side effects in arguments}$
    3700 [ v1, v2 ] = [ x++, x++ ]; $\C{// side effects in right-hand side of multiple assignment}$
     4074f( x++, x++ ); §\C{// C routine call with side effects in arguments}§
     4075[ v1, v2 ] = [ x++, x++ ]; §\C{// side effects in right-hand side of multiple assignment}§
    37014076\end{cfa}
    37024077
     
    37974172\begin{cfa}
    37984173[int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 4, [ 5, 6 ] ];
    3799 sout | t1 | t2; $\C{// print tuples}$
     4174sout | t1 | t2; §\C{// print tuples}§
    38004175\end{cfa}
    38014176\begin{cfa}[showspaces=true,aboveskip=0pt]
     
    38814256
    38824257int main( int argc, char * argv[] ) {
    3883         ®ifstream® in  = stdin;                                 $\C{// copy default files}$
     4258        ®ifstream® in  = stdin;                                 §\C{// copy default files}§
    38844259        ®ofstream® out = stdout;
    38854260
     
    38874262                choose ( argc ) {
    38884263                  case 2, 3:
    3889                         ®open®( in, argv[1] );                  $\C{// open input file first as output creates file}$
    3890                         if ( argc == 3 ) ®open®( out, argv[2] ); $\C{// do not create output unless input opens}$
    3891                   case 1: ;                                                     $\C{// use default files}$
     4264                        ®open®( in, argv[1] );                  §\C{// open input file first as output creates file}§
     4265                        if ( argc == 3 ) ®open®( out, argv[2] ); §\C{// do not create output unless input opens}§
     4266                  case 1: ;                                                     §\C{// use default files}§
    38924267                  default:
    38934268                        ®exit® | "Usage" | argv[0] | "[ input-file (default stdin) "
    38944269                                   "[ output-file (default stdout) ] ]";
    38954270                } // choose
    3896         } catch( ®open_failure® * ex; ex->istream == &in ) { $\C{// input file errors}$
     4271        } catch( ®open_failure® * ex; ex->istream == &in ) { §\C{// input file errors}§
    38974272                ®exit® | "Unable to open input file" | argv[1];
    3898         } catch( ®open_failure® * ex; ex->ostream == &out ) { $\C{// output file errors}$
    3899                 ®close®( in );                                          $\C{// optional}$
     4273        } catch( ®open_failure® * ex; ex->ostream == &out ) { §\C{// output file errors}§
     4274                ®close®( in );                                          §\C{// optional}§
    39004275                ®exit® | "Unable to open output file" | argv[2];
    39014276        } // try
    39024277
    3903         out | nlOff;                                                    $\C{// turn off auto newline}$
    3904         in | nlOn;                                                              $\C{// turn on reading newline}$
     4278        out | nlOff;                                                    §\C{// turn off auto newline}§
     4279        in | nlOn;                                                              §\C{// turn on reading newline}§
    39054280        char ch;
    3906         for () {                                                                $\C{// read/write characters}$
     4281        for () {                                                                §\C{// read/write characters}§
    39074282                in | ch;
    3908           if ( eof( in ) ) break;                               $\C{// eof ?}$
     4283          if ( eof( in ) ) break;                               §\C{// eof ?}§
    39094284                out | ch;
    39104285        } // for
     
    39534328// *********************************** ofstream ***********************************
    39544329
    3955 bool fail( ofstream & );$\indexc{fail}\index{ofstream@©ofstream©!©fail©}$
    3956 void clear( ofstream & );$\indexc{clear}\index{ofstream@©ofstream©!©clear©}$
    3957 int flush( ofstream & );$\indexc{flush}\index{ofstream@©ofstream©!©flush©}$
    3958 void open( ofstream &, const char name[], const char mode[] = "w" );$\indexc{open}\index{ofstream@©ofstream©!©open©}$
    3959 void close( ofstream & );$\indexc{close}\index{ofstream@©ofstream©!©close©}$
    3960 ofstream & write( ofstream &, const char data[], size_t size );$\indexc{write}\index{ofstream@©ofstream©!©write©}$
    3961 
    3962 void ?{}( ofstream & );$\index{ofstream@©ofstream©!©?{}©}$
     4330bool fail( ofstream & );§\indexc{fail}\index{ofstream@©ofstream©!©fail©}§
     4331void clear( ofstream & );§\indexc{clear}\index{ofstream@©ofstream©!©clear©}§
     4332int flush( ofstream & );§\indexc{flush}\index{ofstream@©ofstream©!©flush©}§
     4333void open( ofstream &, const char name[], const char mode[] = "w" );§\indexc{open}\index{ofstream@©ofstream©!©open©}§
     4334void close( ofstream & );§\indexc{close}\index{ofstream@©ofstream©!©close©}§
     4335ofstream & write( ofstream &, const char data[], size_t size );§\indexc{write}\index{ofstream@©ofstream©!©write©}§
     4336
     4337void ?{}( ofstream & );§\index{ofstream@©ofstream©!©?{}©}§
    39634338void ?{}( ofstream &, const char name[], const char mode[] = "w" );
    3964 void ^?{}( ofstream & );$\index{ofstream@©ofstream©!©^?{}©}$
     4339void ^?{}( ofstream & );§\index{ofstream@©ofstream©!©^?{}©}§
    39654340
    39664341// *********************************** ifstream ***********************************
    39674342
    3968 bool fail( ifstream & is );$\indexc{fail}\index{ifstream@©ifstream©!©fail©}$
    3969 void clear( ifstream & );$\indexc{clear}\index{ifstream@©ifstream©!©clear©}$
    3970 bool eof( ifstream & is );$\indexc{eof}\index{ifstream@©ifstream©!©eof©}$
    3971 void open( ifstream & is, const char name[], const char mode[] = "r" );$\indexc{open}\index{ifstream@©ifstream©!©open©}$
    3972 void close( ifstream & is );$\indexc{close}\index{ifstream@©ifstream©!©close©}$
    3973 ifstream & read( ifstream & is, char data[], size_t size );$\indexc{read}\index{ifstream@©ifstream©!©read©}$
    3974 ifstream & ungetc( ifstream & is, char c );$\indexc{unget}\index{ifstream@©ifstream©!©unget©}$
    3975 
    3976 void ?{}( ifstream & is );$\index{ifstream@©ifstream©!©?{}©}$
     4343bool fail( ifstream & is );§\indexc{fail}\index{ifstream@©ifstream©!©fail©}§
     4344void clear( ifstream & );§\indexc{clear}\index{ifstream@©ifstream©!©clear©}§
     4345bool eof( ifstream & is );§\indexc{eof}\index{ifstream@©ifstream©!©eof©}§
     4346void open( ifstream & is, const char name[], const char mode[] = "r" );§\indexc{open}\index{ifstream@©ifstream©!©open©}§
     4347void close( ifstream & is );§\indexc{close}\index{ifstream@©ifstream©!©close©}§
     4348ifstream & read( ifstream & is, char data[], size_t size );§\indexc{read}\index{ifstream@©ifstream©!©read©}§
     4349ifstream & ungetc( ifstream & is, char c );§\indexc{unget}\index{ifstream@©ifstream©!©unget©}§
     4350
     4351void ?{}( ifstream & is );§\index{ifstream@©ifstream©!©?{}©}§
    39774352void ?{}( ifstream & is, const char name[], const char mode[] = "r" );
    3978 void ^?{}( ifstream & is );$\index{ifstream@©ifstream©!©^?{}©}$
     4353void ^?{}( ifstream & is );§\index{ifstream@©ifstream©!©^?{}©}§
    39794354\end{cfa}
    39804355\caption{Stream Functions}
     
    40634438The separator string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters).
    40644439\begin{cfa}[belowskip=0pt]
    4065 sepSet( sout, ", $\LstStringStyle{\textdollar}$" ); $\C{// set separator from " " to ", \$"}$
     4440sepSet( sout, ", $\LstStringStyle{\textdollar}$" ); §\C{// set separator from " " to ", \$"}§
    40664441sout | 1 | 2 | 3 | " \"" | ®sepVal® | "\"";
    40674442\end{cfa}
     
    40704445\end{cfa}
    40714446\begin{cfa}[belowskip=0pt]
    4072 sepSet( sout, " " ); $\C{// reset separator to " "}$
     4447sepSet( sout, " " ); §\C{// reset separator to " "}§
    40734448sout | 1 | 2 | 3 | " \"" | ®sepGet( sout )® | "\"";
    40744449\end{cfa}
     
    40784453©sepGet© can be used to store a separator and then restore it:
    40794454\begin{cfa}[belowskip=0pt]
    4080 char store[®sepSize®]; $\C{// sepSize is the maximum separator size}$
    4081 strcpy( store, sepGet( sout ) ); $\C{// copy current separator}$
    4082 sepSet( sout, "_" ); $\C{// change separator to underscore}$
     4455char store[®sepSize®]; §\C{// sepSize is the maximum separator size}§
     4456strcpy( store, sepGet( sout ) ); §\C{// copy current separator}§
     4457sepSet( sout, "_" ); §\C{// change separator to underscore}§
    40834458sout | 1 | 2 | 3;
    40844459\end{cfa}
     
    40874462\end{cfa}
    40884463\begin{cfa}[belowskip=0pt]
    4089 sepSet( sout, store ); $\C{// change separator back to original}$
     4464sepSet( sout, store ); §\C{// change separator back to original}§
    40904465sout | 1 | 2 | 3;
    40914466\end{cfa}
     
    40984473The tuple separator-string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters).
    40994474\begin{cfa}[belowskip=0pt]
    4100 sepSetTuple( sout, " " ); $\C{// set tuple separator from ", " to " "}$
     4475sepSetTuple( sout, " " ); §\C{// set tuple separator from ", " to " "}§
    41014476sout | t1 | t2 | " \"" | ®sepTupleVal® | "\"";
    41024477\end{cfa}
     
    41054480\end{cfa}
    41064481\begin{cfa}[belowskip=0pt]
    4107 sepSetTuple( sout, ", " ); $\C{// reset tuple separator to ", "}$
     4482sepSetTuple( sout, ", " ); §\C{// reset tuple separator to ", "}§
    41084483sout | t1 | t2 | " \"" | ®sepGetTuple( sout )® | "\"";
    41094484\end{cfa}
     
    41164491\Indexc{sepOff}\index{manipulator!sepOff@©sepOff©} and \Indexc{sepOn}\index{manipulator!sepOn@©sepOn©} globally toggle printing the separator.
    41174492\begin{cfa}[belowskip=0pt]
    4118 sout | ®sepOff® | 1 | 2 | 3; $\C{// turn off implicit separator}$
     4493sout | ®sepOff® | 1 | 2 | 3; §\C{// turn off implicit separator}§
    41194494\end{cfa}
    41204495\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    41224497\end{cfa}
    41234498\begin{cfa}[belowskip=0pt]
    4124 sout | ®sepOn® | 1 | 2 | 3; $\C{// turn on implicit separator}$
     4499sout | ®sepOn® | 1 | 2 | 3; §\C{// turn on implicit separator}§
    41254500\end{cfa}
    41264501\begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    41314506\Indexc{sep}\index{manipulator!sep@©sep©} and \Indexc{nosep}\index{manipulator!nosep@©nosep©} locally toggle printing the separator with respect to the next printed item, and then return to the global separator setting.
    41324507\begin{cfa}[belowskip=0pt]
    4133 sout | 1 | ®nosep® | 2 | 3; $\C{// turn off implicit separator for the next item}$
     4508sout | 1 | ®nosep® | 2 | 3; §\C{// turn off implicit separator for the next item}§
    41344509\end{cfa}
    41354510\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    41374512\end{cfa}
    41384513\begin{cfa}[belowskip=0pt]
    4139 sout | sepOff | 1 | ®sep® | 2 | 3; $\C{// turn on implicit separator for the next item}$
     4514sout | sepOff | 1 | ®sep® | 2 | 3; §\C{// turn on implicit separator for the next item}§
    41404515\end{cfa}
    41414516\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    41444519The tuple separator also responses to being turned on and off.
    41454520\begin{cfa}[belowskip=0pt]
    4146 sout | t1 | ®nosep® | t2; $\C{// turn off implicit separator for the next item}$
     4521sout | t1 | ®nosep® | t2; §\C{// turn off implicit separator for the next item}§
    41474522\end{cfa}
    41484523\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    41524527Use ©sep© to accomplish this functionality.
    41534528\begin{cfa}[belowskip=0pt]
    4154 sout | ®sep® | 1 | 2 | 3 | ®sep®; $\C{// sep does nothing at start/end of line}$
     4529sout | ®sep® | 1 | 2 | 3 | ®sep®; §\C{// sep does nothing at start/end of line}§
    41554530\end{cfa}
    41564531\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    41584533\end{cfa}
    41594534\begin{cfa}[belowskip=0pt]
    4160 sout | ®sepVal® | 1 | 2 | 3 | ®sepVal® ; $\C{// use sepVal to print separator at start/end of line}$
     4535sout | ®sepVal® | 1 | 2 | 3 | ®sepVal® ; §\C{// use sepVal to print separator at start/end of line}§
    41614536\end{cfa}
    41624537\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    41974572\Indexc{nl}\index{manipulator!nl@©nl©} inserts a newline.
    41984573\begin{cfa}
    4199 sout | ®nl®; $\C{// only print newline}$
    4200 sout | 2; $\C{// implicit newline}$
    4201 sout | 3 | ®nl® | 4 | ®nl®; $\C{// terminating nl merged with implicit newline}$
    4202 sout | 5 | ®nl® | ®nl®; $\C{// again terminating nl merged with implicit newline}$
    4203 sout | 6; $\C{// implicit newline}$
     4574sout | ®nl®; §\C{// only print newline}§
     4575sout | 2; §\C{// implicit newline}§
     4576sout | 3 | ®nl® | 4 | ®nl®; §\C{// terminating nl merged with implicit newline}§
     4577sout | 5 | ®nl® | ®nl®; §\C{// again terminating nl merged with implicit newline}§
     4578sout | 6; §\C{// implicit newline}§
    42044579
    420545802
     
    46485023®mutex( sout )® {
    46495024        sout | 1;
    4650         ®mutex( sout ) sout® | 2 | 3;                           $\C{// unnecessary, but ok because of recursive lock}$
     5025        ®mutex( sout ) sout® | 2 | 3;                           §\C{// unnecessary, but ok because of recursive lock}§
    46515026        sout | 4;
    46525027} // implicitly release sout lock
     
    46605035        int x, y, z, w;
    46615036        sin | x;
    4662         ®mutex( sin )® sin | y | z;                                     $\C{// unnecessary, but ok because of recursive lock}$
     5037        ®mutex( sin )® sin | y | z;                                     §\C{// unnecessary, but ok because of recursive lock}§
    46635038        sin | w;
    46645039} // implicitly release sin lock
     
    46695044\Textbf{WARNING:} The general problem of \Index{nested locking} can occur if routines are called in an I/O sequence that block, \eg:
    46705045\begin{cfa}
    4671 ®mutex( sout )® sout | "data:" | rtn( mon );    $\C{// mutex call on monitor}$
     5046®mutex( sout )® sout | "data:" | rtn( mon );    §\C{// mutex call on monitor}§
    46725047\end{cfa}
    46735048If the thread executing the I/O expression blocks in the monitor with the ©sout© lock, other threads writing to ©sout© also block until the thread holding the lock is unblocked and releases it.
     
    46875062\begin{cfa}
    4688506312®,®345®.®123          $\C[1.25in]{// comma separator, period decimal-point}$
    4689 12®.®345®,®123          $\C{// period separator, comma decimal-point}$
    4690 12$\Sp$345®,®123®.®     $\C{// space separator, comma decimal-point, period terminator}\CRT$
     506412®.®345®,®123          §\C{// period separator, comma decimal-point}§
     506512$\Sp$345®,®123®.®     §\C{// space separator, comma decimal-point, period terminator}\CRT§
    46915066\end{cfa}
    46925067A locale is selected with function ©setlocale©, and the corresponding locale package \emph{must} be installed on the underlying system;
     
    46995074\begin{cfa}
    47005075#include <fstream.hfa>
    4701 #include <locale.h>                                                     $\C{// setlocale}$
    4702 #include <stdlib.h>                                                     $\C{// getenv}$
     5076#include <locale.h>                                                     §\C{// setlocale}§
     5077#include <stdlib.h>                                                     §\C{// getenv}§
    47035078
    47045079int main() {
     
    47725147int main() {
    47735148        enum { size = 256 };
    4774         char buf[size]; $\C{// output buffer}$
    4775         ®ostrstream osstr = { buf, size };® $\C{// bind output buffer/size}$
     5149        char buf[size]; §\C{// output buffer}§
     5150        ®ostrstream osstr = { buf, size };® §\C{// bind output buffer/size}§
    47765151        int i = 3, j = 5, k = 7;
    47775152        double x = 12345678.9, y = 98765.4321e-11;
    47785153
    47795154        osstr | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y)) | "abc";
    4780         write( osstr ); $\C{// write string to stdout}$
    4781         printf( "%s", buf ); $\C{// same lines of output}$
     5155        write( osstr ); §\C{// write string to stdout}§
     5156        printf( "%s", buf ); §\C{// same lines of output}§
    47825157        sout | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y)) | "abc";
    47835158
    4784         char buf2[] = "12 14 15 3.5 7e4 abc"; $\C{// input buffer}$
     5159        char buf2[] = "12 14 15 3.5 7e4 abc"; §\C{// input buffer}§
    47855160        ®istrstream isstr = { buf2 };®
    47865161        char s[10];
     
    49345309// Subsequent arguments can be specified for initialization
    49355310
    4936 void ?{}( Widget & w ) { $\C{// default constructor}$
     5311void ?{}( Widget & w ) { §\C{// default constructor}§
    49375312        w.id = -1;
    49385313        w.size = 0.0;
     
    49485323
    49495324// ^?{} is the destructor operator identifier
    4950 void ^?{}( Widget & w ) { $\C{// destructor}$
     5325void ^?{}( Widget & w ) { §\C{// destructor}§
    49515326        w.id = 0;
    49525327        w.size = 0.0;
     
    49575332}
    49585333
    4959 Widget baz; $\C{// reserve space only}$
    4960 Widget foo{}; $\C{// calls default constructor}$
    4961 Widget bar{ 23, 2.45 }; $\C{// calls constructor with values}$
    4962 baz{ 24, 0.91 }; $\C{// calls constructor with values}$
    4963 ?{}( baz, 24, 0.91 ); $\C{// explicit call to constructor}$
    4964 ^?{} (bar ); $\C{// explicit call to destructor}$
     5334Widget baz; §\C{// reserve space only}§
     5335Widget foo{}; §\C{// calls default constructor}§
     5336Widget bar{ 23, 2.45 }; §\C{// calls constructor with values}§
     5337baz{ 24, 0.91 }; §\C{// calls constructor with values}§
     5338?{}( baz, 24, 0.91 ); §\C{// explicit call to constructor}§
     5339^?{} (bar ); §\C{// explicit call to destructor}§
    49655340\end{cfa}
    49665341\caption{Constructors and Destructors}
     
    54805855
    54815856®coroutine® Fibonacci {
    5482         int fn; $\C{// used for communication}$
     5857        int fn; §\C{// used for communication}§
    54835858};
    54845859
    5485 void main( Fibonacci & fib ) with( fib ) { $\C{// called on first resume}$
    5486         int fn1, fn2; $\C{// retained between resumes}$
    5487         fn = 0;  fn1 = fn; $\C{// 1st case}$
    5488         ®suspend;® $\C{// restart last resume}$
    5489         fn = 1;  fn2 = fn1;  fn1 = fn; $\C{// 2nd case}$
    5490         ®suspend;® $\C{// restart last resume}$
     5860void main( Fibonacci & fib ) with( fib ) { §\C{// called on first resume}§
     5861        int fn1, fn2; §\C{// retained between resumes}§
     5862        fn = 0;  fn1 = fn; §\C{// 1st case}§
     5863        ®suspend;® §\C{// restart last resume}§
     5864        fn = 1;  fn2 = fn1;  fn1 = fn; §\C{// 2nd case}§
     5865        ®suspend;® §\C{// restart last resume}§
    54915866        for () {
    5492                 fn = fn1 + fn2;  fn2 = fn1;  fn1 = fn; $\C{// general case}$
    5493                 ®suspend;® $\C{// restart last resume}$
     5867                fn = fn1 + fn2;  fn2 = fn1;  fn1 = fn; §\C{// general case}§
     5868                ®suspend;® §\C{// restart last resume}§
    54945869        }
    54955870}
    54965871int next( Fibonacci & fib ) with( fib ) {
    5497         ®resume( fib );® $\C{// restart last suspend}$
     5872        ®resume( fib );® §\C{// restart last suspend}§
    54985873        return fn;
    54995874}
    55005875int main() {
    55015876        Fibonacci f1, f2;
    5502         for ( 10 ) { $\C{// print N Fibonacci values}$
     5877        for ( 10 ) { §\C{// print N Fibonacci values}§
    55035878                sout | next( f1 ) | next( f2 );
    55045879        }
     
    55385913int inc( AtomicCnt & ®mutex® c, int inc = 1 ) with(c) { return counter += inc; }
    55395914int dec( AtomicCnt & ®mutex® c, int dec = 1 ) with(c) { return counter -= dec; }
    5540 forall( ostype & | ostream( ostype ) ) { $\C{// print any stream}$
     5915forall( ostype & | ostream( ostype ) ) { §\C{// print any stream}§
    55415916        ostype & ?|?( ostype & os, AtomicCnt c ) { return os | c.counter; }
    55425917        void ?|?( ostype & os, AtomicCnt c ) { (ostype &)(os | c.counter); ends( os ); }
    55435918}
    55445919
    5545 AtomicCnt global; $\C{// shared}$
     5920AtomicCnt global; §\C{// shared}§
    55465921
    55475922thread MyThread {};
     
    55545929int main() {
    55555930        enum { Threads = 4 };
    5556         processor p[Threads - 1]; $\C{// + starting processor}$
     5931        processor p[Threads - 1]; §\C{// + starting processor}§
    55575932        {
    55585933                MyThread t[Threads];
    55595934        }
    5560         sout | global; $\C{// print 0}$
     5935        sout | global; §\C{// print 0}§
    55615936}
    55625937\end{cfa}
     
    70317406In \CFA, there are ambiguous cases with dereference and operator identifiers, \eg ©int *?*?()©, where the string ©*?*?© can be interpreted as:
    70327407\begin{cfa}
    7033 *?$\Sp$*? $\C{// dereference operator, dereference operator}$
    7034 *$\Sp$?*? $\C{// dereference, multiplication operator}$
     7408*?$\Sp$*? §\C{// dereference operator, dereference operator}§
     7409*$\Sp$?*? §\C{// dereference, multiplication operator}§
    70357410\end{cfa}
    70367411By default, the first interpretation is selected, which does not yield a meaningful parse.
     
    70847459\eg:
    70857460\begin{cfa}
    7086 x; $\C{// int x}$
    7087 *y; $\C{// int *y}$
    7088 f( p1, p2 ); $\C{// int f( int p1, int p2 );}$
    7089 g( p1, p2 ) int p1, p2; $\C{// int g( int p1, int p2 );}$
     7461x; §\C{// int x}§
     7462*y; §\C{// int *y}§
     7463f( p1, p2 ); §\C{// int f( int p1, int p2 );}§
     7464g( p1, p2 ) int p1, p2; §\C{// int g( int p1, int p2 );}§
    70907465\end{cfa}
    70917466\CFA continues to support K\&R routine definitions:
    70927467\begin{cfa}
    7093 f( a, b, c ) $\C{// default int return}$
    7094         int a, b; char c $\C{// K\&R parameter declarations}$
     7468f( a, b, c ) §\C{// default int return}§
     7469        int a, b; char c §\C{// K\&R parameter declarations}§
    70957470{
    70967471        ...
     
    71117486int rtn( int i );
    71127487int rtn( char c );
    7113 rtn( 'x' ); $\C{// programmer expects 2nd rtn to be called}$
     7488rtn( 'x' ); §\C{// programmer expects 2nd rtn to be called}§
    71147489\end{cfa}
    71157490\item[Rationale:] it is more intuitive for the call to ©rtn© to match the second version of definition of ©rtn© rather than the first.
     
    71337508\item[Change:] make string literals ©const©:
    71347509\begin{cfa}
    7135 char * p = "abc"; $\C{// valid in C, deprecated in \CFA}$
    7136 char * q = expr ? "abc" : "de"; $\C{// valid in C, invalid in \CFA}$
     7510char * p = "abc"; §\C{// valid in C, deprecated in \CFA}§
     7511char * q = expr ? "abc" : "de"; §\C{// valid in C, invalid in \CFA}§
    71377512\end{cfa}
    71387513The type of a string literal is changed from ©[] char© to ©const [] char©.
     
    71417516\begin{cfa}
    71427517char * p = "abc";
    7143 p[0] = 'w'; $\C{// segment fault or change constant literal}$
     7518p[0] = 'w'; §\C{// segment fault or change constant literal}§
    71447519\end{cfa}
    71457520The same problem occurs when passing a string literal to a routine that changes its argument.
     
    71537528\item[Change:] remove \newterm{tentative definitions}, which only occurs at file scope:
    71547529\begin{cfa}
    7155 int i; $\C{// forward definition}$
    7156 int *j = ®&i®; $\C{// forward reference, valid in C, invalid in \CFA}$
    7157 int i = 0; $\C{// definition}$
     7530int i; §\C{// forward definition}§
     7531int *j = ®&i®; §\C{// forward reference, valid in C, invalid in \CFA}§
     7532int i = 0; §\C{// definition}§
    71587533\end{cfa}
    71597534is valid in C, and invalid in \CFA because duplicate overloaded object definitions at the same scope level are disallowed.
     
    71617536\begin{cfa}
    71627537struct X { int i; struct X *next; };
    7163 static struct X a; $\C{// forward definition}$
    7164 static struct X b = { 0, ®&a® };$\C{// forward reference, valid in C, invalid in \CFA}$
    7165 static struct X a = { 1, &b }; $\C{// definition}$
     7538static struct X a; §\C{// forward definition}§
     7539static struct X b = { 0, ®&a® };§\C{// forward reference, valid in C, invalid in \CFA}§
     7540static struct X a = { 1, &b }; §\C{// definition}§
    71667541\end{cfa}
    71677542\item[Rationale:] avoids having different initialization rules for builtin types and user-defined types.
     
    71787553struct Person {
    71797554        enum ®Colour® { R, G, B };      $\C[7cm]{// nested type}$
    7180         struct Face { $\C{// nested type}$
    7181                 ®Colour® Eyes, Hair; $\C{// type defined outside (1 level)}$
     7555        struct Face { §\C{// nested type}§
     7556                ®Colour® Eyes, Hair; §\C{// type defined outside (1 level)}§
    71827557        };
    7183         ®.Colour® shirt; $\C{// type defined outside (top level)}$
    7184         ®Colour® pants; $\C{// type defined same level}$
    7185         Face looks[10]; $\C{// type defined same level}$
     7558        ®.Colour® shirt; §\C{// type defined outside (top level)}§
     7559        ®Colour® pants; §\C{// type defined same level}§
     7560        Face looks[10]; §\C{// type defined same level}§
    71867561};
    7187 ®Colour® c = R; $\C{// type/enum defined same level}$
    7188 Person®.Colour® pc = Person®.®R;$\C{// type/enum defined inside}$
    7189 Person®.®Face pretty; $\C{// type defined inside}\CRT$
     7562®Colour® c = R; §\C{// type/enum defined same level}§
     7563Person®.Colour® pc = Person®.®R;§\C{// type/enum defined inside}§
     7564Person®.®Face pretty; §\C{// type defined inside}\CRT§
    71907565\end{cfa}
    71917566In C, the name of the nested types belongs to the same scope as the name of the outermost enclosing structure, \ie the nested types are hoisted to the scope of the outer-most type, which is not useful and confusing.
     
    72047579\item[Difficulty of converting:] Semantic transformation. To make the struct type name visible in the scope of the enclosing struct, the struct tag could be declared in the scope of the enclosing struct, before the enclosing struct is defined. Example:
    72057580\begin{cfa}
    7206 struct Y; $\C{// struct Y and struct X are at the same scope}$
     7581struct Y; §\C{// struct Y and struct X are at the same scope}§
    72077582struct X {
    72087583        struct Y { /* ... */ } y;
     
    72197594\begin{cfa}
    72207595void foo() {
    7221         int * b = malloc( sizeof(int) ); $\C{// implicitly convert void * to int *}$
    7222         char * c = b; $\C{// implicitly convert int * to void *, and then void * to char *}$
     7596        int * b = malloc( sizeof(int) ); §\C{// implicitly convert void * to int *}§
     7597        char * c = b; §\C{// implicitly convert int * to void *, and then void * to char *}§
    72237598}
    72247599\end{cfa}
     
    74627837Type-safe allocation is provided for all C allocation routines and new \CFA allocation routines, \eg in
    74637838\begin{cfa}
    7464 int * ip = (int *)malloc( sizeof(int) );                $\C{// C}$
    7465 int * ip = malloc();                                                    $\C{// \CFA type-safe version of C malloc}$
    7466 int * ip = alloc();                                                             $\C{// \CFA type-safe uniform alloc}$
     7839int * ip = (int *)malloc( sizeof(int) );                §\C{// C}§
     7840int * ip = malloc();                                                    §\C{// \CFA type-safe version of C malloc}§
     7841int * ip = alloc();                                                             §\C{// \CFA type-safe uniform alloc}§
    74677842\end{cfa}
    74687843the latter two allocations determine the allocation size from the type of ©p© (©int©) and cast the pointer to the allocated storage to ©int *©.
     
    74717846\begin{cfa}
    74727847struct S { int i; } __attribute__(( aligned( 128 ) )); // cache-line alignment
    7473 S * sp = malloc();                                                              $\C{// honour type alignment}$
     7848S * sp = malloc();                                                              §\C{// honour type alignment}§
    74747849\end{cfa}
    74757850the storage allocation is implicitly aligned to 128 rather than the default 16.
     
    74867861\CFA memory management extends allocation to support constructors for initialization of allocated storage, \eg in
    74877862\begin{cfa}
    7488 struct S { int i; };                                                    $\C{// cache-line alignment}$
     7863struct S { int i; };                                                    §\C{// cache-line alignment}§
    74897864void ?{}( S & s, int i ) { s.i = i; }
    74907865// assume ?|? operator for printing an S
    74917866
    7492 S & sp = *®new®( 3 );                                                   $\C{// call constructor after allocation}$
     7867S & sp = *®new®( 3 );                                                   §\C{// call constructor after allocation}§
    74937868sout | sp.i;
    74947869®delete®( &sp );
    74957870
    7496 S * spa = ®anew®( 10, 5 );                                              $\C{// allocate array and initialize each array element}$
     7871S * spa = ®anew®( 10, 5 );                                              §\C{// allocate array and initialize each array element}§
    74977872for ( i; 10 ) sout | spa[i] | nonl;
    74987873sout | nl;
     
    75337908        // $\CFA$ safe general allocation, fill, resize, alignment, array
    75347909        T * alloc( void );$\indexc{alloc}$                                      $\C[3.5in]{// variable, T size}$
    7535         T * alloc( size_t dim );                                                        $\C{// array[dim], T size elements}$
    7536         T * alloc( T ptr[], size_t dim );                                       $\C{// realloc array[dim], T size elements}$
    7537 
    7538         T * alloc_set( char fill );$\indexc{alloc_set}$         $\C{// variable, T size, fill bytes with value}$
    7539         T * alloc_set( T fill );                                                        $\C{// variable, T size, fill with value}$
    7540         T * alloc_set( size_t dim, char fill );                         $\C{// array[dim], T size elements, fill bytes with value}$
    7541         T * alloc_set( size_t dim, T fill );                            $\C{// array[dim], T size elements, fill elements with value}$
    7542         T * alloc_set( size_t dim, const T fill[] );            $\C{// array[dim], T size elements, fill elements with array}$
    7543         T * alloc_set( T ptr[], size_t dim, char fill );        $\C{// realloc array[dim], T size elements, fill bytes with value}$
    7544 
    7545         T * alloc_align( size_t align );                                        $\C{// aligned variable, T size}$
    7546         T * alloc_align( size_t align, size_t dim );            $\C{// aligned array[dim], T size elements}$
    7547         T * alloc_align( T ptr[], size_t align );                       $\C{// realloc new aligned array}$
    7548         T * alloc_align( T ptr[], size_t align, size_t dim ); $\C{// realloc new aligned array[dim]}$
    7549 
    7550         T * alloc_align_set( size_t align, char fill );         $\C{// aligned variable, T size, fill bytes with value}$
    7551         T * alloc_align_set( size_t align, T fill );            $\C{// aligned variable, T size, fill with value}$
    7552         T * alloc_align_set( size_t align, size_t dim, char fill ); $\C{// aligned array[dim], T size elements, fill bytes with value}$
    7553         T * alloc_align_set( size_t align, size_t dim, T fill ); $\C{// aligned array[dim], T size elements, fill elements with value}$
    7554         T * alloc_align_set( size_t align, size_t dim, const T fill[] ); $\C{// aligned array[dim], T size elements, fill elements with array}$
    7555         T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); $\C{// realloc new aligned array[dim], fill new bytes with value}$
     7910        T * alloc( size_t dim );                                                        §\C{// array[dim], T size elements}§
     7911        T * alloc( T ptr[], size_t dim );                                       §\C{// realloc array[dim], T size elements}§
     7912
     7913        T * alloc_set( char fill );$\indexc{alloc_set}$         §\C{// variable, T size, fill bytes with value}§
     7914        T * alloc_set( T fill );                                                        §\C{// variable, T size, fill with value}§
     7915        T * alloc_set( size_t dim, char fill );                         §\C{// array[dim], T size elements, fill bytes with value}§
     7916        T * alloc_set( size_t dim, T fill );                            §\C{// array[dim], T size elements, fill elements with value}§
     7917        T * alloc_set( size_t dim, const T fill[] );            §\C{// array[dim], T size elements, fill elements with array}§
     7918        T * alloc_set( T ptr[], size_t dim, char fill );        §\C{// realloc array[dim], T size elements, fill bytes with value}§
     7919
     7920        T * alloc_align( size_t align );                                        §\C{// aligned variable, T size}§
     7921        T * alloc_align( size_t align, size_t dim );            §\C{// aligned array[dim], T size elements}§
     7922        T * alloc_align( T ptr[], size_t align );                       §\C{// realloc new aligned array}§
     7923        T * alloc_align( T ptr[], size_t align, size_t dim ); §\C{// realloc new aligned array[dim]}§
     7924
     7925        T * alloc_align_set( size_t align, char fill );         §\C{// aligned variable, T size, fill bytes with value}§
     7926        T * alloc_align_set( size_t align, T fill );            §\C{// aligned variable, T size, fill with value}§
     7927        T * alloc_align_set( size_t align, size_t dim, char fill ); §\C{// aligned array[dim], T size elements, fill bytes with value}§
     7928        T * alloc_align_set( size_t align, size_t dim, T fill ); §\C{// aligned array[dim], T size elements, fill elements with value}§
     7929        T * alloc_align_set( size_t align, size_t dim, const T fill[] ); §\C{// aligned array[dim], T size elements, fill elements with array}§
     7930        T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); §\C{// realloc new aligned array[dim], fill new bytes with value}§
    75567931
    75577932        // $\CFA$ safe initialization/copy, i.e., implicit size specification
     
    76147989\leavevmode
    76157990\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    7616 forall( T | { int ?<?( T, T ); } ) $\C{// location}$
     7991forall( T | { int ?<?( T, T ); } ) §\C{// location}§
    76177992T * bsearch( T key, const T * arr, size_t dim );$\indexc{bsearch}$
    76187993
    7619 forall( T | { int ?<?( T, T ); } ) $\C{// position}$
     7994forall( T | { int ?<?( T, T ); } ) §\C{// position}§
    76207995unsigned int bsearch( T key, const T * arr, size_t dim );
    76217996
     
    76247999
    76258000forall( E | { int ?<?( E, E ); } ) {
    7626         E * bsearch( E key, const E * vals, size_t dim );$\indexc{bsearch}$ $\C{// location}$
    7627         size_t bsearch( E key, const E * vals, size_t dim );$\C{// position}$
     8001        E * bsearch( E key, const E * vals, size_t dim );$\indexc{bsearch}$ §\C{// location}§
     8002        size_t bsearch( E key, const E * vals, size_t dim );§\C{// position}§
    76288003        E * bsearchl( E key, const E * vals, size_t dim );$\indexc{bsearchl}$
    76298004        size_t bsearchl( E key, const E * vals, size_t dim );
     
    76728047void srandom( unsigned int seed );$\indexc{srandom}$
    76738048char random( void );$\indexc{random}$
    7674 char random( char u ); $\C{// [0,u)}$
    7675 char random( char l, char u ); $\C{// [l,u]}$
     8049char random( char u ); §\C{// [0,u)}§
     8050char random( char l, char u ); §\C{// [l,u]}§
    76768051int random( void );
    7677 int random( int u ); $\C{// [0,u)}$
    7678 int random( int l, int u ); $\C{// [l,u]}$
     8052int random( int u ); §\C{// [0,u)}§
     8053int random( int l, int u ); §\C{// [l,u]}§
    76798054unsigned int random( void );
    7680 unsigned int random( unsigned int u ); $\C{// [0,u)}$
    7681 unsigned int random( unsigned int l, unsigned int u ); $\C{// [l,u]}$
     8055unsigned int random( unsigned int u ); §\C{// [0,u)}§
     8056unsigned int random( unsigned int l, unsigned int u ); §\C{// [l,u]}§
    76828057long int random( void );
    7683 long int random( long int u ); $\C{// [0,u)}$
    7684 long int random( long int l, long int u ); $\C{// [l,u]}$
     8058long int random( long int u ); §\C{// [0,u)}§
     8059long int random( long int l, long int u ); §\C{// [l,u]}§
    76858060unsigned long int random( void );
    7686 unsigned long int random( unsigned long int u ); $\C{// [0,u)}$
    7687 unsigned long int random( unsigned long int l, unsigned long int u ); $\C{// [l,u]}$
    7688 float random( void );                                            $\C{// [0.0, 1.0)}$
    7689 double random( void );                                           $\C{// [0.0, 1.0)}$
    7690 float _Complex random( void );                           $\C{// [0.0, 1.0)+[0.0, 1.0)i}$
    7691 double _Complex random( void );                          $\C{// [0.0, 1.0)+[0.0, 1.0)i}$
    7692 long double _Complex random( void );             $\C{// [0.0, 1.0)+[0.0, 1.0)i}$
     8061unsigned long int random( unsigned long int u ); §\C{// [0,u)}§
     8062unsigned long int random( unsigned long int l, unsigned long int u ); §\C{// [l,u]}§
     8063float random( void );                                            §\C{// [0.0, 1.0)}§
     8064double random( void );                                           §\C{// [0.0, 1.0)}§
     8065float _Complex random( void );                           §\C{// [0.0, 1.0)+[0.0, 1.0)i}§
     8066double _Complex random( void );                          §\C{// [0.0, 1.0)+[0.0, 1.0)i}§
     8067long double _Complex random( void );             §\C{// [0.0, 1.0)+[0.0, 1.0)i}§
    76938068\end{cfa}
    76948069
     
    78898264long double atan2( long double, long double );
    78908265
    7891 float atan( float, float ); $\C{// alternative name for atan2}$
     8266float atan( float, float ); §\C{// alternative name for atan2}§
    78928267double atan( double, double );$\indexc{atan}$
    78938268long double atan( long double, long double );
     
    81168491\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    81178492struct Duration {
    8118         int64_t tn; $\C{// nanoseconds}$
     8493        int64_t tn; §\C{// nanoseconds}§
    81198494};
    81208495
     
    82618636\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    82628637struct Time {
    8263         uint64_t tn; $\C{// nanoseconds since UNIX epoch}$
     8638        uint64_t tn; §\C{// nanoseconds since UNIX epoch}§
    82648639};
    82658640
     
    83268701\leavevmode
    83278702\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    8328 struct Clock { $\C{// virtual clock}$
    8329         Duration offset; $\C{// offset from computer real-time}$
     8703struct Clock { §\C{// virtual clock}§
     8704        Duration offset; §\C{// offset from computer real-time}§
    83308705};
    83318706
    8332 void ?{}( Clock & clk ); $\C{// create no offset}$
    8333 void ?{}( Clock & clk, Duration adj ); $\C{// create with offset}$
    8334 void reset( Clock & clk, Duration adj ); $\C{// change offset}$
    8335 
    8336 Duration resolutionHi(); $\C{// clock resolution in nanoseconds (fine)}$
    8337 Duration resolution(); $\C{// clock resolution without nanoseconds (coarse)}$
    8338 
    8339 Time timeHiRes(); $\C{// real time with nanoseconds}$
    8340 Time time(); $\C{// real time without nanoseconds}$
    8341 Time time( Clock & clk ); $\C{// real time for given clock}$
    8342 Time ?()( Clock & clk ); $\C{//\ \ \ \ alternative syntax}$
    8343 timeval time( Clock & clk ); $\C{// convert to C time format}$
     8707void ?{}( Clock & clk ); §\C{// create no offset}§
     8708void ?{}( Clock & clk, Duration adj ); §\C{// create with offset}§
     8709void reset( Clock & clk, Duration adj ); §\C{// change offset}§
     8710
     8711Duration resolutionHi(); §\C{// clock resolution in nanoseconds (fine)}§
     8712Duration resolution(); §\C{// clock resolution without nanoseconds (coarse)}§
     8713
     8714Time timeHiRes(); §\C{// real time with nanoseconds}§
     8715Time time(); §\C{// real time without nanoseconds}§
     8716Time time( Clock & clk ); §\C{// real time for given clock}§
     8717Time ?()( Clock & clk ); §\C{//\ \ \ \ alternative syntax}§
     8718timeval time( Clock & clk ); §\C{// convert to C time format}§
    83448719tm time( Clock & clk );
    8345 Duration processor(); $\C{// non-monotonic duration of kernel thread}$
    8346 Duration program(); $\C{// non-monotonic duration of program CPU}$
    8347 Duration boot(); $\C{// monotonic duration since computer boot}$
     8720Duration processor(); §\C{// non-monotonic duration of kernel thread}§
     8721Duration program(); §\C{// non-monotonic duration of program CPU}§
     8722Duration boot(); §\C{// monotonic duration since computer boot}§
    83488723\end{cfa}
    83498724
     
    83868761\begin{cfa}
    83878762struct PRNG { ... }; $\C[3.75in]{// opaque type}$
    8388 void ?{}( PRNG & prng ); $\C{// random seed}$
    8389 void ?{}( PRNG & prng, uint32_t seed ); $\C{// fixed seed}$
    8390 void set_seed( PRNG & prng, uint32_t seed ); $\C{// set seed}$
    8391 uint32_t get_seed( PRNG & prng ); $\C{// get seed}$
    8392 uint32_t prng( PRNG & prng ); $\C{// [0,UINT\_MAX]}$
    8393 uint32_t prng( PRNG & prng, uint32_t u ); $\C{// [0,u)}$
    8394 uint32_t prng( PRNG & prng, uint32_t l, uint32_t u ); $\C{// [l,u]}$
    8395 uint32_t calls( PRNG & prng ); $\C{// number of calls}\CRT$
     8763void ?{}( PRNG & prng ); §\C{// random seed}§
     8764void ?{}( PRNG & prng, uint32_t seed ); §\C{// fixed seed}§
     8765void set_seed( PRNG & prng, uint32_t seed ); §\C{// set seed}§
     8766uint32_t get_seed( PRNG & prng ); §\C{// get seed}§
     8767uint32_t prng( PRNG & prng ); §\C{// [0,UINT\_MAX]}§
     8768uint32_t prng( PRNG & prng, uint32_t u ); §\C{// [0,u)}§
     8769uint32_t prng( PRNG & prng, uint32_t l, uint32_t u ); §\C{// [l,u]}§
     8770uint32_t calls( PRNG & prng ); §\C{// number of calls}\CRT§
    83968771\end{cfa}
    83978772A ©PRNG© object is used to randomize behaviour or values during execution, \eg in games, a character makes a random move or an object takes on a random value.
     
    84478822\begin{cfa}
    84488823void set_seed( uint32_t seed ); $\C[3.75in]{// set global seed}$
    8449 uint32_t get_seed(); $\C{// get global seed}$
     8824uint32_t get_seed(); §\C{// get global seed}§
    84508825// SLOWER
    8451 uint32_t prng(); $\C{// [0,UINT\_MAX]}$
    8452 uint32_t prng( uint32_t u ); $\C{// [0,u)}$
    8453 uint32_t prng( uint32_t l, uint32_t u ); $\C{// [l,u]}$
     8826uint32_t prng(); §\C{// [0,UINT\_MAX]}§
     8827uint32_t prng( uint32_t u ); §\C{// [0,u)}§
     8828uint32_t prng( uint32_t l, uint32_t u ); §\C{// [l,u]}§
    84548829// FASTER
    8455 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th );     $\C{// [0,UINT\_MAX]}$
    8456 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t u ); $\C{// [0,u)}$
    8457 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t l, uint32_t u );     $\C{// [l,u]}\CRT$
     8830uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th );     §\C{// [0,UINT\_MAX]}§
     8831uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t u ); §\C{// [0,u)}§
     8832uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t l, uint32_t u );     §\C{// [l,u]}\CRT§
    84588833\end{cfa}
    84598834The only difference between the two sets of ©prng© routines is performance.
     
    85368911
    85378912\begin{cfa}
    8538 void ?{}( Int * this ); $\C{// constructor/destructor}$
     8913void ?{}( Int * this ); §\C{// constructor/destructor}§
    85398914void ?{}( Int * this, Int init );
    85408915void ?{}( Int * this, zero_t );
     
    85458920void ^?{}( Int * this );
    85468921
    8547 Int ?=?( Int * lhs, Int rhs ); $\C{// assignment}$
     8922Int ?=?( Int * lhs, Int rhs ); §\C{// assignment}§
    85488923Int ?=?( Int * lhs, long int rhs );
    85498924Int ?=?( Int * lhs, unsigned long int rhs );
     
    85628937unsigned long int narrow( Int val );
    85638938
    8564 int ?==?( Int oper1, Int oper2 ); $\C{// comparison}$
     8939int ?==?( Int oper1, Int oper2 ); §\C{// comparison}§
    85658940int ?==?( Int oper1, long int oper2 );
    85668941int ?==?( long int oper2, Int oper1 );
     
    85988973int ?>=?( unsigned long int oper1, Int oper2 );
    85998974
    8600 Int +?( Int oper ); $\C{// arithmetic}$
     8975Int +?( Int oper ); §\C{// arithmetic}§
    86018976Int -?( Int oper );
    86028977Int ~?( Int oper );
     
    86809055Int ?>>=?( Int * lhs, mp_bitcnt_t shift );
    86819056
    8682 Int abs( Int oper ); $\C{// number functions}$
     9057Int abs( Int oper ); §\C{// number functions}§
    86839058Int fact( unsigned long int N );
    86849059Int gcd( Int oper1, Int oper2 );
     
    86929067Int sqrt( Int oper );
    86939068
    8694 forall( dtype istype | istream( istype ) ) istype * ?|?( istype * is, Int * mp );  $\C{// I/O}$
     9069forall( dtype istype | istream( istype ) ) istype * ?|?( istype * is, Int * mp );  §\C{// I/O}§
    86959070forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype * os, Int mp );
    86969071\end{cfa}
     
    87919166// implementation
    87929167struct Rational {$\indexc{Rational}$
    8793         long int numerator, denominator; $\C{// invariant: denominator > 0}$
     9168        long int numerator, denominator; §\C{// invariant: denominator > 0}§
    87949169}; // Rational
    87959170
    8796 Rational rational(); $\C{// constructors}$
     9171Rational rational(); §\C{// constructors}§
    87979172Rational rational( long int n );
    87989173Rational rational( long int n, long int d );
     
    88009175void ?{}( Rational * r, one_t );
    88019176
    8802 long int numerator( Rational r ); $\C{// numerator/denominator getter/setter}$
     9177long int numerator( Rational r ); §\C{// numerator/denominator getter/setter}§
    88039178long int numerator( Rational r, long int n );
    88049179long int denominator( Rational r );
    88059180long int denominator( Rational r, long int d );
    88069181
    8807 int ?==?( Rational l, Rational r ); $\C{// comparison}$
     9182int ?==?( Rational l, Rational r ); §\C{// comparison}§
    88089183int ?!=?( Rational l, Rational r );
    88099184int ?<?( Rational l, Rational r );
     
    88129187int ?>=?( Rational l, Rational r );
    88139188
    8814 Rational -?( Rational r ); $\C{// arithmetic}$
     9189Rational -?( Rational r ); §\C{// arithmetic}§
    88159190Rational ?+?( Rational l, Rational r );
    88169191Rational ?-?( Rational l, Rational r );
     
    88189193Rational ?/?( Rational l, Rational r );
    88199194
    8820 double widen( Rational r ); $\C{// conversion}$
     9195double widen( Rational r ); §\C{// conversion}§
    88219196Rational narrow( double f, long int md );
    88229197
  • libcfa/src/Makefile.am

    r59c8dff rf988834  
    4848        math.trait.hfa \
    4949        math.hfa \
     50        raii.hfa \
    5051        time_t.hfa \
    5152        virtual_dtor.hfa \
  • libcfa/src/collections/array.hfa

    r59c8dff rf988834  
    131131
    132132    static inline void __taglen( tag(arpk(N, S, Timmed, Tbase)), tag(N) ) {}
    133 
    134     // workaround #226 (and array relevance thereof demonstrated in mike102/otype-slow-ndims.cfa)
    135     static inline void ?{}( arpk(N, S, Timmed, Tbase) & this ) {
    136         void ?{}( S (&inner)[N] ) {}
    137         ?{}(this.strides);
    138     }
    139     static inline void ^?{}( arpk(N, S, Timmed, Tbase) & this ) {
    140         void ^?{}( S (&inner)[N] ) {}
    141         ^?{}(this.strides);
     133}
     134
     135// RAII pattern has workarounds for
     136//  - Trac 226:  Simplest handling would be, require immediate element to be otype, let autogen
     137//    raii happen.  Performance on even a couple dimensions is unacceptable because of exponential
     138//    thunk creation: ?{}() needs all four otype funcs from next level, so does ^?{}(), so do the
     139//    other two.  This solution offers ?{}() that needs only ?{}(), and similar for ^?{}.
     140
     141forall( [N], S & | sized(S), Timmed &, Tbase & | { void ?{}( Timmed & ); } )
     142static inline void ?{}( arpk(N, S, Timmed, Tbase) & this ) {   
     143    void ?{}( S (&)[N] ) {}
     144    ?{}(this.strides);
     145
     146    for (i; N) ?{}( (Timmed &) this.strides[i] );
     147}
     148
     149forall( [N], S & | sized(S), Timmed &, Tbase & | { void ^?{}( Timmed & ); } )
     150static inline void ^?{}( arpk(N, S, Timmed, Tbase) & this ) {
     151    void ^?{}( S (&)[N] ) {}
     152    ^?{}(this.strides);
     153
     154    for (i; N ) {
     155        ^?{}( (Timmed &) this.strides[N-i-1] );
    142156    }
    143157}
     
    147161//
    148162
    149 forall( Te )
     163forall( Te * )
    150164static inline Te mkar_( tag(Te) ) {}
    151165
  • libcfa/src/collections/string.cfa

    r59c8dff rf988834  
    1010// Created On       : Fri Sep 03 11:00:00 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Oct 18 21:52:09 2023
    13 // Update Count     : 208
     12// Last Modified On : Sun Jan 14 12:03:47 2024
     13// Update Count     : 240
    1414//
    1515
     
    2929// string RAII
    3030
    31 
    32 void ?{}( string & this ) {
    33     (this.inner) { malloc() };
    34     ?{}( *this.inner );
    35 }
    36 
    3731// private (not in header)
    38 static void ?{}( string & this, string_res & src, size_t start, size_t end ) {
    39     (this.inner) { malloc() };
    40     ?{}( *this.inner, src, SHARE_EDITS, start, end );
    41 }
    42 
    43 void ?{}( string & this, const string & other ) {
    44     (this.inner) { malloc() };
    45     ?{}( *this.inner, *other.inner, COPY_VALUE );
    46 }
    47 
    48 void ?{}( string & this, string & other ) {
    49     ?{}( this, (const string &) other );
    50 }
    51 
    52 void ?{}( string & this, const char * val ) {
    53     (this.inner) { malloc() };
    54     ?{}( *this.inner, val );
    55 }
    56 
    57 void ?{}( string & this, const char * buffer, size_t bsize) {
    58     (this.inner) { malloc() };
    59     ?{}( *this.inner, buffer, bsize );
    60 }
    61 
    62 void ^?{}( string & this ) {
    63     ^(*this.inner){};
    64     free( this.inner );
    65     this.inner = 0p;
     32static void ?{}( string & s, string_res & src, size_t start, size_t len ) {
     33    (s.inner) { malloc() };
     34    ?{}( *s.inner, src, SHARE_EDITS, start, len );
     35}
     36
     37void ?{}( string & s ) {
     38    (s.inner) { malloc() };
     39    ?{}( *s.inner );
     40}
     41
     42void ?{}( string & s, const string & c ) {
     43    (s.inner) { malloc() };
     44    ?{}( *s.inner, *c.inner, COPY_VALUE );
     45}
     46
     47void ?{}( string & s, const string & s2, size_t maxlen) {
     48    (s.inner) { malloc() };
     49    ?{}( *s.inner, *s2.inner, COPY_VALUE, maxlen );
     50}
     51
     52
     53void ?{}( string & s, string & c ) {
     54    ?{}( s, (const string &) c );
     55}
     56
     57void ?{}( string & s, const char c ) {
     58    (s.inner) { malloc() };
     59    ?{}( *s.inner, c );
     60}
     61
     62void ?{}( string & s, const char * c ) {
     63    (s.inner) { malloc() };
     64    ?{}( *s.inner, c );
     65}
     66
     67void ?{}( string & s, const char * c, size_t size) {
     68    (s.inner) { malloc() };
     69    ?{}( *s.inner, c, size );
     70}
     71
     72void ^?{}( string & s ) {
     73    ^(*s.inner){};
     74    free( s.inner );
     75    s.inner = 0p;
    6676}
    6777
     
    6979// Alternate construction: request shared edits
    7080
    71 string_WithSharedEdits ?`shareEdits( string & this ) {
    72     string_WithSharedEdits ret = { &this };
    73     return ret;
    74 }
    75 
    76 void ?{}( string & this, string_WithSharedEdits src ) {
    77     ?{}( this, *src.s->inner, 0, src.s->inner->Handle.lnth);
     81string_WithSharedEdits ?`shareEdits( string & s ) {
     82    string_WithSharedEdits ret = { &s };
     83    return ret;
     84}
     85
     86void ?{}( string & s, string_WithSharedEdits src ) {
     87    ?{}( s, *src.s->inner, 0, src.s->inner->Handle.lnth);
    7888}
    7989
     
    8191// Assignment
    8292
    83 void ?=?( string & this, const char * val ) {
    84     (*this.inner) = val;
    85 }
    86 
    87 void ?=?(string & this, const string & other) {
    88     (*this.inner) = (*other.inner);
    89 }
    90 
    91 void ?=?( string & this, char val ) {
    92     (*this.inner) = val;
    93 }
    94 
    95 string & ?=?(string & this, string & other) { //// <---- straw man change
    96     (*this.inner) = (*other.inner);
    97     return this;
     93void ?=?( string & s, const char * val ) {
     94    (*s.inner) = val;
     95}
     96
     97// with and without const on "other" argument helps keep prevent autogen ?=? calls
     98void ?=?(string & s, const string & c) {
     99    (*s.inner) = (*c.inner);
     100}
     101string & ?=?(string & s, string & c) {
     102    (*s.inner) = (*c.inner);
     103    return s;
     104}
     105
     106void ?=?( string & s, char val ) {
     107    (*s.inner) = val;
     108}
     109
     110void assign(string & s, const string & c, size_t n) {
     111    assign(*s.inner, *c.inner, n);
     112}
     113void assign(string & s, const char * c, size_t n) {
     114    assign(*s.inner, c, n);
    98115}
    99116
     
    102119// Input-Output
    103120
    104 ofstream & ?|?( ofstream & out, const string & this ) {
    105     return out | (*this.inner); // print internal string_res
    106 }
    107 
    108 void ?|?( ofstream & out, const string & this ) {
    109     (ofstream &)(out | (*this.inner)); ends( out );
     121ofstream & ?|?( ofstream & out, const string & s ) {
     122    return out | (*s.inner); // print internal string_res
     123}
     124
     125void ?|?( ofstream & out, const string & s ) {
     126    (ofstream &)(out | (*s.inner)); ends( out );
    110127}
    111128
     
    124141}
    125142
    126 ifstream & ?|?(ifstream & in, string & this) {
    127     return in | (*this.inner); // read to internal string_res
    128 }
    129 
    130 void ?|?( ifstream & in, string & this ) {
    131     in | (*this.inner);
     143ifstream & ?|?(ifstream & in, string & s) {
     144    return in | (*s.inner); // read to internal string_res
     145}
     146
     147void ?|?( ifstream & in, string & s ) {
     148    in | (*s.inner);
    132149}
    133150
     
    144161// Slicing
    145162
    146 string ?()( string & this, size_t start, size_t end ) {
    147     string ret = { *this.inner, start, end };
     163string ?()( string & s, size_t start, size_t len ) {
     164    string ret = { *s.inner, start, len };
    148165    return ret`shareEdits;
    149166}
    150167
    151 string ?()( string & this, size_t start ) {
    152     string ret = { *this.inner, start, size( this ) };
     168string ?()( string & s, size_t start ) {
     169    string ret = { *s.inner, start, size( s ) - start };
    153170    return ret`shareEdits;
    154171}
     
    157174// Comparison
    158175
    159 int  cmp (const string &s1, const string &s2) { return cmp(*s1.inner , *s2.inner); }
    160 bool ?==?(const string &s1, const string &s2) { return     *s1.inner == *s2.inner ; }
    161 bool ?!=?(const string &s1, const string &s2) { return     *s1.inner != *s2.inner ; }
    162 bool ?>? (const string &s1, const string &s2) { return     *s1.inner >  *s2.inner ; }
    163 bool ?>=?(const string &s1, const string &s2) { return     *s1.inner >= *s2.inner ; }
    164 bool ?<=?(const string &s1, const string &s2) { return     *s1.inner <= *s2.inner ; }
    165 bool ?<? (const string &s1, const string &s2) { return     *s1.inner <  *s2.inner ; }
    166 
    167 int  cmp (const string &s1, const char*   s2) { return cmp(*s1.inner ,   s2      ); }
    168 bool ?==?(const string &s1, const char*   s2) { return     *s1.inner ==  s2       ; }
    169 bool ?!=?(const string &s1, const char*   s2) { return     *s1.inner !=  s2       ; }
    170 bool ?>? (const string &s1, const char*   s2) { return     *s1.inner >   s2       ; }
    171 bool ?>=?(const string &s1, const char*   s2) { return     *s1.inner >=  s2       ; }
    172 bool ?<=?(const string &s1, const char*   s2) { return     *s1.inner <=  s2       ; }
    173 bool ?<? (const string &s1, const char*   s2) { return     *s1.inner <   s2       ; }
    174 
    175 int  cmp (const char*   s1, const string &s2) { return cmp( s1       , *s2.inner); }
    176 bool ?==?(const char*   s1, const string &s2) { return      s1       == *s2.inner ; }
    177 bool ?!=?(const char*   s1, const string &s2) { return      s1       != *s2.inner ; }
    178 bool ?>? (const char*   s1, const string &s2) { return      s1       >  *s2.inner ; }
    179 bool ?>=?(const char*   s1, const string &s2) { return      s1       >= *s2.inner ; }
    180 bool ?<=?(const char*   s1, const string &s2) { return      s1       <= *s2.inner ; }
    181 bool ?<? (const char*   s1, const string &s2) { return      s1       <  *s2.inner ; }
     176int  strcmp(const string & s1, const string & s2) { return strcmp(*s1.inner, *s2.inner); }
     177bool ?==?(const string & s1, const string & s2) { return *s1.inner == *s2.inner; }
     178bool ?!=?(const string & s1, const string & s2) { return *s1.inner != *s2.inner; }
     179bool ?>? (const string & s1, const string & s2) { return *s1.inner >  *s2.inner; }
     180bool ?>=?(const string & s1, const string & s2) { return *s1.inner >= *s2.inner; }
     181bool ?<=?(const string & s1, const string & s2) { return *s1.inner <= *s2.inner; }
     182bool ?<? (const string & s1, const string & s2) { return *s1.inner <  *s2.inner; }
     183
     184int  strcmp(const string & s1, const char * s2) { return strcmp(*s1.inner, s2 ); }
     185bool ?==?(const string & s1, const char * s2) { return *s1.inner == s2; }
     186bool ?!=?(const string & s1, const char * s2) { return *s1.inner != s2; }
     187bool ?>? (const string & s1, const char * s2) { return *s1.inner >  s2; }
     188bool ?>=?(const string & s1, const char * s2) { return *s1.inner >= s2; }
     189bool ?<=?(const string & s1, const char * s2) { return *s1.inner <= s2; }
     190bool ?<? (const string & s1, const char * s2) { return *s1.inner <  s2; }
     191
     192int  strcmp(const char * s1, const string & s2) { return strcmp( s1, *s2.inner); }
     193bool ?==?(const char * s1, const string & s2) { return s1 == *s2.inner; }
     194bool ?!=?(const char * s1, const string & s2) { return s1 != *s2.inner; }
     195bool ?>? (const char * s1, const string & s2) { return s1 >  *s2.inner; }
     196bool ?>=?(const char * s1, const string & s2) { return s1 >= *s2.inner; }
     197bool ?<=?(const char * s1, const string & s2) { return s1 <= *s2.inner; }
     198bool ?<? (const char * s1, const string & s2) { return s1 <  *s2.inner; }
    182199
    183200
     
    186203
    187204size_t size(const string & s) {
    188     return size( * s.inner );
     205    return size( *s.inner );
    189206}
    190207
     
    192209// Concatenation
    193210
    194 void ?+=?(string & s, char other) {
    195     (*s.inner) += other;
     211void ?+=?(string & s, char c) {
     212    (*s.inner) += c;
    196213}
    197214
     
    200217}
    201218
    202 void ?+=?(string & s, const char * other) {
    203     (*s.inner) += other;
    204 }
    205 
    206 string ?+?(const string & s, char other) {
     219void append(string & s, const string & s2, size_t maxlen) {
     220    append( (*s.inner), (*s2.inner), maxlen );
     221}
     222
     223void ?+=?(string & s, const char * c) {
     224    (*s.inner) += c;
     225}
     226
     227void append(string & s, const char * buffer, size_t bsize) {
     228    append( (*s.inner), buffer, bsize );
     229}
     230
     231string ?+?(const string & s, char c) {
    207232    string ret = s;
    208     ret += other;
     233    ret += c;
    209234    return ret;
    210235}
     
    222247}
    223248
    224 string ?+?(const string & s, const char * other) {
     249string ?+?(const string & s, const char * c) {
    225250    string ret = s;
    226     ret += other;
     251    ret += c;
    227252    return ret;
    228253}
     
    231256// Repetition
    232257
     258void ?*=?(string & s, size_t factor) {
     259    (*s.inner) *= factor;
     260}
     261
    233262string ?*?(const string & s, size_t factor) {
    234     string ret = "";
    235     for (factor) ret += s;
    236     return ret;
    237 }
    238 
    239 string ?*?(char c, size_t size) {
    240     string ret = "";
    241     for ((size_t)size) ret += c;
    242     return ret;
    243 }
    244 
    245 string ?*?(const char *s, size_t factor) {
    246     string ss = s;
    247     return ss * factor;
     263    string ret = s;
     264    ret *= factor;
     265    return ret;
     266}
     267
     268string ?*?(char c, size_t factor) {
     269    string ret = c;
     270    ret *= factor;
     271    return ret;
     272}
     273
     274string ?*?(const char * s, size_t factor) {
     275    string ret = s;
     276    ret *= factor;
     277    return ret;
    248278}
    249279
     
    256286
    257287string ?[?](string & s, size_t index) {
    258     string ret = { *s.inner, index, index + 1 };
     288    string ret = { *s.inner, index, 1 };
    259289    return ret`shareEdits;
    260290}
     
    339369// charclass, include, exclude
    340370
    341 void ?{}( charclass & this, const string & chars) {
    342     (this.inner) { malloc() };
    343     ?{}( *this.inner, *(const string_res *)chars.inner );
    344 }
    345 
    346 void ?{}( charclass & this, const char * chars ) {
    347     (this.inner) { malloc() };
    348     ?{}( *this.inner, chars );
    349 }
    350 
    351 void ?{}( charclass & this, const char * chars, size_t charssize ) {
    352     (this.inner) { malloc() };
    353     ?{}( *this.inner, chars, charssize );
    354 }
    355 
    356 void ^?{}( charclass & this ) {
    357     ^(*this.inner){};
    358     free( this.inner );
    359     this.inner = 0p;
     371void ?{}( charclass & s, const string & chars) {
     372    (s.inner) { malloc() };
     373    ?{}( *s.inner, *(const string_res *)chars.inner );
     374}
     375
     376void ?{}( charclass & s, const char * chars ) {
     377    (s.inner) { malloc() };
     378    ?{}( *s.inner, chars );
     379}
     380
     381void ?{}( charclass & s, const char * chars, size_t charssize ) {
     382    (s.inner) { malloc() };
     383    ?{}( *s.inner, chars, charssize );
     384}
     385
     386void ^?{}( charclass & s ) {
     387    ^(*s.inner){};
     388    free( s.inner );
     389    s.inner = 0p;
    360390}
    361391
  • libcfa/src/collections/string.hfa

    r59c8dff rf988834  
    1010// Created On       : Fri Sep 03 11:00:00 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Sep  2 11:26:28 2023
    13 // Update Count     : 55
     12// Last Modified On : Sun Jan 14 12:03:46 2024
     13// Update Count     : 81
    1414//
    1515
     
    2929// Getters
    3030size_t size(const string & s);
     31static inline size_t strlen(const string & s) { return size( s ); }
    3132
    3233// RAII, assignment
    33 void ?{}(string & this); // empty string
    34 void ?{}(string & s, const char * initial); // copy from string literal (NULL-terminated)
    35 void ?{}(string & s, const char * buffer, size_t bsize); // copy specific length from buffer
    36 
     34void ?{}(string & s); // empty string
    3735void ?{}(string & s, const string & s2);
     36void ?{}(string & s, const string & s2, size_t maxlen);
    3837void ?{}(string & s, string & s2);
    3938
    40 void ?=?(string & s, const char * other); // copy assignment from literal
    41 void ?=?(string & s, const string & other);
    42 void ?=?(string & s, char other);
    43 string & ?=?(string & s, string & other);  // surprising ret seems to help avoid calls to autogen
     39void ?{}(string & s, char);
     40void ?{}(string & s, const char * c); // copy from string literal (NULL-terminated)
     41void ?{}(string & s, const char * c, size_t size); // copy specific length from buffer
     42
     43void ?=?(string & s, const char * c); // copy assignment from literal
     44void ?=?(string & s, const string & c);
     45void ?=?(string & s, char c);
     46string & ?=?(string & s, string & c);  // surprising ret seems to help avoid calls to autogen
     47void assign(string & s, const string & c, size_t n);
     48void assign(string & s, const char * c, size_t n);
    4449//string ?=?( string &, string ) = void;
     50
     51static inline string & strcpy(string & s, const char * c) { s = c; return s; }
     52static inline string & strncpy(string & s, const char * c, size_t n) { assign( s, c, n); return s; }
     53static inline string & strcpy(string & s, const string & c) { s = c; return s; }
     54static inline string & strncpy(string & s, const string & c, size_t n) { assign(s, c, n); return s; }
     55
    4556void ^?{}(string & s);
    4657
     
    4960    string * s;
    5061};
    51 string_WithSharedEdits ?`shareEdits( string & this );
    52 void ?{}( string & this, string_WithSharedEdits src );
     62string_WithSharedEdits ?`shareEdits( string & s );
     63void ?{}( string & s, string_WithSharedEdits src );
    5364
    5465// IO Operator
     
    5667void ?|?(ofstream & out, const string & s);
    5768ifstream & ?|?(ifstream & in, string & s);
    58 void ?|?( ifstream & in, string & this );
     69void ?|?( ifstream & in, string & s );
    5970
    6071static inline {
     
    8192        _Istream_Sstr wdi( unsigned int rwd, string & s ) { return (_Istream_Sstr)@{ s, {{0p}, rwd, {.flags.rwd : true}} }; }
    8293        _Istream_Sstr getline( string & s, const char delimiter = '\n' ) {
    83                 return (_Istream_Sstr)@{ s, {{.delimiter : { delimiter, '\0' } }, -1, {.flags.delimiter : true, .flags.inex : true}} };
     94                return (_Istream_Sstr)@{ s, {{.delimiters : { delimiter, '\0' } }, -1, {.flags.delimiter : true, .flags.inex : true}} };
    8495        }
    8596        _Istream_Sstr & getline( _Istream_Sstr & fmt, const char delimiter = '\n' ) {
    86                 fmt.delimiter[0] = delimiter; fmt.delimiter[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt;
     97                fmt.delimiters[0] = delimiter; fmt.delimiters[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt;
    8798        }
    8899        _Istream_Sstr incl( const char scanset[], string & s ) { return (_Istream_Sstr)@{ s, {{scanset}, -1, {.flags.inex : false}} }; }
     
    97108
    98109// Concatenation
    99 void ?+=?(string & s, char other); // append a character
     110void ?+=?(string & s, char c); // append a character
    100111void ?+=?(string & s, const string & s2); // append-concatenate to first string
    101 void ?+=?(string & s, const char * other); // append-concatenate to first string
    102 string ?+?(const string & s, char other); // add a character to a copy of the string
     112void append(string & s, const string & s2, size_t maxlen);  // append-concatenate to first string, up to maxlen
     113void ?+=?(string & s, const char * s2); // append-concatenate NULL-terminated string to first string
     114void append(string & s, const char * buffer, size_t bsize);  // append-concatenate given range to first string
     115
     116string ?+?(const string & s, char c); // add a character to a copy of the string
    103117string ?+?(const string & s, const string & s2); // copy and concatenate both strings
    104 string ?+?(const char * s1, const char * s2); // concatenate both strings
    105 string ?+?(const string & s, const char * other); // copy and concatenate with NULL-terminated string
     118string ?+?(const char * s1, const char * s2); // copy and concatenate both strings
     119string ?+?(const string & s, const char * c); // copy and concatenate with NULL-terminated string
     120
     121static inline string & strcat(string & s, const string & s2) { s += s2; return s; }
     122static inline string & strcat(string & s, const char * c) { s += c; return s; }
     123static inline string & strncat(string & s, const string & s2, size_t maxlen) { append(s, s2, maxlen); return s; }
     124static inline string & strncat(string & s, const char * buffer, size_t bsize) { append(s, buffer, bsize); return s; }
    106125
    107126// Repetition
    108127string ?*?(const string & s, size_t factor);
    109 string ?*?(char c, size_t size);
    110 string ?*?(const char *s, size_t size);
     128void ?*=?(string & s, size_t factor);
     129string ?*?(char c, size_t factor);
     130string ?*?(const char *s, size_t factor);
    111131
    112132// Character access
     
    116136
    117137// Comparisons
    118 int  cmp (const string &, const string &);
     138int  strcmp (const string &, const string &);
    119139bool ?==?(const string &, const string &);
    120140bool ?!=?(const string &, const string &);
     
    124144bool ?<? (const string &, const string &);
    125145
    126 int  cmp (const string &, const char*);
    127 bool ?==?(const string &, const char*);
    128 bool ?!=?(const string &, const char*);
    129 bool ?>? (const string &, const char*);
    130 bool ?>=?(const string &, const char*);
    131 bool ?<=?(const string &, const char*);
    132 bool ?<? (const string &, const char*);
    133 
    134 int  cmp (const char*, const string &);
    135 bool ?==?(const char*, const string &);
    136 bool ?!=?(const char*, const string &);
    137 bool ?>? (const char*, const string &);
    138 bool ?>=?(const char*, const string &);
    139 bool ?<=?(const char*, const string &);
    140 bool ?<? (const char*, const string &);
     146int  strcmp (const string &, const char *);
     147bool ?==?(const string &, const char *);
     148bool ?!=?(const string &, const char *);
     149bool ?>? (const string &, const char *);
     150bool ?>=?(const string &, const char *);
     151bool ?<=?(const string &, const char *);
     152bool ?<? (const string &, const char *);
     153
     154int  strcmp (const char *, const string &);
     155bool ?==?(const char *, const string &);
     156bool ?!=?(const char *, const string &);
     157bool ?>? (const char *, const string &);
     158bool ?>=?(const char *, const string &);
     159bool ?<=?(const char *, const string &);
     160bool ?<? (const char *, const string &);
    141161
    142162
    143163// Slicing
    144 string ?()( string & this, size_t start, size_t end );  // TODO const?
    145 string ?()( string & this, size_t start);
     164string ?()( string & s, size_t start, size_t len );  // TODO const?
     165string ?()( string & s, size_t start);
    146166
    147167// String search
     
    177197
    178198
    179 
    180199struct charclass {
    181200    charclass_res * inner;
  • libcfa/src/collections/string_res.cfa

    r59c8dff rf988834  
    1010// Created On       : Fri Sep 03 11:00:00 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Oct 18 21:54:54 2023
    13 // Update Count     : 15
     12// Last Modified On : Tue Jan 16 22:19:27 2024
     13// Update Count     : 35
    1414//
    1515
     
    2222// Workaround is:  EndVbyte = TEMP_ALLOC(char, CurrSize)
    2323// Should be:      EndVbyte = alloc(CurrSize)
    24 #define TEMP_ALLOC(T, n) (( T* ) malloc( n * sizeof( T ) ))
     24#define TEMP_ALLOC(T, n) (( T * ) malloc( n * sizeof( T ) ))
    2525
    2626#include <assert.h>
     
    3333
    3434struct VbyteHeap {
    35 
    36     int NoOfCompactions;                                // number of compactions of the byte area
    37     int NoOfExtensions;                                 // number of extensions in the size of the byte area
    38     int NoOfReductions;                                 // number of reductions in the size of the byte area
     35    int NoOfCompactions;                                                // number of compactions of the byte area
     36    int NoOfExtensions;                                                 // number of extensions in the size of the byte area
     37    int NoOfReductions;                                                 // number of reductions in the size of the byte area
    3938   
    40     int InitSize;                                       // initial number of bytes in the byte-string area
    41     int CurrSize;                                       // current number of bytes in the byte-string area
    42     char *StartVbyte;                                   // pointer to the `st byte of the start of the byte-string area
    43     char *EndVbyte;                                     // pointer to the next byte after the end of the currently used portion of byte-string area
    44     void *ExtVbyte;                                     // pointer to the next byte after the end of the byte-string area
    45 
    46     HandleNode Header;                                  // header node for handle list
     39    int InitSize;                                                               // initial number of bytes in the byte-string area
     40    int CurrSize;                                                               // current number of bytes in the byte-string area
     41    char *StartVbyte;                                                   // pointer to the `st byte of the start of the byte-string area
     42    char *EndVbyte;                                                             // pointer to the next byte after the end of the currently used portion of byte-string area
     43    void *ExtVbyte;                                                             // pointer to the next byte after the end of the byte-string area
     44
     45    HandleNode Header;                                                  // header node for handle list
    4746}; // VbyteHeap
    4847
    4948   
    50 static void compaction( VbyteHeap & );                          // compaction of the byte area
    51 static void garbage( VbyteHeap &, int );                                // garbage collect the byte area
     49static void compaction( VbyteHeap & );                  // compaction of the byte area
     50static void garbage( VbyteHeap &, int );                // garbage collect the byte area
    5251static void extend( VbyteHeap &, int );                 // extend the size of the byte area
    5352static void reduce( VbyteHeap &, int );                 // reduce the size of the byte area
     
    6766// Allocate the storage for the variable sized area and intialize the heap variables.
    6867
    69 static void ?{}( VbyteHeap & this, size_t Size ) with(this) {
    70 #ifdef VbyteDebug
    71     serr | "enter:VbyteHeap::VbyteHeap, this:" | &this | " Size:" | Size;
     68static void ?{}( VbyteHeap & s, size_t Size ) with(s) {
     69#ifdef VbyteDebug
     70    serr | "enter:VbyteHeap::VbyteHeap, s:" | &s | " Size:" | Size;
    7271#endif // VbyteDebug
    7372    NoOfCompactions = NoOfExtensions = NoOfReductions = 0;
     
    7675    ExtVbyte = (void *)( StartVbyte + CurrSize );
    7776    Header.flink = Header.blink = &Header;
    78     Header.ulink = & this;
     77    Header.ulink = &s;
    7978#ifdef VbyteDebug
    8079    HeaderPtr = &Header;
    81     serr | "exit:VbyteHeap::VbyteHeap, this:" | &this;
     80    serr | "exit:VbyteHeap::VbyteHeap, s:" | &s;
    8281#endif // VbyteDebug
    8382} // VbyteHeap
     
    8685// Release the dynamically allocated storage for the byte area.
    8786
    88 static void ^?{}( VbyteHeap & this ) with(this) {
     87static void ^?{}( VbyteHeap & s ) with(s) {
    8988    free( StartVbyte );
    9089} // ~VbyteHeap
     
    9796// creator.
    9897
    99 static void ?{}( HandleNode & this ) with(this) {
    100 #ifdef VbyteDebug
    101     serr | "enter:HandleNode::HandleNode, this:" | &this;
     98static void ?{}( HandleNode & s ) with(s) {
     99#ifdef VbyteDebug
     100    serr | "enter:HandleNode::HandleNode, s:" | &s;
    102101#endif // VbyteDebug
    103102    s = 0;
    104103    lnth = 0;
    105104#ifdef VbyteDebug
    106     serr | "exit:HandleNode::HandleNode, this:" | &this;
     105    serr | "exit:HandleNode::HandleNode, s:" | &s;
    107106#endif // VbyteDebug
    108107} // HandleNode
     
    112111// collection.
    113112
    114 static void ?{}( HandleNode & this, VbyteHeap & vh ) with(this) {
    115 #ifdef VbyteDebug
    116     serr | "enter:HandleNode::HandleNode, this:" | &this;
     113static void ?{}( HandleNode & s, VbyteHeap & vh ) with(s) {
     114#ifdef VbyteDebug
     115    serr | "enter:HandleNode::HandleNode, s:" | &s;
    117116#endif // VbyteDebug
    118117    s = 0;
    119118    lnth = 0;
    120119    ulink = &vh;
    121     AddThisAfter( this, *vh.Header.blink );
    122 #ifdef VbyteDebug
    123     serr | "exit:HandleNode::HandleNode, this:" | &this;
     120    AddThisAfter( s, *vh.Header.blink );
     121#ifdef VbyteDebug
     122    serr | "exit:HandleNode::HandleNode, s:" | &s;
    124123#endif // VbyteDebug
    125124} // HandleNode
     
    129128// is the responsibility of the creator to destroy it.
    130129
    131 static void ^?{}( HandleNode & this ) with(this) {
    132 #ifdef VbyteDebug
    133     serr | "enter:HandleNode::~HandleNode, this:" | & this;
     130static void ^?{}( HandleNode & s ) with(s) {
     131#ifdef VbyteDebug
     132    serr | "enter:HandleNode::~HandleNode, s:" | & s;
    134133    {
    135134        serr | nlOff;
     
    142141    }
    143142#endif // VbyteDebug
    144     DeleteNode( this );
     143    DeleteNode( s );
    145144} // ~HandleNode
    146145
     
    151150static string_sharectx default_string_sharectx = {NEW_SHARING}; // stable bottom of stack
    152151
    153 void ?{}( string_sharectx & this, StringSharectx_Mode mode ) with( this ) {
     152void ?{}( string_sharectx & s, StringSharectx_Mode mode ) with( s ) {
    154153    (older){ ambient_string_sharectx };
    155154    if ( mode == NEW_SHARING ) {
     
    159158        (activeHeap){ 0p };
    160159    }
    161     ambient_string_sharectx = & this;
    162 }
    163 
    164 void ^?{}( string_sharectx & this ) with( this ) {
     160    ambient_string_sharectx = & s;
     161}
     162
     163void ^?{}( string_sharectx & s ) with( s ) {
    165164    if ( activeHeap ) delete( activeHeap );
    166165
    167     // unlink this from older-list starting from ambient_string_sharectx
    168     // usually, this==ambient_string_sharectx and the loop runs zero times
     166    // unlink s from older-list starting from ambient_string_sharectx
     167    // usually, s==ambient_string_sharectx and the loop runs zero times
    169168    string_sharectx *& c = ambient_string_sharectx;
    170     while ( c != &this ) &c = &c->older;              // find this
    171     c = this.older;                                   // unlink
     169    while ( c != &s ) &c = &c->older;              // find s
     170    c = s.older;                                   // unlink
    172171}
    173172
     
    181180
    182181size_t DEBUG_string_bytes_avail_until_gc( VbyteHeap * heap ) {
    183     return ((char*)heap->ExtVbyte) - heap->EndVbyte;
     182    return ((char *)heap->ExtVbyte) - heap->EndVbyte;
    184183}
    185184
     
    193192
    194193// Returns the size of the string in bytes
    195 size_t size(const string_res &s) with(s) {
     194size_t size(const string_res & s) with(s) {
    196195    return Handle.lnth;
    197196}
    198197
    199198// Output operator
    200 ofstream & ?|?(ofstream &out, const string_res &s) {
     199ofstream & ?|?(ofstream & out, const string_res & s) {
    201200        // CFA string is NOT null terminated, so print exactly lnth characters in a minimum width of 0.
    202201        out | wd( 0, s.Handle.lnth, s.Handle.s ) | nonl;
     
    204203}
    205204
    206 void ?|?(ofstream &out, const string_res &s) {
     205void ?|?(ofstream & out, const string_res & s) {
    207206        (ofstream &)(out | s); ends( out );
    208207}
    209208
    210209// Input operator
    211 ifstream & ?|?(ifstream &in, string_res &s) {
    212 
     210ifstream & ?|?(ifstream & in, string_res & s) {
    213211    // Reading into a temp before assigning to s is near zero overhead in typical cases because of sharing.
    214212    // If s is a substring of something larger, simple assignment takes care of that case correctly.
     
    231229
    232230        // rest of heap is available to read into
    233         int lenReadable = (char*)temp.Handle.ulink->ExtVbyte - temp.Handle.ulink->EndVbyte;
     231        int lenReadable = (char *)temp.Handle.ulink->ExtVbyte - temp.Handle.ulink->EndVbyte;
    234232        assert (lenReadable >= 2);
    235233
     
    238236                        *(temp.Handle.ulink->EndVbyte) = '\0';   // pre-assign empty cstring
    239237            in | wdi( lenReadable, temp.Handle.ulink->EndVbyte );
    240         } catch (cstring_length*) {
     238        } catch (cstring_length *) {
    241239            cont = true;
    242240        }
     
    252250}
    253251
    254 void ?|?( ifstream & in, string_res & this ) {
    255     (ifstream &)(in | this);
     252void ?|?( ifstream & in, string_res & s ) {
     253    (ifstream &)(in | s);
    256254}
    257255
     
    274272                cont = true;
    275273        } finally {
    276                 if ( ! cf.flags.ignore &&                                               // ok to initialize string
    277                                 cstr[0] != '\0' ) {                                             // something was read
     274                if ( ! cf.flags.ignore                                                  // ok to initialize string
     275//                       &&     cstr[0] != '\0'                                                 // something was read
     276                        ) {
    278277                        *(f.s) = cstr;
    279278                }
     
    287286                        cont = true;                                                            // continue not allowed
    288287                } finally {
    289                         if ( ! cf.flags.ignore &&
    290                                         cstr[0] != '\0' ) {                                     // something was read
     288                        if ( ! cf.flags.ignore && cstr[0] != '\0' ) { // something was read
    291289                                *(f.s) += cstr;                                                 // build string chunk at a time
    292290                        }
     
    302300
    303301// Empty constructor
    304 void ?{}(string_res &s) with(s) {
     302void ?{}(string_res & s) with(s) {
    305303    if( ambient_string_sharectx->activeHeap ) {
    306304        (Handle){ * ambient_string_sharectx->activeHeap };
     
    317315}
    318316
    319 static void eagerCopyCtorHelper(string_res &s, const char* rhs, size_t rhslnth) with(s) {
     317static void eagerCopyCtorHelper(string_res & s, const char * rhs, size_t rhslnth) with(s) {
    320318    if( ambient_string_sharectx->activeHeap ) {
    321319        (Handle){ * ambient_string_sharectx->activeHeap };
     
    333331
    334332// Constructor from a raw buffer and size
    335 void ?{}(string_res &s, const char* rhs, size_t rhslnth) with(s) {
     333void ?{}(string_res & s, const char * rhs, size_t rhslnth) with(s) {
    336334    eagerCopyCtorHelper(s, rhs, rhslnth);
    337335}
    338336
    339337// private ctor (not in header): use specified heap (ignore ambient) and copy chars in
    340 void ?{}( string_res &s, VbyteHeap & heap, const char* rhs, size_t rhslnth ) with(s) {
     338void ?{}( string_res & s, VbyteHeap & heap, const char * rhs, size_t rhslnth ) with(s) {
    341339    (Handle){ heap };
    342340    Handle.s = VbyteAlloc(*Handle.ulink, rhslnth);
     
    348346}
    349347
     348
    350349// General copy constructor
    351 void ?{}(string_res &s, const string_res & s2, StrResInitMode mode, size_t start, size_t end ) {
    352 
     350void ?{}(string_res & s, const string_res & s2, StrResInitMode mode, size_t start, size_t len ) {
     351
     352    size_t end = start + len;
    353353    verify( start <= end && end <= s2.Handle.lnth );
    354354
     
    394394}
    395395
    396 static void assignEditSet(string_res & this, string_res * shareEditSetStartPeer, string_res * shareEditSetEndPeer,
     396static void assignEditSet(string_res & s, string_res * shareEditSetStartPeer, string_res * shareEditSetEndPeer,
    397397    char * resultSesStart,
    398398    size_t resultSesLnth,
     
    400400
    401401    char * beforeBegin = shareEditSetStartPeer->Handle.s;
    402     size_t beforeLen = this.Handle.s - beforeBegin;
    403 
    404     char * afterBegin = this.Handle.s + this.Handle.lnth;
     402    size_t beforeLen = s.Handle.s - beforeBegin;
     403
     404    char * afterBegin = s.Handle.s + s.Handle.lnth;
    405405    size_t afterLen = shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth - afterBegin;
    406406
    407     size_t oldLnth = this.Handle.lnth;
    408 
    409     this.Handle.s = resultSesStart + beforeLen;
    410     this.Handle.lnth = bsize;
     407    size_t oldLnth = s.Handle.lnth;
     408
     409    s.Handle.s = resultSesStart + beforeLen;
     410    s.Handle.lnth = bsize;
    411411    if (resultPadPosition)
    412         MoveThisAfter( this.Handle, *resultPadPosition );
     412        MoveThisAfter( s.Handle, *resultPadPosition );
    413413
    414414    // adjust all substring string and handle locations, and check if any substring strings are outside the new base string
    415415    char *limit = resultSesStart + resultSesLnth;
    416     for ( string_res * p = this.shareEditSet_next; p != &this; p = p->shareEditSet_next ) {
     416    for ( string_res * p = s.shareEditSet_next; p != &s; p = p->shareEditSet_next ) {
    417417        verify (p->Handle.s >= beforeBegin);
    418418        if ( p->Handle.s >= afterBegin ) {
     
    439439                // take end as end-anchored
    440440                // stretch-shrink p according to the edit
    441                 p->Handle.lnth += this.Handle.lnth;
     441                p->Handle.lnth += s.Handle.lnth;
    442442                p->Handle.lnth -= oldLnth;
    443443            }
     
    452452                // p ends during the edit; p does not include the last character replaced
    453453                // set p to empty string at start of edit
    454                 p->Handle.s = this.Handle.s;
     454                p->Handle.s = s.Handle.s;
    455455                p->Handle.lnth = 0;
    456456            } else {
     
    458458                // clip start of p to start at end of edit
    459459                int charsToClip = afterBegin - p->Handle.s;
    460                 p->Handle.s = this.Handle.s + this.Handle.lnth;
     460                p->Handle.s = s.Handle.s + s.Handle.lnth;
    461461                p->Handle.lnth -= charsToClip;
    462462            }
     
    467467}
    468468
    469 // traverse the share-edit set (SES) to recover the range of a base string to which `this` belongs
    470 static void locateInShareEditSet( string_res &this, string_res *&shareEditSetStartPeer, string_res *&shareEditSetEndPeer ) {
    471     shareEditSetStartPeer = & this;
    472     shareEditSetEndPeer = & this;
    473     for (string_res * editPeer = this.shareEditSet_next; editPeer != &this; editPeer = editPeer->shareEditSet_next) {
     469// traverse the share-edit set (SES) to recover the range of a base string to which `s` belongs
     470static void locateInShareEditSet( string_res & s, string_res *& shareEditSetStartPeer, string_res *& shareEditSetEndPeer ) {
     471    shareEditSetStartPeer = & s;
     472    shareEditSetEndPeer = & s;
     473    for (string_res * editPeer = s.shareEditSet_next; editPeer != &s; editPeer = editPeer->shareEditSet_next) {
    474474        if ( editPeer->Handle.s < shareEditSetStartPeer->Handle.s ) {
    475475            shareEditSetStartPeer = editPeer;
     
    481481}
    482482
    483 static string_res & assign_(string_res &this, const char* buffer, size_t bsize, const string_res & valSrc) {
     483static string_res & assign_(string_res & s, const char * buffer, size_t bsize, const string_res & valSrc) {
    484484
    485485    string_res * shareEditSetStartPeer;
    486486    string_res * shareEditSetEndPeer;
    487     locateInShareEditSet( this, shareEditSetStartPeer, shareEditSetEndPeer );
     487    locateInShareEditSet( s, shareEditSetStartPeer, shareEditSetEndPeer );
    488488
    489489    verify( shareEditSetEndPeer->Handle.s >= shareEditSetStartPeer->Handle.s );
    490490    size_t origEditSetLength = shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth - shareEditSetStartPeer->Handle.s;
    491     verify( origEditSetLength >= this.Handle.lnth );
    492 
    493     if ( this.shareEditSet_owns_ulink ) {                 // assigning to private context
     491    verify( origEditSetLength >= s.Handle.lnth );
     492
     493    if ( s.shareEditSet_owns_ulink ) {                 // assigning to private context
    494494        // ok to overwrite old value within LHS
    495495        char * prefixStartOrig = shareEditSetStartPeer->Handle.s;
    496         int prefixLen = this.Handle.s - prefixStartOrig;
    497         char * suffixStartOrig = this.Handle.s + this.Handle.lnth;
     496        int prefixLen = s.Handle.s - prefixStartOrig;
     497        char * suffixStartOrig = s.Handle.s + s.Handle.lnth;
    498498        int suffixLen = shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth - suffixStartOrig;
    499499
    500         int delta = bsize - this.Handle.lnth;
    501         if ( char * oldBytes = VbyteTryAdjustLast( *this.Handle.ulink, delta ) ) {
     500        int delta = bsize - s.Handle.lnth;
     501        if ( char * oldBytes = VbyteTryAdjustLast( *s.Handle.ulink, delta ) ) {
    502502            // growing: copy from old to new
    503             char * dest = VbyteAlloc( *this.Handle.ulink, origEditSetLength + delta );
     503            char * dest = VbyteAlloc( *s.Handle.ulink, origEditSetLength + delta );
    504504            char *destCursor = dest;  memcpy(destCursor, prefixStartOrig, prefixLen);
    505505            destCursor += prefixLen;  memcpy(destCursor, buffer         , bsize    );
    506506            destCursor += bsize;      memcpy(destCursor, suffixStartOrig, suffixLen);
    507             assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer,
     507            assignEditSet(s, shareEditSetStartPeer, shareEditSetEndPeer,
    508508                dest,
    509509                origEditSetLength + delta,
     
    513513            // room is already allocated in-place: bubble suffix and overwite middle
    514514            memmove( suffixStartOrig + delta, suffixStartOrig, suffixLen );
    515             memcpy( this.Handle.s, buffer, bsize );
    516 
    517             assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer,
     515            memcpy( s.Handle.s, buffer, bsize );
     516
     517            assignEditSet(s, shareEditSetStartPeer, shareEditSetEndPeer,
    518518                shareEditSetStartPeer->Handle.s,
    519519                origEditSetLength + delta,
     
    522522
    523523    } else if (                                           // assigning to shared context
    524         this.Handle.lnth == origEditSetLength &&          // overwriting entire run of SES
     524        s.Handle.lnth == origEditSetLength &&          // overwriting entire run of SES
    525525        & valSrc &&                                       // sourcing from a managed string
    526         valSrc.Handle.ulink == this.Handle.ulink  ) {     // sourcing from same heap
     526        valSrc.Handle.ulink == s.Handle.ulink  ) {     // sourcing from same heap
    527527
    528528        // SES's result will only use characters from the source string => reuse source
    529         assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer,
     529        assignEditSet(s, shareEditSetStartPeer, shareEditSetEndPeer,
    530530            valSrc.Handle.s,
    531531            valSrc.Handle.lnth,
     
    537537
    538538        // full string is from start of shareEditSetStartPeer thru end of shareEditSetEndPeer
    539         // `this` occurs in the middle of it, to be replaced
     539        // `s` occurs in the middle of it, to be replaced
    540540        // build up the new text in `pasting`
    541541
    542542        string_res pasting = {
    543             * this.Handle.ulink,                               // maintain same heap, regardless of context
     543            * s.Handle.ulink,                               // maintain same heap, regardless of context
    544544            shareEditSetStartPeer->Handle.s,                   // start of SES
    545             this.Handle.s - shareEditSetStartPeer->Handle.s }; // length of SES, before this
     545            s.Handle.s - shareEditSetStartPeer->Handle.s }; // length of SES, before s
    546546        append( pasting,
    547             buffer,                                            // start of replacement for this
    548             bsize );                                           // length of replacement for this
     547            buffer,                                            // start of replacement for s
     548            bsize );                                           // length of replacement for s
    549549        append( pasting,
    550             this.Handle.s + this.Handle.lnth,                  // start of SES after this
     550            s.Handle.s + s.Handle.lnth,                  // start of SES after s
    551551            shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth -
    552             (this.Handle.s + this.Handle.lnth) );              // length of SES, after this
     552            (s.Handle.s + s.Handle.lnth) );              // length of SES, after s
    553553
    554554        // The above string building can trigger compaction.
    555555        // The reference points (that are arguments of the string building) may move during that building.
    556         // From this point on, they are stable.
    557 
    558         assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer,
     556        // From s point on, they are stable.
     557
     558        assignEditSet(s, shareEditSetStartPeer, shareEditSetEndPeer,
    559559            pasting.Handle.s,
    560560            pasting.Handle.lnth,
     
    562562    }
    563563
    564     return this;
    565 }
    566 
    567 string_res & assign(string_res &this, const char* buffer, size_t bsize) {
    568     return assign_(this, buffer, bsize, *0p);
    569 }
    570 
    571 string_res & ?=?(string_res &s, char other) {
    572     return assign(s, &other, 1);
     564    return s;
     565}
     566
     567string_res & assign(string_res & s, const string_res & src, size_t maxlen) {
     568    return assign_(s, src.Handle.s, min(src.Handle.lnth, maxlen), *0p);
     569}
     570
     571string_res & assign(string_res & s, const char * buffer, size_t bsize) {
     572    return assign_(s, buffer, bsize, *0p);
     573}
     574
     575string_res & ?=?(string_res & s, char c) {
     576    return assign(s, &c, 1);
    573577}
    574578
    575579// Copy assignment operator
    576 string_res & ?=?(string_res & this, const string_res & rhs) with( this ) {
    577     return assign_(this, rhs.Handle.s, rhs.Handle.lnth, rhs);
    578 }
    579 
    580 string_res & ?=?(string_res & this, string_res & rhs) with( this ) {
     580string_res & ?=?(string_res & s, const string_res & rhs) with( s ) {
     581    return assign_(s, rhs.Handle.s, rhs.Handle.lnth, rhs);
     582}
     583
     584string_res & ?=?(string_res & s, string_res & rhs) with( s ) {
    581585    const string_res & rhs2 = rhs;
    582     return this = rhs2;
     586    return s = rhs2;
    583587}
    584588
    585589
    586590// Destructor
    587 void ^?{}(string_res &s) with(s) {
     591void ^?{}(string_res & s) with(s) {
    588592    // much delegated to implied ^VbyteSM
    589593
     
    603607// With unicode support, this may be different from just the byte at the given
    604608// offset from the start of the string.
    605 char ?[?](const string_res &s, size_t index) with(s) {
     609char ?[?](const string_res & s, size_t index) with(s) {
    606610    //TODO: Check if index is valid (no exceptions yet)
    607611    return Handle.s[index];
    608612}
    609613
    610 void assignAt(const string_res &s, size_t index, char val) {
    611     string_res editZone = { s, SHARE_EDITS, index, index+1 };
     614void assignAt(const string_res & s, size_t index, char val) {
     615    // caution: not tested (not reachable by string-api-coverage interface)
     616    // equivalent form at string level is `s[index] = val`,
     617    // which uses the overload that returns a length-1 string
     618    string_res editZone = { s, SHARE_EDITS, index, 1 };
    612619    assign(editZone, &val, 1);
    613620}
     
    617624// Concatenation
    618625
    619 void append(string_res &str1, const char * buffer, size_t bsize) {
     626void append(string_res & str1, const char * buffer, size_t bsize) {
    620627    size_t clnth = str1.Handle.lnth + bsize;
    621628    if ( str1.Handle.s + str1.Handle.lnth == buffer ) { // already juxtapose ?
     
    635642}
    636643
    637 void ?+=?(string_res &str1, const string_res &str2) {
     644void ?+=?(string_res & str1, const string_res & str2) {
    638645    append( str1, str2.Handle.s, str2.Handle.lnth );
    639646}
    640647
    641 void ?+=?(string_res &s, char other) {
    642     append( s, &other, 1 );
    643 }
    644 
    645 
    646 
    647 
     648void append(string_res & str1, const string_res & str2, size_t maxlen) {
     649    append( str1, str2.Handle.s, min(str2.Handle.lnth, maxlen) );
     650}
     651
     652void ?+=?(string_res & s, char c) {
     653    append( s, & c, 1 );
     654}
     655void ?+=?(string_res & s, const char * c) {
     656    append( s, c, strlen(c) );
     657}
     658
     659///////////////////////////////////////////////////////////////////
     660// Repetition
     661
     662void ?*=?(string_res & s, size_t factor) {
     663    string_res s2 = { s, COPY_VALUE };
     664    s = "";
     665    for (factor) s += s2;
     666}
    648667
    649668//////////////////////////////////////////////////////////
    650669// Comparisons
    651670
    652 int cmp(const string_res &s1, const string_res &s2) {
     671int strcmp(const string_res & s1, const string_res & s2) {
    653672    // return 0;
    654673    int ans1 = memcmp(s1.Handle.s, s2.Handle.s, min(s1.Handle.lnth, s2.Handle.lnth));
     
    657676}
    658677
    659 bool ?==?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) == 0; }
    660 bool ?!=?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) != 0; }
    661 bool ?>? (const string_res &s1, const string_res &s2) { return cmp(s1, s2) >  0; }
    662 bool ?>=?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) >= 0; }
    663 bool ?<=?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) <= 0; }
    664 bool ?<? (const string_res &s1, const string_res &s2) { return cmp(s1, s2) <  0; }
    665 
    666 int cmp (const string_res &s1, const char* s2) {
     678bool ?==?(const string_res & s1, const string_res & s2) { return strcmp(s1, s2) == 0; }
     679bool ?!=?(const string_res & s1, const string_res & s2) { return strcmp(s1, s2) != 0; }
     680bool ?>? (const string_res & s1, const string_res & s2) { return strcmp(s1, s2) >  0; }
     681bool ?>=?(const string_res & s1, const string_res & s2) { return strcmp(s1, s2) >= 0; }
     682bool ?<=?(const string_res & s1, const string_res & s2) { return strcmp(s1, s2) <= 0; }
     683bool ?<? (const string_res & s1, const string_res & s2) { return strcmp(s1, s2) <  0; }
     684
     685int strcmp (const string_res & s1, const char * s2) {
    667686    string_res s2x = s2;
    668     return cmp(s1, s2x);
    669 }
    670 
    671 bool ?==?(const string_res &s1, const char* s2) { return cmp(s1, s2) == 0; }
    672 bool ?!=?(const string_res &s1, const char* s2) { return cmp(s1, s2) != 0; }
    673 bool ?>? (const string_res &s1, const char* s2) { return cmp(s1, s2) >  0; }
    674 bool ?>=?(const string_res &s1, const char* s2) { return cmp(s1, s2) >= 0; }
    675 bool ?<=?(const string_res &s1, const char* s2) { return cmp(s1, s2) <= 0; }
    676 bool ?<? (const string_res &s1, const char* s2) { return cmp(s1, s2) <  0; }
    677 
    678 int cmp (const char* s1, const string_res & s2) {
     687    return strcmp(s1, s2x);
     688}
     689
     690bool ?==?(const string_res & s1, const char * s2) { return strcmp(s1, s2) == 0; }
     691bool ?!=?(const string_res & s1, const char * s2) { return strcmp(s1, s2) != 0; }
     692bool ?>? (const string_res & s1, const char * s2) { return strcmp(s1, s2) >  0; }
     693bool ?>=?(const string_res & s1, const char * s2) { return strcmp(s1, s2) >= 0; }
     694bool ?<=?(const string_res & s1, const char * s2) { return strcmp(s1, s2) <= 0; }
     695bool ?<? (const string_res & s1, const char * s2) { return strcmp(s1, s2) <  0; }
     696
     697int strcmp (const char * s1, const string_res & s2) {
    679698    string_res s1x = s1;
    680     return cmp(s1x, s2);
    681 }
    682 
    683 bool ?==?(const char* s1, const string_res &s2) { return cmp(s1, s2) == 0; }
    684 bool ?!=?(const char* s1, const string_res &s2) { return cmp(s1, s2) != 0; }
    685 bool ?>? (const char* s1, const string_res &s2) { return cmp(s1, s2) >  0; }
    686 bool ?>=?(const char* s1, const string_res &s2) { return cmp(s1, s2) >= 0; }
    687 bool ?<=?(const char* s1, const string_res &s2) { return cmp(s1, s2) <= 0; }
    688 bool ?<? (const char* s1, const string_res &s2) { return cmp(s1, s2) <  0; }
     699    return strcmp(s1x, s2);
     700}
     701
     702bool ?==?(const char * s1, const string_res & s2) { return strcmp(s1, s2) == 0; }
     703bool ?!=?(const char * s1, const string_res & s2) { return strcmp(s1, s2) != 0; }
     704bool ?>? (const char * s1, const string_res & s2) { return strcmp(s1, s2) >  0; }
     705bool ?>=?(const char * s1, const string_res & s2) { return strcmp(s1, s2) >= 0; }
     706bool ?<=?(const char * s1, const string_res & s2) { return strcmp(s1, s2) <= 0; }
     707bool ?<? (const char * s1, const string_res & s2) { return strcmp(s1, s2) <  0; }
    689708
    690709
     
    693712// Search
    694713
    695 bool contains(const string_res &s, char ch) {
     714bool contains(const string_res & s, char ch) {
    696715    for ( i; size(s) ) {
    697716        if (s[i] == ch) return true;
     
    700719}
    701720
    702 int find(const string_res &s, char search) {
     721int find(const string_res & s, char search) {
    703722    return findFrom(s, 0, search);
    704723}
    705724
    706 int findFrom(const string_res &s, size_t fromPos, char search) {
     725int findFrom(const string_res & s, size_t fromPos, char search) {
    707726    // FIXME: This paricular overload (find of single char) is optimized to use memchr.
    708727    // The general overload (find of string, memchr applying to its first character) and `contains` should be adjusted to match.
     
    715734}
    716735
    717 int find(const string_res &s, const string_res &search) {
     736int find(const string_res & s, const string_res & search) {
    718737    return findFrom(s, 0, search);
    719738}
    720739
    721 int findFrom(const string_res &s, size_t fromPos, const string_res &search) {
     740int findFrom(const string_res & s, size_t fromPos, const string_res & search) {
    722741    return findFrom(s, fromPos, search.Handle.s, search.Handle.lnth);
    723742}
    724743
    725 int find(const string_res &s, const char* search) {
     744int find(const string_res & s, const char * search) {
    726745    return findFrom(s, 0, search);
    727746}
    728 int findFrom(const string_res &s, size_t fromPos, const char* search) {
     747int findFrom(const string_res & s, size_t fromPos, const char * search) {
    729748    return findFrom(s, fromPos, search, strlen(search));
    730749}
    731750
    732 int find(const string_res &s, const char* search, size_t searchsize) {
     751int find(const string_res & s, const char * search, size_t searchsize) {
    733752    return findFrom(s, 0, search, searchsize);
    734753}
    735754
    736 int findFrom(const string_res &s, size_t fromPos, const char* search, size_t searchsize) {
     755int findFrom(const string_res & s, size_t fromPos, const char * search, size_t searchsize) {
    737756
    738757    /* Remaining implementations essentially ported from Sunjay's work */
     
    771790}
    772791
    773 bool includes(const string_res &s, const string_res &search) {
     792bool includes(const string_res & s, const string_res & search) {
    774793    return includes(s, search.Handle.s, search.Handle.lnth);
    775794}
    776795
    777 bool includes(const string_res &s, const char* search) {
     796bool includes(const string_res & s, const char * search) {
    778797    return includes(s, search, strlen(search));
    779798}
    780799
    781 bool includes(const string_res &s, const char* search, size_t searchsize) {
     800bool includes(const string_res & s, const char * search, size_t searchsize) {
    782801    return find(s, search, searchsize) < s.Handle.lnth;
    783802}
    784803
    785 bool startsWith(const string_res &s, const string_res &prefix) {
     804bool startsWith(const string_res & s, const string_res & prefix) {
    786805    return startsWith(s, prefix.Handle.s, prefix.Handle.lnth);
    787806}
    788807
    789 bool startsWith(const string_res &s, const char* prefix) {
     808bool startsWith(const string_res & s, const char * prefix) {
    790809    return startsWith(s, prefix, strlen(prefix));
    791810}
    792811
    793 bool startsWith(const string_res &s, const char* prefix, size_t prefixsize) {
     812bool startsWith(const string_res & s, const char * prefix, size_t prefixsize) {
    794813    if (s.Handle.lnth < prefixsize) {
    795814        return false;
     
    798817}
    799818
    800 bool endsWith(const string_res &s, const string_res &suffix) {
     819bool endsWith(const string_res & s, const string_res & suffix) {
    801820    return endsWith(s, suffix.Handle.s, suffix.Handle.lnth);
    802821}
    803822
    804 bool endsWith(const string_res &s, const char* suffix) {
     823bool endsWith(const string_res & s, const char * suffix) {
    805824    return endsWith(s, suffix, strlen(suffix));
    806825}
    807826
    808 bool endsWith(const string_res &s, const char* suffix, size_t suffixsize) {
     827bool endsWith(const string_res & s, const char * suffix, size_t suffixsize) {
    809828    if (s.Handle.lnth < suffixsize) {
    810829        return false;
     
    822841// charclass, include, exclude
    823842
    824 void ?{}( charclass_res & this, const string_res & chars) {
    825     (this){ chars.Handle.s, chars.Handle.lnth };
    826 }
    827 
    828 void ?{}( charclass_res & this, const char * chars ) {
    829     (this){ chars, strlen(chars) };
    830 }
    831 
    832 void ?{}( charclass_res & this, const char * chars, size_t charssize ) {
    833     (this.chars){ chars, charssize };
     843void ?{}( charclass_res & s, const string_res & chars) {
     844    (s){ chars.Handle.s, chars.Handle.lnth };
     845}
     846
     847void ?{}( charclass_res & s, const char * chars ) {
     848    (s){ chars, strlen(chars) };
     849}
     850
     851void ?{}( charclass_res & s, const char * chars, size_t charssize ) {
     852    (s.chars){ chars, charssize };
    834853    // now sort it ?
    835854}
    836855
    837 void ^?{}( charclass_res & this ) {
    838     ^(this.chars){};
     856void ^?{}( charclass_res & s ) {
     857    ^(s.chars){};
    839858}
    840859
     
    844863}
    845864
    846 int exclude(const string_res &s, const charclass_res &mask) {
     865int exclude(const string_res & s, const charclass_res & mask) {
    847866    for ( i; size(s) ) {
    848867        if ( test(mask, s[i]) ) return i;
     
    851870}
    852871
    853 int include(const string_res &s, const charclass_res &mask) {
     872int include(const string_res & s, const charclass_res & mask) {
    854873    for ( i; size(s) ) {
    855874        if ( ! test(mask, s[i]) ) return i;
     
    863882// Add a new HandleNode node n after the current HandleNode node.
    864883
    865 static void AddThisAfter( HandleNode & this, HandleNode & n ) with(this) {
    866 #ifdef VbyteDebug
    867     serr | "enter:AddThisAfter, this:" | &this | " n:" | &n;
     884static void AddThisAfter( HandleNode & s, HandleNode & n ) with(s) {
     885#ifdef VbyteDebug
     886    serr | "enter:AddThisAfter, s:" | &s | " n:" | &n;
    868887#endif // VbyteDebug
    869888    // Performance note: we are on the critical path here. MB has ensured that the verifies don't contribute to runtime (are compiled away, like they're supposed to be).
    870889    verify( n.ulink != 0p );
    871     verify( this.ulink == n.ulink );
     890    verify( s.ulink == n.ulink );
    872891    flink = n.flink;
    873892    blink = &n;
    874     n.flink->blink = &this;
    875     n.flink = &this;
     893    n.flink->blink = &s;
     894    n.flink = &s;
    876895#ifdef VbyteDebug
    877896    {
     
    894913// Delete the current HandleNode node.
    895914
    896 static void DeleteNode( HandleNode & this ) with(this) {
    897 #ifdef VbyteDebug
    898     serr | "enter:DeleteNode, this:" | &this;
     915static void DeleteNode( HandleNode & s ) with(s) {
     916#ifdef VbyteDebug
     917    serr | "enter:DeleteNode, s:" | &s;
    899918#endif // VbyteDebug
    900919    flink->blink = blink;
     
    906925
    907926
    908 
    909927// Allocates specified storage for a string from byte-string area. If not enough space remains to perform the
    910928// allocation, the garbage collection routine is called.
    911929
    912 static char * VbyteAlloc( VbyteHeap & this, int size ) with(this) {
     930static char * VbyteAlloc( VbyteHeap & s, int size ) with(s) {
    913931#ifdef VbyteDebug
    914932    serr | "enter:VbyteAlloc, size:" | size;
     
    918936
    919937    NoBytes = ( uintptr_t )EndVbyte + size;
    920     if ( NoBytes > ( uintptr_t )ExtVbyte ) {            // enough room for new byte-string ?
    921                 garbage( this, size );                                  // firer up the garbage collector
     938    if ( NoBytes > ( uintptr_t )ExtVbyte ) {                    // enough room for new byte-string ?
     939                garbage( s, size );                                                             // firer up the garbage collector
    922940                verify( (( uintptr_t )EndVbyte + size) <= ( uintptr_t )ExtVbyte  && "garbage run did not free up required space" );
    923941    } // if
     
    939957// VbyteAlloc to claim the new space, while doing optimal copying from old to new, then free old.
    940958
    941 static char * VbyteTryAdjustLast( VbyteHeap & this, int delta ) with(this) {
    942 
     959static char * VbyteTryAdjustLast( VbyteHeap & s, int delta ) with(s) {
    943960    if ( ( uintptr_t )EndVbyte + delta <= ( uintptr_t )ExtVbyte ) {
    944961        // room available
     
    961978// the address in the byte string area.
    962979
    963 static void MoveThisAfter( HandleNode & this, const HandleNode  & h ) with(this) {
    964 #ifdef VbyteDebug
    965     serr | "enter:MoveThisAfter, this:" | & this | " h:" | & h;
     980static void MoveThisAfter( HandleNode & s, const HandleNode  & h ) with(s) {
     981#ifdef VbyteDebug
     982    serr | "enter:MoveThisAfter, s:" | & s | " h:" | & h;
    966983#endif // VbyteDebug
    967984    verify( h.ulink != 0p );
    968     verify( this.ulink == h.ulink );
     985    verify( s.ulink == h.ulink );
    969986    if ( s < h.s ) {                                    // check argument values
    970987                // serr | "VbyteSM: Error - Cannot move byte string starting at:" | s | " after byte string starting at:"
     
    976993    HandleNode *i;
    977994    for ( i = h.flink; i->s != 0 && s > ( i->s ); i = i->flink ); // find the position for this node after h
    978     if ( & this != i->blink ) {
    979                 DeleteNode( this );
    980                 AddThisAfter( this, *i->blink );
     995    if ( & s != i->blink ) {
     996                DeleteNode( s );
     997                AddThisAfter( s, *i->blink );
    981998    } // if
    982999#ifdef VbyteDebug
     
    10581075// the containing string has been moved. Hence, they only require that their string pointers be adjusted.
    10591076
    1060 void compaction(VbyteHeap & this) with(this) {
     1077void compaction(VbyteHeap & s) with(s) {
    10611078    HandleNode *h;
    10621079    char *obase, *nbase, *limit;
     
    10981115// the heap.  The heap is then compacted in the existing heap or into the newly allocated heap.
    10991116
    1100 void garbage(VbyteHeap & this, int minreq ) with(this) {
     1117void garbage(VbyteHeap & s, int minreq ) with(s) {
    11011118#ifdef VbyteDebug
    11021119    serr | "enter:garbage";
     
    11241141    if ( ( double ) AmountFree < ( CurrSize * heap_expansion_freespace_threshold ) || AmountFree < minreq ) {   // free space less than threshold or not enough to serve cur request
    11251142
    1126                 extend( this, max( CurrSize, minreq ) );                                // extend the heap
     1143                extend( s, max( CurrSize, minreq ) );                           // extend the heap
    11271144
    11281145                        //  Peter says, "This needs work before it should be used."
     
    11331150
    11341151    } else {
    1135         compaction(this);                                       // in-place
     1152        compaction(s);                                  // in-place
    11361153    }// if
    11371154#ifdef VbyteDebug
     
    11591176// area is deleted.
    11601177
    1161 void extend( VbyteHeap & this, int size ) with (this) {
     1178void extend( VbyteHeap & s, int size ) with (s) {
    11621179#ifdef VbyteDebug
    11631180    serr | "enter:extend, size:" | size;
     
    11711188    StartVbyte = EndVbyte = TEMP_ALLOC(char, CurrSize);
    11721189    ExtVbyte = (void *)( StartVbyte + CurrSize );
    1173     compaction(this);                                   // copy from old heap to new & adjust pointers to new heap
     1190    compaction(s);                                      // copy from old heap to new & adjust pointers to new heap
    11741191    free( OldStartVbyte );                              // release old heap
    11751192#ifdef VbyteDebug
  • libcfa/src/collections/string_res.hfa

    r59c8dff rf988834  
    1010// Created On       : Fri Sep 03 11:00:00 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Aug 12 15:45:47 2023
    13 // Update Count     : 2
     12// Last Modified On : Thu Jan  4 11:28:06 2024
     13// Update Count     : 27
    1414//
    1515
     
    7070
    7171// Getters
    72 size_t size(const string_res &s);
     72size_t size(const string_res & s);
    7373
    7474// Constructors, Assignment Operators, Destructor
    75 void ?{}(string_res &s); // empty string
    76 void ?{}(string_res &s, const char* buffer, size_t bsize); // copy specific length from buffer
    77 static inline void ?{}(string_res &s, const char* rhs) { // copy from string literal (NULL-terminated)
     75void ?{}(string_res & s); // empty string
     76void ?{}(string_res & s, const char * buffer, size_t bsize); // copy specific length from buffer
     77static inline void ?{}(string_res & s, const char * rhs) { // copy from string literal (NULL-terminated)
    7878    (s){ rhs, strlen(rhs) };
    7979}
    80 
    81 void ?{}(string_res &s, const string_res & s2) = void;
    82 void ?{}(string_res &s, string_res & s2) = void;
     80static inline void ?{}(string_res & s, char c ) {
     81    ?{}( s, &c, 1);
     82}
     83
     84// Deleting the copy constructors makes the compiler reject an attempt to call/return by value
     85void ?{}(string_res & s, const string_res & s2) = void;
     86void ?{}(string_res & s, string_res & s2) = void;
    8387
    8488enum StrResInitMode { COPY_VALUE, SHARE_EDITS };
    85 void ?{}(string_res &s, const string_res & src, StrResInitMode, size_t start, size_t end );
    86 static inline void ?{}(string_res &s, const string_res & src, StrResInitMode mode ) {
     89void ?{}(string_res & s, const string_res & src, StrResInitMode, size_t start, size_t len );
     90static inline void ?{}(string_res & s, const string_res & src, StrResInitMode mode ) {
    8791    ?{}( s, src, mode, 0, size(src));
    8892}
    89 
    90 string_res & assign(string_res &s, const char* buffer, size_t bsize); // copy specific length from buffer
    91 static inline string_res & ?=?(string_res &s, const char* other) {  // copy from string literal (NULL-terminated)
    92     return assign(s, other, strlen(other));
    93 }
    94 string_res & ?=?(string_res &s, const string_res &other);
    95 string_res & ?=?(string_res &s, string_res &other);
    96 string_res & ?=?(string_res &s, char other);
    97 
    98 void ^?{}(string_res &s);
     93static inline void ?{}(string_res & s, const string_res & src, StrResInitMode mode, size_t maxlen ) {
     94    ?{}( s, src, mode, 0, (size(src) > maxlen)?maxlen:size(src) );
     95}
     96
     97string_res & assign(string_res & s, const string_res & src, size_t maxlen); // copy specific length from other string
     98string_res & assign(string_res & s, const char * buffer, size_t bsize); // copy specific length from buffer
     99static inline string_res & ?=?(string_res & s, const char * c) {  // copy from string literal (NULL-terminated)
     100    return assign(s, c, strlen(c));
     101}
     102string_res & ?=?(string_res & s, const string_res & c);
     103string_res & ?=?(string_res & s, string_res & c);
     104string_res & ?=?(string_res & s, char c);
     105
     106void ^?{}(string_res & s);
    99107
    100108// IO Operator
    101 ofstream & ?|?(ofstream &out, const string_res &s);
    102 void ?|?(ofstream &out, const string_res &s);
    103 ifstream & ?|?(ifstream &in, string_res &s);
    104 void ?|?( ifstream & in, string_res & this );
     109ofstream & ?|?(ofstream & out, const string_res & s);
     110void ?|?(ofstream & out, const string_res & s);
     111ifstream & ?|?(ifstream & in, string_res & s);
     112void ?|?( ifstream & in, string_res & s );
    105113
    106114struct _Istream_Rstr {
     
    113121        _Istream_Rstr wdi( unsigned int rwd, string_res & s ) { return (_Istream_Rstr)@{ &s, {{0p}, rwd, {.flags.rwd : true}} }; }
    114122        _Istream_Rstr getline( string_res & s, const char delimiter = '\n' ) {
    115                 return (_Istream_Rstr)@{ &s, {{.delimiter : { delimiter, '\0' } }, -1, {.flags.delimiter : true, .flags.inex : true}} };
     123                return (_Istream_Rstr)@{ &s, {{.delimiters : { delimiter, '\0' } }, -1, {.flags.delimiter : true, .flags.inex : true}} };
    116124        }
    117125        _Istream_Rstr & getline( _Istream_Rstr & fmt, const char delimiter = '\n' ) {
    118                 fmt.delimiter[0] = delimiter; fmt.delimiter[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt;
     126                fmt.delimiters[0] = delimiter; fmt.delimiters[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt;
    119127        }
    120128        _Istream_Rstr incl( const char scanset[], string_res & s ) { return (_Istream_Rstr)@{ &s, {{scanset}, -1, {.flags.inex : false}} }; }
     
    129137
    130138// Concatenation
    131 void append(string_res &s, const char* buffer, size_t bsize);
    132 void ?+=?(string_res &s, char other); // append a character
    133 void ?+=?(string_res &s, const string_res &s2); // append-concatenate to first string
    134 static inline void ?+=?(string_res &s, const char* other) {
    135     append( s, other, strlen(other) );
    136 }
     139void ?+=?(string_res & s, const string_res & s2);
     140void ?+=?(string_res & s, char c);
     141void append(string_res & s, const string_res & s2, size_t maxlen);
     142void ?+=?(string_res & s, const char * c);
     143void append(string_res & s, const char * buffer, size_t bsize);
     144
     145static inline string_res & strcat(string_res & s, const string_res & s2) { s += s2; return s; }
     146static inline string_res & strcat(string_res & s, const char * c) { s += c; return s; }
     147static inline string_res & strncat(string_res & s, const string_res & s2, size_t maxlen) { append(s, s2, maxlen); return s; }
     148static inline string_res & strncat(string_res & s, const char * buffer, size_t bsize) { append(s, buffer, bsize); return s; }
     149
     150// Repetition
     151void ?*=?(string_res & s, size_t factor);
    137152
    138153// Character access
    139 void assignAt(const string_res &s, size_t index, char val);
    140 char ?[?](const string_res &s, size_t index); // Mike changed to ret by val from Sunjay's ref, to match Peter's
    141 //char codePointAt(const string_res &s, size_t index); // revisit under Unicode
     154void assignAt(const string_res & s, size_t index, char val);
     155char ?[?](const string_res & s, size_t index); // Mike changed to ret by val from Sunjay's ref, to match Peter's
     156//char codePointAt(const string_res & s, size_t index); // revisit under Unicode
    142157
    143158// Comparisons
    144 int  cmp (const string_res &, const string_res &);
     159int  strcmp (const string_res &, const string_res &);
    145160bool ?==?(const string_res &, const string_res &);
    146161bool ?!=?(const string_res &, const string_res &);
     
    150165bool ?<? (const string_res &, const string_res &);
    151166
    152 int  cmp (const string_res &, const char*);
    153 bool ?==?(const string_res &, const char*);
    154 bool ?!=?(const string_res &, const char*);
    155 bool ?>? (const string_res &, const char*);
    156 bool ?>=?(const string_res &, const char*);
    157 bool ?<=?(const string_res &, const char*);
    158 bool ?<? (const string_res &, const char*);
    159 
    160 int  cmp (const char*, const string_res &);
    161 bool ?==?(const char*, const string_res &);
    162 bool ?!=?(const char*, const string_res &);
    163 bool ?>? (const char*, const string_res &);
    164 bool ?>=?(const char*, const string_res &);
    165 bool ?<=?(const char*, const string_res &);
    166 bool ?<? (const char*, const string_res &);
     167int  strcmp(const string_res &, const char *);
     168bool ?==?(const string_res &, const char *);
     169bool ?!=?(const string_res &, const char *);
     170bool ?>? (const string_res &, const char *);
     171bool ?>=?(const string_res &, const char *);
     172bool ?<=?(const string_res &, const char *);
     173bool ?<? (const string_res &, const char *);
     174
     175int  strcmp(const char *, const string_res &);
     176bool ?==?(const char *, const string_res &);
     177bool ?!=?(const char *, const string_res &);
     178bool ?>? (const char *, const string_res &);
     179bool ?>=?(const char *, const string_res &);
     180bool ?<=?(const char *, const string_res &);
     181bool ?<? (const char *, const string_res &);
    167182
    168183// String search
    169 bool contains(const string_res &s, char ch); // single character
    170 
    171 int find(const string_res &s, char search);
    172 int find(const string_res &s, const string_res &search);
    173 int find(const string_res &s, const char* search);
    174 int find(const string_res &s, const char* search, size_t searchsize);
    175 
    176 int findFrom(const string_res &s, size_t fromPos, char search);
    177 int findFrom(const string_res &s, size_t fromPos, const string_res &search);
    178 int findFrom(const string_res &s, size_t fromPos, const char* search);
    179 int findFrom(const string_res &s, size_t fromPos, const char* search, size_t searchsize);
    180 
    181 bool includes(const string_res &s, const string_res &search);
    182 bool includes(const string_res &s, const char* search);
    183 bool includes(const string_res &s, const char* search, size_t searchsize);
    184 
    185 bool startsWith(const string_res &s, const string_res &prefix);
    186 bool startsWith(const string_res &s, const char* prefix);
    187 bool startsWith(const string_res &s, const char* prefix, size_t prefixsize);
    188 
    189 bool endsWith(const string_res &s, const string_res &suffix);
    190 bool endsWith(const string_res &s, const char* suffix);
    191 bool endsWith(const string_res &s, const char* suffix, size_t suffixsize);
    192 
    193 int include(const string_res &s, const charclass_res &mask);
    194 int exclude(const string_res &s, const charclass_res &mask);
     184bool contains(const string_res & s, char ch); // single character
     185
     186int find(const string_res & s, char search);
     187int find(const string_res & s, const string_res & search);
     188int find(const string_res & s, const char * search);
     189int find(const string_res & s, const char * search, size_t searchsize);
     190
     191int findFrom(const string_res & s, size_t fromPos, char search);
     192int findFrom(const string_res & s, size_t fromPos, const string_res & search);
     193int findFrom(const string_res & s, size_t fromPos, const char * search);
     194int findFrom(const string_res & s, size_t fromPos, const char * search, size_t searchsize);
     195
     196bool includes(const string_res & s, const string_res & search);
     197bool includes(const string_res & s, const char * search);
     198bool includes(const string_res & s, const char * search, size_t searchsize);
     199
     200bool startsWith(const string_res & s, const string_res & prefix);
     201bool startsWith(const string_res & s, const char * prefix);
     202bool startsWith(const string_res & s, const char * prefix, size_t prefixsize);
     203
     204bool endsWith(const string_res & s, const string_res & suffix);
     205bool endsWith(const string_res & s, const char * suffix);
     206bool endsWith(const string_res & s, const char * suffix, size_t suffixsize);
     207
     208int include(const string_res & s, const charclass_res & mask);
     209int exclude(const string_res & s, const charclass_res & mask);
    195210
    196211// Modifiers
    197 void padStart(string_res &s, size_t n);
    198 void padStart(string_res &s, size_t n, char padding);
    199 void padEnd(string_res &s, size_t n);
     212void padStart(string_res & s, size_t n);
     213void padStart(string_res & s, size_t n, char padding);
     214void padEnd(string_res & s, size_t n);
    200215void padEnd(string_res &s, size_t n, char padding);
    201216
  • libcfa/src/heap.cfa

    r59c8dff rf988834  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Sep 30 17:31:15 2023
    13 // Update Count     : 1617
     12// Last Modified On : Wed Jan  3 21:30:54 2024
     13// Update Count     : 1619
    1414//
    1515
     
    2727#include "bits/align.hfa"                                                               // libAlign
    2828#include "bits/defs.hfa"                                                                // likely, unlikely
    29 #include "concurrency/kernel/fwd.hfa"                                   // __POLL_PREEMPTION
     29#include "concurrency/kernel/fwd.hfa"                                   // disable_interrupts, enable_interrupts
    3030#include "startup.hfa"                                                                  // STARTUP_PRIORITY_MEMORY
    3131#include "math.hfa"                                                                             // ceiling, min
  • libcfa/src/interpose.cfa

    r59c8dff rf988834  
    1010// Created On       : Wed Mar 29 16:10:31 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 27 21:09:03 2023
    13 // Update Count     : 196
     12// Last Modified On : Thu Jan 11 18:45:31 2024
     13// Update Count     : 218
    1414//
    1515
     
    1818extern "C" {
    1919#include <dlfcn.h>                                                                              // dlopen, dlsym
     20//#include <link.h>                                                                             // dl_iterate_phdr
     21struct dl_phdr_info;
     22int dl_iterate_phdr( int (*)( struct dl_phdr_info *, size_t, void * ), void * );
    2023#include <execinfo.h>                                                                   // backtrace, messages
    2124}
     
    2326#include "bits/defs.hfa"
    2427#include "bits/signal.hfa"                                                              // sigHandler_?
     28#include "concurrency/kernel/fwd.hfa"                                   // disable_interrupts, enable_interrupts
    2529#include "startup.hfa"                                                                  // STARTUP_PRIORITY_CORE
    2630#include <assert.h>
     
    8791        void (* exit)( int ) __attribute__(( __noreturn__ ));
    8892        void (* abort)( void ) __attribute__(( __noreturn__ ));
     93        int (* dl_iterate_phdr)( int (*)( struct dl_phdr_info *, size_t, void * ), void * );
    8994} __cabi_libc;
    9095
     
    102107                #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
    103108                INTERPOSE_LIBC( abort, version );
    104                 INTERPOSE_LIBC( exit , version );
     109                INTERPOSE_LIBC( exit, version );
     110                INTERPOSE_LIBC( dl_iterate_phdr, version );
    105111                #pragma GCC diagnostic pop
    106112
     
    150156        }
    151157}
     158
     159extern "C" int dl_iterate_phdr( int (* callback)( struct dl_phdr_info *, size_t, void * ), void * data ) {
     160        disable_interrupts();
     161        int ret = __cabi_libc.dl_iterate_phdr( callback, data ); // call real routine
     162        enable_interrupts( false );
     163        return ret;
     164} // dl_iterate_phdr
    152165
    153166//=============================================================================================
  • libcfa/src/iostream.cfa

    r59c8dff rf988834  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Nov 17 13:33:12 2023
    13 // Update Count     : 1853
     12// Last Modified On : Wed Jan  3 10:53:13 2024
     13// Update Count     : 1898
    1414//
    1515
     
    984984        }
    985985
    986         istype & ?|?( istype & is, _Istream_Cquoted f ) {
     986        istype & ?|?( istype & is, _Istream_Cquoted f ) with( f ) {
    987987                char fmtstr[32];                                                                // storage scanset and format codes
    988988                fmtstr[0] = '%';
     
    992992                bool check = true;
    993993
    994                 if ( f.flags.ignore ) { check = false; fmtstr[1] = '*'; pos += 1; }
    995                 int rwd = f.wd;
    996                 if ( f.wd != -1 ) {                                                             // => just ignore versus ignore with width
     994                if ( cstr.flags.ignore ) { check = false; fmtstr[1] = '*'; pos += 1; }
     995                int rwd = cstr.wd;
     996                if ( cstr.wd != -1 ) {                                          // => just ignore versus ignore with width
    997997                        // wd is buffer bytes available (for input chars + null terminator)
    998998                        // rwd is count of input chars
    999999                        // no maximum width necessary because text ignored => width is read width
    1000                         if ( f.flags.rwd ) check = false;
    1001                         else rwd = f.wd - 1;
     1000                        if ( cstr.flags.rwd ) check = false;
     1001                        else rwd = cstr.wd - 1;
    10021002                        pos += sprintf( &fmtstr[pos], "%d", rwd );
    10031003                } // if
    10041004
    10051005                int len = 0;                                                                    // may not be set in fmt
    1006                 if ( ! f.flags.inex ) {                                                 // => quoted getline
    1007                         // fprintf( stderr, "quoted\n" );
     1006                char enddelim;
     1007                if ( ! cstr.flags.inex ) {                                              // => quoted getline
    10081008                        args = fmt( is, "%*[ \f\n\r\t\v]" );            // remove leading whitespace
    10091009                        if ( eof( is ) ) goto Eof;
    1010 //                      args = fmt( is, (const char *)f.delimiter ); // remove leading quote
    1011                         args = fmt( is, "'%n", &len ); // remove leading quote
    1012                         fprintf( stderr, "quoted %d %d\n", args, len );
     1010                        char rfmt[4] = { cstr.delimiters[0], '%', 'n', '\0' };
     1011                        args = fmt( is, rfmt, &len );                           // remove leading quote
    10131012                        if ( len == 0 || eof( is ) ) goto Eof;
    10141013                } // if
    1015                 sprintf( &fmtstr[pos], "[^%c]%%n", f.delimiter[0] );
    1016                 // fprintf( stderr, "getline %s %d\n", fmtstr, f.wd );
    1017                 if ( f.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
    1018                 else args = fmt( is, fmtstr, f.s, &len );
    1019                 // fprintf( stderr, "getline %s %d %d %d\n", fmtstr, args, f.wd, eof( is ) );
     1014                enddelim = cstr.delimiters[1] == '\0' ? cstr.delimiters[0] : cstr.delimiters[1];
     1015                sprintf( &fmtstr[pos], "[^%c]%%n", enddelim );
     1016                if ( cstr.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
     1017                else args = fmt( is, fmtstr, cstr.s, &len );
    10201018                if ( check && len == rwd && ! eof( is ) ) {             // might not fit
    10211019                        char peek;
    10221020                        fmt( is, "%c", &peek );                                         // check for delimiter
    1023                         // fprintf( stderr, "peek %d '%c'\n", args, peek );
    10241021                        if ( ! eof( is ) ) {
    1025                                 if ( peek != f.delimiter[0] ) {
     1022                                if ( peek != enddelim ) {
    10261023                                        ungetc( is, peek );
    10271024                                        throwResume ExceptionInst( cstring_length );
     
    10301027                } else fmt( is, "%*c" );                                                // remove delimiter
    10311028          Eof: ;
    1032                 if ( rwd > 0 && args == 0 ) f.s[0] = '\0';              // read failed => no pattern match => set string to null
     1029                if ( rwd > 0 && args == 0 ) cstr.s[0] = '\0';   // read failed => no pattern match => set string to null
    10331030                if ( args == 1 && eof( is ) ) {                                 // data but scan ended at EOF
    1034                         // fprintf( stderr, "clear\n" );
    10351031                        clear( is );                                                            // => reset EOF => detect again on next read
    10361032                } // if
     
    10381034        }
    10391035
    1040         istype & ?|?( istype & is, _Istream_Cstr f ) {
     1036        istype & ?|?( istype & is, _Istream_Cstr f ) with( f ) {
    10411037                const char * scanset;
    10421038                size_t nscanset = 0;
    1043                 if ( f.flags.delimiter ) scanset = f.delimiter; // getline ?
     1039                if ( flags.delimiter ) scanset = delimiters;    // getline ?
    10441040                else scanset = f.scanset;
    10451041                if ( scanset ) nscanset = strlen( scanset );
     
    10841080                        if ( f.flags.delimiter ) {                                      // getline
    10851081                                int len = 0;                                                    // may not be set in fmt
    1086                                 if ( ! f.flags.inex ) {                                 // => quoted getline
    1087                                         // fprintf( stderr, "quoted\n" );
    1088                                         args = fmt( is, "%*[ \f\n\r\t\v]" ); // remove leading whitespace
    1089                                         if ( eof( is ) ) goto X;
    1090                                         args = fmt( is, "\"" );                         // remove leading quote
    1091                                         if ( eof( is ) ) goto X;
    1092                                 } // if
    1093                                 // fprintf( stderr, "getline\n" );
    1094                                 // sprintf( &fmtstr[pos], "[%s%s]%%n", f.flags.inex ? "^" : "", scanset );
    1095                                 sprintf( &fmtstr[pos], "[^%s]%%n", scanset );
    1096                                 // fprintf( stderr, "getline %s %d\n", fmtstr, f.wd );
     1082                                sprintf( &fmtstr[pos], "[^%c]%%n", f.delimiters[0] );
    10971083                                if ( f.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
    10981084                                else args = fmt( is, fmtstr, f.s, &len );
    1099                                 // fprintf( stderr, "getline %s %d %d %d\n", fmtstr, args, f.wd, eof( is ) );
    11001085                                if ( check && len == rwd && ! eof( is ) ) {     // might not fit
    1101                                         char peek;
    1102                                         fmt( is, "%c", &peek );                         // check for delimiter
    1103                                         // fprintf( stderr, "peek %d '%c'\n", args, peek );
     1086                                        fmtstr[0] = f.delimiters[0]; fmtstr[1] = '%'; fmtstr[2] = 'n'; fmtstr[3] = '\0';
     1087                                        fmt( is, fmtstr, &len );                        // remove delimiter
    11041088                                        if ( ! eof( is ) ) {
    1105                                                 if ( peek != f.delimiter[0] ) {
    1106                                                         ungetc( is, peek );
     1089//                                              if ( peek != f.delimiter[0] ) {
     1090                                                if ( len != 1 ) {
     1091//                                                      ungetc( is, peek );
    11071092                                                        throwResume ExceptionInst( cstring_length );
    11081093                                                } // if
    11091094                                        } // if
    1110                                 } else fmt( is, "%*c" );                        // remove delimiter
    1111                           X: ;
     1095                                } else fmt( is, "%*c" );                                // remove delimiter
    11121096                        } else {
    11131097                                // incl %[xxx],  %*[xxx],  %w[xxx],  %*w[xxx]
  • libcfa/src/iostream.hfa

    r59c8dff rf988834  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Nov 15 17:55:31 2023
    13 // Update Count     : 596
     12// Last Modified On : Wed Jan  3 10:53:18 2024
     13// Update Count     : 610
    1414//
    1515
     
    392392        union {
    393393                const char * scanset;
    394                 char delimiter[2];
     394                char delimiters[3];                                                             // [0] => left, [1] => right
    395395        };
    396396        int wd;                                                                                         // width
     
    412412
    413413struct _Istream_Cquoted {
    414         char * s;
    415         inline _Istream_str_base;
     414        _Istream_Cstr cstr;
    416415}; // _Istream_Cquoted
    417416
     
    419418        // width must include room for null terminator
    420419        _Istream_Cstr wdi( unsigned int wd, char s[] ) { return (_Istream_Cstr)@{ s, { {0p}, wd, {.all : 0} } }; }
    421         // read width does not include null terminator
    422420        _Istream_Cstr wdi( unsigned int wd, unsigned int rwd, char s[] ) {
    423421                if ( wd <= rwd ) throw (cstring_length){ &cstring_length_vt };
    424422                return (_Istream_Cstr)@{ s, { {0p}, rwd, {.flags.rwd : true} } };
    425423        }
    426         _Istream_Cquoted & quoted( _Istream_Cstr & fmt, const char delimiter = '"' ) {
    427                 fmt.delimiter[0] = delimiter; fmt.delimiter[1] = '\0';
     424        _Istream_Cquoted & quoted( _Istream_Cstr & fmt, const char Ldelimiter = '"', const char Rdelimiter = '\0' ) {
     425                fmt.delimiters[0] = Ldelimiter;  fmt.delimiters[1] = Rdelimiter;  fmt.delimiters[2] = '\0';
    428426                return (_Istream_Cquoted &)fmt;
    429427        }
    430428        _Istream_Cstr & getline( _Istream_Cstr & fmt, const char delimiter = '\n' ) {
    431                 fmt.delimiter[0] = delimiter; fmt.delimiter[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt; }
     429                fmt.delimiters[0] = delimiter; fmt.delimiters[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt;
     430        }
    432431        _Istream_Cstr & incl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = false; return fmt; }
    433432        _Istream_Cstr & excl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; }
  • src/AST/Attribute.cpp

    r59c8dff rf988834  
    3838
    3939bool Attribute::isValidOnFuncParam() const {
    40         // attributes such as aligned, cleanup, etc. produce GCC errors when they appear
    41         // on function parameters. Maintain here a whitelist of attribute names that are
    42         // allowed to appear on parameters.
     40        // Attributes produce GCC errors when they appear on function
     41        // parameters. Names on the previous allow-list implementation:
     42        // unused, noreturn, __vector_size__
    4343        std::string norm = normalizedName();
    44         return norm == "unused" || norm == "noreturn";
     44        return norm != "aligned" && norm != "packed" && norm != "used";
    4545}
    4646
  • src/AST/Decl.hpp

    r59c8dff rf988834  
    2929#include "StorageClasses.hpp"
    3030#include "Visitor.hpp"
    31 #include "Common/utility.h"
    3231
    3332// Must be included in *all* AST classes; should be #undef'd at the end of the file
  • src/AST/Pass.proto.hpp

    r59c8dff rf988834  
    1919#include "Common/Iterate.hpp"
    2020#include "Common/Stats/Heap.h"
     21#include "Common/utility.h"
    2122namespace ast {
    2223        template<typename core_t> class Pass;
  • src/CodeGen/CodeGenerator.hpp

    r59c8dff rf988834  
    2121#include "AST/Pass.hpp"          // for WithGuards, WithShortCircuiting, ...
    2222#include "CodeGen/Options.h"     // for Options
     23#include "Common/Indenter.h"     // for Indenter
    2324
    2425
  • src/Common/utility.h

    r59c8dff rf988834  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Feb 17 15:25:00 2023
    13 // Update Count     : 53
     12// Last Modified On : Wed Jan 17 14:40:00 2024
     13// Update Count     : 54
    1414//
    1515
     
    1717
    1818#include <cassert>
    19 #include <cctype>
    2019#include <algorithm>
    21 #include <iostream>
    2220#include <list>
    23 #include <memory>
    2421#include <string>
    2522#include <type_traits>
    2623#include <vector>
    27 #include <cstring>                                                                              // memcmp
    28 
    29 #include "Common/Indenter.h"
    30 
    31 class Expression;
    32 
    33 /// bring std::move into global scope
    34 using std::move;
    3524
    3625/// partner to move that copies any copyable type
    3726template<typename T>
    3827T copy( const T & x ) { return x; }
    39 
    40 template< typename T >
    41 static inline T * maybeClone( const T *orig ) {
    42         if ( orig ) {
    43                 return orig->clone();
    44         } else {
    45                 return 0;
    46         } // if
    47 }
    48 
    49 template< typename Input_iterator >
    50 void printEnums( Input_iterator begin, Input_iterator end, const char * const *name_array, std::ostream &os ) {
    51         for ( Input_iterator i = begin; i != end; ++i ) {
    52                 os << name_array[ *i ] << ' ';
    53         } // for
    54 }
    55 
    56 template< typename Container >
    57 void deleteAll( const Container &container ) {
    58         for ( const auto &i : container ) {
    59                 delete i;
    60         } // for
    61 }
    62 
    63 template< typename Container >
    64 void printAll( const Container &container, std::ostream &os, Indenter indent = {} ) {
    65         for ( typename Container::const_iterator i = container.begin(); i != container.end(); ++i ) {
    66                 if ( *i ) {
    67                         os << indent;
    68                         (*i)->print( os, indent );
    69                         // need an endl after each element because it's not easy to know when each individual item should end
    70                         os << std::endl;
    71                 } // if
    72         } // for
    73 }
    74 
    75 template< typename SrcContainer, typename DestContainer >
    76 void cloneAll( const SrcContainer &src, DestContainer &dest ) {
    77         typename SrcContainer::const_iterator in = src.begin();
    78         std::back_insert_iterator< DestContainer > out( dest );
    79         while ( in != src.end() ) {
    80                 *out++ = (*in++)->clone();
    81         } // while
    82 }
    83 
    84 template< typename SrcContainer, typename DestContainer, typename Predicate >
    85 void cloneAll_if( const SrcContainer &src, DestContainer &dest, Predicate pred ) {
    86         std::back_insert_iterator< DestContainer > out( dest );
    87         for ( auto x : src ) {
    88                 if ( pred(x) ) {
    89                         *out++ = x->clone();
    90                 }
    91         } // while
    92 }
    93 
    94 template< typename Container >
    95 void assertAll( const Container &container ) {
    96         int count = 0;
    97         for ( typename Container::const_iterator i = container.begin(); i != container.end(); ++i ) {
    98                 if ( !(*i) ) {
    99                         std::cerr << count << " is null" << std::endl;
    100                 } // if
    101         } // for
    102 }
    103 
    104 template < typename T >
    105 std::list<T> tail( std::list<T> l ) {
    106         if ( ! l.empty() ) {
    107                 std::list<T> ret(++(l.begin()), l.end());
    108                 return ret;
    109         } // if
    110 }
    111 
    112 template < typename T >
    113 std::list<T> flatten( std::list < std::list<T> > l) {
    114         typedef std::list <T> Ts;
    115 
    116         Ts ret;
    117 
    118         switch ( l.size() ) {
    119           case 0:
    120                 return ret;
    121           case 1:
    122                 return l.front();
    123           default:
    124                 ret = flatten(tail(l));
    125                 ret.insert(ret.begin(), l.front().begin(), l.front().end());
    126                 return ret;
    127         } // switch
    128 }
    12928
    13029/// Splice src onto the end of dst, clearing src
     
    14342}
    14443
    145 template< typename... Args >
    146 auto filter(Args&&... args) -> decltype(std::copy_if(std::forward<Args>(args)...)) {
    147   return std::copy_if(std::forward<Args>(args)...);
    148 }
    149 
    150 template <typename E, typename UnaryPredicate, template< typename, typename...> class Container, typename... Args >
    151 void filter( Container< E *, Args... > & container, UnaryPredicate pred, bool doDelete ) {
    152         auto i = begin( container );
    153         while ( i != end( container ) ) {
    154                 auto it = next( i );
    155                 if ( pred( *i ) ) {
    156                         if ( doDelete ) {
    157                                 delete *i;
    158                         } // if
    159                         container.erase( i );
    160                 } // if
    161                 i = it;
    162         } // while
    163 }
    164 
     44/// Remove elements that match pred from the container.
    16545template<typename Container, typename Pred>
    16646void erase_if( Container & cont, Pred && pred ) {
  • src/InitTweak/FixInit.cpp

    r59c8dff rf988834  
    581581        }
    582582
    583         if ( ! dtor->env ) dtor->env = maybeClone( env );
     583        if ( nullptr == dtor->env && nullptr != env ) {
     584                dtor->env = ast::shallowCopy( env );
     585        }
    584586        auto dtorFunc = getDtorFunc( ret, new ast::ExprStmt(loc, dtor ), stmtsToAddBefore );
    585587
  • src/Parser/DeclarationNode.cc

    r59c8dff rf988834  
    3535#include "Common/SemanticError.h"  // for SemanticError
    3636#include "Common/UniqueName.h"     // for UniqueName
    37 #include "Common/utility.h"        // for maybeClone
     37#include "Common/utility.h"        // for copy, spliceBegin
    3838#include "Parser/ExpressionNode.h" // for ExpressionNode
    3939#include "Parser/InitializerNode.h"// for InitializerNode
     
    4141#include "TypeData.h"              // for TypeData, TypeData::Aggregate_t
    4242#include "TypedefTable.h"          // for TypedefTable
    43 
    44 class Initializer;
    4543
    4644extern TypedefTable typedefTable;
     
    10199DeclarationNode * DeclarationNode::clone() const {
    102100        DeclarationNode * newnode = new DeclarationNode;
    103         newnode->set_next( maybeClone( get_next() ) );
     101        newnode->set_next( maybeCopy( get_next() ) );
    104102        newnode->name = name ? new string( *name ) : nullptr;
    105103
    106104        newnode->builtin = NoBuiltinType;
    107         newnode->type = maybeClone( type );
     105        newnode->type = maybeCopy( type );
    108106        newnode->inLine = inLine;
    109107        newnode->storageClasses = storageClasses;
    110108        newnode->funcSpecs = funcSpecs;
    111         newnode->bitfieldWidth = maybeClone( bitfieldWidth );
    112         newnode->enumeratorValue.reset( maybeClone( enumeratorValue.get() ) );
     109        newnode->bitfieldWidth = maybeCopy( bitfieldWidth );
     110        newnode->enumeratorValue.reset( maybeCopy( enumeratorValue.get() ) );
    113111        newnode->hasEllipsis = hasEllipsis;
    114112        newnode->linkage = linkage;
    115113        newnode->asmName = maybeCopy( asmName );
    116114        newnode->attributes = attributes;
    117         newnode->initializer = maybeClone( initializer );
     115        newnode->initializer = maybeCopy( initializer );
    118116        newnode->extension = extension;
    119         newnode->asmStmt = maybeClone( asmStmt );
     117        newnode->asmStmt = maybeCopy( asmStmt );
    120118        newnode->error = error;
    121119
    122120//      newnode->variable.name = variable.name ? new string( *variable.name ) : nullptr;
    123121        newnode->variable.tyClass = variable.tyClass;
    124         newnode->variable.assertions = maybeClone( variable.assertions );
    125         newnode->variable.initializer = maybeClone( variable.initializer );
    126 
    127         newnode->assert.condition = maybeClone( assert.condition );
     122        newnode->variable.assertions = maybeCopy( variable.assertions );
     123        newnode->variable.initializer = maybeCopy( variable.initializer );
     124
     125        newnode->assert.condition = maybeCopy( assert.condition );
    128126        newnode->assert.message = maybeCopy( assert.message );
    129127        return newnode;
     
    664662                                dst->base->aggInst.aggregate = src;
    665663                                if ( src->kind == TypeData::Aggregate ) {
    666                                         dst->base->aggInst.params = maybeClone( src->aggregate.actuals );
     664                                        dst->base->aggInst.params = maybeCopy( src->aggregate.actuals );
    667665                                } // if
    668666                                dst->base->qualifiers |= src->qualifiers;
     
    694692                                        if ( o->type->kind == TypeData::Aggregate ) {
    695693                                                type->aggInst.hoistType = o->type->aggregate.body;
    696                                                 type->aggInst.params = maybeClone( o->type->aggregate.actuals );
     694                                                type->aggInst.params = maybeCopy( o->type->aggregate.actuals );
    697695                                        } else {
    698696                                                type->aggInst.hoistType = o->type->enumeration.body;
     
    860858                                p->type->base->aggInst.aggregate = type;
    861859                                if ( type->kind == TypeData::Aggregate ) {
    862                                         p->type->base->aggInst.params = maybeClone( type->aggregate.actuals );
     860                                        p->type->base->aggInst.params = maybeCopy( type->aggregate.actuals );
    863861                                } // if
    864862                                p->type->base->qualifiers |= type->qualifiers;
     
    897895                        lastArray->base->aggInst.aggregate = type;
    898896                        if ( type->kind == TypeData::Aggregate ) {
    899                                 lastArray->base->aggInst.params = maybeClone( type->aggregate.actuals );
     897                                lastArray->base->aggInst.params = maybeCopy( type->aggregate.actuals );
    900898                        } // if
    901899                        lastArray->base->qualifiers |= type->qualifiers;
     
    950948DeclarationNode * DeclarationNode::cloneType( string * name ) {
    951949        DeclarationNode * newnode = newName( name );
    952         newnode->type = maybeClone( type );
     950        newnode->type = maybeCopy( type );
    953951        newnode->copySpecifiers( this );
    954952        return newnode;
     
    984982                } // if
    985983
    986                 newType->forall = maybeClone( type->forall );
     984                newType->forall = maybeCopy( type->forall );
    987985                if ( ! o->type ) {
    988986                        o->type = newType;
  • src/Parser/ParseNode.h

    r59c8dff rf988834  
    3030#include "Common/SemanticError.h"  // for SemanticError
    3131#include "Common/UniqueName.h"     // for UniqueName
    32 #include "Common/utility.h"        // for maybeClone
    3332#include "Parser/parserutility.h"  // for maybeBuild, maybeCopy
    3433
  • src/Parser/TypeData.cc

    r59c8dff rf988834  
    167167        TypeData * newtype = new TypeData( kind );
    168168        newtype->qualifiers = qualifiers;
    169         newtype->base = maybeClone( base );
    170         newtype->forall = maybeClone( forall );
     169        newtype->base = maybeCopy( base );
     170        newtype->forall = maybeCopy( forall );
    171171
    172172        switch ( kind ) {
     
    185185                break;
    186186        case Array:
    187                 newtype->array.dimension = maybeClone( array.dimension );
     187                newtype->array.dimension = maybeCopy( array.dimension );
    188188                newtype->array.isVarLen = array.isVarLen;
    189189                newtype->array.isStatic = array.isStatic;
    190190                break;
    191191        case Function:
    192                 newtype->function.params = maybeClone( function.params );
    193                 newtype->function.idList = maybeClone( function.idList );
    194                 newtype->function.oldDeclList = maybeClone( function.oldDeclList );
    195                 newtype->function.body = maybeClone( function.body );
    196                 newtype->function.withExprs = maybeClone( function.withExprs );
     192                newtype->function.params = maybeCopy( function.params );
     193                newtype->function.idList = maybeCopy( function.idList );
     194                newtype->function.oldDeclList = maybeCopy( function.oldDeclList );
     195                newtype->function.body = maybeCopy( function.body );
     196                newtype->function.withExprs = maybeCopy( function.withExprs );
    197197                break;
    198198        case Aggregate:
    199199                newtype->aggregate.kind = aggregate.kind;
    200200                newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr;
    201                 newtype->aggregate.params = maybeClone( aggregate.params );
    202                 newtype->aggregate.actuals = maybeClone( aggregate.actuals );
    203                 newtype->aggregate.fields = maybeClone( aggregate.fields );
     201                newtype->aggregate.params = maybeCopy( aggregate.params );
     202                newtype->aggregate.actuals = maybeCopy( aggregate.actuals );
     203                newtype->aggregate.fields = maybeCopy( aggregate.fields );
    204204                newtype->aggregate.body = aggregate.body;
    205205                newtype->aggregate.anon = aggregate.anon;
     
    208208                break;
    209209        case AggregateInst:
    210                 newtype->aggInst.aggregate = maybeClone( aggInst.aggregate );
    211                 newtype->aggInst.params = maybeClone( aggInst.params );
     210                newtype->aggInst.aggregate = maybeCopy( aggInst.aggregate );
     211                newtype->aggInst.params = maybeCopy( aggInst.params );
    212212                newtype->aggInst.hoistType = aggInst.hoistType;
    213213                break;
    214214        case Enum:
    215215                newtype->enumeration.name = enumeration.name ? new string( *enumeration.name ) : nullptr;
    216                 newtype->enumeration.constants = maybeClone( enumeration.constants );
     216                newtype->enumeration.constants = maybeCopy( enumeration.constants );
    217217                newtype->enumeration.body = enumeration.body;
    218218                newtype->enumeration.anon = enumeration.anon;
     
    221221        case SymbolicInst:
    222222                newtype->symbolic.name = symbolic.name ? new string( *symbolic.name ) : nullptr;
    223                 newtype->symbolic.params = maybeClone( symbolic.params );
    224                 newtype->symbolic.actuals = maybeClone( symbolic.actuals );
    225                 newtype->symbolic.assertions = maybeClone( symbolic.assertions );
     223                newtype->symbolic.params = maybeCopy( symbolic.params );
     224                newtype->symbolic.actuals = maybeCopy( symbolic.actuals );
     225                newtype->symbolic.assertions = maybeCopy( symbolic.assertions );
    226226                newtype->symbolic.isTypedef = symbolic.isTypedef;
    227227                break;
    228228        case Tuple:
    229                 newtype->tuple = maybeClone( tuple );
     229                newtype->tuple = maybeCopy( tuple );
    230230                break;
    231231        case Typeof:
    232232        case Basetypeof:
    233                 newtype->typeexpr = maybeClone( typeexpr );
     233                newtype->typeexpr = maybeCopy( typeexpr );
    234234                break;
    235235        case Vtable:
     
    240240                break;
    241241        case Qualified:
    242                 newtype->qualified.parent = maybeClone( qualified.parent );
    243                 newtype->qualified.child = maybeClone( qualified.child );
     242                newtype->qualified.parent = maybeCopy( qualified.parent );
     243                newtype->qualified.child = maybeCopy( qualified.child );
    244244                break;
    245245        } // switch
  • src/Parser/parser.yy

    r59c8dff rf988834  
    19601960                        // Append the return type at the start (left-hand-side) to each identifier in the list.
    19611961                        DeclarationNode * ret = new DeclarationNode;
    1962                         ret->type = maybeClone( $1->type->base );
     1962                        ret->type = maybeCopy( $1->type->base );
    19631963                        $$ = $1->appendList( DeclarationNode::newFunction( $3, ret, $6, nullptr ) );
    19641964                }
  • src/Parser/parserutility.h

    r59c8dff rf988834  
    3636
    3737template<typename node_t>
    38 node_t * maybeCopy( node_t const * node ) {
     38static inline node_t * maybeCopy( node_t const * node ) {
    3939        return node ? ast::shallowCopy( node ) : nullptr;
    4040}
  • src/SymTab/GenImplicitCall.cpp

    r59c8dff rf988834  
    2525#include "CodeGen/OperatorTable.h"       // for isCtorDtor
    2626#include "Common/UniqueName.h"           // for UniqueName
     27#include "Common/utility.h"              // for splice
    2728
    2829namespace SymTab {
  • src/Validate/Autogen.cpp

    r59c8dff rf988834  
    445445
    446446                auto * paramType = ast::deepCopy( member->get_type() );
    447                 paramType->attributes.clear();
     447                erase_if( paramType->attributes, []( ast::Attribute const * attr ){
     448                        return !attr->isValidOnFuncParam();
     449                } );
    448450                ast::ObjectDecl * param = new ast::ObjectDecl(
    449451                        getLocation(), member->name, paramType );
  • src/Validate/ReplaceTypedef.cpp

    r59c8dff rf988834  
    2525
    2626namespace {
    27 
    28 bool isNonParameterAttribute( ast::Attribute const * attr ) {
    29         static const std::vector<std::string> bad_names = {
    30                 "aligned", "__aligned__",
    31         };
    32         for ( auto name : bad_names ) {
    33                 if ( name == attr->name ) {
    34                         return true;
    35                 }
    36         }
    37         return false;
    38 }
    3927
    4028struct ReplaceTypedefCore final :
     
    10189                // by typedef. GCC appears to do the same thing.
    10290                if ( isAtFunctionTop ) {
    103                         erase_if( ret->attributes, isNonParameterAttribute );
     91                        erase_if( ret->attributes, []( ast::Attribute const * attr ){
     92                                return !attr->isValidOnFuncParam();
     93                        } );
    10494                }
    10595                for ( const auto & attribute : type->attributes ) {
  • tests/Makefile.am

    r59c8dff rf988834  
    9292        concurrency/channels/parallel_harness.hfa \
    9393        array-collections/dimexpr-match.hfa \
    94         array-collections/dimexpr-match-detail.sh
     94        array-collections/dimexpr-match-detail.sh \
     95        array-collections/array-raii.hfa
    9596
    9697dist-hook:
  • tests/collections/.expect/string-api-coverage.txt

    r59c8dff rf988834  
    1414true false
    1515true false
     161234567
    1617123
    1718hello
     19hell
    1820hello
    1921world
    2022hello
    2123world
     24Q
     251234567
     26hello
     27Q
     28123
     29hell
     301234567
     31hello
     32123
     33hell
    22345
    2335helloworld
     
    2941hello, friend
    3042bye, friend
     43ohello
     44ohell
     45ohell
     46omydarling
     47omy
     48omy
     49hellohellohellohello
    3150hellohellohello
    3251QQQ
    3352asdfasdfasdf
     53lo
     54hello heliocentric
    3455e
    3556help!!!o
  • tests/collections/.expect/string-compare.txt

    r59c8dff rf988834  
    11------- string -------
    2 (cmp(s_, s_) == 0) ok
     2(strcmp(s_, s_) == 0) ok
    33(s_ == s_) ok
    44!(s_ != s_) ok
     
    77(s_ <= s_) ok
    88!(s_ < s_) ok
    9 (cmp("", s_) == 0) ok
     9(strcmp("", s_) == 0) ok
    1010("" == s_) ok
    1111!("" != s_) ok
     
    1414("" <= s_) ok
    1515!("" < s_) ok
    16 (cmp(s_, "") == 0) ok
     16(strcmp(s_, "") == 0) ok
    1717(s_ == "") ok
    1818!(s_ != "") ok
     
    2121(s_ <= "") ok
    2222!(s_ < "") ok
    23 (cmp(s_, s_a) < 0) ok
     23(strcmp(s_, s_a) < 0) ok
    2424!(s_ == s_a) ok
    2525(s_ != s_a) ok
     
    2828(s_ <= s_a) ok
    2929(s_ < s_a) ok
    30 (cmp("", s_a) < 0) ok
     30(strcmp("", s_a) < 0) ok
    3131!("" == s_a) ok
    3232("" != s_a) ok
     
    3535("" <= s_a) ok
    3636("" < s_a) ok
    37 (cmp(s_, "a") < 0) ok
     37(strcmp(s_, "a") < 0) ok
    3838!(s_ == "a") ok
    3939(s_ != "a") ok
     
    4242(s_ <= "a") ok
    4343(s_ < "a") ok
    44 (cmp(s_a, s_) > 0) ok
     44(strcmp(s_a, s_) > 0) ok
    4545!(s_a == s_) ok
    4646(s_a != s_) ok
     
    4949!(s_a <= s_) ok
    5050!(s_a < s_) ok
    51 (cmp("a", s_) > 0) ok
     51(strcmp("a", s_) > 0) ok
    5252!("a" == s_) ok
    5353("a" != s_) ok
     
    5656!("a" <= s_) ok
    5757!("a" < s_) ok
    58 (cmp(s_a, "") > 0) ok
     58(strcmp(s_a, "") > 0) ok
    5959!(s_a == "") ok
    6060(s_a != "") ok
     
    6363!(s_a <= "") ok
    6464!(s_a < "") ok
    65 (cmp(s_, s_aa) < 0) ok
     65(strcmp(s_, s_aa) < 0) ok
    6666!(s_ == s_aa) ok
    6767(s_ != s_aa) ok
     
    7070(s_ <= s_aa) ok
    7171(s_ < s_aa) ok
    72 (cmp("", s_aa) < 0) ok
     72(strcmp("", s_aa) < 0) ok
    7373!("" == s_aa) ok
    7474("" != s_aa) ok
     
    7777("" <= s_aa) ok
    7878("" < s_aa) ok
    79 (cmp(s_, "aa") < 0) ok
     79(strcmp(s_, "aa") < 0) ok
    8080!(s_ == "aa") ok
    8181(s_ != "aa") ok
     
    8484(s_ <= "aa") ok
    8585(s_ < "aa") ok
    86 (cmp(s_aa, s_) > 0) ok
     86(strcmp(s_aa, s_) > 0) ok
    8787!(s_aa == s_) ok
    8888(s_aa != s_) ok
     
    9191!(s_aa <= s_) ok
    9292!(s_aa < s_) ok
    93 (cmp("aa", s_) > 0) ok
     93(strcmp("aa", s_) > 0) ok
    9494!("aa" == s_) ok
    9595("aa" != s_) ok
     
    9898!("aa" <= s_) ok
    9999!("aa" < s_) ok
    100 (cmp(s_aa, "") > 0) ok
     100(strcmp(s_aa, "") > 0) ok
    101101!(s_aa == "") ok
    102102(s_aa != "") ok
     
    105105!(s_aa <= "") ok
    106106!(s_aa < "") ok
    107 (cmp(s_a, s_aa) < 0) ok
     107(strcmp(s_a, s_aa) < 0) ok
    108108!(s_a == s_aa) ok
    109109(s_a != s_aa) ok
     
    112112(s_a <= s_aa) ok
    113113(s_a < s_aa) ok
    114 (cmp("a", s_aa) < 0) ok
     114(strcmp("a", s_aa) < 0) ok
    115115!("a" == s_aa) ok
    116116("a" != s_aa) ok
     
    119119("a" <= s_aa) ok
    120120("a" < s_aa) ok
    121 (cmp(s_a, "aa") < 0) ok
     121(strcmp(s_a, "aa") < 0) ok
    122122!(s_a == "aa") ok
    123123(s_a != "aa") ok
     
    126126(s_a <= "aa") ok
    127127(s_a < "aa") ok
    128 (cmp(s_aa, s_a) > 0) ok
     128(strcmp(s_aa, s_a) > 0) ok
    129129!(s_aa == s_a) ok
    130130(s_aa != s_a) ok
     
    133133!(s_aa <= s_a) ok
    134134!(s_aa < s_a) ok
    135 (cmp("aa", s_a) > 0) ok
     135(strcmp("aa", s_a) > 0) ok
    136136!("aa" == s_a) ok
    137137("aa" != s_a) ok
     
    140140!("aa" <= s_a) ok
    141141!("aa" < s_a) ok
    142 (cmp(s_aa, "a") > 0) ok
     142(strcmp(s_aa, "a") > 0) ok
    143143!(s_aa == "a") ok
    144144(s_aa != "a") ok
     
    147147!(s_aa <= "a") ok
    148148!(s_aa < "a") ok
    149 (cmp(s_a, s_a) == 0) ok
     149(strcmp(s_a, s_a) == 0) ok
    150150(s_a == s_a) ok
    151151!(s_a != s_a) ok
     
    154154(s_a <= s_a) ok
    155155!(s_a < s_a) ok
    156 (cmp("a", s_a) == 0) ok
     156(strcmp("a", s_a) == 0) ok
    157157("a" == s_a) ok
    158158!("a" != s_a) ok
     
    161161("a" <= s_a) ok
    162162!("a" < s_a) ok
    163 (cmp(s_a, "a") == 0) ok
     163(strcmp(s_a, "a") == 0) ok
    164164(s_a == "a") ok
    165165!(s_a != "a") ok
     
    168168(s_a <= "a") ok
    169169!(s_a < "a") ok
    170 (cmp(s_aa, s_aa) == 0) ok
     170(strcmp(s_aa, s_aa) == 0) ok
    171171(s_aa == s_aa) ok
    172172!(s_aa != s_aa) ok
     
    175175(s_aa <= s_aa) ok
    176176!(s_aa < s_aa) ok
    177 (cmp("aa", s_aa) == 0) ok
     177(strcmp("aa", s_aa) == 0) ok
    178178("aa" == s_aa) ok
    179179!("aa" != s_aa) ok
     
    182182("aa" <= s_aa) ok
    183183!("aa" < s_aa) ok
    184 (cmp(s_aa, "aa") == 0) ok
     184(strcmp(s_aa, "aa") == 0) ok
    185185(s_aa == "aa") ok
    186186!(s_aa != "aa") ok
     
    189189(s_aa <= "aa") ok
    190190!(s_aa < "aa") ok
    191 (cmp(s_a, s_b) < 0) ok
     191(strcmp(s_a, s_b) < 0) ok
    192192!(s_a == s_b) ok
    193193(s_a != s_b) ok
     
    196196(s_a <= s_b) ok
    197197(s_a < s_b) ok
    198 (cmp("a", s_b) < 0) ok
     198(strcmp("a", s_b) < 0) ok
    199199!("a" == s_b) ok
    200200("a" != s_b) ok
     
    203203("a" <= s_b) ok
    204204("a" < s_b) ok
    205 (cmp(s_a, "b") < 0) ok
     205(strcmp(s_a, "b") < 0) ok
    206206!(s_a == "b") ok
    207207(s_a != "b") ok
     
    210210(s_a <= "b") ok
    211211(s_a < "b") ok
    212 (cmp(s_b, s_a) > 0) ok
     212(strcmp(s_b, s_a) > 0) ok
    213213!(s_b == s_a) ok
    214214(s_b != s_a) ok
     
    217217!(s_b <= s_a) ok
    218218!(s_b < s_a) ok
    219 (cmp("b", s_a) > 0) ok
     219(strcmp("b", s_a) > 0) ok
    220220!("b" == s_a) ok
    221221("b" != s_a) ok
     
    224224!("b" <= s_a) ok
    225225!("b" < s_a) ok
    226 (cmp(s_b, "a") > 0) ok
     226(strcmp(s_b, "a") > 0) ok
    227227!(s_b == "a") ok
    228228(s_b != "a") ok
     
    231231!(s_b <= "a") ok
    232232!(s_b < "a") ok
    233 (cmp(s_a, s_ba) < 0) ok
     233(strcmp(s_a, s_ba) < 0) ok
    234234!(s_a == s_ba) ok
    235235(s_a != s_ba) ok
     
    238238(s_a <= s_ba) ok
    239239(s_a < s_ba) ok
    240 (cmp("a", s_ba) < 0) ok
     240(strcmp("a", s_ba) < 0) ok
    241241!("a" == s_ba) ok
    242242("a" != s_ba) ok
     
    245245("a" <= s_ba) ok
    246246("a" < s_ba) ok
    247 (cmp(s_a, "ba") < 0) ok
     247(strcmp(s_a, "ba") < 0) ok
    248248!(s_a == "ba") ok
    249249(s_a != "ba") ok
     
    252252(s_a <= "ba") ok
    253253(s_a < "ba") ok
    254 (cmp(s_ba, s_a) > 0) ok
     254(strcmp(s_ba, s_a) > 0) ok
    255255!(s_ba == s_a) ok
    256256(s_ba != s_a) ok
     
    259259!(s_ba <= s_a) ok
    260260!(s_ba < s_a) ok
    261 (cmp("ba", s_a) > 0) ok
     261(strcmp("ba", s_a) > 0) ok
    262262!("ba" == s_a) ok
    263263("ba" != s_a) ok
     
    266266!("ba" <= s_a) ok
    267267!("ba" < s_a) ok
    268 (cmp(s_ba, "a") > 0) ok
     268(strcmp(s_ba, "a") > 0) ok
    269269!(s_ba == "a") ok
    270270(s_ba != "a") ok
     
    273273!(s_ba <= "a") ok
    274274!(s_ba < "a") ok
    275 (cmp(s_aa, s_ab) < 0) ok
     275(strcmp(s_aa, s_ab) < 0) ok
    276276!(s_aa == s_ab) ok
    277277(s_aa != s_ab) ok
     
    280280(s_aa <= s_ab) ok
    281281(s_aa < s_ab) ok
    282 (cmp("aa", s_ab) < 0) ok
     282(strcmp("aa", s_ab) < 0) ok
    283283!("aa" == s_ab) ok
    284284("aa" != s_ab) ok
     
    287287("aa" <= s_ab) ok
    288288("aa" < s_ab) ok
    289 (cmp(s_aa, "ab") < 0) ok
     289(strcmp(s_aa, "ab") < 0) ok
    290290!(s_aa == "ab") ok
    291291(s_aa != "ab") ok
     
    294294(s_aa <= "ab") ok
    295295(s_aa < "ab") ok
    296 (cmp(s_ab, s_aa) > 0) ok
     296(strcmp(s_ab, s_aa) > 0) ok
    297297!(s_ab == s_aa) ok
    298298(s_ab != s_aa) ok
     
    301301!(s_ab <= s_aa) ok
    302302!(s_ab < s_aa) ok
    303 (cmp("ab", s_aa) > 0) ok
     303(strcmp("ab", s_aa) > 0) ok
    304304!("ab" == s_aa) ok
    305305("ab" != s_aa) ok
     
    308308!("ab" <= s_aa) ok
    309309!("ab" < s_aa) ok
    310 (cmp(s_ab, "aa") > 0) ok
     310(strcmp(s_ab, "aa") > 0) ok
    311311!(s_ab == "aa") ok
    312312(s_ab != "aa") ok
     
    315315!(s_ab <= "aa") ok
    316316!(s_ab < "aa") ok
    317 (cmp(s_ba, s_bb) < 0) ok
     317(strcmp(s_ba, s_bb) < 0) ok
    318318!(s_ba == s_bb) ok
    319319(s_ba != s_bb) ok
     
    322322(s_ba <= s_bb) ok
    323323(s_ba < s_bb) ok
    324 (cmp("ba", s_bb) < 0) ok
     324(strcmp("ba", s_bb) < 0) ok
    325325!("ba" == s_bb) ok
    326326("ba" != s_bb) ok
     
    329329("ba" <= s_bb) ok
    330330("ba" < s_bb) ok
    331 (cmp(s_ba, "bb") < 0) ok
     331(strcmp(s_ba, "bb") < 0) ok
    332332!(s_ba == "bb") ok
    333333(s_ba != "bb") ok
     
    336336(s_ba <= "bb") ok
    337337(s_ba < "bb") ok
    338 (cmp(s_bb, s_ba) > 0) ok
     338(strcmp(s_bb, s_ba) > 0) ok
    339339!(s_bb == s_ba) ok
    340340(s_bb != s_ba) ok
     
    343343!(s_bb <= s_ba) ok
    344344!(s_bb < s_ba) ok
    345 (cmp("bb", s_ba) > 0) ok
     345(strcmp("bb", s_ba) > 0) ok
    346346!("bb" == s_ba) ok
    347347("bb" != s_ba) ok
     
    350350!("bb" <= s_ba) ok
    351351!("bb" < s_ba) ok
    352 (cmp(s_bb, "ba") > 0) ok
     352(strcmp(s_bb, "ba") > 0) ok
    353353!(s_bb == "ba") ok
    354354(s_bb != "ba") ok
     
    357357!(s_bb <= "ba") ok
    358358!(s_bb < "ba") ok
    359 (cmp(s_aa, s_b) < 0) ok
     359(strcmp(s_aa, s_b) < 0) ok
    360360!(s_aa == s_b) ok
    361361(s_aa != s_b) ok
     
    364364(s_aa <= s_b) ok
    365365(s_aa < s_b) ok
    366 (cmp("aa", s_b) < 0) ok
     366(strcmp("aa", s_b) < 0) ok
    367367!("aa" == s_b) ok
    368368("aa" != s_b) ok
     
    371371("aa" <= s_b) ok
    372372("aa" < s_b) ok
    373 (cmp(s_aa, "b") < 0) ok
     373(strcmp(s_aa, "b") < 0) ok
    374374!(s_aa == "b") ok
    375375(s_aa != "b") ok
     
    378378(s_aa <= "b") ok
    379379(s_aa < "b") ok
    380 (cmp(s_b, s_aa) > 0) ok
     380(strcmp(s_b, s_aa) > 0) ok
    381381!(s_b == s_aa) ok
    382382(s_b != s_aa) ok
     
    385385!(s_b <= s_aa) ok
    386386!(s_b < s_aa) ok
    387 (cmp("b", s_aa) > 0) ok
     387(strcmp("b", s_aa) > 0) ok
    388388!("b" == s_aa) ok
    389389("b" != s_aa) ok
     
    392392!("b" <= s_aa) ok
    393393!("b" < s_aa) ok
    394 (cmp(s_b, "aa") > 0) ok
     394(strcmp(s_b, "aa") > 0) ok
    395395!(s_b == "aa") ok
    396396(s_b != "aa") ok
     
    400400!(s_b < "aa") ok
    401401------- string_res -------
    402 (cmp(s_, s_) == 0) ok
     402(strcmp(s_, s_) == 0) ok
    403403(s_ == s_) ok
    404404!(s_ != s_) ok
     
    407407(s_ <= s_) ok
    408408!(s_ < s_) ok
    409 (cmp("", s_) == 0) ok
     409(strcmp("", s_) == 0) ok
    410410("" == s_) ok
    411411!("" != s_) ok
     
    414414("" <= s_) ok
    415415!("" < s_) ok
    416 (cmp(s_, "") == 0) ok
     416(strcmp(s_, "") == 0) ok
    417417(s_ == "") ok
    418418!(s_ != "") ok
     
    421421(s_ <= "") ok
    422422!(s_ < "") ok
    423 (cmp(s_, s_a) < 0) ok
     423(strcmp(s_, s_a) < 0) ok
    424424!(s_ == s_a) ok
    425425(s_ != s_a) ok
     
    428428(s_ <= s_a) ok
    429429(s_ < s_a) ok
    430 (cmp("", s_a) < 0) ok
     430(strcmp("", s_a) < 0) ok
    431431!("" == s_a) ok
    432432("" != s_a) ok
     
    435435("" <= s_a) ok
    436436("" < s_a) ok
    437 (cmp(s_, "a") < 0) ok
     437(strcmp(s_, "a") < 0) ok
    438438!(s_ == "a") ok
    439439(s_ != "a") ok
     
    442442(s_ <= "a") ok
    443443(s_ < "a") ok
    444 (cmp(s_a, s_) > 0) ok
     444(strcmp(s_a, s_) > 0) ok
    445445!(s_a == s_) ok
    446446(s_a != s_) ok
     
    449449!(s_a <= s_) ok
    450450!(s_a < s_) ok
    451 (cmp("a", s_) > 0) ok
     451(strcmp("a", s_) > 0) ok
    452452!("a" == s_) ok
    453453("a" != s_) ok
     
    456456!("a" <= s_) ok
    457457!("a" < s_) ok
    458 (cmp(s_a, "") > 0) ok
     458(strcmp(s_a, "") > 0) ok
    459459!(s_a == "") ok
    460460(s_a != "") ok
     
    463463!(s_a <= "") ok
    464464!(s_a < "") ok
    465 (cmp(s_, s_aa) < 0) ok
     465(strcmp(s_, s_aa) < 0) ok
    466466!(s_ == s_aa) ok
    467467(s_ != s_aa) ok
     
    470470(s_ <= s_aa) ok
    471471(s_ < s_aa) ok
    472 (cmp("", s_aa) < 0) ok
     472(strcmp("", s_aa) < 0) ok
    473473!("" == s_aa) ok
    474474("" != s_aa) ok
     
    477477("" <= s_aa) ok
    478478("" < s_aa) ok
    479 (cmp(s_, "aa") < 0) ok
     479(strcmp(s_, "aa") < 0) ok
    480480!(s_ == "aa") ok
    481481(s_ != "aa") ok
     
    484484(s_ <= "aa") ok
    485485(s_ < "aa") ok
    486 (cmp(s_aa, s_) > 0) ok
     486(strcmp(s_aa, s_) > 0) ok
    487487!(s_aa == s_) ok
    488488(s_aa != s_) ok
     
    491491!(s_aa <= s_) ok
    492492!(s_aa < s_) ok
    493 (cmp("aa", s_) > 0) ok
     493(strcmp("aa", s_) > 0) ok
    494494!("aa" == s_) ok
    495495("aa" != s_) ok
     
    498498!("aa" <= s_) ok
    499499!("aa" < s_) ok
    500 (cmp(s_aa, "") > 0) ok
     500(strcmp(s_aa, "") > 0) ok
    501501!(s_aa == "") ok
    502502(s_aa != "") ok
     
    505505!(s_aa <= "") ok
    506506!(s_aa < "") ok
    507 (cmp(s_a, s_aa) < 0) ok
     507(strcmp(s_a, s_aa) < 0) ok
    508508!(s_a == s_aa) ok
    509509(s_a != s_aa) ok
     
    512512(s_a <= s_aa) ok
    513513(s_a < s_aa) ok
    514 (cmp("a", s_aa) < 0) ok
     514(strcmp("a", s_aa) < 0) ok
    515515!("a" == s_aa) ok
    516516("a" != s_aa) ok
     
    519519("a" <= s_aa) ok
    520520("a" < s_aa) ok
    521 (cmp(s_a, "aa") < 0) ok
     521(strcmp(s_a, "aa") < 0) ok
    522522!(s_a == "aa") ok
    523523(s_a != "aa") ok
     
    526526(s_a <= "aa") ok
    527527(s_a < "aa") ok
    528 (cmp(s_aa, s_a) > 0) ok
     528(strcmp(s_aa, s_a) > 0) ok
    529529!(s_aa == s_a) ok
    530530(s_aa != s_a) ok
     
    533533!(s_aa <= s_a) ok
    534534!(s_aa < s_a) ok
    535 (cmp("aa", s_a) > 0) ok
     535(strcmp("aa", s_a) > 0) ok
    536536!("aa" == s_a) ok
    537537("aa" != s_a) ok
     
    540540!("aa" <= s_a) ok
    541541!("aa" < s_a) ok
    542 (cmp(s_aa, "a") > 0) ok
     542(strcmp(s_aa, "a") > 0) ok
    543543!(s_aa == "a") ok
    544544(s_aa != "a") ok
     
    547547!(s_aa <= "a") ok
    548548!(s_aa < "a") ok
    549 (cmp(s_a, s_a) == 0) ok
     549(strcmp(s_a, s_a) == 0) ok
    550550(s_a == s_a) ok
    551551!(s_a != s_a) ok
     
    554554(s_a <= s_a) ok
    555555!(s_a < s_a) ok
    556 (cmp("a", s_a) == 0) ok
     556(strcmp("a", s_a) == 0) ok
    557557("a" == s_a) ok
    558558!("a" != s_a) ok
     
    561561("a" <= s_a) ok
    562562!("a" < s_a) ok
    563 (cmp(s_a, "a") == 0) ok
     563(strcmp(s_a, "a") == 0) ok
    564564(s_a == "a") ok
    565565!(s_a != "a") ok
     
    568568(s_a <= "a") ok
    569569!(s_a < "a") ok
    570 (cmp(s_aa, s_aa) == 0) ok
     570(strcmp(s_aa, s_aa) == 0) ok
    571571(s_aa == s_aa) ok
    572572!(s_aa != s_aa) ok
     
    575575(s_aa <= s_aa) ok
    576576!(s_aa < s_aa) ok
    577 (cmp("aa", s_aa) == 0) ok
     577(strcmp("aa", s_aa) == 0) ok
    578578("aa" == s_aa) ok
    579579!("aa" != s_aa) ok
     
    582582("aa" <= s_aa) ok
    583583!("aa" < s_aa) ok
    584 (cmp(s_aa, "aa") == 0) ok
     584(strcmp(s_aa, "aa") == 0) ok
    585585(s_aa == "aa") ok
    586586!(s_aa != "aa") ok
     
    589589(s_aa <= "aa") ok
    590590!(s_aa < "aa") ok
    591 (cmp(s_a, s_b) < 0) ok
     591(strcmp(s_a, s_b) < 0) ok
    592592!(s_a == s_b) ok
    593593(s_a != s_b) ok
     
    596596(s_a <= s_b) ok
    597597(s_a < s_b) ok
    598 (cmp("a", s_b) < 0) ok
     598(strcmp("a", s_b) < 0) ok
    599599!("a" == s_b) ok
    600600("a" != s_b) ok
     
    603603("a" <= s_b) ok
    604604("a" < s_b) ok
    605 (cmp(s_a, "b") < 0) ok
     605(strcmp(s_a, "b") < 0) ok
    606606!(s_a == "b") ok
    607607(s_a != "b") ok
     
    610610(s_a <= "b") ok
    611611(s_a < "b") ok
    612 (cmp(s_b, s_a) > 0) ok
     612(strcmp(s_b, s_a) > 0) ok
    613613!(s_b == s_a) ok
    614614(s_b != s_a) ok
     
    617617!(s_b <= s_a) ok
    618618!(s_b < s_a) ok
    619 (cmp("b", s_a) > 0) ok
     619(strcmp("b", s_a) > 0) ok
    620620!("b" == s_a) ok
    621621("b" != s_a) ok
     
    624624!("b" <= s_a) ok
    625625!("b" < s_a) ok
    626 (cmp(s_b, "a") > 0) ok
     626(strcmp(s_b, "a") > 0) ok
    627627!(s_b == "a") ok
    628628(s_b != "a") ok
     
    631631!(s_b <= "a") ok
    632632!(s_b < "a") ok
    633 (cmp(s_a, s_ba) < 0) ok
     633(strcmp(s_a, s_ba) < 0) ok
    634634!(s_a == s_ba) ok
    635635(s_a != s_ba) ok
     
    638638(s_a <= s_ba) ok
    639639(s_a < s_ba) ok
    640 (cmp("a", s_ba) < 0) ok
     640(strcmp("a", s_ba) < 0) ok
    641641!("a" == s_ba) ok
    642642("a" != s_ba) ok
     
    645645("a" <= s_ba) ok
    646646("a" < s_ba) ok
    647 (cmp(s_a, "ba") < 0) ok
     647(strcmp(s_a, "ba") < 0) ok
    648648!(s_a == "ba") ok
    649649(s_a != "ba") ok
     
    652652(s_a <= "ba") ok
    653653(s_a < "ba") ok
    654 (cmp(s_ba, s_a) > 0) ok
     654(strcmp(s_ba, s_a) > 0) ok
    655655!(s_ba == s_a) ok
    656656(s_ba != s_a) ok
     
    659659!(s_ba <= s_a) ok
    660660!(s_ba < s_a) ok
    661 (cmp("ba", s_a) > 0) ok
     661(strcmp("ba", s_a) > 0) ok
    662662!("ba" == s_a) ok
    663663("ba" != s_a) ok
     
    666666!("ba" <= s_a) ok
    667667!("ba" < s_a) ok
    668 (cmp(s_ba, "a") > 0) ok
     668(strcmp(s_ba, "a") > 0) ok
    669669!(s_ba == "a") ok
    670670(s_ba != "a") ok
     
    673673!(s_ba <= "a") ok
    674674!(s_ba < "a") ok
    675 (cmp(s_aa, s_ab) < 0) ok
     675(strcmp(s_aa, s_ab) < 0) ok
    676676!(s_aa == s_ab) ok
    677677(s_aa != s_ab) ok
     
    680680(s_aa <= s_ab) ok
    681681(s_aa < s_ab) ok
    682 (cmp("aa", s_ab) < 0) ok
     682(strcmp("aa", s_ab) < 0) ok
    683683!("aa" == s_ab) ok
    684684("aa" != s_ab) ok
     
    687687("aa" <= s_ab) ok
    688688("aa" < s_ab) ok
    689 (cmp(s_aa, "ab") < 0) ok
     689(strcmp(s_aa, "ab") < 0) ok
    690690!(s_aa == "ab") ok
    691691(s_aa != "ab") ok
     
    694694(s_aa <= "ab") ok
    695695(s_aa < "ab") ok
    696 (cmp(s_ab, s_aa) > 0) ok
     696(strcmp(s_ab, s_aa) > 0) ok
    697697!(s_ab == s_aa) ok
    698698(s_ab != s_aa) ok
     
    701701!(s_ab <= s_aa) ok
    702702!(s_ab < s_aa) ok
    703 (cmp("ab", s_aa) > 0) ok
     703(strcmp("ab", s_aa) > 0) ok
    704704!("ab" == s_aa) ok
    705705("ab" != s_aa) ok
     
    708708!("ab" <= s_aa) ok
    709709!("ab" < s_aa) ok
    710 (cmp(s_ab, "aa") > 0) ok
     710(strcmp(s_ab, "aa") > 0) ok
    711711!(s_ab == "aa") ok
    712712(s_ab != "aa") ok
     
    715715!(s_ab <= "aa") ok
    716716!(s_ab < "aa") ok
    717 (cmp(s_ba, s_bb) < 0) ok
     717(strcmp(s_ba, s_bb) < 0) ok
    718718!(s_ba == s_bb) ok
    719719(s_ba != s_bb) ok
     
    722722(s_ba <= s_bb) ok
    723723(s_ba < s_bb) ok
    724 (cmp("ba", s_bb) < 0) ok
     724(strcmp("ba", s_bb) < 0) ok
    725725!("ba" == s_bb) ok
    726726("ba" != s_bb) ok
     
    729729("ba" <= s_bb) ok
    730730("ba" < s_bb) ok
    731 (cmp(s_ba, "bb") < 0) ok
     731(strcmp(s_ba, "bb") < 0) ok
    732732!(s_ba == "bb") ok
    733733(s_ba != "bb") ok
     
    736736(s_ba <= "bb") ok
    737737(s_ba < "bb") ok
    738 (cmp(s_bb, s_ba) > 0) ok
     738(strcmp(s_bb, s_ba) > 0) ok
    739739!(s_bb == s_ba) ok
    740740(s_bb != s_ba) ok
     
    743743!(s_bb <= s_ba) ok
    744744!(s_bb < s_ba) ok
    745 (cmp("bb", s_ba) > 0) ok
     745(strcmp("bb", s_ba) > 0) ok
    746746!("bb" == s_ba) ok
    747747("bb" != s_ba) ok
     
    750750!("bb" <= s_ba) ok
    751751!("bb" < s_ba) ok
    752 (cmp(s_bb, "ba") > 0) ok
     752(strcmp(s_bb, "ba") > 0) ok
    753753!(s_bb == "ba") ok
    754754(s_bb != "ba") ok
     
    757757!(s_bb <= "ba") ok
    758758!(s_bb < "ba") ok
    759 (cmp(s_aa, s_b) < 0) ok
     759(strcmp(s_aa, s_b) < 0) ok
    760760!(s_aa == s_b) ok
    761761(s_aa != s_b) ok
     
    764764(s_aa <= s_b) ok
    765765(s_aa < s_b) ok
    766 (cmp("aa", s_b) < 0) ok
     766(strcmp("aa", s_b) < 0) ok
    767767!("aa" == s_b) ok
    768768("aa" != s_b) ok
     
    771771("aa" <= s_b) ok
    772772("aa" < s_b) ok
    773 (cmp(s_aa, "b") < 0) ok
     773(strcmp(s_aa, "b") < 0) ok
    774774!(s_aa == "b") ok
    775775(s_aa != "b") ok
     
    778778(s_aa <= "b") ok
    779779(s_aa < "b") ok
    780 (cmp(s_b, s_aa) > 0) ok
     780(strcmp(s_b, s_aa) > 0) ok
    781781!(s_b == s_aa) ok
    782782(s_b != s_aa) ok
     
    785785!(s_b <= s_aa) ok
    786786!(s_b < s_aa) ok
    787 (cmp("b", s_aa) > 0) ok
     787(strcmp("b", s_aa) > 0) ok
    788788!("b" == s_aa) ok
    789789("b" != s_aa) ok
     
    792792!("b" <= s_aa) ok
    793793!("b" < s_aa) ok
    794 (cmp(s_b, "aa") > 0) ok
     794(strcmp(s_b, "aa") > 0) ok
    795795!(s_b == "aa") ok
    796796(s_b != "aa") ok
  • tests/collections/.expect/string-istream-manip.txt

    r59c8dff rf988834  
    696913 wwwwwwww
    707014 cccc
    71 15 q
     7115
    72721 yyyyyyyyyyyyyyyyyyyy
    73732 abcxxx
     
    848413 wwwwwwww
    858514 cccc
    86 15 q
     8615
  • tests/collections/string-api-coverage.cfa

    r59c8dff rf988834  
    5151    sout | (s == "hello") | (s == "world");
    5252    sout | (s != "world") | (s != "hello");
    53     sout | ( frag == s(1,4) ) | ( s3   == s(1,4) );
    54     sout | ( s3   != s(1,4) ) | ( frag != s(1,4) );
    55     sout | ( s2(1,4) == s(1,4) ) | ( s3(1,4)   == s(1,4) );
    56     sout | ( s3(1,4) != s(1,4) ) | ( s2(1,4)   != s(1,4) );
    57     sout | ( s(1,4) == frag ) | ( s(1,4) == s3   );
    58     sout | ( s(1,4) != s3   ) | ( s(1,4) != frag );
    59     sout | ( s(1,4) == "ell"   ) | ( s(1,4) == "world" );
    60     sout | ( s(1,4) != "world" ) | ( s(1,4) != "ell"   );
     53    sout | ( frag == s(1,3) ) | ( s3   == s(1,3) );
     54    sout | ( s3   != s(1,3) ) | ( frag != s(1,3) );
     55    sout | ( s2(1,3) == s(1,3) ) | ( s3(1,3)   == s(1,3) );
     56    sout | ( s3(1,3) != s(1,3) ) | ( s2(1,3)   != s(1,3) );
     57    sout | ( s(1,3) == frag ) | ( s(1,3) == s3   );
     58    sout | ( s(1,3) != s3   ) | ( s(1,3) != frag );
     59    sout | ( s(1,3) == "ell"   ) | ( s(1,3) == "world" );
     60    sout | ( s(1,3) != "world" ) | ( s(1,3) != "ell"   );
    6161
    6262
     
    6666    //
    6767    {
    68         string b1 = { "1234567", 3 };
    69         sout | b1; // 123
     68        string b1 = "1234567";
     69        sout | b1; // 1234567
     70
     71        string b1x = { "1234567", 3 };
     72        sout | b1x; // 123
    7073
    7174        string b2 = s;
    7275        sout | b2; // hello
     76
     77        string b2x = { s, 4 };
     78        sout | b2x; // hell
    7379
    7480        // todo: a plain string &
     
    8894        b4 = s_constref;
    8995        sout | b4;  // world
     96
     97        string b5 = 'Q';
     98        sout | b5; // Q
     99
     100
    90101    }
    91102                                            assertWellFormedHandleList( 10 );
     103    //
     104    // Assignments
     105    //
     106    {
     107        string b = "xxx";
     108
     109        b = "1234567";
     110        sout | b; // 1234567
     111
     112        b = "xxx";
     113        b = s;
     114        sout | b; // hello
     115       
     116        b = "xxx";
     117        b = 'Q';
     118        sout | b; // Q
     119       
     120        b = "xxx";
     121        assign( b, "1234567", 3 );
     122        sout | b; // 123
     123
     124        b = "xxx";
     125        assign( b, s, 4 );
     126        sout | b; // hell
     127
     128        b = "xxx";
     129        strcpy(b, "1234567");
     130        sout | b; // 1234567
     131
     132        b = "xxx";
     133        strcpy(b, s);
     134        sout | b; // hello
     135       
     136        b = "xxx";
     137        strncpy( b, "1234567", 3 );
     138        sout | b; // 123
     139
     140        b = "xxx";
     141        strncpy( b, s, 4 );
     142        sout | b; // hell
     143    }
     144                                            assertWellFormedHandleList( 10 );
     145
     146
    92147
    93148    sout | size(s); // 5
     
    126181    sout | sx; // bye, friend
    127182
     183    sx = "o";
     184    strcat( sx, s );
     185    sout | sx; // ohello
     186
     187    sx = "o";
     188    append( sx, s, 4 );
     189    sout | sx; // ohell
     190
     191    sx = "o";
     192    strncat( sx, s, 4 );
     193    sout | sx; // ohell
     194
     195    sx = "o";
     196    strcat( sx, "mydarling" );
     197    sout | sx; // omydarling
     198
     199    sx = "o";
     200    append( sx, "mydarling", 2 );
     201    sout | sx; // omy
     202
     203    sx = "o";
     204    strncat( sx, "mydarling", 2 );
     205    sout | sx; // omy
     206
    128207    //
    129208    // repetition
    130209    //
     210
     211    sx = s;
     212    sx *= 4;
     213    sout | sx; // hellohellohellohello
     214
    131215    sx = s * 3;
    132216    sout | sx; // hellohellohello
     
    142226    //
    143227
    144     //...
     228    // Range cases treated thoroughly in "string-overwrite" test.
     229    // Composability with comparison and search are demoed above and below.
     230    // Coverage here adds the single-argument ("rest of string") overload.
     231
     232    sx = s;
     233    sout | sx(3); // lo
     234    sx(3) = "iocentric";
     235    sout | s | sx; // hello heliocentric
    145236
    146237    //
     
    244335        | find( alphabet        , "def")  // 3
    245336        | find( alphabet( 0, 26), "def")  // 3
    246         | find( alphabet( 2, 26), "def")  // 1
    247         | find( alphabet( 3, 26), "def")  // 0
    248         | find( alphabet( 4, 26), "def")  // 22, not found
    249         | find( alphabet( 4, 26),  "ef")  // 0
     337        | find( alphabet( 2, 24), "def")  // 1
     338        | find( alphabet( 3, 23), "def")  // 0
     339        | find( alphabet( 4, 22), "def")  // 22, not found
     340        | find( alphabet( 4, 22),  "ef")  // 0
    250341        | find( alphabet( 0,  6), "def")  // 3
    251342        | find( alphabet( 0,  5), "def")  // 5, not found
     
    255346        | includes( alphabet        , "def")  // true
    256347        | includes( alphabet( 0, 26), "def")  // true
    257         | includes( alphabet( 2, 26), "def")  // true
    258         | includes( alphabet( 3, 26), "def")  // true
    259         | includes( alphabet( 4, 26), "def")  // false
    260         | includes( alphabet( 4, 26),  "ef")  // true
     348        | includes( alphabet( 2, 24), "def")  // true
     349        | includes( alphabet( 3, 23), "def")  // true
     350        | includes( alphabet( 4, 22), "def")  // false
     351        | includes( alphabet( 4, 22),  "ef")  // true
    261352        | includes( alphabet( 0,  6), "def")  // true
    262353        | includes( alphabet( 0,  5), "def")  // false
     
    266357        | startsWith( alphabet        , "abc")  // true
    267358        | startsWith( alphabet( 0, 26), "abc")  // true
    268         | startsWith( alphabet( 1, 26), "abc")  // false
    269         | startsWith( alphabet( 1, 26),  "bc")  // true
     359        | startsWith( alphabet( 1, 25), "abc")  // false
     360        | startsWith( alphabet( 1, 25),  "bc")  // true
    270361        | startsWith( alphabet( 0, 26), "abc")  // true
    271362        | startsWith( alphabet( 0,  4), "abc")  // true
     
    281372        | endsWith( alphabet( 0, 25), "xy" )  // true
    282373        | endsWith( alphabet( 0, 26), "xyz")  // true
    283         | endsWith( alphabet(23, 26), "xyz")  // true
    284         | endsWith( alphabet(24, 26), "xyz")  // false
    285         | endsWith( alphabet(24, 26),  "yz")  // true
     374        | endsWith( alphabet(23,  3), "xyz")  // true
     375        | endsWith( alphabet(24,  2), "xyz")  // false
     376        | endsWith( alphabet(24,  2),  "yz")  // true
    286377        | endsWith( alphabet        , "abc"); // false
    287378
  • tests/collections/string-compare.cfa

    r59c8dff rf988834  
    33
    44#define test_eq_(l, r) \
    5     chk( (cmp(l, r) == 0) ) \
     5    chk( (strcmp(l, r) == 0) ) \
    66    chk(  (l == r) ) \
    77    chk( !(l != r) ) \
     
    1717
    1818#define test_lt_(l, r) \
    19     chk( (cmp(l, r) < 0) ) \
     19    chk( (strcmp(l, r) < 0) ) \
    2020    chk( !(l == r) ) \
    2121    chk(  (l != r) ) \
     
    2626
    2727#define test_gt_(l, r) \
    28     chk( (cmp(l, r) > 0) ) \
     28    chk( (strcmp(l, r) > 0) ) \
    2929    chk( !(l == r) ) \
    3030    chk(  (l != r) ) \
  • tests/collections/string-overwrite.cfa

    r59c8dff rf988834  
    99MS = modifier start
    1010ME = modifier end
     11ML = modifier length
    1112WS = witness start
    1213WE = witness end
     14WL = witness length
    1315
    1416The test does:
     
    7173
    7274
    73 void showOneReplacement(string & s, int ms, int me, int ws, int we, const char* replaceWith) {
     75void showOneReplacement(string & s, int ms, int ml, int ws, int wl, const char* replaceWith) {
     76
     77    int me = ms + ml;
     78    int we = ws + wl;
    7479
    7580    assert( ms >= 0 && ms <= me && me <= size(s) );
    7681    assert( ws >= 0 && ws <= we && we <= size(s) );
    7782
    78     string mod = s(ms, me)`shareEdits;
    79     string wit = s(ws, we)`shareEdits;
     83    string mod = s(ms, ml)`shareEdits;
     84    string wit = s(ws, wl)`shareEdits;
    8085
    8186    string modOld = mod;
     
    118123void runReplaceCases() {
    119124    char * alphabetTemplate = "abcdefghijklmnopqrstuvwxyz";
    120     struct { int ms; int me; int ws; int we; char *replaceWith; char *label; } cases[] = {
    121         { 12, 14, 10, 20, "xxxxx", "warmup" },
    122         { 10, 10, 10, 10, "=====", "1"      },
    123         { 10, 10, 10, 10, "=="   , ""       },
    124         { 10, 10, 10, 10, "="    , ""       },
    125         { 10, 10, 10, 10, ""     , ""       },
    126         { 10, 12, 12, 12, "=====", "2"      },
    127         { 10, 12, 12, 12, "=="   , ""       },
    128         { 10, 12, 12, 12, "="    , ""       },
    129         { 10, 12, 12, 12, ""     , ""       },
    130         { 12, 12, 10, 12, "=====", "3"      },
    131         { 12, 12, 10, 12, "=="   , ""       },
    132         { 12, 12, 10, 12, "="    , ""       },
    133         { 12, 12, 10, 12, ""     , ""       },
    134         { 10, 10, 12, 12, "=====", "4"      },
    135         { 10, 10, 12, 12, "=="   , ""       },
    136         { 10, 10, 12, 12, "="    , ""       },
    137         { 10, 10, 12, 12, ""     , ""       },
    138         { 12, 12, 10, 10, "=====", "5"      },
    139         { 12, 12, 10, 10, "=="   , ""       },
    140         { 12, 12, 10, 10, "="    , ""       },
    141         { 12, 12, 10, 10, ""     , ""       },
    142         { 10, 12, 10, 12, "=====", "6"      },
    143         { 10, 12, 10, 12, "=="   , ""       },
    144         { 10, 12, 10, 12, "="    , ""       },
    145         { 10, 12, 10, 12, ""     , ""       },
    146         { 10, 12, 10, 10, "=====", "7"      },
    147         { 10, 12, 10, 10, "=="   , ""       },
    148         { 10, 12, 10, 10, "="    , ""       },
    149         { 10, 12, 10, 10, ""     , ""       },
    150         { 10, 10, 10, 12, "=====", "8"      },
    151         { 10, 10, 10, 12, "=="   , ""       },
    152         { 10, 10, 10, 12, "="    , ""       },
    153         { 10, 10, 10, 12, ""     , ""       },
    154         { 10, 12, 14, 14, "=====", "9"      },
    155         { 10, 12, 14, 14, "=="   , ""       },
    156         { 10, 12, 14, 14, "="    , ""       },
    157         { 10, 12, 14, 14, ""     , ""       },
    158         { 10, 14, 12, 14, "=====", "10"     },
    159         { 10, 14, 12, 14, "=="   , ""       },
    160         { 10, 14, 12, 14, "="    , ""       },  // FORMERLY unrunnable bug: tries to print seemingly infinite string
    161         { 10, 14, 12, 14, ""     , ""       },  // ditto
    162         { 14, 14, 10, 12, "=====", "11"     },
    163         { 14, 14, 10, 12, "=="   , ""       },
    164         { 14, 14, 10, 12, "="    , ""       },
    165         { 14, 14, 10, 12, ""     , ""       },
    166         { 12, 14, 10, 14, "=====", "12"     }, // correctness observation:  watching klmn while mn |-> xxx gives klxxx because the mn is inside what I'm watching
    167         { 12, 14, 10, 14, "=="   , ""       },
    168         { 12, 14, 10, 14, "="    , ""       },
    169         { 12, 14, 10, 14, ""     , ""       },
    170         { 10, 12, 12, 14, "=====", "13"     },
    171         { 10, 12, 12, 14, "=="   , ""       },
    172         { 10, 12, 12, 14, "="    , ""       },
    173         { 10, 12, 12, 14, ""     , ""       },
    174         { 10, 14, 12, 12, "=====", "14"     },
    175         { 10, 14, 12, 12, "=="   , ""       },
    176         { 10, 14, 12, 12, "="    , ""       },
    177         { 10, 14, 12, 12, ""     , ""       },
    178         { 12, 14, 10, 12, "=====", "15"     },
    179         { 12, 14, 10, 12, "=="   , ""       },
    180         { 12, 14, 10, 12, "="    , ""       },
    181         { 12, 14, 10, 12, ""     , ""       },
    182         { 12, 12, 10, 14, "=====", "16"     },
    183         { 12, 12, 10, 14, "=="   , ""       },
    184         { 12, 12, 10, 14, "="    , ""       },
    185         { 12, 12, 10, 14, ""     , ""       },
    186         { 10, 14, 10, 12, "=====", "17"     },
    187         { 10, 14, 10, 12, "=="   , ""       },
    188         { 10, 14, 10, 12, "="    , ""       },
    189         { 10, 14, 10, 12, ""     , ""       },
    190         { 10, 10, 12, 14, "=====", "18"     },
    191         { 10, 10, 12, 14, "=="   , ""       },
    192         { 10, 10, 12, 14, "="    , ""       },
    193         { 10, 10, 12, 14, ""     , ""       },
    194         { 10, 12, 10, 14, "=====", "19"     },
    195         { 10, 12, 10, 14, "=="   , ""       },
    196         { 10, 12, 10, 14, "="    , ""       },
    197         { 10, 12, 10, 14, ""     , ""       },
    198         { 12, 14, 10, 10, "=====", "20"     },
    199         { 12, 14, 10, 10, "=="   , ""       },
    200         { 12, 14, 10, 10, "="    , ""       },
    201         { 12, 14, 10, 10, ""     , ""       },
    202         { 10, 12, 14, 16, "=====", "21"     },
    203         { 10, 12, 14, 16, "=="   , ""       },
    204         { 10, 12, 14, 16, "="    , ""       },
    205         { 10, 12, 14, 16, ""     , ""       },
    206         { 10, 14, 12, 16, "=====", "22"     },
    207         { 10, 14, 12, 16, "=="   , ""       },
    208         { 10, 14, 12, 16, "="    , ""       },
    209         { 10, 14, 12, 16, ""     , ""       },
    210         { 10, 16, 12, 14, "=====", "23"     },
    211         { 10, 16, 12, 14, "=="   , ""       },
    212         { 10, 16, 12, 14, "="    , ""       },
    213         { 10, 16, 12, 14, ""     , ""       },
    214         { 14, 16, 10, 12, "=====", "24"     },
    215         { 14, 16, 10, 12, "=="   , ""       },
    216         { 14, 16, 10, 12, "="    , ""       },
    217         { 14, 16, 10, 12, ""     , ""       },
    218         { 12, 16, 10, 14, "=====", "25"     },
    219         { 12, 16, 10, 14, "=="   , ""       },
    220         { 12, 16, 10, 14, "="    , ""       },
    221         { 12, 16, 10, 14, ""     , ""       },
    222         { 12, 14, 10, 16, "=====", "26"     },
    223         { 12, 14, 10, 16, "=="   , ""       },
    224         { 12, 14, 10, 16, "="    , ""       },
    225         { 12, 14, 10, 16, ""     , ""       },
     125    struct { int ms; int ml; int ws; int wl; char *replaceWith; char *label; } cases[] = {
     126        { 12,  2, 10, 10, "xxxxx", "warmup" },
     127        { 10,  0, 10,  0, "=====", "1"      },
     128        { 10,  0, 10,  0, "=="   , ""       },
     129        { 10,  0, 10,  0, "="    , ""       },
     130        { 10,  0, 10,  0, ""     , ""       },
     131        { 10,  2, 12,  0, "=====", "2"      },
     132        { 10,  2, 12,  0, "=="   , ""       },
     133        { 10,  2, 12,  0, "="    , ""       },
     134        { 10,  2, 12,  0, ""     , ""       },
     135        { 12,  0, 10,  2, "=====", "3"      },
     136        { 12,  0, 10,  2, "=="   , ""       },
     137        { 12,  0, 10,  2, "="    , ""       },
     138        { 12,  0, 10,  2, ""     , ""       },
     139        { 10,  0, 12,  0, "=====", "4"      },
     140        { 10,  0, 12,  0, "=="   , ""       },
     141        { 10,  0, 12,  0, "="    , ""       },
     142        { 10,  0, 12,  0, ""     , ""       },
     143        { 12,  0, 10,  0, "=====", "5"      },
     144        { 12,  0, 10,  0, "=="   , ""       },
     145        { 12,  0, 10,  0, "="    , ""       },
     146        { 12,  0, 10,  0, ""     , ""       },
     147        { 10,  2, 10,  2, "=====", "6"      },
     148        { 10,  2, 10,  2, "=="   , ""       },
     149        { 10,  2, 10,  2, "="    , ""       },
     150        { 10,  2, 10,  2, ""     , ""       },
     151        { 10,  2, 10,  0, "=====", "7"      },
     152        { 10,  2, 10,  0, "=="   , ""       },
     153        { 10,  2, 10,  0, "="    , ""       },
     154        { 10,  2, 10,  0, ""     , ""       },
     155        { 10,  0, 10,  2, "=====", "8"      },
     156        { 10,  0, 10,  2, "=="   , ""       },
     157        { 10,  0, 10,  2, "="    , ""       },
     158        { 10,  0, 10,  2, ""     , ""       },
     159        { 10,  2, 14,  0, "=====", "9"      },
     160        { 10,  2, 14,  0, "=="   , ""       },
     161        { 10,  2, 14,  0, "="    , ""       },
     162        { 10,  2, 14,  0, ""     , ""       },
     163        { 10,  4, 12,  2, "=====", "10"     },
     164        { 10,  4, 12,  2, "=="   , ""       },
     165        { 10,  4, 12,  2, "="    , ""       },  // FORMERLY unrunnable bug: tries to print seemingly infinite string
     166        { 10,  4, 12,  2, ""     , ""       },  // ditto
     167        { 14,  0, 10,  2, "=====", "11"     },
     168        { 14,  0, 10,  2, "=="   , ""       },
     169        { 14,  0, 10,  2, "="    , ""       },
     170        { 14,  0, 10,  2, ""     , ""       },
     171        { 12,  2, 10,  4, "=====", "12"     }, // correctness observation:  watching klmn while mn |-> xxx gives klxxx because the mn is inside what I'm watching
     172        { 12,  2, 10,  4, "=="   , ""       },
     173        { 12,  2, 10,  4, "="    , ""       },
     174        { 12,  2, 10,  4, ""     , ""       },
     175        { 10,  2, 12,  2, "=====", "13"     },
     176        { 10,  2, 12,  2, "=="   , ""       },
     177        { 10,  2, 12,  2, "="    , ""       },
     178        { 10,  2, 12,  2, ""     , ""       },
     179        { 10,  4, 12,  0, "=====", "14"     },
     180        { 10,  4, 12,  0, "=="   , ""       },
     181        { 10,  4, 12,  0, "="    , ""       },
     182        { 10,  4, 12,  0, ""     , ""       },
     183        { 12,  2, 10,  2, "=====", "15"     },
     184        { 12,  2, 10,  2, "=="   , ""       },
     185        { 12,  2, 10,  2, "="    , ""       },
     186        { 12,  2, 10,  2, ""     , ""       },
     187        { 12,  0, 10,  4, "=====", "16"     },
     188        { 12,  0, 10,  4, "=="   , ""       },
     189        { 12,  0, 10,  4, "="    , ""       },
     190        { 12,  0, 10,  4, ""     , ""       },
     191        { 10,  4, 10,  2, "=====", "17"     },
     192        { 10,  4, 10,  2, "=="   , ""       },
     193        { 10,  4, 10,  2, "="    , ""       },
     194        { 10,  4, 10,  2, ""     , ""       },
     195        { 10,  0, 12,  2, "=====", "18"     },
     196        { 10,  0, 12,  2, "=="   , ""       },
     197        { 10,  0, 12,  2, "="    , ""       },
     198        { 10,  0, 12,  2, ""     , ""       },
     199        { 10,  2, 10,  4, "=====", "19"     },
     200        { 10,  2, 10,  4, "=="   , ""       },
     201        { 10,  2, 10,  4, "="    , ""       },
     202        { 10,  2, 10,  4, ""     , ""       },
     203        { 12,  2, 10,  0, "=====", "20"     },
     204        { 12,  2, 10,  0, "=="   , ""       },
     205        { 12,  2, 10,  0, "="    , ""       },
     206        { 12,  2, 10,  0, ""     , ""       },
     207        { 10,  2, 14,  2, "=====", "21"     },
     208        { 10,  2, 14,  2, "=="   , ""       },
     209        { 10,  2, 14,  2, "="    , ""       },
     210        { 10,  2, 14,  2, ""     , ""       },
     211        { 10,  4, 12,  4, "=====", "22"     },
     212        { 10,  4, 12,  4, "=="   , ""       },
     213        { 10,  4, 12,  4, "="    , ""       },
     214        { 10,  4, 12,  4, ""     , ""       },
     215        { 10,  6, 12,  2, "=====", "23"     },
     216        { 10,  6, 12,  2, "=="   , ""       },
     217        { 10,  6, 12,  2, "="    , ""       },
     218        { 10,  6, 12,  2, ""     , ""       },
     219        { 14,  2, 10,  2, "=====", "24"     },
     220        { 14,  2, 10,  2, "=="   , ""       },
     221        { 14,  2, 10,  2, "="    , ""       },
     222        { 14,  2, 10,  2, ""     , ""       },
     223        { 12,  4, 10,  4, "=====", "25"     },
     224        { 12,  4, 10,  4, "=="   , ""       },
     225        { 12,  4, 10,  4, "="    , ""       },
     226        { 12,  4, 10,  4, ""     , ""       },
     227        { 12,  2, 10,  6, "=====", "26"     },
     228        { 12,  2, 10,  6, "=="   , ""       },
     229        { 12,  2, 10,  6, "="    , ""       },
     230        { 12,  2, 10,  6, ""     , ""       },
    226231    };
    227232    for ( i; sizeof(cases)/sizeof(cases[0]) ) {
    228233        sout | "------------------------------------------------------------------------" | cases[i].label;
    229234        string replaceIn = alphabetTemplate;
    230         showOneReplacement( replaceIn, cases[i].ms, cases[i].me, cases[i].ws, cases[i].we, cases[i].replaceWith );
     235        showOneReplacement( replaceIn, cases[i].ms, cases[i].ml, cases[i].ws, cases[i].wl, cases[i].replaceWith );
    231236    }
    232237}
     
    244249    string s = "abcdefghijklmnopqrstuvwxyz";
    245250
    246     s(5,10) = "qqqqq";  // start=5, end=10, len=5
    247 
    248     sout | s;
    249 
    250 
    251     s(5,5) = "-----";  // start=5, end=5, len=0
     251    s(5,5) = "qqqqq";  // start=5, end=10, len=5
     252
     253    sout | s;
     254
     255
     256    s(5,0) = "-----";  // start=5, end=5, len=0
    252257
    253258    sout | s;
  • tests/concurrency/examples/quickSort.cfa

    r59c8dff rf988834  
    1111// Created On       : Wed Dec  6 12:15:52 2017
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Wed Feb 12 18:24:47 2020
    14 // Update Count     : 177
    15 //
    16 
    17 #include <fstream.hfa>
    18 #include <stdlib.hfa>
    19 #include <kernel.hfa>
     13// Last Modified On : Mon Jan  1 12:07:59 2024
     14// Update Count     : 188
     15//
     16
     17#include <fstream.hfa>                                                                  // sin/sout
     18#include <stdlib.hfa>                                                                   // convert
    2019#include <thread.hfa>
     20#include <math.hfa>                                                                             // sqrt
    2121#include <string.h>                                                                             // strcmp
    2222
     
    8282} // main
    8383
    84 
    85 bool convert( int & val, const char * nptr ) {                  // convert C string to integer
    86         char * eptr;
    87         int temp = strto( nptr, &eptr, 10 );                            // do not change val on false
    88         // true => entire string valid with no extra characters
    89         return *nptr != '\0' && *eptr == '\0' ? val = temp, true : false;
    90 } // convert
    91 
    92 void usage( char * argv[] ) {
    93         sout | "Usage:" | argv[0] | "( -s unsorted-file [ sorted-file ] | -t size (>= 0) [ depth (>= 0) ] )";
    94         exit( EXIT_FAILURE );                                                           // TERMINATE!
    95 } // usage
    96 
     84// convert(...) throws out_of_range or invalid_argument
     85ExceptionDecl( cmd_error );
    9786
    9887int main( int argc, char * argv[] ) {
    99         ifstream & unsortedfile = sin;
    100         ofstream & sortedfile = sout;                                           // default value
    101         int depth = 0, size;
    102 
    103         if ( argc != 1 ) {                                                                      // do not use defaults
    104                 if ( argc < 2 || argc > 4 ) usage( argv );              // wrong number of options
    105                 if ( strcmp( argv[1], "-t" ) == 0 ) {                   // timing ?
    106                         &unsortedfile = (ifstream *)0;                          // no input
     88        ifstream unsortedfile = sin;                                            // default values
     89        ofstream sortedfile = sout;
     90        // Must be signed because of the conversion routine.
     91        intmax_t depth = 0;
     92        intmax_t size = -1;                                                                     // -1 means time mode not activated
     93
     94        try {
     95                if ( 1 < argc && strcmp( argv[1], "-t" ) == 0 ) { // time mode ?
    10796                        choose ( argc ) {
    10897                          case 4:
    109                                 if ( ! convert( depth, argv[3] ) || depth < 0 ) usage( argv );
     98                                depth = convert( argv[3] );                             // invalid integer ?
     99                                if ( depth < 0 ) throw ExceptionInst( cmd_error );
    110100                                fallthrough;
    111101                          case 3:
    112                                 if ( ! convert( size, argv[2] ) || size < 0 ) usage( argv );
     102                                size = convert( argv[2] );                              // invalid integer ?
     103                                if ( size < 0 ) throw ExceptionInst( cmd_error );
     104                          default:                                                                      // wrong number of options
     105                                throw ExceptionInst( cmd_error );
    113106                        } // choose
    114107                } else {                                                                                // sort file
    115108                        choose ( argc ) {
    116                           case 3:
    117                                 &sortedfile = new( (const char *)argv[2] ); // open the output file
    118                                 if ( fail( sortedfile ) ) {
    119                                         serr | "Error! Could not open sorted output file \"" | argv[2] | "\"";
    120                                         usage( argv );
     109                          case 4:
     110                                depth = convert( argv[3] );                             // invalid integer ?
     111                                if ( depth < 0 ) throw ExceptionInst( cmd_error );
     112                                fallthrough;
     113                          case 3: case 2:
     114                                if ( strcmp( argv[1], "d" ) != 0 ) {
     115                                        try {                                                           // open input file first as output creates file
     116                                                open( unsortedfile, argv[1] );
     117                                        } catch( open_failure * ) {                     // open failed ?
     118                                                serr | "Error! Could not open unsorted input file \"" | argv[1] | "\"";
     119                                                throw ExceptionInst( cmd_error );
     120                                        } // try
     121                                } // if
     122                                if ( argc > 2 && strcmp( argv[2], "d" ) != 0 ) {
     123                                        try {
     124                                                open( sortedfile, argv[2] );
     125                                        } catch( open_failure * ) {                     // open failed ?
     126                                                serr | "Error! Could not open sorted output file \"" | argv[2] | "\"";
     127                                                throw ExceptionInst( cmd_error );
     128                                        } // try
    121129                                } // if
    122130                                fallthrough;
    123                           case 2:
    124                                 &unsortedfile = new( (const char *)argv[1] ); // open the input file
    125                                 if ( fail( unsortedfile ) ) {
    126                                         serr | "Error! Could not open unsorted input file \"" | argv[1] | "\"";
    127                                         usage( argv );
    128                                 } // if
     131                          case 1: ;                                                                     // defaults
     132                          default:                                                                      // wrong number of options
     133                                throw ExceptionInst( cmd_error );
    129134                        } // choose
    130135                } // if
    131         } // if
     136        } catch( exception_t * ) {                                                      // catch any
     137                exit | "Usage: " | argv[0] |                                    // TERMINATE
     138                        " ( [ unsorted-file | 'd' [ sorted-file | 'd' [ depth (>= 0) ] ] ]"
     139                        " | -t size (>= 0) [ depth (>= 0) ] )";
     140        } //  try
     141
     142        enum { ValuesPerLine = 22 };                                            // number of values printed per line
     143
    132144        sortedfile | nlOff;                                                                     // turn off auto newline
    133145
    134         enum { ValuesPerLine = 22 };                                            // number of values printed per line
    135 
    136         if ( &unsortedfile ) {                                                          // generate output ?
     146        if ( size == -1 ) {                                                                     // generate output ?
    137147                for () {
    138148                        unsortedfile | size;                                            // read number of elements in the list
    139149                  if ( eof( unsortedfile ) ) break;
    140                         int * values = alloc( size );                           // values to be sorted, too large to put on stack
     150
     151                        int * values = aalloc( size );                          // values to be sorted, too large to put on stack
    141152                        for ( counter; size ) {                                         // read unsorted numbers
    142153                                unsortedfile | values[counter];
     
    146157                        } // for
    147158                        sortedfile | nl;
     159
    148160                        if ( size > 0 ) {                                                       // values to sort ?
    149161                                Quicksort QS = { values, size - 1, 0 }; // sort values
     
    158170                        delete( values );
    159171                } // for
    160                 if ( &unsortedfile != &sin ) delete( &unsortedfile ); // close input/output files
    161                 if ( &sortedfile != &sout ) delete( &sortedfile );
    162         } else {
     172        } else {                                                                                        // timing
     173                PRNG prng;                                                                             
    163174                processor processors[ (1 << depth) - 1 ] __attribute__(( unused )); // create 2^depth-1 kernel threads
    164 
    165                 int * values = alloc( size );                                   // values to be sorted, too large to put on stack
     175                int * values = aalloc( size );                                  // values to be sorted, too large to put on stack
     176
    166177                for ( counter; size ) {                                                 // generate unsorted numbers
    167178                        values[counter] = size - counter;                       // descending values
    168179                } // for
    169                 for ( i; 200 ) {                                                                // random shuffle a few values
    170                         swap( values[rand() % size], values[rand() % size] );
     180
     181                unsigned int times = sqrt( size );
     182                for ( unsigned int counter = 0; counter < times; counter += 1 ) {
     183                        swap( values[0], values[prng(size)] );          // randomize unsorted numbers
    171184                } // for
    172185                {
  • tests/exceptions/hotpotato.cfa

    r59c8dff rf988834  
    55
    66struct Potato {
    7         PRNG & prng;
    8         unsigned int deadline;                                                          // when timer goes off
    9         unsigned int timer;                                                                     // up counter to deadline
     7        PRNG & prng;
     8        unsigned int deadline;                                                          // when timer goes off
     9        unsigned int timer;                                                                     // up counter to deadline
    1010}; // Potato
    1111
     
    1616        &potato.prng = &prng;
    1717        reset( potato, maxTicks );
    18 } // Potato
     18                } // Potato
    1919
    2020coroutine Player {
    21         PRNG & prng;
    22         int id;                                                                                         // player identity
    23         Potato & potato;                                                                        // potato being tossed
    24         Player * partner[2];                                                            // left and right player
     21        PRNG & prng;
     22        int id;                                                                                         // player identity
     23        Potato & potato;                                                                        // potato being tossed
     24        Player * partner[2];                                                            // left and right player
    2525}; // Player
    2626
     
    2929        player.id = id;
    3030        &player.potato = &potato;
    31 } // Player
     31                } // Player
    3232
    3333Player & umpire;
     
    3939
    4040void reset( Potato & potato, unsigned int maxTicks ) with(potato) {
    41   if ( maxTicks < 2 ) abort( "Hot Potato initialized with less than 2 ticks" ); // optional
     41        if ( maxTicks < 2 ) abort( "Hot Potato initialized with less than 2 ticks" ); // optional
    4242        deadline = prng( prng, 1, maxTicks );
    4343        timer = 0;
     
    6060enum { LEFT = 0, RIGHT = 1 };
    6161
    62 static void vote( Player & player, Election & election ) {                                      // cause partner to vote
    63     resumeAt( player, election );
     62static void vote( Player & player, Election & election ) { // cause partner to vote
     63        resumeAt( player, election );
    6464        resume( player );
    6565} // vote
     
    7676
    7777void main( Player & player ) with(player) {
    78     suspend;                                                                    // return immediately after establishing starter
     78        suspend;                                                                                        // return immediately after establishing starter
    7979        try {
    80         for ( ;; ) {
    81             poll();                                     // check for non-local exceptions before proceeding
    82 
    83             if ( partner[LEFT] == &player ) {                   // stop when only one player
    84                 sout | id | " wins the Match!";
    85                 return;
    86             } // exit
    87            
    88             countdown( potato );                                // player is eliminated if countdown() returned true
    89            
    90             size_t side = prng( prng, 2 );
    91             sout | id | " -> " | nonl;
    92             resume( *partner[ side ] );                 // random toss left/right
    93         } // for
     80                for ( ;; ) {
     81                        poll();                                                                         // check for non-local exceptions before proceeding
     82
     83                        if ( partner[LEFT] == &player ) {                       // stop when only one player
     84                                sout | id | " wins the Match!";
     85                                return;
     86                        } // exit
     87
     88                        countdown( potato );                                            // player is eliminated if countdown() returned true
     89
     90                        size_t side = prng( prng, 2 );
     91                        sout | id | " -> " | nonl;
     92                        resume( *partner[ side ] );                                     // random toss left/right
     93                } // for
    9494        } catchResume( Terminate * v ) {
    9595                v->victim->partner[LEFT]->partner[RIGHT] = v->victim->partner[RIGHT]; // unlink node
    9696                v->victim->partner[RIGHT]->partner[LEFT] = v->victim->partner[LEFT];
    97         delete( v->victim );
     97                delete( v->victim );
    9898                reset( potato );
    9999                sout | "U " | nonl;                                                             // start new game
     
    102102                sout | "election";
    103103                sout | " -> " | id | nonl;
    104                 if ( id > getId( umpire ) ) &umpire = &player; // set umpire to highest id so far
     104                if ( id > getId( umpire ) ) &umpire = &player;  // set umpire to highest id so far
    105105                vote( *partner[RIGHT], *election );
    106106        } catchResume ( Explode * ) {
    107         sout | id | " is eliminated";
    108         if ( &player == &umpire ) {
    109             id = -1;                                    // remove from election
    110             vote( *partner[RIGHT], ExceptionInst( Election ) );         // start election
    111             try { poll(); } catchResume( Election * election ) {} // handle end of election
    112             sout | " : umpire " | getId( umpire );
    113         } // if
    114         resumeAt( umpire, ExceptionInst( Terminate, &player ) );
    115         resume( umpire );                   // resume umpire to terminate this player
    116         assert( false );                                        // no return
    117     } // try
     107                sout | id | " is eliminated";
     108                if ( &player == &umpire ) {
     109                        id = -1;                                                                        // remove from election
     110                        vote( *partner[RIGHT], ExceptionInst( Election ) );     // start election
     111                        try { poll(); } catchResume( Election * election ) {} // handle end of election
     112                        sout | " : umpire " | getId( umpire );
     113                } // if
     114                resumeAt( umpire, ExceptionInst( Terminate, &player ) );
     115                resume( umpire );                                                               // resume umpire to terminate this player
     116                assert( false );                                                                // no return
     117        } // try
    118118} // main
    119119
     
    151151                  case 1: ;                                                                             // defaults
    152152                  default:                                                                              // too many arguments
    153                         throw ExceptionInst( cmd_error );
     153                          throw ExceptionInst( cmd_error );
    154154                } // choose
    155155        } catch( exception_t * ) {                                                      // catch any
    156156                exit | "Usage: " | argv[0]
    157                          | " [ games (>=0) | 'd' (default " | DefaultGames
    158                          | ") [ players (>=2) | 'd' (random " | MinNoPlayers | "-" | MaxNoPlayers
    159                          | ") [ seed (>0) | 'd' (random) ] ] ]";
     157                        | " [ games (>=0) | 'd' (default " | DefaultGames
     158                        | ") [ players (>=2) | 'd' (random " | MinNoPlayers | "-" | MaxNoPlayers
     159                        | ") [ seed (>0) | 'd' (random) ] ] ]";
    160160        } // try
    161161        sout | numGames | numPlayers | seed;
  • tests/exceptions/hotpotato_checked.cfa

    r59c8dff rf988834  
    55
    66struct Potato {
    7         PRNG & prng;
    8         unsigned int deadline;                                                          // when timer goes off
    9         unsigned int timer;                                                                     // up counter to deadline
     7        PRNG & prng;
     8        unsigned int deadline;                                                          // when timer goes off
     9        unsigned int timer;                                                                     // up counter to deadline
    1010}; // Potato
    1111
     
    1616        &potato.prng = &prng;
    1717        reset( potato, maxTicks );
    18 } // Potato
     18                } // Potato
    1919
    2020coroutine Player {
    21         PRNG & prng;
    22         int id;                                                                                         // player identity
    23         Potato & potato;                                                                        // potato being tossed
    24         Player * partner[2];                                                            // left and right player
     21        PRNG & prng;
     22        int id;                                                                                         // player identity
     23        Potato & potato;                                                                        // potato being tossed
     24        Player * partner[2];                                                            // left and right player
    2525}; // Player
    2626
     
    2929        player.id = id;
    3030        &player.potato = &potato;
    31 } // Player
     31                } // Player
    3232
    3333Player & umpire;
     
    3939
    4040void reset( Potato & potato, unsigned int maxTicks ) with(potato) {
    41   if ( maxTicks < 2 ) abort( "Hot Potato initialized with less than 2 ticks" ); // optional
     41        if ( maxTicks < 2 ) abort( "Hot Potato initialized with less than 2 ticks" ); // optional
    4242        deadline = prng( prng, 1, maxTicks );
    4343        timer = 0;
     
    6666static void terminate( Player & player ) {                              // resume umpire
    6767        resume( player );
    68     checked_poll();
    69     sout | "THIS SHOULD NOT BE REACHED";
     68        checked_poll();
     69        sout | "THIS SHOULD NOT BE REACHED";
    7070} // terminate
    7171
     
    7474        partner[RIGHT] = &rp;
    7575        resume( player );                                                                       // establish main as starter for termination
    76     checked_poll();
     76        checked_poll();
    7777} // init
    7878
     
    8282
    8383void toss( Player & player ) {                                                  // tossed the potato
    84     resume( player );
     84        resume( player );
    8585        checked_poll();
    8686} // toss
     
    8888void main( Player & player ) with(player) {
    8989        try {
    90         enable_ehm();                                                           // allow delivery of nonlocal exceptions
    91         suspend;                                                                        // return immediately after establishing starter
    92         checked_poll();
    93 
    94         for ( ;; ) {
    95             checked_poll();
    96             if ( partner[LEFT] == &player ) {                   // stop when only one player
    97                 sout | id | " wins the Match!";
    98                 return;
    99             } // exit
    100 
    101             countdown( potato );                                // player is eliminated if countdown() returned true
    102 
    103             size_t side = prng( prng, 2 );
    104             sout | id | " -> " | nonl;
    105             toss( *partner[ side ] );                   // random toss left/right
    106         } // for
    107         disable_ehm();
     90                enable_ehm();                                                                   // allow delivery of nonlocal exceptions
     91                suspend;                                                                                // return immediately after establishing starter
     92                checked_poll();
     93
     94                for ( ;; ) {
     95                        checked_poll();
     96                        if ( partner[LEFT] == &player ) {                       // stop when only one player
     97                                sout | id | " wins the Match!";
     98                                return;
     99                        } // exit
     100
     101                        countdown( potato );                                            // player is eliminated if countdown() returned true
     102
     103                        size_t side = prng( prng, 2 );
     104                        sout | id | " -> " | nonl;
     105                        toss( *partner[ side ] );                                       // random toss left/right
     106                } // for
     107                disable_ehm();
    108108        } catchResume( Terminate * v ) {
    109109                v->victim->partner[LEFT]->partner[RIGHT] = v->victim->partner[RIGHT]; // unlink node
    110110                v->victim->partner[RIGHT]->partner[LEFT] = v->victim->partner[LEFT];
    111         delete( v->victim );
     111                delete( v->victim );
    112112                reset( potato );
    113113                sout | "U " | nonl;                                                             // start new game
     
    116116                sout | "election";
    117117                sout | " -> " | id | nonl;
    118                 if ( id > getId( umpire ) ) &umpire = &player; // set umpire to highest id so far
    119         resumeAt( *partner[RIGHT], *election );
    120         disable_ehm();              // disable ehm since we can't handle execption thrown in vote here and want to poll later
     118                if ( id > getId( umpire ) ) &umpire = &player;  // set umpire to highest id so far
     119                resumeAt( *partner[RIGHT], *election );
     120                disable_ehm();                                                                  // disable ehm since we can't handle execption thrown in vote here and want to poll later
    121121                vote( *partner[RIGHT] );
    122         enable_ehm();               // enable after vote
     122                enable_ehm();                                                                   // enable after vote
    123123        } catchResume( Explode * ) {
    124         sout | id | " is eliminated";
    125         if ( &player == &umpire ) {
    126             try {
    127                 id = -1;                                        // remove from election
    128                 resumeAt( *partner[RIGHT], ExceptionInst( Election ) );
    129                 vote( *partner[RIGHT] );                // start election
    130                 checked_poll();
    131             } catchResume( Election * election ) {
    132                 sout | " : umpire " | getId( umpire );
    133             } // try
    134         } // if
    135         resumeAt( umpire, ExceptionInst( Terminate, &player ) );
    136         terminate( umpire );
    137         assert( false );                                        // no return
    138     } // try
     124                sout | id | " is eliminated";
     125                if ( &player == &umpire ) {
     126                        try {
     127                                id = -1;                                                                // remove from election
     128                                resumeAt( *partner[RIGHT], ExceptionInst( Election ) );
     129                                vote( *partner[RIGHT] );                                // start election
     130                                checked_poll();
     131                        } catchResume( Election * election ) {
     132                                sout | " : umpire " | getId( umpire );
     133                        } // try
     134                } // if
     135                resumeAt( umpire, ExceptionInst( Terminate, &player ) );
     136                terminate( umpire );
     137                assert( false );                                                                // no return
     138        } // try
    139139} // main
    140140
     
    172172                  case 1: ;                                                                             // defaults
    173173                  default:                                                                              // too many arguments
    174                         throw ExceptionInst( cmd_error );
     174                          throw ExceptionInst( cmd_error );
    175175                } // choose
    176176        } catch( exception_t * ) {                                                      // catch any
    177177                exit | "Usage: " | argv[0]
    178                          | " [ games (>=0) | 'd' (default " | DefaultGames
    179                          | ") [ players (>=2) | 'd' (random " | MinNoPlayers | "-" | MaxNoPlayers
    180                          | ") [ seed (>0) | 'd' (random) ] ] ]";
     178                        | " [ games (>=0) | 'd' (default " | DefaultGames
     179                        | ") [ players (>=2) | 'd' (random " | MinNoPlayers | "-" | MaxNoPlayers
     180                        | ") [ seed (>0) | 'd' (random) ] ] ]";
    181181        } // try
    182182        sout | numGames | numPlayers | seed;
  • tests/io/.expect/manipulatorsInput.arm64.txt

    r59c8dff rf988834  
    202014 rc=1, cccc
    212115 rc=0, q
     2216 get this line
     2317 @# this line 1)-{}
     2418 abc
     2519 abc 
     2620  d d
     27
     28d
     2921              ZC44%
    22301 yyyyyyyyyyyyyyyyyyyy
    23312 abcxxx
     
    354314 cccc
    364415
     4516 get this line
     4617 @# this line 1)-{}
     4718 abc
     4819 abc 
     4920 d d
     50
     51d
     5221              ZC44%
    3753a
    3854a
  • tests/io/.expect/manipulatorsInput.x64.txt

    r59c8dff rf988834  
    202014 rc=1, cccc
    212115 rc=0, q
     2216 get this line
     2317 @# this line 1)-{}
     2418 abc
     2519 abc 
     2620  d d
     27
     28d
     2921              ZC44%
    22301 yyyyyyyyyyyyyyyyyyyy
    23312 abcxxx
     
    354314 cccc
    364415
     4516 get this line
     4617 @# this line 1)-{}
     4718 abc
     4819 abc 
     4920 d d
     50
     51d
     5221              ZC44%
    3753a
    3854a
  • tests/io/.expect/manipulatorsInput.x86.txt

    r59c8dff rf988834  
    202014 rc=1, cccc
    212115 rc=0, q
     2216 get this line
     2317 @# this line 1)-{}
     2418 abc
     2519 abc 
     2620  d d
     27
     28d
     2921              ZC44%
    22301 yyyyyyyyyyyyyyyyyyyy
    23312 abcxxx
     
    354314 cccc
    364415
     4516 get this line
     4617 @# this line 1)-{}
     4718 abc
     4819 abc 
     4920 d d
     50
     51d
     5221              ZC44%
    3753a
    3854a
  • tests/io/.in/manipulatorsInput.txt

    r59c8dff rf988834  
    1010aaaaaaaaxxxxxxxxaabbccbbdddwwwbbbbbbbbwwwwwwwwaaaaaaaawwwwwwww
    1111uuuuuccccuuuuu
     12get this line
     13@# this line 1)-{}%
     14"abc"
     15'abc  '
     16{ d d
     17
     18d }
     19X               ZC44%Y
    1220abc
    1321cccccb
     
    1725aaaaaaaaxxxxxxxxaabbccbbdddwwwbbbbbbbbwwwwwwwwaaaaaaaawwwwwwww
    1826uuuuuccccuuuuu
     27get this line
     28@# this line 1)-{}%
     29"abc"
     30'abc  '
     31{ d d
     32
     33d }
     34X               ZC44%Y
    1935ab
    20360xff 017 15-15
  • tests/io/manipulatorsInput.cfa

    r59c8dff rf988834  
    77// Created On       : Sat Jun  8 17:58:54 2019
    88// Last Modified By : Peter A. Buhr
    9 // Last Modified On : Sat Sep  2 14:27:46 2023
    10 // Update Count     : 65
     9// Last Modified On : Wed Jan  3 11:15:04 2024
     10// Update Count     : 103
    1111//
    1212
     
    7777                s[0] = 'q'; s[1] = '\0'; rc = 99;
    7878                rc = scanf( "%[^u]", s );                                               printf( "15 rc=%d, %s\n", rc, s );
    79                 scanf( "%*[u]" );
    80                 scanf("\n");
     79                scanf( "%*[u]\n" );
     80                scanf( "%[^\n]\n", s );                                                 printf( "16 %s\n", s );
     81                scanf( "%[^%%]%%\n", s );                                               printf( "17 %s\n", s );
     82
     83                scanf( "%*[ \f\n\r\t\v]" );                                             // ignore whitespace
     84                scanf( "\"%[^\"]\"", s );                                               printf( "18 %s\n", s );
     85                scanf( "%*[ \f\n\r\t\v]" );                                             // ignore whitespace
     86                scanf( "'%[^']'", s );                                                  printf( "19 %s\n", s );
     87                scanf( "%*[ \f\n\r\t\v]" );                                             // ignore whitespace
     88                scanf( "{%[^}]}", s );                                                  printf( "20 %s\n", s );
     89                scanf( "%*[ \f\n\r\t\v]" );                                             // ignore whitespace
     90                scanf( "X%[^Y]Y", s );                                                  printf( "21 %s\n", s );
     91                scanf( "\n" );                                                                  // must start next line
    8192        }
    8293        {
     
    102113                s[0] = 'q'; s[1] = '\0';
    103114                sin | excl( "u", wdi( sizeof(s), s ) );                 sout | "15" | s;
    104                 sin | skip( "u" );
    105                 sin | "\n";
    106         }
    107     /* Keep harmonized with collections/string-istream-manip */
     115                sin | skip( "u" ) | "\n";
     116                sin | getline( wdi( sizeof(s), s ) );                   sout | "16" | s;
     117                sin | getline( wdi( sizeof(s), s ), '%' ) | "\n"; sout | "17" | s;
     118
     119                sin | quoted( wdi( sizeof(s), s ) );                    sout | "18" | s;
     120                sin | quoted( wdi( sizeof(s), s ), '\'' );              sout | "19" | s;
     121                sin | quoted( wdi( sizeof(s), s ), '{', '}' );  sout | "20" | s;
     122                sin | quoted( wdi( sizeof(s), s ), 'X', 'Y' );  sout | "21" | s;
     123        }
     124    // Keep harmonized with collections/string-istream-manip
    108125        {
    109126                char c;
Note: See TracChangeset for help on using the changeset viewer.