Add libString.
This commit is contained in:
parent
57ccfb9e8f
commit
7f11104a57
20 changed files with 1315 additions and 0 deletions
141
src/libString/s_rdinstack.c
Normal file
141
src/libString/s_rdinstack.c
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include "libString.h"
|
||||
|
||||
struct Sinstack{
|
||||
int depth;
|
||||
Biobuf *fp[32]; /* hard limit to avoid infinite recursion */
|
||||
};
|
||||
|
||||
/* initialize */
|
||||
extern Sinstack *
|
||||
s_allocinstack(char *file)
|
||||
{
|
||||
Sinstack *sp;
|
||||
Biobuf *fp;
|
||||
|
||||
fp = Bopen(file, OREAD);
|
||||
if(fp == nil)
|
||||
return nil;
|
||||
|
||||
sp = malloc(sizeof *sp);
|
||||
sp->depth = 0;
|
||||
sp->fp[0] = fp;
|
||||
return sp;
|
||||
}
|
||||
|
||||
extern void
|
||||
s_freeinstack(Sinstack *sp)
|
||||
{
|
||||
while(sp->depth >= 0)
|
||||
Bterm(sp->fp[sp->depth--]);
|
||||
free(sp);
|
||||
}
|
||||
|
||||
/* Append an input line to a String.
|
||||
*
|
||||
* Empty lines and leading whitespace are removed.
|
||||
*/
|
||||
static char *
|
||||
rdline(Biobuf *fp, String *to)
|
||||
{
|
||||
int c;
|
||||
int len = 0;
|
||||
|
||||
c = Bgetc(fp);
|
||||
|
||||
/* eat leading white */
|
||||
while(c==' ' || c=='\t' || c=='\n' || c=='\r')
|
||||
c = Bgetc(fp);
|
||||
|
||||
if(c < 0)
|
||||
return 0;
|
||||
|
||||
for(;;){
|
||||
switch(c) {
|
||||
case -1:
|
||||
goto out;
|
||||
case '\\':
|
||||
c = Bgetc(fp);
|
||||
if (c != '\n') {
|
||||
s_putc(to, '\\');
|
||||
s_putc(to, c);
|
||||
len += 2;
|
||||
}
|
||||
break;
|
||||
case '\r':
|
||||
break;
|
||||
case '\n':
|
||||
if(len != 0)
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
s_putc(to, c);
|
||||
len++;
|
||||
break;
|
||||
}
|
||||
c = Bgetc(fp);
|
||||
}
|
||||
out:
|
||||
s_terminate(to);
|
||||
return to->ptr - len;
|
||||
}
|
||||
|
||||
/* Append an input line to a String.
|
||||
*
|
||||
* Returns a pointer to the character string (or 0).
|
||||
* Leading whitespace and newlines are removed.
|
||||
* Lines starting with #include cause us to descend into the new file.
|
||||
* Empty lines and other lines starting with '#' are ignored.
|
||||
*/
|
||||
extern char *
|
||||
s_rdinstack(Sinstack *sp, String *to)
|
||||
{
|
||||
char *p;
|
||||
Biobuf *fp, *nfp;
|
||||
|
||||
s_terminate(to);
|
||||
fp = sp->fp[sp->depth];
|
||||
|
||||
for(;;){
|
||||
p = rdline(fp, to);
|
||||
if(p == nil){
|
||||
if(sp->depth == 0)
|
||||
break;
|
||||
Bterm(fp);
|
||||
sp->depth--;
|
||||
return s_rdinstack(sp, to);
|
||||
}
|
||||
|
||||
if(strncmp(p, "#include", 8) == 0 && (p[8] == ' ' || p[8] == '\t')){
|
||||
to->ptr = p;
|
||||
p += 8;
|
||||
|
||||
/* sanity (and looping) */
|
||||
if(sp->depth >= nelem(sp->fp))
|
||||
sysfatal("s_recgetline: includes too deep");
|
||||
|
||||
/* skip white */
|
||||
while(*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
|
||||
nfp = Bopen(p, OREAD);
|
||||
if(nfp == nil)
|
||||
continue;
|
||||
sp->depth++;
|
||||
sp->fp[sp->depth] = nfp;
|
||||
return s_rdinstack(sp, to);
|
||||
}
|
||||
|
||||
/* got milk? */
|
||||
if(*p != '#')
|
||||
break;
|
||||
|
||||
/* take care of comments */
|
||||
to->ptr = p;
|
||||
s_terminate(to);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue