1/* Copyright (C) 2012-2022 Free Software Foundation, Inc. 2 Contributed by Georg-Johann Lay (avr@gjlay.de) 3 4 This file is part of GCC. 5 6 GCC 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 3, or (at your option) 9 any later version. 10 11 GCC 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 GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20#include <stdlib.h> 21#include <stdio.h> 22#include <string.h> 23 24#define IN_GEN_AVR_MMCU_TEXI 25 26#include "avr-devices.cc" 27 28static const avr_mcu_t* 29mcus[sizeof avr_mcu_types / sizeof avr_mcu_types[0]]; 30 31static int letter (char c) 32{ 33 return c >= 'a' && c <= 'z'; 34} 35 36static int digit (char c) 37{ 38 return c >= '0' && c <= '9'; 39} 40 41static int 42str_prefix_p (const char *str, const char *prefix) 43{ 44 return strncmp (str, prefix, strlen (prefix)) == 0; 45} 46 47 48/* Used by string comparator to group MCUs by their 49 name prefix like "attiny" or "atmega". */ 50 51static int 52c_prefix (const char *str) 53{ 54 static const char *const prefixes[] = 55 { 56 "attiny", "atmega", "atxmega", "ata", "at90" 57 }; 58 59 int i, n = (int) (sizeof (prefixes) / sizeof (*prefixes)); 60 61 for (i = 0; i < n; i++) 62 if (str_prefix_p (str, prefixes[i])) 63 return i; 64 65 return n; 66} 67 68 69/* If A starts a group of digits, return their value as a number. */ 70 71static int 72c_number (const char *a) 73{ 74 int val = 0; 75 76 if (digit (*a) && ! digit (*(a-1))) 77 { 78 while (digit (*a)) 79 val = 10 * val + (*a++) - '0'; 80 } 81 82 return val; 83} 84 85 86/* Compare two MCUs and order them for easy lookup. */ 87 88static int 89comparator (const void *va, const void *vb) 90{ 91 const avr_mcu_t *mcu_a = *(const avr_mcu_t* const*) va; 92 const avr_mcu_t *mcu_b = *(const avr_mcu_t* const*) vb; 93 const char *a = mcu_a->name; 94 const char *b = mcu_b->name; 95 96 // First, group MCUs according to their pure-letter prefix. 97 98 int c = c_prefix (a) - c_prefix (b); 99 if (c) 100 return c; 101 102 // Second, if their prefixes are the same, group according to 103 // their flash size. 104 105 c = (int) mcu_a->flash_size - (int) mcu_b->flash_size; 106 if (c) 107 return c; 108 109 // Third, group according to aligned groups of digits. 110 111 while (*a && *b) 112 { 113 c = c_number (a) - c_number (b); 114 if (c) 115 return c; 116 117 if (*a != *b) 118 return *a - *b; 119 120 a++; 121 b++; 122 } 123 124 return *a - *b; 125} 126 127static void 128print_mcus (size_t n_mcus) 129{ 130 int duplicate = 0; 131 size_t i; 132 133 if (!n_mcus) 134 return; 135 136 qsort (mcus, n_mcus, sizeof (avr_mcu_t*), comparator); 137 138 printf ("@*@var{mcu}@tie{}="); 139 140 for (i = 0; i < n_mcus; i++) 141 { 142 printf (" @code{%s}%s", mcus[i]->name, i == n_mcus-1 ? ".\n\n" : ","); 143 144 if (i && !strcmp (mcus[i]->name, mcus[i-1]->name)) 145 { 146 // Sanity-check: Fail on devices that are present more than once. 147 148 duplicate = 1; 149 fprintf (stderr, "error: duplicate device: %s\n", mcus[i]->name); 150 } 151 } 152 153 if (duplicate) 154 exit (1); 155} 156 157int main (void) 158{ 159 enum avr_arch_id arch_id = ARCH_UNKNOWN; 160 size_t i, n_mcus = 0; 161 const avr_mcu_t *mcu; 162 163 printf ("@c Copyright (C) 2012-2022 Free Software Foundation, Inc.\n"); 164 printf ("@c This is part of the GCC manual.\n"); 165 printf ("@c For copying conditions, see the file " 166 "gcc/doc/include/fdl.texi.\n\n"); 167 168 printf ("@c This file is generated automatically using\n"); 169 printf ("@c gcc/config/avr/gen-avr-mmcu-texi.cc from:\n"); 170 printf ("@c gcc/config/avr/avr-arch.h\n"); 171 printf ("@c gcc/config/avr/avr-devices.cc\n"); 172 printf ("@c gcc/config/avr/avr-mcus.def\n\n"); 173 174 printf ("@c Please do not edit manually.\n\n"); 175 176 printf ("@table @code\n\n"); 177 178 for (mcu = avr_mcu_types; mcu->name; mcu++) 179 { 180 if (mcu->macro == NULL) 181 { 182 arch_id = mcu->arch_id; 183 184 // Start a new architecture: Flush the MCUs collected so far. 185 print_mcus (n_mcus); 186 n_mcus = 0; 187 188 for (i = 0; i < sizeof (avr_texinfo) / sizeof (*avr_texinfo); i++) 189 if (arch_id == avr_texinfo[i].arch_id) 190 printf ("@item %s\n%s\n", mcu->name, avr_texinfo[i].texinfo); 191 } 192 else if (arch_id == (enum avr_arch_id) mcu->arch_id) 193 { 194 mcus[n_mcus++] = mcu; 195 } 196 } 197 198 print_mcus (n_mcus); 199 printf ("@end table\n"); 200 201 return EXIT_SUCCESS; 202} 203