1 /*
2     AutoHelp file reader.
3     Copyright 2000 Randall Maas (randym@acm.org)
4     Copyright 1998-2000 Fraser Mc
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 
20 */
21 
22 
23 #include "dillib.h"
24 
25 #define BUFSIZE 1024
26 #define COMMENT '#' /* comment character in rc files */
27 #define SAMEAS  "=" /* entries with this get set to the previous equivalent */
28 
29 static int AppendText(__AutoHelpEntry_t* Ptr, const char* Str);
30 
31 /* @txh */
__AutoHelp_load(const char * Path,__AutoHelpEntry_t ** Rules,size_t * NRules)32 int __AutoHelp_load(const char *Path, __AutoHelpEntry_t**Rules, size_t* NRules)
33 {
34    /*
35       Description
36        Opens the specified file and reads in the table of help information
37 
38       Return Value
39        -1 on error, 0 on success
40       @end txh
41    */
42 
43   FILE *fp;
44   char in[BUFSIZE];
45   unsigned int lineno=0;
46   char hl[BUFSIZE], regex[BUFSIZE];
47   size_t NAllocd=*NRules;
48 
49   if ((fp = fopen(Path, "r")) == NULL) {
50     if (errno != ENOENT) {
51       Err_cmdline("unable to open \"%s\" (%s)\n", Path, strerror(errno));
52     }
53     return -1;
54   }
55 
56   while (fgets(in, sizeof(in), fp) != NULL) {
57     ++lineno;
58     if (in[0] == COMMENT) continue;
59     if (sscanf(in, ":%s %[^\n]\n", hl, regex) == 2) {
60       /* a control line, make a new help entry */
61       __AutoHelpEntry_t *new;
62       if (NAllocd <= *NRules)
63 	{
64 	  NAllocd = (NAllocd+1)<<1;
65 	  if (!(*Rules = realloc(*Rules, sizeof(**Rules)*NAllocd)))
66 	    {
67 	      fprintf(stderr, "%s:%u hl %s regex %s\n", Path, lineno,
68 		      hl, regex);
69 	      return -1;
70 	    }
71 	}
72       new = *Rules+(*NRules)++;
73       new->Hint = NULL;
74 #if 0
75       new->helplevel = 0;
76       if (strcmp(hl, SAMEAS) == 0 && current != NULL) {
77 	new->helplevel = current->helplevel;
78       }
79       else {
80 	for (i = hl; *i != '\0'; ++i) {
81 	  if (*i >= '0' && *i <= '9') {
82 	    new->helplevel |= 1 << (*i - '0');
83 	  }
84 	}
85       }
86 #endif
87       if (strcmp(regex, SAMEAS) == 0 && *NRules) {
88 	new->Reg = new[-1].Reg;
89       }
90       else if (regcomp(&(new->Reg), regex,
91 		       REG_EXTENDED|REG_NOSUB) != 0) {
92 	Err_cmdline("%s:%u: bad regular expression \"%s\"\n", Path, lineno,
93 		    regex);
94       }
95       continue;
96     }
97 
98     /* not a control line, must be a help text line */
99     if (!*NRules) {
100       Err_cmdline("%s:%u: help text without control line\n", Path, lineno);
101       continue;
102     }
103 
104     if (AppendText(*Rules + *NRules -1, in)) return -1;
105   }
106 
107   fclose(fp);
108   return 0;
109 }
110 
AppendText(__AutoHelpEntry_t * Ptr,const char * Str)111 static int AppendText(__AutoHelpEntry_t* Ptr, const char* Str)
112 {
113    /*
114       Description
115       Return Value
116        0 on success, otherwise error
117    */
118    char *newhint;
119    if (Ptr->Hint == NULL) { /* nothing yet */
120      if ((Ptr->Hint = (char *) malloc(strlen(Str)+1)) == NULL)
121        return -1;
122      strcpy(Ptr->Hint, Str);
123      return 0;
124    }
125 
126    /* stuff exists, append to it */
127    if ((newhint = (char *) realloc(Ptr->Hint,
128 				   strlen(Ptr->Hint) +
129 				   strlen(Str) + 1)) == NULL)
130      return -1;
131    strcpy(newhint + strlen(newhint), Str);
132    Ptr->Hint = newhint;
133    return 0;
134 }
135