Imported Upstream version 2.9.0
[debian/cc1111] / support / scripts / mh2h.c
1 /*-------------------------------------------------------------------------
2   mh2h.c - megaheader to header conversion utility.  This utility converts
3    the mega-header MCS51 mcs51reg.h file to multiple simple header files.
4
5    We want the simple headers for compatibility with other compilers
6    and also for documentation(quick reference of registers names and
7    bit defines while programming).
8    At the same time we don't want to maintain all these redundant files.
9
10    So this offers a solution of converting 1 master .h file into many
11    simple header files.
12
13    We use the preprocessor(sdcpp) to do most of the work.  Then we
14    use some c code to clean it up and make it look pretty.
15
16    Usage# mh2h {include_dir {bin_dir}} ; no options used.
17      default include_dir is "/usr/local/share/sdcc/include"
18      default bin_dir(run sdcpp from is ""
19
20    Written by Karl Bongers(kbongers@turbobit.com)
21 |-------------------------------------------------------------------------*/
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 void get_micro_h_name(char *name, char *ret_str);
28 void get_micro_list(void);
29 void strip_eol(char *str);
30 void strip_trailing_sp(char *str);
31
32 #define MAX_LISTSIZE 100
33 char *micro_list[MAX_LISTSIZE];
34 char bin_dir[256];
35 char inc_dir[256];
36
37 /*-------------------------------------------------------------------------
38 |-------------------------------------------------------------------------*/
39 int main(int argc, char *argv[])
40 {
41   int stat;
42   FILE *fpi, *fpo;
43   char str[256];
44   char fname[256];
45   int mi;
46   int last_line_was_sfr = 1;  // used to print pretty, add a blank line
47
48   // 1st arg optional inc dir to pull mcs51reg.h from
49   if (argc > 1) {
50     strcpy(inc_dir, argv[1]);
51     printf("using %s bin dir\n", inc_dir);
52   }
53   else {
54     strcpy(inc_dir, "/usr/local/share/sdcc/include/");
55   }
56
57   // 2nd arg optional bin dir to run sdcpp from
58   if (argc > 2) {
59     strcpy(bin_dir, argv[2]);
60     printf("using %s bin dir\n", bin_dir);
61   }
62   else {
63     bin_dir[0] = 0;
64   }
65
66
67   get_micro_list();
68   mi = 0;
69   while (micro_list[mi] != NULL)
70   {
71     printf("LIST:%s\n", micro_list[mi++]);
72   }
73
74   mi = 0;
75   while (micro_list[mi] != NULL)
76   {
77     printf("converting %s\n", micro_list[mi]);
78     fflush(0);
79
80     sprintf(str, "%ssdcpp -D%s %smcs51reg.h tmp1",
81        bin_dir,
82        micro_list[mi],
83        inc_dir);
84
85     stat = system(str);
86     /* stat = -1, or 127 error */
87
88     fpi = fopen("tmp1", "r");
89     if (fpi == NULL) {
90       printf("error opening file to read\n");
91       exit(1);
92     }
93
94     get_micro_h_name(micro_list[mi], fname);
95     //sprintf(fname, "tmp%d.h", mi+1);
96
97     fpo = fopen(fname, "w");
98     if (fpo == NULL) {
99       printf("error opening %s  file to write\n", fname);
100       exit(1);
101     }
102
103     fputs("/*-------------------------------------------------------------------------\n",
104        fpo);
105     fprintf(fpo, " %s - %s header file.\n", fname, micro_list[mi]);
106     fputs(" This file was automatically generated using mh2h utility\n", fpo);
107     fputs(" to convert from mcs51reg.h.\n", fpo);
108     fputs("|-------------------------------------------------------------------------*/\n",
109        fpo);
110     fprintf(fpo, "#define %s\n", micro_list[mi]);
111     fputs("#include <mcs51reg.h>\n\n", fpo);
112
113     fprintf(fpo, "#if 0\n");
114     fputs("The following is for your reference only\n", fpo);
115     fputs("and is an accurate translation of what the\n", fpo);
116     fputs("above included mcs51reg.h file generates.\n\n", fpo);
117       
118     while (fgets(str, 256, fpi) != NULL) {
119       strip_eol(str);
120       strip_trailing_sp(str);
121
122       if (strlen(str) <= 0)
123         continue;
124       if (strncmp(str, "#line ", 6) == 0)
125         continue;
126       if (strncmp(str, "//", 2) == 0)
127         continue;
128
129       if (strncmp(str, "sfr ", 4) == 0)
130       {
131         if (!last_line_was_sfr)
132           fputs("\n", fpo);  /* for readability, add a blank line) */
133         last_line_was_sfr = 1;
134       }
135       else
136       {
137         if (strncmp(str, "sbit ", 5) == 0)
138           fputs("  ", fpo);  /* for readability, indent */
139
140         last_line_was_sfr = 0;
141       }
142
143       //printf("[%d,%s]\n", strlen(str), str);
144       fputs(str, fpo);
145       fputs("\n", fpo);
146     }
147     fprintf(fpo, "#endif\n");
148
149     fclose(fpi);
150     fclose(fpo);
151     ++mi;
152   }  // while micro_list[mi]
153
154   return 0;
155 }
156
157 /*-------------------------------------------------------------------------
158   get_micro_h_name - get a .h filename to output to.  Preferably, we will
159     have this info in mcs51reg.h file(alias:8051.h) and not do it like this.
160 |-------------------------------------------------------------------------*/
161 void get_micro_h_name(char *name, char *ret_str)
162 {
163   int mi;
164 static int name_i = 1;
165   // note: pulling these from mcs51reg.h would be better...
166 static char *micro_strings[] = {
167    "MICROCONTROLLER_8051", "8051.h",
168    "MICROCONTROLLER_8052", "8052.h",
169    "MICROCONTROLLER_AT89CX051", "at89x051.h",
170    "MICROCONTROLLER_AT89S53",  "at89s53.h",
171    "MICROCONTROLLER_AT89X52",  "at89x52.h",
172    "MICROCONTROLLER_AT89X55",  "at89x55.h",
173    "MICROCONTROLLER_DS5000",   "ds5000.h",
174    "MICROCONTROLLER_DS5001",   "ds5001.h",
175    "MICROCONTROLLER_DS80C32X", "ds80c32x.h",
176    "MICROCONTROLLER_DS80C390", "ds80c390.h",
177    "MICROCONTROLLER_DS89C420", "ds89c420.h",
178    "MICROCONTROLLER_DS8XC520", "ds8xc520.h",
179    "MICROCONTROLLER_SAB80515",  "sab80515.h",
180    "MICROCONTROLLER_SAB80515A", "sab80515a.h",
181    "MICROCONTROLLER_SAB80517",  "sab80517.h",
182    "MICROCONTROLLER_P80C552",   "p80c552.h",
183    NULL};
184
185    *ret_str = 0;
186    mi = 0;
187    while (micro_strings[mi] != NULL)
188    {
189      if (strcmp(micro_strings[mi], name) == 0)
190      {
191        strcpy(ret_str, micro_strings[mi+1]);
192      }
193      mi += 2;
194    }
195
196    if (*ret_str == 0)
197    {
198      sprintf(ret_str, "noname%d.h", name_i++);
199      printf("warning, could not find .h filename for %s using %s\n",
200        name, ret_str);
201    }
202 }
203
204 /*-------------------------------------------------------------------------
205   get_micro_list - get the list of micros supported by mcs51reg.h, grab
206     this list out of the mcs51reg.h file.
207 |-------------------------------------------------------------------------*/
208 void get_micro_list(void)
209 {
210  FILE *fp;
211  char str[256];
212  int li = 0;
213  char *s;
214  char *s_start;
215
216   strcpy(str, inc_dir);
217   strcat(str, "mcs51reg.h");
218   fp = fopen(str, "r");
219   if (fp == NULL) {
220     printf("error opening %s file to read\n", str);
221     exit(1);
222   }
223   while (fgets(str, 256, fp) != NULL)
224   {
225     strip_eol(str);
226     strip_trailing_sp(str);
227     s = str;
228     while (*s == ' ')
229       ++s;
230     if (strlen(s) <= 0)
231       continue;
232
233     if (strncmp(s, "MICROCONTROLLER_", 16) == 0)
234     {
235       s_start = s;
236       while ((*s != 0) && (*s != ' '))
237         ++s;
238       *s = 0;
239       micro_list[li++] = strdup(s_start); // add to our list MICROCONTROLLER_X
240       if (li >= MAX_LISTSIZE)
241         exit(1);
242     }
243   }  // while
244
245   micro_list[li] = NULL;
246
247   if (li == 0)
248   {
249     printf("Error, no MICROCONTROLLER_ defines found\n");
250     exit(1);
251   }
252   printf("%d MICRO defines found\n", li);
253   fclose(fp);
254 }
255
256 /*-------------------------------------------------------------------------
257 |-------------------------------------------------------------------------*/
258 void strip_trailing_sp(char *str)
259 {
260   int sz;
261   sz = strlen(str);
262   if (sz == 0)
263     return;
264   while(str[sz-1] == ' ')
265   {
266     str[sz-1] = 0;
267     --sz;
268     if (sz == 0)
269       return;
270   }  
271 }
272
273 /*-------------------------------------------------------------------------
274 |-------------------------------------------------------------------------*/
275 void strip_eol(char *str)
276 {
277   int sz;
278 #define is_eol_char(c) ((c == 0x0d) || (c == 0x0a))
279   sz = strlen(str);
280   if (sz == 0)
281     return;
282   if (is_eol_char(str[sz-1]))
283     str[sz-1] = 0;
284
285   sz = strlen(str);
286   if (sz == 0)
287     return;
288   if (is_eol_char(str[sz-1]))
289     str[sz-1] = 0;
290 }    
291