1 /*
2  * $Id: yio.h,v 1.4 2010-01-01 00:59:21 dhmunro Exp $
3  * Declare Yorick I/O functions.
4  */
5 /* Copyright (c) 2005, The Regents of the University of California.
6  * All rights reserved.
7  * This file is part of yorick (http://yorick.sourceforge.net).
8  * Read the accompanying LICENSE file for details.
9  */
10 
11 #ifndef YIO_H
12 #define YIO_H
13 
14 #include "hash.h"
15 
16 /*--------------------------------------------------------------------------*/
17 
18 #include "pstdio.h"
19 #include <stdio.h>
20 
21 /*--------------------------------------------------------------------------*/
22 
23 /* Yorick wrappers for fgets, feof, and ferror.  */
24 PLUG_API char *Yfgets(char *s, int n, p_file *stream);
25 PLUG_API int Yfeof(p_file *stream);
26 PLUG_API int Yferror(p_file *stream);
27 
28 /* Yorick routines use the following virtual functions to do fgets and
29    fputs to stdin, stdout, and stderr.  Other packages may replace the
30    default routines when initializing if more sophistocated I/O is required,
31    as for an X window graphics package.  */
32 PLUG_API int (*YPrompt)(char *s);      /* no \n appended, like fputs */
33 PLUG_API int (*YputsOut)(char *s);     /* \n appended, like puts */
34 PLUG_API int (*YputsErr)(char *s);     /* \n appended, like puts */
35 PLUG_API int YDPrompt(char *s);
36 PLUG_API int YDputsOut(char *s);
37 PLUG_API int YDputsErr(char *s);
38 
39 /*--------------------------------------------------------------------------*/
40 /* The gets function is handy, but dicey if you aren't sure how long
41    the input line is.  Ygets circumvents this problem at the cost of
42    a new data type, the YgetsLine, which manages an input line buffer.
43    Each call to Ygets returns either getsLine->line, or 0 if EOF or
44    an error:
45       if (!Ygets(&buf, file)) {
46          if (Yferror(file))     { there really was a read error }
47          else if (!Yfeof(file)) { no \n after MAX_LINE chars read }
48          else                   { end-of-file (no characters first) }
49       }
50    The returned buf.line contains one line of input, with the trailing
51    \n stripped (if EOF before EOL, nothing was stripped).
52    Ygets keeps buf.max between MIN_LINE and BIG_LINE; if it is bigger
53    than BIG_LINE initially, it is reallocated with length MIN_LINE.
54    More characters are added to the buffer as needed in increments of
55    INC_LINE.  If more than MAX_LINE characters are read without a \n,
56    Ygets gives up, sets buf.line="", and returns 0.
57    Ygets calls Yfgets, and so obeys the latter's convention for stream==0.
58  */
59 typedef struct YgetsLine YgetsLine;
60 struct YgetsLine {
61   char *line;    /* pointer to current line buffer, no '\n' */
62   int max;       /* line created with p_malloc(max) */
63   int n;         /* strlen(line) */
64 };
65 
66 PLUG_API char *Ygets(YgetsLine *getsLine, p_file *stream);
67 
68 /*--------------------------------------------------------------------------*/
69 
70 /* Filename gymnastics are inevitable, but system dependent (at least
71    on non-UNIX platforms).  The following are intended to help.
72    Free char* results with p_free when finished.  */
73 PLUG_API char *YExpandName(const char *name);    /* return absolute pathname */
74 PLUG_API char *YNameTail(const char *name);
75 PLUG_API char *YNameHead(const char *name);           /* includes trailing / */
76 PLUG_API void YNameToHead(char **name);         /* ensure trailing / present */
77 PLUG_API int YIsAbsolute(const char *name);       /* Does name start with /? */
78 PLUG_API int YIsDotRelative(const char *name);  /* ., .., or with ./ or ../? */
79 
80 PLUG_API char *yCWD;      /* current working directory, including trailing / */
81 PLUG_API char *yHOME;     /* home directory from $HOME, including trailing / */
82 
83 /* Use p_free to get rid of return value from Ygetenv.  */
84 PLUG_API char *Ygetenv(const char *name);
85 
86 /* YSetCWD returns non-0 if operation fails, resets yCWD on success.
87    If name==0, just sets yCWD to ".".  */
88 PLUG_API int YSetCWD(const char *name);
89 PLUG_API void YGetHOME(void);  /* sets yHOME */
90 
91 /*--------------------------------------------------------------------------*/
92 
93 /* Scan for C-style escape sequences in quoted strings (e.g.- \n, \t),
94    returning the (single character) value of the escape sequence, and,
95    if the 2nd parameter is non-0, the character which stopped the scan.
96    Thus, if s=="tXYZ", then YpEscapeSeq returns 9 (ASCII tab), and
97    endp=="XYZ"; the same results would obtain if s=="011XYZ".  */
98 PLUG_API int YpEscapeSeq(const char *s, char **endp);
99 
100 /*--------------------------------------------------------------------------*/
101 /* Yorick include files are managed using the following variables
102    and functions.  */
103 
104 /* ypIncludes-- the stack of currently open include files, maintain using
105    YpPushInclude and YpClearIncludes */
106 typedef struct IncludeFile IncludeFile;
107 struct IncludeFile {
108   p_file *file;
109   char *filename;     /* expanded filename (allocated with p_malloc) */
110   long lastLineRead;  /* number of times Ygets has been called */
111   long index;         /* into globTab of current variable */
112 };
113 
114 PLUG_API IncludeFile *ypIncludes;
115 PLUG_API int nYpIncludes;
116 
117 /* YpPushInclude opens a file and pushes it onto the include stack.
118       The very next input will be taken from that file.
119    IncludeNow parses the file just pushed by YpPushInclude
120    YpPush pushes a filename onto the pending input sources list.
121       When all other sources of input are exhausted, Yorick will
122       attempt to include these files in reverse order to the YpPush calls.
123    YpClearIncludes closes all files on the current include stack, and
124       forgets the contents of the pending input list.  */
125 PLUG_API p_file *YpPushInclude(const char *filename);
126 PLUG_API void IncludeNow(void);
127 PLUG_API void YpPush(const char *filename);      /* filename will be copied */
128 PLUG_API p_file *YpPop(void);  /* call YpPushInclude with top of input list */
129 PLUG_API void YpClearIncludes(void);
130 /* like YpPushInclude, but does not open file */
131 PLUG_API void y_push_include(p_file *file, const char *filename);
132 /*
133   The on_include callback returns a p_file* on success, or 0 on failure.
134   ycall_on_include sets this callback, returing the old callback.
135   ycall_on_include(0) resets the default include file open function,
136     which is simply p_fopen
137   (This is an esoteric function needed by mpy.)
138 */
139 typedef p_file *yon_include_cb(const char *filename, int fullparse);
140 PLUG_API yon_include_cb *ycall_on_include(yon_include_cb *on_include);
141 
142 PLUG_API void ResetStack(int hard);
143 PLUG_API void yr_reset(void);
144 
145 /* sourceTab-- a permanent list of all files which have ever been included */
146 PLUG_API HashTable sourceTab;
147 PLUG_API long **sourceList;   /* maxItems array of pointers to lists of
148                                  globTab indices of func/struct/extern
149                                  definitions in corresponding source file */
150 PLUG_API long *lenSourceList; /* length of sourceList[i] is lenSourceList[i] */
151 
152 /* Record the given globTab index in the sourceList.  This index
153    corresponds to either a func definition, a struct definition, or an
154    extern statement outside of any functions.  */
155 PLUG_API long RecordSource(long index);
156 
157 PLUG_API long ypBeginLine;  /* source line number at which current parse
158                                began (<=0 if input from keyboard) */
159 
160 /* Given an index into globTab, OpenSource searches through the source
161    lists to find the the source file in which the corresponding func,
162    struct, or variable was defined, then returns the source file,
163    positioned for read at the beginning of the definition.  The
164    number of that line is in ypBeginLine.  */
165 PLUG_API p_file *OpenSource(long index, long isrc);
166 
167 /* Given a function, YpReparse searches through the source lists to find
168    the the source file in which the corresponding func or struct was
169    defined.  It then reparses this func or struct definition, replacing
170    the corresponding globTab entry with the new definition, and
171    returns a pointer to an error message string which begins with "*****"
172    if YpReparse failed, otherwise gives the line number and filename
173    of the function.  */
174 PLUG_API char *YpReparse(void *function);
175 
176 /* ypPrefixes-- the ordered list of directories which Yorick will search
177      to locate an include file (./ for CWD), set using YpSetPaths */
178 PLUG_API char **ypPrefixes;
179 PLUG_API int nYpPrefixes;
180 
181 /* Yorick has two search paths for include files.  The first is the
182    startup search path, which must allow std.i and other compiled-in
183    package include files to be found.  After initialization, the
184    normal search path is installed.  The first path is:
185       yLaunchDir:ySiteDir:ySiteDir/contrib
186    where yLaunchDir is the directory containing the executable, as
187    determined at runtime, and ySiteDir is a compiled-in value (set
188    by Codger from the value in the Makefile).  If yLaunchDir contains
189    a paths.i file (the first file Yorick includes), that file may set
190    the interpreted variable Y_SITE in order to change ySiteDir in both
191    the first and second search paths.
192    The second path is initialized in stdx.i to:
193       .:~/Yorick:ySiteDir/include:ySiteDir/contrib
194    This can be overridden by an interpreted command to set the search
195    path (in, say, custom.i).  Alternatively, yLaunchDir can contain a
196    special version of stdx.i.  */
197 PLUG_API void YpSetPaths(const char *pathlist);    /* also sets yCWD, yHOME */
198 PLUG_API char *yLaunchDir, *ySiteDir, *yHomeDir, *defaultPath;
199 PLUG_API char *y_user_dir, *y_gist_dir, *y_home_pkg;
200 
201 /*--------------------------------------------------------------------------*/
202 
203 /* PrintFunc prints a string (as in the Y_print built-in function),
204    breaking the result into multiple lines if required.  To accomplish this,
205    PrintFunc remembers the most recent call to PermitLine and first flushes
206    the line to that point.  If s still doesn't fit within printLength
207    characters, then PrintFunc prints the first printLength-1, a '\',
208    and so on until s is exhausted.  ForceNewline immediately flushes any
209    pending line.
210    PrintInit initializes PrintFunc (e.g.- PrintInit(YputsOut)).
211    The Print and Y_print commands will not print more than
212    maxPrintLines lines of output.  */
213 PLUG_API void PrintFunc(const char *s);
214 PLUG_API void PermitNewline(int nSpaces);
215 PLUG_API void ForceNewline(void);
216 PLUG_API void PrintInit(int (*puts)(char *));
217 PLUG_API int printLength;     /* forced between 40 and 256 inclusive */
218 PLUG_API long maxPrintLines;  /* default 5000 */
219 
220 /* formats used by Print and Y_print (be careful...) */
221 PLUG_API char *yCharFormat, *yShortFormat, *yIntFormat, *yLongFormat;
222 PLUG_API char *yFloatFormat, *yDoubleFormat, *yComplexFormat, *yPointerFormat;
223 PLUG_API void DefaultPrintFormat(int type);  /* type == (1<<T_CHAR)|etc */
224 
225 PLUG_API char *ScanForEscape(char *s);
226 PLUG_API int AddEscapeSeq(char *s, int esc);
227 
228 /*--------------------------------------------------------------------------*/
229 
230 /* linked list of open files */
231 typedef struct IOFileLink IOFileLink;
232 struct IOFileLink {
233   struct IOFileLink *next;
234   struct IOFileLink **prev;  /* for unlinking only, can't go backwards */
235   void *ios;                 /* either TextStream or IOStream */
236 };
237 
238 PLUG_API IOFileLink *yTextFiles, *yBinaryFiles;
239 
240 PLUG_API void AddIOLink(IOFileLink** list, void *ios);
241 PLUG_API void RemoveIOLink(IOFileLink* list, void *ios);
242 
243 /*--------------------------------------------------------------------------*/
244 
245 #endif
246