1%% Copyright (c) 2008-2016 Robert Virding 2%% 3%% Licensed under the Apache License, Version 2.0 (the "License"); 4%% you may not use this file except in compliance with the License. 5%% You may obtain a copy of the License at 6%% 7%% http://www.apache.org/licenses/LICENSE-2.0 8%% 9%% Unless required by applicable law or agreed to in writing, software 10%% distributed under the License is distributed on an "AS IS" BASIS, 11%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12%% See the License for the specific language governing permissions and 13%% limitations under the License. 14 15%% File : lfe_io.erl 16%% Author : Robert Virding 17%% Purpose : Some basic i/o functions for Lisp Flavoured Erlang. 18%% 19%% The io functions have been split into the following modules: 20%% lfe_io - basic read and write functions 21%% lfe_io_write - basic write functions 22%% lfe_io_pretty - basic print functions 23%% lfe_io_format - formatted output 24 25-module(lfe_io). 26 27-export([parse_file/1,read_file/1]). 28-export([read/0,read/1,read/2,read_line/0,read_line/1,read_line/2]). 29-export([read_string/1]). 30-export([scan_sexpr/2,scan_sexpr/3]). 31-export([print/1,print/2,print1/1,print1/2]). 32-export([prettyprint/1,prettyprint/2, 33 prettyprint1/1,prettyprint1/2,prettyprint1/3,prettyprint1/4]). 34-export([format/2,format/3,fwrite/2,fwrite/3, 35 format1/2,fwrite1/2]). 36 37%% -compile(export_all). 38 39-import(lists, [flatten/1,reverse/1,reverse/2,map/2,mapfoldl/3,all/2]). 40 41%% Define IS_MAP/1 macro for is_map/1 bif. 42-ifdef(HAS_MAPS). 43-define(IS_MAP(T), is_map(T)). 44-else. 45-define(IS_MAP(T), false). 46-endif. 47 48%% parse_file(FileName) -> {ok,[{Sexpr,Line}]} | {error,Error}. 49%% Parse a file returning the raw sexprs (as it should be) and line 50%% numbers of start of each sexpr. Handle errors consistently. 51 52parse_file(Name) -> 53 with_token_file(Name, fun (Ts) -> parse_file1(Ts, [], []) end). 54 55parse_file1([_|_]=Ts0, Pc0, Ss) -> 56 case lfe_parse:sexpr(Pc0, Ts0) of 57 {ok,L,S,Ts1} -> parse_file1(Ts1, [], [{S,L}|Ss]); 58 {more,Pc1} -> 59 %% Need more tokens but there are none, so call again to 60 %% generate an error message. 61 {error,E,_} = lfe_parse:sexpr(Pc1, {eof,99999}), 62 {error,E}; 63 {error,E,_} -> {error,E} 64 end; 65parse_file1([], _, Ss) -> {ok,reverse(Ss)}. 66 67%% read_file(FileName) -> {ok,[Sexpr]} | {error,Error}. 68%% Read a file returning the raw sexprs (as it should be). 69 70read_file(Name) -> 71 with_token_file(Name, fun (Ts) -> read_file1(Ts, []) end). 72 73read_file1([_|_]=Ts0, Ss) -> 74 case lfe_parse:sexpr(Ts0) of 75 {ok,_,S,Ts1} -> read_file1(Ts1, [S|Ss]); 76 {more,Pc1} -> 77 %% Need more tokens but there are none, so call again to 78 %% generate an error message. 79 {error,E,_} = lfe_parse:sexpr(Pc1, {eof,99999}), 80 {error,E}; 81 {error,E,_} -> {error,E} 82 end; 83read_file1([], Ss) -> {ok,reverse(Ss)}. 84 85%% with_token_file(FileName, DoFunc) 86%% Open the file, scan all LFE tokens and apply DoFunc on them. 87 88with_token_file(Name, Do) -> 89 case file:open(Name, [read]) of 90 {ok,F} -> 91 Ret = case io:request(F, {get_until,unicode,'',lfe_scan,tokens,[1]}) of 92 {ok,Ts,_} -> Do(Ts); 93 {error,Error,_} -> {error,Error} 94 end, 95 file:close(F), %Close the file 96 Ret; % and return value 97 {error,Error} -> {error,{none,file,Error}} 98 end. 99 100%% read() -> {ok,Sexpr} | {error,Error}. 101%% read(Prompt) -> {ok,Sexpr} | {error,Error}. 102%% read(IoDevice, Prompt) -> {ok,Sexpr} | {error,Error}. 103%% A simple read function. It is not line oriented and stops as soon 104%% as it has consumed enough. 105 106read() -> read(standard_io, ''). 107read(Prompt) -> read(standard_io, Prompt). 108read(Io, Prompt) -> 109 case io:request(Io, {get_until,unicode,Prompt,?MODULE,scan_sexpr,[1]}) of 110 {ok,Sexpr,_} -> {ok,Sexpr}; 111 {error,E} -> {error,{1,io,E}}; 112 {error,Error,_} -> {error,Error}; 113 {eof,_} -> eof 114 end. 115 116%% read_line() -> {ok,Sexpr} | {error,Error}. 117%% read_line(Prompt) -> {ok,Sexpr} | {error,Error}. 118%% read_line(IoDevice, Prompt) -> {ok,Sexpr} | {error,Error}. 119%% A simple read function. It is line oriented and reads whole lines 120%% until it has consumed enough characters. Left-over characters in 121%% the last line are discarded. 122 123read_line() -> read_line(standard_io, ''). 124read_line(Prompt) -> read_line(standard_io, Prompt). 125read_line(Io, Prompt) -> 126 %% We input lines and call scan_sexpr directly ourself. 127 read_line_1(Io, Prompt, [], 1). 128 129read_line_1(Io, P, C0, L0) -> 130 case io:get_line(Io, P) of 131 {error,Error} -> {error,{L0,io,Error}}; 132 Cs0 -> 133 case scan_sexpr(C0, Cs0, L0) of 134 {done,{ok,Ret,_L1},_Cs1} -> {ok,Ret}; 135 {done,{error,Error,_},_Cs1} -> {error,Error}; 136 {more,C1} -> 137 read_line_1(Io, P, C1, L0) 138 end 139 end. 140 141%% scan_sexpr(Continuation, Chars) -> 142%% scan_sexpr(Continuation, Chars, Line) -> 143%% {done,Ret,Rest} | {more,Continuation}. 144%% This function is a re-entrant call which scans tokens from the 145%% input and parses a sexpr. If there are enough characters then it 146%% returns {done,...} else {cont,Cont} if it needs more characters. 147%% This is continued until a sexpr has been scanned. 148 149scan_sexpr([], Cs) -> 150 scan_sexpr({[],[]}, Cs, 1). 151 152scan_sexpr([], Cs, L) -> 153 scan_sexpr({[],[]}, Cs, L); 154scan_sexpr({Sc,Pc}, Cs, L) -> 155 scan_sexpr_1(Sc, Pc, Cs, L). 156 157scan_sexpr_1(Sc0, Pc0, Cs0, L0) -> 158 case lfe_scan:token(Sc0, Cs0, L0) of 159 {done,{error,_,_},_}=Error -> Error; 160 {done,{ok,T,L1},Cs1} -> 161 %% We have a token, now check if we have a sexpr. 162 case lfe_parse:sexpr(Pc0, [T]) of 163 {ok,L2,Sexpr,_} -> 164 {done,{ok,Sexpr,L2},Cs1}; 165 {error,Error,_} -> 166 {done,{error,Error,Cs1},Cs1}; 167 {more,Pc1} -> %Need more tokens 168 scan_sexpr_1([], Pc1, Cs1, L1) 169 end; 170 {done,{eof,_},_}=Eof -> Eof; 171 {more,Sc1} -> 172 {more,{Sc1,Pc0}} 173 end. 174 175%% read_string(String) -> {ok,Sexpr} | {error,Error}. 176%% Read a string. 177 178read_string(Cs) -> 179 case lfe_scan:string(Cs, 1) of 180 {ok,Ts,L} -> 181 case lfe_parse:sexpr(Ts ++ {eof,L}) of 182 {ok,_,S,_} -> {ok,S}; 183 {error,E,_} -> {error,E} 184 end; 185 {error,E,_} -> {error,E} 186 end. 187 188%% print([IoDevice], Sexpr) -> ok. 189%% print1(Sexpr) -> [char()]. 190%% print1(Sexpr, Depth) -> [char()]. 191%% A simple print function. Does not pretty-print but stops at Depth. 192 193print(S) -> print(standard_io, S). 194print(Io, S) -> io:put_chars(Io, print1(S)). 195 196print1(S) -> print1(S, -1). %All the way 197print1(S, D) -> lfe_io_write:term(S, D). 198 199%% prettyprint([IoDevice], Sexpr) -> ok. 200%% prettyprint1(Sexpr, Depth, Indentation, LineLength) -> [char()]. 201%% External interface to the prettyprint functions. 202 203prettyprint(S) -> prettyprint(standard_io, S). 204prettyprint(Io, S) -> io:put_chars(Io, prettyprint1(S, -1)). 205 206prettyprint1(S) -> lfe_io_pretty:term(S). 207prettyprint1(S, D) -> lfe_io_pretty:term(S, D, 0, 80). 208prettyprint1(S, D, I) -> lfe_io_pretty:term(S, D, I, 80). 209prettyprint1(S, D, I, L) -> lfe_io_pretty:term(S, D, I, L). 210 211%% format([IoDevice,] Format, Args) -> ok. 212%% fwrite([IoDevice,] Format, Args) -> ok. 213%% format1(Format, Args) -> [char()]. 214%% fwrite1(Format, Args) -> [char()]. 215%% External interface to the formated output functions. 216 217format(F, As) -> format(standard_io, F, As). 218format(Io, F, As) -> io:put_chars(Io, format1(F, As)). 219 220format1(F, As) -> fwrite1(F, As). 221 222fwrite(F, As) -> fwrite(standard_io, F, As). 223fwrite(Io, F, As) -> io:put_chars(Io, fwrite1(F, As)). 224 225fwrite1(F, As) -> 226 case catch lfe_io_format:fwrite1(F, As) of 227 {'EXIT',_} -> %Something went wrong 228 erlang:error(badarg, [F,As]); %Signal from here 229 Result -> Result 230 end. 231