/* inserts a character at the cursor */ void insertc(view_t *view,unsigned char c) { /* check readonly */ if(view->buffer->readonly) error_throw(ERR_READONLY); /* check valid character */ if((char)c<0) return; char *line=view->buffer->lines[view->cursor_line]; /* make sure the line is long enough */ view->buffer->lines[view->cursor_line]=strexpand(line,strlen(line)+2); line=view->buffer->lines[view->cursor_line]; /* make a copy of the line */ char *tln=malloc(strlen(line)+2); char *ln=tln; sprintf(ln,"%s",line); /* put the line back together */ /* copy the first part back */ line[0]='\0'; strncat(line,ln,view->cursor_x); /* copy the character */ line[strlen(line)+1]='\0'; line[strlen(line)]=c; /* copy the second part back */ ln+=view->cursor_x; strcat(line,ln); free(tln); /* free temporary buffer */ /* advance the cursor */ view->pref_x++; clean_cursor_x(view); /* we've been modified */ view->buffer->modified=1; }
SC_FUNC int phopt_init(void) { int number, i, len; char str[160]; /* count number of sequences */ for (number=0; sequences_cmp[number].find!=NULL; number++) /* nothing */; number++; /* include an item for the NULL terminator */ if ((sequences=(SEQUENCE*)malloc(number * sizeof(SEQUENCE)))==NULL) return FALSE; /* pre-initialize all to NULL (in case of failure) */ for (i=0; i<number; i++) { sequences[i].find=NULL; sequences[i].replace=NULL; sequences[i].opc=0; sequences[i].arg=0; } /* for */ /* expand all strings */ for (i=0; i<number-1; i++) { len = strexpand(str,(unsigned char*)sequences_cmp[i].find,sizeof str,SCPACK_TABLE); assert(len<=sizeof str); assert(len==(int)strlen(str)+1); sequences[i].find=(char*)malloc(len); if (sequences[i].find!=NULL) strcpy((char*)sequences[i].find,str); len = strexpand(str,(unsigned char*)sequences_cmp[i].replace,sizeof str,SCPACK_TABLE); assert(len<=sizeof str); assert(len==(int)strlen(str)+1); sequences[i].replace=(char*)malloc(len); if (sequences[i].replace!=NULL) strcpy((char*)sequences[i].replace,str); sequences[i].opc=sequences_cmp[i].opc; sequences[i].arg=sequences_cmp[i].arg; if (sequences[i].find==NULL || sequences[i].replace==NULL) return phopt_cleanup(); } /* for */ return TRUE; }
int main (int argc, char **argv) { int i; char str[128]; for (i=0; i<58; i++) { strexpand(str, errmsg[i], sizeof str, SCPACK_TABLE); printf("%s", str); } /* for */ return 0; }
/* delete a character at the cursor */ void deletec(view_t *view) { /* exit if there's nothing to delete */ if(view->cursor_x==0 && view->cursor_line==0) return; /* clean up our position */ clean_cursor_x(view); clean_pref_x(view); /* should we merge lines? */ if(view->cursor_x==0) { /* merge lines */ char *line=view->buffer->lines[view->cursor_line]; view->buffer->lines[view->cursor_line-1]= strexpand(view->buffer->lines[view->cursor_line-1], strlen(view->buffer->lines[view->cursor_line-1])+ strlen(line)); view->pref_x=strlen(view->buffer->lines[view->cursor_line-1]); strcat(view->buffer->lines[view->cursor_line-1],line); free(line); /* free the line */ /* reduce line count */ view->buffer->line_count--; /* scroll all future lines up */ int i; for(i=view->cursor_line;i<view->buffer->line_count;i++) view->buffer->lines[i]=view->buffer->lines[i+1]; /* move the cursor */ cursor_up(view); return; } /* no line merging to be done */ /* get the line */ char *line=view->buffer->lines[view->cursor_line]; /* make a copy of the line */ char *tln=malloc(strlen(line)+2); char *ln=tln; sprintf(ln,"%s",line); /* copy the first part back */ line[0]='\0'; strncat(line,ln,view->cursor_x-1); /* copy the second part back */ ln+=view->cursor_x; strcat(line,ln); free(tln); /* free temporary buffer */ /* retreat the cursor */ view->pref_x--; view->cursor_x--; /* we've been modified */ view->buffer->modified=1; }
int main(int argc, char **argv) { while(--argc > 0) { char *s= strexpand(*++argv, table); if(s) { puts(s); free(s); } else printf("strexpand(\"%s\") failed.\n",*argv); } return 0; }
int gen_autodoc(FILE *fp, int cols, int tabsize, int flags, char **body_macros) { int err= 0; char *fun, *sec, *text; for(fun= stepfun(0); fun && (err==0); fun= stepfun(1)) { if(flags & ADOC_FORM_FEEDS) fputc('\f',fp); fprintf(fp,"%s%*s\n\n",fun,(int)(cols-strlen(fun)),fun); for(sec= stepsec(0); sec && (err==0); sec= stepsec(1)) { /* indent the section heading with 3 spaces */ if(*sec) fprintf(fp," %s\n",sec); if( (text= getsec(sec)) ) { if(text && *text) { char *x= strexpand(text, body_macros); if(x) { if(tabsize > 0) fexpand(fp,tabsize,x); else fputs(x,fp); free(x); } else err= __LINE__; } fputc('\n',fp); } } } return err; }
/* error * * Outputs an error message (note: msg is passed optionally). * If an error is found, the variable "errflag" is set and subsequent * errors are ignored until lex() finds a semicolon or a keyword * (lex() resets "errflag" in that case). * * Global references: inpfname (reffered to only) * fline (reffered to only) * fcurrent (reffered to only) * errflag (altered) */ SC_FUNC int error(long number,...) { static char *prefix[3]={ "error", "fatal error", "warning" }; static int lastline,errorcount; static short lastfile; char *msg,*pre,*filename; va_list argptr; char string[256]; int notice; /* split the error field between the real error/warning number and an optional * "notice" number */ notice=number >> (sizeof(long)*4); number&=((unsigned long)~0) >> (sizeof(long)*4); assert(number>0 && number<300); /* errflag is reset on each semicolon. * In a two-pass compiler, an error should not be reported twice. Therefore * the error reporting is enabled only in the second pass (and only when * actually producing output). Fatal errors may never be ignored. */ if ((errflag || sc_status!=statWRITE) && (number<100 || number>=200)) return 0; /* also check for disabled warnings */ if (number>=200) { int index=(number-200)/8; int mask=1 << ((number-200)%8); if ((warndisable[index] & mask)!=0) { errline=-1; errfile=-1; return 0; } /* if */ } /* if */ if (number<100){ assert(number>0 && number<sizearray(errmsg)); msg=errmsg[number]; pre=prefix[0]; errflag=TRUE; /* set errflag (skip rest of erroneous expression) */ errnum++; } else if (number<200) { assert((number-100)>=0 && (number-100)<sizearray(fatalmsg)); msg=fatalmsg[number-100]; pre=prefix[1]; errnum++; /* a fatal error also counts as an error */ } else { assert((number-200)>=0 && (number-200)<sizearray(warnmsg)); msg=warnmsg[number-200]; pre=prefix[2]; warnnum++; } /* if */ strexpand(string,(unsigned char *)msg,sizeof string-2,SCPACK_TABLE); if (notice>0) { int len; assert(notice<sizearray(noticemsg)); strcat(string,"; "); len=strlen(string); strexpand(string+len,(unsigned char *)noticemsg[notice],sizeof string-len-1,SCPACK_TABLE); } /* if */ strcat(string,"\n"); if (errline>0) errstart=errline; /* forced error position, set single line destination */ else errline=fline; /* normal error, errstart may (or may not) have been marked, endpoint is current line */ if (errstart>errline) errstart=errline; /* special case: error found at end of included file */ if (errfile>=0) { filename=get_inputfile(errfile);/* forced filename */ } else { filename=inpfname; /* current file */ if (filename==NULL || strlen(filename)==0) filename=get_sourcefile(0); if (filename==NULL || strlen(filename)==0) filename="(none)"; } /* if */ assert(filename!=NULL); va_start(argptr,number); if (strlen(errfname)==0) { int start= (errstart==errline) ? -1 : errstart; if (pc_error((int)number,string,filename,start,errline,argptr)) { if (outf!=NULL) { pc_closeasm(outf,TRUE); outf=NULL; } /* if */ longjmp(errbuf,3); /* user abort */ } /* if */ } else { FILE *fp=fopen(errfname,"a"); if (fp!=NULL) { if (errstart>=0 && errstart!=errline) fprintf(fp,"%s(%d -- %d) : %s %03d: ",filename,errstart,errline,pre,(int)number); else fprintf(fp,"%s(%d) : %s %03d: ",filename,errline,pre,(int)number); vfprintf(fp,string,argptr); fclose(fp); } /* if */ } /* if */ va_end(argptr); if (number>=100 && number<200 || errnum>25){ if (strlen(errfname)==0) { va_start(argptr,number); pc_error(0,"\nCompilation aborted.",NULL,0,0,argptr); va_end(argptr); } /* if */ if (outf!=NULL) { pc_closeasm(outf,TRUE); outf=NULL; } /* if */ longjmp(errbuf,2); /* fatal error, quit */ } /* if */ errline=-1; errfile=-1; /* check whether we are seeing many errors on the same line */ if ((errstart<0 && lastline!=fline) || lastline<errstart || lastline>fline || fcurrent!=lastfile) errorcount=0; lastline=fline; lastfile=fcurrent; if (number<200) errorcount++; if (errorcount>=3) error(107); /* too many error/warning messages on one line */ return 0; }
int gen_texinfo_header(FILE *fp, char *fname, char **header_macros) { int err= 0; char *default_header= "\\input texinfo @c -*-texinfo-*-\n" "@comment %%**start of header\n" "@setfilename PROJECT.guide\n" "@settitle Autodocs for @code{PROJECT}\n" "@paragraphindent 0\n" "@iftex\n" "@afourpaper\n" "@finalout\n" "@setchapternewpage on\n" /* odd */ "@end iftex\n" "@comment %%**end of header\n\n" "@ifinfo\n" "@node Top\n" "@top\n" "This document describes @code{PROJECT} version REVISION.\n\n" "@noindent Copyright @copyright{} COPYRIGHT\n" "@end ifinfo\n\n" "@titlepage\n" "@title PROJECT\n" "@subtitle Documentation taken from source code\n" "@subtitle Edition EDITION for Version REVISION\n" "@subtitle @today\n" "@author AUTHOR\n\n" "@page\n" "@vskip 0pt plus 1filll\n" "Copyright @copyright{} COPYRIGHT\n" "@end titlepage\n" "@headings double\n\n"; if(fname && *fname) { FILE *fh= fopen(fname,"r"); if(fh) { char *header= (char *)0; size_t header_size= 0; /* compute the size of the header file */ #ifdef BUGGY_FTELL do { (void)fgetc(fh); if(!feof(fh)) ++header_size; } while(!feof(fh) || ferror(fh)) #else /* ftell() works fine */ if( fseek(fh,0L,2L) >= 0) /* 2 == OFFSET_END */ header_size= ftell(fh); else err= __LINE__; #endif /* BUGGY_FTELL */ if(!ferror(fh) && header_size > 0) { if(fseek(fh,-header_size,1L) < 0) /* 1 == OFFSET_CURRENT */ err= __LINE__; } else err= __LINE__; /* load the header */ if(err == 0) { if( (header= (char *)malloc( (header_size + 1) * sizeof(char) )) ) { fread(header, sizeof(char), header_size, fh); header[header_size]= '\0'; if( ferror(fh) ) { free(header); header= (char *)0; err= __LINE__; } } else err= __LINE__; } if(err == 0) { char *x= strexpand(header, header_macros); if(x) { fputs(x,fp); free(x); } else /* out of memory */ err= __LINE__; } fclose(fh); } }
/* error * * Outputs an error message (note: msg is passed optionally). * If an error is found, the variable "errflag" is set and subsequent * errors are ignored until lex() finds a semicolumn or a keyword * (lex() resets "errflag" in that case). * * Global references: inpfname (referred to only) * fline (referred to only) * fcurrent (referred to only) * errflag (altered) */ int error(int number, ...) { static int lastline, lastfile, errorcount; char *msg; va_list argptr; char string[1024]; int start; /* errflag is reset on each semicolon. * In a two-pass compiler, an error should not be reported twice. Therefore * the error reporting is enabled only in the second pass (and only when * actually producing output). Fatal errors may never be ignored. */ if (((errflag) || (sc_status != statWRITE)) && ((number < 100) || (number >= 200))) return 0; if (number < 100) { if (number > 74) number = 74; msg = errmsg[number - 1]; errflag = TRUE; /* set errflag (skip rest of erroneous expression) */ errnum++; } else if (number < 200) { if (number > 107) number = 107; msg = fatalmsg[number - 100]; errnum++; /* a fatal error also counts as an error */ } else { msg = warnmsg[number - 200]; warnnum++; } strexpand(string, (unsigned char *)msg, sizeof string, SCPACK_TABLE); va_start(argptr, number); start = (errstart == fline) ? -1 : errstart; if (sc_error(number, string, inpfname, start, fline, argptr)) { sc_closeasm(outf); outf = NULL; longjmp(errbuf, 3); } va_end(argptr); if (((number >= 100) && (number < 200)) || (errnum > 250)) { va_start(argptr, number); sc_error(0, "\nCompilation aborted.", NULL, 0, 0, argptr); va_end(argptr); if (outf) { sc_closeasm(outf); outf = NULL; } /* if */ longjmp(errbuf, 2); /* fatal error, quit */ } /* if */ /* check whether we are seeing many errors on the same line */ if (((errstart < 0) && (lastline != fline)) || (lastline < errstart) || (lastline > fline) || (fcurrent != lastfile)) errorcount = 0; lastline = fline; lastfile = fcurrent; if (number < 200) errorcount++; if (errorcount >= 3) error(107); /* too many error/warning messages on one line */ return 0; }
/* * Parse the configuration file at `path' and execute the `action' call-back * functions for any directives defined by the array of config options (first * argument). * * For unknown directives that are encountered, you can optionally pass a * call-back function for the third argument to be called for unknowns. * * Returns zero on success; otherwise returns -1 and errno should be consulted. */ int parse_config(struct fp_config options[], const char *path, int (*unknown)(struct fp_config *option, uint32_t line, char *directive, char *value), uint16_t processing_options) { uint8_t bequals; uint8_t bsemicolon; uint8_t case_sensitive; uint8_t comment = 0; uint8_t end; uint8_t found; uint8_t have_equals = 0; uint8_t quote; uint8_t require_equals; uint8_t strict_equals; char p[2]; char *directive; char *t; char *value; int error; int fd; ssize_t r = 1; uint32_t dsize; uint32_t line = 1; uint32_t n; uint32_t vsize; uint32_t x; off_t charpos; off_t curpos; char rpath[PATH_MAX]; /* Sanity check: if no options and no unknown function, return */ if (options == NULL && unknown == NULL) return (-1); /* Processing options */ bequals = (processing_options & FP_BREAK_ON_EQUALS) == 0 ? 0 : 1; bsemicolon = (processing_options & FP_BREAK_ON_SEMICOLON) == 0 ? 0 : 1; case_sensitive = (processing_options & FP_CASE_SENSITIVE) == 0 ? 0 : 1; require_equals = (processing_options & FP_REQUIRE_EQUALS) == 0 ? 0 : 1; strict_equals = (processing_options & FP_STRICT_EQUALS) == 0 ? 0 : 1; /* Initialize strings */ directive = value = 0; vsize = dsize = 0; /* Resolve the file path */ if (realpath(path, rpath) == 0) return (-1); /* Open the file */ if ((fd = open(rpath, O_RDONLY)) < 0) return (-1); /* Read the file until EOF */ while (r != 0) { r = read(fd, p, 1); /* skip to the beginning of a directive */ while (r != 0 && (isspace(*p) || *p == '#' || comment || (bsemicolon && *p == ';'))) { if (*p == '#') comment = 1; else if (*p == '\n') { comment = 0; line++; } r = read(fd, p, 1); } /* Test for EOF; if EOF then no directive was found */ if (r == 0) { close(fd); return (0); } /* Get the current offset */ curpos = lseek(fd, 0, SEEK_CUR) - 1; if (curpos == -1) { close(fd); return (-1); } /* Find the length of the directive */ for (n = 0; r != 0; n++) { if (isspace(*p)) break; if (bequals && *p == '=') { have_equals = 1; break; } if (bsemicolon && *p == ';') break; r = read(fd, p, 1); } /* Test for EOF, if EOF then no directive was found */ if (n == 0 && r == 0) { close(fd); return (0); } /* Go back to the beginning of the directive */ error = (int)lseek(fd, curpos, SEEK_SET); if (error == (curpos - 1)) { close(fd); return (-1); } /* Allocate and read the directive into memory */ if (n > dsize) { if ((directive = realloc(directive, n + 1)) == NULL) { close(fd); return (-1); } dsize = n; } r = read(fd, directive, n); /* Advance beyond the equals sign if appropriate/desired */ if (bequals && *p == '=') { if (lseek(fd, 1, SEEK_CUR) != -1) r = read(fd, p, 1); if (strict_equals && isspace(*p)) *p = '\n'; } /* Terminate the string */ directive[n] = '\0'; /* Convert directive to lower case before comparison */ if (!case_sensitive) strtolower(directive); /* Move to what may be the start of the value */ if (!(bsemicolon && *p == ';') && !(strict_equals && *p == '=')) { while (r != 0 && isspace(*p) && *p != '\n') r = read(fd, p, 1); } /* An equals sign may have stopped us, should we eat it? */ if (r != 0 && bequals && *p == '=' && !strict_equals) { have_equals = 1; r = read(fd, p, 1); while (r != 0 && isspace(*p) && *p != '\n') r = read(fd, p, 1); } /* If no value, allocate a dummy value and jump to action */ if (r == 0 || *p == '\n' || *p == '#' || (bsemicolon && *p == ';')) { /* Initialize the value if not already done */ if (value == NULL && (value = malloc(1)) == NULL) { close(fd); return (-1); } value[0] = '\0'; goto call_function; } /* Get the current offset */ curpos = lseek(fd, 0, SEEK_CUR) - 1; if (curpos == -1) { close(fd); return (-1); } /* Find the end of the value */ quote = 0; end = 0; while (r != 0 && end == 0) { /* Advance to the next character if we know we can */ if (*p != '\"' && *p != '#' && *p != '\n' && (!bsemicolon || *p != ';')) { r = read(fd, p, 1); continue; } /* * If we get this far, we've hit an end-key */ /* Get the current offset */ charpos = lseek(fd, 0, SEEK_CUR) - 1; if (charpos == -1) { close(fd); return (-1); } /* * Go back so we can read the character before the key * to check if the character is escaped (which means we * should continue). */ error = (int)lseek(fd, -2, SEEK_CUR); if (error == -3) { close(fd); return (-1); } r = read(fd, p, 1); /* * Count how many backslashes there are (an odd number * means the key is escaped, even means otherwise). */ for (n = 1; *p == '\\'; n++) { /* Move back another offset to read */ error = (int)lseek(fd, -2, SEEK_CUR); if (error == -3) { close(fd); return (-1); } r = read(fd, p, 1); } /* Move offset back to the key and read it */ error = (int)lseek(fd, charpos, SEEK_SET); if (error == (charpos - 1)) { close(fd); return (-1); } r = read(fd, p, 1); /* * If an even number of backslashes was counted meaning * key is not escaped, we should evaluate what to do. */ if ((n & 1) == 1) { switch (*p) { case '\"': /* * Flag current sequence of characters * to follow as being quoted (hashes * are not considered comments). */ quote = !quote; break; case '#': /* * If we aren't in a quoted series, we * just hit an inline comment and have * found the end of the value. */ if (!quote) end = 1; break; case '\n': /* * Newline characters must always be * escaped, whether inside a quoted * series or not, otherwise they * terminate the value. */ end = 1; case ';': if (!quote && bsemicolon) end = 1; break; } } else if (*p == '\n') /* Escaped newline character. increment */ line++; /* Advance to the next character */ r = read(fd, p, 1); } /* Get the current offset */ charpos = lseek(fd, 0, SEEK_CUR) - 1; if (charpos == -1) { close(fd); return (-1); } /* Get the length of the value */ n = (uint32_t)(charpos - curpos); if (r != 0) /* more to read, but don't read ending key */ n--; /* Move offset back to the beginning of the value */ error = (int)lseek(fd, curpos, SEEK_SET); if (error == (curpos - 1)) { close(fd); return (-1); } /* Allocate and read the value into memory */ if (n > vsize) { if ((value = realloc(value, n + 1)) == NULL) { close(fd); return (-1); } vsize = n; } r = read(fd, value, n); /* Terminate the string */ value[n] = '\0'; /* Cut trailing whitespace off by termination */ t = value + n; while (isspace(*--t)) *t = '\0'; /* Escape the escaped quotes (replaceall is in string_m.c) */ x = strcount(value, "\\\""); /* in string_m.c */ if (x != 0 && (n + x) > vsize) { if ((value = realloc(value, n + x + 1)) == NULL) { close(fd); return (-1); } vsize = n + x; } if (replaceall(value, "\\\"", "\\\\\"") < 0) { /* Replace operation failed for some unknown reason */ close(fd); return (-1); } /* Remove all new line characters */ if (replaceall(value, "\\\n", "") < 0) { /* Replace operation failed for some unknown reason */ close(fd); return (-1); } /* Resolve escape sequences */ strexpand(value); /* in string_m.c */ call_function: /* Abort if we're seeking only assignments */ if (require_equals && !have_equals) return (-1); found = have_equals = 0; /* reset */ /* If there are no options defined, call unknown and loop */ if (options == NULL && unknown != NULL) { error = unknown(NULL, line, directive, value); if (error != 0) { close(fd); return (error); } continue; } /* Loop through the array looking for a match for the value */ for (n = 0; options[n].directive != NULL; n++) { error = fnmatch(options[n].directive, directive, FNM_NOESCAPE); if (error == 0) { found = 1; /* Call function for array index item */ if (options[n].action != NULL) { error = options[n].action( &options[n], line, directive, value); if (error != 0) { close(fd); return (error); } } } else if (error != FNM_NOMATCH) { /* An error has occurred */ close(fd); return (-1); } } if (!found && unknown != NULL) { /* * No match was found for the value we read from the * file; call function designated for unknown values. */ error = unknown(NULL, line, directive, value); if (error != 0) { close(fd); return (error); } } } close(fd); return (0); }